android-gmp

git clone git://git.codymlewis.com/android-gmp.git
Log | Files | Refs

gmpxx.h (129113B)


      1 /* gmpxx.h -- C++ class wrapper for GMP types.  -*- C++ -*-
      2 
      3 Copyright 2001-2003, 2006, 2008, 2011-2015, 2018 Free Software
      4 Foundation, Inc.
      5 
      6 This file is part of the GNU MP Library.
      7 
      8 The GNU MP Library is free software; you can redistribute it and/or modify
      9 it under the terms of either:
     10 
     11   * the GNU Lesser General Public License as published by the Free
     12     Software Foundation; either version 3 of the License, or (at your
     13     option) any later version.
     14 
     15 or
     16 
     17   * the GNU General Public License as published by the Free Software
     18     Foundation; either version 2 of the License, or (at your option) any
     19     later version.
     20 
     21 or both in parallel, as here.
     22 
     23 The GNU MP Library is distributed in the hope that it will be useful, but
     24 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     25 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     26 for more details.
     27 
     28 You should have received copies of the GNU General Public License and the
     29 GNU Lesser General Public License along with the GNU MP Library.  If not,
     30 see https://www.gnu.org/licenses/.  */
     31 
     32 #ifndef __GMP_PLUSPLUS__
     33 #define __GMP_PLUSPLUS__
     34 
     35 #include <iosfwd>
     36 
     37 #include <cstring>  /* for strlen */
     38 #include <limits>  /* numeric_limits */
     39 #include <utility>
     40 #include <algorithm>  /* swap */
     41 #include <string>
     42 #include <stdexcept>
     43 #include <cfloat>
     44 #include <gmp.h>
     45 
     46 // wrapper for gcc's __builtin_constant_p
     47 // __builtin_constant_p has been in gcc since forever,
     48 // but g++-3.4 miscompiles it.
     49 #if __GMP_GNUC_PREREQ(4, 2)
     50 #define __GMPXX_CONSTANT(X) __builtin_constant_p(X)
     51 #else
     52 #define __GMPXX_CONSTANT(X) false
     53 #endif
     54 #define __GMPXX_CONSTANT_TRUE(X) (__GMPXX_CONSTANT(X) && (X))
     55 
     56 // Use C++11 features
     57 #ifndef __GMPXX_USE_CXX11
     58 #if __cplusplus >= 201103L
     59 #define __GMPXX_USE_CXX11 1
     60 #else
     61 #define __GMPXX_USE_CXX11 0
     62 #endif
     63 #endif
     64 
     65 #if __GMPXX_USE_CXX11
     66 #define __GMPXX_NOEXCEPT noexcept
     67 #include <type_traits> // for common_type
     68 #else
     69 #define __GMPXX_NOEXCEPT
     70 #endif
     71 
     72 // Max allocations for plain types when converted to GMP types
     73 #if GMP_NAIL_BITS != 0 && ! defined _LONG_LONG_LIMB
     74 #define __GMPZ_ULI_LIMBS 2
     75 #else
     76 #define __GMPZ_ULI_LIMBS 1
     77 #endif
     78 
     79 #define __GMPXX_BITS_TO_LIMBS(n)  (((n) + (GMP_NUMB_BITS - 1)) / GMP_NUMB_BITS)
     80 #define __GMPZ_DBL_LIMBS __GMPXX_BITS_TO_LIMBS(DBL_MAX_EXP)+1
     81 #define __GMPQ_NUM_DBL_LIMBS __GMPZ_DBL_LIMBS
     82 #define __GMPQ_DEN_DBL_LIMBS __GMPXX_BITS_TO_LIMBS(DBL_MANT_DIG+1-DBL_MIN_EXP)+1
     83 // The final +1s are a security margin. The current implementation of
     84 // mpq_set_d seems to need it for the denominator.
     85 
     86 inline void __mpz_set_ui_safe(mpz_ptr p, unsigned long l)
     87 {
     88   p->_mp_size = (l != 0);
     89   p->_mp_d[0] = l & GMP_NUMB_MASK;
     90 #if __GMPZ_ULI_LIMBS > 1
     91   l >>= GMP_NUMB_BITS;
     92   p->_mp_d[1] = l;
     93   p->_mp_size += (l != 0);
     94 #endif
     95 }
     96 
     97 inline void __mpz_set_si_safe(mpz_ptr p, long l)
     98 {
     99   if(l < 0)
    100   {
    101     __mpz_set_ui_safe(p, -static_cast<unsigned long>(l));
    102     mpz_neg(p, p);
    103   }
    104   else
    105     __mpz_set_ui_safe(p, l);
    106     // Note: we know the high bit of l is 0 so we could do slightly better
    107 }
    108 
    109 // Fake temporary variables
    110 #define __GMPXX_TMPZ_UI							\
    111   mpz_t temp;								\
    112   mp_limb_t limbs[__GMPZ_ULI_LIMBS];					\
    113   temp->_mp_d = limbs;							\
    114   __mpz_set_ui_safe (temp, l)
    115 #define __GMPXX_TMPZ_SI							\
    116   mpz_t temp;								\
    117   mp_limb_t limbs[__GMPZ_ULI_LIMBS];					\
    118   temp->_mp_d = limbs;							\
    119   __mpz_set_si_safe (temp, l)
    120 #define __GMPXX_TMPZ_D							\
    121   mpz_t temp;								\
    122   mp_limb_t limbs[__GMPZ_DBL_LIMBS];					\
    123   temp->_mp_d = limbs;							\
    124   temp->_mp_alloc = __GMPZ_DBL_LIMBS;					\
    125   mpz_set_d (temp, d)
    126 
    127 #define __GMPXX_TMPQ_UI							\
    128   mpq_t temp;								\
    129   mp_limb_t limbs[__GMPZ_ULI_LIMBS+1];					\
    130   mpq_numref(temp)->_mp_d = limbs;					\
    131   __mpz_set_ui_safe (mpq_numref(temp), l);				\
    132   mpq_denref(temp)->_mp_d = limbs + __GMPZ_ULI_LIMBS;			\
    133   mpq_denref(temp)->_mp_size = 1;					\
    134   mpq_denref(temp)->_mp_d[0] = 1
    135 #define __GMPXX_TMPQ_SI							\
    136   mpq_t temp;								\
    137   mp_limb_t limbs[__GMPZ_ULI_LIMBS+1];					\
    138   mpq_numref(temp)->_mp_d = limbs;					\
    139   __mpz_set_si_safe (mpq_numref(temp), l);				\
    140   mpq_denref(temp)->_mp_d = limbs + __GMPZ_ULI_LIMBS;			\
    141   mpq_denref(temp)->_mp_size = 1;					\
    142   mpq_denref(temp)->_mp_d[0] = 1
    143 #define __GMPXX_TMPQ_D							\
    144   mpq_t temp;								\
    145   mp_limb_t limbs[__GMPQ_NUM_DBL_LIMBS + __GMPQ_DEN_DBL_LIMBS];		\
    146   mpq_numref(temp)->_mp_d = limbs;					\
    147   mpq_numref(temp)->_mp_alloc = __GMPQ_NUM_DBL_LIMBS;			\
    148   mpq_denref(temp)->_mp_d = limbs + __GMPQ_NUM_DBL_LIMBS;		\
    149   mpq_denref(temp)->_mp_alloc = __GMPQ_DEN_DBL_LIMBS;			\
    150   mpq_set_d (temp, d)
    151 
    152 inline unsigned long __gmpxx_abs_ui (signed long l)
    153 {
    154   return l >= 0 ? static_cast<unsigned long>(l)
    155 	  : -static_cast<unsigned long>(l);
    156 }
    157 
    158 /**************** Function objects ****************/
    159 /* Any evaluation of a __gmp_expr ends up calling one of these functions
    160    all intermediate functions being inline, the evaluation should optimize
    161    to a direct call to the relevant function, thus yielding no overhead
    162    over the C interface. */
    163 
    164 struct __gmp_unary_plus
    165 {
    166   static void eval(mpz_ptr z, mpz_srcptr w) { mpz_set(z, w); }
    167   static void eval(mpq_ptr q, mpq_srcptr r) { mpq_set(q, r); }
    168   static void eval(mpf_ptr f, mpf_srcptr g) { mpf_set(f, g); }
    169 };
    170 
    171 struct __gmp_unary_minus
    172 {
    173   static void eval(mpz_ptr z, mpz_srcptr w) { mpz_neg(z, w); }
    174   static void eval(mpq_ptr q, mpq_srcptr r) { mpq_neg(q, r); }
    175   static void eval(mpf_ptr f, mpf_srcptr g) { mpf_neg(f, g); }
    176 };
    177 
    178 struct __gmp_unary_com
    179 {
    180   static void eval(mpz_ptr z, mpz_srcptr w) { mpz_com(z, w); }
    181 };
    182 
    183 struct __gmp_binary_plus
    184 {
    185   static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
    186   { mpz_add(z, w, v); }
    187 
    188   static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
    189   {
    190     // Ideally, those checks should happen earlier so that the tree
    191     // generated for a+0+b would just be sum(a,b).
    192     if (__GMPXX_CONSTANT(l) && l == 0)
    193     {
    194       if (z != w) mpz_set(z, w);
    195     }
    196     else
    197       mpz_add_ui(z, w, l);
    198   }
    199   static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
    200   { eval(z, w, l); }
    201   static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
    202   {
    203     if (l >= 0)
    204       eval(z, w, static_cast<unsigned long>(l));
    205     else
    206       mpz_sub_ui(z, w, -static_cast<unsigned long>(l));
    207   }
    208   static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
    209   { eval(z, w, l); }
    210   static void eval(mpz_ptr z, mpz_srcptr w, double d)
    211   {  __GMPXX_TMPZ_D;    mpz_add (z, w, temp); }
    212   static void eval(mpz_ptr z, double d, mpz_srcptr w)
    213   { eval(z, w, d); }
    214 
    215   static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s)
    216   { mpq_add(q, r, s); }
    217 
    218   static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l)
    219   {
    220     if (__GMPXX_CONSTANT(l) && l == 0)
    221     {
    222       if (q != r) mpq_set(q, r);
    223     }
    224     else if (__GMPXX_CONSTANT(l) && l == 1)
    225     {
    226       mpz_add (mpq_numref(q), mpq_numref(r), mpq_denref(r));
    227       if (q != r) mpz_set(mpq_denref(q), mpq_denref(r));
    228     }
    229     else
    230     {
    231       if (q == r)
    232         mpz_addmul_ui(mpq_numref(q), mpq_denref(q), l);
    233       else
    234       {
    235         mpz_mul_ui(mpq_numref(q), mpq_denref(r), l);
    236         mpz_add(mpq_numref(q), mpq_numref(q), mpq_numref(r));
    237         mpz_set(mpq_denref(q), mpq_denref(r));
    238       }
    239     }
    240   }
    241   static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r)
    242   { eval(q, r, l); }
    243   static inline void eval(mpq_ptr q, mpq_srcptr r, signed long int l);
    244   // defined after __gmp_binary_minus
    245   static void eval(mpq_ptr q, signed long int l, mpq_srcptr r)
    246   { eval(q, r, l); }
    247   static void eval(mpq_ptr q, mpq_srcptr r, double d)
    248   {  __GMPXX_TMPQ_D;    mpq_add (q, r, temp); }
    249   static void eval(mpq_ptr q, double d, mpq_srcptr r)
    250   { eval(q, r, d); }
    251 
    252   static void eval(mpq_ptr q, mpq_srcptr r, mpz_srcptr z)
    253   {
    254     if (q == r)
    255       mpz_addmul(mpq_numref(q), mpq_denref(q), z);
    256     else
    257     {
    258       mpz_mul(mpq_numref(q), mpq_denref(r), z);
    259       mpz_add(mpq_numref(q), mpq_numref(q), mpq_numref(r));
    260       mpz_set(mpq_denref(q), mpq_denref(r));
    261     }
    262   }
    263   static void eval(mpq_ptr q, mpz_srcptr z, mpq_srcptr r)
    264   { eval(q, r, z); }
    265 
    266   static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)
    267   { mpf_add(f, g, h); }
    268 
    269   static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l)
    270   { mpf_add_ui(f, g, l); }
    271   static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g)
    272   { mpf_add_ui(f, g, l); }
    273   static void eval(mpf_ptr f, mpf_srcptr g, signed long int l)
    274   {
    275     if (l >= 0)
    276       mpf_add_ui(f, g, l);
    277     else
    278       mpf_sub_ui(f, g, -static_cast<unsigned long>(l));
    279   }
    280   static void eval(mpf_ptr f, signed long int l, mpf_srcptr g)
    281   { eval(f, g, l); }
    282   static void eval(mpf_ptr f, mpf_srcptr g, double d)
    283   {
    284     mpf_t temp;
    285     mpf_init2(temp, 8*sizeof(double));
    286     mpf_set_d(temp, d);
    287     mpf_add(f, g, temp);
    288     mpf_clear(temp);
    289   }
    290   static void eval(mpf_ptr f, double d, mpf_srcptr g)
    291   { eval(f, g, d); }
    292 };
    293 
    294 struct __gmp_binary_minus
    295 {
    296   static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
    297   { mpz_sub(z, w, v); }
    298 
    299   static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
    300   {
    301     if (__GMPXX_CONSTANT(l) && l == 0)
    302     {
    303       if (z != w) mpz_set(z, w);
    304     }
    305     else
    306       mpz_sub_ui(z, w, l);
    307   }
    308   static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
    309   {
    310     if (__GMPXX_CONSTANT(l) && l == 0)
    311     {
    312       mpz_neg(z, w);
    313     }
    314     else
    315       mpz_ui_sub(z, l, w);
    316   }
    317   static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
    318   {
    319     if (l >= 0)
    320       eval(z, w, static_cast<unsigned long>(l));
    321     else
    322       mpz_add_ui(z, w, -static_cast<unsigned long>(l));
    323   }
    324   static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
    325   {
    326     if (l >= 0)
    327       eval(z, static_cast<unsigned long>(l), w);
    328     else
    329       {
    330         mpz_add_ui(z, w, -static_cast<unsigned long>(l));
    331         mpz_neg(z, z);
    332       }
    333   }
    334   static void eval(mpz_ptr z, mpz_srcptr w, double d)
    335   {  __GMPXX_TMPZ_D;    mpz_sub (z, w, temp); }
    336   static void eval(mpz_ptr z, double d, mpz_srcptr w)
    337   {  __GMPXX_TMPZ_D;    mpz_sub (z, temp, w); }
    338 
    339   static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s)
    340   { mpq_sub(q, r, s); }
    341 
    342   static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l)
    343   {
    344     if (__GMPXX_CONSTANT(l) && l == 0)
    345     {
    346       if (q != r) mpq_set(q, r);
    347     }
    348     else if (__GMPXX_CONSTANT(l) && l == 1)
    349     {
    350       mpz_sub (mpq_numref(q), mpq_numref(r), mpq_denref(r));
    351       if (q != r) mpz_set(mpq_denref(q), mpq_denref(r));
    352     }
    353     else
    354     {
    355       if (q == r)
    356         mpz_submul_ui(mpq_numref(q), mpq_denref(q), l);
    357       else
    358       {
    359         mpz_mul_ui(mpq_numref(q), mpq_denref(r), l);
    360         mpz_sub(mpq_numref(q), mpq_numref(r), mpq_numref(q));
    361         mpz_set(mpq_denref(q), mpq_denref(r));
    362       }
    363     }
    364   }
    365   static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r)
    366   { eval(q, r, l); mpq_neg(q, q); }
    367   static void eval(mpq_ptr q, mpq_srcptr r, signed long int l)
    368   {
    369     if (l >= 0)
    370       eval(q, r, static_cast<unsigned long>(l));
    371     else
    372       __gmp_binary_plus::eval(q, r, -static_cast<unsigned long>(l));
    373   }
    374   static void eval(mpq_ptr q, signed long int l, mpq_srcptr r)
    375   { eval(q, r, l); mpq_neg(q, q); }
    376   static void eval(mpq_ptr q, mpq_srcptr r, double d)
    377   {  __GMPXX_TMPQ_D;    mpq_sub (q, r, temp); }
    378   static void eval(mpq_ptr q, double d, mpq_srcptr r)
    379   {  __GMPXX_TMPQ_D;    mpq_sub (q, temp, r); }
    380 
    381   static void eval(mpq_ptr q, mpq_srcptr r, mpz_srcptr z)
    382   {
    383     if (q == r)
    384       mpz_submul(mpq_numref(q), mpq_denref(q), z);
    385     else
    386     {
    387       mpz_mul(mpq_numref(q), mpq_denref(r), z);
    388       mpz_sub(mpq_numref(q), mpq_numref(r), mpq_numref(q));
    389       mpz_set(mpq_denref(q), mpq_denref(r));
    390     }
    391   }
    392   static void eval(mpq_ptr q, mpz_srcptr z, mpq_srcptr r)
    393   { eval(q, r, z); mpq_neg(q, q); }
    394 
    395   static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)
    396   { mpf_sub(f, g, h); }
    397 
    398   static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l)
    399   { mpf_sub_ui(f, g, l); }
    400   static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g)
    401   { mpf_ui_sub(f, l, g); }
    402   static void eval(mpf_ptr f, mpf_srcptr g, signed long int l)
    403   {
    404     if (l >= 0)
    405       mpf_sub_ui(f, g, l);
    406     else
    407       mpf_add_ui(f, g, -static_cast<unsigned long>(l));
    408   }
    409   static void eval(mpf_ptr f, signed long int l, mpf_srcptr g)
    410   {
    411     if (l >= 0)
    412       mpf_sub_ui(f, g, l);
    413     else
    414       mpf_add_ui(f, g, -static_cast<unsigned long>(l));
    415     mpf_neg(f, f);
    416   }
    417   static void eval(mpf_ptr f, mpf_srcptr g, double d)
    418   {
    419     mpf_t temp;
    420     mpf_init2(temp, 8*sizeof(double));
    421     mpf_set_d(temp, d);
    422     mpf_sub(f, g, temp);
    423     mpf_clear(temp);
    424   }
    425   static void eval(mpf_ptr f, double d, mpf_srcptr g)
    426   {
    427     mpf_t temp;
    428     mpf_init2(temp, 8*sizeof(double));
    429     mpf_set_d(temp, d);
    430     mpf_sub(f, temp, g);
    431     mpf_clear(temp);
    432   }
    433 };
    434 
    435 // defined here so it can reference __gmp_binary_minus
    436 inline void
    437 __gmp_binary_plus::eval(mpq_ptr q, mpq_srcptr r, signed long int l)
    438 {
    439   if (l >= 0)
    440     eval(q, r, static_cast<unsigned long>(l));
    441   else
    442     __gmp_binary_minus::eval(q, r, -static_cast<unsigned long>(l));
    443 }
    444 
    445 struct __gmp_binary_lshift
    446 {
    447   static void eval(mpz_ptr z, mpz_srcptr w, mp_bitcnt_t l)
    448   {
    449     if (__GMPXX_CONSTANT(l) && (l == 0))
    450     {
    451       if (z != w) mpz_set(z, w);
    452     }
    453     else
    454       mpz_mul_2exp(z, w, l);
    455   }
    456   static void eval(mpq_ptr q, mpq_srcptr r, mp_bitcnt_t l)
    457   {
    458     if (__GMPXX_CONSTANT(l) && (l == 0))
    459     {
    460       if (q != r) mpq_set(q, r);
    461     }
    462     else
    463       mpq_mul_2exp(q, r, l);
    464   }
    465   static void eval(mpf_ptr f, mpf_srcptr g, mp_bitcnt_t l)
    466   { mpf_mul_2exp(f, g, l); }
    467 };
    468 
    469 struct __gmp_binary_rshift
    470 {
    471   static void eval(mpz_ptr z, mpz_srcptr w, mp_bitcnt_t l)
    472   {
    473     if (__GMPXX_CONSTANT(l) && (l == 0))
    474     {
    475       if (z != w) mpz_set(z, w);
    476     }
    477     else
    478       mpz_fdiv_q_2exp(z, w, l);
    479   }
    480   static void eval(mpq_ptr q, mpq_srcptr r, mp_bitcnt_t l)
    481   {
    482     if (__GMPXX_CONSTANT(l) && (l == 0))
    483     {
    484       if (q != r) mpq_set(q, r);
    485     }
    486     else
    487       mpq_div_2exp(q, r, l);
    488   }
    489   static void eval(mpf_ptr f, mpf_srcptr g, mp_bitcnt_t l)
    490   { mpf_div_2exp(f, g, l); }
    491 };
    492 
    493 struct __gmp_binary_multiplies
    494 {
    495   static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
    496   { mpz_mul(z, w, v); }
    497 
    498   static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
    499   {
    500 // gcc-3.3 doesn't have __builtin_ctzl. Don't bother optimizing for old gcc.
    501 #if __GMP_GNUC_PREREQ(3, 4)
    502     if (__GMPXX_CONSTANT(l) && (l & (l-1)) == 0)
    503     {
    504       if (l == 0)
    505       {
    506         z->_mp_size = 0;
    507       }
    508       else
    509       {
    510         __gmp_binary_lshift::eval(z, w, __builtin_ctzl(l));
    511       }
    512     }
    513     else
    514 #endif
    515       mpz_mul_ui(z, w, l);
    516   }
    517   static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
    518   { eval(z, w, l); }
    519   static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
    520   {
    521     if (__GMPXX_CONSTANT_TRUE(l >= 0))
    522       eval(z, w, static_cast<unsigned long>(l));
    523     else if (__GMPXX_CONSTANT_TRUE(l <= 0))
    524       {
    525         eval(z, w, -static_cast<unsigned long>(l));
    526 	mpz_neg(z, z);
    527       }
    528     else
    529       mpz_mul_si (z, w, l);
    530   }
    531   static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
    532   { eval(z, w, l); }
    533   static void eval(mpz_ptr z, mpz_srcptr w, double d)
    534   {  __GMPXX_TMPZ_D;    mpz_mul (z, w, temp); }
    535   static void eval(mpz_ptr z, double d, mpz_srcptr w)
    536   { eval(z, w, d); }
    537 
    538   static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s)
    539   { mpq_mul(q, r, s); }
    540 
    541   static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l)
    542   {
    543 #if __GMP_GNUC_PREREQ(3, 4)
    544     if (__GMPXX_CONSTANT(l) && (l & (l-1)) == 0)
    545     {
    546       if (l == 0)
    547       {
    548 	mpq_set_ui(q, 0, 1);
    549       }
    550       else
    551       {
    552         __gmp_binary_lshift::eval(q, r, __builtin_ctzl(l));
    553       }
    554     }
    555     else
    556 #endif
    557     {
    558       __GMPXX_TMPQ_UI;
    559       mpq_mul (q, r, temp);
    560     }
    561   }
    562   static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r)
    563   { eval(q, r, l); }
    564   static void eval(mpq_ptr q, mpq_srcptr r, signed long int l)
    565   {
    566     if (__GMPXX_CONSTANT_TRUE(l >= 0))
    567       eval(q, r, static_cast<unsigned long>(l));
    568     else if (__GMPXX_CONSTANT_TRUE(l <= 0))
    569       {
    570         eval(q, r, -static_cast<unsigned long>(l));
    571 	mpq_neg(q, q);
    572       }
    573     else
    574       {
    575 	__GMPXX_TMPQ_SI;
    576 	mpq_mul (q, r, temp);
    577       }
    578   }
    579   static void eval(mpq_ptr q, signed long int l, mpq_srcptr r)
    580   { eval(q, r, l); }
    581   static void eval(mpq_ptr q, mpq_srcptr r, double d)
    582   {  __GMPXX_TMPQ_D;    mpq_mul (q, r, temp); }
    583   static void eval(mpq_ptr q, double d, mpq_srcptr r)
    584   { eval(q, r, d); }
    585 
    586   static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)
    587   { mpf_mul(f, g, h); }
    588 
    589   static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l)
    590   { mpf_mul_ui(f, g, l); }
    591   static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g)
    592   { mpf_mul_ui(f, g, l); }
    593   static void eval(mpf_ptr f, mpf_srcptr g, signed long int l)
    594   {
    595     if (l >= 0)
    596       mpf_mul_ui(f, g, l);
    597     else
    598       {
    599 	mpf_mul_ui(f, g, -static_cast<unsigned long>(l));
    600 	mpf_neg(f, f);
    601       }
    602   }
    603   static void eval(mpf_ptr f, signed long int l, mpf_srcptr g)
    604   { eval(f, g, l); }
    605   static void eval(mpf_ptr f, mpf_srcptr g, double d)
    606   {
    607     mpf_t temp;
    608     mpf_init2(temp, 8*sizeof(double));
    609     mpf_set_d(temp, d);
    610     mpf_mul(f, g, temp);
    611     mpf_clear(temp);
    612   }
    613   static void eval(mpf_ptr f, double d, mpf_srcptr g)
    614   { eval(f, g, d); }
    615 };
    616 
    617 struct __gmp_binary_divides
    618 {
    619   static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
    620   { mpz_tdiv_q(z, w, v); }
    621 
    622   static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
    623   {
    624 #if __GMP_GNUC_PREREQ(3, 4)
    625     // Don't optimize division by 0...
    626     if (__GMPXX_CONSTANT(l) && (l & (l-1)) == 0 && l != 0)
    627     {
    628       if (l == 1)
    629       {
    630         if (z != w) mpz_set(z, w);
    631       }
    632       else
    633         mpz_tdiv_q_2exp(z, w, __builtin_ctzl(l));
    634         // warning: do not use rshift (fdiv)
    635     }
    636     else
    637 #endif
    638       mpz_tdiv_q_ui(z, w, l);
    639   }
    640   static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
    641   {
    642     if (mpz_sgn(w) >= 0)
    643       {
    644 	if (mpz_fits_ulong_p(w))
    645 	  mpz_set_ui(z, l / mpz_get_ui(w));
    646 	else
    647 	  mpz_set_ui(z, 0);
    648       }
    649     else
    650       {
    651 	mpz_neg(z, w);
    652 	if (mpz_fits_ulong_p(z))
    653 	  {
    654 	    mpz_set_ui(z, l / mpz_get_ui(z));
    655 	    mpz_neg(z, z);
    656 	  }
    657 	else
    658 	  mpz_set_ui(z, 0);
    659       }
    660   }
    661   static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
    662   {
    663     if (l >= 0)
    664       eval(z, w, static_cast<unsigned long>(l));
    665     else
    666       {
    667 	eval(z, w, -static_cast<unsigned long>(l));
    668 	mpz_neg(z, z);
    669       }
    670   }
    671   static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
    672   {
    673     if (mpz_fits_slong_p(w))
    674       mpz_set_si(z, l / mpz_get_si(w));
    675     else
    676       {
    677         /* if w is bigger than a long then the quotient must be zero, unless
    678            l==LONG_MIN and w==-LONG_MIN in which case the quotient is -1 */
    679         mpz_set_si (z, (mpz_cmpabs_ui (w, __gmpxx_abs_ui(l)) == 0 ? -1 : 0));
    680       }
    681   }
    682   static void eval(mpz_ptr z, mpz_srcptr w, double d)
    683   {  __GMPXX_TMPZ_D;    mpz_tdiv_q (z, w, temp); }
    684   static void eval(mpz_ptr z, double d, mpz_srcptr w)
    685   {  __GMPXX_TMPZ_D;    mpz_tdiv_q (z, temp, w); }
    686 
    687   static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s)
    688   { mpq_div(q, r, s); }
    689 
    690   static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l)
    691   {
    692 #if __GMP_GNUC_PREREQ(3, 4)
    693     if (__GMPXX_CONSTANT(l) && (l & (l-1)) == 0 && l != 0)
    694       __gmp_binary_rshift::eval(q, r, __builtin_ctzl(l));
    695     else
    696 #endif
    697     {
    698       __GMPXX_TMPQ_UI;
    699       mpq_div (q, r, temp);
    700     }
    701   }
    702   static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r)
    703   {
    704     if (__GMPXX_CONSTANT_TRUE(l == 0))
    705       mpq_set_ui(q, 0, 1);
    706     else if (__GMPXX_CONSTANT_TRUE(l == 1))
    707       mpq_inv(q, r);
    708     else
    709       {
    710 	__GMPXX_TMPQ_UI;
    711 	mpq_div (q, temp, r);
    712       }
    713   }
    714   static void eval(mpq_ptr q, mpq_srcptr r, signed long int l)
    715   {
    716     if (__GMPXX_CONSTANT_TRUE(l >= 0))
    717       eval(q, r, static_cast<unsigned long>(l));
    718     else if (__GMPXX_CONSTANT_TRUE(l <= 0))
    719       {
    720         eval(q, r, -static_cast<unsigned long>(l));
    721 	mpq_neg(q, q);
    722       }
    723     else
    724       {
    725 	__GMPXX_TMPQ_SI;
    726 	mpq_div (q, r, temp);
    727       }
    728   }
    729   static void eval(mpq_ptr q, signed long int l, mpq_srcptr r)
    730   {
    731     if (__GMPXX_CONSTANT_TRUE(l == 0))
    732       mpq_set_ui(q, 0, 1);
    733     else if (__GMPXX_CONSTANT_TRUE(l == 1))
    734       mpq_inv(q, r);
    735     else if (__GMPXX_CONSTANT_TRUE(l == -1))
    736       {
    737 	mpq_inv(q, r);
    738 	mpq_neg(q, q);
    739       }
    740     else
    741       {
    742 	__GMPXX_TMPQ_SI;
    743 	mpq_div (q, temp, r);
    744       }
    745   }
    746   static void eval(mpq_ptr q, mpq_srcptr r, double d)
    747   {  __GMPXX_TMPQ_D;    mpq_div (q, r, temp); }
    748   static void eval(mpq_ptr q, double d, mpq_srcptr r)
    749   {  __GMPXX_TMPQ_D;    mpq_div (q, temp, r); }
    750 
    751   static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)
    752   { mpf_div(f, g, h); }
    753 
    754   static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l)
    755   { mpf_div_ui(f, g, l); }
    756   static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g)
    757   { mpf_ui_div(f, l, g); }
    758   static void eval(mpf_ptr f, mpf_srcptr g, signed long int l)
    759   {
    760     if (l >= 0)
    761       mpf_div_ui(f, g, l);
    762     else
    763       {
    764 	mpf_div_ui(f, g, -static_cast<unsigned long>(l));
    765 	mpf_neg(f, f);
    766       }
    767   }
    768   static void eval(mpf_ptr f, signed long int l, mpf_srcptr g)
    769   {
    770     if (l >= 0)
    771       mpf_ui_div(f, l, g);
    772     else
    773       {
    774 	mpf_ui_div(f, -static_cast<unsigned long>(l), g);
    775 	mpf_neg(f, f);
    776       }
    777   }
    778   static void eval(mpf_ptr f, mpf_srcptr g, double d)
    779   {
    780     mpf_t temp;
    781     mpf_init2(temp, 8*sizeof(double));
    782     mpf_set_d(temp, d);
    783     mpf_div(f, g, temp);
    784     mpf_clear(temp);
    785   }
    786   static void eval(mpf_ptr f, double d, mpf_srcptr g)
    787   {
    788     mpf_t temp;
    789     mpf_init2(temp, 8*sizeof(double));
    790     mpf_set_d(temp, d);
    791     mpf_div(f, temp, g);
    792     mpf_clear(temp);
    793   }
    794 };
    795 
    796 struct __gmp_binary_modulus
    797 {
    798   static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
    799   { mpz_tdiv_r(z, w, v); }
    800 
    801   static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
    802   { mpz_tdiv_r_ui(z, w, l); }
    803   static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
    804   {
    805     if (mpz_sgn(w) >= 0)
    806       {
    807 	if (mpz_fits_ulong_p(w))
    808 	  mpz_set_ui(z, l % mpz_get_ui(w));
    809 	else
    810 	  mpz_set_ui(z, l);
    811       }
    812     else
    813       {
    814 	mpz_neg(z, w);
    815 	if (mpz_fits_ulong_p(z))
    816 	  mpz_set_ui(z, l % mpz_get_ui(z));
    817 	else
    818 	  mpz_set_ui(z, l);
    819       }
    820   }
    821   static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
    822   {
    823     mpz_tdiv_r_ui (z, w, __gmpxx_abs_ui(l));
    824   }
    825   static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
    826   {
    827     if (mpz_fits_slong_p(w))
    828       mpz_set_si(z, l % mpz_get_si(w));
    829     else
    830       {
    831         /* if w is bigger than a long then the remainder is l unchanged,
    832            unless l==LONG_MIN and w==-LONG_MIN in which case it's 0 */
    833         mpz_set_si (z, mpz_cmpabs_ui (w, __gmpxx_abs_ui(l)) == 0 ? 0 : l);
    834       }
    835   }
    836   static void eval(mpz_ptr z, mpz_srcptr w, double d)
    837   {  __GMPXX_TMPZ_D;    mpz_tdiv_r (z, w, temp); }
    838   static void eval(mpz_ptr z, double d, mpz_srcptr w)
    839   {  __GMPXX_TMPZ_D;    mpz_tdiv_r (z, temp, w); }
    840 };
    841 
    842 struct __gmp_binary_and
    843 {
    844   static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
    845   { mpz_and(z, w, v); }
    846 
    847   static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
    848   {  __GMPXX_TMPZ_UI;   mpz_and (z, w, temp);  }
    849   static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
    850   { eval(z, w, l);  }
    851   static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
    852   {  __GMPXX_TMPZ_SI;   mpz_and (z, w, temp);  }
    853   static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
    854   { eval(z, w, l);  }
    855   static void eval(mpz_ptr z, mpz_srcptr w, double d)
    856   {  __GMPXX_TMPZ_D;    mpz_and (z, w, temp); }
    857   static void eval(mpz_ptr z, double d, mpz_srcptr w)
    858   { eval(z, w, d);  }
    859 };
    860 
    861 struct __gmp_binary_ior
    862 {
    863   static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
    864   { mpz_ior(z, w, v); }
    865   static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
    866   {  __GMPXX_TMPZ_UI;   mpz_ior (z, w, temp);  }
    867   static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
    868   { eval(z, w, l);  }
    869   static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
    870   {  __GMPXX_TMPZ_SI;   mpz_ior (z, w, temp);  }
    871   static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
    872   { eval(z, w, l);  }
    873   static void eval(mpz_ptr z, mpz_srcptr w, double d)
    874   {  __GMPXX_TMPZ_D;    mpz_ior (z, w, temp); }
    875   static void eval(mpz_ptr z, double d, mpz_srcptr w)
    876   { eval(z, w, d);  }
    877 };
    878 
    879 struct __gmp_binary_xor
    880 {
    881   static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
    882   { mpz_xor(z, w, v); }
    883   static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
    884   {  __GMPXX_TMPZ_UI;   mpz_xor (z, w, temp);  }
    885   static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
    886   { eval(z, w, l);  }
    887   static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
    888   {  __GMPXX_TMPZ_SI;   mpz_xor (z, w, temp);  }
    889   static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
    890   { eval(z, w, l);  }
    891   static void eval(mpz_ptr z, mpz_srcptr w, double d)
    892   {  __GMPXX_TMPZ_D;    mpz_xor (z, w, temp); }
    893   static void eval(mpz_ptr z, double d, mpz_srcptr w)
    894   { eval(z, w, d);  }
    895 };
    896 
    897 struct __gmp_cmp_function
    898 {
    899   static int eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w); }
    900 
    901   static int eval(mpz_srcptr z, unsigned long int l)
    902   { return mpz_cmp_ui(z, l); }
    903   static int eval(unsigned long int l, mpz_srcptr z)
    904   { return -mpz_cmp_ui(z, l); }
    905   static int eval(mpz_srcptr z, signed long int l)
    906   { return mpz_cmp_si(z, l); }
    907   static int eval(signed long int l, mpz_srcptr z)
    908   { return -mpz_cmp_si(z, l); }
    909   static int eval(mpz_srcptr z, double d)
    910   { return mpz_cmp_d(z, d); }
    911   static int eval(double d, mpz_srcptr z)
    912   { return -mpz_cmp_d(z, d); }
    913 
    914   static int eval(mpq_srcptr q, mpq_srcptr r) { return mpq_cmp(q, r); }
    915 
    916   static int eval(mpq_srcptr q, unsigned long int l)
    917   { return mpq_cmp_ui(q, l, 1); }
    918   static int eval(unsigned long int l, mpq_srcptr q)
    919   { return -mpq_cmp_ui(q, l, 1); }
    920   static int eval(mpq_srcptr q, signed long int l)
    921   { return mpq_cmp_si(q, l, 1); }
    922   static int eval(signed long int l, mpq_srcptr q)
    923   { return -mpq_cmp_si(q, l, 1); }
    924   static int eval(mpq_srcptr q, double d)
    925   {  __GMPXX_TMPQ_D;    return mpq_cmp (q, temp); }
    926   static int eval(double d, mpq_srcptr q)
    927   {  __GMPXX_TMPQ_D;    return mpq_cmp (temp, q); }
    928   static int eval(mpq_srcptr q, mpz_srcptr z)
    929   { return mpq_cmp_z(q, z); }
    930   static int eval(mpz_srcptr z, mpq_srcptr q)
    931   { return -mpq_cmp_z(q, z); }
    932 
    933   static int eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g); }
    934 
    935   static int eval(mpf_srcptr f, unsigned long int l)
    936   { return mpf_cmp_ui(f, l); }
    937   static int eval(unsigned long int l, mpf_srcptr f)
    938   { return -mpf_cmp_ui(f, l); }
    939   static int eval(mpf_srcptr f, signed long int l)
    940   { return mpf_cmp_si(f, l); }
    941   static int eval(signed long int l, mpf_srcptr f)
    942   { return -mpf_cmp_si(f, l); }
    943   static int eval(mpf_srcptr f, double d)
    944   { return mpf_cmp_d(f, d); }
    945   static int eval(double d, mpf_srcptr f)
    946   { return -mpf_cmp_d(f, d); }
    947   static int eval(mpf_srcptr f, mpz_srcptr z)
    948   { return mpf_cmp_z(f, z); }
    949   static int eval(mpz_srcptr z, mpf_srcptr f)
    950   { return -mpf_cmp_z(f, z); }
    951   static int eval(mpf_srcptr f, mpq_srcptr q)
    952   {
    953     mpf_t qf;
    954     mpf_init(qf); /* Should we use the precision of f?  */
    955     mpf_set_q(qf, q);
    956     int ret = eval(f, qf);
    957     mpf_clear(qf);
    958     return ret;
    959   }
    960   static int eval(mpq_srcptr q, mpf_srcptr f)
    961   { return -eval(f, q); }
    962 };
    963 
    964 struct __gmp_binary_equal
    965 {
    966   static bool eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w) == 0; }
    967 
    968   static bool eval(mpz_srcptr z, unsigned long int l)
    969   { return mpz_cmp_ui(z, l) == 0; }
    970   static bool eval(unsigned long int l, mpz_srcptr z)
    971   { return eval(z, l); }
    972   static bool eval(mpz_srcptr z, signed long int l)
    973   { return mpz_cmp_si(z, l) == 0; }
    974   static bool eval(signed long int l, mpz_srcptr z)
    975   { return eval(z, l); }
    976   static bool eval(mpz_srcptr z, double d)
    977   { return mpz_cmp_d(z, d) == 0; }
    978   static bool eval(double d, mpz_srcptr z)
    979   { return eval(z, d); }
    980 
    981   static bool eval(mpq_srcptr q, mpq_srcptr r)
    982   { return mpq_equal(q, r) != 0; }
    983 
    984   static bool eval(mpq_srcptr q, unsigned long int l)
    985   { return ((__GMPXX_CONSTANT(l) && l == 0) ||
    986 	    mpz_cmp_ui(mpq_denref(q), 1) == 0) &&
    987       mpz_cmp_ui(mpq_numref(q), l) == 0; }
    988   static bool eval(unsigned long int l, mpq_srcptr q)
    989   { return eval(q, l); }
    990   static bool eval(mpq_srcptr q, signed long int l)
    991   { return ((__GMPXX_CONSTANT(l) && l == 0) ||
    992 	    mpz_cmp_ui(mpq_denref(q), 1) == 0) &&
    993       mpz_cmp_si(mpq_numref(q), l) == 0; }
    994   static bool eval(signed long int l, mpq_srcptr q)
    995   { return eval(q, l); }
    996   static bool eval(mpq_srcptr q, double d)
    997   {  __GMPXX_TMPQ_D;    return mpq_equal (q, temp) != 0; }
    998   static bool eval(double d, mpq_srcptr q)
    999   { return eval(q, d); }
   1000   static bool eval(mpq_srcptr q, mpz_srcptr z)
   1001   { return mpz_cmp_ui(mpq_denref(q), 1) == 0 && mpz_cmp(mpq_numref(q), z) == 0; }
   1002   static bool eval(mpz_srcptr z, mpq_srcptr q)
   1003   { return eval(q, z); }
   1004 
   1005   static bool eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g) == 0; }
   1006 
   1007   static bool eval(mpf_srcptr f, unsigned long int l)
   1008   { return mpf_cmp_ui(f, l) == 0; }
   1009   static bool eval(unsigned long int l, mpf_srcptr f)
   1010   { return eval(f, l); }
   1011   static bool eval(mpf_srcptr f, signed long int l)
   1012   { return mpf_cmp_si(f, l) == 0; }
   1013   static bool eval(signed long int l, mpf_srcptr f)
   1014   { return eval(f, l); }
   1015   static bool eval(mpf_srcptr f, double d)
   1016   { return mpf_cmp_d(f, d) == 0; }
   1017   static bool eval(double d, mpf_srcptr f)
   1018   { return eval(f, d); }
   1019   static bool eval(mpf_srcptr f, mpz_srcptr z)
   1020   { return mpf_cmp_z(f, z) == 0; }
   1021   static bool eval(mpz_srcptr z, mpf_srcptr f)
   1022   { return eval(f, z); }
   1023   static bool eval(mpf_srcptr f, mpq_srcptr q)
   1024   { return __gmp_cmp_function::eval(f, q) == 0; }
   1025   static bool eval(mpq_srcptr q, mpf_srcptr f)
   1026   { return eval(f, q); }
   1027 };
   1028 
   1029 struct __gmp_binary_less
   1030 {
   1031   static bool eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w) < 0; }
   1032 
   1033   static bool eval(mpz_srcptr z, unsigned long int l)
   1034   { return mpz_cmp_ui(z, l) < 0; }
   1035   static bool eval(unsigned long int l, mpz_srcptr z)
   1036   { return mpz_cmp_ui(z, l) > 0; }
   1037   static bool eval(mpz_srcptr z, signed long int l)
   1038   { return mpz_cmp_si(z, l) < 0; }
   1039   static bool eval(signed long int l, mpz_srcptr z)
   1040   { return mpz_cmp_si(z, l) > 0; }
   1041   static bool eval(mpz_srcptr z, double d)
   1042   { return mpz_cmp_d(z, d) < 0; }
   1043   static bool eval(double d, mpz_srcptr z)
   1044   { return mpz_cmp_d(z, d) > 0; }
   1045 
   1046   static bool eval(mpq_srcptr q, mpq_srcptr r) { return mpq_cmp(q, r) < 0; }
   1047 
   1048   static bool eval(mpq_srcptr q, unsigned long int l)
   1049   { return mpq_cmp_ui(q, l, 1) < 0; }
   1050   static bool eval(unsigned long int l, mpq_srcptr q)
   1051   { return mpq_cmp_ui(q, l, 1) > 0; }
   1052   static bool eval(mpq_srcptr q, signed long int l)
   1053   { return mpq_cmp_si(q, l, 1) < 0; }
   1054   static bool eval(signed long int l, mpq_srcptr q)
   1055   { return mpq_cmp_si(q, l, 1) > 0; }
   1056   static bool eval(mpq_srcptr q, double d)
   1057   {  __GMPXX_TMPQ_D;    return mpq_cmp (q, temp) < 0; }
   1058   static bool eval(double d, mpq_srcptr q)
   1059   {  __GMPXX_TMPQ_D;    return mpq_cmp (temp, q) < 0; }
   1060   static bool eval(mpq_srcptr q, mpz_srcptr z)
   1061   { return mpq_cmp_z(q, z) < 0; }
   1062   static bool eval(mpz_srcptr z, mpq_srcptr q)
   1063   { return mpq_cmp_z(q, z) > 0; }
   1064 
   1065   static bool eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g) < 0; }
   1066 
   1067   static bool eval(mpf_srcptr f, unsigned long int l)
   1068   { return mpf_cmp_ui(f, l) < 0; }
   1069   static bool eval(unsigned long int l, mpf_srcptr f)
   1070   { return mpf_cmp_ui(f, l) > 0; }
   1071   static bool eval(mpf_srcptr f, signed long int l)
   1072   { return mpf_cmp_si(f, l) < 0; }
   1073   static bool eval(signed long int l, mpf_srcptr f)
   1074   { return mpf_cmp_si(f, l) > 0; }
   1075   static bool eval(mpf_srcptr f, double d)
   1076   { return mpf_cmp_d(f, d) < 0; }
   1077   static bool eval(double d, mpf_srcptr f)
   1078   { return mpf_cmp_d(f, d) > 0; }
   1079   static bool eval(mpf_srcptr f, mpz_srcptr z)
   1080   { return mpf_cmp_z(f, z) < 0; }
   1081   static bool eval(mpz_srcptr z, mpf_srcptr f)
   1082   { return mpf_cmp_z(f, z) > 0; }
   1083   static bool eval(mpf_srcptr f, mpq_srcptr q)
   1084   { return __gmp_cmp_function::eval(f, q) < 0; }
   1085   static bool eval(mpq_srcptr q, mpf_srcptr f)
   1086   { return __gmp_cmp_function::eval(q, f) < 0; }
   1087 };
   1088 
   1089 struct __gmp_binary_greater
   1090 {
   1091   template <class T, class U>
   1092   static inline bool eval(T t, U u) { return __gmp_binary_less::eval(u, t); }
   1093 };
   1094 
   1095 struct __gmp_unary_increment
   1096 {
   1097   static void eval(mpz_ptr z) { mpz_add_ui(z, z, 1); }
   1098   static void eval(mpq_ptr q)
   1099   { mpz_add(mpq_numref(q), mpq_numref(q), mpq_denref(q)); }
   1100   static void eval(mpf_ptr f) { mpf_add_ui(f, f, 1); }
   1101 };
   1102 
   1103 struct __gmp_unary_decrement
   1104 {
   1105   static void eval(mpz_ptr z) { mpz_sub_ui(z, z, 1); }
   1106   static void eval(mpq_ptr q)
   1107   { mpz_sub(mpq_numref(q), mpq_numref(q), mpq_denref(q)); }
   1108   static void eval(mpf_ptr f) { mpf_sub_ui(f, f, 1); }
   1109 };
   1110 
   1111 struct __gmp_abs_function
   1112 {
   1113   static void eval(mpz_ptr z, mpz_srcptr w) { mpz_abs(z, w); }
   1114   static void eval(mpq_ptr q, mpq_srcptr r) { mpq_abs(q, r); }
   1115   static void eval(mpf_ptr f, mpf_srcptr g) { mpf_abs(f, g); }
   1116 };
   1117 
   1118 struct __gmp_trunc_function
   1119 {
   1120   static void eval(mpf_ptr f, mpf_srcptr g) { mpf_trunc(f, g); }
   1121 };
   1122 
   1123 struct __gmp_floor_function
   1124 {
   1125   static void eval(mpf_ptr f, mpf_srcptr g) { mpf_floor(f, g); }
   1126 };
   1127 
   1128 struct __gmp_ceil_function
   1129 {
   1130   static void eval(mpf_ptr f, mpf_srcptr g) { mpf_ceil(f, g); }
   1131 };
   1132 
   1133 struct __gmp_sqrt_function
   1134 {
   1135   static void eval(mpz_ptr z, mpz_srcptr w) { mpz_sqrt(z, w); }
   1136   static void eval(mpf_ptr f, mpf_srcptr g) { mpf_sqrt(f, g); }
   1137 };
   1138 
   1139 struct __gmp_hypot_function
   1140 {
   1141   static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)
   1142   {
   1143     mpf_t temp;
   1144     mpf_init2(temp, mpf_get_prec(f));
   1145     mpf_mul(temp, g, g);
   1146     mpf_mul(f, h, h);
   1147     mpf_add(f, f, temp);
   1148     mpf_sqrt(f, f);
   1149     mpf_clear(temp);
   1150   }
   1151 
   1152   static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l)
   1153   {
   1154     mpf_t temp;
   1155     mpf_init2(temp, mpf_get_prec(f));
   1156     mpf_mul(temp, g, g);
   1157     mpf_set_ui(f, l);
   1158     mpf_mul_ui(f, f, l);
   1159     mpf_add(f, f, temp);
   1160     mpf_clear(temp);
   1161     mpf_sqrt(f, f);
   1162   }
   1163   static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g)
   1164   { eval(f, g, l); }
   1165   static void eval(mpf_ptr f, mpf_srcptr g, signed long int l)
   1166   { eval(f, g, __gmpxx_abs_ui(l)); }
   1167   static void eval(mpf_ptr f, signed long int l, mpf_srcptr g)
   1168   { eval(f, g, l); }
   1169   static void eval(mpf_ptr f, mpf_srcptr g, double d)
   1170   {
   1171     mpf_t temp;
   1172     mpf_init2(temp, mpf_get_prec(f));
   1173     mpf_mul(temp, g, g);
   1174     mpf_set_d(f, d);
   1175     mpf_mul(f, f, f);
   1176     mpf_add(f, f, temp);
   1177     mpf_sqrt(f, f);
   1178     mpf_clear(temp);
   1179   }
   1180   static void eval(mpf_ptr f, double d, mpf_srcptr g)
   1181   { eval(f, g, d); }
   1182 };
   1183 
   1184 struct __gmp_sgn_function
   1185 {
   1186   static int eval(mpz_srcptr z) { return mpz_sgn(z); }
   1187   static int eval(mpq_srcptr q) { return mpq_sgn(q); }
   1188   static int eval(mpf_srcptr f) { return mpf_sgn(f); }
   1189 };
   1190 
   1191 struct __gmp_gcd_function
   1192 {
   1193   static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
   1194   { mpz_gcd(z, w, v); }
   1195   static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
   1196   { mpz_gcd_ui(z, w, l); }
   1197   static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
   1198   { eval(z, w, l); }
   1199   static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
   1200   { eval(z, w, __gmpxx_abs_ui(l)); }
   1201   static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
   1202   { eval(z, w, l); }
   1203   static void eval(mpz_ptr z, mpz_srcptr w, double d)
   1204   {  __GMPXX_TMPZ_D;    mpz_gcd (z, w, temp); }
   1205   static void eval(mpz_ptr z, double d, mpz_srcptr w)
   1206   { eval(z, w, d); }
   1207 };
   1208 
   1209 struct __gmp_lcm_function
   1210 {
   1211   static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
   1212   { mpz_lcm(z, w, v); }
   1213   static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
   1214   { mpz_lcm_ui(z, w, l); }
   1215   static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
   1216   { eval(z, w, l); }
   1217   static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
   1218   { eval(z, w, __gmpxx_abs_ui(l)); }
   1219   static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
   1220   { eval(z, w, l); }
   1221   static void eval(mpz_ptr z, mpz_srcptr w, double d)
   1222   {  __GMPXX_TMPZ_D;    mpz_lcm (z, w, temp); }
   1223   static void eval(mpz_ptr z, double d, mpz_srcptr w)
   1224   { eval(z, w, d); }
   1225 };
   1226 
   1227 struct __gmp_rand_function
   1228 {
   1229   static void eval(mpz_ptr z, gmp_randstate_t s, mp_bitcnt_t l)
   1230   { mpz_urandomb(z, s, l); }
   1231   static void eval(mpz_ptr z, gmp_randstate_t s, mpz_srcptr w)
   1232   { mpz_urandomm(z, s, w); }
   1233   static void eval(mpf_ptr f, gmp_randstate_t s, mp_bitcnt_t prec)
   1234   { mpf_urandomb(f, s, prec); }
   1235 };
   1236 
   1237 struct __gmp_fac_function
   1238 {
   1239   static void eval(mpz_ptr z, unsigned long l) { mpz_fac_ui(z, l); }
   1240   static void eval(mpz_ptr z, signed long l)
   1241   {
   1242     if (l < 0)
   1243       throw std::domain_error ("factorial(negative)");
   1244     eval(z, static_cast<unsigned long>(l));
   1245   }
   1246   static void eval(mpz_ptr z, mpz_srcptr w)
   1247   {
   1248     if (!mpz_fits_ulong_p(w))
   1249       {
   1250 	if (mpz_sgn(w) < 0)
   1251 	  throw std::domain_error ("factorial(negative)");
   1252 	else
   1253 	  throw std::bad_alloc(); // or std::overflow_error ("factorial")?
   1254       }
   1255     eval(z, mpz_get_ui(w));
   1256   }
   1257   static void eval(mpz_ptr z, double d)
   1258   {  __GMPXX_TMPZ_D;    eval (z, temp); }
   1259 };
   1260 
   1261 struct __gmp_primorial_function
   1262 {
   1263   static void eval(mpz_ptr z, unsigned long l) { mpz_primorial_ui(z, l); }
   1264   static void eval(mpz_ptr z, signed long l)
   1265   {
   1266     if (l < 0)
   1267       throw std::domain_error ("primorial(negative)");
   1268     eval(z, static_cast<unsigned long>(l));
   1269   }
   1270   static void eval(mpz_ptr z, mpz_srcptr w)
   1271   {
   1272     if (!mpz_fits_ulong_p(w))
   1273       {
   1274 	if (mpz_sgn(w) < 0)
   1275 	  throw std::domain_error ("primorial(negative)");
   1276 	else
   1277 	  throw std::bad_alloc(); // or std::overflow_error ("primorial")?
   1278       }
   1279     eval(z, mpz_get_ui(w));
   1280   }
   1281   static void eval(mpz_ptr z, double d)
   1282   {  __GMPXX_TMPZ_D;    eval (z, temp); }
   1283 };
   1284 
   1285 struct __gmp_fib_function
   1286 {
   1287   static void eval(mpz_ptr z, unsigned long l) { mpz_fib_ui(z, l); }
   1288   static void eval(mpz_ptr z, signed long l)
   1289   {
   1290     if (l < 0)
   1291       {
   1292 	eval(z, -static_cast<unsigned long>(l));
   1293 	if ((l & 1) == 0)
   1294 	  mpz_neg(z, z);
   1295       }
   1296     else
   1297       eval(z, static_cast<unsigned long>(l));
   1298   }
   1299   static void eval(mpz_ptr z, mpz_srcptr w)
   1300   {
   1301     if (!mpz_fits_slong_p(w))
   1302       throw std::bad_alloc(); // or std::overflow_error ("fibonacci")?
   1303     eval(z, mpz_get_si(w));
   1304   }
   1305   static void eval(mpz_ptr z, double d)
   1306   {  __GMPXX_TMPZ_D;    eval (z, temp); }
   1307 };
   1308 
   1309 
   1310 /**************** Auxiliary classes ****************/
   1311 
   1312 /* this is much the same as gmp_allocated_string in gmp-impl.h
   1313    since gmp-impl.h is not publicly available, I redefine it here
   1314    I use a different name to avoid possible clashes */
   1315 
   1316 extern "C" {
   1317   typedef void (*__gmp_freefunc_t) (void *, size_t);
   1318 }
   1319 struct __gmp_alloc_cstring
   1320 {
   1321   char *str;
   1322   __gmp_alloc_cstring(char *s) { str = s; }
   1323   ~__gmp_alloc_cstring()
   1324   {
   1325     __gmp_freefunc_t freefunc;
   1326     mp_get_memory_functions (NULL, NULL, &freefunc);
   1327     (*freefunc) (str, std::strlen(str)+1);
   1328   }
   1329 };
   1330 
   1331 
   1332 // general expression template class
   1333 template <class T, class U>
   1334 class __gmp_expr;
   1335 
   1336 
   1337 // templates for resolving expression types
   1338 template <class T>
   1339 struct __gmp_resolve_ref
   1340 {
   1341   typedef T ref_type;
   1342 };
   1343 
   1344 template <class T, class U>
   1345 struct __gmp_resolve_ref<__gmp_expr<T, U> >
   1346 {
   1347   typedef const __gmp_expr<T, U> & ref_type;
   1348 };
   1349 
   1350 
   1351 template <class T, class U = T>
   1352 struct __gmp_resolve_expr;
   1353 
   1354 template <>
   1355 struct __gmp_resolve_expr<mpz_t>
   1356 {
   1357   typedef mpz_t value_type;
   1358   typedef mpz_ptr ptr_type;
   1359   typedef mpz_srcptr srcptr_type;
   1360 };
   1361 
   1362 template <>
   1363 struct __gmp_resolve_expr<mpq_t>
   1364 {
   1365   typedef mpq_t value_type;
   1366   typedef mpq_ptr ptr_type;
   1367   typedef mpq_srcptr srcptr_type;
   1368 };
   1369 
   1370 template <>
   1371 struct __gmp_resolve_expr<mpf_t>
   1372 {
   1373   typedef mpf_t value_type;
   1374   typedef mpf_ptr ptr_type;
   1375   typedef mpf_srcptr srcptr_type;
   1376 };
   1377 
   1378 template <>
   1379 struct __gmp_resolve_expr<mpz_t, mpq_t>
   1380 {
   1381   typedef mpq_t value_type;
   1382 };
   1383 
   1384 template <>
   1385 struct __gmp_resolve_expr<mpq_t, mpz_t>
   1386 {
   1387   typedef mpq_t value_type;
   1388 };
   1389 
   1390 template <>
   1391 struct __gmp_resolve_expr<mpz_t, mpf_t>
   1392 {
   1393   typedef mpf_t value_type;
   1394 };
   1395 
   1396 template <>
   1397 struct __gmp_resolve_expr<mpf_t, mpz_t>
   1398 {
   1399   typedef mpf_t value_type;
   1400 };
   1401 
   1402 template <>
   1403 struct __gmp_resolve_expr<mpq_t, mpf_t>
   1404 {
   1405   typedef mpf_t value_type;
   1406 };
   1407 
   1408 template <>
   1409 struct __gmp_resolve_expr<mpf_t, mpq_t>
   1410 {
   1411   typedef mpf_t value_type;
   1412 };
   1413 
   1414 #if __GMPXX_USE_CXX11
   1415 namespace std {
   1416   template <class T, class U, class V, class W>
   1417   struct common_type <__gmp_expr<T, U>, __gmp_expr<V, W> >
   1418   {
   1419   private:
   1420     typedef typename __gmp_resolve_expr<T, V>::value_type X;
   1421   public:
   1422     typedef __gmp_expr<X, X> type;
   1423   };
   1424 
   1425   template <class T, class U>
   1426   struct common_type <__gmp_expr<T, U> >
   1427   {
   1428     typedef __gmp_expr<T, T> type;
   1429   };
   1430 
   1431 #define __GMPXX_DECLARE_COMMON_TYPE(typ)	\
   1432   template <class T, class U>			\
   1433   struct common_type <__gmp_expr<T, U>, typ >	\
   1434   {						\
   1435     typedef __gmp_expr<T, T> type;		\
   1436   };						\
   1437 						\
   1438   template <class T, class U>			\
   1439   struct common_type <typ, __gmp_expr<T, U> >	\
   1440   {						\
   1441     typedef __gmp_expr<T, T> type;		\
   1442   }
   1443 
   1444   __GMPXX_DECLARE_COMMON_TYPE(signed char);
   1445   __GMPXX_DECLARE_COMMON_TYPE(unsigned char);
   1446   __GMPXX_DECLARE_COMMON_TYPE(signed int);
   1447   __GMPXX_DECLARE_COMMON_TYPE(unsigned int);
   1448   __GMPXX_DECLARE_COMMON_TYPE(signed short int);
   1449   __GMPXX_DECLARE_COMMON_TYPE(unsigned short int);
   1450   __GMPXX_DECLARE_COMMON_TYPE(signed long int);
   1451   __GMPXX_DECLARE_COMMON_TYPE(unsigned long int);
   1452   __GMPXX_DECLARE_COMMON_TYPE(float);
   1453   __GMPXX_DECLARE_COMMON_TYPE(double);
   1454 #undef __GMPXX_DECLARE_COMMON_TYPE
   1455 }
   1456 #endif
   1457 
   1458 // classes for evaluating unary and binary expressions
   1459 template <class T, class Op>
   1460 struct __gmp_unary_expr
   1461 {
   1462   typename __gmp_resolve_ref<T>::ref_type val;
   1463 
   1464   __gmp_unary_expr(const T &v) : val(v) { }
   1465 private:
   1466   __gmp_unary_expr();
   1467 };
   1468 
   1469 template <class T, class U, class Op>
   1470 struct __gmp_binary_expr
   1471 {
   1472   typename __gmp_resolve_ref<T>::ref_type val1;
   1473   typename __gmp_resolve_ref<U>::ref_type val2;
   1474 
   1475   __gmp_binary_expr(const T &v1, const U &v2) : val1(v1), val2(v2) { }
   1476 private:
   1477   __gmp_binary_expr();
   1478 };
   1479 
   1480 
   1481 
   1482 /**************** Macros for in-class declarations ****************/
   1483 /* This is just repetitive code that is easier to maintain if it's written
   1484    only once */
   1485 
   1486 #define __GMPP_DECLARE_COMPOUND_OPERATOR(fun)                         \
   1487   template <class T, class U>                                         \
   1488   __gmp_expr<value_type, value_type> & fun(const __gmp_expr<T, U> &);
   1489 
   1490 #define __GMPN_DECLARE_COMPOUND_OPERATOR(fun) \
   1491   __gmp_expr & fun(signed char);              \
   1492   __gmp_expr & fun(unsigned char);            \
   1493   __gmp_expr & fun(signed int);               \
   1494   __gmp_expr & fun(unsigned int);             \
   1495   __gmp_expr & fun(signed short int);         \
   1496   __gmp_expr & fun(unsigned short int);       \
   1497   __gmp_expr & fun(signed long int);          \
   1498   __gmp_expr & fun(unsigned long int);        \
   1499   __gmp_expr & fun(float);                    \
   1500   __gmp_expr & fun(double);                   \
   1501   /* __gmp_expr & fun(long double); */
   1502 
   1503 #define __GMP_DECLARE_COMPOUND_OPERATOR(fun) \
   1504 __GMPP_DECLARE_COMPOUND_OPERATOR(fun)        \
   1505 __GMPN_DECLARE_COMPOUND_OPERATOR(fun)
   1506 
   1507 #define __GMP_DECLARE_COMPOUND_OPERATOR_UI(fun) \
   1508   __gmp_expr & fun(mp_bitcnt_t);
   1509 
   1510 #define __GMP_DECLARE_INCREMENT_OPERATOR(fun) \
   1511   inline __gmp_expr & fun();                  \
   1512   inline __gmp_expr fun(int);
   1513 
   1514 #define __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS		\
   1515   __gmp_expr(signed char c) { init_si(c); }		\
   1516   __gmp_expr(unsigned char c) { init_ui(c); }		\
   1517   __gmp_expr(signed int i) { init_si(i); }		\
   1518   __gmp_expr(unsigned int i) { init_ui(i); }		\
   1519   __gmp_expr(signed short int s) { init_si(s); }	\
   1520   __gmp_expr(unsigned short int s) { init_ui(s); }	\
   1521   __gmp_expr(signed long int l) { init_si(l); }		\
   1522   __gmp_expr(unsigned long int l) { init_ui(l); }	\
   1523   __gmp_expr(float f) { init_d(f); }			\
   1524   __gmp_expr(double d) { init_d(d); }
   1525 
   1526 #define __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS		\
   1527   __gmp_expr & operator=(signed char c) { assign_si(c); return *this; } \
   1528   __gmp_expr & operator=(unsigned char c) { assign_ui(c); return *this; } \
   1529   __gmp_expr & operator=(signed int i) { assign_si(i); return *this; } \
   1530   __gmp_expr & operator=(unsigned int i) { assign_ui(i); return *this; } \
   1531   __gmp_expr & operator=(signed short int s) { assign_si(s); return *this; } \
   1532   __gmp_expr & operator=(unsigned short int s) { assign_ui(s); return *this; } \
   1533   __gmp_expr & operator=(signed long int l) { assign_si(l); return *this; } \
   1534   __gmp_expr & operator=(unsigned long int l) { assign_ui(l); return *this; } \
   1535   __gmp_expr & operator=(float f) { assign_d(f); return *this; } \
   1536   __gmp_expr & operator=(double d) { assign_d(d); return *this; }
   1537 
   1538 #define __GMPP_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun)                 \
   1539 template <class U>                                                           \
   1540 static __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, eval_fun> >          \
   1541 fun(const __gmp_expr<T, U> &expr);
   1542 
   1543 #define __GMPNN_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type, bigtype) \
   1544 static inline __gmp_expr<T, __gmp_unary_expr<bigtype, eval_fun> >            \
   1545 fun(type expr);
   1546 
   1547 #define __GMPNS_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type)  \
   1548 __GMPNN_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type, signed long)
   1549 #define __GMPNU_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type)  \
   1550 __GMPNN_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type, unsigned long)
   1551 #define __GMPND_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type)  \
   1552 __GMPNN_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type, double)
   1553 
   1554 #define __GMPN_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun)                 \
   1555 __GMPNS_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, signed char)           \
   1556 __GMPNU_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, unsigned char)         \
   1557 __GMPNS_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, signed int)            \
   1558 __GMPNU_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, unsigned int)          \
   1559 __GMPNS_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, signed short int)      \
   1560 __GMPNU_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, unsigned short int)    \
   1561 __GMPNS_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, signed long int)       \
   1562 __GMPNU_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, unsigned long int)     \
   1563 __GMPND_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, float)                 \
   1564 __GMPND_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, double)
   1565 
   1566 #define __GMP_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun)                  \
   1567 __GMPP_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun)                         \
   1568 __GMPN_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun)
   1569 
   1570 /**************** mpz_class -- wrapper for mpz_t ****************/
   1571 
   1572 template <>
   1573 class __gmp_expr<mpz_t, mpz_t>
   1574 {
   1575 private:
   1576   typedef mpz_t value_type;
   1577   value_type mp;
   1578 
   1579   // Helper functions used for all arithmetic types
   1580   void assign_ui(unsigned long l)
   1581   {
   1582     if (__GMPXX_CONSTANT_TRUE(l == 0))
   1583       mp->_mp_size = 0;
   1584     else
   1585       mpz_set_ui(mp, l);
   1586   }
   1587   void assign_si(signed long l)
   1588   {
   1589     if (__GMPXX_CONSTANT_TRUE(l >= 0))
   1590       assign_ui(l);
   1591     else if (__GMPXX_CONSTANT_TRUE(l <= 0))
   1592       {
   1593 	assign_ui(-static_cast<unsigned long>(l));
   1594 	mpz_neg(mp, mp);
   1595       }
   1596     else
   1597       mpz_set_si(mp, l);
   1598   }
   1599   void assign_d (double d)
   1600   {
   1601     mpz_set_d (mp, d);
   1602   }
   1603 
   1604   void init_ui(unsigned long l)
   1605   {
   1606     if (__GMPXX_CONSTANT_TRUE(l == 0))
   1607       mpz_init(mp);
   1608     else
   1609       mpz_init_set_ui(mp, l);
   1610   }
   1611   void init_si(signed long l)
   1612   {
   1613     if (__GMPXX_CONSTANT_TRUE(l >= 0))
   1614       init_ui(l);
   1615     else if (__GMPXX_CONSTANT_TRUE(l <= 0))
   1616       {
   1617 	init_ui(-static_cast<unsigned long>(l));
   1618 	mpz_neg(mp, mp);
   1619       }
   1620     else
   1621       mpz_init_set_si(mp, l);
   1622   }
   1623   void init_d (double d)
   1624   {
   1625     mpz_init_set_d (mp, d);
   1626   }
   1627 
   1628 public:
   1629   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }
   1630 
   1631   // constructors and destructor
   1632   __gmp_expr() __GMPXX_NOEXCEPT { mpz_init(mp); }
   1633 
   1634   __gmp_expr(const __gmp_expr &z) { mpz_init_set(mp, z.mp); }
   1635 #if __GMPXX_USE_CXX11
   1636   __gmp_expr(__gmp_expr &&z) noexcept
   1637   { *mp = *z.mp; mpz_init(z.mp); }
   1638 #endif
   1639   template <class T>
   1640   __gmp_expr(const __gmp_expr<mpz_t, T> &expr)
   1641   { mpz_init(mp); __gmp_set_expr(mp, expr); }
   1642   template <class T, class U>
   1643   explicit __gmp_expr(const __gmp_expr<T, U> &expr)
   1644   { mpz_init(mp); __gmp_set_expr(mp, expr); }
   1645 
   1646   __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS
   1647 
   1648   explicit __gmp_expr(const char *s, int base = 0)
   1649   {
   1650     if (mpz_init_set_str (mp, s, base) != 0)
   1651       {
   1652         mpz_clear (mp);
   1653         throw std::invalid_argument ("mpz_set_str");
   1654       }
   1655   }
   1656   explicit __gmp_expr(const std::string &s, int base = 0)
   1657   {
   1658     if (mpz_init_set_str(mp, s.c_str(), base) != 0)
   1659       {
   1660         mpz_clear (mp);
   1661         throw std::invalid_argument ("mpz_set_str");
   1662       }
   1663   }
   1664 
   1665   explicit __gmp_expr(mpz_srcptr z) { mpz_init_set(mp, z); }
   1666 
   1667   ~__gmp_expr() { mpz_clear(mp); }
   1668 
   1669   void swap(__gmp_expr& z) __GMPXX_NOEXCEPT { std::swap(*mp, *z.mp); }
   1670 
   1671   // assignment operators
   1672   __gmp_expr & operator=(const __gmp_expr &z)
   1673   { mpz_set(mp, z.mp); return *this; }
   1674 #if __GMPXX_USE_CXX11
   1675   __gmp_expr & operator=(__gmp_expr &&z) noexcept
   1676   { swap(z); return *this; }
   1677 #endif
   1678   template <class T, class U>
   1679   __gmp_expr<value_type, value_type> & operator=(const __gmp_expr<T, U> &expr)
   1680   { __gmp_set_expr(mp, expr); return *this; }
   1681 
   1682   __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS
   1683 
   1684   __gmp_expr & operator=(const char *s)
   1685   {
   1686     if (mpz_set_str (mp, s, 0) != 0)
   1687       throw std::invalid_argument ("mpz_set_str");
   1688     return *this;
   1689   }
   1690   __gmp_expr & operator=(const std::string &s)
   1691   {
   1692     if (mpz_set_str(mp, s.c_str(), 0) != 0)
   1693       throw std::invalid_argument ("mpz_set_str");
   1694     return *this;
   1695   }
   1696 
   1697   // string input/output functions
   1698   int set_str(const char *s, int base)
   1699   { return mpz_set_str(mp, s, base); }
   1700   int set_str(const std::string &s, int base)
   1701   { return mpz_set_str(mp, s.c_str(), base); }
   1702   std::string get_str(int base = 10) const
   1703   {
   1704     __gmp_alloc_cstring temp(mpz_get_str(0, base, mp));
   1705     return std::string(temp.str);
   1706   }
   1707 
   1708   // conversion functions
   1709   mpz_srcptr __get_mp() const { return mp; }
   1710   mpz_ptr __get_mp() { return mp; }
   1711   mpz_srcptr get_mpz_t() const { return mp; }
   1712   mpz_ptr get_mpz_t() { return mp; }
   1713 
   1714   signed long int get_si() const { return mpz_get_si(mp); }
   1715   unsigned long int get_ui() const { return mpz_get_ui(mp); }
   1716   double get_d() const { return mpz_get_d(mp); }
   1717 
   1718   // bool fits_schar_p() const { return mpz_fits_schar_p(mp); }
   1719   // bool fits_uchar_p() const { return mpz_fits_uchar_p(mp); }
   1720   bool fits_sint_p() const { return mpz_fits_sint_p(mp); }
   1721   bool fits_uint_p() const { return mpz_fits_uint_p(mp); }
   1722   bool fits_sshort_p() const { return mpz_fits_sshort_p(mp); }
   1723   bool fits_ushort_p() const { return mpz_fits_ushort_p(mp); }
   1724   bool fits_slong_p() const { return mpz_fits_slong_p(mp); }
   1725   bool fits_ulong_p() const { return mpz_fits_ulong_p(mp); }
   1726   // bool fits_float_p() const { return mpz_fits_float_p(mp); }
   1727   // bool fits_double_p() const { return mpz_fits_double_p(mp); }
   1728   // bool fits_ldouble_p() const { return mpz_fits_ldouble_p(mp); }
   1729 
   1730 #if __GMPXX_USE_CXX11
   1731   explicit operator bool() const { return mp->_mp_size != 0; }
   1732 #endif
   1733 
   1734   // member operators
   1735   __GMP_DECLARE_COMPOUND_OPERATOR(operator+=)
   1736   __GMP_DECLARE_COMPOUND_OPERATOR(operator-=)
   1737   __GMP_DECLARE_COMPOUND_OPERATOR(operator*=)
   1738   __GMP_DECLARE_COMPOUND_OPERATOR(operator/=)
   1739   __GMP_DECLARE_COMPOUND_OPERATOR(operator%=)
   1740 
   1741   __GMP_DECLARE_COMPOUND_OPERATOR(operator&=)
   1742   __GMP_DECLARE_COMPOUND_OPERATOR(operator|=)
   1743   __GMP_DECLARE_COMPOUND_OPERATOR(operator^=)
   1744 
   1745   __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=)
   1746   __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=)
   1747 
   1748   __GMP_DECLARE_INCREMENT_OPERATOR(operator++)
   1749   __GMP_DECLARE_INCREMENT_OPERATOR(operator--)
   1750 
   1751   __GMP_DECLARE_UNARY_STATIC_MEMFUN(mpz_t, factorial, __gmp_fac_function)
   1752   __GMP_DECLARE_UNARY_STATIC_MEMFUN(mpz_t, primorial, __gmp_primorial_function)
   1753   __GMP_DECLARE_UNARY_STATIC_MEMFUN(mpz_t, fibonacci, __gmp_fib_function)
   1754 };
   1755 
   1756 typedef __gmp_expr<mpz_t, mpz_t> mpz_class;
   1757 
   1758 
   1759 /**************** mpq_class -- wrapper for mpq_t ****************/
   1760 
   1761 template <>
   1762 class __gmp_expr<mpq_t, mpq_t>
   1763 {
   1764 private:
   1765   typedef mpq_t value_type;
   1766   value_type mp;
   1767 
   1768   // Helper functions used for all arithmetic types
   1769   void assign_ui(unsigned long l) { mpq_set_ui(mp, l, 1); }
   1770   void assign_si(signed long l)
   1771   {
   1772     if (__GMPXX_CONSTANT_TRUE(l >= 0))
   1773       assign_ui(l);
   1774     else
   1775       mpq_set_si(mp, l, 1);
   1776   }
   1777   void assign_d (double d)        { mpq_set_d (mp, d); }
   1778 
   1779   void init_ui(unsigned long l)	{ mpq_init(mp); get_num() = l; }
   1780   void init_si(signed long l)	{ mpq_init(mp); get_num() = l; }
   1781   void init_d (double d)	{ mpq_init(mp); assign_d (d); }
   1782 
   1783 public:
   1784   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }
   1785   void canonicalize() { mpq_canonicalize(mp); }
   1786 
   1787   // constructors and destructor
   1788   __gmp_expr() { mpq_init(mp); }
   1789 
   1790   __gmp_expr(const __gmp_expr &q)
   1791   {
   1792     mpz_init_set(mpq_numref(mp), mpq_numref(q.mp));
   1793     mpz_init_set(mpq_denref(mp), mpq_denref(q.mp));
   1794   }
   1795 #if __GMPXX_USE_CXX11
   1796   __gmp_expr(__gmp_expr &&q)
   1797   { *mp = *q.mp; mpq_init(q.mp); }
   1798 #endif
   1799   template <class T>
   1800   __gmp_expr(const __gmp_expr<mpz_t, T> &expr)
   1801   { mpq_init(mp); __gmp_set_expr(mp, expr); }
   1802   template <class T>
   1803   __gmp_expr(const __gmp_expr<mpq_t, T> &expr)
   1804   { mpq_init(mp); __gmp_set_expr(mp, expr); }
   1805   template <class T, class U>
   1806   explicit __gmp_expr(const __gmp_expr<T, U> &expr)
   1807   { mpq_init(mp); __gmp_set_expr(mp, expr); }
   1808 
   1809   __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS
   1810 
   1811   explicit __gmp_expr(const char *s, int base = 0)
   1812   {
   1813     mpq_init (mp);
   1814     // If s is the literal 0, we meant to call another constructor.
   1815     // If s just happens to evaluate to 0, we would crash, so whatever.
   1816     if (s == 0)
   1817       {
   1818 	// Don't turn mpq_class(0,0) into 0
   1819 	mpz_set_si(mpq_denref(mp), base);
   1820       }
   1821     else if (mpq_set_str(mp, s, base) != 0)
   1822       {
   1823         mpq_clear (mp);
   1824         throw std::invalid_argument ("mpq_set_str");
   1825       }
   1826   }
   1827   explicit __gmp_expr(const std::string &s, int base = 0)
   1828   {
   1829     mpq_init(mp);
   1830     if (mpq_set_str (mp, s.c_str(), base) != 0)
   1831       {
   1832         mpq_clear (mp);
   1833         throw std::invalid_argument ("mpq_set_str");
   1834       }
   1835   }
   1836   explicit __gmp_expr(mpq_srcptr q)
   1837   {
   1838     mpz_init_set(mpq_numref(mp), mpq_numref(q));
   1839     mpz_init_set(mpq_denref(mp), mpq_denref(q));
   1840   }
   1841 
   1842   __gmp_expr(const mpz_class &num, const mpz_class &den)
   1843   {
   1844     mpz_init_set(mpq_numref(mp), num.get_mpz_t());
   1845     mpz_init_set(mpq_denref(mp), den.get_mpz_t());
   1846   }
   1847 
   1848   ~__gmp_expr() { mpq_clear(mp); }
   1849 
   1850   void swap(__gmp_expr& q) __GMPXX_NOEXCEPT { std::swap(*mp, *q.mp); }
   1851 
   1852   // assignment operators
   1853   __gmp_expr & operator=(const __gmp_expr &q)
   1854   { mpq_set(mp, q.mp); return *this; }
   1855 #if __GMPXX_USE_CXX11
   1856   __gmp_expr & operator=(__gmp_expr &&q) noexcept
   1857   { swap(q); return *this; }
   1858   __gmp_expr & operator=(mpz_class &&z) noexcept
   1859   { get_num() = std::move(z); get_den() = 1u; return *this; }
   1860 #endif
   1861   template <class T, class U>
   1862   __gmp_expr<value_type, value_type> & operator=(const __gmp_expr<T, U> &expr)
   1863   { __gmp_set_expr(mp, expr); return *this; }
   1864 
   1865   __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS
   1866 
   1867   __gmp_expr & operator=(const char *s)
   1868   {
   1869     if (mpq_set_str (mp, s, 0) != 0)
   1870       throw std::invalid_argument ("mpq_set_str");
   1871     return *this;
   1872   }
   1873   __gmp_expr & operator=(const std::string &s)
   1874   {
   1875     if (mpq_set_str(mp, s.c_str(), 0) != 0)
   1876       throw std::invalid_argument ("mpq_set_str");
   1877     return *this;
   1878   }
   1879 
   1880   // string input/output functions
   1881   int set_str(const char *s, int base)
   1882   { return mpq_set_str(mp, s, base); }
   1883   int set_str(const std::string &s, int base)
   1884   { return mpq_set_str(mp, s.c_str(), base); }
   1885   std::string get_str(int base = 10) const
   1886   {
   1887     __gmp_alloc_cstring temp(mpq_get_str(0, base, mp));
   1888     return std::string(temp.str);
   1889   }
   1890 
   1891   // conversion functions
   1892 
   1893   // casting a reference to an mpz_t to mpz_class & is a dirty hack,
   1894   // but works because the internal representation of mpz_class is
   1895   // exactly an mpz_t
   1896   const mpz_class & get_num() const
   1897   { return reinterpret_cast<const mpz_class &>(*mpq_numref(mp)); }
   1898   mpz_class & get_num()
   1899   { return reinterpret_cast<mpz_class &>(*mpq_numref(mp)); }
   1900   const mpz_class & get_den() const
   1901   { return reinterpret_cast<const mpz_class &>(*mpq_denref(mp)); }
   1902   mpz_class & get_den()
   1903   { return reinterpret_cast<mpz_class &>(*mpq_denref(mp)); }
   1904 
   1905   mpq_srcptr __get_mp() const { return mp; }
   1906   mpq_ptr __get_mp() { return mp; }
   1907   mpq_srcptr get_mpq_t() const { return mp; }
   1908   mpq_ptr get_mpq_t() { return mp; }
   1909 
   1910   mpz_srcptr get_num_mpz_t() const { return mpq_numref(mp); }
   1911   mpz_ptr get_num_mpz_t() { return mpq_numref(mp); }
   1912   mpz_srcptr get_den_mpz_t() const { return mpq_denref(mp); }
   1913   mpz_ptr get_den_mpz_t() { return mpq_denref(mp); }
   1914 
   1915   double get_d() const { return mpq_get_d(mp); }
   1916 
   1917 #if __GMPXX_USE_CXX11
   1918   explicit operator bool() const { return mpq_numref(mp)->_mp_size != 0; }
   1919 #endif
   1920 
   1921   // compound assignments
   1922   __GMP_DECLARE_COMPOUND_OPERATOR(operator+=)
   1923   __GMP_DECLARE_COMPOUND_OPERATOR(operator-=)
   1924   __GMP_DECLARE_COMPOUND_OPERATOR(operator*=)
   1925   __GMP_DECLARE_COMPOUND_OPERATOR(operator/=)
   1926 
   1927   __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=)
   1928   __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=)
   1929 
   1930   __GMP_DECLARE_INCREMENT_OPERATOR(operator++)
   1931   __GMP_DECLARE_INCREMENT_OPERATOR(operator--)
   1932 };
   1933 
   1934 typedef __gmp_expr<mpq_t, mpq_t> mpq_class;
   1935 
   1936 
   1937 /**************** mpf_class -- wrapper for mpf_t ****************/
   1938 
   1939 template <>
   1940 class __gmp_expr<mpf_t, mpf_t>
   1941 {
   1942 private:
   1943   typedef mpf_t value_type;
   1944   value_type mp;
   1945 
   1946   // Helper functions used for all arithmetic types
   1947   void assign_ui(unsigned long l) { mpf_set_ui(mp, l); }
   1948   void assign_si(signed long l)
   1949   {
   1950     if (__GMPXX_CONSTANT_TRUE(l >= 0))
   1951       assign_ui(l);
   1952     else
   1953       mpf_set_si(mp, l);
   1954   }
   1955   void assign_d (double d)        { mpf_set_d (mp, d); }
   1956 
   1957   void init_ui(unsigned long l)
   1958   {
   1959     if (__GMPXX_CONSTANT_TRUE(l == 0))
   1960       mpf_init(mp);
   1961     else
   1962       mpf_init_set_ui(mp, l);
   1963   }
   1964   void init_si(signed long l)
   1965   {
   1966     if (__GMPXX_CONSTANT_TRUE(l >= 0))
   1967       init_ui(l);
   1968     else
   1969       mpf_init_set_si(mp, l);
   1970   }
   1971   void init_d (double d)	{ mpf_init_set_d (mp, d); }
   1972 
   1973 public:
   1974   mp_bitcnt_t get_prec() const { return mpf_get_prec(mp); }
   1975 
   1976   void set_prec(mp_bitcnt_t prec) { mpf_set_prec(mp, prec); }
   1977   void set_prec_raw(mp_bitcnt_t prec) { mpf_set_prec_raw(mp, prec); }
   1978 
   1979   // constructors and destructor
   1980   __gmp_expr() { mpf_init(mp); }
   1981 
   1982   __gmp_expr(const __gmp_expr &f)
   1983   { mpf_init2(mp, f.get_prec()); mpf_set(mp, f.mp); }
   1984 #if __GMPXX_USE_CXX11
   1985   __gmp_expr(__gmp_expr &&f)
   1986   { *mp = *f.mp; mpf_init2(f.mp, get_prec()); }
   1987 #endif
   1988   __gmp_expr(const __gmp_expr &f, mp_bitcnt_t prec)
   1989   { mpf_init2(mp, prec); mpf_set(mp, f.mp); }
   1990   template <class T, class U>
   1991   __gmp_expr(const __gmp_expr<T, U> &expr)
   1992   { mpf_init2(mp, expr.get_prec()); __gmp_set_expr(mp, expr); }
   1993   template <class T, class U>
   1994   __gmp_expr(const __gmp_expr<T, U> &expr, mp_bitcnt_t prec)
   1995   { mpf_init2(mp, prec); __gmp_set_expr(mp, expr); }
   1996 
   1997   __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS
   1998 
   1999   __gmp_expr(signed char c, mp_bitcnt_t prec)
   2000   { mpf_init2(mp, prec); mpf_set_si(mp, c); }
   2001   __gmp_expr(unsigned char c, mp_bitcnt_t prec)
   2002   { mpf_init2(mp, prec); mpf_set_ui(mp, c); }
   2003 
   2004   __gmp_expr(signed int i, mp_bitcnt_t prec)
   2005   { mpf_init2(mp, prec); mpf_set_si(mp, i); }
   2006   __gmp_expr(unsigned int i, mp_bitcnt_t prec)
   2007   { mpf_init2(mp, prec); mpf_set_ui(mp, i); }
   2008 
   2009   __gmp_expr(signed short int s, mp_bitcnt_t prec)
   2010   { mpf_init2(mp, prec); mpf_set_si(mp, s); }
   2011   __gmp_expr(unsigned short int s, mp_bitcnt_t prec)
   2012   { mpf_init2(mp, prec); mpf_set_ui(mp, s); }
   2013 
   2014   __gmp_expr(signed long int l, mp_bitcnt_t prec)
   2015   { mpf_init2(mp, prec); mpf_set_si(mp, l); }
   2016   __gmp_expr(unsigned long int l, mp_bitcnt_t prec)
   2017   { mpf_init2(mp, prec); mpf_set_ui(mp, l); }
   2018 
   2019   __gmp_expr(float f, mp_bitcnt_t prec)
   2020   { mpf_init2(mp, prec); mpf_set_d(mp, f); }
   2021   __gmp_expr(double d, mp_bitcnt_t prec)
   2022   { mpf_init2(mp, prec); mpf_set_d(mp, d); }
   2023   // __gmp_expr(long double ld) { mpf_init_set_d(mp, ld); }
   2024   // __gmp_expr(long double ld, mp_bitcnt_t prec)
   2025   // { mpf_init2(mp, prec); mpf_set_d(mp, ld); }
   2026 
   2027   explicit __gmp_expr(const char *s)
   2028   {
   2029     if (mpf_init_set_str (mp, s, 0) != 0)
   2030       {
   2031         mpf_clear (mp);
   2032         throw std::invalid_argument ("mpf_set_str");
   2033       }
   2034   }
   2035   __gmp_expr(const char *s, mp_bitcnt_t prec, int base = 0)
   2036   {
   2037     mpf_init2(mp, prec);
   2038     if (mpf_set_str(mp, s, base) != 0)
   2039       {
   2040         mpf_clear (mp);
   2041         throw std::invalid_argument ("mpf_set_str");
   2042       }
   2043   }
   2044   explicit __gmp_expr(const std::string &s)
   2045   {
   2046     if (mpf_init_set_str(mp, s.c_str(), 0) != 0)
   2047       {
   2048         mpf_clear (mp);
   2049         throw std::invalid_argument ("mpf_set_str");
   2050       }
   2051   }
   2052   __gmp_expr(const std::string &s, mp_bitcnt_t prec, int base = 0)
   2053   {
   2054     mpf_init2(mp, prec);
   2055     if (mpf_set_str(mp, s.c_str(), base) != 0)
   2056       {
   2057         mpf_clear (mp);
   2058         throw std::invalid_argument ("mpf_set_str");
   2059       }
   2060   }
   2061 
   2062   explicit __gmp_expr(mpf_srcptr f)
   2063   { mpf_init2(mp, mpf_get_prec(f)); mpf_set(mp, f); }
   2064   __gmp_expr(mpf_srcptr f, mp_bitcnt_t prec)
   2065   { mpf_init2(mp, prec); mpf_set(mp, f); }
   2066 
   2067   ~__gmp_expr() { mpf_clear(mp); }
   2068 
   2069   void swap(__gmp_expr& f) __GMPXX_NOEXCEPT { std::swap(*mp, *f.mp); }
   2070 
   2071   // assignment operators
   2072   __gmp_expr & operator=(const __gmp_expr &f)
   2073   { mpf_set(mp, f.mp); return *this; }
   2074 #if __GMPXX_USE_CXX11
   2075   __gmp_expr & operator=(__gmp_expr &&f) noexcept
   2076   { swap(f); return *this; }
   2077 #endif
   2078   template <class T, class U>
   2079   __gmp_expr<value_type, value_type> & operator=(const __gmp_expr<T, U> &expr)
   2080   { __gmp_set_expr(mp, expr); return *this; }
   2081 
   2082   __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS
   2083 
   2084   __gmp_expr & operator=(const char *s)
   2085   {
   2086     if (mpf_set_str (mp, s, 0) != 0)
   2087       throw std::invalid_argument ("mpf_set_str");
   2088     return *this;
   2089   }
   2090   __gmp_expr & operator=(const std::string &s)
   2091   {
   2092     if (mpf_set_str(mp, s.c_str(), 0) != 0)
   2093       throw std::invalid_argument ("mpf_set_str");
   2094     return *this;
   2095   }
   2096 
   2097   // string input/output functions
   2098   int set_str(const char *s, int base)
   2099   { return mpf_set_str(mp, s, base); }
   2100   int set_str(const std::string &s, int base)
   2101   { return mpf_set_str(mp, s.c_str(), base); }
   2102   std::string get_str(mp_exp_t &expo, int base = 10, size_t size = 0) const
   2103   {
   2104     __gmp_alloc_cstring temp(mpf_get_str(0, &expo, base, size, mp));
   2105     return std::string(temp.str);
   2106   }
   2107 
   2108   // conversion functions
   2109   mpf_srcptr __get_mp() const { return mp; }
   2110   mpf_ptr __get_mp() { return mp; }
   2111   mpf_srcptr get_mpf_t() const { return mp; }
   2112   mpf_ptr get_mpf_t() { return mp; }
   2113 
   2114   signed long int get_si() const { return mpf_get_si(mp); }
   2115   unsigned long int get_ui() const { return mpf_get_ui(mp); }
   2116   double get_d() const { return mpf_get_d(mp); }
   2117 
   2118   // bool fits_schar_p() const { return mpf_fits_schar_p(mp); }
   2119   // bool fits_uchar_p() const { return mpf_fits_uchar_p(mp); }
   2120   bool fits_sint_p() const { return mpf_fits_sint_p(mp); }
   2121   bool fits_uint_p() const { return mpf_fits_uint_p(mp); }
   2122   bool fits_sshort_p() const { return mpf_fits_sshort_p(mp); }
   2123   bool fits_ushort_p() const { return mpf_fits_ushort_p(mp); }
   2124   bool fits_slong_p() const { return mpf_fits_slong_p(mp); }
   2125   bool fits_ulong_p() const { return mpf_fits_ulong_p(mp); }
   2126   // bool fits_float_p() const { return mpf_fits_float_p(mp); }
   2127   // bool fits_double_p() const { return mpf_fits_double_p(mp); }
   2128   // bool fits_ldouble_p() const { return mpf_fits_ldouble_p(mp); }
   2129 
   2130 #if __GMPXX_USE_CXX11
   2131   explicit operator bool() const { return mpf_sgn(mp) != 0; }
   2132 #endif
   2133 
   2134   // compound assignments
   2135   __GMP_DECLARE_COMPOUND_OPERATOR(operator+=)
   2136   __GMP_DECLARE_COMPOUND_OPERATOR(operator-=)
   2137   __GMP_DECLARE_COMPOUND_OPERATOR(operator*=)
   2138   __GMP_DECLARE_COMPOUND_OPERATOR(operator/=)
   2139 
   2140   __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=)
   2141   __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=)
   2142 
   2143   __GMP_DECLARE_INCREMENT_OPERATOR(operator++)
   2144   __GMP_DECLARE_INCREMENT_OPERATOR(operator--)
   2145 };
   2146 
   2147 typedef __gmp_expr<mpf_t, mpf_t> mpf_class;
   2148 
   2149 
   2150 
   2151 /**************** User-defined literals ****************/
   2152 
   2153 #if __GMPXX_USE_CXX11
   2154 inline mpz_class operator"" _mpz(const char* s)
   2155 {
   2156   return mpz_class(s);
   2157 }
   2158 
   2159 inline mpq_class operator"" _mpq(const char* s)
   2160 {
   2161   mpq_class q;
   2162   q.get_num() = s;
   2163   return q;
   2164 }
   2165 
   2166 inline mpf_class operator"" _mpf(const char* s)
   2167 {
   2168   return mpf_class(s);
   2169 }
   2170 #endif
   2171 
   2172 /**************** I/O operators ****************/
   2173 
   2174 // these should (and will) be provided separately
   2175 
   2176 template <class T, class U>
   2177 inline std::ostream & operator<<
   2178 (std::ostream &o, const __gmp_expr<T, U> &expr)
   2179 {
   2180   __gmp_expr<T, T> const& temp(expr);
   2181   return o << temp.__get_mp();
   2182 }
   2183 
   2184 template <class T>
   2185 inline std::istream & operator>>(std::istream &i, __gmp_expr<T, T> &expr)
   2186 {
   2187   return i >> expr.__get_mp();
   2188 }
   2189 
   2190 /*
   2191 // you might want to uncomment this
   2192 inline std::istream & operator>>(std::istream &i, mpq_class &q)
   2193 {
   2194   i >> q.get_mpq_t();
   2195   q.canonicalize();
   2196   return i;
   2197 }
   2198 */
   2199 
   2200 
   2201 /**************** Functions for type conversion ****************/
   2202 
   2203 inline void __gmp_set_expr(mpz_ptr z, const mpz_class &w)
   2204 {
   2205   mpz_set(z, w.get_mpz_t());
   2206 }
   2207 
   2208 template <class T>
   2209 inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr<mpz_t, T> &expr)
   2210 {
   2211   expr.eval(z);
   2212 }
   2213 
   2214 template <class T>
   2215 inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr<mpq_t, T> &expr)
   2216 {
   2217   mpq_class const& temp(expr);
   2218   mpz_set_q(z, temp.get_mpq_t());
   2219 }
   2220 
   2221 template <class T>
   2222 inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr<mpf_t, T> &expr)
   2223 {
   2224   mpf_class const& temp(expr);
   2225   mpz_set_f(z, temp.get_mpf_t());
   2226 }
   2227 
   2228 inline void __gmp_set_expr(mpq_ptr q, const mpz_class &z)
   2229 {
   2230   mpq_set_z(q, z.get_mpz_t());
   2231 }
   2232 
   2233 template <class T>
   2234 inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr<mpz_t, T> &expr)
   2235 {
   2236   __gmp_set_expr(mpq_numref(q), expr);
   2237   mpz_set_ui(mpq_denref(q), 1);
   2238 }
   2239 
   2240 inline void __gmp_set_expr(mpq_ptr q, const mpq_class &r)
   2241 {
   2242   mpq_set(q, r.get_mpq_t());
   2243 }
   2244 
   2245 template <class T>
   2246 inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr<mpq_t, T> &expr)
   2247 {
   2248   expr.eval(q);
   2249 }
   2250 
   2251 template <class T>
   2252 inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr<mpf_t, T> &expr)
   2253 {
   2254   mpf_class const& temp(expr);
   2255   mpq_set_f(q, temp.get_mpf_t());
   2256 }
   2257 
   2258 template <class T>
   2259 inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr<mpz_t, T> &expr)
   2260 {
   2261   mpz_class const& temp(expr);
   2262   mpf_set_z(f, temp.get_mpz_t());
   2263 }
   2264 
   2265 template <class T>
   2266 inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr<mpq_t, T> &expr)
   2267 {
   2268   mpq_class const& temp(expr);
   2269   mpf_set_q(f, temp.get_mpq_t());
   2270 }
   2271 
   2272 inline void __gmp_set_expr(mpf_ptr f, const mpf_class &g)
   2273 {
   2274   mpf_set(f, g.get_mpf_t());
   2275 }
   2276 
   2277 template <class T>
   2278 inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr<mpf_t, T> &expr)
   2279 {
   2280   expr.eval(f);
   2281 }
   2282 
   2283 
   2284 /* Temporary objects */
   2285 
   2286 template <class T>
   2287 class __gmp_temp
   2288 {
   2289   __gmp_expr<T, T> val;
   2290   public:
   2291   template<class U, class V>
   2292   __gmp_temp(U const& u, V) : val (u) {}
   2293   typename __gmp_resolve_expr<T>::srcptr_type
   2294   __get_mp() const { return val.__get_mp(); }
   2295 };
   2296 
   2297 template <>
   2298 class __gmp_temp <mpf_t>
   2299 {
   2300   mpf_class val;
   2301   public:
   2302   template<class U>
   2303   __gmp_temp(U const& u, mpf_ptr res) : val (u, mpf_get_prec(res)) {}
   2304   mpf_srcptr __get_mp() const { return val.__get_mp(); }
   2305 };
   2306 
   2307 /**************** Specializations of __gmp_expr ****************/
   2308 /* The eval() method of __gmp_expr<T, U> evaluates the corresponding
   2309    expression and assigns the result to its argument, which is either an
   2310    mpz_t, mpq_t, or mpf_t as specified by the T argument.
   2311    Compound expressions are evaluated recursively (temporaries are created
   2312    to hold intermediate values), while for simple expressions the eval()
   2313    method of the appropriate function object (available as the Op argument
   2314    of either __gmp_unary_expr<T, Op> or __gmp_binary_expr<T, U, Op>) is
   2315    called. */
   2316 
   2317 
   2318 /**************** Unary expressions ****************/
   2319 /* cases:
   2320    - simple:   argument is mp*_class, that is, __gmp_expr<T, T>
   2321    - compound: argument is __gmp_expr<T, U> (with U not equal to T) */
   2322 
   2323 
   2324 // simple expressions
   2325 
   2326 template <class T, class Op>
   2327 class __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, T>, Op> >
   2328 {
   2329 private:
   2330   typedef __gmp_expr<T, T> val_type;
   2331 
   2332   __gmp_unary_expr<val_type, Op> expr;
   2333 public:
   2334   explicit __gmp_expr(const val_type &val) : expr(val) { }
   2335   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
   2336   { Op::eval(p, expr.val.__get_mp()); }
   2337   const val_type & get_val() const { return expr.val; }
   2338   mp_bitcnt_t get_prec() const { return expr.val.get_prec(); }
   2339 };
   2340 
   2341 
   2342 // simple expressions, U is a built-in numerical type
   2343 
   2344 template <class T, class U, class Op>
   2345 class __gmp_expr<T, __gmp_unary_expr<U, Op> >
   2346 {
   2347 private:
   2348   typedef U val_type;
   2349 
   2350   __gmp_unary_expr<val_type, Op> expr;
   2351 public:
   2352   explicit __gmp_expr(const val_type &val) : expr(val) { }
   2353   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
   2354   { Op::eval(p, expr.val); }
   2355   const val_type & get_val() const { return expr.val; }
   2356   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }
   2357 };
   2358 
   2359 
   2360 // compound expressions
   2361 
   2362 template <class T, class U, class Op>
   2363 class __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, Op> >
   2364 {
   2365 private:
   2366   typedef __gmp_expr<T, U> val_type;
   2367 
   2368   __gmp_unary_expr<val_type, Op> expr;
   2369 public:
   2370   explicit __gmp_expr(const val_type &val) : expr(val) { }
   2371   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
   2372   { expr.val.eval(p); Op::eval(p, p); }
   2373   const val_type & get_val() const { return expr.val; }
   2374   mp_bitcnt_t get_prec() const { return expr.val.get_prec(); }
   2375 };
   2376 
   2377 
   2378 /**************** Binary expressions ****************/
   2379 /* simple:
   2380    - arguments are both mp*_class
   2381    - one argument is mp*_class, one is a built-in type
   2382    compound:
   2383    - one is mp*_class, one is __gmp_expr<T, U>
   2384    - one is __gmp_expr<T, U>, one is built-in
   2385    - both arguments are __gmp_expr<...> */
   2386 
   2387 
   2388 // simple expressions
   2389 
   2390 template <class T, class Op>
   2391 class __gmp_expr
   2392 <T, __gmp_binary_expr<__gmp_expr<T, T>, __gmp_expr<T, T>, Op> >
   2393 {
   2394 private:
   2395   typedef __gmp_expr<T, T> val1_type;
   2396   typedef __gmp_expr<T, T> val2_type;
   2397 
   2398   __gmp_binary_expr<val1_type, val2_type, Op> expr;
   2399 public:
   2400   __gmp_expr(const val1_type &val1, const val2_type &val2)
   2401     : expr(val1, val2) { }
   2402   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
   2403   { Op::eval(p, expr.val1.__get_mp(), expr.val2.__get_mp()); }
   2404   const val1_type & get_val1() const { return expr.val1; }
   2405   const val2_type & get_val2() const { return expr.val2; }
   2406   mp_bitcnt_t get_prec() const
   2407   {
   2408     mp_bitcnt_t prec1 = expr.val1.get_prec(),
   2409       prec2 = expr.val2.get_prec();
   2410     return (prec1 > prec2) ? prec1 : prec2;
   2411   }
   2412 };
   2413 
   2414 
   2415 // simple expressions, U is a built-in numerical type
   2416 
   2417 template <class T, class U, class Op>
   2418 class __gmp_expr<T, __gmp_binary_expr<__gmp_expr<T, T>, U, Op> >
   2419 {
   2420 private:
   2421   typedef __gmp_expr<T, T> val1_type;
   2422   typedef U val2_type;
   2423 
   2424   __gmp_binary_expr<val1_type, val2_type, Op> expr;
   2425 public:
   2426   __gmp_expr(const val1_type &val1, const val2_type &val2)
   2427     : expr(val1, val2) { }
   2428   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
   2429   { Op::eval(p, expr.val1.__get_mp(), expr.val2); }
   2430   const val1_type & get_val1() const { return expr.val1; }
   2431   const val2_type & get_val2() const { return expr.val2; }
   2432   mp_bitcnt_t get_prec() const { return expr.val1.get_prec(); }
   2433 };
   2434 
   2435 template <class T, class U, class Op>
   2436 class __gmp_expr<T, __gmp_binary_expr<U, __gmp_expr<T, T>, Op> >
   2437 {
   2438 private:
   2439   typedef U val1_type;
   2440   typedef __gmp_expr<T, T> val2_type;
   2441 
   2442   __gmp_binary_expr<val1_type, val2_type, Op> expr;
   2443 public:
   2444   __gmp_expr(const val1_type &val1, const val2_type &val2)
   2445     : expr(val1, val2) { }
   2446   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
   2447   { Op::eval(p, expr.val1, expr.val2.__get_mp()); }
   2448   const val1_type & get_val1() const { return expr.val1; }
   2449   const val2_type & get_val2() const { return expr.val2; }
   2450   mp_bitcnt_t get_prec() const { return expr.val2.get_prec(); }
   2451 };
   2452 
   2453 
   2454 // compound expressions, one argument is a subexpression
   2455 
   2456 template <class T, class U, class V, class Op>
   2457 class __gmp_expr
   2458 <T, __gmp_binary_expr<__gmp_expr<T, T>, __gmp_expr<U, V>, Op> >
   2459 {
   2460 private:
   2461   typedef __gmp_expr<T, T> val1_type;
   2462   typedef __gmp_expr<U, V> val2_type;
   2463 
   2464   __gmp_binary_expr<val1_type, val2_type, Op> expr;
   2465 public:
   2466   __gmp_expr(const val1_type &val1, const val2_type &val2)
   2467     : expr(val1, val2) { }
   2468   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
   2469   {
   2470     if(p != expr.val1.__get_mp())
   2471     {
   2472       __gmp_set_expr(p, expr.val2);
   2473       Op::eval(p, expr.val1.__get_mp(), p);
   2474     }
   2475     else
   2476     {
   2477       __gmp_temp<T> temp(expr.val2, p);
   2478       Op::eval(p, expr.val1.__get_mp(), temp.__get_mp());
   2479     }
   2480   }
   2481   const val1_type & get_val1() const { return expr.val1; }
   2482   const val2_type & get_val2() const { return expr.val2; }
   2483   mp_bitcnt_t get_prec() const
   2484   {
   2485     mp_bitcnt_t prec1 = expr.val1.get_prec(),
   2486       prec2 = expr.val2.get_prec();
   2487     return (prec1 > prec2) ? prec1 : prec2;
   2488   }
   2489 };
   2490 
   2491 template <class T, class U, class V, class Op>
   2492 class __gmp_expr
   2493 <T, __gmp_binary_expr<__gmp_expr<U, V>, __gmp_expr<T, T>, Op> >
   2494 {
   2495 private:
   2496   typedef __gmp_expr<U, V> val1_type;
   2497   typedef __gmp_expr<T, T> val2_type;
   2498 
   2499   __gmp_binary_expr<val1_type, val2_type, Op> expr;
   2500 public:
   2501   __gmp_expr(const val1_type &val1, const val2_type &val2)
   2502     : expr(val1, val2) { }
   2503   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
   2504   {
   2505     if(p != expr.val2.__get_mp())
   2506     {
   2507       __gmp_set_expr(p, expr.val1);
   2508       Op::eval(p, p, expr.val2.__get_mp());
   2509     }
   2510     else
   2511     {
   2512       __gmp_temp<T> temp(expr.val1, p);
   2513       Op::eval(p, temp.__get_mp(), expr.val2.__get_mp());
   2514     }
   2515   }
   2516   const val1_type & get_val1() const { return expr.val1; }
   2517   const val2_type & get_val2() const { return expr.val2; }
   2518   mp_bitcnt_t get_prec() const
   2519   {
   2520     mp_bitcnt_t prec1 = expr.val1.get_prec(),
   2521       prec2 = expr.val2.get_prec();
   2522     return (prec1 > prec2) ? prec1 : prec2;
   2523   }
   2524 };
   2525 
   2526 template <class T, class U, class Op>
   2527 class __gmp_expr
   2528 <T, __gmp_binary_expr<__gmp_expr<T, T>, __gmp_expr<T, U>, Op> >
   2529 {
   2530 private:
   2531   typedef __gmp_expr<T, T> val1_type;
   2532   typedef __gmp_expr<T, U> val2_type;
   2533 
   2534   __gmp_binary_expr<val1_type, val2_type, Op> expr;
   2535 public:
   2536   __gmp_expr(const val1_type &val1, const val2_type &val2)
   2537     : expr(val1, val2) { }
   2538   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
   2539   {
   2540     if(p != expr.val1.__get_mp())
   2541     {
   2542       __gmp_set_expr(p, expr.val2);
   2543       Op::eval(p, expr.val1.__get_mp(), p);
   2544     }
   2545     else
   2546     {
   2547       __gmp_temp<T> temp(expr.val2, p);
   2548       Op::eval(p, expr.val1.__get_mp(), temp.__get_mp());
   2549     }
   2550   }
   2551   const val1_type & get_val1() const { return expr.val1; }
   2552   const val2_type & get_val2() const { return expr.val2; }
   2553   mp_bitcnt_t get_prec() const
   2554   {
   2555     mp_bitcnt_t prec1 = expr.val1.get_prec(),
   2556       prec2 = expr.val2.get_prec();
   2557     return (prec1 > prec2) ? prec1 : prec2;
   2558   }
   2559 };
   2560 
   2561 template <class T, class U, class Op>
   2562 class __gmp_expr
   2563 <T, __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<T, T>, Op> >
   2564 {
   2565 private:
   2566   typedef __gmp_expr<T, U> val1_type;
   2567   typedef __gmp_expr<T, T> val2_type;
   2568 
   2569   __gmp_binary_expr<val1_type, val2_type, Op> expr;
   2570 public:
   2571   __gmp_expr(const val1_type &val1, const val2_type &val2)
   2572     : expr(val1, val2) { }
   2573   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
   2574   {
   2575     if(p != expr.val2.__get_mp())
   2576     {
   2577       __gmp_set_expr(p, expr.val1);
   2578       Op::eval(p, p, expr.val2.__get_mp());
   2579     }
   2580     else
   2581     {
   2582       __gmp_temp<T> temp(expr.val1, p);
   2583       Op::eval(p, temp.__get_mp(), expr.val2.__get_mp());
   2584     }
   2585   }
   2586   const val1_type & get_val1() const { return expr.val1; }
   2587   const val2_type & get_val2() const { return expr.val2; }
   2588   mp_bitcnt_t get_prec() const
   2589   {
   2590     mp_bitcnt_t prec1 = expr.val1.get_prec(),
   2591       prec2 = expr.val2.get_prec();
   2592     return (prec1 > prec2) ? prec1 : prec2;
   2593   }
   2594 };
   2595 
   2596 
   2597 // one argument is a subexpression, one is a built-in
   2598 
   2599 template <class T, class U, class V, class Op>
   2600 class __gmp_expr<T, __gmp_binary_expr<__gmp_expr<T, U>, V, Op> >
   2601 {
   2602 private:
   2603   typedef __gmp_expr<T, U> val1_type;
   2604   typedef V val2_type;
   2605 
   2606   __gmp_binary_expr<val1_type, val2_type, Op> expr;
   2607 public:
   2608   __gmp_expr(const val1_type &val1, const val2_type &val2)
   2609     : expr(val1, val2) { }
   2610   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
   2611   {
   2612     expr.val1.eval(p);
   2613     Op::eval(p, p, expr.val2);
   2614   }
   2615   const val1_type & get_val1() const { return expr.val1; }
   2616   const val2_type & get_val2() const { return expr.val2; }
   2617   mp_bitcnt_t get_prec() const { return expr.val1.get_prec(); }
   2618 };
   2619 
   2620 template <class T, class U, class V, class Op>
   2621 class __gmp_expr<T, __gmp_binary_expr<U, __gmp_expr<T, V>, Op> >
   2622 {
   2623 private:
   2624   typedef U val1_type;
   2625   typedef __gmp_expr<T, V> val2_type;
   2626 
   2627   __gmp_binary_expr<val1_type, val2_type, Op> expr;
   2628 public:
   2629   __gmp_expr(const val1_type &val1, const val2_type &val2)
   2630     : expr(val1, val2) { }
   2631   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
   2632   {
   2633     expr.val2.eval(p);
   2634     Op::eval(p, expr.val1, p);
   2635   }
   2636   const val1_type & get_val1() const { return expr.val1; }
   2637   const val2_type & get_val2() const { return expr.val2; }
   2638   mp_bitcnt_t get_prec() const { return expr.val2.get_prec(); }
   2639 };
   2640 
   2641 
   2642 // both arguments are subexpressions
   2643 
   2644 template <class T, class U, class V, class W, class Op>
   2645 class __gmp_expr
   2646 <T, __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, Op> >
   2647 {
   2648 private:
   2649   typedef __gmp_expr<T, U> val1_type;
   2650   typedef __gmp_expr<V, W> val2_type;
   2651 
   2652   __gmp_binary_expr<val1_type, val2_type, Op> expr;
   2653 public:
   2654   __gmp_expr(const val1_type &val1, const val2_type &val2)
   2655     : expr(val1, val2) { }
   2656   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
   2657   {
   2658     __gmp_temp<T> temp2(expr.val2, p);
   2659     expr.val1.eval(p);
   2660     Op::eval(p, p, temp2.__get_mp());
   2661   }
   2662   const val1_type & get_val1() const { return expr.val1; }
   2663   const val2_type & get_val2() const { return expr.val2; }
   2664   mp_bitcnt_t get_prec() const
   2665   {
   2666     mp_bitcnt_t prec1 = expr.val1.get_prec(),
   2667       prec2 = expr.val2.get_prec();
   2668     return (prec1 > prec2) ? prec1 : prec2;
   2669   }
   2670 };
   2671 
   2672 template <class T, class U, class V, class W, class Op>
   2673 class __gmp_expr
   2674 <T, __gmp_binary_expr<__gmp_expr<U, V>, __gmp_expr<T, W>, Op> >
   2675 {
   2676 private:
   2677   typedef __gmp_expr<U, V> val1_type;
   2678   typedef __gmp_expr<T, W> val2_type;
   2679 
   2680   __gmp_binary_expr<val1_type, val2_type, Op> expr;
   2681 public:
   2682   __gmp_expr(const val1_type &val1, const val2_type &val2)
   2683     : expr(val1, val2) { }
   2684   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
   2685   {
   2686     __gmp_temp<T> temp1(expr.val1, p);
   2687     expr.val2.eval(p);
   2688     Op::eval(p, temp1.__get_mp(), p);
   2689   }
   2690   const val1_type & get_val1() const { return expr.val1; }
   2691   const val2_type & get_val2() const { return expr.val2; }
   2692   mp_bitcnt_t get_prec() const
   2693   {
   2694     mp_bitcnt_t prec1 = expr.val1.get_prec(),
   2695       prec2 = expr.val2.get_prec();
   2696     return (prec1 > prec2) ? prec1 : prec2;
   2697   }
   2698 };
   2699 
   2700 template <class T, class U, class V, class Op>
   2701 class __gmp_expr
   2702 <T, __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<T, V>, Op> >
   2703 {
   2704 private:
   2705   typedef __gmp_expr<T, U> val1_type;
   2706   typedef __gmp_expr<T, V> val2_type;
   2707 
   2708   __gmp_binary_expr<val1_type, val2_type, Op> expr;
   2709 public:
   2710   __gmp_expr(const val1_type &val1, const val2_type &val2)
   2711     : expr(val1, val2) { }
   2712   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
   2713   {
   2714     __gmp_temp<T> temp2(expr.val2, p);
   2715     expr.val1.eval(p);
   2716     Op::eval(p, p, temp2.__get_mp());
   2717   }
   2718   const val1_type & get_val1() const { return expr.val1; }
   2719   const val2_type & get_val2() const { return expr.val2; }
   2720   mp_bitcnt_t get_prec() const
   2721   {
   2722     mp_bitcnt_t prec1 = expr.val1.get_prec(),
   2723       prec2 = expr.val2.get_prec();
   2724     return (prec1 > prec2) ? prec1 : prec2;
   2725   }
   2726 };
   2727 
   2728 
   2729 /**************** Special cases ****************/
   2730 
   2731 /* Some operations (i.e., add and subtract) with mixed mpz/mpq arguments
   2732    can be done directly without first converting the mpz to mpq.
   2733    Appropriate specializations of __gmp_expr are required. */
   2734 
   2735 
   2736 #define __GMPZQ_DEFINE_EXPR(eval_fun)                                       \
   2737                                                                             \
   2738 template <>                                                                 \
   2739 class __gmp_expr<mpq_t, __gmp_binary_expr<mpz_class, mpq_class, eval_fun> > \
   2740 {                                                                           \
   2741 private:                                                                    \
   2742   typedef mpz_class val1_type;                                              \
   2743   typedef mpq_class val2_type;                                              \
   2744                                                                             \
   2745   __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
   2746 public:                                                                     \
   2747   __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
   2748     : expr(val1, val2) { }                                                  \
   2749   void eval(mpq_ptr q) const                                                \
   2750   { eval_fun::eval(q, expr.val1.get_mpz_t(), expr.val2.get_mpq_t()); }      \
   2751   const val1_type & get_val1() const { return expr.val1; }                  \
   2752   const val2_type & get_val2() const { return expr.val2; }                  \
   2753   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }           \
   2754 };                                                                          \
   2755                                                                             \
   2756 template <>                                                                 \
   2757 class __gmp_expr<mpq_t, __gmp_binary_expr<mpq_class, mpz_class, eval_fun> > \
   2758 {                                                                           \
   2759 private:                                                                    \
   2760   typedef mpq_class val1_type;                                              \
   2761   typedef mpz_class val2_type;                                              \
   2762                                                                             \
   2763   __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
   2764 public:                                                                     \
   2765   __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
   2766     : expr(val1, val2) { }                                                  \
   2767   void eval(mpq_ptr q) const                                                \
   2768   { eval_fun::eval(q, expr.val1.get_mpq_t(), expr.val2.get_mpz_t()); }      \
   2769   const val1_type & get_val1() const { return expr.val1; }                  \
   2770   const val2_type & get_val2() const { return expr.val2; }                  \
   2771   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }           \
   2772 };                                                                          \
   2773                                                                             \
   2774 template <class T>                                                          \
   2775 class __gmp_expr                                                            \
   2776 <mpq_t, __gmp_binary_expr<mpz_class, __gmp_expr<mpq_t, T>, eval_fun> >      \
   2777 {                                                                           \
   2778 private:                                                                    \
   2779   typedef mpz_class val1_type;                                              \
   2780   typedef __gmp_expr<mpq_t, T> val2_type;                                   \
   2781                                                                             \
   2782   __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
   2783 public:                                                                     \
   2784   __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
   2785     : expr(val1, val2) { }                                                  \
   2786   void eval(mpq_ptr q) const                                                \
   2787   {                                                                         \
   2788     mpq_class temp(expr.val2);                                              \
   2789     eval_fun::eval(q, expr.val1.get_mpz_t(), temp.get_mpq_t());             \
   2790   }                                                                         \
   2791   const val1_type & get_val1() const { return expr.val1; }                  \
   2792   const val2_type & get_val2() const { return expr.val2; }                  \
   2793   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }           \
   2794 };                                                                          \
   2795                                                                             \
   2796 template <class T>                                                          \
   2797 class __gmp_expr                                                            \
   2798 <mpq_t, __gmp_binary_expr<mpq_class, __gmp_expr<mpz_t, T>, eval_fun> >      \
   2799 {                                                                           \
   2800 private:                                                                    \
   2801   typedef mpq_class val1_type;                                              \
   2802   typedef __gmp_expr<mpz_t, T> val2_type;                                   \
   2803                                                                             \
   2804   __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
   2805 public:                                                                     \
   2806   __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
   2807     : expr(val1, val2) { }                                                  \
   2808   void eval(mpq_ptr q) const                                                \
   2809   {                                                                         \
   2810     mpz_class temp(expr.val2);                                              \
   2811     eval_fun::eval(q, expr.val1.get_mpq_t(), temp.get_mpz_t());             \
   2812   }                                                                         \
   2813   const val1_type & get_val1() const { return expr.val1; }                  \
   2814   const val2_type & get_val2() const { return expr.val2; }                  \
   2815   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }           \
   2816 };                                                                          \
   2817                                                                             \
   2818 template <class T>                                                          \
   2819 class __gmp_expr                                                            \
   2820 <mpq_t, __gmp_binary_expr<__gmp_expr<mpz_t, T>, mpq_class, eval_fun> >      \
   2821 {                                                                           \
   2822 private:                                                                    \
   2823   typedef __gmp_expr<mpz_t, T> val1_type;                                   \
   2824   typedef mpq_class val2_type;                                              \
   2825                                                                             \
   2826   __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
   2827 public:                                                                     \
   2828   __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
   2829     : expr(val1, val2) { }                                                  \
   2830   void eval(mpq_ptr q) const                                                \
   2831   {                                                                         \
   2832     mpz_class temp(expr.val1);                                              \
   2833     eval_fun::eval(q, temp.get_mpz_t(), expr.val2.get_mpq_t());             \
   2834   }                                                                         \
   2835   const val1_type & get_val1() const { return expr.val1; }                  \
   2836   const val2_type & get_val2() const { return expr.val2; }                  \
   2837   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }           \
   2838 };                                                                          \
   2839                                                                             \
   2840 template <class T>                                                          \
   2841 class __gmp_expr                                                            \
   2842 <mpq_t, __gmp_binary_expr<__gmp_expr<mpq_t, T>, mpz_class, eval_fun> >      \
   2843 {                                                                           \
   2844 private:                                                                    \
   2845   typedef __gmp_expr<mpq_t, T> val1_type;                                   \
   2846   typedef mpz_class val2_type;                                              \
   2847                                                                             \
   2848   __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
   2849 public:                                                                     \
   2850   __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
   2851     : expr(val1, val2) { }                                                  \
   2852   void eval(mpq_ptr q) const                                                \
   2853   {                                                                         \
   2854     mpq_class temp(expr.val1);                                              \
   2855     eval_fun::eval(q, temp.get_mpq_t(), expr.val2.get_mpz_t());             \
   2856   }                                                                         \
   2857   const val1_type & get_val1() const { return expr.val1; }                  \
   2858   const val2_type & get_val2() const { return expr.val2; }                  \
   2859   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }           \
   2860 };                                                                          \
   2861                                                                             \
   2862 template <class T, class U>                                                 \
   2863 class __gmp_expr<mpq_t, __gmp_binary_expr                                   \
   2864 <__gmp_expr<mpz_t, T>, __gmp_expr<mpq_t, U>, eval_fun> >                    \
   2865 {                                                                           \
   2866 private:                                                                    \
   2867   typedef __gmp_expr<mpz_t, T> val1_type;                                   \
   2868   typedef __gmp_expr<mpq_t, U> val2_type;                                   \
   2869                                                                             \
   2870   __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
   2871 public:                                                                     \
   2872   __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
   2873     : expr(val1, val2) { }                                                  \
   2874   void eval(mpq_ptr q) const                                                \
   2875   {                                                                         \
   2876     mpz_class temp1(expr.val1);                                             \
   2877     expr.val2.eval(q);                                                      \
   2878     eval_fun::eval(q, temp1.get_mpz_t(), q);                                \
   2879   }                                                                         \
   2880   const val1_type & get_val1() const { return expr.val1; }                  \
   2881   const val2_type & get_val2() const { return expr.val2; }                  \
   2882   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }           \
   2883 };                                                                          \
   2884                                                                             \
   2885 template <class T, class U>                                                 \
   2886 class __gmp_expr<mpq_t, __gmp_binary_expr                                   \
   2887 <__gmp_expr<mpq_t, T>, __gmp_expr<mpz_t, U>, eval_fun> >                    \
   2888 {                                                                           \
   2889 private:                                                                    \
   2890   typedef __gmp_expr<mpq_t, T> val1_type;                                   \
   2891   typedef __gmp_expr<mpz_t, U> val2_type;                                   \
   2892                                                                             \
   2893   __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
   2894 public:                                                                     \
   2895   __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
   2896     : expr(val1, val2) { }                                                  \
   2897   void eval(mpq_ptr q) const                                                \
   2898   {                                                                         \
   2899     mpz_class temp2(expr.val2);                                             \
   2900     expr.val1.eval(q);                                             \
   2901     eval_fun::eval(q, q, temp2.get_mpz_t());                \
   2902   }                                                                         \
   2903   const val1_type & get_val1() const { return expr.val1; }                  \
   2904   const val2_type & get_val2() const { return expr.val2; }                  \
   2905   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }           \
   2906 };
   2907 
   2908 
   2909 __GMPZQ_DEFINE_EXPR(__gmp_binary_plus)
   2910 __GMPZQ_DEFINE_EXPR(__gmp_binary_minus)
   2911 
   2912 
   2913 
   2914 /**************** Macros for defining functions ****************/
   2915 /* Results of operators and functions are instances of __gmp_expr<T, U>.
   2916    T determines the numerical type of the expression: it can be either
   2917    mpz_t, mpq_t, or mpf_t.  When the arguments of a binary
   2918    expression have different numerical types, __gmp_resolve_expr is used
   2919    to determine the "larger" type.
   2920    U is either __gmp_unary_expr<V, Op> or __gmp_binary_expr<V, W, Op>,
   2921    where V and W are the arguments' types -- they can in turn be
   2922    expressions, thus allowing to build compound expressions to any
   2923    degree of complexity.
   2924    Op is a function object that must have an eval() method accepting
   2925    appropriate arguments.
   2926    Actual evaluation of a __gmp_expr<T, U> object is done when it gets
   2927    assigned to an mp*_class ("lazy" evaluation): this is done by calling
   2928    its eval() method. */
   2929 
   2930 
   2931 // non-member unary operators and functions
   2932 
   2933 #define __GMP_DEFINE_UNARY_FUNCTION(fun, eval_fun)                           \
   2934                                                                              \
   2935 template <class T, class U>                                                  \
   2936 inline __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, eval_fun> >          \
   2937 fun(const __gmp_expr<T, U> &expr)                                            \
   2938 {                                                                            \
   2939   return __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, eval_fun> >(expr); \
   2940 }
   2941 
   2942 // variant that only works for one of { mpz, mpq, mpf }
   2943 
   2944 #define __GMP_DEFINE_UNARY_FUNCTION_1(T, fun, eval_fun)                      \
   2945                                                                              \
   2946 template <class U>                                                           \
   2947 inline __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, eval_fun> >          \
   2948 fun(const __gmp_expr<T, U> &expr)                                            \
   2949 {                                                                            \
   2950   return __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, eval_fun> >(expr); \
   2951 }
   2952 
   2953 #define __GMP_DEFINE_UNARY_TYPE_FUNCTION(type, fun, eval_fun) \
   2954                                                               \
   2955 template <class T, class U>                                   \
   2956 inline type fun(const __gmp_expr<T, U> &expr)                 \
   2957 {                                                             \
   2958   __gmp_expr<T, T> const& temp(expr); \
   2959   return eval_fun::eval(temp.__get_mp());                     \
   2960 }
   2961 
   2962 
   2963 // non-member binary operators and functions
   2964 
   2965 #define __GMPP_DEFINE_BINARY_FUNCTION(fun, eval_fun)                   \
   2966                                                                        \
   2967 template <class T, class U, class V, class W>                          \
   2968 inline __gmp_expr<typename __gmp_resolve_expr<T, V>::value_type,       \
   2969 __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, eval_fun> >      \
   2970 fun(const __gmp_expr<T, U> &expr1, const __gmp_expr<V, W> &expr2)      \
   2971 {                                                                      \
   2972   return __gmp_expr<typename __gmp_resolve_expr<T, V>::value_type,     \
   2973      __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, eval_fun> > \
   2974     (expr1, expr2);                                                    \
   2975 }
   2976 
   2977 #define __GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, bigtype)       \
   2978                                                                            \
   2979 template <class T, class U>                                                \
   2980 inline __gmp_expr                                                          \
   2981 <T, __gmp_binary_expr<__gmp_expr<T, U>, bigtype, eval_fun> >               \
   2982 fun(const __gmp_expr<T, U> &expr, type t)                                  \
   2983 {                                                                          \
   2984   return __gmp_expr                                                        \
   2985     <T, __gmp_binary_expr<__gmp_expr<T, U>, bigtype, eval_fun> >(expr, t); \
   2986 }                                                                          \
   2987                                                                            \
   2988 template <class T, class U>                                                \
   2989 inline __gmp_expr                                                          \
   2990 <T, __gmp_binary_expr<bigtype, __gmp_expr<T, U>, eval_fun> >               \
   2991 fun(type t, const __gmp_expr<T, U> &expr)                                  \
   2992 {                                                                          \
   2993   return __gmp_expr                                                        \
   2994     <T, __gmp_binary_expr<bigtype, __gmp_expr<T, U>, eval_fun> >(t, expr); \
   2995 }
   2996 
   2997 #define __GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, type)          \
   2998 __GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, signed long int)
   2999 
   3000 #define __GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, type)            \
   3001 __GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, unsigned long int)
   3002 
   3003 #define __GMPND_DEFINE_BINARY_FUNCTION(fun, eval_fun, type) \
   3004 __GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, double)
   3005 
   3006 #define __GMPNLD_DEFINE_BINARY_FUNCTION(fun, eval_fun, type)     \
   3007 __GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, long double)
   3008 
   3009 #define __GMPN_DEFINE_BINARY_FUNCTION(fun, eval_fun)              \
   3010 __GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed char)        \
   3011 __GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned char)      \
   3012 __GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed int)         \
   3013 __GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned int)       \
   3014 __GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed short int)   \
   3015 __GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned short int) \
   3016 __GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed long int)    \
   3017 __GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned long int)  \
   3018 __GMPND_DEFINE_BINARY_FUNCTION(fun, eval_fun, float)              \
   3019 __GMPND_DEFINE_BINARY_FUNCTION(fun, eval_fun, double)             \
   3020 /* __GMPNLD_DEFINE_BINARY_FUNCTION(fun, eval_fun, long double) */
   3021 
   3022 #define __GMP_DEFINE_BINARY_FUNCTION(fun, eval_fun) \
   3023 __GMPP_DEFINE_BINARY_FUNCTION(fun, eval_fun)        \
   3024 __GMPN_DEFINE_BINARY_FUNCTION(fun, eval_fun)
   3025 
   3026 // variant that only works for one of { mpz, mpq, mpf }
   3027 
   3028 #define __GMPP_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun)              \
   3029                                                                        \
   3030 template <class U, class W>                                            \
   3031 inline __gmp_expr<T,                                                   \
   3032 __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<T, W>, eval_fun> >      \
   3033 fun(const __gmp_expr<T, U> &expr1, const __gmp_expr<T, W> &expr2)      \
   3034 {                                                                      \
   3035   return __gmp_expr<T,                                                 \
   3036      __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<T, W>, eval_fun> > \
   3037     (expr1, expr2);                                                    \
   3038 }
   3039 
   3040 #define __GMPNN_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, type, bigtype)  \
   3041                                                                            \
   3042 template <class U>                                                         \
   3043 inline __gmp_expr                                                          \
   3044 <T, __gmp_binary_expr<__gmp_expr<T, U>, bigtype, eval_fun> >               \
   3045 fun(const __gmp_expr<T, U> &expr, type t)                                  \
   3046 {                                                                          \
   3047   return __gmp_expr                                                        \
   3048     <T, __gmp_binary_expr<__gmp_expr<T, U>, bigtype, eval_fun> >(expr, t); \
   3049 }                                                                          \
   3050                                                                            \
   3051 template <class U>                                                         \
   3052 inline __gmp_expr                                                          \
   3053 <T, __gmp_binary_expr<bigtype, __gmp_expr<T, U>, eval_fun> >               \
   3054 fun(type t, const __gmp_expr<T, U> &expr)                                  \
   3055 {                                                                          \
   3056   return __gmp_expr                                                        \
   3057     <T, __gmp_binary_expr<bigtype, __gmp_expr<T, U>, eval_fun> >(t, expr); \
   3058 }
   3059 
   3060 #define __GMPNS_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, type)          \
   3061 __GMPNN_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, type, signed long int)
   3062 
   3063 #define __GMPNU_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, type)          \
   3064 __GMPNN_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, type, unsigned long int)
   3065 
   3066 #define __GMPND_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, type) \
   3067 __GMPNN_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, type, double)
   3068 
   3069 #define __GMPNLD_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, type)     \
   3070 __GMPNN_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, type, long double)
   3071 
   3072 #define __GMPN_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun)              \
   3073 __GMPNS_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, signed char)        \
   3074 __GMPNU_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, unsigned char)      \
   3075 __GMPNS_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, signed int)         \
   3076 __GMPNU_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, unsigned int)       \
   3077 __GMPNS_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, signed short int)   \
   3078 __GMPNU_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, unsigned short int) \
   3079 __GMPNS_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, signed long int)    \
   3080 __GMPNU_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, unsigned long int)  \
   3081 __GMPND_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, float)              \
   3082 __GMPND_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, double)             \
   3083 /* __GMPNLD_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, long double) */
   3084 
   3085 #define __GMP_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun) \
   3086 __GMPP_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun)        \
   3087 __GMPN_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun)
   3088 
   3089 
   3090 #define __GMP_DEFINE_BINARY_FUNCTION_UI(fun, eval_fun)                 \
   3091                                                                        \
   3092 template <class T, class U>                                            \
   3093 inline __gmp_expr                                                      \
   3094 <T, __gmp_binary_expr<__gmp_expr<T, U>, mp_bitcnt_t, eval_fun> > \
   3095 fun(const __gmp_expr<T, U> &expr, mp_bitcnt_t l)                 \
   3096 {                                                                      \
   3097   return __gmp_expr<T, __gmp_binary_expr                               \
   3098     <__gmp_expr<T, U>, mp_bitcnt_t, eval_fun> >(expr, l);        \
   3099 }
   3100 
   3101 
   3102 #define __GMPP_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun)         \
   3103                                                                         \
   3104 template <class T, class U, class V, class W>                           \
   3105 inline type fun(const __gmp_expr<T, U> &expr1,                          \
   3106 		const __gmp_expr<V, W> &expr2)                          \
   3107 {                                                                       \
   3108   __gmp_expr<T, T> const& temp1(expr1);                                 \
   3109   __gmp_expr<V, V> const& temp2(expr2);                                 \
   3110   return eval_fun::eval(temp1.__get_mp(), temp2.__get_mp());            \
   3111 }
   3112 
   3113 #define __GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun,   \
   3114 					    type2, bigtype)        \
   3115                                                                    \
   3116 template <class T, class U>                                        \
   3117 inline type fun(const __gmp_expr<T, U> &expr, type2 t)             \
   3118 {                                                                  \
   3119   __gmp_expr<T, T> const& temp(expr);      \
   3120   return eval_fun::eval(temp.__get_mp(), static_cast<bigtype>(t)); \
   3121 }                                                                  \
   3122                                                                    \
   3123 template <class T, class U>                                        \
   3124 inline type fun(type2 t, const __gmp_expr<T, U> &expr)             \
   3125 {                                                                  \
   3126   __gmp_expr<T, T> const& temp(expr);      \
   3127   return eval_fun::eval(static_cast<bigtype>(t), temp.__get_mp()); \
   3128 }
   3129 
   3130 #define __GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2) \
   3131 __GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun,                \
   3132 				    type2, signed long int)
   3133 
   3134 #define __GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2) \
   3135 __GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun,                \
   3136 				    type2, unsigned long int)
   3137 
   3138 #define __GMPND_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2) \
   3139 __GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2, double)
   3140 
   3141 #define __GMPNLD_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2)     \
   3142 __GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2, long double)
   3143 
   3144 #define __GMPN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun)              \
   3145 __GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed char)        \
   3146 __GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned char)      \
   3147 __GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed int)         \
   3148 __GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned int)       \
   3149 __GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed short int)   \
   3150 __GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned short int) \
   3151 __GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed long int)    \
   3152 __GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned long int)  \
   3153 __GMPND_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, float)              \
   3154 __GMPND_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, double)             \
   3155 /* __GMPNLD_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, long double) */
   3156 
   3157 #define __GMP_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun) \
   3158 __GMPP_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun)        \
   3159 __GMPN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun)
   3160 
   3161 
   3162 // member operators
   3163 
   3164 #define __GMPP_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun)                 \
   3165                                                                              \
   3166 template <class T, class U>                                                  \
   3167 inline type##_class & type##_class::fun(const __gmp_expr<T, U> &expr)        \
   3168 {                                                                            \
   3169   __gmp_set_expr(mp, __gmp_expr<type##_t, __gmp_binary_expr                  \
   3170 		 <type##_class, __gmp_expr<T, U>, eval_fun> >(*this, expr)); \
   3171   return *this;                                                              \
   3172 }
   3173 
   3174 #define __GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun,    \
   3175 					 type2, bigtype)         \
   3176                                                                  \
   3177 inline type##_class & type##_class::fun(type2 t)                 \
   3178 {                                                                \
   3179   __gmp_set_expr(mp, __gmp_expr<type##_t, __gmp_binary_expr      \
   3180 		 <type##_class, bigtype, eval_fun> >(*this, t)); \
   3181   return *this;                                                  \
   3182 }
   3183 
   3184 #define __GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2) \
   3185 __GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun,                \
   3186 				 type2, signed long int)
   3187 
   3188 #define __GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2) \
   3189 __GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun,                \
   3190 				 type2, unsigned long int)
   3191 
   3192 #define __GMPND_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2) \
   3193 __GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2, double)
   3194 
   3195 #define __GMPNLD_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2)     \
   3196 __GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2, long double)
   3197 
   3198 #define __GMPN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun)              \
   3199 __GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed char)        \
   3200 __GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned char)      \
   3201 __GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed int)         \
   3202 __GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned int)       \
   3203 __GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed short int)   \
   3204 __GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned short int) \
   3205 __GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed long int)    \
   3206 __GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned long int)  \
   3207 __GMPND_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, float)              \
   3208 __GMPND_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, double)             \
   3209 /* __GMPNLD_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, long double) */
   3210 
   3211 #define __GMP_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun) \
   3212 __GMPP_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun)        \
   3213 __GMPN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun)
   3214 
   3215 #define __GMPZ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \
   3216 __GMP_DEFINE_COMPOUND_OPERATOR(mpz, fun, eval_fun)
   3217 
   3218 #define __GMPQ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \
   3219 __GMP_DEFINE_COMPOUND_OPERATOR(mpq, fun, eval_fun)
   3220 
   3221 #define __GMPF_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \
   3222 __GMP_DEFINE_COMPOUND_OPERATOR(mpf, fun, eval_fun)
   3223 
   3224 
   3225 
   3226 #define __GMP_DEFINE_COMPOUND_OPERATOR_UI(type, fun, eval_fun)  \
   3227                                                                 \
   3228 inline type##_class & type##_class::fun(mp_bitcnt_t l)    \
   3229 {                                                               \
   3230   __gmp_set_expr(mp, __gmp_expr<type##_t, __gmp_binary_expr     \
   3231     <type##_class, mp_bitcnt_t, eval_fun> >(*this, l));   \
   3232   return *this;                                                 \
   3233 }
   3234 
   3235 #define __GMPZ_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \
   3236 __GMP_DEFINE_COMPOUND_OPERATOR_UI(mpz, fun, eval_fun)
   3237 
   3238 #define __GMPQ_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \
   3239 __GMP_DEFINE_COMPOUND_OPERATOR_UI(mpq, fun, eval_fun)
   3240 
   3241 #define __GMPF_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \
   3242 __GMP_DEFINE_COMPOUND_OPERATOR_UI(mpf, fun, eval_fun)
   3243 
   3244 
   3245 
   3246 #define __GMP_DEFINE_INCREMENT_OPERATOR(type, fun, eval_fun) \
   3247                                                              \
   3248 inline type##_class & type##_class::fun()                    \
   3249 {                                                            \
   3250   eval_fun::eval(mp);                                        \
   3251   return *this;                                              \
   3252 }                                                            \
   3253                                                              \
   3254 inline type##_class type##_class::fun(int)                   \
   3255 {                                                            \
   3256   type##_class temp(*this);                                  \
   3257   eval_fun::eval(mp);                                        \
   3258   return temp;                                               \
   3259 }
   3260 
   3261 #define __GMPZ_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \
   3262 __GMP_DEFINE_INCREMENT_OPERATOR(mpz, fun, eval_fun)
   3263 
   3264 #define __GMPQ_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \
   3265 __GMP_DEFINE_INCREMENT_OPERATOR(mpq, fun, eval_fun)
   3266 
   3267 #define __GMPF_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \
   3268 __GMP_DEFINE_INCREMENT_OPERATOR(mpf, fun, eval_fun)
   3269 
   3270 
   3271 #define __GMPP_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun)                  \
   3272 template <class U>                                                           \
   3273 __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, eval_fun> >          \
   3274 fun(const __gmp_expr<T, U> &expr)                                            \
   3275 {                                                                            \
   3276   return __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, eval_fun> >(expr); \
   3277 }
   3278 
   3279 #define __GMPNN_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type, bigtype)  \
   3280 inline __gmp_expr<T, __gmp_unary_expr<bigtype, eval_fun> >                   \
   3281 fun(type expr)                                                               \
   3282 {                                                                            \
   3283   return __gmp_expr<T, __gmp_unary_expr<bigtype, eval_fun> >(expr);          \
   3284 }
   3285 
   3286 #define __GMPNS_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type)  \
   3287 __GMPNN_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type, signed long)
   3288 #define __GMPNU_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type)  \
   3289 __GMPNN_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type, unsigned long)
   3290 #define __GMPND_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type)  \
   3291 __GMPNN_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type, double)
   3292 
   3293 #define __GMPN_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun)                 \
   3294 __GMPNS_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, signed char)           \
   3295 __GMPNU_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, unsigned char)         \
   3296 __GMPNS_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, signed int)            \
   3297 __GMPNU_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, unsigned int)          \
   3298 __GMPNS_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, signed short int)      \
   3299 __GMPNU_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, unsigned short int)    \
   3300 __GMPNS_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, signed long int)       \
   3301 __GMPNU_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, unsigned long int)     \
   3302 __GMPND_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, float)                 \
   3303 __GMPND_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, double)                \
   3304 
   3305 #define __GMP_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun)                  \
   3306 __GMPP_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun)                         \
   3307 __GMPN_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun)                         \
   3308 
   3309 
   3310 /**************** Arithmetic operators and functions ****************/
   3311 
   3312 // non-member operators and functions
   3313 
   3314 __GMP_DEFINE_UNARY_FUNCTION(operator+, __gmp_unary_plus)
   3315 __GMP_DEFINE_UNARY_FUNCTION(operator-, __gmp_unary_minus)
   3316 __GMP_DEFINE_UNARY_FUNCTION_1(mpz_t, operator~, __gmp_unary_com)
   3317 
   3318 __GMP_DEFINE_BINARY_FUNCTION(operator+, __gmp_binary_plus)
   3319 __GMP_DEFINE_BINARY_FUNCTION(operator-, __gmp_binary_minus)
   3320 __GMP_DEFINE_BINARY_FUNCTION(operator*, __gmp_binary_multiplies)
   3321 __GMP_DEFINE_BINARY_FUNCTION(operator/, __gmp_binary_divides)
   3322 __GMP_DEFINE_BINARY_FUNCTION_1(mpz_t, operator%, __gmp_binary_modulus)
   3323 __GMP_DEFINE_BINARY_FUNCTION_1(mpz_t, operator&, __gmp_binary_and)
   3324 __GMP_DEFINE_BINARY_FUNCTION_1(mpz_t, operator|, __gmp_binary_ior)
   3325 __GMP_DEFINE_BINARY_FUNCTION_1(mpz_t, operator^, __gmp_binary_xor)
   3326 
   3327 __GMP_DEFINE_BINARY_FUNCTION_UI(operator<<, __gmp_binary_lshift)
   3328 __GMP_DEFINE_BINARY_FUNCTION_UI(operator>>, __gmp_binary_rshift)
   3329 
   3330 __GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator==, __gmp_binary_equal)
   3331 __GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator!=, ! __gmp_binary_equal)
   3332 __GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator<, __gmp_binary_less)
   3333 __GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator<=, ! __gmp_binary_greater)
   3334 __GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator>, __gmp_binary_greater)
   3335 __GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator>=, ! __gmp_binary_less)
   3336 
   3337 __GMP_DEFINE_UNARY_FUNCTION(abs, __gmp_abs_function)
   3338 __GMP_DEFINE_UNARY_FUNCTION_1(mpf_t, trunc, __gmp_trunc_function)
   3339 __GMP_DEFINE_UNARY_FUNCTION_1(mpf_t, floor, __gmp_floor_function)
   3340 __GMP_DEFINE_UNARY_FUNCTION_1(mpf_t, ceil, __gmp_ceil_function)
   3341 __GMP_DEFINE_UNARY_FUNCTION_1(mpf_t, sqrt, __gmp_sqrt_function)
   3342 __GMP_DEFINE_UNARY_FUNCTION_1(mpz_t, sqrt, __gmp_sqrt_function)
   3343 __GMP_DEFINE_UNARY_FUNCTION_1(mpz_t, factorial, __gmp_fac_function)
   3344 __GMP_DEFINE_UNARY_FUNCTION_1(mpz_t, primorial, __gmp_primorial_function)
   3345 __GMP_DEFINE_UNARY_FUNCTION_1(mpz_t, fibonacci, __gmp_fib_function)
   3346 __GMP_DEFINE_BINARY_FUNCTION_1(mpf_t, hypot, __gmp_hypot_function)
   3347 __GMP_DEFINE_BINARY_FUNCTION_1(mpz_t, gcd, __gmp_gcd_function)
   3348 __GMP_DEFINE_BINARY_FUNCTION_1(mpz_t, lcm, __gmp_lcm_function)
   3349 
   3350 __GMP_DEFINE_UNARY_TYPE_FUNCTION(int, sgn, __gmp_sgn_function)
   3351 __GMP_DEFINE_BINARY_TYPE_FUNCTION(int, cmp, __gmp_cmp_function)
   3352 
   3353 template <class T>
   3354 void swap(__gmp_expr<T, T>& x, __gmp_expr<T, T>& y) __GMPXX_NOEXCEPT
   3355 { x.swap(y); }
   3356 
   3357 // member operators for mpz_class
   3358 
   3359 __GMPZ_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus)
   3360 __GMPZ_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus)
   3361 __GMPZ_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies)
   3362 __GMPZ_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides)
   3363 __GMPZ_DEFINE_COMPOUND_OPERATOR(operator%=, __gmp_binary_modulus)
   3364 
   3365 __GMPZ_DEFINE_COMPOUND_OPERATOR(operator&=, __gmp_binary_and)
   3366 __GMPZ_DEFINE_COMPOUND_OPERATOR(operator|=, __gmp_binary_ior)
   3367 __GMPZ_DEFINE_COMPOUND_OPERATOR(operator^=, __gmp_binary_xor)
   3368 
   3369 __GMPZ_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift)
   3370 __GMPZ_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift)
   3371 
   3372 __GMPZ_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment)
   3373 __GMPZ_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement)
   3374 
   3375 __GMP_DEFINE_UNARY_STATIC_MEMFUN(mpz_t, mpz_class::factorial, __gmp_fac_function)
   3376 __GMP_DEFINE_UNARY_STATIC_MEMFUN(mpz_t, mpz_class::primorial, __gmp_primorial_function)
   3377 __GMP_DEFINE_UNARY_STATIC_MEMFUN(mpz_t, mpz_class::fibonacci, __gmp_fib_function)
   3378 
   3379 // member operators for mpq_class
   3380 
   3381 __GMPQ_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus)
   3382 __GMPQ_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus)
   3383 __GMPQ_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies)
   3384 __GMPQ_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides)
   3385 
   3386 __GMPQ_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift)
   3387 __GMPQ_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift)
   3388 
   3389 __GMPQ_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment)
   3390 __GMPQ_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement)
   3391 
   3392 // member operators for mpf_class
   3393 
   3394 __GMPF_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus)
   3395 __GMPF_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus)
   3396 __GMPF_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies)
   3397 __GMPF_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides)
   3398 
   3399 __GMPF_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift)
   3400 __GMPF_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift)
   3401 
   3402 __GMPF_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment)
   3403 __GMPF_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement)
   3404 
   3405 
   3406 
   3407 /**************** Class wrapper for gmp_randstate_t ****************/
   3408 
   3409 class __gmp_urandomb_value { };
   3410 class __gmp_urandomm_value { };
   3411 
   3412 template <>
   3413 class __gmp_expr<mpz_t, __gmp_urandomb_value>
   3414 {
   3415 private:
   3416   __gmp_randstate_struct *state;
   3417   mp_bitcnt_t bits;
   3418 public:
   3419   __gmp_expr(gmp_randstate_t s, mp_bitcnt_t l) : state(s), bits(l) { }
   3420   void eval(mpz_ptr z) const { __gmp_rand_function::eval(z, state, bits); }
   3421   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }
   3422 };
   3423 
   3424 template <>
   3425 class __gmp_expr<mpz_t, __gmp_urandomm_value>
   3426 {
   3427 private:
   3428   __gmp_randstate_struct *state;
   3429   mpz_class range;
   3430 public:
   3431   __gmp_expr(gmp_randstate_t s, const mpz_class &z) : state(s), range(z) { }
   3432   void eval(mpz_ptr z) const
   3433   { __gmp_rand_function::eval(z, state, range.get_mpz_t()); }
   3434   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }
   3435 };
   3436 
   3437 template <>
   3438 class __gmp_expr<mpf_t, __gmp_urandomb_value>
   3439 {
   3440 private:
   3441   __gmp_randstate_struct *state;
   3442   mp_bitcnt_t bits;
   3443 public:
   3444   __gmp_expr(gmp_randstate_t s, mp_bitcnt_t l) : state(s), bits(l) { }
   3445   void eval(mpf_ptr f) const
   3446   {
   3447     __gmp_rand_function::eval(f, state,
   3448 	(bits>0) ? bits : mpf_get_prec(f));
   3449   }
   3450   mp_bitcnt_t get_prec() const
   3451   {
   3452     if (bits == 0)
   3453       return mpf_get_default_prec();
   3454     else
   3455       return bits;
   3456   }
   3457 };
   3458 
   3459 extern "C" {
   3460   typedef void __gmp_randinit_default_t (gmp_randstate_t);
   3461   typedef void __gmp_randinit_lc_2exp_t (gmp_randstate_t, mpz_srcptr, unsigned long int, mp_bitcnt_t);
   3462   typedef int __gmp_randinit_lc_2exp_size_t (gmp_randstate_t, mp_bitcnt_t);
   3463 }
   3464 
   3465 class gmp_randclass
   3466 {
   3467 private:
   3468   gmp_randstate_t state;
   3469 
   3470   // copy construction and assignment not allowed
   3471   gmp_randclass(const gmp_randclass &);
   3472   void operator=(const gmp_randclass &);
   3473 public:
   3474   // constructors and destructor
   3475   gmp_randclass(gmp_randalg_t alg, unsigned long int size)
   3476   {
   3477     switch (alg)
   3478       {
   3479       case GMP_RAND_ALG_LC: // no other cases for now
   3480       default:
   3481 	gmp_randinit(state, alg, size);
   3482 	break;
   3483       }
   3484   }
   3485 
   3486   // gmp_randinit_default
   3487   gmp_randclass(__gmp_randinit_default_t* f) { f(state); }
   3488 
   3489   // gmp_randinit_lc_2exp
   3490   gmp_randclass(__gmp_randinit_lc_2exp_t* f,
   3491 		mpz_class z, unsigned long int l1, mp_bitcnt_t l2)
   3492   { f(state, z.get_mpz_t(), l1, l2); }
   3493 
   3494   // gmp_randinit_lc_2exp_size
   3495   gmp_randclass(__gmp_randinit_lc_2exp_size_t* f,
   3496 		mp_bitcnt_t size)
   3497   {
   3498     if (f (state, size) == 0)
   3499       throw std::length_error ("gmp_randinit_lc_2exp_size");
   3500   }
   3501 
   3502   ~gmp_randclass() { gmp_randclear(state); }
   3503 
   3504   // initialize
   3505   void seed(); // choose a random seed some way (?)
   3506   void seed(unsigned long int s) { gmp_randseed_ui(state, s); }
   3507   void seed(const mpz_class &z) { gmp_randseed(state, z.get_mpz_t()); }
   3508 
   3509   // get random number
   3510   __gmp_expr<mpz_t, __gmp_urandomb_value> get_z_bits(mp_bitcnt_t l)
   3511   { return __gmp_expr<mpz_t, __gmp_urandomb_value>(state, l); }
   3512   __gmp_expr<mpz_t, __gmp_urandomb_value> get_z_bits(const mpz_class &z)
   3513   { return get_z_bits(z.get_ui()); }
   3514   // FIXME: z.get_bitcnt_t() ?
   3515 
   3516   __gmp_expr<mpz_t, __gmp_urandomm_value> get_z_range(const mpz_class &z)
   3517   { return __gmp_expr<mpz_t, __gmp_urandomm_value>(state, z); }
   3518 
   3519   __gmp_expr<mpf_t, __gmp_urandomb_value> get_f(mp_bitcnt_t prec = 0)
   3520   { return __gmp_expr<mpf_t, __gmp_urandomb_value>(state, prec); }
   3521 };
   3522 
   3523 
   3524 /**************** Specialize std::numeric_limits ****************/
   3525 
   3526 namespace std {
   3527   template <> class numeric_limits<mpz_class>
   3528   {
   3529   public:
   3530     static const bool is_specialized = true;
   3531     static mpz_class min() { return mpz_class(); }
   3532     static mpz_class max() { return mpz_class(); }
   3533     static mpz_class lowest() { return mpz_class(); }
   3534     static const int digits = 0;
   3535     static const int digits10 = 0;
   3536     static const int max_digits10 = 0;
   3537     static const bool is_signed = true;
   3538     static const bool is_integer = true;
   3539     static const bool is_exact = true;
   3540     static const int radix = 2;
   3541     static mpz_class epsilon() { return mpz_class(); }
   3542     static mpz_class round_error() { return mpz_class(); }
   3543     static const int min_exponent = 0;
   3544     static const int min_exponent10 = 0;
   3545     static const int max_exponent = 0;
   3546     static const int max_exponent10 = 0;
   3547     static const bool has_infinity = false;
   3548     static const bool has_quiet_NaN = false;
   3549     static const bool has_signaling_NaN = false;
   3550     static const float_denorm_style has_denorm = denorm_absent;
   3551     static const bool has_denorm_loss = false;
   3552     static mpz_class infinity() { return mpz_class(); }
   3553     static mpz_class quiet_NaN() { return mpz_class(); }
   3554     static mpz_class signaling_NaN() { return mpz_class(); }
   3555     static mpz_class denorm_min() { return mpz_class(); }
   3556     static const bool is_iec559 = false;
   3557     static const bool is_bounded = false;
   3558     static const bool is_modulo = false;
   3559     static const bool traps = false;
   3560     static const bool tinyness_before = false;
   3561     static const float_round_style round_style = round_toward_zero;
   3562   };
   3563 
   3564   template <> class numeric_limits<mpq_class>
   3565   {
   3566   public:
   3567     static const bool is_specialized = true;
   3568     static mpq_class min() { return mpq_class(); }
   3569     static mpq_class max() { return mpq_class(); }
   3570     static mpq_class lowest() { return mpq_class(); }
   3571     static const int digits = 0;
   3572     static const int digits10 = 0;
   3573     static const int max_digits10 = 0;
   3574     static const bool is_signed = true;
   3575     static const bool is_integer = false;
   3576     static const bool is_exact = true;
   3577     static const int radix = 2;
   3578     static mpq_class epsilon() { return mpq_class(); }
   3579     static mpq_class round_error() { return mpq_class(); }
   3580     static const int min_exponent = 0;
   3581     static const int min_exponent10 = 0;
   3582     static const int max_exponent = 0;
   3583     static const int max_exponent10 = 0;
   3584     static const bool has_infinity = false;
   3585     static const bool has_quiet_NaN = false;
   3586     static const bool has_signaling_NaN = false;
   3587     static const float_denorm_style has_denorm = denorm_absent;
   3588     static const bool has_denorm_loss = false;
   3589     static mpq_class infinity() { return mpq_class(); }
   3590     static mpq_class quiet_NaN() { return mpq_class(); }
   3591     static mpq_class signaling_NaN() { return mpq_class(); }
   3592     static mpq_class denorm_min() { return mpq_class(); }
   3593     static const bool is_iec559 = false;
   3594     static const bool is_bounded = false;
   3595     static const bool is_modulo = false;
   3596     static const bool traps = false;
   3597     static const bool tinyness_before = false;
   3598     static const float_round_style round_style = round_toward_zero;
   3599   };
   3600 
   3601   template <> class numeric_limits<mpf_class>
   3602   {
   3603   public:
   3604     static const bool is_specialized = true;
   3605     static mpf_class min() { return mpf_class(); }
   3606     static mpf_class max() { return mpf_class(); }
   3607     static mpf_class lowest() { return mpf_class(); }
   3608     static const int digits = 0;
   3609     static const int digits10 = 0;
   3610     static const int max_digits10 = 0;
   3611     static const bool is_signed = true;
   3612     static const bool is_integer = false;
   3613     static const bool is_exact = false;
   3614     static const int radix = 2;
   3615     static mpf_class epsilon() { return mpf_class(); }
   3616     static mpf_class round_error() { return mpf_class(); }
   3617     static const int min_exponent = 0;
   3618     static const int min_exponent10 = 0;
   3619     static const int max_exponent = 0;
   3620     static const int max_exponent10 = 0;
   3621     static const bool has_infinity = false;
   3622     static const bool has_quiet_NaN = false;
   3623     static const bool has_signaling_NaN = false;
   3624     static const float_denorm_style has_denorm = denorm_absent;
   3625     static const bool has_denorm_loss = false;
   3626     static mpf_class infinity() { return mpf_class(); }
   3627     static mpf_class quiet_NaN() { return mpf_class(); }
   3628     static mpf_class signaling_NaN() { return mpf_class(); }
   3629     static mpf_class denorm_min() { return mpf_class(); }
   3630     static const bool is_iec559 = false;
   3631     static const bool is_bounded = false;
   3632     static const bool is_modulo = false;
   3633     static const bool traps = false;
   3634     static const bool tinyness_before = false;
   3635     static const float_round_style round_style = round_indeterminate;
   3636   };
   3637 }
   3638 
   3639 
   3640 /**************** #undef all private macros ****************/
   3641 
   3642 #undef __GMPP_DECLARE_COMPOUND_OPERATOR
   3643 #undef __GMPN_DECLARE_COMPOUND_OPERATOR
   3644 #undef __GMP_DECLARE_COMPOUND_OPERATOR
   3645 #undef __GMP_DECLARE_COMPOUND_OPERATOR_UI
   3646 #undef __GMP_DECLARE_INCREMENT_OPERATOR
   3647 #undef __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS
   3648 #undef __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS
   3649 
   3650 #undef __GMPZQ_DEFINE_EXPR
   3651 
   3652 #undef __GMP_DEFINE_UNARY_FUNCTION_1
   3653 #undef __GMP_DEFINE_UNARY_FUNCTION
   3654 #undef __GMP_DEFINE_UNARY_TYPE_FUNCTION
   3655 
   3656 #undef __GMPP_DEFINE_BINARY_FUNCTION
   3657 #undef __GMPNN_DEFINE_BINARY_FUNCTION
   3658 #undef __GMPNS_DEFINE_BINARY_FUNCTION
   3659 #undef __GMPNU_DEFINE_BINARY_FUNCTION
   3660 #undef __GMPND_DEFINE_BINARY_FUNCTION
   3661 #undef __GMPNLD_DEFINE_BINARY_FUNCTION
   3662 #undef __GMPN_DEFINE_BINARY_FUNCTION
   3663 #undef __GMP_DEFINE_BINARY_FUNCTION
   3664 
   3665 #undef __GMP_DEFINE_BINARY_FUNCTION_UI
   3666 
   3667 #undef __GMPP_DEFINE_BINARY_TYPE_FUNCTION
   3668 #undef __GMPNN_DEFINE_BINARY_TYPE_FUNCTION
   3669 #undef __GMPNS_DEFINE_BINARY_TYPE_FUNCTION
   3670 #undef __GMPNU_DEFINE_BINARY_TYPE_FUNCTION
   3671 #undef __GMPND_DEFINE_BINARY_TYPE_FUNCTION
   3672 #undef __GMPNLD_DEFINE_BINARY_TYPE_FUNCTION
   3673 #undef __GMPN_DEFINE_BINARY_TYPE_FUNCTION
   3674 #undef __GMP_DEFINE_BINARY_TYPE_FUNCTION
   3675 
   3676 #undef __GMPZ_DEFINE_COMPOUND_OPERATOR
   3677 
   3678 #undef __GMPP_DEFINE_COMPOUND_OPERATOR
   3679 #undef __GMPNN_DEFINE_COMPOUND_OPERATOR
   3680 #undef __GMPNS_DEFINE_COMPOUND_OPERATOR
   3681 #undef __GMPNU_DEFINE_COMPOUND_OPERATOR
   3682 #undef __GMPND_DEFINE_COMPOUND_OPERATOR
   3683 #undef __GMPNLD_DEFINE_COMPOUND_OPERATOR
   3684 #undef __GMPN_DEFINE_COMPOUND_OPERATOR
   3685 #undef __GMP_DEFINE_COMPOUND_OPERATOR
   3686 
   3687 #undef __GMPQ_DEFINE_COMPOUND_OPERATOR
   3688 #undef __GMPF_DEFINE_COMPOUND_OPERATOR
   3689 
   3690 #undef __GMP_DEFINE_COMPOUND_OPERATOR_UI
   3691 #undef __GMPZ_DEFINE_COMPOUND_OPERATOR_UI
   3692 #undef __GMPQ_DEFINE_COMPOUND_OPERATOR_UI
   3693 #undef __GMPF_DEFINE_COMPOUND_OPERATOR_UI
   3694 
   3695 #undef __GMP_DEFINE_INCREMENT_OPERATOR
   3696 #undef __GMPZ_DEFINE_INCREMENT_OPERATOR
   3697 #undef __GMPQ_DEFINE_INCREMENT_OPERATOR
   3698 #undef __GMPF_DEFINE_INCREMENT_OPERATOR
   3699 
   3700 #undef __GMPXX_CONSTANT_TRUE
   3701 #undef __GMPXX_CONSTANT
   3702 
   3703 #endif /* __GMP_PLUSPLUS__ */