mercredi 24 avril 2013

Use Iterator to decouple your algorithm from your container...

Today, I had to implement a function to check error between data contains in different kind of container. Typically the data type can be int, float or double, store in std::vector or boost::numeric::ublas vector and matrix.

It's here that template and iterator pattern have to be use to decouple the algorithm/function implementation of the container implementation.

template<class InputIteratorT1, typename InputIteratorT2> void CheckEqualForGivenAccuracy( InputIteratorT1 first_left, InputIteratorT1 last_left, InputIteratorT2 first_right, InputIteratorT2 last_right, double tstEspilon = (double)std::numeric_limits<typename InputIteratorT1::value_type>::epsilon(), std::ostream& stream = null_ostream )

{

  CHECK(std::distance(first_left, last_left) && std::distance(first_right, last_right));

  stream << std::string(__FUNCTION__) << " of " << std::distance(first_left, last_left) << " elements with epsilon = " << tstEspilon << std::endl;

 

  unsigned int nb_error = 0;

  double sum_abs_diff = 0.0;

  double max_diff = 0.0;

  double min_diff = 0.0;

  while(first_left != last_left)

  {

    if(fabs((double)*first_left - (double)*first_right) > tstEspilon)

    {

      nb_error++;

      double diff = (double)*first_left - (double)*first_right;

      sum_abs_diff += std::abs<double>(diff);

      max_diff = std::max(max_diff, diff);

      min_diff = std::min(min_diff, diff);     

    }

    first_left++; first_right++;

  }

  if(nb_error > 0)

  {

    stream << std::string(__FUNCTION__) << " error= " << nb_error << " sum_abs_diff = " << sum_abs_diff << " max_diff = " << max_diff << " min_diff = " << min_diff << std::endl;

  }

 

  CHECK(nb_error == 0);

}


That implementation is range-based, the 2 data type can be different ((internally a promotion to double is made), and we have 2 optional parameters, one to specify the error limit and the second to log message. By default the error limit use the standard epsilon value from the numeric type_trait class, and the ostream my implementation of a /dev/null output.

Aucun commentaire :

Enregistrer un commentaire