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