00001
00002
00003
00004
00005
00006 #ifndef SYNAPS_NUMERICS_EPSILON_HPP
00007 #define SYNAPS_NUMERICS_EPSILON_HPP
00008 #include <synaps/init.h>
00009 #include <synaps/arithm/rounding.h>
00010
00011 __BEGIN_NAMESPACE_SYNAPS
00012
00013 namespace numerics
00014 {
00015
00016 struct false_t{};
00017 struct true_t {};
00018 template < typename T > struct inexact { typedef false_t result_t; };
00019 template <> struct inexact<long double>{ typedef true_t result_t; };
00020 template < typename T > struct epsilon {
00021 static T result;
00022 static T _init_(const true_t&) {
00023 volatile T half(0.5), curr(1.0), one(1.0), prev, eps(1.0);
00024 do
00025 {
00026 prev = curr;
00027 eps *= half;
00028 curr = one+eps;
00029 }
00030 while ((curr!=1.0)&&(curr!=prev));
00031 return eps;
00032 };
00033 static T _init_(const false_t&) { return T(0); };
00034 static T _init_() { return _init_(typename inexact< typename LongVersion<T>::result_t >::result_t()); };
00035 };
00036 template < typename T > T epsilon<T>::result = epsilon<T>::_init_();
00037 };
00038
00039 __END_NAMESPACE_SYNAPS
00040
00041 #endif //