1 /* GMP module external subroutines.
2 
3 Copyright 2001-2003 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
new_mpf(unsigned long prec)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
tmp_mpf_grow(tmp_mpf_ptr f,unsigned long prec)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
class_or_croak(SV * sv,classconst char * cl)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
x_mpz_odd_p(mpz_srcptr z)359 x_mpz_odd_p (mpz_srcptr z)
360 {
361   return mpz_odd_p (z);
362 }
363 static int
x_mpz_even_p(mpz_srcptr z)364 x_mpz_even_p (mpz_srcptr z)
365 {
366   return mpz_even_p (z);
367 }
368 
369 static void
x_mpq_pow_ui(mpq_ptr r,mpq_srcptr b,unsigned long e)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 *
my_gmp_alloc(size_t n)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 *
my_gmp_realloc(void * p,size_t oldsize,size_t newsize)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
my_gmp_free(void * p,size_t n)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)
my_mpx_set_svstr(mpq)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
x_mpq_fits_slong_p(mpq_srcptr q)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
x_mpz_cmp_q(mpz_ptr x,mpq_srcptr y)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
x_mpz_cmp_f(mpz_srcptr x,mpf_srcptr y)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
use_sv(SV * sv)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
coerce_mpz_using(mpz_ptr tmp,SV * sv,int use)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
coerce_mpz(mpz_ptr tmp,SV * sv)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
coerce_mpq_using(mpq_ptr tmp,SV * sv,int use)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
coerce_mpq(mpq_ptr tmp,SV * sv)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
my_mpf_set_sv_using(mpf_ptr f,SV * sv,int use)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
coerce_mpf_using(tmp_mpf_ptr tmp,SV * sv,unsigned long prec,int use)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
coerce_mpf(tmp_mpf_ptr tmp,SV * sv,unsigned long prec)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
coerce_mpf_pair(mpf * xp,SV * xv,mpf * yp,SV * yv)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
coerce_ulong(SV * sv)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
coerce_long(SV * sv)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
overload_constant(str,pv,d1,...)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_div_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_div_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
overload_spaceship(xv,yv,order)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
overload_spaceship(xv,yv,order)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
3213