1 /* GMP module external subroutines.
3 Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
5 This file is part of the GNU MP Library.
7 The GNU MP Library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
12 The GNU MP Library is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with the GNU MP Library. If not, see http://www.gnu.org/licenses/.
23 Routines are grouped with the alias feature and a table of function
24 pointers where possible, since each xsub routine ends up with quite a bit
25 of code size. Different combinations of arguments and return values have
26 to be separate though.
28 The "INTERFACE:" feature isn't available in perl 5.005 and so isn't used.
29 "ALIAS:" requires a table lookup with CvXSUBANY(cv).any_i32 (which is
30 "ix") whereas "INTERFACE:" would have CvXSUBANY(cv).any_dptr as the
31 function pointer immediately.
33 Mixed-type swapped-order assignments like "$a = 123; $a += mpz(456);"
34 invoke the plain overloaded "+", not "+=", which makes life easier.
36 mpz_assume etc types are used with the overloaded operators since such
37 operators are always called with a class object as the first argument, we
38 don't need an sv_derived_from() lookup to check. There's assert()s in
39 MPX_ASSUME() for this though.
41 The overload_constant routines reached via overload::constant get 4
42 arguments in perl 5.6, not the 3 as documented. This is apparently a
43 bug, using "..." lets us ignore the extra one.
45 There's only a few "si" functions in gmp, so usually SvIV values get
46 handled with an mpz_set_si into a temporary and then a full precision mpz
47 routine. This is reasonably efficient.
49 Argument types are checked, with a view to preserving all bits in the
50 operand. Perl is a bit looser in its arithmetic, allowing rounding or
51 truncation to an intended operand type (IV, UV or NV).
55 The memory leak detection attempted in GMP::END() doesn't work when mpz's
56 are created as constants because END() is called before they're
57 destroyed. What's the right place to hook such a check?
59 See the bugs section of GMP.pm too. */
62 /* Comment this out to get assertion checking. */
65 /* Change this to "#define TRACE(x) x" for some diagnostics. */
75 #include "patchlevel.h"
80 /* Perl 5.005 doesn't have SvIsUV, only 5.6 and up.
81 Perl 5.8 has SvUOK, but not 5.6, so we don't use that. */
86 #define SvUVX(sv) (croak("GMP: oops, shouldn't be using SvUVX"), 0)
90 /* Code which doesn't check anything itself, but exists to support other
93 #define assert_support(x)
95 #define assert_support(x) x
98 /* LONG_MAX + 1 and ULONG_MAX + 1, as a doubles */
99 #define LONG_MAX_P1_AS_DOUBLE ((double) ((unsigned long) LONG_MAX + 1))
100 #define ULONG_MAX_P1_AS_DOUBLE (2.0 * (double) ((unsigned long) ULONG_MAX/2 + 1))
102 /* Check for perl version "major.minor".
103 Perl 5.004 doesn't have PERL_REVISION and PERL_VERSION, but that's ok,
104 we're only interested in tests above that. */
105 #if defined (PERL_REVISION) && defined (PERL_VERSION)
106 #define PERL_GE(major,minor) \
107 (PERL_REVISION > (major) \
108 || ((major) == PERL_REVISION && PERL_VERSION >= (minor)))
110 #define PERL_GE(major,minor) (0)
112 #define PERL_LT(major,minor) (! PERL_GE(major,minor))
114 /* sv_derived_from etc in 5.005 took "char *" rather than "const char *".
115 Avoid some compiler warnings by using const only where it works. */
119 #define classconst const
122 /* In a MINGW or Cygwin DLL build of gmp, the various gmp functions are
123 given with dllimport directives, which prevents them being used as
124 initializers for constant data. We give function tables as
125 "static_functable const ...", which is normally "static const", but for
126 mingw expands to just "const" making the table an automatic with a
127 run-time initializer.
129 In gcc 3.3.1, the function tables initialized like this end up getting
130 all the __imp__foo values fetched, even though just one or two will be
131 used. This is wasteful, but probably not too bad. */
133 #if defined (__MINGW32__) || defined (__CYGWIN__)
134 #define static_functable
136 #define static_functable static
139 #define GMP_MALLOC_ID 42
141 static classconst char mpz_class[] = "GMP::Mpz";
142 static classconst char mpq_class[] = "GMP::Mpq";
143 static classconst char mpf_class[] = "GMP::Mpf";
144 static classconst char rand_class[] = "GMP::Rand";
146 static HV *mpz_class_hv;
147 static HV *mpq_class_hv;
148 static HV *mpf_class_hv;
150 assert_support (static long mpz_count = 0;)
151 assert_support (static long mpq_count = 0;)
152 assert_support (static long mpf_count = 0;)
153 assert_support (static long rand_count = 0;)
155 #define TRACE_ACTIVE() \
157 (TRACE (printf (" active %ld mpz, %ld mpq, %ld mpf, %ld randstate\n", \
158 mpz_count, mpq_count, mpf_count, rand_count)))
161 /* Each "struct mpz_elem" etc is an mpz_t with a link field tacked on the
162 end so they can be held on a linked list. */
164 #define CREATE_MPX(type) \
166 /* must have mpz_t etc first, for sprintf below */ \
167 struct type##_elem { \
169 struct type##_elem *next; \
171 typedef struct type##_elem *type; \
172 typedef struct type##_elem *type##_assume; \
173 typedef type##_ptr type##_coerce; \
175 static type type##_freelist = NULL; \
181 TRACE (printf ("new %s\n", type##_class)); \
182 if (type##_freelist != NULL) \
184 p = type##_freelist; \
185 type##_freelist = type##_freelist->next; \
189 New (GMP_MALLOC_ID, p, 1, struct type##_elem); \
190 type##_init (p->m); \
192 TRACE (printf (" p=%p\n", p)); \
193 assert_support (type##_count++); \
202 typedef mpf_ptr mpf_assume;
203 typedef mpf_ptr mpf_coerce_st0;
204 typedef mpf_ptr mpf_coerce_def;
208 new_mpf (unsigned long prec)
211 New (GMP_MALLOC_ID, p, 1, __mpf_struct);
213 TRACE (printf (" mpf p=%p\n", p));
214 assert_support (mpf_count++);
220 /* tmp_mpf_t records an allocated precision with an mpf_t so changes of
221 precision can be done with just an mpf_set_prec_raw. */
223 struct tmp_mpf_struct {
225 unsigned long allocated_prec;
227 typedef const struct tmp_mpf_struct *tmp_mpf_srcptr;
228 typedef struct tmp_mpf_struct *tmp_mpf_ptr;
229 typedef struct tmp_mpf_struct tmp_mpf_t[1];
231 #define tmp_mpf_init(f) \
234 f->allocated_prec = mpf_get_prec (f->m); \
238 tmp_mpf_grow (tmp_mpf_ptr f, unsigned long prec)
240 mpf_set_prec_raw (f->m, f->allocated_prec);
241 mpf_set_prec (f->m, prec);
242 f->allocated_prec = mpf_get_prec (f->m);
245 #define tmp_mpf_shrink(f) tmp_mpf_grow (f, 1L)
247 #define tmp_mpf_set_prec(f,prec) \
249 if (prec > f->allocated_prec) \
250 tmp_mpf_grow (f, prec); \
252 mpf_set_prec_raw (f->m, prec); \
256 static mpz_t tmp_mpz_0, tmp_mpz_1, tmp_mpz_2;
257 static mpq_t tmp_mpq_0, tmp_mpq_1;
258 static tmp_mpf_t tmp_mpf_0, tmp_mpf_1;
260 /* for GMP::Mpz::export */
261 #define tmp_mpz_4 tmp_mpz_2
264 #define FREE_MPX_FREELIST(p,type) \
266 TRACE (printf ("free %s\n", type##_class)); \
267 p->next = type##_freelist; \
268 type##_freelist = p; \
269 assert_support (type##_count--); \
271 assert (type##_count >= 0); \
274 /* this version for comparison, if desired */
275 #define FREE_MPX_NOFREELIST(p,type) \
277 TRACE (printf ("free %s\n", type##_class)); \
278 type##_clear (p->m); \
280 assert_support (type##_count--); \
282 assert (type##_count >= 0); \
285 #define free_mpz(z) FREE_MPX_FREELIST (z, mpz)
286 #define free_mpq(q) FREE_MPX_FREELIST (q, mpq)
289 /* Return a new mortal SV holding the given mpx_ptr pointer.
290 class_hv should be one of mpz_class_hv etc. */
291 #define MPX_NEWMORTAL(mpx_ptr, class_hv) \
292 sv_bless (sv_setref_pv (sv_newmortal(), NULL, mpx_ptr), class_hv)
294 /* Aliases for use in typemaps */
295 typedef char *malloced_string;
296 typedef const char *const_string;
297 typedef const char *const_string_assume;
298 typedef char *string;
299 typedef SV *order_noswap;
301 typedef SV *SV_copy_0;
302 typedef unsigned long ulong_coerce;
303 typedef __gmp_randstate_struct *randstate;
306 #define SvMPX(s,type) ((type) SvIV((SV*) SvRV(s)))
307 #define SvMPZ(s) SvMPX(s,mpz)
308 #define SvMPQ(s) SvMPX(s,mpq)
309 #define SvMPF(s) SvMPX(s,mpf)
310 #define SvRANDSTATE(s) SvMPX(s,randstate)
312 #define MPX_ASSUME(x,sv,type) \
314 assert (sv_derived_from (sv, type##_class)); \
315 x = SvMPX(sv,type); \
318 #define MPZ_ASSUME(z,sv) MPX_ASSUME(z,sv,mpz)
319 #define MPQ_ASSUME(q,sv) MPX_ASSUME(q,sv,mpq)
320 #define MPF_ASSUME(f,sv) MPX_ASSUME(f,sv,mpf)
322 #define numberof(x) (sizeof (x) / sizeof ((x)[0]))
323 #define SGN(x) ((x)<0 ? -1 : (x) != 0)
324 #define ABS(x) ((x)>=0 ? (x) : -(x))
325 #define double_integer_p(d) (floor (d) == (d))
327 #define x_mpq_integer_p(q) \
328 (mpz_cmp_ui (mpq_denref(q), 1L) == 0)
330 #define assert_table(ix) assert (ix >= 0 && ix < numberof (table))
332 #define SV_PTR_SWAP(x,y) \
333 do { SV *__tmp = (x); (x) = (y); (y) = __tmp; } while (0)
334 #define MPF_PTR_SWAP(x,y) \
335 do { mpf_ptr __tmp = (x); (x) = (y); (y) = __tmp; } while (0)
339 class_or_croak (SV *sv, classconst char *cl)
341 if (! sv_derived_from (sv, cl))
342 croak("not type %s", cl);
346 /* These are macros, wrap them in functions. */
348 x_mpz_odd_p (mpz_srcptr z)
350 return mpz_odd_p (z);
353 x_mpz_even_p (mpz_srcptr z)
355 return mpz_even_p (z);
359 x_mpq_pow_ui (mpq_ptr r, mpq_srcptr b, unsigned long e)
361 mpz_pow_ui (mpq_numref(r), mpq_numref(b), e);
362 mpz_pow_ui (mpq_denref(r), mpq_denref(b), e);
367 my_gmp_alloc (size_t n)
370 TRACE (printf ("my_gmp_alloc %u\n", n));
371 New (GMP_MALLOC_ID, p, n, char);
372 TRACE (printf (" p=%p\n", p));
377 my_gmp_realloc (void *p, size_t oldsize, size_t newsize)
379 TRACE (printf ("my_gmp_realloc %p, %u to %u\n", p, oldsize, newsize));
380 Renew (p, newsize, char);
381 TRACE (printf (" p=%p\n", p));
386 my_gmp_free (void *p, size_t n)
388 TRACE (printf ("my_gmp_free %p %u\n", p, n));
393 #define my_mpx_set_svstr(type) \
395 my_##type##_set_svstr (type##_ptr x, SV *sv) \
399 TRACE (printf (" my_" #type "_set_svstr\n")); \
400 assert (SvPOK(sv) || SvPOKp(sv)); \
401 str = SvPV (sv, len); \
402 TRACE (printf (" str \"%s\"\n", str)); \
403 if (type##_set_str (x, str, 0) != 0) \
404 croak ("%s: invalid string: %s", type##_class, str); \
407 my_mpx_set_svstr(mpz)
408 my_mpx_set_svstr(mpq)
409 my_mpx_set_svstr(mpf)
414 x_mpq_cmp_si (mpq_srcptr x, long yn, unsigned long yd)
419 mpq_set_si (y->m, yn, yd);
420 ret = mpq_cmp (x, y->m);
426 x_mpq_fits_slong_p (mpq_srcptr q)
428 return x_mpq_cmp_si (q, LONG_MIN, 1L) >= 0
429 && mpq_cmp_ui (q, LONG_MAX, 1L) <= 0;
433 x_mpz_cmp_q (mpz_ptr x, mpq_srcptr y)
436 mpz_set_ui (mpq_denref(tmp_mpq_0), 1L);
437 mpz_swap (mpq_numref(tmp_mpq_0), x);
438 ret = mpq_cmp (tmp_mpq_0, y);
439 mpz_swap (mpq_numref(tmp_mpq_0), x);
444 x_mpz_cmp_f (mpz_srcptr x, mpf_srcptr y)
446 tmp_mpf_set_prec (tmp_mpf_0, mpz_sizeinbase (x, 2));
447 mpf_set_z (tmp_mpf_0->m, x);
448 return mpf_cmp (tmp_mpf_0->m, y);
452 #define USE_UNKNOWN 0
461 /* mg_get is called every time we get a value, even if the private flags are
462 still set from a previous such call. This is the same as as SvIV and
465 When POK, we use the PV, even if there's an IV or NV available. This is
466 because it's hard to be sure there wasn't any rounding in establishing
467 the IV and/or NV. Cases of overflow, where the PV should definitely be
468 used, are easy enough to spot, but rounding is hard. So although IV or
469 NV would be more efficient, we must use the PV to be sure of getting all
470 the data. Applications should convert once to mpz, mpq or mpf when using
473 Zany dual-type scalars like $! where the IV is an error code and the PV
474 is an error description string won't work with this preference for PV,
475 but that's too bad. Such scalars should be rare, and unlikely to be used
476 in bignum calculations.
478 When IOK and NOK are both set, we would prefer to use the IV since it can
479 be converted more efficiently, and because on a 64-bit system the NV may
480 have less bits than the IV. The following rules are applied,
482 - If the NV is not an integer, then we must use that NV, since clearly
483 the IV was merely established by rounding and is not the full value.
485 - In perl prior to 5.8, an NV too big for an IV leaves an overflow value
486 0xFFFFFFFF. If the NV is too big to fit an IV then clearly it's the NV
487 which is the true value and must be used.
489 - In perl 5.8 and up, such an overflow doesn't set IOK, so that test is
490 unnecessary. However when coming from get-magic, IOKp _is_ set, and we
491 must check for overflow the same as in older perl.
495 We'd like to call mg_get just once, but unfortunately sv_derived_from()
496 will call it for each of our checks. We could do a string compare like
497 sv_isa ourselves, but that only tests the exact class, it doesn't
498 recognise subclassing. There doesn't seem to be a public interface to
499 the subclassing tests (in the internal isa_lookup() function). */
548 if (d >= ULONG_MAX_P1_AS_DOUBLE || d < 0.0)
565 if (d >= LONG_MAX_P1_AS_DOUBLE || d < (double) LONG_MIN)
582 if (sv_derived_from (sv, mpz_class))
584 if (sv_derived_from (sv, mpq_class))
586 if (sv_derived_from (sv, mpf_class))
594 /* Coerce sv to an mpz. Use tmp to hold the converted value if sv isn't
595 already an mpz (or an mpq of which the numerator can be used). Return
596 the chosen mpz (tmp or the contents of sv). */
599 coerce_mpz_using (mpz_ptr tmp, SV *sv, int use)
603 mpz_set_si (tmp, SvIVX(sv));
607 mpz_set_ui (tmp, SvUVX(sv));
614 if (! double_integer_p (d))
615 croak ("cannot coerce non-integer double to mpz");
621 my_mpz_set_svstr (tmp, sv);
630 if (! x_mpq_integer_p (q->m))
631 croak ("cannot coerce non-integer mpq to mpz");
632 return mpq_numref(q->m);
638 if (! mpf_integer_p (f))
639 croak ("cannot coerce non-integer mpf to mpz");
645 croak ("cannot coerce to mpz");
649 coerce_mpz (mpz_ptr tmp, SV *sv)
651 return coerce_mpz_using (tmp, sv, use_sv (sv));
655 /* Coerce sv to an mpq. If sv is an mpq then just return that, otherwise
656 use tmp to hold the converted value and return that. */
659 coerce_mpq_using (mpq_ptr tmp, SV *sv, int use)
661 TRACE (printf ("coerce_mpq_using %p %d\n", tmp, use));
664 mpq_set_si (tmp, SvIVX(sv), 1L);
668 mpq_set_ui (tmp, SvUVX(sv), 1L);
672 mpq_set_d (tmp, SvNVX(sv));
676 my_mpq_set_svstr (tmp, sv);
680 mpq_set_z (tmp, SvMPZ(sv)->m);
687 mpq_set_f (tmp, SvMPF(sv));
691 croak ("cannot coerce to mpq");
695 coerce_mpq (mpq_ptr tmp, SV *sv)
697 return coerce_mpq_using (tmp, sv, use_sv (sv));
702 my_mpf_set_sv_using (mpf_ptr f, SV *sv, int use)
706 mpf_set_si (f, SvIVX(sv));
710 mpf_set_ui (f, SvUVX(sv));
714 mpf_set_d (f, SvNVX(sv));
718 my_mpf_set_svstr (f, sv);
722 mpf_set_z (f, SvMPZ(sv)->m);
726 mpf_set_q (f, SvMPQ(sv)->m);
730 mpf_set (f, SvMPF(sv));
734 croak ("cannot coerce to mpf");
738 /* Coerce sv to an mpf. If sv is an mpf then just return that, otherwise
739 use tmp to hold the converted value (with prec precision). */
741 coerce_mpf_using (tmp_mpf_ptr tmp, SV *sv, unsigned long prec, int use)
746 tmp_mpf_set_prec (tmp, prec);
747 my_mpf_set_sv_using (tmp->m, sv, use);
751 coerce_mpf (tmp_mpf_ptr tmp, SV *sv, unsigned long prec)
753 return coerce_mpf_using (tmp, sv, prec, use_sv (sv));
757 /* Coerce xv to an mpf and store the pointer in x, ditto for yv to x. If
758 one of xv or yv is an mpf then use it for the precision, otherwise use
759 the default precision. */
761 coerce_mpf_pair (mpf *xp, SV *xv, mpf *yp, SV *yv)
763 int x_use = use_sv (xv);
764 int y_use = use_sv (yv);
768 if (x_use == USE_MPF)
771 prec = mpf_get_prec (x);
772 y = coerce_mpf_using (tmp_mpf_0, yv, prec, y_use);
776 y = coerce_mpf_using (tmp_mpf_0, yv, mpf_get_default_prec(), y_use);
777 prec = mpf_get_prec (y);
778 x = coerce_mpf_using (tmp_mpf_1, xv, prec, x_use);
786 /* Note that SvUV is not used, since it merely treats the signed IV as if it
787 was unsigned. We get an IV and check its sign. */
789 coerce_ulong (SV *sv)
793 switch (use_sv (sv)) {
808 if (! double_integer_p (d))
815 /* FIXME: Check the string is an integer. */
822 if (! mpz_fits_ulong_p (z->m))
824 return mpz_get_ui (z->m);
830 if (! x_mpq_integer_p (q->m))
832 if (! mpz_fits_ulong_p (mpq_numref (q->m)))
834 return mpz_get_ui (mpq_numref (q->m));
840 if (! mpf_integer_p (f))
842 if (! mpf_fits_ulong_p (f))
844 return mpf_get_ui (f);
848 croak ("cannot coerce to ulong");
852 croak ("not an integer");
855 croak ("out of range for ulong");
862 switch (use_sv (sv)) {
869 if (u > (UV) LONG_MAX)
876 double d = SvNVX(sv);
877 if (! double_integer_p (d))
883 /* FIXME: Check the string is an integer. */
889 if (! mpz_fits_slong_p (z->m))
891 return mpz_get_si (z->m);
897 if (! x_mpq_integer_p (q->m))
899 if (! mpz_fits_slong_p (mpq_numref (q->m)))
901 return mpz_get_si (mpq_numref (q->m));
907 if (! mpf_integer_p (f))
909 if (! mpf_fits_slong_p (f))
911 return mpf_get_si (f);
915 croak ("cannot coerce to long");
919 croak ("not an integer");
922 croak ("out of range for ulong");
926 /* ------------------------------------------------------------------------- */
928 MODULE = GMP PACKAGE = GMP
931 TRACE (printf ("GMP boot\n"));
932 mp_set_memory_functions (my_gmp_alloc, my_gmp_realloc, my_gmp_free);
933 mpz_init (tmp_mpz_0);
934 mpz_init (tmp_mpz_1);
935 mpz_init (tmp_mpz_2);
936 mpq_init (tmp_mpq_0);
937 mpq_init (tmp_mpq_1);
938 tmp_mpf_init (tmp_mpf_0);
939 tmp_mpf_init (tmp_mpf_1);
940 mpz_class_hv = gv_stashpv (mpz_class, 1);
941 mpq_class_hv = gv_stashpv (mpq_class, 1);
942 mpf_class_hv = gv_stashpv (mpf_class, 1);
948 TRACE (printf ("GMP end\n"));
950 /* These are not always true, see Bugs at the top of the file. */
951 /* assert (mpz_count == 0); */
952 /* assert (mpq_count == 0); */
953 /* assert (mpf_count == 0); */
954 /* assert (rand_count == 0); */
960 RETVAL = gmp_version;
969 switch (use_sv (sv)) {
977 RETVAL = (u <= LONG_MAX);
983 double d = SvNVX(sv);
984 RETVAL = (d >= (double) LONG_MIN && d < LONG_MAX_P1_AS_DOUBLE);
991 const char *str = SvPV (sv, len);
992 if (mpq_set_str (tmp_mpq_0, str, 0) == 0)
993 RETVAL = x_mpq_fits_slong_p (tmp_mpq_0);
996 /* enough precision for a long */
997 tmp_mpf_set_prec (tmp_mpf_0, 2*mp_bits_per_limb);
998 if (mpf_set_str (tmp_mpf_0->m, str, 10) != 0)
999 croak ("GMP::fits_slong_p invalid string format");
1000 RETVAL = mpf_fits_slong_p (tmp_mpf_0->m);
1006 RETVAL = mpz_fits_slong_p (SvMPZ(sv)->m);
1010 RETVAL = x_mpq_fits_slong_p (SvMPQ(sv)->m);
1014 RETVAL = mpf_fits_slong_p (SvMPF(sv));
1018 croak ("GMP::fits_slong_p invalid argument");
1028 switch (use_sv (sv)) {
1030 RETVAL = (double) SvIVX(sv);
1034 RETVAL = (double) SvUVX(sv);
1044 RETVAL = atof(SvPV(sv, len));
1049 RETVAL = mpz_get_d (SvMPZ(sv)->m);
1053 RETVAL = mpq_get_d (SvMPQ(sv)->m);
1057 RETVAL = mpf_get_d (SvMPF(sv));
1061 croak ("GMP::get_d invalid argument");
1074 switch (use_sv (sv)) {
1076 ret = (double) SvIVX(sv);
1080 ret = (double) SvUVX(sv);
1088 ret = frexp (ret, &i_exp);
1094 /* put strings through mpf to give full exp range */
1095 tmp_mpf_set_prec (tmp_mpf_0, DBL_MANT_DIG);
1096 my_mpf_set_svstr (tmp_mpf_0->m, sv);
1097 ret = mpf_get_d_2exp (&exp, tmp_mpf_0->m);
1101 ret = mpz_get_d_2exp (&exp, SvMPZ(sv)->m);
1105 tmp_mpf_set_prec (tmp_mpf_0, DBL_MANT_DIG);
1106 mpf_set_q (tmp_mpf_0->m, SvMPQ(sv)->m);
1107 ret = mpf_get_d_2exp (&exp, tmp_mpf_0->m);
1111 ret = mpf_get_d_2exp (&exp, SvMPF(sv));
1115 croak ("GMP::get_d_2exp invalid argument");
1117 PUSHs (sv_2mortal (newSVnv (ret)));
1118 PUSHs (sv_2mortal (newSViv (exp)));
1125 switch (use_sv (sv)) {
1135 RETVAL = (long) SvNVX(sv);
1143 RETVAL = mpz_get_si (SvMPZ(sv)->m);
1147 mpz_set_q (tmp_mpz_0, SvMPQ(sv)->m);
1148 RETVAL = mpz_get_si (tmp_mpz_0);
1152 RETVAL = mpf_get_si (SvMPF(sv));
1156 croak ("GMP::get_si invalid argument");
1174 TRACE (printf ("GMP::get_str\n"));
1177 base = coerce_long (ST(1));
1180 TRACE (printf (" base=%d\n", base));
1183 ndigits = coerce_long (ST(2));
1186 TRACE (printf (" ndigits=%d\n", ndigits));
1190 switch (use_sv (sv)) {
1192 mpz_set_si (tmp_mpz_0, SvIVX(sv));
1198 mpz_set_ui (tmp_mpz_0, SvUVX(sv));
1202 /* only digits in the original double, not in the coerced form */
1205 mpf_set_d (tmp_mpf_0->m, SvNVX(sv));
1211 /* get_str on a string is not much more than a base conversion */
1213 str = SvPV (sv, len);
1214 if (mpz_set_str (tmp_mpz_0, str, 0) == 0)
1219 else if (mpq_set_str (tmp_mpq_0, str, 0) == 0)
1226 /* FIXME: Would like perhaps a precision equivalent to the
1227 number of significant digits of the string, in its given
1229 tmp_mpf_set_prec (tmp_mpf_0, strlen(str));
1230 if (mpf_set_str (tmp_mpf_0->m, str, 10) == 0)
1236 croak ("GMP::get_str invalid string format");
1244 str = mpz_get_str (NULL, base, z);
1246 PUSHs (sv_2mortal (newSVpv (str, 0)));
1252 str = mpq_get_str (NULL, base, q);
1258 str = mpf_get_str (NULL, &exp, base, 0, f);
1259 PUSHs (sv_2mortal (newSVpv (str, 0)));
1260 PUSHs (sv_2mortal (newSViv (exp)));
1264 croak ("GMP::get_str invalid argument");
1272 switch (use_sv (sv)) {
1279 RETVAL = double_integer_p (SvNVX(sv));
1284 /* FIXME: Maybe this should be done by parsing the string, not by an
1285 actual conversion. */
1287 const char *str = SvPV (sv, len);
1288 if (mpq_set_str (tmp_mpq_0, str, 0) == 0)
1289 RETVAL = x_mpq_integer_p (tmp_mpq_0);
1292 /* enough for all digits of the string */
1293 tmp_mpf_set_prec (tmp_mpf_0, strlen(str)+64);
1294 if (mpf_set_str (tmp_mpf_0->m, str, 10) == 0)
1295 RETVAL = mpf_integer_p (tmp_mpf_0->m);
1297 croak ("GMP::integer_p invalid string format");
1307 RETVAL = x_mpq_integer_p (SvMPQ(sv)->m);
1311 RETVAL = mpf_integer_p (SvMPF(sv));
1315 croak ("GMP::integer_p invalid argument");
1325 switch (use_sv (sv)) {
1327 RETVAL = SGN (SvIVX(sv));
1331 RETVAL = (SvUVX(sv) > 0);
1335 RETVAL = SGN (SvNVX(sv));
1340 /* FIXME: Maybe this should be done by parsing the string, not by an
1341 actual conversion. */
1343 const char *str = SvPV (sv, len);
1344 if (mpq_set_str (tmp_mpq_0, str, 0) == 0)
1345 RETVAL = mpq_sgn (tmp_mpq_0);
1348 /* enough for all digits of the string */
1349 tmp_mpf_set_prec (tmp_mpf_0, strlen(str)+64);
1350 if (mpf_set_str (tmp_mpf_0->m, str, 10) == 0)
1351 RETVAL = mpf_sgn (tmp_mpf_0->m);
1353 croak ("GMP::sgn invalid string format");
1359 RETVAL = mpz_sgn (SvMPZ(sv)->m);
1363 RETVAL = mpq_sgn (SvMPQ(sv)->m);
1367 RETVAL = mpf_sgn (SvMPF(sv));
1371 croak ("GMP::sgn invalid argument");
1377 # currently undocumented
1381 #define x_mpz_shrink(z) \
1382 mpz_set_ui (z, 0L); _mpz_realloc (z, 1)
1383 #define x_mpq_shrink(q) \
1384 x_mpz_shrink (mpq_numref(q)); x_mpz_shrink (mpq_denref(q))
1386 x_mpz_shrink (tmp_mpz_0);
1387 x_mpz_shrink (tmp_mpz_1);
1388 x_mpz_shrink (tmp_mpz_2);
1389 x_mpq_shrink (tmp_mpq_0);
1390 x_mpq_shrink (tmp_mpq_1);
1391 tmp_mpf_shrink (tmp_mpf_0);
1392 tmp_mpf_shrink (tmp_mpf_1);
1397 sprintf_internal (fmt, sv)
1401 assert (strlen (fmt) >= 3);
1403 assert ((sv_derived_from (sv, mpz_class) && fmt[strlen(fmt)-2] == 'Z')
1404 || (sv_derived_from (sv, mpq_class) && fmt[strlen(fmt)-2] == 'Q')
1405 || (sv_derived_from (sv, mpf_class) && fmt[strlen(fmt)-2] == 'F'));
1406 TRACE (printf ("GMP::sprintf_internal\n");
1407 printf (" fmt |%s|\n", fmt);
1408 printf (" sv |%p|\n", SvMPZ(sv)));
1410 /* cheat a bit here, SvMPZ works for mpq and mpf too */
1411 gmp_asprintf (&RETVAL, fmt, SvMPZ(sv));
1413 TRACE (printf (" result |%s|\n", RETVAL));
1419 #------------------------------------------------------------------------------
1421 MODULE = GMP PACKAGE = GMP::Mpz
1430 TRACE (printf ("%s new, ix=%ld, items=%d\n", mpz_class, ix, (int) items));
1435 mpz_set_ui (RETVAL->m, 0L);
1440 TRACE (printf (" use %d\n", use_sv (sv)));
1441 switch (use_sv (sv)) {
1443 mpz_set_si (RETVAL->m, SvIVX(sv));
1447 mpz_set_ui (RETVAL->m, SvUVX(sv));
1451 mpz_set_d (RETVAL->m, SvNVX(sv));
1455 my_mpz_set_svstr (RETVAL->m, sv);
1459 mpz_set (RETVAL->m, SvMPZ(sv)->m);
1463 mpz_set_q (RETVAL->m, SvMPQ(sv)->m);
1467 mpz_set_f (RETVAL->m, SvMPF(sv));
1477 croak ("%s new: invalid arguments", mpz_class);
1484 overload_constant (str, pv, d1, ...)
1485 const_string_assume str
1491 TRACE (printf ("%s constant: %s\n", mpz_class, str));
1493 if (mpz_set_str (z->m, str, 0) == 0)
1495 PUSHs (MPX_NEWMORTAL (z, mpz_class_hv));
1505 overload_copy (z, d1, d2)
1511 mpz_set (RETVAL->m, z->m);
1520 TRACE (printf ("%s DESTROY %p\n", mpz_class, z));
1525 overload_string (z, d1, d2)
1530 TRACE (printf ("%s overload_string %p\n", mpz_class, z));
1531 RETVAL = mpz_get_str (NULL, 10, z->m);
1537 overload_add (xv, yv, order)
1542 GMP::Mpz::overload_sub = 1
1543 GMP::Mpz::overload_mul = 2
1544 GMP::Mpz::overload_div = 3
1545 GMP::Mpz::overload_rem = 4
1546 GMP::Mpz::overload_and = 5
1547 GMP::Mpz::overload_ior = 6
1548 GMP::Mpz::overload_xor = 7
1550 static_functable const struct {
1551 void (*op) (mpz_ptr, mpz_srcptr, mpz_srcptr);
1553 { mpz_add }, /* 0 */
1554 { mpz_sub }, /* 1 */
1555 { mpz_mul }, /* 2 */
1556 { mpz_tdiv_q }, /* 3 */
1557 { mpz_tdiv_r }, /* 4 */
1558 { mpz_and }, /* 5 */
1559 { mpz_ior }, /* 6 */
1560 { mpz_xor }, /* 7 */
1564 if (order == &PL_sv_yes)
1565 SV_PTR_SWAP (xv, yv);
1567 (*table[ix].op) (RETVAL->m,
1568 coerce_mpz (tmp_mpz_0, xv),
1569 coerce_mpz (tmp_mpz_1, yv));
1575 overload_addeq (x, y, o)
1580 GMP::Mpz::overload_subeq = 1
1581 GMP::Mpz::overload_muleq = 2
1582 GMP::Mpz::overload_diveq = 3
1583 GMP::Mpz::overload_remeq = 4
1584 GMP::Mpz::overload_andeq = 5
1585 GMP::Mpz::overload_ioreq = 6
1586 GMP::Mpz::overload_xoreq = 7
1588 static_functable const struct {
1589 void (*op) (mpz_ptr, mpz_srcptr, mpz_srcptr);
1591 { mpz_add }, /* 0 */
1592 { mpz_sub }, /* 1 */
1593 { mpz_mul }, /* 2 */
1594 { mpz_tdiv_q }, /* 3 */
1595 { mpz_tdiv_r }, /* 4 */
1596 { mpz_and }, /* 5 */
1597 { mpz_ior }, /* 6 */
1598 { mpz_xor }, /* 7 */
1602 (*table[ix].op) (x->m, x->m, y);
1607 overload_lshift (zv, nv, order)
1612 GMP::Mpz::overload_rshift = 1
1613 GMP::Mpz::overload_pow = 2
1615 static_functable const struct {
1616 void (*op) (mpz_ptr, mpz_srcptr, unsigned long);
1618 { mpz_mul_2exp }, /* 0 */
1619 { mpz_div_2exp }, /* 1 */
1620 { mpz_pow_ui }, /* 2 */
1624 if (order == &PL_sv_yes)
1625 SV_PTR_SWAP (zv, nv);
1627 (*table[ix].op) (RETVAL->m, coerce_mpz (RETVAL->m, zv), coerce_ulong (nv));
1633 overload_lshifteq (z, n, o)
1638 GMP::Mpz::overload_rshifteq = 1
1639 GMP::Mpz::overload_poweq = 2
1641 static_functable const struct {
1642 void (*op) (mpz_ptr, mpz_srcptr, unsigned long);
1644 { mpz_mul_2exp }, /* 0 */
1645 { mpz_div_2exp }, /* 1 */
1646 { mpz_pow_ui }, /* 2 */
1650 (*table[ix].op) (z->m, z->m, n);
1655 overload_abs (z, d1, d2)
1660 GMP::Mpz::overload_neg = 1
1661 GMP::Mpz::overload_com = 2
1662 GMP::Mpz::overload_sqrt = 3
1664 static_functable const struct {
1665 void (*op) (mpz_ptr w, mpz_srcptr x);
1667 { mpz_abs }, /* 0 */
1668 { mpz_neg }, /* 1 */
1669 { mpz_com }, /* 2 */
1670 { mpz_sqrt }, /* 3 */
1675 (*table[ix].op) (RETVAL->m, z->m);
1681 overload_inc (z, d1, d2)
1686 GMP::Mpz::overload_dec = 1
1688 static_functable const struct {
1689 void (*op) (mpz_ptr w, mpz_srcptr x, unsigned long y);
1691 { mpz_add_ui }, /* 0 */
1692 { mpz_sub_ui }, /* 1 */
1696 (*table[ix].op) (z->m, z->m, 1L);
1700 overload_spaceship (xv, yv, order)
1707 TRACE (printf ("%s overload_spaceship\n", mpz_class));
1709 switch (use_sv (yv)) {
1711 RETVAL = mpz_cmp_si (x->m, SvIVX(yv));
1714 RETVAL = mpz_cmp_ui (x->m, SvUVX(yv));
1717 RETVAL = mpz_cmp (x->m, coerce_mpz (tmp_mpz_0, yv));
1720 RETVAL = mpz_cmp_d (x->m, SvNVX(yv));
1723 RETVAL = mpz_cmp (x->m, SvMPZ(yv)->m);
1726 RETVAL = x_mpz_cmp_q (x->m, SvMPQ(yv)->m);
1729 RETVAL = x_mpz_cmp_f (x->m, SvMPF(yv));
1732 croak ("%s <=>: invalid operand", mpz_class);
1734 RETVAL = SGN (RETVAL);
1735 if (order == &PL_sv_yes)
1742 overload_bool (z, d1, d2)
1747 GMP::Mpz::overload_not = 1
1749 RETVAL = (mpz_sgn (z->m) != 0) ^ ix;
1761 /* mpz_root returns an int, hence the cast */
1762 static_functable const struct {
1763 void (*op) (mpz_ptr, mpz_srcptr, unsigned long);
1765 { mpz_bin_ui }, /* 0 */
1766 { (void (*)(mpz_ptr, mpz_srcptr, unsigned long)) mpz_root }, /* 1 */
1771 (*table[ix].op) (RETVAL->m, n, k);
1784 static_functable const struct {
1785 void (*op) (mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr);
1787 { mpz_cdiv_qr }, /* 0 */
1788 { mpz_fdiv_qr }, /* 1 */
1789 { mpz_tdiv_qr }, /* 2 */
1796 (*table[ix].op) (q->m, r->m, a, d);
1798 PUSHs (MPX_NEWMORTAL (q, mpz_class_hv));
1799 PUSHs (MPX_NEWMORTAL (r, mpz_class_hv));
1807 GMP::Mpz::fdiv_2exp = 1
1808 GMP::Mpz::tdiv_2exp = 2
1810 static_functable const struct {
1811 void (*q) (mpz_ptr, mpz_srcptr, unsigned long);
1812 void (*r) (mpz_ptr, mpz_srcptr, unsigned long);
1814 { mpz_cdiv_q_2exp, mpz_cdiv_r_2exp }, /* 0 */
1815 { mpz_fdiv_q_2exp, mpz_fdiv_r_2exp }, /* 1 */
1816 { mpz_tdiv_q_2exp, mpz_tdiv_r_2exp }, /* 2 */
1823 (*table[ix].q) (q->m, a, d);
1824 (*table[ix].r) (r->m, a, d);
1826 PUSHs (MPX_NEWMORTAL (q, mpz_class_hv));
1827 PUSHs (MPX_NEWMORTAL (r, mpz_class_hv));
1831 congruent_p (a, c, d)
1837 RETVAL = mpz_congruent_p (a, c, d);
1843 congruent_2exp_p (a, c, d)
1849 RETVAL = mpz_congruent_2exp_p (a, c, d);
1861 static_functable const struct {
1862 void (*op) (mpz_ptr, mpz_srcptr, mpz_srcptr);
1864 { mpz_divexact }, /* 0 */
1865 { mpz_mod }, /* 1 */
1870 (*table[ix].op) (RETVAL->m, a, d);
1880 RETVAL = mpz_divisible_p (a, d);
1886 divisible_2exp_p (a, d)
1890 RETVAL = mpz_divisible_2exp_p (a, d);
1900 GMP::Mpz::perfect_square_p = 2
1901 GMP::Mpz::perfect_power_p = 3
1903 static_functable const struct {
1904 int (*op) (mpz_srcptr z);
1906 { x_mpz_even_p }, /* 0 */
1907 { x_mpz_odd_p }, /* 1 */
1908 { mpz_perfect_square_p }, /* 2 */
1909 { mpz_perfect_power_p }, /* 3 */
1913 RETVAL = (*table[ix].op) (z);
1923 GMP::Mpz::lucnum = 2
1925 static_functable const struct {
1926 void (*op) (mpz_ptr r, unsigned long n);
1928 { mpz_fac_ui }, /* 0 */
1929 { mpz_fib_ui }, /* 1 */
1930 { mpz_lucnum_ui }, /* 2 */
1935 (*table[ix].op) (RETVAL->m, n);
1944 GMP::Mpz::lucnum2 = 1
1946 static_functable const struct {
1947 void (*op) (mpz_ptr r, mpz_ptr r2, unsigned long n);
1949 { mpz_fib2_ui }, /* 0 */
1950 { mpz_lucnum2_ui }, /* 1 */
1957 (*table[ix].op) (r->m, r2->m, n);
1959 PUSHs (MPX_NEWMORTAL (r, mpz_class_hv));
1960 PUSHs (MPX_NEWMORTAL (r2, mpz_class_hv));
1969 static_functable const struct {
1970 void (*op) (mpz_ptr w, mpz_srcptr x, mpz_srcptr y);
1971 void (*op_ui) (mpz_ptr w, mpz_srcptr x, unsigned long y);
1973 /* cast to ignore ulong return from mpz_gcd_ui */
1975 (void (*) (mpz_ptr, mpz_srcptr, unsigned long)) mpz_gcd_ui }, /* 0 */
1976 { mpz_lcm, mpz_lcm_ui }, /* 1 */
1984 mpz_set (RETVAL->m, x);
1987 for (i = 1; i < items; i++)
1991 (*table[ix].op_ui) (RETVAL->m, x, ABS(SvIVX(yv)));
1993 (*table[ix].op) (RETVAL->m, x, coerce_mpz (tmp_mpz_1, yv));
2012 mpz_gcdext (g->m, x->m, y->m, a, b);
2014 PUSHs (MPX_NEWMORTAL (g, mpz_class_hv));
2015 PUSHs (MPX_NEWMORTAL (x, mpz_class_hv));
2016 PUSHs (MPX_NEWMORTAL (y, mpz_class_hv));
2024 RETVAL = mpz_hamdist (x, y);
2035 if (! mpz_invert (RETVAL->m, a, m))
2049 RETVAL = mpz_jacobi (a, b);
2060 RETVAL = mpz_kronecker_si (coerce_mpz(tmp_mpz_0,a), SvIVX(b));
2062 RETVAL = mpz_si_kronecker (SvIVX(a), coerce_mpz(tmp_mpz_0,b));
2064 RETVAL = mpz_kronecker (coerce_mpz(tmp_mpz_0,a),
2065 coerce_mpz(tmp_mpz_1,b));
2071 mpz_export (order, size, endian, nails, z)
2078 size_t numb, count, bytes, actual_count;
2082 numb = 8*size - nails;
2083 count = (mpz_sizeinbase (z, 2) + numb-1) / numb;
2084 bytes = count * size;
2085 New (GMP_MALLOC_ID, data, bytes+1, char);
2086 mpz_export (data, &actual_count, order, size, endian, nails, z);
2087 assert (count == actual_count);
2089 sv = sv_newmortal(); sv_usepvn_mg (sv, data, bytes); PUSHs(sv);
2093 mpz_import (order, size, endian, nails, sv)
2104 data = SvPV (sv, len);
2105 if ((len % size) != 0)
2106 croak ("%s mpz_import: string not a multiple of the given size",
2110 mpz_import (RETVAL->m, count, order, size, endian, nails, data);
2120 mpz_nextprime (RETVAL->m, z);
2129 RETVAL = mpz_popcount (x);
2141 mpz_powm (RETVAL->m, b, e, m);
2147 probab_prime_p (z, n)
2151 RETVAL = mpz_probab_prime_p (z, n);
2156 # No attempt to coerce here, only an mpz makes sense.
2162 _mpz_realloc (z->m, limbs);
2175 mult = mpz_remove (rem->m, z, f);
2177 PUSHs (MPX_NEWMORTAL (rem, mpz_class_hv));
2178 PUSHs (sv_2mortal (newSViv (mult)));
2191 exact = mpz_root (root->m, z, n);
2193 PUSHs (MPX_NEWMORTAL (root, mpz_class_hv));
2194 sv = (exact ? &PL_sv_yes : &PL_sv_no); sv_2mortal(sv); PUSHs(sv);
2208 mpz_rootrem (root->m, rem->m, z, n);
2210 PUSHs (MPX_NEWMORTAL (root, mpz_class_hv));
2211 PUSHs (MPX_NEWMORTAL (rem, mpz_class_hv));
2214 # In the past scan0 and scan1 were described as returning ULONG_MAX which
2215 # could be obtained in perl with ~0. That wasn't true on 64-bit systems
2216 # (eg. alpha) with perl 5.005, since in that version IV and UV were still
2219 # We changed in gmp 4.2 to just say ~0 for the not-found return. It's
2220 # likely most people have used ~0 rather than POSIX::ULONG_MAX(), so this
2221 # change should match existing usage. It only actually makes a difference
2222 # in old perl, since recent versions have gone to 64-bits for IV and UV, the
2225 # In perl 5.005 we explicitly mask the mpz return down to 32-bits to get ~0.
2226 # UV_MAX is no good, it reflects the size of the UV type (64-bits), rather
2227 # than the size of the values one ought to be storing in an SV (32-bits).
2236 static_functable const struct {
2237 unsigned long (*op) (mpz_srcptr, unsigned long);
2239 { mpz_scan0 }, /* 0 */
2240 { mpz_scan1 }, /* 1 */
2244 RETVAL = (*table[ix].op) (z, start);
2246 RETVAL &= 0xFFFFFFFF;
2256 GMP::Mpz::clrbit = 1
2257 GMP::Mpz::combit = 2
2259 static_functable const struct {
2260 void (*op) (mpz_ptr, unsigned long);
2262 { mpz_setbit }, /* 0 */
2263 { mpz_clrbit }, /* 1 */
2264 { mpz_combit }, /* 2 */
2270 if (use == USE_MPZ && SvREFCNT(SvRV(sv)) == 1 && ! SvSMAGICAL(sv))
2272 /* our operand is a non-magical mpz with a reference count of 1, so
2273 we can just modify it */
2274 (*table[ix].op) (SvMPZ(sv)->m, bit);
2278 /* otherwise we need to make a new mpz, from whatever we have, and
2279 operate on that, possibly invoking magic when storing back */
2282 mpz_ptr coerce_ptr = coerce_mpz_using (z->m, sv, use);
2283 if (coerce_ptr != z->m)
2284 mpz_set (z->m, coerce_ptr);
2285 (*table[ix].op) (z->m, bit);
2286 new_sv = sv_bless (sv_setref_pv (sv_newmortal(), NULL, z),
2288 SvSetMagicSV (sv, new_sv);
2302 mpz_sqrtrem (root->m, rem->m, z);
2304 PUSHs (MPX_NEWMORTAL (root, mpz_class_hv));
2305 PUSHs (MPX_NEWMORTAL (rem, mpz_class_hv));
2309 sizeinbase (z, base)
2313 RETVAL = mpz_sizeinbase (z, base);
2323 RETVAL = mpz_tstbit (z, bit);
2329 #------------------------------------------------------------------------------
2331 MODULE = GMP PACKAGE = GMP::Mpq
2339 TRACE (printf ("%s new, ix=%ld, items=%d\n", mpq_class, ix, (int) items));
2343 mpq_set_ui (RETVAL->m, 0L, 1L);
2347 mpq_ptr rp = RETVAL->m;
2348 mpq_ptr cp = coerce_mpq (rp, ST(0));
2356 rp = mpq_numref (RETVAL->m);
2357 cp = coerce_mpz (rp, ST(0));
2360 rp = mpq_denref (RETVAL->m);
2361 cp = coerce_mpz (rp, ST(1));
2367 croak ("%s new: invalid arguments", mpq_class);
2374 overload_constant (str, pv, d1, ...)
2375 const_string_assume str
2382 TRACE (printf ("%s constant: %s\n", mpq_class, str));
2384 if (mpq_set_str (q->m, str, 0) == 0)
2385 { sv = sv_bless (sv_setref_pv (sv_newmortal(), NULL, q), mpq_class_hv); }
2387 { free_mpq (q); sv = pv; }
2392 overload_copy (q, d1, d2)
2398 mpq_set (RETVAL->m, q->m);
2407 TRACE (printf ("%s DESTROY %p\n", mpq_class, q));
2412 overload_string (q, d1, d2)
2417 TRACE (printf ("%s overload_string %p\n", mpq_class, q));
2418 RETVAL = mpq_get_str (NULL, 10, q->m);
2424 overload_add (xv, yv, order)
2429 GMP::Mpq::overload_sub = 1
2430 GMP::Mpq::overload_mul = 2
2431 GMP::Mpq::overload_div = 3
2433 static_functable const struct {
2434 void (*op) (mpq_ptr, mpq_srcptr, mpq_srcptr);
2436 { mpq_add }, /* 0 */
2437 { mpq_sub }, /* 1 */
2438 { mpq_mul }, /* 2 */
2439 { mpq_div }, /* 3 */
2442 TRACE (printf ("%s binary\n", mpf_class));
2444 if (order == &PL_sv_yes)
2445 SV_PTR_SWAP (xv, yv);
2447 (*table[ix].op) (RETVAL->m,
2448 coerce_mpq (tmp_mpq_0, xv),
2449 coerce_mpq (tmp_mpq_1, yv));
2455 overload_addeq (x, y, o)
2460 GMP::Mpq::overload_subeq = 1
2461 GMP::Mpq::overload_muleq = 2
2462 GMP::Mpq::overload_diveq = 3
2464 static_functable const struct {
2465 void (*op) (mpq_ptr, mpq_srcptr, mpq_srcptr);
2467 { mpq_add }, /* 0 */
2468 { mpq_sub }, /* 1 */
2469 { mpq_mul }, /* 2 */
2470 { mpq_div }, /* 3 */
2474 (*table[ix].op) (x->m, x->m, y);
2479 overload_lshift (qv, nv, order)
2484 GMP::Mpq::overload_rshift = 1
2485 GMP::Mpq::overload_pow = 2
2487 static_functable const struct {
2488 void (*op) (mpq_ptr, mpq_srcptr, unsigned long);
2490 { mpq_mul_2exp }, /* 0 */
2491 { mpq_div_2exp }, /* 1 */
2492 { x_mpq_pow_ui }, /* 2 */
2496 if (order == &PL_sv_yes)
2497 SV_PTR_SWAP (qv, nv);
2499 (*table[ix].op) (RETVAL->m, coerce_mpq (RETVAL->m, qv), coerce_ulong (nv));
2505 overload_lshifteq (q, n, o)
2510 GMP::Mpq::overload_rshifteq = 1
2511 GMP::Mpq::overload_poweq = 2
2513 static_functable const struct {
2514 void (*op) (mpq_ptr, mpq_srcptr, unsigned long);
2516 { mpq_mul_2exp }, /* 0 */
2517 { mpq_div_2exp }, /* 1 */
2518 { x_mpq_pow_ui }, /* 2 */
2522 (*table[ix].op) (q->m, q->m, n);
2527 overload_inc (q, d1, d2)
2532 GMP::Mpq::overload_dec = 1
2534 static_functable const struct {
2535 void (*op) (mpz_ptr, mpz_srcptr, mpz_srcptr);
2537 { mpz_add }, /* 0 */
2538 { mpz_sub }, /* 1 */
2542 (*table[ix].op) (mpq_numref(q->m), mpq_numref(q->m), mpq_denref(q->m));
2546 overload_abs (q, d1, d2)
2551 GMP::Mpq::overload_neg = 1
2553 static_functable const struct {
2554 void (*op) (mpq_ptr w, mpq_srcptr x);
2556 { mpq_abs }, /* 0 */
2557 { mpq_neg }, /* 1 */
2562 (*table[ix].op) (RETVAL->m, q->m);
2568 overload_spaceship (x, y, order)
2573 RETVAL = mpq_cmp (x->m, y);
2574 RETVAL = SGN (RETVAL);
2575 if (order == &PL_sv_yes)
2582 overload_bool (q, d1, d2)
2587 GMP::Mpq::overload_not = 1
2589 RETVAL = (mpq_sgn (q->m) != 0) ^ ix;
2595 overload_eq (x, yv, d)
2600 GMP::Mpq::overload_ne = 1
2610 if (x_mpq_integer_p (x->m))
2614 RETVAL = (mpz_cmp_si (mpq_numref(x->m), SvIVX(yv)) == 0);
2617 RETVAL = (mpz_cmp_ui (mpq_numref(x->m), SvUVX(yv)) == 0);
2620 RETVAL = (mpz_cmp (mpq_numref(x->m), SvMPZ(yv)->m) == 0);
2627 RETVAL = (mpq_equal (x->m, SvMPQ(yv)->m) != 0);
2631 RETVAL = (mpq_equal (x->m, coerce_mpq_using (tmp_mpq_0, yv, use)) != 0);
2643 mpq_canonicalize (q->m);
2651 mpq_inv (RETVAL->m, q);
2663 mpz_set (RETVAL->m, (ix == 0 ? mpq_numref(q->m) : mpq_denref(q->m)));
2669 #------------------------------------------------------------------------------
2671 MODULE = GMP PACKAGE = GMP::Mpf
2681 TRACE (printf ("%s new\n", mpf_class));
2683 croak ("%s new: invalid arguments", mpf_class);
2684 prec = (items == 2 ? coerce_ulong (ST(1)) : mpf_get_default_prec());
2685 RETVAL = new_mpf (prec);
2689 my_mpf_set_sv_using (RETVAL, sv, use_sv(sv));
2696 overload_constant (sv, d1, d2, ...)
2701 assert (SvPOK (sv));
2702 TRACE (printf ("%s constant: %s\n", mpq_class, SvPVX(sv)));
2703 RETVAL = new_mpf (mpf_get_default_prec());
2704 my_mpf_set_svstr (RETVAL, sv);
2710 overload_copy (f, d1, d2)
2715 TRACE (printf ("%s copy\n", mpf_class));
2716 RETVAL = new_mpf (mpf_get_prec (f));
2717 mpf_set (RETVAL, f);
2726 TRACE (printf ("%s DESTROY %p\n", mpf_class, f));
2729 assert_support (mpf_count--);
2734 overload_add (x, y, order)
2739 GMP::Mpf::overload_sub = 1
2740 GMP::Mpf::overload_mul = 2
2741 GMP::Mpf::overload_div = 3
2743 static_functable const struct {
2744 void (*op) (mpf_ptr, mpf_srcptr, mpf_srcptr);
2746 { mpf_add }, /* 0 */
2747 { mpf_sub }, /* 1 */
2748 { mpf_mul }, /* 2 */
2749 { mpf_div }, /* 3 */
2753 RETVAL = new_mpf (mpf_get_prec (x));
2754 if (order == &PL_sv_yes)
2755 MPF_PTR_SWAP (x, y);
2756 (*table[ix].op) (RETVAL, x, y);
2762 overload_addeq (x, y, o)
2767 GMP::Mpf::overload_subeq = 1
2768 GMP::Mpf::overload_muleq = 2
2769 GMP::Mpf::overload_diveq = 3
2771 static_functable const struct {
2772 void (*op) (mpf_ptr, mpf_srcptr, mpf_srcptr);
2774 { mpf_add }, /* 0 */
2775 { mpf_sub }, /* 1 */
2776 { mpf_mul }, /* 2 */
2777 { mpf_div }, /* 3 */
2781 (*table[ix].op) (x, x, y);
2786 overload_lshift (fv, nv, order)
2791 GMP::Mpf::overload_rshift = 1
2792 GMP::Mpf::overload_pow = 2
2794 static_functable const struct {
2795 void (*op) (mpf_ptr, mpf_srcptr, unsigned long);
2797 { mpf_mul_2exp }, /* 0 */
2798 { mpf_div_2exp }, /* 1 */
2799 { mpf_pow_ui }, /* 2 */
2806 prec = mpf_get_prec (f);
2807 if (order == &PL_sv_yes)
2808 SV_PTR_SWAP (fv, nv);
2809 f = coerce_mpf (tmp_mpf_0, fv, prec);
2810 RETVAL = new_mpf (prec);
2811 (*table[ix].op) (RETVAL, f, coerce_ulong (nv));
2817 overload_lshifteq (f, n, o)
2822 GMP::Mpf::overload_rshifteq = 1
2823 GMP::Mpf::overload_poweq = 2
2825 static_functable const struct {
2826 void (*op) (mpf_ptr, mpf_srcptr, unsigned long);
2828 { mpf_mul_2exp }, /* 0 */
2829 { mpf_div_2exp }, /* 1 */
2830 { mpf_pow_ui }, /* 2 */
2834 (*table[ix].op) (f, f, n);
2839 overload_abs (f, d1, d2)
2844 GMP::Mpf::overload_neg = 1
2845 GMP::Mpf::overload_sqrt = 2
2847 static_functable const struct {
2848 void (*op) (mpf_ptr w, mpf_srcptr x);
2850 { mpf_abs }, /* 0 */
2851 { mpf_neg }, /* 1 */
2852 { mpf_sqrt }, /* 2 */
2856 RETVAL = new_mpf (mpf_get_prec (f));
2857 (*table[ix].op) (RETVAL, f);
2863 overload_inc (f, d1, d2)
2868 GMP::Mpf::overload_dec = 1
2870 static_functable const struct {
2871 void (*op) (mpf_ptr w, mpf_srcptr x, unsigned long y);
2873 { mpf_add_ui }, /* 0 */
2874 { mpf_sub_ui }, /* 1 */
2878 (*table[ix].op) (f, f, 1L);
2882 overload_spaceship (xv, yv, order)
2890 switch (use_sv (yv)) {
2892 RETVAL = mpf_cmp_si (x, SvIVX(yv));
2895 RETVAL = mpf_cmp_ui (x, SvUVX(yv));
2898 RETVAL = mpf_cmp_d (x, SvNVX(yv));
2903 const char *str = SvPV (yv, len);
2904 /* enough for all digits of the string */
2905 tmp_mpf_set_prec (tmp_mpf_0, strlen(str)+64);
2906 if (mpf_set_str (tmp_mpf_0->m, str, 10) != 0)
2907 croak ("%s <=>: invalid string format", mpf_class);
2908 RETVAL = mpf_cmp (x, tmp_mpf_0->m);
2912 RETVAL = - x_mpz_cmp_f (SvMPZ(yv)->m, x);
2915 RETVAL = mpf_cmp (x, SvMPF(yv));
2918 RETVAL = mpq_cmp (coerce_mpq (tmp_mpq_0, xv),
2919 coerce_mpq (tmp_mpq_1, yv));
2922 RETVAL = SGN (RETVAL);
2923 if (order == &PL_sv_yes)
2930 overload_bool (f, d1, d2)
2935 GMP::Mpf::overload_not = 1
2937 RETVAL = (mpf_sgn (f) != 0) ^ ix;
2949 static_functable const struct {
2950 void (*op) (mpf_ptr w, mpf_srcptr x);
2952 { mpf_ceil }, /* 0 */
2953 { mpf_floor }, /* 1 */
2954 { mpf_trunc }, /* 2 */
2958 RETVAL = new_mpf (mpf_get_prec (f));
2959 (*table[ix].op) (RETVAL, f);
2967 RETVAL = mpf_get_default_prec();
2976 RETVAL = mpf_get_prec (f);
2982 mpf_eq (xv, yv, bits)
2989 TRACE (printf ("%s eq\n", mpf_class));
2990 coerce_mpf_pair (&x,xv, &y,yv);
2991 RETVAL = mpf_eq (x, y, bits);
3004 TRACE (printf ("%s reldiff\n", mpf_class));
3005 prec = coerce_mpf_pair (&x,xv, &y,yv);
3006 RETVAL = new_mpf (prec);
3007 mpf_reldiff (RETVAL, x, y);
3013 set_default_prec (prec)
3016 TRACE (printf ("%s set_default_prec %lu\n", mpf_class, prec));
3017 mpf_set_default_prec (prec);
3025 mpf_ptr old_f, new_f;
3028 TRACE (printf ("%s set_prec to %lu\n", mpf_class, prec));
3033 if (SvREFCNT(SvRV(sv)) == 1)
3034 mpf_set_prec (old_f, prec);
3037 TRACE (printf (" fork new mpf\n"));
3038 new_f = new_mpf (prec);
3039 mpf_set (new_f, old_f);
3045 TRACE (printf (" coerce to mpf\n"));
3046 new_f = new_mpf (prec);
3047 my_mpf_set_sv_using (new_f, sv, use);
3049 sv_bless (sv_setref_pv (sv, NULL, new_f), mpf_class_hv);
3054 #------------------------------------------------------------------------------
3056 MODULE = GMP PACKAGE = GMP::Rand
3061 GMP::Rand::randstate = 1
3063 TRACE (printf ("%s new\n", rand_class));
3064 New (GMP_MALLOC_ID, RETVAL, 1, __gmp_randstate_struct);
3065 TRACE (printf (" RETVAL %p\n", RETVAL));
3066 assert_support (rand_count++);
3071 gmp_randinit_default (RETVAL);
3075 if (SvROK (ST(0)) && sv_derived_from (ST(0), rand_class))
3079 gmp_randinit_set (RETVAL, SvRANDSTATE (ST(0)));
3084 const char *method = SvPV (ST(0), len);
3085 assert (len == strlen (method));
3086 if (strcmp (method, "lc_2exp") == 0)
3090 gmp_randinit_lc_2exp (RETVAL,
3091 coerce_mpz (tmp_mpz_0, ST(1)),
3092 coerce_ulong (ST(2)),
3093 coerce_ulong (ST(3)));
3095 else if (strcmp (method, "lc_2exp_size") == 0)
3099 if (! gmp_randinit_lc_2exp_size (RETVAL, coerce_ulong (ST(1))))
3105 else if (strcmp (method, "mt") == 0)
3109 gmp_randinit_mt (RETVAL);
3114 croak ("%s new: invalid arguments", rand_class);
3126 TRACE (printf ("%s DESTROY\n", rand_class));
3129 assert_support (rand_count--);
3138 gmp_randseed (r, z);
3142 mpz_urandomb (r, bits)
3146 GMP::Rand::mpz_rrandomb = 1
3148 static_functable const struct {
3149 void (*fun) (mpz_ptr, gmp_randstate_t r, unsigned long bits);
3151 { mpz_urandomb }, /* 0 */
3152 { mpz_rrandomb }, /* 1 */
3157 (*table[ix].fun) (RETVAL->m, r, bits);
3168 mpz_urandomm (RETVAL->m, r, m);
3174 mpf_urandomb (r, bits)
3178 RETVAL = new_mpf (bits);
3179 mpf_urandomb (RETVAL, r, bits);
3185 gmp_urandomb_ui (r, bits)
3189 GMP::Rand::gmp_urandomm_ui = 1
3191 static_functable const struct {
3192 unsigned long (*fun) (gmp_randstate_t r, unsigned long bits);
3194 { gmp_urandomb_ui }, /* 0 */
3195 { gmp_urandomm_ui }, /* 1 */
3199 RETVAL = (*table[ix].fun) (r, bits);