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