Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-05-18 08:30:00

0001 /* gmpxx.h -- C++ class wrapper for GMP types.  -*- C++ -*-
0002 
0003 Copyright 2001-2003, 2006, 2008, 2011-2015, 2018 Free Software
0004 Foundation, Inc.
0005 
0006 This file is part of the GNU MP Library.
0007 
0008 The GNU MP Library is free software; you can redistribute it and/or modify
0009 it under the terms of either:
0010 
0011   * the GNU Lesser General Public License as published by the Free
0012     Software Foundation; either version 3 of the License, or (at your
0013     option) any later version.
0014 
0015 or
0016 
0017   * the GNU General Public License as published by the Free Software
0018     Foundation; either version 2 of the License, or (at your option) any
0019     later version.
0020 
0021 or both in parallel, as here.
0022 
0023 The GNU MP Library is distributed in the hope that it will be useful, but
0024 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
0025 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0026 for more details.
0027 
0028 You should have received copies of the GNU General Public License and the
0029 GNU Lesser General Public License along with the GNU MP Library.  If not,
0030 see https://www.gnu.org/licenses/.  */
0031 
0032 #ifndef __GMP_PLUSPLUS__
0033 #define __GMP_PLUSPLUS__
0034 
0035 #include <iosfwd>
0036 
0037 #include <cstring>  /* for strlen */
0038 #include <limits>  /* numeric_limits */
0039 #include <utility>
0040 #include <algorithm>  /* swap */
0041 #include <string>
0042 #include <stdexcept>
0043 #include <cfloat>
0044 #include <gmp.h>
0045 
0046 // wrapper for gcc's __builtin_constant_p
0047 // __builtin_constant_p has been in gcc since forever,
0048 // but g++-3.4 miscompiles it.
0049 #if __GMP_GNUC_PREREQ(4, 2)
0050 #define __GMPXX_CONSTANT(X) __builtin_constant_p(X)
0051 #else
0052 #define __GMPXX_CONSTANT(X) false
0053 #endif
0054 #define __GMPXX_CONSTANT_TRUE(X) (__GMPXX_CONSTANT(X) && (X))
0055 
0056 // Use C++11 features
0057 #ifndef __GMPXX_USE_CXX11
0058 #if __cplusplus >= 201103L
0059 #define __GMPXX_USE_CXX11 1
0060 #else
0061 #define __GMPXX_USE_CXX11 0
0062 #endif
0063 #endif
0064 
0065 #if __GMPXX_USE_CXX11
0066 #define __GMPXX_NOEXCEPT noexcept
0067 #include <type_traits> // for common_type
0068 #else
0069 #define __GMPXX_NOEXCEPT
0070 #endif
0071 
0072 // Max allocations for plain types when converted to GMP types
0073 #if GMP_NAIL_BITS != 0 && ! defined _LONG_LONG_LIMB
0074 #define __GMPZ_ULI_LIMBS 2
0075 #else
0076 #define __GMPZ_ULI_LIMBS 1
0077 #endif
0078 
0079 #define __GMPXX_BITS_TO_LIMBS(n)  (((n) + (GMP_NUMB_BITS - 1)) / GMP_NUMB_BITS)
0080 #define __GMPZ_DBL_LIMBS __GMPXX_BITS_TO_LIMBS(DBL_MAX_EXP)+1
0081 #define __GMPQ_NUM_DBL_LIMBS __GMPZ_DBL_LIMBS
0082 #define __GMPQ_DEN_DBL_LIMBS __GMPXX_BITS_TO_LIMBS(DBL_MANT_DIG+1-DBL_MIN_EXP)+1
0083 // The final +1s are a security margin. The current implementation of
0084 // mpq_set_d seems to need it for the denominator.
0085 
0086 inline void __mpz_set_ui_safe(mpz_ptr p, unsigned long l)
0087 {
0088   p->_mp_size = (l != 0);
0089   p->_mp_d[0] = l & GMP_NUMB_MASK;
0090 #if __GMPZ_ULI_LIMBS > 1
0091   l >>= GMP_NUMB_BITS;
0092   p->_mp_d[1] = l;
0093   p->_mp_size += (l != 0);
0094 #endif
0095 }
0096 
0097 inline void __mpz_set_si_safe(mpz_ptr p, long l)
0098 {
0099   if(l < 0)
0100   {
0101     __mpz_set_ui_safe(p, -static_cast<unsigned long>(l));
0102     mpz_neg(p, p);
0103   }
0104   else
0105     __mpz_set_ui_safe(p, l);
0106     // Note: we know the high bit of l is 0 so we could do slightly better
0107 }
0108 
0109 // Fake temporary variables
0110 #define __GMPXX_TMPZ_UI                         \
0111   mpz_t temp;                               \
0112   mp_limb_t limbs[__GMPZ_ULI_LIMBS];                    \
0113   temp->_mp_d = limbs;                          \
0114   __mpz_set_ui_safe (temp, l)
0115 #define __GMPXX_TMPZ_SI                         \
0116   mpz_t temp;                               \
0117   mp_limb_t limbs[__GMPZ_ULI_LIMBS];                    \
0118   temp->_mp_d = limbs;                          \
0119   __mpz_set_si_safe (temp, l)
0120 #define __GMPXX_TMPZ_D                          \
0121   mpz_t temp;                               \
0122   mp_limb_t limbs[__GMPZ_DBL_LIMBS];                    \
0123   temp->_mp_d = limbs;                          \
0124   temp->_mp_alloc = __GMPZ_DBL_LIMBS;                   \
0125   mpz_set_d (temp, d)
0126 
0127 #define __GMPXX_TMPQ_UI                         \
0128   mpq_t temp;                               \
0129   mp_limb_t limbs[__GMPZ_ULI_LIMBS+1];                  \
0130   mpq_numref(temp)->_mp_d = limbs;                  \
0131   __mpz_set_ui_safe (mpq_numref(temp), l);              \
0132   mpq_denref(temp)->_mp_d = limbs + __GMPZ_ULI_LIMBS;           \
0133   mpq_denref(temp)->_mp_size = 1;                   \
0134   mpq_denref(temp)->_mp_d[0] = 1
0135 #define __GMPXX_TMPQ_SI                         \
0136   mpq_t temp;                               \
0137   mp_limb_t limbs[__GMPZ_ULI_LIMBS+1];                  \
0138   mpq_numref(temp)->_mp_d = limbs;                  \
0139   __mpz_set_si_safe (mpq_numref(temp), l);              \
0140   mpq_denref(temp)->_mp_d = limbs + __GMPZ_ULI_LIMBS;           \
0141   mpq_denref(temp)->_mp_size = 1;                   \
0142   mpq_denref(temp)->_mp_d[0] = 1
0143 #define __GMPXX_TMPQ_D                          \
0144   mpq_t temp;                               \
0145   mp_limb_t limbs[__GMPQ_NUM_DBL_LIMBS + __GMPQ_DEN_DBL_LIMBS];     \
0146   mpq_numref(temp)->_mp_d = limbs;                  \
0147   mpq_numref(temp)->_mp_alloc = __GMPQ_NUM_DBL_LIMBS;           \
0148   mpq_denref(temp)->_mp_d = limbs + __GMPQ_NUM_DBL_LIMBS;       \
0149   mpq_denref(temp)->_mp_alloc = __GMPQ_DEN_DBL_LIMBS;           \
0150   mpq_set_d (temp, d)
0151 
0152 inline unsigned long __gmpxx_abs_ui (signed long l)
0153 {
0154   return l >= 0 ? static_cast<unsigned long>(l)
0155       : -static_cast<unsigned long>(l);
0156 }
0157 
0158 /**************** Function objects ****************/
0159 /* Any evaluation of a __gmp_expr ends up calling one of these functions
0160    all intermediate functions being inline, the evaluation should optimize
0161    to a direct call to the relevant function, thus yielding no overhead
0162    over the C interface. */
0163 
0164 struct __gmp_unary_plus
0165 {
0166   static void eval(mpz_ptr z, mpz_srcptr w) { mpz_set(z, w); }
0167   static void eval(mpq_ptr q, mpq_srcptr r) { mpq_set(q, r); }
0168   static void eval(mpf_ptr f, mpf_srcptr g) { mpf_set(f, g); }
0169 };
0170 
0171 struct __gmp_unary_minus
0172 {
0173   static void eval(mpz_ptr z, mpz_srcptr w) { mpz_neg(z, w); }
0174   static void eval(mpq_ptr q, mpq_srcptr r) { mpq_neg(q, r); }
0175   static void eval(mpf_ptr f, mpf_srcptr g) { mpf_neg(f, g); }
0176 };
0177 
0178 struct __gmp_unary_com
0179 {
0180   static void eval(mpz_ptr z, mpz_srcptr w) { mpz_com(z, w); }
0181 };
0182 
0183 struct __gmp_binary_plus
0184 {
0185   static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
0186   { mpz_add(z, w, v); }
0187 
0188   static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
0189   {
0190     // Ideally, those checks should happen earlier so that the tree
0191     // generated for a+0+b would just be sum(a,b).
0192     if (__GMPXX_CONSTANT(l) && l == 0)
0193     {
0194       if (z != w) mpz_set(z, w);
0195     }
0196     else
0197       mpz_add_ui(z, w, l);
0198   }
0199   static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
0200   { eval(z, w, l); }
0201   static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
0202   {
0203     if (l >= 0)
0204       eval(z, w, static_cast<unsigned long>(l));
0205     else
0206       mpz_sub_ui(z, w, -static_cast<unsigned long>(l));
0207   }
0208   static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
0209   { eval(z, w, l); }
0210   static void eval(mpz_ptr z, mpz_srcptr w, double d)
0211   {  __GMPXX_TMPZ_D;    mpz_add (z, w, temp); }
0212   static void eval(mpz_ptr z, double d, mpz_srcptr w)
0213   { eval(z, w, d); }
0214 
0215   static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s)
0216   { mpq_add(q, r, s); }
0217 
0218   static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l)
0219   {
0220     if (__GMPXX_CONSTANT(l) && l == 0)
0221     {
0222       if (q != r) mpq_set(q, r);
0223     }
0224     else if (__GMPXX_CONSTANT(l) && l == 1)
0225     {
0226       mpz_add (mpq_numref(q), mpq_numref(r), mpq_denref(r));
0227       if (q != r) mpz_set(mpq_denref(q), mpq_denref(r));
0228     }
0229     else
0230     {
0231       if (q == r)
0232         mpz_addmul_ui(mpq_numref(q), mpq_denref(q), l);
0233       else
0234       {
0235         mpz_mul_ui(mpq_numref(q), mpq_denref(r), l);
0236         mpz_add(mpq_numref(q), mpq_numref(q), mpq_numref(r));
0237         mpz_set(mpq_denref(q), mpq_denref(r));
0238       }
0239     }
0240   }
0241   static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r)
0242   { eval(q, r, l); }
0243   static inline void eval(mpq_ptr q, mpq_srcptr r, signed long int l);
0244   // defined after __gmp_binary_minus
0245   static void eval(mpq_ptr q, signed long int l, mpq_srcptr r)
0246   { eval(q, r, l); }
0247   static void eval(mpq_ptr q, mpq_srcptr r, double d)
0248   {  __GMPXX_TMPQ_D;    mpq_add (q, r, temp); }
0249   static void eval(mpq_ptr q, double d, mpq_srcptr r)
0250   { eval(q, r, d); }
0251 
0252   static void eval(mpq_ptr q, mpq_srcptr r, mpz_srcptr z)
0253   {
0254     if (q == r)
0255       mpz_addmul(mpq_numref(q), mpq_denref(q), z);
0256     else
0257     {
0258       mpz_mul(mpq_numref(q), mpq_denref(r), z);
0259       mpz_add(mpq_numref(q), mpq_numref(q), mpq_numref(r));
0260       mpz_set(mpq_denref(q), mpq_denref(r));
0261     }
0262   }
0263   static void eval(mpq_ptr q, mpz_srcptr z, mpq_srcptr r)
0264   { eval(q, r, z); }
0265 
0266   static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)
0267   { mpf_add(f, g, h); }
0268 
0269   static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l)
0270   { mpf_add_ui(f, g, l); }
0271   static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g)
0272   { mpf_add_ui(f, g, l); }
0273   static void eval(mpf_ptr f, mpf_srcptr g, signed long int l)
0274   {
0275     if (l >= 0)
0276       mpf_add_ui(f, g, l);
0277     else
0278       mpf_sub_ui(f, g, -static_cast<unsigned long>(l));
0279   }
0280   static void eval(mpf_ptr f, signed long int l, mpf_srcptr g)
0281   { eval(f, g, l); }
0282   static void eval(mpf_ptr f, mpf_srcptr g, double d)
0283   {
0284     mpf_t temp;
0285     mpf_init2(temp, 8*sizeof(double));
0286     mpf_set_d(temp, d);
0287     mpf_add(f, g, temp);
0288     mpf_clear(temp);
0289   }
0290   static void eval(mpf_ptr f, double d, mpf_srcptr g)
0291   { eval(f, g, d); }
0292 };
0293 
0294 struct __gmp_binary_minus
0295 {
0296   static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
0297   { mpz_sub(z, w, v); }
0298 
0299   static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
0300   {
0301     if (__GMPXX_CONSTANT(l) && l == 0)
0302     {
0303       if (z != w) mpz_set(z, w);
0304     }
0305     else
0306       mpz_sub_ui(z, w, l);
0307   }
0308   static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
0309   {
0310     if (__GMPXX_CONSTANT(l) && l == 0)
0311     {
0312       mpz_neg(z, w);
0313     }
0314     else
0315       mpz_ui_sub(z, l, w);
0316   }
0317   static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
0318   {
0319     if (l >= 0)
0320       eval(z, w, static_cast<unsigned long>(l));
0321     else
0322       mpz_add_ui(z, w, -static_cast<unsigned long>(l));
0323   }
0324   static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
0325   {
0326     if (l >= 0)
0327       eval(z, static_cast<unsigned long>(l), w);
0328     else
0329       {
0330         mpz_add_ui(z, w, -static_cast<unsigned long>(l));
0331         mpz_neg(z, z);
0332       }
0333   }
0334   static void eval(mpz_ptr z, mpz_srcptr w, double d)
0335   {  __GMPXX_TMPZ_D;    mpz_sub (z, w, temp); }
0336   static void eval(mpz_ptr z, double d, mpz_srcptr w)
0337   {  __GMPXX_TMPZ_D;    mpz_sub (z, temp, w); }
0338 
0339   static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s)
0340   { mpq_sub(q, r, s); }
0341 
0342   static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l)
0343   {
0344     if (__GMPXX_CONSTANT(l) && l == 0)
0345     {
0346       if (q != r) mpq_set(q, r);
0347     }
0348     else if (__GMPXX_CONSTANT(l) && l == 1)
0349     {
0350       mpz_sub (mpq_numref(q), mpq_numref(r), mpq_denref(r));
0351       if (q != r) mpz_set(mpq_denref(q), mpq_denref(r));
0352     }
0353     else
0354     {
0355       if (q == r)
0356         mpz_submul_ui(mpq_numref(q), mpq_denref(q), l);
0357       else
0358       {
0359         mpz_mul_ui(mpq_numref(q), mpq_denref(r), l);
0360         mpz_sub(mpq_numref(q), mpq_numref(r), mpq_numref(q));
0361         mpz_set(mpq_denref(q), mpq_denref(r));
0362       }
0363     }
0364   }
0365   static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r)
0366   { eval(q, r, l); mpq_neg(q, q); }
0367   static void eval(mpq_ptr q, mpq_srcptr r, signed long int l)
0368   {
0369     if (l >= 0)
0370       eval(q, r, static_cast<unsigned long>(l));
0371     else
0372       __gmp_binary_plus::eval(q, r, -static_cast<unsigned long>(l));
0373   }
0374   static void eval(mpq_ptr q, signed long int l, mpq_srcptr r)
0375   { eval(q, r, l); mpq_neg(q, q); }
0376   static void eval(mpq_ptr q, mpq_srcptr r, double d)
0377   {  __GMPXX_TMPQ_D;    mpq_sub (q, r, temp); }
0378   static void eval(mpq_ptr q, double d, mpq_srcptr r)
0379   {  __GMPXX_TMPQ_D;    mpq_sub (q, temp, r); }
0380 
0381   static void eval(mpq_ptr q, mpq_srcptr r, mpz_srcptr z)
0382   {
0383     if (q == r)
0384       mpz_submul(mpq_numref(q), mpq_denref(q), z);
0385     else
0386     {
0387       mpz_mul(mpq_numref(q), mpq_denref(r), z);
0388       mpz_sub(mpq_numref(q), mpq_numref(r), mpq_numref(q));
0389       mpz_set(mpq_denref(q), mpq_denref(r));
0390     }
0391   }
0392   static void eval(mpq_ptr q, mpz_srcptr z, mpq_srcptr r)
0393   { eval(q, r, z); mpq_neg(q, q); }
0394 
0395   static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)
0396   { mpf_sub(f, g, h); }
0397 
0398   static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l)
0399   { mpf_sub_ui(f, g, l); }
0400   static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g)
0401   { mpf_ui_sub(f, l, g); }
0402   static void eval(mpf_ptr f, mpf_srcptr g, signed long int l)
0403   {
0404     if (l >= 0)
0405       mpf_sub_ui(f, g, l);
0406     else
0407       mpf_add_ui(f, g, -static_cast<unsigned long>(l));
0408   }
0409   static void eval(mpf_ptr f, signed long int l, mpf_srcptr g)
0410   {
0411     if (l >= 0)
0412       mpf_sub_ui(f, g, l);
0413     else
0414       mpf_add_ui(f, g, -static_cast<unsigned long>(l));
0415     mpf_neg(f, f);
0416   }
0417   static void eval(mpf_ptr f, mpf_srcptr g, double d)
0418   {
0419     mpf_t temp;
0420     mpf_init2(temp, 8*sizeof(double));
0421     mpf_set_d(temp, d);
0422     mpf_sub(f, g, temp);
0423     mpf_clear(temp);
0424   }
0425   static void eval(mpf_ptr f, double d, mpf_srcptr g)
0426   {
0427     mpf_t temp;
0428     mpf_init2(temp, 8*sizeof(double));
0429     mpf_set_d(temp, d);
0430     mpf_sub(f, temp, g);
0431     mpf_clear(temp);
0432   }
0433 };
0434 
0435 // defined here so it can reference __gmp_binary_minus
0436 inline void
0437 __gmp_binary_plus::eval(mpq_ptr q, mpq_srcptr r, signed long int l)
0438 {
0439   if (l >= 0)
0440     eval(q, r, static_cast<unsigned long>(l));
0441   else
0442     __gmp_binary_minus::eval(q, r, -static_cast<unsigned long>(l));
0443 }
0444 
0445 struct __gmp_binary_lshift
0446 {
0447   static void eval(mpz_ptr z, mpz_srcptr w, mp_bitcnt_t l)
0448   {
0449     if (__GMPXX_CONSTANT(l) && (l == 0))
0450     {
0451       if (z != w) mpz_set(z, w);
0452     }
0453     else
0454       mpz_mul_2exp(z, w, l);
0455   }
0456   static void eval(mpq_ptr q, mpq_srcptr r, mp_bitcnt_t l)
0457   {
0458     if (__GMPXX_CONSTANT(l) && (l == 0))
0459     {
0460       if (q != r) mpq_set(q, r);
0461     }
0462     else
0463       mpq_mul_2exp(q, r, l);
0464   }
0465   static void eval(mpf_ptr f, mpf_srcptr g, mp_bitcnt_t l)
0466   { mpf_mul_2exp(f, g, l); }
0467 };
0468 
0469 struct __gmp_binary_rshift
0470 {
0471   static void eval(mpz_ptr z, mpz_srcptr w, mp_bitcnt_t l)
0472   {
0473     if (__GMPXX_CONSTANT(l) && (l == 0))
0474     {
0475       if (z != w) mpz_set(z, w);
0476     }
0477     else
0478       mpz_fdiv_q_2exp(z, w, l);
0479   }
0480   static void eval(mpq_ptr q, mpq_srcptr r, mp_bitcnt_t l)
0481   {
0482     if (__GMPXX_CONSTANT(l) && (l == 0))
0483     {
0484       if (q != r) mpq_set(q, r);
0485     }
0486     else
0487       mpq_div_2exp(q, r, l);
0488   }
0489   static void eval(mpf_ptr f, mpf_srcptr g, mp_bitcnt_t l)
0490   { mpf_div_2exp(f, g, l); }
0491 };
0492 
0493 struct __gmp_binary_multiplies
0494 {
0495   static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
0496   { mpz_mul(z, w, v); }
0497 
0498   static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
0499   {
0500 // gcc-3.3 doesn't have __builtin_ctzl. Don't bother optimizing for old gcc.
0501 #if __GMP_GNUC_PREREQ(3, 4)
0502     if (__GMPXX_CONSTANT(l) && (l & (l-1)) == 0)
0503     {
0504       if (l == 0)
0505       {
0506         z->_mp_size = 0;
0507       }
0508       else
0509       {
0510         __gmp_binary_lshift::eval(z, w, __builtin_ctzl(l));
0511       }
0512     }
0513     else
0514 #endif
0515       mpz_mul_ui(z, w, l);
0516   }
0517   static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
0518   { eval(z, w, l); }
0519   static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
0520   {
0521     if (__GMPXX_CONSTANT_TRUE(l >= 0))
0522       eval(z, w, static_cast<unsigned long>(l));
0523     else if (__GMPXX_CONSTANT_TRUE(l <= 0))
0524       {
0525         eval(z, w, -static_cast<unsigned long>(l));
0526     mpz_neg(z, z);
0527       }
0528     else
0529       mpz_mul_si (z, w, l);
0530   }
0531   static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
0532   { eval(z, w, l); }
0533   static void eval(mpz_ptr z, mpz_srcptr w, double d)
0534   {  __GMPXX_TMPZ_D;    mpz_mul (z, w, temp); }
0535   static void eval(mpz_ptr z, double d, mpz_srcptr w)
0536   { eval(z, w, d); }
0537 
0538   static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s)
0539   { mpq_mul(q, r, s); }
0540 
0541   static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l)
0542   {
0543 #if __GMP_GNUC_PREREQ(3, 4)
0544     if (__GMPXX_CONSTANT(l) && (l & (l-1)) == 0)
0545     {
0546       if (l == 0)
0547       {
0548     mpq_set_ui(q, 0, 1);
0549       }
0550       else
0551       {
0552         __gmp_binary_lshift::eval(q, r, __builtin_ctzl(l));
0553       }
0554     }
0555     else
0556 #endif
0557     {
0558       __GMPXX_TMPQ_UI;
0559       mpq_mul (q, r, temp);
0560     }
0561   }
0562   static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r)
0563   { eval(q, r, l); }
0564   static void eval(mpq_ptr q, mpq_srcptr r, signed long int l)
0565   {
0566     if (__GMPXX_CONSTANT_TRUE(l >= 0))
0567       eval(q, r, static_cast<unsigned long>(l));
0568     else if (__GMPXX_CONSTANT_TRUE(l <= 0))
0569       {
0570         eval(q, r, -static_cast<unsigned long>(l));
0571     mpq_neg(q, q);
0572       }
0573     else
0574       {
0575     __GMPXX_TMPQ_SI;
0576     mpq_mul (q, r, temp);
0577       }
0578   }
0579   static void eval(mpq_ptr q, signed long int l, mpq_srcptr r)
0580   { eval(q, r, l); }
0581   static void eval(mpq_ptr q, mpq_srcptr r, double d)
0582   {  __GMPXX_TMPQ_D;    mpq_mul (q, r, temp); }
0583   static void eval(mpq_ptr q, double d, mpq_srcptr r)
0584   { eval(q, r, d); }
0585 
0586   static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)
0587   { mpf_mul(f, g, h); }
0588 
0589   static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l)
0590   { mpf_mul_ui(f, g, l); }
0591   static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g)
0592   { mpf_mul_ui(f, g, l); }
0593   static void eval(mpf_ptr f, mpf_srcptr g, signed long int l)
0594   {
0595     if (l >= 0)
0596       mpf_mul_ui(f, g, l);
0597     else
0598       {
0599     mpf_mul_ui(f, g, -static_cast<unsigned long>(l));
0600     mpf_neg(f, f);
0601       }
0602   }
0603   static void eval(mpf_ptr f, signed long int l, mpf_srcptr g)
0604   { eval(f, g, l); }
0605   static void eval(mpf_ptr f, mpf_srcptr g, double d)
0606   {
0607     mpf_t temp;
0608     mpf_init2(temp, 8*sizeof(double));
0609     mpf_set_d(temp, d);
0610     mpf_mul(f, g, temp);
0611     mpf_clear(temp);
0612   }
0613   static void eval(mpf_ptr f, double d, mpf_srcptr g)
0614   { eval(f, g, d); }
0615 };
0616 
0617 struct __gmp_binary_divides
0618 {
0619   static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
0620   { mpz_tdiv_q(z, w, v); }
0621 
0622   static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
0623   {
0624 #if __GMP_GNUC_PREREQ(3, 4)
0625     // Don't optimize division by 0...
0626     if (__GMPXX_CONSTANT(l) && (l & (l-1)) == 0 && l != 0)
0627     {
0628       if (l == 1)
0629       {
0630         if (z != w) mpz_set(z, w);
0631       }
0632       else
0633         mpz_tdiv_q_2exp(z, w, __builtin_ctzl(l));
0634         // warning: do not use rshift (fdiv)
0635     }
0636     else
0637 #endif
0638       mpz_tdiv_q_ui(z, w, l);
0639   }
0640   static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
0641   {
0642     if (mpz_sgn(w) >= 0)
0643       {
0644     if (mpz_fits_ulong_p(w))
0645       mpz_set_ui(z, l / mpz_get_ui(w));
0646     else
0647       mpz_set_ui(z, 0);
0648       }
0649     else
0650       {
0651     mpz_neg(z, w);
0652     if (mpz_fits_ulong_p(z))
0653       {
0654         mpz_set_ui(z, l / mpz_get_ui(z));
0655         mpz_neg(z, z);
0656       }
0657     else
0658       mpz_set_ui(z, 0);
0659       }
0660   }
0661   static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
0662   {
0663     if (l >= 0)
0664       eval(z, w, static_cast<unsigned long>(l));
0665     else
0666       {
0667     eval(z, w, -static_cast<unsigned long>(l));
0668     mpz_neg(z, z);
0669       }
0670   }
0671   static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
0672   {
0673     if (mpz_fits_slong_p(w))
0674       mpz_set_si(z, l / mpz_get_si(w));
0675     else
0676       {
0677         /* if w is bigger than a long then the quotient must be zero, unless
0678            l==LONG_MIN and w==-LONG_MIN in which case the quotient is -1 */
0679         mpz_set_si (z, (mpz_cmpabs_ui (w, __gmpxx_abs_ui(l)) == 0 ? -1 : 0));
0680       }
0681   }
0682   static void eval(mpz_ptr z, mpz_srcptr w, double d)
0683   {  __GMPXX_TMPZ_D;    mpz_tdiv_q (z, w, temp); }
0684   static void eval(mpz_ptr z, double d, mpz_srcptr w)
0685   {  __GMPXX_TMPZ_D;    mpz_tdiv_q (z, temp, w); }
0686 
0687   static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s)
0688   { mpq_div(q, r, s); }
0689 
0690   static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l)
0691   {
0692 #if __GMP_GNUC_PREREQ(3, 4)
0693     if (__GMPXX_CONSTANT(l) && (l & (l-1)) == 0 && l != 0)
0694       __gmp_binary_rshift::eval(q, r, __builtin_ctzl(l));
0695     else
0696 #endif
0697     {
0698       __GMPXX_TMPQ_UI;
0699       mpq_div (q, r, temp);
0700     }
0701   }
0702   static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r)
0703   {
0704     if (__GMPXX_CONSTANT_TRUE(l == 0))
0705       mpq_set_ui(q, 0, 1);
0706     else if (__GMPXX_CONSTANT_TRUE(l == 1))
0707       mpq_inv(q, r);
0708     else
0709       {
0710     __GMPXX_TMPQ_UI;
0711     mpq_div (q, temp, r);
0712       }
0713   }
0714   static void eval(mpq_ptr q, mpq_srcptr r, signed long int l)
0715   {
0716     if (__GMPXX_CONSTANT_TRUE(l >= 0))
0717       eval(q, r, static_cast<unsigned long>(l));
0718     else if (__GMPXX_CONSTANT_TRUE(l <= 0))
0719       {
0720         eval(q, r, -static_cast<unsigned long>(l));
0721     mpq_neg(q, q);
0722       }
0723     else
0724       {
0725     __GMPXX_TMPQ_SI;
0726     mpq_div (q, r, temp);
0727       }
0728   }
0729   static void eval(mpq_ptr q, signed long int l, mpq_srcptr r)
0730   {
0731     if (__GMPXX_CONSTANT_TRUE(l == 0))
0732       mpq_set_ui(q, 0, 1);
0733     else if (__GMPXX_CONSTANT_TRUE(l == 1))
0734       mpq_inv(q, r);
0735     else if (__GMPXX_CONSTANT_TRUE(l == -1))
0736       {
0737     mpq_inv(q, r);
0738     mpq_neg(q, q);
0739       }
0740     else
0741       {
0742     __GMPXX_TMPQ_SI;
0743     mpq_div (q, temp, r);
0744       }
0745   }
0746   static void eval(mpq_ptr q, mpq_srcptr r, double d)
0747   {  __GMPXX_TMPQ_D;    mpq_div (q, r, temp); }
0748   static void eval(mpq_ptr q, double d, mpq_srcptr r)
0749   {  __GMPXX_TMPQ_D;    mpq_div (q, temp, r); }
0750 
0751   static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)
0752   { mpf_div(f, g, h); }
0753 
0754   static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l)
0755   { mpf_div_ui(f, g, l); }
0756   static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g)
0757   { mpf_ui_div(f, l, g); }
0758   static void eval(mpf_ptr f, mpf_srcptr g, signed long int l)
0759   {
0760     if (l >= 0)
0761       mpf_div_ui(f, g, l);
0762     else
0763       {
0764     mpf_div_ui(f, g, -static_cast<unsigned long>(l));
0765     mpf_neg(f, f);
0766       }
0767   }
0768   static void eval(mpf_ptr f, signed long int l, mpf_srcptr g)
0769   {
0770     if (l >= 0)
0771       mpf_ui_div(f, l, g);
0772     else
0773       {
0774     mpf_ui_div(f, -static_cast<unsigned long>(l), g);
0775     mpf_neg(f, f);
0776       }
0777   }
0778   static void eval(mpf_ptr f, mpf_srcptr g, double d)
0779   {
0780     mpf_t temp;
0781     mpf_init2(temp, 8*sizeof(double));
0782     mpf_set_d(temp, d);
0783     mpf_div(f, g, temp);
0784     mpf_clear(temp);
0785   }
0786   static void eval(mpf_ptr f, double d, mpf_srcptr g)
0787   {
0788     mpf_t temp;
0789     mpf_init2(temp, 8*sizeof(double));
0790     mpf_set_d(temp, d);
0791     mpf_div(f, temp, g);
0792     mpf_clear(temp);
0793   }
0794 };
0795 
0796 struct __gmp_binary_modulus
0797 {
0798   static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
0799   { mpz_tdiv_r(z, w, v); }
0800 
0801   static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
0802   { mpz_tdiv_r_ui(z, w, l); }
0803   static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
0804   {
0805     if (mpz_sgn(w) >= 0)
0806       {
0807     if (mpz_fits_ulong_p(w))
0808       mpz_set_ui(z, l % mpz_get_ui(w));
0809     else
0810       mpz_set_ui(z, l);
0811       }
0812     else
0813       {
0814     mpz_neg(z, w);
0815     if (mpz_fits_ulong_p(z))
0816       mpz_set_ui(z, l % mpz_get_ui(z));
0817     else
0818       mpz_set_ui(z, l);
0819       }
0820   }
0821   static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
0822   {
0823     mpz_tdiv_r_ui (z, w, __gmpxx_abs_ui(l));
0824   }
0825   static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
0826   {
0827     if (mpz_fits_slong_p(w))
0828       mpz_set_si(z, l % mpz_get_si(w));
0829     else
0830       {
0831         /* if w is bigger than a long then the remainder is l unchanged,
0832            unless l==LONG_MIN and w==-LONG_MIN in which case it's 0 */
0833         mpz_set_si (z, mpz_cmpabs_ui (w, __gmpxx_abs_ui(l)) == 0 ? 0 : l);
0834       }
0835   }
0836   static void eval(mpz_ptr z, mpz_srcptr w, double d)
0837   {  __GMPXX_TMPZ_D;    mpz_tdiv_r (z, w, temp); }
0838   static void eval(mpz_ptr z, double d, mpz_srcptr w)
0839   {  __GMPXX_TMPZ_D;    mpz_tdiv_r (z, temp, w); }
0840 };
0841 
0842 struct __gmp_binary_and
0843 {
0844   static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
0845   { mpz_and(z, w, v); }
0846 
0847   static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
0848   {  __GMPXX_TMPZ_UI;   mpz_and (z, w, temp);  }
0849   static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
0850   { eval(z, w, l);  }
0851   static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
0852   {  __GMPXX_TMPZ_SI;   mpz_and (z, w, temp);  }
0853   static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
0854   { eval(z, w, l);  }
0855   static void eval(mpz_ptr z, mpz_srcptr w, double d)
0856   {  __GMPXX_TMPZ_D;    mpz_and (z, w, temp); }
0857   static void eval(mpz_ptr z, double d, mpz_srcptr w)
0858   { eval(z, w, d);  }
0859 };
0860 
0861 struct __gmp_binary_ior
0862 {
0863   static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
0864   { mpz_ior(z, w, v); }
0865   static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
0866   {  __GMPXX_TMPZ_UI;   mpz_ior (z, w, temp);  }
0867   static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
0868   { eval(z, w, l);  }
0869   static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
0870   {  __GMPXX_TMPZ_SI;   mpz_ior (z, w, temp);  }
0871   static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
0872   { eval(z, w, l);  }
0873   static void eval(mpz_ptr z, mpz_srcptr w, double d)
0874   {  __GMPXX_TMPZ_D;    mpz_ior (z, w, temp); }
0875   static void eval(mpz_ptr z, double d, mpz_srcptr w)
0876   { eval(z, w, d);  }
0877 };
0878 
0879 struct __gmp_binary_xor
0880 {
0881   static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
0882   { mpz_xor(z, w, v); }
0883   static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
0884   {  __GMPXX_TMPZ_UI;   mpz_xor (z, w, temp);  }
0885   static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
0886   { eval(z, w, l);  }
0887   static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
0888   {  __GMPXX_TMPZ_SI;   mpz_xor (z, w, temp);  }
0889   static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
0890   { eval(z, w, l);  }
0891   static void eval(mpz_ptr z, mpz_srcptr w, double d)
0892   {  __GMPXX_TMPZ_D;    mpz_xor (z, w, temp); }
0893   static void eval(mpz_ptr z, double d, mpz_srcptr w)
0894   { eval(z, w, d);  }
0895 };
0896 
0897 struct __gmp_cmp_function
0898 {
0899   static int eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w); }
0900 
0901   static int eval(mpz_srcptr z, unsigned long int l)
0902   { return mpz_cmp_ui(z, l); }
0903   static int eval(unsigned long int l, mpz_srcptr z)
0904   { return -mpz_cmp_ui(z, l); }
0905   static int eval(mpz_srcptr z, signed long int l)
0906   { return mpz_cmp_si(z, l); }
0907   static int eval(signed long int l, mpz_srcptr z)
0908   { return -mpz_cmp_si(z, l); }
0909   static int eval(mpz_srcptr z, double d)
0910   { return mpz_cmp_d(z, d); }
0911   static int eval(double d, mpz_srcptr z)
0912   { return -mpz_cmp_d(z, d); }
0913 
0914   static int eval(mpq_srcptr q, mpq_srcptr r) { return mpq_cmp(q, r); }
0915 
0916   static int eval(mpq_srcptr q, unsigned long int l)
0917   { return mpq_cmp_ui(q, l, 1); }
0918   static int eval(unsigned long int l, mpq_srcptr q)
0919   { return -mpq_cmp_ui(q, l, 1); }
0920   static int eval(mpq_srcptr q, signed long int l)
0921   { return mpq_cmp_si(q, l, 1); }
0922   static int eval(signed long int l, mpq_srcptr q)
0923   { return -mpq_cmp_si(q, l, 1); }
0924   static int eval(mpq_srcptr q, double d)
0925   {  __GMPXX_TMPQ_D;    return mpq_cmp (q, temp); }
0926   static int eval(double d, mpq_srcptr q)
0927   {  __GMPXX_TMPQ_D;    return mpq_cmp (temp, q); }
0928   static int eval(mpq_srcptr q, mpz_srcptr z)
0929   { return mpq_cmp_z(q, z); }
0930   static int eval(mpz_srcptr z, mpq_srcptr q)
0931   { return -mpq_cmp_z(q, z); }
0932 
0933   static int eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g); }
0934 
0935   static int eval(mpf_srcptr f, unsigned long int l)
0936   { return mpf_cmp_ui(f, l); }
0937   static int eval(unsigned long int l, mpf_srcptr f)
0938   { return -mpf_cmp_ui(f, l); }
0939   static int eval(mpf_srcptr f, signed long int l)
0940   { return mpf_cmp_si(f, l); }
0941   static int eval(signed long int l, mpf_srcptr f)
0942   { return -mpf_cmp_si(f, l); }
0943   static int eval(mpf_srcptr f, double d)
0944   { return mpf_cmp_d(f, d); }
0945   static int eval(double d, mpf_srcptr f)
0946   { return -mpf_cmp_d(f, d); }
0947   static int eval(mpf_srcptr f, mpz_srcptr z)
0948   { return mpf_cmp_z(f, z); }
0949   static int eval(mpz_srcptr z, mpf_srcptr f)
0950   { return -mpf_cmp_z(f, z); }
0951   static int eval(mpf_srcptr f, mpq_srcptr q)
0952   {
0953     mpf_t qf;
0954     mpf_init(qf); /* Should we use the precision of f?  */
0955     mpf_set_q(qf, q);
0956     int ret = eval(f, qf);
0957     mpf_clear(qf);
0958     return ret;
0959   }
0960   static int eval(mpq_srcptr q, mpf_srcptr f)
0961   { return -eval(f, q); }
0962 };
0963 
0964 struct __gmp_binary_equal
0965 {
0966   static bool eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w) == 0; }
0967 
0968   static bool eval(mpz_srcptr z, unsigned long int l)
0969   { return mpz_cmp_ui(z, l) == 0; }
0970   static bool eval(unsigned long int l, mpz_srcptr z)
0971   { return eval(z, l); }
0972   static bool eval(mpz_srcptr z, signed long int l)
0973   { return mpz_cmp_si(z, l) == 0; }
0974   static bool eval(signed long int l, mpz_srcptr z)
0975   { return eval(z, l); }
0976   static bool eval(mpz_srcptr z, double d)
0977   { return mpz_cmp_d(z, d) == 0; }
0978   static bool eval(double d, mpz_srcptr z)
0979   { return eval(z, d); }
0980 
0981   static bool eval(mpq_srcptr q, mpq_srcptr r)
0982   { return mpq_equal(q, r) != 0; }
0983 
0984   static bool eval(mpq_srcptr q, unsigned long int l)
0985   { return ((__GMPXX_CONSTANT(l) && l == 0) ||
0986         mpz_cmp_ui(mpq_denref(q), 1) == 0) &&
0987       mpz_cmp_ui(mpq_numref(q), l) == 0; }
0988   static bool eval(unsigned long int l, mpq_srcptr q)
0989   { return eval(q, l); }
0990   static bool eval(mpq_srcptr q, signed long int l)
0991   { return ((__GMPXX_CONSTANT(l) && l == 0) ||
0992         mpz_cmp_ui(mpq_denref(q), 1) == 0) &&
0993       mpz_cmp_si(mpq_numref(q), l) == 0; }
0994   static bool eval(signed long int l, mpq_srcptr q)
0995   { return eval(q, l); }
0996   static bool eval(mpq_srcptr q, double d)
0997   {  __GMPXX_TMPQ_D;    return mpq_equal (q, temp) != 0; }
0998   static bool eval(double d, mpq_srcptr q)
0999   { 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__ */