#include <algorithm>
#include <cassert>
#include <functional>
#include <vector>
#include <boost/numeric/conversion/cast.hpp>
///fuzzy_equal_to is a predicate to test two doubles for equality
///with a certain tolerance. A tolerance of 0.0 denotes that
///an exact match is requested. Note that the value of 0.0 cannot
///be compared fuzzily.
struct fuzzy_equal_to : public std::binary_function<double,double,bool>
{
fuzzy_equal_to(const double tolerance = 0.01)
: m_tolerance(tolerance)
{
assert(tolerance >= 0.0);
}
bool operator()(const double lhs, const double rhs) const
{
const double d = std::abs(m_tolerance * lhs);
return rhs > lhs - d
&& rhs < lhs + d;
}
const double m_tolerance;
};
///AllAboutEqual tests if all values in a std::vector are about equal.
///From http://www.richelbilderbeek.nl/CppAllAboutEqual.htm
bool AllAboutEqual(
const std::vector<double>& v,
const double tolerance = 0.01)
{
assert(!v.empty());
return std::count_if(
v.begin(),
v.end(),
std::bind2nd(fuzzy_equal_to(tolerance),v[0]))
== boost::numeric_cast<int>(v.size());
}
int main()
{
//C++11 initializer list
assert( AllAboutEqual( { 0.999, 1.0, 1.001 } ));
assert( AllAboutEqual( { -0.999, -1.0, -1.001 } ));
assert(!AllAboutEqual( { 0.999, -1.0, -1.001 } ));
assert(!AllAboutEqual( { -0.999, 1.0, -1.001 } ));
assert(!AllAboutEqual( { -0.999, -1.0, 1.001 } ));
assert(!AllAboutEqual( { 0.98 , 1.0, 1.02 } ));
assert(!AllAboutEqual( { 0.9 , 1.0, 1.1 } ));
}
|