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
00129
00130
00131
00132
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
00158
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 }
00233 #endif