improve treatment of multi-line replies, ignore empty lines
[python/dscho.git] / Modules / mpzmodule.c
blobce31a4bc4736261a435c394d42468ac67818b28e
1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
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 ******************************************************************/
25 /* MPZ module */
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. */
34 /* MPZ objects */
36 #include "allobjects.h"
38 #include <assert.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
47 ** GMP.
48 **
49 ** MPZ_GET_STR_BUG mpz_get_str corrupts memory, seems to be fixed
50 ** in a later release
51 **
52 ** MPZ_DEBUG generates a bunch of diagnostic messages
53 **
54 ** MPZ_SPARE_MALLOC if set, results in extra code that tries to
55 ** minimize the creation of extra objects.
56 **
57 ** MPZ_TEST_DIV extra diagnostic output on stderr, when division
58 ** routines are involved
59 **
60 ** MPZ_LIB_DOES_CHECKING if set, assumes that mpz library doesn't call
61 ** alloca with arg < 0 (when casted to a signed
62 ** integral type).
63 **
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'
69 **
70 ** MP_TEST_ALLOC If set, you would discover why MPZ_GET_STR_BUG
71 ** is needed
72 **
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
88 #include "gmp.h"
89 typedef struct {
90 OB_HEAD
91 MP_INT mpz; /* the actual number */
92 } mpzobject;
94 staticforward typeobject MPZtype;
96 #define is_mpzobject(v) ((v)->ob_type == &MPZtype)
98 static const char initialiser_name[] = "mpz";
100 /* #define MPZ_DEBUG */
102 static mpzobject *
103 newmpzobject()
105 mpzobject *mpzp;
108 #ifdef MPZ_DEBUG
109 fputs( "mpz_object() called...\n", stderr );
110 #endif /* def MPZ_DEBUG */
111 mpzp = NEWOBJ(mpzobject, &MPZtype);
112 if (mpzp == NULL)
113 return NULL;
115 mpz_init(&mpzp->mpz); /* actual initialisation */
116 return mpzp;
117 } /* newmpzobject() */
119 #ifdef MPZ_GET_STR_BUG
120 #include "gmp-impl.h"
121 #include "longlong.h"
122 #endif /* def MPZ_GET_STR_BUG */
124 static object *
125 mpz_format(objp, base, withname)
126 object *objp;
127 int base;
128 unsigned char withname;
130 mpzobject *mpzp = (mpzobject *)objp;
131 stringobject *strobjp;
132 int i;
133 int cmpres;
134 int taglong;
135 char *cp;
136 char prefix[5], *tcp;
139 tcp = &prefix[0];
141 if (mpzp == NULL || !is_mpzobject(mpzp)) {
142 err_badcall();
143 return NULL;
146 assert(base >= 2 && base <= 36);
148 if (withname)
149 i = strlen(initialiser_name) + 2; /* e.g. 'mpz(' + ')' */
150 else
151 i = 0;
153 if ((cmpres = mpz_cmp_si(&mpzp->mpz, 0L)) == 0)
154 base = 10; /* '0' in every base, right */
155 else if (cmpres < 0) {
156 *tcp++ = '-';
157 i += 1; /* space to hold '-' */
160 #ifdef MPZ_DEBUG
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 */
171 if (base == 16) {
172 *tcp++ = '0';
173 *tcp++ = 'x';
174 i += 2; /* space to hold '0x' */
176 else if (base == 8) {
177 *tcp++ = '0';
178 i += 1; /* space to hold the extra '0' */
180 else if (base > 10) {
181 *tcp++ = '0' + base / 10;
182 *tcp++ = '0' + base % 10;
183 *tcp++ = '#';
184 i += 3; /* space to hold e.g. '12#' */
186 else if (base < 10) {
187 *tcp++ = '0' + base;
188 *tcp++ = '#';
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
196 taglong = 0;
197 if (mpz_size(&mpzp->mpz) > 1
198 || (long)mpz_get_ui(&mpzp->mpz) < 0L) {
199 taglong = 1;
200 i += 1; /* space to hold 'L' */
203 #ifdef MPZ_DEBUG
204 fprintf(stderr, "mpz_format: requesting string size %d\n", i);
205 #endif /* def MPZ_DEBUG */
206 if ((strobjp = (stringobject *)newsizedstringobject((char *)0, i))
207 == NULL)
208 return NULL;
210 /* get the beginning of the string memory and start copying things */
211 cp = GETSTRINGVALUE(strobjp);
212 if (withname) {
213 strcpy(cp, initialiser_name);
214 cp += strlen(initialiser_name);
215 *cp++ = '('; /*')'*/
218 /* copy the already prepared prefix; e.g. sign and base indicator */
219 *tcp = '\0';
220 strcpy(cp, prefix);
221 cp += tcp - prefix;
223 /* since' we have the sign already, let the lib think it's a positive
224 number */
225 if (cmpres < 0)
226 mpz_neg(&mpzp->mpz,&mpzp->mpz); /* hack Hack HAck HACk HACK */
227 (void)mpz_get_str(cp, base, &mpzp->mpz);
228 if (cmpres < 0)
229 mpz_neg(&mpzp->mpz,&mpzp->mpz); /* hack Hack HAck HACk HACK */
230 #ifdef MPZ_DEBUG
231 fprintf(stderr, "mpz_format: base (ultim) %d, mpz_get_str: %s\n",
232 base, cp);
233 #endif /* def MPZ_DEBUG */
234 cp += strlen(cp);
236 if (taglong)
237 *cp++ = 'L';
238 if (withname)
239 *cp++ = /*'('*/ ')';
241 *cp = '\0';
243 #ifdef MPZ_DEBUG
244 fprintf(stderr,
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;
255 } /* mpz_format() */
257 /* MPZ methods */
259 static void
260 mpz_dealloc(mpzp)
261 mpzobject *mpzp;
263 #ifdef MPZ_DEBUG
264 fputs( "mpz_dealloc() called...\n", stderr );
265 #endif /* def MPZ_DEBUG */
266 mpz_clear(&mpzp->mpz);
267 DEL(mpzp);
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;
274 static int
275 mpz_compare(a, b)
276 mpzobject *a, *b;
278 int cmpres;
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() */
286 static object *
287 mpz_addition(a, b)
288 mpzobject *a;
289 mpzobject *b;
291 mpzobject *z;
294 #ifdef MPZ_SPARE_MALLOC
295 if (mpz_cmp_ui(&a->mpz, (unsigned long int)0) == 0) {
296 INCREF(b);
297 return (object *)b;
300 if (mpz_cmp_ui(&b->mpz, (unsigned long int)0) == 0) {
301 INCREF(a);
302 return (object *)a;
304 #endif /* def MPZ_SPARE_MALLOC */
306 if ((z = newmpzobject()) == NULL)
307 return NULL;
309 mpz_add(&z->mpz, &a->mpz, &b->mpz);
310 return (object *)z;
311 } /* mpz_addition() */
313 static object *
314 mpz_substract(a, b)
315 mpzobject *a;
316 mpzobject *b;
318 mpzobject *z;
321 #ifdef MPZ_SPARE_MALLOC
322 if (mpz_cmp_ui(&b->mpz, (unsigned long int)0) == 0) {
323 INCREF(a);
324 return (object *)a;
326 #endif /* MPZ_SPARE_MALLOC */
328 if ((z = newmpzobject()) == NULL)
329 return NULL;
331 mpz_sub(&z->mpz, &a->mpz, &b->mpz);
332 return (object *)z;
333 } /* mpz_substract() */
335 static object *
336 mpz_multiply(a, b)
337 mpzobject *a;
338 mpzobject *b;
340 #ifdef MPZ_SPARE_MALLOC
341 int cmpres;
342 #endif /* def MPZ_SPARE_MALLOC */
343 mpzobject *z;
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) {
352 INCREF(b);
353 return (object *)b;
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) {
361 INCREF(a);
362 return (object *)a;
364 #endif /* MPZ_SPARE_MALLOC */
366 if ((z = newmpzobject()) == NULL)
367 return NULL;
369 mpz_mul( &z->mpz, &a->mpz, &b->mpz );
370 return (object *)z;
372 } /* mpz_multiply() */
374 static object *
375 mpz_divide(a, b)
376 mpzobject *a;
377 mpzobject *b;
379 #ifdef MPZ_SPARE_MALLOC
380 int cmpres;
381 #endif /* def MPZ_SPARE_MALLOC */
382 mpzobject *z;
385 if ((
386 #ifdef MPZ_SPARE_MALLOC
387 cmpres =
388 #endif /* def MPZ_SPARE_MALLOC */
389 mpz_cmp_ui(&b->mpz, (unsigned long int)0)) == 0) {
390 err_setstr(ZeroDivisionError, "mpz./ by zero");
391 return NULL;
393 #ifdef MPZ_SPARE_MALLOC
394 if (cmpres > 0 && mpz_cmp_ui(&b->mpz(unsigned long int)1) == 0) {
395 INCREF(a);
396 return (object *)a;
398 #endif /* def MPZ_SPARE_MALLOC */
400 if ((z = newmpzobject()) == NULL)
401 return NULL;
403 #ifdef MPZ_TEST_DIV
404 fputs("mpz_divide: div result", stderr);
405 mpz_div(&z->mpz, &a->mpz, &b->mpz);
406 mpz_out_str(stderr, 10, &z->mpz);
407 putc('\n', stderr);
408 #endif /* def MPZ_TEST_DIV */
409 #ifdef MPZ_MDIV_BUG
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
417 MP_INT tmpmpz;
420 mpz_init(&tmpmpz);
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);
426 mpz_clear(&tmpmpz);
428 else
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 */
436 #ifdef MPZ_TEST_DIV
437 fputs("mpz_divide: mdiv result", stderr);
438 mpz_out_str(stderr, 10, &z->mpz);
439 putc('\n', stderr);
440 #endif /* def MPZ_TEST_DIV */
441 return (object *)z;
443 } /* mpz_divide() */
445 static object *
446 mpz_remainder(a, b)
447 mpzobject *a;
448 mpzobject *b;
450 #ifdef MPZ_SPARE_MALLOC
451 int cmpres;
452 #endif /* def MPZ_SPARE_MALLOC */
453 mpzobject *z;
456 if ((
457 #ifdef MPZ_SPARE_MALLOC
458 cmpres =
459 #endif /* def MPZ_SPARE_MALLOC */
460 mpz_cmp_ui(&b->mpz, (unsigned long int)0)) == 0) {
461 err_setstr(ZeroDivisionError, "mpz.% by zero");
462 return NULL;
464 #ifdef MPZ_SPARE_MALLOC
465 if (cmpres > 0) {
466 if ((cmpres = mpz_cmp_ui(&b->mpz, (unsigned long int)2)) == 0) {
467 INCREF(mpz_value_one);
468 return (object *)mpz_value_one;
470 if (cmpres < 0) {
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)
479 return NULL;
481 #ifdef MPZ_TEST_DIV
482 fputs("mpz_remain: mod result", stderr);
483 mpz_mod(&z->mpz, &a->mpz, &b->mpz);
484 mpz_out_str(stderr, 10, &z->mpz);
485 putc('\n', stderr);
486 #endif /* def MPZ_TEST_DIV */
487 #ifdef MPZ_MDIV_BUG
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 */
506 #ifdef MPZ_TEST_DIV
507 fputs("mpz_remain: mmod result", stderr);
508 mpz_out_str(stderr, 10, &z->mpz);
509 putc('\n', stderr);
510 #endif /* def MPZ_TEST_DIV */
511 return (object *)z;
513 } /* mpz_remainder() */
515 static object *
516 mpz_div_and_mod(a, b)
517 mpzobject *a;
518 mpzobject *b;
520 object *z = NULL;
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");
526 return NULL;
529 if ((z = newtupleobject(2)) == NULL
530 || (x = newmpzobject()) == NULL
531 || (y = newmpzobject()) == NULL) {
532 XDECREF(z);
533 XDECREF(x);
534 XDECREF(y);
535 return NULL;
538 #ifdef MPZ_TEST_DIV
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);
542 putc('\n', stderr);
543 mpz_out_str(stderr, 10, &y->mpz);
544 putc('\n', stderr);
545 #endif /* def MPZ_TEST_DIV */
546 #ifdef MPZ_MDIV_BUG
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 */
561 #ifdef MPZ_TEST_DIV
562 fputs("mpz_divmod: mdm result", stderr);
563 mpz_out_str(stderr, 10, &x->mpz);
564 putc('\n', stderr);
565 mpz_out_str(stderr, 10, &y->mpz);
566 putc('\n', stderr);
567 #endif /* def MPZ_TEST_DIV */
569 (void)settupleitem(z, 0, (object *)x);
570 (void)settupleitem(z, 1, (object *)y);
572 return z;
573 } /* mpz_div_and_mod() */
575 static object *
576 mpz_power(a, b, m)
577 mpzobject *a;
578 mpzobject *b;
579 mpzobject *m;
581 mpzobject *z;
582 int cmpres;
583 long int longtmp1, longtmp2;
585 if ((object *)m!=Py_None)
587 mpzobject *z2;
588 INCREF(Py_None);
589 z=mpz_power(a, b, (mpzobject *)Py_None);
590 DECREF(Py_None);
591 if (z==NULL) return(z);
592 z2=mpz_remainder(z, m);
593 DECREF(z);
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;
604 if (cmpres < 0) {
605 err_setstr(ValueError, "mpz.pow to negative exponent");
606 return NULL;
609 if ((cmpres = mpz_cmp_ui(&a->mpz, (unsigned long int)0)) == 0) {
610 /* the base is 0 */
612 INCREF(mpz_value_zero);
613 return (object *)mpz_value_zero;
615 else if (cmpres > 0
616 && mpz_cmp_ui(&a->mpz, (unsigned long int)1) == 0) {
617 /* the base is 1 */
619 INCREF(mpz_value_one);
620 return (object *)mpz_value_one;
622 else if (cmpres < 0
623 && mpz_cmp_si(&a->mpz, (long int)-1) == 0) {
625 MP_INT tmpmpz;
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? */
632 mpz_init(&tmpmpz);
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) {
638 mpz_clear(&tmpmpz);
639 INCREF(mpz_value_one);
640 return (object *)mpz_value_one;
642 mpz_clear(&tmpmpz);
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");
656 return NULL;
658 #endif /* def MPZ_LIB_DOES_CHECKING else */
660 if ((z = newmpzobject()) == NULL)
661 return NULL;
663 mpz_pow_ui(&z->mpz, &a->mpz, mpz_get_ui(&b->mpz));
665 return (object *)z;
666 } /* mpz_power() */
669 static object *
670 mpz_negative(v)
671 mpzobject *v;
673 mpzobject *z;
676 #ifdef MPZ_SPARE_MALLOC
677 if (mpz_cmp_ui(&v->mpz, (unsigned long int)0) == 0) {
678 /* -0 == 0 */
679 INCREF(v);
680 return (object *)v;
682 #endif /* def MPZ_SPARE_MALLOC */
684 if ((z = newmpzobject()) == NULL)
685 return NULL;
687 mpz_neg(&z->mpz, &v->mpz);
688 return (object *)z;
689 } /* mpz_negative() */
692 static object *
693 mpz_positive(v)
694 mpzobject *v;
696 INCREF(v);
697 return (object *)v;
698 } /* mpz_positive() */
701 static object *
702 mpz_absolute(v)
703 mpzobject *v;
705 mpzobject *z;
708 if (mpz_cmp_ui(&v->mpz, (unsigned long int)0) >= 0) {
709 INCREF(v);
710 return (object *)v;
713 if ((z = newmpzobject()) == NULL)
714 return NULL;
716 mpz_neg(&z->mpz, &v->mpz);
717 return (object *)z;
718 } /* mpz_absolute() */
720 static int
721 mpz_nonzero(v)
722 mpzobject *v;
724 return mpz_cmp_ui(&v->mpz, (unsigned long int)0) != 0;
725 } /* mpz_nonzero() */
727 static object *
728 mpz_invert(v)
729 mpzobject *v;
731 mpzobject *z;
734 /* I think mpz_com does exactly what needed */
735 if ((z = newmpzobject()) == NULL)
736 return NULL;
738 mpz_com(&z->mpz, &v->mpz);
739 return (object *)z;
740 } /* mpz_invert() */
742 static object *
743 mpz_lshift(a, b)
744 mpzobject *a;
745 mpzobject *b;
747 int cmpres;
748 mpzobject *z;
751 if ((cmpres = mpz_cmp_ui(&b->mpz, (unsigned long int)0)) == 0) {
752 /* a << 0 == a */
753 INCREF(a);
754 return (object *)a;
757 if (cmpres < 0) {
758 err_setstr(ValueError, "mpz.<< negative shift count");
759 return NULL;
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");
769 return NULL;
771 #endif /* def MPZ_LIB_DOES_CHECKING else */
773 if ((z = newmpzobject()) == NULL)
774 return NULL;
776 mpz_mul_2exp(&z->mpz, &a->mpz, mpz_get_ui(&b->mpz));
777 return (object *)z;
778 } /* mpz_lshift() */
780 static object *
781 mpz_rshift(a, b)
782 mpzobject *a;
783 mpzobject *b;
785 int cmpres;
786 mpzobject *z;
789 if ((cmpres = mpz_cmp_ui(&b->mpz, (unsigned long int)0)) == 0) {
790 /* a >> 0 == a */
791 INCREF(a);
792 return (object *)a;
795 if (cmpres < 0) {
796 err_setstr(ValueError, "mpz.>> negative shift count");
797 return NULL;
800 if (mpz_size(&b->mpz) > 1)
801 return (object *)err_nomem();
803 if ((z = newmpzobject()) == NULL)
804 return NULL;
806 mpz_div_2exp(&z->mpz, &a->mpz, mpz_get_ui(&b->mpz));
807 return (object *)z;
808 } /* mpz_rshift() */
810 static object *
811 mpz_andfunc(a, b)
812 mpzobject *a;
813 mpzobject *b;
815 mpzobject *z;
818 if ((z = newmpzobject()) == NULL)
819 return NULL;
821 mpz_and(&z->mpz, &a->mpz, &b->mpz);
822 return (object *)z;
823 } /* mpz_andfunc() */
825 /* hack Hack HAck HACk HACK, XXX this code is dead slow */
826 void
827 mpz_xor(res, op1, op2)
828 MP_INT *res;
829 const MP_INT *op1;
830 const MP_INT *op2;
832 MP_INT tmpmpz;
834 mpz_init(&tmpmpz);
836 mpz_and(res, op1, op2);
837 mpz_com(&tmpmpz, res);
838 mpz_ior(res, op1, op2);
839 mpz_and(res, res, &tmpmpz);
841 mpz_clear(&tmpmpz);
842 } /* mpz_xor() HACK */
844 static object *
845 mpz_xorfunc(a, b)
846 mpzobject *a;
847 mpzobject *b;
849 mpzobject *z;
852 if ((z = newmpzobject()) == NULL)
853 return NULL;
855 mpz_xor(&z->mpz, &a->mpz, &b->mpz);
856 return (object *)z;
857 } /* mpz_xorfunc() */
859 static object *
860 mpz_orfunc(a, b)
861 mpzobject *a;
862 mpzobject *b;
864 mpzobject *z;
867 if ((z = newmpzobject()) == NULL)
868 return NULL;
870 mpz_ior(&z->mpz, &a->mpz, &b->mpz);
871 return (object *)z;
872 } /* mpz_orfunc() */
874 /* MPZ initialisation */
876 #include "longintrepr.h"
878 static object *
879 MPZ_mpz(self, args)
880 object *self;
881 object *args;
883 mpzobject *mpzp;
884 object *objp;
887 #ifdef MPZ_DEBUG
888 fputs("MPZ_mpz() called...\n", stderr);
889 #endif /* def MPZ_DEBUG */
891 if (!getargs(args, "O", &objp))
892 return NULL;
894 /* at least we know it's some object */
895 /* note DON't DECREF args NEITHER objp */
897 if (is_intobject(objp)) {
898 long lval;
900 if (!getargs(objp, "l", &lval))
901 return NULL;
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)
912 return NULL;
913 else mpz_set_si(&mpzp->mpz, lval);
915 else if (is_longobject(objp)) {
916 MP_INT mplongdigit;
917 int i;
918 unsigned char isnegative;
921 if ((mpzp = newmpzobject()) == NULL)
922 return 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) )
929 i = -i;
931 while (i--) {
932 mpz_set_ui(&mplongdigit,
933 (unsigned long)
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);
940 if (isnegative)
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)) {
947 char *cp;
948 int len;
949 MP_INT mplongdigit;
951 if (!getargs(objp, "s#", &cp, &len))
952 return NULL;
954 if ((mpzp = newmpzobject()) == NULL)
955 return 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 (-: :-) */
963 cp += len;
964 while (len--) {
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)) {
975 INCREF(objp);
976 mpzp = (mpzobject *)objp;
978 else {
979 err_setstr(TypeError,
980 "mpz.mpz() expects integer, long, string or mpz object argument");
981 return NULL;
985 #ifdef MPZ_DEBUG
986 fputs("MPZ_mpz: created mpz=", stderr);
987 mpz_out_str(stderr, 10, &mpzp->mpz);
988 putc('\n', stderr);
989 #endif /* def MPZ_DEBUG */
990 return (object *)mpzp;
991 } /* MPZ_mpz() */
993 static mpzobject *
994 mpz_mpzcoerce(z)
995 object *z;
997 /* shortcut: 9 out of 10 times the type is already ok */
998 if (is_mpzobject(z)) {
999 INCREF(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");
1008 return NULL;
1009 } /* mpz_mpzcoerce() */
1011 /* Forward */
1012 static void mpz_divm PROTO((MP_INT *res, const MP_INT *num,
1013 const MP_INT *den, const MP_INT *mod));
1015 static object *
1016 MPZ_powm(self, args)
1017 object *self;
1018 object *args;
1020 object *base, *exp, *mod;
1021 mpzobject *mpzbase = NULL, *mpzexp = NULL, *mpzmod = NULL;
1022 mpzobject *z;
1023 int tstres;
1026 if (!getargs(args, "(OOO)", &base, &exp, &mod))
1027 return NULL;
1029 if ((mpzbase = mpz_mpzcoerce(base)) == NULL
1030 || (mpzexp = mpz_mpzcoerce(exp)) == NULL
1031 || (mpzmod = mpz_mpzcoerce(mod)) == NULL
1032 || (z = newmpzobject()) == NULL) {
1033 XDECREF(mpzbase);
1034 XDECREF(mpzexp);
1035 XDECREF(mpzmod);
1036 return 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;
1044 if (tstres < 0) {
1045 MP_INT absexp;
1046 /* negative exp */
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);
1054 mpz_clear(&absexp);
1056 else {
1057 mpz_powm(&z->mpz, &mpzbase->mpz, &mpzexp->mpz, &mpzmod->mpz);
1060 DECREF(mpzbase);
1061 DECREF(mpzexp);
1062 DECREF(mpzmod);
1064 return (object *)z;
1065 } /* MPZ_powm() */
1068 static object *
1069 MPZ_gcd(self, args)
1070 object *self;
1071 object *args;
1073 object *op1, *op2;
1074 mpzobject *mpzop1 = NULL, *mpzop2 = NULL;
1075 mpzobject *z;
1078 if (!getargs(args, "(OO)", &op1, &op2))
1079 return NULL;
1081 if ((mpzop1 = mpz_mpzcoerce(op1)) == NULL
1082 || (mpzop2 = mpz_mpzcoerce(op2)) == NULL
1083 || (z = newmpzobject()) == NULL) {
1084 XDECREF(mpzop1);
1085 XDECREF(mpzop2);
1086 return NULL;
1089 /* ok, we have three mpzobjects, and an initialised result holder */
1090 mpz_gcd(&z->mpz, &mpzop1->mpz, &mpzop2->mpz);
1092 DECREF(mpzop1);
1093 DECREF(mpzop2);
1095 return (object *)z;
1096 } /* MPZ_gcd() */
1099 static object *
1100 MPZ_gcdext(self, args)
1101 object *self;
1102 object *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))
1110 return NULL;
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) {
1118 XDECREF(mpzop1);
1119 XDECREF(mpzop2);
1120 XDECREF(z);
1121 XDECREF(g);
1122 XDECREF(s);
1123 /*XDECREF(t);*/
1124 return NULL;
1127 mpz_gcdext(&g->mpz, &s->mpz, &t->mpz, &mpzop1->mpz, &mpzop2->mpz);
1129 DECREF(mpzop1);
1130 DECREF(mpzop2);
1132 (void)settupleitem(z, 0, (object *)g);
1133 (void)settupleitem(z, 1, (object *)s);
1134 (void)settupleitem(z, 2, (object *)t);
1136 return (object *)z;
1137 } /* MPZ_gcdext() */
1140 static object *
1141 MPZ_sqrt(self, args)
1142 object *self;
1143 object *args;
1145 object *op;
1146 mpzobject *mpzop = NULL;
1147 mpzobject *z;
1150 if (!getargs(args, "O", &op))
1151 return NULL;
1153 if ((mpzop = mpz_mpzcoerce(op)) == NULL
1154 || (z = newmpzobject()) == NULL) {
1155 XDECREF(mpzop);
1156 return NULL;
1159 mpz_sqrt(&z->mpz, &mpzop->mpz);
1161 DECREF(mpzop);
1163 return (object *)z;
1164 } /* MPZ_sqrt() */
1167 static object *
1168 MPZ_sqrtrem(self, args)
1169 object *self;
1170 object *args;
1172 object *op, *z = NULL;
1173 mpzobject *mpzop = NULL;
1174 mpzobject *root = NULL, *rem = NULL;
1177 if (!getargs(args, "O", &op))
1178 return NULL;
1180 if ((mpzop = mpz_mpzcoerce(op)) == NULL
1181 || (z = newtupleobject(2)) == NULL
1182 || (root = newmpzobject()) == NULL
1183 || (rem = newmpzobject()) == NULL) {
1184 XDECREF(mpzop);
1185 XDECREF(z);
1186 XDECREF(root);
1187 /*XDECREF(rem);*/
1188 return NULL;
1191 mpz_sqrtrem(&root->mpz, &rem->mpz, &mpzop->mpz);
1193 DECREF(mpzop);
1195 (void)settupleitem(z, 0, (object *)root);
1196 (void)settupleitem(z, 1, (object *)rem);
1198 return (object *)z;
1199 } /* MPZ_sqrtrem() */
1202 static void
1203 #if __STDC__
1204 mpz_divm(MP_INT *res, const MP_INT *num, const MP_INT *den, const MP_INT *mod)
1205 #else
1206 mpz_divm(res, num, den, mod)
1207 MP_INT *res;
1208 const MP_INT *num;
1209 const MP_INT *den;
1210 const MP_INT *mod;
1211 #endif
1213 MP_INT s0, s1, q, r, x, d0, d1;
1215 mpz_init_set(&s0, num);
1216 mpz_init_set_ui(&s1, 0);
1217 mpz_init(&q);
1218 mpz_init(&r);
1219 mpz_init(&x);
1220 mpz_init_set(&d0, den);
1221 mpz_init_set(&d1, mod);
1223 while (d1.size != 0) {
1224 mpz_divmod(&q, &r, &d0, &d1);
1225 mpz_set(&d0, &d1);
1226 mpz_set(&d1, &r);
1228 mpz_mul(&x, &s1, &q);
1229 mpz_sub(&x, &s0, &x);
1230 mpz_set(&s0, &s1);
1231 mpz_set(&s1, &x);
1234 if (d0.size != 1 || d0.d[0] != 1)
1235 res->size = 0; /* trouble: the gcd != 1; set s to zero */
1236 else {
1237 #ifdef MPZ_MDIV_BUG
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);
1243 if (res->size)
1244 mpz_add(res, res, mod);
1246 else
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 */
1254 mpz_clear(&s0);
1255 mpz_clear(&s1);
1256 mpz_clear(&q);
1257 mpz_clear(&r);
1258 mpz_clear(&x);
1259 mpz_clear(&d0);
1260 mpz_clear(&d1);
1261 } /* mpz_divm() */
1264 static object *
1265 MPZ_divm(self, args)
1266 object *self;
1267 object *args;
1269 object *num, *den, *mod;
1270 mpzobject *mpznum, *mpzden, *mpzmod = NULL;
1271 mpzobject *z = NULL;
1274 if (!getargs(args, "(OOO)", &num, &den, &mod))
1275 return NULL;
1277 if ((mpznum = mpz_mpzcoerce(num)) == NULL
1278 || (mpzden = mpz_mpzcoerce(den)) == NULL
1279 || (mpzmod = mpz_mpzcoerce(mod)) == NULL
1280 || (z = newmpzobject()) == NULL ) {
1281 XDECREF(mpznum);
1282 XDECREF(mpzden);
1283 XDECREF(mpzmod);
1284 return NULL;
1287 mpz_divm(&z->mpz, &mpznum->mpz, &mpzden->mpz, &mpzmod->mpz);
1289 DECREF(mpznum);
1290 DECREF(mpzden);
1291 DECREF(mpzmod);
1293 if (mpz_cmp_ui(&z->mpz, (unsigned long int)0) == 0) {
1294 DECREF(z);
1295 err_setstr(ValueError, "gcd(den, mod) != 1 or num == 0");
1296 return NULL;
1299 return (object *)z;
1300 } /* MPZ_divm() */
1303 /* MPZ methods-as-attributes */
1304 #ifdef MPZ_CONVERSIONS_AS_METHODS
1305 static object *
1306 mpz_int(self, args)
1307 mpzobject *self;
1308 object *args;
1309 #else /* def MPZ_CONVERSIONS_AS_METHODS */
1310 static object *
1311 mpz_int(self)
1312 mpzobject *self;
1313 #endif /* def MPZ_CONVERSIONS_AS_METHODS else */
1315 long sli;
1318 #ifdef MPZ_CONVERSIONS_AS_METHODS
1319 if (!getnoarg(args))
1320 return NULL;
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");
1326 return NULL;
1329 if (mpz_cmp_ui(&self->mpz, (unsigned long)0) < 0)
1330 sli = -sli;
1332 return newintobject(sli);
1333 } /* mpz_int() */
1335 static object *
1336 #ifdef MPZ_CONVERSIONS_AS_METHODS
1337 mpz_long(self, args)
1338 mpzobject *self;
1339 object *args;
1340 #else /* def MPZ_CONVERSIONS_AS_METHODS */
1341 mpz_long(self)
1342 mpzobject *self;
1343 #endif /* def MPZ_CONVERSIONS_AS_METHODS else */
1345 int i, isnegative;
1346 unsigned long int uli;
1347 longobject *longobjp;
1348 int ldcount;
1349 int bitpointer, newbitpointer;
1350 MP_INT mpzscratch;
1353 #ifdef MPZ_CONVERSIONS_AS_METHODS
1354 if (!getnoarg(args))
1355 return NULL;
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
1361 + SHIFT - 1) /
1362 SHIFT))) == NULL)
1363 return NULL;
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 */
1374 newbitpointer = 0;
1375 ldcount = 0; /* the python-long limb counter */
1376 uli = (unsigned long int)0;
1377 while (i--) {
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,
1388 BITS_PER_MP_LIMB);
1390 else
1391 uli >>= SHIFT;
1392 bitpointer -= SHIFT;
1393 ldcount++;
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)
1403 ldcount--;
1404 longobjp->ob_size = ldcount;
1407 if (isnegative)
1408 longobjp->ob_size = -longobjp->ob_size;
1410 return (object *)longobjp;
1412 } /* mpz_long() */
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
1419 static object *
1420 mpz_float(self, args)
1421 mpzobject *self;
1422 object *args;
1423 #else /* def MPZ_CONVERSIONS_AS_METHODS */
1424 static object *
1425 mpz_float(self)
1426 mpzobject *self;
1427 #endif /* def MPZ_CONVERSIONS_AS_METHODS else */
1429 int i, isnegative;
1430 double x;
1431 double mulstate;
1432 MP_INT mpzscratch;
1435 #ifdef MPZ_CONVERSIONS_AS_METHODS
1436 if (!getnoarg(args))
1437 return NULL;
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);
1447 else
1448 mpz_init_set(&mpzscratch, &self->mpz);
1450 /* let those bits come, let those bits go,
1451 e.g. dismantle mpzscratch, build floatobject */
1453 x = 0.0;
1454 mulstate = 1.0;
1455 while (i--) {
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);
1464 if (isnegative)
1465 x = -x;
1467 return newfloatobject(x);
1469 } /* mpz_float() */
1471 #ifdef MPZ_CONVERSIONS_AS_METHODS
1472 static object *
1473 mpz_hex(self, args)
1474 mpzobject *self;
1475 object *args;
1476 #else /* def MPZ_CONVERSIONS_AS_METHODS */
1477 static object *
1478 mpz_hex(self)
1479 mpzobject *self;
1480 #endif /* def MPZ_CONVERSIONS_AS_METHODS else */
1482 #ifdef MPZ_CONVERSIONS_AS_METHODS
1483 if (!getnoarg(args))
1484 return NULL;
1485 #endif /* def MPZ_CONVERSIONS_AS_METHODS */
1487 return mpz_format(self, 16, (unsigned char)1);
1488 } /* mpz_hex() */
1490 #ifdef MPZ_CONVERSIONS_AS_METHODS
1491 static object *
1492 mpz_oct(self, args)
1493 mpzobject *self;
1494 object *args;
1495 #else /* def MPZ_CONVERSIONS_AS_METHODS */
1496 static object *
1497 mpz_oct(self)
1498 mpzobject *self;
1499 #endif /* def MPZ_CONVERSIONS_AS_METHODS else */
1501 #ifdef MPZ_CONVERSIONS_AS_METHODS
1502 if (!getnoarg(args))
1503 return NULL;
1504 #endif /* def MPZ_CONVERSIONS_AS_METHODS */
1506 return mpz_format(self, 8, (unsigned char)1);
1507 } /* mpz_oct() */
1509 static object *
1510 mpz_binary(self, args)
1511 mpzobject *self;
1512 object *args;
1514 int size;
1515 stringobject *strobjp;
1516 char *cp;
1517 MP_INT mp;
1518 unsigned long ldigit;
1520 if (!getnoarg(args))
1521 return NULL;
1523 if (mpz_cmp_ui(&self->mpz, (unsigned long int)0) < 0) {
1524 err_setstr(ValueError, "mpz.binary() arg must be >= 0");
1525 return NULL;
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)
1534 return 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 */
1541 while (size--) {
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)
1551 strobjp->ob_size--;
1553 return (object *)strobjp;
1554 } /* mpz_binary() */
1557 static struct methodlist mpz_methods[] = {
1558 #ifdef MPZ_CONVERSIONS_AS_METHODS
1559 {"int", mpz_int},
1560 {"long", mpz_long},
1561 {"float", mpz_float},
1562 {"hex", mpz_hex},
1563 {"oct", mpz_oct},
1564 #endif /* def MPZ_CONVERSIONS_AS_METHODS */
1565 {"binary", (object *(*)(object *, object *))mpz_binary},
1566 {NULL, NULL} /* sentinel */
1569 static object *
1570 mpz_getattr(self, name)
1571 mpzobject *self;
1572 char *name;
1574 return findmethod(mpz_methods, (object *)self, name);
1575 } /* mpz_getattr() */
1578 static int
1579 mpz_coerce(pv, pw)
1580 object **pv;
1581 object **pw;
1583 object *z;
1585 #ifdef MPZ_DEBUG
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 */
1596 INCREF(*pv);
1597 *pw = z;
1599 else {
1600 if ((z = mpz_float(*pv, NULL)) == NULL)
1601 return -1;
1603 INCREF(*pw);
1604 *pv = z;
1606 return 0; /* coercion succeeded */
1608 } /* mpz_coerce() */
1611 static object *
1612 mpz_repr(v)
1613 object *v;
1615 return mpz_format(v, 10, (unsigned char)1);
1616 } /* mpz_repr() */
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)
1656 0, /*ob_size*/
1657 "mpz", /*tp_name*/
1658 sizeof(mpzobject), /*tp_size*/
1659 0, /*tp_itemsize*/
1660 /* methods */
1661 (destructor)mpz_dealloc, /*tp_dealloc*/
1662 0, /*tp_print*/
1663 (getattrfunc)mpz_getattr, /*tp_getattr*/
1664 0, /*tp_setattr*/
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[] = {
1673 #if 0
1674 {initialiser_name, MPZ_mpz},
1675 #else /* 0 */
1676 /* until guido ``fixes'' struct methodlist */
1677 {(char *)initialiser_name, MPZ_mpz},
1678 #endif /* 0 else */
1679 {"powm", MPZ_powm},
1680 {"gcd", MPZ_gcd},
1681 {"gcdext", MPZ_gcdext},
1682 {"sqrt", MPZ_sqrt},
1683 {"sqrtrem", MPZ_sqrtrem},
1684 {"divm", MPZ_divm},
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 )
1695 int *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 ) ) \
1706 else \
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 )
1715 size_t alloc_size;
1717 void *res;
1719 #ifdef MPZ_DEBUG
1720 fprintf(stderr, "mp_allocate : size %ld\n",
1721 alloc_size);
1722 #endif /* def MPZ_DEBUG */
1724 if ( (res = malloc(MP_EXTRA_ALLOC(alloc_size))) == NULL )
1725 fatal("mp_allocate failure");
1727 #ifdef MPZ_DEBUG
1728 fprintf(stderr, "mp_allocate : address 0x%08x\n", res);
1729 #endif /* def MPZ_DEBUG */
1731 MP_SET_TEST(res,alloc_size);
1733 return res;
1734 } /* mp_allocate() */
1737 void *mp_reallocate( ptr, old_size, new_size )
1738 void *ptr;
1739 size_t old_size;
1740 size_t new_size;
1742 void *res;
1744 #ifdef MPZ_DEBUG
1745 fprintf(stderr, "mp_reallocate: old address 0x%08x, old size %ld\n",
1746 ptr, old_size);
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");
1754 #ifdef MPZ_DEBUG
1755 fprintf(stderr, "mp_reallocate: new address 0x%08x, new size %ld\n",
1756 res, new_size);
1757 #endif /* def MPZ_DEBUG */
1759 MP_SET_TEST(res, new_size);
1761 return res;
1762 } /* mp_reallocate() */
1765 void mp_free( ptr, size )
1766 void *ptr;
1767 size_t size;
1770 #ifdef MPZ_DEBUG
1771 fprintf(stderr, "mp_free : old address 0x%08x, old size %ld\n",
1772 ptr, size);
1773 #endif /* def MPZ_DEBUG */
1775 MP_DO_TEST(ptr, size);
1776 free(ptr);
1777 } /* mp_free() */
1781 /* Initialize this module. */
1783 void
1784 initmpz()
1786 #ifdef MPZ_DEBUG
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);
1806 } /* initmpz() */
1807 #ifdef MAKEDUMMYINT
1808 int _mpz_dummy_int; /* XXX otherwise, we're .bss-less (DYNLOAD->Jack?) */
1809 #endif /* def MAKEDUMMYINT */