1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
27 /* This module provides an interface to an alternate Multi-Precision
28 library, GNU MP in this case */
30 /* XXX note: everywhere where mpz_size is called,
31 sizeof (limb) == sizeof (long) has been assumed. */
36 #include "allobjects.h"
39 #include <sys/types.h> /* For size_t */
42 ** These are the cpp-flags used in this file...
45 ** MPZ_MDIV_BUG works around the mpz_m{div,mod,...} routines.
46 ** This bug has been fixed in a later release of
49 ** MPZ_GET_STR_BUG mpz_get_str corrupts memory, seems to be fixed
52 ** MPZ_DEBUG generates a bunch of diagnostic messages
54 ** MPZ_SPARE_MALLOC if set, results in extra code that tries to
55 ** minimize the creation of extra objects.
57 ** MPZ_TEST_DIV extra diagnostic output on stderr, when division
58 ** routines are involved
60 ** MPZ_LIB_DOES_CHECKING if set, assumes that mpz library doesn't call
61 ** alloca with arg < 0 (when casted to a signed
64 ** MPZ_CONVERSIONS_AS_METHODS if set, presents the conversions as
65 ** methods. e.g., `mpz(5).long() == 5L'
66 ** Later, Guido provided an interface to the
67 ** standard functions. So this flag has no been
68 ** cleared, and `long(mpz(5)) == 5L'
70 ** MP_TEST_ALLOC If set, you would discover why MPZ_GET_STR_BUG
73 ** MAKEDUMMYINT Must be set if dynamic linking will be used
78 ** IMHO, mpz_m{div,mod,divmod}() do the wrong things when the denominator < 0
79 ** I assume that this will be fixed in a future release
81 /*#define MPZ_MDIV_BUG fixed the (for me) nexessary parts in libgmp.a */
83 ** IMO, mpz_get_str() assumes a bit too large target space, if he doesn't
84 ** allocate it himself
86 #define MPZ_GET_STR_BUG
91 MP_INT mpz
; /* the actual number */
94 staticforward typeobject MPZtype
;
96 #define is_mpzobject(v) ((v)->ob_type == &MPZtype)
98 static const char initialiser_name
[] = "mpz";
100 /* #define MPZ_DEBUG */
109 fputs( "mpz_object() called...\n", stderr
);
110 #endif /* def MPZ_DEBUG */
111 mpzp
= NEWOBJ(mpzobject
, &MPZtype
);
115 mpz_init(&mpzp
->mpz
); /* actual initialisation */
117 } /* newmpzobject() */
119 #ifdef MPZ_GET_STR_BUG
120 #include "gmp-impl.h"
121 #include "longlong.h"
122 #endif /* def MPZ_GET_STR_BUG */
125 mpz_format(objp
, base
, withname
)
128 unsigned char withname
;
130 mpzobject
*mpzp
= (mpzobject
*)objp
;
131 stringobject
*strobjp
;
136 char prefix
[5], *tcp
;
141 if (mpzp
== NULL
|| !is_mpzobject(mpzp
)) {
146 assert(base
>= 2 && base
<= 36);
149 i
= strlen(initialiser_name
) + 2; /* e.g. 'mpz(' + ')' */
153 if ((cmpres
= mpz_cmp_si(&mpzp
->mpz
, 0L)) == 0)
154 base
= 10; /* '0' in every base, right */
155 else if (cmpres
< 0) {
157 i
+= 1; /* space to hold '-' */
161 fprintf(stderr
, "mpz_format: mpz_sizeinbase %d\n",
162 (int)mpz_sizeinbase(&mpzp
->mpz
, base
));
163 #endif /* def MPZ_DEBUG */
164 #ifdef MPZ_GET_STR_BUG
165 i
+= ((size_t) abs(mpzp
->mpz
.size
) * BITS_PER_MP_LIMB
166 * __mp_bases
[base
].chars_per_bit_exactly
) + 1;
167 #else /* def MPZ_GET_STR_BUG */
168 i
+= (int)mpz_sizeinbase(&mpzp
->mpz
, base
);
169 #endif /* def MPZ_GET_STR_BUG else */
174 i
+= 2; /* space to hold '0x' */
176 else if (base
== 8) {
178 i
+= 1; /* space to hold the extra '0' */
180 else if (base
> 10) {
181 *tcp
++ = '0' + base
/ 10;
182 *tcp
++ = '0' + base
% 10;
184 i
+= 3; /* space to hold e.g. '12#' */
186 else if (base
< 10) {
189 i
+= 2; /* space to hold e.g. '6#' */
193 ** the following code looks if we need a 'L' attached to the number
194 ** it will also attach an 'L' to the value -0x80000000
197 if (mpz_size(&mpzp
->mpz
) > 1
198 || (long)mpz_get_ui(&mpzp
->mpz
) < 0L) {
200 i
+= 1; /* space to hold 'L' */
204 fprintf(stderr
, "mpz_format: requesting string size %d\n", i
);
205 #endif /* def MPZ_DEBUG */
206 if ((strobjp
= (stringobject
*)newsizedstringobject((char *)0, i
))
210 /* get the beginning of the string memory and start copying things */
211 cp
= GETSTRINGVALUE(strobjp
);
213 strcpy(cp
, initialiser_name
);
214 cp
+= strlen(initialiser_name
);
218 /* copy the already prepared prefix; e.g. sign and base indicator */
223 /* since' we have the sign already, let the lib think it's a positive
226 mpz_neg(&mpzp
->mpz
,&mpzp
->mpz
); /* hack Hack HAck HACk HACK */
227 (void)mpz_get_str(cp
, base
, &mpzp
->mpz
);
229 mpz_neg(&mpzp
->mpz
,&mpzp
->mpz
); /* hack Hack HAck HACk HACK */
231 fprintf(stderr
, "mpz_format: base (ultim) %d, mpz_get_str: %s\n",
233 #endif /* def MPZ_DEBUG */
245 "mpz_format: cp (str end) 0x%x, begin 0x%x, diff %d, i %d\n",
246 cp
, GETSTRINGVALUE(strobjp
), cp
- GETSTRINGVALUE(strobjp
), i
);
247 #endif /* def MPZ_DEBUG */
248 assert(cp
- GETSTRINGVALUE(strobjp
) <= i
);
250 if (cp
- GETSTRINGVALUE(strobjp
) != i
) {
251 strobjp
->ob_size
-= i
- (cp
- GETSTRINGVALUE(strobjp
));
254 return (object
*)strobjp
;
264 fputs( "mpz_dealloc() called...\n", stderr
);
265 #endif /* def MPZ_DEBUG */
266 mpz_clear(&mpzp
->mpz
);
268 } /* mpz_dealloc() */
271 /* pointers to frequently used values 0, 1 and -1 */
272 static mpzobject
*mpz_value_zero
, *mpz_value_one
, *mpz_value_mone
;
281 /* guido sez it's better to return -1, 0 or 1 */
282 return (cmpres
= mpz_cmp( &a
->mpz
, &b
->mpz
)) == 0 ? 0
283 : cmpres
> 0 ? 1 : -1;
284 } /* mpz_compare() */
294 #ifdef MPZ_SPARE_MALLOC
295 if (mpz_cmp_ui(&a
->mpz
, (unsigned long int)0) == 0) {
300 if (mpz_cmp_ui(&b
->mpz
, (unsigned long int)0) == 0) {
304 #endif /* def MPZ_SPARE_MALLOC */
306 if ((z
= newmpzobject()) == NULL
)
309 mpz_add(&z
->mpz
, &a
->mpz
, &b
->mpz
);
311 } /* mpz_addition() */
321 #ifdef MPZ_SPARE_MALLOC
322 if (mpz_cmp_ui(&b
->mpz
, (unsigned long int)0) == 0) {
326 #endif /* MPZ_SPARE_MALLOC */
328 if ((z
= newmpzobject()) == NULL
)
331 mpz_sub(&z
->mpz
, &a
->mpz
, &b
->mpz
);
333 } /* mpz_substract() */
340 #ifdef MPZ_SPARE_MALLOC
342 #endif /* def MPZ_SPARE_MALLOC */
346 #ifdef MPZ_SPARE_MALLOC
347 if ((cmpres
= mpz_cmp_ui(&a
->mpz
, (unsigned long int)0)) == 0) {
348 INCREF(mpz_value_zero
);
349 return (object
*)mpz_value_zero
;
351 if (cmpres
> 0 && mpz_cmp_ui(&a
->mpz
, (unsigned long int)1) == 0) {
356 if ((cmpres
= mpz_cmp_ui(&b
->mpz
, (unsigned long_int
)0)) == 0) {
357 INCREF(mpz_value_zero
);
358 return (object
*)mpz_value_zero
;
360 if (cmpres
> 0 && mpz_cmp_ui(&b
->mpz
, (unsigned long int)1) == 0) {
364 #endif /* MPZ_SPARE_MALLOC */
366 if ((z
= newmpzobject()) == NULL
)
369 mpz_mul( &z
->mpz
, &a
->mpz
, &b
->mpz
);
372 } /* mpz_multiply() */
379 #ifdef MPZ_SPARE_MALLOC
381 #endif /* def MPZ_SPARE_MALLOC */
386 #ifdef MPZ_SPARE_MALLOC
388 #endif /* def MPZ_SPARE_MALLOC */
389 mpz_cmp_ui(&b
->mpz
, (unsigned long int)0)) == 0) {
390 err_setstr(ZeroDivisionError
, "mpz./ by zero");
393 #ifdef MPZ_SPARE_MALLOC
394 if (cmpres
> 0 && mpz_cmp_ui(&b
->mpz(unsigned long int)1) == 0) {
398 #endif /* def MPZ_SPARE_MALLOC */
400 if ((z
= newmpzobject()) == NULL
)
404 fputs("mpz_divide: div result", stderr
);
405 mpz_div(&z
->mpz
, &a
->mpz
, &b
->mpz
);
406 mpz_out_str(stderr
, 10, &z
->mpz
);
408 #endif /* def MPZ_TEST_DIV */
410 if ((mpz_cmp_ui(&a
->mpz
, (unsigned long int)0) < 0)
411 != (mpz_cmp_ui(&b
->mpz
, (unsigned long int)0) < 0)) {
413 ** numerator has other sign than denominator: we have
414 ** to look at the remainder for a correction, since mpz_mdiv
415 ** also calls mpz_divmod, I can as well do it myself
421 mpz_divmod(&z
->mpz
, &tmpmpz
, &a
->mpz
, &b
->mpz
);
423 if (mpz_cmp_ui(&tmpmpz
, (unsigned long int)0) != 0)
424 mpz_sub_ui(&z
->mpz
, &z
->mpz
, (unsigned long int)1);
429 mpz_div(&z
->mpz
, &a
->mpz
, &b
->mpz
);
430 /* the ``naive'' implementation does it right for operands
431 having the same sign */
433 #else /* def MPZ_MDIV_BUG */
434 mpz_mdiv(&z
->mpz
, &a
->mpz
, &b
->mpz
);
435 #endif /* def MPZ_MDIV_BUG else */
437 fputs("mpz_divide: mdiv result", stderr
);
438 mpz_out_str(stderr
, 10, &z
->mpz
);
440 #endif /* def MPZ_TEST_DIV */
450 #ifdef MPZ_SPARE_MALLOC
452 #endif /* def MPZ_SPARE_MALLOC */
457 #ifdef MPZ_SPARE_MALLOC
459 #endif /* def MPZ_SPARE_MALLOC */
460 mpz_cmp_ui(&b
->mpz
, (unsigned long int)0)) == 0) {
461 err_setstr(ZeroDivisionError
, "mpz.% by zero");
464 #ifdef MPZ_SPARE_MALLOC
466 if ((cmpres
= mpz_cmp_ui(&b
->mpz
, (unsigned long int)2)) == 0) {
467 INCREF(mpz_value_one
);
468 return (object
*)mpz_value_one
;
471 /* b must be 1 now */
472 INCREF(mpz_value_zero
);
473 return (object
*)mpz_value_zero
;
476 #endif /* def MPZ_SPARE_MALLOC */
478 if ((z
= newmpzobject()) == NULL
)
482 fputs("mpz_remain: mod result", stderr
);
483 mpz_mod(&z
->mpz
, &a
->mpz
, &b
->mpz
);
484 mpz_out_str(stderr
, 10, &z
->mpz
);
486 #endif /* def MPZ_TEST_DIV */
489 /* the ``naive'' implementation does it right for operands
490 having the same sign */
491 mpz_mod(&z
->mpz
, &a
->mpz
, &b
->mpz
);
493 /* assumption: z, a and b all point to different locations */
494 if ((mpz_cmp_ui(&a
->mpz
, (unsigned long int)0) < 0)
495 != (mpz_cmp_ui(&b
->mpz
, (unsigned long int)0) < 0)
496 && mpz_cmp_ui(&z
->mpz
, (unsigned long int)0) != 0)
497 mpz_add(&z
->mpz
, &z
->mpz
, &b
->mpz
);
499 ** numerator has other sign than denominator: we have
500 ** to look at the remainder for a correction, since mpz_mdiv
501 ** also calls mpz_divmod, I can as well do it myself
503 #else /* def MPZ_MDIV_BUG */
504 mpz_mmod(&z
->mpz
, &a
->mpz
, &b
->mpz
);
505 #endif /* def MPZ_MDIV_BUG else */
507 fputs("mpz_remain: mmod result", stderr
);
508 mpz_out_str(stderr
, 10, &z
->mpz
);
510 #endif /* def MPZ_TEST_DIV */
513 } /* mpz_remainder() */
516 mpz_div_and_mod(a
, b
)
521 mpzobject
*x
= NULL
, *y
= NULL
;
524 if (mpz_cmp_ui(&b
->mpz
, (unsigned long int)0) == 0) {
525 err_setstr(ZeroDivisionError
, "mpz.divmod by zero");
529 if ((z
= newtupleobject(2)) == NULL
530 || (x
= newmpzobject()) == NULL
531 || (y
= newmpzobject()) == NULL
) {
539 fputs("mpz_divmod: dm result", stderr
);
540 mpz_divmod(&x
->mpz
, &y
->mpz
, &a
->mpz
, &b
->mpz
);
541 mpz_out_str(stderr
, 10, &x
->mpz
);
543 mpz_out_str(stderr
, 10, &y
->mpz
);
545 #endif /* def MPZ_TEST_DIV */
547 mpz_divmod(&x
->mpz
, &y
->mpz
, &a
->mpz
, &b
->mpz
);
548 if ((mpz_cmp_ui(&a
->mpz
, (unsigned long int)0) < 0)
549 != (mpz_cmp_ui(&b
->mpz
, (unsigned long int)0) < 0)
550 && mpz_cmp_ui(&y
->mpz
, (unsigned long int)0) != 0) {
552 ** numerator has other sign than denominator: we have
553 ** to look at the remainder for a correction.
555 mpz_add(&y
->mpz
, &y
->mpz
, &b
->mpz
);
556 mpz_sub_ui(&x
->mpz
, &x
->mpz
, (unsigned long int)1);
558 #else /* def MPZ_MDIV_BUG */
559 mpz_mdivmod( &x
->mpz
, &y
->mpz
, &a
->mpz
, &b
->mpz
);
560 #endif /* def MPZ_MDIV_BUG else */
562 fputs("mpz_divmod: mdm result", stderr
);
563 mpz_out_str(stderr
, 10, &x
->mpz
);
565 mpz_out_str(stderr
, 10, &y
->mpz
);
567 #endif /* def MPZ_TEST_DIV */
569 (void)settupleitem(z
, 0, (object
*)x
);
570 (void)settupleitem(z
, 1, (object
*)y
);
573 } /* mpz_div_and_mod() */
583 long int longtmp1
, longtmp2
;
585 if ((object
*)m
!=Py_None
)
589 z
=mpz_power(a
, b
, (mpzobject
*)Py_None
);
591 if (z
==NULL
) return(z
);
592 z2
=mpz_remainder(z
, m
);
594 return((object
*)z2
);
597 if ((cmpres
= mpz_cmp_ui(&b
->mpz
, (unsigned long int)0)) == 0) {
598 /* the gnu-mp lib sets pow(0,0) to 0, we to 1 */
600 INCREF(mpz_value_one
);
601 return (object
*)mpz_value_one
;
605 err_setstr(ValueError
, "mpz.pow to negative exponent");
609 if ((cmpres
= mpz_cmp_ui(&a
->mpz
, (unsigned long int)0)) == 0) {
612 INCREF(mpz_value_zero
);
613 return (object
*)mpz_value_zero
;
616 && mpz_cmp_ui(&a
->mpz
, (unsigned long int)1) == 0) {
619 INCREF(mpz_value_one
);
620 return (object
*)mpz_value_one
;
623 && mpz_cmp_si(&a
->mpz
, (long int)-1) == 0) {
626 /* the base is -1: pow(-1, any) == 1,-1 for even,uneven b */
627 /* XXX this code needs to be optimized: what's better?
628 mpz_mmod_ui or mpz_mod_2exp, I choose for the latter
629 for *un*obvious reasons */
631 /* is the exponent even? */
634 /* look to the remainder after a division by (1 << 1) */
635 mpz_mod_2exp(&tmpmpz
, &b
->mpz
, (unsigned long int)1);
637 if (mpz_cmp_ui(&tmpmpz
, (unsigned int)0) == 0) {
639 INCREF(mpz_value_one
);
640 return (object
*)mpz_value_one
;
643 INCREF(mpz_value_mone
);
644 return (object
*)mpz_value_mone
;
647 #ifdef MPZ_LIB_DOES_CHECKING
648 /* check if it's doable: sizeof(exp) > sizeof(long) &&
649 abs(base) > 1 ?? --> No Way */
650 if (mpz_size(&b
->mpz
) > 1)
651 return (object
*)err_nomem();
652 #else /* def MPZ_LIB_DOES_CHECKING */
653 /* wet finger method */
654 if (mpz_cmp_ui(&b
->mpz
, (unsigned long int)0x10000) >= 0) {
655 err_setstr(ValueError
, "mpz.pow outrageous exponent");
658 #endif /* def MPZ_LIB_DOES_CHECKING else */
660 if ((z
= newmpzobject()) == NULL
)
663 mpz_pow_ui(&z
->mpz
, &a
->mpz
, mpz_get_ui(&b
->mpz
));
676 #ifdef MPZ_SPARE_MALLOC
677 if (mpz_cmp_ui(&v
->mpz
, (unsigned long int)0) == 0) {
682 #endif /* def MPZ_SPARE_MALLOC */
684 if ((z
= newmpzobject()) == NULL
)
687 mpz_neg(&z
->mpz
, &v
->mpz
);
689 } /* mpz_negative() */
698 } /* mpz_positive() */
708 if (mpz_cmp_ui(&v
->mpz
, (unsigned long int)0) >= 0) {
713 if ((z
= newmpzobject()) == NULL
)
716 mpz_neg(&z
->mpz
, &v
->mpz
);
718 } /* mpz_absolute() */
724 return mpz_cmp_ui(&v
->mpz
, (unsigned long int)0) != 0;
725 } /* mpz_nonzero() */
734 /* I think mpz_com does exactly what needed */
735 if ((z
= newmpzobject()) == NULL
)
738 mpz_com(&z
->mpz
, &v
->mpz
);
751 if ((cmpres
= mpz_cmp_ui(&b
->mpz
, (unsigned long int)0)) == 0) {
758 err_setstr(ValueError
, "mpz.<< negative shift count");
762 #ifdef MPZ_LIB_DOES_CHECKING
763 if (mpz_size(&b
->mpz
) > 1)
764 return (object
*)err_nomem();
765 #else /* def MPZ_LIB_DOES_CHECKING */
766 /* wet finger method */
767 if (mpz_cmp_ui(&b
->mpz
, (unsigned long int)0x10000) >= 0) {
768 err_setstr(ValueError
, "mpz.<< outrageous shift count");
771 #endif /* def MPZ_LIB_DOES_CHECKING else */
773 if ((z
= newmpzobject()) == NULL
)
776 mpz_mul_2exp(&z
->mpz
, &a
->mpz
, mpz_get_ui(&b
->mpz
));
789 if ((cmpres
= mpz_cmp_ui(&b
->mpz
, (unsigned long int)0)) == 0) {
796 err_setstr(ValueError
, "mpz.>> negative shift count");
800 if (mpz_size(&b
->mpz
) > 1)
801 return (object
*)err_nomem();
803 if ((z
= newmpzobject()) == NULL
)
806 mpz_div_2exp(&z
->mpz
, &a
->mpz
, mpz_get_ui(&b
->mpz
));
818 if ((z
= newmpzobject()) == NULL
)
821 mpz_and(&z
->mpz
, &a
->mpz
, &b
->mpz
);
823 } /* mpz_andfunc() */
825 /* hack Hack HAck HACk HACK, XXX this code is dead slow */
827 mpz_xor(res
, op1
, op2
)
836 mpz_and(res
, op1
, op2
);
837 mpz_com(&tmpmpz
, res
);
838 mpz_ior(res
, op1
, op2
);
839 mpz_and(res
, res
, &tmpmpz
);
842 } /* mpz_xor() HACK */
852 if ((z
= newmpzobject()) == NULL
)
855 mpz_xor(&z
->mpz
, &a
->mpz
, &b
->mpz
);
857 } /* mpz_xorfunc() */
867 if ((z
= newmpzobject()) == NULL
)
870 mpz_ior(&z
->mpz
, &a
->mpz
, &b
->mpz
);
874 /* MPZ initialisation */
876 #include "longintrepr.h"
888 fputs("MPZ_mpz() called...\n", stderr
);
889 #endif /* def MPZ_DEBUG */
891 if (!getargs(args
, "O", &objp
))
894 /* at least we know it's some object */
895 /* note DON't DECREF args NEITHER objp */
897 if (is_intobject(objp
)) {
900 if (!getargs(objp
, "l", &lval
))
903 if (lval
== (long)0) {
904 INCREF(mpz_value_zero
);
905 mpzp
= mpz_value_zero
;
907 else if (lval
== (long)1) {
908 INCREF(mpz_value_one
);
909 mpzp
= mpz_value_one
;
911 else if ((mpzp
= newmpzobject()) == NULL
)
913 else mpz_set_si(&mpzp
->mpz
, lval
);
915 else if (is_longobject(objp
)) {
918 unsigned char isnegative
;
921 if ((mpzp
= newmpzobject()) == NULL
)
924 mpz_set_si(&mpzp
->mpz
, 0L);
925 mpz_init(&mplongdigit
);
927 /* how we're gonna handle this? */
928 if (isnegative
= ((i
= ((longobject
*)objp
)->ob_size
) < 0) )
932 mpz_set_ui(&mplongdigit
,
934 ((longobject
*)objp
)->ob_digit
[i
]);
935 mpz_mul_2exp(&mplongdigit
,&mplongdigit
,
936 (unsigned long int)i
* SHIFT
);
937 mpz_ior(&mpzp
->mpz
, &mpzp
->mpz
, &mplongdigit
);
941 mpz_neg(&mpzp
->mpz
, &mpzp
->mpz
);
943 /* get rid of allocation for tmp variable */
944 mpz_clear(&mplongdigit
);
946 else if (is_stringobject(objp
)) {
951 if (!getargs(objp
, "s#", &cp
, &len
))
954 if ((mpzp
= newmpzobject()) == NULL
)
957 mpz_set_si(&mpzp
->mpz
, 0L);
958 mpz_init(&mplongdigit
);
960 /* let's do it the same way as with the long conversion:
961 without thinking how it can be faster (-: :-) */
965 mpz_set_ui(&mplongdigit
, (unsigned long)*--cp
);
966 mpz_mul_2exp(&mplongdigit
,&mplongdigit
,
967 (unsigned long int)len
* 8);
968 mpz_ior(&mpzp
->mpz
, &mpzp
->mpz
, &mplongdigit
);
971 /* get rid of allocation for tmp variable */
972 mpz_clear(&mplongdigit
);
974 else if (is_mpzobject(objp
)) {
976 mpzp
= (mpzobject
*)objp
;
979 err_setstr(TypeError
,
980 "mpz.mpz() expects integer, long, string or mpz object argument");
986 fputs("MPZ_mpz: created mpz=", stderr
);
987 mpz_out_str(stderr
, 10, &mpzp
->mpz
);
989 #endif /* def MPZ_DEBUG */
990 return (object
*)mpzp
;
997 /* shortcut: 9 out of 10 times the type is already ok */
998 if (is_mpzobject(z
)) {
1000 return (mpzobject
*)z
; /* coercion succeeded */
1003 /* what types do we accept?: intobjects and longobjects */
1004 if (is_intobject(z
) || is_longobject(z
))
1005 return (mpzobject
*)MPZ_mpz((object
*)NULL
, z
);
1007 err_setstr(TypeError
, "number coercion (to mpzobject) failed");
1009 } /* mpz_mpzcoerce() */
1012 static void mpz_divm
PROTO((MP_INT
*res
, const MP_INT
*num
,
1013 const MP_INT
*den
, const MP_INT
*mod
));
1016 MPZ_powm(self
, args
)
1020 object
*base
, *exp
, *mod
;
1021 mpzobject
*mpzbase
= NULL
, *mpzexp
= NULL
, *mpzmod
= NULL
;
1026 if (!getargs(args
, "(OOO)", &base
, &exp
, &mod
))
1029 if ((mpzbase
= mpz_mpzcoerce(base
)) == NULL
1030 || (mpzexp
= mpz_mpzcoerce(exp
)) == NULL
1031 || (mpzmod
= mpz_mpzcoerce(mod
)) == NULL
1032 || (z
= newmpzobject()) == NULL
) {
1039 if ((tstres
=mpz_cmp_ui(&mpzexp
->mpz
, (unsigned long int)0)) == 0) {
1040 INCREF(mpz_value_one
);
1041 return (object
*)mpz_value_one
;
1048 mpz_init_set(&absexp
, &mpzexp
->mpz
);
1049 mpz_abs(&absexp
, &absexp
);
1050 mpz_powm(&z
->mpz
, &mpzbase
->mpz
, &absexp
, &mpzmod
->mpz
);
1052 mpz_divm(&z
->mpz
, &mpz_value_one
->mpz
, &z
->mpz
, &mpzmod
->mpz
);
1057 mpz_powm(&z
->mpz
, &mpzbase
->mpz
, &mpzexp
->mpz
, &mpzmod
->mpz
);
1074 mpzobject
*mpzop1
= NULL
, *mpzop2
= NULL
;
1078 if (!getargs(args
, "(OO)", &op1
, &op2
))
1081 if ((mpzop1
= mpz_mpzcoerce(op1
)) == NULL
1082 || (mpzop2
= mpz_mpzcoerce(op2
)) == NULL
1083 || (z
= newmpzobject()) == NULL
) {
1089 /* ok, we have three mpzobjects, and an initialised result holder */
1090 mpz_gcd(&z
->mpz
, &mpzop1
->mpz
, &mpzop2
->mpz
);
1100 MPZ_gcdext(self
, args
)
1104 object
*op1
, *op2
, *z
= NULL
;
1105 mpzobject
*mpzop1
= NULL
, *mpzop2
= NULL
;
1106 mpzobject
*g
= NULL
, *s
= NULL
, *t
= NULL
;
1109 if (!getargs(args
, "(OO)", &op1
, &op2
))
1112 if ((mpzop1
= mpz_mpzcoerce(op1
)) == NULL
1113 || (mpzop2
= mpz_mpzcoerce(op2
)) == NULL
1114 || (z
= newtupleobject(3)) == NULL
1115 || (g
= newmpzobject()) == NULL
1116 || (s
= newmpzobject()) == NULL
1117 || (t
= newmpzobject()) == NULL
) {
1127 mpz_gcdext(&g
->mpz
, &s
->mpz
, &t
->mpz
, &mpzop1
->mpz
, &mpzop2
->mpz
);
1132 (void)settupleitem(z
, 0, (object
*)g
);
1133 (void)settupleitem(z
, 1, (object
*)s
);
1134 (void)settupleitem(z
, 2, (object
*)t
);
1137 } /* MPZ_gcdext() */
1141 MPZ_sqrt(self
, args
)
1146 mpzobject
*mpzop
= NULL
;
1150 if (!getargs(args
, "O", &op
))
1153 if ((mpzop
= mpz_mpzcoerce(op
)) == NULL
1154 || (z
= newmpzobject()) == NULL
) {
1159 mpz_sqrt(&z
->mpz
, &mpzop
->mpz
);
1168 MPZ_sqrtrem(self
, args
)
1172 object
*op
, *z
= NULL
;
1173 mpzobject
*mpzop
= NULL
;
1174 mpzobject
*root
= NULL
, *rem
= NULL
;
1177 if (!getargs(args
, "O", &op
))
1180 if ((mpzop
= mpz_mpzcoerce(op
)) == NULL
1181 || (z
= newtupleobject(2)) == NULL
1182 || (root
= newmpzobject()) == NULL
1183 || (rem
= newmpzobject()) == NULL
) {
1191 mpz_sqrtrem(&root
->mpz
, &rem
->mpz
, &mpzop
->mpz
);
1195 (void)settupleitem(z
, 0, (object
*)root
);
1196 (void)settupleitem(z
, 1, (object
*)rem
);
1199 } /* MPZ_sqrtrem() */
1204 mpz_divm(MP_INT
*res
, const MP_INT
*num
, const MP_INT
*den
, const MP_INT
*mod
)
1206 mpz_divm(res
, num
, den
, mod
)
1213 MP_INT s0
, s1
, q
, r
, x
, d0
, d1
;
1215 mpz_init_set(&s0
, num
);
1216 mpz_init_set_ui(&s1
, 0);
1220 mpz_init_set(&d0
, den
);
1221 mpz_init_set(&d1
, mod
);
1223 while (d1
.size
!= 0) {
1224 mpz_divmod(&q
, &r
, &d0
, &d1
);
1228 mpz_mul(&x
, &s1
, &q
);
1229 mpz_sub(&x
, &s0
, &x
);
1234 if (d0
.size
!= 1 || d0
.d
[0] != 1)
1235 res
->size
= 0; /* trouble: the gcd != 1; set s to zero */
1238 /* watch out here! first check the signs, and then perform
1239 the mpz_mod() since mod could point to res */
1240 if ((s0
.size
< 0) != (mod
->size
< 0)) {
1241 mpz_mod(res
, &s0
, mod
);
1244 mpz_add(res
, res
, mod
);
1247 mpz_mod(res
, &s0
, mod
);
1249 #else /* def MPZ_MDIV_BUG */
1250 mpz_mmod(res
, &s0
, mod
);
1251 #endif /* def MPZ_MDIV_BUG else */
1265 MPZ_divm(self
, args
)
1269 object
*num
, *den
, *mod
;
1270 mpzobject
*mpznum
, *mpzden
, *mpzmod
= NULL
;
1271 mpzobject
*z
= NULL
;
1274 if (!getargs(args
, "(OOO)", &num
, &den
, &mod
))
1277 if ((mpznum
= mpz_mpzcoerce(num
)) == NULL
1278 || (mpzden
= mpz_mpzcoerce(den
)) == NULL
1279 || (mpzmod
= mpz_mpzcoerce(mod
)) == NULL
1280 || (z
= newmpzobject()) == NULL
) {
1287 mpz_divm(&z
->mpz
, &mpznum
->mpz
, &mpzden
->mpz
, &mpzmod
->mpz
);
1293 if (mpz_cmp_ui(&z
->mpz
, (unsigned long int)0) == 0) {
1295 err_setstr(ValueError
, "gcd(den, mod) != 1 or num == 0");
1303 /* MPZ methods-as-attributes */
1304 #ifdef MPZ_CONVERSIONS_AS_METHODS
1309 #else /* def MPZ_CONVERSIONS_AS_METHODS */
1313 #endif /* def MPZ_CONVERSIONS_AS_METHODS else */
1318 #ifdef MPZ_CONVERSIONS_AS_METHODS
1319 if (!getnoarg(args
))
1321 #endif /* def MPZ_CONVERSIONS_AS_METHODS */
1323 if (mpz_size(&self
->mpz
) > 1
1324 || (sli
= (long)mpz_get_ui(&self
->mpz
)) < (long)0 ) {
1325 err_setstr(ValueError
, "mpz.int() arg too long to convert");
1329 if (mpz_cmp_ui(&self
->mpz
, (unsigned long)0) < 0)
1332 return newintobject(sli
);
1336 #ifdef MPZ_CONVERSIONS_AS_METHODS
1337 mpz_long(self
, args
)
1340 #else /* def MPZ_CONVERSIONS_AS_METHODS */
1343 #endif /* def MPZ_CONVERSIONS_AS_METHODS else */
1346 unsigned long int uli
;
1347 longobject
*longobjp
;
1349 int bitpointer
, newbitpointer
;
1353 #ifdef MPZ_CONVERSIONS_AS_METHODS
1354 if (!getnoarg(args
))
1356 #endif /* def MPZ_CONVERSIONS_AS_METHODS */
1358 /* determine length of python-long to be allocated */
1359 if ((longobjp
= alloclongobject(i
= (int)
1360 ((mpz_size(&self
->mpz
) * BITS_PER_MP_LIMB
1365 /* determine sign, and copy self to scratch var */
1366 mpz_init_set(&mpzscratch
, &self
->mpz
);
1367 if (isnegative
= (mpz_cmp_ui(&self
->mpz
, (unsigned long int)0) < 0))
1368 mpz_neg(&mpzscratch
, &mpzscratch
);
1370 /* let those bits come, let those bits go,
1371 e.g. dismantle mpzscratch, build longobject */
1373 bitpointer
= 0; /* the number of valid bits in stock */
1375 ldcount
= 0; /* the python-long limb counter */
1376 uli
= (unsigned long int)0;
1378 longobjp
->ob_digit
[ldcount
] = uli
& MASK
;
1380 /* check if we've had enough bits for this digit */
1381 if (bitpointer
< SHIFT
) {
1382 uli
= mpz_get_ui(&mpzscratch
);
1383 longobjp
->ob_digit
[ldcount
] |=
1384 (uli
<< bitpointer
) & MASK
;
1385 uli
>>= SHIFT
-bitpointer
;
1386 bitpointer
+= BITS_PER_MP_LIMB
;
1387 mpz_div_2exp(&mpzscratch
, &mpzscratch
,
1392 bitpointer
-= SHIFT
;
1396 assert(mpz_cmp_ui(&mpzscratch
, (unsigned long int)0) == 0);
1397 mpz_clear(&mpzscratch
);
1398 assert(ldcount
<= longobjp
->ob_size
);
1400 /* long_normalize() is file-static */
1401 /* longobjp = long_normalize(longobjp); */
1402 while (ldcount
> 0 && longobjp
->ob_digit
[ldcount
-1] == 0)
1404 longobjp
->ob_size
= ldcount
;
1408 longobjp
->ob_size
= -longobjp
->ob_size
;
1410 return (object
*)longobjp
;
1415 /* I would have avoided pow() anyways, so ... */
1416 static const double multiplier
= 256.0 * 256.0 * 256.0 * 256.0;
1418 #ifdef MPZ_CONVERSIONS_AS_METHODS
1420 mpz_float(self
, args
)
1423 #else /* def MPZ_CONVERSIONS_AS_METHODS */
1427 #endif /* def MPZ_CONVERSIONS_AS_METHODS else */
1435 #ifdef MPZ_CONVERSIONS_AS_METHODS
1436 if (!getnoarg(args
))
1438 #endif /* def MPZ_CONVERSIONS_AS_METHODS */
1440 i
= (int)mpz_size(&self
->mpz
);
1442 /* determine sign, and copy abs(self) to scratch var */
1443 if (isnegative
= (mpz_cmp_ui(&self
->mpz
, (unsigned long int)0) < 0)) {
1444 mpz_init(&mpzscratch
);
1445 mpz_neg(&mpzscratch
, &self
->mpz
);
1448 mpz_init_set(&mpzscratch
, &self
->mpz
);
1450 /* let those bits come, let those bits go,
1451 e.g. dismantle mpzscratch, build floatobject */
1456 x
+= mulstate
* mpz_get_ui(&mpzscratch
);
1457 mulstate
*= multiplier
;
1458 mpz_div_2exp(&mpzscratch
, &mpzscratch
, BITS_PER_MP_LIMB
);
1461 assert(mpz_cmp_ui(&mpzscratch
, (unsigned long int)0) == 0);
1462 mpz_clear(&mpzscratch
);
1467 return newfloatobject(x
);
1471 #ifdef MPZ_CONVERSIONS_AS_METHODS
1476 #else /* def MPZ_CONVERSIONS_AS_METHODS */
1480 #endif /* def MPZ_CONVERSIONS_AS_METHODS else */
1482 #ifdef MPZ_CONVERSIONS_AS_METHODS
1483 if (!getnoarg(args
))
1485 #endif /* def MPZ_CONVERSIONS_AS_METHODS */
1487 return mpz_format(self
, 16, (unsigned char)1);
1490 #ifdef MPZ_CONVERSIONS_AS_METHODS
1495 #else /* def MPZ_CONVERSIONS_AS_METHODS */
1499 #endif /* def MPZ_CONVERSIONS_AS_METHODS else */
1501 #ifdef MPZ_CONVERSIONS_AS_METHODS
1502 if (!getnoarg(args
))
1504 #endif /* def MPZ_CONVERSIONS_AS_METHODS */
1506 return mpz_format(self
, 8, (unsigned char)1);
1510 mpz_binary(self
, args
)
1515 stringobject
*strobjp
;
1518 unsigned long ldigit
;
1520 if (!getnoarg(args
))
1523 if (mpz_cmp_ui(&self
->mpz
, (unsigned long int)0) < 0) {
1524 err_setstr(ValueError
, "mpz.binary() arg must be >= 0");
1528 mpz_init_set(&mp
, &self
->mpz
);
1529 size
= (int)mpz_size(&mp
);
1531 if ((strobjp
= (stringobject
*)
1532 newsizedstringobject((char *)0,
1533 size
* sizeof (unsigned long int))) == NULL
)
1536 /* get the beginning of the string memory and start copying things */
1537 cp
= GETSTRINGVALUE(strobjp
);
1539 /* this has been programmed using a (fairly) decent lib-i/f it could
1540 be must faster if we looked into the GMP lib */
1542 ldigit
= mpz_get_ui(&mp
);
1543 mpz_div_2exp(&mp
, &mp
, BITS_PER_MP_LIMB
);
1544 *cp
++ = (unsigned char)(ldigit
& 0xFF);
1545 *cp
++ = (unsigned char)((ldigit
>>= 8) & 0xFF);
1546 *cp
++ = (unsigned char)((ldigit
>>= 8) & 0xFF);
1547 *cp
++ = (unsigned char)((ldigit
>>= 8) & 0xFF);
1550 while (strobjp
->ob_size
&& !*--cp
)
1553 return (object
*)strobjp
;
1554 } /* mpz_binary() */
1557 static struct methodlist mpz_methods
[] = {
1558 #ifdef MPZ_CONVERSIONS_AS_METHODS
1561 {"float", mpz_float
},
1564 #endif /* def MPZ_CONVERSIONS_AS_METHODS */
1565 {"binary", (object
*(*)(object
*, object
*))mpz_binary
},
1566 {NULL
, NULL
} /* sentinel */
1570 mpz_getattr(self
, name
)
1574 return findmethod(mpz_methods
, (object
*)self
, name
);
1575 } /* mpz_getattr() */
1586 fputs("mpz_coerce() called...\n", stderr
);
1587 #endif /* def MPZ_DEBUG */
1589 assert(is_mpzobject(*pv
));
1591 /* always convert other arg to mpz value, except for floats */
1592 if (!is_floatobject(*pw
)) {
1593 if ((z
= (object
*)mpz_mpzcoerce(*pw
)) == NULL
)
1594 return -1; /* -1: an error always has been set */
1600 if ((z
= mpz_float(*pv
, NULL
)) == NULL
)
1606 return 0; /* coercion succeeded */
1608 } /* mpz_coerce() */
1615 return mpz_format(v
, 10, (unsigned char)1);
1620 #define UF (unaryfunc)
1621 #define BF (binaryfunc)
1622 #define TF (ternaryfunc)
1623 #define IF (inquiry)
1624 #define CF (coercion)
1626 static number_methods mpz_as_number
= {
1627 BF mpz_addition
, /*nb_add*/
1628 BF mpz_substract
, /*nb_subtract*/
1629 BF mpz_multiply
, /*nb_multiply*/
1630 BF mpz_divide
, /*nb_divide*/
1631 BF mpz_remainder
, /*nb_remainder*/
1632 BF mpz_div_and_mod
, /*nb_divmod*/
1633 TF mpz_power
, /*nb_power*/
1634 UF mpz_negative
, /*nb_negative*/
1635 UF mpz_positive
, /*tp_positive*/
1636 UF mpz_absolute
, /*tp_absolute*/
1637 IF mpz_nonzero
, /*tp_nonzero*/
1638 UF mpz_invert
, /*nb_invert*/
1639 BF mpz_lshift
, /*nb_lshift*/
1640 BF mpz_rshift
, /*nb_rshift*/
1641 BF mpz_andfunc
, /*nb_and*/
1642 BF mpz_xorfunc
, /*nb_xor*/
1643 BF mpz_orfunc
, /*nb_or*/
1644 CF mpz_coerce
, /*nb_coerce*/
1645 #ifndef MPZ_CONVERSIONS_AS_METHODS
1646 UF mpz_int
, /*nb_int*/
1647 UF mpz_long
, /*nb_long*/
1648 UF mpz_float
, /*nb_float*/
1649 UF mpz_oct
, /*nb_oct*/
1650 UF mpz_hex
, /*nb_hex*/
1651 #endif /* ndef MPZ_CONVERSIONS_AS_METHODS */
1654 static typeobject MPZtype
= {
1655 OB_HEAD_INIT(&Typetype
)
1658 sizeof(mpzobject
), /*tp_size*/
1661 (destructor
)mpz_dealloc
, /*tp_dealloc*/
1663 (getattrfunc
)mpz_getattr
, /*tp_getattr*/
1665 (cmpfunc
)mpz_compare
, /*tp_compare*/
1666 (reprfunc
)mpz_repr
, /*tp_repr*/
1667 &mpz_as_number
, /*tp_as_number*/
1670 /* List of functions exported by this module */
1672 static struct methodlist mpz_functions
[] = {
1674 {initialiser_name
, MPZ_mpz
},
1676 /* until guido ``fixes'' struct methodlist */
1677 {(char *)initialiser_name
, MPZ_mpz
},
1681 {"gcdext", MPZ_gcdext
},
1683 {"sqrtrem", MPZ_sqrtrem
},
1685 {NULL
, NULL
} /* Sentinel */
1689 /* #define MP_TEST_ALLOC */
1691 #ifdef MP_TEST_ALLOC
1692 #define MP_TEST_SIZE 4
1693 static const char mp_test_magic
[MP_TEST_SIZE
] = {'\xAA','\xAA','\xAA','\xAA'};
1694 static mp_test_error( location
)
1697 /* assumptions: *alloc returns address dividable by 4,
1698 mpz_* routines allocate in chunks dividable by four */
1699 fprintf(stderr
, "MP_TEST_ERROR: location holds 0x%08d\n", *location
);
1700 fatal("MP_TEST_ERROR");
1701 } /* static mp_test_error() */
1702 #define MP_EXTRA_ALLOC(size) ((size) + MP_TEST_SIZE)
1703 #define MP_SET_TEST(basep,size) (void)memcpy( ((char *)(basep))+(size), mp_test_magic, MP_TEST_SIZE)
1704 #define MP_DO_TEST(basep,size) if ( !memcmp( ((char *)(basep))+(size), mp_test_magic, MP_TEST_SIZE ) ) \
1707 mp_test_error((int *)((char *)(basep) + size))
1708 #else /* def MP_TEST_ALLOC */
1709 #define MP_EXTRA_ALLOC(size) (size)
1710 #define MP_SET_TEST(basep,size)
1711 #define MP_DO_TEST(basep,size)
1712 #endif /* def MP_TEST_ALLOC else */
1714 void *mp_allocate( alloc_size
)
1720 fprintf(stderr
, "mp_allocate : size %ld\n",
1722 #endif /* def MPZ_DEBUG */
1724 if ( (res
= malloc(MP_EXTRA_ALLOC(alloc_size
))) == NULL
)
1725 fatal("mp_allocate failure");
1728 fprintf(stderr
, "mp_allocate : address 0x%08x\n", res
);
1729 #endif /* def MPZ_DEBUG */
1731 MP_SET_TEST(res
,alloc_size
);
1734 } /* mp_allocate() */
1737 void *mp_reallocate( ptr
, old_size
, new_size
)
1745 fprintf(stderr
, "mp_reallocate: old address 0x%08x, old size %ld\n",
1747 #endif /* def MPZ_DEBUG */
1749 MP_DO_TEST(ptr
, old_size
);
1751 if ( (res
= realloc(ptr
, MP_EXTRA_ALLOC(new_size
))) == NULL
)
1752 fatal("mp_reallocate failure");
1755 fprintf(stderr
, "mp_reallocate: new address 0x%08x, new size %ld\n",
1757 #endif /* def MPZ_DEBUG */
1759 MP_SET_TEST(res
, new_size
);
1762 } /* mp_reallocate() */
1765 void mp_free( ptr
, size
)
1771 fprintf(stderr
, "mp_free : old address 0x%08x, old size %ld\n",
1773 #endif /* def MPZ_DEBUG */
1775 MP_DO_TEST(ptr
, size
);
1781 /* Initialize this module. */
1787 fputs( "initmpz() called...\n", stderr
);
1788 #endif /* def MPZ_DEBUG */
1790 mp_set_memory_functions( mp_allocate
, mp_reallocate
, mp_free
);
1791 (void)initmodule("mpz", mpz_functions
);
1793 /* create some frequently used constants */
1794 if ((mpz_value_zero
= newmpzobject()) == NULL
)
1795 fatal("initmpz: can't initialize mpz constants");
1796 mpz_set_ui(&mpz_value_zero
->mpz
, (unsigned long int)0);
1798 if ((mpz_value_one
= newmpzobject()) == NULL
)
1799 fatal("initmpz: can't initialize mpz constants");
1800 mpz_set_ui(&mpz_value_one
->mpz
, (unsigned long int)1);
1802 if ((mpz_value_mone
= newmpzobject()) == NULL
)
1803 fatal("initmpz: can't initialize mpz constants");
1804 mpz_set_si(&mpz_value_mone
->mpz
, (long)-1);
1808 int _mpz_dummy_int
; /* XXX otherwise, we're .bss-less (DYNLOAD->Jack?) */
1809 #endif /* def MAKEDUMMYINT */