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