realroot_doc 0.1.1
|
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