Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it

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