github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/demos/perl/GMP.xs (about)

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