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