realroot_doc 0.1.1
/Users/mourrain/Devel/mmx/realroot/include/realroot/GMPXX.hpp
Go to the documentation of this file.
00001 #ifndef realroot_ARITHM_GMP_H
00002 #define realroot_ARITHM_GMP_H
00003 
00004 #include <realroot/config.hpp>
00005 #include <realroot/rounding_mode.hpp>
00006 #include <realroot/Interval.hpp>
00007 #include <realroot/sign.hpp>
00008 
00009 #include <gmpxx.h>
00010 
00011 
00012 #ifdef HAVE_MPFR
00013 #include <mpfr.h>
00014 #endif
00015 namespace mmx {
00016 
00017 struct GMP
00018 {
00019   typedef mpz_class integer;
00020   typedef mpq_class rational;
00021   typedef mpf_class floating;
00022   typedef double    ieee;
00023   
00024 };
00025 
00026 
00027 typedef GMP::rational QQ;
00028 typedef GMP::integer  ZZ;
00029 typedef GMP::floating RR;
00030 
00031 
00032 inline long int bit_size(const ZZ& z)  {return mpz_sizeinbase(z.get_mpz_t(),2);}
00033 
00034 namespace meta {
00035 
00036   template<class C> struct kernelof_;
00037   template<> struct kernelof_< GMP::ieee >     { typedef GMP T; };
00038   template<> struct kernelof_< GMP::rational > { typedef GMP T; };
00039   template<> struct kernelof_< GMP::integer  > { typedef GMP T; };
00040   template<> struct kernelof_< GMP::floating > { typedef GMP T; };
00041 
00042   template<class C> struct hasgcd_;
00043   template<> struct hasgcd_<ZZ> { typedef meta::true_t T; };
00044   
00045   template<class C> struct structureof_;
00046   template<> struct structureof_< GMP::rational > { typedef structure::scalar T; };
00047   template<> struct structureof_< GMP::integer  > { typedef structure::scalar T; };
00048   template<> struct structureof_< GMP::floating > { typedef structure::scalar T; };
00049 }
00050   
00051   inline ZZ gcd(const ZZ & a, const ZZ & b)
00052     {
00053       mpz_class r;
00054       mpz_gcd(r.get_mpz_t(), a.get_mpz_t(), b.get_mpz_t());
00055       return r;
00056     }
00057   
00058   inline ZZ lcm(const ZZ & a, const ZZ & b)  { return (a*b)/gcd(a,b); }
00059 
00060 
00061   inline int sign(const QQ& a) { return sgn(a); }
00062   inline int sign(const RR& a) { return sgn(a); }
00063 
00064   inline QQ Size(const QQ & r) { return abs(r); };
00065   inline ZZ Size( const ZZ & z ) { return abs(z); };
00066 
00067   inline ZZ size( const ZZ & z ) { return abs(z); };
00068   inline QQ size(const QQ & r) { return abs(r); };
00069   
00070   
00071   inline int compare(const QQ& a, const QQ& b) { return cmp(a, b); }
00072   inline int compare(const RR& a, const RR& b) { return cmp(a, b); }
00073 
00074   inline bool with_plus_sign(const ZZ & c) { return (c>0);}
00075   inline bool with_plus_sign(const QQ & c) { return (c>0);}
00076   inline bool with_plus_sign(const RR & c) { return (c>0);}
00077   
00078 
00079   inline double to_double(const QQ& a) { return a.get_d(); }
00080   inline double to_double( const ZZ & z ) { return z.get_d(); };
00081   inline double to_double(const RR& a) { return a.get_d(); }
00082 
00083   inline QQ to_FT(const ZZ& a, const ZZ& b = 1)
00084     {
00085       QQ r(a, b);
00086       r.canonicalize();
00087       return r;
00088     }
00089   inline QQ to_FT(const QQ& a, const QQ& b = 1) { return a; }
00090 
00091   inline double to_XT(const ZZ& a) {  return to_double(a);  }
00092   inline double to_XT(const QQ& a) { return to_double(a); }
00093   inline double to_XT(const RR& a) { return to_double(a); }
00094 
00095   inline ZZ numerator(const QQ& a)   { return a.get_num(); }
00096   inline ZZ denominator(const QQ& a) { return a.get_den(); }
00097 
00098   inline ZZ pow(const ZZ& a, unsigned  n)
00099     {
00100       mpz_class r;
00101       mpz_pow_ui(r.get_mpz_t(), a.get_mpz_t(), n);
00102       return r;
00103     }
00104   inline ZZ isqrt(const ZZ& a)    { return sqrt(a) + 1; }
00105   inline RR fracpart(const RR& r) { return r - trunc(r); }
00106 
00107 
00108 //----------------------------------------------------------------------
00112 inline void Precision(unsigned long l)
00113 {
00114     mpf_set_default_prec(l);
00115 }
00116 
00117 //----------------------------------------------------------------------
00121 inline void Precision( RR b, unsigned long l)
00122 {
00123     mpf_set_prec(b.get_mpf_t(),l);
00124 
00125     }
00126 
00127 /*
00128 template<class X>
00129 inline void precision( unsigned nb )
00130 {
00131   typedef kernelof<X>::T K;
00132   K::precision(nb);
00133 };
00134 */
00135 //======================================================================
00136 
00137 namespace let
00138 {
00139   inline void assign(QQ & x, char *s) { mpq_set_str(x.get_mpq_t(), s, 10);}
00140 
00141   inline void assign(ZZ& z, char * s)   { mpz_set_str(z.get_mpz_t(), s, 10); }
00142   inline void assign(ZZ& z, int n)      { mpz_set_si(z.get_mpz_t(),n); }
00143   inline void assign(ZZ& z, double d )  { z = (int)d; };
00144   inline void assign(ZZ& x, const ZZ& r)      { mpz_set(x.get_mpz_t(),r.get_mpz_t()); }
00145   inline void assign(int& x, const ZZ& r)       { x = mpz_get_si(r.get_mpz_t()); }
00146   inline void assign(long int& x, const ZZ& r)  { x = mpz_get_si(r.get_mpz_t()); }
00147   inline void assign( double & r, const ZZ & z ) { r = z.get_d(); };
00148   
00149   inline void assign(ZZ& x, const QQ& r) { x= r.get_num(); x/=r.get_den();}
00150   inline void assign(QQ& x, const ZZ& r) { mpq_set_z(x.get_mpq_t(), r.get_mpz_t());}
00151   inline void assign(QQ & q, double d ) { q = d; };
00152   inline void assign(RR & r, double d ) { r = d; };
00153   inline void assign(double & d, const QQ & x ) 
00154   {
00155 #ifdef HAVE_MPFR 
00156     mp_rnd_t round=GMP_RNDU;
00157     //    if(numerics::get_rnd()==numerics::rnd_up())
00158     //      round=GMP_RNDU;
00159 
00160     if(numerics::get_rnd()==numerics::rnd_dw())
00161       round=GMP_RNDD;
00162 
00163     mpfr_t r; mpfr_init2(r,53);
00164     mpfr_set_q(r, x.get_mpq_t(), round);
00165     d = mpfr_get_d(r,round);
00166 #else
00167        d = x.get_d(); 
00168 #endif
00169   }
00170 
00171   inline void assign(double & r, const RR & z ) { r = z.get_d(); };  
00172   inline void assign(RR& r, char* s)        { mpf_set_str(r.get_mpf_t(),s,10); }
00173   inline void assign(RR& x, const RR& r)    { mpf_set(x.get_mpf_t(),r.get_mpf_t()); }
00174 
00175   inline double convert( const QQ & q, meta::As<double> ) { return q.get_d(); };
00176   inline double convert( const ZZ & z, meta::As<double> ) { return z.get_d(); };
00177   inline double convert( const RR & r, meta::As<double> ) { return r.get_d(); };
00178 
00179   inline void assign( Interval<double>& a, 
00180                       const QQ & b )
00181     {
00182       double  mn,mx;
00183       {
00184         numerics::rounding<double> rnd( numerics::rnd_up() );
00185         assign(mx,b);
00186       }
00187       {
00188         numerics::rounding<double> rnd( numerics::rnd_dw() );
00189         assign(mn,b);
00190       }
00191       
00192       if( mx < mn ) std::swap(mn,mx);
00193       QQ MN(mn);
00194       QQ MX(mx);
00195       new (&a) Interval<double>(mn,mx);
00196     };
00197   inline void assign( Interval<double>& a, 
00198                       const QQ & u,
00199                       const QQ & v )
00200     {
00201       double  mn,mx;
00202       {
00203         numerics::rounding<double> rnd( numerics::rnd_up() );
00204         assign(mx,v);
00205       }
00206       {
00207         numerics::rounding<double> rnd( numerics::rnd_dw() );
00208         assign(mn,u);
00209       }
00210       new (&a) Interval<double>(mn,mx);
00211     };
00212 
00213 
00214   inline void assign( Interval<QQ>& a, 
00215                       const QQ & u,
00216                       const QQ & v )
00217   {
00218     a.lower()=u;
00219     a.upper()=v;
00220   }
00221 }
00222 
00223 template<class T, class U> struct cast_helper;
00224 
00225 template<> struct cast_helper<QQ,ZZ>     { static inline QQ cv(const ZZ& x)     { QQ r;mpq_set_z(r.get_mpq_t(),x.get_mpz_t()); return r; } };
00226 
00227 template<> struct cast_helper<double,ZZ> { static inline double cv(const ZZ& x) { return x.get_d(); } };
00228 template<> struct cast_helper<double,QQ> { static inline double cv(const QQ& x) { double r; let::assign(r,x); return r; } };
00229 template<> struct cast_helper<double,RR> { static inline double cv(const RR& x) { return x.get_d(); } };
00230 
00231 //====================================================================
00232 } //namespace mmx
00233 #endif