4 /* This module provides an interface to an alternate Multi-Precision
5 library, GNU MP in this case */
7 /* XXX note: everywhere where mpz_size is called,
8 sizeof (limb) == sizeof (long) has been assumed. */
15 #include <sys/types.h> /* For size_t */
18 ** These are the cpp-flags used in this file...
21 ** MPZ_MDIV_BUG works around the mpz_m{div,mod,...} routines.
22 ** This bug has been fixed in a later release of
25 ** MPZ_GET_STR_BUG mpz_get_str corrupts memory, seems to be fixed
28 ** MPZ_DEBUG generates a bunch of diagnostic messages
30 ** MPZ_SPARE_MALLOC if set, results in extra code that tries to
31 ** minimize the creation of extra objects.
33 ** MPZ_TEST_DIV extra diagnostic output on stderr, when division
34 ** routines are involved
36 ** MPZ_LIB_DOES_CHECKING if set, assumes that mpz library doesn't call
37 ** alloca with arg < 0 (when casted to a signed
40 ** MPZ_CONVERSIONS_AS_METHODS if set, presents the conversions as
41 ** methods. e.g., `mpz(5).long() == 5L'
42 ** Later, Guido provided an interface to the
43 ** standard functions. So this flag has no been
44 ** cleared, and `long(mpz(5)) == 5L'
46 ** MP_TEST_ALLOC If set, you would discover why MPZ_GET_STR_BUG
49 ** MAKEDUMMYINT Must be set if dynamic linking will be used
54 ** IMHO, mpz_m{div,mod,divmod}() do the wrong things when the denominator < 0
55 ** This has been fixed with gmp release 2.0
57 /*#define MPZ_MDIV_BUG fixed the (for me) nexessary parts in libgmp.a */
59 ** IMO, mpz_get_str() assumes a bit too large target space, if he doesn't
60 ** allocate it himself
65 #if __GNU_MP__ + 0 >= 2
67 #define BITS_PER_MP_LIMB mp_bits_per_limb
69 #define MPZ_GET_STR_BUG
70 #include "gmp-mparam.h"
75 MP_INT mpz
; /* the actual number */
78 staticforward PyTypeObject MPZtype
;
80 #define is_mpzobject(v) ((v)->ob_type == &MPZtype)
82 static const char initialiser_name
[] = "mpz";
84 /* #define MPZ_DEBUG */
93 fputs( "mpz_object() called...\n", stderr
);
94 #endif /* def MPZ_DEBUG */
95 mpzp
= PyObject_New(mpzobject
, &MPZtype
);
99 mpz_init(&mpzp
->mpz
); /* actual initialisation */
101 } /* newmpzobject() */
103 #ifdef MPZ_GET_STR_BUG
104 #include "longlong.h"
105 #endif /* def MPZ_GET_STR_BUG */
108 mpz_format(PyObject
*objp
, int base
, unsigned char withname
)
110 mpzobject
*mpzp
= (mpzobject
*)objp
;
111 PyStringObject
*strobjp
;
116 char prefix
[5], *tcp
;
121 if (mpzp
== NULL
|| !is_mpzobject(mpzp
)) {
122 PyErr_BadInternalCall();
126 assert(base
>= 2 && base
<= 36);
129 i
= strlen(initialiser_name
) + 2; /* e.g. 'mpz(' + ')' */
133 if ((cmpres
= mpz_cmp_si(&mpzp
->mpz
, 0L)) == 0)
134 base
= 10; /* '0' in every base, right */
135 else if (cmpres
< 0) {
137 i
+= 1; /* space to hold '-' */
141 fprintf(stderr
, "mpz_format: mpz_sizeinbase %d\n",
142 (int)mpz_sizeinbase(&mpzp
->mpz
, base
));
143 #endif /* def MPZ_DEBUG */
144 #ifdef MPZ_GET_STR_BUG
146 i
+= ((size_t) abs(mpzp
->mpz
._mp_size
) * BITS_PER_MP_LIMB
147 * __mp_bases
[base
].chars_per_bit_exactly
) + 1;
149 i
+= ((size_t) abs(mpzp
->mpz
.size
) * BITS_PER_MP_LIMB
150 * __mp_bases
[base
].chars_per_bit_exactly
) + 1;
152 #else /* def MPZ_GET_STR_BUG */
153 i
+= (int)mpz_sizeinbase(&mpzp
->mpz
, base
);
154 #endif /* def MPZ_GET_STR_BUG else */
159 i
+= 2; /* space to hold '0x' */
161 else if (base
== 8) {
163 i
+= 1; /* space to hold the extra '0' */
165 else if (base
> 10) {
166 *tcp
++ = '0' + base
/ 10;
167 *tcp
++ = '0' + base
% 10;
169 i
+= 3; /* space to hold e.g. '12#' */
171 else if (base
< 10) {
174 i
+= 2; /* space to hold e.g. '6#' */
178 ** the following code looks if we need a 'L' attached to the number
179 ** it will also attach an 'L' to the value -0x80000000
182 if (mpz_size(&mpzp
->mpz
) > 1
183 || (long)mpz_get_ui(&mpzp
->mpz
) < 0L) {
185 i
+= 1; /* space to hold 'L' */
189 fprintf(stderr
, "mpz_format: requesting string size %d\n", i
);
190 #endif /* def MPZ_DEBUG */
192 (PyStringObject
*)PyString_FromStringAndSize((char *)0, i
))
196 /* get the beginning of the string memory and start copying things */
197 cp
= PyString_AS_STRING(strobjp
);
199 strcpy(cp
, initialiser_name
);
200 cp
+= strlen(initialiser_name
);
204 /* copy the already prepared prefix; e.g. sign and base indicator */
209 /* since' we have the sign already, let the lib think it's a positive
212 mpz_neg(&mpzp
->mpz
,&mpzp
->mpz
); /* hack Hack HAck HACk HACK */
213 (void)mpz_get_str(cp
, base
, &mpzp
->mpz
);
215 mpz_neg(&mpzp
->mpz
,&mpzp
->mpz
); /* hack Hack HAck HACk HACK */
217 fprintf(stderr
, "mpz_format: base (ultim) %d, mpz_get_str: %s\n",
219 #endif /* def MPZ_DEBUG */
231 "mpz_format: cp (str end) %p, begin %p, diff %d, i %d\n",
232 cp
, PyString_AS_STRING(strobjp
),
233 cp
- PyString_AS_STRING(strobjp
), i
);
234 #endif /* def MPZ_DEBUG */
235 assert(cp
- PyString_AS_STRING(strobjp
) <= i
);
237 if (cp
- PyString_AS_STRING(strobjp
) != i
) {
238 strobjp
->ob_size
-= i
- (cp
- PyString_AS_STRING(strobjp
));
241 return (PyObject
*)strobjp
;
247 mpz_dealloc(mpzobject
*mpzp
)
250 fputs( "mpz_dealloc() called...\n", stderr
);
251 #endif /* def MPZ_DEBUG */
252 mpz_clear(&mpzp
->mpz
);
254 } /* mpz_dealloc() */
257 /* pointers to frequently used values 0, 1 and -1 */
258 static mpzobject
*mpz_value_zero
, *mpz_value_one
, *mpz_value_mone
;
261 mpz_compare(mpzobject
*a
, mpzobject
*b
)
266 /* guido sez it's better to return -1, 0 or 1 */
267 return (cmpres
= mpz_cmp( &a
->mpz
, &b
->mpz
)) == 0 ? 0
268 : cmpres
> 0 ? 1 : -1;
269 } /* mpz_compare() */
272 mpz_addition(mpzobject
*a
, mpzobject
*b
)
277 #ifdef MPZ_SPARE_MALLOC
278 if (mpz_cmp_ui(&a
->mpz
, (unsigned long int)0) == 0) {
280 return (PyObject
*)b
;
283 if (mpz_cmp_ui(&b
->mpz
, (unsigned long int)0) == 0) {
285 return (PyObject
*)a
;
287 #endif /* def MPZ_SPARE_MALLOC */
289 if ((z
= newmpzobject()) == NULL
)
292 mpz_add(&z
->mpz
, &a
->mpz
, &b
->mpz
);
293 return (PyObject
*)z
;
294 } /* mpz_addition() */
297 mpz_substract(mpzobject
*a
, mpzobject
*b
)
302 #ifdef MPZ_SPARE_MALLOC
303 if (mpz_cmp_ui(&b
->mpz
, (unsigned long int)0) == 0) {
305 return (PyObject
*)a
;
307 #endif /* MPZ_SPARE_MALLOC */
309 if ((z
= newmpzobject()) == NULL
)
312 mpz_sub(&z
->mpz
, &a
->mpz
, &b
->mpz
);
313 return (PyObject
*)z
;
314 } /* mpz_substract() */
317 mpz_multiply(mpzobject
*a
, mpzobject
*b
)
319 #ifdef MPZ_SPARE_MALLOC
321 #endif /* def MPZ_SPARE_MALLOC */
325 #ifdef MPZ_SPARE_MALLOC
326 if ((cmpres
= mpz_cmp_ui(&a
->mpz
, (unsigned long int)0)) == 0) {
327 Py_INCREF(mpz_value_zero
);
328 return (PyObject
*)mpz_value_zero
;
330 if (cmpres
> 0 && mpz_cmp_ui(&a
->mpz
, (unsigned long int)1) == 0) {
332 return (PyObject
*)b
;
335 if ((cmpres
= mpz_cmp_ui(&b
->mpz
, (unsigned long_int
)0)) == 0) {
336 Py_INCREF(mpz_value_zero
);
337 return (PyObject
*)mpz_value_zero
;
339 if (cmpres
> 0 && mpz_cmp_ui(&b
->mpz
, (unsigned long int)1) == 0) {
341 return (PyObject
*)a
;
343 #endif /* MPZ_SPARE_MALLOC */
345 if ((z
= newmpzobject()) == NULL
)
348 mpz_mul( &z
->mpz
, &a
->mpz
, &b
->mpz
);
349 return (PyObject
*)z
;
351 } /* mpz_multiply() */
354 mpz_divide(mpzobject
*a
, mpzobject
*b
)
356 #ifdef MPZ_SPARE_MALLOC
358 #endif /* def MPZ_SPARE_MALLOC */
363 #ifdef MPZ_SPARE_MALLOC
365 #endif /* def MPZ_SPARE_MALLOC */
366 mpz_cmp_ui(&b
->mpz
, (unsigned long int)0)) == 0) {
367 PyErr_SetString(PyExc_ZeroDivisionError
, "mpz./ by zero");
370 #ifdef MPZ_SPARE_MALLOC
371 if (cmpres
> 0 && mpz_cmp_ui(&b
->mpz(unsigned long int)1) == 0) {
373 return (PyObject
*)a
;
375 #endif /* def MPZ_SPARE_MALLOC */
377 if ((z
= newmpzobject()) == NULL
)
381 fputs("mpz_divide: div result", stderr
);
382 mpz_div(&z
->mpz
, &a
->mpz
, &b
->mpz
);
383 mpz_out_str(stderr
, 10, &z
->mpz
);
385 #endif /* def MPZ_TEST_DIV */
387 if ((mpz_cmp_ui(&a
->mpz
, (unsigned long int)0) < 0)
388 != (mpz_cmp_ui(&b
->mpz
, (unsigned long int)0) < 0)) {
390 ** numerator has other sign than denominator: we have
391 ** to look at the remainder for a correction, since mpz_mdiv
392 ** also calls mpz_divmod, I can as well do it myself
398 mpz_divmod(&z
->mpz
, &tmpmpz
, &a
->mpz
, &b
->mpz
);
400 if (mpz_cmp_ui(&tmpmpz
, (unsigned long int)0) != 0)
401 mpz_sub_ui(&z
->mpz
, &z
->mpz
, (unsigned long int)1);
406 mpz_div(&z
->mpz
, &a
->mpz
, &b
->mpz
);
407 /* the ``naive'' implementation does it right for operands
408 having the same sign */
410 #else /* def MPZ_MDIV_BUG */
411 mpz_mdiv(&z
->mpz
, &a
->mpz
, &b
->mpz
);
412 #endif /* def MPZ_MDIV_BUG else */
414 fputs("mpz_divide: mdiv result", stderr
);
415 mpz_out_str(stderr
, 10, &z
->mpz
);
417 #endif /* def MPZ_TEST_DIV */
418 return (PyObject
*)z
;
423 mpz_remainder(mpzobject
*a
, mpzobject
*b
)
425 #ifdef MPZ_SPARE_MALLOC
427 #endif /* def MPZ_SPARE_MALLOC */
432 #ifdef MPZ_SPARE_MALLOC
434 #endif /* def MPZ_SPARE_MALLOC */
435 mpz_cmp_ui(&b
->mpz
, (unsigned long int)0)) == 0) {
436 PyErr_SetString(PyExc_ZeroDivisionError
, "mpz.% by zero");
439 #ifdef MPZ_SPARE_MALLOC
441 if ((cmpres
= mpz_cmp_ui(&b
->mpz
, (unsigned long int)2)) == 0)
443 Py_INCREF(mpz_value_one
);
444 return (PyObject
*)mpz_value_one
;
447 /* b must be 1 now */
448 Py_INCREF(mpz_value_zero
);
449 return (PyObject
*)mpz_value_zero
;
452 #endif /* def MPZ_SPARE_MALLOC */
454 if ((z
= newmpzobject()) == NULL
)
458 fputs("mpz_remain: mod result", stderr
);
459 mpz_mod(&z
->mpz
, &a
->mpz
, &b
->mpz
);
460 mpz_out_str(stderr
, 10, &z
->mpz
);
462 #endif /* def MPZ_TEST_DIV */
465 /* the ``naive'' implementation does it right for operands
466 having the same sign */
467 mpz_mod(&z
->mpz
, &a
->mpz
, &b
->mpz
);
469 /* assumption: z, a and b all point to different locations */
470 if ((mpz_cmp_ui(&a
->mpz
, (unsigned long int)0) < 0)
471 != (mpz_cmp_ui(&b
->mpz
, (unsigned long int)0) < 0)
472 && mpz_cmp_ui(&z
->mpz
, (unsigned long int)0) != 0)
473 mpz_add(&z
->mpz
, &z
->mpz
, &b
->mpz
);
475 ** numerator has other sign than denominator: we have
476 ** to look at the remainder for a correction, since mpz_mdiv
477 ** also calls mpz_divmod, I can as well do it myself
479 #else /* def MPZ_MDIV_BUG */
480 mpz_mmod(&z
->mpz
, &a
->mpz
, &b
->mpz
);
481 #endif /* def MPZ_MDIV_BUG else */
483 fputs("mpz_remain: mmod result", stderr
);
484 mpz_out_str(stderr
, 10, &z
->mpz
);
486 #endif /* def MPZ_TEST_DIV */
487 return (PyObject
*)z
;
489 } /* mpz_remainder() */
492 mpz_div_and_mod(mpzobject
*a
, mpzobject
*b
)
495 mpzobject
*x
= NULL
, *y
= NULL
;
498 if (mpz_cmp_ui(&b
->mpz
, (unsigned long int)0) == 0) {
499 PyErr_SetString(PyExc_ZeroDivisionError
, "mpz.divmod by zero");
503 if ((z
= PyTuple_New(2)) == NULL
504 || (x
= newmpzobject()) == NULL
505 || (y
= newmpzobject()) == NULL
) {
513 fputs("mpz_divmod: dm result", stderr
);
514 mpz_divmod(&x
->mpz
, &y
->mpz
, &a
->mpz
, &b
->mpz
);
515 mpz_out_str(stderr
, 10, &x
->mpz
);
517 mpz_out_str(stderr
, 10, &y
->mpz
);
519 #endif /* def MPZ_TEST_DIV */
521 mpz_divmod(&x
->mpz
, &y
->mpz
, &a
->mpz
, &b
->mpz
);
522 if ((mpz_cmp_ui(&a
->mpz
, (unsigned long int)0) < 0)
523 != (mpz_cmp_ui(&b
->mpz
, (unsigned long int)0) < 0)
524 && mpz_cmp_ui(&y
->mpz
, (unsigned long int)0) != 0) {
526 ** numerator has other sign than denominator: we have
527 ** to look at the remainder for a correction.
529 mpz_add(&y
->mpz
, &y
->mpz
, &b
->mpz
);
530 mpz_sub_ui(&x
->mpz
, &x
->mpz
, (unsigned long int)1);
532 #else /* def MPZ_MDIV_BUG */
533 mpz_mdivmod( &x
->mpz
, &y
->mpz
, &a
->mpz
, &b
->mpz
);
534 #endif /* def MPZ_MDIV_BUG else */
536 fputs("mpz_divmod: mdm result", stderr
);
537 mpz_out_str(stderr
, 10, &x
->mpz
);
539 mpz_out_str(stderr
, 10, &y
->mpz
);
541 #endif /* def MPZ_TEST_DIV */
543 (void)PyTuple_SetItem(z
, 0, (PyObject
*)x
);
544 (void)PyTuple_SetItem(z
, 1, (PyObject
*)y
);
547 } /* mpz_div_and_mod() */
550 mpz_power(mpzobject
*a
, mpzobject
*b
, mpzobject
*m
)
555 if ((PyObject
*)m
!= Py_None
) {
558 z
=(mpzobject
*)mpz_power(a
, b
, (mpzobject
*)Py_None
);
560 if (z
==NULL
) return((PyObject
*)z
);
561 z2
=(mpzobject
*)mpz_remainder(z
, m
);
563 return((PyObject
*)z2
);
566 if ((cmpres
= mpz_cmp_ui(&b
->mpz
, (unsigned long int)0)) == 0) {
567 /* the gnu-mp lib sets pow(0,0) to 0, we to 1 */
569 Py_INCREF(mpz_value_one
);
570 return (PyObject
*)mpz_value_one
;
574 PyErr_SetString(PyExc_ValueError
,
575 "mpz.pow to negative exponent");
579 if ((cmpres
= mpz_cmp_ui(&a
->mpz
, (unsigned long int)0)) == 0) {
582 Py_INCREF(mpz_value_zero
);
583 return (PyObject
*)mpz_value_zero
;
586 && mpz_cmp_ui(&a
->mpz
, (unsigned long int)1) == 0) {
589 Py_INCREF(mpz_value_one
);
590 return (PyObject
*)mpz_value_one
;
593 && mpz_cmp_si(&a
->mpz
, (long int)-1) == 0) {
596 /* the base is -1: pow(-1, any) == 1,-1 for even,uneven b */
597 /* XXX this code needs to be optimized: what's better?
598 mpz_mmod_ui or mpz_mod_2exp, I choose for the latter
599 for *un*obvious reasons */
601 /* is the exponent even? */
604 /* look to the remainder after a division by (1 << 1) */
605 mpz_mod_2exp(&tmpmpz
, &b
->mpz
, (unsigned long int)1);
607 if (mpz_cmp_ui(&tmpmpz
, (unsigned int)0) == 0) {
609 Py_INCREF(mpz_value_one
);
610 return (PyObject
*)mpz_value_one
;
613 Py_INCREF(mpz_value_mone
);
614 return (PyObject
*)mpz_value_mone
;
617 #ifdef MPZ_LIB_DOES_CHECKING
618 /* check if it's doable: sizeof(exp) > sizeof(long) &&
619 abs(base) > 1 ?? --> No Way */
620 if (mpz_size(&b
->mpz
) > 1)
621 return (PyObject
*)PyErr_NoMemory();
622 #else /* def MPZ_LIB_DOES_CHECKING */
623 /* wet finger method */
624 if (mpz_cmp_ui(&b
->mpz
, (unsigned long int)0x10000) >= 0) {
625 PyErr_SetString(PyExc_ValueError
,
626 "mpz.pow outrageous exponent");
629 #endif /* def MPZ_LIB_DOES_CHECKING else */
631 if ((z
= newmpzobject()) == NULL
)
634 mpz_pow_ui(&z
->mpz
, &a
->mpz
, mpz_get_ui(&b
->mpz
));
636 return (PyObject
*)z
;
641 mpz_negative(mpzobject
*v
)
646 #ifdef MPZ_SPARE_MALLOC
647 if (mpz_cmp_ui(&v
->mpz
, (unsigned long int)0) == 0) {
650 return (PyObject
*)v
;
652 #endif /* def MPZ_SPARE_MALLOC */
654 if ((z
= newmpzobject()) == NULL
)
657 mpz_neg(&z
->mpz
, &v
->mpz
);
658 return (PyObject
*)z
;
659 } /* mpz_negative() */
663 mpz_positive(mpzobject
*v
)
666 return (PyObject
*)v
;
667 } /* mpz_positive() */
671 mpz_absolute(mpzobject
*v
)
676 if (mpz_cmp_ui(&v
->mpz
, (unsigned long int)0) >= 0) {
678 return (PyObject
*)v
;
681 if ((z
= newmpzobject()) == NULL
)
684 mpz_neg(&z
->mpz
, &v
->mpz
);
685 return (PyObject
*)z
;
686 } /* mpz_absolute() */
689 mpz_nonzero(mpzobject
*v
)
691 return mpz_cmp_ui(&v
->mpz
, (unsigned long int)0) != 0;
692 } /* mpz_nonzero() */
695 py_mpz_invert(mpzobject
*v
)
700 /* I think mpz_com does exactly what needed */
701 if ((z
= newmpzobject()) == NULL
)
704 mpz_com(&z
->mpz
, &v
->mpz
);
705 return (PyObject
*)z
;
706 } /* py_mpz_invert() */
709 mpz_lshift(mpzobject
*a
, mpzobject
*b
)
715 if ((cmpres
= mpz_cmp_ui(&b
->mpz
, (unsigned long int)0)) == 0) {
718 return (PyObject
*)a
;
722 PyErr_SetString(PyExc_ValueError
,
723 "mpz.<< negative shift count");
727 #ifdef MPZ_LIB_DOES_CHECKING
728 if (mpz_size(&b
->mpz
) > 1)
729 return (PyObject
*)PyErr_NoMemory();
730 #else /* def MPZ_LIB_DOES_CHECKING */
731 /* wet finger method */
732 if (mpz_cmp_ui(&b
->mpz
, (unsigned long int)0x10000) >= 0) {
733 PyErr_SetString(PyExc_ValueError
,
734 "mpz.<< outrageous shift count");
737 #endif /* def MPZ_LIB_DOES_CHECKING else */
739 if ((z
= newmpzobject()) == NULL
)
742 mpz_mul_2exp(&z
->mpz
, &a
->mpz
, mpz_get_ui(&b
->mpz
));
743 return (PyObject
*)z
;
747 mpz_rshift(mpzobject
*a
, mpzobject
*b
)
753 if ((cmpres
= mpz_cmp_ui(&b
->mpz
, (unsigned long int)0)) == 0) {
756 return (PyObject
*)a
;
760 PyErr_SetString(PyExc_ValueError
,
761 "mpz.>> negative shift count");
765 if (mpz_size(&b
->mpz
) > 1)
766 return (PyObject
*)PyErr_NoMemory();
768 if ((z
= newmpzobject()) == NULL
)
771 mpz_div_2exp(&z
->mpz
, &a
->mpz
, mpz_get_ui(&b
->mpz
));
772 return (PyObject
*)z
;
776 mpz_andfunc(mpzobject
*a
, mpzobject
*b
)
781 if ((z
= newmpzobject()) == NULL
)
784 mpz_and(&z
->mpz
, &a
->mpz
, &b
->mpz
);
785 return (PyObject
*)z
;
786 } /* mpz_andfunc() */
788 /* hack Hack HAck HACk HACK, XXX this code is dead slow */
790 mpz_xor(MP_INT
*res
, const MP_INT
*op1
, const MP_INT
*op2
)
796 mpz_and(res
, op1
, op2
);
797 mpz_com(&tmpmpz
, res
);
798 mpz_ior(res
, op1
, op2
);
799 mpz_and(res
, res
, &tmpmpz
);
802 } /* mpz_xor() HACK */
805 mpz_xorfunc(mpzobject
*a
, mpzobject
*b
)
810 if ((z
= newmpzobject()) == NULL
)
813 mpz_xor(&z
->mpz
, &a
->mpz
, &b
->mpz
);
814 return (PyObject
*)z
;
815 } /* mpz_xorfunc() */
818 mpz_orfunc(mpzobject
*a
, mpzobject
*b
)
823 if ((z
= newmpzobject()) == NULL
)
826 mpz_ior(&z
->mpz
, &a
->mpz
, &b
->mpz
);
827 return (PyObject
*)z
;
830 /* MPZ initialisation */
832 #include "longintrepr.h"
835 MPZ_mpz(PyObject
*self
, PyObject
*args
)
842 fputs("MPZ_mpz() called...\n", stderr
);
843 #endif /* def MPZ_DEBUG */
845 if (!PyArg_Parse(args
, "O", &objp
))
848 /* at least we know it's some object */
849 /* note DON't Py_DECREF args NEITHER objp */
851 if (PyInt_Check(objp
)) {
854 if (!PyArg_Parse(objp
, "l", &lval
))
857 if (lval
== (long)0) {
858 Py_INCREF(mpz_value_zero
);
859 mpzp
= mpz_value_zero
;
861 else if (lval
== (long)1) {
862 Py_INCREF(mpz_value_one
);
863 mpzp
= mpz_value_one
;
865 else if ((mpzp
= newmpzobject()) == NULL
)
867 else mpz_set_si(&mpzp
->mpz
, lval
);
869 else if (PyLong_Check(objp
)) {
872 unsigned char isnegative
;
875 if ((mpzp
= newmpzobject()) == NULL
)
878 mpz_set_si(&mpzp
->mpz
, 0L);
879 mpz_init(&mplongdigit
);
881 /* how we're gonna handle this? */
883 ((i
= ((PyLongObject
*)objp
)->ob_size
) < 0) ))
887 mpz_set_ui(&mplongdigit
,
889 ((PyLongObject
*)objp
)->ob_digit
[i
]);
890 mpz_mul_2exp(&mplongdigit
,&mplongdigit
,
891 (unsigned long int)i
* SHIFT
);
892 mpz_ior(&mpzp
->mpz
, &mpzp
->mpz
, &mplongdigit
);
896 mpz_neg(&mpzp
->mpz
, &mpzp
->mpz
);
898 /* get rid of allocation for tmp variable */
899 mpz_clear(&mplongdigit
);
901 else if (PyString_Check(objp
)) {
902 unsigned char *cp
= (unsigned char *)PyString_AS_STRING(objp
);
903 int len
= PyString_GET_SIZE(objp
);
906 if ((mpzp
= newmpzobject()) == NULL
)
909 mpz_set_si(&mpzp
->mpz
, 0L);
910 mpz_init(&mplongdigit
);
912 /* let's do it the same way as with the long conversion:
913 without thinking how it can be faster (-: :-) */
917 mpz_set_ui(&mplongdigit
, (unsigned long)*--cp
);
918 mpz_mul_2exp(&mplongdigit
,&mplongdigit
,
919 (unsigned long int)len
* 8);
920 mpz_ior(&mpzp
->mpz
, &mpzp
->mpz
, &mplongdigit
);
923 /* get rid of allocation for tmp variable */
924 mpz_clear(&mplongdigit
);
926 else if (is_mpzobject(objp
)) {
928 mpzp
= (mpzobject
*)objp
;
931 PyErr_SetString(PyExc_TypeError
,
932 "mpz.mpz() expects integer, long, string or mpz object argument");
938 fputs("MPZ_mpz: created mpz=", stderr
);
939 mpz_out_str(stderr
, 10, &mpzp
->mpz
);
941 #endif /* def MPZ_DEBUG */
942 return (PyObject
*)mpzp
;
946 mpz_mpzcoerce(PyObject
*z
)
948 /* shortcut: 9 out of 10 times the type is already ok */
949 if (is_mpzobject(z
)) {
951 return (mpzobject
*)z
; /* coercion succeeded */
954 /* what types do we accept?: intobjects and longobjects */
955 if (PyInt_Check(z
) || PyLong_Check(z
))
956 return (mpzobject
*)MPZ_mpz((PyObject
*)NULL
, z
);
958 PyErr_SetString(PyExc_TypeError
,
959 "number coercion (to mpzobject) failed");
961 } /* mpz_mpzcoerce() */
964 static void mpz_divm(MP_INT
*res
, const MP_INT
*num
,
965 const MP_INT
*den
, const MP_INT
*mod
);
968 MPZ_powm(PyObject
*self
, PyObject
*args
)
970 PyObject
*base
, *exp
, *mod
;
971 mpzobject
*mpzbase
= NULL
, *mpzexp
= NULL
, *mpzmod
= NULL
;
976 if (!PyArg_Parse(args
, "(OOO)", &base
, &exp
, &mod
))
979 if ((mpzbase
= mpz_mpzcoerce(base
)) == NULL
980 || (mpzexp
= mpz_mpzcoerce(exp
)) == NULL
981 || (mpzmod
= mpz_mpzcoerce(mod
)) == NULL
982 || (z
= newmpzobject()) == NULL
) {
989 if ((tstres
=mpz_cmp_ui(&mpzexp
->mpz
, (unsigned long int)0)) == 0) {
990 Py_INCREF(mpz_value_one
);
991 return (PyObject
*)mpz_value_one
;
998 mpz_init_set(&absexp
, &mpzexp
->mpz
);
999 mpz_abs(&absexp
, &absexp
);
1000 mpz_powm(&z
->mpz
, &mpzbase
->mpz
, &absexp
, &mpzmod
->mpz
);
1002 mpz_divm(&z
->mpz
, &mpz_value_one
->mpz
, &z
->mpz
, &mpzmod
->mpz
);
1007 mpz_powm(&z
->mpz
, &mpzbase
->mpz
, &mpzexp
->mpz
, &mpzmod
->mpz
);
1014 return (PyObject
*)z
;
1019 MPZ_gcd(PyObject
*self
, PyObject
*args
)
1021 PyObject
*op1
, *op2
;
1022 mpzobject
*mpzop1
= NULL
, *mpzop2
= NULL
;
1026 if (!PyArg_Parse(args
, "(OO)", &op1
, &op2
))
1029 if ((mpzop1
= mpz_mpzcoerce(op1
)) == NULL
1030 || (mpzop2
= mpz_mpzcoerce(op2
)) == NULL
1031 || (z
= newmpzobject()) == NULL
) {
1037 /* ok, we have three mpzobjects, and an initialised result holder */
1038 mpz_gcd(&z
->mpz
, &mpzop1
->mpz
, &mpzop2
->mpz
);
1043 return (PyObject
*)z
;
1048 MPZ_gcdext(PyObject
*self
, PyObject
*args
)
1050 PyObject
*op1
, *op2
, *z
= NULL
;
1051 mpzobject
*mpzop1
= NULL
, *mpzop2
= NULL
;
1052 mpzobject
*g
= NULL
, *s
= NULL
, *t
= NULL
;
1055 if (!PyArg_Parse(args
, "(OO)", &op1
, &op2
))
1058 if ((mpzop1
= mpz_mpzcoerce(op1
)) == NULL
1059 || (mpzop2
= mpz_mpzcoerce(op2
)) == NULL
1060 || (z
= PyTuple_New(3)) == NULL
1061 || (g
= newmpzobject()) == NULL
1062 || (s
= newmpzobject()) == NULL
1063 || (t
= newmpzobject()) == NULL
) {
1073 mpz_gcdext(&g
->mpz
, &s
->mpz
, &t
->mpz
, &mpzop1
->mpz
, &mpzop2
->mpz
);
1078 (void)PyTuple_SetItem(z
, 0, (PyObject
*)g
);
1079 (void)PyTuple_SetItem(z
, 1, (PyObject
*)s
);
1080 (void)PyTuple_SetItem(z
, 2, (PyObject
*)t
);
1082 return (PyObject
*)z
;
1083 } /* MPZ_gcdext() */
1087 MPZ_sqrt(PyObject
*self
, PyObject
*args
)
1090 mpzobject
*mpzop
= NULL
;
1094 if (!PyArg_Parse(args
, "O", &op
))
1097 if ((mpzop
= mpz_mpzcoerce(op
)) == NULL
1098 || (z
= newmpzobject()) == NULL
) {
1103 mpz_sqrt(&z
->mpz
, &mpzop
->mpz
);
1107 return (PyObject
*)z
;
1112 MPZ_sqrtrem(PyObject
*self
, PyObject
*args
)
1114 PyObject
*op
, *z
= NULL
;
1115 mpzobject
*mpzop
= NULL
;
1116 mpzobject
*root
= NULL
, *rem
= NULL
;
1119 if (!PyArg_Parse(args
, "O", &op
))
1122 if ((mpzop
= mpz_mpzcoerce(op
)) == NULL
1123 || (z
= PyTuple_New(2)) == NULL
1124 || (root
= newmpzobject()) == NULL
1125 || (rem
= newmpzobject()) == NULL
) {
1129 /*Py_XDECREF(rem);*/
1133 mpz_sqrtrem(&root
->mpz
, &rem
->mpz
, &mpzop
->mpz
);
1137 (void)PyTuple_SetItem(z
, 0, (PyObject
*)root
);
1138 (void)PyTuple_SetItem(z
, 1, (PyObject
*)rem
);
1140 return (PyObject
*)z
;
1141 } /* MPZ_sqrtrem() */
1145 mpz_divm(MP_INT
*res
, const MP_INT
*num
, const MP_INT
*den
, const MP_INT
*mod
)
1147 MP_INT s0
, s1
, q
, r
, x
, d0
, d1
;
1149 mpz_init_set(&s0
, num
);
1150 mpz_init_set_ui(&s1
, 0);
1154 mpz_init_set(&d0
, den
);
1155 mpz_init_set(&d1
, mod
);
1158 while (d1
._mp_size
!= 0) {
1160 while (d1
.size
!= 0) {
1162 mpz_divmod(&q
, &r
, &d0
, &d1
);
1166 mpz_mul(&x
, &s1
, &q
);
1167 mpz_sub(&x
, &s0
, &x
);
1173 if (d0
._mp_size
!= 1 || d0
._mp_d
[0] != 1)
1174 res
->_mp_size
= 0; /* trouble: the gcd != 1; set s to zero */
1176 if (d0
.size
!= 1 || d0
.d
[0] != 1)
1177 res
->size
= 0; /* trouble: the gcd != 1; set s to zero */
1181 /* watch out here! first check the signs, and then perform
1182 the mpz_mod() since mod could point to res */
1183 if ((s0
.size
< 0) != (mod
->size
< 0)) {
1184 mpz_mod(res
, &s0
, mod
);
1187 mpz_add(res
, res
, mod
);
1190 mpz_mod(res
, &s0
, mod
);
1192 #else /* def MPZ_MDIV_BUG */
1193 mpz_mmod(res
, &s0
, mod
);
1194 #endif /* def MPZ_MDIV_BUG else */
1208 MPZ_divm(PyObject
*self
, PyObject
*args
)
1210 PyObject
*num
, *den
, *mod
;
1211 mpzobject
*mpznum
, *mpzden
= NULL
, *mpzmod
= NULL
;
1212 mpzobject
*z
= NULL
;
1215 if (!PyArg_Parse(args
, "(OOO)", &num
, &den
, &mod
))
1218 if ((mpznum
= mpz_mpzcoerce(num
)) == NULL
1219 || (mpzden
= mpz_mpzcoerce(den
)) == NULL
1220 || (mpzmod
= mpz_mpzcoerce(mod
)) == NULL
1221 || (z
= newmpzobject()) == NULL
) {
1228 mpz_divm(&z
->mpz
, &mpznum
->mpz
, &mpzden
->mpz
, &mpzmod
->mpz
);
1234 if (mpz_cmp_ui(&z
->mpz
, (unsigned long int)0) == 0) {
1236 PyErr_SetString(PyExc_ValueError
,
1237 "gcd(den, mod) != 1 or num == 0");
1241 return (PyObject
*)z
;
1245 /* MPZ methods-as-attributes */
1246 #ifdef MPZ_CONVERSIONS_AS_METHODS
1248 mpz_int(mpzobject
*self
, PyObject
*args
)
1249 #else /* def MPZ_CONVERSIONS_AS_METHODS */
1251 mpz_int(mpzobject
*self
)
1252 #endif /* def MPZ_CONVERSIONS_AS_METHODS else */
1257 #ifdef MPZ_CONVERSIONS_AS_METHODS
1258 if (!PyArg_NoArgs(args
))
1260 #endif /* def MPZ_CONVERSIONS_AS_METHODS */
1262 if (mpz_size(&self
->mpz
) > 1
1263 || (sli
= (long)mpz_get_ui(&self
->mpz
)) < (long)0 ) {
1264 PyErr_SetString(PyExc_ValueError
,
1265 "mpz.int() arg too long to convert");
1269 if (mpz_cmp_ui(&self
->mpz
, (unsigned long)0) < 0)
1272 return PyInt_FromLong(sli
);
1276 #ifdef MPZ_CONVERSIONS_AS_METHODS
1277 mpz_long(mpzobject
*self
, PyObject
*args
)
1278 #else /* def MPZ_CONVERSIONS_AS_METHODS */
1279 mpz_long(mpzobject
*self
)
1280 #endif /* def MPZ_CONVERSIONS_AS_METHODS else */
1283 unsigned long int uli
;
1284 PyLongObject
*longobjp
;
1286 int bitpointer
, newbitpointer
;
1290 #ifdef MPZ_CONVERSIONS_AS_METHODS
1291 if (!PyArg_NoArgs(args
))
1293 #endif /* def MPZ_CONVERSIONS_AS_METHODS */
1295 /* determine length of python-long to be allocated */
1296 if ((longobjp
= _PyLong_New(i
= (int)
1297 ((mpz_size(&self
->mpz
) * BITS_PER_MP_LIMB
1302 /* determine sign, and copy self to scratch var */
1303 mpz_init_set(&mpzscratch
, &self
->mpz
);
1304 if ((isnegative
= (mpz_cmp_ui(&self
->mpz
, (unsigned long int)0) < 0)))
1305 mpz_neg(&mpzscratch
, &mpzscratch
);
1307 /* let those bits come, let those bits go,
1308 e.g. dismantle mpzscratch, build PyLongObject */
1310 bitpointer
= 0; /* the number of valid bits in stock */
1312 ldcount
= 0; /* the python-long limb counter */
1313 uli
= (unsigned long int)0;
1315 longobjp
->ob_digit
[ldcount
] = uli
& MASK
;
1317 /* check if we've had enough bits for this digit */
1318 if (bitpointer
< SHIFT
) {
1319 uli
= mpz_get_ui(&mpzscratch
);
1320 longobjp
->ob_digit
[ldcount
] |=
1321 (uli
<< bitpointer
) & MASK
;
1322 uli
>>= SHIFT
-bitpointer
;
1323 bitpointer
+= BITS_PER_MP_LIMB
;
1324 mpz_div_2exp(&mpzscratch
, &mpzscratch
,
1329 bitpointer
-= SHIFT
;
1333 assert(mpz_cmp_ui(&mpzscratch
, (unsigned long int)0) == 0);
1334 mpz_clear(&mpzscratch
);
1335 assert(ldcount
<= longobjp
->ob_size
);
1337 /* long_normalize() is file-static */
1338 /* longobjp = long_normalize(longobjp); */
1339 while (ldcount
> 0 && longobjp
->ob_digit
[ldcount
-1] == 0)
1341 longobjp
->ob_size
= ldcount
;
1345 longobjp
->ob_size
= -longobjp
->ob_size
;
1347 return (PyObject
*)longobjp
;
1352 /* I would have avoided pow() anyways, so ... */
1353 static const double multiplier
= 256.0 * 256.0 * 256.0 * 256.0;
1355 #ifdef MPZ_CONVERSIONS_AS_METHODS
1357 mpz_float(mpzobject
*self
, PyObject
*args
)
1358 #else /* def MPZ_CONVERSIONS_AS_METHODS */
1360 mpz_float(mpzobject
*self
)
1361 #endif /* def MPZ_CONVERSIONS_AS_METHODS else */
1369 #ifdef MPZ_CONVERSIONS_AS_METHODS
1370 if (!PyArg_NoArgs(args
))
1372 #endif /* def MPZ_CONVERSIONS_AS_METHODS */
1374 i
= (int)mpz_size(&self
->mpz
);
1376 /* determine sign, and copy abs(self) to scratch var */
1377 if ((isnegative
= (mpz_cmp_ui(&self
->mpz
, (unsigned long int)0) < 0)))
1379 mpz_init(&mpzscratch
);
1380 mpz_neg(&mpzscratch
, &self
->mpz
);
1383 mpz_init_set(&mpzscratch
, &self
->mpz
);
1385 /* let those bits come, let those bits go,
1386 e.g. dismantle mpzscratch, build PyFloatObject */
1388 /* Can this overflow? Dunno, protect against that possibility. */
1389 PyFPE_START_PROTECT("mpz_float", return 0)
1393 x
+= mulstate
* mpz_get_ui(&mpzscratch
);
1394 mulstate
*= multiplier
;
1395 mpz_div_2exp(&mpzscratch
, &mpzscratch
, BITS_PER_MP_LIMB
);
1397 PyFPE_END_PROTECT(mulstate
)
1399 assert(mpz_cmp_ui(&mpzscratch
, (unsigned long int)0) == 0);
1400 mpz_clear(&mpzscratch
);
1405 return PyFloat_FromDouble(x
);
1409 #ifdef MPZ_CONVERSIONS_AS_METHODS
1411 mpz_hex(mpzobject
*self
, PyObject
*args
)
1412 #else /* def MPZ_CONVERSIONS_AS_METHODS */
1414 mpz_hex(mpzobject
*self
)
1415 #endif /* def MPZ_CONVERSIONS_AS_METHODS else */
1417 #ifdef MPZ_CONVERSIONS_AS_METHODS
1418 if (!PyArg_NoArgs(args
))
1420 #endif /* def MPZ_CONVERSIONS_AS_METHODS */
1422 return mpz_format((PyObject
*)self
, 16, (unsigned char)1);
1425 #ifdef MPZ_CONVERSIONS_AS_METHODS
1427 mpz_oct(mpzobject
*self
, PyObject
*args
)
1428 #else /* def MPZ_CONVERSIONS_AS_METHODS */
1430 mpz_oct(mpzobject
*self
)
1431 #endif /* def MPZ_CONVERSIONS_AS_METHODS else */
1433 #ifdef MPZ_CONVERSIONS_AS_METHODS
1434 if (!PyArg_NoArgs(args
))
1436 #endif /* def MPZ_CONVERSIONS_AS_METHODS */
1438 return mpz_format((PyObject
*)self
, 8, (unsigned char)1);
1442 mpz_binary(mpzobject
*self
, PyObject
*args
)
1445 PyStringObject
*strobjp
;
1448 unsigned long ldigit
;
1450 if (!PyArg_NoArgs(args
))
1453 if (mpz_cmp_ui(&self
->mpz
, (unsigned long int)0) < 0) {
1454 PyErr_SetString(PyExc_ValueError
,
1455 "mpz.binary() arg must be >= 0");
1459 mpz_init_set(&mp
, &self
->mpz
);
1460 size
= (int)mpz_size(&mp
);
1462 if ((strobjp
= (PyStringObject
*)
1463 PyString_FromStringAndSize(
1464 (char *)0, size
* sizeof (unsigned long int))) == NULL
)
1467 /* get the beginning of the string memory and start copying things */
1468 cp
= PyString_AS_STRING(strobjp
);
1470 /* this has been programmed using a (fairly) decent lib-i/f it could
1471 be must faster if we looked into the GMP lib */
1473 ldigit
= mpz_get_ui(&mp
);
1474 mpz_div_2exp(&mp
, &mp
, BITS_PER_MP_LIMB
);
1475 *cp
++ = (unsigned char)(ldigit
& 0xFF);
1476 *cp
++ = (unsigned char)((ldigit
>>= 8) & 0xFF);
1477 *cp
++ = (unsigned char)((ldigit
>>= 8) & 0xFF);
1478 *cp
++ = (unsigned char)((ldigit
>>= 8) & 0xFF);
1479 if (sizeof(ldigit
) == 8 && BITS_PER_MP_LIMB
== 64) {
1480 *cp
++ = (unsigned char)((ldigit
>>= 8) & 0xFF);
1481 *cp
++ = (unsigned char)((ldigit
>>= 8) & 0xFF);
1482 *cp
++ = (unsigned char)((ldigit
>>= 8) & 0xFF);
1483 *cp
++ = (unsigned char)((ldigit
>>= 8) & 0xFF);
1487 while (strobjp
->ob_size
&& !*--cp
)
1490 return (PyObject
*)strobjp
;
1491 } /* mpz_binary() */
1494 static PyMethodDef mpz_methods
[] = {
1495 #ifdef MPZ_CONVERSIONS_AS_METHODS
1498 {"float", mpz_float
},
1501 #endif /* def MPZ_CONVERSIONS_AS_METHODS */
1502 {"binary", (PyCFunction
)mpz_binary
},
1503 {NULL
, NULL
} /* sentinel */
1507 mpz_getattr(mpzobject
*self
, char *name
)
1509 return Py_FindMethod(mpz_methods
, (PyObject
*)self
, name
);
1510 } /* mpz_getattr() */
1514 mpz_coerce(PyObject
**pv
, PyObject
**pw
)
1519 fputs("mpz_coerce() called...\n", stderr
);
1520 #endif /* def MPZ_DEBUG */
1522 assert(is_mpzobject(*pv
));
1524 /* always convert other arg to mpz value, except for floats */
1525 if (!PyFloat_Check(*pw
)) {
1526 if ((z
= (PyObject
*)mpz_mpzcoerce(*pw
)) == NULL
)
1527 return -1; /* -1: an error always has been set */
1533 #ifdef MPZ_CONVERSIONS_AS_METHODS
1534 if ((z
= mpz_float((mpzobject
*)(*pv
), NULL
)) == NULL
)
1536 #else /* def MPZ_CONVERSIONS_AS_METHODS */
1537 if ((z
= mpz_float((mpzobject
*)(*pv
))) == NULL
)
1539 #endif /* def MPZ_CONVERSIONS_AS_METHODS else */
1544 return 0; /* coercion succeeded */
1546 } /* mpz_coerce() */
1550 mpz_repr(PyObject
*v
)
1552 return mpz_format(v
, 10, (unsigned char)1);
1557 #define UF (unaryfunc)
1558 #define BF (binaryfunc)
1559 #define TF (ternaryfunc)
1560 #define IF (inquiry)
1561 #define CF (coercion)
1563 static PyNumberMethods mpz_as_number
= {
1564 BF mpz_addition
, /*nb_add*/
1565 BF mpz_substract
, /*nb_subtract*/
1566 BF mpz_multiply
, /*nb_multiply*/
1567 BF mpz_divide
, /*nb_divide*/
1568 BF mpz_remainder
, /*nb_remainder*/
1569 BF mpz_div_and_mod
, /*nb_divmod*/
1570 TF mpz_power
, /*nb_power*/
1571 UF mpz_negative
, /*nb_negative*/
1572 UF mpz_positive
, /*tp_positive*/
1573 UF mpz_absolute
, /*tp_absolute*/
1574 IF mpz_nonzero
, /*tp_nonzero*/
1575 UF py_mpz_invert
, /*nb_invert*/
1576 BF mpz_lshift
, /*nb_lshift*/
1577 BF mpz_rshift
, /*nb_rshift*/
1578 BF mpz_andfunc
, /*nb_and*/
1579 BF mpz_xorfunc
, /*nb_xor*/
1580 BF mpz_orfunc
, /*nb_or*/
1581 CF mpz_coerce
, /*nb_coerce*/
1582 #ifndef MPZ_CONVERSIONS_AS_METHODS
1583 UF mpz_int
, /*nb_int*/
1584 UF mpz_long
, /*nb_long*/
1585 UF mpz_float
, /*nb_float*/
1586 UF mpz_oct
, /*nb_oct*/
1587 UF mpz_hex
, /*nb_hex*/
1588 #endif /* ndef MPZ_CONVERSIONS_AS_METHODS */
1591 static PyTypeObject MPZtype
= {
1592 PyObject_HEAD_INIT(NULL
)
1594 "mpz.mpz", /*tp_name*/
1595 sizeof(mpzobject
), /*tp_size*/
1598 (destructor
)mpz_dealloc
, /*tp_dealloc*/
1600 (getattrfunc
)mpz_getattr
, /*tp_getattr*/
1602 (cmpfunc
)mpz_compare
, /*tp_compare*/
1603 (reprfunc
)mpz_repr
, /*tp_repr*/
1604 &mpz_as_number
, /*tp_as_number*/
1607 /* List of functions exported by this module */
1609 static PyMethodDef mpz_functions
[] = {
1611 {initialiser_name
, MPZ_mpz
},
1613 /* until guido ``fixes'' struct PyMethodDef */
1614 {(char *)initialiser_name
, MPZ_mpz
},
1618 {"gcdext", MPZ_gcdext
},
1620 {"sqrtrem", MPZ_sqrtrem
},
1622 {NULL
, NULL
} /* Sentinel */
1626 /* #define MP_TEST_ALLOC */
1628 #ifdef MP_TEST_ALLOC
1629 #define MP_TEST_SIZE 4
1630 static const char mp_test_magic
[MP_TEST_SIZE
] = {'\xAA','\xAA','\xAA','\xAA'};
1631 static mp_test_error(int *location
)
1633 /* assumptions: *alloc returns address divisible by 4,
1634 mpz_* routines allocate in chunks divisible by four */
1635 fprintf(stderr
, "MP_TEST_ERROR: location holds 0x%08d\n", *location
);
1636 Py_FatalError("MP_TEST_ERROR");
1637 } /* static mp_test_error() */
1638 #define MP_EXTRA_ALLOC(size) ((size) + MP_TEST_SIZE)
1639 #define MP_SET_TEST(basep,size) (void)memcpy( ((char *)(basep))+(size), mp_test_magic, MP_TEST_SIZE)
1640 #define MP_DO_TEST(basep,size) if ( !memcmp( ((char *)(basep))+(size), mp_test_magic, MP_TEST_SIZE ) ) \
1643 mp_test_error((int *)((char *)(basep) + size))
1644 #else /* def MP_TEST_ALLOC */
1645 #define MP_EXTRA_ALLOC(size) (size)
1646 #define MP_SET_TEST(basep,size)
1647 #define MP_DO_TEST(basep,size)
1648 #endif /* def MP_TEST_ALLOC else */
1650 void *mp_allocate(size_t alloc_size
)
1655 fprintf(stderr
, "mp_allocate : size %ld\n",
1657 #endif /* def MPZ_DEBUG */
1659 if ( (res
= malloc(MP_EXTRA_ALLOC(alloc_size
))) == NULL
)
1660 Py_FatalError("mp_allocate failure");
1663 fprintf(stderr
, "mp_allocate : address %08p\n", res
);
1664 #endif /* def MPZ_DEBUG */
1666 MP_SET_TEST(res
,alloc_size
);
1669 } /* mp_allocate() */
1672 void *mp_reallocate(void *ptr
, size_t old_size
, size_t new_size
)
1677 fprintf(stderr
, "mp_reallocate: old address %08p, old size %ld\n",
1679 #endif /* def MPZ_DEBUG */
1681 MP_DO_TEST(ptr
, old_size
);
1683 if ( (res
= realloc(ptr
, MP_EXTRA_ALLOC(new_size
))) == NULL
)
1684 Py_FatalError("mp_reallocate failure");
1687 fprintf(stderr
, "mp_reallocate: new address %08p, new size %ld\n",
1689 #endif /* def MPZ_DEBUG */
1691 MP_SET_TEST(res
, new_size
);
1694 } /* mp_reallocate() */
1697 void mp_free(void *ptr
, size_t size
)
1701 fprintf(stderr
, "mp_free : old address %08p, old size %ld\n",
1703 #endif /* def MPZ_DEBUG */
1705 MP_DO_TEST(ptr
, size
);
1711 /* Initialize this module. */
1720 fputs( "initmpz() called...\n", stderr
);
1721 #endif /* def MPZ_DEBUG */
1723 mp_set_memory_functions( mp_allocate
, mp_reallocate
, mp_free
);
1724 MPZtype
.ob_type
= &PyType_Type
;
1725 module
= Py_InitModule("mpz", mpz_functions
);
1727 /* create some frequently used constants */
1728 if ((mpz_value_zero
= newmpzobject()) == NULL
)
1730 mpz_set_ui(&mpz_value_zero
->mpz
, (unsigned long int)0);
1732 if ((mpz_value_one
= newmpzobject()) == NULL
)
1734 mpz_set_ui(&mpz_value_one
->mpz
, (unsigned long int)1);
1736 if ((mpz_value_mone
= newmpzobject()) == NULL
)
1738 mpz_set_si(&mpz_value_mone
->mpz
, (long)-1);
1740 dict
= PyModule_GetDict(module
);
1742 PyDict_SetItemString(dict
, "MPZType", (PyObject
*)&MPZtype
);
1749 int _mpz_dummy_int
; /* XXX otherwise, we're .bss-less (DYNLOAD->Jack?) */
1750 #endif /* def MAKEDUMMYINT */