00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <cstring>
00028 #include "mpreal.h"
00029
00030 using std::ws;
00031 using std::cerr;
00032 using std::endl;
00033 using std::string;
00034 using std::ostream;
00035 using std::istream;
00036
00037 namespace mpfr{
00038
00039 mp_rnd_t mpreal::default_rnd = mpfr_get_default_rounding_mode();
00040 mp_prec_t mpreal::default_prec = mpfr_get_default_prec();
00041 int mpreal::default_base = 10;
00042 int mpreal::double_bits = -1;
00043
00044
00045 mpreal::mpreal()
00046 {
00047 mpfr_init2(mp,default_prec);
00048 mpfr_set_ui(mp,0,default_rnd);
00049 }
00050
00051 mpreal::mpreal(const mpreal& u)
00052 {
00053 mpfr_init2(mp,mpfr_get_prec(u.mp));
00054 mpfr_set(mp,u.mp,default_rnd);
00055 }
00056
00057 mpreal::mpreal(const mpfr_t u)
00058 {
00059 mpfr_init2(mp,mpfr_get_prec(u));
00060 mpfr_set(mp,u,default_rnd);
00061 }
00062
00063 mpreal::mpreal(const mpf_t u)
00064 {
00065 mpfr_init2(mp,mpf_get_prec(u));
00066 mpfr_set_f(mp,u,default_rnd);
00067 }
00068
00069 mpreal::mpreal(const mpz_t u, mp_prec_t prec, mp_rnd_t mode)
00070 {
00071 mpfr_init2(mp,prec);
00072 mpfr_set_z(mp,u,mode);
00073 }
00074
00075 mpreal::mpreal(const mpq_t u, mp_prec_t prec, mp_rnd_t mode)
00076 {
00077 mpfr_init2(mp,prec);
00078 mpfr_set_q(mp,u,mode);
00079 }
00080
00081 mpreal::mpreal(const double u, mp_prec_t prec, mp_rnd_t mode)
00082 {
00083 if(double_bits == -1 || fits_in_bits(u, double_bits))
00084 {
00085 mpfr_init2(mp,prec);
00086 mpfr_set_d(mp,u,mode);
00087 }
00088 else
00089 throw conversion_overflow();
00090 }
00091
00092 mpreal::mpreal(const long double u, mp_prec_t prec, mp_rnd_t mode)
00093 {
00094 mpfr_init2(mp,prec);
00095 mpfr_set_ld(mp,u,mode);
00096 }
00097
00098 mpreal::mpreal(const unsigned long int u, mp_prec_t prec, mp_rnd_t mode)
00099 {
00100 mpfr_init2(mp,prec);
00101 mpfr_set_ui(mp,u,mode);
00102 }
00103
00104 mpreal::mpreal(const unsigned int u, mp_prec_t prec, mp_rnd_t mode)
00105 {
00106 mpfr_init2(mp,prec);
00107 mpfr_set_ui(mp,u,mode);
00108 }
00109
00110 mpreal::mpreal(const long int u, mp_prec_t prec, mp_rnd_t mode)
00111 {
00112 mpfr_init2(mp,prec);
00113 mpfr_set_si(mp,u,mode);
00114 }
00115
00116 mpreal::mpreal(const int u, mp_prec_t prec, mp_rnd_t mode)
00117 {
00118 mpfr_init2(mp,prec);
00119 mpfr_set_si(mp,u,mode);
00120 }
00121
00122 mpreal::mpreal(const char* s, mp_prec_t prec, int base, mp_rnd_t mode)
00123 {
00124 mpfr_init2(mp,prec);
00125 mpfr_set_str(mp, s, base, mode);
00126 }
00127
00128 mpreal::~mpreal()
00129 {
00130 mpfr_clear(mp);
00131 }
00132
00133
00134 mpreal& mpreal::operator=(const char* s)
00135 {
00136 mpfr_t t;
00137 if(0==mpfr_init_set_str(t,s,default_base,default_rnd))
00138 {
00139 mpfr_set(mp,t,mpreal::default_rnd);
00140 mpfr_clear(t);
00141 }else{
00142 mpfr_clear(t);
00143
00144 }
00145
00146 return *this;
00147 }
00148
00149 const mpreal fma (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode)
00150 {
00151 mpreal a;
00152 mp_prec_t p1, p2, p3;
00153
00154 p1 = v1.get_prec();
00155 p2 = v2.get_prec();
00156 p3 = v3.get_prec();
00157
00158 a.set_prec(p3>p2?(p3>p1?p3:p1):(p2>p1?p2:p1));
00159
00160 mpfr_fma(a.mp,v1.mp,v2.mp,v3.mp,rnd_mode);
00161 return a;
00162 }
00163
00164 const mpreal fms (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode)
00165 {
00166 mpreal a;
00167 mp_prec_t p1, p2, p3;
00168
00169 p1 = v1.get_prec();
00170 p2 = v2.get_prec();
00171 p3 = v3.get_prec();
00172
00173 a.set_prec(p3>p2?(p3>p1?p3:p1):(p2>p1?p2:p1));
00174
00175 mpfr_fms(a.mp,v1.mp,v2.mp,v3.mp,rnd_mode);
00176 return a;
00177 }
00178
00179 const mpreal agm (const mpreal& v1, const mpreal& v2, mp_rnd_t rnd_mode)
00180 {
00181 mpreal a;
00182 mp_prec_t p1, p2;
00183
00184 p1 = v1.get_prec();
00185 p2 = v2.get_prec();
00186
00187 a.set_prec(p1>p2?p1:p2);
00188
00189 mpfr_agm(a.mp, v1.mp, v2.mp, rnd_mode);
00190
00191 return a;
00192 }
00193
00194 const mpreal hypot (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode)
00195 {
00196 mpreal a;
00197 mp_prec_t yp, xp;
00198
00199 yp = y.get_prec();
00200 xp = x.get_prec();
00201
00202 a.set_prec(yp>xp?yp:xp);
00203
00204 mpfr_hypot(a.mp, x.mp, y.mp, rnd_mode);
00205
00206 return a;
00207 }
00208
00209 const mpreal sum (const mpreal tab[], unsigned long int n, mp_rnd_t rnd_mode)
00210 {
00211 mpreal x;
00212 mpfr_ptr* t;
00213 unsigned long int i;
00214
00215 t = new mpfr_ptr[n];
00216 for (i=0;i<n;i++) t[i] = (mpfr_ptr)tab[i].mp;
00217 mpfr_sum(x.mp,t,n,rnd_mode);
00218 delete[] t;
00219 return x;
00220 }
00221
00222 const mpreal remainder (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode)
00223 {
00224 mpreal a;
00225 mp_prec_t yp, xp;
00226
00227 yp = y.get_prec();
00228 xp = x.get_prec();
00229
00230 a.set_prec(yp>xp?yp:xp);
00231
00232 mpfr_remainder(a.mp, x.mp, y.mp, rnd_mode);
00233
00234 return a;
00235 }
00236
00237 const mpreal remquo (long* q, const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode)
00238 {
00239 mpreal a;
00240 mp_prec_t yp, xp;
00241
00242 yp = y.get_prec();
00243 xp = x.get_prec();
00244
00245 a.set_prec(yp>xp?yp:xp);
00246
00247 mpfr_remquo(a.mp,q, x.mp, y.mp, rnd_mode);
00248
00249 return a;
00250 }
00251
00252 template <class T>
00253 std::string to_string(T t, std::ios_base & (*f)(std::ios_base&))
00254 {
00255 std::ostringstream oss;
00256 oss << f << t;
00257 return oss.str();
00258 }
00259
00260 mpreal::operator std::string() const
00261 {
00262 return to_string();
00263 }
00264
00265 string mpreal::to_string(size_t n, int b, mp_rnd_t mode) const
00266 {
00267 char *s, *ns = NULL;
00268 size_t slen, nslen;
00269 mp_exp_t exp;
00270 string out;
00271
00272 if(mpfr_inf_p(mp))
00273 {
00274 if(mpfr_sgn(mp)>0) return "+@Inf@";
00275 else return "-@Inf@";
00276 }
00277
00278 if(mpfr_zero_p(mp)) return "0";
00279 if(mpfr_nan_p(mp)) return "@NaN@";
00280
00281
00282 s = mpfr_get_str(NULL,&exp,b,0,mp,mode);
00283 ns = mpfr_get_str(NULL,&exp,b,n,mp,mode);
00284
00285 if(s!=NULL && ns!=NULL)
00286 {
00287 slen = strlen(s);
00288 nslen = strlen(ns);
00289 if(nslen<=slen)
00290 {
00291 mpfr_free_str(s);
00292 s = ns;
00293 slen = nslen;
00294 }
00295 else {
00296 mpfr_free_str(ns);
00297 }
00298
00299
00300 if (exp>0 && static_cast<size_t>(exp)<slen)
00301 {
00302 if(s[0]=='-')
00303 {
00304
00305 char* ptr = s+slen-1;
00306 while (*ptr=='0' && ptr>s+exp) ptr--;
00307
00308 if(ptr==s+exp) out = string(s,exp+1);
00309 else out = string(s,exp+1)+'.'+string(s+exp+1,ptr-(s+exp+1)+1);
00310
00311
00312 }
00313 else
00314 {
00315
00316 char* ptr = s+slen-1;
00317 while (*ptr=='0' && ptr>s+exp-1) ptr--;
00318
00319 if(ptr==s+exp-1) out = string(s,exp);
00320 else out = string(s,exp)+'.'+string(s+exp,ptr-(s+exp)+1);
00321
00322
00323 }
00324
00325 }else{
00326 if(s[0]=='-')
00327 {
00328
00329 char* ptr = s+slen-1;
00330 while (*ptr=='0' && ptr>s+1) ptr--;
00331
00332 if(ptr==s+1) out = string(s,2);
00333 else out = string(s,2)+'.'+string(s+2,ptr-(s+2)+1);
00334
00335
00336 }
00337 else
00338 {
00339
00340 char* ptr = s+slen-1;
00341 while (*ptr=='0' && ptr>s) ptr--;
00342
00343 if(ptr==s) out = string(s,1);
00344 else out = string(s,1)+'.'+string(s+1,ptr-(s+1)+1);
00345
00346
00347 }
00348
00349
00350 if(--exp)
00351 {
00352 if(exp>0) out += "e+"+mpfr::to_string<mp_exp_t>(exp,std::dec);
00353 else out += "e"+mpfr::to_string<mp_exp_t>(exp,std::dec);
00354 }
00355 }
00356
00357 mpfr_free_str(s);
00358 return out;
00359 }else{
00360 return "conversion error!";
00361 }
00362 }
00363
00365
00366 ostream& operator<<(ostream& os, const mpreal& v)
00367 {
00368 return os<<v.to_string(os.precision());
00369 }
00370
00371 istream& operator>>(istream &is, mpreal& v)
00372 {
00373 char c;
00374 string s = "";
00375 mpfr_t t;
00376
00377 if(is.good())
00378 {
00379 is>>ws;
00380 while ((c = is.get())!=EOF)
00381 {
00382 if(c ==' ' || c == '\t' || c == '\n' || c == '\r')
00383 {
00384 is.putback(c);
00385 break;
00386 }
00387 s += c;
00388 }
00389
00390 if(s.size() != 0)
00391 {
00392
00393
00394 if(0==mpfr_init_set_str(t,s.c_str(),mpreal::default_base,mpreal::default_rnd))
00395 {
00396 mpfr_set(v.mp,t,mpreal::default_rnd);
00397 mpfr_clear(t);
00398
00399 }else{
00400 mpfr_clear(t);
00401 cerr<<"error reading from istream"<<endl;
00402
00403 }
00404 }
00405 }
00406 return is;
00407 }
00408 }