source: Daodan/MSYS2/mingw32/include/gmpxx.h

Last change on this file was 1166, checked in by rossy, 3 years ago

Daodan: Replace MinGW build env with an up-to-date MSYS2 env

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