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