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 //