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