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