xref: /netbsd-src/external/lgpl3/gmp/dist/gmpxx.h (revision 796c32c94f6e154afc9de0f63da35c91bb739b45)
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_cmp_function
862 {
863   static int eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w); }
864 
865   static int eval(mpz_srcptr z, unsigned long int l)
866   { return mpz_cmp_ui(z, l); }
867   static int eval(unsigned long int l, mpz_srcptr z)
868   { return -mpz_cmp_ui(z, l); }
869   static int eval(mpz_srcptr z, signed long int l)
870   { return mpz_cmp_si(z, l); }
871   static int eval(signed long int l, mpz_srcptr z)
872   { return -mpz_cmp_si(z, l); }
873   static int eval(mpz_srcptr z, double d)
874   { return mpz_cmp_d(z, d); }
875   static int eval(double d, mpz_srcptr z)
876   { return -mpz_cmp_d(z, d); }
877 
878   static int eval(mpq_srcptr q, mpq_srcptr r) { return mpq_cmp(q, r); }
879 
880   static int eval(mpq_srcptr q, unsigned long int l)
881   { return mpq_cmp_ui(q, l, 1); }
882   static int eval(unsigned long int l, mpq_srcptr q)
883   { return -mpq_cmp_ui(q, l, 1); }
884   static int eval(mpq_srcptr q, signed long int l)
885   { return mpq_cmp_si(q, l, 1); }
886   static int eval(signed long int l, mpq_srcptr q)
887   { return -mpq_cmp_si(q, l, 1); }
888   static int eval(mpq_srcptr q, double d)
889   {  __GMPXX_TMPQ_D;    return mpq_cmp (q, temp); }
890   static int eval(double d, mpq_srcptr q)
891   {  __GMPXX_TMPQ_D;    return mpq_cmp (temp, q); }
892   static int eval(mpq_srcptr q, mpz_srcptr z)
893   { return mpq_cmp_z(q, z); }
894   static int eval(mpz_srcptr z, mpq_srcptr q)
895   { return -mpq_cmp_z(q, z); }
896 
897   static int eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g); }
898 
899   static int eval(mpf_srcptr f, unsigned long int l)
900   { return mpf_cmp_ui(f, l); }
901   static int eval(unsigned long int l, mpf_srcptr f)
902   { return -mpf_cmp_ui(f, l); }
903   static int eval(mpf_srcptr f, signed long int l)
904   { return mpf_cmp_si(f, l); }
905   static int eval(signed long int l, mpf_srcptr f)
906   { return -mpf_cmp_si(f, l); }
907   static int eval(mpf_srcptr f, double d)
908   { return mpf_cmp_d(f, d); }
909   static int eval(double d, mpf_srcptr f)
910   { return -mpf_cmp_d(f, d); }
911   static int eval(mpf_srcptr f, mpz_srcptr z)
912   { return mpf_cmp_z(f, z); }
913   static int eval(mpz_srcptr z, mpf_srcptr f)
914   { return -mpf_cmp_z(f, z); }
915   static int eval(mpf_srcptr f, mpq_srcptr q)
916   {
917     mpf_t qf;
918     mpf_init(qf); /* Should we use the precision of f?  */
919     mpf_set_q(qf, q);
920     int ret = eval(f, qf);
921     mpf_clear(qf);
922     return ret;
923   }
924   static int eval(mpq_srcptr q, mpf_srcptr f)
925   { return -eval(f, q); }
926 };
927 
928 struct __gmp_binary_equal
929 {
930   static bool eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w) == 0; }
931 
932   static bool eval(mpz_srcptr z, unsigned long int l)
933   { return mpz_cmp_ui(z, l) == 0; }
934   static bool eval(unsigned long int l, mpz_srcptr z)
935   { return eval(z, l); }
936   static bool eval(mpz_srcptr z, signed long int l)
937   { return mpz_cmp_si(z, l) == 0; }
938   static bool eval(signed long int l, mpz_srcptr z)
939   { return eval(z, l); }
940   static bool eval(mpz_srcptr z, double d)
941   { return mpz_cmp_d(z, d) == 0; }
942   static bool eval(double d, mpz_srcptr z)
943   { return eval(z, d); }
944 
945   static bool eval(mpq_srcptr q, mpq_srcptr r)
946   { return mpq_equal(q, r) != 0; }
947 
948   static bool eval(mpq_srcptr q, unsigned long int l)
949   { return mpq_cmp_ui(q, l, 1) == 0; }
950   static bool eval(unsigned long int l, mpq_srcptr q)
951   { return eval(q, l); }
952   static bool eval(mpq_srcptr q, signed long int l)
953   { return mpq_cmp_si(q, l, 1) == 0; }
954   static bool eval(signed long int l, mpq_srcptr q)
955   { return eval(q, l); }
956   static bool eval(mpq_srcptr q, double d)
957   {  __GMPXX_TMPQ_D;    return mpq_equal (q, temp) != 0; }
958   static bool eval(double d, mpq_srcptr q)
959   { return eval(q, d); }
960   static bool eval(mpq_srcptr q, mpz_srcptr z)
961   { return mpq_cmp_z(q, z) == 0; }
962   static bool eval(mpz_srcptr z, mpq_srcptr q)
963   { return eval(q, z); }
964 
965   static bool eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g) == 0; }
966 
967   static bool eval(mpf_srcptr f, unsigned long int l)
968   { return mpf_cmp_ui(f, l) == 0; }
969   static bool eval(unsigned long int l, mpf_srcptr f)
970   { return eval(f, l); }
971   static bool eval(mpf_srcptr f, signed long int l)
972   { return mpf_cmp_si(f, l) == 0; }
973   static bool eval(signed long int l, mpf_srcptr f)
974   { return eval(f, l); }
975   static bool eval(mpf_srcptr f, double d)
976   { return mpf_cmp_d(f, d) == 0; }
977   static bool eval(double d, mpf_srcptr f)
978   { return eval(f, d); }
979   static bool eval(mpf_srcptr f, mpz_srcptr z)
980   { return mpf_cmp_z(f, z) == 0; }
981   static bool eval(mpz_srcptr z, mpf_srcptr f)
982   { return eval(f, z); }
983   static bool eval(mpf_srcptr f, mpq_srcptr q)
984   { return __gmp_cmp_function::eval(f, q) == 0; }
985   static bool eval(mpq_srcptr q, mpf_srcptr f)
986   { return eval(f, q); }
987 };
988 
989 struct __gmp_binary_less
990 {
991   static bool eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w) < 0; }
992 
993   static bool eval(mpz_srcptr z, unsigned long int l)
994   { return mpz_cmp_ui(z, l) < 0; }
995   static bool eval(unsigned long int l, mpz_srcptr z)
996   { return mpz_cmp_ui(z, l) > 0; }
997   static bool eval(mpz_srcptr z, signed long int l)
998   { return mpz_cmp_si(z, l) < 0; }
999   static bool eval(signed long int l, mpz_srcptr z)
1000   { return mpz_cmp_si(z, l) > 0; }
1001   static bool eval(mpz_srcptr z, double d)
1002   { return mpz_cmp_d(z, d) < 0; }
1003   static bool eval(double d, mpz_srcptr z)
1004   { return mpz_cmp_d(z, d) > 0; }
1005 
1006   static bool eval(mpq_srcptr q, mpq_srcptr r) { return mpq_cmp(q, r) < 0; }
1007 
1008   static bool eval(mpq_srcptr q, unsigned long int l)
1009   { return mpq_cmp_ui(q, l, 1) < 0; }
1010   static bool eval(unsigned long int l, mpq_srcptr q)
1011   { return mpq_cmp_ui(q, l, 1) > 0; }
1012   static bool eval(mpq_srcptr q, signed long int l)
1013   { return mpq_cmp_si(q, l, 1) < 0; }
1014   static bool eval(signed long int l, mpq_srcptr q)
1015   { return mpq_cmp_si(q, l, 1) > 0; }
1016   static bool eval(mpq_srcptr q, double d)
1017   {  __GMPXX_TMPQ_D;    return mpq_cmp (q, temp) < 0; }
1018   static bool eval(double d, mpq_srcptr q)
1019   {  __GMPXX_TMPQ_D;    return mpq_cmp (temp, q) < 0; }
1020   static bool eval(mpq_srcptr q, mpz_srcptr z)
1021   { return mpq_cmp_z(q, z) < 0; }
1022   static bool eval(mpz_srcptr z, mpq_srcptr q)
1023   { return mpq_cmp_z(q, z) > 0; }
1024 
1025   static bool eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g) < 0; }
1026 
1027   static bool eval(mpf_srcptr f, unsigned long int l)
1028   { return mpf_cmp_ui(f, l) < 0; }
1029   static bool eval(unsigned long int l, mpf_srcptr f)
1030   { return mpf_cmp_ui(f, l) > 0; }
1031   static bool eval(mpf_srcptr f, signed long int l)
1032   { return mpf_cmp_si(f, l) < 0; }
1033   static bool eval(signed long int l, mpf_srcptr f)
1034   { return mpf_cmp_si(f, l) > 0; }
1035   static bool eval(mpf_srcptr f, double d)
1036   { return mpf_cmp_d(f, d) < 0; }
1037   static bool eval(double d, mpf_srcptr f)
1038   { return mpf_cmp_d(f, d) > 0; }
1039   static bool eval(mpf_srcptr f, mpz_srcptr z)
1040   { return mpf_cmp_z(f, z) < 0; }
1041   static bool eval(mpz_srcptr z, mpf_srcptr f)
1042   { return mpf_cmp_z(f, z) > 0; }
1043   static bool eval(mpf_srcptr f, mpq_srcptr q)
1044   { return __gmp_cmp_function::eval(f, q) < 0; }
1045   static bool eval(mpq_srcptr q, mpf_srcptr f)
1046   { return __gmp_cmp_function::eval(q, f) < 0; }
1047 };
1048 
1049 struct __gmp_binary_greater
1050 {
1051   template <class T, class U>
1052   static inline bool eval(T t, U u) { return __gmp_binary_less::eval(u, t); }
1053 };
1054 
1055 struct __gmp_unary_increment
1056 {
1057   static void eval(mpz_ptr z) { mpz_add_ui(z, z, 1); }
1058   static void eval(mpq_ptr q)
1059   { mpz_add(mpq_numref(q), mpq_numref(q), mpq_denref(q)); }
1060   static void eval(mpf_ptr f) { mpf_add_ui(f, f, 1); }
1061 };
1062 
1063 struct __gmp_unary_decrement
1064 {
1065   static void eval(mpz_ptr z) { mpz_sub_ui(z, z, 1); }
1066   static void eval(mpq_ptr q)
1067   { mpz_sub(mpq_numref(q), mpq_numref(q), mpq_denref(q)); }
1068   static void eval(mpf_ptr f) { mpf_sub_ui(f, f, 1); }
1069 };
1070 
1071 struct __gmp_abs_function
1072 {
1073   static void eval(mpz_ptr z, mpz_srcptr w) { mpz_abs(z, w); }
1074   static void eval(mpq_ptr q, mpq_srcptr r) { mpq_abs(q, r); }
1075   static void eval(mpf_ptr f, mpf_srcptr g) { mpf_abs(f, g); }
1076 };
1077 
1078 struct __gmp_trunc_function
1079 {
1080   static void eval(mpf_ptr f, mpf_srcptr g) { mpf_trunc(f, g); }
1081 };
1082 
1083 struct __gmp_floor_function
1084 {
1085   static void eval(mpf_ptr f, mpf_srcptr g) { mpf_floor(f, g); }
1086 };
1087 
1088 struct __gmp_ceil_function
1089 {
1090   static void eval(mpf_ptr f, mpf_srcptr g) { mpf_ceil(f, g); }
1091 };
1092 
1093 struct __gmp_sqrt_function
1094 {
1095   static void eval(mpz_ptr z, mpz_srcptr w) { mpz_sqrt(z, w); }
1096   static void eval(mpf_ptr f, mpf_srcptr g) { mpf_sqrt(f, g); }
1097 };
1098 
1099 struct __gmp_hypot_function
1100 {
1101   static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)
1102   {
1103     mpf_t temp;
1104     mpf_init2(temp, mpf_get_prec(f));
1105     mpf_mul(temp, g, g);
1106     mpf_mul(f, h, h);
1107     mpf_add(f, f, temp);
1108     mpf_sqrt(f, f);
1109     mpf_clear(temp);
1110   }
1111 
1112   static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l)
1113   {
1114     mpf_t temp;
1115     mpf_init2(temp, mpf_get_prec(f));
1116     mpf_mul(temp, g, g);
1117     mpf_set_ui(f, l);
1118     mpf_mul_ui(f, f, l);
1119     mpf_add(f, f, temp);
1120     mpf_clear(temp);
1121     mpf_sqrt(f, f);
1122   }
1123   static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g)
1124   { eval(f, g, l); }
1125   static void eval(mpf_ptr f, mpf_srcptr g, signed long int l)
1126   { eval(f, g, __gmpxx_abs_ui(l)); }
1127   static void eval(mpf_ptr f, signed long int l, mpf_srcptr g)
1128   { eval(f, g, l); }
1129   static void eval(mpf_ptr f, mpf_srcptr g, double d)
1130   {
1131     mpf_t temp;
1132     mpf_init2(temp, mpf_get_prec(f));
1133     mpf_mul(temp, g, g);
1134     mpf_set_d(f, d);
1135     mpf_mul(f, f, f);
1136     mpf_add(f, f, temp);
1137     mpf_sqrt(f, f);
1138     mpf_clear(temp);
1139   }
1140   static void eval(mpf_ptr f, double d, mpf_srcptr g)
1141   { eval(f, g, d); }
1142 };
1143 
1144 struct __gmp_sgn_function
1145 {
1146   static int eval(mpz_srcptr z) { return mpz_sgn(z); }
1147   static int eval(mpq_srcptr q) { return mpq_sgn(q); }
1148   static int eval(mpf_srcptr f) { return mpf_sgn(f); }
1149 };
1150 
1151 struct __gmp_gcd_function
1152 {
1153   static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
1154   { mpz_gcd(z, w, v); }
1155   static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
1156   { mpz_gcd_ui(z, w, l); }
1157   static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
1158   { eval(z, w, l); }
1159   static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
1160   { eval(z, w, __gmpxx_abs_ui(l)); }
1161   static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
1162   { eval(z, w, l); }
1163   static void eval(mpz_ptr z, mpz_srcptr w, double d)
1164   {  __GMPXX_TMPZ_D;    mpz_gcd (z, w, temp); }
1165   static void eval(mpz_ptr z, double d, mpz_srcptr w)
1166   { eval(z, w, d); }
1167 };
1168 
1169 struct __gmp_lcm_function
1170 {
1171   static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
1172   { mpz_lcm(z, w, v); }
1173   static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
1174   { mpz_lcm_ui(z, w, l); }
1175   static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
1176   { eval(z, w, l); }
1177   static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
1178   { eval(z, w, __gmpxx_abs_ui(l)); }
1179   static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
1180   { eval(z, w, l); }
1181   static void eval(mpz_ptr z, mpz_srcptr w, double d)
1182   {  __GMPXX_TMPZ_D;    mpz_lcm (z, w, temp); }
1183   static void eval(mpz_ptr z, double d, mpz_srcptr w)
1184   { eval(z, w, d); }
1185 };
1186 
1187 struct __gmp_rand_function
1188 {
1189   static void eval(mpz_ptr z, gmp_randstate_t s, mp_bitcnt_t l)
1190   { mpz_urandomb(z, s, l); }
1191   static void eval(mpz_ptr z, gmp_randstate_t s, mpz_srcptr w)
1192   { mpz_urandomm(z, s, w); }
1193   static void eval(mpf_ptr f, gmp_randstate_t s, mp_bitcnt_t prec)
1194   { mpf_urandomb(f, s, prec); }
1195 };
1196 
1197 
1198 /**************** Auxiliary classes ****************/
1199 
1200 /* this is much the same as gmp_allocated_string in gmp-impl.h
1201    since gmp-impl.h is not publicly available, I redefine it here
1202    I use a different name to avoid possible clashes */
1203 
1204 extern "C" {
1205   typedef void (*__gmp_freefunc_t) (void *, size_t);
1206 }
1207 struct __gmp_alloc_cstring
1208 {
1209   char *str;
1210   __gmp_alloc_cstring(char *s) { str = s; }
1211   ~__gmp_alloc_cstring()
1212   {
1213     __gmp_freefunc_t freefunc;
1214     mp_get_memory_functions (NULL, NULL, &freefunc);
1215     (*freefunc) (str, std::strlen(str)+1);
1216   }
1217 };
1218 
1219 
1220 // general expression template class
1221 template <class T, class U>
1222 class __gmp_expr;
1223 
1224 
1225 // templates for resolving expression types
1226 template <class T>
1227 struct __gmp_resolve_ref
1228 {
1229   typedef T ref_type;
1230 };
1231 
1232 template <class T, class U>
1233 struct __gmp_resolve_ref<__gmp_expr<T, U> >
1234 {
1235   typedef const __gmp_expr<T, U> & ref_type;
1236 };
1237 
1238 
1239 template <class T, class U = T>
1240 struct __gmp_resolve_expr;
1241 
1242 template <>
1243 struct __gmp_resolve_expr<mpz_t>
1244 {
1245   typedef mpz_t value_type;
1246   typedef mpz_ptr ptr_type;
1247   typedef mpz_srcptr srcptr_type;
1248 };
1249 
1250 template <>
1251 struct __gmp_resolve_expr<mpq_t>
1252 {
1253   typedef mpq_t value_type;
1254   typedef mpq_ptr ptr_type;
1255   typedef mpq_srcptr srcptr_type;
1256 };
1257 
1258 template <>
1259 struct __gmp_resolve_expr<mpf_t>
1260 {
1261   typedef mpf_t value_type;
1262   typedef mpf_ptr ptr_type;
1263   typedef mpf_srcptr srcptr_type;
1264 };
1265 
1266 template <>
1267 struct __gmp_resolve_expr<mpz_t, mpq_t>
1268 {
1269   typedef mpq_t value_type;
1270 };
1271 
1272 template <>
1273 struct __gmp_resolve_expr<mpq_t, mpz_t>
1274 {
1275   typedef mpq_t value_type;
1276 };
1277 
1278 template <>
1279 struct __gmp_resolve_expr<mpz_t, mpf_t>
1280 {
1281   typedef mpf_t value_type;
1282 };
1283 
1284 template <>
1285 struct __gmp_resolve_expr<mpf_t, mpz_t>
1286 {
1287   typedef mpf_t value_type;
1288 };
1289 
1290 template <>
1291 struct __gmp_resolve_expr<mpq_t, mpf_t>
1292 {
1293   typedef mpf_t value_type;
1294 };
1295 
1296 template <>
1297 struct __gmp_resolve_expr<mpf_t, mpq_t>
1298 {
1299   typedef mpf_t value_type;
1300 };
1301 
1302 #if __GMPXX_USE_CXX11
1303 namespace std {
1304   template <class T, class U, class V, class W>
1305   struct common_type <__gmp_expr<T, U>, __gmp_expr<V, W> >
1306   {
1307   private:
1308     typedef typename __gmp_resolve_expr<T, V>::value_type X;
1309   public:
1310     typedef __gmp_expr<X, X> type;
1311   };
1312 
1313   template <class T, class U>
1314   struct common_type <__gmp_expr<T, U> >
1315   {
1316     typedef __gmp_expr<T, T> type;
1317   };
1318 
1319 #define __GMPXX_DECLARE_COMMON_TYPE(typ)	\
1320   template <class T, class U>			\
1321   struct common_type <__gmp_expr<T, U>, typ >	\
1322   {						\
1323     typedef __gmp_expr<T, T> type;		\
1324   };						\
1325 						\
1326   template <class T, class U>			\
1327   struct common_type <typ, __gmp_expr<T, U> >	\
1328   {						\
1329     typedef __gmp_expr<T, T> type;		\
1330   }
1331 
1332   __GMPXX_DECLARE_COMMON_TYPE(signed char);
1333   __GMPXX_DECLARE_COMMON_TYPE(unsigned char);
1334   __GMPXX_DECLARE_COMMON_TYPE(signed int);
1335   __GMPXX_DECLARE_COMMON_TYPE(unsigned int);
1336   __GMPXX_DECLARE_COMMON_TYPE(signed short int);
1337   __GMPXX_DECLARE_COMMON_TYPE(unsigned short int);
1338   __GMPXX_DECLARE_COMMON_TYPE(signed long int);
1339   __GMPXX_DECLARE_COMMON_TYPE(unsigned long int);
1340   __GMPXX_DECLARE_COMMON_TYPE(float);
1341   __GMPXX_DECLARE_COMMON_TYPE(double);
1342 #undef __GMPXX_DECLARE_COMMON_TYPE
1343 }
1344 #endif
1345 
1346 // classes for evaluating unary and binary expressions
1347 template <class T, class Op>
1348 struct __gmp_unary_expr
1349 {
1350   typename __gmp_resolve_ref<T>::ref_type val;
1351 
1352   __gmp_unary_expr(const T &v) : val(v) { }
1353 private:
1354   __gmp_unary_expr();
1355 };
1356 
1357 template <class T, class U, class Op>
1358 struct __gmp_binary_expr
1359 {
1360   typename __gmp_resolve_ref<T>::ref_type val1;
1361   typename __gmp_resolve_ref<U>::ref_type val2;
1362 
1363   __gmp_binary_expr(const T &v1, const U &v2) : val1(v1), val2(v2) { }
1364 private:
1365   __gmp_binary_expr();
1366 };
1367 
1368 
1369 
1370 /**************** Macros for in-class declarations ****************/
1371 /* This is just repetitive code that is easier to maintain if it's written
1372    only once */
1373 
1374 #define __GMPP_DECLARE_COMPOUND_OPERATOR(fun)                         \
1375   template <class T, class U>                                         \
1376   __gmp_expr<value_type, value_type> & fun(const __gmp_expr<T, U> &);
1377 
1378 #define __GMPN_DECLARE_COMPOUND_OPERATOR(fun) \
1379   __gmp_expr & fun(signed char);              \
1380   __gmp_expr & fun(unsigned char);            \
1381   __gmp_expr & fun(signed int);               \
1382   __gmp_expr & fun(unsigned int);             \
1383   __gmp_expr & fun(signed short int);         \
1384   __gmp_expr & fun(unsigned short int);       \
1385   __gmp_expr & fun(signed long int);          \
1386   __gmp_expr & fun(unsigned long int);        \
1387   __gmp_expr & fun(float);                    \
1388   __gmp_expr & fun(double);                   \
1389   /* __gmp_expr & fun(long double); */
1390 
1391 #define __GMP_DECLARE_COMPOUND_OPERATOR(fun) \
1392 __GMPP_DECLARE_COMPOUND_OPERATOR(fun)        \
1393 __GMPN_DECLARE_COMPOUND_OPERATOR(fun)
1394 
1395 #define __GMP_DECLARE_COMPOUND_OPERATOR_UI(fun) \
1396   __gmp_expr & fun(mp_bitcnt_t);
1397 
1398 #define __GMP_DECLARE_INCREMENT_OPERATOR(fun) \
1399   inline __gmp_expr & fun();                  \
1400   inline __gmp_expr fun(int);
1401 
1402 #define __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS		\
1403   __gmp_expr(signed char c) { init_si(c); }		\
1404   __gmp_expr(unsigned char c) { init_ui(c); }		\
1405   __gmp_expr(signed int i) { init_si(i); }		\
1406   __gmp_expr(unsigned int i) { init_ui(i); }		\
1407   __gmp_expr(signed short int s) { init_si(s); }	\
1408   __gmp_expr(unsigned short int s) { init_ui(s); }	\
1409   __gmp_expr(signed long int l) { init_si(l); }		\
1410   __gmp_expr(unsigned long int l) { init_ui(l); }	\
1411   __gmp_expr(float f) { init_d(f); }			\
1412   __gmp_expr(double d) { init_d(d); }
1413 
1414 #define __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS		\
1415   __gmp_expr & operator=(signed char c) { assign_si(c); return *this; } \
1416   __gmp_expr & operator=(unsigned char c) { assign_ui(c); return *this; } \
1417   __gmp_expr & operator=(signed int i) { assign_si(i); return *this; } \
1418   __gmp_expr & operator=(unsigned int i) { assign_ui(i); return *this; } \
1419   __gmp_expr & operator=(signed short int s) { assign_si(s); return *this; } \
1420   __gmp_expr & operator=(unsigned short int s) { assign_ui(s); return *this; } \
1421   __gmp_expr & operator=(signed long int l) { assign_si(l); return *this; } \
1422   __gmp_expr & operator=(unsigned long int l) { assign_ui(l); return *this; } \
1423   __gmp_expr & operator=(float f) { assign_d(f); return *this; } \
1424   __gmp_expr & operator=(double d) { assign_d(d); return *this; }
1425 
1426 /**************** mpz_class -- wrapper for mpz_t ****************/
1427 
1428 template <>
1429 class __gmp_expr<mpz_t, mpz_t>
1430 {
1431 private:
1432   typedef mpz_t value_type;
1433   value_type mp;
1434 
1435   // Helper functions used for all arithmetic types
1436   void assign_ui(unsigned long l)
1437   {
1438     if (__GMPXX_CONSTANT_TRUE(l == 0))
1439       mp->_mp_size = 0;
1440     else
1441       mpz_set_ui(mp, l);
1442   }
1443   void assign_si(signed long l)
1444   {
1445     if (__GMPXX_CONSTANT_TRUE(l >= 0))
1446       assign_ui(l);
1447     else if (__GMPXX_CONSTANT_TRUE(l <= 0))
1448       {
1449 	assign_ui(-static_cast<unsigned long>(l));
1450 	mpz_neg(mp, mp);
1451       }
1452     else
1453       mpz_set_si(mp, l);
1454   }
1455   void assign_d (double d)
1456   {
1457     mpz_set_d (mp, d);
1458   }
1459 
1460   void init_ui(unsigned long l)
1461   {
1462     if (__GMPXX_CONSTANT_TRUE(l == 0))
1463       mpz_init(mp);
1464     else
1465       mpz_init_set_ui(mp, l);
1466   }
1467   void init_si(signed long l)
1468   {
1469     if (__GMPXX_CONSTANT_TRUE(l >= 0))
1470       init_ui(l);
1471     else if (__GMPXX_CONSTANT_TRUE(l <= 0))
1472       {
1473 	init_ui(-static_cast<unsigned long>(l));
1474 	mpz_neg(mp, mp);
1475       }
1476     else
1477       mpz_init_set_si(mp, l);
1478   }
1479   void init_d (double d)
1480   {
1481     mpz_init_set_d (mp, d);
1482   }
1483 
1484 public:
1485   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }
1486 
1487   // constructors and destructor
1488   __gmp_expr() { mpz_init(mp); }
1489 
1490   __gmp_expr(const __gmp_expr &z) { mpz_init_set(mp, z.mp); }
1491 #if __GMPXX_USE_CXX11
1492   __gmp_expr(__gmp_expr &&z)
1493   { *mp = *z.mp; mpz_init(z.mp); }
1494 #endif
1495   template <class T>
1496   __gmp_expr(const __gmp_expr<mpz_t, T> &expr)
1497   { mpz_init(mp); __gmp_set_expr(mp, expr); }
1498   template <class T, class U>
1499   explicit __gmp_expr(const __gmp_expr<T, U> &expr)
1500   { mpz_init(mp); __gmp_set_expr(mp, expr); }
1501 
1502   __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS
1503 
1504   explicit __gmp_expr(const char *s, int base = 0)
1505   {
1506     if (mpz_init_set_str (mp, s, base) != 0)
1507       {
1508         mpz_clear (mp);
1509         throw std::invalid_argument ("mpz_set_str");
1510       }
1511   }
1512   explicit __gmp_expr(const std::string &s, int base = 0)
1513   {
1514     if (mpz_init_set_str(mp, s.c_str(), base) != 0)
1515       {
1516         mpz_clear (mp);
1517         throw std::invalid_argument ("mpz_set_str");
1518       }
1519   }
1520 
1521   explicit __gmp_expr(mpz_srcptr z) { mpz_init_set(mp, z); }
1522 
1523   ~__gmp_expr() { mpz_clear(mp); }
1524 
1525   void swap(__gmp_expr& z) __GMPXX_NOEXCEPT { std::swap(*mp, *z.mp); }
1526 
1527   // assignment operators
1528   __gmp_expr & operator=(const __gmp_expr &z)
1529   { mpz_set(mp, z.mp); return *this; }
1530 #if __GMPXX_USE_CXX11
1531   __gmp_expr & operator=(__gmp_expr &&z) noexcept
1532   { swap(z); return *this; }
1533 #endif
1534   template <class T, class U>
1535   __gmp_expr<value_type, value_type> & operator=(const __gmp_expr<T, U> &expr)
1536   { __gmp_set_expr(mp, expr); return *this; }
1537 
1538   __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS
1539 
1540   __gmp_expr & operator=(const char *s)
1541   {
1542     if (mpz_set_str (mp, s, 0) != 0)
1543       throw std::invalid_argument ("mpz_set_str");
1544     return *this;
1545   }
1546   __gmp_expr & operator=(const std::string &s)
1547   {
1548     if (mpz_set_str(mp, s.c_str(), 0) != 0)
1549       throw std::invalid_argument ("mpz_set_str");
1550     return *this;
1551   }
1552 
1553   // string input/output functions
1554   int set_str(const char *s, int base)
1555   { return mpz_set_str(mp, s, base); }
1556   int set_str(const std::string &s, int base)
1557   { return mpz_set_str(mp, s.c_str(), base); }
1558   std::string get_str(int base = 10) const
1559   {
1560     __gmp_alloc_cstring temp(mpz_get_str(0, base, mp));
1561     return std::string(temp.str);
1562   }
1563 
1564   // conversion functions
1565   mpz_srcptr __get_mp() const { return mp; }
1566   mpz_ptr __get_mp() { return mp; }
1567   mpz_srcptr get_mpz_t() const { return mp; }
1568   mpz_ptr get_mpz_t() { return mp; }
1569 
1570   signed long int get_si() const { return mpz_get_si(mp); }
1571   unsigned long int get_ui() const { return mpz_get_ui(mp); }
1572   double get_d() const { return mpz_get_d(mp); }
1573 
1574   // bool fits_schar_p() const { return mpz_fits_schar_p(mp); }
1575   // bool fits_uchar_p() const { return mpz_fits_uchar_p(mp); }
1576   bool fits_sint_p() const { return mpz_fits_sint_p(mp); }
1577   bool fits_uint_p() const { return mpz_fits_uint_p(mp); }
1578   bool fits_sshort_p() const { return mpz_fits_sshort_p(mp); }
1579   bool fits_ushort_p() const { return mpz_fits_ushort_p(mp); }
1580   bool fits_slong_p() const { return mpz_fits_slong_p(mp); }
1581   bool fits_ulong_p() const { return mpz_fits_ulong_p(mp); }
1582   // bool fits_float_p() const { return mpz_fits_float_p(mp); }
1583   // bool fits_double_p() const { return mpz_fits_double_p(mp); }
1584   // bool fits_ldouble_p() const { return mpz_fits_ldouble_p(mp); }
1585 
1586 #if __GMPXX_USE_CXX11
1587   explicit operator bool() const { return mp->_mp_size != 0; }
1588 #endif
1589 
1590   // member operators
1591   __GMP_DECLARE_COMPOUND_OPERATOR(operator+=)
1592   __GMP_DECLARE_COMPOUND_OPERATOR(operator-=)
1593   __GMP_DECLARE_COMPOUND_OPERATOR(operator*=)
1594   __GMP_DECLARE_COMPOUND_OPERATOR(operator/=)
1595   __GMP_DECLARE_COMPOUND_OPERATOR(operator%=)
1596 
1597   __GMP_DECLARE_COMPOUND_OPERATOR(operator&=)
1598   __GMP_DECLARE_COMPOUND_OPERATOR(operator|=)
1599   __GMP_DECLARE_COMPOUND_OPERATOR(operator^=)
1600 
1601   __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=)
1602   __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=)
1603 
1604   __GMP_DECLARE_INCREMENT_OPERATOR(operator++)
1605   __GMP_DECLARE_INCREMENT_OPERATOR(operator--)
1606 };
1607 
1608 typedef __gmp_expr<mpz_t, mpz_t> mpz_class;
1609 
1610 
1611 /**************** mpq_class -- wrapper for mpq_t ****************/
1612 
1613 template <>
1614 class __gmp_expr<mpq_t, mpq_t>
1615 {
1616 private:
1617   typedef mpq_t value_type;
1618   value_type mp;
1619 
1620   // Helper functions used for all arithmetic types
1621   void assign_ui(unsigned long l) { mpq_set_ui(mp, l, 1); }
1622   void assign_si(signed long l)
1623   {
1624     if (__GMPXX_CONSTANT_TRUE(l >= 0))
1625       assign_ui(l);
1626     else
1627       mpq_set_si(mp, l, 1);
1628   }
1629   void assign_d (double d)        { mpq_set_d (mp, d); }
1630 
1631   void init_ui(unsigned long l)	{ mpq_init(mp); get_num() = l; }
1632   void init_si(signed long l)	{ mpq_init(mp); get_num() = l; }
1633   void init_d (double d)	{ mpq_init(mp); assign_d (d); }
1634 
1635 public:
1636   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }
1637   void canonicalize() { mpq_canonicalize(mp); }
1638 
1639   // constructors and destructor
1640   __gmp_expr() { mpq_init(mp); }
1641 
1642   __gmp_expr(const __gmp_expr &q)
1643   {
1644     mpz_init_set(mpq_numref(mp), mpq_numref(q.mp));
1645     mpz_init_set(mpq_denref(mp), mpq_denref(q.mp));
1646   }
1647 #if __GMPXX_USE_CXX11
1648   __gmp_expr(__gmp_expr &&q)
1649   { *mp = *q.mp; mpq_init(q.mp); }
1650 #endif
1651   template <class T>
1652   __gmp_expr(const __gmp_expr<mpz_t, T> &expr)
1653   { mpq_init(mp); __gmp_set_expr(mp, expr); }
1654   template <class T>
1655   __gmp_expr(const __gmp_expr<mpq_t, T> &expr)
1656   { mpq_init(mp); __gmp_set_expr(mp, expr); }
1657   template <class T, class U>
1658   explicit __gmp_expr(const __gmp_expr<T, U> &expr)
1659   { mpq_init(mp); __gmp_set_expr(mp, expr); }
1660 
1661   __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS
1662 
1663   explicit __gmp_expr(const char *s, int base = 0)
1664   {
1665     mpq_init (mp);
1666     // If s is the literal 0, we meant to call another constructor.
1667     // If s just happens to evaluate to 0, we would crash, so whatever.
1668     if (s == 0)
1669       {
1670 	// Don't turn mpq_class(0,0) into 0
1671 	mpz_set_si(mpq_denref(mp), base);
1672       }
1673     else if (mpq_set_str(mp, s, base) != 0)
1674       {
1675         mpq_clear (mp);
1676         throw std::invalid_argument ("mpq_set_str");
1677       }
1678   }
1679   explicit __gmp_expr(const std::string &s, int base = 0)
1680   {
1681     mpq_init(mp);
1682     if (mpq_set_str (mp, s.c_str(), base) != 0)
1683       {
1684         mpq_clear (mp);
1685         throw std::invalid_argument ("mpq_set_str");
1686       }
1687   }
1688   explicit __gmp_expr(mpq_srcptr q)
1689   {
1690     mpz_init_set(mpq_numref(mp), mpq_numref(q));
1691     mpz_init_set(mpq_denref(mp), mpq_denref(q));
1692   }
1693 
1694   __gmp_expr(const mpz_class &num, const mpz_class &den)
1695   {
1696     mpz_init_set(mpq_numref(mp), num.get_mpz_t());
1697     mpz_init_set(mpq_denref(mp), den.get_mpz_t());
1698   }
1699 
1700   ~__gmp_expr() { mpq_clear(mp); }
1701 
1702   void swap(__gmp_expr& q) __GMPXX_NOEXCEPT { std::swap(*mp, *q.mp); }
1703 
1704   // assignment operators
1705   __gmp_expr & operator=(const __gmp_expr &q)
1706   { mpq_set(mp, q.mp); return *this; }
1707 #if __GMPXX_USE_CXX11
1708   __gmp_expr & operator=(__gmp_expr &&q) noexcept
1709   { swap(q); return *this; }
1710   __gmp_expr & operator=(mpz_class &&z) noexcept
1711   { get_num() = std::move(z); get_den() = 1u; return *this; }
1712 #endif
1713   template <class T, class U>
1714   __gmp_expr<value_type, value_type> & operator=(const __gmp_expr<T, U> &expr)
1715   { __gmp_set_expr(mp, expr); return *this; }
1716 
1717   __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS
1718 
1719   __gmp_expr & operator=(const char *s)
1720   {
1721     if (mpq_set_str (mp, s, 0) != 0)
1722       throw std::invalid_argument ("mpq_set_str");
1723     return *this;
1724   }
1725   __gmp_expr & operator=(const std::string &s)
1726   {
1727     if (mpq_set_str(mp, s.c_str(), 0) != 0)
1728       throw std::invalid_argument ("mpq_set_str");
1729     return *this;
1730   }
1731 
1732   // string input/output functions
1733   int set_str(const char *s, int base)
1734   { return mpq_set_str(mp, s, base); }
1735   int set_str(const std::string &s, int base)
1736   { return mpq_set_str(mp, s.c_str(), base); }
1737   std::string get_str(int base = 10) const
1738   {
1739     __gmp_alloc_cstring temp(mpq_get_str(0, base, mp));
1740     return std::string(temp.str);
1741   }
1742 
1743   // conversion functions
1744 
1745   // casting a reference to an mpz_t to mpz_class & is a dirty hack,
1746   // but works because the internal representation of mpz_class is
1747   // exactly an mpz_t
1748   const mpz_class & get_num() const
1749   { return reinterpret_cast<const mpz_class &>(*mpq_numref(mp)); }
1750   mpz_class & get_num()
1751   { return reinterpret_cast<mpz_class &>(*mpq_numref(mp)); }
1752   const mpz_class & get_den() const
1753   { return reinterpret_cast<const mpz_class &>(*mpq_denref(mp)); }
1754   mpz_class & get_den()
1755   { return reinterpret_cast<mpz_class &>(*mpq_denref(mp)); }
1756 
1757   mpq_srcptr __get_mp() const { return mp; }
1758   mpq_ptr __get_mp() { return mp; }
1759   mpq_srcptr get_mpq_t() const { return mp; }
1760   mpq_ptr get_mpq_t() { return mp; }
1761 
1762   mpz_srcptr get_num_mpz_t() const { return mpq_numref(mp); }
1763   mpz_ptr get_num_mpz_t() { return mpq_numref(mp); }
1764   mpz_srcptr get_den_mpz_t() const { return mpq_denref(mp); }
1765   mpz_ptr get_den_mpz_t() { return mpq_denref(mp); }
1766 
1767   double get_d() const { return mpq_get_d(mp); }
1768 
1769 #if __GMPXX_USE_CXX11
1770   explicit operator bool() const { return mpq_numref(mp)->_mp_size != 0; }
1771 #endif
1772 
1773   // compound assignments
1774   __GMP_DECLARE_COMPOUND_OPERATOR(operator+=)
1775   __GMP_DECLARE_COMPOUND_OPERATOR(operator-=)
1776   __GMP_DECLARE_COMPOUND_OPERATOR(operator*=)
1777   __GMP_DECLARE_COMPOUND_OPERATOR(operator/=)
1778 
1779   __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=)
1780   __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=)
1781 
1782   __GMP_DECLARE_INCREMENT_OPERATOR(operator++)
1783   __GMP_DECLARE_INCREMENT_OPERATOR(operator--)
1784 };
1785 
1786 typedef __gmp_expr<mpq_t, mpq_t> mpq_class;
1787 
1788 
1789 /**************** mpf_class -- wrapper for mpf_t ****************/
1790 
1791 template <>
1792 class __gmp_expr<mpf_t, mpf_t>
1793 {
1794 private:
1795   typedef mpf_t value_type;
1796   value_type mp;
1797 
1798   // Helper functions used for all arithmetic types
1799   void assign_ui(unsigned long l) { mpf_set_ui(mp, l); }
1800   void assign_si(signed long l)
1801   {
1802     if (__GMPXX_CONSTANT_TRUE(l >= 0))
1803       assign_ui(l);
1804     else
1805       mpf_set_si(mp, l);
1806   }
1807   void assign_d (double d)        { mpf_set_d (mp, d); }
1808 
1809   void init_ui(unsigned long l)
1810   {
1811     if (__GMPXX_CONSTANT_TRUE(l == 0))
1812       mpf_init(mp);
1813     else
1814       mpf_init_set_ui(mp, l);
1815   }
1816   void init_si(signed long l)
1817   {
1818     if (__GMPXX_CONSTANT_TRUE(l >= 0))
1819       init_ui(l);
1820     else
1821       mpf_init_set_si(mp, l);
1822   }
1823   void init_d (double d)	{ mpf_init_set_d (mp, d); }
1824 
1825 public:
1826   mp_bitcnt_t get_prec() const { return mpf_get_prec(mp); }
1827 
1828   void set_prec(mp_bitcnt_t prec) { mpf_set_prec(mp, prec); }
1829   void set_prec_raw(mp_bitcnt_t prec) { mpf_set_prec_raw(mp, prec); }
1830 
1831   // constructors and destructor
1832   __gmp_expr() { mpf_init(mp); }
1833 
1834   __gmp_expr(const __gmp_expr &f)
1835   { mpf_init2(mp, f.get_prec()); mpf_set(mp, f.mp); }
1836 #if __GMPXX_USE_CXX11
1837   __gmp_expr(__gmp_expr &&f)
1838   { *mp = *f.mp; mpf_init2(f.mp, get_prec()); }
1839 #endif
1840   __gmp_expr(const __gmp_expr &f, mp_bitcnt_t prec)
1841   { mpf_init2(mp, prec); mpf_set(mp, f.mp); }
1842   template <class T, class U>
1843   __gmp_expr(const __gmp_expr<T, U> &expr)
1844   { mpf_init2(mp, expr.get_prec()); __gmp_set_expr(mp, expr); }
1845   template <class T, class U>
1846   __gmp_expr(const __gmp_expr<T, U> &expr, mp_bitcnt_t prec)
1847   { mpf_init2(mp, prec); __gmp_set_expr(mp, expr); }
1848 
1849   __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS
1850 
1851   __gmp_expr(signed char c, mp_bitcnt_t prec)
1852   { mpf_init2(mp, prec); mpf_set_si(mp, c); }
1853   __gmp_expr(unsigned char c, mp_bitcnt_t prec)
1854   { mpf_init2(mp, prec); mpf_set_ui(mp, c); }
1855 
1856   __gmp_expr(signed int i, mp_bitcnt_t prec)
1857   { mpf_init2(mp, prec); mpf_set_si(mp, i); }
1858   __gmp_expr(unsigned int i, mp_bitcnt_t prec)
1859   { mpf_init2(mp, prec); mpf_set_ui(mp, i); }
1860 
1861   __gmp_expr(signed short int s, mp_bitcnt_t prec)
1862   { mpf_init2(mp, prec); mpf_set_si(mp, s); }
1863   __gmp_expr(unsigned short int s, mp_bitcnt_t prec)
1864   { mpf_init2(mp, prec); mpf_set_ui(mp, s); }
1865 
1866   __gmp_expr(signed long int l, mp_bitcnt_t prec)
1867   { mpf_init2(mp, prec); mpf_set_si(mp, l); }
1868   __gmp_expr(unsigned long int l, mp_bitcnt_t prec)
1869   { mpf_init2(mp, prec); mpf_set_ui(mp, l); }
1870 
1871   __gmp_expr(float f, mp_bitcnt_t prec)
1872   { mpf_init2(mp, prec); mpf_set_d(mp, f); }
1873   __gmp_expr(double d, mp_bitcnt_t prec)
1874   { mpf_init2(mp, prec); mpf_set_d(mp, d); }
1875   // __gmp_expr(long double ld) { mpf_init_set_d(mp, ld); }
1876   // __gmp_expr(long double ld, mp_bitcnt_t prec)
1877   // { mpf_init2(mp, prec); mpf_set_d(mp, ld); }
1878 
1879   explicit __gmp_expr(const char *s)
1880   {
1881     if (mpf_init_set_str (mp, s, 0) != 0)
1882       {
1883         mpf_clear (mp);
1884         throw std::invalid_argument ("mpf_set_str");
1885       }
1886   }
1887   __gmp_expr(const char *s, mp_bitcnt_t prec, int base = 0)
1888   {
1889     mpf_init2(mp, prec);
1890     if (mpf_set_str(mp, s, base) != 0)
1891       {
1892         mpf_clear (mp);
1893         throw std::invalid_argument ("mpf_set_str");
1894       }
1895   }
1896   explicit __gmp_expr(const std::string &s)
1897   {
1898     if (mpf_init_set_str(mp, s.c_str(), 0) != 0)
1899       {
1900         mpf_clear (mp);
1901         throw std::invalid_argument ("mpf_set_str");
1902       }
1903   }
1904   __gmp_expr(const std::string &s, mp_bitcnt_t prec, int base = 0)
1905   {
1906     mpf_init2(mp, prec);
1907     if (mpf_set_str(mp, s.c_str(), base) != 0)
1908       {
1909         mpf_clear (mp);
1910         throw std::invalid_argument ("mpf_set_str");
1911       }
1912   }
1913 
1914   explicit __gmp_expr(mpf_srcptr f)
1915   { mpf_init2(mp, mpf_get_prec(f)); mpf_set(mp, f); }
1916   __gmp_expr(mpf_srcptr f, mp_bitcnt_t prec)
1917   { mpf_init2(mp, prec); mpf_set(mp, f); }
1918 
1919   ~__gmp_expr() { mpf_clear(mp); }
1920 
1921   void swap(__gmp_expr& f) __GMPXX_NOEXCEPT { std::swap(*mp, *f.mp); }
1922 
1923   // assignment operators
1924   __gmp_expr & operator=(const __gmp_expr &f)
1925   { mpf_set(mp, f.mp); return *this; }
1926 #if __GMPXX_USE_CXX11
1927   __gmp_expr & operator=(__gmp_expr &&f) noexcept
1928   { swap(f); return *this; }
1929 #endif
1930   template <class T, class U>
1931   __gmp_expr<value_type, value_type> & operator=(const __gmp_expr<T, U> &expr)
1932   { __gmp_set_expr(mp, expr); return *this; }
1933 
1934   __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS
1935 
1936   __gmp_expr & operator=(const char *s)
1937   {
1938     if (mpf_set_str (mp, s, 0) != 0)
1939       throw std::invalid_argument ("mpf_set_str");
1940     return *this;
1941   }
1942   __gmp_expr & operator=(const std::string &s)
1943   {
1944     if (mpf_set_str(mp, s.c_str(), 0) != 0)
1945       throw std::invalid_argument ("mpf_set_str");
1946     return *this;
1947   }
1948 
1949   // string input/output functions
1950   int set_str(const char *s, int base)
1951   { return mpf_set_str(mp, s, base); }
1952   int set_str(const std::string &s, int base)
1953   { return mpf_set_str(mp, s.c_str(), base); }
1954   std::string get_str(mp_exp_t &expo, int base = 10, size_t size = 0) const
1955   {
1956     __gmp_alloc_cstring temp(mpf_get_str(0, &expo, base, size, mp));
1957     return std::string(temp.str);
1958   }
1959 
1960   // conversion functions
1961   mpf_srcptr __get_mp() const { return mp; }
1962   mpf_ptr __get_mp() { return mp; }
1963   mpf_srcptr get_mpf_t() const { return mp; }
1964   mpf_ptr get_mpf_t() { return mp; }
1965 
1966   signed long int get_si() const { return mpf_get_si(mp); }
1967   unsigned long int get_ui() const { return mpf_get_ui(mp); }
1968   double get_d() const { return mpf_get_d(mp); }
1969 
1970   // bool fits_schar_p() const { return mpf_fits_schar_p(mp); }
1971   // bool fits_uchar_p() const { return mpf_fits_uchar_p(mp); }
1972   bool fits_sint_p() const { return mpf_fits_sint_p(mp); }
1973   bool fits_uint_p() const { return mpf_fits_uint_p(mp); }
1974   bool fits_sshort_p() const { return mpf_fits_sshort_p(mp); }
1975   bool fits_ushort_p() const { return mpf_fits_ushort_p(mp); }
1976   bool fits_slong_p() const { return mpf_fits_slong_p(mp); }
1977   bool fits_ulong_p() const { return mpf_fits_ulong_p(mp); }
1978   // bool fits_float_p() const { return mpf_fits_float_p(mp); }
1979   // bool fits_double_p() const { return mpf_fits_double_p(mp); }
1980   // bool fits_ldouble_p() const { return mpf_fits_ldouble_p(mp); }
1981 
1982 #if __GMPXX_USE_CXX11
1983   explicit operator bool() const { return mp->_mp_size != 0; }
1984 #endif
1985 
1986   // compound assignments
1987   __GMP_DECLARE_COMPOUND_OPERATOR(operator+=)
1988   __GMP_DECLARE_COMPOUND_OPERATOR(operator-=)
1989   __GMP_DECLARE_COMPOUND_OPERATOR(operator*=)
1990   __GMP_DECLARE_COMPOUND_OPERATOR(operator/=)
1991 
1992   __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=)
1993   __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=)
1994 
1995   __GMP_DECLARE_INCREMENT_OPERATOR(operator++)
1996   __GMP_DECLARE_INCREMENT_OPERATOR(operator--)
1997 };
1998 
1999 typedef __gmp_expr<mpf_t, mpf_t> mpf_class;
2000 
2001 
2002 
2003 /**************** User-defined literals ****************/
2004 
2005 #if __GMPXX_USE_CXX11
2006 inline mpz_class operator"" _mpz(const char* s)
2007 {
2008   return mpz_class(s);
2009 }
2010 
2011 inline mpq_class operator"" _mpq(const char* s)
2012 {
2013   mpq_class q;
2014   q.get_num() = s;
2015   return q;
2016 }
2017 
2018 inline mpf_class operator"" _mpf(const char* s)
2019 {
2020   return mpf_class(s);
2021 }
2022 #endif
2023 
2024 /**************** I/O operators ****************/
2025 
2026 // these should (and will) be provided separately
2027 
2028 template <class T, class U>
2029 inline std::ostream & operator<<
2030 (std::ostream &o, const __gmp_expr<T, U> &expr)
2031 {
2032   __gmp_expr<T, T> const& temp(expr);
2033   return o << temp.__get_mp();
2034 }
2035 
2036 template <class T>
2037 inline std::istream & operator>>(std::istream &i, __gmp_expr<T, T> &expr)
2038 {
2039   return i >> expr.__get_mp();
2040 }
2041 
2042 /*
2043 // you might want to uncomment this
2044 inline std::istream & operator>>(std::istream &i, mpq_class &q)
2045 {
2046   i >> q.get_mpq_t();
2047   q.canonicalize();
2048   return i;
2049 }
2050 */
2051 
2052 
2053 /**************** Functions for type conversion ****************/
2054 
2055 inline void __gmp_set_expr(mpz_ptr z, const mpz_class &w)
2056 {
2057   mpz_set(z, w.get_mpz_t());
2058 }
2059 
2060 template <class T>
2061 inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr<mpz_t, T> &expr)
2062 {
2063   expr.eval(z);
2064 }
2065 
2066 template <class T>
2067 inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr<mpq_t, T> &expr)
2068 {
2069   mpq_class const& temp(expr);
2070   mpz_set_q(z, temp.get_mpq_t());
2071 }
2072 
2073 template <class T>
2074 inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr<mpf_t, T> &expr)
2075 {
2076   mpf_class const& temp(expr);
2077   mpz_set_f(z, temp.get_mpf_t());
2078 }
2079 
2080 inline void __gmp_set_expr(mpq_ptr q, const mpz_class &z)
2081 {
2082   mpq_set_z(q, z.get_mpz_t());
2083 }
2084 
2085 template <class T>
2086 inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr<mpz_t, T> &expr)
2087 {
2088   __gmp_set_expr(mpq_numref(q), expr);
2089   mpz_set_ui(mpq_denref(q), 1);
2090 }
2091 
2092 inline void __gmp_set_expr(mpq_ptr q, const mpq_class &r)
2093 {
2094   mpq_set(q, r.get_mpq_t());
2095 }
2096 
2097 template <class T>
2098 inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr<mpq_t, T> &expr)
2099 {
2100   expr.eval(q);
2101 }
2102 
2103 template <class T>
2104 inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr<mpf_t, T> &expr)
2105 {
2106   mpf_class const& temp(expr);
2107   mpq_set_f(q, temp.get_mpf_t());
2108 }
2109 
2110 template <class T>
2111 inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr<mpz_t, T> &expr)
2112 {
2113   mpz_class const& temp(expr);
2114   mpf_set_z(f, temp.get_mpz_t());
2115 }
2116 
2117 template <class T>
2118 inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr<mpq_t, T> &expr)
2119 {
2120   mpq_class const& temp(expr);
2121   mpf_set_q(f, temp.get_mpq_t());
2122 }
2123 
2124 inline void __gmp_set_expr(mpf_ptr f, const mpf_class &g)
2125 {
2126   mpf_set(f, g.get_mpf_t());
2127 }
2128 
2129 template <class T>
2130 inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr<mpf_t, T> &expr)
2131 {
2132   expr.eval(f);
2133 }
2134 
2135 
2136 /* Temporary objects */
2137 
2138 template <class T>
2139 class __gmp_temp
2140 {
2141   __gmp_expr<T, T> val;
2142   public:
2143   template<class U, class V>
2144   __gmp_temp(U const& u, V) : val (u) {}
2145   typename __gmp_resolve_expr<T>::srcptr_type
2146   __get_mp() const { return val.__get_mp(); }
2147 };
2148 
2149 template <>
2150 class __gmp_temp <mpf_t>
2151 {
2152   mpf_class val;
2153   public:
2154   template<class U>
2155   __gmp_temp(U const& u, mpf_ptr res) : val (u, mpf_get_prec(res)) {}
2156   mpf_srcptr __get_mp() const { return val.__get_mp(); }
2157 };
2158 
2159 /**************** Specializations of __gmp_expr ****************/
2160 /* The eval() method of __gmp_expr<T, U> evaluates the corresponding
2161    expression and assigns the result to its argument, which is either an
2162    mpz_t, mpq_t, or mpf_t as specified by the T argument.
2163    Compound expressions are evaluated recursively (temporaries are created
2164    to hold intermediate values), while for simple expressions the eval()
2165    method of the appropriate function object (available as the Op argument
2166    of either __gmp_unary_expr<T, Op> or __gmp_binary_expr<T, U, Op>) is
2167    called. */
2168 
2169 
2170 /**************** Unary expressions ****************/
2171 /* cases:
2172    - simple:   argument is mp*_class, that is, __gmp_expr<T, T>
2173    - compound: argument is __gmp_expr<T, U> (with U not equal to T) */
2174 
2175 
2176 // simple expressions
2177 
2178 template <class T, class Op>
2179 class __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, T>, Op> >
2180 {
2181 private:
2182   typedef __gmp_expr<T, T> val_type;
2183 
2184   __gmp_unary_expr<val_type, Op> expr;
2185 public:
2186   explicit __gmp_expr(const val_type &val) : expr(val) { }
2187   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
2188   { Op::eval(p, expr.val.__get_mp()); }
2189   const val_type & get_val() const { return expr.val; }
2190   mp_bitcnt_t get_prec() const { return expr.val.get_prec(); }
2191 };
2192 
2193 
2194 // simple expressions, U is a built-in numerical type
2195 
2196 template <class T, class U, class Op>
2197 class __gmp_expr<T, __gmp_unary_expr<U, Op> >
2198 {
2199 private:
2200   typedef U val_type;
2201 
2202   __gmp_unary_expr<val_type, Op> expr;
2203 public:
2204   explicit __gmp_expr(const val_type &val) : expr(val) { }
2205   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
2206   { Op::eval(p, expr.val); }
2207   const val_type & get_val() const { return expr.val; }
2208   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }
2209 };
2210 
2211 
2212 // compound expressions
2213 
2214 template <class T, class U, class Op>
2215 class __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, Op> >
2216 {
2217 private:
2218   typedef __gmp_expr<T, U> val_type;
2219 
2220   __gmp_unary_expr<val_type, Op> expr;
2221 public:
2222   explicit __gmp_expr(const val_type &val) : expr(val) { }
2223   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
2224   { expr.val.eval(p); Op::eval(p, p); }
2225   const val_type & get_val() const { return expr.val; }
2226   mp_bitcnt_t get_prec() const { return expr.val.get_prec(); }
2227 };
2228 
2229 
2230 /**************** Binary expressions ****************/
2231 /* simple:
2232    - arguments are both mp*_class
2233    - one argument is mp*_class, one is a built-in type
2234    compound:
2235    - one is mp*_class, one is __gmp_expr<T, U>
2236    - one is __gmp_expr<T, U>, one is built-in
2237    - both arguments are __gmp_expr<...> */
2238 
2239 
2240 // simple expressions
2241 
2242 template <class T, class Op>
2243 class __gmp_expr
2244 <T, __gmp_binary_expr<__gmp_expr<T, T>, __gmp_expr<T, T>, Op> >
2245 {
2246 private:
2247   typedef __gmp_expr<T, T> val1_type;
2248   typedef __gmp_expr<T, T> val2_type;
2249 
2250   __gmp_binary_expr<val1_type, val2_type, Op> expr;
2251 public:
2252   __gmp_expr(const val1_type &val1, const val2_type &val2)
2253     : expr(val1, val2) { }
2254   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
2255   { Op::eval(p, expr.val1.__get_mp(), expr.val2.__get_mp()); }
2256   const val1_type & get_val1() const { return expr.val1; }
2257   const val2_type & get_val2() const { return expr.val2; }
2258   mp_bitcnt_t get_prec() const
2259   {
2260     mp_bitcnt_t prec1 = expr.val1.get_prec(),
2261       prec2 = expr.val2.get_prec();
2262     return (prec1 > prec2) ? prec1 : prec2;
2263   }
2264 };
2265 
2266 
2267 // simple expressions, U is a built-in numerical type
2268 
2269 template <class T, class U, class Op>
2270 class __gmp_expr<T, __gmp_binary_expr<__gmp_expr<T, T>, U, Op> >
2271 {
2272 private:
2273   typedef __gmp_expr<T, T> val1_type;
2274   typedef U val2_type;
2275 
2276   __gmp_binary_expr<val1_type, val2_type, Op> expr;
2277 public:
2278   __gmp_expr(const val1_type &val1, const val2_type &val2)
2279     : expr(val1, val2) { }
2280   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
2281   { Op::eval(p, expr.val1.__get_mp(), expr.val2); }
2282   const val1_type & get_val1() const { return expr.val1; }
2283   const val2_type & get_val2() const { return expr.val2; }
2284   mp_bitcnt_t get_prec() const { return expr.val1.get_prec(); }
2285 };
2286 
2287 template <class T, class U, class Op>
2288 class __gmp_expr<T, __gmp_binary_expr<U, __gmp_expr<T, T>, Op> >
2289 {
2290 private:
2291   typedef U val1_type;
2292   typedef __gmp_expr<T, T> val2_type;
2293 
2294   __gmp_binary_expr<val1_type, val2_type, Op> expr;
2295 public:
2296   __gmp_expr(const val1_type &val1, const val2_type &val2)
2297     : expr(val1, val2) { }
2298   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
2299   { Op::eval(p, expr.val1, expr.val2.__get_mp()); }
2300   const val1_type & get_val1() const { return expr.val1; }
2301   const val2_type & get_val2() const { return expr.val2; }
2302   mp_bitcnt_t get_prec() const { return expr.val2.get_prec(); }
2303 };
2304 
2305 
2306 // compound expressions, one argument is a subexpression
2307 
2308 template <class T, class U, class V, class Op>
2309 class __gmp_expr
2310 <T, __gmp_binary_expr<__gmp_expr<T, T>, __gmp_expr<U, V>, Op> >
2311 {
2312 private:
2313   typedef __gmp_expr<T, T> val1_type;
2314   typedef __gmp_expr<U, V> val2_type;
2315 
2316   __gmp_binary_expr<val1_type, val2_type, Op> expr;
2317 public:
2318   __gmp_expr(const val1_type &val1, const val2_type &val2)
2319     : expr(val1, val2) { }
2320   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
2321   {
2322     if(p != expr.val1.__get_mp())
2323     {
2324       __gmp_set_expr(p, expr.val2);
2325       Op::eval(p, expr.val1.__get_mp(), p);
2326     }
2327     else
2328     {
2329       __gmp_temp<T> temp(expr.val2, p);
2330       Op::eval(p, expr.val1.__get_mp(), temp.__get_mp());
2331     }
2332   }
2333   const val1_type & get_val1() const { return expr.val1; }
2334   const val2_type & get_val2() const { return expr.val2; }
2335   mp_bitcnt_t get_prec() const
2336   {
2337     mp_bitcnt_t prec1 = expr.val1.get_prec(),
2338       prec2 = expr.val2.get_prec();
2339     return (prec1 > prec2) ? prec1 : prec2;
2340   }
2341 };
2342 
2343 template <class T, class U, class V, class Op>
2344 class __gmp_expr
2345 <T, __gmp_binary_expr<__gmp_expr<U, V>, __gmp_expr<T, T>, Op> >
2346 {
2347 private:
2348   typedef __gmp_expr<U, V> val1_type;
2349   typedef __gmp_expr<T, T> val2_type;
2350 
2351   __gmp_binary_expr<val1_type, val2_type, Op> expr;
2352 public:
2353   __gmp_expr(const val1_type &val1, const val2_type &val2)
2354     : expr(val1, val2) { }
2355   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
2356   {
2357     if(p != expr.val2.__get_mp())
2358     {
2359       __gmp_set_expr(p, expr.val1);
2360       Op::eval(p, p, expr.val2.__get_mp());
2361     }
2362     else
2363     {
2364       __gmp_temp<T> temp(expr.val1, p);
2365       Op::eval(p, temp.__get_mp(), expr.val2.__get_mp());
2366     }
2367   }
2368   const val1_type & get_val1() const { return expr.val1; }
2369   const val2_type & get_val2() const { return expr.val2; }
2370   mp_bitcnt_t get_prec() const
2371   {
2372     mp_bitcnt_t prec1 = expr.val1.get_prec(),
2373       prec2 = expr.val2.get_prec();
2374     return (prec1 > prec2) ? prec1 : prec2;
2375   }
2376 };
2377 
2378 template <class T, class U, class Op>
2379 class __gmp_expr
2380 <T, __gmp_binary_expr<__gmp_expr<T, T>, __gmp_expr<T, U>, Op> >
2381 {
2382 private:
2383   typedef __gmp_expr<T, T> val1_type;
2384   typedef __gmp_expr<T, U> val2_type;
2385 
2386   __gmp_binary_expr<val1_type, val2_type, Op> expr;
2387 public:
2388   __gmp_expr(const val1_type &val1, const val2_type &val2)
2389     : expr(val1, val2) { }
2390   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
2391   {
2392     if(p != expr.val1.__get_mp())
2393     {
2394       __gmp_set_expr(p, expr.val2);
2395       Op::eval(p, expr.val1.__get_mp(), p);
2396     }
2397     else
2398     {
2399       __gmp_temp<T> temp(expr.val2, p);
2400       Op::eval(p, expr.val1.__get_mp(), temp.__get_mp());
2401     }
2402   }
2403   const val1_type & get_val1() const { return expr.val1; }
2404   const val2_type & get_val2() const { return expr.val2; }
2405   mp_bitcnt_t get_prec() const
2406   {
2407     mp_bitcnt_t prec1 = expr.val1.get_prec(),
2408       prec2 = expr.val2.get_prec();
2409     return (prec1 > prec2) ? prec1 : prec2;
2410   }
2411 };
2412 
2413 template <class T, class U, class Op>
2414 class __gmp_expr
2415 <T, __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<T, T>, Op> >
2416 {
2417 private:
2418   typedef __gmp_expr<T, U> val1_type;
2419   typedef __gmp_expr<T, T> val2_type;
2420 
2421   __gmp_binary_expr<val1_type, val2_type, Op> expr;
2422 public:
2423   __gmp_expr(const val1_type &val1, const val2_type &val2)
2424     : expr(val1, val2) { }
2425   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
2426   {
2427     if(p != expr.val2.__get_mp())
2428     {
2429       __gmp_set_expr(p, expr.val1);
2430       Op::eval(p, p, expr.val2.__get_mp());
2431     }
2432     else
2433     {
2434       __gmp_temp<T> temp(expr.val1, p);
2435       Op::eval(p, temp.__get_mp(), expr.val2.__get_mp());
2436     }
2437   }
2438   const val1_type & get_val1() const { return expr.val1; }
2439   const val2_type & get_val2() const { return expr.val2; }
2440   mp_bitcnt_t get_prec() const
2441   {
2442     mp_bitcnt_t prec1 = expr.val1.get_prec(),
2443       prec2 = expr.val2.get_prec();
2444     return (prec1 > prec2) ? prec1 : prec2;
2445   }
2446 };
2447 
2448 
2449 // one argument is a subexpression, one is a built-in
2450 
2451 template <class T, class U, class V, class Op>
2452 class __gmp_expr<T, __gmp_binary_expr<__gmp_expr<T, U>, V, Op> >
2453 {
2454 private:
2455   typedef __gmp_expr<T, U> val1_type;
2456   typedef V val2_type;
2457 
2458   __gmp_binary_expr<val1_type, val2_type, Op> expr;
2459 public:
2460   __gmp_expr(const val1_type &val1, const val2_type &val2)
2461     : expr(val1, val2) { }
2462   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
2463   {
2464     expr.val1.eval(p);
2465     Op::eval(p, p, expr.val2);
2466   }
2467   const val1_type & get_val1() const { return expr.val1; }
2468   const val2_type & get_val2() const { return expr.val2; }
2469   mp_bitcnt_t get_prec() const { return expr.val1.get_prec(); }
2470 };
2471 
2472 template <class T, class U, class V, class Op>
2473 class __gmp_expr<T, __gmp_binary_expr<U, __gmp_expr<T, V>, Op> >
2474 {
2475 private:
2476   typedef U val1_type;
2477   typedef __gmp_expr<T, V> val2_type;
2478 
2479   __gmp_binary_expr<val1_type, val2_type, Op> expr;
2480 public:
2481   __gmp_expr(const val1_type &val1, const val2_type &val2)
2482     : expr(val1, val2) { }
2483   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
2484   {
2485     expr.val2.eval(p);
2486     Op::eval(p, expr.val1, p);
2487   }
2488   const val1_type & get_val1() const { return expr.val1; }
2489   const val2_type & get_val2() const { return expr.val2; }
2490   mp_bitcnt_t get_prec() const { return expr.val2.get_prec(); }
2491 };
2492 
2493 
2494 // both arguments are subexpressions
2495 
2496 template <class T, class U, class V, class W, class Op>
2497 class __gmp_expr
2498 <T, __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, Op> >
2499 {
2500 private:
2501   typedef __gmp_expr<T, U> val1_type;
2502   typedef __gmp_expr<V, W> val2_type;
2503 
2504   __gmp_binary_expr<val1_type, val2_type, Op> expr;
2505 public:
2506   __gmp_expr(const val1_type &val1, const val2_type &val2)
2507     : expr(val1, val2) { }
2508   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
2509   {
2510     __gmp_temp<T> temp2(expr.val2, p);
2511     expr.val1.eval(p);
2512     Op::eval(p, p, temp2.__get_mp());
2513   }
2514   const val1_type & get_val1() const { return expr.val1; }
2515   const val2_type & get_val2() const { return expr.val2; }
2516   mp_bitcnt_t get_prec() const
2517   {
2518     mp_bitcnt_t prec1 = expr.val1.get_prec(),
2519       prec2 = expr.val2.get_prec();
2520     return (prec1 > prec2) ? prec1 : prec2;
2521   }
2522 };
2523 
2524 template <class T, class U, class V, class W, class Op>
2525 class __gmp_expr
2526 <T, __gmp_binary_expr<__gmp_expr<U, V>, __gmp_expr<T, W>, Op> >
2527 {
2528 private:
2529   typedef __gmp_expr<U, V> val1_type;
2530   typedef __gmp_expr<T, W> val2_type;
2531 
2532   __gmp_binary_expr<val1_type, val2_type, Op> expr;
2533 public:
2534   __gmp_expr(const val1_type &val1, const val2_type &val2)
2535     : expr(val1, val2) { }
2536   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
2537   {
2538     __gmp_temp<T> temp1(expr.val1, p);
2539     expr.val2.eval(p);
2540     Op::eval(p, temp1.__get_mp(), p);
2541   }
2542   const val1_type & get_val1() const { return expr.val1; }
2543   const val2_type & get_val2() const { return expr.val2; }
2544   mp_bitcnt_t get_prec() const
2545   {
2546     mp_bitcnt_t prec1 = expr.val1.get_prec(),
2547       prec2 = expr.val2.get_prec();
2548     return (prec1 > prec2) ? prec1 : prec2;
2549   }
2550 };
2551 
2552 template <class T, class U, class V, class Op>
2553 class __gmp_expr
2554 <T, __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<T, V>, Op> >
2555 {
2556 private:
2557   typedef __gmp_expr<T, U> val1_type;
2558   typedef __gmp_expr<T, V> val2_type;
2559 
2560   __gmp_binary_expr<val1_type, val2_type, Op> expr;
2561 public:
2562   __gmp_expr(const val1_type &val1, const val2_type &val2)
2563     : expr(val1, val2) { }
2564   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
2565   {
2566     __gmp_temp<T> temp2(expr.val2, p);
2567     expr.val1.eval(p);
2568     Op::eval(p, p, temp2.__get_mp());
2569   }
2570   const val1_type & get_val1() const { return expr.val1; }
2571   const val2_type & get_val2() const { return expr.val2; }
2572   mp_bitcnt_t get_prec() const
2573   {
2574     mp_bitcnt_t prec1 = expr.val1.get_prec(),
2575       prec2 = expr.val2.get_prec();
2576     return (prec1 > prec2) ? prec1 : prec2;
2577   }
2578 };
2579 
2580 
2581 /**************** Special cases ****************/
2582 
2583 /* Some operations (i.e., add and subtract) with mixed mpz/mpq arguments
2584    can be done directly without first converting the mpz to mpq.
2585    Appropriate specializations of __gmp_expr are required. */
2586 
2587 
2588 #define __GMPZQ_DEFINE_EXPR(eval_fun)                                       \
2589                                                                             \
2590 template <>                                                                 \
2591 class __gmp_expr<mpq_t, __gmp_binary_expr<mpz_class, mpq_class, eval_fun> > \
2592 {                                                                           \
2593 private:                                                                    \
2594   typedef mpz_class val1_type;                                              \
2595   typedef mpq_class val2_type;                                              \
2596                                                                             \
2597   __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
2598 public:                                                                     \
2599   __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
2600     : expr(val1, val2) { }                                                  \
2601   void eval(mpq_ptr q) const                                                \
2602   { eval_fun::eval(q, expr.val1.get_mpz_t(), expr.val2.get_mpq_t()); }      \
2603   const val1_type & get_val1() const { return expr.val1; }                  \
2604   const val2_type & get_val2() const { return expr.val2; }                  \
2605   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }           \
2606 };                                                                          \
2607                                                                             \
2608 template <>                                                                 \
2609 class __gmp_expr<mpq_t, __gmp_binary_expr<mpq_class, mpz_class, eval_fun> > \
2610 {                                                                           \
2611 private:                                                                    \
2612   typedef mpq_class val1_type;                                              \
2613   typedef mpz_class val2_type;                                              \
2614                                                                             \
2615   __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
2616 public:                                                                     \
2617   __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
2618     : expr(val1, val2) { }                                                  \
2619   void eval(mpq_ptr q) const                                                \
2620   { eval_fun::eval(q, expr.val1.get_mpq_t(), expr.val2.get_mpz_t()); }      \
2621   const val1_type & get_val1() const { return expr.val1; }                  \
2622   const val2_type & get_val2() const { return expr.val2; }                  \
2623   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }           \
2624 };                                                                          \
2625                                                                             \
2626 template <class T>                                                          \
2627 class __gmp_expr                                                            \
2628 <mpq_t, __gmp_binary_expr<mpz_class, __gmp_expr<mpq_t, T>, eval_fun> >      \
2629 {                                                                           \
2630 private:                                                                    \
2631   typedef mpz_class val1_type;                                              \
2632   typedef __gmp_expr<mpq_t, T> val2_type;                                   \
2633                                                                             \
2634   __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
2635 public:                                                                     \
2636   __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
2637     : expr(val1, val2) { }                                                  \
2638   void eval(mpq_ptr q) const                                                \
2639   {                                                                         \
2640     mpq_class temp(expr.val2);                                              \
2641     eval_fun::eval(q, expr.val1.get_mpz_t(), temp.get_mpq_t());             \
2642   }                                                                         \
2643   const val1_type & get_val1() const { return expr.val1; }                  \
2644   const val2_type & get_val2() const { return expr.val2; }                  \
2645   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }           \
2646 };                                                                          \
2647                                                                             \
2648 template <class T>                                                          \
2649 class __gmp_expr                                                            \
2650 <mpq_t, __gmp_binary_expr<mpq_class, __gmp_expr<mpz_t, T>, eval_fun> >      \
2651 {                                                                           \
2652 private:                                                                    \
2653   typedef mpq_class val1_type;                                              \
2654   typedef __gmp_expr<mpz_t, T> val2_type;                                   \
2655                                                                             \
2656   __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
2657 public:                                                                     \
2658   __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
2659     : expr(val1, val2) { }                                                  \
2660   void eval(mpq_ptr q) const                                                \
2661   {                                                                         \
2662     mpz_class temp(expr.val2);                                              \
2663     eval_fun::eval(q, expr.val1.get_mpq_t(), temp.get_mpz_t());             \
2664   }                                                                         \
2665   const val1_type & get_val1() const { return expr.val1; }                  \
2666   const val2_type & get_val2() const { return expr.val2; }                  \
2667   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }           \
2668 };                                                                          \
2669                                                                             \
2670 template <class T>                                                          \
2671 class __gmp_expr                                                            \
2672 <mpq_t, __gmp_binary_expr<__gmp_expr<mpz_t, T>, mpq_class, eval_fun> >      \
2673 {                                                                           \
2674 private:                                                                    \
2675   typedef __gmp_expr<mpz_t, T> val1_type;                                   \
2676   typedef mpq_class val2_type;                                              \
2677                                                                             \
2678   __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
2679 public:                                                                     \
2680   __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
2681     : expr(val1, val2) { }                                                  \
2682   void eval(mpq_ptr q) const                                                \
2683   {                                                                         \
2684     mpz_class temp(expr.val1);                                              \
2685     eval_fun::eval(q, temp.get_mpz_t(), expr.val2.get_mpq_t());             \
2686   }                                                                         \
2687   const val1_type & get_val1() const { return expr.val1; }                  \
2688   const val2_type & get_val2() const { return expr.val2; }                  \
2689   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }           \
2690 };                                                                          \
2691                                                                             \
2692 template <class T>                                                          \
2693 class __gmp_expr                                                            \
2694 <mpq_t, __gmp_binary_expr<__gmp_expr<mpq_t, T>, mpz_class, eval_fun> >      \
2695 {                                                                           \
2696 private:                                                                    \
2697   typedef __gmp_expr<mpq_t, T> val1_type;                                   \
2698   typedef mpz_class val2_type;                                              \
2699                                                                             \
2700   __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
2701 public:                                                                     \
2702   __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
2703     : expr(val1, val2) { }                                                  \
2704   void eval(mpq_ptr q) const                                                \
2705   {                                                                         \
2706     mpq_class temp(expr.val1);                                              \
2707     eval_fun::eval(q, temp.get_mpq_t(), expr.val2.get_mpz_t());             \
2708   }                                                                         \
2709   const val1_type & get_val1() const { return expr.val1; }                  \
2710   const val2_type & get_val2() const { return expr.val2; }                  \
2711   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }           \
2712 };                                                                          \
2713                                                                             \
2714 template <class T, class U>                                                 \
2715 class __gmp_expr<mpq_t, __gmp_binary_expr                                   \
2716 <__gmp_expr<mpz_t, T>, __gmp_expr<mpq_t, U>, eval_fun> >                    \
2717 {                                                                           \
2718 private:                                                                    \
2719   typedef __gmp_expr<mpz_t, T> val1_type;                                   \
2720   typedef __gmp_expr<mpq_t, U> val2_type;                                   \
2721                                                                             \
2722   __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
2723 public:                                                                     \
2724   __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
2725     : expr(val1, val2) { }                                                  \
2726   void eval(mpq_ptr q) const                                                \
2727   {                                                                         \
2728     mpz_class temp1(expr.val1);                                             \
2729     expr.val2.eval(q);                                                      \
2730     eval_fun::eval(q, temp1.get_mpz_t(), q);                                \
2731   }                                                                         \
2732   const val1_type & get_val1() const { return expr.val1; }                  \
2733   const val2_type & get_val2() const { return expr.val2; }                  \
2734   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }           \
2735 };                                                                          \
2736                                                                             \
2737 template <class T, class U>                                                 \
2738 class __gmp_expr<mpq_t, __gmp_binary_expr                                   \
2739 <__gmp_expr<mpq_t, T>, __gmp_expr<mpz_t, U>, eval_fun> >                    \
2740 {                                                                           \
2741 private:                                                                    \
2742   typedef __gmp_expr<mpq_t, T> val1_type;                                   \
2743   typedef __gmp_expr<mpz_t, U> val2_type;                                   \
2744                                                                             \
2745   __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
2746 public:                                                                     \
2747   __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
2748     : expr(val1, val2) { }                                                  \
2749   void eval(mpq_ptr q) const                                                \
2750   {                                                                         \
2751     mpz_class temp2(expr.val2);                                             \
2752     expr.val1.eval(q);                                             \
2753     eval_fun::eval(q, q, temp2.get_mpz_t());                \
2754   }                                                                         \
2755   const val1_type & get_val1() const { return expr.val1; }                  \
2756   const val2_type & get_val2() const { return expr.val2; }                  \
2757   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }           \
2758 };
2759 
2760 
2761 __GMPZQ_DEFINE_EXPR(__gmp_binary_plus)
2762 __GMPZQ_DEFINE_EXPR(__gmp_binary_minus)
2763 
2764 
2765 
2766 /**************** Macros for defining functions ****************/
2767 /* Results of operators and functions are instances of __gmp_expr<T, U>.
2768    T determines the numerical type of the expression: it can be either
2769    mpz_t, mpq_t, or mpf_t.  When the arguments of a binary
2770    expression have different numerical types, __gmp_resolve_expr is used
2771    to determine the "larger" type.
2772    U is either __gmp_unary_expr<V, Op> or __gmp_binary_expr<V, W, Op>,
2773    where V and W are the arguments' types -- they can in turn be
2774    expressions, thus allowing to build compound expressions to any
2775    degree of complexity.
2776    Op is a function object that must have an eval() method accepting
2777    appropriate arguments.
2778    Actual evaluation of a __gmp_expr<T, U> object is done when it gets
2779    assigned to an mp*_class ("lazy" evaluation): this is done by calling
2780    its eval() method. */
2781 
2782 
2783 // non-member unary operators and functions
2784 
2785 #define __GMP_DEFINE_UNARY_FUNCTION(fun, eval_fun)                           \
2786                                                                              \
2787 template <class T, class U>                                                  \
2788 inline __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, eval_fun> >          \
2789 fun(const __gmp_expr<T, U> &expr)                                            \
2790 {                                                                            \
2791   return __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, eval_fun> >(expr); \
2792 }
2793 
2794 #define __GMP_DEFINE_UNARY_TYPE_FUNCTION(type, fun, eval_fun) \
2795                                                               \
2796 template <class T, class U>                                   \
2797 inline type fun(const __gmp_expr<T, U> &expr)                 \
2798 {                                                             \
2799   __gmp_expr<T, T> const& temp(expr); \
2800   return eval_fun::eval(temp.__get_mp());                     \
2801 }
2802 
2803 
2804 // non-member binary operators and functions
2805 
2806 #define __GMPP_DEFINE_BINARY_FUNCTION(fun, eval_fun)                   \
2807                                                                        \
2808 template <class T, class U, class V, class W>                          \
2809 inline __gmp_expr<typename __gmp_resolve_expr<T, V>::value_type,       \
2810 __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, eval_fun> >      \
2811 fun(const __gmp_expr<T, U> &expr1, const __gmp_expr<V, W> &expr2)      \
2812 {                                                                      \
2813   return __gmp_expr<typename __gmp_resolve_expr<T, V>::value_type,     \
2814      __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, eval_fun> > \
2815     (expr1, expr2);                                                    \
2816 }
2817 
2818 #define __GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, bigtype)       \
2819                                                                            \
2820 template <class T, class U>                                                \
2821 inline __gmp_expr                                                          \
2822 <T, __gmp_binary_expr<__gmp_expr<T, U>, bigtype, eval_fun> >               \
2823 fun(const __gmp_expr<T, U> &expr, type t)                                  \
2824 {                                                                          \
2825   return __gmp_expr                                                        \
2826     <T, __gmp_binary_expr<__gmp_expr<T, U>, bigtype, eval_fun> >(expr, t); \
2827 }                                                                          \
2828                                                                            \
2829 template <class T, class U>                                                \
2830 inline __gmp_expr                                                          \
2831 <T, __gmp_binary_expr<bigtype, __gmp_expr<T, U>, eval_fun> >               \
2832 fun(type t, const __gmp_expr<T, U> &expr)                                  \
2833 {                                                                          \
2834   return __gmp_expr                                                        \
2835     <T, __gmp_binary_expr<bigtype, __gmp_expr<T, U>, eval_fun> >(t, expr); \
2836 }
2837 
2838 #define __GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, type)          \
2839 __GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, signed long int)
2840 
2841 #define __GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, type)            \
2842 __GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, unsigned long int)
2843 
2844 #define __GMPND_DEFINE_BINARY_FUNCTION(fun, eval_fun, type) \
2845 __GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, double)
2846 
2847 #define __GMPNLD_DEFINE_BINARY_FUNCTION(fun, eval_fun, type)     \
2848 __GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, long double)
2849 
2850 #define __GMPN_DEFINE_BINARY_FUNCTION(fun, eval_fun)              \
2851 __GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed char)        \
2852 __GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned char)      \
2853 __GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed int)         \
2854 __GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned int)       \
2855 __GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed short int)   \
2856 __GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned short int) \
2857 __GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed long int)    \
2858 __GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned long int)  \
2859 __GMPND_DEFINE_BINARY_FUNCTION(fun, eval_fun, float)              \
2860 __GMPND_DEFINE_BINARY_FUNCTION(fun, eval_fun, double)             \
2861 /* __GMPNLD_DEFINE_BINARY_FUNCTION(fun, eval_fun, long double) */
2862 
2863 #define __GMP_DEFINE_BINARY_FUNCTION(fun, eval_fun) \
2864 __GMPP_DEFINE_BINARY_FUNCTION(fun, eval_fun)        \
2865 __GMPN_DEFINE_BINARY_FUNCTION(fun, eval_fun)
2866 
2867 
2868 #define __GMP_DEFINE_BINARY_FUNCTION_UI(fun, eval_fun)                 \
2869                                                                        \
2870 template <class T, class U>                                            \
2871 inline __gmp_expr                                                      \
2872 <T, __gmp_binary_expr<__gmp_expr<T, U>, mp_bitcnt_t, eval_fun> > \
2873 fun(const __gmp_expr<T, U> &expr, mp_bitcnt_t l)                 \
2874 {                                                                      \
2875   return __gmp_expr<T, __gmp_binary_expr                               \
2876     <__gmp_expr<T, U>, mp_bitcnt_t, eval_fun> >(expr, l);        \
2877 }
2878 
2879 
2880 #define __GMPP_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun)         \
2881                                                                         \
2882 template <class T, class U, class V, class W>                           \
2883 inline type fun(const __gmp_expr<T, U> &expr1,                          \
2884 		const __gmp_expr<V, W> &expr2)                          \
2885 {                                                                       \
2886   __gmp_expr<T, T> const& temp1(expr1);                                 \
2887   __gmp_expr<V, V> const& temp2(expr2);                                 \
2888   return eval_fun::eval(temp1.__get_mp(), temp2.__get_mp());            \
2889 }
2890 
2891 #define __GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun,   \
2892 					    type2, bigtype)        \
2893                                                                    \
2894 template <class T, class U>                                        \
2895 inline type fun(const __gmp_expr<T, U> &expr, type2 t)             \
2896 {                                                                  \
2897   __gmp_expr<T, T> const& temp(expr);      \
2898   return eval_fun::eval(temp.__get_mp(), static_cast<bigtype>(t)); \
2899 }                                                                  \
2900                                                                    \
2901 template <class T, class U>                                        \
2902 inline type fun(type2 t, const __gmp_expr<T, U> &expr)             \
2903 {                                                                  \
2904   __gmp_expr<T, T> const& temp(expr);      \
2905   return eval_fun::eval(static_cast<bigtype>(t), temp.__get_mp()); \
2906 }
2907 
2908 #define __GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2) \
2909 __GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun,                \
2910 				    type2, signed long int)
2911 
2912 #define __GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2) \
2913 __GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun,                \
2914 				    type2, unsigned long int)
2915 
2916 #define __GMPND_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2) \
2917 __GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2, double)
2918 
2919 #define __GMPNLD_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2)     \
2920 __GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2, long double)
2921 
2922 #define __GMPN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun)              \
2923 __GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed char)        \
2924 __GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned char)      \
2925 __GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed int)         \
2926 __GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned int)       \
2927 __GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed short int)   \
2928 __GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned short int) \
2929 __GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed long int)    \
2930 __GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned long int)  \
2931 __GMPND_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, float)              \
2932 __GMPND_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, double)             \
2933 /* __GMPNLD_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, long double) */
2934 
2935 #define __GMP_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun) \
2936 __GMPP_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun)        \
2937 __GMPN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun)
2938 
2939 
2940 // member operators
2941 
2942 #define __GMPP_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun)                 \
2943                                                                              \
2944 template <class T, class U>                                                  \
2945 inline type##_class & type##_class::fun(const __gmp_expr<T, U> &expr)        \
2946 {                                                                            \
2947   __gmp_set_expr(mp, __gmp_expr<type##_t, __gmp_binary_expr                  \
2948 		 <type##_class, __gmp_expr<T, U>, eval_fun> >(*this, expr)); \
2949   return *this;                                                              \
2950 }
2951 
2952 #define __GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun,    \
2953 					 type2, bigtype)         \
2954                                                                  \
2955 inline type##_class & type##_class::fun(type2 t)                 \
2956 {                                                                \
2957   __gmp_set_expr(mp, __gmp_expr<type##_t, __gmp_binary_expr      \
2958 		 <type##_class, bigtype, eval_fun> >(*this, t)); \
2959   return *this;                                                  \
2960 }
2961 
2962 #define __GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2) \
2963 __GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun,                \
2964 				 type2, signed long int)
2965 
2966 #define __GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2) \
2967 __GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun,                \
2968 				 type2, unsigned long int)
2969 
2970 #define __GMPND_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2) \
2971 __GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2, double)
2972 
2973 #define __GMPNLD_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2)     \
2974 __GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2, long double)
2975 
2976 #define __GMPN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun)              \
2977 __GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed char)        \
2978 __GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned char)      \
2979 __GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed int)         \
2980 __GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned int)       \
2981 __GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed short int)   \
2982 __GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned short int) \
2983 __GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed long int)    \
2984 __GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned long int)  \
2985 __GMPND_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, float)              \
2986 __GMPND_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, double)             \
2987 /* __GMPNLD_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, long double) */
2988 
2989 #define __GMP_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun) \
2990 __GMPP_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun)        \
2991 __GMPN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun)
2992 
2993 #define __GMPZ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \
2994 __GMP_DEFINE_COMPOUND_OPERATOR(mpz, fun, eval_fun)
2995 
2996 #define __GMPQ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \
2997 __GMP_DEFINE_COMPOUND_OPERATOR(mpq, fun, eval_fun)
2998 
2999 #define __GMPF_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \
3000 __GMP_DEFINE_COMPOUND_OPERATOR(mpf, fun, eval_fun)
3001 
3002 
3003 
3004 #define __GMP_DEFINE_COMPOUND_OPERATOR_UI(type, fun, eval_fun)  \
3005                                                                 \
3006 inline type##_class & type##_class::fun(mp_bitcnt_t l)    \
3007 {                                                               \
3008   __gmp_set_expr(mp, __gmp_expr<type##_t, __gmp_binary_expr     \
3009     <type##_class, mp_bitcnt_t, eval_fun> >(*this, l));   \
3010   return *this;                                                 \
3011 }
3012 
3013 #define __GMPZ_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \
3014 __GMP_DEFINE_COMPOUND_OPERATOR_UI(mpz, fun, eval_fun)
3015 
3016 #define __GMPQ_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \
3017 __GMP_DEFINE_COMPOUND_OPERATOR_UI(mpq, fun, eval_fun)
3018 
3019 #define __GMPF_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \
3020 __GMP_DEFINE_COMPOUND_OPERATOR_UI(mpf, fun, eval_fun)
3021 
3022 
3023 
3024 #define __GMP_DEFINE_INCREMENT_OPERATOR(type, fun, eval_fun) \
3025                                                              \
3026 inline type##_class & type##_class::fun()                    \
3027 {                                                            \
3028   eval_fun::eval(mp);                                        \
3029   return *this;                                              \
3030 }                                                            \
3031                                                              \
3032 inline type##_class type##_class::fun(int)                   \
3033 {                                                            \
3034   type##_class temp(*this);                                  \
3035   eval_fun::eval(mp);                                        \
3036   return temp;                                               \
3037 }
3038 
3039 #define __GMPZ_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \
3040 __GMP_DEFINE_INCREMENT_OPERATOR(mpz, fun, eval_fun)
3041 
3042 #define __GMPQ_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \
3043 __GMP_DEFINE_INCREMENT_OPERATOR(mpq, fun, eval_fun)
3044 
3045 #define __GMPF_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \
3046 __GMP_DEFINE_INCREMENT_OPERATOR(mpf, fun, eval_fun)
3047 
3048 
3049 
3050 /**************** Arithmetic operators and functions ****************/
3051 
3052 // non-member operators and functions
3053 
3054 __GMP_DEFINE_UNARY_FUNCTION(operator+, __gmp_unary_plus)
3055 __GMP_DEFINE_UNARY_FUNCTION(operator-, __gmp_unary_minus)
3056 __GMP_DEFINE_UNARY_FUNCTION(operator~, __gmp_unary_com)
3057 
3058 __GMP_DEFINE_BINARY_FUNCTION(operator+, __gmp_binary_plus)
3059 __GMP_DEFINE_BINARY_FUNCTION(operator-, __gmp_binary_minus)
3060 __GMP_DEFINE_BINARY_FUNCTION(operator*, __gmp_binary_multiplies)
3061 __GMP_DEFINE_BINARY_FUNCTION(operator/, __gmp_binary_divides)
3062 __GMP_DEFINE_BINARY_FUNCTION(operator%, __gmp_binary_modulus)
3063 __GMP_DEFINE_BINARY_FUNCTION(operator&, __gmp_binary_and)
3064 __GMP_DEFINE_BINARY_FUNCTION(operator|, __gmp_binary_ior)
3065 __GMP_DEFINE_BINARY_FUNCTION(operator^, __gmp_binary_xor)
3066 
3067 __GMP_DEFINE_BINARY_FUNCTION_UI(operator<<, __gmp_binary_lshift)
3068 __GMP_DEFINE_BINARY_FUNCTION_UI(operator>>, __gmp_binary_rshift)
3069 
3070 __GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator==, __gmp_binary_equal)
3071 __GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator!=, ! __gmp_binary_equal)
3072 __GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator<, __gmp_binary_less)
3073 __GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator<=, ! __gmp_binary_greater)
3074 __GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator>, __gmp_binary_greater)
3075 __GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator>=, ! __gmp_binary_less)
3076 
3077 __GMP_DEFINE_UNARY_FUNCTION(abs, __gmp_abs_function)
3078 __GMP_DEFINE_UNARY_FUNCTION(trunc, __gmp_trunc_function)
3079 __GMP_DEFINE_UNARY_FUNCTION(floor, __gmp_floor_function)
3080 __GMP_DEFINE_UNARY_FUNCTION(ceil, __gmp_ceil_function)
3081 __GMP_DEFINE_UNARY_FUNCTION(sqrt, __gmp_sqrt_function)
3082 __GMP_DEFINE_BINARY_FUNCTION(hypot, __gmp_hypot_function)
3083 __GMP_DEFINE_BINARY_FUNCTION(gcd, __gmp_gcd_function)
3084 __GMP_DEFINE_BINARY_FUNCTION(lcm, __gmp_lcm_function)
3085 
3086 __GMP_DEFINE_UNARY_TYPE_FUNCTION(int, sgn, __gmp_sgn_function)
3087 __GMP_DEFINE_BINARY_TYPE_FUNCTION(int, cmp, __gmp_cmp_function)
3088 
3089 template <class T>
3090 void swap(__gmp_expr<T, T>& x, __gmp_expr<T, T>& y) __GMPXX_NOEXCEPT
3091 { x.swap(y); }
3092 
3093 // member operators for mpz_class
3094 
3095 __GMPZ_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus)
3096 __GMPZ_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus)
3097 __GMPZ_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies)
3098 __GMPZ_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides)
3099 __GMPZ_DEFINE_COMPOUND_OPERATOR(operator%=, __gmp_binary_modulus)
3100 
3101 __GMPZ_DEFINE_COMPOUND_OPERATOR(operator&=, __gmp_binary_and)
3102 __GMPZ_DEFINE_COMPOUND_OPERATOR(operator|=, __gmp_binary_ior)
3103 __GMPZ_DEFINE_COMPOUND_OPERATOR(operator^=, __gmp_binary_xor)
3104 
3105 __GMPZ_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift)
3106 __GMPZ_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift)
3107 
3108 __GMPZ_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment)
3109 __GMPZ_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement)
3110 
3111 // member operators for mpq_class
3112 
3113 __GMPQ_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus)
3114 __GMPQ_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus)
3115 __GMPQ_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies)
3116 __GMPQ_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides)
3117 
3118 __GMPQ_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift)
3119 __GMPQ_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift)
3120 
3121 __GMPQ_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment)
3122 __GMPQ_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement)
3123 
3124 // member operators for mpf_class
3125 
3126 __GMPF_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus)
3127 __GMPF_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus)
3128 __GMPF_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies)
3129 __GMPF_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides)
3130 
3131 __GMPF_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift)
3132 __GMPF_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift)
3133 
3134 __GMPF_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment)
3135 __GMPF_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement)
3136 
3137 
3138 
3139 /**************** Class wrapper for gmp_randstate_t ****************/
3140 
3141 class __gmp_urandomb_value { };
3142 class __gmp_urandomm_value { };
3143 
3144 template <>
3145 class __gmp_expr<mpz_t, __gmp_urandomb_value>
3146 {
3147 private:
3148   __gmp_randstate_struct *state;
3149   mp_bitcnt_t bits;
3150 public:
3151   __gmp_expr(gmp_randstate_t s, mp_bitcnt_t l) : state(s), bits(l) { }
3152   void eval(mpz_ptr z) const { __gmp_rand_function::eval(z, state, bits); }
3153   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }
3154 };
3155 
3156 template <>
3157 class __gmp_expr<mpz_t, __gmp_urandomm_value>
3158 {
3159 private:
3160   __gmp_randstate_struct *state;
3161   mpz_class range;
3162 public:
3163   __gmp_expr(gmp_randstate_t s, const mpz_class &z) : state(s), range(z) { }
3164   void eval(mpz_ptr z) const
3165   { __gmp_rand_function::eval(z, state, range.get_mpz_t()); }
3166   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }
3167 };
3168 
3169 template <>
3170 class __gmp_expr<mpf_t, __gmp_urandomb_value>
3171 {
3172 private:
3173   __gmp_randstate_struct *state;
3174   mp_bitcnt_t bits;
3175 public:
3176   __gmp_expr(gmp_randstate_t s, mp_bitcnt_t l) : state(s), bits(l) { }
3177   void eval(mpf_ptr f) const
3178   {
3179     __gmp_rand_function::eval(f, state,
3180 	(bits>0) ? bits : mpf_get_prec(f));
3181   }
3182   mp_bitcnt_t get_prec() const
3183   {
3184     if (bits == 0)
3185       return mpf_get_default_prec();
3186     else
3187       return bits;
3188   }
3189 };
3190 
3191 extern "C" {
3192   typedef void __gmp_randinit_default_t (gmp_randstate_t);
3193   typedef void __gmp_randinit_lc_2exp_t (gmp_randstate_t, mpz_srcptr, unsigned long int, mp_bitcnt_t);
3194   typedef int __gmp_randinit_lc_2exp_size_t (gmp_randstate_t, mp_bitcnt_t);
3195 }
3196 
3197 class gmp_randclass
3198 {
3199 private:
3200   gmp_randstate_t state;
3201 
3202   // copy construction and assignment not allowed
3203   gmp_randclass(const gmp_randclass &);
3204   void operator=(const gmp_randclass &);
3205 public:
3206   // constructors and destructor
3207   gmp_randclass(gmp_randalg_t alg, unsigned long int size)
3208   {
3209     switch (alg)
3210       {
3211       case GMP_RAND_ALG_LC: // no other cases for now
3212       default:
3213 	gmp_randinit(state, alg, size);
3214 	break;
3215       }
3216   }
3217 
3218   // gmp_randinit_default
3219   gmp_randclass(__gmp_randinit_default_t* f) { f(state); }
3220 
3221   // gmp_randinit_lc_2exp
3222   gmp_randclass(__gmp_randinit_lc_2exp_t* f,
3223 		mpz_class z, unsigned long int l1, mp_bitcnt_t l2)
3224   { f(state, z.get_mpz_t(), l1, l2); }
3225 
3226   // gmp_randinit_lc_2exp_size
3227   gmp_randclass(__gmp_randinit_lc_2exp_size_t* f,
3228 		mp_bitcnt_t size)
3229   {
3230     if (f (state, size) == 0)
3231       throw std::length_error ("gmp_randinit_lc_2exp_size");
3232   }
3233 
3234   ~gmp_randclass() { gmp_randclear(state); }
3235 
3236   // initialize
3237   void seed(); // choose a random seed some way (?)
3238   void seed(unsigned long int s) { gmp_randseed_ui(state, s); }
3239   void seed(const mpz_class &z) { gmp_randseed(state, z.get_mpz_t()); }
3240 
3241   // get random number
3242   __gmp_expr<mpz_t, __gmp_urandomb_value> get_z_bits(mp_bitcnt_t l)
3243   { return __gmp_expr<mpz_t, __gmp_urandomb_value>(state, l); }
3244   __gmp_expr<mpz_t, __gmp_urandomb_value> get_z_bits(const mpz_class &z)
3245   { return get_z_bits(z.get_ui()); }
3246   // FIXME: z.get_bitcnt_t() ?
3247 
3248   __gmp_expr<mpz_t, __gmp_urandomm_value> get_z_range(const mpz_class &z)
3249   { return __gmp_expr<mpz_t, __gmp_urandomm_value>(state, z); }
3250 
3251   __gmp_expr<mpf_t, __gmp_urandomb_value> get_f(mp_bitcnt_t prec = 0)
3252   { return __gmp_expr<mpf_t, __gmp_urandomb_value>(state, prec); }
3253 };
3254 
3255 
3256 /**************** Specialize std::numeric_limits ****************/
3257 
3258 namespace std {
3259   template <> class numeric_limits<mpz_class>
3260   {
3261   public:
3262     static const bool is_specialized = true;
3263     static mpz_class min() { return mpz_class(); }
3264     static mpz_class max() { return mpz_class(); }
3265     static mpz_class lowest() { return mpz_class(); }
3266     static const int digits = 0;
3267     static const int digits10 = 0;
3268     static const int max_digits10 = 0;
3269     static const bool is_signed = true;
3270     static const bool is_integer = true;
3271     static const bool is_exact = true;
3272     static const int radix = 2;
3273     static mpz_class epsilon() { return mpz_class(); }
3274     static mpz_class round_error() { return mpz_class(); }
3275     static const int min_exponent = 0;
3276     static const int min_exponent10 = 0;
3277     static const int max_exponent = 0;
3278     static const int max_exponent10 = 0;
3279     static const bool has_infinity = false;
3280     static const bool has_quiet_NaN = false;
3281     static const bool has_signaling_NaN = false;
3282     static const float_denorm_style has_denorm = denorm_absent;
3283     static const bool has_denorm_loss = false;
3284     static mpz_class infinity() { return mpz_class(); }
3285     static mpz_class quiet_NaN() { return mpz_class(); }
3286     static mpz_class signaling_NaN() { return mpz_class(); }
3287     static mpz_class denorm_min() { return mpz_class(); }
3288     static const bool is_iec559 = false;
3289     static const bool is_bounded = false;
3290     static const bool is_modulo = false;
3291     static const bool traps = false;
3292     static const bool tinyness_before = false;
3293     static const float_round_style round_style = round_toward_zero;
3294   };
3295 
3296   template <> class numeric_limits<mpq_class>
3297   {
3298   public:
3299     static const bool is_specialized = true;
3300     static mpq_class min() { return mpq_class(); }
3301     static mpq_class max() { return mpq_class(); }
3302     static mpq_class lowest() { return mpq_class(); }
3303     static const int digits = 0;
3304     static const int digits10 = 0;
3305     static const int max_digits10 = 0;
3306     static const bool is_signed = true;
3307     static const bool is_integer = false;
3308     static const bool is_exact = true;
3309     static const int radix = 2;
3310     static mpq_class epsilon() { return mpq_class(); }
3311     static mpq_class round_error() { return mpq_class(); }
3312     static const int min_exponent = 0;
3313     static const int min_exponent10 = 0;
3314     static const int max_exponent = 0;
3315     static const int max_exponent10 = 0;
3316     static const bool has_infinity = false;
3317     static const bool has_quiet_NaN = false;
3318     static const bool has_signaling_NaN = false;
3319     static const float_denorm_style has_denorm = denorm_absent;
3320     static const bool has_denorm_loss = false;
3321     static mpq_class infinity() { return mpq_class(); }
3322     static mpq_class quiet_NaN() { return mpq_class(); }
3323     static mpq_class signaling_NaN() { return mpq_class(); }
3324     static mpq_class denorm_min() { return mpq_class(); }
3325     static const bool is_iec559 = false;
3326     static const bool is_bounded = false;
3327     static const bool is_modulo = false;
3328     static const bool traps = false;
3329     static const bool tinyness_before = false;
3330     static const float_round_style round_style = round_toward_zero;
3331   };
3332 
3333   template <> class numeric_limits<mpf_class>
3334   {
3335   public:
3336     static const bool is_specialized = true;
3337     static mpf_class min() { return mpf_class(); }
3338     static mpf_class max() { return mpf_class(); }
3339     static mpf_class lowest() { return mpf_class(); }
3340     static const int digits = 0;
3341     static const int digits10 = 0;
3342     static const int max_digits10 = 0;
3343     static const bool is_signed = true;
3344     static const bool is_integer = false;
3345     static const bool is_exact = false;
3346     static const int radix = 2;
3347     static mpf_class epsilon() { return mpf_class(); }
3348     static mpf_class round_error() { return mpf_class(); }
3349     static const int min_exponent = 0;
3350     static const int min_exponent10 = 0;
3351     static const int max_exponent = 0;
3352     static const int max_exponent10 = 0;
3353     static const bool has_infinity = false;
3354     static const bool has_quiet_NaN = false;
3355     static const bool has_signaling_NaN = false;
3356     static const float_denorm_style has_denorm = denorm_absent;
3357     static const bool has_denorm_loss = false;
3358     static mpf_class infinity() { return mpf_class(); }
3359     static mpf_class quiet_NaN() { return mpf_class(); }
3360     static mpf_class signaling_NaN() { return mpf_class(); }
3361     static mpf_class denorm_min() { return mpf_class(); }
3362     static const bool is_iec559 = false;
3363     static const bool is_bounded = false;
3364     static const bool is_modulo = false;
3365     static const bool traps = false;
3366     static const bool tinyness_before = false;
3367     static const float_round_style round_style = round_indeterminate;
3368   };
3369 }
3370 
3371 
3372 /**************** #undef all private macros ****************/
3373 
3374 #undef __GMPP_DECLARE_COMPOUND_OPERATOR
3375 #undef __GMPN_DECLARE_COMPOUND_OPERATOR
3376 #undef __GMP_DECLARE_COMPOUND_OPERATOR
3377 #undef __GMP_DECLARE_COMPOUND_OPERATOR_UI
3378 #undef __GMP_DECLARE_INCREMENT_OPERATOR
3379 #undef __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS
3380 #undef __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS
3381 
3382 #undef __GMPZQ_DEFINE_EXPR
3383 
3384 #undef __GMP_DEFINE_UNARY_FUNCTION
3385 #undef __GMP_DEFINE_UNARY_TYPE_FUNCTION
3386 
3387 #undef __GMPP_DEFINE_BINARY_FUNCTION
3388 #undef __GMPNN_DEFINE_BINARY_FUNCTION
3389 #undef __GMPNS_DEFINE_BINARY_FUNCTION
3390 #undef __GMPNU_DEFINE_BINARY_FUNCTION
3391 #undef __GMPND_DEFINE_BINARY_FUNCTION
3392 #undef __GMPNLD_DEFINE_BINARY_FUNCTION
3393 #undef __GMPN_DEFINE_BINARY_FUNCTION
3394 #undef __GMP_DEFINE_BINARY_FUNCTION
3395 
3396 #undef __GMP_DEFINE_BINARY_FUNCTION_UI
3397 
3398 #undef __GMPP_DEFINE_BINARY_TYPE_FUNCTION
3399 #undef __GMPNN_DEFINE_BINARY_TYPE_FUNCTION
3400 #undef __GMPNS_DEFINE_BINARY_TYPE_FUNCTION
3401 #undef __GMPNU_DEFINE_BINARY_TYPE_FUNCTION
3402 #undef __GMPND_DEFINE_BINARY_TYPE_FUNCTION
3403 #undef __GMPNLD_DEFINE_BINARY_TYPE_FUNCTION
3404 #undef __GMPN_DEFINE_BINARY_TYPE_FUNCTION
3405 #undef __GMP_DEFINE_BINARY_TYPE_FUNCTION
3406 
3407 #undef __GMPZ_DEFINE_COMPOUND_OPERATOR
3408 
3409 #undef __GMPP_DEFINE_COMPOUND_OPERATOR
3410 #undef __GMPNN_DEFINE_COMPOUND_OPERATOR
3411 #undef __GMPNS_DEFINE_COMPOUND_OPERATOR
3412 #undef __GMPNU_DEFINE_COMPOUND_OPERATOR
3413 #undef __GMPND_DEFINE_COMPOUND_OPERATOR
3414 #undef __GMPNLD_DEFINE_COMPOUND_OPERATOR
3415 #undef __GMPN_DEFINE_COMPOUND_OPERATOR
3416 #undef __GMP_DEFINE_COMPOUND_OPERATOR
3417 
3418 #undef __GMPQ_DEFINE_COMPOUND_OPERATOR
3419 #undef __GMPF_DEFINE_COMPOUND_OPERATOR
3420 
3421 #undef __GMP_DEFINE_COMPOUND_OPERATOR_UI
3422 #undef __GMPZ_DEFINE_COMPOUND_OPERATOR_UI
3423 #undef __GMPQ_DEFINE_COMPOUND_OPERATOR_UI
3424 #undef __GMPF_DEFINE_COMPOUND_OPERATOR_UI
3425 
3426 #undef __GMP_DEFINE_INCREMENT_OPERATOR
3427 #undef __GMPZ_DEFINE_INCREMENT_OPERATOR
3428 #undef __GMPQ_DEFINE_INCREMENT_OPERATOR
3429 #undef __GMPF_DEFINE_INCREMENT_OPERATOR
3430 
3431 #undef __GMPXX_CONSTANT_TRUE
3432 #undef __GMPXX_CONSTANT
3433 
3434 #endif /* __GMP_PLUSPLUS__ */
3435