+++ /dev/null
-/**
- * @brief Additional ensures for scientific/engineering applications.
- * @author Joerg <yogi2005@users.sourceforge.net>
- * @date 07/04/2008
- */
-#ifndef TUT_Float_H_GUARD
-#define TUT_Float_H_GUARD
-
-#include <limits>
-#include <iostream>
-
-namespace tut
-{
- namespace detail
- {
- template<bool Predicate, typename Then, typename Else>
- struct If
- {
- typedef Else type;
- };
-
- template<typename Then, typename Else>
- struct If<true,Then,Else>
- {
- typedef Then type;
- };
-
- template<typename T>
- struct fpt_traits
- {
- struct StdNumericLimitsNotAvailable {};
- static const StdNumericLimitsNotAvailable static_check[ std::numeric_limits<T>::is_specialized ];
-
- static const T zero;
-
- typedef typename If<std::numeric_limits<T>::is_integer,
- double,
- T>::type Result;
-
- static T abs(const T &arg)
- {
- if(arg < zero)
- return zero - arg;
- else
- return arg;
- }
-
- static T sig(const T &arg)
- {
- if(arg < zero)
- return -1;
- else
- return 1;
- }
-
- static inline Result div(const Result &number, const T &divisor)
- {
- static_cast<void>(static_check);
-
- if(number == zero && divisor == zero)
- return std::numeric_limits<Result>::quiet_NaN();
-
- if(number == zero)
- return zero;
-
- if(divisor == zero)
- return sig(number) * std::numeric_limits<Result>::infinity();
-
- assert(zero < number);
- assert(zero < divisor);
-
- // Avoid underflow
- if(static_cast<T>(1) < abs(divisor))
- {
- // number / divisor < min <=> number < min * divisor
- if( abs(number) < abs(divisor) * std::numeric_limits<T>::min())
- {
- return sig(divisor) * sig(number) * std::numeric_limits<T>::min();
- }
- }
-
- // Avoid overflow
- if( abs(divisor) < static_cast<T>(1))
- {
- // number / divisor > max <=> number > max * divisor
- if( abs(divisor) * std::numeric_limits<T>::max() < abs(number))
- {
- return sig(divisor) * sig(number) * std::numeric_limits<T>::max();
- }
- }
-
- return number / divisor;
- }
- };
-
- template<typename T>
- const typename fpt_traits<T>::StdNumericLimitsNotAvailable
- fpt_traits<T>::static_check[ std::numeric_limits<T>::is_specialized ] = { {} };
-
- template<typename T>
- const T fpt_traits<T>::zero = static_cast<T>(0);
-
- template<typename T, typename U>
- bool check_tolerance(T actual, T expected, U fraction)
- {
- typename fpt_traits<T>::Result diff = fpt_traits<T>::div( fpt_traits<T>::abs( expected - actual ),
- fpt_traits<T>::abs( expected ) );
-
- return (diff == fraction) || (diff < fraction);
- }
-
- } // namespace detail
-
- template<typename T, typename U>
- void ensure_close(const char* msg, const T& actual, const T& expected, const U& tolerance )
- {
- typedef detail::fpt_traits<U> Traits;
-
- typename Traits::Result fraction = Traits::div( Traits::abs(static_cast<typename Traits::Result>(tolerance)),
- static_cast<typename Traits::Result>(100) );
- if( !detail::check_tolerance(actual, expected, fraction) )
- {
- std::ostringstream ss;
- ss << ( msg ? msg : "" )
- << ( msg ? ": " : "" )
- << "expected `"
- << expected
- << "` and actual `"
- << actual
- << "` differ more than "
- << tolerance
- << "%";
- throw failure( ss.str().c_str() );
- }
- }
-
- template<typename T, typename Tolerance>
- void ensure_close(const T& actual, const T& expected, const Tolerance& tolerance )
- {
- ensure_close( 0, actual, expected, tolerance );
- }
-
- template<typename T, typename U>
- void ensure_close_fraction(const char* msg, const T& actual, const T& expected, const U& fraction)
- {
- typedef char StdNumericLimitsNotAvailable;
- const StdNumericLimitsNotAvailable static_check[ std::numeric_limits<U>::is_specialized ] = { 0 };
- static_cast<void>(static_check);
-
- typedef typename detail::If<std::numeric_limits<U>::is_integer,
- double,
- U>::type Tolerance;
-
- if( !detail::check_tolerance(actual, expected, fraction) )
- {
- std::ostringstream ss;
- ss << ( msg ? msg : "" )
- << ( msg ? ": " : "" )
- << "expected `"
- << expected
- << "` and actual `"
- << actual
- << "` differ more than fraction `"
- << fraction
- << "`";
- throw failure( ss.str().c_str() );
- }
- }
-
- template<typename T>
- void ensure_close_fraction( const char* msg, const T& actual, const T& expected, const int& tolerance )
- {
- ensure_close(msg, actual, expected, double(tolerance));
- }
-
- template< typename T, typename Tolerance>
- void ensure_close_fraction(const T& actual, const T& expected, const Tolerance& fraction)
- {
- ensure_close_fraction( 0, actual, expected, fraction );
- }
-
-} // namespace tut
-
-#endif
-