github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/demos/perl/GMP.xs (about) 1 /* GMP module external subroutines. 2 3 Copyright 2001-2003, 2015 Free Software Foundation, Inc. 4 5 This file is part of the GNU MP Library. 6 7 The GNU MP Library is free software; you can redistribute it and/or modify 8 it under the terms of either: 9 10 * the GNU Lesser General Public License as published by the Free 11 Software Foundation; either version 3 of the License, or (at your 12 option) any later version. 13 14 or 15 16 * the GNU General Public License as published by the Free Software 17 Foundation; either version 2 of the License, or (at your option) any 18 later version. 19 20 or both in parallel, as here. 21 22 The GNU MP Library is distributed in the hope that it will be useful, but 23 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 24 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 25 for more details. 26 27 You should have received copies of the GNU General Public License and the 28 GNU Lesser General Public License along with the GNU MP Library. If not, 29 see https://www.gnu.org/licenses/. 30 31 32 /* Notes: 33 34 Routines are grouped with the alias feature and a table of function 35 pointers where possible, since each xsub routine ends up with quite a bit 36 of code size. Different combinations of arguments and return values have 37 to be separate though. 38 39 The "INTERFACE:" feature isn't available in perl 5.005 and so isn't used. 40 "ALIAS:" requires a table lookup with CvXSUBANY(cv).any_i32 (which is 41 "ix") whereas "INTERFACE:" would have CvXSUBANY(cv).any_dptr as the 42 function pointer immediately. 43 44 Mixed-type swapped-order assignments like "$a = 123; $a += mpz(456);" 45 invoke the plain overloaded "+", not "+=", which makes life easier. 46 47 mpz_assume etc types are used with the overloaded operators since such 48 operators are always called with a class object as the first argument, we 49 don't need an sv_derived_from() lookup to check. There's assert()s in 50 MPX_ASSUME() for this though. 51 52 The overload_constant routines reached via overload::constant get 4 53 arguments in perl 5.6, not the 3 as documented. This is apparently a 54 bug, using "..." lets us ignore the extra one. 55 56 There's only a few "si" functions in gmp, so usually SvIV values get 57 handled with an mpz_set_si into a temporary and then a full precision mpz 58 routine. This is reasonably efficient. 59 60 Argument types are checked, with a view to preserving all bits in the 61 operand. Perl is a bit looser in its arithmetic, allowing rounding or 62 truncation to an intended operand type (IV, UV or NV). 63 64 Bugs: 65 66 The memory leak detection attempted in GMP::END() doesn't work when mpz's 67 are created as constants because END() is called before they're 68 destroyed. What's the right place to hook such a check? 69 70 See the bugs section of GMP.pm too. */ 71 72 73 /* Comment this out to get assertion checking. */ 74 #define NDEBUG 75 76 /* Change this to "#define TRACE(x) x" for some diagnostics. */ 77 #define TRACE(x) 78 79 80 #include <assert.h> 81 #include <float.h> 82 83 #include "EXTERN.h" 84 #include "perl.h" 85 #include "XSUB.h" 86 #include "patchlevel.h" 87 88 #include "gmp.h" 89 90 91 /* Perl 5.005 doesn't have SvIsUV, only 5.6 and up. 92 Perl 5.8 has SvUOK, but not 5.6, so we don't use that. */ 93 #ifndef SvIsUV 94 #define SvIsUV(sv) 0 95 #endif 96 #ifndef SvUVX 97 #define SvUVX(sv) (croak("GMP: oops, shouldn't be using SvUVX"), 0) 98 #endif 99 100 101 /* Code which doesn't check anything itself, but exists to support other 102 assert()s. */ 103 #ifdef NDEBUG 104 #define assert_support(x) 105 #else 106 #define assert_support(x) x 107 #endif 108 109 /* LONG_MAX + 1 and ULONG_MAX + 1, as a doubles */ 110 #define LONG_MAX_P1_AS_DOUBLE ((double) ((unsigned long) LONG_MAX + 1)) 111 #define ULONG_MAX_P1_AS_DOUBLE (2.0 * (double) ((unsigned long) ULONG_MAX/2 + 1)) 112 113 /* Check for perl version "major.minor". 114 Perl 5.004 doesn't have PERL_REVISION and PERL_VERSION, but that's ok, 115 we're only interested in tests above that. */ 116 #if defined (PERL_REVISION) && defined (PERL_VERSION) 117 #define PERL_GE(major,minor) \ 118 (PERL_REVISION > (major) \ 119 || ((major) == PERL_REVISION && PERL_VERSION >= (minor))) 120 #else 121 #define PERL_GE(major,minor) (0) 122 #endif 123 #define PERL_LT(major,minor) (! PERL_GE(major,minor)) 124 125 /* sv_derived_from etc in 5.005 took "char *" rather than "const char *". 126 Avoid some compiler warnings by using const only where it works. */ 127 #if PERL_LT (5,6) 128 #define classconst 129 #else 130 #define classconst const 131 #endif 132 133 /* In a MINGW or Cygwin DLL build of gmp, the various gmp functions are 134 given with dllimport directives, which prevents them being used as 135 initializers for constant data. We give function tables as 136 "static_functable const ...", which is normally "static const", but for 137 mingw expands to just "const" making the table an automatic with a 138 run-time initializer. 139 140 In gcc 3.3.1, the function tables initialized like this end up getting 141 all the __imp__foo values fetched, even though just one or two will be 142 used. This is wasteful, but probably not too bad. */ 143 144 #if defined (__MINGW32__) || defined (__CYGWIN__) 145 #define static_functable 146 #else 147 #define static_functable static 148 #endif 149 150 #define GMP_MALLOC_ID 42 151 152 static classconst char mpz_class[] = "GMP::Mpz"; 153 static classconst char mpq_class[] = "GMP::Mpq"; 154 static classconst char mpf_class[] = "GMP::Mpf"; 155 static classconst char rand_class[] = "GMP::Rand"; 156 157 static HV *mpz_class_hv; 158 static HV *mpq_class_hv; 159 static HV *mpf_class_hv; 160 161 assert_support (static long mpz_count = 0;) 162 assert_support (static long mpq_count = 0;) 163 assert_support (static long mpf_count = 0;) 164 assert_support (static long rand_count = 0;) 165 166 #define TRACE_ACTIVE() \ 167 assert_support \ 168 (TRACE (printf (" active %ld mpz, %ld mpq, %ld mpf, %ld randstate\n", \ 169 mpz_count, mpq_count, mpf_count, rand_count))) 170 171 172 /* Each "struct mpz_elem" etc is an mpz_t with a link field tacked on the 173 end so they can be held on a linked list. */ 174 175 #define CREATE_MPX(type) \ 176 \ 177 /* must have mpz_t etc first, for sprintf below */ \ 178 struct type##_elem { \ 179 type##_t m; \ 180 struct type##_elem *next; \ 181 }; \ 182 typedef struct type##_elem *type; \ 183 typedef struct type##_elem *type##_assume; \ 184 typedef type##_ptr type##_coerce; \ 185 \ 186 static type type##_freelist = NULL; \ 187 \ 188 static type \ 189 new_##type (void) \ 190 { \ 191 type p; \ 192 TRACE (printf ("new %s\n", type##_class)); \ 193 if (type##_freelist != NULL) \ 194 { \ 195 p = type##_freelist; \ 196 type##_freelist = type##_freelist->next; \ 197 } \ 198 else \ 199 { \ 200 New (GMP_MALLOC_ID, p, 1, struct type##_elem); \ 201 type##_init (p->m); \ 202 } \ 203 TRACE (printf (" p=%p\n", p)); \ 204 assert_support (type##_count++); \ 205 TRACE_ACTIVE (); \ 206 return p; \ 207 } \ 208 209 CREATE_MPX (mpz) 210 CREATE_MPX (mpq) 211 212 typedef mpf_ptr mpf; 213 typedef mpf_ptr mpf_assume; 214 typedef mpf_ptr mpf_coerce_st0; 215 typedef mpf_ptr mpf_coerce_def; 216 217 218 static mpf 219 new_mpf (unsigned long prec) 220 { 221 mpf p; 222 New (GMP_MALLOC_ID, p, 1, __mpf_struct); 223 mpf_init2 (p, prec); 224 TRACE (printf (" mpf p=%p\n", p)); 225 assert_support (mpf_count++); 226 TRACE_ACTIVE (); 227 return p; 228 } 229 230 231 /* tmp_mpf_t records an allocated precision with an mpf_t so changes of 232 precision can be done with just an mpf_set_prec_raw. */ 233 234 struct tmp_mpf_struct { 235 mpf_t m; 236 unsigned long allocated_prec; 237 }; 238 typedef const struct tmp_mpf_struct *tmp_mpf_srcptr; 239 typedef struct tmp_mpf_struct *tmp_mpf_ptr; 240 typedef struct tmp_mpf_struct tmp_mpf_t[1]; 241 242 #define tmp_mpf_init(f) \ 243 do { \ 244 mpf_init (f->m); \ 245 f->allocated_prec = mpf_get_prec (f->m); \ 246 } while (0) 247 248 static void 249 tmp_mpf_grow (tmp_mpf_ptr f, unsigned long prec) 250 { 251 mpf_set_prec_raw (f->m, f->allocated_prec); 252 mpf_set_prec (f->m, prec); 253 f->allocated_prec = mpf_get_prec (f->m); 254 } 255 256 #define tmp_mpf_shrink(f) tmp_mpf_grow (f, 1L) 257 258 #define tmp_mpf_set_prec(f,prec) \ 259 do { \ 260 if (prec > f->allocated_prec) \ 261 tmp_mpf_grow (f, prec); \ 262 else \ 263 mpf_set_prec_raw (f->m, prec); \ 264 } while (0) 265 266 267 static mpz_t tmp_mpz_0, tmp_mpz_1, tmp_mpz_2; 268 static mpq_t tmp_mpq_0, tmp_mpq_1; 269 static tmp_mpf_t tmp_mpf_0, tmp_mpf_1; 270 271 /* for GMP::Mpz::export */ 272 #define tmp_mpz_4 tmp_mpz_2 273 274 275 #define FREE_MPX_FREELIST(p,type) \ 276 do { \ 277 TRACE (printf ("free %s\n", type##_class)); \ 278 p->next = type##_freelist; \ 279 type##_freelist = p; \ 280 assert_support (type##_count--); \ 281 TRACE_ACTIVE (); \ 282 assert (type##_count >= 0); \ 283 } while (0) 284 285 /* this version for comparison, if desired */ 286 #define FREE_MPX_NOFREELIST(p,type) \ 287 do { \ 288 TRACE (printf ("free %s\n", type##_class)); \ 289 type##_clear (p->m); \ 290 Safefree (p); \ 291 assert_support (type##_count--); \ 292 TRACE_ACTIVE (); \ 293 assert (type##_count >= 0); \ 294 } while (0) 295 296 #define free_mpz(z) FREE_MPX_FREELIST (z, mpz) 297 #define free_mpq(q) FREE_MPX_FREELIST (q, mpq) 298 299 300 /* Return a new mortal SV holding the given mpx_ptr pointer. 301 class_hv should be one of mpz_class_hv etc. */ 302 #define MPX_NEWMORTAL(mpx_ptr, class_hv) \ 303 sv_bless (sv_setref_pv (sv_newmortal(), NULL, mpx_ptr), class_hv) 304 305 /* Aliases for use in typemaps */ 306 typedef char *malloced_string; 307 typedef const char *const_string; 308 typedef const char *const_string_assume; 309 typedef char *string; 310 typedef SV *order_noswap; 311 typedef SV *dummy; 312 typedef SV *SV_copy_0; 313 typedef unsigned long ulong_coerce; 314 typedef __gmp_randstate_struct *randstate; 315 typedef UV gmp_UV; 316 317 #define SvMPX(s,type) ((type) SvIV((SV*) SvRV(s))) 318 #define SvMPZ(s) SvMPX(s,mpz) 319 #define SvMPQ(s) SvMPX(s,mpq) 320 #define SvMPF(s) SvMPX(s,mpf) 321 #define SvRANDSTATE(s) SvMPX(s,randstate) 322 323 #define MPX_ASSUME(x,sv,type) \ 324 do { \ 325 assert (sv_derived_from (sv, type##_class)); \ 326 x = SvMPX(sv,type); \ 327 } while (0) 328 329 #define MPZ_ASSUME(z,sv) MPX_ASSUME(z,sv,mpz) 330 #define MPQ_ASSUME(q,sv) MPX_ASSUME(q,sv,mpq) 331 #define MPF_ASSUME(f,sv) MPX_ASSUME(f,sv,mpf) 332 333 #define numberof(x) (sizeof (x) / sizeof ((x)[0])) 334 #define SGN(x) ((x)<0 ? -1 : (x) != 0) 335 #define ABS(x) ((x)>=0 ? (x) : -(x)) 336 #define double_integer_p(d) (floor (d) == (d)) 337 338 #define x_mpq_integer_p(q) \ 339 (mpz_cmp_ui (mpq_denref(q), 1L) == 0) 340 341 #define assert_table(ix) assert (ix >= 0 && ix < numberof (table)) 342 343 #define SV_PTR_SWAP(x,y) \ 344 do { SV *__tmp = (x); (x) = (y); (y) = __tmp; } while (0) 345 #define MPF_PTR_SWAP(x,y) \ 346 do { mpf_ptr __tmp = (x); (x) = (y); (y) = __tmp; } while (0) 347 348 349 static void 350 class_or_croak (SV *sv, classconst char *cl) 351 { 352 if (! sv_derived_from (sv, cl)) 353 croak("not type %s", cl); 354 } 355 356 357 /* These are macros, wrap them in functions. */ 358 static int 359 x_mpz_odd_p (mpz_srcptr z) 360 { 361 return mpz_odd_p (z); 362 } 363 static int 364 x_mpz_even_p (mpz_srcptr z) 365 { 366 return mpz_even_p (z); 367 } 368 369 static void 370 x_mpq_pow_ui (mpq_ptr r, mpq_srcptr b, unsigned long e) 371 { 372 mpz_pow_ui (mpq_numref(r), mpq_numref(b), e); 373 mpz_pow_ui (mpq_denref(r), mpq_denref(b), e); 374 } 375 376 377 static void * 378 my_gmp_alloc (size_t n) 379 { 380 void *p; 381 TRACE (printf ("my_gmp_alloc %u\n", n)); 382 New (GMP_MALLOC_ID, p, n, char); 383 TRACE (printf (" p=%p\n", p)); 384 return p; 385 } 386 387 static void * 388 my_gmp_realloc (void *p, size_t oldsize, size_t newsize) 389 { 390 TRACE (printf ("my_gmp_realloc %p, %u to %u\n", p, oldsize, newsize)); 391 Renew (p, newsize, char); 392 TRACE (printf (" p=%p\n", p)); 393 return p; 394 } 395 396 static void 397 my_gmp_free (void *p, size_t n) 398 { 399 TRACE (printf ("my_gmp_free %p %u\n", p, n)); 400 Safefree (p); 401 } 402 403 404 #define my_mpx_set_svstr(type) \ 405 static void \ 406 my_##type##_set_svstr (type##_ptr x, SV *sv) \ 407 { \ 408 const char *str; \ 409 STRLEN len; \ 410 TRACE (printf (" my_" #type "_set_svstr\n")); \ 411 assert (SvPOK(sv) || SvPOKp(sv)); \ 412 str = SvPV (sv, len); \ 413 TRACE (printf (" str \"%s\"\n", str)); \ 414 if (type##_set_str (x, str, 0) != 0) \ 415 croak ("%s: invalid string: %s", type##_class, str); \ 416 } 417 418 my_mpx_set_svstr(mpz) 419 my_mpx_set_svstr(mpq) 420 my_mpx_set_svstr(mpf) 421 422 423 /* very slack */ 424 static int 425 x_mpq_cmp_si (mpq_srcptr x, long yn, unsigned long yd) 426 { 427 mpq y; 428 int ret; 429 y = new_mpq (); 430 mpq_set_si (y->m, yn, yd); 431 ret = mpq_cmp (x, y->m); 432 free_mpq (y); 433 return ret; 434 } 435 436 static int 437 x_mpq_fits_slong_p (mpq_srcptr q) 438 { 439 return x_mpq_cmp_si (q, LONG_MIN, 1L) >= 0 440 && mpq_cmp_ui (q, LONG_MAX, 1L) <= 0; 441 } 442 443 static int 444 x_mpz_cmp_q (mpz_ptr x, mpq_srcptr y) 445 { 446 int ret; 447 mpz_set_ui (mpq_denref(tmp_mpq_0), 1L); 448 mpz_swap (mpq_numref(tmp_mpq_0), x); 449 ret = mpq_cmp (tmp_mpq_0, y); 450 mpz_swap (mpq_numref(tmp_mpq_0), x); 451 return ret; 452 } 453 454 static int 455 x_mpz_cmp_f (mpz_srcptr x, mpf_srcptr y) 456 { 457 tmp_mpf_set_prec (tmp_mpf_0, mpz_sizeinbase (x, 2)); 458 mpf_set_z (tmp_mpf_0->m, x); 459 return mpf_cmp (tmp_mpf_0->m, y); 460 } 461 462 463 #define USE_UNKNOWN 0 464 #define USE_IVX 1 465 #define USE_UVX 2 466 #define USE_NVX 3 467 #define USE_PVX 4 468 #define USE_MPZ 5 469 #define USE_MPQ 6 470 #define USE_MPF 7 471 472 /* mg_get is called every time we get a value, even if the private flags are 473 still set from a previous such call. This is the same as as SvIV and 474 friends do. 475 476 When POK, we use the PV, even if there's an IV or NV available. This is 477 because it's hard to be sure there wasn't any rounding in establishing 478 the IV and/or NV. Cases of overflow, where the PV should definitely be 479 used, are easy enough to spot, but rounding is hard. So although IV or 480 NV would be more efficient, we must use the PV to be sure of getting all 481 the data. Applications should convert once to mpz, mpq or mpf when using 482 a value repeatedly. 483 484 Zany dual-type scalars like $! where the IV is an error code and the PV 485 is an error description string won't work with this preference for PV, 486 but that's too bad. Such scalars should be rare, and unlikely to be used 487 in bignum calculations. 488 489 When IOK and NOK are both set, we would prefer to use the IV since it can 490 be converted more efficiently, and because on a 64-bit system the NV may 491 have less bits than the IV. The following rules are applied, 492 493 - If the NV is not an integer, then we must use that NV, since clearly 494 the IV was merely established by rounding and is not the full value. 495 496 - In perl prior to 5.8, an NV too big for an IV leaves an overflow value 497 0xFFFFFFFF. If the NV is too big to fit an IV then clearly it's the NV 498 which is the true value and must be used. 499 500 - In perl 5.8 and up, such an overflow doesn't set IOK, so that test is 501 unnecessary. However when coming from get-magic, IOKp _is_ set, and we 502 must check for overflow the same as in older perl. 503 504 FIXME: 505 506 We'd like to call mg_get just once, but unfortunately sv_derived_from() 507 will call it for each of our checks. We could do a string compare like 508 sv_isa ourselves, but that only tests the exact class, it doesn't 509 recognise subclassing. There doesn't seem to be a public interface to 510 the subclassing tests (in the internal isa_lookup() function). */ 511 512 int 513 use_sv (SV *sv) 514 { 515 double d; 516 517 if (SvGMAGICAL(sv)) 518 { 519 mg_get(sv); 520 521 if (SvPOKp(sv)) 522 return USE_PVX; 523 524 if (SvIOKp(sv)) 525 { 526 if (SvIsUV(sv)) 527 { 528 if (SvNOKp(sv)) 529 goto u_or_n; 530 return USE_UVX; 531 } 532 else 533 { 534 if (SvNOKp(sv)) 535 goto i_or_n; 536 return USE_IVX; 537 } 538 } 539 540 if (SvNOKp(sv)) 541 return USE_NVX; 542 543 goto rok_or_unknown; 544 } 545 546 if (SvPOK(sv)) 547 return USE_PVX; 548 549 if (SvIOK(sv)) 550 { 551 if (SvIsUV(sv)) 552 { 553 if (SvNOK(sv)) 554 { 555 if (PERL_LT (5, 8)) 556 { 557 u_or_n: 558 d = SvNVX(sv); 559 if (d >= ULONG_MAX_P1_AS_DOUBLE || d < 0.0) 560 return USE_NVX; 561 } 562 d = SvNVX(sv); 563 if (d != floor (d)) 564 return USE_NVX; 565 } 566 return USE_UVX; 567 } 568 else 569 { 570 if (SvNOK(sv)) 571 { 572 if (PERL_LT (5, 8)) 573 { 574 i_or_n: 575 d = SvNVX(sv); 576 if (d >= LONG_MAX_P1_AS_DOUBLE || d < (double) LONG_MIN) 577 return USE_NVX; 578 } 579 d = SvNVX(sv); 580 if (d != floor (d)) 581 return USE_NVX; 582 } 583 return USE_IVX; 584 } 585 } 586 587 if (SvNOK(sv)) 588 return USE_NVX; 589 590 rok_or_unknown: 591 if (SvROK(sv)) 592 { 593 if (sv_derived_from (sv, mpz_class)) 594 return USE_MPZ; 595 if (sv_derived_from (sv, mpq_class)) 596 return USE_MPQ; 597 if (sv_derived_from (sv, mpf_class)) 598 return USE_MPF; 599 } 600 601 return USE_UNKNOWN; 602 } 603 604 605 /* Coerce sv to an mpz. Use tmp to hold the converted value if sv isn't 606 already an mpz (or an mpq of which the numerator can be used). Return 607 the chosen mpz (tmp or the contents of sv). */ 608 609 static mpz_ptr 610 coerce_mpz_using (mpz_ptr tmp, SV *sv, int use) 611 { 612 switch (use) { 613 case USE_IVX: 614 mpz_set_si (tmp, SvIVX(sv)); 615 return tmp; 616 617 case USE_UVX: 618 mpz_set_ui (tmp, SvUVX(sv)); 619 return tmp; 620 621 case USE_NVX: 622 { 623 double d; 624 d = SvNVX(sv); 625 if (! double_integer_p (d)) 626 croak ("cannot coerce non-integer double to mpz"); 627 mpz_set_d (tmp, d); 628 return tmp; 629 } 630 631 case USE_PVX: 632 my_mpz_set_svstr (tmp, sv); 633 return tmp; 634 635 case USE_MPZ: 636 return SvMPZ(sv)->m; 637 638 case USE_MPQ: 639 { 640 mpq q = SvMPQ(sv); 641 if (! x_mpq_integer_p (q->m)) 642 croak ("cannot coerce non-integer mpq to mpz"); 643 return mpq_numref(q->m); 644 } 645 646 case USE_MPF: 647 { 648 mpf f = SvMPF(sv); 649 if (! mpf_integer_p (f)) 650 croak ("cannot coerce non-integer mpf to mpz"); 651 mpz_set_f (tmp, f); 652 return tmp; 653 } 654 655 default: 656 croak ("cannot coerce to mpz"); 657 } 658 } 659 static mpz_ptr 660 coerce_mpz (mpz_ptr tmp, SV *sv) 661 { 662 return coerce_mpz_using (tmp, sv, use_sv (sv)); 663 } 664 665 666 /* Coerce sv to an mpq. If sv is an mpq then just return that, otherwise 667 use tmp to hold the converted value and return that. */ 668 669 static mpq_ptr 670 coerce_mpq_using (mpq_ptr tmp, SV *sv, int use) 671 { 672 TRACE (printf ("coerce_mpq_using %p %d\n", tmp, use)); 673 switch (use) { 674 case USE_IVX: 675 mpq_set_si (tmp, SvIVX(sv), 1L); 676 return tmp; 677 678 case USE_UVX: 679 mpq_set_ui (tmp, SvUVX(sv), 1L); 680 return tmp; 681 682 case USE_NVX: 683 mpq_set_d (tmp, SvNVX(sv)); 684 return tmp; 685 686 case USE_PVX: 687 my_mpq_set_svstr (tmp, sv); 688 return tmp; 689 690 case USE_MPZ: 691 mpq_set_z (tmp, SvMPZ(sv)->m); 692 return tmp; 693 694 case USE_MPQ: 695 return SvMPQ(sv)->m; 696 697 case USE_MPF: 698 mpq_set_f (tmp, SvMPF(sv)); 699 return tmp; 700 701 default: 702 croak ("cannot coerce to mpq"); 703 } 704 } 705 static mpq_ptr 706 coerce_mpq (mpq_ptr tmp, SV *sv) 707 { 708 return coerce_mpq_using (tmp, sv, use_sv (sv)); 709 } 710 711 712 static void 713 my_mpf_set_sv_using (mpf_ptr f, SV *sv, int use) 714 { 715 switch (use) { 716 case USE_IVX: 717 mpf_set_si (f, SvIVX(sv)); 718 break; 719 720 case USE_UVX: 721 mpf_set_ui (f, SvUVX(sv)); 722 break; 723 724 case USE_NVX: 725 mpf_set_d (f, SvNVX(sv)); 726 break; 727 728 case USE_PVX: 729 my_mpf_set_svstr (f, sv); 730 break; 731 732 case USE_MPZ: 733 mpf_set_z (f, SvMPZ(sv)->m); 734 break; 735 736 case USE_MPQ: 737 mpf_set_q (f, SvMPQ(sv)->m); 738 break; 739 740 case USE_MPF: 741 mpf_set (f, SvMPF(sv)); 742 break; 743 744 default: 745 croak ("cannot coerce to mpf"); 746 } 747 } 748 749 /* Coerce sv to an mpf. If sv is an mpf then just return that, otherwise 750 use tmp to hold the converted value (with prec precision). */ 751 static mpf_ptr 752 coerce_mpf_using (tmp_mpf_ptr tmp, SV *sv, unsigned long prec, int use) 753 { 754 if (use == USE_MPF) 755 return SvMPF(sv); 756 757 tmp_mpf_set_prec (tmp, prec); 758 my_mpf_set_sv_using (tmp->m, sv, use); 759 return tmp->m; 760 } 761 static mpf_ptr 762 coerce_mpf (tmp_mpf_ptr tmp, SV *sv, unsigned long prec) 763 { 764 return coerce_mpf_using (tmp, sv, prec, use_sv (sv)); 765 } 766 767 768 /* Coerce xv to an mpf and store the pointer in x, ditto for yv to x. If 769 one of xv or yv is an mpf then use it for the precision, otherwise use 770 the default precision. */ 771 unsigned long 772 coerce_mpf_pair (mpf *xp, SV *xv, mpf *yp, SV *yv) 773 { 774 int x_use = use_sv (xv); 775 int y_use = use_sv (yv); 776 unsigned long prec; 777 mpf x, y; 778 779 if (x_use == USE_MPF) 780 { 781 x = SvMPF(xv); 782 prec = mpf_get_prec (x); 783 y = coerce_mpf_using (tmp_mpf_0, yv, prec, y_use); 784 } 785 else 786 { 787 y = coerce_mpf_using (tmp_mpf_0, yv, mpf_get_default_prec(), y_use); 788 prec = mpf_get_prec (y); 789 x = coerce_mpf_using (tmp_mpf_1, xv, prec, x_use); 790 } 791 *xp = x; 792 *yp = y; 793 return prec; 794 } 795 796 797 /* Note that SvUV is not used, since it merely treats the signed IV as if it 798 was unsigned. We get an IV and check its sign. */ 799 static unsigned long 800 coerce_ulong (SV *sv) 801 { 802 long n; 803 804 switch (use_sv (sv)) { 805 case USE_IVX: 806 n = SvIVX(sv); 807 negative_check: 808 if (n < 0) 809 goto range_error; 810 return n; 811 812 case USE_UVX: 813 return SvUVX(sv); 814 815 case USE_NVX: 816 { 817 double d; 818 d = SvNVX(sv); 819 if (! double_integer_p (d)) 820 goto integer_error; 821 n = SvIV(sv); 822 } 823 goto negative_check; 824 825 case USE_PVX: 826 /* FIXME: Check the string is an integer. */ 827 n = SvIV(sv); 828 goto negative_check; 829 830 case USE_MPZ: 831 { 832 mpz z = SvMPZ(sv); 833 if (! mpz_fits_ulong_p (z->m)) 834 goto range_error; 835 return mpz_get_ui (z->m); 836 } 837 838 case USE_MPQ: 839 { 840 mpq q = SvMPQ(sv); 841 if (! x_mpq_integer_p (q->m)) 842 goto integer_error; 843 if (! mpz_fits_ulong_p (mpq_numref (q->m))) 844 goto range_error; 845 return mpz_get_ui (mpq_numref (q->m)); 846 } 847 848 case USE_MPF: 849 { 850 mpf f = SvMPF(sv); 851 if (! mpf_integer_p (f)) 852 goto integer_error; 853 if (! mpf_fits_ulong_p (f)) 854 goto range_error; 855 return mpf_get_ui (f); 856 } 857 858 default: 859 croak ("cannot coerce to ulong"); 860 } 861 862 integer_error: 863 croak ("not an integer"); 864 865 range_error: 866 croak ("out of range for ulong"); 867 } 868 869 870 static long 871 coerce_long (SV *sv) 872 { 873 switch (use_sv (sv)) { 874 case USE_IVX: 875 return SvIVX(sv); 876 877 case USE_UVX: 878 { 879 UV u = SvUVX(sv); 880 if (u > (UV) LONG_MAX) 881 goto range_error; 882 return u; 883 } 884 885 case USE_NVX: 886 { 887 double d = SvNVX(sv); 888 if (! double_integer_p (d)) 889 goto integer_error; 890 return SvIV(sv); 891 } 892 893 case USE_PVX: 894 /* FIXME: Check the string is an integer. */ 895 return SvIV(sv); 896 897 case USE_MPZ: 898 { 899 mpz z = SvMPZ(sv); 900 if (! mpz_fits_slong_p (z->m)) 901 goto range_error; 902 return mpz_get_si (z->m); 903 } 904 905 case USE_MPQ: 906 { 907 mpq q = SvMPQ(sv); 908 if (! x_mpq_integer_p (q->m)) 909 goto integer_error; 910 if (! mpz_fits_slong_p (mpq_numref (q->m))) 911 goto range_error; 912 return mpz_get_si (mpq_numref (q->m)); 913 } 914 915 case USE_MPF: 916 { 917 mpf f = SvMPF(sv); 918 if (! mpf_integer_p (f)) 919 goto integer_error; 920 if (! mpf_fits_slong_p (f)) 921 goto range_error; 922 return mpf_get_si (f); 923 } 924 925 default: 926 croak ("cannot coerce to long"); 927 } 928 929 integer_error: 930 croak ("not an integer"); 931 932 range_error: 933 croak ("out of range for ulong"); 934 } 935 936 937 /* ------------------------------------------------------------------------- */ 938 939 MODULE = GMP PACKAGE = GMP 940 941 BOOT: 942 TRACE (printf ("GMP boot\n")); 943 mp_set_memory_functions (my_gmp_alloc, my_gmp_realloc, my_gmp_free); 944 mpz_init (tmp_mpz_0); 945 mpz_init (tmp_mpz_1); 946 mpz_init (tmp_mpz_2); 947 mpq_init (tmp_mpq_0); 948 mpq_init (tmp_mpq_1); 949 tmp_mpf_init (tmp_mpf_0); 950 tmp_mpf_init (tmp_mpf_1); 951 mpz_class_hv = gv_stashpv (mpz_class, 1); 952 mpq_class_hv = gv_stashpv (mpq_class, 1); 953 mpf_class_hv = gv_stashpv (mpf_class, 1); 954 955 956 void 957 END() 958 CODE: 959 TRACE (printf ("GMP end\n")); 960 TRACE_ACTIVE (); 961 /* These are not always true, see Bugs at the top of the file. */ 962 /* assert (mpz_count == 0); */ 963 /* assert (mpq_count == 0); */ 964 /* assert (mpf_count == 0); */ 965 /* assert (rand_count == 0); */ 966 967 968 const_string 969 version() 970 CODE: 971 RETVAL = gmp_version; 972 OUTPUT: 973 RETVAL 974 975 976 bool 977 fits_slong_p (sv) 978 SV *sv 979 CODE: 980 switch (use_sv (sv)) { 981 case USE_IVX: 982 RETVAL = 1; 983 break; 984 985 case USE_UVX: 986 { 987 UV u = SvUVX(sv); 988 RETVAL = (u <= LONG_MAX); 989 } 990 break; 991 992 case USE_NVX: 993 { 994 double d = SvNVX(sv); 995 RETVAL = (d >= (double) LONG_MIN && d < LONG_MAX_P1_AS_DOUBLE); 996 } 997 break; 998 999 case USE_PVX: 1000 { 1001 STRLEN len; 1002 const char *str = SvPV (sv, len); 1003 if (mpq_set_str (tmp_mpq_0, str, 0) == 0) 1004 RETVAL = x_mpq_fits_slong_p (tmp_mpq_0); 1005 else 1006 { 1007 /* enough precision for a long */ 1008 tmp_mpf_set_prec (tmp_mpf_0, 2*mp_bits_per_limb); 1009 if (mpf_set_str (tmp_mpf_0->m, str, 10) != 0) 1010 croak ("GMP::fits_slong_p invalid string format"); 1011 RETVAL = mpf_fits_slong_p (tmp_mpf_0->m); 1012 } 1013 } 1014 break; 1015 1016 case USE_MPZ: 1017 RETVAL = mpz_fits_slong_p (SvMPZ(sv)->m); 1018 break; 1019 1020 case USE_MPQ: 1021 RETVAL = x_mpq_fits_slong_p (SvMPQ(sv)->m); 1022 break; 1023 1024 case USE_MPF: 1025 RETVAL = mpf_fits_slong_p (SvMPF(sv)); 1026 break; 1027 1028 default: 1029 croak ("GMP::fits_slong_p invalid argument"); 1030 } 1031 OUTPUT: 1032 RETVAL 1033 1034 1035 double 1036 get_d (sv) 1037 SV *sv 1038 CODE: 1039 switch (use_sv (sv)) { 1040 case USE_IVX: 1041 RETVAL = (double) SvIVX(sv); 1042 break; 1043 1044 case USE_UVX: 1045 RETVAL = (double) SvUVX(sv); 1046 break; 1047 1048 case USE_NVX: 1049 RETVAL = SvNVX(sv); 1050 break; 1051 1052 case USE_PVX: 1053 { 1054 STRLEN len; 1055 RETVAL = atof(SvPV(sv, len)); 1056 } 1057 break; 1058 1059 case USE_MPZ: 1060 RETVAL = mpz_get_d (SvMPZ(sv)->m); 1061 break; 1062 1063 case USE_MPQ: 1064 RETVAL = mpq_get_d (SvMPQ(sv)->m); 1065 break; 1066 1067 case USE_MPF: 1068 RETVAL = mpf_get_d (SvMPF(sv)); 1069 break; 1070 1071 default: 1072 croak ("GMP::get_d invalid argument"); 1073 } 1074 OUTPUT: 1075 RETVAL 1076 1077 1078 void 1079 get_d_2exp (sv) 1080 SV *sv 1081 PREINIT: 1082 double ret; 1083 long exp; 1084 PPCODE: 1085 switch (use_sv (sv)) { 1086 case USE_IVX: 1087 ret = (double) SvIVX(sv); 1088 goto use_frexp; 1089 1090 case USE_UVX: 1091 ret = (double) SvUVX(sv); 1092 goto use_frexp; 1093 1094 case USE_NVX: 1095 { 1096 int i_exp; 1097 ret = SvNVX(sv); 1098 use_frexp: 1099 ret = frexp (ret, &i_exp); 1100 exp = i_exp; 1101 } 1102 break; 1103 1104 case USE_PVX: 1105 /* put strings through mpf to give full exp range */ 1106 tmp_mpf_set_prec (tmp_mpf_0, DBL_MANT_DIG); 1107 my_mpf_set_svstr (tmp_mpf_0->m, sv); 1108 ret = mpf_get_d_2exp (&exp, tmp_mpf_0->m); 1109 break; 1110 1111 case USE_MPZ: 1112 ret = mpz_get_d_2exp (&exp, SvMPZ(sv)->m); 1113 break; 1114 1115 case USE_MPQ: 1116 tmp_mpf_set_prec (tmp_mpf_0, DBL_MANT_DIG); 1117 mpf_set_q (tmp_mpf_0->m, SvMPQ(sv)->m); 1118 ret = mpf_get_d_2exp (&exp, tmp_mpf_0->m); 1119 break; 1120 1121 case USE_MPF: 1122 ret = mpf_get_d_2exp (&exp, SvMPF(sv)); 1123 break; 1124 1125 default: 1126 croak ("GMP::get_d_2exp invalid argument"); 1127 } 1128 PUSHs (sv_2mortal (newSVnv (ret))); 1129 PUSHs (sv_2mortal (newSViv (exp))); 1130 1131 1132 long 1133 get_si (sv) 1134 SV *sv 1135 CODE: 1136 switch (use_sv (sv)) { 1137 case USE_IVX: 1138 RETVAL = SvIVX(sv); 1139 break; 1140 1141 case USE_UVX: 1142 RETVAL = SvUVX(sv); 1143 break; 1144 1145 case USE_NVX: 1146 RETVAL = (long) SvNVX(sv); 1147 break; 1148 1149 case USE_PVX: 1150 RETVAL = SvIV(sv); 1151 break; 1152 1153 case USE_MPZ: 1154 RETVAL = mpz_get_si (SvMPZ(sv)->m); 1155 break; 1156 1157 case USE_MPQ: 1158 mpz_set_q (tmp_mpz_0, SvMPQ(sv)->m); 1159 RETVAL = mpz_get_si (tmp_mpz_0); 1160 break; 1161 1162 case USE_MPF: 1163 RETVAL = mpf_get_si (SvMPF(sv)); 1164 break; 1165 1166 default: 1167 croak ("GMP::get_si invalid argument"); 1168 } 1169 OUTPUT: 1170 RETVAL 1171 1172 1173 void 1174 get_str (sv, ...) 1175 SV *sv 1176 PREINIT: 1177 char *str; 1178 mp_exp_t exp; 1179 mpz_ptr z; 1180 mpq_ptr q; 1181 mpf f; 1182 int base; 1183 int ndigits; 1184 PPCODE: 1185 TRACE (printf ("GMP::get_str\n")); 1186 1187 if (items >= 2) 1188 base = coerce_long (ST(1)); 1189 else 1190 base = 10; 1191 TRACE (printf (" base=%d\n", base)); 1192 1193 if (items >= 3) 1194 ndigits = coerce_long (ST(2)); 1195 else 1196 ndigits = 10; 1197 TRACE (printf (" ndigits=%d\n", ndigits)); 1198 1199 EXTEND (SP, 2); 1200 1201 switch (use_sv (sv)) { 1202 case USE_IVX: 1203 mpz_set_si (tmp_mpz_0, SvIVX(sv)); 1204 get_tmp_mpz_0: 1205 z = tmp_mpz_0; 1206 goto get_mpz; 1207 1208 case USE_UVX: 1209 mpz_set_ui (tmp_mpz_0, SvUVX(sv)); 1210 goto get_tmp_mpz_0; 1211 1212 case USE_NVX: 1213 /* only digits in the original double, not in the coerced form */ 1214 if (ndigits == 0) 1215 ndigits = DBL_DIG; 1216 mpf_set_d (tmp_mpf_0->m, SvNVX(sv)); 1217 f = tmp_mpf_0->m; 1218 goto get_mpf; 1219 1220 case USE_PVX: 1221 { 1222 /* get_str on a string is not much more than a base conversion */ 1223 STRLEN len; 1224 str = SvPV (sv, len); 1225 if (mpz_set_str (tmp_mpz_0, str, 0) == 0) 1226 { 1227 z = tmp_mpz_0; 1228 goto get_mpz; 1229 } 1230 else if (mpq_set_str (tmp_mpq_0, str, 0) == 0) 1231 { 1232 q = tmp_mpq_0; 1233 goto get_mpq; 1234 } 1235 else 1236 { 1237 /* FIXME: Would like perhaps a precision equivalent to the 1238 number of significant digits of the string, in its given 1239 base. */ 1240 tmp_mpf_set_prec (tmp_mpf_0, strlen(str)); 1241 if (mpf_set_str (tmp_mpf_0->m, str, 10) == 0) 1242 { 1243 f = tmp_mpf_0->m; 1244 goto get_mpf; 1245 } 1246 else 1247 croak ("GMP::get_str invalid string format"); 1248 } 1249 } 1250 break; 1251 1252 case USE_MPZ: 1253 z = SvMPZ(sv)->m; 1254 get_mpz: 1255 str = mpz_get_str (NULL, base, z); 1256 push_str: 1257 PUSHs (sv_2mortal (newSVpv (str, 0))); 1258 break; 1259 1260 case USE_MPQ: 1261 q = SvMPQ(sv)->m; 1262 get_mpq: 1263 str = mpq_get_str (NULL, base, q); 1264 goto push_str; 1265 1266 case USE_MPF: 1267 f = SvMPF(sv); 1268 get_mpf: 1269 str = mpf_get_str (NULL, &exp, base, 0, f); 1270 PUSHs (sv_2mortal (newSVpv (str, 0))); 1271 PUSHs (sv_2mortal (newSViv (exp))); 1272 break; 1273 1274 default: 1275 croak ("GMP::get_str invalid argument"); 1276 } 1277 1278 1279 bool 1280 integer_p (sv) 1281 SV *sv 1282 CODE: 1283 switch (use_sv (sv)) { 1284 case USE_IVX: 1285 case USE_UVX: 1286 RETVAL = 1; 1287 break; 1288 1289 case USE_NVX: 1290 RETVAL = double_integer_p (SvNVX(sv)); 1291 break; 1292 1293 case USE_PVX: 1294 { 1295 /* FIXME: Maybe this should be done by parsing the string, not by an 1296 actual conversion. */ 1297 STRLEN len; 1298 const char *str = SvPV (sv, len); 1299 if (mpq_set_str (tmp_mpq_0, str, 0) == 0) 1300 RETVAL = x_mpq_integer_p (tmp_mpq_0); 1301 else 1302 { 1303 /* enough for all digits of the string */ 1304 tmp_mpf_set_prec (tmp_mpf_0, strlen(str)+64); 1305 if (mpf_set_str (tmp_mpf_0->m, str, 10) == 0) 1306 RETVAL = mpf_integer_p (tmp_mpf_0->m); 1307 else 1308 croak ("GMP::integer_p invalid string format"); 1309 } 1310 } 1311 break; 1312 1313 case USE_MPZ: 1314 RETVAL = 1; 1315 break; 1316 1317 case USE_MPQ: 1318 RETVAL = x_mpq_integer_p (SvMPQ(sv)->m); 1319 break; 1320 1321 case USE_MPF: 1322 RETVAL = mpf_integer_p (SvMPF(sv)); 1323 break; 1324 1325 default: 1326 croak ("GMP::integer_p invalid argument"); 1327 } 1328 OUTPUT: 1329 RETVAL 1330 1331 1332 int 1333 sgn (sv) 1334 SV *sv 1335 CODE: 1336 switch (use_sv (sv)) { 1337 case USE_IVX: 1338 RETVAL = SGN (SvIVX(sv)); 1339 break; 1340 1341 case USE_UVX: 1342 RETVAL = (SvUVX(sv) > 0); 1343 break; 1344 1345 case USE_NVX: 1346 RETVAL = SGN (SvNVX(sv)); 1347 break; 1348 1349 case USE_PVX: 1350 { 1351 /* FIXME: Maybe this should be done by parsing the string, not by an 1352 actual conversion. */ 1353 STRLEN len; 1354 const char *str = SvPV (sv, len); 1355 if (mpq_set_str (tmp_mpq_0, str, 0) == 0) 1356 RETVAL = mpq_sgn (tmp_mpq_0); 1357 else 1358 { 1359 /* enough for all digits of the string */ 1360 tmp_mpf_set_prec (tmp_mpf_0, strlen(str)+64); 1361 if (mpf_set_str (tmp_mpf_0->m, str, 10) == 0) 1362 RETVAL = mpf_sgn (tmp_mpf_0->m); 1363 else 1364 croak ("GMP::sgn invalid string format"); 1365 } 1366 } 1367 break; 1368 1369 case USE_MPZ: 1370 RETVAL = mpz_sgn (SvMPZ(sv)->m); 1371 break; 1372 1373 case USE_MPQ: 1374 RETVAL = mpq_sgn (SvMPQ(sv)->m); 1375 break; 1376 1377 case USE_MPF: 1378 RETVAL = mpf_sgn (SvMPF(sv)); 1379 break; 1380 1381 default: 1382 croak ("GMP::sgn invalid argument"); 1383 } 1384 OUTPUT: 1385 RETVAL 1386 1387 1388 # currently undocumented 1389 void 1390 shrink () 1391 CODE: 1392 #define x_mpz_shrink(z) \ 1393 mpz_set_ui (z, 0L); _mpz_realloc (z, 1) 1394 #define x_mpq_shrink(q) \ 1395 x_mpz_shrink (mpq_numref(q)); x_mpz_shrink (mpq_denref(q)) 1396 1397 x_mpz_shrink (tmp_mpz_0); 1398 x_mpz_shrink (tmp_mpz_1); 1399 x_mpz_shrink (tmp_mpz_2); 1400 x_mpq_shrink (tmp_mpq_0); 1401 x_mpq_shrink (tmp_mpq_1); 1402 tmp_mpf_shrink (tmp_mpf_0); 1403 tmp_mpf_shrink (tmp_mpf_1); 1404 1405 1406 1407 malloced_string 1408 sprintf_internal (fmt, sv) 1409 const_string fmt 1410 SV *sv 1411 CODE: 1412 assert (strlen (fmt) >= 3); 1413 assert (SvROK(sv)); 1414 assert ((sv_derived_from (sv, mpz_class) && fmt[strlen(fmt)-2] == 'Z') 1415 || (sv_derived_from (sv, mpq_class) && fmt[strlen(fmt)-2] == 'Q') 1416 || (sv_derived_from (sv, mpf_class) && fmt[strlen(fmt)-2] == 'F')); 1417 TRACE (printf ("GMP::sprintf_internal\n"); 1418 printf (" fmt |%s|\n", fmt); 1419 printf (" sv |%p|\n", SvMPZ(sv))); 1420 1421 /* cheat a bit here, SvMPZ works for mpq and mpf too */ 1422 gmp_asprintf (&RETVAL, fmt, SvMPZ(sv)); 1423 1424 TRACE (printf (" result |%s|\n", RETVAL)); 1425 OUTPUT: 1426 RETVAL 1427 1428 1429 1430 #------------------------------------------------------------------------------ 1431 1432 MODULE = GMP PACKAGE = GMP::Mpz 1433 1434 mpz 1435 mpz (...) 1436 ALIAS: 1437 GMP::Mpz::new = 1 1438 PREINIT: 1439 SV *sv; 1440 CODE: 1441 TRACE (printf ("%s new, ix=%ld, items=%d\n", mpz_class, ix, (int) items)); 1442 RETVAL = new_mpz(); 1443 1444 switch (items) { 1445 case 0: 1446 mpz_set_ui (RETVAL->m, 0L); 1447 break; 1448 1449 case 1: 1450 sv = ST(0); 1451 TRACE (printf (" use %d\n", use_sv (sv))); 1452 switch (use_sv (sv)) { 1453 case USE_IVX: 1454 mpz_set_si (RETVAL->m, SvIVX(sv)); 1455 break; 1456 1457 case USE_UVX: 1458 mpz_set_ui (RETVAL->m, SvUVX(sv)); 1459 break; 1460 1461 case USE_NVX: 1462 mpz_set_d (RETVAL->m, SvNVX(sv)); 1463 break; 1464 1465 case USE_PVX: 1466 my_mpz_set_svstr (RETVAL->m, sv); 1467 break; 1468 1469 case USE_MPZ: 1470 mpz_set (RETVAL->m, SvMPZ(sv)->m); 1471 break; 1472 1473 case USE_MPQ: 1474 mpz_set_q (RETVAL->m, SvMPQ(sv)->m); 1475 break; 1476 1477 case USE_MPF: 1478 mpz_set_f (RETVAL->m, SvMPF(sv)); 1479 break; 1480 1481 default: 1482 goto invalid; 1483 } 1484 break; 1485 1486 default: 1487 invalid: 1488 croak ("%s new: invalid arguments", mpz_class); 1489 } 1490 OUTPUT: 1491 RETVAL 1492 1493 1494 void 1495 overload_constant (str, pv, d1, ...) 1496 const_string_assume str 1497 SV *pv 1498 dummy d1 1499 PREINIT: 1500 mpz z; 1501 PPCODE: 1502 TRACE (printf ("%s constant: %s\n", mpz_class, str)); 1503 z = new_mpz(); 1504 if (mpz_set_str (z->m, str, 0) == 0) 1505 { 1506 PUSHs (MPX_NEWMORTAL (z, mpz_class_hv)); 1507 } 1508 else 1509 { 1510 free_mpz (z); 1511 PUSHs(pv); 1512 } 1513 1514 1515 mpz 1516 overload_copy (z, d1, d2) 1517 mpz_assume z 1518 dummy d1 1519 dummy d2 1520 CODE: 1521 RETVAL = new_mpz(); 1522 mpz_set (RETVAL->m, z->m); 1523 OUTPUT: 1524 RETVAL 1525 1526 1527 void 1528 DESTROY (z) 1529 mpz_assume z 1530 CODE: 1531 TRACE (printf ("%s DESTROY %p\n", mpz_class, z)); 1532 free_mpz (z); 1533 1534 1535 malloced_string 1536 overload_string (z, d1, d2) 1537 mpz_assume z 1538 dummy d1 1539 dummy d2 1540 CODE: 1541 TRACE (printf ("%s overload_string %p\n", mpz_class, z)); 1542 RETVAL = mpz_get_str (NULL, 10, z->m); 1543 OUTPUT: 1544 RETVAL 1545 1546 1547 mpz 1548 overload_add (xv, yv, order) 1549 SV *xv 1550 SV *yv 1551 SV *order 1552 ALIAS: 1553 GMP::Mpz::overload_sub = 1 1554 GMP::Mpz::overload_mul = 2 1555 GMP::Mpz::overload_div = 3 1556 GMP::Mpz::overload_rem = 4 1557 GMP::Mpz::overload_and = 5 1558 GMP::Mpz::overload_ior = 6 1559 GMP::Mpz::overload_xor = 7 1560 PREINIT: 1561 static_functable const struct { 1562 void (*op) (mpz_ptr, mpz_srcptr, mpz_srcptr); 1563 } table[] = { 1564 { mpz_add }, /* 0 */ 1565 { mpz_sub }, /* 1 */ 1566 { mpz_mul }, /* 2 */ 1567 { mpz_tdiv_q }, /* 3 */ 1568 { mpz_tdiv_r }, /* 4 */ 1569 { mpz_and }, /* 5 */ 1570 { mpz_ior }, /* 6 */ 1571 { mpz_xor }, /* 7 */ 1572 }; 1573 CODE: 1574 assert_table (ix); 1575 if (order == &PL_sv_yes) 1576 SV_PTR_SWAP (xv, yv); 1577 RETVAL = new_mpz(); 1578 (*table[ix].op) (RETVAL->m, 1579 coerce_mpz (tmp_mpz_0, xv), 1580 coerce_mpz (tmp_mpz_1, yv)); 1581 OUTPUT: 1582 RETVAL 1583 1584 1585 void 1586 overload_addeq (x, y, o) 1587 mpz_assume x 1588 mpz_coerce y 1589 order_noswap o 1590 ALIAS: 1591 GMP::Mpz::overload_subeq = 1 1592 GMP::Mpz::overload_muleq = 2 1593 GMP::Mpz::overload_diveq = 3 1594 GMP::Mpz::overload_remeq = 4 1595 GMP::Mpz::overload_andeq = 5 1596 GMP::Mpz::overload_ioreq = 6 1597 GMP::Mpz::overload_xoreq = 7 1598 PREINIT: 1599 static_functable const struct { 1600 void (*op) (mpz_ptr, mpz_srcptr, mpz_srcptr); 1601 } table[] = { 1602 { mpz_add }, /* 0 */ 1603 { mpz_sub }, /* 1 */ 1604 { mpz_mul }, /* 2 */ 1605 { mpz_tdiv_q }, /* 3 */ 1606 { mpz_tdiv_r }, /* 4 */ 1607 { mpz_and }, /* 5 */ 1608 { mpz_ior }, /* 6 */ 1609 { mpz_xor }, /* 7 */ 1610 }; 1611 PPCODE: 1612 assert_table (ix); 1613 (*table[ix].op) (x->m, x->m, y); 1614 XPUSHs (ST(0)); 1615 1616 1617 mpz 1618 overload_lshift (zv, nv, order) 1619 SV *zv 1620 SV *nv 1621 SV *order 1622 ALIAS: 1623 GMP::Mpz::overload_rshift = 1 1624 GMP::Mpz::overload_pow = 2 1625 PREINIT: 1626 static_functable const struct { 1627 void (*op) (mpz_ptr, mpz_srcptr, unsigned long); 1628 } table[] = { 1629 { mpz_mul_2exp }, /* 0 */ 1630 { mpz_fdiv_q_2exp }, /* 1 */ 1631 { mpz_pow_ui }, /* 2 */ 1632 }; 1633 CODE: 1634 assert_table (ix); 1635 if (order == &PL_sv_yes) 1636 SV_PTR_SWAP (zv, nv); 1637 RETVAL = new_mpz(); 1638 (*table[ix].op) (RETVAL->m, coerce_mpz (RETVAL->m, zv), coerce_ulong (nv)); 1639 OUTPUT: 1640 RETVAL 1641 1642 1643 void 1644 overload_lshifteq (z, n, o) 1645 mpz_assume z 1646 ulong_coerce n 1647 order_noswap o 1648 ALIAS: 1649 GMP::Mpz::overload_rshifteq = 1 1650 GMP::Mpz::overload_poweq = 2 1651 PREINIT: 1652 static_functable const struct { 1653 void (*op) (mpz_ptr, mpz_srcptr, unsigned long); 1654 } table[] = { 1655 { mpz_mul_2exp }, /* 0 */ 1656 { mpz_fdiv_q_2exp }, /* 1 */ 1657 { mpz_pow_ui }, /* 2 */ 1658 }; 1659 PPCODE: 1660 assert_table (ix); 1661 (*table[ix].op) (z->m, z->m, n); 1662 XPUSHs(ST(0)); 1663 1664 1665 mpz 1666 overload_abs (z, d1, d2) 1667 mpz_assume z 1668 dummy d1 1669 dummy d2 1670 ALIAS: 1671 GMP::Mpz::overload_neg = 1 1672 GMP::Mpz::overload_com = 2 1673 GMP::Mpz::overload_sqrt = 3 1674 PREINIT: 1675 static_functable const struct { 1676 void (*op) (mpz_ptr w, mpz_srcptr x); 1677 } table[] = { 1678 { mpz_abs }, /* 0 */ 1679 { mpz_neg }, /* 1 */ 1680 { mpz_com }, /* 2 */ 1681 { mpz_sqrt }, /* 3 */ 1682 }; 1683 CODE: 1684 assert_table (ix); 1685 RETVAL = new_mpz(); 1686 (*table[ix].op) (RETVAL->m, z->m); 1687 OUTPUT: 1688 RETVAL 1689 1690 1691 void 1692 overload_inc (z, d1, d2) 1693 mpz_assume z 1694 dummy d1 1695 dummy d2 1696 ALIAS: 1697 GMP::Mpz::overload_dec = 1 1698 PREINIT: 1699 static_functable const struct { 1700 void (*op) (mpz_ptr w, mpz_srcptr x, unsigned long y); 1701 } table[] = { 1702 { mpz_add_ui }, /* 0 */ 1703 { mpz_sub_ui }, /* 1 */ 1704 }; 1705 CODE: 1706 assert_table (ix); 1707 (*table[ix].op) (z->m, z->m, 1L); 1708 1709 1710 int 1711 overload_spaceship (xv, yv, order) 1712 SV *xv 1713 SV *yv 1714 SV *order 1715 PREINIT: 1716 mpz x; 1717 CODE: 1718 TRACE (printf ("%s overload_spaceship\n", mpz_class)); 1719 MPZ_ASSUME (x, xv); 1720 switch (use_sv (yv)) { 1721 case USE_IVX: 1722 RETVAL = mpz_cmp_si (x->m, SvIVX(yv)); 1723 break; 1724 case USE_UVX: 1725 RETVAL = mpz_cmp_ui (x->m, SvUVX(yv)); 1726 break; 1727 case USE_PVX: 1728 RETVAL = mpz_cmp (x->m, coerce_mpz (tmp_mpz_0, yv)); 1729 break; 1730 case USE_NVX: 1731 RETVAL = mpz_cmp_d (x->m, SvNVX(yv)); 1732 break; 1733 case USE_MPZ: 1734 RETVAL = mpz_cmp (x->m, SvMPZ(yv)->m); 1735 break; 1736 case USE_MPQ: 1737 RETVAL = x_mpz_cmp_q (x->m, SvMPQ(yv)->m); 1738 break; 1739 case USE_MPF: 1740 RETVAL = x_mpz_cmp_f (x->m, SvMPF(yv)); 1741 break; 1742 default: 1743 croak ("%s <=>: invalid operand", mpz_class); 1744 } 1745 RETVAL = SGN (RETVAL); 1746 if (order == &PL_sv_yes) 1747 RETVAL = -RETVAL; 1748 OUTPUT: 1749 RETVAL 1750 1751 1752 bool 1753 overload_bool (z, d1, d2) 1754 mpz_assume z 1755 dummy d1 1756 dummy d2 1757 ALIAS: 1758 GMP::Mpz::overload_not = 1 1759 CODE: 1760 RETVAL = (mpz_sgn (z->m) != 0) ^ ix; 1761 OUTPUT: 1762 RETVAL 1763 1764 1765 mpz 1766 bin (n, k) 1767 mpz_coerce n 1768 ulong_coerce k 1769 ALIAS: 1770 GMP::Mpz::root = 1 1771 PREINIT: 1772 /* mpz_root returns an int, hence the cast */ 1773 static_functable const struct { 1774 void (*op) (mpz_ptr, mpz_srcptr, unsigned long); 1775 } table[] = { 1776 { mpz_bin_ui }, /* 0 */ 1777 { (void (*)(mpz_ptr, mpz_srcptr, unsigned long)) mpz_root }, /* 1 */ 1778 }; 1779 CODE: 1780 assert_table (ix); 1781 RETVAL = new_mpz(); 1782 (*table[ix].op) (RETVAL->m, n, k); 1783 OUTPUT: 1784 RETVAL 1785 1786 1787 void 1788 cdiv (a, d) 1789 mpz_coerce a 1790 mpz_coerce d 1791 ALIAS: 1792 GMP::Mpz::fdiv = 1 1793 GMP::Mpz::tdiv = 2 1794 PREINIT: 1795 static_functable const struct { 1796 void (*op) (mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr); 1797 } table[] = { 1798 { mpz_cdiv_qr }, /* 0 */ 1799 { mpz_fdiv_qr }, /* 1 */ 1800 { mpz_tdiv_qr }, /* 2 */ 1801 }; 1802 mpz q, r; 1803 PPCODE: 1804 assert_table (ix); 1805 q = new_mpz(); 1806 r = new_mpz(); 1807 (*table[ix].op) (q->m, r->m, a, d); 1808 EXTEND (SP, 2); 1809 PUSHs (MPX_NEWMORTAL (q, mpz_class_hv)); 1810 PUSHs (MPX_NEWMORTAL (r, mpz_class_hv)); 1811 1812 1813 void 1814 cdiv_2exp (a, d) 1815 mpz_coerce a 1816 ulong_coerce d 1817 ALIAS: 1818 GMP::Mpz::fdiv_2exp = 1 1819 GMP::Mpz::tdiv_2exp = 2 1820 PREINIT: 1821 static_functable const struct { 1822 void (*q) (mpz_ptr, mpz_srcptr, unsigned long); 1823 void (*r) (mpz_ptr, mpz_srcptr, unsigned long); 1824 } table[] = { 1825 { mpz_cdiv_q_2exp, mpz_cdiv_r_2exp }, /* 0 */ 1826 { mpz_fdiv_q_2exp, mpz_fdiv_r_2exp }, /* 1 */ 1827 { mpz_tdiv_q_2exp, mpz_tdiv_r_2exp }, /* 2 */ 1828 }; 1829 mpz q, r; 1830 PPCODE: 1831 assert_table (ix); 1832 q = new_mpz(); 1833 r = new_mpz(); 1834 (*table[ix].q) (q->m, a, d); 1835 (*table[ix].r) (r->m, a, d); 1836 EXTEND (SP, 2); 1837 PUSHs (MPX_NEWMORTAL (q, mpz_class_hv)); 1838 PUSHs (MPX_NEWMORTAL (r, mpz_class_hv)); 1839 1840 1841 bool 1842 congruent_p (a, c, d) 1843 mpz_coerce a 1844 mpz_coerce c 1845 mpz_coerce d 1846 PREINIT: 1847 CODE: 1848 RETVAL = mpz_congruent_p (a, c, d); 1849 OUTPUT: 1850 RETVAL 1851 1852 1853 bool 1854 congruent_2exp_p (a, c, d) 1855 mpz_coerce a 1856 mpz_coerce c 1857 ulong_coerce d 1858 PREINIT: 1859 CODE: 1860 RETVAL = mpz_congruent_2exp_p (a, c, d); 1861 OUTPUT: 1862 RETVAL 1863 1864 1865 mpz 1866 divexact (a, d) 1867 mpz_coerce a 1868 mpz_coerce d 1869 ALIAS: 1870 GMP::Mpz::mod = 1 1871 PREINIT: 1872 static_functable const struct { 1873 void (*op) (mpz_ptr, mpz_srcptr, mpz_srcptr); 1874 } table[] = { 1875 { mpz_divexact }, /* 0 */ 1876 { mpz_mod }, /* 1 */ 1877 }; 1878 CODE: 1879 assert_table (ix); 1880 RETVAL = new_mpz(); 1881 (*table[ix].op) (RETVAL->m, a, d); 1882 OUTPUT: 1883 RETVAL 1884 1885 1886 bool 1887 divisible_p (a, d) 1888 mpz_coerce a 1889 mpz_coerce d 1890 CODE: 1891 RETVAL = mpz_divisible_p (a, d); 1892 OUTPUT: 1893 RETVAL 1894 1895 1896 bool 1897 divisible_2exp_p (a, d) 1898 mpz_coerce a 1899 ulong_coerce d 1900 CODE: 1901 RETVAL = mpz_divisible_2exp_p (a, d); 1902 OUTPUT: 1903 RETVAL 1904 1905 1906 bool 1907 even_p (z) 1908 mpz_coerce z 1909 ALIAS: 1910 GMP::Mpz::odd_p = 1 1911 GMP::Mpz::perfect_square_p = 2 1912 GMP::Mpz::perfect_power_p = 3 1913 PREINIT: 1914 static_functable const struct { 1915 int (*op) (mpz_srcptr z); 1916 } table[] = { 1917 { x_mpz_even_p }, /* 0 */ 1918 { x_mpz_odd_p }, /* 1 */ 1919 { mpz_perfect_square_p }, /* 2 */ 1920 { mpz_perfect_power_p }, /* 3 */ 1921 }; 1922 CODE: 1923 assert_table (ix); 1924 RETVAL = (*table[ix].op) (z); 1925 OUTPUT: 1926 RETVAL 1927 1928 1929 mpz 1930 fac (n) 1931 ulong_coerce n 1932 ALIAS: 1933 GMP::Mpz::fib = 1 1934 GMP::Mpz::lucnum = 2 1935 PREINIT: 1936 static_functable const struct { 1937 void (*op) (mpz_ptr r, unsigned long n); 1938 } table[] = { 1939 { mpz_fac_ui }, /* 0 */ 1940 { mpz_fib_ui }, /* 1 */ 1941 { mpz_lucnum_ui }, /* 2 */ 1942 }; 1943 CODE: 1944 assert_table (ix); 1945 RETVAL = new_mpz(); 1946 (*table[ix].op) (RETVAL->m, n); 1947 OUTPUT: 1948 RETVAL 1949 1950 1951 void 1952 fib2 (n) 1953 ulong_coerce n 1954 ALIAS: 1955 GMP::Mpz::lucnum2 = 1 1956 PREINIT: 1957 static_functable const struct { 1958 void (*op) (mpz_ptr r, mpz_ptr r2, unsigned long n); 1959 } table[] = { 1960 { mpz_fib2_ui }, /* 0 */ 1961 { mpz_lucnum2_ui }, /* 1 */ 1962 }; 1963 mpz r, r2; 1964 PPCODE: 1965 assert_table (ix); 1966 r = new_mpz(); 1967 r2 = new_mpz(); 1968 (*table[ix].op) (r->m, r2->m, n); 1969 EXTEND (SP, 2); 1970 PUSHs (MPX_NEWMORTAL (r, mpz_class_hv)); 1971 PUSHs (MPX_NEWMORTAL (r2, mpz_class_hv)); 1972 1973 1974 mpz 1975 gcd (x, ...) 1976 mpz_coerce x 1977 ALIAS: 1978 GMP::Mpz::lcm = 1 1979 PREINIT: 1980 static_functable const struct { 1981 void (*op) (mpz_ptr w, mpz_srcptr x, mpz_srcptr y); 1982 void (*op_ui) (mpz_ptr w, mpz_srcptr x, unsigned long y); 1983 } table[] = { 1984 /* cast to ignore ulong return from mpz_gcd_ui */ 1985 { mpz_gcd, 1986 (void (*) (mpz_ptr, mpz_srcptr, unsigned long)) mpz_gcd_ui }, /* 0 */ 1987 { mpz_lcm, mpz_lcm_ui }, /* 1 */ 1988 }; 1989 int i; 1990 SV *yv; 1991 CODE: 1992 assert_table (ix); 1993 RETVAL = new_mpz(); 1994 if (items == 1) 1995 mpz_set (RETVAL->m, x); 1996 else 1997 { 1998 for (i = 1; i < items; i++) 1999 { 2000 yv = ST(i); 2001 if (SvIOK(yv)) 2002 (*table[ix].op_ui) (RETVAL->m, x, ABS(SvIVX(yv))); 2003 else 2004 (*table[ix].op) (RETVAL->m, x, coerce_mpz (tmp_mpz_1, yv)); 2005 x = RETVAL->m; 2006 } 2007 } 2008 OUTPUT: 2009 RETVAL 2010 2011 2012 void 2013 gcdext (a, b) 2014 mpz_coerce a 2015 mpz_coerce b 2016 PREINIT: 2017 mpz g, x, y; 2018 SV *sv; 2019 PPCODE: 2020 g = new_mpz(); 2021 x = new_mpz(); 2022 y = new_mpz(); 2023 mpz_gcdext (g->m, x->m, y->m, a, b); 2024 EXTEND (SP, 3); 2025 PUSHs (MPX_NEWMORTAL (g, mpz_class_hv)); 2026 PUSHs (MPX_NEWMORTAL (x, mpz_class_hv)); 2027 PUSHs (MPX_NEWMORTAL (y, mpz_class_hv)); 2028 2029 2030 unsigned long 2031 hamdist (x, y) 2032 mpz_coerce x 2033 mpz_coerce y 2034 CODE: 2035 RETVAL = mpz_hamdist (x, y); 2036 OUTPUT: 2037 RETVAL 2038 2039 2040 mpz 2041 invert (a, m) 2042 mpz_coerce a 2043 mpz_coerce m 2044 CODE: 2045 RETVAL = new_mpz(); 2046 if (! mpz_invert (RETVAL->m, a, m)) 2047 { 2048 free_mpz (RETVAL); 2049 XSRETURN_UNDEF; 2050 } 2051 OUTPUT: 2052 RETVAL 2053 2054 2055 int 2056 jacobi (a, b) 2057 mpz_coerce a 2058 mpz_coerce b 2059 CODE: 2060 RETVAL = mpz_jacobi (a, b); 2061 OUTPUT: 2062 RETVAL 2063 2064 2065 int 2066 kronecker (a, b) 2067 SV *a 2068 SV *b 2069 CODE: 2070 if (SvIOK(b)) 2071 RETVAL = mpz_kronecker_si (coerce_mpz(tmp_mpz_0,a), SvIVX(b)); 2072 else if (SvIOK(a)) 2073 RETVAL = mpz_si_kronecker (SvIVX(a), coerce_mpz(tmp_mpz_0,b)); 2074 else 2075 RETVAL = mpz_kronecker (coerce_mpz(tmp_mpz_0,a), 2076 coerce_mpz(tmp_mpz_1,b)); 2077 OUTPUT: 2078 RETVAL 2079 2080 2081 void 2082 mpz_export (order, size, endian, nails, z) 2083 int order 2084 size_t size 2085 int endian 2086 size_t nails 2087 mpz_coerce z 2088 PREINIT: 2089 size_t numb, count, bytes, actual_count; 2090 char *data; 2091 SV *sv; 2092 PPCODE: 2093 numb = 8*size - nails; 2094 count = (mpz_sizeinbase (z, 2) + numb-1) / numb; 2095 bytes = count * size; 2096 New (GMP_MALLOC_ID, data, bytes+1, char); 2097 mpz_export (data, &actual_count, order, size, endian, nails, z); 2098 assert (count == actual_count); 2099 data[bytes] = '\0'; 2100 sv = sv_newmortal(); sv_usepvn_mg (sv, data, bytes); PUSHs(sv); 2101 2102 2103 mpz 2104 mpz_import (order, size, endian, nails, sv) 2105 int order 2106 size_t size 2107 int endian 2108 size_t nails 2109 SV *sv 2110 PREINIT: 2111 size_t count; 2112 const char *data; 2113 STRLEN len; 2114 CODE: 2115 data = SvPV (sv, len); 2116 if ((len % size) != 0) 2117 croak ("%s mpz_import: string not a multiple of the given size", 2118 mpz_class); 2119 count = len / size; 2120 RETVAL = new_mpz(); 2121 mpz_import (RETVAL->m, count, order, size, endian, nails, data); 2122 OUTPUT: 2123 RETVAL 2124 2125 2126 mpz 2127 nextprime (z) 2128 mpz_coerce z 2129 CODE: 2130 RETVAL = new_mpz(); 2131 mpz_nextprime (RETVAL->m, z); 2132 OUTPUT: 2133 RETVAL 2134 2135 2136 unsigned long 2137 popcount (x) 2138 mpz_coerce x 2139 CODE: 2140 RETVAL = mpz_popcount (x); 2141 OUTPUT: 2142 RETVAL 2143 2144 2145 mpz 2146 powm (b, e, m) 2147 mpz_coerce b 2148 mpz_coerce e 2149 mpz_coerce m 2150 CODE: 2151 RETVAL = new_mpz(); 2152 mpz_powm (RETVAL->m, b, e, m); 2153 OUTPUT: 2154 RETVAL 2155 2156 2157 bool 2158 probab_prime_p (z, n) 2159 mpz_coerce z 2160 ulong_coerce n 2161 CODE: 2162 RETVAL = mpz_probab_prime_p (z, n); 2163 OUTPUT: 2164 RETVAL 2165 2166 2167 # No attempt to coerce here, only an mpz makes sense. 2168 void 2169 realloc (z, limbs) 2170 mpz z 2171 int limbs 2172 CODE: 2173 _mpz_realloc (z->m, limbs); 2174 2175 2176 void 2177 remove (z, f) 2178 mpz_coerce z 2179 mpz_coerce f 2180 PREINIT: 2181 SV *sv; 2182 mpz rem; 2183 unsigned long mult; 2184 PPCODE: 2185 rem = new_mpz(); 2186 mult = mpz_remove (rem->m, z, f); 2187 EXTEND (SP, 2); 2188 PUSHs (MPX_NEWMORTAL (rem, mpz_class_hv)); 2189 PUSHs (sv_2mortal (newSViv (mult))); 2190 2191 2192 void 2193 roote (z, n) 2194 mpz_coerce z 2195 ulong_coerce n 2196 PREINIT: 2197 SV *sv; 2198 mpz root; 2199 int exact; 2200 PPCODE: 2201 root = new_mpz(); 2202 exact = mpz_root (root->m, z, n); 2203 EXTEND (SP, 2); 2204 PUSHs (MPX_NEWMORTAL (root, mpz_class_hv)); 2205 sv = (exact ? &PL_sv_yes : &PL_sv_no); sv_2mortal(sv); PUSHs(sv); 2206 2207 2208 void 2209 rootrem (z, n) 2210 mpz_coerce z 2211 ulong_coerce n 2212 PREINIT: 2213 SV *sv; 2214 mpz root; 2215 mpz rem; 2216 PPCODE: 2217 root = new_mpz(); 2218 rem = new_mpz(); 2219 mpz_rootrem (root->m, rem->m, z, n); 2220 EXTEND (SP, 2); 2221 PUSHs (MPX_NEWMORTAL (root, mpz_class_hv)); 2222 PUSHs (MPX_NEWMORTAL (rem, mpz_class_hv)); 2223 2224 2225 # In the past scan0 and scan1 were described as returning ULONG_MAX which 2226 # could be obtained in perl with ~0. That wasn't true on 64-bit systems 2227 # (eg. alpha) with perl 5.005, since in that version IV and UV were still 2228 # 32-bits. 2229 # 2230 # We changed in gmp 4.2 to just say ~0 for the not-found return. It's 2231 # likely most people have used ~0 rather than POSIX::ULONG_MAX(), so this 2232 # change should match existing usage. It only actually makes a difference 2233 # in old perl, since recent versions have gone to 64-bits for IV and UV, the 2234 # same as a ulong. 2235 # 2236 # In perl 5.005 we explicitly mask the mpz return down to 32-bits to get ~0. 2237 # UV_MAX is no good, it reflects the size of the UV type (64-bits), rather 2238 # than the size of the values one ought to be storing in an SV (32-bits). 2239 2240 gmp_UV 2241 scan0 (z, start) 2242 mpz_coerce z 2243 ulong_coerce start 2244 ALIAS: 2245 GMP::Mpz::scan1 = 1 2246 PREINIT: 2247 static_functable const struct { 2248 unsigned long (*op) (mpz_srcptr, unsigned long); 2249 } table[] = { 2250 { mpz_scan0 }, /* 0 */ 2251 { mpz_scan1 }, /* 1 */ 2252 }; 2253 CODE: 2254 assert_table (ix); 2255 RETVAL = (*table[ix].op) (z, start); 2256 if (PERL_LT (5,6)) 2257 RETVAL &= 0xFFFFFFFF; 2258 OUTPUT: 2259 RETVAL 2260 2261 2262 void 2263 setbit (sv, bit) 2264 SV *sv 2265 ulong_coerce bit 2266 ALIAS: 2267 GMP::Mpz::clrbit = 1 2268 GMP::Mpz::combit = 2 2269 PREINIT: 2270 static_functable const struct { 2271 void (*op) (mpz_ptr, unsigned long); 2272 } table[] = { 2273 { mpz_setbit }, /* 0 */ 2274 { mpz_clrbit }, /* 1 */ 2275 { mpz_combit }, /* 2 */ 2276 }; 2277 int use; 2278 mpz z; 2279 CODE: 2280 use = use_sv (sv); 2281 if (use == USE_MPZ && SvREFCNT(SvRV(sv)) == 1 && ! SvSMAGICAL(sv)) 2282 { 2283 /* our operand is a non-magical mpz with a reference count of 1, so 2284 we can just modify it */ 2285 (*table[ix].op) (SvMPZ(sv)->m, bit); 2286 } 2287 else 2288 { 2289 /* otherwise we need to make a new mpz, from whatever we have, and 2290 operate on that, possibly invoking magic when storing back */ 2291 SV *new_sv; 2292 mpz z = new_mpz (); 2293 mpz_ptr coerce_ptr = coerce_mpz_using (z->m, sv, use); 2294 if (coerce_ptr != z->m) 2295 mpz_set (z->m, coerce_ptr); 2296 (*table[ix].op) (z->m, bit); 2297 new_sv = sv_bless (sv_setref_pv (sv_newmortal(), NULL, z), 2298 mpz_class_hv); 2299 SvSetMagicSV (sv, new_sv); 2300 } 2301 2302 2303 void 2304 sqrtrem (z) 2305 mpz_coerce z 2306 PREINIT: 2307 SV *sv; 2308 mpz root; 2309 mpz rem; 2310 PPCODE: 2311 root = new_mpz(); 2312 rem = new_mpz(); 2313 mpz_sqrtrem (root->m, rem->m, z); 2314 EXTEND (SP, 2); 2315 PUSHs (MPX_NEWMORTAL (root, mpz_class_hv)); 2316 PUSHs (MPX_NEWMORTAL (rem, mpz_class_hv)); 2317 2318 2319 size_t 2320 sizeinbase (z, base) 2321 mpz_coerce z 2322 int base 2323 CODE: 2324 RETVAL = mpz_sizeinbase (z, base); 2325 OUTPUT: 2326 RETVAL 2327 2328 2329 int 2330 tstbit (z, bit) 2331 mpz_coerce z 2332 ulong_coerce bit 2333 CODE: 2334 RETVAL = mpz_tstbit (z, bit); 2335 OUTPUT: 2336 RETVAL 2337 2338 2339 2340 #------------------------------------------------------------------------------ 2341 2342 MODULE = GMP PACKAGE = GMP::Mpq 2343 2344 2345 mpq 2346 mpq (...) 2347 ALIAS: 2348 GMP::Mpq::new = 1 2349 CODE: 2350 TRACE (printf ("%s new, ix=%ld, items=%d\n", mpq_class, ix, (int) items)); 2351 RETVAL = new_mpq(); 2352 switch (items) { 2353 case 0: 2354 mpq_set_ui (RETVAL->m, 0L, 1L); 2355 break; 2356 case 1: 2357 { 2358 mpq_ptr rp = RETVAL->m; 2359 mpq_ptr cp = coerce_mpq (rp, ST(0)); 2360 if (cp != rp) 2361 mpq_set (rp, cp); 2362 } 2363 break; 2364 case 2: 2365 { 2366 mpz_ptr rp, cp; 2367 rp = mpq_numref (RETVAL->m); 2368 cp = coerce_mpz (rp, ST(0)); 2369 if (cp != rp) 2370 mpz_set (rp, cp); 2371 rp = mpq_denref (RETVAL->m); 2372 cp = coerce_mpz (rp, ST(1)); 2373 if (cp != rp) 2374 mpz_set (rp, cp); 2375 } 2376 break; 2377 default: 2378 croak ("%s new: invalid arguments", mpq_class); 2379 } 2380 OUTPUT: 2381 RETVAL 2382 2383 2384 void 2385 overload_constant (str, pv, d1, ...) 2386 const_string_assume str 2387 SV *pv 2388 dummy d1 2389 PREINIT: 2390 SV *sv; 2391 mpq q; 2392 PPCODE: 2393 TRACE (printf ("%s constant: %s\n", mpq_class, str)); 2394 q = new_mpq(); 2395 if (mpq_set_str (q->m, str, 0) == 0) 2396 { sv = sv_bless (sv_setref_pv (sv_newmortal(), NULL, q), mpq_class_hv); } 2397 else 2398 { free_mpq (q); sv = pv; } 2399 XPUSHs(sv); 2400 2401 2402 mpq 2403 overload_copy (q, d1, d2) 2404 mpq_assume q 2405 dummy d1 2406 dummy d2 2407 CODE: 2408 RETVAL = new_mpq(); 2409 mpq_set (RETVAL->m, q->m); 2410 OUTPUT: 2411 RETVAL 2412 2413 2414 void 2415 DESTROY (q) 2416 mpq_assume q 2417 CODE: 2418 TRACE (printf ("%s DESTROY %p\n", mpq_class, q)); 2419 free_mpq (q); 2420 2421 2422 malloced_string 2423 overload_string (q, d1, d2) 2424 mpq_assume q 2425 dummy d1 2426 dummy d2 2427 CODE: 2428 TRACE (printf ("%s overload_string %p\n", mpq_class, q)); 2429 RETVAL = mpq_get_str (NULL, 10, q->m); 2430 OUTPUT: 2431 RETVAL 2432 2433 2434 mpq 2435 overload_add (xv, yv, order) 2436 SV *xv 2437 SV *yv 2438 SV *order 2439 ALIAS: 2440 GMP::Mpq::overload_sub = 1 2441 GMP::Mpq::overload_mul = 2 2442 GMP::Mpq::overload_div = 3 2443 PREINIT: 2444 static_functable const struct { 2445 void (*op) (mpq_ptr, mpq_srcptr, mpq_srcptr); 2446 } table[] = { 2447 { mpq_add }, /* 0 */ 2448 { mpq_sub }, /* 1 */ 2449 { mpq_mul }, /* 2 */ 2450 { mpq_div }, /* 3 */ 2451 }; 2452 CODE: 2453 TRACE (printf ("%s binary\n", mpf_class)); 2454 assert_table (ix); 2455 if (order == &PL_sv_yes) 2456 SV_PTR_SWAP (xv, yv); 2457 RETVAL = new_mpq(); 2458 (*table[ix].op) (RETVAL->m, 2459 coerce_mpq (tmp_mpq_0, xv), 2460 coerce_mpq (tmp_mpq_1, yv)); 2461 OUTPUT: 2462 RETVAL 2463 2464 2465 void 2466 overload_addeq (x, y, o) 2467 mpq_assume x 2468 mpq_coerce y 2469 order_noswap o 2470 ALIAS: 2471 GMP::Mpq::overload_subeq = 1 2472 GMP::Mpq::overload_muleq = 2 2473 GMP::Mpq::overload_diveq = 3 2474 PREINIT: 2475 static_functable const struct { 2476 void (*op) (mpq_ptr, mpq_srcptr, mpq_srcptr); 2477 } table[] = { 2478 { mpq_add }, /* 0 */ 2479 { mpq_sub }, /* 1 */ 2480 { mpq_mul }, /* 2 */ 2481 { mpq_div }, /* 3 */ 2482 }; 2483 PPCODE: 2484 assert_table (ix); 2485 (*table[ix].op) (x->m, x->m, y); 2486 XPUSHs(ST(0)); 2487 2488 2489 mpq 2490 overload_lshift (qv, nv, order) 2491 SV *qv 2492 SV *nv 2493 SV *order 2494 ALIAS: 2495 GMP::Mpq::overload_rshift = 1 2496 GMP::Mpq::overload_pow = 2 2497 PREINIT: 2498 static_functable const struct { 2499 void (*op) (mpq_ptr, mpq_srcptr, unsigned long); 2500 } table[] = { 2501 { mpq_mul_2exp }, /* 0 */ 2502 { mpq_div_2exp }, /* 1 */ 2503 { x_mpq_pow_ui }, /* 2 */ 2504 }; 2505 CODE: 2506 assert_table (ix); 2507 if (order == &PL_sv_yes) 2508 SV_PTR_SWAP (qv, nv); 2509 RETVAL = new_mpq(); 2510 (*table[ix].op) (RETVAL->m, coerce_mpq (RETVAL->m, qv), coerce_ulong (nv)); 2511 OUTPUT: 2512 RETVAL 2513 2514 2515 void 2516 overload_lshifteq (q, n, o) 2517 mpq_assume q 2518 ulong_coerce n 2519 order_noswap o 2520 ALIAS: 2521 GMP::Mpq::overload_rshifteq = 1 2522 GMP::Mpq::overload_poweq = 2 2523 PREINIT: 2524 static_functable const struct { 2525 void (*op) (mpq_ptr, mpq_srcptr, unsigned long); 2526 } table[] = { 2527 { mpq_mul_2exp }, /* 0 */ 2528 { mpq_div_2exp }, /* 1 */ 2529 { x_mpq_pow_ui }, /* 2 */ 2530 }; 2531 PPCODE: 2532 assert_table (ix); 2533 (*table[ix].op) (q->m, q->m, n); 2534 XPUSHs(ST(0)); 2535 2536 2537 void 2538 overload_inc (q, d1, d2) 2539 mpq_assume q 2540 dummy d1 2541 dummy d2 2542 ALIAS: 2543 GMP::Mpq::overload_dec = 1 2544 PREINIT: 2545 static_functable const struct { 2546 void (*op) (mpz_ptr, mpz_srcptr, mpz_srcptr); 2547 } table[] = { 2548 { mpz_add }, /* 0 */ 2549 { mpz_sub }, /* 1 */ 2550 }; 2551 CODE: 2552 assert_table (ix); 2553 (*table[ix].op) (mpq_numref(q->m), mpq_numref(q->m), mpq_denref(q->m)); 2554 2555 2556 mpq 2557 overload_abs (q, d1, d2) 2558 mpq_assume q 2559 dummy d1 2560 dummy d2 2561 ALIAS: 2562 GMP::Mpq::overload_neg = 1 2563 PREINIT: 2564 static_functable const struct { 2565 void (*op) (mpq_ptr w, mpq_srcptr x); 2566 } table[] = { 2567 { mpq_abs }, /* 0 */ 2568 { mpq_neg }, /* 1 */ 2569 }; 2570 CODE: 2571 assert_table (ix); 2572 RETVAL = new_mpq(); 2573 (*table[ix].op) (RETVAL->m, q->m); 2574 OUTPUT: 2575 RETVAL 2576 2577 2578 int 2579 overload_spaceship (x, y, order) 2580 mpq_assume x 2581 mpq_coerce y 2582 SV *order 2583 CODE: 2584 RETVAL = mpq_cmp (x->m, y); 2585 RETVAL = SGN (RETVAL); 2586 if (order == &PL_sv_yes) 2587 RETVAL = -RETVAL; 2588 OUTPUT: 2589 RETVAL 2590 2591 2592 bool 2593 overload_bool (q, d1, d2) 2594 mpq_assume q 2595 dummy d1 2596 dummy d2 2597 ALIAS: 2598 GMP::Mpq::overload_not = 1 2599 CODE: 2600 RETVAL = (mpq_sgn (q->m) != 0) ^ ix; 2601 OUTPUT: 2602 RETVAL 2603 2604 2605 bool 2606 overload_eq (x, yv, d) 2607 mpq_assume x 2608 SV *yv 2609 dummy d 2610 ALIAS: 2611 GMP::Mpq::overload_ne = 1 2612 PREINIT: 2613 int use; 2614 CODE: 2615 use = use_sv (yv); 2616 switch (use) { 2617 case USE_IVX: 2618 case USE_UVX: 2619 case USE_MPZ: 2620 RETVAL = 0; 2621 if (x_mpq_integer_p (x->m)) 2622 { 2623 switch (use) { 2624 case USE_IVX: 2625 RETVAL = (mpz_cmp_si (mpq_numref(x->m), SvIVX(yv)) == 0); 2626 break; 2627 case USE_UVX: 2628 RETVAL = (mpz_cmp_ui (mpq_numref(x->m), SvUVX(yv)) == 0); 2629 break; 2630 case USE_MPZ: 2631 RETVAL = (mpz_cmp (mpq_numref(x->m), SvMPZ(yv)->m) == 0); 2632 break; 2633 } 2634 } 2635 break; 2636 2637 case USE_MPQ: 2638 RETVAL = (mpq_equal (x->m, SvMPQ(yv)->m) != 0); 2639 break; 2640 2641 default: 2642 RETVAL = (mpq_equal (x->m, coerce_mpq_using (tmp_mpq_0, yv, use)) != 0); 2643 break; 2644 } 2645 RETVAL ^= ix; 2646 OUTPUT: 2647 RETVAL 2648 2649 2650 void 2651 canonicalize (q) 2652 mpq q 2653 CODE: 2654 mpq_canonicalize (q->m); 2655 2656 2657 mpq 2658 inv (q) 2659 mpq_coerce q 2660 CODE: 2661 RETVAL = new_mpq(); 2662 mpq_inv (RETVAL->m, q); 2663 OUTPUT: 2664 RETVAL 2665 2666 2667 mpz 2668 num (q) 2669 mpq q 2670 ALIAS: 2671 GMP::Mpq::den = 1 2672 CODE: 2673 RETVAL = new_mpz(); 2674 mpz_set (RETVAL->m, (ix == 0 ? mpq_numref(q->m) : mpq_denref(q->m))); 2675 OUTPUT: 2676 RETVAL 2677 2678 2679 2680 #------------------------------------------------------------------------------ 2681 2682 MODULE = GMP PACKAGE = GMP::Mpf 2683 2684 2685 mpf 2686 mpf (...) 2687 ALIAS: 2688 GMP::Mpf::new = 1 2689 PREINIT: 2690 unsigned long prec; 2691 CODE: 2692 TRACE (printf ("%s new\n", mpf_class)); 2693 if (items > 2) 2694 croak ("%s new: invalid arguments", mpf_class); 2695 prec = (items == 2 ? coerce_ulong (ST(1)) : mpf_get_default_prec()); 2696 RETVAL = new_mpf (prec); 2697 if (items >= 1) 2698 { 2699 SV *sv = ST(0); 2700 my_mpf_set_sv_using (RETVAL, sv, use_sv(sv)); 2701 } 2702 OUTPUT: 2703 RETVAL 2704 2705 2706 mpf 2707 overload_constant (sv, d1, d2, ...) 2708 SV *sv 2709 dummy d1 2710 dummy d2 2711 CODE: 2712 assert (SvPOK (sv)); 2713 TRACE (printf ("%s constant: %s\n", mpq_class, SvPVX(sv))); 2714 RETVAL = new_mpf (mpf_get_default_prec()); 2715 my_mpf_set_svstr (RETVAL, sv); 2716 OUTPUT: 2717 RETVAL 2718 2719 2720 mpf 2721 overload_copy (f, d1, d2) 2722 mpf_assume f 2723 dummy d1 2724 dummy d2 2725 CODE: 2726 TRACE (printf ("%s copy\n", mpf_class)); 2727 RETVAL = new_mpf (mpf_get_prec (f)); 2728 mpf_set (RETVAL, f); 2729 OUTPUT: 2730 RETVAL 2731 2732 2733 void 2734 DESTROY (f) 2735 mpf_assume f 2736 CODE: 2737 TRACE (printf ("%s DESTROY %p\n", mpf_class, f)); 2738 mpf_clear (f); 2739 Safefree (f); 2740 assert_support (mpf_count--); 2741 TRACE_ACTIVE (); 2742 2743 2744 mpf 2745 overload_add (x, y, order) 2746 mpf_assume x 2747 mpf_coerce_st0 y 2748 SV *order 2749 ALIAS: 2750 GMP::Mpf::overload_sub = 1 2751 GMP::Mpf::overload_mul = 2 2752 GMP::Mpf::overload_div = 3 2753 PREINIT: 2754 static_functable const struct { 2755 void (*op) (mpf_ptr, mpf_srcptr, mpf_srcptr); 2756 } table[] = { 2757 { mpf_add }, /* 0 */ 2758 { mpf_sub }, /* 1 */ 2759 { mpf_mul }, /* 2 */ 2760 { mpf_div }, /* 3 */ 2761 }; 2762 CODE: 2763 assert_table (ix); 2764 RETVAL = new_mpf (mpf_get_prec (x)); 2765 if (order == &PL_sv_yes) 2766 MPF_PTR_SWAP (x, y); 2767 (*table[ix].op) (RETVAL, x, y); 2768 OUTPUT: 2769 RETVAL 2770 2771 2772 void 2773 overload_addeq (x, y, o) 2774 mpf_assume x 2775 mpf_coerce_st0 y 2776 order_noswap o 2777 ALIAS: 2778 GMP::Mpf::overload_subeq = 1 2779 GMP::Mpf::overload_muleq = 2 2780 GMP::Mpf::overload_diveq = 3 2781 PREINIT: 2782 static_functable const struct { 2783 void (*op) (mpf_ptr, mpf_srcptr, mpf_srcptr); 2784 } table[] = { 2785 { mpf_add }, /* 0 */ 2786 { mpf_sub }, /* 1 */ 2787 { mpf_mul }, /* 2 */ 2788 { mpf_div }, /* 3 */ 2789 }; 2790 PPCODE: 2791 assert_table (ix); 2792 (*table[ix].op) (x, x, y); 2793 XPUSHs(ST(0)); 2794 2795 2796 mpf 2797 overload_lshift (fv, nv, order) 2798 SV *fv 2799 SV *nv 2800 SV *order 2801 ALIAS: 2802 GMP::Mpf::overload_rshift = 1 2803 GMP::Mpf::overload_pow = 2 2804 PREINIT: 2805 static_functable const struct { 2806 void (*op) (mpf_ptr, mpf_srcptr, unsigned long); 2807 } table[] = { 2808 { mpf_mul_2exp }, /* 0 */ 2809 { mpf_div_2exp }, /* 1 */ 2810 { mpf_pow_ui }, /* 2 */ 2811 }; 2812 mpf f; 2813 unsigned long prec; 2814 CODE: 2815 assert_table (ix); 2816 MPF_ASSUME (f, fv); 2817 prec = mpf_get_prec (f); 2818 if (order == &PL_sv_yes) 2819 SV_PTR_SWAP (fv, nv); 2820 f = coerce_mpf (tmp_mpf_0, fv, prec); 2821 RETVAL = new_mpf (prec); 2822 (*table[ix].op) (RETVAL, f, coerce_ulong (nv)); 2823 OUTPUT: 2824 RETVAL 2825 2826 2827 void 2828 overload_lshifteq (f, n, o) 2829 mpf_assume f 2830 ulong_coerce n 2831 order_noswap o 2832 ALIAS: 2833 GMP::Mpf::overload_rshifteq = 1 2834 GMP::Mpf::overload_poweq = 2 2835 PREINIT: 2836 static_functable const struct { 2837 void (*op) (mpf_ptr, mpf_srcptr, unsigned long); 2838 } table[] = { 2839 { mpf_mul_2exp }, /* 0 */ 2840 { mpf_div_2exp }, /* 1 */ 2841 { mpf_pow_ui }, /* 2 */ 2842 }; 2843 PPCODE: 2844 assert_table (ix); 2845 (*table[ix].op) (f, f, n); 2846 XPUSHs(ST(0)); 2847 2848 2849 mpf 2850 overload_abs (f, d1, d2) 2851 mpf_assume f 2852 dummy d1 2853 dummy d2 2854 ALIAS: 2855 GMP::Mpf::overload_neg = 1 2856 GMP::Mpf::overload_sqrt = 2 2857 PREINIT: 2858 static_functable const struct { 2859 void (*op) (mpf_ptr w, mpf_srcptr x); 2860 } table[] = { 2861 { mpf_abs }, /* 0 */ 2862 { mpf_neg }, /* 1 */ 2863 { mpf_sqrt }, /* 2 */ 2864 }; 2865 CODE: 2866 assert_table (ix); 2867 RETVAL = new_mpf (mpf_get_prec (f)); 2868 (*table[ix].op) (RETVAL, f); 2869 OUTPUT: 2870 RETVAL 2871 2872 2873 void 2874 overload_inc (f, d1, d2) 2875 mpf_assume f 2876 dummy d1 2877 dummy d2 2878 ALIAS: 2879 GMP::Mpf::overload_dec = 1 2880 PREINIT: 2881 static_functable const struct { 2882 void (*op) (mpf_ptr w, mpf_srcptr x, unsigned long y); 2883 } table[] = { 2884 { mpf_add_ui }, /* 0 */ 2885 { mpf_sub_ui }, /* 1 */ 2886 }; 2887 CODE: 2888 assert_table (ix); 2889 (*table[ix].op) (f, f, 1L); 2890 2891 2892 int 2893 overload_spaceship (xv, yv, order) 2894 SV *xv 2895 SV *yv 2896 SV *order 2897 PREINIT: 2898 mpf x; 2899 CODE: 2900 MPF_ASSUME (x, xv); 2901 switch (use_sv (yv)) { 2902 case USE_IVX: 2903 RETVAL = mpf_cmp_si (x, SvIVX(yv)); 2904 break; 2905 case USE_UVX: 2906 RETVAL = mpf_cmp_ui (x, SvUVX(yv)); 2907 break; 2908 case USE_NVX: 2909 RETVAL = mpf_cmp_d (x, SvNVX(yv)); 2910 break; 2911 case USE_PVX: 2912 { 2913 STRLEN len; 2914 const char *str = SvPV (yv, len); 2915 /* enough for all digits of the string */ 2916 tmp_mpf_set_prec (tmp_mpf_0, strlen(str)+64); 2917 if (mpf_set_str (tmp_mpf_0->m, str, 10) != 0) 2918 croak ("%s <=>: invalid string format", mpf_class); 2919 RETVAL = mpf_cmp (x, tmp_mpf_0->m); 2920 } 2921 break; 2922 case USE_MPZ: 2923 RETVAL = - x_mpz_cmp_f (SvMPZ(yv)->m, x); 2924 break; 2925 case USE_MPF: 2926 RETVAL = mpf_cmp (x, SvMPF(yv)); 2927 break; 2928 default: 2929 RETVAL = mpq_cmp (coerce_mpq (tmp_mpq_0, xv), 2930 coerce_mpq (tmp_mpq_1, yv)); 2931 break; 2932 } 2933 RETVAL = SGN (RETVAL); 2934 if (order == &PL_sv_yes) 2935 RETVAL = -RETVAL; 2936 OUTPUT: 2937 RETVAL 2938 2939 2940 bool 2941 overload_bool (f, d1, d2) 2942 mpf_assume f 2943 dummy d1 2944 dummy d2 2945 ALIAS: 2946 GMP::Mpf::overload_not = 1 2947 CODE: 2948 RETVAL = (mpf_sgn (f) != 0) ^ ix; 2949 OUTPUT: 2950 RETVAL 2951 2952 2953 mpf 2954 ceil (f) 2955 mpf_coerce_def f 2956 ALIAS: 2957 GMP::Mpf::floor = 1 2958 GMP::Mpf::trunc = 2 2959 PREINIT: 2960 static_functable const struct { 2961 void (*op) (mpf_ptr w, mpf_srcptr x); 2962 } table[] = { 2963 { mpf_ceil }, /* 0 */ 2964 { mpf_floor }, /* 1 */ 2965 { mpf_trunc }, /* 2 */ 2966 }; 2967 CODE: 2968 assert_table (ix); 2969 RETVAL = new_mpf (mpf_get_prec (f)); 2970 (*table[ix].op) (RETVAL, f); 2971 OUTPUT: 2972 RETVAL 2973 2974 2975 unsigned long 2976 get_default_prec () 2977 CODE: 2978 RETVAL = mpf_get_default_prec(); 2979 OUTPUT: 2980 RETVAL 2981 2982 2983 unsigned long 2984 get_prec (f) 2985 mpf_coerce_def f 2986 CODE: 2987 RETVAL = mpf_get_prec (f); 2988 OUTPUT: 2989 RETVAL 2990 2991 2992 bool 2993 mpf_eq (xv, yv, bits) 2994 SV *xv 2995 SV *yv 2996 ulong_coerce bits 2997 PREINIT: 2998 mpf x, y; 2999 CODE: 3000 TRACE (printf ("%s eq\n", mpf_class)); 3001 coerce_mpf_pair (&x,xv, &y,yv); 3002 RETVAL = mpf_eq (x, y, bits); 3003 OUTPUT: 3004 RETVAL 3005 3006 3007 mpf 3008 reldiff (xv, yv) 3009 SV *xv 3010 SV *yv 3011 PREINIT: 3012 mpf x, y; 3013 unsigned long prec; 3014 CODE: 3015 TRACE (printf ("%s reldiff\n", mpf_class)); 3016 prec = coerce_mpf_pair (&x,xv, &y,yv); 3017 RETVAL = new_mpf (prec); 3018 mpf_reldiff (RETVAL, x, y); 3019 OUTPUT: 3020 RETVAL 3021 3022 3023 void 3024 set_default_prec (prec) 3025 ulong_coerce prec 3026 CODE: 3027 TRACE (printf ("%s set_default_prec %lu\n", mpf_class, prec)); 3028 mpf_set_default_prec (prec); 3029 3030 3031 void 3032 set_prec (sv, prec) 3033 SV *sv 3034 ulong_coerce prec 3035 PREINIT: 3036 mpf_ptr old_f, new_f; 3037 int use; 3038 CODE: 3039 TRACE (printf ("%s set_prec to %lu\n", mpf_class, prec)); 3040 use = use_sv (sv); 3041 if (use == USE_MPF) 3042 { 3043 old_f = SvMPF(sv); 3044 if (SvREFCNT(SvRV(sv)) == 1) 3045 mpf_set_prec (old_f, prec); 3046 else 3047 { 3048 TRACE (printf (" fork new mpf\n")); 3049 new_f = new_mpf (prec); 3050 mpf_set (new_f, old_f); 3051 goto setref; 3052 } 3053 } 3054 else 3055 { 3056 TRACE (printf (" coerce to mpf\n")); 3057 new_f = new_mpf (prec); 3058 my_mpf_set_sv_using (new_f, sv, use); 3059 setref: 3060 sv_bless (sv_setref_pv (sv, NULL, new_f), mpf_class_hv); 3061 } 3062 3063 3064 3065 #------------------------------------------------------------------------------ 3066 3067 MODULE = GMP PACKAGE = GMP::Rand 3068 3069 randstate 3070 new (...) 3071 ALIAS: 3072 GMP::Rand::randstate = 1 3073 CODE: 3074 TRACE (printf ("%s new\n", rand_class)); 3075 New (GMP_MALLOC_ID, RETVAL, 1, __gmp_randstate_struct); 3076 TRACE (printf (" RETVAL %p\n", RETVAL)); 3077 assert_support (rand_count++); 3078 TRACE_ACTIVE (); 3079 3080 if (items == 0) 3081 { 3082 gmp_randinit_default (RETVAL); 3083 } 3084 else 3085 { 3086 if (SvROK (ST(0)) && sv_derived_from (ST(0), rand_class)) 3087 { 3088 if (items != 1) 3089 goto invalid; 3090 gmp_randinit_set (RETVAL, SvRANDSTATE (ST(0))); 3091 } 3092 else 3093 { 3094 STRLEN len; 3095 const char *method = SvPV (ST(0), len); 3096 assert (len == strlen (method)); 3097 if (strcmp (method, "lc_2exp") == 0) 3098 { 3099 if (items != 4) 3100 goto invalid; 3101 gmp_randinit_lc_2exp (RETVAL, 3102 coerce_mpz (tmp_mpz_0, ST(1)), 3103 coerce_ulong (ST(2)), 3104 coerce_ulong (ST(3))); 3105 } 3106 else if (strcmp (method, "lc_2exp_size") == 0) 3107 { 3108 if (items != 2) 3109 goto invalid; 3110 if (! gmp_randinit_lc_2exp_size (RETVAL, coerce_ulong (ST(1)))) 3111 { 3112 Safefree (RETVAL); 3113 XSRETURN_UNDEF; 3114 } 3115 } 3116 else if (strcmp (method, "mt") == 0) 3117 { 3118 if (items != 1) 3119 goto invalid; 3120 gmp_randinit_mt (RETVAL); 3121 } 3122 else 3123 { 3124 invalid: 3125 croak ("%s new: invalid arguments", rand_class); 3126 } 3127 } 3128 } 3129 OUTPUT: 3130 RETVAL 3131 3132 3133 void 3134 DESTROY (r) 3135 randstate r 3136 CODE: 3137 TRACE (printf ("%s DESTROY\n", rand_class)); 3138 gmp_randclear (r); 3139 Safefree (r); 3140 assert_support (rand_count--); 3141 TRACE_ACTIVE (); 3142 3143 3144 void 3145 seed (r, z) 3146 randstate r 3147 mpz_coerce z 3148 CODE: 3149 gmp_randseed (r, z); 3150 3151 3152 mpz 3153 mpz_urandomb (r, bits) 3154 randstate r 3155 ulong_coerce bits 3156 ALIAS: 3157 GMP::Rand::mpz_rrandomb = 1 3158 PREINIT: 3159 static_functable const struct { 3160 void (*fun) (mpz_ptr, gmp_randstate_t r, unsigned long bits); 3161 } table[] = { 3162 { mpz_urandomb }, /* 0 */ 3163 { mpz_rrandomb }, /* 1 */ 3164 }; 3165 CODE: 3166 assert_table (ix); 3167 RETVAL = new_mpz(); 3168 (*table[ix].fun) (RETVAL->m, r, bits); 3169 OUTPUT: 3170 RETVAL 3171 3172 3173 mpz 3174 mpz_urandomm (r, m) 3175 randstate r 3176 mpz_coerce m 3177 CODE: 3178 RETVAL = new_mpz(); 3179 mpz_urandomm (RETVAL->m, r, m); 3180 OUTPUT: 3181 RETVAL 3182 3183 3184 mpf 3185 mpf_urandomb (r, bits) 3186 randstate r 3187 ulong_coerce bits 3188 CODE: 3189 RETVAL = new_mpf (bits); 3190 mpf_urandomb (RETVAL, r, bits); 3191 OUTPUT: 3192 RETVAL 3193 3194 3195 unsigned long 3196 gmp_urandomb_ui (r, bits) 3197 randstate r 3198 ulong_coerce bits 3199 ALIAS: 3200 GMP::Rand::gmp_urandomm_ui = 1 3201 PREINIT: 3202 static_functable const struct { 3203 unsigned long (*fun) (gmp_randstate_t r, unsigned long bits); 3204 } table[] = { 3205 { gmp_urandomb_ui }, /* 0 */ 3206 { gmp_urandomm_ui }, /* 1 */ 3207 }; 3208 CODE: 3209 assert_table (ix); 3210 RETVAL = (*table[ix].fun) (r, bits); 3211 OUTPUT: 3212 RETVAL