Friday, September 1, 2017

C++11: Algorithms: iota

The function iota stores an increasing value in each element in a container. Here is an example:

#include <numeric>
#include <iostream>

int main()
{
  int myArray[5];

  int * beginIter = &myArray[0];
  int * endIter   = &myArray[5];

  std::iota(beginIter, endIter, 7);

  std::cout << myArray[0] << " " << 
               myArray[1] << " " <<
               myArray[2] << " " << std::endl;
  return 0;
}
// Output: 7 8 9
Reference: https://isocpp.org/wiki/faq/cpp11-library-stl#cpp11-algorithms

C++11: Algorithms: find_if_not

The find_if_not algorithm was added. Here is an example:

#include <algorithm>
#include <iostream>
 
int main()
{//                 0  1  2  3  4
  int myArray[]  = {1, 1, 1, 5, 1};
 
  int * beginIter = &myArray[0];
  int * endIter   = &myArray[5];
 
  int * iter = std::find_if_not(beginIter, endIter,
                                [](int element){return element == 1;});
 
  if (iter != endIter)
  {
    std::cout << *iter << " ";
  }
  else
  {
    std::cout << "Did not find anything ";
  }
 
  myArray[3] = 1;
  iter = std::find_if_not(beginIter, endIter,
                          [](int element){return element == 1;});
 
  if (iter != endIter)
  {
    std::cout << *iter << " ";
  }
  else
  {
    std::cout << "Did not find anything ";
  }
 
  std::cout << std::endl;
  return 0;
}
// Output: 5 Did not find anything
Reference: https://isocpp.org/wiki/faq/cpp11-library-stl#cpp11-algorithms

C++11: Algorithms: all_of, any_of, none_of

Given first and last iterators and a predicate, you can test to see if all, any or none of the elements in a container satisfies the predicates. Here is an example:

#include <algorithm>
#include <iostream>
int main()
{//                 0  1  2  3  4
  int allOnes[]  = {1, 1, 1, 1, 1};
  int someOnes[] = {1, 1, 1, 1, 0};

  int * beginIter = &allOnes[0];
  int * endIter   = &allOnes[5];

  bool allAreOnes = std::all_of  (beginIter, endIter,
                                  [](int element) {return element == 1;});
  std::cout << allAreOnes << " ";

  bool someAreOnes = std::any_of (beginIter, endIter,
                                  [](int element) {return element == 1;});
  std::cout << someAreOnes << " ";

  bool noneAreOnes = std::none_of(beginIter, endIter,
                                  [](int element) {return element == 1;});
  std::cout << noneAreOnes << " : ";

  beginIter = &someOnes[0];
  endIter  = &someOnes[5];

  allAreOnes = std::all_of  (beginIter, endIter,
                             [](int element) {return element == 1;});
  std::cout << allAreOnes << " ";

  someAreOnes = std::any_of (beginIter, endIter,
                             [](int element) {return element == 1;});
  std::cout << someAreOnes << " ";

  noneAreOnes = std::none_of(beginIter, endIter,
                             [](int element) {return element == 1;});
  std::cout << noneAreOnes << " ";

  return 0;
}
// Output: 1 1 0 : 0 1 0
Reference: https://isocpp.org/wiki/faq/cpp11-library-stl#cpp11-algorithms

C++11: Scoped Allocators

C++11 added to ability to write allocators that can maintain state. Here is an example:

#include <iostream>
#include <vector>

class Arena
{
  void * mPointerToMemory;
  int    mMaxNumberOfBytes;
  int    mNextAvailableByte;

 public:
  Arena(void * pointerToMemory, int maxNumberOfBytes)
  : mPointerToMemory(pointerToMemory),
    mMaxNumberOfBytes(maxNumberOfBytes),
    mNextAvailableByte(0)
  {
    ;
  }

  void * getPointerToBlockOfBytes(int numberOfBytes)
  {
    void * pointerToBlockOfBytes  = nullptr;
    int    remainingNumberOfBytes = mMaxNumberOfBytes - mNextAvailableByte;

    if (numberOfBytes <= remainingNumberOfBytes)
    {
      pointerToBlockOfBytes  = (void*)((unsigned char*)mPointerToMemory +
                                                       mNextAvailableByte);
      mNextAvailableByte    += numberOfBytes;       
    }
    return pointerToBlockOfBytes;
  }
};

template <class T>
struct MyAllocator
{
  typedef T value_type;

  Arena * mArena;

  MyAllocator(Arena * arena) : mArena(arena)
  {
    ;
  }

  template <class U>
  constexpr MyAllocator(const MyAllocator<U> & rhs) noexcept
  : mArena(rhs.mArena)
  {
    ;
  }

  T * allocate(std::size_t n)
  {
    void * pointerToBlockOfBytes = mArena->getPointerToBlockOfBytes(n);
    if (!pointerToBlockOfBytes)
    {
      throw std::bad_alloc();
    }
    return (T *) pointerToBlockOfBytes;
  }

  void deallocate(T* p, std::size_t) noexcept
  {
    ;
  }
};

template <class T, class U>
bool operator==(const MyAllocator<T>&, const MyAllocator<U>&)
{
  return true;
}

template <class T, class U>
bool operator!=(const MyAllocator<T>&, const MyAllocator<U>&)
{
  return false;
}

int main()
{
  Arena myArena(new int[8], 8);

  std::vector<int, MyAllocator<int>> v1(MyAllocator<int>{&myArena});

  std::cout << sizeof(v1) << " ";
  try{v1.push_back(0);}catch(...){std::cout << "Exception0" <<  " ";}
  std::cout << v1[0] << " ";
  try{v1.push_back(1);}catch(...){std::cout << "Exception1" <<  " ";}
  std::cout << v1[1] << " ";
  try{v1.push_back(2);}catch(...){std::cout << "Exception2" <<  " ";}
  std::cout << v1[2] << " ";
  try{v1.push_back(3);}catch(...){std::cout << "Exception3" <<  " ";}
  std::cout << v1[3] << " ";
  try{v1.push_back(4);}catch(...){std::cout << "Exception4" <<  " ";}
  std::cout << v1[4] << " ";

  std::cout << std::endl;
  return 0;
}
// Output: 20 0 1 2 Exception3
Reference: https://isocpp.org/wiki/faq/cpp11-library#scoped-allocator

C++11: Random Numbers: Distributions

C++11 provides the following distributions:
Uniform distributions:
  uniform_int_distribution
  uniform_real_distribution

Bernoulli distributions:
  bernoulli_distribution
  geometric_distribution
  binomial_distribution
  negative_binomial_distribution

Poisson distributions:
  poisson_distribution
  gamma_distribution
  exponential_distribution
  weibull_distribution
  extreme_value_distribution

Normal distributions:
  normal_distribution
  fisher_f_distribution
  cauchy_distribution
  lognormal_distribution
  chi_squared_distribution
  student_t_distribution

Sampling distributions:
  discrete_distribution
  piecewise_linear_distribution
  piecewise_constant_distribution

                     http://www.cplusplus.com/reference/random/


C++11: Random Numbers: Normal Distribution

You can easily create normally distributed numbers. Here is an example:

#include <iostream>
#include <random>
#include <vector>

std::normal_distribution<double>   norm_double_dist_0_9{4.5 /*mean*/,
                                                        2.0 /* sd */};
std::default_random_engine         random_engine{};
const int NbrOfBins    =  10;
const int NbrOfSamples = 100;

int main()
{
  std::vector<int> histogram(NbrOfBins);
  int              sampleValue;

  for (int sample = 0; sample < NbrOfSamples; ++sample)
  {
    sampleValue             = (int)norm_double_dist_0_9(random_engine);
    if (sampleValue < 0) sampleValue = 0;
    if (sampleValue > 9) sampleValue = 9;
    ++histogram[sampleValue];
  }

  for (int bin = 0; bin < NbrOfBins; ++bin)
  {
    std::cout << histogram[bin] << std::endl;
  }
  return 0;
}
/* Output:
     8
     6
     8
     15
     19
     18
     14
     8
     3
     1
*/
Reference: https://isocpp.org/wiki/faq/cpp11-library#std-random

C++11: Random Numbers

C++11 added more flexibility in generating random numbers. The system is divided into two parts: 1) A random number generator; and 2) a distribution. Each one can be set separately. Here is an example:

#include <iostream>
#include <random>
#include <vector>

std::uniform_int_distribution<int> uni_int_dist_0_9{0, 9};
std::default_random_engine         random_engine{};
const int NbrOfBins    =  10;
const int NbrOfSamples = 100;

int main()
{
  std::vector<int> histogram(NbrOfBins);
  int              sampleValue;

  for (int sample = 0; sample < NbrOfSamples; ++sample)
  {
    sampleValue             = uni_int_dist_0_9(random_engine);
    ++histogram[sampleValue];
  }

  for (int bin = 0; bin < NbrOfBins; ++bin)
  {
    std::cout << histogram[bin] << std::endl;
  }
  return 0;
}
/* Output:
    10
    6
    11
    10
    9
    9
    16
    6
    8
    15
*/
Reference: https://isocpp.org/wiki/faq/cpp11-library#std-random