1 
2 #ifdef  __MINGW32__
3 #ifndef __USE_MINGW_ANSI_STDIO
4 #define __USE_MINGW_ANSI_STDIO 1
5 #endif
6 #endif
7 
8 #define PERL_NO_GET_CONTEXT 1
9 
10 #include "EXTERN.h"
11 #include "perl.h"
12 #include "XSUB.h"
13 
14 
15 
16 #include "math_gmpz_include.h"
17 
MATH_GMPz_IV_MAX(pTHX)18 SV * MATH_GMPz_IV_MAX(pTHX) {
19      return newSViv((IV)IV_MAX);
20 }
21 
MATH_GMPz_IV_MIN(pTHX)22 SV * MATH_GMPz_IV_MIN(pTHX) {
23      return newSViv((IV)IV_MIN);
24 }
25 
MATH_GMPz_UV_MAX(pTHX)26 SV * MATH_GMPz_UV_MAX(pTHX) {
27      return newSVuv((UV)UV_MAX);
28 }
29 
_is_infstring(char * s)30 int _is_infstring(char * s) {
31   int sign = 1;
32 
33   if(s[0] == '-') {
34     sign = -1;
35     s++;
36   }
37   else {
38     if(s[0] == '+') s++;
39   }
40 
41   if((s[0] == 'i' || s[0] == 'I') && (s[1] == 'n' || s[1] == 'N') && (s[2] == 'f' || s[2] == 'F'))
42     return sign;
43 
44 #ifdef _WIN32_BIZARRE_INFNAN /* older Win32 perls stringify infinities as(-)1.#INF */
45 
46    if(!strcmp(s, "1.#INF")) return sign;
47 
48 #endif
49 
50   return 0;
51 }
52 
Rmpz_init_set_str_nobless(pTHX_ SV * num,SV * base)53 SV * Rmpz_init_set_str_nobless(pTHX_ SV * num, SV * base) {
54      mpz_t * mpz_t_obj;
55      int b = (int)SvUV(base);
56      SV * obj_ref, * obj;
57 
58      if(b == 1 || b > 62) croak("Second argument supplied to Rmpz_init_set_str_nobless is not in acceptable range");
59 
60      New(1, mpz_t_obj, 1, mpz_t);
61      if(mpz_t_obj == NULL) croak("Failed to allocate memory in Rmpz_create function");
62      if(mpz_init_set_str (*mpz_t_obj, SvPV_nolen(num), b))
63         croak("First argument supplied to Rmpz_create_init_nobless is not a valid base %u integer", b);
64 
65      obj_ref = newSV(0);
66      obj = newSVrv(obj_ref, NULL);
67      sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
68      SvREADONLY_on(obj);
69      return obj_ref;
70 
71 }
72 
Rmpz_init2_nobless(pTHX_ SV * bits)73 SV * Rmpz_init2_nobless(pTHX_ SV * bits) {
74      mpz_t * mpz_t_obj;
75      SV * obj_ref, * obj;
76 
77      New(1, mpz_t_obj, 1, mpz_t);
78      if(mpz_t_obj == NULL) croak("Failed to allocate memory in Rmpz_init2_nobless function");
79      obj_ref = newSV(0);
80      obj = newSVrv(obj_ref, NULL);
81      mpz_init2 (*mpz_t_obj, SvUV(bits));
82 
83      sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
84      SvREADONLY_on(obj);
85      return obj_ref;
86 
87 }
88 
Rmpz_init_nobless(pTHX)89 SV * Rmpz_init_nobless(pTHX) {
90      mpz_t * mpz_t_obj;
91      SV * obj_ref, * obj;
92 
93      New(1, mpz_t_obj, 1, mpz_t);
94      if(mpz_t_obj == NULL) croak("Failed to allocate memory in Rmpz_init_nobless function");
95      obj_ref = newSV(0);
96      obj = newSVrv(obj_ref, NULL);
97      mpz_init(*mpz_t_obj);
98 
99      sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
100      SvREADONLY_on(obj);
101      return obj_ref;
102 }
103 
Rmpz_init_set_nobless(pTHX_ mpz_t * p)104 SV * Rmpz_init_set_nobless(pTHX_ mpz_t * p) {
105      mpz_t * mpz_t_obj;
106      SV * obj_ref, * obj;
107 
108      New(1, mpz_t_obj, 1, mpz_t);
109      if(mpz_t_obj == NULL) croak("Failed to allocate memory in Rmpz_init_set_nobless function");
110      obj_ref = newSV(0);
111      obj = newSVrv(obj_ref, NULL);
112      mpz_init_set(*mpz_t_obj, *p);
113 
114      sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
115      SvREADONLY_on(obj);
116      return obj_ref;
117 }
118 
Rmpz_init_set_ui_nobless(pTHX_ SV * p)119 SV * Rmpz_init_set_ui_nobless(pTHX_ SV * p) {
120      mpz_t * mpz_t_obj;
121      SV * obj_ref, * obj;
122 
123      New(1, mpz_t_obj, 1, mpz_t);
124      if(mpz_t_obj == NULL) croak("Failed to allocate memory in Rmpz_init_set_ui_nobless function");
125      obj_ref = newSV(0);
126      obj = newSVrv(obj_ref, NULL);
127      mpz_init_set_ui(*mpz_t_obj, SvUV(p));
128 
129      sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
130      SvREADONLY_on(obj);
131      return obj_ref;
132 }
133 
Rmpz_init_set_si_nobless(pTHX_ SV * p)134 SV * Rmpz_init_set_si_nobless(pTHX_ SV * p) {
135      mpz_t * mpz_t_obj;
136      SV * obj_ref, * obj;
137 
138      New(1, mpz_t_obj, 1, mpz_t);
139      if(mpz_t_obj == NULL) croak("Failed to allocate memory in Rmpz_init_set_si_nobless function");
140      obj_ref = newSV(0);
141      obj = newSVrv(obj_ref, NULL);
142      mpz_init_set_si(*mpz_t_obj, SvIV(p));
143 
144      sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
145      SvREADONLY_on(obj);
146      return obj_ref;
147 }
148 
149 
Rmpz_init_set_d_nobless(pTHX_ SV * p)150 SV * Rmpz_init_set_d_nobless(pTHX_ SV * p) {
151      mpz_t * mpz_t_obj;
152      SV * obj_ref, * obj;
153      double d = SvNV(p);
154 
155      if(d != d) croak("In Rmpz_set_d, cannot coerce a NaN to a Math::GMPz value");
156      if(d != 0 && (d / d != 1))
157        croak("In Rmpz_init_set_d_nobless, cannot coerce an Inf to a Math::GMPz value");
158 
159      New(1, mpz_t_obj, 1, mpz_t);
160      if(mpz_t_obj == NULL) croak("Failed to allocate memory in Rmpz_init_set_d_nobless function");
161      obj_ref = newSV(0);
162      obj = newSVrv(obj_ref, NULL);
163      mpz_init_set_d(*mpz_t_obj, d);
164 
165      sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
166      SvREADONLY_on(obj);
167      return obj_ref;
168 }
169 
Rmpz_init(pTHX)170 SV * Rmpz_init(pTHX) {
171      mpz_t * mpz_t_obj;
172      SV * obj_ref, * obj;
173 
174      New(1, mpz_t_obj, 1, mpz_t);
175      if(mpz_t_obj == NULL) croak("Failed to allocate memory in Rmpz_init function");
176      obj_ref = newSV(0);
177      obj = newSVrv(obj_ref, "Math::GMPz");
178      mpz_init(*mpz_t_obj);
179 
180      sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
181      SvREADONLY_on(obj);
182      return obj_ref;
183 }
184 
Rmpz_init_set(pTHX_ mpz_t * p)185 SV * Rmpz_init_set(pTHX_ mpz_t * p) {
186      mpz_t * mpz_t_obj;
187      SV * obj_ref, * obj;
188 
189      New(1, mpz_t_obj, 1, mpz_t);
190      if(mpz_t_obj == NULL) croak("Failed to allocate memory in Rmpz_init_set function");
191      obj_ref = newSV(0);
192      obj = newSVrv(obj_ref, "Math::GMPz");
193      mpz_init_set(*mpz_t_obj, *p);
194 
195      sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
196      SvREADONLY_on(obj);
197      return obj_ref;
198 }
199 
Rmpz_init_set_ui(pTHX_ SV * p)200 SV * Rmpz_init_set_ui(pTHX_ SV * p) {
201      mpz_t * mpz_t_obj;
202      SV * obj_ref, * obj;
203 
204      New(1, mpz_t_obj, 1, mpz_t);
205      if(mpz_t_obj == NULL) croak("Failed to allocate memory in Rmpz_init_set_ui function");
206      obj_ref = newSV(0);
207      obj = newSVrv(obj_ref, "Math::GMPz");
208      mpz_init_set_ui(*mpz_t_obj, SvUV(p));
209 
210      sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
211      SvREADONLY_on(obj);
212      return obj_ref;
213 }
214 
Rmpz_init_set_si(pTHX_ SV * p)215 SV * Rmpz_init_set_si(pTHX_ SV * p) {
216      mpz_t * mpz_t_obj;
217      SV * obj_ref, * obj;
218 
219      New(1, mpz_t_obj, 1, mpz_t);
220      if(mpz_t_obj == NULL) croak("Failed to allocate memory in Rmpz_init_set_si function");
221      obj_ref = newSV(0);
222      obj = newSVrv(obj_ref, "Math::GMPz");
223      mpz_init_set_si(*mpz_t_obj, SvIV(p));
224 
225      sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
226      SvREADONLY_on(obj);
227      return obj_ref;
228 }
229 
Rmpz_set_uj(mpz_t * copy,UV original)230 void Rmpz_set_uj(mpz_t * copy, UV original) {
231 #ifdef MATH_GMPZ_NEED_LONG_LONG_INT
232      mpz_set_ui(*copy, original >> 32);
233      if(mpz_cmp_ui(*copy, 0))
234        mpz_mul_2exp(*copy, *copy, 32);
235      mpz_add_ui(*copy, *copy, original & 4294967295);
236 
237 #else
238      croak("Rmpz_set_uj function not implemented on this build of perl");
239 
240 #endif
241 
242 }
243 
Rmpz_set_sj(mpz_t * copy,IV original)244 void Rmpz_set_sj(mpz_t * copy, IV original) {
245 #ifdef MATH_GMPZ_NEED_LONG_LONG_INT
246      if(original >= 0) Rmpz_set_uj(copy, original);
247      else {
248        Rmpz_set_uj(copy, -original);
249        mpz_neg(*copy, *copy);
250      }
251 
252 #else
253      croak("Rmpz_set_sj function not implemented on this build of perl");
254 
255 #endif
256 
257 }
258 
259 /* also handles UV values */
260 
Rmpz_set_IV(pTHX_ mpz_t * copy,SV * original)261 void Rmpz_set_IV(pTHX_ mpz_t * copy, SV * original) {
262 
263      if(SV_IS_IOK(original)) {
264 #ifndef MATH_GMPZ_NEED_LONG_LONG_INT
265        if(SvUOK(original))   mpz_set_ui(*copy, SvUVX(original));
266        else mpz_set_si(*copy, SvIVX(original));
267      }
268 
269 #else
270        if(SvUOK(original))   Rmpz_set_uj(copy, SvUVX(original));
271        else Rmpz_set_sj(copy, SvIVX(original));
272      }
273 
274 #endif
275      else croak("Arg provided to Rmpz_set_IV is not an IV");
276 }
277 
278 /* also handles UV values */
Rmpz_init_set_IV(pTHX_ SV * p)279 SV * Rmpz_init_set_IV(pTHX_ SV * p) {
280      mpz_t * mpz_t_obj;
281      SV * obj_ref, * obj;
282 
283      New(1, mpz_t_obj, 1, mpz_t);
284      if(mpz_t_obj == NULL) croak("Failed to allocate memory in Rmpz_init_set_IV function");
285      obj_ref = newSV(0);
286      obj = newSVrv(obj_ref, "Math::GMPz");
287 
288      mpz_init(*mpz_t_obj);
289 
290      sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
291      Rmpz_set_IV(aTHX_ mpz_t_obj, p);
292      SvREADONLY_on(obj);
293      return obj_ref;
294 }
295 
296 /* also handles UV values */
Rmpz_init_set_IV_nobless(pTHX_ SV * p)297 SV * Rmpz_init_set_IV_nobless(pTHX_ SV * p) {
298      mpz_t * mpz_t_obj;
299      SV * obj_ref, * obj;
300 
301      New(1, mpz_t_obj, 1, mpz_t);
302      if(mpz_t_obj == NULL) croak("Failed to allocate memory in Rmpz_init_set_IV_nobless function");
303      obj_ref = newSV(0);
304      obj = newSVrv(obj_ref, "NULL");
305 
306      mpz_init(*mpz_t_obj);
307 
308      sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
309      Rmpz_set_IV(aTHX_ mpz_t_obj, p);
310      SvREADONLY_on(obj);
311      return obj_ref;
312 }
313 
314 /* also handles UV values */
_Rmpz_get_IV(pTHX_ mpz_t * n)315 SV * _Rmpz_get_IV(pTHX_ mpz_t * n) {
316 
317 #ifdef MATH_GMPZ_NEED_LONG_LONG_INT
318 
319    int negative = 0;
320    char * out;
321    SV * outsv;
322    mpz_t temp;
323    mpz_t _uv_max;
324    mpz_t _iv_max;
325    mpz_t _iv_min;
326 
327 #endif
328 
329    if(mpz_fits_slong_p(*n))
330      return newSViv(mpz_get_si(*n));
331 
332    if(mpz_fits_ulong_p(*n))
333      return newSVuv(mpz_get_ui(*n));
334 
335 #ifndef MATH_GMPZ_NEED_LONG_LONG_INT
336 
337    if(mpz_cmp_ui(*n, 0) > 0)
338      return newSVuv(mpz_get_ui(*n));
339 
340    return newSViv(mpz_get_si(*n));
341 
342 #else
343 
344    if(mpz_sgn(*n) < 0) negative = 1;
345 
346    Newxz(out, 24, char);
347    if(out == NULL)
348      croak("Failed to allocate memory in Rmpz_get_IV function");
349 
350    if(negative) { /* must be less than LONG_MIN */
351      mpz_init_set_str(_iv_min, SvPV_nolen(MATH_GMPz_IV_MIN(aTHX)), 10);
352      if(mpz_cmp(*n, _iv_min) < 0) { /* must be less than IV_MIN */
353        mpz_clear(_iv_min);
354        mpz_init(temp);
355        mpz_init_set_str(_iv_max, SvPV_nolen(MATH_GMPz_IV_MAX(aTHX)), 10);
356        mpz_abs(temp, *n);
357        mpz_and(temp, temp, _iv_max);
358        mpz_clear(_iv_max);
359        mpz_neg(temp, temp);
360        mpz_get_str(out, 10, temp);
361        mpz_clear(temp);
362        outsv = newSVpv(out, 0);
363        Safefree(out);
364        return outsv;
365      }
366      else { /* must fit into an IV */
367        mpz_clear(_iv_min);
368        mpz_get_str(out, 10, *n);
369        outsv = newSVpv(out, 0);
370        Safefree(out);
371        return outsv;
372      }
373    }
374    else { /* it's +ve */
375      mpz_init_set_str(_uv_max, SvPV_nolen(MATH_GMPz_UV_MAX(aTHX)), 10);
376      if(mpz_cmp(*n, _uv_max) > 0) { /* needs to be truncated */
377        mpz_init_set(temp, *n);
378        mpz_and(temp, temp, _uv_max);
379        mpz_clear(_uv_max);
380        mpz_get_str(out, 10, temp);
381        mpz_clear(temp);
382        outsv = newSVpv(out, 0);
383        Safefree(out);
384        return outsv;
385      }
386      else { /* must fit into a UV */
387        mpz_clear(_uv_max);
388        mpz_get_str(out, 10, *n);
389        outsv = newSVpv(out, 0);
390        Safefree(out);
391        return outsv;
392      }
393    }
394 
395 #endif
396 }
397 
398 /* also handles UVs */
Rmpz_fits_IV_p(pTHX_ mpz_t * n)399 int Rmpz_fits_IV_p(pTHX_ mpz_t * n) {
400 
401 #ifndef MATH_GMPZ_NEED_LONG_LONG_INT
402      if(mpz_fits_slong_p(*n) || mpz_fits_ulong_p(*n)) return 1;
403      return 0;
404 #else
405      mpz_t t;
406 
407      if(mpz_fits_slong_p(*n) || mpz_fits_ulong_p(*n)) return 1;
408 
409      mpz_init_set_str(t, SvPV_nolen(MATH_GMPz_UV_MAX(aTHX)), 10);
410      if(mpz_cmp(*n, t) > 0) {
411        mpz_clear(t);
412        return 0;
413      }
414 
415      mpz_set_str(t, SvPV_nolen(MATH_GMPz_IV_MIN(aTHX)), 10);
416      if(mpz_cmp(*n, t) < 0) {
417        mpz_clear(t);
418        return 0;
419      }
420 
421      mpz_clear(t);
422      return 1;
423 
424 #endif
425 }
426 
Rmpz_get_d(mpz_t * n)427 double Rmpz_get_d(mpz_t * n) {
428      return mpz_get_d(*n);
429 }
430 
Rmpz_get_NV(mpz_t * n)431 NV Rmpz_get_NV(mpz_t * n) {
432 
433 #if NVSIZE == 8
434      return mpz_get_d(*n);
435 
436 #else
437    /* Rely on strtold/strtoflt128 to correctly handle *
438     * the stringified form of the mpz_t argument      */
439      NV d;
440      char * out;
441 
442      Newxz(out, mpz_sizeinbase(*n, 10) + 3, char);
443      if(out == NULL) croak("Failed to allocate memory in Rmpz_get_NV function");
444 
445      mpz_get_str(out, 10, *n);
446 
447 #  if defined(USE_LONG_DOUBLE)
448        d = strtold(out, NULL);
449 
450 #  elif defined(USE_QUADMATH)
451        d = strtoflt128(out, NULL);
452 
453 #  else
454        Safefree(out);
455        croak("Unrecognized nvtype");
456 
457 #  endif
458      Safefree(out);
459      return d;
460 
461 #endif
462 }
463 
464 /* also handles UV values */
465 
Rmpz_cmp_IV(pTHX_ mpz_t * z,SV * iv)466 int Rmpz_cmp_IV(pTHX_ mpz_t * z, SV * iv) {
467      int ret;
468 
469 #ifndef MATH_GMPZ_NEED_LONG_LONG_INT
470      if(SV_IS_IOK(iv)) {
471        if(SvUOK(iv)) ret =  mpz_cmp_ui(*z, SvUVX(iv));
472        else ret = mpz_cmp_si(*z, SvIVX(iv));
473        return ret;
474      }
475      else croak("Arg provided to Rmpz_cmp_IV is not an IV");
476 #else
477      mpz_t temp;
478      if(SV_IS_IOK(iv)) mpz_init_set_str(temp, SvPV_nolen(iv), 10);
479      else croak("Arg provided to Rmpz_cmp_IV is not an IV");
480      ret = mpz_cmp(*z, temp);
481      mpz_clear(temp);
482      return ret;
483 #endif
484 
485 
486 }
487 
Rmpz_init_set_d(pTHX_ SV * p)488 SV * Rmpz_init_set_d(pTHX_ SV * p) {
489      mpz_t * mpz_t_obj;
490      SV * obj_ref, * obj;
491      double d = SvNV(p);
492 
493      if(d != d) croak("In Rmpz_init_set_d, cannot coerce a NaN to a Math::GMPz value");
494      if(d != 0 && (d / d != 1))
495        croak("In Rmpz_init_set_d, cannot coerce an Inf to a Math::GMPz value");
496 
497      New(1, mpz_t_obj, 1, mpz_t);
498      if(mpz_t_obj == NULL) croak("Failed to allocate memory in Rmpz_init_set_d function");
499      obj_ref = newSV(0);
500      obj = newSVrv(obj_ref, "Math::GMPz");
501      mpz_init_set_d(*mpz_t_obj, d);
502 
503      sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
504      SvREADONLY_on(obj);
505      return obj_ref;
506 }
507 
_mpf_set_dd(mpf_t * q,SV * p)508 void _mpf_set_dd(mpf_t * q, SV * p) {
509 #if defined(NV_IS_DOUBLEDOUBLE)  /* double-double */
510      double msd;                 /* Most Significant Double */
511      mpf_t t, d;
512      long double lsd;            /* Will be assigned the Least Siginficant Double */
513 
514      msd = (double)SvNV(p);
515      if(msd != 0.0) {
516        if(msd != msd) croak("In _Rmpf_set_ld, cannot coerce a NaN to a Math::GMPf object");
517        if(msd / msd != 1.0) croak("In _Rmpf_set_ld, cannot coerce an Inf to a Math::GMPf object");
518      }
519 
520      lsd = SvNV(p) - (long double)msd;
521 
522      mpf_init2(t, 2098);
523      mpf_init2(d, 53);
524      mpf_set_d(t, msd);
525      mpf_set_d(d, (double)lsd);
526      mpf_add(t, t, d);
527 
528      mpf_clear(d);
529 
530      mpf_set(*q, t);
531 
532      mpf_clear(t);
533 #else
534      croak("_mpf_set_dd is unavailable because NV is not DoubleDouble");
535 
536 #endif
537 }
538 
Rmpz_set_NV(pTHX_ mpz_t * copy,SV * original)539 void Rmpz_set_NV(pTHX_ mpz_t * copy, SV * original) {
540    NV nv;
541 
542 #if defined(USE_QUADMATH) || defined(USE_LONG_DOUBLE)
543 #  if defined(NV_IS_DOUBLEDOUBLE)
544      mpf_t f;
545 
546 #  else
547      NV buffer_size;
548      int returned;
549      char * buffer;
550 
551 #  endif
552 
553 #endif
554 
555      if(!SV_IS_NOK(original))
556        croak("In Rmpz_set_NV, 2nd argument is not an NV");
557 
558      nv = SvNV(original); /* First check that the NV flag is set   *
559                            * else flags of "original" might change */
560 
561      if(nv != nv) croak("In Rmpz_set_NV, cannot coerce a NaN to a Math::GMPz value");
562 
563      if(nv != 0 && (nv / nv != 1))
564        croak("In Rmpz_set_NV, cannot coerce an Inf to a Math::GMPz value");
565 
566 #if defined(USE_QUADMATH)
567      buffer_size = nv < 0.0Q ? nv * -1.0Q : nv;
568      buffer_size = ceilq(logq(buffer_size + 1) / 2.30258509299404568401799145468436418Q);
569 
570      Newxz(buffer, (int)buffer_size + 5, char);
571 
572      nv = nv >= 0 ? floorq(nv) : ceilq(nv);
573 
574      returned = quadmath_snprintf(buffer, (size_t)buffer_size + 5, "%.0Qf", nv);
575      if(returned < 0) croak("In Rmpz_set_NV, encoding error in quadmath_snprintf function");
576      if(returned >= buffer_size + 5) croak("In Rmpz_set_NV, buffer given to quadmath_snprintf function was too small");
577      mpz_set_str(*copy, buffer, 10);
578      Safefree(buffer);
579 
580 #elif defined(USE_LONG_DOUBLE)
581 # if defined(NV_IS_DOUBLEDOUBLE)
582      mpf_init2(f, 2098);
583      _mpf_set_dd(&f, original);
584      mpz_set_f(*copy, f);
585      mpf_clear(f);
586 
587 #  else
588      buffer_size = nv < 0.0L ? nv * -1.0L : nv;
589      buffer_size = ceill(logl(buffer_size + 1) / 2.30258509299404568401799145468436418L);
590      Newxz(buffer, buffer_size + 5, char);
591 
592      nv = nv >= 0 ? floorl(nv) : ceill(nv);
593      if(sprintf(buffer, "%.0Lf", nv) >= (int)buffer_size + 5) croak("In Rmpz_set_NV, buffer overflow in sprintf function");
594 
595      mpz_set_str(*copy, buffer, 10);
596      Safefree(buffer);
597 
598 #  endif
599 
600 #else
601      mpz_set_d(*copy, nv);
602 
603 #endif
604 }
605 
Rmpz_init_set_NV(pTHX_ SV * p)606 SV * Rmpz_init_set_NV(pTHX_ SV * p) {
607      mpz_t * mpz_t_obj;
608      SV * obj_ref, * obj;
609 
610      Newx(mpz_t_obj, 1, mpz_t);
611      if(mpz_t_obj == NULL) croak("Failed to allocate memory in Rmpz_init_set_NV function");
612      obj_ref = newSV(0);
613      obj = newSVrv(obj_ref, "Math::GMPz");
614 
615      mpz_init(*mpz_t_obj);
616 
617      sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
618      Rmpz_set_NV(aTHX_ mpz_t_obj, p);
619      SvREADONLY_on(obj);
620      return obj_ref;
621 }
622 
Rmpz_init_set_NV_nobless(pTHX_ SV * p)623 SV * Rmpz_init_set_NV_nobless(pTHX_ SV * p) {
624      mpz_t * mpz_t_obj;
625      SV * obj_ref, * obj;
626 
627      Newx(mpz_t_obj, 1, mpz_t);
628      if(mpz_t_obj == NULL) croak("Failed to allocate memory in Rmpz_init_set_NV_nobless function");
629      obj_ref = newSV(0);
630      obj = newSVrv(obj_ref, "NULL");
631 
632      mpz_init(*mpz_t_obj);
633 
634      sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
635      Rmpz_set_NV(aTHX_ mpz_t_obj, p);
636      SvREADONLY_on(obj);
637      return obj_ref;
638 }
639 
Rmpz_init_set_str(pTHX_ SV * num,SV * base)640 SV * Rmpz_init_set_str(pTHX_ SV * num, SV * base) {
641      mpz_t * mpz_t_obj;
642      int b = (int)SvUV(base);
643      SV * obj_ref, * obj;
644 
645      if(b == 1 || b > 62) croak("Second argument supplied to Rmpz_init_set_str is not in acceptable range");
646 
647      New(1, mpz_t_obj, 1, mpz_t);
648      if(mpz_t_obj == NULL) croak("Failed to allocate memory in Rmpz_init_set_str function");
649      if(mpz_init_set_str (*mpz_t_obj, SvPV_nolen(num), b))
650         croak("First argument supplied to Rmpz_init_set_str is not a valid base %u integer", b);
651 
652      obj_ref = newSV(0);
653      obj = newSVrv(obj_ref, "Math::GMPz");
654      sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
655      SvREADONLY_on(obj);
656      return obj_ref;
657 
658 }
659 
Rmpz_init2(pTHX_ SV * bits)660 SV * Rmpz_init2(pTHX_ SV * bits) {
661      mpz_t * mpz_t_obj;
662      SV * obj_ref, * obj;
663 
664      New(1, mpz_t_obj, 1, mpz_t);
665      if(mpz_t_obj == NULL) croak("Failed to allocate memory in Rmpz_init2 function");
666      obj_ref = newSV(0);
667      obj = newSVrv(obj_ref, "Math::GMPz");
668      mpz_init2 (*mpz_t_obj, SvUV(bits));
669 
670      sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
671      SvREADONLY_on(obj);
672      return obj_ref;
673 
674 }
675 
Rmpz_get_str(pTHX_ mpz_t * p,SV * base)676 SV * Rmpz_get_str(pTHX_ mpz_t * p, SV * base) {
677      char * out;
678      SV * outsv;
679      int c = (int)SvIV(base), b = (int)SvIV(base);
680 
681      if((b > -2 && b < 2) || b < -36 || b > 62) croak("Second argument supplied to Rmpz_get_str is not in acceptable range");
682 
683      if(c < 0) c *= -1;
684 
685      New(2, out, mpz_sizeinbase(*p, c) + 5, char);
686      if(out == NULL) croak("Failed to allocate memory in Rmpz_deref function");
687 
688      mpz_get_str(out, b, *p);
689      outsv = newSVpv(out, 0);
690      Safefree(out);
691      return outsv;
692 }
693 
DESTROY(pTHX_ mpz_t * p)694 void DESTROY(pTHX_ mpz_t * p) {
695 /*     printf("Destroying mpz "); */
696      mpz_clear(*p);
697      Safefree(p);
698 /*     printf("...destroyed\n"); */
699 }
700 
Rmpz_clear(pTHX_ mpz_t * p)701 void Rmpz_clear(pTHX_ mpz_t * p) {
702      mpz_clear(*p);
703      Safefree(p);
704 }
705 
Rmpz_clear_mpz(mpz_t * p)706 void Rmpz_clear_mpz(mpz_t * p) {
707      mpz_clear(*p);
708 }
709 
Rmpz_clear_ptr(pTHX_ mpz_t * p)710 void Rmpz_clear_ptr(pTHX_ mpz_t * p) {
711      Safefree(p);
712 }
713 
Rmpz_realloc2(pTHX_ mpz_t * integer,SV * bits)714 void Rmpz_realloc2(pTHX_ mpz_t * integer, SV * bits){
715      mpz_realloc2(*integer, SvUV(bits));
716 }
717 
Rmpz_set(mpz_t * copy,mpz_t * original)718 void Rmpz_set(mpz_t * copy, mpz_t * original) {
719      mpz_set(*copy, *original);
720 }
721 
Rmpz_set_q(mpz_t * copy,mpq_t * original)722 void Rmpz_set_q(mpz_t * copy, mpq_t * original) {
723      mpz_set_q(*copy, *original);
724 }
725 
Rmpz_set_f(mpz_t * copy,mpf_t * original)726 void Rmpz_set_f(mpz_t * copy, mpf_t * original) {
727      mpz_set_f(*copy, *original);
728 }
729 
Rmpz_set_si(mpz_t * copy,long original)730 void Rmpz_set_si(mpz_t * copy, long original) {
731      mpz_set_si(*copy, original);
732 }
733 
Rmpz_set_ui(mpz_t * copy,unsigned long original)734 void Rmpz_set_ui(mpz_t * copy, unsigned long original) {
735      mpz_set_ui(*copy, original);
736 }
737 
Rmpz_set_d(mpz_t * copy,double d)738 void Rmpz_set_d(mpz_t * copy, double d) {
739 
740      if(d != d) croak("In Rmpz_set_d, cannot coerce a NaN to a Math::GMPz value");
741      if(d != 0 && (d / d != 1))
742        croak("In Rmpz_set_d, cannot coerce an Inf to a Math::GMPz value");
743      mpz_set_d(*copy, d);
744 }
745 
Rmpz_set_str(pTHX_ mpz_t * copy,SV * original,int base)746 void Rmpz_set_str(pTHX_ mpz_t * copy, SV * original, int base) {
747     if(base == 1 || base > 62) croak("Second argument supplied to Rmpz_set_str is not in acceptable range");
748     if(mpz_set_str(*copy, SvPV_nolen(original), base))
749        croak("Second argument supplied to Rmpz_set_str is not a valid base %u integer", base);
750 }
751 
Rmpz_swap(mpz_t * a,mpz_t * b)752 void Rmpz_swap(mpz_t * a, mpz_t * b) {
753      mpz_swap(*a, *b);
754 }
755 
Rmpz_get_ui(mpz_t * n)756 unsigned long Rmpz_get_ui(mpz_t * n) {
757      return mpz_get_ui(*n);
758 }
759 
Rmpz_get_si(mpz_t * n)760 long Rmpz_get_si(mpz_t * n) {
761      return mpz_get_si(*n);
762 }
763 
Rmpz_get_d_2exp(pTHX_ mpz_t * n)764 void Rmpz_get_d_2exp(pTHX_ mpz_t * n) {
765      dXSARGS;
766      double d;
767      long exp;
768 
769      d = mpz_get_d_2exp(&exp, *n);
770 
771      /* sp = mark; */ /* not needed */
772      EXTEND(SP, 2);
773      ST(0) = sv_2mortal(newSVnv(d));
774      ST(1) = sv_2mortal(newSVuv(exp));
775      /* PUTBACK; */ /* not needed */
776      XSRETURN(2);
777 }
778 
Rmpz_getlimbn(pTHX_ mpz_t * p,SV * n)779 SV * Rmpz_getlimbn(pTHX_ mpz_t * p, SV * n) {
780      return newSVuv(mpz_getlimbn(*p, SvUV(n)));
781 }
782 
Rmpz_add(mpz_t * dest,mpz_t * src1,mpz_t * src2)783 void Rmpz_add(mpz_t * dest, mpz_t * src1, mpz_t * src2) {
784      mpz_add(*dest, *src1, *src2 );
785 }
786 
Rmpz_add_ui(mpz_t * dest,mpz_t * src,unsigned long num)787 void Rmpz_add_ui(mpz_t * dest, mpz_t * src, unsigned long num) {
788      mpz_add_ui(*dest, *src, num);
789 /*     return sv_setref_pv(newSViv(0), Nullch, INT2PTR(mpz_t *, SvIVX(SvRV(dest)))); */
790 }
791 
Rmpz_sub(mpz_t * dest,mpz_t * src1,mpz_t * src2)792 void Rmpz_sub(mpz_t * dest, mpz_t * src1, mpz_t * src2) {
793      mpz_sub(*dest, *src1, *src2 );
794 }
795 
Rmpz_sub_ui(mpz_t * dest,mpz_t * src,unsigned long num)796 void Rmpz_sub_ui(mpz_t * dest, mpz_t * src, unsigned long num) {
797      mpz_sub_ui(*dest, *src, num);
798 }
799 
Rmpz_ui_sub(mpz_t * dest,unsigned long num,mpz_t * src)800 void Rmpz_ui_sub(mpz_t * dest, unsigned long num, mpz_t * src) {
801      mpz_ui_sub(*dest, num, *src);
802 }
803 
Rmpz_mul(mpz_t * dest,mpz_t * src1,mpz_t * src2)804 void Rmpz_mul(mpz_t * dest, mpz_t * src1, mpz_t * src2) {
805      mpz_mul(*dest, *src1, *src2 );
806 }
807 
Rmpz_mul_si(mpz_t * dest,mpz_t * src,long num)808 void Rmpz_mul_si(mpz_t * dest, mpz_t * src, long num) {
809      mpz_mul_si(*dest, *src, num);
810 }
811 
812 /* NOT TO BE USED
813 void overload_mul_expt(SV * op, SV * iv, SV * unused) {
814      mpz_mul_si(*(INT2PTR(mpz_t *, SvIVX(SvRV(op)))),
815                 *(INT2PTR(mpz_t *, SvIVX(SvRV(op)))),
816                 SvIV(iv));
817 }
818 */
819 
Rmpz_mul_ui(mpz_t * dest,mpz_t * src,unsigned long num)820 void Rmpz_mul_ui(mpz_t * dest, mpz_t * src, unsigned long num) {
821      mpz_mul_ui(*dest, *src, num);
822 }
823 
Rmpz_addmul(mpz_t * dest,mpz_t * src1,mpz_t * src2)824 void Rmpz_addmul(mpz_t * dest, mpz_t * src1, mpz_t * src2) {
825      mpz_addmul(*dest, *src1, *src2 );
826 }
827 
Rmpz_addmul_ui(mpz_t * dest,mpz_t * src,unsigned long num)828 void Rmpz_addmul_ui(mpz_t * dest, mpz_t * src, unsigned long num) {
829      mpz_addmul_ui(*dest, *src, num);
830 }
831 
Rmpz_submul(mpz_t * dest,mpz_t * src1,mpz_t * src2)832 void Rmpz_submul(mpz_t * dest, mpz_t * src1, mpz_t * src2) {
833      mpz_submul(*dest, *src1, *src2 );
834 }
835 
Rmpz_submul_ui(mpz_t * dest,mpz_t * src,unsigned long num)836 void Rmpz_submul_ui(mpz_t * dest, mpz_t * src, unsigned long num) {
837      mpz_submul_ui(*dest, *src, num);
838 }
839 
Rmpz_mul_2exp(pTHX_ mpz_t * dest,mpz_t * src1,SV * b)840 void Rmpz_mul_2exp(pTHX_ mpz_t * dest, mpz_t * src1, SV * b) {
841 
842      CHECK_MP_BITCNT_T_OVERFLOW(b)
843 
844      mpz_mul_2exp(*dest, *src1, (mp_bitcnt_t)SvUVX(b));
845 }
846 
Rmpz_div_2exp(pTHX_ mpz_t * dest,mpz_t * src1,SV * b)847 void Rmpz_div_2exp(pTHX_ mpz_t * dest, mpz_t * src1, SV * b) {
848 
849      CHECK_MP_BITCNT_T_OVERFLOW(b)
850 
851      mpz_div_2exp(*dest, *src1, (mp_bitcnt_t)SvUVX(b));
852 }
853 
Rmpz_neg(mpz_t * dest,mpz_t * src)854 void Rmpz_neg(mpz_t * dest, mpz_t * src) {
855      mpz_neg(*dest, *src );
856 }
857 
Rmpz_abs(mpz_t * dest,mpz_t * src)858 void Rmpz_abs(mpz_t * dest, mpz_t * src) {
859      mpz_abs(*dest, *src );
860 }
861 
Rmpz_cdiv_q(mpz_t * q,mpz_t * n,mpz_t * d)862 void Rmpz_cdiv_q( mpz_t * q, mpz_t *  n, mpz_t * d) {
863      if(!mpz_cmp_ui(*d, 0))
864        croak("Division by 0 not allowed in Rmpz_cdiv_q");
865      mpz_cdiv_q(*q, *n, *d);
866 }
867 
Rmpz_cdiv_r(mpz_t * mod,mpz_t * n,mpz_t * d)868 void Rmpz_cdiv_r( mpz_t * mod, mpz_t *  n, mpz_t * d) {
869      if(!mpz_cmp_ui(*d, 0))
870        croak("Division by 0 not allowed in Rmpz_cdiv_r");
871      mpz_cdiv_r(*mod, *n, *d);
872 }
873 
Rmpz_cdiv_qr(mpz_t * q,mpz_t * r,mpz_t * n,mpz_t * d)874 void Rmpz_cdiv_qr( mpz_t * q, mpz_t * r, mpz_t *  n, mpz_t * d) {
875      if(!mpz_cmp_ui(*d, 0))
876        croak("Division by 0 not allowed in Rmpz_cdiv_qr");
877      mpz_cdiv_qr(*q, *r, *n, *d);
878 }
879 
Rmpz_cdiv_q_ui(mpz_t * q,mpz_t * n,unsigned long d)880 unsigned long Rmpz_cdiv_q_ui( mpz_t * q, mpz_t *  n, unsigned long d) {
881      if(d == 0)
882        croak("Division by 0 not allowed in Rmpz_cdiv_q_ui");
883      return mpz_cdiv_q_ui(*q, *n, d);
884 }
885 
Rmpz_cdiv_r_ui(mpz_t * q,mpz_t * n,unsigned long d)886 unsigned long Rmpz_cdiv_r_ui( mpz_t * q, mpz_t *  n, unsigned long d) {
887      if(d == 0)
888        croak("Division by 0 not allowed in Rmpz_cdiv_r_ui");
889      return mpz_cdiv_r_ui(*q, *n, d);
890 }
891 
Rmpz_cdiv_qr_ui(mpz_t * q,mpz_t * r,mpz_t * n,unsigned long d)892 unsigned long Rmpz_cdiv_qr_ui( mpz_t * q, mpz_t * r, mpz_t *  n, unsigned long d) {
893      if(d == 0)
894        croak("Division by 0 not allowed in Rmpz_cdiv_qr_ui");
895      return mpz_cdiv_qr_ui(*q, *r, *n, d);
896 }
897 
Rmpz_cdiv_ui(mpz_t * n,unsigned long d)898 unsigned long Rmpz_cdiv_ui( mpz_t *  n, unsigned long d) {
899      if(d == 0)
900        croak("Division by 0 not allowed in Rmpz_cdiv_ui");
901      return mpz_cdiv_ui(*n, d);
902 }
903 
Rmpz_cdiv_q_2exp(pTHX_ mpz_t * q,mpz_t * n,SV * b)904 void Rmpz_cdiv_q_2exp(pTHX_  mpz_t * q, mpz_t *  n, SV * b) {
905 
906      CHECK_MP_BITCNT_T_OVERFLOW(b)
907 
908      mpz_cdiv_q_2exp(*q, *n, (mp_bitcnt_t)SvUVX(b));
909 }
910 
Rmpz_cdiv_r_2exp(pTHX_ mpz_t * r,mpz_t * n,SV * b)911 void Rmpz_cdiv_r_2exp(pTHX_  mpz_t * r, mpz_t *  n, SV * b) {
912 
913      CHECK_MP_BITCNT_T_OVERFLOW(b)
914 
915      mpz_cdiv_r_2exp(*r, *n, (mp_bitcnt_t)SvUVX(b));
916 }
917 
Rmpz_fdiv_q(mpz_t * q,mpz_t * n,mpz_t * d)918 void Rmpz_fdiv_q( mpz_t * q, mpz_t *  n, mpz_t * d) {
919      if(!mpz_cmp_ui(*d, 0))
920        croak("Division by 0 not allowed in Rmpz_fdiv_q");
921      mpz_fdiv_q(*q, *n, *d);
922 }
923 
Rmpz_div(mpz_t * q,mpz_t * n,mpz_t * d)924 void Rmpz_div( mpz_t * q, mpz_t *  n, mpz_t * d) {
925      if(!mpz_cmp_ui(*d, 0))
926        croak("Division by 0 not allowed in Rmpz_div");
927      mpz_div(*q, *n, *d);
928 }
929 
930 /* % mpz-t (modulus) operator */
Rmpz_fdiv_r(mpz_t * mod,mpz_t * n,mpz_t * d)931 void Rmpz_fdiv_r( mpz_t * mod, mpz_t *  n, mpz_t * d) {
932      if(!mpz_cmp_ui(*d, 0))
933        croak("Division by 0 not allowed in Rmpz_fdiv_r");
934      mpz_fdiv_r(*mod, *n, *d);
935 }
936 
Rmpz_fdiv_qr(mpz_t * q,mpz_t * r,mpz_t * n,mpz_t * d)937 void Rmpz_fdiv_qr( mpz_t * q, mpz_t * r, mpz_t *  n, mpz_t * d) {
938      if(!mpz_cmp_ui(*d, 0))
939        croak("Division by 0 not allowed in Rmpz_fdiv_qr");
940      mpz_fdiv_qr(*q, *r, *n, *d);
941 }
942 
Rmpz_divmod(mpz_t * q,mpz_t * r,mpz_t * n,mpz_t * d)943 void Rmpz_divmod( mpz_t * q, mpz_t * r, mpz_t *  n, mpz_t * d) {
944      if(!mpz_cmp_ui(*d, 0))
945        croak("Division by 0 not allowed in Rmpz_divmod");
946      mpz_divmod(*q, *r, *n, *d);
947 }
948 
Rmpz_fdiv_q_ui(mpz_t * q,mpz_t * n,unsigned long d)949 unsigned long Rmpz_fdiv_q_ui( mpz_t * q, mpz_t *  n, unsigned long d) {
950      if(d == 0)
951        croak("Division by 0 not allowed in Rmpz_fdiv_q_ui");
952      return mpz_fdiv_q_ui(*q, *n, d);
953 }
954 
Rmpz_div_ui(mpz_t * q,mpz_t * n,unsigned long d)955 unsigned long Rmpz_div_ui( mpz_t * q, mpz_t *  n, unsigned long d) {
956      if(d == 0)
957        croak("Division by 0 not allowed in Rmpz_div_ui");
958      return mpz_div_ui(*q, *n, d);
959 }
960 
Rmpz_fdiv_r_ui(mpz_t * q,mpz_t * n,unsigned long d)961 unsigned long Rmpz_fdiv_r_ui( mpz_t * q, mpz_t *  n, unsigned long d) {
962      if(d == 0)
963        croak("Division by 0 not allowed in Rmpz_fdiv_r_ui");
964      return mpz_fdiv_r_ui(*q, *n, d);
965 }
966 
Rmpz_fdiv_qr_ui(mpz_t * q,mpz_t * r,mpz_t * n,unsigned long d)967 unsigned long Rmpz_fdiv_qr_ui( mpz_t * q, mpz_t * r, mpz_t *  n, unsigned long d) {
968      if(d == 0)
969        croak("Division by 0 not allowed in Rmpz_fdiv_qr_ui");
970      return mpz_fdiv_qr_ui(*q, *r, *n, d);
971 }
972 
Rmpz_divmod_ui(mpz_t * q,mpz_t * r,mpz_t * n,unsigned long d)973 unsigned long Rmpz_divmod_ui( mpz_t * q, mpz_t * r, mpz_t *  n, unsigned long d) {
974      if(d == 0)
975        croak("Division by 0 not allowed in Rmpz_divmod_ui");
976      return mpz_divmod_ui(*q, *r, *n, d);
977 }
978 
979 /* % int (modulus) operator */
Rmpz_fdiv_ui(mpz_t * n,unsigned long d)980 unsigned long Rmpz_fdiv_ui( mpz_t *  n, unsigned long d) {
981      if(d == 0)
982        croak("Division by 0 not allowed in Rmpz_fdiv_ui");
983      return mpz_fdiv_ui(*n, d);
984 }
985 
Rmpz_fdiv_q_2exp(pTHX_ mpz_t * q,mpz_t * n,SV * b)986 void Rmpz_fdiv_q_2exp(pTHX_  mpz_t * q, mpz_t *  n, SV * b) {
987 
988      CHECK_MP_BITCNT_T_OVERFLOW(b)
989 
990      mpz_fdiv_q_2exp(*q, *n, (mp_bitcnt_t)SvUVX(b));
991 }
992 
Rmpz_fdiv_r_2exp(pTHX_ mpz_t * r,mpz_t * n,SV * b)993 void Rmpz_fdiv_r_2exp(pTHX_  mpz_t * r, mpz_t *  n, SV * b) {
994 
995      CHECK_MP_BITCNT_T_OVERFLOW(b)
996 
997      mpz_fdiv_r_2exp(*r, *n, (mp_bitcnt_t)SvUVX(b));
998 }
999 
Rmpz_mod_2exp(pTHX_ mpz_t * r,mpz_t * n,SV * b)1000 void Rmpz_mod_2exp(pTHX_  mpz_t * r, mpz_t *  n, SV * b) {
1001 
1002      CHECK_MP_BITCNT_T_OVERFLOW(b)
1003 
1004      mpz_mod_2exp(*r, *n, (mp_bitcnt_t)SvUVX(b));
1005 }
1006 
Rmpz_tdiv_q(mpz_t * q,mpz_t * n,mpz_t * d)1007 void Rmpz_tdiv_q( mpz_t * q, mpz_t *  n, mpz_t * d) {
1008      if(!mpz_cmp_ui(*d, 0))
1009        croak("Division by 0 not allowed in Rmpz_tdiv_q");
1010      mpz_tdiv_q(*q, *n, *d);
1011 }
1012 
1013 /* % mpz-t (modulus) operator */
Rmpz_tdiv_r(mpz_t * mod,mpz_t * n,mpz_t * d)1014 void Rmpz_tdiv_r( mpz_t * mod, mpz_t *  n, mpz_t * d) {
1015      if(!mpz_cmp_ui(*d, 0))
1016        croak("Division by 0 not allowed in Rmpz_tdiv_r");
1017      mpz_tdiv_r(*mod, *n, *d);
1018 }
1019 
Rmpz_tdiv_qr(mpz_t * q,mpz_t * r,mpz_t * n,mpz_t * d)1020 void Rmpz_tdiv_qr( mpz_t * q, mpz_t * r, mpz_t *  n, mpz_t * d) {
1021      if(!mpz_cmp_ui(*d, 0))
1022        croak("Division by 0 not allowed in Rmpz_tdiv_qr");
1023      mpz_tdiv_qr(*q, *r, *n, *d);
1024 }
1025 
Rmpz_tdiv_q_ui(mpz_t * q,mpz_t * n,unsigned long d)1026 unsigned long Rmpz_tdiv_q_ui( mpz_t * q, mpz_t *  n, unsigned long d) {
1027      if(d == 0)
1028        croak("Division by 0 not allowed in Rmpz_tdiv_q_ui");
1029      return mpz_tdiv_q_ui(*q, *n, d);
1030 }
1031 
Rmpz_tdiv_r_ui(mpz_t * q,mpz_t * n,unsigned long d)1032 unsigned long Rmpz_tdiv_r_ui( mpz_t * q, mpz_t *  n, unsigned long d) {
1033      if(d == 0)
1034        croak("Division by 0 not allowed in Rmpz_tdiv_r_ui");
1035      return mpz_tdiv_r_ui(*q, *n, d);
1036 }
1037 
Rmpz_tdiv_qr_ui(mpz_t * q,mpz_t * r,mpz_t * n,unsigned long d)1038 unsigned long Rmpz_tdiv_qr_ui( mpz_t * q, mpz_t * r, mpz_t *  n, unsigned long d) {
1039      if(d == 0)
1040        croak("Division by 0 not allowed in Rmpz_tdiv_qr_ui");
1041      return mpz_tdiv_qr_ui(*q, *r, *n, d);
1042 }
1043 
1044 /* % int (modulus) operator */
Rmpz_tdiv_ui(mpz_t * n,unsigned long d)1045 unsigned long Rmpz_tdiv_ui( mpz_t *  n, unsigned long d) {
1046      if(d == 0)
1047        croak("Division by 0 not allowed in Rmpz_tdiv_ui");
1048      return mpz_tdiv_ui(*n, d);
1049 }
1050 
Rmpz_tdiv_q_2exp(pTHX_ mpz_t * q,mpz_t * n,SV * b)1051 void Rmpz_tdiv_q_2exp(pTHX_  mpz_t * q, mpz_t *  n, SV * b) {
1052 
1053      CHECK_MP_BITCNT_T_OVERFLOW(b)
1054 
1055      mpz_tdiv_q_2exp(*q, *n, (mp_bitcnt_t)SvUVX(b));
1056 }
1057 
Rmpz_tdiv_r_2exp(pTHX_ mpz_t * r,mpz_t * n,SV * b)1058 void Rmpz_tdiv_r_2exp(pTHX_  mpz_t * r, mpz_t *  n, SV * b) {
1059 
1060      CHECK_MP_BITCNT_T_OVERFLOW(b)
1061 
1062      mpz_tdiv_r_2exp(*r, *n, (mp_bitcnt_t)SvUVX(b));
1063 }
1064 
Rmpz_mod(mpz_t * r,mpz_t * n,mpz_t * d)1065 void Rmpz_mod( mpz_t * r, mpz_t *  n, mpz_t * d) {
1066      if(!mpz_cmp_ui(*d, 0))
1067        croak("Division by 0 not allowed in Rmpz_mod");
1068      mpz_mod(*r, *n, *d);
1069 }
1070 
Rmpz_mod_ui(mpz_t * r,mpz_t * n,unsigned long d)1071 unsigned long Rmpz_mod_ui( mpz_t * r, mpz_t *  n, unsigned long d) {
1072      if(d == 0)
1073        croak("Division by 0 not allowed in Rmpz_mod_ui");
1074      return mpz_mod_ui(*r, *n, d);
1075 }
1076 
Rmpz_divexact(mpz_t * dest,mpz_t * n,mpz_t * d)1077 void Rmpz_divexact(mpz_t * dest, mpz_t * n, mpz_t * d) {
1078      if(!mpz_cmp_ui(*d, 0))
1079        croak("Division by 0 not allowed in Rmpz_divexact");
1080      mpz_divexact(*dest, *n, *d );
1081 }
1082 
Rmpz_divexact_ui(mpz_t * dest,mpz_t * n,unsigned long d)1083 void Rmpz_divexact_ui(mpz_t * dest, mpz_t * n, unsigned long d) {
1084      if(d == 0)
1085        croak("Division by 0 not allowed in Rmpz_divexact_ui");
1086      mpz_divexact_ui(*dest, *n, d);
1087 }
1088 
Rmpz_divisible_p(mpz_t * n,mpz_t * d)1089 int Rmpz_divisible_p(mpz_t * n, mpz_t * d) {
1090     return mpz_divisible_p(*n, *d);
1091 }
1092 
Rmpz_divisible_ui_p(mpz_t * n,unsigned long d)1093 int Rmpz_divisible_ui_p(mpz_t * n, unsigned long d) {
1094      return mpz_divisible_ui_p(*n, d);
1095 }
1096 
Rmpz_divisible_2exp_p(pTHX_ mpz_t * n,SV * b)1097 int Rmpz_divisible_2exp_p(pTHX_ mpz_t * n, SV * b) {
1098 
1099      CHECK_MP_BITCNT_T_OVERFLOW(b)
1100 
1101      return mpz_divisible_2exp_p(*n, SvUVX(b));
1102 }
1103 
Rmpz_congruent_p(mpz_t * n,mpz_t * c,mpz_t * d)1104 int Rmpz_congruent_p(mpz_t * n, mpz_t * c, mpz_t * d) {
1105      return mpz_congruent_p(*n, *c, *d);
1106 }
1107 
Rmpz_congruent_ui_p(mpz_t * n,unsigned long c,unsigned long d)1108 int Rmpz_congruent_ui_p(mpz_t * n, unsigned long c, unsigned long d) {
1109      return mpz_congruent_ui_p(*n, c, d);
1110 }
1111 
Rmpz_congruent_2exp_p(pTHX_ mpz_t * n,mpz_t * c,SV * d)1112 SV * Rmpz_congruent_2exp_p(pTHX_ mpz_t * n, mpz_t * c, SV * d) {
1113 
1114      CHECK_MP_BITCNT_T_OVERFLOW(d)
1115 
1116      return newSViv(mpz_congruent_2exp_p(*n, *c, SvUVX(d)));
1117 }
1118 
Rmpz_powm(mpz_t * dest,mpz_t * base,mpz_t * exp,mpz_t * mod)1119 void Rmpz_powm(mpz_t * dest, mpz_t * base, mpz_t * exp, mpz_t * mod) {
1120      mpz_powm(*dest, *base, *exp, *mod);
1121 }
1122 
Rmpz_powm_ui(mpz_t * dest,mpz_t * base,unsigned long exp,mpz_t * mod)1123 void Rmpz_powm_ui(mpz_t * dest, mpz_t * base, unsigned long exp, mpz_t * mod) {
1124      mpz_powm_ui(*dest, *base, exp, *mod);
1125 }
1126 
Rmpz_pow_ui(mpz_t * dest,mpz_t * base,unsigned long exp)1127 void Rmpz_pow_ui(mpz_t * dest, mpz_t * base, unsigned long exp) {
1128      mpz_pow_ui(*dest, *base, exp);
1129 }
1130 
Rmpz_ui_pow_ui(mpz_t * dest,unsigned long base,unsigned long exp)1131 void Rmpz_ui_pow_ui(mpz_t * dest, unsigned long base, unsigned long exp) {
1132      mpz_ui_pow_ui(*dest, base, exp);
1133 }
1134 
Rmpz_root(mpz_t * r,mpz_t * n,unsigned long d)1135 int Rmpz_root(mpz_t * r, mpz_t * n, unsigned long d) {
1136      return mpz_root(*r, *n, d);
1137 }
1138 
Rmpz_sqrt(mpz_t * r,mpz_t * n)1139 void Rmpz_sqrt(mpz_t * r, mpz_t * n) {
1140      mpz_sqrt(*r, *n);
1141 }
1142 
Rmpz_sqrtrem(mpz_t * root,mpz_t * rem,mpz_t * src)1143 void Rmpz_sqrtrem(mpz_t * root, mpz_t * rem, mpz_t * src) {
1144      mpz_sqrtrem(*root, *rem, *src);
1145 }
1146 
Rmpz_perfect_power_p(mpz_t * in)1147 int Rmpz_perfect_power_p(mpz_t * in) {
1148     return mpz_perfect_power_p(*in);
1149 }
1150 
Rmpz_perfect_square_p(mpz_t * in)1151 int Rmpz_perfect_square_p(mpz_t * in) {
1152     return mpz_perfect_square_p(*in);
1153 }
1154 
Rmpz_probab_prime_p(pTHX_ mpz_t * cand,SV * reps)1155 int Rmpz_probab_prime_p(pTHX_ mpz_t * cand, SV * reps) {
1156      return mpz_probab_prime_p(*cand, (int)SvIV(reps));
1157 }
1158 
Rmpz_nextprime(mpz_t * prime,mpz_t * init)1159 void Rmpz_nextprime(mpz_t * prime, mpz_t * init) {
1160      mpz_nextprime(*prime, *init);
1161 }
1162 
Rmpz_gcd(mpz_t * gcd,mpz_t * src1,mpz_t * src2)1163 void Rmpz_gcd(mpz_t * gcd, mpz_t * src1, mpz_t * src2) {
1164      mpz_gcd(*gcd, *src1, *src2);
1165 }
1166 
1167 /* First arg can be either (the unblessed) $Math::GMPz::NULL or a
1168  * (blessed) Math::GMPz object.
1169  */
Rmpz_gcd_ui(mpz_t * gcd,mpz_t * n,unsigned long d)1170 unsigned long Rmpz_gcd_ui(mpz_t * gcd, mpz_t * n, unsigned long d) {
1171      return mpz_gcd_ui(*gcd, *n, d);
1172 }
1173 
Rmpz_gcdext(mpz_t * g,mpz_t * s,mpz_t * t,mpz_t * a,mpz_t * b)1174 void Rmpz_gcdext(mpz_t * g, mpz_t * s, mpz_t * t, mpz_t * a, mpz_t * b) {
1175      mpz_gcdext(*g, *s, *t, *a, *b);
1176 }
1177 
Rmpz_lcm(mpz_t * lcm,mpz_t * src1,mpz_t * src2)1178 void Rmpz_lcm(mpz_t * lcm, mpz_t * src1, mpz_t * src2) {
1179      mpz_lcm(*lcm, *src1, *src2);
1180 }
1181 
Rmpz_lcm_ui(mpz_t * lcm,mpz_t * src1,unsigned long src2)1182 void Rmpz_lcm_ui(mpz_t * lcm, mpz_t * src1, unsigned long src2) {
1183      mpz_lcm_ui(*lcm, *src1, src2);
1184 }
1185 
Rmpz_invert(mpz_t * inv,mpz_t * src1,mpz_t * src2)1186 int Rmpz_invert(mpz_t * inv, mpz_t * src1, mpz_t * src2) {
1187     return mpz_invert(*inv, *src1, *src2);
1188 }
1189 
Rmpz_jacobi(mpz_t * a,mpz_t * b)1190 int Rmpz_jacobi(mpz_t * a, mpz_t * b) {
1191     return mpz_jacobi(*a, *b);
1192 }
1193 
Rmpz_legendre(mpz_t * a,mpz_t * b)1194 int Rmpz_legendre(mpz_t * a, mpz_t * b) {
1195     return mpz_legendre(*a, *b);
1196 }
1197 
Rmpz_kronecker(mpz_t * a,mpz_t * b)1198 int Rmpz_kronecker(mpz_t * a, mpz_t * b) {
1199     return mpz_kronecker(*a, *b);
1200 }
1201 
Rmpz_kronecker_si(mpz_t * a,long b)1202 int Rmpz_kronecker_si(mpz_t * a, long b) {
1203      return mpz_kronecker_si(*a, b);
1204 }
1205 
Rmpz_kronecker_ui(mpz_t * a,unsigned long b)1206 int Rmpz_kronecker_ui(mpz_t * a, unsigned long b) {
1207      return mpz_kronecker_ui(*a, b);
1208 }
1209 
Rmpz_si_kronecker(long a,mpz_t * b)1210 int Rmpz_si_kronecker(long a, mpz_t * b) {
1211      return mpz_si_kronecker(a, *b);
1212 }
1213 
Rmpz_ui_kronecker(unsigned long a,mpz_t * b)1214 int Rmpz_ui_kronecker(unsigned long a, mpz_t * b) {
1215      return mpz_ui_kronecker(a, *b);
1216 }
1217 
Rmpz_remove(pTHX_ mpz_t * rem,mpz_t * src1,mpz_t * src2)1218 SV * Rmpz_remove(pTHX_ mpz_t * rem, mpz_t * src1, mpz_t * src2) {
1219      return newSVuv(mpz_remove(*rem, *src1, *src2));
1220 }
1221 
Rmpz_fac_ui(mpz_t * fac,unsigned long b)1222 void Rmpz_fac_ui(mpz_t * fac, unsigned long b) {
1223      mpz_fac_ui(*fac, b);
1224 }
1225 
1226 #if __GNU_MP_VERSION > 5 || (__GNU_MP_VERSION == 5 && __GNU_MP_VERSION_MINOR >= 1)
1227 
Rmpz_2fac_ui(mpz_t * fac,unsigned long b)1228 void Rmpz_2fac_ui(mpz_t * fac, unsigned long b) {
1229      mpz_2fac_ui(*fac, b);
1230 }
1231 
Rmpz_mfac_uiui(mpz_t * fac,unsigned long b,unsigned long c)1232 void Rmpz_mfac_uiui(mpz_t * fac, unsigned long b, unsigned long c) {
1233      mpz_mfac_uiui(*fac, b, c);
1234 }
1235 
Rmpz_primorial_ui(mpz_t * fac,unsigned long b)1236 void Rmpz_primorial_ui(mpz_t * fac, unsigned long b) {
1237      mpz_primorial_ui(*fac, b);
1238 }
1239 
1240 #else
1241 
Rmpz_2fac_ui(mpz_t * fac,unsigned long b)1242 void Rmpz_2fac_ui(mpz_t * fac, unsigned long b) {
1243      croak("Rmpz_2fac_ui not implemented - gmp-5.1.0 (or later) is needed");
1244 }
1245 
Rmpz_mfac_uiui(mpz_t * fac,unsigned long b,unsigned long c)1246 void Rmpz_mfac_uiui(mpz_t * fac, unsigned long b, unsigned long c) {
1247      croak("Rmpz_mfac_uiui not implemented - gmp-5.1.0 (or later) is needed");
1248 }
1249 
Rmpz_primorial_ui(mpz_t * fac,unsigned long b)1250 void Rmpz_primorial_ui(mpz_t * fac, unsigned long b) {
1251      croak("Rmpz_primorial_ui not implemented - gmp-5.1.0 (or later) is needed");
1252 }
1253 
1254 #endif
1255 
Rmpz_bin_ui(mpz_t * dest,mpz_t * n,unsigned long d)1256 void Rmpz_bin_ui(mpz_t * dest, mpz_t * n, unsigned long d) {
1257      mpz_bin_ui(*dest, *n, d);
1258 }
1259 
Rmpz_bin_si(mpz_t * dest,mpz_t * n,long d)1260 void Rmpz_bin_si(mpz_t * dest, mpz_t * n, long d) {
1261      signed long int t = d;
1262      if(t >= 0) mpz_bin_ui(*dest, *n, t);
1263      else {
1264        if(mpz_sgn(*n) >= 0 || mpz_cmp_si(*n, t) < 0)
1265          mpz_set_ui(*dest, 0);
1266        else
1267          mpz_bin_ui(*dest, *n, mpz_get_si(*n) - t);
1268      }
1269 }
1270 
Rmpz_bin_uiui(mpz_t * dest,unsigned long n,unsigned long d)1271 void Rmpz_bin_uiui(mpz_t * dest, unsigned long n, unsigned long d) {
1272      mpz_bin_uiui(*dest, n, d);
1273 }
1274 
Rmpz_fib_ui(mpz_t * dest,unsigned long b)1275 void Rmpz_fib_ui(mpz_t * dest, unsigned long b) {
1276      mpz_fib_ui(*dest, b);
1277 }
1278 
Rmpz_fib2_ui(mpz_t * fn,mpz_t * fnsub1,unsigned long b)1279 void Rmpz_fib2_ui(mpz_t * fn, mpz_t * fnsub1, unsigned long b) {
1280      mpz_fib2_ui(*fn, *fnsub1, b);
1281 }
1282 
Rmpz_lucnum_ui(mpz_t * dest,unsigned long b)1283 void Rmpz_lucnum_ui(mpz_t * dest, unsigned long b) {
1284      mpz_lucnum_ui(*dest, b);
1285 }
1286 
Rmpz_lucnum2_ui(mpz_t * ln,mpz_t * lnsub1,unsigned long b)1287 void Rmpz_lucnum2_ui(mpz_t * ln, mpz_t * lnsub1, unsigned long b) {
1288      mpz_lucnum2_ui(*ln, *lnsub1, b);
1289 }
1290 
Rmpz_cmp(mpz_t * n,mpz_t * d)1291 int Rmpz_cmp(mpz_t * n, mpz_t * d) {
1292     return mpz_cmp(*n, *d );
1293 }
1294 
Rmpz_cmp_d(mpz_t * n,double d)1295 int Rmpz_cmp_d(mpz_t * n, double d) {
1296     if(d != d) croak("In Rmpz_cmp_d, cannot compare a NaN to a Math::GMPz value");
1297     return mpz_cmp_d(*n, d);
1298 }
1299 
Rmpz_cmp_NV(pTHX_ mpz_t * a,SV * b)1300 int Rmpz_cmp_NV(pTHX_ mpz_t * a, SV * b) {
1301 
1302 #if defined(USE_QUADMATH)
1303 
1304      char * buffer;
1305      int ret, returned;
1306      __float128 buffer_size;
1307      __float128 ld;
1308      mpz_t t;
1309 
1310      if(!SvNOK(b))
1311        croak("In Rmpz_cmp_NV, 2nd argument is not an NV");
1312 
1313      ld = (__float128)SvNV(b) >= 0 ? floorq((__float128)SvNV(b)) : ceilq((__float128)SvNV(b));
1314      if(ld != ld) croak("In Rmpz_cmp_NV, cannot compare a NaN to a Math::GMPz value");
1315      if((ld != 0 && (ld / ld != 1))) {
1316        if(ld > 0) return -1;
1317        return 1;
1318      }
1319      buffer_size = ld < 0.0Q ? ld * -1.0Q : ld;
1320      buffer_size = ceilq(logq(buffer_size + 1) / 2.30258509299404568401799145468436418Q);
1321      Newxz(buffer, (int)buffer_size + 5, char);
1322 
1323      returned = quadmath_snprintf(buffer, (size_t)buffer_size + 5, "%.0Qf", ld);
1324      if(returned < 0) croak("In Rmpz_cmp_NV, encoding error in quadmath_snprintf function");
1325      if(returned >= buffer_size + 5) croak("In Rmpz_cmp_NV, buffer given to quadmath_snprintf function was too small");
1326      mpz_init_set_str(t, buffer, 10);
1327      Safefree(buffer);
1328      ret = mpz_cmp(*a, t);
1329      mpz_clear(t);
1330 
1331      if(ld == (__float128)SvNV(b)) return ret;
1332      /* else cannot be equal - ie must be less than or greater than */
1333      if(!ret) {
1334        if(ld >= 0) ret = -1;
1335        else ret = 1;
1336      }
1337 
1338      return ret;
1339 
1340 #elif defined(USE_LONG_DOUBLE)
1341      long double ld;
1342      int ret;
1343 
1344 # if defined(NV_IS_DOUBLEDOUBLE)
1345      mpf_t f, f_trunc;
1346      mpz_t z;
1347 
1348      if(!SvNOK(b))
1349        croak("In Rmpz_cmp_NV, 2nd argument is not an NV");
1350 
1351      ld = SvNV(b);
1352 
1353      if(ld != ld) croak("In Rmpz_cmp_NV, cannot compare a NaN to a Math::GMPz value");
1354      if((ld != 0 && (ld / ld != 1))) {
1355        if(ld > 0) return -1;
1356        return 1;
1357      }
1358 
1359      mpf_init2(f, 2098);
1360      mpf_init2(f_trunc, 2098);
1361      mpz_init(z);
1362 
1363      _mpf_set_dd(&f, b);
1364      mpf_trunc(f_trunc, f);
1365      mpz_set_f(z, f_trunc);
1366 
1367      ret = mpf_cmp(f, f_trunc);
1368 
1369      if(ret == 0) {
1370        ret = mpz_cmp(*a, z);
1371      }
1372      else if(ret > 0) {
1373        if(mpz_cmp(*a, z) <= 0) ret = -1;
1374      }
1375 
1376      else {
1377        if(mpz_cmp(*a, z) >= 0) ret = 1;
1378      }
1379 
1380      mpf_clear(f);
1381      mpf_clear(f_trunc);
1382      mpz_clear(z);
1383      return ret;
1384 
1385 # else
1386      char * buffer;
1387      long double buffer_size;
1388      mpz_t t;
1389 
1390      if(!SvNOK(b))
1391        croak("In Rmpz_cmp_NV, 2nd argument is not an NV");
1392 
1393      ld = SvNV(b);
1394 
1395      if(ld != ld) croak("In Rmpz_cmp_NV, cannot compare a NaN to a Math::GMPz value");
1396      if((ld != 0 && (ld / ld != 1))) {
1397        if(ld > 0) return -1;
1398        return 1;
1399      }
1400 
1401      ld = ld >= 0 ? floorl((long double)SvNV(b)) : ceill((long double)SvNV(b));
1402 
1403      buffer_size = ld < 0.0L ? ld * -1.0L : ld;
1404      buffer_size = ceill(logl(buffer_size + 1) / 2.30258509299404568401799145468436418L);
1405      Newxz(buffer, (int)buffer_size + 5, char);
1406 
1407      if(sprintf(buffer, "%.0Lf", ld) >= (int)buffer_size + 5) croak("In Rmpz_cmp_NV, buffer overflow in sprintf function");
1408      mpz_init_set_str(t, buffer, 10);
1409      Safefree(buffer);
1410      ret = mpz_cmp(*a, t);
1411      mpz_clear(t);
1412      if(ld == (long double)SvNV(b)) return ret;
1413      /* else cannot be equal - ie must be less than or greater than */
1414      if(!ret) {
1415        if(ld >= 0) ret = -1;
1416        else ret = 1;
1417      }
1418 
1419      return ret;
1420 
1421 #  endif
1422 
1423 #else
1424 
1425      if(!SvNOK(b))
1426        croak("In Rmpz_cmp_NV, 2nd argument is not an NV");
1427 
1428      if((double)SvNV(b) != (double)SvNV(b))
1429        croak("In Rmpz_cmp_NV, cannot compare a NaN to a Math::GMPz value");
1430 
1431      return mpz_cmp_d(*a, (double)SvNV(b));
1432 
1433 #endif
1434 
1435 }
1436 
Rmpz_cmp_si(mpz_t * n,long d)1437 int Rmpz_cmp_si(mpz_t * n, long d) {
1438     return mpz_cmp_si(*n, d);
1439 }
1440 
Rmpz_cmp_ui(mpz_t * n,unsigned long d)1441 int Rmpz_cmp_ui(mpz_t * n, unsigned long d) {
1442      return mpz_cmp_ui(*n, d);
1443 }
1444 
Rmpz_cmpabs(mpz_t * n,mpz_t * d)1445 int Rmpz_cmpabs(mpz_t * n, mpz_t * d) {
1446     return mpz_cmpabs(*n, *d );
1447 }
1448 
Rmpz_cmpabs_d(mpz_t * n,double d)1449 int Rmpz_cmpabs_d(mpz_t * n, double d) {
1450      return mpz_cmpabs_d(*n, d);
1451 }
1452 
Rmpz_cmpabs_ui(mpz_t * n,unsigned long d)1453 int Rmpz_cmpabs_ui(mpz_t * n, unsigned long d) {
1454      return mpz_cmpabs_ui(*n, d);
1455 }
1456 
Rmpz_sgn(mpz_t * n)1457 int Rmpz_sgn(mpz_t * n) {
1458     return mpz_sgn(*n);
1459 }
1460 
Rmpz_and(mpz_t * dest,mpz_t * src1,mpz_t * src2)1461 void Rmpz_and(mpz_t * dest, mpz_t * src1, mpz_t * src2) {
1462      mpz_and(*dest, *src1, *src2 );
1463 }
1464 
Rmpz_ior(mpz_t * dest,mpz_t * src1,mpz_t * src2)1465 void Rmpz_ior(mpz_t * dest, mpz_t * src1, mpz_t * src2) {
1466      mpz_ior(*dest, *src1, *src2 );
1467 }
1468 
Rmpz_xor(mpz_t * dest,mpz_t * src1,mpz_t * src2)1469 void Rmpz_xor(mpz_t * dest, mpz_t * src1, mpz_t * src2) {
1470      mpz_xor(*dest, *src1, *src2 );
1471 }
1472 
Rmpz_com(mpz_t * dest,mpz_t * src)1473 void Rmpz_com(mpz_t * dest, mpz_t * src) {
1474      mpz_com(*dest, *src );
1475 }
1476 
Rmpz_popcount(pTHX_ mpz_t * in)1477 SV * Rmpz_popcount(pTHX_ mpz_t * in) {
1478     return newSVuv(mpz_popcount(*in));
1479 }
1480 
Rmpz_hamdist(pTHX_ mpz_t * dest,mpz_t * src)1481 SV * Rmpz_hamdist(pTHX_ mpz_t * dest, mpz_t * src) {
1482      return newSVuv(mpz_hamdist(*dest, *src ));
1483 }
1484 
Rmpz_scan0(pTHX_ mpz_t * n,SV * start_bit)1485 SV * Rmpz_scan0(pTHX_ mpz_t * n, SV * start_bit) {
1486 
1487      CHECK_MP_BITCNT_T_OVERFLOW(start_bit)
1488 
1489     return newSVuv(mpz_scan0(*n, (mp_bitcnt_t)SvUV(start_bit)));
1490 }
1491 
Rmpz_scan1(pTHX_ mpz_t * n,SV * start_bit)1492 SV * Rmpz_scan1(pTHX_ mpz_t * n, SV * start_bit) {
1493 
1494      CHECK_MP_BITCNT_T_OVERFLOW(start_bit)
1495 
1496     return newSVuv(mpz_scan1(*n, (mp_bitcnt_t)SvUV(start_bit)));
1497 }
1498 
Rmpz_setbit(pTHX_ mpz_t * num,SV * bit_index)1499 void Rmpz_setbit(pTHX_ mpz_t * num, SV * bit_index) {
1500 
1501      CHECK_MP_BITCNT_T_OVERFLOW(bit_index)
1502 
1503      mpz_setbit(*num, (mp_bitcnt_t)SvUV(bit_index));
1504 }
1505 
Rmpz_clrbit(pTHX_ mpz_t * num,SV * bit_index)1506 void Rmpz_clrbit(pTHX_ mpz_t * num, SV * bit_index) {
1507 
1508      CHECK_MP_BITCNT_T_OVERFLOW(bit_index)
1509 
1510      mpz_clrbit(*num, (mp_bitcnt_t)SvUV(bit_index));
1511 }
1512 
Rmpz_tstbit(pTHX_ mpz_t * num,SV * bit_index)1513 SV * Rmpz_tstbit(pTHX_ mpz_t * num, SV * bit_index) {
1514 
1515      CHECK_MP_BITCNT_T_OVERFLOW(bit_index)
1516 
1517      return newSViv(mpz_tstbit(*num, (mp_bitcnt_t)SvUV(bit_index)));
1518 }
1519 
1520 /* Turn a binary string into an mpz_t */
Rmpz_import(pTHX_ mpz_t * rop,SV * count,SV * order,SV * size,SV * endian,SV * nails,SV * op)1521 void Rmpz_import(pTHX_ mpz_t * rop, SV * count, SV * order, SV * size, SV * endian, SV * nails, SV * op){
1522     int is_utf8 = 0;
1523 
1524     if(SvUTF8(op) && !SvIV(get_sv("Math::GMPz::utf8_no_downgrade", 0))) {
1525       if(!SvIV(get_sv("Math::GMPz::utf8_no_warn", 0))) {
1526         warn( "%s", RMPZ_IMPORT_UTF8_WARN ); /* RMPZ_IMPORT_UTF8_WARN defined in math_gmpz_include.h */
1527         warn("  To disable this warning set $Math::GMPz::utf8_no_warn to 1.");
1528       }
1529 
1530       is_utf8 = 1;
1531       if(!sv_utf8_downgrade(op, SvIV(get_sv("Math::GMPz::utf8_no_croak", 0)))) {
1532         /* downgrade has failed, and this will cause an immediate croak if     *
1533          * $Math::GMPz::utf8_no_croak is false. If $Math::GMPz::utf8_no_croak  *
1534          * is true && $Math::GMPz::utf8_no_fail is false, we warn as follows:  */
1535 
1536         if(!SvIV(get_sv("Math::GMPz::utf8_no_fail", 0))) {
1537           /* No need to check status of $Math::GMPz::utf8_no_croak. *
1538            * If we've reached here then it must be true.            */
1539           warn("%s", RMPZ_IMPORT_DOWNGRADE_WARN); /*RMPZ_IMPORT_DOWNGRADE_WARN defined in math_gmpz_include.h */
1540           warn("  To disable this warning set $Math::GMPz::utf8_no_fail to 1");
1541         }
1542       }
1543     }
1544 
1545     mpz_import(*rop, SvUV(count), SvIV(order), SvIV(size), SvIV(endian), SvUV(nails), SvPV_nolen(op));
1546     if(is_utf8) sv_utf8_upgrade(op);
1547 }
1548 
1549 /* Return an mpz_t to a binary string */
Rmpz_export(pTHX_ SV * order,SV * size,SV * endian,SV * nails,mpz_t * op)1550 SV * Rmpz_export(pTHX_ SV * order, SV * size, SV * endian, SV * nails, mpz_t * op) {
1551     SV * outsv;
1552     char * arr;
1553     int count;
1554     int numb = (8 * SvIV(size)) - SvUV(nails);
1555 
1556     count = (mpz_sizeinbase (*op, 2) + numb - 1) / numb;
1557 
1558     Newxz(arr, count, char);
1559     if(arr == NULL) croak("Couldn't allocate memory in Rmpz_export");
1560 
1561     mpz_export(arr, NULL, SvIV(order), SvIV(size), SvIV(endian), SvIV(nails), *op);
1562     outsv = newSVpv(arr, count);
1563     Safefree(arr);
1564     return outsv;
1565 }
1566 
1567 /* Turn an array of UVs into an mpz_t */
Rmpz_import_UV(pTHX_ mpz_t * rop,SV * count,SV * order,SV * size,SV * endian,SV * nails,AV * op)1568 void Rmpz_import_UV(pTHX_ mpz_t * rop, SV * count, SV * order, SV * size, SV * endian, SV * nails, AV * op){
1569     int len, i;
1570     UV * arr;
1571 
1572     len = av_len(op) + 1;
1573 
1574     Newxz(arr, len, UV);
1575     if(arr == NULL) croak("Couldn't allocate memory in Rmpz_import_UV");
1576 
1577     for(i = 0; i < len; i++) {
1578       arr[i] = SvUV(*(av_fetch(op, i, 0)));
1579     }
1580 
1581     mpz_import(*rop, SvUV(count), SvIV(order), SvIV(size), SvIV(endian), SvUV(nails), arr);
1582 
1583     Safefree(arr);
1584 }
1585 
1586 
1587 /* Return an mpz_t to an array of UVs */
Rmpz_export_UV(pTHX_ SV * order,SV * size,SV * endian,SV * nails,mpz_t * op)1588 void Rmpz_export_UV(pTHX_ SV * order, SV * size, SV * endian, SV * nails, mpz_t * op) {
1589     dXSARGS;
1590     UV * arr;
1591     int count, i;
1592     int numb = (8 * SvIV(size)) - SvUV(nails);
1593 
1594     count = (mpz_sizeinbase (*op, 2) + numb - 1) / numb;
1595 
1596     Newxz(arr, count, UV);
1597     if(arr == NULL) croak("Couldn't allocate memory in Rmpz_export_UV");
1598 
1599     mpz_export(arr, NULL, SvIV(order), SvIV(size), SvIV(endian), SvIV(nails), *op);
1600 
1601     sp = mark;
1602 
1603     for(i = 0; i < count; i++) {
1604       XPUSHs(sv_2mortal(newSVuv(arr[i])));
1605     }
1606 
1607     Safefree(arr);
1608     XSRETURN(count);
1609 }
1610 
Rmpz_fits_ulong_p(mpz_t * in)1611 int Rmpz_fits_ulong_p(mpz_t * in) {
1612     return mpz_fits_ulong_p(*in);
1613 }
1614 
Rmpz_fits_slong_p(mpz_t * in)1615 int Rmpz_fits_slong_p(mpz_t * in) {
1616     return mpz_fits_slong_p(*in);
1617 }
1618 
Rmpz_fits_uint_p(mpz_t * in)1619 int Rmpz_fits_uint_p(mpz_t * in) {
1620     return mpz_fits_uint_p(*in);
1621 }
1622 
Rmpz_fits_sint_p(mpz_t * in)1623 int Rmpz_fits_sint_p(mpz_t * in) {
1624     return mpz_fits_sint_p(*in);
1625 }
1626 
Rmpz_fits_ushort_p(mpz_t * in)1627 int Rmpz_fits_ushort_p(mpz_t * in) {
1628     return mpz_fits_ushort_p(*in);
1629 }
1630 
Rmpz_fits_sshort_p(mpz_t * in)1631 int Rmpz_fits_sshort_p(mpz_t * in) {
1632     return mpz_fits_sshort_p(*in);
1633 }
1634 
Rmpz_odd_p(mpz_t * in)1635 int Rmpz_odd_p(mpz_t * in) {
1636     return mpz_odd_p(*in);
1637 }
1638 
Rmpz_even_p(mpz_t * in)1639 int Rmpz_even_p(mpz_t * in) {
1640     return mpz_even_p(*in);
1641 }
1642 
Rmpz_size(pTHX_ mpz_t * in)1643 SV * Rmpz_size(pTHX_ mpz_t * in) {
1644     return newSVuv(mpz_size(*in));
1645 }
1646 
Rmpz_sizeinbase(pTHX_ mpz_t * in,int base)1647 SV * Rmpz_sizeinbase(pTHX_ mpz_t * in, int base) {
1648     if(base < 2 || base > 62) croak("Rmpz_sizeinbase handles only bases in the range 2..62");
1649     return newSVuv(mpz_sizeinbase(*in, base));
1650 }
1651 
Rsieve_gmp(pTHX_ int x_arg,int a,mpz_t * number)1652 void Rsieve_gmp(pTHX_ int x_arg, int a, mpz_t *number) {
1653 dXSARGS;
1654 unsigned short *v, *addon, set[16] = {65534,65533,65531,65527,65519,65503,65471,65407,65279,65023,64511,63487,61439,57343,49151,32767};
1655 unsigned long init, leap, abits, asize, i, size, b, imax, k, x = x_arg;
1656 
1657 if(sizeof(short) != 2) croak("The sieve_gmp function is unsuitable for this architecture.\nContact the author and he may do something about it.");
1658 if(a & 1) croak("max_add must be even in sieve_gmp function");
1659 if(x & 1) croak("max_prime must be even in sieve_gmp function");
1660 
1661 if(!mpz_tstbit(*number, 0)) croak("candidate must be odd in sieve_gmp function");
1662 
1663 abits = (a / 2) + 1;
1664 
1665 if(!(abits % 16)) asize = abits / 16;
1666 else asize = (abits / 16) + 1;
1667 
1668 Newz(1, addon, asize, unsigned short);
1669 if(addon == NULL) croak("1: Unable to allocate memory in sieve_gmp function");
1670 
1671 for(i = 0; i < asize; ++i) addon[i] = 65535;
1672 
1673 imax = sqrt(x - 1) / 2;
1674 
1675 b = (x + 1) / 2;
1676 
1677 if(!(b % 16)) size = b / 16;
1678 else size = (b / 16) + 1;
1679 
1680 Newz(2, v, size, unsigned short);
1681 if(v == NULL) croak("2: Unable to allocate memory in sieve_gmp function");
1682 
1683 for(i = 1; i < size; ++i) v[i] = 65535;
1684 v[0] = 65534;
1685 
1686 for(i = 0; i <= imax; ++i) {
1687 
1688     if(v[i / 16] & (1 << (i % 16))) {
1689        leap = (2 * i) + 1;
1690        k = 2 * i * (i + 1);
1691        while(k < b) {
1692              v[k / 16] &= set[k % 16];
1693              k += leap;
1694              }
1695        }
1696 }
1697 
1698 size = 0;
1699 sp = mark;
1700 
1701 for(i = 0; i < b; ++i) {
1702     if(v[i / 16] & (1 << (i % 16))) {
1703       leap = 2 * i + 1;
1704         init = mpz_fdiv_ui(*number, leap);
1705       if(init) {
1706         if(init & 1) init = (leap - init) / 2;
1707         else init = leap - (init / 2);
1708         }
1709       while(init < abits) {
1710          addon[init / 16] &= set[init % 16];
1711          init += leap;
1712          }
1713       }
1714    }
1715 
1716 Safefree(v);
1717 
1718 for(i = 0; i < abits; ++i) {
1719     if(addon[i / 16] & (1 << (i % 16))) {
1720       XPUSHs(sv_2mortal(newSViv(2 * i)));
1721       ++size;
1722       }
1723    }
1724 
1725 Safefree(addon);
1726 
1727 PUTBACK;
1728 XSRETURN(size);
1729 
1730 }
1731 
Rfermat_gmp(pTHX_ mpz_t * num,int base)1732 SV * Rfermat_gmp(pTHX_ mpz_t * num, int base){
1733      mpz_t b, num_less_1;
1734 
1735      mpz_init_set_ui(b, base);
1736      mpz_init_set(num_less_1, *num);
1737      mpz_sub_ui(num_less_1, num_less_1, 1);
1738      mpz_powm(b, b, num_less_1, *num);
1739 
1740      if(!mpz_cmp_si(b, 1)) {
1741         mpz_clear(b);
1742         mpz_clear(num_less_1);
1743         return newSViv(1);
1744      }
1745 
1746      mpz_clear(b);
1747      mpz_clear(num_less_1);
1748      return newSViv(0);
1749 }
1750 
Rrm_gmp(pTHX_ mpz_t * num,int base)1751 SV * Rrm_gmp(pTHX_ mpz_t * num, int base){
1752      mpz_t c_less, r, y, bb;
1753      unsigned long i, s = 0, b = base;
1754 
1755      mpz_init(c_less);
1756      mpz_init(r);
1757      mpz_init(y);
1758 
1759      mpz_sub_ui(c_less, *num, 1);
1760      mpz_set(r, c_less);
1761      mpz_init_set_ui(bb, b);
1762 
1763      while(mpz_even_p(r)) {
1764        mpz_tdiv_q_2exp(r, r, 1);
1765        ++s;
1766      }
1767 
1768      mpz_powm(y, bb, r, *num);
1769      mpz_clear(r);
1770      mpz_clear(bb);
1771      if(mpz_cmp_ui(y, 1) && mpz_cmp(y, c_less)) {
1772        for(i = 0; i < s; ++i) {
1773           mpz_powm_ui(y, y, 2, *num);
1774           if(!mpz_cmp_ui(y, 1)) {
1775              mpz_clear(c_less);
1776              mpz_clear(y);
1777              return 0;
1778           }
1779           if(!mpz_cmp(y, c_less)) break;
1780        }
1781        if(mpz_cmp(y, c_less)) {
1782          mpz_clear(c_less);
1783          mpz_clear(y);
1784          return newSViv(0);
1785        }
1786      }
1787 
1788      mpz_clear(c_less);
1789      mpz_clear(y);
1790      return newSVuv(1);
1791 }
1792 
_Rmpz_out_str(pTHX_ mpz_t * p,int base)1793 SV * _Rmpz_out_str(pTHX_ mpz_t * p, int base) {
1794      unsigned long ret;
1795      if((base > -2 && base < 2) || base < -36 || base > 62)
1796        croak("2nd argument supplied to Rmpz_out_str is out of allowable range (must be in range -36..-2, 2..62)");
1797      ret = mpz_out_str(NULL, base, *p);
1798      fflush(stdout);
1799      return newSVuv(ret);
1800 }
1801 
_Rmpz_out_strS(pTHX_ mpz_t * p,SV * base,SV * suff)1802 SV * _Rmpz_out_strS(pTHX_ mpz_t * p, SV * base, SV * suff) {
1803      unsigned long ret;
1804      if((SvIV(base) > -2 && SvIV(base) < 2) || SvIV(base) < -36 || SvIV(base) > 62)
1805        croak("2nd argument supplied to Rmpz_out_str is out of allowable range (must be in range -36..-2, 2..62)");
1806      ret = mpz_out_str(NULL, SvUV(base), *p);
1807      printf("%s", SvPV_nolen(suff));
1808      fflush(stdout);
1809      return newSVuv(ret);
1810 }
1811 
_Rmpz_out_strP(pTHX_ SV * pre,mpz_t * p,SV * base)1812 SV * _Rmpz_out_strP(pTHX_ SV * pre, mpz_t * p, SV * base) {
1813      unsigned long ret;
1814      if((SvIV(base) > -2 && SvIV(base) < 2) || SvIV(base) < -36 || SvIV(base) > 62)
1815        croak("3rd argument supplied to Rmpz_out_str is out of allowable range (must be in range -36..-2, 2..62)");
1816      printf("%s", SvPV_nolen(pre));
1817      ret = mpz_out_str(NULL, SvUV(base), *p);
1818      fflush(stdout);
1819      return newSVuv(ret);
1820 }
1821 
_Rmpz_out_strPS(pTHX_ SV * pre,mpz_t * p,SV * base,SV * suff)1822 SV * _Rmpz_out_strPS(pTHX_ SV * pre, mpz_t * p, SV * base, SV * suff) {
1823      unsigned long ret;
1824      if((SvIV(base) > -2 && SvIV(base) < 2) || SvIV(base) < -36 || SvIV(base) > 62)
1825        croak("3rd argument supplied to Rmpz_out_str is out of allowable range (must be in range -36..-2, 2..62)");
1826      printf("%s", SvPV_nolen(pre));
1827      ret = mpz_out_str(NULL, SvUV(base), *p);
1828      printf("%s", SvPV_nolen(suff));
1829      fflush(stdout);
1830      return newSVuv(ret);
1831 }
1832 
_TRmpz_out_str(pTHX_ FILE * stream,SV * base,mpz_t * p)1833 SV * _TRmpz_out_str(pTHX_ FILE * stream, SV * base, mpz_t * p) {
1834      size_t ret;
1835      if((SvIV(base) > -2 && SvIV(base) < 2) || SvIV(base) < -36 || SvIV(base) > 62)
1836        croak("2nd argument supplied to TRmpz_out_str is out of allowable range (must be in range -36..-2, 2..62)");
1837      ret = mpz_out_str(stream, (int)SvIV(base), *p);
1838      fflush(stream);
1839      return newSVuv(ret);
1840 }
1841 
_TRmpz_out_strS(pTHX_ FILE * stream,SV * base,mpz_t * p,SV * suff)1842 SV * _TRmpz_out_strS(pTHX_ FILE * stream, SV * base, mpz_t * p, SV * suff) {
1843      size_t ret;
1844      if((SvIV(base) > -2 && SvIV(base) < 2) || SvIV(base) < -36 || SvIV(base) > 62)
1845        croak("2nd argument supplied to TRmpz_out_str is out of allowable range (must be in range -36..-2, 2..62)");
1846      ret = mpz_out_str(stream, (int)SvIV(base), *p);
1847      fflush(stream);
1848      fprintf(stream, "%s", SvPV_nolen(suff));
1849      fflush(stream);
1850      return newSVuv(ret);
1851 }
1852 
_TRmpz_out_strP(pTHX_ SV * pre,FILE * stream,SV * base,mpz_t * p)1853 SV * _TRmpz_out_strP(pTHX_ SV * pre, FILE * stream, SV * base, mpz_t * p) {
1854      size_t ret;
1855      if((SvIV(base) > -2 && SvIV(base) < 2) || SvIV(base) < -36 || SvIV(base) > 62)
1856        croak("3rd argument supplied to TRmpz_out_str is out of allowable range (must be in range -36..-2, 2..62)");
1857      fprintf(stream, "%s", SvPV_nolen(pre));
1858      fflush(stream);
1859      ret = mpz_out_str(stream, (int)SvIV(base), *p);
1860      fflush(stream);
1861      return newSVuv(ret);
1862 }
1863 
_TRmpz_out_strPS(pTHX_ SV * pre,FILE * stream,SV * base,mpz_t * p,SV * suff)1864 SV * _TRmpz_out_strPS(pTHX_ SV * pre, FILE * stream, SV * base, mpz_t * p, SV * suff) {
1865      size_t ret;
1866      if((SvIV(base) > -2 && SvIV(base) < 2) || SvIV(base) < -36 || SvIV(base) > 62)
1867        croak("3rd argument supplied to TRmpz_out_str is out of allowable range (must be in range -36..-2, 2..62)");
1868      fprintf(stream, "%s", SvPV_nolen(pre));
1869      fflush(stream);
1870      ret = mpz_out_str(stream, (int)SvIV(base), *p);
1871      fflush(stream);
1872      fprintf(stream, "%s", SvPV_nolen(suff));
1873      fflush(stream);
1874      return newSVuv(ret);
1875 }
1876 
Rmpz_inp_str(pTHX_ mpz_t * p,int base)1877 SV * Rmpz_inp_str(pTHX_ mpz_t * p, int base) {
1878      size_t ret;
1879      if(base == 1 || base > 62)
1880        croak("2nd argument supplied to Rmpz_inp_str is out of allowable range (must be in range 0, 2..62)");
1881      ret = mpz_inp_str(*p, NULL, base);
1882      /* fflush(stdin); */
1883      return newSVuv(ret);
1884 }
1885 
TRmpz_inp_str(pTHX_ mpz_t * p,FILE * stream,int base)1886 SV * TRmpz_inp_str(pTHX_ mpz_t * p, FILE * stream, int base) {
1887      size_t ret;
1888      if(base == 1 || base > 62)
1889        croak("4th argument supplied to TRmpz_inp_str is out of allowable range (must be in range 0, 2..62)");
1890      ret = mpz_inp_str(*p, stream, base);
1891      /* fflush(stream); */
1892      return newSVuv(ret);
1893 }
1894 
eratosthenes(pTHX_ SV * x_arg)1895 void eratosthenes(pTHX_ SV * x_arg) {
1896 dXSARGS;
1897 
1898 unsigned short *v, set[16] = {65534,65533,65531,65527,65519,65503,65471,65407,65279,65023,64511,63487,61439,57343,49151,32767};
1899 unsigned long leap, i, size, b, imax, k, x = SvUV(x_arg);
1900 
1901 if(x & 1) croak("max_num argument must be even in eratosthenes function");
1902 
1903 imax = sqrt(x - 1) / 2;
1904 
1905 b = (x + 1) / 2;
1906 
1907 if(!(b % 16)) size = b / 16;
1908 else size = (b / 16) + 1;
1909 
1910 Newz(2, v, size, unsigned short);
1911 if(v == NULL) croak("2: Unable to allocate memory in eratosthenes function");
1912 
1913 for(i = 1; i < size; ++i) v[i] = 65535;
1914 v[0] = 65534;
1915 
1916 for(i = 0; i <= imax; ++i) {
1917 
1918     if(v[i / 16] & (1 << (i % 16))) {
1919        leap = (2 * i) + 1;
1920        k = 2 * i * (i + 1);
1921        while(k < b) {
1922              v[k / 16] &= set[k % 16];
1923              k += leap;
1924              }
1925        }
1926 }
1927 
1928 size = 1;
1929 sp = mark;
1930 XPUSHs(sv_2mortal(newSVuv(2)));
1931 
1932 for(i = 0; i < b; ++i) {
1933     if(v[i / 16] & (1 << (i % 16))) {
1934       XPUSHs(sv_2mortal(newSVuv(2 * i + 1)));
1935       ++size;
1936       }
1937    }
1938 
1939 Safefree(v);
1940 
1941 PUTBACK;
1942 XSRETURN(size);
1943 
1944 }
1945 
1946 
trial_div_ul(pTHX_ mpz_t * num,SV * x_arg)1947 SV * trial_div_ul(pTHX_ mpz_t * num, SV * x_arg) {
1948 
1949      unsigned short *v, set[16] = {65534,65533,65531,65527,65519,65503,65471,65407,65279,65023,64511,63487,61439,57343,49151,32767};
1950      unsigned long leap, i, size, b, imax, k, x = SvUV(x_arg);
1951 
1952      if(x & 1) croak("Second argument supplied to trial_div_ul must be even");
1953 
1954      imax = sqrt(x - 1) / 2;
1955 
1956      b = (x + 1) / 2;
1957 
1958      if(!(b % 16)) size = b / 16;
1959      else size = (b / 16) + 1;
1960 
1961      Newz(2, v, size, unsigned short);
1962      if(v == NULL) croak("2: Unable to allocate memory in trial_div_ul function");
1963 
1964      for(i = 1; i < size; ++i) v[i] = 65535;
1965      v[0] = 65534;
1966 
1967      for(i = 0; i <= imax; ++i) {
1968 
1969        if(v[i / 16] & (1 << (i % 16))) {
1970          leap = (2 * i) + 1;
1971          k = 2 * i * (i + 1);
1972          while(k < b) {
1973            v[k / 16] &= set[k % 16];
1974            k += leap;
1975          }
1976        }
1977      }
1978 
1979      if(mpz_divisible_ui_p(*num, 2)) {
1980        Safefree(v);
1981        return newSViv(2);
1982      }
1983 
1984      for(i = 0; i < b; ++i) {
1985        if(v[i / 16] & (1 << (i % 16))) {
1986          if(mpz_divisible_ui_p(*num, 2 * i + 1)) {
1987            Safefree(v);
1988            return newSViv(2 * i + 1);
1989          }
1990        }
1991      }
1992 
1993      Safefree(v);
1994 
1995      return newSViv(1);
1996 }
1997 
1998 /* Next 2 functions became available with GMP-4.2 */
1999 
Rmpz_rootrem(mpz_t * root,mpz_t * rem,mpz_t * u,unsigned long d)2000 void Rmpz_rootrem(mpz_t * root, mpz_t * rem, mpz_t * u, unsigned long d) {
2001      mpz_rootrem(*root, *rem, *u, d);
2002 }
2003 
Rmpz_combit(pTHX_ mpz_t * num,SV * bitpos)2004 void Rmpz_combit(pTHX_ mpz_t * num, SV * bitpos) {
2005 
2006      CHECK_MP_BITCNT_T_OVERFLOW(bitpos)
2007 
2008      mpz_combit(*num, (mp_bitcnt_t)SvUV(bitpos));
2009 }
2010 
2011 /* Finish typemapping - typemap 1st arg only */
2012 
overload_mul(pTHX_ SV * a,SV * b,SV * third)2013 SV * overload_mul(pTHX_ SV * a, SV * b, SV * third) {
2014      mpz_t * mpz_t_obj;
2015      SV * obj_ref, * obj;
2016      const char *h;
2017      MBI_DECLARATIONS
2018      MBI_GMP_DECLARATIONS
2019 
2020 #if defined(USE_QUADMATH)
2021 
2022      char * buffer;
2023      int returned;
2024      __float128 buffer_size;
2025      __float128 ld;
2026 
2027 #elif defined(USE_LONG_DOUBLE)
2028 
2029      char * buffer;
2030      long double buffer_size;
2031      long double ld;
2032 
2033 #endif
2034 
2035      if(sv_isobject(b)) h = HvNAME(SvSTASH(SvRV(b)));
2036 
2037      if(!sv_isobject(b) || (strNE(h, "Math::MPFR") && strNE(h, "Math::GMPq"))) {
2038        New(1, mpz_t_obj, 1, mpz_t);
2039        if(mpz_t_obj == NULL) croak("Failed to allocate memory in overload_mul function");
2040        obj_ref = newSV(0);
2041        obj = newSVrv(obj_ref, "Math::GMPz");
2042        mpz_init(*mpz_t_obj);
2043        sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
2044        SvREADONLY_on(obj);
2045      }
2046 
2047 #ifdef MATH_GMPZ_NEED_LONG_LONG_INT
2048      if(SV_IS_IOK(b)) {
2049        Rmpz_set_IV(aTHX_ mpz_t_obj, b);
2050        mpz_mul(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *mpz_t_obj);
2051        return obj_ref;
2052      }
2053 #else
2054 
2055      if(SV_IS_IOK(b)) {
2056        if(SvUOK(b)) {
2057          mpz_mul_ui(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), SvUVX(b));
2058          return obj_ref;
2059        }
2060 
2061        mpz_mul_si(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), SvIVX(b));
2062        return obj_ref;
2063      }
2064 #endif
2065 
2066      if(SV_IS_POK(b)) {
2067        if(mpz_set_str(*mpz_t_obj, SvPV_nolen(b), 0))
2068          croak(" Invalid string (%s) supplied to Math::GMPz::overload_mul", SvPV_nolen(b));
2069        mpz_mul(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *mpz_t_obj);
2070        return obj_ref;
2071      }
2072 
2073      if(SV_IS_NOK(b)) {
2074 
2075 #if defined(USE_QUADMATH)
2076 
2077        ld = (__float128)SvNVX(b) >= 0 ? floorq((__float128)SvNVX(b)) : ceilq((__float128)SvNVX(b));
2078        if(ld != ld) croak("In Math::GMPz::overload_mul, cannot coerce a NaN to a Math::GMPz value");
2079        if(ld != 0 && (ld / ld != 1))
2080          croak("In Math::GMPz::overload_mul, cannot coerce an Inf to a Math::GMPz value");
2081 
2082        buffer_size = ld < 0.0Q ? ld * -1.0Q : ld;
2083        buffer_size = ceilq(logq(buffer_size + 1) / 2.30258509299404568401799145468436418Q);
2084 
2085        Newxz(buffer, (int)buffer_size + 5, char);
2086 
2087        returned = quadmath_snprintf(buffer, (size_t)buffer_size + 5, "%.0Qf", ld);
2088        if(returned < 0) croak("In Math::GMPz::overload_mul, encoding error in quadmath_snprintf function");
2089        if(returned >= buffer_size + 5) croak("In Math::GMPz::overload_mul, buffer given to quadmath_snprintf function was too small");
2090        mpz_init_set_str(*mpz_t_obj, buffer, 10);
2091        Safefree(buffer);
2092 
2093 #elif defined(USE_LONG_DOUBLE)
2094 
2095        ld = (long double)SvNVX(b) >= 0 ? floorl((long double)SvNVX(b)) : ceill((long double)SvNVX(b));
2096        if(ld != ld) croak("In Math::GMPz::overload_mul, cannot coerce a NaN to a Math::GMPz value");
2097        if(ld != 0 && (ld / ld != 1))
2098          croak("In Math::GMPz::overload_mul, cannot coerce an Inf to a Math::GMPz value");
2099 
2100        buffer_size = ld < 0.0L ? ld * -1.0L : ld;
2101        buffer_size = ceill(logl(buffer_size + 1) / 2.30258509299404568401799145468436418L);
2102 
2103        Newxz(buffer, (int)buffer_size + 5, char);
2104 
2105        if(sprintf(buffer, "%.0Lf", ld) >= (int)buffer_size + 5) croak("In Math::GMPz::overload_mul, buffer overflow in sprintf function");
2106        mpz_init_set_str(*mpz_t_obj, buffer, 10);
2107        Safefree(buffer);
2108 
2109 #else
2110        double d = SvNVX(b);
2111        if(d != d) croak("In Math::GMPz::overload_mul, cannot coerce a NaN to a Math::GMPz value");
2112        if(d != 0 && (d / d != 1))
2113          croak("In Math::GMPz::overload_mul, cannot coerce an Inf to a Math::GMPz value");
2114        mpz_set_d(*mpz_t_obj, d);
2115 #endif
2116        mpz_mul(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *mpz_t_obj);
2117        return obj_ref;
2118      }
2119 
2120      if(sv_isobject(b)) {
2121        if(strEQ(h, "Math::GMPz")) {
2122          mpz_mul(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(b)))));
2123          return obj_ref;
2124        }
2125        if(strEQ(h, "Math::MPFR")) {
2126          _overload_callback("Math::MPFR::overload_mul", "Math::GMPz::overload_mul", newSViv(0));
2127        }
2128 
2129        if(strEQ(h, "Math::BigInt")) {
2130          VALIDATE_MBI_OBJECT
2131          croak("Invalid Math::BigInt object supplied to Math::GMPz::overload_mul");
2132 
2133          MBI_GMP_INSERT
2134 
2135          if(mpz) {
2136            mpz_mul(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), (mpz_srcptr)mpz);
2137            if(strEQ("-", sign)) mpz_neg(*mpz_t_obj, *mpz_t_obj);
2138            return obj_ref;
2139          }
2140 
2141          mpz_set_str(*mpz_t_obj, SvPV_nolen(b), 0);
2142          mpz_mul(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *mpz_t_obj);
2143          return obj_ref;
2144        }
2145        if(strEQ(h, "Math::GMPq")) {
2146          _overload_callback("Math::GMPq::overload_mul", "Math::GMPz::overload_mul", newSViv(0));
2147        }
2148      }
2149 
2150      croak("Invalid argument supplied to Math::GMPz::overload_mul");
2151 }
2152 
overload_add(pTHX_ SV * a,SV * b,SV * third)2153 SV * overload_add(pTHX_ SV * a, SV * b, SV * third) {
2154      mpz_t * mpz_t_obj;
2155      SV * obj_ref, * obj;
2156      const char *h;
2157      MBI_DECLARATIONS
2158      MBI_GMP_DECLARATIONS
2159 
2160 #if defined(USE_QUADMATH)
2161 
2162      char * buffer;
2163      int returned;
2164      __float128 buffer_size;
2165      __float128 ld;
2166 
2167 #elif defined(USE_LONG_DOUBLE)
2168 
2169      char * buffer;
2170      long double buffer_size;
2171      long double ld;
2172 
2173 #endif
2174 
2175      if(sv_isobject(b)) h = HvNAME(SvSTASH(SvRV(b)));
2176 
2177      if(!sv_isobject(b) || (strNE(h, "Math::MPFR") && strNE(h, "Math::GMPq"))) {
2178        New(1, mpz_t_obj, 1, mpz_t);
2179        if(mpz_t_obj == NULL) croak("Failed to allocate memory in overload_add function");
2180        obj_ref = newSV(0);
2181        obj = newSVrv(obj_ref, "Math::GMPz");
2182        mpz_init(*mpz_t_obj);
2183        sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
2184        SvREADONLY_on(obj);
2185      }
2186 
2187 #ifdef MATH_GMPZ_NEED_LONG_LONG_INT
2188      if(SV_IS_IOK(b)) {
2189        Rmpz_set_IV(aTHX_ mpz_t_obj, b);
2190        mpz_add(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *mpz_t_obj);
2191        return obj_ref;
2192      }
2193 #else
2194      if(SV_IS_IOK(b)) {
2195        if(SvUOK(b)) {
2196          mpz_add_ui(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), SvUVX(b));
2197          return obj_ref;
2198        }
2199 
2200        if(SvIV(b) >= 0) {
2201          mpz_add_ui(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), SvIVX(b));
2202          return obj_ref;
2203        }
2204        mpz_sub_ui(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), SvIVX(b) * -1);
2205        return obj_ref;
2206      }
2207 #endif
2208 
2209      if(SV_IS_POK(b)) {
2210        if(mpz_set_str(*mpz_t_obj, SvPV_nolen(b), 0))
2211          croak(" Invalid string (%s) supplied to Math::GMPz::overload_add", SvPV_nolen(b));
2212        mpz_add(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *mpz_t_obj);
2213        return obj_ref;
2214      }
2215 
2216      if(SV_IS_NOK(b)) {
2217 
2218 #if defined(USE_QUADMATH)
2219 
2220        ld = (__float128)SvNVX(b) >= 0 ? floorq((__float128)SvNVX(b)) : ceilq((__float128)SvNVX(b));
2221        if(ld != ld) croak("In Math::GMPz::overload_add, cannot coerce a NaN to a Math::GMPz value");
2222        if(ld != 0 && (ld / ld != 1))
2223          croak("In Math::GMPz::overload_add, cannot coerce an Inf to a Math::GMPz value");
2224 
2225        buffer_size = ld < 0.0Q ? ld * -1.0Q : ld;
2226        buffer_size = ceilq(logq(buffer_size + 1) / 2.30258509299404568401799145468436418Q);
2227 
2228        Newxz(buffer, (int)buffer_size + 5, char);
2229 
2230        returned = quadmath_snprintf(buffer, (size_t)buffer_size + 5, "%.0Qf", ld);
2231        if(returned < 0) croak("In Math::GMPz::overload_add, encoding error in quadmath_snprintf function");
2232        if(returned >= buffer_size + 5) croak("In Math::GMPz::overload_add, buffer given to quadmath_snprintf function was too small");
2233        mpz_init_set_str(*mpz_t_obj, buffer, 10);
2234        Safefree(buffer);
2235 
2236 #elif defined(USE_LONG_DOUBLE)
2237 
2238        ld = (long double)SvNVX(b) >= 0 ? floorl((long double)SvNVX(b)) : ceill((long double)SvNVX(b));
2239        if(ld != ld) croak("In Math::GMPz::overload_add, cannot coerce a NaN to a Math::GMPz value");
2240        if(ld != 0 && (ld / ld != 1))
2241          croak("In Math::GMPz::overload_add, cannot coerce an Inf to a Math::GMPz value");
2242 
2243        buffer_size = ld < 0.0L ? ld * -1.0L : ld;
2244        buffer_size = ceill(logl(buffer_size + 1) / 2.30258509299404568401799145468436418L);
2245 
2246        Newxz(buffer, (int)buffer_size + 5, char);
2247 
2248        if(sprintf(buffer, "%.0Lf", ld) >= (int)buffer_size + 5) croak("In Math::GMPz::overload_add, buffer overflow in sprintf function");
2249        mpz_init_set_str(*mpz_t_obj, buffer, 10);
2250        Safefree(buffer);
2251 #else
2252        double d = SvNVX(b);
2253        if(d != d) croak("In Math::GMPz::overload_add, cannot coerce a NaN to a Math::GMPz value");
2254        if(d != 0 && (d / d != 1))
2255          croak("In Math::GMPz::overload_add, cannot coerce an Inf to a Math::GMPz value");
2256        mpz_set_d(*mpz_t_obj, d);
2257 #endif
2258        mpz_add(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *mpz_t_obj);
2259        return obj_ref;
2260      }
2261 
2262      if(sv_isobject(b)) {
2263        if(strEQ(h, "Math::GMPz")) {
2264          mpz_add(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(b)))));
2265          return obj_ref;
2266        }
2267        if(strEQ(h, "Math::MPFR")) {
2268          _overload_callback("Math::MPFR::overload_add", "Math::GMPz::overload_add", newSViv(0));
2269        }
2270 
2271        if(strEQ(h, "Math::BigInt")) {
2272          VALIDATE_MBI_OBJECT
2273          croak("Invalid Math::BigInt object supplied to Math::GMPz::overload_add");
2274 
2275          MBI_GMP_INSERT
2276 
2277          if(mpz) {
2278            if(strEQ("-", sign)) {
2279              mpz_sub(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), (mpz_srcptr)mpz);
2280              return obj_ref;
2281            }
2282 
2283            mpz_add(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), (mpz_srcptr)mpz);
2284            return obj_ref;
2285          }
2286 
2287          mpz_set_str(*mpz_t_obj, SvPV_nolen(b), 0);
2288          mpz_add(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *mpz_t_obj);
2289          return obj_ref;
2290        }
2291        if(strEQ(h, "Math::GMPq")) {
2292          _overload_callback("Math::GMPq::overload_add", "Math::GMPz::overload_add", newSViv(0));
2293        }
2294      }
2295 
2296      croak("Invalid argument supplied to Math::GMPz::overload_add function");
2297 
2298 }
2299 
overload_sub(pTHX_ SV * a,SV * b,SV * third)2300 SV * overload_sub(pTHX_ SV * a, SV * b, SV * third) {
2301      mpz_t * mpz_t_obj;
2302      SV * obj_ref, * obj;
2303      const char *h;
2304      MBI_DECLARATIONS
2305      MBI_GMP_DECLARATIONS
2306 
2307 #if defined(USE_QUADMATH)
2308 
2309      char * buffer;
2310      int returned;
2311      __float128 buffer_size;
2312      __float128 ld;
2313 
2314 #elif defined(USE_LONG_DOUBLE)
2315 
2316      char * buffer;
2317      long double buffer_size;
2318      long double ld;
2319 
2320 #endif
2321 
2322      if(sv_isobject(b)) h = HvNAME(SvSTASH(SvRV(b)));
2323 
2324      if(!sv_isobject(b) || (strNE(h, "Math::MPFR") && strNE(h, "Math::GMPq"))) {
2325        New(1, mpz_t_obj, 1, mpz_t);
2326        if(mpz_t_obj == NULL) croak("Failed to allocate memory in overload_sub function");
2327        obj_ref = newSV(0);
2328        obj = newSVrv(obj_ref, "Math::GMPz");
2329        mpz_init(*mpz_t_obj);
2330        sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
2331        SvREADONLY_on(obj);
2332      }
2333 
2334 
2335 #ifdef MATH_GMPZ_NEED_LONG_LONG_INT
2336      if(SV_IS_IOK(b)) {
2337        Rmpz_set_IV(aTHX_ mpz_t_obj, b);
2338        if(third == &PL_sv_yes) mpz_sub(*mpz_t_obj, *mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))));
2339        else mpz_sub(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *mpz_t_obj);
2340        return obj_ref;
2341      }
2342 #else
2343      if(SV_IS_IOK(b)) {
2344        if(SvUOK(b)) {
2345          if(third == &PL_sv_yes) {
2346            mpz_ui_sub(*mpz_t_obj, SvUVX(b), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))));
2347            return obj_ref;
2348          }
2349          mpz_sub_ui(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), SvUVX(b));
2350          return obj_ref;
2351        }
2352 
2353        if(SvIV(b) >= 0) {
2354          if(third == &PL_sv_yes) {
2355            mpz_ui_sub(*mpz_t_obj, SvIVX(b), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))));
2356            return obj_ref;
2357            }
2358          mpz_sub_ui(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), SvIVX(b));
2359          return obj_ref;
2360        }
2361        mpz_add_ui(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), SvIVX(b) * -1);
2362        if(third == &PL_sv_yes) mpz_neg(*mpz_t_obj, *mpz_t_obj);
2363        return obj_ref;
2364      }
2365 #endif
2366 
2367      if(SV_IS_POK(b)) {
2368        if(mpz_set_str(*mpz_t_obj, SvPV_nolen(b), 0))
2369          croak(" Invalid string (%s) supplied to Math::GMPz::overload_sub", SvPV_nolen(b));
2370        if(third == &PL_sv_yes) mpz_sub(*mpz_t_obj, *mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))));
2371        else mpz_sub(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *mpz_t_obj);
2372        return obj_ref;
2373      }
2374 
2375      if(SV_IS_NOK(b)) {
2376 
2377 #if defined(USE_QUADMATH)
2378 
2379      ld = (__float128)SvNVX(b) >= 0 ? floorq((__float128)SvNVX(b)) : ceilq((__float128)SvNVX(b));
2380      if(ld != ld) croak("In Math::GMPz::overload_sub, cannot coerce a NaN to a Math::GMPz value");
2381      if(ld != 0 && (ld / ld != 1))
2382        croak("In Math::GMPz::overload_sub, cannot coerce an Inf to a Math::GMPz value");
2383 
2384      buffer_size = ld < 0.0Q ? ld * -1.0Q : ld;
2385      buffer_size = ceilq(logq(buffer_size + 1) / 2.30258509299404568401799145468436418Q);
2386 
2387      Newxz(buffer, (int)buffer_size + 5, char);
2388 
2389      returned = quadmath_snprintf(buffer, (size_t)buffer_size + 5, "%.0Qf", ld);
2390      if(returned < 0) croak("In Math::GMPz::overload_sub, encoding error in quadmath_snprintf function");
2391      if(returned >= buffer_size + 5) croak("In Math::GMPz::overload_sub, buffer given to quadmath_snprintf function was too small");
2392      mpz_init_set_str(*mpz_t_obj, buffer, 10);
2393      Safefree(buffer);
2394 
2395 #elif defined(USE_LONG_DOUBLE)
2396 
2397      ld = (long double)SvNVX(b) >= 0 ? floorl((long double)SvNVX(b)) : ceill((long double)SvNVX(b));
2398      if(ld != ld) croak("In Math::GMPz::overload_sub, cannot coerce a NaN to a Math::GMPz value");
2399      if(ld != 0 && (ld / ld != 1))
2400        croak("In Math::GMPz::overload_sub, cannot coerce an Inf to a Math::GMPz value");
2401 
2402      buffer_size = ld < 0.0L ? ld * -1.0L : ld;
2403      buffer_size = ceill(logl(buffer_size + 1) / 2.30258509299404568401799145468436418L);
2404 
2405      Newxz(buffer, (int)buffer_size + 5, char);
2406 
2407      if(sprintf(buffer, "%.0Lf", ld) >= (int)buffer_size + 5) croak("In Math::GMPz::overload_sub, buffer overflow in sprintf function");
2408      mpz_init_set_str(*mpz_t_obj, buffer, 10);
2409      Safefree(buffer);
2410 #else
2411        double d = SvNVX(b);
2412        if(d != d) croak("In Math::GMPz::overload_sub, cannot coerce a NaN to a Math::GMPz value");
2413        if(d != 0 && (d / d != 1))
2414          croak("In Math::GMPz::overload_sub, cannot coerce an Inf to a Math::GMPz value");
2415        mpz_set_d(*mpz_t_obj, SvNVX(b));
2416 #endif
2417        if(third == &PL_sv_yes) mpz_sub(*mpz_t_obj, *mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))));
2418        else mpz_sub(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *mpz_t_obj);
2419        return obj_ref;
2420      }
2421 
2422      if(sv_isobject(b)) {
2423        if(strEQ(h, "Math::GMPz")) {
2424          mpz_sub(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(b)))));
2425          return obj_ref;
2426        }
2427        if(strEQ(h, "Math::MPFR")) {
2428          _overload_callback("Math::MPFR::overload_sub", "Math::GMPz::overload_sub", &PL_sv_yes);
2429        }
2430 
2431        if(strEQ(h, "Math::BigInt")) {
2432          VALIDATE_MBI_OBJECT
2433          croak("Invalid Math::BigInt object supplied to Math::GMPz::overload_sub");
2434 
2435          MBI_GMP_INSERT
2436 
2437          if(mpz) {
2438            if(strEQ("-", sign)) {
2439              mpz_add(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), (mpz_srcptr)mpz);
2440              return obj_ref;
2441            }
2442 
2443            mpz_sub(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), (mpz_srcptr)mpz);
2444            return obj_ref;
2445          }
2446 
2447          mpz_set_str(*mpz_t_obj, SvPV_nolen(b), 0);
2448          mpz_sub(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *mpz_t_obj);
2449          return obj_ref;
2450        }
2451        if(strEQ(h, "Math::GMPq")) {
2452          _overload_callback("Math::GMPq::overload_sub", "Math::GMPz::overload_sub", &PL_sv_yes);
2453        }
2454      }
2455 
2456      croak("Invalid argument supplied to Math::GMPz::overload_sub function");
2457 
2458 }
2459 
overload_div(pTHX_ SV * a,SV * b,SV * third)2460 SV * overload_div(pTHX_ SV * a, SV * b, SV * third) {
2461      mpz_t * mpz_t_obj;
2462      SV * obj_ref, * obj;
2463      const char *h;
2464      MBI_DECLARATIONS
2465      MBI_GMP_DECLARATIONS
2466 
2467 #if defined(USE_QUADMATH)
2468 
2469      char * buffer;
2470      int returned;
2471      __float128 buffer_size;
2472      __float128 ld;
2473 
2474 #elif defined(USE_LONG_DOUBLE)
2475 
2476      char * buffer;
2477      long double buffer_size;
2478      long double ld;
2479 
2480 #endif
2481 
2482      if(sv_isobject(b)) h = HvNAME(SvSTASH(SvRV(b)));
2483 
2484      if(!sv_isobject(b) || (strNE(h, "Math::MPFR") && strNE(h, "Math::GMPq"))) {
2485        New(1, mpz_t_obj, 1, mpz_t);
2486        if(mpz_t_obj == NULL) croak("Failed to allocate memory in overload_div function");
2487        obj_ref = newSV(0);
2488        obj = newSVrv(obj_ref, "Math::GMPz");
2489        mpz_init(*mpz_t_obj);
2490        sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
2491        SvREADONLY_on(obj);
2492      }
2493 
2494 #ifdef MATH_GMPZ_NEED_LONG_LONG_INT
2495      if(SV_IS_IOK(b)) {
2496        Rmpz_set_IV(aTHX_ mpz_t_obj, b);
2497        if(third == &PL_sv_yes) Rmpz_tdiv_q(mpz_t_obj, mpz_t_obj, INT2PTR(mpz_t *, SvIVX(SvRV(a))));
2498        else Rmpz_tdiv_q(mpz_t_obj, INT2PTR(mpz_t *, SvIVX(SvRV(a))), mpz_t_obj);
2499        return obj_ref;
2500      }
2501 #else
2502      if(SV_IS_IOK(b)) {
2503        if(SvUOK(b)) {
2504          if(third == &PL_sv_yes) {
2505            mpz_set_ui(*mpz_t_obj, SvUVX(b));
2506            Rmpz_tdiv_q(mpz_t_obj, mpz_t_obj, INT2PTR(mpz_t *, SvIVX(SvRV(a))));
2507            return obj_ref;
2508          }
2509          Rmpz_tdiv_q_ui(mpz_t_obj, INT2PTR(mpz_t *, SvIVX(SvRV(a))), SvUVX(b));
2510          return obj_ref;
2511        }
2512 
2513        if(SvIVX(b) >= 0) {
2514          if(third == &PL_sv_yes) {
2515            mpz_set_si(*mpz_t_obj, SvIVX(b));
2516            Rmpz_tdiv_q(mpz_t_obj, mpz_t_obj, INT2PTR(mpz_t *, SvIVX(SvRV(a))));
2517            return obj_ref;
2518          }
2519          Rmpz_tdiv_q_ui(mpz_t_obj, INT2PTR(mpz_t *, SvIVX(SvRV(a))), SvIVX(b));
2520          return obj_ref;
2521        }
2522 
2523        if(third == &PL_sv_yes) {
2524          mpz_set_si(*mpz_t_obj, SvIVX(b));
2525          Rmpz_tdiv_q(mpz_t_obj, mpz_t_obj, INT2PTR(mpz_t *, SvIVX(SvRV(a))));
2526          return obj_ref;
2527        }
2528 
2529        Rmpz_tdiv_q_ui(mpz_t_obj, INT2PTR(mpz_t *, SvIVX(SvRV(a))), SvIVX(b) * -1);
2530        mpz_neg(*mpz_t_obj, *mpz_t_obj);
2531        return obj_ref;
2532      }
2533 #endif
2534 
2535      if(SV_IS_POK(b)) {
2536        if(mpz_set_str(*mpz_t_obj, SvPV_nolen(b), 0))
2537           croak(" Invalid string (%s) supplied to Math::GMPz::overload_div", SvPV_nolen(b));
2538        if(third == &PL_sv_yes) Rmpz_tdiv_q(mpz_t_obj, mpz_t_obj, INT2PTR(mpz_t *, SvIVX(SvRV(a))));
2539        else Rmpz_tdiv_q(mpz_t_obj, INT2PTR(mpz_t *, SvIVX(SvRV(a))), mpz_t_obj);
2540        return obj_ref;
2541      }
2542 
2543      if(SV_IS_NOK(b)) {
2544 
2545 #if defined(USE_QUADMATH)
2546 
2547      ld = (__float128)SvNVX(b) >= 0 ? floorq((__float128)SvNVX(b)) : ceilq((__float128)SvNVX(b));
2548      if(ld != ld) croak("In Math::GMPz::overload_div, cannot coerce a NaN to a Math::GMPz value");
2549      if(ld != 0 && (ld / ld != 1))
2550        croak("In Math::GMPz::overload_div, cannot coerce an Inf to a Math::GMPz value");
2551 
2552      buffer_size = ld < 0.0Q ? ld * -1.0Q : ld;
2553      buffer_size = ceilq(logq(buffer_size + 1) / 2.30258509299404568401799145468436418Q);
2554 
2555      Newxz(buffer, (int)buffer_size + 5, char);
2556 
2557      returned = quadmath_snprintf(buffer, (size_t)buffer_size + 5, "%.0Qf", ld);
2558      if(returned < 0) croak("In Math::GMPz::overload_div, encoding error in quadmath_snprintf function");
2559      if(returned >= buffer_size + 5) croak("In Math::GMPz::overload_div, buffer given to quadmath_snprintf function was too small");
2560      mpz_init_set_str(*mpz_t_obj, buffer, 10);
2561      Safefree(buffer);
2562 
2563 #elif defined(USE_LONG_DOUBLE)
2564 
2565      ld = (long double)SvNVX(b) >= 0 ? floorl((long double)SvNVX(b)) : ceill((long double)SvNVX(b));
2566      if(ld != ld) croak("In Math::GMPz::overload_div, cannot coerce a NaN to a Math::GMPz value");
2567      if(ld != 0 && (ld / ld != 1))
2568        croak("In Math::GMPz::overload_div, cannot coerce an Inf to a Math::GMPz value");
2569 
2570      buffer_size = ld < 0.0L ? ld * -1.0L : ld;
2571      buffer_size = ceill(logl(buffer_size + 1) / 2.30258509299404568401799145468436418L);
2572 
2573      Newxz(buffer, (int)buffer_size + 5, char);
2574 
2575      if(sprintf(buffer, "%.0Lf", ld) >= (int)buffer_size + 5) croak("In Math::GMPz::overload_div, buffer overflow in sprintf function");
2576      mpz_init_set_str(*mpz_t_obj, buffer, 10);
2577      Safefree(buffer);
2578 #else
2579        double d = SvNVX(b);
2580        if(d != d) croak("In Math::GMPz::overload_div, cannot coerce a NaN to a Math::GMPz value");
2581        if(d != 0 && (d / d != 1))
2582          croak("In Math::GMPz::overload_div, cannot coerce an Inf to a Math::GMPz value");
2583        mpz_set_d(*mpz_t_obj, d);
2584 #endif
2585        if(third == &PL_sv_yes) Rmpz_tdiv_q(mpz_t_obj, mpz_t_obj, INT2PTR(mpz_t *, SvIVX(SvRV(a))));
2586        else Rmpz_tdiv_q(mpz_t_obj, INT2PTR(mpz_t *, SvIVX(SvRV(a))), mpz_t_obj);
2587        return obj_ref;
2588      }
2589 
2590      if(sv_isobject(b)) {
2591        if(strEQ(h, "Math::GMPz")) {
2592          Rmpz_tdiv_q(mpz_t_obj, INT2PTR(mpz_t *, SvIVX(SvRV(a))), INT2PTR(mpz_t *, SvIVX(SvRV(b))));
2593          return obj_ref;
2594        }
2595        if(strEQ(h, "Math::MPFR")) {
2596          _overload_callback("Math::MPFR::overload_div", "Math::GMPz::overload_div", &PL_sv_yes);
2597        }
2598 
2599        if(strEQ(h, "Math::BigInt")) {
2600          VALIDATE_MBI_OBJECT
2601            croak("Invalid Math::BigInt object supplied to Math::GMPz::overload_div");
2602 
2603          MBI_GMP_INSERT
2604 
2605          if(mpz) {
2606            mpz_tdiv_q(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), (mpz_srcptr)mpz);
2607            if(strEQ("-", sign)) mpz_neg(*mpz_t_obj, *mpz_t_obj);
2608            return obj_ref;
2609          }
2610 
2611          mpz_set_str(*mpz_t_obj, SvPV_nolen(b), 0);
2612          Rmpz_tdiv_q(mpz_t_obj, INT2PTR(mpz_t *, SvIVX(SvRV(a))), mpz_t_obj);
2613          return obj_ref;
2614        }
2615        if(strEQ(h, "Math::GMPq")) {
2616          _overload_callback("Math::GMPq::overload_div", "Math::GMPz::overload_div", &PL_sv_yes);
2617        }
2618      }
2619 
2620      croak("Invalid argument supplied to Math::GMPz::overload_div function");
2621 
2622 }
2623 
overload_mod(pTHX_ mpz_t * a,SV * b,SV * third)2624 SV * overload_mod (pTHX_ mpz_t * a, SV * b, SV * third) {
2625      mpz_t *mpz_t_obj;
2626      SV * obj_ref, * obj;
2627      MBI_DECLARATIONS
2628      MBI_GMP_DECLARATIONS
2629 
2630 #if defined(USE_QUADMATH)
2631 
2632      char * buffer;
2633      int returned;
2634      __float128 buffer_size;
2635      __float128 ld;
2636 
2637 #elif defined(USE_LONG_DOUBLE)
2638 
2639      char * buffer;
2640      long double buffer_size;
2641      long double ld;
2642 
2643 #endif
2644 
2645      New(1, mpz_t_obj, 1, mpz_t);
2646      if(mpz_t_obj == NULL) croak("Failed to allocate memory in overload_mod function");
2647      obj_ref = newSV(0);
2648      obj = newSVrv(obj_ref, "Math::GMPz");
2649      mpz_init(*mpz_t_obj);
2650      sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
2651      SvREADONLY_on(obj);
2652 
2653 #ifdef MATH_GMPZ_NEED_LONG_LONG_INT
2654      if(SV_IS_IOK(b)) {
2655        Rmpz_set_IV(aTHX_ mpz_t_obj, b);
2656        if(third == &PL_sv_yes) {
2657          mpz_mod(*mpz_t_obj, *mpz_t_obj, *a);
2658          return obj_ref;
2659        }
2660        mpz_mod(*mpz_t_obj, *a, *mpz_t_obj);
2661        return obj_ref;
2662      }
2663 #else
2664      if(SV_IS_IOK(b)) {
2665        if(SvUOK(b)) {
2666          if(third == &PL_sv_yes) {
2667            mpz_set_ui(*mpz_t_obj, SvUVX(b));
2668            mpz_mod(*mpz_t_obj, *mpz_t_obj, *a);
2669            return obj_ref;
2670          }
2671          mpz_mod_ui(*mpz_t_obj, *a, SvUVX(b));
2672          return obj_ref;
2673        }
2674 
2675        mpz_set_si(*mpz_t_obj, SvIVX(b));
2676        if(third == &PL_sv_yes) {
2677          mpz_mod(*mpz_t_obj, *mpz_t_obj, *a);
2678          return obj_ref;
2679        }
2680        mpz_mod(*mpz_t_obj, *a, *mpz_t_obj);
2681        return obj_ref;
2682      }
2683 #endif
2684 
2685      if(SV_IS_POK(b)) {
2686        if(mpz_set_str(*mpz_t_obj, SvPV_nolen(b), 0))
2687           croak(" Invalid string (%s) supplied to Math::GMPz::overload_mod", SvPV_nolen(b));
2688        if(third == &PL_sv_yes) {
2689          mpz_mod(*mpz_t_obj, *mpz_t_obj, *a);
2690          return obj_ref;
2691        }
2692        mpz_mod(*mpz_t_obj, *a, *mpz_t_obj);
2693        return obj_ref;
2694      }
2695 
2696      if(SV_IS_NOK(b)) {
2697 
2698 #if defined(USE_QUADMATH)
2699 
2700        ld = (__float128)SvNVX(b) >= 0 ? floorq((__float128)SvNVX(b)) : ceilq((__float128)SvNVX(b));
2701        if(ld != ld) croak("In Math::GMPz::overload_mod, cannot coerce a NaN to a Math::GMPz value");
2702        if(ld != 0 && (ld / ld != 1))
2703          croak("In Math::GMPz::overload_mod, cannot coerce an Inf to a Math::GMPz value");
2704 
2705        buffer_size = ld < 0.0Q ? ld * -1.0Q : ld;
2706        buffer_size = ceilq(logq(buffer_size + 1) / 2.30258509299404568401799145468436418Q);
2707 
2708        Newxz(buffer, (int)buffer_size + 5, char);
2709 
2710        returned = quadmath_snprintf(buffer, (size_t)buffer_size + 5, "%.0Qf", ld);
2711        if(returned < 0) croak("In Math::GMPz::overload_mod, encoding error in quadmath_snprintf function");
2712        if(returned >= buffer_size + 5) croak("In Math::GMPz::overload_mod, buffer given to quadmath_snprintf function was too small");
2713        mpz_init_set_str(*mpz_t_obj, buffer, 10);
2714        Safefree(buffer);
2715 
2716 #elif defined(USE_LONG_DOUBLE)
2717 
2718        ld = (long double)SvNVX(b) >= 0 ? floorl((long double)SvNVX(b)) : ceill((long double)SvNVX(b));
2719        if(ld != ld) croak("In Math::GMPz::overload_mod, cannot coerce a NaN to a Math::GMPz value");
2720        if(ld != 0 && (ld / ld != 1))
2721          croak("In Math::GMPz::overload_mod, cannot coerce an Inf to a Math::GMPz value");
2722 
2723        buffer_size = ld < 0.0L ? ld * -1.0L : ld;
2724        buffer_size = ceill(logl(buffer_size + 1) / 2.30258509299404568401799145468436418L);
2725 
2726        Newxz(buffer, (int)buffer_size + 5, char);
2727 
2728        if(sprintf(buffer, "%.0Lf", ld) >= (int)buffer_size + 5) croak("In Math::GMPz::overload_mod, buffer overflow in sprintf function");
2729        mpz_init_set_str(*mpz_t_obj, buffer, 10);
2730        Safefree(buffer);
2731 #else
2732        double d = SvNVX(b);
2733        if(d != d) croak("In Math::GMPz::overload_mod, cannot coerce a NaN to a Math::GMPz value");
2734        if(d != 0 && (d / d != 1))
2735          croak("In Math::GMPz::overload_mod, cannot coerce an Inf to a Math::GMPz value");
2736        mpz_set_d(*mpz_t_obj, d);
2737 #endif
2738        if(third == &PL_sv_yes) {
2739          mpz_mod(*mpz_t_obj, *mpz_t_obj, *a);
2740          return obj_ref;
2741        }
2742        mpz_mod(*mpz_t_obj, *a, *mpz_t_obj);
2743        return obj_ref;
2744      }
2745 
2746      if(sv_isobject(b)) {
2747        const char *h = HvNAME(SvSTASH(SvRV(b)));
2748        if(strEQ(h, "Math::GMPz")) {
2749          mpz_mod(*mpz_t_obj, *a, *(INT2PTR(mpz_t *, SvIVX(SvRV(b)))));
2750          return obj_ref;
2751          }
2752        if(strEQ(h, "Math::BigInt")) {
2753          VALIDATE_MBI_OBJECT
2754            croak("Invalid Math::BigInt object supplied to Math::GMPz::overload_mod");
2755 
2756          MBI_GMP_INSERT
2757 
2758          if(mpz) {
2759            mpz_mod(*mpz_t_obj, *a, (mpz_srcptr)mpz);
2760            /* if(strEQ("-", sign)) ...... sign of divisor has no bearing on mod */
2761            return obj_ref;
2762          }
2763 
2764          mpz_set_str(*mpz_t_obj, SvPV_nolen(b), 0);
2765          mpz_mod(*mpz_t_obj, *a, *mpz_t_obj);
2766          return obj_ref;
2767        }
2768      }
2769 
2770      croak("Invalid argument supplied to Math::GMPz::overload_mod function");
2771 }
2772 
overload_string(pTHX_ mpz_t * p,SV * second,SV * third)2773 SV * overload_string(pTHX_ mpz_t * p, SV * second, SV * third) {
2774      char * out;
2775      SV * outsv;
2776 
2777      New(2, out, mpz_sizeinbase(*p, 10) + 3, char);
2778      if(out == NULL) croak("Failed to allocate memory in overload_string function");
2779 
2780      mpz_get_str(out, 10, *p);
2781      outsv = newSVpv(out, 0);
2782      Safefree(out);
2783      return outsv;
2784 }
2785 
overload_copy(pTHX_ mpz_t * p,SV * second,SV * third)2786 SV * overload_copy(pTHX_ mpz_t * p, SV * second, SV * third) {
2787      mpz_t * mpz_t_obj;
2788      SV * obj_ref, * obj;
2789 
2790      New(1, mpz_t_obj, 1, mpz_t);
2791      if(mpz_t_obj == NULL) croak("Failed to allocate memory in overload_copy function");
2792      obj_ref = newSV(0);
2793      obj = newSVrv(obj_ref, "Math::GMPz");
2794 
2795      mpz_init_set(*mpz_t_obj, *p);
2796      sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
2797      SvREADONLY_on(obj);
2798      return obj_ref;
2799 }
2800 
overload_abs(pTHX_ mpz_t * p,SV * second,SV * third)2801 SV * overload_abs(pTHX_ mpz_t * p, SV * second, SV * third) {
2802      mpz_t * mpz_t_obj;
2803      SV * obj_ref, * obj;
2804 
2805      New(1, mpz_t_obj, 1, mpz_t);
2806      if(mpz_t_obj == NULL) croak("Failed to allocate memory in overload_abs function");
2807      obj_ref = newSV(0);
2808      obj = newSVrv(obj_ref, "Math::GMPz");
2809      mpz_init(*mpz_t_obj);
2810 
2811      mpz_abs(*mpz_t_obj, *p);
2812      sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
2813      SvREADONLY_on(obj);
2814      return obj_ref;
2815 }
2816 
overload_lshift(pTHX_ mpz_t * a,SV * b,SV * third)2817 SV * overload_lshift(pTHX_ mpz_t * a, SV * b, SV * third) {
2818      mpz_t * mpz_t_obj;
2819      SV * obj_ref, * obj;
2820 
2821      CHECK_MP_BITCNT_T_OVERFLOW(b)
2822 
2823      New(1, mpz_t_obj, 1, mpz_t);
2824      if(mpz_t_obj == NULL) croak("Failed to allocate memory in overload_lshift function");
2825      obj_ref = newSV(0);
2826      obj = newSVrv(obj_ref, "Math::GMPz");
2827      mpz_init(*mpz_t_obj);
2828 
2829      if(SV_IS_IOK(b)) {
2830        if(SvUOK(b)) {
2831          mpz_mul_2exp(*mpz_t_obj, *a, (mp_bitcnt_t)SvUV(b));
2832          sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
2833          SvREADONLY_on(obj);
2834          return obj_ref;
2835        }
2836 
2837        if(SvIV(b) < 0) croak("Invalid argument supplied to Math::GMPz::overload_lshift");
2838        mpz_mul_2exp(*mpz_t_obj, *a, SvUV(b));
2839        sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
2840        SvREADONLY_on(obj);
2841        return obj_ref;
2842      }
2843 
2844      croak("Invalid argument supplied to Math::GMPz::overload_lshift");
2845 }
2846 
overload_rshift(pTHX_ mpz_t * a,SV * b,SV * third)2847 SV * overload_rshift(pTHX_ mpz_t * a, SV * b, SV * third) {
2848      mpz_t * mpz_t_obj;
2849      SV * obj_ref, * obj;
2850 
2851      CHECK_MP_BITCNT_T_OVERFLOW(b)
2852 
2853      New(1, mpz_t_obj, 1, mpz_t);
2854      if(mpz_t_obj == NULL) croak("Failed to allocate memory in overload_rshift function");
2855      obj_ref = newSV(0);
2856      obj = newSVrv(obj_ref, "Math::GMPz");
2857      mpz_init(*mpz_t_obj);
2858 
2859      if(SV_IS_IOK(b)) {
2860        if(SvUOK(b)) {
2861          mpz_tdiv_q_2exp(*mpz_t_obj, *a, (mp_bitcnt_t)SvUVX(b));
2862          sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
2863          SvREADONLY_on(obj);
2864          return obj_ref;
2865        }
2866 
2867        if(SvIV(b) < 0) croak("Invalid argument supplied to Math::GMPz::overload_rshift");
2868        mpz_tdiv_q_2exp(*mpz_t_obj, *a, (mp_bitcnt_t)SvUVX(b));
2869        sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
2870        SvREADONLY_on(obj);
2871        return obj_ref;
2872      }
2873 
2874      croak("Invalid argument supplied to Math::GMPz::overload_rshift");
2875 }
2876 
overload_pow(pTHX_ SV * a,SV * b,SV * third)2877 SV * overload_pow(pTHX_ SV * a, SV * b, SV * third) {
2878      mpz_t * mpz_t_obj;
2879      SV * obj_ref, * obj;
2880      unsigned long int ui = 0;
2881 
2882      if(mpz_fits_uint_p(*(INT2PTR(mpz_t *, SvIVX(SvRV(a))))))
2883        ui = mpz_get_ui(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))));
2884 
2885      if(!sv_isobject(b)) {
2886        New(1, mpz_t_obj, 1, mpz_t);
2887        if(mpz_t_obj == NULL) croak("Failed to allocate memory in overload_pow function");
2888        obj_ref = newSV(0);
2889        obj = newSVrv(obj_ref, "Math::GMPz");
2890        mpz_init(*mpz_t_obj);
2891        sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
2892        SvREADONLY_on(obj);
2893      }
2894 
2895      if(SV_IS_IOK(b)) {
2896        if(SvUOK(b)) {
2897          if(third == &PL_sv_yes) {
2898            if(ui) {
2899              mpz_ui_pow_ui(*mpz_t_obj, SvUVX(b), ui);
2900              return obj_ref;
2901            }
2902            croak("Exponent does not fit into unsigned long int in Math::GMPz::overload_pow");
2903          }
2904          mpz_pow_ui(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))) , SvUVX(b));
2905          return obj_ref;
2906        }
2907 
2908        if(SvIVX(b) < 0) croak("Negative argument supplied to Math::GMPz::overload_pow");
2909        if(third == &PL_sv_yes) {
2910          if(ui) {
2911            mpz_ui_pow_ui(*mpz_t_obj, SvUVX(b), ui);
2912            return obj_ref;
2913          }
2914          croak("Exponent does not fit into unsigned long int in Math::GMPz::overload_pow");
2915        }
2916        mpz_pow_ui(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), SvUVX(b));
2917        return obj_ref;
2918      }
2919 
2920      if(sv_isobject(b)) {
2921        const char *h = HvNAME(SvSTASH(SvRV(b)));
2922        if(strEQ(h, "Math::GMPz")) {
2923          if(mpz_fits_uint_p(*(INT2PTR(mpz_t *, SvIVX(SvRV(b)))))) {
2924            New(1, mpz_t_obj, 1, mpz_t);
2925            if(mpz_t_obj == NULL) croak("Failed to allocate memory in overload_pow function");
2926            obj_ref = newSV(0);
2927            obj = newSVrv(obj_ref, "Math::GMPz");
2928            mpz_init(*mpz_t_obj);
2929            sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
2930            SvREADONLY_on(obj);
2931            ui = mpz_get_ui(*(INT2PTR(mpz_t *, SvIVX(SvRV(b)))));
2932            mpz_pow_ui(*mpz_t_obj, *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), ui);
2933            return obj_ref;
2934          }
2935        }
2936        if(strEQ(h, "Math::MPFR")) {
2937          _overload_callback("Math::MPFR::overload_pow", "Math::GMPz:overload_pow", &PL_sv_yes);
2938        }
2939      }
2940 
2941      croak("Invalid argument supplied to Math::GMPz::overload_pow. Exponent must fit into unsigned long (or be a Math::MPFR object)");
2942 }
2943 
overload_sqrt(pTHX_ mpz_t * p,SV * second,SV * third)2944 SV * overload_sqrt(pTHX_ mpz_t * p, SV * second, SV * third) {
2945      mpz_t * mpz_t_obj;
2946      SV * obj_ref, * obj;
2947 
2948      New(1, mpz_t_obj, 1, mpz_t);
2949      if(mpz_t_obj == NULL) croak("Failed to allocate memory in overload_sqrt function");
2950      obj_ref = newSV(0);
2951      obj = newSVrv(obj_ref, "Math::GMPz");
2952      mpz_init(*mpz_t_obj);
2953 
2954      if(mpz_cmp_ui(*p, 0) < 0) croak("Negative value supplied as argument to overload_sqrt");
2955      mpz_sqrt(*mpz_t_obj, *p);
2956      sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
2957      SvREADONLY_on(obj);
2958      return obj_ref;
2959 }
2960 
overload_and(pTHX_ mpz_t * a,SV * b,SV * third,...)2961 SV * overload_and(pTHX_ mpz_t * a, SV * b, SV * third, ...) {
2962      mpz_t * mpz_t_obj;
2963      SV * obj_ref, * obj;
2964      MBI_DECLARATIONS
2965      MBI_GMP_DECLARATIONS
2966 
2967 #if defined(USE_QUADMATH)
2968 
2969      char * buffer;
2970      int returned;
2971      __float128 buffer_size;
2972      __float128 ld;
2973 
2974 #elif defined(USE_LONG_DOUBLE)
2975 
2976      char * buffer;
2977      long double buffer_size;
2978      long double ld;
2979 
2980 #endif
2981 
2982      New(1, mpz_t_obj, 1, mpz_t);
2983      if(mpz_t_obj == NULL) croak("Failed to allocate memory in overload_and function");
2984      obj_ref = newSV(0);
2985      obj = newSVrv(obj_ref, "Math::GMPz");
2986      mpz_init(*mpz_t_obj);
2987      sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
2988      SvREADONLY_on(obj);
2989 
2990 #ifdef MATH_GMPZ_NEED_LONG_LONG_INT
2991      if(SV_IS_IOK(b)) {
2992        Rmpz_set_IV(aTHX_ mpz_t_obj, b);
2993        mpz_and(*mpz_t_obj, *a, *mpz_t_obj);
2994        return obj_ref;
2995      }
2996 #else
2997      if(SV_IS_IOK(b)) {
2998        if(SvUOK(b)) {
2999          mpz_set_ui(*mpz_t_obj, SvUVX(b));
3000          mpz_and(*mpz_t_obj, *a, *mpz_t_obj);
3001          return obj_ref;
3002        }
3003 
3004        mpz_set_si(*mpz_t_obj, SvIVX(b));
3005        mpz_and(*mpz_t_obj, *a, *mpz_t_obj);
3006        return obj_ref;
3007      }
3008 #endif
3009 
3010      if(SV_IS_POK(b)) {
3011        if(mpz_set_str(*mpz_t_obj, SvPV_nolen(b), 0))
3012          croak("Invalid string (%s) supplied to Math::GMPz::overload_and", SvPV_nolen(b));
3013        mpz_and(*mpz_t_obj, *a, *mpz_t_obj);
3014        return obj_ref;
3015      }
3016 
3017      if(SV_IS_NOK(b)) {
3018 
3019 #if defined(USE_QUADMATH)
3020 
3021        ld = (__float128)SvNVX(b) >= 0 ? floorq((__float128)SvNVX(b)) : ceilq((__float128)SvNVX(b));
3022        if(ld != ld) croak("In Math::GMPz::overload_and, cannot coerce a NaN to a Math::GMPz value");
3023        if(ld != 0 && (ld / ld != 1))
3024          croak("In Math::GMPz::overload_and, cannot coerce an Inf to a Math::GMPz value");
3025 
3026        buffer_size = ld < 0.0Q ? ld * -1.0Q : ld;
3027        buffer_size = ceilq(logq(buffer_size + 1) / 2.30258509299404568401799145468436418Q);
3028 
3029        Newxz(buffer, (int)buffer_size + 5, char);
3030 
3031        returned = quadmath_snprintf(buffer, (size_t)buffer_size + 5, "%.0Qf", ld);
3032        if(returned < 0) croak("In Math::GMPz::overload_and, encoding error in quadmath_snprintf function");
3033        if(returned >= buffer_size + 5) croak("In Math::GMPz::overload_and, buffer given to quadmath_snprintf function was too small");
3034        mpz_init_set_str(*mpz_t_obj, buffer, 10);
3035        Safefree(buffer);
3036 
3037 #elif defined(USE_LONG_DOUBLE)
3038 
3039        ld = (long double)SvNVX(b) >= 0 ? floorl((long double)SvNVX(b)) : ceill((long double)SvNVX(b));
3040        if(ld != ld) croak("In Math::GMPz::overload_and, cannot coerce a NaN to a Math::GMPz value");
3041        if(ld != 0 && (ld / ld != 1))
3042          croak("In Math::GMPz::overload_and, cannot coerce an Inf to a Math::GMPz value");
3043 
3044        buffer_size = ld < 0.0L ? ld * -1.0L : ld;
3045        buffer_size = ceill(logl(buffer_size + 1) / 2.30258509299404568401799145468436418L);
3046 
3047        Newxz(buffer, (int)buffer_size + 5, char);
3048 
3049        if(sprintf(buffer, "%.0Lf", ld) >= (int)buffer_size + 5) croak("In Math::GMPz::overload_and, buffer overflow in sprintf function");
3050        mpz_init_set_str(*mpz_t_obj, buffer, 10);
3051        Safefree(buffer);
3052 #else
3053        double d = SvNVX(b);
3054        if(d != d) croak("In Math::GMPz::overload_and, cannot coerce a NaN to a Math::GMPz value");
3055        if(d != 0 && (d / d != 1))
3056          croak("In Math::GMPz::overload_and, cannot coerce an Inf to a Math::GMPz value");
3057        mpz_set_d(*mpz_t_obj, d);
3058 #endif
3059        mpz_and(*mpz_t_obj, *a, *mpz_t_obj);
3060        return obj_ref;
3061      }
3062 
3063      if(sv_isobject(b)) {
3064        const char *h = HvNAME(SvSTASH(SvRV(b)));
3065        if(strEQ(h, "Math::GMPz")) {
3066          mpz_and(*mpz_t_obj, *a, *(INT2PTR(mpz_t *, SvIVX(SvRV(b)))));
3067          return obj_ref;
3068        }
3069        if(strEQ(h, "Math::BigInt")) {
3070          VALIDATE_MBI_OBJECT
3071            croak("Invalid Math::BigInt object supplied to Math::GMPz::overload_and");
3072 
3073          MBI_GMP_INSERT
3074 
3075          if(mpz) {
3076            if(strEQ("-", sign)) {
3077              mpz_neg((mpz_ptr)mpz, (mpz_srcptr)mpz);
3078              mpz_and(*mpz_t_obj, *a, (mpz_srcptr)mpz);
3079              mpz_neg((mpz_ptr)mpz, (mpz_srcptr)mpz); /* restore to original */
3080              return obj_ref;
3081            }
3082 
3083            mpz_and(*mpz_t_obj, *a, (mpz_srcptr)mpz);
3084            return obj_ref;
3085          }
3086 
3087          mpz_set_str(*mpz_t_obj, SvPV_nolen(b), 0);
3088          mpz_and(*mpz_t_obj, *a, *mpz_t_obj);
3089          return obj_ref;
3090        }
3091      }
3092 
3093      croak("Invalid argument supplied to Math::GMPz::overload_and");
3094 }
3095 
overload_ior(pTHX_ mpz_t * a,SV * b,SV * third,...)3096 SV * overload_ior(pTHX_ mpz_t * a, SV * b, SV * third, ...) {
3097      mpz_t * mpz_t_obj;
3098      SV * obj_ref, * obj;
3099      MBI_DECLARATIONS
3100      MBI_GMP_DECLARATIONS
3101 
3102 #if defined(USE_QUADMATH)
3103 
3104      char * buffer;
3105      int returned;
3106      __float128 buffer_size;
3107      __float128 ld;
3108 
3109 #elif defined(USE_LONG_DOUBLE)
3110 
3111      char * buffer;
3112      long double buffer_size;
3113      long double ld;
3114 
3115 #endif
3116 
3117      New(1, mpz_t_obj, 1, mpz_t);
3118      if(mpz_t_obj == NULL) croak("Failed to allocate memory in overload_ior function");
3119      obj_ref = newSV(0);
3120      obj = newSVrv(obj_ref, "Math::GMPz");
3121      mpz_init(*mpz_t_obj);
3122      sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
3123      SvREADONLY_on(obj);
3124 
3125 #ifdef MATH_GMPZ_NEED_LONG_LONG_INT
3126      if(SV_IS_IOK(b)) {
3127        Rmpz_set_IV(aTHX_ mpz_t_obj, b);
3128        mpz_ior(*mpz_t_obj, *a, *mpz_t_obj);
3129        return obj_ref;
3130      }
3131 #else
3132      if(SV_IS_IOK(b)) {
3133        if(SvUOK(b)) {
3134          mpz_set_ui(*mpz_t_obj, SvUVX(b));
3135          mpz_ior(*mpz_t_obj, *a, *mpz_t_obj);
3136          return obj_ref;
3137        }
3138 
3139        mpz_set_si(*mpz_t_obj, SvIVX(b));
3140        mpz_ior(*mpz_t_obj, *a, *mpz_t_obj);
3141        return obj_ref;
3142      }
3143 #endif
3144 
3145      if(SV_IS_POK(b)) {
3146        if(mpz_set_str(*mpz_t_obj, SvPV_nolen(b), 0))
3147          croak("Invalid string (%s) supplied to Math::GMPz::overload_ior", SvPV_nolen(b));
3148        mpz_ior(*mpz_t_obj, *a, *mpz_t_obj);
3149        return obj_ref;
3150      }
3151 
3152      if(SV_IS_NOK(b)) {
3153 
3154 #if defined(USE_QUADMATH)
3155 
3156        ld = (__float128)SvNVX(b) >= 0 ? floorq((__float128)SvNVX(b)) : ceilq((__float128)SvNVX(b));
3157        if(ld != ld) croak("In Math::GMPz::overload_ior, cannot coerce a NaN to a Math::GMPz value");
3158        if(ld != 0 && (ld / ld != 1))
3159          croak("In Math::GMPz::overload_ior, cannot coerce an Inf to a Math::GMPz value");
3160 
3161        buffer_size = ld < 0.0Q ? ld * -1.0Q : ld;
3162        buffer_size = ceilq(logq(buffer_size + 1) / 2.30258509299404568401799145468436418Q);
3163 
3164        Newxz(buffer, (int)buffer_size + 5, char);
3165 
3166        returned = quadmath_snprintf(buffer, (size_t)buffer_size + 5, "%.0Qf", ld);
3167        if(returned < 0) croak("In Math::GMPz::overload_ior, encoding error in quadmath_snprintf function");
3168        if(returned >= buffer_size + 5) croak("In Math::GMPz::overload_ior, buffer given to quadmath_snprintf function was too small");
3169        mpz_init_set_str(*mpz_t_obj, buffer, 10);
3170        Safefree(buffer);
3171 
3172 #elif defined(USE_LONG_DOUBLE)
3173 
3174        ld = (long double)SvNVX(b) >= 0 ? floorl((long double)SvNVX(b)) : ceill((long double)SvNVX(b));
3175        if(ld != ld) croak("In Math::GMPz::overload_ior, cannot coerce a NaN to a Math::GMPz value");
3176        if(ld != 0 && (ld / ld != 1))
3177          croak("In Math::GMPz::overload_ior, cannot coerce an Inf to a Math::GMPz value");
3178 
3179        buffer_size = ld < 0.0L ? ld * -1.0L : ld;
3180        buffer_size = ceill(logl(buffer_size + 1) / 2.30258509299404568401799145468436418L);
3181 
3182        Newxz(buffer, (int)buffer_size + 5, char);
3183 
3184        if(sprintf(buffer, "%.0Lf", ld) >= (int)buffer_size + 5) croak("In Math::GMPz::overload_ior, buffer overflow in sprintf function");
3185        mpz_init_set_str(*mpz_t_obj, buffer, 10);
3186        Safefree(buffer);
3187 #else
3188        double d = SvNVX(b);
3189        if(d != d) croak("In Math::GMPz::overload_ior, cannot coerce a NaN to a Math::GMPz value");
3190        if(d != 0 && (d / d != 1))
3191          croak("In Math::GMPz::overload_ior, cannot coerce an Inf to a Math::GMPz value");
3192        mpz_set_d(*mpz_t_obj, d);
3193 #endif
3194        mpz_ior(*mpz_t_obj, *a, *mpz_t_obj);
3195        return obj_ref;
3196      }
3197 
3198      if(sv_isobject(b)) {
3199        const char *h = HvNAME(SvSTASH(SvRV(b)));
3200        if(strEQ(h, "Math::GMPz")) {
3201          mpz_ior(*mpz_t_obj, *a, *(INT2PTR(mpz_t *, SvIVX(SvRV(b)))));
3202          return obj_ref;
3203        }
3204        if(strEQ(h, "Math::BigInt")) {
3205          VALIDATE_MBI_OBJECT
3206            croak("Invalid Math::BigInt object supplied to Math::GMPz::overload_ior");
3207 
3208          MBI_GMP_INSERT
3209 
3210          if(mpz) {
3211            if(strEQ("-", sign)) {
3212              mpz_neg((mpz_ptr)mpz, (mpz_srcptr)mpz);
3213              mpz_ior(*mpz_t_obj, *a, (mpz_srcptr)mpz);
3214              mpz_neg((mpz_ptr)mpz, (mpz_srcptr)mpz); /* restore to original */
3215              return obj_ref;
3216            }
3217 
3218            mpz_ior(*mpz_t_obj, *a, (mpz_srcptr)mpz);
3219            return obj_ref;
3220          }
3221 
3222          mpz_set_str(*mpz_t_obj, SvPV_nolen(b), 0);
3223          mpz_ior(*mpz_t_obj, *a, *mpz_t_obj);
3224          return obj_ref;
3225        }
3226      }
3227 
3228      croak("Invalid argument supplied to Math::GMPz::overload_ior");
3229 }
3230 
overload_xor(pTHX_ mpz_t * a,SV * b,SV * third,...)3231 SV * overload_xor(pTHX_ mpz_t * a, SV * b, SV * third, ...) {
3232      mpz_t * mpz_t_obj;
3233      SV * obj_ref, * obj;
3234      MBI_DECLARATIONS
3235      MBI_GMP_DECLARATIONS
3236 
3237 #if defined(USE_QUADMATH)
3238 
3239      char * buffer;
3240      int returned;
3241      __float128 buffer_size;
3242      __float128 ld;
3243 
3244 #elif defined(USE_LONG_DOUBLE)
3245 
3246      char * buffer;
3247      long double buffer_size;
3248      long double ld;
3249 
3250 #endif
3251 
3252      New(1, mpz_t_obj, 1, mpz_t);
3253      if(mpz_t_obj == NULL) croak("Failed to allocate memory in overload_xor function");
3254      obj_ref = newSV(0);
3255      obj = newSVrv(obj_ref, "Math::GMPz");
3256      mpz_init(*mpz_t_obj);
3257      sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
3258      SvREADONLY_on(obj);
3259 
3260 #ifdef MATH_GMPZ_NEED_LONG_LONG_INT
3261      if(SV_IS_IOK(b)) {
3262        Rmpz_set_IV(aTHX_ mpz_t_obj, b);
3263        mpz_xor(*mpz_t_obj, *a, *mpz_t_obj);
3264        return obj_ref;
3265      }
3266 #else
3267      if(SV_IS_IOK(b)) {
3268        if(SvUOK(b)) {
3269          mpz_set_ui(*mpz_t_obj, SvUVX(b));
3270          mpz_xor(*mpz_t_obj, *a, *mpz_t_obj);
3271          return obj_ref;
3272        }
3273 
3274        mpz_set_si(*mpz_t_obj, SvIVX(b));
3275        mpz_xor(*mpz_t_obj, *a, *mpz_t_obj);
3276        return obj_ref;
3277      }
3278 #endif
3279 
3280      if(SV_IS_POK(b)) {
3281        if(mpz_set_str(*mpz_t_obj, SvPV_nolen(b), 0))
3282          croak("Invalid string (%s) supplied to Math::GMPz::overload_xor", SvPV_nolen(b));
3283        mpz_xor(*mpz_t_obj, *a, *mpz_t_obj);
3284        return obj_ref;
3285      }
3286 
3287      if(SV_IS_NOK(b)) {
3288 
3289 #if defined(USE_QUADMATH)
3290 
3291        ld = (__float128)SvNVX(b) >= 0 ? floorq((__float128)SvNVX(b)) : ceilq((__float128)SvNVX(b));
3292        if(ld != ld) croak("In Math::GMPz::overload_xor, cannot coerce a NaN to a Math::GMPz value");
3293        if(ld != 0 && (ld / ld != 1))
3294          croak("In Math::GMPz::overload_xor, cannot coerce an Inf to a Math::GMPz value");
3295 
3296        buffer_size = ld < 0.0Q ? ld * -1.0Q : ld;
3297        buffer_size = ceilq(logq(buffer_size + 1) / 2.30258509299404568401799145468436418Q);
3298 
3299        Newxz(buffer, (int)buffer_size + 5, char);
3300 
3301        returned = quadmath_snprintf(buffer, (size_t)buffer_size + 5, "%.0Qf", ld);
3302        if(returned < 0) croak("In Math::GMPz::overload_xor, encoding error in quadmath_snprintf function");
3303        if(returned >= buffer_size + 5) croak("In Math::GMPz::overload_xor, buffer given to quadmath_snprintf function was too small");
3304        mpz_init_set_str(*mpz_t_obj, buffer, 10);
3305        Safefree(buffer);
3306 
3307 #elif defined(USE_LONG_DOUBLE)
3308 
3309        ld = (long double)SvNVX(b) >= 0 ? floorl((long double)SvNVX(b)) : ceill((long double)SvNVX(b));
3310        if(ld != ld) croak("In Math::GMPz::overload_xor, cannot coerce a NaN to a Math::GMPz value");
3311        if(ld != 0 && (ld / ld != 1))
3312          croak("In Math::GMPz::overload_xor, cannot coerce an Inf to a Math::GMPz value");
3313 
3314        buffer_size = ld < 0.0L ? ld * -1.0L : ld;
3315        buffer_size = ceill(logl(buffer_size + 1) / 2.30258509299404568401799145468436418L);
3316 
3317        Newxz(buffer, (int)buffer_size + 5, char);
3318 
3319        if(sprintf(buffer, "%.0Lf", ld) >= (int)buffer_size + 5) croak("In Math::GMPz::overload_xor, buffer overflow in sprintf function");
3320        mpz_init_set_str(*mpz_t_obj, buffer, 10);
3321        Safefree(buffer);
3322 #else
3323        double d = SvNVX(b);
3324        if(d != d) croak("In Math::GMPz::overload_xor, cannot coerce a NaN to a Math::GMPz value");
3325        if(d != 0 && (d / d != 1))
3326          croak("In Math::GMPz::overload_xor, cannot coerce an Inf to a Math::GMPz value");
3327        mpz_set_d(*mpz_t_obj, d);
3328 #endif
3329        mpz_xor(*mpz_t_obj, *a, *mpz_t_obj);
3330        return obj_ref;
3331      }
3332 
3333      if(sv_isobject(b)) {
3334        const char *h = HvNAME(SvSTASH(SvRV(b)));
3335        if(strEQ(h, "Math::GMPz")) {
3336          mpz_xor(*mpz_t_obj, *a, *(INT2PTR(mpz_t *, SvIVX(SvRV(b)))));
3337          return obj_ref;
3338        }
3339        if(strEQ(h, "Math::BigInt")) {
3340          VALIDATE_MBI_OBJECT
3341            croak("Invalid Math::BigInt object supplied to Math::GMPz::overload_xor");
3342 
3343          MBI_GMP_INSERT
3344 
3345          if(mpz) {
3346            if(strEQ("-", sign)) {
3347              mpz_neg((mpz_ptr)mpz, (mpz_srcptr)mpz);
3348              mpz_xor(*mpz_t_obj, *a, (mpz_srcptr)mpz);
3349              mpz_neg((mpz_ptr)mpz, (mpz_srcptr)mpz); /* restore to original */
3350              return obj_ref;
3351            }
3352 
3353            mpz_xor(*mpz_t_obj, *a, (mpz_srcptr)mpz);
3354            return obj_ref;
3355          }
3356 
3357          mpz_set_str(*mpz_t_obj, SvPV_nolen(b), 0);
3358          mpz_xor(*mpz_t_obj, *a, *mpz_t_obj);
3359          return obj_ref;
3360        }
3361      }
3362 
3363      croak("Invalid argument supplied to Math::GMPz::overload_xor");
3364 }
3365 
overload_com(pTHX_ mpz_t * p,SV * second,SV * third)3366 SV * overload_com(pTHX_ mpz_t * p, SV * second, SV * third) {
3367      mpz_t * mpz_t_obj;
3368      SV * obj_ref, * obj;
3369 
3370      New(1, mpz_t_obj, 1, mpz_t);
3371      if(mpz_t_obj == NULL) croak("Failed to allocate memory in overload_com function");
3372      obj_ref = newSV(0);
3373      obj = newSVrv(obj_ref, "Math::GMPz");
3374      mpz_init(*mpz_t_obj);
3375 
3376      mpz_com(*mpz_t_obj, *p);
3377      sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
3378      SvREADONLY_on(obj);
3379      return obj_ref;
3380 }
3381 
my_cmp_z(mpq_t * p,mpz_t * z)3382 int my_cmp_z(mpq_t * p, mpz_t *z) {
3383     int ret;
3384     mpz_t temp;
3385 
3386     mpz_init_set(temp, *z);
3387     mpz_mul(temp, temp, mpq_denref(*p));
3388     ret = mpz_cmp(mpq_numref(*p), temp);
3389     mpz_clear(temp);
3390     return ret;
3391 }
3392 
overload_gt(pTHX_ mpz_t * a,SV * b,SV * third)3393 SV * overload_gt(pTHX_ mpz_t * a, SV * b, SV * third) {
3394      int ret;
3395      mpz_t t;
3396      MBI_DECLARATIONS
3397      MBI_GMP_DECLARATIONS
3398 
3399      if(SV_IS_IOK(b)) {
3400        ret = Rmpz_cmp_IV(aTHX_ a, b);
3401        if(third == &PL_sv_yes) ret *= -1;
3402        if(ret > 0) return newSViv(1);
3403        return newSViv(0);
3404      }
3405 
3406 
3407      if(SV_IS_POK(b)) {
3408        ret = _is_infstring(SvPV_nolen(b));
3409        if(ret) {
3410          if(ret > 0) return newSViv(0);
3411          return newSViv(1);
3412        }
3413 
3414        if(mpz_init_set_str(t, SvPV_nolen(b), 0))
3415          croak("Invalid string (%s) supplied to Math::GMPz::overload_gt", SvPV_nolen(b));
3416        ret = mpz_cmp(*a, t);
3417        mpz_clear(t);
3418        if(third == &PL_sv_yes) ret *= -1;
3419        if(ret > 0) return newSViv(1);
3420        return newSViv(0);
3421      }
3422 
3423      if(SV_IS_NOK(b)) {
3424        ret = Rmpz_cmp_NV(aTHX_ a, b);
3425        if(third == &PL_sv_yes) ret *= -1;
3426        if(ret > 0) return newSViv(1);
3427        return newSViv(0);
3428      }
3429 
3430      if(sv_isobject(b)) {
3431        const char *h = HvNAME(SvSTASH(SvRV(b)));
3432        if(strEQ(h, "Math::GMPz")) {
3433          ret = mpz_cmp(*a, *(INT2PTR(mpz_t *, SvIVX(SvRV(b)))));
3434          if(ret > 0) return newSViv(1);
3435          return newSViv(0);
3436        }
3437 
3438        if(strEQ(h, "Math::GMPq")) {
3439 #if __GNU_MP_RELEASE < 60099
3440          ret = my_cmp_z(INT2PTR(mpq_t *, SvIVX(SvRV(b))), a);
3441          if(ret < 0) return newSViv(1);
3442          return newSViv(0);
3443 #else
3444          ret = mpq_cmp_z(*(INT2PTR(mpq_t *, SvIVX(SvRV(b)))), *a);
3445          if(ret < 0) return newSViv(1);
3446          return newSViv(0);
3447 #endif
3448        }
3449 
3450        if(strEQ(h, "Math::BigInt")) {
3451          VALIDATE_MBI_OBJECT
3452            croak("Invalid Math::BigInt object supplied to Math::GMPz::overload_gt");
3453 
3454          MBI_GMP_INSERT
3455 
3456          if(mpz) {
3457            if(strEQ("-", sign)) {
3458              mpz_neg((mpz_ptr)mpz, (mpz_srcptr)mpz);
3459              ret = mpz_cmp(*a, (mpz_srcptr)mpz);
3460              mpz_neg((mpz_ptr)mpz, (mpz_srcptr)mpz); /* restore to original */
3461              if(ret > 0) return newSViv(1);
3462              return newSViv(0);
3463            }
3464 
3465            ret = mpz_cmp(*a, (mpz_srcptr)mpz);
3466            if(ret > 0) return newSViv(1);
3467            return newSViv(0);
3468          }
3469 
3470          mpz_init_set_str(t, SvPV_nolen(b), 0);
3471          ret = mpz_cmp(*a, t);
3472          mpz_clear(t);
3473          /* if(third == &PL_sv_yes) ret *= -1; */
3474          if(ret > 0) return newSViv(1);
3475          return newSViv(0);
3476        }
3477      }
3478 
3479      croak("Invalid argument supplied to Math::GMPz::overload_gt");
3480 }
3481 
overload_gte(pTHX_ mpz_t * a,SV * b,SV * third)3482 SV * overload_gte(pTHX_ mpz_t * a, SV * b, SV * third) {
3483      int ret;
3484      mpz_t t;
3485      MBI_DECLARATIONS
3486      MBI_GMP_DECLARATIONS
3487 
3488      if(SV_IS_IOK(b)) {
3489        ret = Rmpz_cmp_IV(aTHX_ a, b);
3490        if(third == &PL_sv_yes) ret *= -1;
3491        if(ret >= 0) return newSViv(1);
3492        return newSViv(0);
3493      }
3494 
3495      if(SV_IS_POK(b)) {
3496        ret = _is_infstring(SvPV_nolen(b));
3497        if(ret) {
3498          if(ret > 0) return newSViv(0);
3499          return newSViv(1);
3500        }
3501 
3502        if(mpz_init_set_str(t, SvPV_nolen(b), 0))
3503          croak("Invalid string (%s) supplied to Math::GMPz::overload_gte", SvPV_nolen(b));
3504        ret = mpz_cmp(*a, t);
3505        mpz_clear(t);
3506        if(third == &PL_sv_yes) ret *= -1;
3507        if(ret >= 0) return newSViv(1);
3508        return newSViv(0);
3509      }
3510 
3511      if(SV_IS_NOK(b)) {
3512        ret = Rmpz_cmp_NV(aTHX_ a, b);
3513        if(third == &PL_sv_yes) ret *= -1;
3514        if(ret >= 0) return newSViv(1);
3515        return newSViv(0);
3516      }
3517 
3518      if(sv_isobject(b)) {
3519        const char *h = HvNAME(SvSTASH(SvRV(b)));
3520        if(strEQ(h, "Math::GMPz")) {
3521          ret = mpz_cmp(*a, *(INT2PTR(mpz_t *, SvIVX(SvRV(b)))));
3522          if(ret >= 0) return newSViv(1);
3523          return newSViv(0);
3524        }
3525 
3526        if(strEQ(h, "Math::GMPq")) {
3527 #if __GNU_MP_RELEASE < 60099
3528          ret = my_cmp_z(INT2PTR(mpq_t *, SvIVX(SvRV(b))), a);
3529          if(ret <= 0) return newSViv(1);
3530          return newSViv(0);
3531 #else
3532          ret = mpq_cmp_z(*(INT2PTR(mpq_t *, SvIVX(SvRV(b)))), *a);
3533          if(ret <= 0) return newSViv(1);
3534          return newSViv(0);
3535 #endif
3536        }
3537 
3538        if(strEQ(h, "Math::BigInt")) {
3539          VALIDATE_MBI_OBJECT
3540            croak("Invalid Math::BigInt object supplied to Math::GMPz::overload_gte");
3541 
3542          MBI_GMP_INSERT
3543 
3544          if(mpz) {
3545            if(strEQ("-", sign)) {
3546              mpz_neg((mpz_ptr)mpz, (mpz_srcptr)mpz);
3547              ret = mpz_cmp(*a, (mpz_srcptr)mpz);
3548              mpz_neg((mpz_ptr)mpz, (mpz_srcptr)mpz); /* restore to original */
3549              if(ret >= 0) return newSViv(1);
3550              return newSViv(0);
3551            }
3552 
3553            ret = mpz_cmp(*a, (mpz_srcptr)mpz);
3554            if(ret >= 0) return newSViv(1);
3555            return newSViv(0);
3556          }
3557 
3558          mpz_init_set_str(t, SvPV_nolen(b), 0);
3559          ret = mpz_cmp(*a, t);
3560          mpz_clear(t);
3561          /* if(third == &PL_sv_yes) ret *= -1; */
3562          if(ret >= 0) return newSViv(1);
3563          return newSViv(0);
3564        }
3565      }
3566 
3567      croak("Invalid argument supplied to Math::GMPz::overload_gte");
3568 }
3569 
overload_lt(pTHX_ mpz_t * a,SV * b,SV * third)3570 SV * overload_lt(pTHX_ mpz_t * a, SV * b, SV * third) {
3571      int ret;
3572      mpz_t t;
3573      MBI_DECLARATIONS
3574      MBI_GMP_DECLARATIONS
3575 
3576      if(SV_IS_IOK(b)) {
3577        ret = Rmpz_cmp_IV(aTHX_ a, b);
3578        if(third == &PL_sv_yes) ret *= -1;
3579        if(ret < 0) return newSViv(1);
3580        return newSViv(0);
3581      }
3582 
3583      if(SV_IS_POK(b)) {
3584        ret = _is_infstring(SvPV_nolen(b));
3585        if(ret) {
3586          if(ret > 0) return newSViv(1);
3587          return newSViv(0);
3588        }
3589 
3590        if(mpz_init_set_str(t, SvPV_nolen(b), 0))
3591          croak("Invalid string (%s) supplied to Math::GMPz::overload_lt", SvPV_nolen(b));
3592        ret = mpz_cmp(*a, t);
3593        mpz_clear(t);
3594        if(third == &PL_sv_yes) ret *= -1;
3595        if(ret < 0) return newSViv(1);
3596        return newSViv(0);
3597      }
3598 
3599      if(SV_IS_NOK(b)) {
3600        ret = Rmpz_cmp_NV(aTHX_ a, b);
3601        if(third == &PL_sv_yes) ret *= -1;
3602        if(ret < 0) return newSViv(1);
3603        return newSViv(0);
3604      }
3605 
3606      if(sv_isobject(b)) {
3607        const char *h = HvNAME(SvSTASH(SvRV(b)));
3608        if(strEQ(h, "Math::GMPz")) {
3609          ret = mpz_cmp(*a, *(INT2PTR(mpz_t *, SvIVX(SvRV(b)))));
3610          if(ret < 0) return newSViv(1);
3611          return newSViv(0);
3612        }
3613 
3614        if(strEQ(h, "Math::GMPq")) {
3615 #if __GNU_MP_RELEASE < 60099
3616          ret = my_cmp_z(INT2PTR(mpq_t *, SvIVX(SvRV(b))), a);
3617          if(ret > 0) return newSViv(1);
3618          return newSViv(0);
3619 #else
3620          ret = mpq_cmp_z(*(INT2PTR(mpq_t *, SvIVX(SvRV(b)))), *a);
3621          if(ret > 0) return newSViv(1);
3622          return newSViv(0);
3623 #endif
3624        }
3625 
3626        if(strEQ(h, "Math::BigInt")) {
3627          VALIDATE_MBI_OBJECT
3628            croak("Invalid Math::BigInt object supplied to Math::GMPz::overload_lt");
3629 
3630          MBI_GMP_INSERT
3631 
3632          if(mpz) {
3633            if(strEQ("-", sign)) {
3634              mpz_neg((mpz_ptr)mpz, (mpz_srcptr)mpz);
3635              ret = mpz_cmp(*a, (mpz_srcptr)mpz);
3636              mpz_neg((mpz_ptr)mpz, (mpz_srcptr)mpz); /* restore to original */
3637              if(ret < 0) return newSViv(1);
3638              return newSViv(0);
3639            }
3640 
3641            ret = mpz_cmp(*a, (mpz_srcptr)mpz);
3642            if(ret < 0) return newSViv(1);
3643            return newSViv(0);
3644          }
3645 
3646          mpz_init_set_str(t, SvPV_nolen(b), 0);
3647          ret = mpz_cmp(*a, t);
3648          mpz_clear(t);
3649          /* if(third == &PL_sv_yes) ret *= -1; */
3650          if(ret < 0) return newSViv(1);
3651          return newSViv(0);
3652        }
3653      }
3654 
3655      croak("Invalid argument supplied to Math::GMPz::overload_lt");
3656 }
3657 
overload_lte(pTHX_ mpz_t * a,SV * b,SV * third)3658 SV * overload_lte(pTHX_ mpz_t * a, SV * b, SV * third) {
3659      int ret;
3660      mpz_t t;
3661      MBI_DECLARATIONS
3662      MBI_GMP_DECLARATIONS
3663 
3664      if(SV_IS_IOK(b)) {
3665        ret = Rmpz_cmp_IV(aTHX_ a, b);
3666        if(third == &PL_sv_yes) ret *= -1;
3667        if(ret <= 0) return newSViv(1);
3668        return newSViv(0);
3669      }
3670 
3671      if(SV_IS_POK(b)) {
3672        ret = _is_infstring(SvPV_nolen(b));
3673        if(ret) {
3674          if(ret > 0) return newSViv(1);
3675          return newSViv(0);
3676        }
3677 
3678        if(mpz_init_set_str(t, SvPV_nolen(b), 0))
3679          croak("Invalid string (%s) supplied to Math::GMPz::overload_lte", SvPV_nolen(b));
3680        ret = mpz_cmp(*a, t);
3681        mpz_clear(t);
3682        if(third == &PL_sv_yes) ret *= -1;
3683        if(ret <= 0) return newSViv(1);
3684        return newSViv(0);
3685      }
3686 
3687      if(SV_IS_NOK(b)) {
3688        ret = Rmpz_cmp_NV(aTHX_ a, b);
3689        if(third == &PL_sv_yes) ret *= -1;
3690        if(ret <= 0) return newSViv(1);
3691        return newSViv(0);
3692      }
3693 
3694      if(sv_isobject(b)) {
3695        const char *h = HvNAME(SvSTASH(SvRV(b)));
3696        if(strEQ(h, "Math::GMPz")) {
3697          ret = mpz_cmp(*a, *(INT2PTR(mpz_t *, SvIVX(SvRV(b)))));
3698          if(ret <= 0) return newSViv(1);
3699          return newSViv(0);
3700        }
3701 
3702        if(strEQ(h, "Math::GMPq")) {
3703 #if __GNU_MP_RELEASE < 60099
3704          ret = my_cmp_z(INT2PTR(mpq_t *, SvIVX(SvRV(b))), a);
3705          if(ret >= 0) return newSViv(1);
3706          return newSViv(0);
3707 #else
3708          ret = mpq_cmp_z(*(INT2PTR(mpq_t *, SvIVX(SvRV(b)))), *a);
3709          if(ret >= 0) return newSViv(1);
3710          return newSViv(0);
3711 #endif
3712        }
3713 
3714        if(strEQ(h, "Math::BigInt")) {
3715          VALIDATE_MBI_OBJECT
3716            croak("Invalid Math::BigInt object supplied to Math::GMPz::overload_lte");
3717 
3718          MBI_GMP_INSERT
3719 
3720          if(mpz) {
3721            if(strEQ("-", sign)) {
3722              mpz_neg((mpz_ptr)mpz, (mpz_srcptr)mpz);
3723              ret = mpz_cmp(*a, (mpz_srcptr)mpz);
3724              mpz_neg((mpz_ptr)mpz, (mpz_srcptr)mpz); /* restore to original */
3725              if(ret <= 0) return newSViv(1);
3726              return newSViv(0);
3727            }
3728 
3729            ret = mpz_cmp(*a, (mpz_srcptr)mpz);
3730            if(ret <= 0) return newSViv(1);
3731            return newSViv(0);
3732          }
3733 
3734          mpz_init_set_str(t, SvPV_nolen(b), 0);
3735          ret = mpz_cmp(*a, t);
3736          mpz_clear(t);
3737          /* if(third == &PL_sv_yes) ret *= -1; */
3738          if(ret <= 0) return newSViv(1);
3739          return newSViv(0);
3740        }
3741      }
3742 
3743      croak("Invalid argument supplied to Math::GMPz::overload_lte");
3744 }
3745 
overload_spaceship(pTHX_ mpz_t * a,SV * b,SV * third)3746 SV * overload_spaceship(pTHX_ mpz_t * a, SV * b, SV * third) {
3747      int ret;
3748      mpz_t t;
3749      MBI_DECLARATIONS
3750      MBI_GMP_DECLARATIONS
3751 
3752      if(SV_IS_IOK(b)) {
3753        ret = Rmpz_cmp_IV(aTHX_ a, b);
3754        if(third == &PL_sv_yes) ret *= -1;
3755        return newSViv(ret);
3756      }
3757 
3758      if(SV_IS_POK(b)) {
3759        ret = _is_infstring(SvPV_nolen(b));
3760        if(ret) return newSViv(ret * -1);
3761 
3762        if(mpz_init_set_str(t, SvPV_nolen(b), 0))
3763          croak("Invalid string (%s) supplied to Math::GMPz::overload_spaceship", SvPV_nolen(b));
3764        ret = mpz_cmp(*a, t);
3765        mpz_clear(t);
3766        if(third == &PL_sv_yes) ret *= -1;
3767        return newSViv(ret);
3768      }
3769 
3770      if(SV_IS_NOK(b)) {
3771        ret = Rmpz_cmp_NV(aTHX_ a, b);
3772        if(third == &PL_sv_yes) ret *= -1;
3773        return newSViv(ret);
3774      }
3775 
3776      if(sv_isobject(b)) {
3777        const char *h = HvNAME(SvSTASH(SvRV(b)));
3778        if(strEQ(h, "Math::GMPz")) {
3779          ret = mpz_cmp(*a, *(INT2PTR(mpz_t *, SvIVX(SvRV(b)))));
3780          return newSViv(ret);
3781        }
3782 
3783        if(strEQ(h, "Math::GMPq")) {
3784 #if __GNU_MP_RELEASE < 60099
3785          ret = my_cmp_z(INT2PTR(mpq_t *, SvIVX(SvRV(b))), a);
3786          return newSViv(ret * -1);
3787 #else
3788          ret = mpq_cmp_z(*(INT2PTR(mpq_t *, SvIVX(SvRV(b)))), *a);
3789          return newSViv(ret * -1);
3790 #endif
3791        }
3792 
3793        if(strEQ(h, "Math::BigInt")) {
3794          VALIDATE_MBI_OBJECT
3795            croak("Invalid Math::BigInt object supplied to Math::GMPz::overload_spaceship");
3796 
3797          MBI_GMP_INSERT
3798 
3799          if(mpz) {
3800            if(strEQ("-", sign)) {
3801              mpz_neg((mpz_ptr)mpz, (mpz_srcptr)mpz);
3802              ret = mpz_cmp(*a, (mpz_srcptr)mpz);
3803              mpz_neg((mpz_ptr)mpz, (mpz_srcptr)mpz); /* restore to original */
3804              return newSViv(ret);
3805            }
3806 
3807            ret = mpz_cmp(*a, (mpz_srcptr)mpz);
3808            return newSViv(ret);
3809          }
3810 
3811          mpz_init_set_str(t, SvPV_nolen(b), 0);
3812          ret = mpz_cmp(*a, t);
3813          mpz_clear(t);
3814          /* if(third == &PL_sv_yes) ret *= -1; */
3815          return newSViv(ret);
3816        }
3817      }
3818 
3819      croak("Invalid argument supplied to Math::GMPz::overload_spaceship");
3820 }
3821 
overload_equiv(pTHX_ mpz_t * a,SV * b,SV * third)3822 SV * overload_equiv(pTHX_ mpz_t * a, SV * b, SV * third) {
3823      int ret = 0;
3824      mpz_t t;
3825      MBI_DECLARATIONS
3826      MBI_GMP_DECLARATIONS
3827 
3828      if(SV_IS_IOK(b)) {
3829        ret = Rmpz_cmp_IV(aTHX_ a, b);
3830        if(ret == 0) return newSViv(1);
3831        return newSViv(0);
3832      }
3833 
3834      if(SV_IS_POK(b)) {
3835        if(_is_infstring(SvPV_nolen(b))) return newSViv(0);
3836        if(mpz_init_set_str(t, SvPV_nolen(b), 0))
3837          croak("Invalid string (%s) supplied to Math::GMPz::overload_equiv", SvPV_nolen(b));
3838        ret = mpz_cmp(*a, t);
3839        mpz_clear(t);
3840        if(ret == 0) return newSViv(1);
3841        return newSViv(0);
3842      }
3843 
3844      if(SV_IS_NOK(b)) { /* do not use the NV if POK is set */
3845        ret = Rmpz_cmp_NV(aTHX_ a, b);
3846        if(ret == 0) return newSViv(1);
3847        return newSViv(0);
3848      }
3849 
3850      if(sv_isobject(b)) {
3851        const char *h = HvNAME(SvSTASH(SvRV(b)));
3852        if(strEQ(h, "Math::GMPz")) {
3853          ret = mpz_cmp(*a, *(INT2PTR(mpz_t *, SvIVX(SvRV(b)))));
3854          if(ret == 0) return newSViv(1);
3855          return newSViv(0);
3856        }
3857 
3858        if(strEQ(h, "Math::GMPq")) {
3859 #if __GNU_MP_RELEASE < 60099
3860          ret = my_cmp_z(INT2PTR(mpq_t *, SvIVX(SvRV(b))), a);
3861          if(ret == 0) return newSViv(1);
3862          return newSViv(0);
3863 #else
3864          ret = mpq_cmp_z(*(INT2PTR(mpq_t *, SvIVX(SvRV(b)))), *a);
3865          if(ret == 0) return newSViv(1);
3866          return newSViv(0);
3867 #endif
3868        }
3869 
3870        if(strEQ(h, "Math::BigInt")) {
3871          VALIDATE_MBI_OBJECT
3872            croak("Invalid Math::BigInt object supplied to Math::GMPz::overload_equiv");
3873 
3874          MBI_GMP_INSERT
3875 
3876          if(mpz) {
3877            if(strEQ("-", sign)) {
3878              mpz_neg((mpz_ptr)mpz, (mpz_srcptr)mpz);
3879              ret = mpz_cmp(*a, (mpz_srcptr)mpz);
3880              mpz_neg((mpz_ptr)mpz, (mpz_srcptr)mpz); /* restore to original */
3881              if(ret == 0) return newSViv(1);
3882              return newSViv(0);
3883            }
3884 
3885            ret = mpz_cmp(*a, (mpz_srcptr)mpz);
3886            if(ret == 0) return newSViv(1);
3887            return newSViv(0);
3888          }
3889 
3890          mpz_init_set_str(t, SvPV_nolen(b), 0);
3891          ret = mpz_cmp(*a, t);
3892          mpz_clear(t);
3893          if(ret == 0) return newSViv(1);
3894          return newSViv(0);
3895        }
3896      }
3897 
3898      croak("Invalid argument supplied to Math::GMPz::overload_equiv");
3899 }
3900 
overload_not_equiv(pTHX_ mpz_t * a,SV * b,SV * third)3901 SV * overload_not_equiv(pTHX_ mpz_t * a, SV * b, SV * third) {
3902      int ret = 0;
3903      mpz_t t;
3904      MBI_DECLARATIONS
3905      MBI_GMP_DECLARATIONS
3906 
3907      if(SV_IS_IOK(b)) {
3908        ret = Rmpz_cmp_IV(aTHX_ a, b);
3909        if(ret != 0) return newSViv(1);
3910        return newSViv(0);
3911      }
3912 
3913      if(SV_IS_POK(b)) {
3914        if(_is_infstring(SvPV_nolen(b))) return newSViv(1);
3915        if(mpz_init_set_str(t, SvPV_nolen(b), 0))
3916          croak("Invalid string (%s) supplied to Math::GMPz::overload_not_equiv", SvPV_nolen(b));
3917        ret = mpz_cmp(*a, t);
3918        mpz_clear(t);
3919        if(ret != 0) return newSViv(1);
3920        return newSViv(0);
3921      }
3922 
3923      if(SV_IS_NOK(b)) { /* do not use the NV if POK is set */
3924        ret = Rmpz_cmp_NV(aTHX_ a, b);
3925        if(ret != 0) return newSViv(1);
3926        return newSViv(0);
3927      }
3928 
3929      if(sv_isobject(b)) {
3930        const char *h = HvNAME(SvSTASH(SvRV(b)));
3931        if(strEQ(h, "Math::GMPz")) {
3932          ret = mpz_cmp(*a, *(INT2PTR(mpz_t *, SvIVX(SvRV(b)))));
3933          if(ret != 0) return newSViv(1);
3934          return newSViv(0);
3935        }
3936 
3937        if(strEQ(h, "Math::GMPq")) {
3938 #if __GNU_MP_RELEASE < 60099
3939          ret = my_cmp_z(INT2PTR(mpq_t *, SvIVX(SvRV(b))), a);
3940          if(ret != 0) return newSViv(1);
3941          return newSViv(0);
3942 #else
3943          ret = mpq_cmp_z(*(INT2PTR(mpq_t *, SvIVX(SvRV(b)))), *a);
3944          if(ret != 0) return newSViv(1);
3945          return newSViv(0);
3946 #endif
3947        }
3948 
3949        if(strEQ(h, "Math::BigInt")) {
3950          VALIDATE_MBI_OBJECT
3951            croak("Invalid Math::BigInt object supplied to Math::GMPz::overload_not_equiv");
3952 
3953          MBI_GMP_INSERT
3954 
3955          if(mpz) {
3956            if(strEQ("-", sign)) {
3957              mpz_neg((mpz_ptr)mpz, (mpz_srcptr)mpz);
3958              ret = mpz_cmp(*a, (mpz_srcptr)mpz);
3959              mpz_neg((mpz_ptr)mpz, (mpz_srcptr)mpz); /* restore to original */
3960              if(ret != 0) return newSViv(1);
3961              return newSViv(0);
3962            }
3963 
3964            ret = mpz_cmp(*a, (mpz_srcptr)mpz);
3965            if(ret != 0) return newSViv(1);
3966            return newSViv(0);
3967          }
3968 
3969          mpz_init_set_str(t, SvPV_nolen(b), 0);
3970          ret = mpz_cmp(*a, t);
3971          mpz_clear(t);
3972          if(ret != 0) return newSViv(1);
3973          return newSViv(0);
3974        }
3975      }
3976 
3977      croak("Invalid argument supplied to Math::GMPz::overload_not_equiv");
3978 }
3979 
overload_not(pTHX_ mpz_t * a,SV * second,SV * third)3980 SV * overload_not(pTHX_ mpz_t * a, SV * second, SV * third) {
3981      if(mpz_cmp_ui(*a, 0)) return newSViv(0);
3982      return newSViv(1);
3983 }
3984 
3985 /* Finish typemapping */
3986 
overload_xor_eq(pTHX_ SV * a,SV * b,SV * third,...)3987 SV * overload_xor_eq(pTHX_ SV * a, SV * b, SV * third, ...) {
3988      mpz_t t;
3989      MBI_DECLARATIONS
3990      MBI_GMP_DECLARATIONS
3991 
3992 #if defined(USE_QUADMATH)
3993 
3994      char * buffer;
3995      int returned;
3996      __float128 buffer_size;
3997      __float128 ld;
3998 
3999 #elif defined(USE_LONG_DOUBLE)
4000 
4001      char * buffer;
4002      long double buffer_size;
4003      long double ld;
4004 
4005 #endif
4006 
4007      SvREFCNT_inc(a);
4008 
4009 #ifdef MATH_GMPZ_NEED_LONG_LONG_INT
4010      if(SV_IS_IOK(b)) {
4011        if(mpz_init_set_str(t, SvPV_nolen(b), 0)) {
4012          SvREFCNT_dec(a);
4013          croak("Invalid string (%s)supplied to Math::GMPz::overload_xor_eq", SvPV_nolen(b));
4014          }
4015        mpz_xor(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4016        mpz_clear(t);
4017        return a;
4018      }
4019 #else
4020      if(SV_IS_IOK(b)) {
4021        if(SvUOK(b)) {
4022          mpz_init_set_ui(t, SvUVX(b));
4023          mpz_xor(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4024          mpz_clear(t);
4025          return a;
4026        }
4027 
4028        mpz_init_set_si(t, SvIVX(b));
4029        mpz_xor(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4030        mpz_clear(t);
4031        return a;
4032      }
4033 #endif
4034 
4035      if(SV_IS_POK(b)) {
4036        if(mpz_init_set_str(t, SvPV_nolen(b), 0)) {
4037          SvREFCNT_dec(a);
4038          croak("Invalid string (%s) supplied to Math::GMPz::overload_xor_eq", SvPV_nolen(b));
4039          }
4040        mpz_xor(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4041        mpz_clear(t);
4042        return a;
4043      }
4044 
4045      if(SV_IS_NOK(b)) {
4046 
4047 #if defined(USE_QUADMATH)
4048 
4049        ld = (__float128)SvNVX(b) >= 0 ? floorq((__float128)SvNVX(b)) : ceilq((__float128)SvNVX(b));
4050        if(ld != ld) {
4051          SvREFCNT_dec(a);
4052          croak("In Math::GMPz::overload_xor_eq, cannot coerce a NaN to a Math::GMPz value");
4053        }
4054        if(ld != 0 && (ld / ld != 1)) {
4055          SvREFCNT_dec(a);
4056          croak("In Math::GMPz::overload_xor_eq, cannot coerce an Inf to a Math::GMPz value");
4057        }
4058 
4059        buffer_size = ld < 0.0Q ? ld * -1.0Q : ld;
4060        buffer_size = ceilq(logq(buffer_size + 1) / 2.30258509299404568401799145468436418Q);
4061 
4062        Newxz(buffer, (int)buffer_size + 5, char);
4063 
4064        returned = quadmath_snprintf(buffer, (size_t)buffer_size + 5, "%.0Qf", ld);
4065        if(returned < 0) {
4066          SvREFCNT_dec(a);
4067          croak("In Math::GMPz::overload_xor_eq, encoding error in quadmath_snprintf function");
4068        }
4069        if(returned >= buffer_size + 5) {
4070          SvREFCNT_dec(a);
4071          croak("In Math::GMPz::overload_xor_eq, buffer given to quadmath_snprintf function was too small");
4072        }
4073        mpz_init_set_str(t, buffer, 10);
4074        Safefree(buffer);
4075 
4076 #elif defined(USE_LONG_DOUBLE)
4077 
4078        ld = (long double)SvNVX(b) >= 0 ? floorl((long double)SvNVX(b)) : ceill((long double)SvNVX(b));
4079        if(ld != ld) {
4080          SvREFCNT_dec(a);
4081          croak("In Math::GMPz::overload_xor_eq, cannot coerce a NaN to a Math::GMPz value");
4082        }
4083        if(ld != 0 && (ld / ld != 1)) {
4084          SvREFCNT_dec(a);
4085          croak("In Math::GMPz::overload_xor_eq, cannot coerce an Inf to a Math::GMPz value");
4086        }
4087 
4088        buffer_size = ld < 0.0L ? ld * -1.0L : ld;
4089        buffer_size = ceill(logl(buffer_size + 1) / 2.30258509299404568401799145468436418L);
4090 
4091        Newxz(buffer, (int)buffer_size + 5, char);
4092 
4093        if(sprintf(buffer, "%.0Lf", ld) >= (int)buffer_size + 5) {
4094          SvREFCNT_dec(a);
4095          croak("In Math::GMPz::overload_xor_eq, buffer overflow in sprintf function");
4096        }
4097        mpz_init_set_str(t, buffer, 10);
4098        Safefree(buffer);
4099 #else
4100        double d = SvNVX(b);
4101        if(d != d) {
4102          SvREFCNT_dec(a);
4103          croak("In Math::GMPz::overload_xor_eq, cannot coerce a NaN to a Math::GMPz value");
4104        }
4105        if(d != 0 && (d / d != 1)) {
4106          SvREFCNT_dec(a);
4107          croak("In Math::GMPz::overload_xor_eq, cannot coerce an Inf to a Math::GMPz value");
4108        }
4109        mpz_init_set_d(t, d);
4110 #endif
4111        mpz_xor(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4112        mpz_clear(t);
4113        return a;
4114      }
4115 
4116 
4117      if(sv_isobject(b)) {
4118        const char *h = HvNAME(SvSTASH(SvRV(b)));
4119        if(strEQ(h, "Math::GMPz")) {
4120          mpz_xor(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(b)))));
4121          return a;
4122        }
4123 
4124        if(strEQ(h, "Math::BigInt")) {
4125          VALIDATE_MBI_OBJECT {
4126            SvREFCNT_dec(a);
4127            croak("Invalid Math::BigInt object supplied to Math::GMPz::overload_xor_eq");
4128          }
4129 
4130          MBI_GMP_INSERT
4131 
4132          if(mpz) {
4133            if(strEQ("-", sign)) {
4134              mpz_neg((mpz_ptr)mpz, (mpz_srcptr)mpz);
4135              mpz_xor(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), (mpz_srcptr)mpz);
4136              mpz_neg((mpz_ptr)mpz, (mpz_srcptr)mpz); /* restore to original */
4137              return a;
4138            }
4139 
4140            mpz_xor(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), (mpz_srcptr)mpz);
4141            return a;
4142          }
4143 
4144          mpz_init_set_str(t, SvPV_nolen(b), 0);
4145          mpz_xor(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4146          mpz_clear(t);
4147          return a;
4148        }
4149      }
4150 
4151      SvREFCNT_dec(a);
4152      croak("Invalid argument supplied to Math::GMPz::overload_xor_eq");
4153 }
4154 
overload_ior_eq(pTHX_ SV * a,SV * b,SV * third,...)4155 SV * overload_ior_eq(pTHX_ SV * a, SV * b, SV * third, ...) {
4156      mpz_t t;
4157      MBI_DECLARATIONS
4158      MBI_GMP_DECLARATIONS
4159 
4160 #if defined(USE_QUADMATH)
4161 
4162      char * buffer;
4163      int returned;
4164      __float128 buffer_size;
4165      __float128 ld;
4166 
4167 #elif defined(USE_LONG_DOUBLE)
4168 
4169      char * buffer;
4170      long double buffer_size;
4171      long double ld;
4172 
4173 #endif
4174 
4175      SvREFCNT_inc(a);
4176 
4177 #ifdef MATH_GMPZ_NEED_LONG_LONG_INT
4178      if(SV_IS_IOK(b)) {
4179        if(mpz_init_set_str(t, SvPV_nolen(b), 0)) {
4180          SvREFCNT_dec(a);
4181          croak("Invalid string (%s) supplied to Math::GMPz::overload_ior_eq", SvPV_nolen(b));
4182        }
4183        mpz_ior(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4184        mpz_clear(t);
4185        return a;
4186      }
4187 #else
4188      if(SV_IS_IOK(b)) {
4189        if(SvUOK(b)) {
4190          mpz_init_set_ui(t, SvUVX(b));
4191          mpz_ior(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4192          mpz_clear(t);
4193          return a;
4194        }
4195 
4196        mpz_init_set_si(t, SvIVX(b));
4197        mpz_ior(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4198        mpz_clear(t);
4199        return a;
4200      }
4201 #endif
4202 
4203      if(SV_IS_POK(b)) {
4204        if(mpz_init_set_str(t, SvPV_nolen(b), 0)) {
4205          SvREFCNT_dec(a);
4206          croak("Invalid string (%s) supplied to Math::GMPz::overload_ior_eq", SvPV_nolen(b));
4207        }
4208        mpz_ior(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4209        mpz_clear(t);
4210        return a;
4211      }
4212 
4213      if(SV_IS_NOK(b)) {
4214 
4215 #if defined(USE_QUADMATH)
4216 
4217        ld = (__float128)SvNVX(b) >= 0 ? floorq((__float128)SvNVX(b)) : ceilq((__float128)SvNVX(b));
4218        if(ld != ld) {
4219          SvREFCNT_dec(a);
4220          croak("In Math::GMPz::overload_ior_eq, cannot coerce a NaN to a Math::GMPz value");
4221        }
4222        if(ld != 0 && (ld / ld != 1)) {
4223          SvREFCNT_dec(a);
4224          croak("In Math::GMPz::overload_ior_eq, cannot coerce an Inf to a Math::GMPz value");
4225        }
4226 
4227        buffer_size = ld < 0.0Q ? ld * -1.0Q : ld;
4228        buffer_size = ceilq(logq(buffer_size + 1) / 2.30258509299404568401799145468436418Q);
4229 
4230        Newxz(buffer, (int)buffer_size + 5, char);
4231 
4232        returned = quadmath_snprintf(buffer, (size_t)buffer_size + 5, "%.0Qf", ld);
4233        if(returned < 0) {
4234          SvREFCNT_dec(a);
4235          croak("In Math::GMPz::overload_ior_eq, encoding error in quadmath_snprintf function");
4236        }
4237        if(returned >= buffer_size + 5) {
4238          SvREFCNT_dec(a);
4239          croak("In Math::GMPz::overload_ior_eq, buffer given to quadmath_snprintf function was too small");
4240        }
4241        mpz_init_set_str(t, buffer, 10);
4242        Safefree(buffer);
4243 
4244 #elif defined(USE_LONG_DOUBLE)
4245 
4246        ld = (long double)SvNVX(b) >= 0 ? floorl((long double)SvNVX(b)) : ceill((long double)SvNVX(b));
4247        if(ld != ld) {
4248          SvREFCNT_dec(a);
4249          croak("In Math::GMPz::overload_ior_eq, cannot coerce a NaN to a Math::GMPz value");
4250        }
4251        if(ld != 0 && (ld / ld != 1)) {
4252          SvREFCNT_dec(a);
4253          croak("In Math::GMPz::overload_ior_eq, cannot coerce an Inf to a Math::GMPz value");
4254        }
4255 
4256        buffer_size = ld < 0.0L ? ld * -1.0L : ld;
4257        buffer_size = ceill(logl(buffer_size + 1) / 2.30258509299404568401799145468436418L);
4258 
4259        Newxz(buffer, (int)buffer_size + 5, char);
4260 
4261        if(sprintf(buffer, "%.0Lf", ld) >= (int)buffer_size + 5) {
4262          SvREFCNT_dec(a);
4263          croak("In Math::GMPz::overload_ior_eq, buffer overflow in sprintf function");
4264        }
4265        mpz_init_set_str(t, buffer, 10);
4266        Safefree(buffer);
4267 #else
4268        double d = SvNVX(b);
4269        if(d != d) {
4270          SvREFCNT_dec(a);
4271          croak("In Math::GMPz::overload_ior_eq, cannot coerce a NaN to a Math::GMPz value");
4272        }
4273        if(d != 0 && (d / d != 1)) {
4274          SvREFCNT_dec(a);
4275          croak("In Math::GMPz::overload_ior_eq, cannot coerce an Inf to a Math::GMPz value");
4276        }
4277        mpz_init_set_d(t, d);
4278 #endif
4279        mpz_ior(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4280        mpz_clear(t);
4281        return a;
4282      }
4283 
4284      if(sv_isobject(b)) {
4285        const char *h = HvNAME(SvSTASH(SvRV(b)));
4286        if(strEQ(h, "Math::GMPz")) {
4287          mpz_ior(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(b)))));
4288          return a;
4289        }
4290 
4291        if(strEQ(h, "Math::BigInt")) {
4292          VALIDATE_MBI_OBJECT {
4293            SvREFCNT_dec(a);
4294            croak("Invalid Math::BigInt object supplied to Math::GMPz::overload_ior_eq");
4295          }
4296 
4297          MBI_GMP_INSERT
4298 
4299          if(mpz) {
4300            if(strEQ("-", sign)) {
4301              mpz_neg((mpz_ptr)mpz, (mpz_srcptr)mpz);
4302              mpz_ior(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), (mpz_srcptr)mpz);
4303              mpz_neg((mpz_ptr)mpz, (mpz_srcptr)mpz); /* restore to original */
4304              return a;
4305            }
4306 
4307            mpz_ior(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), (mpz_srcptr)mpz);
4308            return a;
4309          }
4310 
4311          mpz_init_set_str(t, SvPV_nolen(b), 0);
4312          mpz_ior(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4313          mpz_clear(t);
4314          return a;
4315        }
4316      }
4317 
4318      SvREFCNT_dec(a);
4319      croak("Invalid argument supplied to Math::GMPz::overload_ior_eq");
4320 }
4321 
overload_and_eq(pTHX_ SV * a,SV * b,SV * third,...)4322 SV * overload_and_eq(pTHX_ SV * a, SV * b, SV * third, ...) {
4323      mpz_t t;
4324      MBI_DECLARATIONS
4325      MBI_GMP_DECLARATIONS
4326 
4327 #if defined(USE_QUADMATH)
4328 
4329      char * buffer;
4330      int returned;
4331      __float128 buffer_size;
4332      __float128 ld;
4333 
4334 #elif defined(USE_LONG_DOUBLE)
4335 
4336      char * buffer;
4337      long double buffer_size;
4338      long double ld;
4339 
4340 #endif
4341 
4342      SvREFCNT_inc(a);
4343 
4344 #ifdef MATH_GMPZ_NEED_LONG_LONG_INT
4345      if(SV_IS_IOK(b)) {
4346        if(mpz_init_set_str(t, SvPV_nolen(b), 0)) {
4347          SvREFCNT_dec(a);
4348          croak("Invalid string (%s) supplied to Math::GMPz::overload_and_eq", SvPV_nolen(b));
4349          }
4350        mpz_and(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4351        mpz_clear(t);
4352        return a;
4353      }
4354 #else
4355      if(SV_IS_IOK(b)) {
4356        if(SvUOK(b)) {
4357          mpz_init_set_ui(t, SvUVX(b));
4358          mpz_and(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4359          mpz_clear(t);
4360          return a;
4361        }
4362 
4363        mpz_init_set_si(t, SvIVX(b));
4364        mpz_and(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4365        mpz_clear(t);
4366        return a;
4367      }
4368 #endif
4369 
4370      if(SV_IS_POK(b)) {
4371        if(mpz_init_set_str(t, SvPV_nolen(b), 0)) {
4372          SvREFCNT_dec(a);
4373          croak("Invalid string (%s) supplied to Math::GMPz::overload_and_eq", SvPV_nolen(b));
4374        }
4375        mpz_and(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4376        mpz_clear(t);
4377        return a;
4378      }
4379 
4380      if(SV_IS_NOK(b)) {
4381 
4382 #if defined(USE_QUADMATH)
4383 
4384        ld = (__float128)SvNVX(b) >= 0 ? floorq((__float128)SvNVX(b)) : ceilq((__float128)SvNVX(b));
4385        if(ld != ld) {
4386          SvREFCNT_dec(a);
4387          croak("In Math::GMPz::overload_and_eq, cannot coerce a NaN to a Math::GMPz value");
4388        }
4389        if(ld != 0 && (ld / ld != 1)) {
4390          SvREFCNT_dec(a);
4391          croak("In Math::GMPz::overload_and_eq, cannot coerce an Inf to a Math::GMPz value");
4392        }
4393 
4394        buffer_size = ld < 0.0Q ? ld * -1.0Q : ld;
4395        buffer_size = ceilq(logq(buffer_size + 1) / 2.30258509299404568401799145468436418Q);
4396 
4397        Newxz(buffer, (int)buffer_size + 5, char);
4398 
4399        returned = quadmath_snprintf(buffer, (size_t)buffer_size + 5, "%.0Qf", ld);
4400        if(returned < 0) {
4401          SvREFCNT_dec(a);
4402          croak("In Math::GMPz::overload_and_eq, encoding error in quadmath_snprintf function");
4403        }
4404        if(returned >= buffer_size + 5) {
4405          SvREFCNT_dec(a);
4406          croak("In Math::GMPz::overload_and_eq, buffer given to quadmath_snprintf function was too small");
4407        }
4408        mpz_init_set_str(t, buffer, 10);
4409        Safefree(buffer);
4410 
4411 #elif defined(USE_LONG_DOUBLE)
4412 
4413        ld = (long double)SvNVX(b) >= 0 ? floorl((long double)SvNVX(b)) : ceill((long double)SvNVX(b));
4414        if(ld != ld) {
4415          SvREFCNT_dec(a);
4416          croak("In Math::GMPz::overload_and_eq, cannot coerce a NaN to a Math::GMPz value");
4417        }
4418        if(ld != 0 && (ld / ld != 1)) {
4419          SvREFCNT_dec(a);
4420          croak("In Math::GMPz::overload_and_eq, cannot coerce an Inf to a Math::GMPz value");
4421        }
4422 
4423        buffer_size = ld < 0.0L ? ld * -1.0L : ld;
4424        buffer_size = ceill(logl(buffer_size + 1) / 2.30258509299404568401799145468436418L);
4425 
4426        Newxz(buffer, (int)buffer_size + 5, char);
4427 
4428        if(sprintf(buffer, "%.0Lf", ld) >= (int)buffer_size + 5) {
4429          SvREFCNT_dec(a);
4430          croak("In Math::GMPz::overload_and_eq, buffer overflow in sprintf function");
4431        }
4432        mpz_init_set_str(t, buffer, 10);
4433        Safefree(buffer);
4434 #else
4435        double d = SvNVX(b);
4436        if(d != d) {
4437          SvREFCNT_dec(a);
4438          croak("In Math::GMPz::overload_and_eq, cannot coerce a NaN to a Math::GMPz value");
4439        }
4440        if(d != 0 && (d / d != 1)) {
4441          SvREFCNT_dec(a);
4442          croak("In Math::GMPz::overload_and_eq, cannot coerce an Inf to a Math::GMPz value");
4443        }
4444        mpz_init_set_d(t, d);
4445 #endif
4446        mpz_and(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4447        mpz_clear(t);
4448        return a;
4449      }
4450 
4451      if(sv_isobject(b)) {
4452        const char *h = HvNAME(SvSTASH(SvRV(b)));
4453        if(strEQ(h, "Math::GMPz")) {
4454          mpz_and(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(b)))));
4455          return a;
4456        }
4457 
4458        if(strEQ(h, "Math::BigInt")) {
4459          VALIDATE_MBI_OBJECT {
4460            SvREFCNT_dec(a);
4461            croak("Invalid Math::BigInt object supplied to Math::GMPz::overload_and_eq");
4462          }
4463 
4464          MBI_GMP_INSERT
4465 
4466          if(mpz) {
4467            if(strEQ("-", sign)) {
4468              mpz_neg((mpz_ptr)mpz, (mpz_srcptr)mpz);
4469              mpz_and(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), (mpz_srcptr)mpz);
4470              mpz_neg((mpz_ptr)mpz, (mpz_srcptr)mpz); /* restore to original */
4471              return a;
4472            }
4473 
4474            mpz_and(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), (mpz_srcptr)mpz);
4475            return a;
4476          }
4477 
4478          mpz_init_set_str(t, SvPV_nolen(b), 0);
4479          mpz_and(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4480          mpz_clear(t);
4481          return a;
4482        }
4483      }
4484 
4485      SvREFCNT_dec(a);
4486      croak("Invalid argument supplied to Math::GMPz::overload_and_eq");
4487 }
4488 
overload_pow_eq(pTHX_ SV * a,SV * b,SV * third)4489 SV * overload_pow_eq(pTHX_ SV * a, SV * b, SV * third) {
4490      SvREFCNT_inc(a);
4491 
4492      if(SV_IS_IOK(b)) {
4493        if(SvUOK(b)) {
4494          mpz_pow_ui(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), SvUVX(b));
4495          return a;
4496        }
4497 
4498        if(SvIVX(b) < 0) {
4499          SvREFCNT_dec(a);
4500          croak("Negative argument supplied to Math::GMPz::overload_pow_eq");
4501        }
4502        mpz_pow_ui(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), SvUVX(b));
4503        return a;
4504      }
4505 
4506      if(sv_isobject(b)) {
4507        const char *h = HvNAME(SvSTASH(SvRV(b)));
4508        if(strEQ(h, "Math::GMPz")) {
4509          if(mpz_fits_uint_p(*(INT2PTR(mpz_t *, SvIVX(SvRV(b)))))) {
4510            mpz_pow_ui(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))),
4511                       *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))),
4512                       mpz_get_ui(*(INT2PTR(mpz_t *, SvIVX(SvRV(b))))));
4513            return a;
4514          }
4515        }
4516      }
4517 
4518      SvREFCNT_dec(a);
4519      croak("Invalid argument supplied to Math::GMPz::overload_pow_eq. Exponent must fit into an unsigned long");
4520 }
4521 
overload_rshift_eq(pTHX_ SV * a,SV * b,SV * third)4522 SV * overload_rshift_eq(pTHX_ SV * a, SV * b, SV * third) {
4523 
4524      CHECK_MP_BITCNT_T_OVERFLOW(b)
4525 
4526      SvREFCNT_inc(a);
4527 
4528      if(SV_IS_IOK(b)) {
4529        if(SvUOK(b)) {
4530          mpz_tdiv_q_2exp(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), (mp_bitcnt_t)SvUVX(b));
4531          return a;
4532        }
4533 
4534        if(SvIV(b) < 0) {
4535          SvREFCNT_dec(a);
4536          croak("Invalid argument supplied to Math::GMPz::overload_rshift_eq");
4537        }
4538        mpz_tdiv_q_2exp(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), (mp_bitcnt_t)SvUVX(b));
4539        return a;
4540      }
4541 
4542      SvREFCNT_dec(a);
4543      croak("Invalid argument supplied to Math::GMPz::overload_rshift_eq");
4544 }
4545 
overload_lshift_eq(pTHX_ SV * a,SV * b,SV * third)4546 SV * overload_lshift_eq(pTHX_ SV * a, SV * b, SV * third) {
4547 
4548      CHECK_MP_BITCNT_T_OVERFLOW(b)
4549 
4550      SvREFCNT_inc(a);
4551 
4552      if(SV_IS_IOK(b)) {
4553        if(SvUOK(b)) {
4554          mpz_mul_2exp(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), (mp_bitcnt_t)SvUV(b));
4555          return a;
4556        }
4557 
4558        if(SvIV(b) < 0) {
4559          SvREFCNT_dec(a);
4560          croak("Invalid argument supplied to Math::GMPz::overload_lshift_eq");
4561        }
4562        mpz_mul_2exp(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), (mp_bitcnt_t)SvUV(b));
4563        return a;
4564      }
4565 
4566      SvREFCNT_dec(a);
4567      croak("Invalid argument supplied to Math::GMPz::overload_lshift_eq");
4568 }
4569 
overload_inc(pTHX_ SV * p,SV * second,SV * third)4570 SV * overload_inc(pTHX_ SV * p, SV * second, SV * third) {
4571      SvREFCNT_inc(p);
4572      mpz_add_ui(*(INT2PTR(mpz_t *, SvIVX(SvRV(p)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(p)))), 1);
4573      return p;
4574 }
4575 
overload_dec(pTHX_ SV * p,SV * second,SV * third)4576 SV * overload_dec(pTHX_ SV * p, SV * second, SV * third) {
4577      SvREFCNT_inc(p);
4578      mpz_sub_ui(*(INT2PTR(mpz_t *, SvIVX(SvRV(p)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(p)))), 1);
4579      return p;
4580 }
4581 
overload_mod_eq(pTHX_ SV * a,SV * b,SV * third)4582 SV * overload_mod_eq(pTHX_ SV * a, SV * b, SV * third) {
4583      mpz_t t;
4584      MBI_DECLARATIONS
4585      MBI_GMP_DECLARATIONS
4586 
4587 #if defined(USE_QUADMATH)
4588 
4589      char * buffer;
4590      int returned;
4591      __float128 buffer_size;
4592      __float128 ld;
4593 
4594 #elif defined(USE_LONG_DOUBLE)
4595 
4596      char * buffer;
4597      long double buffer_size;
4598      long double ld;
4599 
4600 #endif
4601 
4602      SvREFCNT_inc(a);
4603 
4604 #ifdef MATH_GMPZ_NEED_LONG_LONG_INT
4605      if(SV_IS_IOK(b)) {
4606        if(mpz_init_set_str(t, SvPV_nolen(b), 0)) {
4607          SvREFCNT_dec(a);
4608          croak("Invalid string (%s) supplied to Math::GMPz::overload_mod_eq", SvPV_nolen(b));
4609          }
4610        mpz_mod(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4611        mpz_clear(t);
4612        return a;
4613      }
4614 #else
4615      if(SV_IS_IOK(b)) {
4616        if(SvUOK(b)) {
4617          mpz_mod_ui(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), SvUVX(b));
4618          return a;
4619        }
4620 
4621        if(SvIV(b) > 0) {
4622          mpz_mod_ui(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), SvUVX(b));
4623          return a;
4624        }
4625        mpz_init_set_si(t, SvIVX(b)); /* was SvNV(b) ?? */
4626        mpz_mod(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4627        mpz_clear(t);
4628        return a;
4629      }
4630 #endif
4631 
4632      if(SV_IS_POK(b)) {
4633        if(mpz_init_set_str(t, SvPV_nolen(b), 0)) {
4634          SvREFCNT_dec(a);
4635          croak("Invalid string (%s) supplied to Math::GMPz::overload_mod_eq", SvPV_nolen(b));
4636        }
4637        mpz_mod(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4638        mpz_clear(t);
4639        return a;
4640      }
4641 
4642      if(SV_IS_NOK(b)) {
4643 
4644 #if defined(USE_QUADMATH)
4645 
4646        ld = (__float128)SvNVX(b) >= 0 ? floorq((__float128)SvNVX(b)) : ceilq((__float128)SvNVX(b));
4647        if(ld != ld) {
4648          SvREFCNT_dec(a);
4649          croak("In Math::GMPz::overload_mod_eq, cannot coerce a NaN to a Math::GMPz value");
4650        }
4651        if(ld != 0 && (ld / ld != 1)) {
4652          SvREFCNT_dec(a);
4653          croak("In Math::GMPz::overload_mod_eq, cannot coerce an Inf to a Math::GMPz value");
4654        }
4655 
4656        buffer_size = ld < 0.0Q ? ld * -1.0Q : ld;
4657        buffer_size = ceilq(logq(buffer_size + 1) / 2.30258509299404568401799145468436418Q);
4658 
4659        Newxz(buffer, (int)buffer_size + 5, char);
4660 
4661        returned = quadmath_snprintf(buffer, (size_t)buffer_size + 5, "%.0Qf", ld);
4662        if(returned < 0) {
4663          SvREFCNT_dec(a);
4664          croak("In Math::GMPz::overload_mod_eq, encoding error in quadmath_snprintf function");
4665        }
4666        if(returned >= buffer_size + 5) {
4667          SvREFCNT_dec(a);
4668          croak("In Math::GMPz::overload_mod_eq, buffer given to quadmath_snprintf function was too small");
4669        }
4670        mpz_init_set_str(t, buffer, 10);
4671        Safefree(buffer);
4672 
4673 #elif defined(USE_LONG_DOUBLE)
4674 
4675        ld = (long double)SvNVX(b) >= 0 ? floorl((long double)SvNVX(b)) : ceill((long double)SvNVX(b));
4676        if(ld != ld) {
4677          SvREFCNT_dec(a);
4678          croak("In Math::GMPz::overload_mod_eq, cannot coerce a NaN to a Math::GMPz value");
4679        }
4680        if(ld != 0 && (ld / ld != 1)) {
4681          SvREFCNT_dec(a);
4682          croak("In Math::GMPz::overload_mod_eq, cannot coerce an Inf to a Math::GMPz value");
4683        }
4684 
4685        buffer_size = ld < 0.0L ? ld * -1.0L : ld;
4686        buffer_size = ceill(logl(buffer_size + 1) / 2.30258509299404568401799145468436418L);
4687 
4688        Newxz(buffer, (int)buffer_size + 5, char);
4689 
4690        if(sprintf(buffer, "%.0Lf", ld) >= (int)buffer_size + 5) {
4691          SvREFCNT_dec(a);
4692          croak("In Math::GMPz::overload_mod_eq, buffer overflow in sprintf function");
4693        }
4694        mpz_init_set_str(t, buffer, 10);
4695        Safefree(buffer);
4696 #else
4697        double d = SvNVX(b);
4698        if(d != d) {
4699          SvREFCNT_dec(a);
4700          croak("In Math::GMPz::overload_mod_eq, cannot coerce a NaN to a Math::GMPz value");
4701        }
4702        if(d != 0 && (d / d != 1)) {
4703          SvREFCNT_dec(a);
4704          croak("In Math::GMPz::overload_mod_eq, cannot coerce an Inf to a Math::GMPz value");
4705        }
4706        mpz_init_set_d(t, d);
4707 #endif
4708        mpz_mod(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4709        mpz_clear(t);
4710        return a;
4711      }
4712 
4713      if(sv_isobject(b)) {
4714        const char *h = HvNAME(SvSTASH(SvRV(b)));
4715        if(strEQ(h, "Math::GMPz")) {
4716          mpz_mod(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(b)))));
4717          return a;
4718        }
4719 
4720        if(strEQ(h, "Math::BigInt")) {
4721          VALIDATE_MBI_OBJECT {
4722            SvREFCNT_dec(a);
4723            croak("Invalid Math::BigInt object supplied to Math::GMPz::overload_mod_eq");
4724          }
4725 
4726          MBI_GMP_INSERT
4727 
4728          if(mpz) {
4729            /* if(strEQ("-", sign)) ...... not an issue for the divisor in a mod operation */
4730            mpz_mod(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), (mpz_srcptr)mpz);
4731            return a;
4732          }
4733 
4734          mpz_init_set_str(t, SvPV_nolen(b), 0);
4735          mpz_mod(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4736          mpz_clear(t);
4737          return a;
4738        }
4739      }
4740 
4741      SvREFCNT_dec(a);
4742      croak("Invalid argument supplied to Math::GMPz::overload_mod_eq");
4743 }
4744 
get_refcnt(pTHX_ SV * s)4745 SV * get_refcnt(pTHX_ SV * s) {
4746      return newSVuv(SvREFCNT(s));
4747 }
4748 
overload_div_eq(pTHX_ SV * a,SV * b,SV * third)4749 SV * overload_div_eq(pTHX_ SV * a, SV * b, SV * third) {
4750      mpz_t t;
4751      MBI_DECLARATIONS
4752      MBI_GMP_DECLARATIONS
4753 
4754 #if defined(USE_QUADMATH)
4755 
4756      char * buffer;
4757      int returned;
4758      __float128 buffer_size;
4759      __float128 ld;
4760 
4761 #elif defined(USE_LONG_DOUBLE)
4762 
4763      char * buffer;
4764      long double buffer_size;
4765      long double ld;
4766 
4767 #endif
4768 
4769      SvREFCNT_inc(a);
4770 
4771 #ifdef MATH_GMPZ_NEED_LONG_LONG_INT
4772      if(SV_IS_IOK(b)) {
4773        if(mpz_init_set_str(t, SvPV_nolen(b), 0)) {
4774          SvREFCNT_dec(a);
4775          croak("Invalid string (%s) supplied to Math::GMPz::overload_div_eq", SvPV_nolen(b));
4776        }
4777        mpz_tdiv_q(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4778        mpz_clear(t);
4779        return a;
4780      }
4781 #else
4782      if(SV_IS_IOK(b)) {
4783        if(SvUOK(b)) {
4784          mpz_tdiv_q_ui(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), SvUVX(b));
4785          return a;
4786        }
4787 
4788        if(SvIV(b) >= 0) {
4789          mpz_tdiv_q_ui(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), SvIVX(b));
4790          return a;
4791        }
4792        mpz_tdiv_q_ui(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), SvIVX(b) * -1);
4793        mpz_neg(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))));
4794        return a;
4795      }
4796 #endif
4797 
4798      if(SV_IS_POK(b)) {
4799        if(mpz_init_set_str(t, SvPV_nolen(b), 0)) {
4800          SvREFCNT_dec(a);
4801          croak("Invalid string (%s) supplied to Math::GMPz::overload_div_eq", SvPV_nolen(b));
4802        }
4803        mpz_tdiv_q(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4804        mpz_clear(t);
4805        return a;
4806      }
4807 
4808      if(SV_IS_NOK(b)) {
4809 
4810 #if defined(USE_QUADMATH)
4811 
4812        ld = (__float128)SvNVX(b) >= 0 ? floorq((__float128)SvNVX(b)) : ceilq((__float128)SvNVX(b));
4813        if(ld != ld) {
4814          SvREFCNT_dec(a);
4815          croak("In Math::GMPz::overload_div_eq, cannot coerce a NaN to a Math::GMPz value");
4816        }
4817        if(ld != 0 && (ld / ld != 1)) {
4818          SvREFCNT_dec(a);
4819          croak("In Math::GMPz::overload_div_eq, cannot coerce an Inf to a Math::GMPz value");
4820        }
4821 
4822        buffer_size = ld < 0.0Q ? ld * -1.0Q : ld;
4823        buffer_size = ceilq(logq(buffer_size + 1) / 2.30258509299404568401799145468436418Q);
4824 
4825        Newxz(buffer, (int)buffer_size + 5, char);
4826 
4827        returned = quadmath_snprintf(buffer, (size_t)buffer_size + 5, "%.0Qf", ld);
4828        if(returned < 0) {
4829          SvREFCNT_dec(a);
4830          croak("In Math::GMPz::overload_div_eq, encoding error in quadmath_snprintf function");
4831        }
4832        if(returned >= buffer_size + 5) {
4833          SvREFCNT_dec(a);
4834          croak("In Math::GMPz::overload_div_eq, buffer given to quadmath_snprintf function was too small");
4835        }
4836        mpz_init_set_str(t, buffer, 10);
4837        Safefree(buffer);
4838 
4839 #elif defined(USE_LONG_DOUBLE)
4840 
4841        ld = (long double)SvNVX(b) >= 0 ? floorl((long double)SvNVX(b)) : ceill((long double)SvNVX(b));
4842        if(ld != ld) {
4843          SvREFCNT_dec(a);
4844          croak("In Math::GMPz::overload_div_eq, cannot coerce a NaN to a Math::GMPz value");
4845        }
4846        if(ld != 0 && (ld / ld != 1)) {
4847          SvREFCNT_dec(a);
4848          croak("In Math::GMPz::overload_div_eq, cannot coerce an Inf to a Math::GMPz value");
4849        }
4850 
4851        buffer_size = ld < 0.0L ? ld * -1.0L : ld;
4852        buffer_size = ceill(logl(buffer_size + 1) / 2.30258509299404568401799145468436418L);
4853 
4854        Newxz(buffer, (int)buffer_size + 5, char);
4855 
4856        if(sprintf(buffer, "%.0Lf", ld) >= (int)buffer_size + 5) {
4857          SvREFCNT_dec(a);
4858          croak("In Math::GMPz::overload_div_eq, buffer overflow in sprintf function");
4859        }
4860        mpz_init_set_str(t, buffer, 10);
4861        Safefree(buffer);
4862 #else
4863        double d = SvNVX(b);
4864        if(d != d) {
4865          SvREFCNT_dec(a);
4866          croak("In Math::GMPz::overload_div_eq, cannot coerce a NaN to a Math::GMPz value");
4867        }
4868        if(d != 0 && (d / d != 1)) {
4869          SvREFCNT_dec(a);
4870          croak("In Math::GMPz::overload_div_eq, cannot coerce an Inf to a Math::GMPz value");
4871        }
4872        mpz_init_set_d(t, d);
4873 #endif
4874        mpz_tdiv_q(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4875        mpz_clear(t);
4876        return a;
4877      }
4878 
4879      if(sv_isobject(b)) {
4880        const char *h = HvNAME(SvSTASH(SvRV(b)));
4881        if(strEQ(h, "Math::GMPz")) {
4882          mpz_tdiv_q(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(b)))));
4883          return a;
4884        }
4885 
4886        if(strEQ(h, "Math::BigInt")) {
4887          VALIDATE_MBI_OBJECT {
4888          SvREFCNT_dec(a);
4889          croak("Invalid Math::BigInt object supplied to Math::GMPz::overload_div_eq");
4890          }
4891 
4892          MBI_GMP_INSERT
4893 
4894          if(mpz) {
4895            mpz_tdiv_q(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), (mpz_srcptr)mpz);
4896            if(strEQ("-", sign)) mpz_neg(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))));
4897            return a;
4898          }
4899 
4900          mpz_init_set_str(t, SvPV_nolen(b), 0);
4901          mpz_tdiv_q(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4902          mpz_clear(t);
4903          return a;
4904        }
4905      }
4906 
4907      SvREFCNT_dec(a);
4908      croak("Invalid argument supplied to Math::GMPz::overload_div_eq function");
4909 
4910 }
4911 
overload_sub_eq(pTHX_ SV * a,SV * b,SV * third)4912 SV * overload_sub_eq(pTHX_ SV * a, SV * b, SV * third) {
4913      mpz_t t;
4914      MBI_DECLARATIONS
4915      MBI_GMP_DECLARATIONS
4916 
4917 #if defined(USE_QUADMATH)
4918 
4919      char * buffer;
4920      int returned;
4921      __float128 buffer_size;
4922      __float128 ld;
4923 
4924 #elif defined(USE_LONG_DOUBLE)
4925 
4926      char * buffer;
4927      long double buffer_size;
4928      long double ld;
4929 
4930 #endif
4931 
4932      SvREFCNT_inc(a);
4933 
4934 #ifdef MATH_GMPZ_NEED_LONG_LONG_INT
4935      if(SV_IS_IOK(b)) {
4936        if(mpz_init_set_str(t, SvPV_nolen(b), 0)) {
4937          SvREFCNT_dec(a);
4938          croak("Invalid string (%s) supplied to Math::GMPz::overload_sub_eq", SvPV_nolen(b));
4939          }
4940        mpz_sub(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4941        mpz_clear(t);
4942        return a;
4943      }
4944 #else
4945      if(SV_IS_IOK(b)) {
4946        if(SvUOK(b)) {
4947          mpz_sub_ui(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), SvUVX(b));
4948          return a;
4949        }
4950 
4951        if(SvIV(b) >= 0) {
4952          mpz_sub_ui(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), SvIVX(b));
4953          return a;
4954        }
4955        mpz_add_ui(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), SvIVX(b) * -1);
4956        return a;
4957      }
4958 #endif
4959 
4960      if(SV_IS_POK(b)) {
4961        if(mpz_init_set_str(t, SvPV_nolen(b), 0)) {
4962          SvREFCNT_dec(a);
4963          croak("Invalid string (%s) supplied to Math::GMPz::overload_sub_eq", SvPV_nolen(b));
4964        }
4965        mpz_sub(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
4966        mpz_clear(t);
4967        return a;
4968      }
4969 
4970      if(SV_IS_NOK(b)) {
4971 
4972 #if defined(USE_QUADMATH)
4973 
4974        ld = (__float128)SvNVX(b) >= 0 ? floorq((__float128)SvNVX(b)) : ceilq((__float128)SvNVX(b));
4975        if(ld != ld) {
4976          SvREFCNT_dec(a);
4977          croak("In Math::GMPz::overload_sub_eq, cannot coerce a NaN to a Math::GMPz value");
4978        }
4979        if(ld != 0 && (ld / ld != 1)) {
4980          SvREFCNT_dec(a);
4981          croak("In Math::GMPz::overload_sub_eq, cannot coerce an Inf to a Math::GMPz value");
4982        }
4983 
4984        buffer_size = ld < 0.0Q ? ld * -1.0Q : ld;
4985        buffer_size = ceilq(logq(buffer_size + 1) / 2.30258509299404568401799145468436418Q);
4986 
4987        Newxz(buffer, (int)buffer_size + 5, char);
4988 
4989        returned = quadmath_snprintf(buffer, (size_t)buffer_size + 5, "%.0Qf", ld);
4990        if(returned < 0) {
4991          SvREFCNT_dec(a);
4992          croak("In Math::GMPz::overload_sub_eq, encoding error in quadmath_snprintf function");
4993        }
4994        if(returned >= buffer_size + 5) {
4995          SvREFCNT_dec(a);
4996          croak("In Math::GMPz::overload_sub_eq, buffer given to quadmath_snprintf function was too small");
4997        }
4998        mpz_init_set_str(t, buffer, 10);
4999        Safefree(buffer);
5000 
5001 #elif defined(USE_LONG_DOUBLE)
5002 
5003        ld = (long double)SvNVX(b) >= 0 ? floorl((long double)SvNVX(b)) : ceill((long double)SvNVX(b));
5004        if(ld != ld) {
5005          SvREFCNT_dec(a);
5006          croak("In Math::GMPz::overload_sub_eq, cannot coerce a NaN to a Math::GMPz value");
5007        }
5008        if(ld != 0 && (ld / ld != 1)) {
5009          SvREFCNT_dec(a);
5010          croak("In Math::GMPz::overload_sub_eq, cannot coerce an Inf to a Math::GMPz value");
5011        }
5012 
5013        buffer_size = ld < 0.0L ? ld * -1.0L : ld;
5014        buffer_size = ceill(logl(buffer_size + 1) / 2.30258509299404568401799145468436418L);
5015 
5016        Newxz(buffer, (int)buffer_size + 5, char);
5017 
5018        if(sprintf(buffer, "%.0Lf", ld) >= (int)buffer_size + 5) {
5019          SvREFCNT_dec(a);
5020          croak("In Math::GMPz::overload_sub_eq, buffer overflow in sprintf function");
5021        }
5022        mpz_init_set_str(t, buffer, 10);
5023        Safefree(buffer);
5024 #else
5025        double d = SvNVX(b);
5026        if(d != d) {
5027          SvREFCNT_dec(a);
5028          croak("In Math::GMPz::overload_sub_eq, cannot coerce a NaN to a Math::GMPz value");
5029        }
5030        if(d != 0 && (d / d != 1)) {
5031          SvREFCNT_dec(a);
5032          croak("In Math::GMPz::overload_sub_eq, cannot coerce an Inf to a Math::GMPz value");
5033        }
5034        mpz_init_set_d(t, d);
5035 #endif
5036        mpz_sub(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
5037        mpz_clear(t);
5038        return a;
5039      }
5040 
5041      if(sv_isobject(b)) {
5042        const char *h = HvNAME(SvSTASH(SvRV(b)));
5043        if(strEQ(h, "Math::GMPz")) {
5044          mpz_sub(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(b)))));
5045          return a;
5046        }
5047 
5048        if(strEQ(h, "Math::BigInt")) {
5049          VALIDATE_MBI_OBJECT {
5050            SvREFCNT_dec(a);
5051            croak("Invalid Math::BigInt object supplied to Math::GMPz::overload_sub_eq");
5052          }
5053 
5054          MBI_GMP_INSERT
5055 
5056          if(mpz) {
5057            if(strEQ("-", sign)) {
5058              mpz_add(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), (mpz_srcptr)mpz);
5059              return a;
5060            }
5061 
5062            mpz_sub(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), (mpz_srcptr)mpz);
5063            return a;
5064          }
5065 
5066          mpz_init_set_str(t, SvPV_nolen(b), 0);
5067          mpz_sub(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
5068          mpz_clear(t);
5069          return a;
5070        }
5071      }
5072 
5073      SvREFCNT_dec(a);
5074      croak("Invalid argument supplied to Math::GMPz::overload_sub_eq function");
5075 
5076 }
5077 
overload_add_eq(pTHX_ SV * a,SV * b,SV * third)5078 SV * overload_add_eq(pTHX_ SV * a, SV * b, SV * third) {
5079      mpz_t t;
5080      MBI_DECLARATIONS
5081      MBI_GMP_DECLARATIONS
5082 
5083 #if defined(USE_QUADMATH)
5084 
5085      char * buffer;
5086      int returned;
5087      __float128 buffer_size;
5088      __float128 ld;
5089 
5090 #elif defined(USE_LONG_DOUBLE)
5091 
5092      char * buffer;
5093      long double buffer_size;
5094      long double ld;
5095 
5096 #endif
5097 
5098      SvREFCNT_inc(a);
5099 
5100 #ifdef MATH_GMPZ_NEED_LONG_LONG_INT
5101      if(SV_IS_IOK(b)) {
5102        if(mpz_init_set_str(t, SvPV_nolen(b), 0)) {
5103          SvREFCNT_dec(a);
5104          croak("Invalid string (%s) supplied to Math::GMPz::overload_add_eq", SvPV_nolen(b));
5105        }
5106        mpz_add(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
5107        mpz_clear(t);
5108        return a;
5109      }
5110 #else
5111      if(SV_IS_IOK(b)) {
5112        if(SvUOK(b)) {
5113          mpz_add_ui(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), SvUVX(b));
5114          return a;
5115        }
5116 
5117 
5118        if(SvIV(b) >= 0) {
5119          mpz_add_ui(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), SvIVX(b));
5120          return a;
5121        }
5122        mpz_sub_ui(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), SvIVX(b) * -1);
5123        return a;
5124      }
5125 #endif
5126 
5127      if(SV_IS_POK(b)) {
5128        if(mpz_init_set_str(t, SvPV_nolen(b), 0)) {
5129          SvREFCNT_dec(a);
5130          croak("Invalid string (%s) supplied to Math::GMPz::overload_add_eq", SvPV_nolen(b));
5131        }
5132        mpz_add(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
5133        mpz_clear(t);
5134        return a;
5135      }
5136 
5137      if(SV_IS_NOK(b)) {
5138 
5139 #if defined(USE_QUADMATH)
5140 
5141        ld = (__float128)SvNVX(b) >= 0 ? floorq((__float128)SvNVX(b)) : ceilq((__float128)SvNVX(b));
5142        if(ld != ld) {
5143          SvREFCNT_dec(a);
5144          croak("In Math::GMPz::overload_add_eq, cannot coerce a NaN to a Math::GMPz value");
5145        }
5146        if(ld != 0 && (ld / ld != 1)) {
5147          SvREFCNT_dec(a);
5148          croak("In Math::GMPz::overload_add_eq, cannot coerce an Inf to a Math::GMPz value");
5149        }
5150 
5151        buffer_size = ld < 0.0Q ? ld * -1.0Q : ld;
5152        buffer_size = ceilq(logq(buffer_size + 1) / 2.30258509299404568401799145468436418Q);
5153 
5154        Newxz(buffer, (int)buffer_size + 5, char);
5155 
5156        returned = quadmath_snprintf(buffer, (size_t)buffer_size + 5, "%.0Qf", ld);
5157        if(returned < 0) {
5158          SvREFCNT_dec(a);
5159          croak("In Math::GMPz::overload_add_eq, encoding error in quadmath_snprintf function");
5160        }
5161        if(returned >= buffer_size + 5) {
5162          SvREFCNT_dec(a);
5163          croak("In Math::GMPz::overload_add_eq, buffer given to quadmath_snprintf function was too small");
5164        }
5165        mpz_init_set_str(t, buffer, 10);
5166        Safefree(buffer);
5167 
5168 #elif defined(USE_LONG_DOUBLE)
5169 
5170        ld = (long double)SvNVX(b) >= 0 ? floorl((long double)SvNVX(b)) : ceill((long double)SvNVX(b));
5171        if(ld != ld) {
5172          SvREFCNT_dec(a);
5173          croak("In Math::GMPz::overload_add_eq, cannot coerce a NaN to a Math::GMPz value");
5174        }
5175        if(ld != 0 && (ld / ld != 1)) {
5176          SvREFCNT_dec(a);
5177          croak("In Math::GMPz::overload_add_eq, cannot coerce an Inf to a Math::GMPz value");
5178        }
5179 
5180        buffer_size = ld < 0.0L ? ld * -1.0L : ld;
5181        buffer_size = ceill(logl(buffer_size + 1) / 2.30258509299404568401799145468436418L);
5182 
5183        Newxz(buffer, (int)buffer_size + 5, char);
5184 
5185        if(sprintf(buffer, "%.0Lf", ld) >= (int)buffer_size + 5) {
5186          SvREFCNT_dec(a);
5187          croak("In Math::GMPz::overload_add_eq, buffer overflow in sprintf function");
5188        }
5189        mpz_init_set_str(t, buffer, 10);
5190        Safefree(buffer);
5191 #else
5192        double d = SvNVX(b);
5193        if(d != d) {
5194          SvREFCNT_dec(a);
5195          croak("In Math::GMPz::overload_add_eq, cannot coerce a NaN to a Math::GMPz value");
5196        }
5197        if(d != 0 && (d / d != 1)) {
5198          SvREFCNT_dec(a);
5199          croak("In Math::GMPz::overload_add_eq, cannot coerce an Inf to a Math::GMPz value");
5200        }
5201        mpz_init_set_d(t, d);
5202 #endif
5203        mpz_add(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
5204        mpz_clear(t);
5205        return a;
5206      }
5207 
5208      if(sv_isobject(b)) {
5209        const char *h = HvNAME(SvSTASH(SvRV(b)));
5210        if(strEQ(h, "Math::GMPz")) {
5211          mpz_add(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(b)))));
5212          return a;
5213        }
5214 
5215        if(strEQ(h, "Math::BigInt")) {
5216          VALIDATE_MBI_OBJECT {
5217            SvREFCNT_dec(a);
5218            croak("Invalid Math::BigInt object supplied to Math::GMPz::overload_add_eq");
5219          }
5220 
5221          MBI_GMP_INSERT
5222 
5223          if(mpz) {
5224            if(strEQ("-", sign)) {
5225              mpz_sub(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), (mpz_srcptr)mpz);
5226              return a;
5227            }
5228 
5229            mpz_add(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), (mpz_srcptr)mpz);
5230            return a;
5231          }
5232 
5233          mpz_init_set_str(t, SvPV_nolen(b), 0);
5234          mpz_add(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
5235          mpz_clear(t);
5236          return a;
5237        }
5238      }
5239 
5240      SvREFCNT_dec(a);
5241      croak("Invalid argument supplied to Math::GMPz::overload_add_eq function");
5242 
5243 }
5244 
overload_mul_eq(pTHX_ SV * a,SV * b,SV * third)5245 SV * overload_mul_eq(pTHX_ SV * a, SV * b, SV * third) {
5246      mpz_t t;
5247      MBI_DECLARATIONS
5248      MBI_GMP_DECLARATIONS
5249 
5250 #if defined(USE_QUADMATH)
5251 
5252      char * buffer;
5253      int returned;
5254      __float128 buffer_size;
5255      __float128 ld;
5256 
5257 #elif defined(USE_LONG_DOUBLE)
5258 
5259      char * buffer;
5260      long double buffer_size;
5261      long double ld;
5262 
5263 #endif
5264 
5265      SvREFCNT_inc(a);
5266 
5267 #ifdef MATH_GMPZ_NEED_LONG_LONG_INT
5268      if(SV_IS_IOK(b)) {
5269        if(mpz_init_set_str(t, SvPV_nolen(b), 0)) {
5270          SvREFCNT_dec(a);
5271          croak(" Invalid string (%s) supplied to Math::GMPz::overload_mul_eq", SvPV_nolen(b));
5272        }
5273        mpz_mul(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
5274        mpz_clear(t);
5275        return a;
5276      }
5277 #else
5278      if(SV_IS_IOK(b)) {
5279        if(SvUOK(b)) {
5280          mpz_mul_ui(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), SvUVX(b));
5281          return a;
5282        }
5283 
5284        mpz_mul_si(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), SvIVX(b));
5285        return a;
5286      }
5287 #endif
5288 
5289      if(SV_IS_POK(b)) {
5290        if(mpz_init_set_str(t, SvPV_nolen(b), 0)) {
5291          SvREFCNT_dec(a);
5292          croak(" Invalid string (%s) supplied to Math::GMPz::overload_mul_eq", SvPV_nolen(b));
5293        }
5294        mpz_mul(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
5295        mpz_clear(t);
5296        return a;
5297      }
5298 
5299      if(SV_IS_NOK(b)) {
5300 
5301 #if defined(USE_QUADMATH)
5302 
5303        ld = (__float128)SvNVX(b) >= 0 ? floorq((__float128)SvNVX(b)) : ceilq((__float128)SvNVX(b));
5304        if(ld != ld) {
5305          SvREFCNT_dec(a);
5306          croak("In Math::GMPz::overload_mul_eq, cannot coerce a NaN to a Math::GMPz value");
5307        }
5308        if(ld != 0 && (ld / ld != 1)) {
5309          SvREFCNT_dec(a);
5310          croak("In Math::GMPz::overload_mul_eq, cannot coerce an Inf to a Math::GMPz value");
5311        }
5312 
5313        buffer_size = ld < 0.0Q ? ld * -1.0Q : ld;
5314        buffer_size = ceilq(logq(buffer_size + 1) / 2.30258509299404568401799145468436418Q);
5315 
5316        Newxz(buffer, (int)buffer_size + 5, char);
5317 
5318        returned = quadmath_snprintf(buffer, (size_t)buffer_size + 5, "%.0Qf", ld);
5319        if(returned < 0) {
5320          SvREFCNT_dec(a);
5321          croak("In Math::GMPz::overload_mul_eq, encoding error in quadmath_snprintf function");
5322        }
5323        if(returned >= buffer_size + 5) {
5324          SvREFCNT_dec(a);
5325          croak("In Math::GMPz::overload_mul_eq, buffer given to quadmath_snprintf function was too small");
5326        }
5327        mpz_init_set_str(t, buffer, 10);
5328        Safefree(buffer);
5329 
5330 #elif defined(USE_LONG_DOUBLE)
5331 
5332        ld = (long double)SvNVX(b) >= 0 ? floorl((long double)SvNVX(b)) : ceill((long double)SvNVX(b));
5333        if(ld != ld) {
5334          SvREFCNT_dec(a);
5335          croak("In Math::GMPz::overload_mul_eq, cannot coerce a NaN to a Math::GMPz value");
5336        }
5337        if(ld != 0 && (ld / ld != 1)) {
5338          SvREFCNT_dec(a);
5339          croak("In Math::GMPz::overload_mul_eq, cannot coerce an Inf to a Math::GMPz value");
5340        }
5341 
5342        buffer_size = ld < 0.0L ? ld * -1.0L : ld;
5343        buffer_size = ceill(logl(buffer_size + 1) / 2.30258509299404568401799145468436418L);
5344 
5345        Newxz(buffer, (int)buffer_size + 5, char);
5346 
5347        if(sprintf(buffer, "%.0Lf", ld) >= (int)buffer_size + 5) {
5348          SvREFCNT_dec(a);
5349          croak("In Math::GMPz::overload_mul_eq, buffer overflow in sprintf function");
5350        }
5351        mpz_init_set_str(t, buffer, 10);
5352        Safefree(buffer);
5353 #else
5354        double d = SvNVX(b);
5355        if(d != d) {
5356          SvREFCNT_dec(a);
5357          croak("In Math::GMPz::overload_mul_eq, cannot coerce a NaN to a Math::GMPz value");
5358        }
5359        if(d != 0 && (d / d != 1)) {
5360          SvREFCNT_dec(a);
5361          croak("In Math::GMPz::overload_mul_eq, cannot coerce an Inf to a Math::GMPz value");
5362        }
5363        mpz_init_set_d(t, d);
5364 #endif
5365        mpz_mul(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
5366        mpz_clear(t);
5367        return a;
5368      }
5369 
5370      if(sv_isobject(b)) {
5371        const char *h = HvNAME(SvSTASH(SvRV(b)));
5372        if(strEQ(h, "Math::GMPz")) {
5373          mpz_mul(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(b)))));
5374          return a;
5375        }
5376 
5377        if(strEQ(h, "Math::BigInt")) {
5378          VALIDATE_MBI_OBJECT {
5379            SvREFCNT_dec(a);
5380            croak("Invalid Math::BigInt object supplied to Math::GMPz::overload_mul_eq");
5381          }
5382 
5383          MBI_GMP_INSERT
5384 
5385          if(mpz) {
5386            mpz_mul(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), (mpz_srcptr)mpz);
5387            if(strEQ("-", sign)) mpz_neg(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))));
5388            return a;
5389          }
5390 
5391          mpz_init_set_str(t, SvPV_nolen(b), 0);
5392          mpz_mul(*(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), *(INT2PTR(mpz_t *, SvIVX(SvRV(a)))), t);
5393          mpz_clear(t);
5394          return a;
5395        }
5396      }
5397 
5398      SvREFCNT_dec(a);
5399      croak("Invalid argument supplied to Math::GMPz::overload_mul_eq");
5400 }
5401 
5402 
5403 
eratosthenes_string(pTHX_ SV * x_arg)5404 SV * eratosthenes_string(pTHX_ SV * x_arg) {
5405 
5406 unsigned char *v, set[8] = {254,253,251,247,239,223,191,127};
5407 unsigned long leap, i, size, b, imax, k, x = (unsigned long)SvUV(x_arg);
5408 SV * ret;
5409 
5410 if(x & 1) croak("max_num argument must be even in eratosthenes_string");
5411 
5412 imax = sqrt(x - 1) / 2;
5413 
5414 b = (x + 1) / 2;
5415 
5416 if(!(b % 8)) size = b / 8;
5417 else size = (b / 8) + 1;
5418 
5419 ret = NEWSV(0, size);
5420 
5421 for(i = 1; i < size; ++i) SvPVX(ret)[i] = 255;
5422 SvPVX(ret)[0] = 254;
5423 
5424 for(i = 0; i <= imax; ++i) {
5425 
5426     if(SvPVX(ret)[i / 8] & (1 << (i % 8))) {
5427        leap = (2 * i) + 1;
5428        k = 2 * i * (i + 1);
5429        while(k < b) {
5430              SvPVX(ret)[k / 8] &= set[k % 8];
5431              k += leap;
5432              }
5433        }
5434 }
5435 
5436 SvPOK_on(ret);
5437 SvCUR_set(ret, size);
5438 *SvEND(ret) = 0;
5439 
5440 return ret;
5441 
5442 }
5443 
gmp_v(pTHX)5444 SV * gmp_v(pTHX) {
5445 #if __GNU_MP_VERSION >= 4
5446      return newSVpv(gmp_version, 0);
5447 #else
5448      warn("From Math::GMPz::gmp_v function: 'gmp_version' is not implemented - returning '0'");
5449      return newSVpv("0", 0);
5450 #endif
5451 }
5452 
wrap_gmp_printf(pTHX_ SV * a,SV * b)5453 SV * wrap_gmp_printf(pTHX_ SV * a, SV * b) {
5454      int ret;
5455      if(sv_isobject(b)) {
5456        const char *h = HvNAME(SvSTASH(SvRV(b)));
5457        if(strEQ(h, "Math::GMPz") ||
5458          strEQ(h, "Math::GMP") ||
5459          strEQ(h, "GMP::Mpz")) {
5460          ret = gmp_printf(SvPV_nolen(a), *(INT2PTR(mpz_t *, SvIVX(SvRV(b)))));
5461          fflush(stdout);
5462          return newSViv(ret);
5463        }
5464        if(strEQ(h, "Math::GMPq") ||
5465          strEQ(h, "GMP::Mpq")) {
5466          ret = gmp_printf(SvPV_nolen(a), *(INT2PTR(mpq_t *, SvIVX(SvRV(b)))));
5467          fflush(stdout);
5468          return newSViv(ret);
5469        }
5470        if(strEQ(h, "Math::GMPf") ||
5471          strEQ(h, "GMP::Mpf")) {
5472          ret = gmp_printf(SvPV_nolen(a), *(INT2PTR(mpf_t *, SvIVX(SvRV(b)))));
5473          fflush(stdout);
5474          return newSViv(ret);
5475        }
5476 
5477        croak("Unrecognised object supplied as argument to Rmpz_printf");
5478      }
5479 
5480      if(SV_IS_IOK(b)) {
5481        if(SvUOK(b)) {
5482          ret = gmp_printf(SvPV_nolen(a), SvUVX(b));
5483          fflush(stdout);
5484          return newSViv(ret);
5485        }
5486 
5487        ret = gmp_printf(SvPV_nolen(a), SvIVX(b));
5488        fflush(stdout);
5489        return newSViv(ret);
5490      }
5491 
5492      if(SV_IS_POK(b)) {
5493        ret = gmp_printf(SvPV_nolen(a), SvPV_nolen(b));
5494        fflush(stdout);
5495        return newSViv(ret);
5496      }
5497 
5498      if(SV_IS_NOK(b)) {
5499        ret = gmp_printf(SvPV_nolen(a), SvNVX(b));
5500        fflush(stdout);
5501        return newSViv(ret);
5502      }
5503 
5504      croak("Unrecognised type supplied as argument to Rmpz_printf");
5505 }
5506 
wrap_gmp_fprintf(pTHX_ FILE * stream,SV * a,SV * b)5507 SV * wrap_gmp_fprintf(pTHX_ FILE * stream, SV * a, SV * b) {
5508      int ret;
5509      if(sv_isobject(b)) {
5510        const char *h = HvNAME(SvSTASH(SvRV(b)));
5511        if(strEQ(h, "Math::GMPz") ||
5512          strEQ(h, "Math::GMP") ||
5513          strEQ(h, "GMP::Mpz")) {
5514          ret = gmp_fprintf(stream, SvPV_nolen(a), *(INT2PTR(mpz_t *, SvIVX(SvRV(b)))));
5515          fflush(stream);
5516          return newSViv(ret);
5517        }
5518        if(strEQ(h, "Math::GMPq") ||
5519          strEQ(h, "GMP::Mpq")) {
5520          ret = gmp_fprintf(stream, SvPV_nolen(a), *(INT2PTR(mpq_t *, SvIVX(SvRV(b)))));
5521          fflush(stream);
5522          return newSViv(ret);
5523        }
5524        if(strEQ(h, "Math::GMPf") ||
5525          strEQ(h, "GMP::Mpf")) {
5526          ret = gmp_fprintf(stream, SvPV_nolen(a), *(INT2PTR(mpf_t *, SvIVX(SvRV(b)))));
5527          fflush(stream);
5528          return newSViv(ret);
5529        }
5530 
5531        else croak("Unrecognised object supplied as argument to Rmpz_fprintf");
5532      }
5533 
5534      if(SV_IS_IOK(b)) {
5535        if(SvUOK(b)) {
5536          ret = gmp_fprintf(stream, SvPV_nolen(a), SvUVX(b));
5537          fflush(stream);
5538          return newSViv(ret);
5539        }
5540 
5541        ret = gmp_fprintf(stream, SvPV_nolen(a), SvIVX(b));
5542        fflush(stream);
5543        return newSViv(ret);
5544      }
5545 
5546      if(SV_IS_POK(b)) {
5547        ret = gmp_fprintf(stream, SvPV_nolen(a), SvPV_nolen(b));
5548        fflush(stream);
5549        return newSViv(ret);
5550      }
5551 
5552      if(SV_IS_NOK(b)) {
5553        ret = gmp_fprintf(stream, SvPV_nolen(a), SvNVX(b));
5554        fflush(stream);
5555        return newSViv(ret);
5556      }
5557 
5558      croak("Unrecognised type supplied as argument to Rmpz_fprintf");
5559 }
5560 
wrap_gmp_sprintf(pTHX_ SV * s,SV * a,SV * b,int buflen)5561 SV * wrap_gmp_sprintf(pTHX_ SV * s, SV * a, SV * b, int buflen) {
5562      int ret;
5563      char *stream;
5564 
5565      Newx(stream, buflen, char);
5566 
5567      if(sv_isobject(b)) {
5568        const char *h = HvNAME(SvSTASH(SvRV(b)));
5569        if(strEQ(h, "Math::GMPz") ||
5570          strEQ(h, "Math::GMP") ||
5571          strEQ(h, "GMP::Mpz")) {
5572          ret = gmp_sprintf(stream, SvPV_nolen(a), *(INT2PTR(mpz_t *, SvIVX(SvRV(b)))));
5573          sv_setpv(s, stream);
5574          Safefree(stream);
5575          return newSViv(ret);
5576        }
5577 
5578        if(strEQ(h, "Math::GMPq") ||
5579          strEQ(h, "GMP::Mpq")) {
5580          ret = gmp_sprintf(stream, SvPV_nolen(a), *(INT2PTR(mpq_t *, SvIVX(SvRV(b)))));
5581          sv_setpv(s, stream);
5582          Safefree(stream);
5583          return newSViv(ret);
5584        }
5585 
5586        if(strEQ(h, "Math::GMPf") ||
5587          strEQ(h, "GMP::Mpf")) {
5588          ret = gmp_sprintf(stream, SvPV_nolen(a), *(INT2PTR(mpf_t *, SvIVX(SvRV(b)))));
5589          sv_setpv(s, stream);
5590          Safefree(stream);
5591          return newSViv(ret);
5592        }
5593 
5594        croak("Unrecognised object supplied as argument to Rmpz_sprintf");
5595      }
5596 
5597      if(SV_IS_IOK(b)) {
5598        if(SvUOK(b)) {
5599          ret = gmp_sprintf(stream, SvPV_nolen(a), SvUVX(b));
5600          sv_setpv(s, stream);
5601          Safefree(stream);
5602          return newSViv(ret);
5603        }
5604 
5605        ret = gmp_sprintf(stream, SvPV_nolen(a), SvIVX(b));
5606        sv_setpv(s, stream);
5607        Safefree(stream);
5608        return newSViv(ret);
5609      }
5610 
5611      if(SV_IS_POK(b)) {
5612        ret = gmp_sprintf(stream, SvPV_nolen(a), SvPV_nolen(b));
5613        sv_setpv(s, stream);
5614        Safefree(stream);
5615        return newSViv(ret);
5616      }
5617 
5618      if(SV_IS_NOK(b)) {
5619        ret = gmp_sprintf(stream, SvPV_nolen(a), SvNVX(b));
5620        sv_setpv(s, stream);
5621        Safefree(stream);
5622        return newSViv(ret);
5623      }
5624 
5625      croak("Unrecognised type supplied as argument to Rmpz_sprintf");
5626 }
5627 
wrap_gmp_snprintf(pTHX_ SV * s,SV * bytes,SV * a,SV * b,int buflen)5628 SV * wrap_gmp_snprintf(pTHX_ SV * s, SV * bytes, SV * a, SV * b, int buflen) {
5629      int ret;
5630      char * stream;
5631 
5632      Newx(stream, buflen, char);
5633 
5634      if(sv_isobject(b)) {
5635        const char *h = HvNAME(SvSTASH(SvRV(b)));
5636        if(strEQ(h, "Math::GMPz") ||
5637          strEQ(h, "Math::GMP") ||
5638          strEQ(h, "GMP::Mpz")) {
5639          ret = gmp_snprintf(stream, (size_t)SvUV(bytes), SvPV_nolen(a), *(INT2PTR(mpz_t *, SvIVX(SvRV(b)))));
5640          sv_setpv(s, stream);
5641          Safefree(stream);
5642          return newSViv(ret);
5643        }
5644 
5645        if(strEQ(h, "Math::GMPq") ||
5646          strEQ(h, "GMP::Mpq")) {
5647          ret = gmp_snprintf(stream, (size_t)SvUV(bytes), SvPV_nolen(a), *(INT2PTR(mpq_t *, SvIVX(SvRV(b)))));
5648          sv_setpv(s, stream);
5649          Safefree(stream);
5650          return newSViv(ret);
5651        }
5652 
5653        if(strEQ(h, "Math::GMPf") ||
5654          strEQ(h, "GMP::Mpf")) {
5655          ret = gmp_snprintf(stream, (size_t)SvUV(bytes), SvPV_nolen(a), *(INT2PTR(mpf_t *, SvIVX(SvRV(b)))));
5656          sv_setpv(s, stream);
5657          Safefree(stream);
5658          return newSViv(ret);
5659        }
5660 
5661        croak("Unrecognised object supplied as argument to Rmpz_snprintf");
5662      }
5663 
5664      if(SV_IS_IOK(b)) {
5665        if(SvUOK(b)) {
5666          ret = gmp_snprintf(stream, (size_t)SvUV(bytes), SvPV_nolen(a), SvUVX(b));
5667          sv_setpv(s, stream);
5668          Safefree(stream);
5669          return newSViv(ret);
5670        }
5671 
5672        ret = gmp_snprintf(stream, (size_t)SvUV(bytes), SvPV_nolen(a), SvIVX(b));
5673        sv_setpv(s, stream);
5674        Safefree(stream);
5675        return newSViv(ret);
5676      }
5677 
5678      if(SV_IS_POK(b)) {
5679        ret = gmp_snprintf(stream, (size_t)SvUV(bytes), SvPV_nolen(a), SvPV_nolen(b));
5680        sv_setpv(s, stream);
5681        Safefree(stream);
5682        return newSViv(ret);
5683      }
5684 
5685      if(SV_IS_NOK(b)) {
5686        ret = gmp_snprintf(stream, (size_t)SvUV(bytes), SvPV_nolen(a), SvNVX(b));
5687        sv_setpv(s, stream);
5688        Safefree(stream);
5689        return newSViv(ret);
5690      }
5691 
5692      croak("Unrecognised type supplied as argument to Rmpz_snprintf");
5693 }
5694 
_itsa(pTHX_ SV * a)5695 SV * _itsa(pTHX_ SV * a) {
5696      if(SV_IS_IOK(a)) {
5697        if(SvUOK(a)) return newSViv(1);
5698        return newSViv(2);
5699      }
5700      if(SV_IS_POK(a)) return newSViv(4);
5701      if(SV_IS_NOK(a)) return newSViv(3);
5702      if(sv_isobject(a)) {
5703        const char *h = HvNAME(SvSTASH(SvRV(a)));
5704        if(strEQ(h, "Math::GMPz"))        return newSViv(8);
5705        if(strEQ(h, "Math::GMP"))         return newSViv(9);
5706        if(strEQ(h, "Math::BigInt"))      return newSViv(-1);
5707      }
5708      return newSVuv(0);
5709 }
5710 
Rmpz_urandomb(pTHX_ SV * p,...)5711 void Rmpz_urandomb(pTHX_ SV * p, ...) {
5712      dXSARGS;
5713      unsigned long q, i, thingies;
5714 
5715      thingies = items;
5716      q = SvUV(ST(thingies - 1));
5717 
5718      if((q + 3) != thingies) croak ("Wrong args supplied to mpz_urandomb function");
5719 
5720      for(i = 0; i < q; ++i) {
5721         mpz_urandomb(*(INT2PTR(mpz_t *, SvIVX(SvRV(ST(i))))), *(INT2PTR(gmp_randstate_t *, SvIVX(SvRV(ST(thingies - 3))))), SvUV(ST(thingies - 2)));
5722         }
5723 
5724      XSRETURN(0);
5725 }
5726 
Rmpz_urandomm(pTHX_ SV * x,...)5727 void Rmpz_urandomm(pTHX_ SV * x, ...){
5728      dXSARGS;
5729      unsigned long q, i, thingies;
5730 
5731      thingies = items;
5732      q = SvUV(ST(thingies - 1));
5733 
5734      if((q + 3) != thingies) croak ("Wrong args supplied to mpz_urandomm function");
5735 
5736      for(i = 0; i < q; ++i) {
5737         mpz_urandomm(*(INT2PTR(mpz_t *, SvIVX(SvRV(ST(i))))), *(INT2PTR(gmp_randstate_t *, SvIVX(SvRV(ST(thingies - 3))))), *(INT2PTR(mpz_t *, SvIVX(SvRV(ST(thingies - 2))))));
5738         }
5739 
5740      XSRETURN(0);
5741 }
5742 
Rmpz_rrandomb(pTHX_ SV * x,...)5743 void Rmpz_rrandomb(pTHX_ SV * x, ...) {
5744      dXSARGS;
5745      unsigned long q, i, thingies;
5746 
5747      thingies = items;
5748      q = SvUV(ST(thingies - 1));
5749 
5750      if((q + 3) != thingies) croak ("Wrong args supplied to mpz_rrandomb function");
5751 
5752      for(i = 0; i < q; ++i) {
5753         mpz_rrandomb(*(INT2PTR(mpz_t *, SvIVX(SvRV(ST(i))))), *(INT2PTR(gmp_randstate_t *, SvIVX(SvRV(ST(thingies - 3))))), SvUV(ST(thingies - 2)));
5754         }
5755 
5756      XSRETURN(0);
5757 }
5758 
rand_init(pTHX_ SV * seed)5759 SV * rand_init(pTHX_ SV * seed) {
5760      gmp_randstate_t * state;
5761      SV * obj_ref, * obj;
5762 
5763      New(1, state, 1, gmp_randstate_t);
5764      if(state == NULL) croak("Failed to allocate memory in rand_init function");
5765      obj_ref = newSV(0);
5766      obj = newSVrv(obj_ref, NULL);
5767      gmp_randinit_default(*state);
5768      gmp_randseed(*state, *(INT2PTR(mpz_t *, SvIVX(SvRV(seed)))));
5769      sv_setiv(obj, INT2PTR(IV, state));
5770      SvREADONLY_on(obj);
5771      return obj_ref;
5772      }
5773 
rand_clear(pTHX_ SV * p)5774 void rand_clear(pTHX_ SV * p) {
5775      gmp_randclear(*(INT2PTR(gmp_randstate_t *, SvIVX(SvRV(p)))));
5776      Safefree(INT2PTR(gmp_randstate_t *, SvIVX(SvRV(p))));
5777      }
5778 
_has_longlong(void)5779 int _has_longlong(void) {
5780 #ifdef MATH_GMPZ_NEED_LONG_LONG_INT
5781     return 1;
5782 #else
5783     return 0;
5784 #endif
5785 }
5786 
_has_longdouble(void)5787 int _has_longdouble(void) {
5788 #if defined(USE_LONG_DOUBLE)
5789     return 1;
5790 #else
5791     return 0;
5792 #endif
5793 }
5794 
_has_float128(void)5795 int _has_float128(void) {
5796 #if defined(USE_QUADMATH)
5797     return 1;
5798 #else
5799     return 0;
5800 #endif
5801 }
5802 
5803 /* Has inttypes.h been included ? */
_has_inttypes(void)5804 int _has_inttypes(void) {
5805 #ifdef _MSC_VER
5806 return 0;
5807 #else
5808 #if defined MATH_GMPZ_NEED_LONG_LONG_INT
5809 return 1;
5810 #else
5811 return 0;
5812 #endif
5813 #endif
5814 }
5815 
Rmpz_inp_raw(pTHX_ mpz_t * a,FILE * stream)5816 SV * Rmpz_inp_raw(pTHX_ mpz_t * a, FILE * stream) {
5817      size_t ret = mpz_inp_raw(*a, stream);
5818      fflush(stream);
5819      return newSVuv(ret);
5820 }
5821 
Rmpz_out_raw(pTHX_ FILE * stream,mpz_t * a)5822 SV * Rmpz_out_raw(pTHX_ FILE * stream, mpz_t * a) {
5823      size_t ret = mpz_out_raw(stream, *a);
5824      fflush(stream);
5825      return newSVuv(ret);
5826 }
5827 
___GNU_MP_VERSION(pTHX)5828 SV * ___GNU_MP_VERSION(pTHX) {
5829      return newSVuv(__GNU_MP_VERSION);
5830 }
5831 
___GNU_MP_VERSION_MINOR(pTHX)5832 SV * ___GNU_MP_VERSION_MINOR(pTHX) {
5833      return newSVuv(__GNU_MP_VERSION_MINOR);
5834 }
5835 
___GNU_MP_VERSION_PATCHLEVEL(pTHX)5836 SV * ___GNU_MP_VERSION_PATCHLEVEL(pTHX) {
5837      return newSVuv(__GNU_MP_VERSION_PATCHLEVEL);
5838 }
5839 
___GNU_MP_RELEASE(pTHX)5840 SV * ___GNU_MP_RELEASE(pTHX) {
5841 #if defined(__GNU_MP_RELEASE)
5842      return newSVuv(__GNU_MP_RELEASE);
5843 #else
5844      return &PL_sv_undef;
5845 #endif
5846 }
5847 
___GMP_CC(pTHX)5848 SV * ___GMP_CC(pTHX) {
5849 #ifdef __GMP_CC
5850      char * ret = __GMP_CC;
5851      return newSVpv(ret, 0);
5852 #else
5853      return &PL_sv_undef;
5854 #endif
5855 }
5856 
___GMP_CFLAGS(pTHX)5857 SV * ___GMP_CFLAGS(pTHX) {
5858 #ifdef __GMP_CFLAGS
5859      char * ret = __GMP_CFLAGS;
5860      return newSVpv(ret, 0);
5861 #else
5862      return &PL_sv_undef;
5863 #endif
5864 }
5865 
5866 #if __GNU_MP_VERSION >= 5
5867 #ifndef __MPIR_VERSION
Rmpz_powm_sec(mpz_t * dest,mpz_t * base,mpz_t * exp,mpz_t * mod)5868 void Rmpz_powm_sec(mpz_t * dest, mpz_t * base, mpz_t * exp, mpz_t * mod) {
5869      mpz_powm_sec(*dest, *base, *exp, *mod);
5870 }
5871 #else
Rmpz_powm_sec(mpz_t * dest,mpz_t * base,mpz_t * exp,mpz_t * mod)5872 void Rmpz_powm_sec(mpz_t * dest, mpz_t * base, mpz_t * exp, mpz_t * mod) {
5873      croak("Rmpz_powm_sec not implemented by the mpir library");
5874 }
5875 #endif
5876 #else
Rmpz_powm_sec(mpz_t * dest,mpz_t * base,mpz_t * exp,mpz_t * mod)5877 void Rmpz_powm_sec(mpz_t * dest, mpz_t * base, mpz_t * exp, mpz_t * mod) {
5878      croak("Rmpz_powm_sec not implemented - gmp-5 or later needed, this is gmp-%d", __GNU_MP_VERSION);
5879 }
5880 #endif
5881 
_using_mpir(void)5882 int _using_mpir(void) {
5883 #ifdef __MPIR_VERSION
5884 return 1;
5885 #else
5886 return 0;
5887 #endif
5888 }
5889 
_Rmpz_NULL(pTHX)5890 SV * _Rmpz_NULL(pTHX) {
5891      mpz_t * mpz_t_obj;
5892      SV * obj_ref, * obj;
5893 
5894      mpz_t_obj = NULL;
5895      obj_ref = newSV(0);
5896      obj = newSVrv(obj_ref, NULL);
5897 
5898      sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
5899      SvREADONLY_on(obj);
5900      return obj_ref;
5901 }
5902 
_wrap_count(pTHX)5903 SV * _wrap_count(pTHX) {
5904      return newSVuv(PL_sv_count);
5905 }
5906 
Rprbg_ms(pTHX_ mpz_t * outref,mpz_t * p,mpz_t * q,mpz_t * seed,int bits_required)5907 void Rprbg_ms(pTHX_ mpz_t * outref, mpz_t * p, mpz_t * q, mpz_t * seed, int bits_required) {
5908      mpz_t n, phi, pless1, qless1, mod, keep;
5909      unsigned long e, k, bign, r, its, i, r_shift, check;
5910      double kdoub;
5911      gmp_randstate_t state;
5912 
5913      mpz_init(n);
5914      mpz_init(phi);
5915      mpz_init(pless1);
5916      mpz_init(qless1);
5917 
5918      mpz_sub_ui(qless1, *q, 1);
5919      mpz_sub_ui(pless1, *p, 1);
5920 
5921      mpz_mul(n, *p, *q);
5922 
5923      mpz_mul(phi, pless1, qless1);
5924      mpz_clear(pless1);
5925      mpz_clear(qless1);
5926 
5927      bign = mpz_sizeinbase(n, 2);
5928      e = bign / 80;
5929 
5930      while(1) {
5931         if(e < 1) croak("You need to choose larger primes P and Q. The product of P-1 and Q-1 needs to be at least an 80-bit number");
5932         if(mpz_gcd_ui(NULL, phi, e) == 1) break;
5933         --e;
5934         if(e < 3) croak("The chosen primes are unsuitable in prbg_ms() function");
5935         }
5936 
5937      mpz_clear(phi);
5938 
5939      kdoub = (double) 2 / (double) e;
5940      kdoub = (double) 1 - kdoub;
5941      kdoub *= (double) bign;
5942      k = kdoub;
5943      r = bign - k;
5944 
5945      gmp_randinit_default(state);
5946      gmp_randseed(state, *seed);
5947      mpz_urandomb(*seed, state, r);
5948      gmp_randclear(state);
5949 
5950      r_shift = bits_required % k;
5951 
5952      if(r_shift) its = (bits_required / k) + 1;
5953      else its = bits_required / k;
5954 
5955      mpz_init(mod);
5956      mpz_init(keep);
5957      mpz_set_ui(*outref, 0);
5958      mpz_ui_pow_ui(mod, 2, k);
5959 
5960      for(i = 0; i < its; ++i) {
5961          mpz_powm_ui(*seed, *seed, e, n);
5962          mpz_mod(keep, *seed, mod);
5963          mpz_mul_2exp(*outref, *outref, k);
5964          mpz_add(*outref, *outref, keep);
5965          mpz_fdiv_q_2exp(*seed, *seed, k);
5966          if(!i) check = k - mpz_sizeinbase(keep, 2);
5967          }
5968      mpz_clear(n);
5969      mpz_clear(keep);
5970      mpz_clear(mod);
5971 
5972      if(r_shift) mpz_fdiv_q_2exp(*outref, *outref, k - r_shift);
5973 
5974      if(check + mpz_sizeinbase(*outref, 2) != bits_required)
5975         croak("Bug in csprng() function");
5976 
5977 }
5978 
Rprbg_bbs(pTHX_ mpz_t * outref,mpz_t * p,mpz_t * q,mpz_t * seed,int bits_required)5979 void Rprbg_bbs(pTHX_ mpz_t * outref, mpz_t * p, mpz_t * q, mpz_t * seed, int bits_required) {
5980      mpz_t n, gcd, one;
5981      unsigned long i, k;
5982      gmp_randstate_t state;
5983 
5984      if(mpz_fdiv_ui(*p, 4) != 3) croak ("First prime is unsuitable for Blum-Blum-Shub prbg (must be congruent to 3, mod 4)");
5985      if(mpz_fdiv_ui(*q, 4) != 3) croak ("Second prime is unsuitable for Blum-Blum-Shub prbg (must be congruent to 3, mod 4)");
5986      mpz_init(n);
5987 
5988      mpz_mul(n, *p, *q);
5989 
5990      mpz_init(gcd);
5991      gmp_randinit_default(state);
5992      gmp_randseed(state, *seed);
5993      mpz_urandomm(*seed, state, n);
5994      gmp_randclear(state);
5995 
5996      while(1) {
5997            if(mpz_cmp_ui(*seed, 100) < 0)croak("Blum-Blum-Shub seed is ridiculously small. How did this happen ?");
5998            mpz_gcd(gcd, *seed, n);
5999            if(!mpz_cmp_ui(gcd, 1)) break;
6000            mpz_sub_ui(*seed, *seed, 1);
6001            }
6002 
6003      mpz_powm_ui(*seed, *seed, 2, n);
6004 
6005      mpz_init_set_ui(*outref, 0);
6006      mpz_init_set_ui(one, 1);
6007 
6008      for(i = 0; i < bits_required; ++i) {
6009          mpz_powm_ui(*seed, *seed, 2, n);
6010          k = mpz_tstbit(*seed, 0);
6011          if(k) {
6012             mpz_mul_2exp(gcd, one, i);
6013             mpz_add(*outref, gcd, *outref);
6014             }
6015          }
6016 
6017      mpz_clear(n);
6018      mpz_clear(gcd);
6019      mpz_clear(one);
6020 
6021 }
6022 
Rmonobit(mpz_t * bitstream)6023 int Rmonobit(mpz_t * bitstream) {
6024     unsigned long len, i, count = 0;
6025 
6026     len = mpz_sizeinbase(*bitstream, 2);
6027 
6028     if(len > 20000) croak("Wrong size random sequence for monobit test");
6029     if(len < 19967) {
6030        warn("More than 33 leading zeroes in Rmonobit test\n");
6031        return 0;
6032        }
6033 
6034     count = mpz_popcount(*bitstream);
6035 
6036     if(count > 9654 && count < 10346) return 1;
6037     return 0;
6038 
6039 }
6040 
Rlong_run(mpz_t * bitstream)6041 int Rlong_run(mpz_t * bitstream) {
6042     unsigned int i, el, init = 0, count = 0, len, t;
6043 
6044     len = mpz_sizeinbase(*bitstream, 2);
6045 
6046     if(len > 20000) croak("Wrong size random sequence for Rlong_run test");
6047     if(len < 19967) {
6048        warn("More than 33 leading zeroes in long_run test\n");
6049        return 0;
6050        }
6051 
6052     el = mpz_tstbit(*bitstream, 0);
6053 
6054     for(i = 0; i < len; ++i) {
6055         t = mpz_tstbit(*bitstream, i);
6056         if(t == el) ++count;
6057         else {
6058            el = t;
6059            if(count > init) init = count;
6060            count = 1;
6061            }
6062         }
6063 
6064     if(init < 34 && count < 34) return 1;
6065     else warn("init: %u count: %u", init, count);
6066     return 0;
6067 
6068 }
6069 
Rruns(mpz_t * bitstream)6070 int Rruns(mpz_t * bitstream) {
6071     int b[6] = {0,0,0,0,0,0}, g[6] = {0,0,0,0,0,0},
6072     len, count = 1, i, t, diff;
6073 
6074     len = mpz_sizeinbase(*bitstream, 2);
6075     diff = 20000 - len;
6076 
6077     if(len > 20000) croak("Wrong size random sequence for monobit test");
6078     if(len < 19967) {
6079        warn("More than 33 leading zeroes in runs test\n");
6080        return 0;
6081        }
6082 
6083     --len;
6084 
6085     for(i = 0; i < len; ++i) {
6086       t = mpz_tstbit(*bitstream, i);
6087       if(t == mpz_tstbit(*bitstream, i + 1)) ++ count;
6088       else {
6089         if(t) {
6090           if(count >= 6) ++b[5];
6091           else ++b[count - 1];
6092         }
6093         else {
6094           if(count >= 6) ++g[5];
6095           else ++g[count - 1];
6096         }
6097         count = 1;
6098       }
6099     }
6100 
6101     if(count >= 6) {
6102       if(mpz_tstbit(*bitstream, len)) {
6103         ++b[5];
6104         if(diff >= 6) {
6105           ++g[5];
6106         }
6107         else {
6108           if(diff) ++g[diff - 1];
6109         }
6110       }
6111       else ++g[5];
6112       }
6113     else {
6114       if(mpz_tstbit(*bitstream, len)) {
6115         ++b[count - 1];
6116         if(diff >= 6) {
6117           ++g[5];
6118         }
6119         else {
6120           if(diff) ++ g[diff - 1];
6121         }
6122       }
6123       else {
6124         count += diff;
6125         count >= 6 ? ++g[5] : ++g[count - 1];
6126       }
6127     }
6128 
6129 
6130     if (
6131             b[0] <= 2267 || g[0] <= 2267 ||
6132             b[0] >= 2733 || g[0] >= 2733 ||
6133             b[1] <= 1079 || g[1] <= 1079 ||
6134             b[1] >= 1421 || g[1] >= 1421 ||
6135             b[2] <= 502  || g[2] <= 502  ||
6136             b[2] >= 748  || g[2] >= 748  ||
6137             b[3] <= 223  || g[3] <= 223  ||
6138             b[3] >= 402  || g[3] >= 402  ||
6139             b[4] <= 90   || g[4] <= 90   ||
6140             b[4] >= 223  || g[4] >= 223  ||
6141             b[5] <= 90   || g[5] <= 90   ||
6142             b[5] >= 223  || g[5] >= 223
6143            ) return 0;
6144 
6145     return 1;
6146 
6147 }
6148 
Rpoker(mpz_t * bitstream)6149 int Rpoker (mpz_t * bitstream) {
6150     int counts[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
6151        len, i, st, diff;
6152     double n = 0;
6153 
6154     len = mpz_sizeinbase(*bitstream, 2);
6155 
6156     if(len > 20000) croak("Wrong size random sequence for poker test");
6157     if(len < 19967) {
6158        warn("More than 33 leading zeroes in poker test\n");
6159        return 0;
6160        }
6161 
6162 /* pad with trailing zeroes (if necessary) to achieve length of 20000 bits. */
6163     diff = 20000 - len;
6164     if(diff) mpz_mul_2exp(*bitstream, *bitstream, diff);
6165     if(mpz_sizeinbase(*bitstream, 2) != 20000) croak("Bug in bit sequence manipulation in poker() function");
6166 
6167     for(i = 0; i < 20000; i += 4) {
6168         st = mpz_tstbit(*bitstream, i) +
6169              (mpz_tstbit(*bitstream, i + 1) * 2) +
6170              (mpz_tstbit(*bitstream, i + 2) * 4) +
6171              (mpz_tstbit(*bitstream, i + 3) * 8);
6172         ++counts[st];
6173         }
6174 
6175 
6176     for(i = 0; i < 16; ++i) n += counts[i] * counts[i];
6177 
6178     n /= 5000;
6179     n *= 16;
6180     n -= 5000;
6181 
6182     if(n > 1.03 && n < 57.4) return 1;
6183 
6184     return 0;
6185 }
6186 
_get_xs_version(pTHX)6187 SV * _get_xs_version(pTHX) {
6188      return newSVpv(XS_VERSION, 0);
6189 }
6190 
query_eratosthenes_string(pTHX_ int candidate,char * str)6191 SV * query_eratosthenes_string(pTHX_ int candidate, char * str) {
6192      int cand = candidate - 1;
6193      if(cand == 1) return newSVuv(1);
6194      if(cand & 1 || cand <= 0) return newSVuv(0);
6195      if(str[cand / 16] & 1 << (cand / 2) % 8)
6196        return newSVuv(1);
6197      return newSVuv(0);
6198 }
6199 
autocorrelation(pTHX_ mpz_t * bitstream,int offset)6200 void autocorrelation(pTHX_ mpz_t * bitstream, int offset) {
6201      dXSARGS;
6202      int i, index, last, count = 0, short_ = 0;
6203      mpz_t temp;
6204      double x, diff;
6205      int len = mpz_sizeinbase(*bitstream, 2);
6206 
6207      if(len > 20000) croak("Wrong size random sequence for autocorrelation test");
6208      if(len < 19967) {
6209         warn("More than 33 leading zeroes in autocorrelation test\n");
6210         ST(0) = sv_2mortal(newSViv(0));
6211         ST(1) = sv_2mortal(newSVnv(0.0));
6212         XSRETURN(2);
6213         }
6214 
6215 /* make sure *bitstream has a length of 20000 bits. */
6216      if(20000 - len) {
6217        short_ = 1;
6218        mpz_init_set_ui(temp, 1);
6219        mpz_mul_2exp(temp, temp, 19999);
6220        mpz_add(*bitstream, *bitstream, temp);
6221      }
6222      if(mpz_sizeinbase(*bitstream, 2) != 20000) croak("Bit sequence has length of %d bits in autocorrelation function", (int)mpz_sizeinbase(*bitstream, 2));
6223 
6224      index = 19999 - offset;
6225      for(i = 0; i < index - 1; ++i) {
6226        if(mpz_tstbit(*bitstream, i) ^ mpz_tstbit(*bitstream, i + offset)) count += 1;
6227      }
6228 
6229      last = short_ ? 0 : 1;
6230 
6231      if(mpz_tstbit(*bitstream, index - 1) ^ last) count += 1;
6232 
6233 /* restore *bitstream to its original value && free temp (iff necessary) */
6234      if(short_) {
6235        mpz_sub(*bitstream, *bitstream, temp);
6236        mpz_clear(temp);
6237      }
6238 
6239    ST(0) = sv_2mortal(newSViv(count));
6240 
6241    diff = 20000.0 - (double)offset;
6242    x = (2 * ((double)count - (diff / 2))) / (sqrt(diff));
6243 
6244    ST(1) = sv_2mortal(newSVnv(x));
6245    XSRETURN(2);
6246 }
6247 
autocorrelation_20000(pTHX_ mpz_t * bitstream,int offset)6248 int autocorrelation_20000(pTHX_ mpz_t * bitstream, int offset) {
6249     dXSARGS;
6250     int i, last, count = 0, short_ = 0;
6251     mpz_t temp;
6252     double x, diff;
6253     int len = mpz_sizeinbase(*bitstream, 2);
6254 
6255     if(len > 20000 + offset) croak("Wrong size random sequence for autocorrelation_20000 test");
6256     if(len < 19967 + offset) {
6257       warn("More than 33 leading zeroes in autocorrelation_20000 test\n");
6258       return 0;
6259     }
6260 
6261 /* make sure *bitstream has a length of 20000 + offset bits. */
6262     if(20000 + offset - len) {
6263       short_ = 1;
6264       mpz_init_set_ui(temp, 1);
6265       mpz_mul_2exp(temp, temp, 19999 + offset);
6266       mpz_add(*bitstream, *bitstream, temp);
6267     }
6268    if(mpz_sizeinbase(*bitstream, 2) != 20000 + offset) croak("Bit sequence has length of %d bits in autocorrelation_20000 function; should have size of %d bits", (int)mpz_sizeinbase(*bitstream, 2), 20000 + offset);
6269 
6270     for(i = 0; i < 19999; ++i) {
6271       if(mpz_tstbit(*bitstream, i) ^ mpz_tstbit(*bitstream, i + offset)) count += 1;
6272     }
6273 
6274     last = short_ ? 0 : 1;
6275 
6276     if(mpz_tstbit(*bitstream, 19999) ^ last) count += 1;
6277 
6278 /* restore *bitstream to its original value && free temp (iff necessary) */
6279     if(short_) {
6280       mpz_sub(*bitstream, *bitstream, temp);
6281       mpz_clear(temp);
6282     }
6283     if(count > 9654 && count < 10346) return 1;
6284     return 0;
6285 }
6286 
_GMP_LIMB_BITS(pTHX)6287 SV * _GMP_LIMB_BITS(pTHX) {
6288 #ifdef GMP_LIMB_BITS
6289      return newSVuv(GMP_LIMB_BITS);
6290 #else
6291      return &PL_sv_undef;
6292 #endif
6293 }
6294 
_GMP_NAIL_BITS(pTHX)6295 SV * _GMP_NAIL_BITS(pTHX) {
6296 #ifdef GMP_NAIL_BITS
6297      return newSVuv(GMP_NAIL_BITS);
6298 #else
6299      return &PL_sv_undef;
6300 #endif
6301 }
6302 
_new_from_MBI(pTHX_ SV * b)6303 SV * _new_from_MBI(pTHX_ SV * b) {
6304      mpz_t * mpz_t_obj;
6305      SV * obj_ref, * obj;
6306      MBI_DECLARATIONS
6307      MBI_GMP_DECLARATIONS
6308 
6309 /*
6310      This function gets called only if it has already been ascertained that b is
6311      an object && HvNAME(SvSTASH(SvRV(b))) is "Math::BigInt", but we still need to
6312      check that the object is not NaN or Inf.
6313 */
6314      VALIDATE_MBI_OBJECT
6315        croak("Invalid Math::BigInt object supplied to Math::GMPz::_new_from_MBI");
6316 
6317      New(1, mpz_t_obj, 1, mpz_t);
6318      if(mpz_t_obj == NULL) croak("Failed to allocate memory in Math::GMPz::_new_from_MBI function");
6319      obj_ref = newSV(0);
6320      obj = newSVrv(obj_ref, "Math::GMPz");
6321      mpz_init(*mpz_t_obj);
6322      sv_setiv(obj, INT2PTR(IV, mpz_t_obj));
6323      SvREADONLY_on(obj);
6324 
6325      MBI_GMP_INSERT
6326 
6327      if(mpz) {
6328        mpz_set(*mpz_t_obj, (mpz_srcptr)mpz);
6329        if(strEQ("-", sign)) mpz_neg(*mpz_t_obj, *mpz_t_obj);
6330        return obj_ref;
6331      }
6332 
6333      mpz_set_str(*mpz_t_obj, SvPV_nolen(b), 0);
6334      return obj_ref;
6335 }
6336 
6337 
_magic_status(pTHX)6338 SV * _magic_status(pTHX) {
6339 #ifdef MATH_GMPz_HAS_MAGICEXT
6340     return newSVuv(MATH_GMPz_HAS_MAGICEXT);
6341 #endif
6342     return &PL_sv_undef;
6343 }
6344 
_dump_mbi_gmp(pTHX_ SV * b)6345 void _dump_mbi_gmp(pTHX_ SV * b) {
6346 
6347      MBI_DECLARATIONS
6348      MBI_GMP_DECLARATIONS
6349 
6350      VALIDATE_MBI_OBJECT
6351        croak("Invalid Math::BigInt object supplied to Math::GMPz::_new_from_MBI");
6352 
6353      MBI_GMP_INSERT
6354 
6355      if(mpz) {
6356        mpz_out_str(NULL, 10, (mpz_srcptr)mpz);
6357        printf(" %s\n", sign);
6358      }
6359 
6360      else printf("Unable to obtain information. (Perhaps NA ?)\n");
6361 }
6362 
_SvIOK(pTHX_ SV * sv)6363 int _SvIOK(pTHX_ SV * sv) {
6364   if(SV_IS_IOK(sv)) return 1;
6365   return 0;
6366 }
6367 
_SvPOK(SV * sv)6368 int _SvPOK(SV * sv) {
6369   if(SV_IS_POK(sv)) return 1;
6370   return 0;
6371 }
6372 
_SvNOK(SV * sv)6373 int _SvNOK(SV * sv) {
6374   if(SV_IS_NOK(sv)) return 1;
6375   return 0;
6376 }
6377 
IOK_flag(SV * sv)6378 int IOK_flag(SV * sv) {
6379   if(SvUOK(sv)) return 2;
6380   if(SvIOK(sv)) return 1;
6381   return 0;
6382 }
6383 
POK_flag(SV * sv)6384 int POK_flag(SV * sv) {
6385   if(SvPOK(sv)) return 1;
6386   return 0;
6387 }
6388 
NOK_flag(SV * sv)6389 int NOK_flag(SV * sv) {
6390   if(SvNOK(sv)) return 1;
6391   return 0;
6392 }
6393 
_sizeof_mp_bitcnt_t(pTHX)6394 SV * _sizeof_mp_bitcnt_t(pTHX) {
6395   return newSVuv(sizeof(mp_bitcnt_t));
6396 }
6397 
_gmp_index_overflow(void)6398 int _gmp_index_overflow(void) {
6399 #if defined(_GMP_INDEX_OVERFLOW)
6400   return 1;
6401 #else
6402   return 0;
6403 #endif
6404 }
6405 
6406 
6407 MODULE = Math::GMPz  PACKAGE = Math::GMPz
6408 
6409 PROTOTYPES: ENABLE
6410 
6411 
6412 SV *
6413 MATH_GMPz_IV_MAX ()
6414 CODE:
6415   RETVAL = MATH_GMPz_IV_MAX (aTHX);
6416 OUTPUT:  RETVAL
6417 
6418 
6419 SV *
6420 MATH_GMPz_IV_MIN ()
6421 CODE:
6422   RETVAL = MATH_GMPz_IV_MIN (aTHX);
6423 OUTPUT:  RETVAL
6424 
6425 
6426 SV *
6427 MATH_GMPz_UV_MAX ()
6428 CODE:
6429   RETVAL = MATH_GMPz_UV_MAX (aTHX);
6430 OUTPUT:  RETVAL
6431 
6432 PROTOTYPES: DISABLE
6433 
6434 int
6435 _is_infstring (s)
6436 	char *	s
6437 
6438 SV *
6439 Rmpz_init_set_str_nobless (num, base)
6440 	SV *	num
6441 	SV *	base
6442 CODE:
6443   RETVAL = Rmpz_init_set_str_nobless (aTHX_ num, base);
6444 OUTPUT:  RETVAL
6445 
6446 SV *
6447 Rmpz_init2_nobless (bits)
6448 	SV *	bits
6449 CODE:
6450   RETVAL = Rmpz_init2_nobless (aTHX_ bits);
6451 OUTPUT:  RETVAL
6452 
6453 SV *
6454 Rmpz_init_nobless ()
6455 CODE:
6456   RETVAL = Rmpz_init_nobless (aTHX);
6457 OUTPUT:  RETVAL
6458 
6459 
6460 SV *
6461 Rmpz_init_set_nobless (p)
6462 	mpz_t *	p
6463 CODE:
6464   RETVAL = Rmpz_init_set_nobless (aTHX_ p);
6465 OUTPUT:  RETVAL
6466 
6467 SV *
6468 Rmpz_init_set_ui_nobless (p)
6469 	SV *	p
6470 CODE:
6471   RETVAL = Rmpz_init_set_ui_nobless (aTHX_ p);
6472 OUTPUT:  RETVAL
6473 
6474 SV *
6475 Rmpz_init_set_si_nobless (p)
6476 	SV *	p
6477 CODE:
6478   RETVAL = Rmpz_init_set_si_nobless (aTHX_ p);
6479 OUTPUT:  RETVAL
6480 
6481 SV *
6482 Rmpz_init_set_d_nobless (p)
6483 	SV *	p
6484 CODE:
6485   RETVAL = Rmpz_init_set_d_nobless (aTHX_ p);
6486 OUTPUT:  RETVAL
6487 
6488 SV *
6489 Rmpz_init ()
6490 CODE:
6491   RETVAL = Rmpz_init (aTHX);
6492 OUTPUT:  RETVAL
6493 
6494 
6495 SV *
6496 Rmpz_init_set (p)
6497 	mpz_t *	p
6498 CODE:
6499   RETVAL = Rmpz_init_set (aTHX_ p);
6500 OUTPUT:  RETVAL
6501 
6502 SV *
6503 Rmpz_init_set_ui (p)
6504 	SV *	p
6505 CODE:
6506   RETVAL = Rmpz_init_set_ui (aTHX_ p);
6507 OUTPUT:  RETVAL
6508 
6509 SV *
6510 Rmpz_init_set_si (p)
6511 	SV *	p
6512 CODE:
6513   RETVAL = Rmpz_init_set_si (aTHX_ p);
6514 OUTPUT:  RETVAL
6515 
6516 void
6517 Rmpz_set_uj (copy, original)
6518 	mpz_t *	copy
6519 	UV	original
6520         PREINIT:
6521         I32* temp;
6522         PPCODE:
6523         temp = PL_markstack_ptr++;
6524         Rmpz_set_uj(copy, original);
6525         if (PL_markstack_ptr != temp) {
6526           /* truly void, because dXSARGS not invoked */
6527           PL_markstack_ptr = temp;
6528           XSRETURN_EMPTY; /* return empty stack */
6529         }
6530         /* must have used dXSARGS; list context implied */
6531         return; /* assume stack size is correct */
6532 
6533 void
6534 Rmpz_set_sj (copy, original)
6535 	mpz_t *	copy
6536 	IV	original
6537         PREINIT:
6538         I32* temp;
6539         PPCODE:
6540         temp = PL_markstack_ptr++;
6541         Rmpz_set_sj(copy, original);
6542         if (PL_markstack_ptr != temp) {
6543           /* truly void, because dXSARGS not invoked */
6544           PL_markstack_ptr = temp;
6545           XSRETURN_EMPTY; /* return empty stack */
6546         }
6547         /* must have used dXSARGS; list context implied */
6548         return; /* assume stack size is correct */
6549 
6550 void
6551 Rmpz_set_IV (copy, original)
6552 	mpz_t *	copy
6553 	SV *	original
6554         PREINIT:
6555         I32* temp;
6556         PPCODE:
6557         temp = PL_markstack_ptr++;
6558         Rmpz_set_IV(aTHX_ copy, original);
6559         if (PL_markstack_ptr != temp) {
6560           /* truly void, because dXSARGS not invoked */
6561           PL_markstack_ptr = temp;
6562           XSRETURN_EMPTY; /* return empty stack */
6563         }
6564         /* must have used dXSARGS; list context implied */
6565         return; /* assume stack size is correct */
6566 
6567 SV *
6568 Rmpz_init_set_IV (p)
6569 	SV *	p
6570 CODE:
6571   RETVAL = Rmpz_init_set_IV (aTHX_ p);
6572 OUTPUT:  RETVAL
6573 
6574 SV *
6575 Rmpz_init_set_IV_nobless (p)
6576 	SV *	p
6577 CODE:
6578   RETVAL = Rmpz_init_set_IV_nobless (aTHX_ p);
6579 OUTPUT:  RETVAL
6580 
6581 SV *
6582 _Rmpz_get_IV (n)
6583 	mpz_t *	n
6584 CODE:
6585   RETVAL = _Rmpz_get_IV (aTHX_ n);
6586 OUTPUT:  RETVAL
6587 
6588 int
6589 Rmpz_fits_IV_p (n)
6590 	mpz_t *	n
6591 CODE:
6592   RETVAL = Rmpz_fits_IV_p (aTHX_ n);
6593 OUTPUT:  RETVAL
6594 
6595 double
6596 Rmpz_get_d (n)
6597 	mpz_t *	n
6598 
6599 NV
6600 Rmpz_get_NV (n)
6601 	mpz_t *	n
6602 
6603 int
6604 Rmpz_cmp_IV (z, iv)
6605 	mpz_t *	z
6606 	SV *	iv
6607 CODE:
6608   RETVAL = Rmpz_cmp_IV (aTHX_ z, iv);
6609 OUTPUT:  RETVAL
6610 
6611 SV *
6612 Rmpz_init_set_d (p)
6613 	SV *	p
6614 CODE:
6615   RETVAL = Rmpz_init_set_d (aTHX_ p);
6616 OUTPUT:  RETVAL
6617 
6618 void
6619 _mpf_set_dd (q, p)
6620 	mpf_t *	q
6621 	SV *	p
6622         PREINIT:
6623         I32* temp;
6624         PPCODE:
6625         temp = PL_markstack_ptr++;
6626         _mpf_set_dd(q, p);
6627         if (PL_markstack_ptr != temp) {
6628           /* truly void, because dXSARGS not invoked */
6629           PL_markstack_ptr = temp;
6630           XSRETURN_EMPTY; /* return empty stack */
6631         }
6632         /* must have used dXSARGS; list context implied */
6633         return; /* assume stack size is correct */
6634 
6635 void
6636 Rmpz_set_NV (copy, original)
6637 	mpz_t *	copy
6638 	SV *	original
6639         PREINIT:
6640         I32* temp;
6641         PPCODE:
6642         temp = PL_markstack_ptr++;
6643         Rmpz_set_NV(aTHX_ copy, original);
6644         if (PL_markstack_ptr != temp) {
6645           /* truly void, because dXSARGS not invoked */
6646           PL_markstack_ptr = temp;
6647           XSRETURN_EMPTY; /* return empty stack */
6648         }
6649         /* must have used dXSARGS; list context implied */
6650         return; /* assume stack size is correct */
6651 
6652 SV *
6653 Rmpz_init_set_NV (p)
6654 	SV *	p
6655 CODE:
6656   RETVAL = Rmpz_init_set_NV (aTHX_ p);
6657 OUTPUT:  RETVAL
6658 
6659 SV *
6660 Rmpz_init_set_NV_nobless (p)
6661 	SV *	p
6662 CODE:
6663   RETVAL = Rmpz_init_set_NV_nobless (aTHX_ p);
6664 OUTPUT:  RETVAL
6665 
6666 SV *
6667 Rmpz_init_set_str (num, base)
6668 	SV *	num
6669 	SV *	base
6670 CODE:
6671   RETVAL = Rmpz_init_set_str (aTHX_ num, base);
6672 OUTPUT:  RETVAL
6673 
6674 SV *
6675 Rmpz_init2 (bits)
6676 	SV *	bits
6677 CODE:
6678   RETVAL = Rmpz_init2 (aTHX_ bits);
6679 OUTPUT:  RETVAL
6680 
6681 SV *
6682 Rmpz_get_str (p, base)
6683 	mpz_t *	p
6684 	SV *	base
6685 CODE:
6686   RETVAL = Rmpz_get_str (aTHX_ p, base);
6687 OUTPUT:  RETVAL
6688 
6689 void
6690 DESTROY (p)
6691 	mpz_t *	p
6692         PREINIT:
6693         I32* temp;
6694         PPCODE:
6695         temp = PL_markstack_ptr++;
6696         DESTROY(aTHX_ p);
6697         if (PL_markstack_ptr != temp) {
6698           /* truly void, because dXSARGS not invoked */
6699           PL_markstack_ptr = temp;
6700           XSRETURN_EMPTY; /* return empty stack */
6701         }
6702         /* must have used dXSARGS; list context implied */
6703         return; /* assume stack size is correct */
6704 
6705 void
6706 Rmpz_clear (p)
6707 	mpz_t *	p
6708         PREINIT:
6709         I32* temp;
6710         PPCODE:
6711         temp = PL_markstack_ptr++;
6712         Rmpz_clear(aTHX_ p);
6713         if (PL_markstack_ptr != temp) {
6714           /* truly void, because dXSARGS not invoked */
6715           PL_markstack_ptr = temp;
6716           XSRETURN_EMPTY; /* return empty stack */
6717         }
6718         /* must have used dXSARGS; list context implied */
6719         return; /* assume stack size is correct */
6720 
6721 void
6722 Rmpz_clear_mpz (p)
6723 	mpz_t *	p
6724         PREINIT:
6725         I32* temp;
6726         PPCODE:
6727         temp = PL_markstack_ptr++;
6728         Rmpz_clear_mpz(p);
6729         if (PL_markstack_ptr != temp) {
6730           /* truly void, because dXSARGS not invoked */
6731           PL_markstack_ptr = temp;
6732           XSRETURN_EMPTY; /* return empty stack */
6733         }
6734         /* must have used dXSARGS; list context implied */
6735         return; /* assume stack size is correct */
6736 
6737 void
6738 Rmpz_clear_ptr (p)
6739 	mpz_t *	p
6740         PREINIT:
6741         I32* temp;
6742         PPCODE:
6743         temp = PL_markstack_ptr++;
6744         Rmpz_clear_ptr(aTHX_ p);
6745         if (PL_markstack_ptr != temp) {
6746           /* truly void, because dXSARGS not invoked */
6747           PL_markstack_ptr = temp;
6748           XSRETURN_EMPTY; /* return empty stack */
6749         }
6750         /* must have used dXSARGS; list context implied */
6751         return; /* assume stack size is correct */
6752 
6753 void
6754 Rmpz_realloc2 (integer, bits)
6755 	mpz_t *	integer
6756 	SV *	bits
6757         PREINIT:
6758         I32* temp;
6759         PPCODE:
6760         temp = PL_markstack_ptr++;
6761         Rmpz_realloc2(aTHX_ integer, bits);
6762         if (PL_markstack_ptr != temp) {
6763           /* truly void, because dXSARGS not invoked */
6764           PL_markstack_ptr = temp;
6765           XSRETURN_EMPTY; /* return empty stack */
6766         }
6767         /* must have used dXSARGS; list context implied */
6768         return; /* assume stack size is correct */
6769 
6770 void
6771 Rmpz_set (copy, original)
6772 	mpz_t *	copy
6773 	mpz_t *	original
6774         PREINIT:
6775         I32* temp;
6776         PPCODE:
6777         temp = PL_markstack_ptr++;
6778         Rmpz_set(copy, original);
6779         if (PL_markstack_ptr != temp) {
6780           /* truly void, because dXSARGS not invoked */
6781           PL_markstack_ptr = temp;
6782           XSRETURN_EMPTY; /* return empty stack */
6783         }
6784         /* must have used dXSARGS; list context implied */
6785         return; /* assume stack size is correct */
6786 
6787 void
6788 Rmpz_set_q (copy, original)
6789 	mpz_t *	copy
6790 	mpq_t *	original
6791         PREINIT:
6792         I32* temp;
6793         PPCODE:
6794         temp = PL_markstack_ptr++;
6795         Rmpz_set_q(copy, original);
6796         if (PL_markstack_ptr != temp) {
6797           /* truly void, because dXSARGS not invoked */
6798           PL_markstack_ptr = temp;
6799           XSRETURN_EMPTY; /* return empty stack */
6800         }
6801         /* must have used dXSARGS; list context implied */
6802         return; /* assume stack size is correct */
6803 
6804 void
6805 Rmpz_set_f (copy, original)
6806 	mpz_t *	copy
6807 	mpf_t *	original
6808         PREINIT:
6809         I32* temp;
6810         PPCODE:
6811         temp = PL_markstack_ptr++;
6812         Rmpz_set_f(copy, original);
6813         if (PL_markstack_ptr != temp) {
6814           /* truly void, because dXSARGS not invoked */
6815           PL_markstack_ptr = temp;
6816           XSRETURN_EMPTY; /* return empty stack */
6817         }
6818         /* must have used dXSARGS; list context implied */
6819         return; /* assume stack size is correct */
6820 
6821 void
6822 Rmpz_set_si (copy, original)
6823 	mpz_t *	copy
6824 	long	original
6825         PREINIT:
6826         I32* temp;
6827         PPCODE:
6828         temp = PL_markstack_ptr++;
6829         Rmpz_set_si(copy, original);
6830         if (PL_markstack_ptr != temp) {
6831           /* truly void, because dXSARGS not invoked */
6832           PL_markstack_ptr = temp;
6833           XSRETURN_EMPTY; /* return empty stack */
6834         }
6835         /* must have used dXSARGS; list context implied */
6836         return; /* assume stack size is correct */
6837 
6838 void
6839 Rmpz_set_ui (copy, original)
6840 	mpz_t *	copy
6841 	unsigned long	original
6842         PREINIT:
6843         I32* temp;
6844         PPCODE:
6845         temp = PL_markstack_ptr++;
6846         Rmpz_set_ui(copy, original);
6847         if (PL_markstack_ptr != temp) {
6848           /* truly void, because dXSARGS not invoked */
6849           PL_markstack_ptr = temp;
6850           XSRETURN_EMPTY; /* return empty stack */
6851         }
6852         /* must have used dXSARGS; list context implied */
6853         return; /* assume stack size is correct */
6854 
6855 void
6856 Rmpz_set_d (copy, d)
6857 	mpz_t *	copy
6858 	double	d
6859         PREINIT:
6860         I32* temp;
6861         PPCODE:
6862         temp = PL_markstack_ptr++;
6863         Rmpz_set_d(copy, d);
6864         if (PL_markstack_ptr != temp) {
6865           /* truly void, because dXSARGS not invoked */
6866           PL_markstack_ptr = temp;
6867           XSRETURN_EMPTY; /* return empty stack */
6868         }
6869         /* must have used dXSARGS; list context implied */
6870         return; /* assume stack size is correct */
6871 
6872 void
Rmpz_set_str(copy,original,base)6873 Rmpz_set_str (copy, original, base)
6874 	mpz_t *	copy
6875 	SV *	original
6876 	int	base
6877         PREINIT:
6878         I32* temp;
6879         PPCODE:
6880         temp = PL_markstack_ptr++;
6881         Rmpz_set_str(aTHX_ copy, original, base);
6882         if (PL_markstack_ptr != temp) {
6883           /* truly void, because dXSARGS not invoked */
6884           PL_markstack_ptr = temp;
6885           XSRETURN_EMPTY; /* return empty stack */
6886         }
6887         /* must have used dXSARGS; list context implied */
6888         return; /* assume stack size is correct */
6889 
6890 void
6891 Rmpz_swap (a, b)
6892 	mpz_t *	a
6893 	mpz_t *	b
6894         PREINIT:
6895         I32* temp;
6896         PPCODE:
6897         temp = PL_markstack_ptr++;
6898         Rmpz_swap(a, b);
6899         if (PL_markstack_ptr != temp) {
6900           /* truly void, because dXSARGS not invoked */
6901           PL_markstack_ptr = temp;
6902           XSRETURN_EMPTY; /* return empty stack */
6903         }
6904         /* must have used dXSARGS; list context implied */
6905         return; /* assume stack size is correct */
6906 
6907 unsigned long
6908 Rmpz_get_ui (n)
6909 	mpz_t *	n
6910 
6911 long
6912 Rmpz_get_si (n)
6913 	mpz_t *	n
6914 
6915 void
6916 Rmpz_get_d_2exp (n)
6917 	mpz_t *	n
6918         PREINIT:
6919         I32* temp;
6920         PPCODE:
6921         temp = PL_markstack_ptr++;
6922         Rmpz_get_d_2exp(aTHX_ n);
6923         if (PL_markstack_ptr != temp) {
6924           /* truly void, because dXSARGS not invoked */
6925           PL_markstack_ptr = temp;
6926           XSRETURN_EMPTY; /* return empty stack */
6927         }
6928         /* must have used dXSARGS; list context implied */
6929         return; /* assume stack size is correct */
6930 
6931 SV *
6932 Rmpz_getlimbn (p, n)
6933 	mpz_t *	p
6934 	SV *	n
6935 CODE:
6936   RETVAL = Rmpz_getlimbn (aTHX_ p, n);
6937 OUTPUT:  RETVAL
6938 
6939 void
Rmpz_add(dest,src1,src2)6940 Rmpz_add (dest, src1, src2)
6941 	mpz_t *	dest
6942 	mpz_t *	src1
6943 	mpz_t *	src2
6944         PREINIT:
6945         I32* temp;
6946         PPCODE:
6947         temp = PL_markstack_ptr++;
6948         Rmpz_add(dest, src1, src2);
6949         if (PL_markstack_ptr != temp) {
6950           /* truly void, because dXSARGS not invoked */
6951           PL_markstack_ptr = temp;
6952           XSRETURN_EMPTY; /* return empty stack */
6953         }
6954         /* must have used dXSARGS; list context implied */
6955         return; /* assume stack size is correct */
6956 
6957 void
Rmpz_add_ui(dest,src,num)6958 Rmpz_add_ui (dest, src, num)
6959 	mpz_t *	dest
6960 	mpz_t *	src
6961 	unsigned long	num
6962         PREINIT:
6963         I32* temp;
6964         PPCODE:
6965         temp = PL_markstack_ptr++;
6966         Rmpz_add_ui(dest, src, num);
6967         if (PL_markstack_ptr != temp) {
6968           /* truly void, because dXSARGS not invoked */
6969           PL_markstack_ptr = temp;
6970           XSRETURN_EMPTY; /* return empty stack */
6971         }
6972         /* must have used dXSARGS; list context implied */
6973         return; /* assume stack size is correct */
6974 
6975 void
Rmpz_sub(dest,src1,src2)6976 Rmpz_sub (dest, src1, src2)
6977 	mpz_t *	dest
6978 	mpz_t *	src1
6979 	mpz_t *	src2
6980         PREINIT:
6981         I32* temp;
6982         PPCODE:
6983         temp = PL_markstack_ptr++;
6984         Rmpz_sub(dest, src1, src2);
6985         if (PL_markstack_ptr != temp) {
6986           /* truly void, because dXSARGS not invoked */
6987           PL_markstack_ptr = temp;
6988           XSRETURN_EMPTY; /* return empty stack */
6989         }
6990         /* must have used dXSARGS; list context implied */
6991         return; /* assume stack size is correct */
6992 
6993 void
Rmpz_sub_ui(dest,src,num)6994 Rmpz_sub_ui (dest, src, num)
6995 	mpz_t *	dest
6996 	mpz_t *	src
6997 	unsigned long	num
6998         PREINIT:
6999         I32* temp;
7000         PPCODE:
7001         temp = PL_markstack_ptr++;
7002         Rmpz_sub_ui(dest, src, num);
7003         if (PL_markstack_ptr != temp) {
7004           /* truly void, because dXSARGS not invoked */
7005           PL_markstack_ptr = temp;
7006           XSRETURN_EMPTY; /* return empty stack */
7007         }
7008         /* must have used dXSARGS; list context implied */
7009         return; /* assume stack size is correct */
7010 
7011 void
Rmpz_ui_sub(dest,num,src)7012 Rmpz_ui_sub (dest, num, src)
7013 	mpz_t *	dest
7014 	unsigned long	num
7015 	mpz_t *	src
7016         PREINIT:
7017         I32* temp;
7018         PPCODE:
7019         temp = PL_markstack_ptr++;
7020         Rmpz_ui_sub(dest, num, src);
7021         if (PL_markstack_ptr != temp) {
7022           /* truly void, because dXSARGS not invoked */
7023           PL_markstack_ptr = temp;
7024           XSRETURN_EMPTY; /* return empty stack */
7025         }
7026         /* must have used dXSARGS; list context implied */
7027         return; /* assume stack size is correct */
7028 
7029 void
Rmpz_mul(dest,src1,src2)7030 Rmpz_mul (dest, src1, src2)
7031 	mpz_t *	dest
7032 	mpz_t *	src1
7033 	mpz_t *	src2
7034         PREINIT:
7035         I32* temp;
7036         PPCODE:
7037         temp = PL_markstack_ptr++;
7038         Rmpz_mul(dest, src1, src2);
7039         if (PL_markstack_ptr != temp) {
7040           /* truly void, because dXSARGS not invoked */
7041           PL_markstack_ptr = temp;
7042           XSRETURN_EMPTY; /* return empty stack */
7043         }
7044         /* must have used dXSARGS; list context implied */
7045         return; /* assume stack size is correct */
7046 
7047 void
Rmpz_mul_si(dest,src,num)7048 Rmpz_mul_si (dest, src, num)
7049 	mpz_t *	dest
7050 	mpz_t *	src
7051 	long	num
7052         PREINIT:
7053         I32* temp;
7054         PPCODE:
7055         temp = PL_markstack_ptr++;
7056         Rmpz_mul_si(dest, src, num);
7057         if (PL_markstack_ptr != temp) {
7058           /* truly void, because dXSARGS not invoked */
7059           PL_markstack_ptr = temp;
7060           XSRETURN_EMPTY; /* return empty stack */
7061         }
7062         /* must have used dXSARGS; list context implied */
7063         return; /* assume stack size is correct */
7064 
7065 void
Rmpz_mul_ui(dest,src,num)7066 Rmpz_mul_ui (dest, src, num)
7067 	mpz_t *	dest
7068 	mpz_t *	src
7069 	unsigned long	num
7070         PREINIT:
7071         I32* temp;
7072         PPCODE:
7073         temp = PL_markstack_ptr++;
7074         Rmpz_mul_ui(dest, src, num);
7075         if (PL_markstack_ptr != temp) {
7076           /* truly void, because dXSARGS not invoked */
7077           PL_markstack_ptr = temp;
7078           XSRETURN_EMPTY; /* return empty stack */
7079         }
7080         /* must have used dXSARGS; list context implied */
7081         return; /* assume stack size is correct */
7082 
7083 void
Rmpz_addmul(dest,src1,src2)7084 Rmpz_addmul (dest, src1, src2)
7085 	mpz_t *	dest
7086 	mpz_t *	src1
7087 	mpz_t *	src2
7088         PREINIT:
7089         I32* temp;
7090         PPCODE:
7091         temp = PL_markstack_ptr++;
7092         Rmpz_addmul(dest, src1, src2);
7093         if (PL_markstack_ptr != temp) {
7094           /* truly void, because dXSARGS not invoked */
7095           PL_markstack_ptr = temp;
7096           XSRETURN_EMPTY; /* return empty stack */
7097         }
7098         /* must have used dXSARGS; list context implied */
7099         return; /* assume stack size is correct */
7100 
7101 void
Rmpz_addmul_ui(dest,src,num)7102 Rmpz_addmul_ui (dest, src, num)
7103 	mpz_t *	dest
7104 	mpz_t *	src
7105 	unsigned long	num
7106         PREINIT:
7107         I32* temp;
7108         PPCODE:
7109         temp = PL_markstack_ptr++;
7110         Rmpz_addmul_ui(dest, src, num);
7111         if (PL_markstack_ptr != temp) {
7112           /* truly void, because dXSARGS not invoked */
7113           PL_markstack_ptr = temp;
7114           XSRETURN_EMPTY; /* return empty stack */
7115         }
7116         /* must have used dXSARGS; list context implied */
7117         return; /* assume stack size is correct */
7118 
7119 void
Rmpz_submul(dest,src1,src2)7120 Rmpz_submul (dest, src1, src2)
7121 	mpz_t *	dest
7122 	mpz_t *	src1
7123 	mpz_t *	src2
7124         PREINIT:
7125         I32* temp;
7126         PPCODE:
7127         temp = PL_markstack_ptr++;
7128         Rmpz_submul(dest, src1, src2);
7129         if (PL_markstack_ptr != temp) {
7130           /* truly void, because dXSARGS not invoked */
7131           PL_markstack_ptr = temp;
7132           XSRETURN_EMPTY; /* return empty stack */
7133         }
7134         /* must have used dXSARGS; list context implied */
7135         return; /* assume stack size is correct */
7136 
7137 void
Rmpz_submul_ui(dest,src,num)7138 Rmpz_submul_ui (dest, src, num)
7139 	mpz_t *	dest
7140 	mpz_t *	src
7141 	unsigned long	num
7142         PREINIT:
7143         I32* temp;
7144         PPCODE:
7145         temp = PL_markstack_ptr++;
7146         Rmpz_submul_ui(dest, src, num);
7147         if (PL_markstack_ptr != temp) {
7148           /* truly void, because dXSARGS not invoked */
7149           PL_markstack_ptr = temp;
7150           XSRETURN_EMPTY; /* return empty stack */
7151         }
7152         /* must have used dXSARGS; list context implied */
7153         return; /* assume stack size is correct */
7154 
7155 void
Rmpz_mul_2exp(dest,src1,b)7156 Rmpz_mul_2exp (dest, src1, b)
7157 	mpz_t *	dest
7158 	mpz_t *	src1
7159 	SV *	b
7160         PREINIT:
7161         I32* temp;
7162         PPCODE:
7163         temp = PL_markstack_ptr++;
7164         Rmpz_mul_2exp(aTHX_ dest, src1, b);
7165         if (PL_markstack_ptr != temp) {
7166           /* truly void, because dXSARGS not invoked */
7167           PL_markstack_ptr = temp;
7168           XSRETURN_EMPTY; /* return empty stack */
7169         }
7170         /* must have used dXSARGS; list context implied */
7171         return; /* assume stack size is correct */
7172 
7173 void
Rmpz_div_2exp(dest,src1,b)7174 Rmpz_div_2exp (dest, src1, b)
7175 	mpz_t *	dest
7176 	mpz_t *	src1
7177 	SV *	b
7178         PREINIT:
7179         I32* temp;
7180         PPCODE:
7181         temp = PL_markstack_ptr++;
7182         Rmpz_div_2exp(aTHX_ dest, src1, b);
7183         if (PL_markstack_ptr != temp) {
7184           /* truly void, because dXSARGS not invoked */
7185           PL_markstack_ptr = temp;
7186           XSRETURN_EMPTY; /* return empty stack */
7187         }
7188         /* must have used dXSARGS; list context implied */
7189         return; /* assume stack size is correct */
7190 
7191 void
7192 Rmpz_neg (dest, src)
7193 	mpz_t *	dest
7194 	mpz_t *	src
7195         PREINIT:
7196         I32* temp;
7197         PPCODE:
7198         temp = PL_markstack_ptr++;
7199         Rmpz_neg(dest, src);
7200         if (PL_markstack_ptr != temp) {
7201           /* truly void, because dXSARGS not invoked */
7202           PL_markstack_ptr = temp;
7203           XSRETURN_EMPTY; /* return empty stack */
7204         }
7205         /* must have used dXSARGS; list context implied */
7206         return; /* assume stack size is correct */
7207 
7208 void
7209 Rmpz_abs (dest, src)
7210 	mpz_t *	dest
7211 	mpz_t *	src
7212         PREINIT:
7213         I32* temp;
7214         PPCODE:
7215         temp = PL_markstack_ptr++;
7216         Rmpz_abs(dest, src);
7217         if (PL_markstack_ptr != temp) {
7218           /* truly void, because dXSARGS not invoked */
7219           PL_markstack_ptr = temp;
7220           XSRETURN_EMPTY; /* return empty stack */
7221         }
7222         /* must have used dXSARGS; list context implied */
7223         return; /* assume stack size is correct */
7224 
7225 void
Rmpz_cdiv_q(q,n,d)7226 Rmpz_cdiv_q (q, n, d)
7227 	mpz_t *	q
7228 	mpz_t *	n
7229 	mpz_t *	d
7230         PREINIT:
7231         I32* temp;
7232         PPCODE:
7233         temp = PL_markstack_ptr++;
7234         Rmpz_cdiv_q(q, n, d);
7235         if (PL_markstack_ptr != temp) {
7236           /* truly void, because dXSARGS not invoked */
7237           PL_markstack_ptr = temp;
7238           XSRETURN_EMPTY; /* return empty stack */
7239         }
7240         /* must have used dXSARGS; list context implied */
7241         return; /* assume stack size is correct */
7242 
7243 void
Rmpz_cdiv_r(mod,n,d)7244 Rmpz_cdiv_r (mod, n, d)
7245 	mpz_t *	mod
7246 	mpz_t *	n
7247 	mpz_t *	d
7248         PREINIT:
7249         I32* temp;
7250         PPCODE:
7251         temp = PL_markstack_ptr++;
7252         Rmpz_cdiv_r(mod, n, d);
7253         if (PL_markstack_ptr != temp) {
7254           /* truly void, because dXSARGS not invoked */
7255           PL_markstack_ptr = temp;
7256           XSRETURN_EMPTY; /* return empty stack */
7257         }
7258         /* must have used dXSARGS; list context implied */
7259         return; /* assume stack size is correct */
7260 
7261 void
Rmpz_cdiv_qr(q,r,n,d)7262 Rmpz_cdiv_qr (q, r, n, d)
7263 	mpz_t *	q
7264 	mpz_t *	r
7265 	mpz_t *	n
7266 	mpz_t *	d
7267         PREINIT:
7268         I32* temp;
7269         PPCODE:
7270         temp = PL_markstack_ptr++;
7271         Rmpz_cdiv_qr(q, r, n, d);
7272         if (PL_markstack_ptr != temp) {
7273           /* truly void, because dXSARGS not invoked */
7274           PL_markstack_ptr = temp;
7275           XSRETURN_EMPTY; /* return empty stack */
7276         }
7277         /* must have used dXSARGS; list context implied */
7278         return; /* assume stack size is correct */
7279 
7280 unsigned long
7281 Rmpz_cdiv_q_ui (q, n, d)
7282 	mpz_t *	q
7283 	mpz_t *	n
7284 	unsigned long	d
7285 
7286 unsigned long
7287 Rmpz_cdiv_r_ui (q, n, d)
7288 	mpz_t *	q
7289 	mpz_t *	n
7290 	unsigned long	d
7291 
7292 unsigned long
7293 Rmpz_cdiv_qr_ui (q, r, n, d)
7294 	mpz_t *	q
7295 	mpz_t *	r
7296 	mpz_t *	n
7297 	unsigned long	d
7298 
7299 unsigned long
7300 Rmpz_cdiv_ui (n, d)
7301 	mpz_t *	n
7302 	unsigned long	d
7303 
7304 void
7305 Rmpz_cdiv_q_2exp (q, n, b)
7306 	mpz_t *	q
7307 	mpz_t *	n
7308 	SV *	b
7309         PREINIT:
7310         I32* temp;
7311         PPCODE:
7312         temp = PL_markstack_ptr++;
7313         Rmpz_cdiv_q_2exp(aTHX_ q, n, b);
7314         if (PL_markstack_ptr != temp) {
7315           /* truly void, because dXSARGS not invoked */
7316           PL_markstack_ptr = temp;
7317           XSRETURN_EMPTY; /* return empty stack */
7318         }
7319         /* must have used dXSARGS; list context implied */
7320         return; /* assume stack size is correct */
7321 
7322 void
Rmpz_cdiv_r_2exp(r,n,b)7323 Rmpz_cdiv_r_2exp (r, n, b)
7324 	mpz_t *	r
7325 	mpz_t *	n
7326 	SV *	b
7327         PREINIT:
7328         I32* temp;
7329         PPCODE:
7330         temp = PL_markstack_ptr++;
7331         Rmpz_cdiv_r_2exp(aTHX_ r, n, b);
7332         if (PL_markstack_ptr != temp) {
7333           /* truly void, because dXSARGS not invoked */
7334           PL_markstack_ptr = temp;
7335           XSRETURN_EMPTY; /* return empty stack */
7336         }
7337         /* must have used dXSARGS; list context implied */
7338         return; /* assume stack size is correct */
7339 
7340 void
Rmpz_fdiv_q(q,n,d)7341 Rmpz_fdiv_q (q, n, d)
7342 	mpz_t *	q
7343 	mpz_t *	n
7344 	mpz_t *	d
7345         PREINIT:
7346         I32* temp;
7347         PPCODE:
7348         temp = PL_markstack_ptr++;
7349         Rmpz_fdiv_q(q, n, d);
7350         if (PL_markstack_ptr != temp) {
7351           /* truly void, because dXSARGS not invoked */
7352           PL_markstack_ptr = temp;
7353           XSRETURN_EMPTY; /* return empty stack */
7354         }
7355         /* must have used dXSARGS; list context implied */
7356         return; /* assume stack size is correct */
7357 
7358 void
Rmpz_div(q,n,d)7359 Rmpz_div (q, n, d)
7360 	mpz_t *	q
7361 	mpz_t *	n
7362 	mpz_t *	d
7363         PREINIT:
7364         I32* temp;
7365         PPCODE:
7366         temp = PL_markstack_ptr++;
7367         Rmpz_div(q, n, d);
7368         if (PL_markstack_ptr != temp) {
7369           /* truly void, because dXSARGS not invoked */
7370           PL_markstack_ptr = temp;
7371           XSRETURN_EMPTY; /* return empty stack */
7372         }
7373         /* must have used dXSARGS; list context implied */
7374         return; /* assume stack size is correct */
7375 
7376 void
Rmpz_fdiv_r(mod,n,d)7377 Rmpz_fdiv_r (mod, n, d)
7378 	mpz_t *	mod
7379 	mpz_t *	n
7380 	mpz_t *	d
7381         PREINIT:
7382         I32* temp;
7383         PPCODE:
7384         temp = PL_markstack_ptr++;
7385         Rmpz_fdiv_r(mod, n, d);
7386         if (PL_markstack_ptr != temp) {
7387           /* truly void, because dXSARGS not invoked */
7388           PL_markstack_ptr = temp;
7389           XSRETURN_EMPTY; /* return empty stack */
7390         }
7391         /* must have used dXSARGS; list context implied */
7392         return; /* assume stack size is correct */
7393 
7394 void
Rmpz_fdiv_qr(q,r,n,d)7395 Rmpz_fdiv_qr (q, r, n, d)
7396 	mpz_t *	q
7397 	mpz_t *	r
7398 	mpz_t *	n
7399 	mpz_t *	d
7400         PREINIT:
7401         I32* temp;
7402         PPCODE:
7403         temp = PL_markstack_ptr++;
7404         Rmpz_fdiv_qr(q, r, n, d);
7405         if (PL_markstack_ptr != temp) {
7406           /* truly void, because dXSARGS not invoked */
7407           PL_markstack_ptr = temp;
7408           XSRETURN_EMPTY; /* return empty stack */
7409         }
7410         /* must have used dXSARGS; list context implied */
7411         return; /* assume stack size is correct */
7412 
7413 void
Rmpz_divmod(q,r,n,d)7414 Rmpz_divmod (q, r, n, d)
7415 	mpz_t *	q
7416 	mpz_t *	r
7417 	mpz_t *	n
7418 	mpz_t *	d
7419         PREINIT:
7420         I32* temp;
7421         PPCODE:
7422         temp = PL_markstack_ptr++;
7423         Rmpz_divmod(q, r, n, d);
7424         if (PL_markstack_ptr != temp) {
7425           /* truly void, because dXSARGS not invoked */
7426           PL_markstack_ptr = temp;
7427           XSRETURN_EMPTY; /* return empty stack */
7428         }
7429         /* must have used dXSARGS; list context implied */
7430         return; /* assume stack size is correct */
7431 
7432 unsigned long
7433 Rmpz_fdiv_q_ui (q, n, d)
7434 	mpz_t *	q
7435 	mpz_t *	n
7436 	unsigned long	d
7437 
7438 unsigned long
7439 Rmpz_div_ui (q, n, d)
7440 	mpz_t *	q
7441 	mpz_t *	n
7442 	unsigned long	d
7443 
7444 unsigned long
7445 Rmpz_fdiv_r_ui (q, n, d)
7446 	mpz_t *	q
7447 	mpz_t *	n
7448 	unsigned long	d
7449 
7450 unsigned long
7451 Rmpz_fdiv_qr_ui (q, r, n, d)
7452 	mpz_t *	q
7453 	mpz_t *	r
7454 	mpz_t *	n
7455 	unsigned long	d
7456 
7457 unsigned long
7458 Rmpz_divmod_ui (q, r, n, d)
7459 	mpz_t *	q
7460 	mpz_t *	r
7461 	mpz_t *	n
7462 	unsigned long	d
7463 
7464 unsigned long
7465 Rmpz_fdiv_ui (n, d)
7466 	mpz_t *	n
7467 	unsigned long	d
7468 
7469 void
7470 Rmpz_fdiv_q_2exp (q, n, b)
7471 	mpz_t *	q
7472 	mpz_t *	n
7473 	SV *	b
7474         PREINIT:
7475         I32* temp;
7476         PPCODE:
7477         temp = PL_markstack_ptr++;
7478         Rmpz_fdiv_q_2exp(aTHX_ q, n, b);
7479         if (PL_markstack_ptr != temp) {
7480           /* truly void, because dXSARGS not invoked */
7481           PL_markstack_ptr = temp;
7482           XSRETURN_EMPTY; /* return empty stack */
7483         }
7484         /* must have used dXSARGS; list context implied */
7485         return; /* assume stack size is correct */
7486 
7487 void
Rmpz_fdiv_r_2exp(r,n,b)7488 Rmpz_fdiv_r_2exp (r, n, b)
7489 	mpz_t *	r
7490 	mpz_t *	n
7491 	SV *	b
7492         PREINIT:
7493         I32* temp;
7494         PPCODE:
7495         temp = PL_markstack_ptr++;
7496         Rmpz_fdiv_r_2exp(aTHX_ r, n, b);
7497         if (PL_markstack_ptr != temp) {
7498           /* truly void, because dXSARGS not invoked */
7499           PL_markstack_ptr = temp;
7500           XSRETURN_EMPTY; /* return empty stack */
7501         }
7502         /* must have used dXSARGS; list context implied */
7503         return; /* assume stack size is correct */
7504 
7505 void
Rmpz_mod_2exp(r,n,b)7506 Rmpz_mod_2exp (r, n, b)
7507 	mpz_t *	r
7508 	mpz_t *	n
7509 	SV *	b
7510         PREINIT:
7511         I32* temp;
7512         PPCODE:
7513         temp = PL_markstack_ptr++;
7514         Rmpz_mod_2exp(aTHX_ r, n, b);
7515         if (PL_markstack_ptr != temp) {
7516           /* truly void, because dXSARGS not invoked */
7517           PL_markstack_ptr = temp;
7518           XSRETURN_EMPTY; /* return empty stack */
7519         }
7520         /* must have used dXSARGS; list context implied */
7521         return; /* assume stack size is correct */
7522 
7523 void
Rmpz_tdiv_q(q,n,d)7524 Rmpz_tdiv_q (q, n, d)
7525 	mpz_t *	q
7526 	mpz_t *	n
7527 	mpz_t *	d
7528         PREINIT:
7529         I32* temp;
7530         PPCODE:
7531         temp = PL_markstack_ptr++;
7532         Rmpz_tdiv_q(q, n, d);
7533         if (PL_markstack_ptr != temp) {
7534           /* truly void, because dXSARGS not invoked */
7535           PL_markstack_ptr = temp;
7536           XSRETURN_EMPTY; /* return empty stack */
7537         }
7538         /* must have used dXSARGS; list context implied */
7539         return; /* assume stack size is correct */
7540 
7541 void
Rmpz_tdiv_r(mod,n,d)7542 Rmpz_tdiv_r (mod, n, d)
7543 	mpz_t *	mod
7544 	mpz_t *	n
7545 	mpz_t *	d
7546         PREINIT:
7547         I32* temp;
7548         PPCODE:
7549         temp = PL_markstack_ptr++;
7550         Rmpz_tdiv_r(mod, n, d);
7551         if (PL_markstack_ptr != temp) {
7552           /* truly void, because dXSARGS not invoked */
7553           PL_markstack_ptr = temp;
7554           XSRETURN_EMPTY; /* return empty stack */
7555         }
7556         /* must have used dXSARGS; list context implied */
7557         return; /* assume stack size is correct */
7558 
7559 void
Rmpz_tdiv_qr(q,r,n,d)7560 Rmpz_tdiv_qr (q, r, n, d)
7561 	mpz_t *	q
7562 	mpz_t *	r
7563 	mpz_t *	n
7564 	mpz_t *	d
7565         PREINIT:
7566         I32* temp;
7567         PPCODE:
7568         temp = PL_markstack_ptr++;
7569         Rmpz_tdiv_qr(q, r, n, d);
7570         if (PL_markstack_ptr != temp) {
7571           /* truly void, because dXSARGS not invoked */
7572           PL_markstack_ptr = temp;
7573           XSRETURN_EMPTY; /* return empty stack */
7574         }
7575         /* must have used dXSARGS; list context implied */
7576         return; /* assume stack size is correct */
7577 
7578 unsigned long
7579 Rmpz_tdiv_q_ui (q, n, d)
7580 	mpz_t *	q
7581 	mpz_t *	n
7582 	unsigned long	d
7583 
7584 unsigned long
7585 Rmpz_tdiv_r_ui (q, n, d)
7586 	mpz_t *	q
7587 	mpz_t *	n
7588 	unsigned long	d
7589 
7590 unsigned long
7591 Rmpz_tdiv_qr_ui (q, r, n, d)
7592 	mpz_t *	q
7593 	mpz_t *	r
7594 	mpz_t *	n
7595 	unsigned long	d
7596 
7597 unsigned long
7598 Rmpz_tdiv_ui (n, d)
7599 	mpz_t *	n
7600 	unsigned long	d
7601 
7602 void
7603 Rmpz_tdiv_q_2exp (q, n, b)
7604 	mpz_t *	q
7605 	mpz_t *	n
7606 	SV *	b
7607         PREINIT:
7608         I32* temp;
7609         PPCODE:
7610         temp = PL_markstack_ptr++;
7611         Rmpz_tdiv_q_2exp(aTHX_ q, n, b);
7612         if (PL_markstack_ptr != temp) {
7613           /* truly void, because dXSARGS not invoked */
7614           PL_markstack_ptr = temp;
7615           XSRETURN_EMPTY; /* return empty stack */
7616         }
7617         /* must have used dXSARGS; list context implied */
7618         return; /* assume stack size is correct */
7619 
7620 void
Rmpz_tdiv_r_2exp(r,n,b)7621 Rmpz_tdiv_r_2exp (r, n, b)
7622 	mpz_t *	r
7623 	mpz_t *	n
7624 	SV *	b
7625         PREINIT:
7626         I32* temp;
7627         PPCODE:
7628         temp = PL_markstack_ptr++;
7629         Rmpz_tdiv_r_2exp(aTHX_ r, n, b);
7630         if (PL_markstack_ptr != temp) {
7631           /* truly void, because dXSARGS not invoked */
7632           PL_markstack_ptr = temp;
7633           XSRETURN_EMPTY; /* return empty stack */
7634         }
7635         /* must have used dXSARGS; list context implied */
7636         return; /* assume stack size is correct */
7637 
7638 void
Rmpz_mod(r,n,d)7639 Rmpz_mod (r, n, d)
7640 	mpz_t *	r
7641 	mpz_t *	n
7642 	mpz_t *	d
7643         PREINIT:
7644         I32* temp;
7645         PPCODE:
7646         temp = PL_markstack_ptr++;
7647         Rmpz_mod(r, n, d);
7648         if (PL_markstack_ptr != temp) {
7649           /* truly void, because dXSARGS not invoked */
7650           PL_markstack_ptr = temp;
7651           XSRETURN_EMPTY; /* return empty stack */
7652         }
7653         /* must have used dXSARGS; list context implied */
7654         return; /* assume stack size is correct */
7655 
7656 unsigned long
7657 Rmpz_mod_ui (r, n, d)
7658 	mpz_t *	r
7659 	mpz_t *	n
7660 	unsigned long	d
7661 
7662 void
7663 Rmpz_divexact (dest, n, d)
7664 	mpz_t *	dest
7665 	mpz_t *	n
7666 	mpz_t *	d
7667         PREINIT:
7668         I32* temp;
7669         PPCODE:
7670         temp = PL_markstack_ptr++;
7671         Rmpz_divexact(dest, n, d);
7672         if (PL_markstack_ptr != temp) {
7673           /* truly void, because dXSARGS not invoked */
7674           PL_markstack_ptr = temp;
7675           XSRETURN_EMPTY; /* return empty stack */
7676         }
7677         /* must have used dXSARGS; list context implied */
7678         return; /* assume stack size is correct */
7679 
7680 void
Rmpz_divexact_ui(dest,n,d)7681 Rmpz_divexact_ui (dest, n, d)
7682 	mpz_t *	dest
7683 	mpz_t *	n
7684 	unsigned long	d
7685         PREINIT:
7686         I32* temp;
7687         PPCODE:
7688         temp = PL_markstack_ptr++;
7689         Rmpz_divexact_ui(dest, n, d);
7690         if (PL_markstack_ptr != temp) {
7691           /* truly void, because dXSARGS not invoked */
7692           PL_markstack_ptr = temp;
7693           XSRETURN_EMPTY; /* return empty stack */
7694         }
7695         /* must have used dXSARGS; list context implied */
7696         return; /* assume stack size is correct */
7697 
7698 int
7699 Rmpz_divisible_p (n, d)
7700 	mpz_t *	n
7701 	mpz_t *	d
7702 
7703 int
7704 Rmpz_divisible_ui_p (n, d)
7705 	mpz_t *	n
7706 	unsigned long	d
7707 
7708 int
7709 Rmpz_divisible_2exp_p (n, b)
7710 	mpz_t *	n
7711 	SV *	b
7712 CODE:
7713   RETVAL = Rmpz_divisible_2exp_p (aTHX_ n, b);
7714 OUTPUT:  RETVAL
7715 
7716 int
7717 Rmpz_congruent_p (n, c, d)
7718 	mpz_t *	n
7719 	mpz_t *	c
7720 	mpz_t *	d
7721 
7722 int
7723 Rmpz_congruent_ui_p (n, c, d)
7724 	mpz_t *	n
7725 	unsigned long	c
7726 	unsigned long	d
7727 
7728 SV *
7729 Rmpz_congruent_2exp_p (n, c, d)
7730 	mpz_t *	n
7731 	mpz_t *	c
7732 	SV *	d
7733 CODE:
7734   RETVAL = Rmpz_congruent_2exp_p (aTHX_ n, c, d);
7735 OUTPUT:  RETVAL
7736 
7737 void
Rmpz_powm(dest,base,exp,mod)7738 Rmpz_powm (dest, base, exp, mod)
7739 	mpz_t *	dest
7740 	mpz_t *	base
7741 	mpz_t *	exp
7742 	mpz_t *	mod
7743         PREINIT:
7744         I32* temp;
7745         PPCODE:
7746         temp = PL_markstack_ptr++;
7747         Rmpz_powm(dest, base, exp, mod);
7748         if (PL_markstack_ptr != temp) {
7749           /* truly void, because dXSARGS not invoked */
7750           PL_markstack_ptr = temp;
7751           XSRETURN_EMPTY; /* return empty stack */
7752         }
7753         /* must have used dXSARGS; list context implied */
7754         return; /* assume stack size is correct */
7755 
7756 void
Rmpz_powm_ui(dest,base,exp,mod)7757 Rmpz_powm_ui (dest, base, exp, mod)
7758 	mpz_t *	dest
7759 	mpz_t *	base
7760 	unsigned long	exp
7761 	mpz_t *	mod
7762         PREINIT:
7763         I32* temp;
7764         PPCODE:
7765         temp = PL_markstack_ptr++;
7766         Rmpz_powm_ui(dest, base, exp, mod);
7767         if (PL_markstack_ptr != temp) {
7768           /* truly void, because dXSARGS not invoked */
7769           PL_markstack_ptr = temp;
7770           XSRETURN_EMPTY; /* return empty stack */
7771         }
7772         /* must have used dXSARGS; list context implied */
7773         return; /* assume stack size is correct */
7774 
7775 void
Rmpz_pow_ui(dest,base,exp)7776 Rmpz_pow_ui (dest, base, exp)
7777 	mpz_t *	dest
7778 	mpz_t *	base
7779 	unsigned long	exp
7780         PREINIT:
7781         I32* temp;
7782         PPCODE:
7783         temp = PL_markstack_ptr++;
7784         Rmpz_pow_ui(dest, base, exp);
7785         if (PL_markstack_ptr != temp) {
7786           /* truly void, because dXSARGS not invoked */
7787           PL_markstack_ptr = temp;
7788           XSRETURN_EMPTY; /* return empty stack */
7789         }
7790         /* must have used dXSARGS; list context implied */
7791         return; /* assume stack size is correct */
7792 
7793 void
Rmpz_ui_pow_ui(dest,base,exp)7794 Rmpz_ui_pow_ui (dest, base, exp)
7795 	mpz_t *	dest
7796 	unsigned long	base
7797 	unsigned long	exp
7798         PREINIT:
7799         I32* temp;
7800         PPCODE:
7801         temp = PL_markstack_ptr++;
7802         Rmpz_ui_pow_ui(dest, base, exp);
7803         if (PL_markstack_ptr != temp) {
7804           /* truly void, because dXSARGS not invoked */
7805           PL_markstack_ptr = temp;
7806           XSRETURN_EMPTY; /* return empty stack */
7807         }
7808         /* must have used dXSARGS; list context implied */
7809         return; /* assume stack size is correct */
7810 
7811 int
7812 Rmpz_root (r, n, d)
7813 	mpz_t *	r
7814 	mpz_t *	n
7815 	unsigned long	d
7816 
7817 void
7818 Rmpz_sqrt (r, n)
7819 	mpz_t *	r
7820 	mpz_t *	n
7821         PREINIT:
7822         I32* temp;
7823         PPCODE:
7824         temp = PL_markstack_ptr++;
7825         Rmpz_sqrt(r, n);
7826         if (PL_markstack_ptr != temp) {
7827           /* truly void, because dXSARGS not invoked */
7828           PL_markstack_ptr = temp;
7829           XSRETURN_EMPTY; /* return empty stack */
7830         }
7831         /* must have used dXSARGS; list context implied */
7832         return; /* assume stack size is correct */
7833 
7834 void
Rmpz_sqrtrem(root,rem,src)7835 Rmpz_sqrtrem (root, rem, src)
7836 	mpz_t *	root
7837 	mpz_t *	rem
7838 	mpz_t *	src
7839         PREINIT:
7840         I32* temp;
7841         PPCODE:
7842         temp = PL_markstack_ptr++;
7843         Rmpz_sqrtrem(root, rem, src);
7844         if (PL_markstack_ptr != temp) {
7845           /* truly void, because dXSARGS not invoked */
7846           PL_markstack_ptr = temp;
7847           XSRETURN_EMPTY; /* return empty stack */
7848         }
7849         /* must have used dXSARGS; list context implied */
7850         return; /* assume stack size is correct */
7851 
7852 int
7853 Rmpz_perfect_power_p (in)
7854 	mpz_t *	in
7855 
7856 int
7857 Rmpz_perfect_square_p (in)
7858 	mpz_t *	in
7859 
7860 int
7861 Rmpz_probab_prime_p (cand, reps)
7862 	mpz_t *	cand
7863 	SV *	reps
7864 CODE:
7865   RETVAL = Rmpz_probab_prime_p (aTHX_ cand, reps);
7866 OUTPUT:  RETVAL
7867 
7868 void
7869 Rmpz_nextprime (prime, init)
7870 	mpz_t *	prime
7871 	mpz_t *	init
7872         PREINIT:
7873         I32* temp;
7874         PPCODE:
7875         temp = PL_markstack_ptr++;
7876         Rmpz_nextprime(prime, init);
7877         if (PL_markstack_ptr != temp) {
7878           /* truly void, because dXSARGS not invoked */
7879           PL_markstack_ptr = temp;
7880           XSRETURN_EMPTY; /* return empty stack */
7881         }
7882         /* must have used dXSARGS; list context implied */
7883         return; /* assume stack size is correct */
7884 
7885 void
Rmpz_gcd(gcd,src1,src2)7886 Rmpz_gcd (gcd, src1, src2)
7887 	mpz_t *	gcd
7888 	mpz_t *	src1
7889 	mpz_t *	src2
7890         PREINIT:
7891         I32* temp;
7892         PPCODE:
7893         temp = PL_markstack_ptr++;
7894         Rmpz_gcd(gcd, src1, src2);
7895         if (PL_markstack_ptr != temp) {
7896           /* truly void, because dXSARGS not invoked */
7897           PL_markstack_ptr = temp;
7898           XSRETURN_EMPTY; /* return empty stack */
7899         }
7900         /* must have used dXSARGS; list context implied */
7901         return; /* assume stack size is correct */
7902 
7903 unsigned long
7904 Rmpz_gcd_ui (gcd, n, d)
7905 	mpz_t *	gcd
7906 	mpz_t *	n
7907 	unsigned long	d
7908 
7909 void
7910 Rmpz_gcdext (g, s, t, a, b)
7911 	mpz_t *	g
7912 	mpz_t *	s
7913 	mpz_t *	t
7914 	mpz_t *	a
7915 	mpz_t *	b
7916         PREINIT:
7917         I32* temp;
7918         PPCODE:
7919         temp = PL_markstack_ptr++;
7920         Rmpz_gcdext(g, s, t, a, b);
7921         if (PL_markstack_ptr != temp) {
7922           /* truly void, because dXSARGS not invoked */
7923           PL_markstack_ptr = temp;
7924           XSRETURN_EMPTY; /* return empty stack */
7925         }
7926         /* must have used dXSARGS; list context implied */
7927         return; /* assume stack size is correct */
7928 
7929 void
Rmpz_lcm(lcm,src1,src2)7930 Rmpz_lcm (lcm, src1, src2)
7931 	mpz_t *	lcm
7932 	mpz_t *	src1
7933 	mpz_t *	src2
7934         PREINIT:
7935         I32* temp;
7936         PPCODE:
7937         temp = PL_markstack_ptr++;
7938         Rmpz_lcm(lcm, src1, src2);
7939         if (PL_markstack_ptr != temp) {
7940           /* truly void, because dXSARGS not invoked */
7941           PL_markstack_ptr = temp;
7942           XSRETURN_EMPTY; /* return empty stack */
7943         }
7944         /* must have used dXSARGS; list context implied */
7945         return; /* assume stack size is correct */
7946 
7947 void
Rmpz_lcm_ui(lcm,src1,src2)7948 Rmpz_lcm_ui (lcm, src1, src2)
7949 	mpz_t *	lcm
7950 	mpz_t *	src1
7951 	unsigned long	src2
7952         PREINIT:
7953         I32* temp;
7954         PPCODE:
7955         temp = PL_markstack_ptr++;
7956         Rmpz_lcm_ui(lcm, src1, src2);
7957         if (PL_markstack_ptr != temp) {
7958           /* truly void, because dXSARGS not invoked */
7959           PL_markstack_ptr = temp;
7960           XSRETURN_EMPTY; /* return empty stack */
7961         }
7962         /* must have used dXSARGS; list context implied */
7963         return; /* assume stack size is correct */
7964 
7965 int
7966 Rmpz_invert (inv, src1, src2)
7967 	mpz_t *	inv
7968 	mpz_t *	src1
7969 	mpz_t *	src2
7970 
7971 int
7972 Rmpz_jacobi (a, b)
7973 	mpz_t *	a
7974 	mpz_t *	b
7975 
7976 int
7977 Rmpz_legendre (a, b)
7978 	mpz_t *	a
7979 	mpz_t *	b
7980 
7981 int
7982 Rmpz_kronecker (a, b)
7983 	mpz_t *	a
7984 	mpz_t *	b
7985 
7986 int
7987 Rmpz_kronecker_si (a, b)
7988 	mpz_t *	a
7989 	long	b
7990 
7991 int
7992 Rmpz_kronecker_ui (a, b)
7993 	mpz_t *	a
7994 	unsigned long	b
7995 
7996 int
7997 Rmpz_si_kronecker (a, b)
7998 	long	a
7999 	mpz_t *	b
8000 
8001 int
8002 Rmpz_ui_kronecker (a, b)
8003 	unsigned long	a
8004 	mpz_t *	b
8005 
8006 SV *
8007 Rmpz_remove (rem, src1, src2)
8008 	mpz_t *	rem
8009 	mpz_t *	src1
8010 	mpz_t *	src2
8011 CODE:
8012   RETVAL = Rmpz_remove (aTHX_ rem, src1, src2);
8013 OUTPUT:  RETVAL
8014 
8015 void
8016 Rmpz_fac_ui (fac, b)
8017 	mpz_t *	fac
8018 	unsigned long	b
8019         PREINIT:
8020         I32* temp;
8021         PPCODE:
8022         temp = PL_markstack_ptr++;
8023         Rmpz_fac_ui(fac, b);
8024         if (PL_markstack_ptr != temp) {
8025           /* truly void, because dXSARGS not invoked */
8026           PL_markstack_ptr = temp;
8027           XSRETURN_EMPTY; /* return empty stack */
8028         }
8029         /* must have used dXSARGS; list context implied */
8030         return; /* assume stack size is correct */
8031 
8032 void
8033 Rmpz_2fac_ui (fac, b)
8034 	mpz_t *	fac
8035 	unsigned long	b
8036         PREINIT:
8037         I32* temp;
8038         PPCODE:
8039         temp = PL_markstack_ptr++;
8040         Rmpz_2fac_ui(fac, b);
8041         if (PL_markstack_ptr != temp) {
8042           /* truly void, because dXSARGS not invoked */
8043           PL_markstack_ptr = temp;
8044           XSRETURN_EMPTY; /* return empty stack */
8045         }
8046         /* must have used dXSARGS; list context implied */
8047         return; /* assume stack size is correct */
8048 
8049 void
Rmpz_mfac_uiui(fac,b,c)8050 Rmpz_mfac_uiui (fac, b, c)
8051 	mpz_t *	fac
8052 	unsigned long	b
8053 	unsigned long	c
8054         PREINIT:
8055         I32* temp;
8056         PPCODE:
8057         temp = PL_markstack_ptr++;
8058         Rmpz_mfac_uiui(fac, b, c);
8059         if (PL_markstack_ptr != temp) {
8060           /* truly void, because dXSARGS not invoked */
8061           PL_markstack_ptr = temp;
8062           XSRETURN_EMPTY; /* return empty stack */
8063         }
8064         /* must have used dXSARGS; list context implied */
8065         return; /* assume stack size is correct */
8066 
8067 void
8068 Rmpz_primorial_ui (fac, b)
8069 	mpz_t *	fac
8070 	unsigned long	b
8071         PREINIT:
8072         I32* temp;
8073         PPCODE:
8074         temp = PL_markstack_ptr++;
8075         Rmpz_primorial_ui(fac, b);
8076         if (PL_markstack_ptr != temp) {
8077           /* truly void, because dXSARGS not invoked */
8078           PL_markstack_ptr = temp;
8079           XSRETURN_EMPTY; /* return empty stack */
8080         }
8081         /* must have used dXSARGS; list context implied */
8082         return; /* assume stack size is correct */
8083 
8084 void
Rmpz_bin_ui(dest,n,d)8085 Rmpz_bin_ui (dest, n, d)
8086 	mpz_t *	dest
8087 	mpz_t *	n
8088 	unsigned long	d
8089         PREINIT:
8090         I32* temp;
8091         PPCODE:
8092         temp = PL_markstack_ptr++;
8093         Rmpz_bin_ui(dest, n, d);
8094         if (PL_markstack_ptr != temp) {
8095           /* truly void, because dXSARGS not invoked */
8096           PL_markstack_ptr = temp;
8097           XSRETURN_EMPTY; /* return empty stack */
8098         }
8099         /* must have used dXSARGS; list context implied */
8100         return; /* assume stack size is correct */
8101 
8102 void
Rmpz_bin_si(dest,n,d)8103 Rmpz_bin_si (dest, n, d)
8104 	mpz_t *	dest
8105 	mpz_t *	n
8106 	long	d
8107         PREINIT:
8108         I32* temp;
8109         PPCODE:
8110         temp = PL_markstack_ptr++;
8111         Rmpz_bin_si(dest, n, d);
8112         if (PL_markstack_ptr != temp) {
8113           /* truly void, because dXSARGS not invoked */
8114           PL_markstack_ptr = temp;
8115           XSRETURN_EMPTY; /* return empty stack */
8116         }
8117         /* must have used dXSARGS; list context implied */
8118         return; /* assume stack size is correct */
8119 
8120 void
Rmpz_bin_uiui(dest,n,d)8121 Rmpz_bin_uiui (dest, n, d)
8122 	mpz_t *	dest
8123 	unsigned long	n
8124 	unsigned long	d
8125         PREINIT:
8126         I32* temp;
8127         PPCODE:
8128         temp = PL_markstack_ptr++;
8129         Rmpz_bin_uiui(dest, n, d);
8130         if (PL_markstack_ptr != temp) {
8131           /* truly void, because dXSARGS not invoked */
8132           PL_markstack_ptr = temp;
8133           XSRETURN_EMPTY; /* return empty stack */
8134         }
8135         /* must have used dXSARGS; list context implied */
8136         return; /* assume stack size is correct */
8137 
8138 void
8139 Rmpz_fib_ui (dest, b)
8140 	mpz_t *	dest
8141 	unsigned long	b
8142         PREINIT:
8143         I32* temp;
8144         PPCODE:
8145         temp = PL_markstack_ptr++;
8146         Rmpz_fib_ui(dest, b);
8147         if (PL_markstack_ptr != temp) {
8148           /* truly void, because dXSARGS not invoked */
8149           PL_markstack_ptr = temp;
8150           XSRETURN_EMPTY; /* return empty stack */
8151         }
8152         /* must have used dXSARGS; list context implied */
8153         return; /* assume stack size is correct */
8154 
8155 void
Rmpz_fib2_ui(fn,fnsub1,b)8156 Rmpz_fib2_ui (fn, fnsub1, b)
8157 	mpz_t *	fn
8158 	mpz_t *	fnsub1
8159 	unsigned long	b
8160         PREINIT:
8161         I32* temp;
8162         PPCODE:
8163         temp = PL_markstack_ptr++;
8164         Rmpz_fib2_ui(fn, fnsub1, b);
8165         if (PL_markstack_ptr != temp) {
8166           /* truly void, because dXSARGS not invoked */
8167           PL_markstack_ptr = temp;
8168           XSRETURN_EMPTY; /* return empty stack */
8169         }
8170         /* must have used dXSARGS; list context implied */
8171         return; /* assume stack size is correct */
8172 
8173 void
8174 Rmpz_lucnum_ui (dest, b)
8175 	mpz_t *	dest
8176 	unsigned long	b
8177         PREINIT:
8178         I32* temp;
8179         PPCODE:
8180         temp = PL_markstack_ptr++;
8181         Rmpz_lucnum_ui(dest, b);
8182         if (PL_markstack_ptr != temp) {
8183           /* truly void, because dXSARGS not invoked */
8184           PL_markstack_ptr = temp;
8185           XSRETURN_EMPTY; /* return empty stack */
8186         }
8187         /* must have used dXSARGS; list context implied */
8188         return; /* assume stack size is correct */
8189 
8190 void
Rmpz_lucnum2_ui(ln,lnsub1,b)8191 Rmpz_lucnum2_ui (ln, lnsub1, b)
8192 	mpz_t *	ln
8193 	mpz_t *	lnsub1
8194 	unsigned long	b
8195         PREINIT:
8196         I32* temp;
8197         PPCODE:
8198         temp = PL_markstack_ptr++;
8199         Rmpz_lucnum2_ui(ln, lnsub1, b);
8200         if (PL_markstack_ptr != temp) {
8201           /* truly void, because dXSARGS not invoked */
8202           PL_markstack_ptr = temp;
8203           XSRETURN_EMPTY; /* return empty stack */
8204         }
8205         /* must have used dXSARGS; list context implied */
8206         return; /* assume stack size is correct */
8207 
8208 int
8209 Rmpz_cmp (n, d)
8210 	mpz_t *	n
8211 	mpz_t *	d
8212 
8213 int
8214 Rmpz_cmp_d (n, d)
8215 	mpz_t *	n
8216 	double	d
8217 
8218 int
8219 Rmpz_cmp_NV (a, b)
8220 	mpz_t *	a
8221 	SV *	b
8222 CODE:
8223   RETVAL = Rmpz_cmp_NV (aTHX_ a, b);
8224 OUTPUT:  RETVAL
8225 
8226 int
8227 Rmpz_cmp_si (n, d)
8228 	mpz_t *	n
8229 	long	d
8230 
8231 int
8232 Rmpz_cmp_ui (n, d)
8233 	mpz_t *	n
8234 	unsigned long	d
8235 
8236 int
8237 Rmpz_cmpabs (n, d)
8238 	mpz_t *	n
8239 	mpz_t *	d
8240 
8241 int
8242 Rmpz_cmpabs_d (n, d)
8243 	mpz_t *	n
8244 	double	d
8245 
8246 int
8247 Rmpz_cmpabs_ui (n, d)
8248 	mpz_t *	n
8249 	unsigned long	d
8250 
8251 int
8252 Rmpz_sgn (n)
8253 	mpz_t *	n
8254 
8255 void
8256 Rmpz_and (dest, src1, src2)
8257 	mpz_t *	dest
8258 	mpz_t *	src1
8259 	mpz_t *	src2
8260         PREINIT:
8261         I32* temp;
8262         PPCODE:
8263         temp = PL_markstack_ptr++;
8264         Rmpz_and(dest, src1, src2);
8265         if (PL_markstack_ptr != temp) {
8266           /* truly void, because dXSARGS not invoked */
8267           PL_markstack_ptr = temp;
8268           XSRETURN_EMPTY; /* return empty stack */
8269         }
8270         /* must have used dXSARGS; list context implied */
8271         return; /* assume stack size is correct */
8272 
8273 void
Rmpz_ior(dest,src1,src2)8274 Rmpz_ior (dest, src1, src2)
8275 	mpz_t *	dest
8276 	mpz_t *	src1
8277 	mpz_t *	src2
8278         PREINIT:
8279         I32* temp;
8280         PPCODE:
8281         temp = PL_markstack_ptr++;
8282         Rmpz_ior(dest, src1, src2);
8283         if (PL_markstack_ptr != temp) {
8284           /* truly void, because dXSARGS not invoked */
8285           PL_markstack_ptr = temp;
8286           XSRETURN_EMPTY; /* return empty stack */
8287         }
8288         /* must have used dXSARGS; list context implied */
8289         return; /* assume stack size is correct */
8290 
8291 void
Rmpz_xor(dest,src1,src2)8292 Rmpz_xor (dest, src1, src2)
8293 	mpz_t *	dest
8294 	mpz_t *	src1
8295 	mpz_t *	src2
8296         PREINIT:
8297         I32* temp;
8298         PPCODE:
8299         temp = PL_markstack_ptr++;
8300         Rmpz_xor(dest, src1, src2);
8301         if (PL_markstack_ptr != temp) {
8302           /* truly void, because dXSARGS not invoked */
8303           PL_markstack_ptr = temp;
8304           XSRETURN_EMPTY; /* return empty stack */
8305         }
8306         /* must have used dXSARGS; list context implied */
8307         return; /* assume stack size is correct */
8308 
8309 void
8310 Rmpz_com (dest, src)
8311 	mpz_t *	dest
8312 	mpz_t *	src
8313         PREINIT:
8314         I32* temp;
8315         PPCODE:
8316         temp = PL_markstack_ptr++;
8317         Rmpz_com(dest, src);
8318         if (PL_markstack_ptr != temp) {
8319           /* truly void, because dXSARGS not invoked */
8320           PL_markstack_ptr = temp;
8321           XSRETURN_EMPTY; /* return empty stack */
8322         }
8323         /* must have used dXSARGS; list context implied */
8324         return; /* assume stack size is correct */
8325 
8326 SV *
8327 Rmpz_popcount (in)
8328 	mpz_t *	in
8329 CODE:
8330   RETVAL = Rmpz_popcount (aTHX_ in);
8331 OUTPUT:  RETVAL
8332 
8333 SV *
8334 Rmpz_hamdist (dest, src)
8335 	mpz_t *	dest
8336 	mpz_t *	src
8337 CODE:
8338   RETVAL = Rmpz_hamdist (aTHX_ dest, src);
8339 OUTPUT:  RETVAL
8340 
8341 SV *
8342 Rmpz_scan0 (n, start_bit)
8343 	mpz_t *	n
8344 	SV *	start_bit
8345 CODE:
8346   RETVAL = Rmpz_scan0 (aTHX_ n, start_bit);
8347 OUTPUT:  RETVAL
8348 
8349 SV *
8350 Rmpz_scan1 (n, start_bit)
8351 	mpz_t *	n
8352 	SV *	start_bit
8353 CODE:
8354   RETVAL = Rmpz_scan1 (aTHX_ n, start_bit);
8355 OUTPUT:  RETVAL
8356 
8357 void
8358 Rmpz_setbit (num, bit_index)
8359 	mpz_t *	num
8360 	SV *	bit_index
8361         PREINIT:
8362         I32* temp;
8363         PPCODE:
8364         temp = PL_markstack_ptr++;
8365         Rmpz_setbit(aTHX_ num, bit_index);
8366         if (PL_markstack_ptr != temp) {
8367           /* truly void, because dXSARGS not invoked */
8368           PL_markstack_ptr = temp;
8369           XSRETURN_EMPTY; /* return empty stack */
8370         }
8371         /* must have used dXSARGS; list context implied */
8372         return; /* assume stack size is correct */
8373 
8374 void
8375 Rmpz_clrbit (num, bit_index)
8376 	mpz_t *	num
8377 	SV *	bit_index
8378         PREINIT:
8379         I32* temp;
8380         PPCODE:
8381         temp = PL_markstack_ptr++;
8382         Rmpz_clrbit(aTHX_ num, bit_index);
8383         if (PL_markstack_ptr != temp) {
8384           /* truly void, because dXSARGS not invoked */
8385           PL_markstack_ptr = temp;
8386           XSRETURN_EMPTY; /* return empty stack */
8387         }
8388         /* must have used dXSARGS; list context implied */
8389         return; /* assume stack size is correct */
8390 
8391 SV *
8392 Rmpz_tstbit (num, bit_index)
8393 	mpz_t *	num
8394 	SV *	bit_index
8395 CODE:
8396   RETVAL = Rmpz_tstbit (aTHX_ num, bit_index);
8397 OUTPUT:  RETVAL
8398 
8399 void
Rmpz_import(rop,count,order,size,endian,nails,op)8400 Rmpz_import (rop, count, order, size, endian, nails, op)
8401 	mpz_t *	rop
8402 	SV *	count
8403 	SV *	order
8404 	SV *	size
8405 	SV *	endian
8406 	SV *	nails
8407 	SV *	op
8408         PREINIT:
8409         I32* temp;
8410         PPCODE:
8411         temp = PL_markstack_ptr++;
8412         Rmpz_import(aTHX_ rop, count, order, size, endian, nails, op);
8413         if (PL_markstack_ptr != temp) {
8414           /* truly void, because dXSARGS not invoked */
8415           PL_markstack_ptr = temp;
8416           XSRETURN_EMPTY; /* return empty stack */
8417         }
8418         /* must have used dXSARGS; list context implied */
8419         return; /* assume stack size is correct */
8420 
8421 SV *
8422 Rmpz_export (order, size, endian, nails, op)
8423 	SV *	order
8424 	SV *	size
8425 	SV *	endian
8426 	SV *	nails
8427 	mpz_t *	op
8428 CODE:
8429   RETVAL = Rmpz_export (aTHX_ order, size, endian, nails, op);
8430 OUTPUT:  RETVAL
8431 
8432 void
Rmpz_import_UV(rop,count,order,size,endian,nails,op)8433 Rmpz_import_UV (rop, count, order, size, endian, nails, op)
8434 	mpz_t *	rop
8435 	SV *	count
8436 	SV *	order
8437 	SV *	size
8438 	SV *	endian
8439 	SV *	nails
8440 	AV *	op
8441         PREINIT:
8442         I32* temp;
8443         PPCODE:
8444         temp = PL_markstack_ptr++;
8445         Rmpz_import_UV(aTHX_ rop, count, order, size, endian, nails, op);
8446         if (PL_markstack_ptr != temp) {
8447           /* truly void, because dXSARGS not invoked */
8448           PL_markstack_ptr = temp;
8449           XSRETURN_EMPTY; /* return empty stack */
8450         }
8451         /* must have used dXSARGS; list context implied */
8452         return; /* assume stack size is correct */
8453 
8454 void
Rmpz_export_UV(order,size,endian,nails,op)8455 Rmpz_export_UV (order, size, endian, nails, op)
8456 	SV *	order
8457 	SV *	size
8458 	SV *	endian
8459 	SV *	nails
8460 	mpz_t *	op
8461         PREINIT:
8462         I32* temp;
8463         PPCODE:
8464         temp = PL_markstack_ptr++;
8465         Rmpz_export_UV(aTHX_ order, size, endian, nails, op);
8466         if (PL_markstack_ptr != temp) {
8467           /* truly void, because dXSARGS not invoked */
8468           PL_markstack_ptr = temp;
8469           XSRETURN_EMPTY; /* return empty stack */
8470         }
8471         /* must have used dXSARGS; list context implied */
8472         return; /* assume stack size is correct */
8473 
8474 int
8475 Rmpz_fits_ulong_p (in)
8476 	mpz_t *	in
8477 
8478 int
8479 Rmpz_fits_slong_p (in)
8480 	mpz_t *	in
8481 
8482 int
8483 Rmpz_fits_uint_p (in)
8484 	mpz_t *	in
8485 
8486 int
8487 Rmpz_fits_sint_p (in)
8488 	mpz_t *	in
8489 
8490 int
8491 Rmpz_fits_ushort_p (in)
8492 	mpz_t *	in
8493 
8494 int
8495 Rmpz_fits_sshort_p (in)
8496 	mpz_t *	in
8497 
8498 int
8499 Rmpz_odd_p (in)
8500 	mpz_t *	in
8501 
8502 int
8503 Rmpz_even_p (in)
8504 	mpz_t *	in
8505 
8506 SV *
8507 Rmpz_size (in)
8508 	mpz_t *	in
8509 CODE:
8510   RETVAL = Rmpz_size (aTHX_ in);
8511 OUTPUT:  RETVAL
8512 
8513 SV *
8514 Rmpz_sizeinbase (in, base)
8515 	mpz_t *	in
8516 	int	base
8517 CODE:
8518   RETVAL = Rmpz_sizeinbase (aTHX_ in, base);
8519 OUTPUT:  RETVAL
8520 
8521 void
Rsieve_gmp(x_arg,a,number)8522 Rsieve_gmp (x_arg, a, number)
8523 	int	x_arg
8524 	int	a
8525 	mpz_t *	number
8526         PREINIT:
8527         I32* temp;
8528         PPCODE:
8529         temp = PL_markstack_ptr++;
8530         Rsieve_gmp(aTHX_ x_arg, a, number);
8531         if (PL_markstack_ptr != temp) {
8532           /* truly void, because dXSARGS not invoked */
8533           PL_markstack_ptr = temp;
8534           XSRETURN_EMPTY; /* return empty stack */
8535         }
8536         /* must have used dXSARGS; list context implied */
8537         return; /* assume stack size is correct */
8538 
8539 SV *
8540 Rfermat_gmp (num, base)
8541 	mpz_t *	num
8542 	int	base
8543 CODE:
8544   RETVAL = Rfermat_gmp (aTHX_ num, base);
8545 OUTPUT:  RETVAL
8546 
8547 SV *
8548 Rrm_gmp (num, base)
8549 	mpz_t *	num
8550 	int	base
8551 CODE:
8552   RETVAL = Rrm_gmp (aTHX_ num, base);
8553 OUTPUT:  RETVAL
8554 
8555 SV *
8556 _Rmpz_out_str (p, base)
8557 	mpz_t *	p
8558 	int	base
8559 CODE:
8560   RETVAL = _Rmpz_out_str (aTHX_ p, base);
8561 OUTPUT:  RETVAL
8562 
8563 SV *
8564 _Rmpz_out_strS (p, base, suff)
8565 	mpz_t *	p
8566 	SV *	base
8567 	SV *	suff
8568 CODE:
8569   RETVAL = _Rmpz_out_strS (aTHX_ p, base, suff);
8570 OUTPUT:  RETVAL
8571 
8572 SV *
8573 _Rmpz_out_strP (pre, p, base)
8574 	SV *	pre
8575 	mpz_t *	p
8576 	SV *	base
8577 CODE:
8578   RETVAL = _Rmpz_out_strP (aTHX_ pre, p, base);
8579 OUTPUT:  RETVAL
8580 
8581 SV *
8582 _Rmpz_out_strPS (pre, p, base, suff)
8583 	SV *	pre
8584 	mpz_t *	p
8585 	SV *	base
8586 	SV *	suff
8587 CODE:
8588   RETVAL = _Rmpz_out_strPS (aTHX_ pre, p, base, suff);
8589 OUTPUT:  RETVAL
8590 
8591 SV *
8592 _TRmpz_out_str (stream, base, p)
8593 	FILE *	stream
8594 	SV *	base
8595 	mpz_t *	p
8596 CODE:
8597   RETVAL = _TRmpz_out_str (aTHX_ stream, base, p);
8598 OUTPUT:  RETVAL
8599 
8600 SV *
8601 _TRmpz_out_strS (stream, base, p, suff)
8602 	FILE *	stream
8603 	SV *	base
8604 	mpz_t *	p
8605 	SV *	suff
8606 CODE:
8607   RETVAL = _TRmpz_out_strS (aTHX_ stream, base, p, suff);
8608 OUTPUT:  RETVAL
8609 
8610 SV *
8611 _TRmpz_out_strP (pre, stream, base, p)
8612 	SV *	pre
8613 	FILE *	stream
8614 	SV *	base
8615 	mpz_t *	p
8616 CODE:
8617   RETVAL = _TRmpz_out_strP (aTHX_ pre, stream, base, p);
8618 OUTPUT:  RETVAL
8619 
8620 SV *
8621 _TRmpz_out_strPS (pre, stream, base, p, suff)
8622 	SV *	pre
8623 	FILE *	stream
8624 	SV *	base
8625 	mpz_t *	p
8626 	SV *	suff
8627 CODE:
8628   RETVAL = _TRmpz_out_strPS (aTHX_ pre, stream, base, p, suff);
8629 OUTPUT:  RETVAL
8630 
8631 SV *
8632 Rmpz_inp_str (p, base)
8633 	mpz_t *	p
8634 	int	base
8635 CODE:
8636   RETVAL = Rmpz_inp_str (aTHX_ p, base);
8637 OUTPUT:  RETVAL
8638 
8639 SV *
8640 TRmpz_inp_str (p, stream, base)
8641 	mpz_t *	p
8642 	FILE *	stream
8643 	int	base
8644 CODE:
8645   RETVAL = TRmpz_inp_str (aTHX_ p, stream, base);
8646 OUTPUT:  RETVAL
8647 
8648 void
8649 eratosthenes (x_arg)
8650 	SV *	x_arg
8651         PREINIT:
8652         I32* temp;
8653         PPCODE:
8654         temp = PL_markstack_ptr++;
8655         eratosthenes(aTHX_ x_arg);
8656         if (PL_markstack_ptr != temp) {
8657           /* truly void, because dXSARGS not invoked */
8658           PL_markstack_ptr = temp;
8659           XSRETURN_EMPTY; /* return empty stack */
8660         }
8661         /* must have used dXSARGS; list context implied */
8662         return; /* assume stack size is correct */
8663 
8664 SV *
8665 trial_div_ul (num, x_arg)
8666 	mpz_t *	num
8667 	SV *	x_arg
8668 CODE:
8669   RETVAL = trial_div_ul (aTHX_ num, x_arg);
8670 OUTPUT:  RETVAL
8671 
8672 void
Rmpz_rootrem(root,rem,u,d)8673 Rmpz_rootrem (root, rem, u, d)
8674 	mpz_t *	root
8675 	mpz_t *	rem
8676 	mpz_t *	u
8677 	unsigned long	d
8678         PREINIT:
8679         I32* temp;
8680         PPCODE:
8681         temp = PL_markstack_ptr++;
8682         Rmpz_rootrem(root, rem, u, d);
8683         if (PL_markstack_ptr != temp) {
8684           /* truly void, because dXSARGS not invoked */
8685           PL_markstack_ptr = temp;
8686           XSRETURN_EMPTY; /* return empty stack */
8687         }
8688         /* must have used dXSARGS; list context implied */
8689         return; /* assume stack size is correct */
8690 
8691 void
8692 Rmpz_combit (num, bitpos)
8693 	mpz_t *	num
8694 	SV *	bitpos
8695         PREINIT:
8696         I32* temp;
8697         PPCODE:
8698         temp = PL_markstack_ptr++;
8699         Rmpz_combit(aTHX_ num, bitpos);
8700         if (PL_markstack_ptr != temp) {
8701           /* truly void, because dXSARGS not invoked */
8702           PL_markstack_ptr = temp;
8703           XSRETURN_EMPTY; /* return empty stack */
8704         }
8705         /* must have used dXSARGS; list context implied */
8706         return; /* assume stack size is correct */
8707 
8708 SV *
8709 overload_mul (a, b, third)
8710 	SV *	a
8711 	SV *	b
8712 	SV *	third
8713 CODE:
8714   RETVAL = overload_mul (aTHX_ a, b, third);
8715 OUTPUT:  RETVAL
8716 
8717 SV *
8718 overload_add (a, b, third)
8719 	SV *	a
8720 	SV *	b
8721 	SV *	third
8722 CODE:
8723   RETVAL = overload_add (aTHX_ a, b, third);
8724 OUTPUT:  RETVAL
8725 
8726 SV *
8727 overload_sub (a, b, third)
8728 	SV *	a
8729 	SV *	b
8730 	SV *	third
8731 CODE:
8732   RETVAL = overload_sub (aTHX_ a, b, third);
8733 OUTPUT:  RETVAL
8734 
8735 SV *
8736 overload_div (a, b, third)
8737 	SV *	a
8738 	SV *	b
8739 	SV *	third
8740 CODE:
8741   RETVAL = overload_div (aTHX_ a, b, third);
8742 OUTPUT:  RETVAL
8743 
8744 SV *
8745 overload_mod (a, b, third)
8746 	mpz_t *	a
8747 	SV *	b
8748 	SV *	third
8749 CODE:
8750   RETVAL = overload_mod (aTHX_ a, b, third);
8751 OUTPUT:  RETVAL
8752 
8753 SV *
8754 overload_string (p, second, third)
8755 	mpz_t *	p
8756 	SV *	second
8757 	SV *	third
8758 CODE:
8759   RETVAL = overload_string (aTHX_ p, second, third);
8760 OUTPUT:  RETVAL
8761 
8762 SV *
8763 overload_copy (p, second, third)
8764 	mpz_t *	p
8765 	SV *	second
8766 	SV *	third
8767 CODE:
8768   RETVAL = overload_copy (aTHX_ p, second, third);
8769 OUTPUT:  RETVAL
8770 
8771 SV *
8772 overload_abs (p, second, third)
8773 	mpz_t *	p
8774 	SV *	second
8775 	SV *	third
8776 CODE:
8777   RETVAL = overload_abs (aTHX_ p, second, third);
8778 OUTPUT:  RETVAL
8779 
8780 SV *
8781 overload_lshift (a, b, third)
8782 	mpz_t *	a
8783 	SV *	b
8784 	SV *	third
8785 CODE:
8786   RETVAL = overload_lshift (aTHX_ a, b, third);
8787 OUTPUT:  RETVAL
8788 
8789 SV *
8790 overload_rshift (a, b, third)
8791 	mpz_t *	a
8792 	SV *	b
8793 	SV *	third
8794 CODE:
8795   RETVAL = overload_rshift (aTHX_ a, b, third);
8796 OUTPUT:  RETVAL
8797 
8798 SV *
8799 overload_pow (a, b, third)
8800 	SV *	a
8801 	SV *	b
8802 	SV *	third
8803 CODE:
8804   RETVAL = overload_pow (aTHX_ a, b, third);
8805 OUTPUT:  RETVAL
8806 
8807 SV *
8808 overload_sqrt (p, second, third)
8809 	mpz_t *	p
8810 	SV *	second
8811 	SV *	third
8812 CODE:
8813   RETVAL = overload_sqrt (aTHX_ p, second, third);
8814 OUTPUT:  RETVAL
8815 
8816 SV *
8817 overload_and (a, b, third, ...)
8818 	mpz_t *	a
8819 	SV *	b
8820 	SV *	third
8821         PREINIT:
8822         I32* temp;
8823         CODE:
8824         temp = PL_markstack_ptr++;
8825         RETVAL = overload_and(aTHX_ a, b, third);
8826         PL_markstack_ptr = temp;
8827         OUTPUT:
8828         RETVAL
8829 
8830 SV *
8831 overload_ior (a, b, third, ...)
8832 	mpz_t *	a
8833 	SV *	b
8834 	SV *	third
8835         PREINIT:
8836         I32* temp;
8837         CODE:
8838         temp = PL_markstack_ptr++;
8839         RETVAL = overload_ior(aTHX_ a, b, third);
8840         PL_markstack_ptr = temp;
8841         OUTPUT:
8842         RETVAL
8843 
8844 SV *
8845 overload_xor (a, b, third, ...)
8846 	mpz_t *	a
8847 	SV *	b
8848 	SV *	third
8849         PREINIT:
8850         I32* temp;
8851         CODE:
8852         temp = PL_markstack_ptr++;
8853         RETVAL = overload_xor(aTHX_ a, b, third);
8854         PL_markstack_ptr = temp;
8855         OUTPUT:
8856         RETVAL
8857 
8858 SV *
8859 overload_com (p, second, third)
8860 	mpz_t *	p
8861 	SV *	second
8862 	SV *	third
8863 CODE:
8864   RETVAL = overload_com (aTHX_ p, second, third);
8865 OUTPUT:  RETVAL
8866 
8867 int
8868 my_cmp_z (p, z)
8869 	mpq_t *	p
8870 	mpz_t *	z
8871 
8872 SV *
8873 overload_gt (a, b, third)
8874 	mpz_t *	a
8875 	SV *	b
8876 	SV *	third
8877 CODE:
8878   RETVAL = overload_gt (aTHX_ a, b, third);
8879 OUTPUT:  RETVAL
8880 
8881 SV *
8882 overload_gte (a, b, third)
8883 	mpz_t *	a
8884 	SV *	b
8885 	SV *	third
8886 CODE:
8887   RETVAL = overload_gte (aTHX_ a, b, third);
8888 OUTPUT:  RETVAL
8889 
8890 SV *
8891 overload_lt (a, b, third)
8892 	mpz_t *	a
8893 	SV *	b
8894 	SV *	third
8895 CODE:
8896   RETVAL = overload_lt (aTHX_ a, b, third);
8897 OUTPUT:  RETVAL
8898 
8899 SV *
8900 overload_lte (a, b, third)
8901 	mpz_t *	a
8902 	SV *	b
8903 	SV *	third
8904 CODE:
8905   RETVAL = overload_lte (aTHX_ a, b, third);
8906 OUTPUT:  RETVAL
8907 
8908 SV *
8909 overload_spaceship (a, b, third)
8910 	mpz_t *	a
8911 	SV *	b
8912 	SV *	third
8913 CODE:
8914   RETVAL = overload_spaceship (aTHX_ a, b, third);
8915 OUTPUT:  RETVAL
8916 
8917 SV *
8918 overload_equiv (a, b, third)
8919 	mpz_t *	a
8920 	SV *	b
8921 	SV *	third
8922 CODE:
8923   RETVAL = overload_equiv (aTHX_ a, b, third);
8924 OUTPUT:  RETVAL
8925 
8926 SV *
8927 overload_not_equiv (a, b, third)
8928 	mpz_t *	a
8929 	SV *	b
8930 	SV *	third
8931 CODE:
8932   RETVAL = overload_not_equiv (aTHX_ a, b, third);
8933 OUTPUT:  RETVAL
8934 
8935 SV *
8936 overload_not (a, second, third)
8937 	mpz_t *	a
8938 	SV *	second
8939 	SV *	third
8940 CODE:
8941   RETVAL = overload_not (aTHX_ a, second, third);
8942 OUTPUT:  RETVAL
8943 
8944 SV *
8945 overload_xor_eq (a, b, third, ...)
8946 	SV *	a
8947 	SV *	b
8948 	SV *	third
8949         PREINIT:
8950         I32* temp;
8951         CODE:
8952         temp = PL_markstack_ptr++;
8953         RETVAL = overload_xor_eq(aTHX_ a, b, third);
8954         PL_markstack_ptr = temp;
8955         OUTPUT:
8956         RETVAL
8957 
8958 SV *
8959 overload_ior_eq (a, b, third, ...)
8960 	SV *	a
8961 	SV *	b
8962 	SV *	third
8963         PREINIT:
8964         I32* temp;
8965         CODE:
8966         temp = PL_markstack_ptr++;
8967         RETVAL = overload_ior_eq(aTHX_ a, b, third);
8968         PL_markstack_ptr = temp;
8969         OUTPUT:
8970         RETVAL
8971 
8972 SV *
8973 overload_and_eq (a, b, third, ...)
8974 	SV *	a
8975 	SV *	b
8976 	SV *	third
8977         PREINIT:
8978         I32* temp;
8979         CODE:
8980         temp = PL_markstack_ptr++;
8981         RETVAL = overload_and_eq(aTHX_ a, b, third);
8982         PL_markstack_ptr = temp;
8983         OUTPUT:
8984         RETVAL
8985 
8986 SV *
8987 overload_pow_eq (a, b, third)
8988 	SV *	a
8989 	SV *	b
8990 	SV *	third
8991 CODE:
8992   RETVAL = overload_pow_eq (aTHX_ a, b, third);
8993 OUTPUT:  RETVAL
8994 
8995 SV *
8996 overload_rshift_eq (a, b, third)
8997 	SV *	a
8998 	SV *	b
8999 	SV *	third
9000 CODE:
9001   RETVAL = overload_rshift_eq (aTHX_ a, b, third);
9002 OUTPUT:  RETVAL
9003 
9004 SV *
9005 overload_lshift_eq (a, b, third)
9006 	SV *	a
9007 	SV *	b
9008 	SV *	third
9009 CODE:
9010   RETVAL = overload_lshift_eq (aTHX_ a, b, third);
9011 OUTPUT:  RETVAL
9012 
9013 SV *
9014 overload_inc (p, second, third)
9015 	SV *	p
9016 	SV *	second
9017 	SV *	third
9018 CODE:
9019   RETVAL = overload_inc (aTHX_ p, second, third);
9020 OUTPUT:  RETVAL
9021 
9022 SV *
9023 overload_dec (p, second, third)
9024 	SV *	p
9025 	SV *	second
9026 	SV *	third
9027 CODE:
9028   RETVAL = overload_dec (aTHX_ p, second, third);
9029 OUTPUT:  RETVAL
9030 
9031 SV *
9032 overload_mod_eq (a, b, third)
9033 	SV *	a
9034 	SV *	b
9035 	SV *	third
9036 CODE:
9037   RETVAL = overload_mod_eq (aTHX_ a, b, third);
9038 OUTPUT:  RETVAL
9039 
9040 SV *
9041 get_refcnt (s)
9042 	SV *	s
9043 CODE:
9044   RETVAL = get_refcnt (aTHX_ s);
9045 OUTPUT:  RETVAL
9046 
9047 SV *
9048 overload_div_eq (a, b, third)
9049 	SV *	a
9050 	SV *	b
9051 	SV *	third
9052 CODE:
9053   RETVAL = overload_div_eq (aTHX_ a, b, third);
9054 OUTPUT:  RETVAL
9055 
9056 SV *
9057 overload_sub_eq (a, b, third)
9058 	SV *	a
9059 	SV *	b
9060 	SV *	third
9061 CODE:
9062   RETVAL = overload_sub_eq (aTHX_ a, b, third);
9063 OUTPUT:  RETVAL
9064 
9065 SV *
9066 overload_add_eq (a, b, third)
9067 	SV *	a
9068 	SV *	b
9069 	SV *	third
9070 CODE:
9071   RETVAL = overload_add_eq (aTHX_ a, b, third);
9072 OUTPUT:  RETVAL
9073 
9074 SV *
9075 overload_mul_eq (a, b, third)
9076 	SV *	a
9077 	SV *	b
9078 	SV *	third
9079 CODE:
9080   RETVAL = overload_mul_eq (aTHX_ a, b, third);
9081 OUTPUT:  RETVAL
9082 
9083 SV *
9084 eratosthenes_string (x_arg)
9085 	SV *	x_arg
9086 CODE:
9087   RETVAL = eratosthenes_string (aTHX_ x_arg);
9088 OUTPUT:  RETVAL
9089 
9090 SV *
9091 gmp_v ()
9092 CODE:
9093   RETVAL = gmp_v (aTHX);
9094 OUTPUT:  RETVAL
9095 
9096 
9097 SV *
9098 wrap_gmp_printf (a, b)
9099 	SV *	a
9100 	SV *	b
9101 CODE:
9102   RETVAL = wrap_gmp_printf (aTHX_ a, b);
9103 OUTPUT:  RETVAL
9104 
9105 SV *
9106 wrap_gmp_fprintf (stream, a, b)
9107 	FILE *	stream
9108 	SV *	a
9109 	SV *	b
9110 CODE:
9111   RETVAL = wrap_gmp_fprintf (aTHX_ stream, a, b);
9112 OUTPUT:  RETVAL
9113 
9114 SV *
9115 wrap_gmp_sprintf (s, a, b, buflen)
9116 	SV *	s
9117 	SV *	a
9118 	SV *	b
9119 	int	buflen
9120 CODE:
9121   RETVAL = wrap_gmp_sprintf (aTHX_ s, a, b, buflen);
9122 OUTPUT:  RETVAL
9123 
9124 SV *
9125 wrap_gmp_snprintf (s, bytes, a, b, buflen)
9126 	SV *	s
9127 	SV *	bytes
9128 	SV *	a
9129 	SV *	b
9130 	int	buflen
9131 CODE:
9132   RETVAL = wrap_gmp_snprintf (aTHX_ s, bytes, a, b, buflen);
9133 OUTPUT:  RETVAL
9134 
9135 SV *
9136 _itsa (a)
9137 	SV *	a
9138 CODE:
9139   RETVAL = _itsa (aTHX_ a);
9140 OUTPUT:  RETVAL
9141 
9142 void
9143 Rmpz_urandomb (p, ...)
9144 	SV *	p
9145         PREINIT:
9146         I32* temp;
9147         PPCODE:
9148         temp = PL_markstack_ptr++;
9149         Rmpz_urandomb(aTHX_ p);
9150         if (PL_markstack_ptr != temp) {
9151           /* truly void, because dXSARGS not invoked */
9152           PL_markstack_ptr = temp;
9153           XSRETURN_EMPTY; /* return empty stack */
9154         }
9155         /* must have used dXSARGS; list context implied */
9156         return; /* assume stack size is correct */
9157 
9158 void
9159 Rmpz_urandomm (x, ...)
9160 	SV *	x
9161         PREINIT:
9162         I32* temp;
9163         PPCODE:
9164         temp = PL_markstack_ptr++;
9165         Rmpz_urandomm(aTHX_ x);
9166         if (PL_markstack_ptr != temp) {
9167           /* truly void, because dXSARGS not invoked */
9168           PL_markstack_ptr = temp;
9169           XSRETURN_EMPTY; /* return empty stack */
9170         }
9171         /* must have used dXSARGS; list context implied */
9172         return; /* assume stack size is correct */
9173 
9174 void
9175 Rmpz_rrandomb (x, ...)
9176 	SV *	x
9177         PREINIT:
9178         I32* temp;
9179         PPCODE:
9180         temp = PL_markstack_ptr++;
9181         Rmpz_rrandomb(aTHX_ x);
9182         if (PL_markstack_ptr != temp) {
9183           /* truly void, because dXSARGS not invoked */
9184           PL_markstack_ptr = temp;
9185           XSRETURN_EMPTY; /* return empty stack */
9186         }
9187         /* must have used dXSARGS; list context implied */
9188         return; /* assume stack size is correct */
9189 
9190 SV *
9191 rand_init (seed)
9192 	SV *	seed
9193 CODE:
9194   RETVAL = rand_init (aTHX_ seed);
9195 OUTPUT:  RETVAL
9196 
9197 void
9198 rand_clear (p)
9199 	SV *	p
9200         PREINIT:
9201         I32* temp;
9202         PPCODE:
9203         temp = PL_markstack_ptr++;
9204         rand_clear(aTHX_ p);
9205         if (PL_markstack_ptr != temp) {
9206           /* truly void, because dXSARGS not invoked */
9207           PL_markstack_ptr = temp;
9208           XSRETURN_EMPTY; /* return empty stack */
9209         }
9210         /* must have used dXSARGS; list context implied */
9211         return; /* assume stack size is correct */
9212 
9213 int
9214 _has_longlong ()
9215 
9216 
9217 int
9218 _has_longdouble ()
9219 
9220 
9221 int
9222 _has_float128 ()
9223 
9224 
9225 int
9226 _has_inttypes ()
9227 
9228 
9229 SV *
9230 Rmpz_inp_raw (a, stream)
9231 	mpz_t *	a
9232 	FILE *	stream
9233 CODE:
9234   RETVAL = Rmpz_inp_raw (aTHX_ a, stream);
9235 OUTPUT:  RETVAL
9236 
9237 SV *
9238 Rmpz_out_raw (stream, a)
9239 	FILE *	stream
9240 	mpz_t *	a
9241 CODE:
9242   RETVAL = Rmpz_out_raw (aTHX_ stream, a);
9243 OUTPUT:  RETVAL
9244 
9245 SV *
9246 ___GNU_MP_VERSION ()
9247 CODE:
9248   RETVAL = ___GNU_MP_VERSION (aTHX);
9249 OUTPUT:  RETVAL
9250 
9251 
9252 SV *
9253 ___GNU_MP_VERSION_MINOR ()
9254 CODE:
9255   RETVAL = ___GNU_MP_VERSION_MINOR (aTHX);
9256 OUTPUT:  RETVAL
9257 
9258 
9259 SV *
9260 ___GNU_MP_VERSION_PATCHLEVEL ()
9261 CODE:
9262   RETVAL = ___GNU_MP_VERSION_PATCHLEVEL (aTHX);
9263 OUTPUT:  RETVAL
9264 
9265 
9266 SV *
9267 ___GNU_MP_RELEASE ()
9268 CODE:
9269   RETVAL = ___GNU_MP_RELEASE (aTHX);
9270 OUTPUT:  RETVAL
9271 
9272 
9273 SV *
9274 ___GMP_CC ()
9275 CODE:
9276   RETVAL = ___GMP_CC (aTHX);
9277 OUTPUT:  RETVAL
9278 
9279 
9280 SV *
9281 ___GMP_CFLAGS ()
9282 CODE:
9283   RETVAL = ___GMP_CFLAGS (aTHX);
9284 OUTPUT:  RETVAL
9285 
9286 
9287 void
Rmpz_powm_sec(dest,base,exp,mod)9288 Rmpz_powm_sec (dest, base, exp, mod)
9289 	mpz_t *	dest
9290 	mpz_t *	base
9291 	mpz_t *	exp
9292 	mpz_t *	mod
9293         PREINIT:
9294         I32* temp;
9295         PPCODE:
9296         temp = PL_markstack_ptr++;
9297         Rmpz_powm_sec(dest, base, exp, mod);
9298         if (PL_markstack_ptr != temp) {
9299           /* truly void, because dXSARGS not invoked */
9300           PL_markstack_ptr = temp;
9301           XSRETURN_EMPTY; /* return empty stack */
9302         }
9303         /* must have used dXSARGS; list context implied */
9304         return; /* assume stack size is correct */
9305 
9306 int
9307 _using_mpir ()
9308 
9309 
9310 SV *
9311 _Rmpz_NULL ()
9312 CODE:
9313   RETVAL = _Rmpz_NULL (aTHX);
9314 OUTPUT:  RETVAL
9315 
9316 
9317 SV *
9318 _wrap_count ()
9319 CODE:
9320   RETVAL = _wrap_count (aTHX);
9321 OUTPUT:  RETVAL
9322 
9323 
9324 void
Rprbg_ms(outref,p,q,seed,bits_required)9325 Rprbg_ms (outref, p, q, seed, bits_required)
9326 	mpz_t *	outref
9327 	mpz_t *	p
9328 	mpz_t *	q
9329 	mpz_t *	seed
9330 	int	bits_required
9331         PREINIT:
9332         I32* temp;
9333         PPCODE:
9334         temp = PL_markstack_ptr++;
9335         Rprbg_ms(aTHX_ outref, p, q, seed, bits_required);
9336         if (PL_markstack_ptr != temp) {
9337           /* truly void, because dXSARGS not invoked */
9338           PL_markstack_ptr = temp;
9339           XSRETURN_EMPTY; /* return empty stack */
9340         }
9341         /* must have used dXSARGS; list context implied */
9342         return; /* assume stack size is correct */
9343 
9344 void
Rprbg_bbs(outref,p,q,seed,bits_required)9345 Rprbg_bbs (outref, p, q, seed, bits_required)
9346 	mpz_t *	outref
9347 	mpz_t *	p
9348 	mpz_t *	q
9349 	mpz_t *	seed
9350 	int	bits_required
9351         PREINIT:
9352         I32* temp;
9353         PPCODE:
9354         temp = PL_markstack_ptr++;
9355         Rprbg_bbs(aTHX_ outref, p, q, seed, bits_required);
9356         if (PL_markstack_ptr != temp) {
9357           /* truly void, because dXSARGS not invoked */
9358           PL_markstack_ptr = temp;
9359           XSRETURN_EMPTY; /* return empty stack */
9360         }
9361         /* must have used dXSARGS; list context implied */
9362         return; /* assume stack size is correct */
9363 
9364 int
9365 Rmonobit (bitstream)
9366 	mpz_t *	bitstream
9367 
9368 int
9369 Rlong_run (bitstream)
9370 	mpz_t *	bitstream
9371 
9372 int
9373 Rruns (bitstream)
9374 	mpz_t *	bitstream
9375 
9376 int
9377 Rpoker (bitstream)
9378 	mpz_t *	bitstream
9379 
9380 SV *
9381 _get_xs_version ()
9382 CODE:
9383   RETVAL = _get_xs_version (aTHX);
9384 OUTPUT:  RETVAL
9385 
9386 
9387 SV *
9388 query_eratosthenes_string (candidate, str)
9389 	int	candidate
9390 	char *	str
9391 CODE:
9392   RETVAL = query_eratosthenes_string (aTHX_ candidate, str);
9393 OUTPUT:  RETVAL
9394 
9395 void
9396 autocorrelation (bitstream, offset)
9397 	mpz_t *	bitstream
9398 	int	offset
9399         PREINIT:
9400         I32* temp;
9401         PPCODE:
9402         temp = PL_markstack_ptr++;
9403         autocorrelation(aTHX_ bitstream, offset);
9404         if (PL_markstack_ptr != temp) {
9405           /* truly void, because dXSARGS not invoked */
9406           PL_markstack_ptr = temp;
9407           XSRETURN_EMPTY; /* return empty stack */
9408         }
9409         /* must have used dXSARGS; list context implied */
9410         return; /* assume stack size is correct */
9411 
9412 int
9413 autocorrelation_20000 (bitstream, offset)
9414 	mpz_t *	bitstream
9415 	int	offset
9416 CODE:
9417   RETVAL = autocorrelation_20000 (aTHX_ bitstream, offset);
9418 OUTPUT:  RETVAL
9419 
9420 SV *
9421 _GMP_LIMB_BITS ()
9422 CODE:
9423   RETVAL = _GMP_LIMB_BITS (aTHX);
9424 OUTPUT:  RETVAL
9425 
9426 
9427 SV *
9428 _GMP_NAIL_BITS ()
9429 CODE:
9430   RETVAL = _GMP_NAIL_BITS (aTHX);
9431 OUTPUT:  RETVAL
9432 
9433 
9434 SV *
9435 _new_from_MBI (b)
9436 	SV *	b
9437 CODE:
9438   RETVAL = _new_from_MBI (aTHX_ b);
9439 OUTPUT:  RETVAL
9440 
9441 SV *
9442 _magic_status ()
9443 CODE:
9444   RETVAL = _magic_status (aTHX);
9445 OUTPUT:  RETVAL
9446 
9447 
9448 void
9449 _dump_mbi_gmp (b)
9450 	SV *	b
9451         PREINIT:
9452         I32* temp;
9453         PPCODE:
9454         temp = PL_markstack_ptr++;
9455         _dump_mbi_gmp(aTHX_ b);
9456         if (PL_markstack_ptr != temp) {
9457           /* truly void, because dXSARGS not invoked */
9458           PL_markstack_ptr = temp;
9459           XSRETURN_EMPTY; /* return empty stack */
9460         }
9461         /* must have used dXSARGS; list context implied */
9462         return; /* assume stack size is correct */
9463 
9464 int
9465 _SvIOK (sv)
9466 	SV *	sv
9467 CODE:
9468   RETVAL = _SvIOK (aTHX_ sv);
9469 OUTPUT:  RETVAL
9470 
9471 int
9472 _SvPOK (sv)
9473 	SV *	sv
9474 
9475 int
9476 _SvNOK (sv)
9477 	SV *	sv
9478 
9479 int
9480 IOK_flag (sv)
9481 	SV *	sv
9482 
9483 int
9484 POK_flag (sv)
9485 	SV *	sv
9486 
9487 int
9488 NOK_flag (sv)
9489 	SV *	sv
9490 
9491 SV *
9492 _sizeof_mp_bitcnt_t ()
9493 CODE:
9494   RETVAL = _sizeof_mp_bitcnt_t (aTHX);
9495 OUTPUT:  RETVAL
9496 
9497 
9498 int
9499 _gmp_index_overflow ()
9500 
9501 
9502