mpreal.cpp
Go to the documentation of this file.
00001 /*
00002         Multi-precision real number class. C++ interface fo MPFR library.
00003         Project homepage: http://www.holoborodko.com/pavel/
00004         Contact e-mail:   pavel@holoborodko.com
00005 
00006         Copyright (c) 2008-2010 Pavel Holoborodko
00007 
00008         Core Developers: 
00009         Pavel Holoborodko, Dmitriy Gubanov, Konstantin Holoborodko. 
00010 
00011         Contributors:
00012         Brian Gladman, Helmut Jarausch, Fokko Beekhof, Ulrich Mutze, 
00013         Heinz van Saanen, Pere Constans, Peter van Hoof.
00014 
00015         ****************************************************************************
00016         This library is free software; you can redistribute it and/or
00017         modify it under the terms of the GNU Lesser General Public
00018         License as published by the Free Software Foundation; either
00019         version 2.1 of the License, or (at your option) any later version.
00020 
00021         This library is distributed in the hope that it will be useful,
00022         but WITHOUT ANY WARRANTY; without even the implied warranty of
00023         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00024         Lesser General Public License for more details.
00025 
00026         You should have received a copy of the GNU Lesser General Public
00027         License along with this library; if not, write to the Free Software
00028         Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00029 
00030         ****************************************************************************
00031         Redistribution and use in source and binary forms, with or without
00032         modification, are permitted provided that the following conditions
00033         are met:
00034         
00035         1. Redistributions of source code must retain the above copyright
00036         notice, this list of conditions and the following disclaimer.
00037         
00038         2. Redistributions in binary form must reproduce the above copyright
00039         notice, this list of conditions and the following disclaimer in the
00040         documentation and/or other materials provided with the distribution.
00041         
00042         3. Redistributions of any form whatsoever must retain the following
00043         acknowledgment:
00044         "
00045          This product includes software developed by Pavel Holoborodko
00046          Web: http://www.holoborodko.com/pavel/
00047          e-mail: pavel@holoborodko.com
00048         "
00049 
00050         4. This software cannot be, by any means, used for any commercial 
00051         purpose without the prior permission of the copyright holder.
00052         
00053         Any of the above conditions can be waived if you get permission from 
00054         the copyright holder. 
00055 
00056         THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
00057         ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00058         IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00059         ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
00060         FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00061         DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00062         OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00063         HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00064         LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00065         OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00066         SUCH DAMAGE.
00067 */
00068 #include <cstring>
00069 #include <cstdlib>
00070 #include "mpreal.h"
00071 #include "dlmalloc.h"
00072 
00073 using std::ws;
00074 using std::cerr;
00075 using std::endl;
00076 using std::string;
00077 using std::ostream;
00078 using std::istream;
00079 
00080 namespace mpfr{
00081 
00082 mp_rnd_t   mpreal::default_rnd  = mpfr_get_default_rounding_mode();     
00083 mp_prec_t  mpreal::default_prec = mpfr_get_default_prec();      
00084 int                mpreal::default_base = 10;
00085 int        mpreal::double_bits = -1;
00086 bool       mpreal::is_custom_malloc = false;
00087 
00088 // Default constructor: creates mp number and initializes it to 0.
00089 mpreal::mpreal() 
00090 { 
00091         set_custom_malloc();
00092         mpfr_init2(mp,default_prec); 
00093         mpfr_set_ui(mp,0,default_rnd);
00094 }
00095 
00096 mpreal::mpreal(const mpreal& u) 
00097 {
00098         set_custom_malloc();
00099         mpfr_init2(mp,mpfr_get_prec(u.mp));
00100         mpfr_set(mp,u.mp,default_rnd);
00101 }
00102 
00103 mpreal::mpreal(const mpfr_t u)
00104 {
00105         set_custom_malloc();
00106         mpfr_init2(mp,mpfr_get_prec(u));
00107         mpfr_set(mp,u,default_rnd);
00108 }
00109 
00110 mpreal::mpreal(const mpf_t u)
00111 {
00112         set_custom_malloc();
00113         mpfr_init2(mp,mpf_get_prec(u));
00114         mpfr_set_f(mp,u,default_rnd);
00115 }
00116 
00117 mpreal::mpreal(const mpz_t u, mp_prec_t prec, mp_rnd_t mode)
00118 {
00119         set_custom_malloc();
00120         mpfr_init2(mp,prec);
00121         mpfr_set_z(mp,u,mode);
00122 }
00123 
00124 mpreal::mpreal(const mpq_t u, mp_prec_t prec, mp_rnd_t mode)
00125 {
00126         set_custom_malloc();
00127         mpfr_init2(mp,prec);
00128         mpfr_set_q(mp,u,mode);
00129 }
00130 
00131 mpreal::mpreal(const double u, mp_prec_t prec, mp_rnd_t mode)
00132 {
00133         set_custom_malloc();
00134     if(double_bits == -1 || fits_in_bits(u, double_bits))
00135     {
00136         mpfr_init2(mp,prec);
00137             mpfr_set_d(mp,u,mode);
00138     }
00139     else
00140         throw conversion_overflow();
00141 }
00142 
00143 mpreal::mpreal(const long double u, mp_prec_t prec, mp_rnd_t mode)
00144 { 
00145         set_custom_malloc();
00146     mpfr_init2(mp,prec);
00147         mpfr_set_ld(mp,u,mode);
00148 }
00149 
00150 mpreal::mpreal(const unsigned long int u, mp_prec_t prec, mp_rnd_t mode)
00151 { 
00152         set_custom_malloc();
00153         mpfr_init2(mp,prec);
00154         mpfr_set_ui(mp,u,mode);
00155 }
00156 
00157 mpreal::mpreal(const unsigned int u, mp_prec_t prec, mp_rnd_t mode)
00158 { 
00159         set_custom_malloc();
00160         mpfr_init2(mp,prec);
00161         mpfr_set_ui(mp,u,mode);
00162 }
00163 
00164 mpreal::mpreal(const long int u, mp_prec_t prec, mp_rnd_t mode)
00165 { 
00166         set_custom_malloc();
00167         mpfr_init2(mp,prec);
00168         mpfr_set_si(mp,u,mode);
00169 }
00170 
00171 mpreal::mpreal(const int u, mp_prec_t prec, mp_rnd_t mode)
00172 { 
00173         set_custom_malloc();
00174         mpfr_init2(mp,prec);
00175         mpfr_set_si(mp,u,mode);
00176 }
00177 
00178 mpreal::mpreal(const char* s, mp_prec_t prec, int base, mp_rnd_t mode)
00179 {
00180         set_custom_malloc();
00181         mpfr_init2(mp,prec);
00182         mpfr_set_str(mp, s, base, mode); 
00183 }
00184 
00185 mpreal::mpreal(const std::string& s, mp_prec_t prec, int base, mp_rnd_t mode)
00186 {
00187         set_custom_malloc();
00188         mpfr_init2(mp,prec);
00189         mpfr_set_str(mp, s.c_str(), base, mode); 
00190 }
00191 
00192 mpreal::~mpreal() 
00193 { 
00194         mpfr_clear(mp);
00195 }                           
00196 
00197 // Operators - Assignment
00198 mpreal& mpreal::operator=(const char* s)
00199 {
00200         mpfr_t t;
00201         
00202         set_custom_malloc();
00203 
00204         if(0==mpfr_init_set_str(t,s,default_base,default_rnd))
00205         {
00206                 // We will rewrite mp anyway, so use flash it and resize
00207                 mpfr_set_prec(mp,mpfr_get_prec(t)); //<- added 01.04.2011
00208                 mpfr_set(mp,t,mpreal::default_rnd);
00209                 mpfr_clear(t);
00210         }else{
00211                 mpfr_clear(t);
00212                 // cerr<<"fail to convert string"<<endl;
00213         }
00214 
00215         return *this;
00216 }
00217 
00218 const mpreal fma (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode)
00219 {
00220         mpreal a;
00221         mp_prec_t p1, p2, p3;
00222 
00223         p1 = v1.get_prec(); 
00224         p2 = v2.get_prec(); 
00225         p3 = v3.get_prec(); 
00226 
00227         a.set_prec(p3>p2?(p3>p1?p3:p1):(p2>p1?p2:p1));
00228 
00229         mpfr_fma(a.mp,v1.mp,v2.mp,v3.mp,rnd_mode);
00230         return a;
00231 }
00232 
00233 const mpreal fms (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode)
00234 {
00235         mpreal a;
00236         mp_prec_t p1, p2, p3;
00237 
00238         p1 = v1.get_prec(); 
00239         p2 = v2.get_prec(); 
00240         p3 = v3.get_prec(); 
00241 
00242         a.set_prec(p3>p2?(p3>p1?p3:p1):(p2>p1?p2:p1));
00243 
00244         mpfr_fms(a.mp,v1.mp,v2.mp,v3.mp,rnd_mode);
00245         return a;
00246 }
00247 
00248 const mpreal agm (const mpreal& v1, const mpreal& v2, mp_rnd_t rnd_mode)
00249 {
00250         mpreal a;
00251         mp_prec_t p1, p2;
00252 
00253         p1 = v1.get_prec(); 
00254         p2 = v2.get_prec(); 
00255 
00256         a.set_prec(p1>p2?p1:p2);
00257 
00258         mpfr_agm(a.mp, v1.mp, v2.mp, rnd_mode);
00259 
00260         return a;
00261 }
00262 
00263 const mpreal hypot (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode)
00264 {
00265         mpreal a;
00266         mp_prec_t yp, xp;
00267 
00268         yp = y.get_prec(); 
00269         xp = x.get_prec(); 
00270 
00271         a.set_prec(yp>xp?yp:xp);
00272 
00273         mpfr_hypot(a.mp, x.mp, y.mp, rnd_mode);
00274 
00275         return a;
00276 }
00277 
00278 const mpreal sum (const mpreal tab[], unsigned long int n, mp_rnd_t rnd_mode)
00279 {
00280         mpreal x;
00281         mpfr_ptr* t;
00282         unsigned long int i;
00283 
00284         t = new mpfr_ptr[n];
00285         for (i=0;i<n;i++) t[i] = (mpfr_ptr)tab[i].mp;
00286         mpfr_sum(x.mp,t,n,rnd_mode);
00287         delete[] t;
00288         return x;
00289 }
00290 
00291 const mpreal remainder (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode)
00292 {       
00293         mpreal a;
00294         mp_prec_t yp, xp;
00295 
00296         yp = y.get_prec(); 
00297         xp = x.get_prec(); 
00298 
00299         a.set_prec(yp>xp?yp:xp);
00300 
00301         mpfr_remainder(a.mp, x.mp, y.mp, rnd_mode);
00302 
00303         return a;
00304 }
00305 
00306 const mpreal remquo (long* q, const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode)
00307 {
00308         mpreal a;
00309         mp_prec_t yp, xp;
00310 
00311         yp = y.get_prec(); 
00312         xp = x.get_prec(); 
00313 
00314         a.set_prec(yp>xp?yp:xp);
00315 
00316         mpfr_remquo(a.mp,q, x.mp, y.mp, rnd_mode);
00317 
00318         return a;
00319 }
00320 
00321 template <class T>
00322 std::string to_string(T t, std::ios_base & (*f)(std::ios_base&))
00323 {
00324         std::ostringstream oss;
00325         oss << f << t;
00326         return oss.str();
00327 }
00328 
00329 mpreal::operator std::string() const
00330 {
00331         return to_string();
00332 }
00333 
00334 std::string mpreal::to_string(size_t n, int b, mp_rnd_t mode) const
00335 {
00336         char *s, *ns = NULL;    
00337         size_t slen, nslen;
00338         mp_exp_t exp;
00339         string out;
00340         
00341         set_custom_malloc();
00342         
00343         if(mpfr_inf_p(mp))
00344         { 
00345                 if(mpfr_sgn(mp)>0) return "+@Inf@";
00346                 else                       return "-@Inf@";
00347         }
00348 
00349         if(mpfr_zero_p(mp)) return "0";
00350         if(mpfr_nan_p(mp))  return "@NaN@";
00351                 
00352         s  = mpfr_get_str(NULL,&exp,b,0,mp,mode);
00353         ns = mpfr_get_str(NULL,&exp,b,n,mp,mode);
00354 
00355         if(s!=NULL && ns!=NULL)
00356         {
00357                 slen  = strlen(s);
00358                 nslen = strlen(ns);
00359                 if(nslen<=slen) 
00360                 {
00361                         mpfr_free_str(s);
00362                         s = ns;
00363                         slen = nslen;
00364                 }
00365                 else {
00366                         mpfr_free_str(ns);
00367                 }
00368 
00369                 // Make human eye-friendly formatting if possible
00370                 if (exp>0 && static_cast<size_t>(exp)<slen)
00371                 {
00372                         if(s[0]=='-')
00373                         {
00374                                 // Remove zeros starting from right end
00375                                 char* ptr = s+slen-1;
00376                                 while (*ptr=='0' && ptr>s+exp) ptr--; 
00377 
00378                                 if(ptr==s+exp) out = string(s,exp+1);
00379                                 else               out = string(s,exp+1)+'.'+string(s+exp+1,ptr-(s+exp+1)+1);
00380 
00381                                 //out = string(s,exp+1)+'.'+string(s+exp+1);
00382                         }
00383                         else
00384                         {
00385                                 // Remove zeros starting from right end
00386                                 char* ptr = s+slen-1;
00387                                 while (*ptr=='0' && ptr>s+exp-1) ptr--; 
00388 
00389                                 if(ptr==s+exp-1) out = string(s,exp);
00390                                 else                 out = string(s,exp)+'.'+string(s+exp,ptr-(s+exp)+1);
00391 
00392                                 //out = string(s,exp)+'.'+string(s+exp);
00393                         }
00394 
00395                 }else{ // exp<0 || exp>slen
00396                         if(s[0]=='-')
00397                         {
00398                                 // Remove zeros starting from right end
00399                                 char* ptr = s+slen-1;
00400                                 while (*ptr=='0' && ptr>s+1) ptr--; 
00401 
00402                                 if(ptr==s+1) out = string(s,2);
00403                                 else             out = string(s,2)+'.'+string(s+2,ptr-(s+2)+1);
00404 
00405                                 //out = string(s,2)+'.'+string(s+2);
00406                         }
00407                         else
00408                         {
00409                                 // Remove zeros starting from right end
00410                                 char* ptr = s+slen-1;
00411                                 while (*ptr=='0' && ptr>s) ptr--; 
00412 
00413                                 if(ptr==s) out = string(s,1);
00414                                 else       out = string(s,1)+'.'+string(s+1,ptr-(s+1)+1);
00415 
00416                                 //out = string(s,1)+'.'+string(s+1);
00417                         }
00418 
00419                         // Make final string
00420                         if(--exp)
00421                         {
00422                                 if(exp>0) out += "e+"+mpfr::to_string<mp_exp_t>(exp,std::dec);
00423                                 else      out += "e"+mpfr::to_string<mp_exp_t>(exp,std::dec);
00424                         }
00425                 }
00426 
00427                 mpfr_free_str(s);
00428                 return out;
00429         }else{
00430                 return "conversion error!";
00431         }
00432 }
00433 
00435 // I/O
00436 ostream& operator<<(ostream& os, const mpreal& v)
00437 {
00438         return os<<v.to_string(static_cast<size_t>(os.precision()));
00439 }
00440 
00441 istream& operator>>(istream &is, mpreal& v)
00442 {
00443         char c; 
00444         string s = "";
00445         mpfr_t t;
00446         
00447         mpreal::set_custom_malloc();
00448         
00449         if(is.good())
00450         {
00451                 is>>ws;
00452                 while ((c = is.get())!=EOF)
00453                 {
00454                         if(c ==' ' || c == '\t' || c == '\n' || c == '\r')
00455                         {
00456                                 is.putback(c);
00457                                 break;
00458                         }
00459                         s += c;
00460                 }
00461 
00462                 if(s.size() != 0)
00463                 {
00464                         // Protect current value from alternation in case of input error
00465                         // so some error handling(roll back) procedure can be used                      
00466 
00467                         if(0==mpfr_init_set_str(t,s.c_str(),mpreal::default_base,mpreal::default_rnd))
00468                         {
00469                                 mpfr_set(v.mp,t,mpreal::default_rnd);                           
00470                                 mpfr_clear(t);
00471 
00472                         }else{
00473                                 mpfr_clear(t);
00474                                 cerr<<"error reading from istream"<<endl;
00475                                 // throw an exception
00476                         }
00477                 }
00478         }
00479         return is;
00480 }
00481 
00482 // Optimized dynamic memory allocation/(re-)deallocation.
00483 void * mpreal::mpreal_allocate(size_t alloc_size)
00484 {
00485         return(dlmalloc(alloc_size));
00486 }
00487 
00488 void * mpreal::mpreal_reallocate(void *ptr, size_t /*old_size*/, size_t new_size)
00489 {
00490         return(dlrealloc(ptr,new_size));
00491 }
00492 
00493 void mpreal::mpreal_free(void *ptr, size_t /*size*/)
00494 {
00495         dlfree(ptr);
00496 }
00497 
00498 inline void mpreal::set_custom_malloc(void)
00499 {
00500         if(!is_custom_malloc)
00501         {
00502                 mp_set_memory_functions(mpreal_allocate,mpreal_reallocate,mpreal_free);
00503                 is_custom_malloc = true;
00504         }
00505 }
00506 }
00507 


libicr
Author(s): Robert Krug
autogenerated on Mon Jan 6 2014 11:33:07