2 * @brief Additional ensures for scientific/engineering applications.
3 * @author Joerg <yogi2005@users.sourceforge.net>
6 #ifndef TUT_Float_H_GUARD
7 #define TUT_Float_H_GUARD
16 template<bool Predicate, typename Then, typename Else>
22 template<typename Then, typename Else>
23 struct If<true,Then,Else>
31 struct StdNumericLimitsNotAvailable {};
32 static const StdNumericLimitsNotAvailable static_check[ std::numeric_limits<T>::is_specialized ];
36 typedef typename If<std::numeric_limits<T>::is_integer,
40 static T abs(const T &arg)
48 static T sig(const T &arg)
56 static inline Result div(const Result &number, const T &divisor)
58 static_cast<void>(static_check);
60 if(number == zero && divisor == zero)
61 return std::numeric_limits<Result>::quiet_NaN();
67 return sig(number) * std::numeric_limits<Result>::infinity();
69 assert(zero < number);
70 assert(zero < divisor);
73 if(static_cast<T>(1) < abs(divisor))
75 // number / divisor < min <=> number < min * divisor
76 if( abs(number) < abs(divisor) * std::numeric_limits<T>::min())
78 return sig(divisor) * sig(number) * std::numeric_limits<T>::min();
83 if( abs(divisor) < static_cast<T>(1))
85 // number / divisor > max <=> number > max * divisor
86 if( abs(divisor) * std::numeric_limits<T>::max() < abs(number))
88 return sig(divisor) * sig(number) * std::numeric_limits<T>::max();
92 return number / divisor;
97 const typename fpt_traits<T>::StdNumericLimitsNotAvailable
98 fpt_traits<T>::static_check[ std::numeric_limits<T>::is_specialized ] = { {} };
101 const T fpt_traits<T>::zero = static_cast<T>(0);
103 template<typename T, typename U>
104 bool check_tolerance(T actual, T expected, U fraction)
106 typename fpt_traits<T>::Result diff = fpt_traits<T>::div( fpt_traits<T>::abs( expected - actual ),
107 fpt_traits<T>::abs( expected ) );
109 return (diff == fraction) || (diff < fraction);
112 } // namespace detail
114 template<typename T, typename U>
115 void ensure_close(const char* msg, const T& actual, const T& expected, const U& tolerance )
117 typedef detail::fpt_traits<U> Traits;
119 typename Traits::Result fraction = Traits::div( Traits::abs(static_cast<typename Traits::Result>(tolerance)),
120 static_cast<typename Traits::Result>(100) );
121 if( !detail::check_tolerance(actual, expected, fraction) )
123 std::ostringstream ss;
124 ss << ( msg ? msg : "" )
125 << ( msg ? ": " : "" )
130 << "` differ more than "
133 throw failure( ss.str().c_str() );
137 template<typename T, typename Tolerance>
138 void ensure_close(const T& actual, const T& expected, const Tolerance& tolerance )
140 ensure_close( 0, actual, expected, tolerance );
143 template<typename T, typename U>
144 void ensure_close_fraction(const char* msg, const T& actual, const T& expected, const U& fraction)
146 typedef char StdNumericLimitsNotAvailable;
147 const StdNumericLimitsNotAvailable static_check[ std::numeric_limits<U>::is_specialized ] = { 0 };
148 static_cast<void>(static_check);
150 typedef typename detail::If<std::numeric_limits<U>::is_integer,
154 if( !detail::check_tolerance(actual, expected, fraction) )
156 std::ostringstream ss;
157 ss << ( msg ? msg : "" )
158 << ( msg ? ": " : "" )
163 << "` differ more than fraction `"
166 throw failure( ss.str().c_str() );
171 void ensure_close_fraction( const char* msg, const T& actual, const T& expected, const int& tolerance )
173 ensure_close(msg, actual, expected, double(tolerance));
176 template< typename T, typename Tolerance>
177 void ensure_close_fraction(const T& actual, const T& expected, const Tolerance& fraction)
179 ensure_close_fraction( 0, actual, expected, fraction );