Home | History | Annotate | Download | only in mpreal
      1 /*
      2     MPFR C++: Multi-precision floating point number class for C++.
      3     Based on MPFR library:    http://mpfr.org
      4 
      5     Project homepage:    http://www.holoborodko.com/pavel/mpfr
      6     Contact e-mail:      pavel (at) holoborodko.com
      7 
      8     Copyright (c) 2008-2014 Pavel Holoborodko
      9 
     10     Contributors:
     11     Dmitriy Gubanov, Konstantin Holoborodko, Brian Gladman,
     12     Helmut Jarausch, Fokko Beekhof, Ulrich Mutze, Heinz van Saanen,
     13     Pere Constans, Peter van Hoof, Gael Guennebaud, Tsai Chia Cheng,
     14     Alexei Zubanov, Jauhien Piatlicki, Victor Berger, John Westwood,
     15     Petr Aleksandrov, Orion Poplawski, Charles Karney.
     16 
     17     Licensing:
     18     (A) MPFR C++ is under GNU General Public License ("GPL").
     19 
     20     (B) Non-free licenses may also be purchased from the author, for users who
     21         do not want their programs protected by the GPL.
     22 
     23         The non-free licenses are for users that wish to use MPFR C++ in
     24         their products but are unwilling to release their software
     25         under the GPL (which would require them to release source code
     26         and allow free redistribution).
     27 
     28         Such users can purchase an unlimited-use license from the author.
     29         Contact us for more details.
     30 
     31     GNU General Public License ("GPL") copyright permissions statement:
     32     **************************************************************************
     33     This program is free software: you can redistribute it and/or modify
     34     it under the terms of the GNU General Public License as published by
     35     the Free Software Foundation, either version 3 of the License, or
     36     (at your option) any later version.
     37 
     38     This program is distributed in the hope that it will be useful,
     39     but WITHOUT ANY WARRANTY; without even the implied warranty of
     40     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     41     GNU General Public License for more details.
     42 
     43     You should have received a copy of the GNU General Public License
     44     along with this program.  If not, see <http://www.gnu.org/licenses/>.
     45 */
     46 
     47 #ifndef __MPREAL_H__
     48 #define __MPREAL_H__
     49 
     50 #include <string>
     51 #include <iostream>
     52 #include <sstream>
     53 #include <stdexcept>
     54 #include <cfloat>
     55 #include <cmath>
     56 #include <cstring>
     57 #include <limits>
     58 
     59 // Options
     60 // FIXME HAVE_INT64_SUPPORT leads to clashes with long int and int64_t on some systems.
     61 //#define MPREAL_HAVE_INT64_SUPPORT               // Enable int64_t support if possible. Available only for MSVC 2010 & GCC.
     62 #define MPREAL_HAVE_MSVC_DEBUGVIEW              // Enable Debugger Visualizer for "Debug" builds in MSVC.
     63 #define MPREAL_HAVE_DYNAMIC_STD_NUMERIC_LIMITS  // Enable extended std::numeric_limits<mpfr::mpreal> specialization.
     64                                                 // Meaning that "digits", "round_style" and similar members are defined as functions, not constants.
     65                                                 // See std::numeric_limits<mpfr::mpreal> at the end of the file for more information.
     66 
     67 // Library version
     68 #define MPREAL_VERSION_MAJOR 3
     69 #define MPREAL_VERSION_MINOR 5
     70 #define MPREAL_VERSION_PATCHLEVEL 9
     71 #define MPREAL_VERSION_STRING "3.5.9"
     72 
     73 // Detect compiler using signatures from http://predef.sourceforge.net/
     74 #if defined(__GNUC__) && defined(__INTEL_COMPILER)
     75     #define IsInf(x) isinf(x)                   // Intel ICC compiler on Linux
     76 
     77 #elif defined(_MSC_VER)                         // Microsoft Visual C++
     78     #define IsInf(x) (!_finite(x))
     79 
     80 #else
     81     #define IsInf(x) std::isinf(x)              // GNU C/C++ (and/or other compilers), just hope for C99 conformance
     82 #endif
     83 
     84 // A Clang feature extension to determine compiler features.
     85 #ifndef __has_feature
     86     #define __has_feature(x) 0
     87 #endif
     88 
     89 // Detect support for r-value references (move semantic). Borrowed from Eigen.
     90 #if (__has_feature(cxx_rvalue_references) || \
     91        defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L || \
     92       (defined(_MSC_VER) && _MSC_VER >= 1600))
     93 
     94     #define MPREAL_HAVE_MOVE_SUPPORT
     95 
     96     // Use fields in mpfr_t structure to check if it was initialized / set dummy initialization
     97     #define mpfr_is_initialized(x)      (0 != (x)->_mpfr_d)
     98     #define mpfr_set_uninitialized(x)   ((x)->_mpfr_d = 0 )
     99 #endif
    100 
    101 // Detect support for explicit converters.
    102 #if (__has_feature(cxx_explicit_conversions) || \
    103        defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L || \
    104       (defined(_MSC_VER) && _MSC_VER >= 1800))
    105 
    106     #define MPREAL_HAVE_EXPLICIT_CONVERTERS
    107 #endif
    108 
    109 // Detect available 64-bit capabilities
    110 #if defined(MPREAL_HAVE_INT64_SUPPORT)
    111 
    112     #define MPFR_USE_INTMAX_T                   // Should be defined before mpfr.h
    113 
    114     #if defined(_MSC_VER)                       // MSVC + Windows
    115         #if (_MSC_VER >= 1600)
    116             #include <stdint.h>                 // <stdint.h> is available only in msvc2010!
    117 
    118         #else                                   // MPFR relies on intmax_t which is available only in msvc2010
    119             #undef MPREAL_HAVE_INT64_SUPPORT    // Besides, MPFR & MPIR have to be compiled with msvc2010
    120             #undef MPFR_USE_INTMAX_T            // Since we cannot detect this, disable x64 by default
    121                                                 // Someone should change this manually if needed.
    122         #endif
    123 
    124     #elif defined (__GNUC__) && defined(__linux__)
    125         #if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(__ia64) || defined(__itanium__) || defined(_M_IA64) || defined (__PPC64__)
    126             #undef MPREAL_HAVE_INT64_SUPPORT    // Remove all shaman dances for x64 builds since
    127             #undef MPFR_USE_INTMAX_T            // GCC already supports x64 as of "long int" is 64-bit integer, nothing left to do
    128         #else
    129             #include <stdint.h>                 // use int64_t, uint64_t otherwise
    130         #endif
    131 
    132     #else
    133         #include <stdint.h>                     // rely on int64_t, uint64_t in all other cases, Mac OSX, etc.
    134     #endif
    135 
    136 #endif
    137 
    138 #if defined(MPREAL_HAVE_MSVC_DEBUGVIEW) && defined(_MSC_VER) && defined(_DEBUG)
    139     #define MPREAL_MSVC_DEBUGVIEW_CODE     DebugView = toString();
    140     #define MPREAL_MSVC_DEBUGVIEW_DATA     std::string DebugView;
    141 #else
    142     #define MPREAL_MSVC_DEBUGVIEW_CODE
    143     #define MPREAL_MSVC_DEBUGVIEW_DATA
    144 #endif
    145 
    146 #include <mpfr.h>
    147 
    148 #if (MPFR_VERSION < MPFR_VERSION_NUM(3,0,0))
    149     #include <cstdlib>                          // Needed for random()
    150 #endif
    151 
    152 // Less important options
    153 #define MPREAL_DOUBLE_BITS_OVERFLOW -1          // Triggers overflow exception during conversion to double if mpreal
    154                                                 // cannot fit in MPREAL_DOUBLE_BITS_OVERFLOW bits
    155                                                 // = -1 disables overflow checks (default)
    156 #if defined(__GNUC__)
    157   #define MPREAL_PERMISSIVE_EXPR __extension__
    158 #else
    159   #define MPREAL_PERMISSIVE_EXPR
    160 #endif
    161 
    162 namespace mpfr {
    163 
    164 class mpreal {
    165 private:
    166     mpfr_t mp;
    167 
    168 public:
    169 
    170     // Get default rounding mode & precision
    171     inline static mp_rnd_t   get_default_rnd()    {    return (mp_rnd_t)(mpfr_get_default_rounding_mode());       }
    172     inline static mp_prec_t  get_default_prec()   {    return mpfr_get_default_prec();                            }
    173 
    174     // Constructors && type conversions
    175     mpreal();
    176     mpreal(const mpreal& u);
    177     mpreal(const mpf_t u);
    178     mpreal(const mpz_t u,             mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());
    179     mpreal(const mpq_t u,             mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());
    180     mpreal(const double u,            mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());
    181     mpreal(const long double u,       mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());
    182     mpreal(const unsigned long int u, mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());
    183     mpreal(const unsigned int u,      mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());
    184     mpreal(const long int u,          mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());
    185     mpreal(const int u,               mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());
    186 
    187     // Construct mpreal from mpfr_t structure.
    188     // shared = true allows to avoid deep copy, so that mpreal and 'u' share the same data & pointers.
    189     mpreal(const mpfr_t  u, bool shared = false);
    190 
    191 #if defined (MPREAL_HAVE_INT64_SUPPORT)
    192     mpreal(const uint64_t u,          mp_prec_t prec = mpreal::get_default_prec(),  mp_rnd_t mode = mpreal::get_default_rnd());
    193     mpreal(const int64_t u,           mp_prec_t prec = mpreal::get_default_prec(),  mp_rnd_t mode = mpreal::get_default_rnd());
    194 #endif
    195 
    196     mpreal(const char* s,             mp_prec_t prec = mpreal::get_default_prec(), int base = 10, mp_rnd_t mode = mpreal::get_default_rnd());
    197     mpreal(const std::string& s,      mp_prec_t prec = mpreal::get_default_prec(), int base = 10, mp_rnd_t mode = mpreal::get_default_rnd());
    198 
    199     ~mpreal();
    200 
    201 #ifdef MPREAL_HAVE_MOVE_SUPPORT
    202     mpreal& operator=(mpreal&& v);
    203     mpreal(mpreal&& u);
    204 #endif
    205 
    206     // Operations
    207     // =
    208     // +, -, *, /, ++, --, <<, >>
    209     // *=, +=, -=, /=,
    210     // <, >, ==, <=, >=
    211 
    212     // =
    213     mpreal& operator=(const mpreal& v);
    214     mpreal& operator=(const mpf_t v);
    215     mpreal& operator=(const mpz_t v);
    216     mpreal& operator=(const mpq_t v);
    217     mpreal& operator=(const long double v);
    218     mpreal& operator=(const double v);
    219     mpreal& operator=(const unsigned long int v);
    220     mpreal& operator=(const unsigned int v);
    221     mpreal& operator=(const long int v);
    222     mpreal& operator=(const int v);
    223     mpreal& operator=(const char* s);
    224     mpreal& operator=(const std::string& s);
    225 
    226     // +
    227     mpreal& operator+=(const mpreal& v);
    228     mpreal& operator+=(const mpf_t v);
    229     mpreal& operator+=(const mpz_t v);
    230     mpreal& operator+=(const mpq_t v);
    231     mpreal& operator+=(const long double u);
    232     mpreal& operator+=(const double u);
    233     mpreal& operator+=(const unsigned long int u);
    234     mpreal& operator+=(const unsigned int u);
    235     mpreal& operator+=(const long int u);
    236     mpreal& operator+=(const int u);
    237 
    238 #if defined (MPREAL_HAVE_INT64_SUPPORT)
    239     mpreal& operator+=(const int64_t  u);
    240     mpreal& operator+=(const uint64_t u);
    241     mpreal& operator-=(const int64_t  u);
    242     mpreal& operator-=(const uint64_t u);
    243     mpreal& operator*=(const int64_t  u);
    244     mpreal& operator*=(const uint64_t u);
    245     mpreal& operator/=(const int64_t  u);
    246     mpreal& operator/=(const uint64_t u);
    247 #endif
    248 
    249     const mpreal operator+() const;
    250     mpreal& operator++ ();
    251     const mpreal  operator++ (int);
    252 
    253     // -
    254     mpreal& operator-=(const mpreal& v);
    255     mpreal& operator-=(const mpz_t v);
    256     mpreal& operator-=(const mpq_t v);
    257     mpreal& operator-=(const long double u);
    258     mpreal& operator-=(const double u);
    259     mpreal& operator-=(const unsigned long int u);
    260     mpreal& operator-=(const unsigned int u);
    261     mpreal& operator-=(const long int u);
    262     mpreal& operator-=(const int u);
    263     const mpreal operator-() const;
    264     friend const mpreal operator-(const unsigned long int b, const mpreal& a);
    265     friend const mpreal operator-(const unsigned int b,      const mpreal& a);
    266     friend const mpreal operator-(const long int b,          const mpreal& a);
    267     friend const mpreal operator-(const int b,               const mpreal& a);
    268     friend const mpreal operator-(const double b,            const mpreal& a);
    269     mpreal& operator-- ();
    270     const mpreal  operator-- (int);
    271 
    272     // *
    273     mpreal& operator*=(const mpreal& v);
    274     mpreal& operator*=(const mpz_t v);
    275     mpreal& operator*=(const mpq_t v);
    276     mpreal& operator*=(const long double v);
    277     mpreal& operator*=(const double v);
    278     mpreal& operator*=(const unsigned long int v);
    279     mpreal& operator*=(const unsigned int v);
    280     mpreal& operator*=(const long int v);
    281     mpreal& operator*=(const int v);
    282 
    283     // /
    284     mpreal& operator/=(const mpreal& v);
    285     mpreal& operator/=(const mpz_t v);
    286     mpreal& operator/=(const mpq_t v);
    287     mpreal& operator/=(const long double v);
    288     mpreal& operator/=(const double v);
    289     mpreal& operator/=(const unsigned long int v);
    290     mpreal& operator/=(const unsigned int v);
    291     mpreal& operator/=(const long int v);
    292     mpreal& operator/=(const int v);
    293     friend const mpreal operator/(const unsigned long int b, const mpreal& a);
    294     friend const mpreal operator/(const unsigned int b,      const mpreal& a);
    295     friend const mpreal operator/(const long int b,          const mpreal& a);
    296     friend const mpreal operator/(const int b,               const mpreal& a);
    297     friend const mpreal operator/(const double b,            const mpreal& a);
    298 
    299     //<<= Fast Multiplication by 2^u
    300     mpreal& operator<<=(const unsigned long int u);
    301     mpreal& operator<<=(const unsigned int u);
    302     mpreal& operator<<=(const long int u);
    303     mpreal& operator<<=(const int u);
    304 
    305     //>>= Fast Division by 2^u
    306     mpreal& operator>>=(const unsigned long int u);
    307     mpreal& operator>>=(const unsigned int u);
    308     mpreal& operator>>=(const long int u);
    309     mpreal& operator>>=(const int u);
    310 
    311     // Boolean Operators
    312     friend bool operator >  (const mpreal& a, const mpreal& b);
    313     friend bool operator >= (const mpreal& a, const mpreal& b);
    314     friend bool operator <  (const mpreal& a, const mpreal& b);
    315     friend bool operator <= (const mpreal& a, const mpreal& b);
    316     friend bool operator == (const mpreal& a, const mpreal& b);
    317     friend bool operator != (const mpreal& a, const mpreal& b);
    318 
    319     // Optimized specializations for boolean operators
    320     friend bool operator == (const mpreal& a, const unsigned long int b);
    321     friend bool operator == (const mpreal& a, const unsigned int b);
    322     friend bool operator == (const mpreal& a, const long int b);
    323     friend bool operator == (const mpreal& a, const int b);
    324     friend bool operator == (const mpreal& a, const long double b);
    325     friend bool operator == (const mpreal& a, const double b);
    326 
    327     // Type Conversion operators
    328     bool            toBool      (mp_rnd_t mode = GMP_RNDZ)    const;
    329     long            toLong      (mp_rnd_t mode = GMP_RNDZ)    const;
    330     unsigned long   toULong     (mp_rnd_t mode = GMP_RNDZ)    const;
    331     float           toFloat     (mp_rnd_t mode = GMP_RNDN)    const;
    332     double          toDouble    (mp_rnd_t mode = GMP_RNDN)    const;
    333     long double     toLDouble   (mp_rnd_t mode = GMP_RNDN)    const;
    334 
    335 #if defined (MPREAL_HAVE_EXPLICIT_CONVERTERS)
    336     explicit operator bool               () const { return toBool();       }
    337     explicit operator int                () const { return toLong();       }
    338     explicit operator long               () const { return toLong();       }
    339     explicit operator long long          () const { return toLong();       }
    340     explicit operator unsigned           () const { return toULong();      }
    341     explicit operator unsigned long      () const { return toULong();      }
    342     explicit operator unsigned long long () const { return toULong();      }
    343     explicit operator float              () const { return toFloat();      }
    344     explicit operator double             () const { return toDouble();     }
    345     explicit operator long double        () const { return toLDouble();    }
    346 #endif
    347 
    348 #if defined (MPREAL_HAVE_INT64_SUPPORT)
    349     int64_t         toInt64     (mp_rnd_t mode = GMP_RNDZ)    const;
    350     uint64_t        toUInt64    (mp_rnd_t mode = GMP_RNDZ)    const;
    351 
    352     #if defined (MPREAL_HAVE_EXPLICIT_CONVERTERS)
    353     explicit operator int64_t   () const { return toInt64();      }
    354     explicit operator uint64_t  () const { return toUInt64();     }
    355     #endif
    356 #endif
    357 
    358     // Get raw pointers so that mpreal can be directly used in raw mpfr_* functions
    359     ::mpfr_ptr    mpfr_ptr();
    360     ::mpfr_srcptr mpfr_ptr()    const;
    361     ::mpfr_srcptr mpfr_srcptr() const;
    362 
    363     // Convert mpreal to string with n significant digits in base b
    364     // n = -1 -> convert with the maximum available digits
    365     std::string toString(int n = -1, int b = 10, mp_rnd_t mode = mpreal::get_default_rnd()) const;
    366 
    367 #if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))
    368     std::string toString(const std::string& format) const;
    369 #endif
    370 
    371     std::ostream& output(std::ostream& os) const;
    372 
    373     // Math Functions
    374     friend const mpreal sqr (const mpreal& v, mp_rnd_t rnd_mode);
    375     friend const mpreal sqrt(const mpreal& v, mp_rnd_t rnd_mode);
    376     friend const mpreal sqrt(const unsigned long int v, mp_rnd_t rnd_mode);
    377     friend const mpreal cbrt(const mpreal& v, mp_rnd_t rnd_mode);
    378     friend const mpreal root(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode);
    379     friend const mpreal pow (const mpreal& a, const mpreal& b, mp_rnd_t rnd_mode);
    380     friend const mpreal pow (const mpreal& a, const mpz_t b, mp_rnd_t rnd_mode);
    381     friend const mpreal pow (const mpreal& a, const unsigned long int b, mp_rnd_t rnd_mode);
    382     friend const mpreal pow (const mpreal& a, const long int b, mp_rnd_t rnd_mode);
    383     friend const mpreal pow (const unsigned long int a, const mpreal& b, mp_rnd_t rnd_mode);
    384     friend const mpreal pow (const unsigned long int a, const unsigned long int b, mp_rnd_t rnd_mode);
    385     friend const mpreal fabs(const mpreal& v, mp_rnd_t rnd_mode);
    386 
    387     friend const mpreal abs(const mpreal& v, mp_rnd_t rnd_mode);
    388     friend const mpreal dim(const mpreal& a, const mpreal& b, mp_rnd_t rnd_mode);
    389     friend inline const mpreal mul_2ui(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode);
    390     friend inline const mpreal mul_2si(const mpreal& v, long int k, mp_rnd_t rnd_mode);
    391     friend inline const mpreal div_2ui(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode);
    392     friend inline const mpreal div_2si(const mpreal& v, long int k, mp_rnd_t rnd_mode);
    393     friend int cmpabs(const mpreal& a,const mpreal& b);
    394 
    395     friend const mpreal log  (const mpreal& v, mp_rnd_t rnd_mode);
    396     friend const mpreal log2 (const mpreal& v, mp_rnd_t rnd_mode);
    397     friend const mpreal log10(const mpreal& v, mp_rnd_t rnd_mode);
    398     friend const mpreal exp  (const mpreal& v, mp_rnd_t rnd_mode);
    399     friend const mpreal exp2 (const mpreal& v, mp_rnd_t rnd_mode);
    400     friend const mpreal exp10(const mpreal& v, mp_rnd_t rnd_mode);
    401     friend const mpreal log1p(const mpreal& v, mp_rnd_t rnd_mode);
    402     friend const mpreal expm1(const mpreal& v, mp_rnd_t rnd_mode);
    403 
    404     friend const mpreal cos(const mpreal& v, mp_rnd_t rnd_mode);
    405     friend const mpreal sin(const mpreal& v, mp_rnd_t rnd_mode);
    406     friend const mpreal tan(const mpreal& v, mp_rnd_t rnd_mode);
    407     friend const mpreal sec(const mpreal& v, mp_rnd_t rnd_mode);
    408     friend const mpreal csc(const mpreal& v, mp_rnd_t rnd_mode);
    409     friend const mpreal cot(const mpreal& v, mp_rnd_t rnd_mode);
    410     friend int sin_cos(mpreal& s, mpreal& c, const mpreal& v, mp_rnd_t rnd_mode);
    411 
    412     friend const mpreal acos  (const mpreal& v, mp_rnd_t rnd_mode);
    413     friend const mpreal asin  (const mpreal& v, mp_rnd_t rnd_mode);
    414     friend const mpreal atan  (const mpreal& v, mp_rnd_t rnd_mode);
    415     friend const mpreal atan2 (const mpreal& y, const mpreal& x, mp_rnd_t rnd_mode);
    416     friend const mpreal acot  (const mpreal& v, mp_rnd_t rnd_mode);
    417     friend const mpreal asec  (const mpreal& v, mp_rnd_t rnd_mode);
    418     friend const mpreal acsc  (const mpreal& v, mp_rnd_t rnd_mode);
    419 
    420     friend const mpreal cosh  (const mpreal& v, mp_rnd_t rnd_mode);
    421     friend const mpreal sinh  (const mpreal& v, mp_rnd_t rnd_mode);
    422     friend const mpreal tanh  (const mpreal& v, mp_rnd_t rnd_mode);
    423     friend const mpreal sech  (const mpreal& v, mp_rnd_t rnd_mode);
    424     friend const mpreal csch  (const mpreal& v, mp_rnd_t rnd_mode);
    425     friend const mpreal coth  (const mpreal& v, mp_rnd_t rnd_mode);
    426     friend const mpreal acosh (const mpreal& v, mp_rnd_t rnd_mode);
    427     friend const mpreal asinh (const mpreal& v, mp_rnd_t rnd_mode);
    428     friend const mpreal atanh (const mpreal& v, mp_rnd_t rnd_mode);
    429     friend const mpreal acoth (const mpreal& v, mp_rnd_t rnd_mode);
    430     friend const mpreal asech (const mpreal& v, mp_rnd_t rnd_mode);
    431     friend const mpreal acsch (const mpreal& v, mp_rnd_t rnd_mode);
    432 
    433     friend const mpreal hypot (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode);
    434 
    435     friend const mpreal fac_ui (unsigned long int v,  mp_prec_t prec, mp_rnd_t rnd_mode);
    436     friend const mpreal eint   (const mpreal& v, mp_rnd_t rnd_mode);
    437 
    438     friend const mpreal gamma    (const mpreal& v, mp_rnd_t rnd_mode);
    439     friend const mpreal lngamma  (const mpreal& v, mp_rnd_t rnd_mode);
    440     friend const mpreal lgamma   (const mpreal& v, int *signp, mp_rnd_t rnd_mode);
    441     friend const mpreal zeta     (const mpreal& v, mp_rnd_t rnd_mode);
    442     friend const mpreal erf      (const mpreal& v, mp_rnd_t rnd_mode);
    443     friend const mpreal erfc     (const mpreal& v, mp_rnd_t rnd_mode);
    444     friend const mpreal besselj0 (const mpreal& v, mp_rnd_t rnd_mode);
    445     friend const mpreal besselj1 (const mpreal& v, mp_rnd_t rnd_mode);
    446     friend const mpreal besseljn (long n, const mpreal& v, mp_rnd_t rnd_mode);
    447     friend const mpreal bessely0 (const mpreal& v, mp_rnd_t rnd_mode);
    448     friend const mpreal bessely1 (const mpreal& v, mp_rnd_t rnd_mode);
    449     friend const mpreal besselyn (long n, const mpreal& v, mp_rnd_t rnd_mode);
    450     friend const mpreal fma      (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode);
    451     friend const mpreal fms      (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode);
    452     friend const mpreal agm      (const mpreal& v1, const mpreal& v2, mp_rnd_t rnd_mode);
    453     friend const mpreal sum      (const mpreal tab[], unsigned long int n, mp_rnd_t rnd_mode);
    454     friend int sgn(const mpreal& v); // returns -1 or +1
    455 
    456 // MPFR 2.4.0 Specifics
    457 #if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))
    458     friend int          sinh_cosh   (mpreal& s, mpreal& c, const mpreal& v, mp_rnd_t rnd_mode);
    459     friend const mpreal li2         (const mpreal& v,                       mp_rnd_t rnd_mode);
    460     friend const mpreal fmod        (const mpreal& x, const mpreal& y,      mp_rnd_t rnd_mode);
    461     friend const mpreal rec_sqrt    (const mpreal& v,                       mp_rnd_t rnd_mode);
    462 
    463     // MATLAB's semantic equivalents
    464     friend const mpreal rem (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode); // Remainder after division
    465     friend const mpreal mod (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode); // Modulus after division
    466 #endif
    467 
    468 // MPFR 3.0.0 Specifics
    469 #if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0))
    470     friend const mpreal digamma (const mpreal& v,        mp_rnd_t rnd_mode);
    471     friend const mpreal ai      (const mpreal& v,        mp_rnd_t rnd_mode);
    472     friend const mpreal urandom (gmp_randstate_t& state, mp_rnd_t rnd_mode);     // use gmp_randinit_default() to init state, gmp_randclear() to clear
    473     friend const mpreal grandom (gmp_randstate_t& state, mp_rnd_t rnd_mode);     // use gmp_randinit_default() to init state, gmp_randclear() to clear
    474     friend const mpreal grandom (unsigned int seed);
    475 #endif
    476 
    477     // Uniformly distributed random number generation in [0,1] using
    478     // Mersenne-Twister algorithm by default.
    479     // Use parameter to setup seed, e.g.: random((unsigned)time(NULL))
    480     // Check urandom() for more precise control.
    481     friend const mpreal random(unsigned int seed);
    482 
    483     // Exponent and mantissa manipulation
    484     friend const mpreal frexp(const mpreal& v, mp_exp_t* exp);
    485     friend const mpreal ldexp(const mpreal& v, mp_exp_t exp);
    486 
    487     // Splits mpreal value into fractional and integer parts.
    488     // Returns fractional part and stores integer part in n.
    489     friend const mpreal modf(const mpreal& v, mpreal& n);
    490 
    491     // Constants
    492     // don't forget to call mpfr_free_cache() for every thread where you are using const-functions
    493     friend const mpreal const_log2      (mp_prec_t prec, mp_rnd_t rnd_mode);
    494     friend const mpreal const_pi        (mp_prec_t prec, mp_rnd_t rnd_mode);
    495     friend const mpreal const_euler     (mp_prec_t prec, mp_rnd_t rnd_mode);
    496     friend const mpreal const_catalan   (mp_prec_t prec, mp_rnd_t rnd_mode);
    497 
    498     // returns +inf iff sign>=0 otherwise -inf
    499     friend const mpreal const_infinity(int sign, mp_prec_t prec);
    500 
    501     // Output/ Input
    502     friend std::ostream& operator<<(std::ostream& os, const mpreal& v);
    503     friend std::istream& operator>>(std::istream& is, mpreal& v);
    504 
    505     // Integer Related Functions
    506     friend const mpreal rint (const mpreal& v, mp_rnd_t rnd_mode);
    507     friend const mpreal ceil (const mpreal& v);
    508     friend const mpreal floor(const mpreal& v);
    509     friend const mpreal round(const mpreal& v);
    510     friend const mpreal trunc(const mpreal& v);
    511     friend const mpreal rint_ceil   (const mpreal& v, mp_rnd_t rnd_mode);
    512     friend const mpreal rint_floor  (const mpreal& v, mp_rnd_t rnd_mode);
    513     friend const mpreal rint_round  (const mpreal& v, mp_rnd_t rnd_mode);
    514     friend const mpreal rint_trunc  (const mpreal& v, mp_rnd_t rnd_mode);
    515     friend const mpreal frac        (const mpreal& v, mp_rnd_t rnd_mode);
    516     friend const mpreal remainder   (         const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode);
    517     friend const mpreal remquo      (long* q, const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode);
    518 
    519     // Miscellaneous Functions
    520     friend const mpreal nexttoward (const mpreal& x, const mpreal& y);
    521     friend const mpreal nextabove  (const mpreal& x);
    522     friend const mpreal nextbelow  (const mpreal& x);
    523 
    524     // use gmp_randinit_default() to init state, gmp_randclear() to clear
    525     friend const mpreal urandomb (gmp_randstate_t& state);
    526 
    527 // MPFR < 2.4.2 Specifics
    528 #if (MPFR_VERSION <= MPFR_VERSION_NUM(2,4,2))
    529     friend const mpreal random2 (mp_size_t size, mp_exp_t exp);
    530 #endif
    531 
    532     // Instance Checkers
    533     friend bool isnan    (const mpreal& v);
    534     friend bool isinf    (const mpreal& v);
    535     friend bool isfinite (const mpreal& v);
    536 
    537     friend bool isnum    (const mpreal& v);
    538     friend bool iszero   (const mpreal& v);
    539     friend bool isint    (const mpreal& v);
    540 
    541 #if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0))
    542     friend bool isregular(const mpreal& v);
    543 #endif
    544 
    545     // Set/Get instance properties
    546     inline mp_prec_t    get_prec() const;
    547     inline void         set_prec(mp_prec_t prec, mp_rnd_t rnd_mode = get_default_rnd());    // Change precision with rounding mode
    548 
    549     // Aliases for get_prec(), set_prec() - needed for compatibility with std::complex<mpreal> interface
    550     inline mpreal&      setPrecision(int Precision, mp_rnd_t RoundingMode = get_default_rnd());
    551     inline int          getPrecision() const;
    552 
    553     // Set mpreal to +/- inf, NaN, +/-0
    554     mpreal&        setInf  (int Sign = +1);
    555     mpreal&        setNan  ();
    556     mpreal&        setZero (int Sign = +1);
    557     mpreal&        setSign (int Sign, mp_rnd_t RoundingMode = get_default_rnd());
    558 
    559     //Exponent
    560     mp_exp_t get_exp();
    561     int set_exp(mp_exp_t e);
    562     int check_range  (int t, mp_rnd_t rnd_mode = get_default_rnd());
    563     int subnormalize (int t,mp_rnd_t rnd_mode = get_default_rnd());
    564 
    565     // Inexact conversion from float
    566     inline bool fits_in_bits(double x, int n);
    567 
    568     // Set/Get global properties
    569     static void            set_default_prec(mp_prec_t prec);
    570     static void            set_default_rnd(mp_rnd_t rnd_mode);
    571 
    572     static mp_exp_t  get_emin (void);
    573     static mp_exp_t  get_emax (void);
    574     static mp_exp_t  get_emin_min (void);
    575     static mp_exp_t  get_emin_max (void);
    576     static mp_exp_t  get_emax_min (void);
    577     static mp_exp_t  get_emax_max (void);
    578     static int       set_emin (mp_exp_t exp);
    579     static int       set_emax (mp_exp_t exp);
    580 
    581     // Efficient swapping of two mpreal values - needed for std algorithms
    582     friend void swap(mpreal& x, mpreal& y);
    583 
    584     friend const mpreal fmax(const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode);
    585     friend const mpreal fmin(const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode);
    586 
    587 private:
    588     // Human friendly Debug Preview in Visual Studio.
    589     // Put one of these lines:
    590     //
    591     // mpfr::mpreal=<DebugView>                              ; Show value only
    592     // mpfr::mpreal=<DebugView>, <mp[0]._mpfr_prec,u>bits    ; Show value & precision
    593     //
    594     // at the beginning of
    595     // [Visual Studio Installation Folder]\Common7\Packages\Debugger\autoexp.dat
    596     MPREAL_MSVC_DEBUGVIEW_DATA
    597 
    598     // "Smart" resources deallocation. Checks if instance initialized before deletion.
    599     void clear(::mpfr_ptr);
    600 };
    601 
    602 //////////////////////////////////////////////////////////////////////////
    603 // Exceptions
    604 class conversion_overflow : public std::exception {
    605 public:
    606     std::string why() { return "inexact conversion from floating point"; }
    607 };
    608 
    609 //////////////////////////////////////////////////////////////////////////
    610 // Constructors & converters
    611 // Default constructor: creates mp number and initializes it to 0.
    612 inline mpreal::mpreal()
    613 {
    614     mpfr_init2 (mpfr_ptr(), mpreal::get_default_prec());
    615     mpfr_set_ui(mpfr_ptr(), 0, mpreal::get_default_rnd());
    616 
    617     MPREAL_MSVC_DEBUGVIEW_CODE;
    618 }
    619 
    620 inline mpreal::mpreal(const mpreal& u)
    621 {
    622     mpfr_init2(mpfr_ptr(),mpfr_get_prec(u.mpfr_srcptr()));
    623     mpfr_set  (mpfr_ptr(),u.mpfr_srcptr(),mpreal::get_default_rnd());
    624 
    625     MPREAL_MSVC_DEBUGVIEW_CODE;
    626 }
    627 
    628 #ifdef MPREAL_HAVE_MOVE_SUPPORT
    629 inline mpreal::mpreal(mpreal&& other)
    630 {
    631     mpfr_set_uninitialized(mpfr_ptr());     // make sure "other" holds no pinter to actual data
    632     mpfr_swap(mpfr_ptr(), other.mpfr_ptr());
    633 
    634     MPREAL_MSVC_DEBUGVIEW_CODE;
    635 }
    636 
    637 inline mpreal& mpreal::operator=(mpreal&& other)
    638 {
    639     mpfr_swap(mpfr_ptr(), other.mpfr_ptr());
    640 
    641     MPREAL_MSVC_DEBUGVIEW_CODE;
    642     return *this;
    643 }
    644 #endif
    645 
    646 inline mpreal::mpreal(const mpfr_t  u, bool shared)
    647 {
    648     if(shared)
    649     {
    650         std::memcpy(mpfr_ptr(), u, sizeof(mpfr_t));
    651     }
    652     else
    653     {
    654         mpfr_init2(mpfr_ptr(), mpfr_get_prec(u));
    655         mpfr_set  (mpfr_ptr(), u, mpreal::get_default_rnd());
    656     }
    657 
    658     MPREAL_MSVC_DEBUGVIEW_CODE;
    659 }
    660 
    661 inline mpreal::mpreal(const mpf_t u)
    662 {
    663     mpfr_init2(mpfr_ptr(),(mp_prec_t) mpf_get_prec(u)); // (gmp: mp_bitcnt_t) unsigned long -> long (mpfr: mp_prec_t)
    664     mpfr_set_f(mpfr_ptr(),u,mpreal::get_default_rnd());
    665 
    666     MPREAL_MSVC_DEBUGVIEW_CODE;
    667 }
    668 
    669 inline mpreal::mpreal(const mpz_t u, mp_prec_t prec, mp_rnd_t mode)
    670 {
    671     mpfr_init2(mpfr_ptr(), prec);
    672     mpfr_set_z(mpfr_ptr(), u, mode);
    673 
    674     MPREAL_MSVC_DEBUGVIEW_CODE;
    675 }
    676 
    677 inline mpreal::mpreal(const mpq_t u, mp_prec_t prec, mp_rnd_t mode)
    678 {
    679     mpfr_init2(mpfr_ptr(), prec);
    680     mpfr_set_q(mpfr_ptr(), u, mode);
    681 
    682     MPREAL_MSVC_DEBUGVIEW_CODE;
    683 }
    684 
    685 inline mpreal::mpreal(const double u, mp_prec_t prec, mp_rnd_t mode)
    686 {
    687      mpfr_init2(mpfr_ptr(), prec);
    688 
    689 #if (MPREAL_DOUBLE_BITS_OVERFLOW > -1)
    690   if(fits_in_bits(u, MPREAL_DOUBLE_BITS_OVERFLOW))
    691   {
    692     mpfr_set_d(mpfr_ptr(), u, mode);
    693   }else
    694     throw conversion_overflow();
    695 #else
    696   mpfr_set_d(mpfr_ptr(), u, mode);
    697 #endif
    698 
    699     MPREAL_MSVC_DEBUGVIEW_CODE;
    700 }
    701 
    702 inline mpreal::mpreal(const long double u, mp_prec_t prec, mp_rnd_t mode)
    703 {
    704     mpfr_init2 (mpfr_ptr(), prec);
    705     mpfr_set_ld(mpfr_ptr(), u, mode);
    706 
    707     MPREAL_MSVC_DEBUGVIEW_CODE;
    708 }
    709 
    710 inline mpreal::mpreal(const unsigned long int u, mp_prec_t prec, mp_rnd_t mode)
    711 {
    712     mpfr_init2 (mpfr_ptr(), prec);
    713     mpfr_set_ui(mpfr_ptr(), u, mode);
    714 
    715     MPREAL_MSVC_DEBUGVIEW_CODE;
    716 }
    717 
    718 inline mpreal::mpreal(const unsigned int u, mp_prec_t prec, mp_rnd_t mode)
    719 {
    720     mpfr_init2 (mpfr_ptr(), prec);
    721     mpfr_set_ui(mpfr_ptr(), u, mode);
    722 
    723     MPREAL_MSVC_DEBUGVIEW_CODE;
    724 }
    725 
    726 inline mpreal::mpreal(const long int u, mp_prec_t prec, mp_rnd_t mode)
    727 {
    728     mpfr_init2 (mpfr_ptr(), prec);
    729     mpfr_set_si(mpfr_ptr(), u, mode);
    730 
    731     MPREAL_MSVC_DEBUGVIEW_CODE;
    732 }
    733 
    734 inline mpreal::mpreal(const int u, mp_prec_t prec, mp_rnd_t mode)
    735 {
    736     mpfr_init2 (mpfr_ptr(), prec);
    737     mpfr_set_si(mpfr_ptr(), u, mode);
    738 
    739     MPREAL_MSVC_DEBUGVIEW_CODE;
    740 }
    741 
    742 #if defined (MPREAL_HAVE_INT64_SUPPORT)
    743 inline mpreal::mpreal(const uint64_t u, mp_prec_t prec, mp_rnd_t mode)
    744 {
    745     mpfr_init2 (mpfr_ptr(), prec);
    746     mpfr_set_uj(mpfr_ptr(), u, mode);
    747 
    748     MPREAL_MSVC_DEBUGVIEW_CODE;
    749 }
    750 
    751 inline mpreal::mpreal(const int64_t u, mp_prec_t prec, mp_rnd_t mode)
    752 {
    753     mpfr_init2 (mpfr_ptr(), prec);
    754     mpfr_set_sj(mpfr_ptr(), u, mode);
    755 
    756     MPREAL_MSVC_DEBUGVIEW_CODE;
    757 }
    758 #endif
    759 
    760 inline mpreal::mpreal(const char* s, mp_prec_t prec, int base, mp_rnd_t mode)
    761 {
    762     mpfr_init2  (mpfr_ptr(), prec);
    763     mpfr_set_str(mpfr_ptr(), s, base, mode);
    764 
    765     MPREAL_MSVC_DEBUGVIEW_CODE;
    766 }
    767 
    768 inline mpreal::mpreal(const std::string& s, mp_prec_t prec, int base, mp_rnd_t mode)
    769 {
    770     mpfr_init2  (mpfr_ptr(), prec);
    771     mpfr_set_str(mpfr_ptr(), s.c_str(), base, mode);
    772 
    773     MPREAL_MSVC_DEBUGVIEW_CODE;
    774 }
    775 
    776 inline void mpreal::clear(::mpfr_ptr x)
    777 {
    778 #ifdef MPREAL_HAVE_MOVE_SUPPORT
    779     if(mpfr_is_initialized(x))
    780 #endif
    781     mpfr_clear(x);
    782 }
    783 
    784 inline mpreal::~mpreal()
    785 {
    786     clear(mpfr_ptr());
    787 }
    788 
    789 // internal namespace needed for template magic
    790 namespace internal{
    791 
    792     // Use SFINAE to restrict arithmetic operations instantiation only for numeric types
    793     // This is needed for smooth integration with libraries based on expression templates, like Eigen.
    794     // TODO: Do the same for boolean operators.
    795     template <typename ArgumentType> struct result_type {};
    796 
    797     template <> struct result_type<mpreal>              {typedef mpreal type;};
    798     template <> struct result_type<mpz_t>               {typedef mpreal type;};
    799     template <> struct result_type<mpq_t>               {typedef mpreal type;};
    800     template <> struct result_type<long double>         {typedef mpreal type;};
    801     template <> struct result_type<double>              {typedef mpreal type;};
    802     template <> struct result_type<unsigned long int>   {typedef mpreal type;};
    803     template <> struct result_type<unsigned int>        {typedef mpreal type;};
    804     template <> struct result_type<long int>            {typedef mpreal type;};
    805     template <> struct result_type<int>                 {typedef mpreal type;};
    806 
    807 #if defined (MPREAL_HAVE_INT64_SUPPORT)
    808     template <> struct result_type<int64_t  >           {typedef mpreal type;};
    809     template <> struct result_type<uint64_t >           {typedef mpreal type;};
    810 #endif
    811 }
    812 
    813 // + Addition
    814 template <typename Rhs>
    815 inline const typename internal::result_type<Rhs>::type
    816     operator+(const mpreal& lhs, const Rhs& rhs){ return mpreal(lhs) += rhs;    }
    817 
    818 template <typename Lhs>
    819 inline const typename internal::result_type<Lhs>::type
    820     operator+(const Lhs& lhs, const mpreal& rhs){ return mpreal(rhs) += lhs;    }
    821 
    822 // - Subtraction
    823 template <typename Rhs>
    824 inline const typename internal::result_type<Rhs>::type
    825     operator-(const mpreal& lhs, const Rhs& rhs){ return mpreal(lhs) -= rhs;    }
    826 
    827 template <typename Lhs>
    828 inline const typename internal::result_type<Lhs>::type
    829     operator-(const Lhs& lhs, const mpreal& rhs){ return mpreal(lhs) -= rhs;    }
    830 
    831 // * Multiplication
    832 template <typename Rhs>
    833 inline const typename internal::result_type<Rhs>::type
    834     operator*(const mpreal& lhs, const Rhs& rhs){ return mpreal(lhs) *= rhs;    }
    835 
    836 template <typename Lhs>
    837 inline const typename internal::result_type<Lhs>::type
    838     operator*(const Lhs& lhs, const mpreal& rhs){ return mpreal(rhs) *= lhs;    }
    839 
    840 // / Division
    841 template <typename Rhs>
    842 inline const typename internal::result_type<Rhs>::type
    843     operator/(const mpreal& lhs, const Rhs& rhs){ return mpreal(lhs) /= rhs;    }
    844 
    845 template <typename Lhs>
    846 inline const typename internal::result_type<Lhs>::type
    847     operator/(const Lhs& lhs, const mpreal& rhs){ return mpreal(lhs) /= rhs;    }
    848 
    849 //////////////////////////////////////////////////////////////////////////
    850 // sqrt
    851 const mpreal sqrt(const unsigned int v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    852 const mpreal sqrt(const long int v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    853 const mpreal sqrt(const int v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    854 const mpreal sqrt(const long double v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    855 const mpreal sqrt(const double v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    856 
    857 // abs
    858 inline const mpreal abs(const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd());
    859 
    860 //////////////////////////////////////////////////////////////////////////
    861 // pow
    862 const mpreal pow(const mpreal& a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    863 const mpreal pow(const mpreal& a, const int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    864 const mpreal pow(const mpreal& a, const long double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    865 const mpreal pow(const mpreal& a, const double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    866 
    867 const mpreal pow(const unsigned int a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    868 const mpreal pow(const long int a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    869 const mpreal pow(const int a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    870 const mpreal pow(const long double a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    871 const mpreal pow(const double a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    872 
    873 const mpreal pow(const unsigned long int a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    874 const mpreal pow(const unsigned long int a, const long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    875 const mpreal pow(const unsigned long int a, const int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    876 const mpreal pow(const unsigned long int a, const long double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    877 const mpreal pow(const unsigned long int a, const double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    878 
    879 const mpreal pow(const unsigned int a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    880 const mpreal pow(const unsigned int a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    881 const mpreal pow(const unsigned int a, const long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    882 const mpreal pow(const unsigned int a, const int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    883 const mpreal pow(const unsigned int a, const long double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    884 const mpreal pow(const unsigned int a, const double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    885 
    886 const mpreal pow(const long int a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    887 const mpreal pow(const long int a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    888 const mpreal pow(const long int a, const long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    889 const mpreal pow(const long int a, const int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    890 const mpreal pow(const long int a, const long double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    891 const mpreal pow(const long int a, const double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    892 
    893 const mpreal pow(const int a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    894 const mpreal pow(const int a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    895 const mpreal pow(const int a, const long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    896 const mpreal pow(const int a, const int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    897 const mpreal pow(const int a, const long double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    898 const mpreal pow(const int a, const double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    899 
    900 const mpreal pow(const long double a, const long double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    901 const mpreal pow(const long double a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    902 const mpreal pow(const long double a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    903 const mpreal pow(const long double a, const long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    904 const mpreal pow(const long double a, const int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    905 
    906 const mpreal pow(const double a, const double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    907 const mpreal pow(const double a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    908 const mpreal pow(const double a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    909 const mpreal pow(const double a, const long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    910 const mpreal pow(const double a, const int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    911 
    912 inline const mpreal mul_2ui(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    913 inline const mpreal mul_2si(const mpreal& v, long int k, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    914 inline const mpreal div_2ui(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    915 inline const mpreal div_2si(const mpreal& v, long int k, mp_rnd_t rnd_mode = mpreal::get_default_rnd());
    916 
    917 //////////////////////////////////////////////////////////////////////////
    918 // Estimate machine epsilon for the given precision
    919 // Returns smallest eps such that 1.0 + eps != 1.0
    920 inline mpreal machine_epsilon(mp_prec_t prec = mpreal::get_default_prec());
    921 
    922 // Returns smallest eps such that x + eps != x (relative machine epsilon)
    923 inline mpreal machine_epsilon(const mpreal& x);
    924 
    925 // Gives max & min values for the required precision,
    926 // minval is 'safe' meaning 1 / minval does not overflow
    927 // maxval is 'safe' meaning 1 / maxval does not underflow
    928 inline mpreal minval(mp_prec_t prec = mpreal::get_default_prec());
    929 inline mpreal maxval(mp_prec_t prec = mpreal::get_default_prec());
    930 
    931 // 'Dirty' equality check 1: |a-b| < min{|a|,|b|} * eps
    932 inline bool isEqualFuzzy(const mpreal& a, const mpreal& b, const mpreal& eps);
    933 
    934 // 'Dirty' equality check 2: |a-b| < min{|a|,|b|} * eps( min{|a|,|b|} )
    935 inline bool isEqualFuzzy(const mpreal& a, const mpreal& b);
    936 
    937 // 'Bitwise' equality check
    938 //  maxUlps - a and b can be apart by maxUlps binary numbers.
    939 inline bool isEqualUlps(const mpreal& a, const mpreal& b, int maxUlps);
    940 
    941 //////////////////////////////////////////////////////////////////////////
    942 //     Convert precision in 'bits' to decimal digits and vice versa.
    943 //        bits   = ceil(digits*log[2](10))
    944 //        digits = floor(bits*log[10](2))
    945 
    946 inline mp_prec_t digits2bits(int d);
    947 inline int       bits2digits(mp_prec_t b);
    948 
    949 //////////////////////////////////////////////////////////////////////////
    950 // min, max
    951 const mpreal (max)(const mpreal& x, const mpreal& y);
    952 const mpreal (min)(const mpreal& x, const mpreal& y);
    953 
    954 //////////////////////////////////////////////////////////////////////////
    955 // Implementation
    956 //////////////////////////////////////////////////////////////////////////
    957 
    958 //////////////////////////////////////////////////////////////////////////
    959 // Operators - Assignment
    960 inline mpreal& mpreal::operator=(const mpreal& v)
    961 {
    962     if (this != &v)
    963     {
    964     mp_prec_t tp = mpfr_get_prec(  mpfr_srcptr());
    965     mp_prec_t vp = mpfr_get_prec(v.mpfr_srcptr());
    966 
    967     if(tp != vp){
    968       clear(mpfr_ptr());
    969       mpfr_init2(mpfr_ptr(), vp);
    970     }
    971 
    972         mpfr_set(mpfr_ptr(), v.mpfr_srcptr(), mpreal::get_default_rnd());
    973 
    974         MPREAL_MSVC_DEBUGVIEW_CODE;
    975     }
    976     return *this;
    977 }
    978 
    979 inline mpreal& mpreal::operator=(const mpf_t v)
    980 {
    981     mpfr_set_f(mpfr_ptr(), v, mpreal::get_default_rnd());
    982 
    983     MPREAL_MSVC_DEBUGVIEW_CODE;
    984     return *this;
    985 }
    986 
    987 inline mpreal& mpreal::operator=(const mpz_t v)
    988 {
    989     mpfr_set_z(mpfr_ptr(), v, mpreal::get_default_rnd());
    990 
    991     MPREAL_MSVC_DEBUGVIEW_CODE;
    992     return *this;
    993 }
    994 
    995 inline mpreal& mpreal::operator=(const mpq_t v)
    996 {
    997     mpfr_set_q(mpfr_ptr(), v, mpreal::get_default_rnd());
    998 
    999     MPREAL_MSVC_DEBUGVIEW_CODE;
   1000     return *this;
   1001 }
   1002 
   1003 inline mpreal& mpreal::operator=(const long double v)
   1004 {
   1005     mpfr_set_ld(mpfr_ptr(), v, mpreal::get_default_rnd());
   1006 
   1007     MPREAL_MSVC_DEBUGVIEW_CODE;
   1008     return *this;
   1009 }
   1010 
   1011 inline mpreal& mpreal::operator=(const double v)
   1012 {
   1013 #if (MPREAL_DOUBLE_BITS_OVERFLOW > -1)
   1014   if(fits_in_bits(v, MPREAL_DOUBLE_BITS_OVERFLOW))
   1015   {
   1016     mpfr_set_d(mpfr_ptr(),v,mpreal::get_default_rnd());
   1017   }else
   1018     throw conversion_overflow();
   1019 #else
   1020   mpfr_set_d(mpfr_ptr(),v,mpreal::get_default_rnd());
   1021 #endif
   1022 
   1023   MPREAL_MSVC_DEBUGVIEW_CODE;
   1024     return *this;
   1025 }
   1026 
   1027 inline mpreal& mpreal::operator=(const unsigned long int v)
   1028 {
   1029     mpfr_set_ui(mpfr_ptr(), v, mpreal::get_default_rnd());
   1030 
   1031     MPREAL_MSVC_DEBUGVIEW_CODE;
   1032     return *this;
   1033 }
   1034 
   1035 inline mpreal& mpreal::operator=(const unsigned int v)
   1036 {
   1037     mpfr_set_ui(mpfr_ptr(), v, mpreal::get_default_rnd());
   1038 
   1039     MPREAL_MSVC_DEBUGVIEW_CODE;
   1040     return *this;
   1041 }
   1042 
   1043 inline mpreal& mpreal::operator=(const long int v)
   1044 {
   1045     mpfr_set_si(mpfr_ptr(), v, mpreal::get_default_rnd());
   1046 
   1047     MPREAL_MSVC_DEBUGVIEW_CODE;
   1048     return *this;
   1049 }
   1050 
   1051 inline mpreal& mpreal::operator=(const int v)
   1052 {
   1053     mpfr_set_si(mpfr_ptr(), v, mpreal::get_default_rnd());
   1054 
   1055     MPREAL_MSVC_DEBUGVIEW_CODE;
   1056     return *this;
   1057 }
   1058 
   1059 inline mpreal& mpreal::operator=(const char* s)
   1060 {
   1061     // Use other converters for more precise control on base & precision & rounding:
   1062     //
   1063     //        mpreal(const char* s,        mp_prec_t prec, int base, mp_rnd_t mode)
   1064     //        mpreal(const std::string& s,mp_prec_t prec, int base, mp_rnd_t mode)
   1065     //
   1066     // Here we assume base = 10 and we use precision of target variable.
   1067 
   1068     mpfr_t t;
   1069 
   1070     mpfr_init2(t, mpfr_get_prec(mpfr_srcptr()));
   1071 
   1072     if(0 == mpfr_set_str(t, s, 10, mpreal::get_default_rnd()))
   1073     {
   1074         mpfr_set(mpfr_ptr(), t, mpreal::get_default_rnd());
   1075         MPREAL_MSVC_DEBUGVIEW_CODE;
   1076     }
   1077 
   1078     clear(t);
   1079     return *this;
   1080 }
   1081 
   1082 inline mpreal& mpreal::operator=(const std::string& s)
   1083 {
   1084     // Use other converters for more precise control on base & precision & rounding:
   1085     //
   1086     //        mpreal(const char* s,        mp_prec_t prec, int base, mp_rnd_t mode)
   1087     //        mpreal(const std::string& s,mp_prec_t prec, int base, mp_rnd_t mode)
   1088     //
   1089     // Here we assume base = 10 and we use precision of target variable.
   1090 
   1091     mpfr_t t;
   1092 
   1093     mpfr_init2(t, mpfr_get_prec(mpfr_srcptr()));
   1094 
   1095     if(0 == mpfr_set_str(t, s.c_str(), 10, mpreal::get_default_rnd()))
   1096     {
   1097         mpfr_set(mpfr_ptr(), t, mpreal::get_default_rnd());
   1098         MPREAL_MSVC_DEBUGVIEW_CODE;
   1099     }
   1100 
   1101     clear(t);
   1102     return *this;
   1103 }
   1104 
   1105 
   1106 //////////////////////////////////////////////////////////////////////////
   1107 // + Addition
   1108 inline mpreal& mpreal::operator+=(const mpreal& v)
   1109 {
   1110     mpfr_add(mpfr_ptr(), mpfr_srcptr(), v.mpfr_srcptr(), mpreal::get_default_rnd());
   1111     MPREAL_MSVC_DEBUGVIEW_CODE;
   1112     return *this;
   1113 }
   1114 
   1115 inline mpreal& mpreal::operator+=(const mpf_t u)
   1116 {
   1117     *this += mpreal(u);
   1118     MPREAL_MSVC_DEBUGVIEW_CODE;
   1119     return *this;
   1120 }
   1121 
   1122 inline mpreal& mpreal::operator+=(const mpz_t u)
   1123 {
   1124     mpfr_add_z(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd());
   1125     MPREAL_MSVC_DEBUGVIEW_CODE;
   1126     return *this;
   1127 }
   1128 
   1129 inline mpreal& mpreal::operator+=(const mpq_t u)
   1130 {
   1131     mpfr_add_q(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd());
   1132     MPREAL_MSVC_DEBUGVIEW_CODE;
   1133     return *this;
   1134 }
   1135 
   1136 inline mpreal& mpreal::operator+= (const long double u)
   1137 {
   1138     *this += mpreal(u);
   1139     MPREAL_MSVC_DEBUGVIEW_CODE;
   1140     return *this;
   1141 }
   1142 
   1143 inline mpreal& mpreal::operator+= (const double u)
   1144 {
   1145 #if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))
   1146     mpfr_add_d(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd());
   1147 #else
   1148     *this += mpreal(u);
   1149 #endif
   1150 
   1151     MPREAL_MSVC_DEBUGVIEW_CODE;
   1152     return *this;
   1153 }
   1154 
   1155 inline mpreal& mpreal::operator+=(const unsigned long int u)
   1156 {
   1157     mpfr_add_ui(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd());
   1158     MPREAL_MSVC_DEBUGVIEW_CODE;
   1159     return *this;
   1160 }
   1161 
   1162 inline mpreal& mpreal::operator+=(const unsigned int u)
   1163 {
   1164     mpfr_add_ui(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd());
   1165     MPREAL_MSVC_DEBUGVIEW_CODE;
   1166     return *this;
   1167 }
   1168 
   1169 inline mpreal& mpreal::operator+=(const long int u)
   1170 {
   1171     mpfr_add_si(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd());
   1172     MPREAL_MSVC_DEBUGVIEW_CODE;
   1173     return *this;
   1174 }
   1175 
   1176 inline mpreal& mpreal::operator+=(const int u)
   1177 {
   1178     mpfr_add_si(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd());
   1179     MPREAL_MSVC_DEBUGVIEW_CODE;
   1180     return *this;
   1181 }
   1182 
   1183 #if defined (MPREAL_HAVE_INT64_SUPPORT)
   1184 inline mpreal& mpreal::operator+=(const int64_t  u){    *this += mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this;    }
   1185 inline mpreal& mpreal::operator+=(const uint64_t u){    *this += mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this;    }
   1186 inline mpreal& mpreal::operator-=(const int64_t  u){    *this -= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this;    }
   1187 inline mpreal& mpreal::operator-=(const uint64_t u){    *this -= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this;    }
   1188 inline mpreal& mpreal::operator*=(const int64_t  u){    *this *= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this;    }
   1189 inline mpreal& mpreal::operator*=(const uint64_t u){    *this *= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this;    }
   1190 inline mpreal& mpreal::operator/=(const int64_t  u){    *this /= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this;    }
   1191 inline mpreal& mpreal::operator/=(const uint64_t u){    *this /= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this;    }
   1192 #endif
   1193 
   1194 inline const mpreal mpreal::operator+()const    {    return mpreal(*this); }
   1195 
   1196 inline const mpreal operator+(const mpreal& a, const mpreal& b)
   1197 {
   1198   mpreal c(0, (std::max)(mpfr_get_prec(a.mpfr_ptr()), mpfr_get_prec(b.mpfr_ptr())));
   1199   mpfr_add(c.mpfr_ptr(), a.mpfr_srcptr(), b.mpfr_srcptr(), mpreal::get_default_rnd());
   1200   return c;
   1201 }
   1202 
   1203 inline mpreal& mpreal::operator++()
   1204 {
   1205     return *this += 1;
   1206 }
   1207 
   1208 inline const mpreal mpreal::operator++ (int)
   1209 {
   1210     mpreal x(*this);
   1211     *this += 1;
   1212     return x;
   1213 }
   1214 
   1215 inline mpreal& mpreal::operator--()
   1216 {
   1217     return *this -= 1;
   1218 }
   1219 
   1220 inline const mpreal mpreal::operator-- (int)
   1221 {
   1222     mpreal x(*this);
   1223     *this -= 1;
   1224     return x;
   1225 }
   1226 
   1227 //////////////////////////////////////////////////////////////////////////
   1228 // - Subtraction
   1229 inline mpreal& mpreal::operator-=(const mpreal& v)
   1230 {
   1231     mpfr_sub(mpfr_ptr(),mpfr_srcptr(),v.mpfr_srcptr(),mpreal::get_default_rnd());
   1232     MPREAL_MSVC_DEBUGVIEW_CODE;
   1233     return *this;
   1234 }
   1235 
   1236 inline mpreal& mpreal::operator-=(const mpz_t v)
   1237 {
   1238     mpfr_sub_z(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());
   1239     MPREAL_MSVC_DEBUGVIEW_CODE;
   1240     return *this;
   1241 }
   1242 
   1243 inline mpreal& mpreal::operator-=(const mpq_t v)
   1244 {
   1245     mpfr_sub_q(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());
   1246     MPREAL_MSVC_DEBUGVIEW_CODE;
   1247     return *this;
   1248 }
   1249 
   1250 inline mpreal& mpreal::operator-=(const long double v)
   1251 {
   1252     *this -= mpreal(v);
   1253     MPREAL_MSVC_DEBUGVIEW_CODE;
   1254     return *this;
   1255 }
   1256 
   1257 inline mpreal& mpreal::operator-=(const double v)
   1258 {
   1259 #if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))
   1260     mpfr_sub_d(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());
   1261 #else
   1262     *this -= mpreal(v);
   1263 #endif
   1264 
   1265     MPREAL_MSVC_DEBUGVIEW_CODE;
   1266     return *this;
   1267 }
   1268 
   1269 inline mpreal& mpreal::operator-=(const unsigned long int v)
   1270 {
   1271     mpfr_sub_ui(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());
   1272     MPREAL_MSVC_DEBUGVIEW_CODE;
   1273     return *this;
   1274 }
   1275 
   1276 inline mpreal& mpreal::operator-=(const unsigned int v)
   1277 {
   1278     mpfr_sub_ui(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());
   1279     MPREAL_MSVC_DEBUGVIEW_CODE;
   1280     return *this;
   1281 }
   1282 
   1283 inline mpreal& mpreal::operator-=(const long int v)
   1284 {
   1285     mpfr_sub_si(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());
   1286     MPREAL_MSVC_DEBUGVIEW_CODE;
   1287     return *this;
   1288 }
   1289 
   1290 inline mpreal& mpreal::operator-=(const int v)
   1291 {
   1292     mpfr_sub_si(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());
   1293     MPREAL_MSVC_DEBUGVIEW_CODE;
   1294     return *this;
   1295 }
   1296 
   1297 inline const mpreal mpreal::operator-()const
   1298 {
   1299     mpreal u(*this);
   1300     mpfr_neg(u.mpfr_ptr(),u.mpfr_srcptr(),mpreal::get_default_rnd());
   1301     return u;
   1302 }
   1303 
   1304 inline const mpreal operator-(const mpreal& a, const mpreal& b)
   1305 {
   1306   mpreal c(0, (std::max)(mpfr_get_prec(a.mpfr_ptr()), mpfr_get_prec(b.mpfr_ptr())));
   1307   mpfr_sub(c.mpfr_ptr(), a.mpfr_srcptr(), b.mpfr_srcptr(), mpreal::get_default_rnd());
   1308   return c;
   1309 }
   1310 
   1311 inline const mpreal operator-(const double  b, const mpreal& a)
   1312 {
   1313 #if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))
   1314     mpreal x(0, mpfr_get_prec(a.mpfr_ptr()));
   1315     mpfr_d_sub(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd());
   1316     return x;
   1317 #else
   1318     mpreal x(b, mpfr_get_prec(a.mpfr_ptr()));
   1319     x -= a;
   1320     return x;
   1321 #endif
   1322 }
   1323 
   1324 inline const mpreal operator-(const unsigned long int b, const mpreal& a)
   1325 {
   1326     mpreal x(0, mpfr_get_prec(a.mpfr_ptr()));
   1327     mpfr_ui_sub(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd());
   1328     return x;
   1329 }
   1330 
   1331 inline const mpreal operator-(const unsigned int b, const mpreal& a)
   1332 {
   1333     mpreal x(0, mpfr_get_prec(a.mpfr_ptr()));
   1334     mpfr_ui_sub(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd());
   1335     return x;
   1336 }
   1337 
   1338 inline const mpreal operator-(const long int b, const mpreal& a)
   1339 {
   1340     mpreal x(0, mpfr_get_prec(a.mpfr_ptr()));
   1341     mpfr_si_sub(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd());
   1342     return x;
   1343 }
   1344 
   1345 inline const mpreal operator-(const int b, const mpreal& a)
   1346 {
   1347     mpreal x(0, mpfr_get_prec(a.mpfr_ptr()));
   1348     mpfr_si_sub(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd());
   1349     return x;
   1350 }
   1351 
   1352 //////////////////////////////////////////////////////////////////////////
   1353 // * Multiplication
   1354 inline mpreal& mpreal::operator*= (const mpreal& v)
   1355 {
   1356     mpfr_mul(mpfr_ptr(),mpfr_srcptr(),v.mpfr_srcptr(),mpreal::get_default_rnd());
   1357     MPREAL_MSVC_DEBUGVIEW_CODE;
   1358     return *this;
   1359 }
   1360 
   1361 inline mpreal& mpreal::operator*=(const mpz_t v)
   1362 {
   1363     mpfr_mul_z(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());
   1364     MPREAL_MSVC_DEBUGVIEW_CODE;
   1365     return *this;
   1366 }
   1367 
   1368 inline mpreal& mpreal::operator*=(const mpq_t v)
   1369 {
   1370     mpfr_mul_q(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());
   1371     MPREAL_MSVC_DEBUGVIEW_CODE;
   1372     return *this;
   1373 }
   1374 
   1375 inline mpreal& mpreal::operator*=(const long double v)
   1376 {
   1377     *this *= mpreal(v);
   1378     MPREAL_MSVC_DEBUGVIEW_CODE;
   1379     return *this;
   1380 }
   1381 
   1382 inline mpreal& mpreal::operator*=(const double v)
   1383 {
   1384 #if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))
   1385     mpfr_mul_d(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());
   1386 #else
   1387     *this *= mpreal(v);
   1388 #endif
   1389     MPREAL_MSVC_DEBUGVIEW_CODE;
   1390     return *this;
   1391 }
   1392 
   1393 inline mpreal& mpreal::operator*=(const unsigned long int v)
   1394 {
   1395     mpfr_mul_ui(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());
   1396     MPREAL_MSVC_DEBUGVIEW_CODE;
   1397     return *this;
   1398 }
   1399 
   1400 inline mpreal& mpreal::operator*=(const unsigned int v)
   1401 {
   1402     mpfr_mul_ui(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());
   1403     MPREAL_MSVC_DEBUGVIEW_CODE;
   1404     return *this;
   1405 }
   1406 
   1407 inline mpreal& mpreal::operator*=(const long int v)
   1408 {
   1409     mpfr_mul_si(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());
   1410     MPREAL_MSVC_DEBUGVIEW_CODE;
   1411     return *this;
   1412 }
   1413 
   1414 inline mpreal& mpreal::operator*=(const int v)
   1415 {
   1416     mpfr_mul_si(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());
   1417     MPREAL_MSVC_DEBUGVIEW_CODE;
   1418     return *this;
   1419 }
   1420 
   1421 inline const mpreal operator*(const mpreal& a, const mpreal& b)
   1422 {
   1423   mpreal c(0, (std::max)(mpfr_get_prec(a.mpfr_ptr()), mpfr_get_prec(b.mpfr_ptr())));
   1424   mpfr_mul(c.mpfr_ptr(), a.mpfr_srcptr(), b.mpfr_srcptr(), mpreal::get_default_rnd());
   1425   return c;
   1426 }
   1427 
   1428 //////////////////////////////////////////////////////////////////////////
   1429 // / Division
   1430 inline mpreal& mpreal::operator/=(const mpreal& v)
   1431 {
   1432     mpfr_div(mpfr_ptr(),mpfr_srcptr(),v.mpfr_srcptr(),mpreal::get_default_rnd());
   1433     MPREAL_MSVC_DEBUGVIEW_CODE;
   1434     return *this;
   1435 }
   1436 
   1437 inline mpreal& mpreal::operator/=(const mpz_t v)
   1438 {
   1439     mpfr_div_z(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());
   1440     MPREAL_MSVC_DEBUGVIEW_CODE;
   1441     return *this;
   1442 }
   1443 
   1444 inline mpreal& mpreal::operator/=(const mpq_t v)
   1445 {
   1446     mpfr_div_q(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());
   1447     MPREAL_MSVC_DEBUGVIEW_CODE;
   1448     return *this;
   1449 }
   1450 
   1451 inline mpreal& mpreal::operator/=(const long double v)
   1452 {
   1453     *this /= mpreal(v);
   1454     MPREAL_MSVC_DEBUGVIEW_CODE;
   1455     return *this;
   1456 }
   1457 
   1458 inline mpreal& mpreal::operator/=(const double v)
   1459 {
   1460 #if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))
   1461     mpfr_div_d(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());
   1462 #else
   1463     *this /= mpreal(v);
   1464 #endif
   1465     MPREAL_MSVC_DEBUGVIEW_CODE;
   1466     return *this;
   1467 }
   1468 
   1469 inline mpreal& mpreal::operator/=(const unsigned long int v)
   1470 {
   1471     mpfr_div_ui(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());
   1472     MPREAL_MSVC_DEBUGVIEW_CODE;
   1473     return *this;
   1474 }
   1475 
   1476 inline mpreal& mpreal::operator/=(const unsigned int v)
   1477 {
   1478     mpfr_div_ui(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());
   1479     MPREAL_MSVC_DEBUGVIEW_CODE;
   1480     return *this;
   1481 }
   1482 
   1483 inline mpreal& mpreal::operator/=(const long int v)
   1484 {
   1485     mpfr_div_si(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());
   1486     MPREAL_MSVC_DEBUGVIEW_CODE;
   1487     return *this;
   1488 }
   1489 
   1490 inline mpreal& mpreal::operator/=(const int v)
   1491 {
   1492     mpfr_div_si(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());
   1493     MPREAL_MSVC_DEBUGVIEW_CODE;
   1494     return *this;
   1495 }
   1496 
   1497 inline const mpreal operator/(const mpreal& a, const mpreal& b)
   1498 {
   1499   mpreal c(0, (std::max)(mpfr_get_prec(a.mpfr_srcptr()), mpfr_get_prec(b.mpfr_srcptr())));
   1500   mpfr_div(c.mpfr_ptr(), a.mpfr_srcptr(), b.mpfr_srcptr(), mpreal::get_default_rnd());
   1501   return c;
   1502 }
   1503 
   1504 inline const mpreal operator/(const unsigned long int b, const mpreal& a)
   1505 {
   1506     mpreal x(0, mpfr_get_prec(a.mpfr_srcptr()));
   1507     mpfr_ui_div(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd());
   1508     return x;
   1509 }
   1510 
   1511 inline const mpreal operator/(const unsigned int b, const mpreal& a)
   1512 {
   1513     mpreal x(0, mpfr_get_prec(a.mpfr_srcptr()));
   1514     mpfr_ui_div(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd());
   1515     return x;
   1516 }
   1517 
   1518 inline const mpreal operator/(const long int b, const mpreal& a)
   1519 {
   1520     mpreal x(0, mpfr_get_prec(a.mpfr_srcptr()));
   1521     mpfr_si_div(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd());
   1522     return x;
   1523 }
   1524 
   1525 inline const mpreal operator/(const int b, const mpreal& a)
   1526 {
   1527     mpreal x(0, mpfr_get_prec(a.mpfr_srcptr()));
   1528     mpfr_si_div(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd());
   1529     return x;
   1530 }
   1531 
   1532 inline const mpreal operator/(const double  b, const mpreal& a)
   1533 {
   1534 #if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))
   1535     mpreal x(0, mpfr_get_prec(a.mpfr_srcptr()));
   1536     mpfr_d_div(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd());
   1537     return x;
   1538 #else
   1539     mpreal x(0, mpfr_get_prec(a.mpfr_ptr()));
   1540     x /= a;
   1541     return x;
   1542 #endif
   1543 }
   1544 
   1545 //////////////////////////////////////////////////////////////////////////
   1546 // Shifts operators - Multiplication/Division by power of 2
   1547 inline mpreal& mpreal::operator<<=(const unsigned long int u)
   1548 {
   1549     mpfr_mul_2ui(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd());
   1550     MPREAL_MSVC_DEBUGVIEW_CODE;
   1551     return *this;
   1552 }
   1553 
   1554 inline mpreal& mpreal::operator<<=(const unsigned int u)
   1555 {
   1556     mpfr_mul_2ui(mpfr_ptr(),mpfr_srcptr(),static_cast<unsigned long int>(u),mpreal::get_default_rnd());
   1557     MPREAL_MSVC_DEBUGVIEW_CODE;
   1558     return *this;
   1559 }
   1560 
   1561 inline mpreal& mpreal::operator<<=(const long int u)
   1562 {
   1563     mpfr_mul_2si(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd());
   1564     MPREAL_MSVC_DEBUGVIEW_CODE;
   1565     return *this;
   1566 }
   1567 
   1568 inline mpreal& mpreal::operator<<=(const int u)
   1569 {
   1570     mpfr_mul_2si(mpfr_ptr(),mpfr_srcptr(),static_cast<long int>(u),mpreal::get_default_rnd());
   1571     MPREAL_MSVC_DEBUGVIEW_CODE;
   1572     return *this;
   1573 }
   1574 
   1575 inline mpreal& mpreal::operator>>=(const unsigned long int u)
   1576 {
   1577     mpfr_div_2ui(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd());
   1578     MPREAL_MSVC_DEBUGVIEW_CODE;
   1579     return *this;
   1580 }
   1581 
   1582 inline mpreal& mpreal::operator>>=(const unsigned int u)
   1583 {
   1584     mpfr_div_2ui(mpfr_ptr(),mpfr_srcptr(),static_cast<unsigned long int>(u),mpreal::get_default_rnd());
   1585     MPREAL_MSVC_DEBUGVIEW_CODE;
   1586     return *this;
   1587 }
   1588 
   1589 inline mpreal& mpreal::operator>>=(const long int u)
   1590 {
   1591     mpfr_div_2si(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd());
   1592     MPREAL_MSVC_DEBUGVIEW_CODE;
   1593     return *this;
   1594 }
   1595 
   1596 inline mpreal& mpreal::operator>>=(const int u)
   1597 {
   1598     mpfr_div_2si(mpfr_ptr(),mpfr_srcptr(),static_cast<long int>(u),mpreal::get_default_rnd());
   1599     MPREAL_MSVC_DEBUGVIEW_CODE;
   1600     return *this;
   1601 }
   1602 
   1603 inline const mpreal operator<<(const mpreal& v, const unsigned long int k)
   1604 {
   1605     return mul_2ui(v,k);
   1606 }
   1607 
   1608 inline const mpreal operator<<(const mpreal& v, const unsigned int k)
   1609 {
   1610     return mul_2ui(v,static_cast<unsigned long int>(k));
   1611 }
   1612 
   1613 inline const mpreal operator<<(const mpreal& v, const long int k)
   1614 {
   1615     return mul_2si(v,k);
   1616 }
   1617 
   1618 inline const mpreal operator<<(const mpreal& v, const int k)
   1619 {
   1620     return mul_2si(v,static_cast<long int>(k));
   1621 }
   1622 
   1623 inline const mpreal operator>>(const mpreal& v, const unsigned long int k)
   1624 {
   1625     return div_2ui(v,k);
   1626 }
   1627 
   1628 inline const mpreal operator>>(const mpreal& v, const long int k)
   1629 {
   1630     return div_2si(v,k);
   1631 }
   1632 
   1633 inline const mpreal operator>>(const mpreal& v, const unsigned int k)
   1634 {
   1635     return div_2ui(v,static_cast<unsigned long int>(k));
   1636 }
   1637 
   1638 inline const mpreal operator>>(const mpreal& v, const int k)
   1639 {
   1640     return div_2si(v,static_cast<long int>(k));
   1641 }
   1642 
   1643 // mul_2ui
   1644 inline const mpreal mul_2ui(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode)
   1645 {
   1646     mpreal x(v);
   1647     mpfr_mul_2ui(x.mpfr_ptr(),v.mpfr_srcptr(),k,rnd_mode);
   1648     return x;
   1649 }
   1650 
   1651 // mul_2si
   1652 inline const mpreal mul_2si(const mpreal& v, long int k, mp_rnd_t rnd_mode)
   1653 {
   1654     mpreal x(v);
   1655     mpfr_mul_2si(x.mpfr_ptr(),v.mpfr_srcptr(),k,rnd_mode);
   1656     return x;
   1657 }
   1658 
   1659 inline const mpreal div_2ui(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode)
   1660 {
   1661     mpreal x(v);
   1662     mpfr_div_2ui(x.mpfr_ptr(),v.mpfr_srcptr(),k,rnd_mode);
   1663     return x;
   1664 }
   1665 
   1666 inline const mpreal div_2si(const mpreal& v, long int k, mp_rnd_t rnd_mode)
   1667 {
   1668     mpreal x(v);
   1669     mpfr_div_2si(x.mpfr_ptr(),v.mpfr_srcptr(),k,rnd_mode);
   1670     return x;
   1671 }
   1672 
   1673 //////////////////////////////////////////////////////////////////////////
   1674 //Boolean operators
   1675 inline bool operator >  (const mpreal& a, const mpreal& b){    return (mpfr_greater_p       (a.mpfr_srcptr(),b.mpfr_srcptr()) !=0 );    }
   1676 inline bool operator >= (const mpreal& a, const mpreal& b){    return (mpfr_greaterequal_p  (a.mpfr_srcptr(),b.mpfr_srcptr()) !=0 );    }
   1677 inline bool operator <  (const mpreal& a, const mpreal& b){    return (mpfr_less_p          (a.mpfr_srcptr(),b.mpfr_srcptr()) !=0 );    }
   1678 inline bool operator <= (const mpreal& a, const mpreal& b){    return (mpfr_lessequal_p     (a.mpfr_srcptr(),b.mpfr_srcptr()) !=0 );    }
   1679 inline bool operator == (const mpreal& a, const mpreal& b){    return (mpfr_equal_p         (a.mpfr_srcptr(),b.mpfr_srcptr()) !=0 );    }
   1680 inline bool operator != (const mpreal& a, const mpreal& b){    return (mpfr_lessgreater_p   (a.mpfr_srcptr(),b.mpfr_srcptr()) !=0 );    }
   1681 
   1682 inline bool operator == (const mpreal& a, const unsigned long int b ){    return (mpfr_cmp_ui(a.mpfr_srcptr(),b) == 0 );    }
   1683 inline bool operator == (const mpreal& a, const unsigned int b      ){    return (mpfr_cmp_ui(a.mpfr_srcptr(),b) == 0 );    }
   1684 inline bool operator == (const mpreal& a, const long int b          ){    return (mpfr_cmp_si(a.mpfr_srcptr(),b) == 0 );    }
   1685 inline bool operator == (const mpreal& a, const int b               ){    return (mpfr_cmp_si(a.mpfr_srcptr(),b) == 0 );    }
   1686 inline bool operator == (const mpreal& a, const long double b       ){    return (mpfr_cmp_ld(a.mpfr_srcptr(),b) == 0 );    }
   1687 inline bool operator == (const mpreal& a, const double b            ){    return (mpfr_cmp_d (a.mpfr_srcptr(),b) == 0 );    }
   1688 
   1689 
   1690 inline bool isnan    (const mpreal& op){    return (mpfr_nan_p    (op.mpfr_srcptr()) != 0 );    }
   1691 inline bool isinf    (const mpreal& op){    return (mpfr_inf_p    (op.mpfr_srcptr()) != 0 );    }
   1692 inline bool isfinite (const mpreal& op){    return (mpfr_number_p (op.mpfr_srcptr()) != 0 );    }
   1693 inline bool iszero   (const mpreal& op){    return (mpfr_zero_p   (op.mpfr_srcptr()) != 0 );    }
   1694 inline bool isint    (const mpreal& op){    return (mpfr_integer_p(op.mpfr_srcptr()) != 0 );    }
   1695 
   1696 #if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0))
   1697 inline bool isregular(const mpreal& op){    return (mpfr_regular_p(op.mpfr_srcptr()));}
   1698 #endif
   1699 
   1700 //////////////////////////////////////////////////////////////////////////
   1701 // Type Converters
   1702 inline bool             mpreal::toBool (mp_rnd_t /*mode*/) const   {    return  mpfr_zero_p (mpfr_srcptr()) == 0;     }
   1703 inline long             mpreal::toLong   (mp_rnd_t mode)  const    {    return  mpfr_get_si (mpfr_srcptr(), mode);    }
   1704 inline unsigned long    mpreal::toULong  (mp_rnd_t mode)  const    {    return  mpfr_get_ui (mpfr_srcptr(), mode);    }
   1705 inline float            mpreal::toFloat  (mp_rnd_t mode)  const    {    return  mpfr_get_flt(mpfr_srcptr(), mode);    }
   1706 inline double           mpreal::toDouble (mp_rnd_t mode)  const    {    return  mpfr_get_d  (mpfr_srcptr(), mode);    }
   1707 inline long double      mpreal::toLDouble(mp_rnd_t mode)  const    {    return  mpfr_get_ld (mpfr_srcptr(), mode);    }
   1708 
   1709 #if defined (MPREAL_HAVE_INT64_SUPPORT)
   1710 inline int64_t      mpreal::toInt64 (mp_rnd_t mode)    const{    return mpfr_get_sj(mpfr_srcptr(), mode);    }
   1711 inline uint64_t     mpreal::toUInt64(mp_rnd_t mode)    const{    return mpfr_get_uj(mpfr_srcptr(), mode);    }
   1712 #endif
   1713 
   1714 inline ::mpfr_ptr     mpreal::mpfr_ptr()             { return mp; }
   1715 inline ::mpfr_srcptr  mpreal::mpfr_ptr()    const    { return mp; }
   1716 inline ::mpfr_srcptr  mpreal::mpfr_srcptr() const    { return mp; }
   1717 
   1718 template <class T>
   1719 inline std::string toString(T t, std::ios_base & (*f)(std::ios_base&))
   1720 {
   1721     std::ostringstream oss;
   1722     oss << f << t;
   1723     return oss.str();
   1724 }
   1725 
   1726 #if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))
   1727 
   1728 inline std::string mpreal::toString(const std::string& format) const
   1729 {
   1730     char *s = NULL;
   1731     std::string out;
   1732 
   1733     if( !format.empty() )
   1734     {
   1735         if(!(mpfr_asprintf(&s, format.c_str(), mpfr_srcptr()) < 0))
   1736         {
   1737             out = std::string(s);
   1738 
   1739             mpfr_free_str(s);
   1740         }
   1741     }
   1742 
   1743     return out;
   1744 }
   1745 
   1746 #endif
   1747 
   1748 inline std::string mpreal::toString(int n, int b, mp_rnd_t mode) const
   1749 {
   1750     // TODO: Add extended format specification (f, e, rounding mode) as it done in output operator
   1751     (void)b;
   1752     (void)mode;
   1753 
   1754 #if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))
   1755 
   1756     std::ostringstream format;
   1757 
   1758     int digits = (n >= 0) ? n : bits2digits(mpfr_get_prec(mpfr_srcptr()));
   1759 
   1760     format << "%." << digits << "RNg";
   1761 
   1762     return toString(format.str());
   1763 
   1764 #else
   1765 
   1766     char *s, *ns = NULL;
   1767     size_t slen, nslen;
   1768     mp_exp_t exp;
   1769     std::string out;
   1770 
   1771     if(mpfr_inf_p(mp))
   1772     {
   1773         if(mpfr_sgn(mp)>0) return "+Inf";
   1774         else               return "-Inf";
   1775     }
   1776 
   1777     if(mpfr_zero_p(mp)) return "0";
   1778     if(mpfr_nan_p(mp))  return "NaN";
   1779 
   1780     s  = mpfr_get_str(NULL, &exp, b, 0, mp, mode);
   1781     ns = mpfr_get_str(NULL, &exp, b, (std::max)(0,n), mp, mode);
   1782 
   1783     if(s!=NULL && ns!=NULL)
   1784     {
   1785         slen  = strlen(s);
   1786         nslen = strlen(ns);
   1787         if(nslen<=slen)
   1788         {
   1789             mpfr_free_str(s);
   1790             s = ns;
   1791             slen = nslen;
   1792         }
   1793         else {
   1794             mpfr_free_str(ns);
   1795         }
   1796 
   1797         // Make human eye-friendly formatting if possible
   1798         if (exp>0 && static_cast<size_t>(exp)<slen)
   1799         {
   1800             if(s[0]=='-')
   1801             {
   1802                 // Remove zeros starting from right end
   1803                 char* ptr = s+slen-1;
   1804                 while (*ptr=='0' && ptr>s+exp) ptr--;
   1805 
   1806                 if(ptr==s+exp) out = std::string(s,exp+1);
   1807                 else           out = std::string(s,exp+1)+'.'+std::string(s+exp+1,ptr-(s+exp+1)+1);
   1808 
   1809                 //out = string(s,exp+1)+'.'+string(s+exp+1);
   1810             }
   1811             else
   1812             {
   1813                 // Remove zeros starting from right end
   1814                 char* ptr = s+slen-1;
   1815                 while (*ptr=='0' && ptr>s+exp-1) ptr--;
   1816 
   1817                 if(ptr==s+exp-1) out = std::string(s,exp);
   1818                 else             out = std::string(s,exp)+'.'+std::string(s+exp,ptr-(s+exp)+1);
   1819 
   1820                 //out = string(s,exp)+'.'+string(s+exp);
   1821             }
   1822 
   1823         }else{ // exp<0 || exp>slen
   1824             if(s[0]=='-')
   1825             {
   1826                 // Remove zeros starting from right end
   1827                 char* ptr = s+slen-1;
   1828                 while (*ptr=='0' && ptr>s+1) ptr--;
   1829 
   1830                 if(ptr==s+1) out = std::string(s,2);
   1831                 else         out = std::string(s,2)+'.'+std::string(s+2,ptr-(s+2)+1);
   1832 
   1833                 //out = string(s,2)+'.'+string(s+2);
   1834             }
   1835             else
   1836             {
   1837                 // Remove zeros starting from right end
   1838                 char* ptr = s+slen-1;
   1839                 while (*ptr=='0' && ptr>s) ptr--;
   1840 
   1841                 if(ptr==s) out = std::string(s,1);
   1842                 else       out = std::string(s,1)+'.'+std::string(s+1,ptr-(s+1)+1);
   1843 
   1844                 //out = string(s,1)+'.'+string(s+1);
   1845             }
   1846 
   1847             // Make final string
   1848             if(--exp)
   1849             {
   1850                 if(exp>0) out += "e+"+mpfr::toString<mp_exp_t>(exp,std::dec);
   1851                 else       out += "e"+mpfr::toString<mp_exp_t>(exp,std::dec);
   1852             }
   1853         }
   1854 
   1855         mpfr_free_str(s);
   1856         return out;
   1857     }else{
   1858         return "conversion error!";
   1859     }
   1860 #endif
   1861 }
   1862 
   1863 
   1864 //////////////////////////////////////////////////////////////////////////
   1865 // I/O
   1866 inline std::ostream& mpreal::output(std::ostream& os) const
   1867 {
   1868     std::ostringstream format;
   1869     const std::ios::fmtflags flags = os.flags();
   1870 
   1871     format << ((flags & std::ios::showpos) ? "%+" : "%");
   1872     if (os.precision() >= 0)
   1873         format << '.' << os.precision() << "R*"
   1874                << ((flags & std::ios::floatfield) == std::ios::fixed ? 'f' :
   1875                    (flags & std::ios::floatfield) == std::ios::scientific ? 'e' :
   1876                    'g');
   1877     else
   1878         format << "R*e";
   1879 
   1880     char *s = NULL;
   1881     if(!(mpfr_asprintf(&s, format.str().c_str(),
   1882                         mpfr::mpreal::get_default_rnd(),
   1883                         mpfr_srcptr())
   1884         < 0))
   1885     {
   1886         os << std::string(s);
   1887         mpfr_free_str(s);
   1888     }
   1889     return os;
   1890 }
   1891 
   1892 inline std::ostream& operator<<(std::ostream& os, const mpreal& v)
   1893 {
   1894     return v.output(os);
   1895 }
   1896 
   1897 inline std::istream& operator>>(std::istream &is, mpreal& v)
   1898 {
   1899     // TODO: use cout::hexfloat and other flags to setup base
   1900     std::string tmp;
   1901     is >> tmp;
   1902     mpfr_set_str(v.mpfr_ptr(), tmp.c_str(), 10, mpreal::get_default_rnd());
   1903     return is;
   1904 }
   1905 
   1906 //////////////////////////////////////////////////////////////////////////
   1907 //     Bits - decimal digits relation
   1908 //        bits   = ceil(digits*log[2](10))
   1909 //        digits = floor(bits*log[10](2))
   1910 
   1911 inline mp_prec_t digits2bits(int d)
   1912 {
   1913     const double LOG2_10 = 3.3219280948873624;
   1914 
   1915     return mp_prec_t(std::ceil( d * LOG2_10 ));
   1916 }
   1917 
   1918 inline int bits2digits(mp_prec_t b)
   1919 {
   1920     const double LOG10_2 = 0.30102999566398119;
   1921 
   1922     return int(std::floor( b * LOG10_2 ));
   1923 }
   1924 
   1925 //////////////////////////////////////////////////////////////////////////
   1926 // Set/Get number properties
   1927 inline int sgn(const mpreal& op)
   1928 {
   1929     int r = mpfr_signbit(op.mpfr_srcptr());
   1930     return (r > 0? -1 : 1);
   1931 }
   1932 
   1933 inline mpreal& mpreal::setSign(int sign, mp_rnd_t RoundingMode)
   1934 {
   1935     mpfr_setsign(mpfr_ptr(), mpfr_srcptr(), (sign < 0 ? 1 : 0), RoundingMode);
   1936     MPREAL_MSVC_DEBUGVIEW_CODE;
   1937     return *this;
   1938 }
   1939 
   1940 inline int mpreal::getPrecision() const
   1941 {
   1942     return int(mpfr_get_prec(mpfr_srcptr()));
   1943 }
   1944 
   1945 inline mpreal& mpreal::setPrecision(int Precision, mp_rnd_t RoundingMode)
   1946 {
   1947     mpfr_prec_round(mpfr_ptr(), Precision, RoundingMode);
   1948     MPREAL_MSVC_DEBUGVIEW_CODE;
   1949     return *this;
   1950 }
   1951 
   1952 inline mpreal& mpreal::setInf(int sign)
   1953 {
   1954     mpfr_set_inf(mpfr_ptr(), sign);
   1955     MPREAL_MSVC_DEBUGVIEW_CODE;
   1956     return *this;
   1957 }
   1958 
   1959 inline mpreal& mpreal::setNan()
   1960 {
   1961     mpfr_set_nan(mpfr_ptr());
   1962     MPREAL_MSVC_DEBUGVIEW_CODE;
   1963     return *this;
   1964 }
   1965 
   1966 inline mpreal&    mpreal::setZero(int sign)
   1967 {
   1968 
   1969 #if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0))
   1970     mpfr_set_zero(mpfr_ptr(), sign);
   1971 #else
   1972     mpfr_set_si(mpfr_ptr(), 0, (mpfr_get_default_rounding_mode)());
   1973     setSign(sign);
   1974 #endif
   1975 
   1976     MPREAL_MSVC_DEBUGVIEW_CODE;
   1977     return *this;
   1978 }
   1979 
   1980 inline mp_prec_t mpreal::get_prec() const
   1981 {
   1982     return mpfr_get_prec(mpfr_srcptr());
   1983 }
   1984 
   1985 inline void mpreal::set_prec(mp_prec_t prec, mp_rnd_t rnd_mode)
   1986 {
   1987     mpfr_prec_round(mpfr_ptr(),prec,rnd_mode);
   1988     MPREAL_MSVC_DEBUGVIEW_CODE;
   1989 }
   1990 
   1991 inline mp_exp_t mpreal::get_exp ()
   1992 {
   1993     return mpfr_get_exp(mpfr_srcptr());
   1994 }
   1995 
   1996 inline int mpreal::set_exp (mp_exp_t e)
   1997 {
   1998     int x = mpfr_set_exp(mpfr_ptr(), e);
   1999     MPREAL_MSVC_DEBUGVIEW_CODE;
   2000     return x;
   2001 }
   2002 
   2003 inline const mpreal frexp(const mpreal& v, mp_exp_t* exp)
   2004 {
   2005     mpreal x(v);
   2006     *exp = x.get_exp();
   2007     x.set_exp(0);
   2008     return x;
   2009 }
   2010 
   2011 inline const mpreal ldexp(const mpreal& v, mp_exp_t exp)
   2012 {
   2013     mpreal x(v);
   2014 
   2015     // rounding is not important since we just increasing the exponent
   2016     mpfr_mul_2si(x.mpfr_ptr(), x.mpfr_srcptr(), exp, mpreal::get_default_rnd());
   2017     return x;
   2018 }
   2019 
   2020 inline mpreal machine_epsilon(mp_prec_t prec)
   2021 {
   2022     /* the smallest eps such that 1 + eps != 1 */
   2023     return machine_epsilon(mpreal(1, prec));
   2024 }
   2025 
   2026 inline mpreal machine_epsilon(const mpreal& x)
   2027 {
   2028     /* the smallest eps such that x + eps != x */
   2029     if( x < 0)
   2030     {
   2031         return nextabove(-x) + x;
   2032     }else{
   2033         return nextabove( x) - x;
   2034     }
   2035 }
   2036 
   2037 // minval is 'safe' meaning 1 / minval does not overflow
   2038 inline mpreal minval(mp_prec_t prec)
   2039 {
   2040     /* min = 1/2 * 2^emin = 2^(emin - 1) */
   2041     return mpreal(1, prec) << mpreal::get_emin()-1;
   2042 }
   2043 
   2044 // maxval is 'safe' meaning 1 / maxval does not underflow
   2045 inline mpreal maxval(mp_prec_t prec)
   2046 {
   2047     /* max = (1 - eps) * 2^emax, eps is machine epsilon */
   2048     return (mpreal(1, prec) - machine_epsilon(prec)) << mpreal::get_emax();
   2049 }
   2050 
   2051 inline bool isEqualUlps(const mpreal& a, const mpreal& b, int maxUlps)
   2052 {
   2053     return abs(a - b) <= machine_epsilon((max)(abs(a), abs(b))) * maxUlps;
   2054 }
   2055 
   2056 inline bool isEqualFuzzy(const mpreal& a, const mpreal& b, const mpreal& eps)
   2057 {
   2058     return abs(a - b) <= eps;
   2059 }
   2060 
   2061 inline bool isEqualFuzzy(const mpreal& a, const mpreal& b)
   2062 {
   2063     return isEqualFuzzy(a, b, machine_epsilon((max)(1, (min)(abs(a), abs(b)))));
   2064 }
   2065 
   2066 inline const mpreal modf(const mpreal& v, mpreal& n)
   2067 {
   2068     mpreal f(v);
   2069 
   2070     // rounding is not important since we are using the same number
   2071     mpfr_frac (f.mpfr_ptr(),f.mpfr_srcptr(),mpreal::get_default_rnd());
   2072     mpfr_trunc(n.mpfr_ptr(),v.mpfr_srcptr());
   2073     return f;
   2074 }
   2075 
   2076 inline int mpreal::check_range (int t, mp_rnd_t rnd_mode)
   2077 {
   2078     return mpfr_check_range(mpfr_ptr(),t,rnd_mode);
   2079 }
   2080 
   2081 inline int mpreal::subnormalize (int t,mp_rnd_t rnd_mode)
   2082 {
   2083     int r = mpfr_subnormalize(mpfr_ptr(),t,rnd_mode);
   2084     MPREAL_MSVC_DEBUGVIEW_CODE;
   2085     return r;
   2086 }
   2087 
   2088 inline mp_exp_t mpreal::get_emin (void)
   2089 {
   2090     return mpfr_get_emin();
   2091 }
   2092 
   2093 inline int mpreal::set_emin (mp_exp_t exp)
   2094 {
   2095     return mpfr_set_emin(exp);
   2096 }
   2097 
   2098 inline mp_exp_t mpreal::get_emax (void)
   2099 {
   2100     return mpfr_get_emax();
   2101 }
   2102 
   2103 inline int mpreal::set_emax (mp_exp_t exp)
   2104 {
   2105     return mpfr_set_emax(exp);
   2106 }
   2107 
   2108 inline mp_exp_t mpreal::get_emin_min (void)
   2109 {
   2110     return mpfr_get_emin_min();
   2111 }
   2112 
   2113 inline mp_exp_t mpreal::get_emin_max (void)
   2114 {
   2115     return mpfr_get_emin_max();
   2116 }
   2117 
   2118 inline mp_exp_t mpreal::get_emax_min (void)
   2119 {
   2120     return mpfr_get_emax_min();
   2121 }
   2122 
   2123 inline mp_exp_t mpreal::get_emax_max (void)
   2124 {
   2125     return mpfr_get_emax_max();
   2126 }
   2127 
   2128 //////////////////////////////////////////////////////////////////////////
   2129 // Mathematical Functions
   2130 //////////////////////////////////////////////////////////////////////////
   2131 #define MPREAL_UNARY_MATH_FUNCTION_BODY(f)                    \
   2132         mpreal y(0, mpfr_get_prec(x.mpfr_srcptr()));          \
   2133         mpfr_##f(y.mpfr_ptr(), x.mpfr_srcptr(), r);           \
   2134         return y;
   2135 
   2136 inline const mpreal sqr  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd())
   2137 {   MPREAL_UNARY_MATH_FUNCTION_BODY(sqr );    }
   2138 
   2139 inline const mpreal sqrt (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd())
   2140 {   MPREAL_UNARY_MATH_FUNCTION_BODY(sqrt);    }
   2141 
   2142 inline const mpreal sqrt(const unsigned long int x, mp_rnd_t r)
   2143 {
   2144     mpreal y;
   2145     mpfr_sqrt_ui(y.mpfr_ptr(), x, r);
   2146     return y;
   2147 }
   2148 
   2149 inline const mpreal sqrt(const unsigned int v, mp_rnd_t rnd_mode)
   2150 {
   2151     return sqrt(static_cast<unsigned long int>(v),rnd_mode);
   2152 }
   2153 
   2154 inline const mpreal sqrt(const long int v, mp_rnd_t rnd_mode)
   2155 {
   2156     if (v>=0)   return sqrt(static_cast<unsigned long int>(v),rnd_mode);
   2157     else        return mpreal().setNan(); // NaN
   2158 }
   2159 
   2160 inline const mpreal sqrt(const int v, mp_rnd_t rnd_mode)
   2161 {
   2162     if (v>=0)   return sqrt(static_cast<unsigned long int>(v),rnd_mode);
   2163     else        return mpreal().setNan(); // NaN
   2164 }
   2165 
   2166 inline const mpreal root(const mpreal& x, unsigned long int k, mp_rnd_t r = mpreal::get_default_rnd())
   2167 {
   2168     mpreal y(0, mpfr_get_prec(x.mpfr_srcptr()));
   2169     mpfr_root(y.mpfr_ptr(), x.mpfr_srcptr(), k, r);
   2170     return y;
   2171 }
   2172 
   2173 inline const mpreal dim(const mpreal& a, const mpreal& b, mp_rnd_t r = mpreal::get_default_rnd())
   2174 {
   2175     mpreal y(0, mpfr_get_prec(a.mpfr_srcptr()));
   2176     mpfr_dim(y.mpfr_ptr(), a.mpfr_srcptr(), b.mpfr_srcptr(), r);
   2177     return y;
   2178 }
   2179 
   2180 inline int cmpabs(const mpreal& a,const mpreal& b)
   2181 {
   2182     return mpfr_cmpabs(a.mpfr_ptr(), b.mpfr_srcptr());
   2183 }
   2184 
   2185 inline int sin_cos(mpreal& s, mpreal& c, const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd())
   2186 {
   2187     return mpfr_sin_cos(s.mpfr_ptr(), c.mpfr_ptr(), v.mpfr_srcptr(), rnd_mode);
   2188 }
   2189 
   2190 inline const mpreal sqrt  (const long double v, mp_rnd_t rnd_mode)    {   return sqrt(mpreal(v),rnd_mode);    }
   2191 inline const mpreal sqrt  (const double v, mp_rnd_t rnd_mode)         {   return sqrt(mpreal(v),rnd_mode);    }
   2192 
   2193 inline const mpreal cbrt  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(cbrt );    }
   2194 inline const mpreal fabs  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(abs  );    }
   2195 inline const mpreal abs   (const mpreal& x, mp_rnd_t r)                             {   MPREAL_UNARY_MATH_FUNCTION_BODY(abs  );    }
   2196 inline const mpreal log   (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(log  );    }
   2197 inline const mpreal log2  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(log2 );    }
   2198 inline const mpreal log10 (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(log10);    }
   2199 inline const mpreal exp   (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(exp  );    }
   2200 inline const mpreal exp2  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(exp2 );    }
   2201 inline const mpreal exp10 (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(exp10);    }
   2202 inline const mpreal cos   (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(cos  );    }
   2203 inline const mpreal sin   (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(sin  );    }
   2204 inline const mpreal tan   (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(tan  );    }
   2205 inline const mpreal sec   (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(sec  );    }
   2206 inline const mpreal csc   (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(csc  );    }
   2207 inline const mpreal cot   (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(cot  );    }
   2208 inline const mpreal acos  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(acos );    }
   2209 inline const mpreal asin  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(asin );    }
   2210 inline const mpreal atan  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(atan );    }
   2211 
   2212 inline const mpreal acot  (const mpreal& v, mp_rnd_t r = mpreal::get_default_rnd()) {   return atan (1/v, r);                      }
   2213 inline const mpreal asec  (const mpreal& v, mp_rnd_t r = mpreal::get_default_rnd()) {   return acos (1/v, r);                      }
   2214 inline const mpreal acsc  (const mpreal& v, mp_rnd_t r = mpreal::get_default_rnd()) {   return asin (1/v, r);                      }
   2215 inline const mpreal acoth (const mpreal& v, mp_rnd_t r = mpreal::get_default_rnd()) {   return atanh(1/v, r);                      }
   2216 inline const mpreal asech (const mpreal& v, mp_rnd_t r = mpreal::get_default_rnd()) {   return acosh(1/v, r);                      }
   2217 inline const mpreal acsch (const mpreal& v, mp_rnd_t r = mpreal::get_default_rnd()) {   return asinh(1/v, r);                      }
   2218 
   2219 inline const mpreal cosh  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(cosh );    }
   2220 inline const mpreal sinh  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(sinh );    }
   2221 inline const mpreal tanh  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(tanh );    }
   2222 inline const mpreal sech  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(sech );    }
   2223 inline const mpreal csch  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(csch );    }
   2224 inline const mpreal coth  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(coth );    }
   2225 inline const mpreal acosh (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(acosh);    }
   2226 inline const mpreal asinh (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(asinh);    }
   2227 inline const mpreal atanh (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(atanh);    }
   2228 
   2229 inline const mpreal log1p   (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(log1p  );    }
   2230 inline const mpreal expm1   (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(expm1  );    }
   2231 inline const mpreal eint    (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(eint   );    }
   2232 inline const mpreal gamma   (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(gamma  );    }
   2233 inline const mpreal lngamma (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(lngamma);    }
   2234 inline const mpreal zeta    (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(zeta   );    }
   2235 inline const mpreal erf     (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(erf    );    }
   2236 inline const mpreal erfc    (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(erfc   );    }
   2237 inline const mpreal besselj0(const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(j0     );    }
   2238 inline const mpreal besselj1(const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(j1     );    }
   2239 inline const mpreal bessely0(const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(y0     );    }
   2240 inline const mpreal bessely1(const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(y1     );    }
   2241 
   2242 inline const mpreal atan2 (const mpreal& y, const mpreal& x, mp_rnd_t rnd_mode = mpreal::get_default_rnd())
   2243 {
   2244     mpreal a(0,(std::max)(y.getPrecision(), x.getPrecision()));
   2245     mpfr_atan2(a.mpfr_ptr(), y.mpfr_srcptr(), x.mpfr_srcptr(), rnd_mode);
   2246     return a;
   2247 }
   2248 
   2249 inline const mpreal hypot (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd())
   2250 {
   2251     mpreal a(0,(std::max)(y.getPrecision(), x.getPrecision()));
   2252     mpfr_hypot(a.mpfr_ptr(), x.mpfr_srcptr(), y.mpfr_srcptr(), rnd_mode);
   2253     return a;
   2254 }
   2255 
   2256 inline const mpreal remainder (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd())
   2257 {
   2258     mpreal a(0,(std::max)(y.getPrecision(), x.getPrecision()));
   2259     mpfr_remainder(a.mpfr_ptr(), x.mpfr_srcptr(), y.mpfr_srcptr(), rnd_mode);
   2260     return a;
   2261 }
   2262 
   2263 inline const mpreal remquo (long* q, const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd())
   2264 {
   2265     mpreal a(0,(std::max)(y.getPrecision(), x.getPrecision()));
   2266     mpfr_remquo(a.mpfr_ptr(),q, x.mpfr_srcptr(), y.mpfr_srcptr(), rnd_mode);
   2267     return a;
   2268 }
   2269 
   2270 inline const mpreal fac_ui (unsigned long int v, mp_prec_t prec     = mpreal::get_default_prec(),
   2271                                            mp_rnd_t  rnd_mode = mpreal::get_default_rnd())
   2272 {
   2273     mpreal x(0, prec);
   2274     mpfr_fac_ui(x.mpfr_ptr(),v,rnd_mode);
   2275     return x;
   2276 }
   2277 
   2278 
   2279 inline const mpreal lgamma (const mpreal& v, int *signp = 0, mp_rnd_t rnd_mode = mpreal::get_default_rnd())
   2280 {
   2281     mpreal x(v);
   2282     int tsignp;
   2283 
   2284     if(signp)   mpfr_lgamma(x.mpfr_ptr(),  signp,v.mpfr_srcptr(),rnd_mode);
   2285     else        mpfr_lgamma(x.mpfr_ptr(),&tsignp,v.mpfr_srcptr(),rnd_mode);
   2286 
   2287     return x;
   2288 }
   2289 
   2290 
   2291 inline const mpreal besseljn (long n, const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd())
   2292 {
   2293     mpreal  y(0, x.getPrecision());
   2294     mpfr_jn(y.mpfr_ptr(), n, x.mpfr_srcptr(), r);
   2295     return y;
   2296 }
   2297 
   2298 inline const mpreal besselyn (long n, const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd())
   2299 {
   2300     mpreal  y(0, x.getPrecision());
   2301     mpfr_yn(y.mpfr_ptr(), n, x.mpfr_srcptr(), r);
   2302     return y;
   2303 }
   2304 
   2305 inline const mpreal fma (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode = mpreal::get_default_rnd())
   2306 {
   2307     mpreal a;
   2308     mp_prec_t p1, p2, p3;
   2309 
   2310     p1 = v1.get_prec();
   2311     p2 = v2.get_prec();
   2312     p3 = v3.get_prec();
   2313 
   2314     a.set_prec(p3>p2?(p3>p1?p3:p1):(p2>p1?p2:p1));
   2315 
   2316     mpfr_fma(a.mp,v1.mp,v2.mp,v3.mp,rnd_mode);
   2317     return a;
   2318 }
   2319 
   2320 inline const mpreal fms (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode = mpreal::get_default_rnd())
   2321 {
   2322     mpreal a;
   2323     mp_prec_t p1, p2, p3;
   2324 
   2325     p1 = v1.get_prec();
   2326     p2 = v2.get_prec();
   2327     p3 = v3.get_prec();
   2328 
   2329     a.set_prec(p3>p2?(p3>p1?p3:p1):(p2>p1?p2:p1));
   2330 
   2331     mpfr_fms(a.mp,v1.mp,v2.mp,v3.mp,rnd_mode);
   2332     return a;
   2333 }
   2334 
   2335 inline const mpreal agm (const mpreal& v1, const mpreal& v2, mp_rnd_t rnd_mode = mpreal::get_default_rnd())
   2336 {
   2337     mpreal a;
   2338     mp_prec_t p1, p2;
   2339 
   2340     p1 = v1.get_prec();
   2341     p2 = v2.get_prec();
   2342 
   2343     a.set_prec(p1>p2?p1:p2);
   2344 
   2345     mpfr_agm(a.mp, v1.mp, v2.mp, rnd_mode);
   2346 
   2347     return a;
   2348 }
   2349 
   2350 inline const mpreal sum (const mpreal tab[], unsigned long int n, mp_rnd_t rnd_mode = mpreal::get_default_rnd())
   2351 {
   2352     mpreal x;
   2353     mpfr_ptr* t;
   2354     unsigned long int i;
   2355 
   2356     t = new mpfr_ptr[n];
   2357     for (i=0;i<n;i++) t[i] = (mpfr_ptr)tab[i].mp;
   2358     mpfr_sum(x.mp,t,n,rnd_mode);
   2359     delete[] t;
   2360     return x;
   2361 }
   2362 
   2363 //////////////////////////////////////////////////////////////////////////
   2364 // MPFR 2.4.0 Specifics
   2365 #if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))
   2366 
   2367 inline int sinh_cosh(mpreal& s, mpreal& c, const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd())
   2368 {
   2369     return mpfr_sinh_cosh(s.mp,c.mp,v.mp,rnd_mode);
   2370 }
   2371 
   2372 inline const mpreal li2 (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd())
   2373 {
   2374     MPREAL_UNARY_MATH_FUNCTION_BODY(li2);
   2375 }
   2376 
   2377 inline const mpreal rem (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd())
   2378 {
   2379     /*  R = rem(X,Y) if Y != 0, returns X - n * Y where n = trunc(X/Y). */
   2380     return fmod(x, y, rnd_mode);
   2381 }
   2382 
   2383 inline const mpreal mod (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd())
   2384 {
   2385     (void)rnd_mode;
   2386 
   2387     /*
   2388 
   2389     m = mod(x,y) if y != 0, returns x - n*y where n = floor(x/y)
   2390 
   2391     The following are true by convention:
   2392     - mod(x,0) is x
   2393     - mod(x,x) is 0
   2394     - mod(x,y) for x != y and y != 0 has the same sign as y.
   2395 
   2396     */
   2397 
   2398     if(iszero(y)) return x;
   2399     if(x == y) return 0;
   2400 
   2401     mpreal m = x - floor(x / y) * y;
   2402 
   2403     m.setSign(sgn(y)); // make sure result has the same sign as Y
   2404 
   2405     return m;
   2406 }
   2407 
   2408 inline const mpreal fmod (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd())
   2409 {
   2410     mpreal a;
   2411     mp_prec_t yp, xp;
   2412 
   2413     yp = y.get_prec();
   2414     xp = x.get_prec();
   2415 
   2416     a.set_prec(yp>xp?yp:xp);
   2417 
   2418     mpfr_fmod(a.mp, x.mp, y.mp, rnd_mode);
   2419 
   2420     return a;
   2421 }
   2422 
   2423 inline const mpreal rec_sqrt(const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd())
   2424 {
   2425     mpreal x(v);
   2426     mpfr_rec_sqrt(x.mp,v.mp,rnd_mode);
   2427     return x;
   2428 }
   2429 #endif //  MPFR 2.4.0 Specifics
   2430 
   2431 //////////////////////////////////////////////////////////////////////////
   2432 // MPFR 3.0.0 Specifics
   2433 #if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0))
   2434 inline const mpreal digamma (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(digamma);     }
   2435 inline const mpreal ai      (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(ai);          }
   2436 #endif // MPFR 3.0.0 Specifics
   2437 
   2438 //////////////////////////////////////////////////////////////////////////
   2439 // Constants
   2440 inline const mpreal const_log2 (mp_prec_t p = mpreal::get_default_prec(), mp_rnd_t r = mpreal::get_default_rnd())
   2441 {
   2442     mpreal x(0, p);
   2443     mpfr_const_log2(x.mpfr_ptr(), r);
   2444     return x;
   2445 }
   2446 
   2447 inline const mpreal const_pi (mp_prec_t p = mpreal::get_default_prec(), mp_rnd_t r = mpreal::get_default_rnd())
   2448 {
   2449     mpreal x(0, p);
   2450     mpfr_const_pi(x.mpfr_ptr(), r);
   2451     return x;
   2452 }
   2453 
   2454 inline const mpreal const_euler (mp_prec_t p = mpreal::get_default_prec(), mp_rnd_t r = mpreal::get_default_rnd())
   2455 {
   2456     mpreal x(0, p);
   2457     mpfr_const_euler(x.mpfr_ptr(), r);
   2458     return x;
   2459 }
   2460 
   2461 inline const mpreal const_catalan (mp_prec_t p = mpreal::get_default_prec(), mp_rnd_t r = mpreal::get_default_rnd())
   2462 {
   2463     mpreal x(0, p);
   2464     mpfr_const_catalan(x.mpfr_ptr(), r);
   2465     return x;
   2466 }
   2467 
   2468 inline const mpreal const_infinity (int sign = 1, mp_prec_t p = mpreal::get_default_prec())
   2469 {
   2470     mpreal x(0, p);
   2471     mpfr_set_inf(x.mpfr_ptr(), sign);
   2472     return x;
   2473 }
   2474 
   2475 //////////////////////////////////////////////////////////////////////////
   2476 // Integer Related Functions
   2477 inline const mpreal ceil(const mpreal& v)
   2478 {
   2479     mpreal x(v);
   2480     mpfr_ceil(x.mp,v.mp);
   2481     return x;
   2482 }
   2483 
   2484 inline const mpreal floor(const mpreal& v)
   2485 {
   2486     mpreal x(v);
   2487     mpfr_floor(x.mp,v.mp);
   2488     return x;
   2489 }
   2490 
   2491 inline const mpreal round(const mpreal& v)
   2492 {
   2493     mpreal x(v);
   2494     mpfr_round(x.mp,v.mp);
   2495     return x;
   2496 }
   2497 
   2498 inline const mpreal trunc(const mpreal& v)
   2499 {
   2500     mpreal x(v);
   2501     mpfr_trunc(x.mp,v.mp);
   2502     return x;
   2503 }
   2504 
   2505 inline const mpreal rint       (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(rint      );     }
   2506 inline const mpreal rint_ceil  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(rint_ceil );     }
   2507 inline const mpreal rint_floor (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(rint_floor);     }
   2508 inline const mpreal rint_round (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(rint_round);     }
   2509 inline const mpreal rint_trunc (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(rint_trunc);     }
   2510 inline const mpreal frac       (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(frac      );     }
   2511 
   2512 //////////////////////////////////////////////////////////////////////////
   2513 // Miscellaneous Functions
   2514 inline void         swap (mpreal& a, mpreal& b)            {    mpfr_swap(a.mp,b.mp);   }
   2515 inline const mpreal (max)(const mpreal& x, const mpreal& y){    return (x>y?x:y);       }
   2516 inline const mpreal (min)(const mpreal& x, const mpreal& y){    return (x<y?x:y);       }
   2517 
   2518 inline const mpreal fmax(const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd())
   2519 {
   2520     mpreal a;
   2521     mpfr_max(a.mp,x.mp,y.mp,rnd_mode);
   2522     return a;
   2523 }
   2524 
   2525 inline const mpreal fmin(const mpreal& x, const mpreal& y,  mp_rnd_t rnd_mode = mpreal::get_default_rnd())
   2526 {
   2527     mpreal a;
   2528     mpfr_min(a.mp,x.mp,y.mp,rnd_mode);
   2529     return a;
   2530 }
   2531 
   2532 inline const mpreal nexttoward (const mpreal& x, const mpreal& y)
   2533 {
   2534     mpreal a(x);
   2535     mpfr_nexttoward(a.mp,y.mp);
   2536     return a;
   2537 }
   2538 
   2539 inline const mpreal nextabove  (const mpreal& x)
   2540 {
   2541     mpreal a(x);
   2542     mpfr_nextabove(a.mp);
   2543     return a;
   2544 }
   2545 
   2546 inline const mpreal nextbelow  (const mpreal& x)
   2547 {
   2548     mpreal a(x);
   2549     mpfr_nextbelow(a.mp);
   2550     return a;
   2551 }
   2552 
   2553 inline const mpreal urandomb (gmp_randstate_t& state)
   2554 {
   2555     mpreal x;
   2556     mpfr_urandomb(x.mp,state);
   2557     return x;
   2558 }
   2559 
   2560 #if (MPFR_VERSION >= MPFR_VERSION_NUM(3,1,0))
   2561 // use gmp_randinit_default() to init state, gmp_randclear() to clear
   2562 inline const mpreal urandom (gmp_randstate_t& state, mp_rnd_t rnd_mode = mpreal::get_default_rnd())
   2563 {
   2564     mpreal x;
   2565     mpfr_urandom(x.mp,state,rnd_mode);
   2566     return x;
   2567 }
   2568 
   2569 inline const mpreal grandom (gmp_randstate_t& state, mp_rnd_t rnd_mode = mpreal::get_default_rnd())
   2570 {
   2571     mpreal x;
   2572     mpfr_grandom(x.mp, NULL, state, rnd_mode);
   2573     return x;
   2574 }
   2575 
   2576 #endif
   2577 
   2578 #if (MPFR_VERSION <= MPFR_VERSION_NUM(2,4,2))
   2579 inline const mpreal random2 (mp_size_t size, mp_exp_t exp)
   2580 {
   2581     mpreal x;
   2582     mpfr_random2(x.mp,size,exp);
   2583     return x;
   2584 }
   2585 #endif
   2586 
   2587 // Uniformly distributed random number generation
   2588 // a = random(seed); <- initialization & first random number generation
   2589 // a = random();     <- next random numbers generation
   2590 // seed != 0
   2591 inline const mpreal random(unsigned int seed = 0)
   2592 {
   2593 
   2594 #if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0))
   2595     static gmp_randstate_t state;
   2596     static bool isFirstTime = true;
   2597 
   2598     if(isFirstTime)
   2599     {
   2600         gmp_randinit_default(state);
   2601         gmp_randseed_ui(state,0);
   2602         isFirstTime = false;
   2603     }
   2604 
   2605     if(seed != 0)    gmp_randseed_ui(state,seed);
   2606 
   2607     return mpfr::urandom(state);
   2608 #else
   2609     if(seed != 0)    std::srand(seed);
   2610     return mpfr::mpreal(std::rand()/(double)RAND_MAX);
   2611 #endif
   2612 
   2613 }
   2614 
   2615 #if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0))
   2616 inline const mpreal grandom(unsigned int seed = 0)
   2617 {
   2618     static gmp_randstate_t state;
   2619     static bool isFirstTime = true;
   2620 
   2621     if(isFirstTime)
   2622     {
   2623         gmp_randinit_default(state);
   2624         gmp_randseed_ui(state,0);
   2625         isFirstTime = false;
   2626     }
   2627 
   2628     if(seed != 0) gmp_randseed_ui(state,seed);
   2629 
   2630     return mpfr::grandom(state);
   2631 }
   2632 #endif
   2633 
   2634 //////////////////////////////////////////////////////////////////////////
   2635 // Set/Get global properties
   2636 inline void mpreal::set_default_prec(mp_prec_t prec)
   2637 {
   2638     mpfr_set_default_prec(prec);
   2639 }
   2640 
   2641 inline void mpreal::set_default_rnd(mp_rnd_t rnd_mode)
   2642 {
   2643     mpfr_set_default_rounding_mode(rnd_mode);
   2644 }
   2645 
   2646 inline bool mpreal::fits_in_bits(double x, int n)
   2647 {
   2648     int i;
   2649     double t;
   2650     return IsInf(x) || (std::modf ( std::ldexp ( std::frexp ( x, &i ), n ), &t ) == 0.0);
   2651 }
   2652 
   2653 inline const mpreal pow(const mpreal& a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd())
   2654 {
   2655     mpreal x(a);
   2656     mpfr_pow(x.mp,x.mp,b.mp,rnd_mode);
   2657     return x;
   2658 }
   2659 
   2660 inline const mpreal pow(const mpreal& a, const mpz_t b, mp_rnd_t rnd_mode = mpreal::get_default_rnd())
   2661 {
   2662     mpreal x(a);
   2663     mpfr_pow_z(x.mp,x.mp,b,rnd_mode);
   2664     return x;
   2665 }
   2666 
   2667 inline const mpreal pow(const mpreal& a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd())
   2668 {
   2669     mpreal x(a);
   2670     mpfr_pow_ui(x.mp,x.mp,b,rnd_mode);
   2671     return x;
   2672 }
   2673 
   2674 inline const mpreal pow(const mpreal& a, const unsigned int b, mp_rnd_t rnd_mode)
   2675 {
   2676     return pow(a,static_cast<unsigned long int>(b),rnd_mode);
   2677 }
   2678 
   2679 inline const mpreal pow(const mpreal& a, const long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd())
   2680 {
   2681     mpreal x(a);
   2682     mpfr_pow_si(x.mp,x.mp,b,rnd_mode);
   2683     return x;
   2684 }
   2685 
   2686 inline const mpreal pow(const mpreal& a, const int b, mp_rnd_t rnd_mode)
   2687 {
   2688     return pow(a,static_cast<long int>(b),rnd_mode);
   2689 }
   2690 
   2691 inline const mpreal pow(const mpreal& a, const long double b, mp_rnd_t rnd_mode)
   2692 {
   2693     return pow(a,mpreal(b),rnd_mode);
   2694 }
   2695 
   2696 inline const mpreal pow(const mpreal& a, const double b, mp_rnd_t rnd_mode)
   2697 {
   2698     return pow(a,mpreal(b),rnd_mode);
   2699 }
   2700 
   2701 inline const mpreal pow(const unsigned long int a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd())
   2702 {
   2703     mpreal x(a);
   2704     mpfr_ui_pow(x.mp,a,b.mp,rnd_mode);
   2705     return x;
   2706 }
   2707 
   2708 inline const mpreal pow(const unsigned int a, const mpreal& b, mp_rnd_t rnd_mode)
   2709 {
   2710     return pow(static_cast<unsigned long int>(a),b,rnd_mode);
   2711 }
   2712 
   2713 inline const mpreal pow(const long int a, const mpreal& b, mp_rnd_t rnd_mode)
   2714 {
   2715     if (a>=0)     return pow(static_cast<unsigned long int>(a),b,rnd_mode);
   2716     else          return pow(mpreal(a),b,rnd_mode);
   2717 }
   2718 
   2719 inline const mpreal pow(const int a, const mpreal& b, mp_rnd_t rnd_mode)
   2720 {
   2721     if (a>=0)     return pow(static_cast<unsigned long int>(a),b,rnd_mode);
   2722     else          return pow(mpreal(a),b,rnd_mode);
   2723 }
   2724 
   2725 inline const mpreal pow(const long double a, const mpreal& b, mp_rnd_t rnd_mode)
   2726 {
   2727     return pow(mpreal(a),b,rnd_mode);
   2728 }
   2729 
   2730 inline const mpreal pow(const double a, const mpreal& b, mp_rnd_t rnd_mode)
   2731 {
   2732     return pow(mpreal(a),b,rnd_mode);
   2733 }
   2734 
   2735 // pow unsigned long int
   2736 inline const mpreal pow(const unsigned long int a, const unsigned long int b, mp_rnd_t rnd_mode)
   2737 {
   2738     mpreal x(a);
   2739     mpfr_ui_pow_ui(x.mp,a,b,rnd_mode);
   2740     return x;
   2741 }
   2742 
   2743 inline const mpreal pow(const unsigned long int a, const unsigned int b, mp_rnd_t rnd_mode)
   2744 {
   2745     return pow(a,static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
   2746 }
   2747 
   2748 inline const mpreal pow(const unsigned long int a, const long int b, mp_rnd_t rnd_mode)
   2749 {
   2750     if(b>0)    return pow(a,static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
   2751     else       return pow(a,mpreal(b),rnd_mode); //mpfr_ui_pow
   2752 }
   2753 
   2754 inline const mpreal pow(const unsigned long int a, const int b, mp_rnd_t rnd_mode)
   2755 {
   2756     if(b>0)    return pow(a,static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
   2757     else       return pow(a,mpreal(b),rnd_mode); //mpfr_ui_pow
   2758 }
   2759 
   2760 inline const mpreal pow(const unsigned long int a, const long double b, mp_rnd_t rnd_mode)
   2761 {
   2762     return pow(a,mpreal(b),rnd_mode); //mpfr_ui_pow
   2763 }
   2764 
   2765 inline const mpreal pow(const unsigned long int a, const double b, mp_rnd_t rnd_mode)
   2766 {
   2767     return pow(a,mpreal(b),rnd_mode); //mpfr_ui_pow
   2768 }
   2769 
   2770 // pow unsigned int
   2771 inline const mpreal pow(const unsigned int a, const unsigned long int b, mp_rnd_t rnd_mode)
   2772 {
   2773     return pow(static_cast<unsigned long int>(a),b,rnd_mode); //mpfr_ui_pow_ui
   2774 }
   2775 
   2776 inline const mpreal pow(const unsigned int a, const unsigned int b, mp_rnd_t rnd_mode)
   2777 {
   2778     return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
   2779 }
   2780 
   2781 inline const mpreal pow(const unsigned int a, const long int b, mp_rnd_t rnd_mode)
   2782 {
   2783     if(b>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
   2784     else    return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
   2785 }
   2786 
   2787 inline const mpreal pow(const unsigned int a, const int b, mp_rnd_t rnd_mode)
   2788 {
   2789     if(b>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
   2790     else    return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
   2791 }
   2792 
   2793 inline const mpreal pow(const unsigned int a, const long double b, mp_rnd_t rnd_mode)
   2794 {
   2795     return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
   2796 }
   2797 
   2798 inline const mpreal pow(const unsigned int a, const double b, mp_rnd_t rnd_mode)
   2799 {
   2800     return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
   2801 }
   2802 
   2803 // pow long int
   2804 inline const mpreal pow(const long int a, const unsigned long int b, mp_rnd_t rnd_mode)
   2805 {
   2806     if (a>0) return pow(static_cast<unsigned long int>(a),b,rnd_mode); //mpfr_ui_pow_ui
   2807     else     return pow(mpreal(a),b,rnd_mode); //mpfr_pow_ui
   2808 }
   2809 
   2810 inline const mpreal pow(const long int a, const unsigned int b, mp_rnd_t rnd_mode)
   2811 {
   2812     if (a>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode);  //mpfr_ui_pow_ui
   2813     else     return pow(mpreal(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_pow_ui
   2814 }
   2815 
   2816 inline const mpreal pow(const long int a, const long int b, mp_rnd_t rnd_mode)
   2817 {
   2818     if (a>0)
   2819     {
   2820         if(b>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
   2821         else    return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
   2822     }else{
   2823         return pow(mpreal(a),b,rnd_mode); // mpfr_pow_si
   2824     }
   2825 }
   2826 
   2827 inline const mpreal pow(const long int a, const int b, mp_rnd_t rnd_mode)
   2828 {
   2829     if (a>0)
   2830     {
   2831         if(b>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
   2832         else    return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
   2833     }else{
   2834         return pow(mpreal(a),static_cast<long int>(b),rnd_mode); // mpfr_pow_si
   2835     }
   2836 }
   2837 
   2838 inline const mpreal pow(const long int a, const long double b, mp_rnd_t rnd_mode)
   2839 {
   2840     if (a>=0)   return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
   2841     else        return pow(mpreal(a),mpreal(b),rnd_mode); //mpfr_pow
   2842 }
   2843 
   2844 inline const mpreal pow(const long int a, const double b, mp_rnd_t rnd_mode)
   2845 {
   2846     if (a>=0)   return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
   2847     else        return pow(mpreal(a),mpreal(b),rnd_mode); //mpfr_pow
   2848 }
   2849 
   2850 // pow int
   2851 inline const mpreal pow(const int a, const unsigned long int b, mp_rnd_t rnd_mode)
   2852 {
   2853     if (a>0) return pow(static_cast<unsigned long int>(a),b,rnd_mode); //mpfr_ui_pow_ui
   2854     else     return pow(mpreal(a),b,rnd_mode); //mpfr_pow_ui
   2855 }
   2856 
   2857 inline const mpreal pow(const int a, const unsigned int b, mp_rnd_t rnd_mode)
   2858 {
   2859     if (a>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode);  //mpfr_ui_pow_ui
   2860     else     return pow(mpreal(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_pow_ui
   2861 }
   2862 
   2863 inline const mpreal pow(const int a, const long int b, mp_rnd_t rnd_mode)
   2864 {
   2865     if (a>0)
   2866     {
   2867         if(b>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
   2868         else    return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
   2869     }else{
   2870         return pow(mpreal(a),b,rnd_mode); // mpfr_pow_si
   2871     }
   2872 }
   2873 
   2874 inline const mpreal pow(const int a, const int b, mp_rnd_t rnd_mode)
   2875 {
   2876     if (a>0)
   2877     {
   2878         if(b>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui
   2879         else    return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
   2880     }else{
   2881         return pow(mpreal(a),static_cast<long int>(b),rnd_mode); // mpfr_pow_si
   2882     }
   2883 }
   2884 
   2885 inline const mpreal pow(const int a, const long double b, mp_rnd_t rnd_mode)
   2886 {
   2887     if (a>=0)   return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
   2888     else        return pow(mpreal(a),mpreal(b),rnd_mode); //mpfr_pow
   2889 }
   2890 
   2891 inline const mpreal pow(const int a, const double b, mp_rnd_t rnd_mode)
   2892 {
   2893     if (a>=0)   return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow
   2894     else        return pow(mpreal(a),mpreal(b),rnd_mode); //mpfr_pow
   2895 }
   2896 
   2897 // pow long double
   2898 inline const mpreal pow(const long double a, const long double b, mp_rnd_t rnd_mode)
   2899 {
   2900     return pow(mpreal(a),mpreal(b),rnd_mode);
   2901 }
   2902 
   2903 inline const mpreal pow(const long double a, const unsigned long int b, mp_rnd_t rnd_mode)
   2904 {
   2905     return pow(mpreal(a),b,rnd_mode); //mpfr_pow_ui
   2906 }
   2907 
   2908 inline const mpreal pow(const long double a, const unsigned int b, mp_rnd_t rnd_mode)
   2909 {
   2910     return pow(mpreal(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_pow_ui
   2911 }
   2912 
   2913 inline const mpreal pow(const long double a, const long int b, mp_rnd_t rnd_mode)
   2914 {
   2915     return pow(mpreal(a),b,rnd_mode); // mpfr_pow_si
   2916 }
   2917 
   2918 inline const mpreal pow(const long double a, const int b, mp_rnd_t rnd_mode)
   2919 {
   2920     return pow(mpreal(a),static_cast<long int>(b),rnd_mode); // mpfr_pow_si
   2921 }
   2922 
   2923 inline const mpreal pow(const double a, const double b, mp_rnd_t rnd_mode)
   2924 {
   2925     return pow(mpreal(a),mpreal(b),rnd_mode);
   2926 }
   2927 
   2928 inline const mpreal pow(const double a, const unsigned long int b, mp_rnd_t rnd_mode)
   2929 {
   2930     return pow(mpreal(a),b,rnd_mode); // mpfr_pow_ui
   2931 }
   2932 
   2933 inline const mpreal pow(const double a, const unsigned int b, mp_rnd_t rnd_mode)
   2934 {
   2935     return pow(mpreal(a),static_cast<unsigned long int>(b),rnd_mode); // mpfr_pow_ui
   2936 }
   2937 
   2938 inline const mpreal pow(const double a, const long int b, mp_rnd_t rnd_mode)
   2939 {
   2940     return pow(mpreal(a),b,rnd_mode); // mpfr_pow_si
   2941 }
   2942 
   2943 inline const mpreal pow(const double a, const int b, mp_rnd_t rnd_mode)
   2944 {
   2945     return pow(mpreal(a),static_cast<long int>(b),rnd_mode); // mpfr_pow_si
   2946 }
   2947 } // End of mpfr namespace
   2948 
   2949 // Explicit specialization of std::swap for mpreal numbers
   2950 // Thus standard algorithms will use efficient version of swap (due to Koenig lookup)
   2951 // Non-throwing swap C++ idiom: http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Non-throwing_swap
   2952 namespace std
   2953 {
   2954   // we are allowed to extend namespace std with specializations only
   2955     template <>
   2956     inline void swap(mpfr::mpreal& x, mpfr::mpreal& y)
   2957     {
   2958         return mpfr::swap(x, y);
   2959     }
   2960 
   2961     template<>
   2962     class numeric_limits<mpfr::mpreal>
   2963     {
   2964     public:
   2965         static const bool is_specialized    = true;
   2966         static const bool is_signed         = true;
   2967         static const bool is_integer        = false;
   2968         static const bool is_exact          = false;
   2969         static const int  radix             = 2;
   2970 
   2971         static const bool has_infinity      = true;
   2972         static const bool has_quiet_NaN     = true;
   2973         static const bool has_signaling_NaN = true;
   2974 
   2975         static const bool is_iec559         = true;        // = IEEE 754
   2976         static const bool is_bounded        = true;
   2977         static const bool is_modulo         = false;
   2978         static const bool traps             = true;
   2979         static const bool tinyness_before   = true;
   2980 
   2981         static const float_denorm_style has_denorm  = denorm_absent;
   2982 
   2983         inline static mpfr::mpreal (min)    (mp_prec_t precision = mpfr::mpreal::get_default_prec()) {  return  mpfr::minval(precision);  }
   2984         inline static mpfr::mpreal (max)    (mp_prec_t precision = mpfr::mpreal::get_default_prec()) {  return  mpfr::maxval(precision);  }
   2985         inline static mpfr::mpreal lowest   (mp_prec_t precision = mpfr::mpreal::get_default_prec()) {  return -mpfr::maxval(precision);  }
   2986 
   2987         // Returns smallest eps such that 1 + eps != 1 (classic machine epsilon)
   2988         inline static mpfr::mpreal epsilon(mp_prec_t precision = mpfr::mpreal::get_default_prec()) {  return  mpfr::machine_epsilon(precision); }
   2989 
   2990         // Returns smallest eps such that x + eps != x (relative machine epsilon)
   2991         inline static mpfr::mpreal epsilon(const mpfr::mpreal& x) {  return mpfr::machine_epsilon(x);  }
   2992 
   2993         inline static mpfr::mpreal round_error(mp_prec_t precision = mpfr::mpreal::get_default_prec())
   2994         {
   2995             mp_rnd_t r = mpfr::mpreal::get_default_rnd();
   2996 
   2997             if(r == GMP_RNDN)  return mpfr::mpreal(0.5, precision);
   2998             else               return mpfr::mpreal(1.0, precision);
   2999         }
   3000 
   3001         inline static const mpfr::mpreal infinity()         { return mpfr::const_infinity();     }
   3002         inline static const mpfr::mpreal quiet_NaN()        { return mpfr::mpreal().setNan();    }
   3003         inline static const mpfr::mpreal signaling_NaN()    { return mpfr::mpreal().setNan();    }
   3004         inline static const mpfr::mpreal denorm_min()       { return (min)();                    }
   3005 
   3006         // Please note, exponent range is not fixed in MPFR
   3007         static const int min_exponent = MPFR_EMIN_DEFAULT;
   3008         static const int max_exponent = MPFR_EMAX_DEFAULT;
   3009         MPREAL_PERMISSIVE_EXPR static const int min_exponent10 = (int) (MPFR_EMIN_DEFAULT * 0.3010299956639811);
   3010         MPREAL_PERMISSIVE_EXPR static const int max_exponent10 = (int) (MPFR_EMAX_DEFAULT * 0.3010299956639811);
   3011 
   3012 #ifdef MPREAL_HAVE_DYNAMIC_STD_NUMERIC_LIMITS
   3013 
   3014         // Following members should be constant according to standard, but they can be variable in MPFR
   3015         // So we define them as functions here.
   3016         //
   3017         // This is preferable way for std::numeric_limits<mpfr::mpreal> specialization.
   3018         // But it is incompatible with standard std::numeric_limits and might not work with other libraries, e.g. boost.
   3019         // See below for compatible implementation.
   3020         inline static float_round_style round_style()
   3021         {
   3022             mp_rnd_t r = mpfr::mpreal::get_default_rnd();
   3023 
   3024             switch (r)
   3025             {
   3026             case GMP_RNDN: return round_to_nearest;
   3027             case GMP_RNDZ: return round_toward_zero;
   3028             case GMP_RNDU: return round_toward_infinity;
   3029             case GMP_RNDD: return round_toward_neg_infinity;
   3030             default: return round_indeterminate;
   3031             }
   3032         }
   3033 
   3034         inline static int digits()                        {    return int(mpfr::mpreal::get_default_prec());    }
   3035         inline static int digits(const mpfr::mpreal& x)   {    return x.getPrecision();                         }
   3036 
   3037         inline static int digits10(mp_prec_t precision = mpfr::mpreal::get_default_prec())
   3038         {
   3039             return mpfr::bits2digits(precision);
   3040         }
   3041 
   3042         inline static int digits10(const mpfr::mpreal& x)
   3043         {
   3044             return mpfr::bits2digits(x.getPrecision());
   3045         }
   3046 
   3047         inline static int max_digits10(mp_prec_t precision = mpfr::mpreal::get_default_prec())
   3048         {
   3049             return digits10(precision);
   3050         }
   3051 #else
   3052         // Digits and round_style are NOT constants when it comes to mpreal.
   3053         // If possible, please use functions digits() and round_style() defined above.
   3054         //
   3055         // These (default) values are preserved for compatibility with existing libraries, e.g. boost.
   3056         // Change them accordingly to your application.
   3057         //
   3058         // For example, if you use 256 bits of precision uniformly in your program, then:
   3059         // digits       = 256
   3060         // digits10     = 77
   3061         // max_digits10 = 78
   3062         //
   3063         // Approximate formula for decimal digits is: digits10 = floor(log10(2) * digits). See bits2digits() for more details.
   3064 
   3065         static const std::float_round_style round_style = round_to_nearest;
   3066         static const int digits       = 53;
   3067         static const int digits10     = 15;
   3068         static const int max_digits10 = 16;
   3069 #endif
   3070     };
   3071 
   3072 }
   3073 
   3074 #endif /* __MPREAL_H__ */
   3075