synaps/arithm/rounding.h

00001 /********************************************************************
00002  *   This file is part of the source code of the SYNAPS library.
00003  *   Author(s): J.P. Pavone, GALAAD, INRIA
00004  *   $Id: fpu.h,v 1.1 2005/07/11 09:15:23 mourrain Exp $
00005  ********************************************************************/
00006 #ifndef SYNAPS_NUMERICS_FPU_HPP
00007 #define SYNAPS_NUMERICS_FPU_HPP
00008 //--------------------------------------------------------------------
00009 #include <fenv.h>
00010 #include <synaps/init.h>
00011 //--------------------------------------------------------------------
00012 __BEGIN_NAMESPACE_SYNAPS
00013 //--------------------------------------------------------------------
00014 namespace numerics
00015 {
00016   inline int get_cw()  { return fegetround(); };
00017   inline int get_rnd() { return fegetround(); };
00018   inline void set_cw( int cw ) { fesetround(cw);};
00019   inline static int rnd_up() { return FE_UPWARD;};
00020   inline static int rnd_dw() { return FE_DOWNWARD;};
00021   inline static int rnd_nr() { return FE_TONEAREST;};
00022   inline static int rnd_z()  { return FE_TOWARDZERO;};
00023   template< typename T > struct LongVersion { typedef T result_t; };
00024   template<> struct LongVersion<float>  { typedef long double result_t; };
00025   template<> struct LongVersion<double> { typedef long double result_t; };
00026   template< typename T > struct fpu_rounding { 
00027     static const int id = 0; 
00028     typedef int rnd_t;
00029     inline static rnd_t  getrnd() { return 0; };
00030     inline static void   setrnd( rnd_t r ) { };
00031     inline static int rnd_up() { return 0; };
00032     inline static int rnd_dw() { return 0; };
00033     inline static int rnd_nr() { return 0; };
00034     inline static int rnd_z()  { return 0; };
00035     fpu_rounding( int ){}; 
00036   };
00037   template<> struct fpu_rounding<long double> 
00038   { 
00039     typedef int rnd_t;
00040     inline static rnd_t  getrnd() { return fegetround(); };
00041     inline static void   setrnd( rnd_t r ) { fesetround(r); };
00042     inline static int rnd_up() { return FE_UPWARD;};
00043     inline static int rnd_dw() { return FE_DOWNWARD;};
00044     inline static int rnd_nr() { return FE_TONEAREST;};
00045     inline static int rnd_z()  { return FE_TOWARDZERO;};
00046     static const int id = 1;
00047     rnd_t m_prev;
00048     bool  m_chg;
00049     fpu_rounding( rnd_t rnd ) 
00050     {
00051       m_chg = false;
00052       rnd_t m_prev = getrnd();
00053       if ( m_prev != rnd ) 
00054         { 
00055           m_chg = true;
00056           setrnd(rnd); 
00057         };
00058     };
00059     ~fpu_rounding() { 
00060       if ( m_chg ) setrnd(m_prev);
00061     };
00062   };
00063   
00064   template< typename T >
00065   struct rounding : fpu_rounding< typename LongVersion< T >::result_t >  
00066   { rounding( int rnd ) : fpu_rounding< typename LongVersion< T >::result_t >( rnd ) {}; };
00067   
00068   template< typename T > inline T div_dw(const T& a, const T& b) { rounding<T> r(rnd_dw()); return a/b; };
00069   template< typename T > inline T div_up(const T& a, const T& b) { rounding<T> r(rnd_up()); return a/b; };
00070   template< typename T > inline T add_dw(const T& a, const T& b) { rounding<T> r(rnd_dw()); return a+b; };
00071   template< typename T > inline T add_up(const T& a, const T& b) { rounding<T> r(rnd_up()); return a+b; };
00072   template< typename T > inline T mul_dw(const T& a, const T& b) { rounding<T> r(rnd_dw()); return a*b; };
00073   template< typename T > inline T mul_up(const T& a, const T& b) { rounding<T> r(rnd_up()); return a*b; };
00074   template< typename T > inline T sub_dw(const T& a, const T& b) { rounding<T> r(rnd_dw()); return a-b; };
00075   template< typename T > inline T sub_up(const T& a, const T& b) { rounding<T> r(rnd_up()); return a-b; };
00076 };
00077 
00078 //--------------------------------------------------------------------
00079 __END_NAMESPACE_SYNAPS
00080 /********************************************************************/
00081 #endif //

SYNAPS DOCUMENTATION
logo