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