blob: 0067397452004749dd02927a92b42b6650615495 [file] [log] [blame]
Guido van Rossum5f59d601992-12-14 16:59:51 +00001/***********************************************************
Guido van Rossumb6775db1994-08-01 11:34:53 +00002Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
3Amsterdam, The Netherlands.
Guido van Rossum5f59d601992-12-14 16:59:51 +00004
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
Guido van Rossumb6775db1994-08-01 11:34:53 +000024
Guido van Rossum5f59d601992-12-14 16:59:51 +000025/* MPZ module */
26
27/* This module provides an interface to an alternate Multi-Precision
28 library, GNU MP in this case */
29
30/* XXX note: everywhere where mpz_size is called,
31 sizeof (limb) == sizeof (long) has been assumed. */
32
33
34/* MPZ objects */
35
36#include "allobjects.h"
37#include "modsupport.h" /* For getargs() etc. */
Guido van Rossum3bbc62e1995-01-02 19:30:30 +000038#include "rename1.h"
Guido van Rossum5f59d601992-12-14 16:59:51 +000039#include <assert.h>
Guido van Rossumb6775db1994-08-01 11:34:53 +000040#include <sys/types.h> /* For size_t */
Guido van Rossum5f59d601992-12-14 16:59:51 +000041
42/*
43** These are the cpp-flags used in this file...
44**
45**
46** MPZ_MDIV_BUG works around the mpz_m{div,mod,...} routines.
47** This bug has been fixed in a later release of
48** GMP.
49**
50** MPZ_GET_STR_BUG mpz_get_str corrupts memory, seems to be fixed
51** in a later release
52**
53** MPZ_DEBUG generates a bunch of diagnostic messages
54**
55** MPZ_SPARE_MALLOC if set, results in extra code that tries to
56** minimize the creation of extra objects.
57**
58** MPZ_TEST_DIV extra diagnostic output on stderr, when division
59** routines are involved
60**
61** MPZ_LIB_DOES_CHECKING if set, assumes that mpz library doesn't call
62** alloca with arg < 0 (when casted to a signed
63** integral type).
64**
65** MPZ_CONVERSIONS_AS_METHODS if set, presents the conversions as
66** methods. e.g., `mpz(5).long() == 5L'
67** Later, Guido provided an interface to the
68** standard functions. So this flag has no been
69** cleared, and `long(mpz(5)) == 5L'
70**
71** MP_TEST_ALLOC If set, you would discover why MPZ_GET_STR_BUG
72** is needed
73**
74** MAKEDUMMYINT Must be set if dynamic linking will be used
75*/
76
77
78/*
79** IMHO, mpz_m{div,mod,divmod}() do the wrong things when the denominator < 0
80** I assume that this will be fixed in a future release
81*/
82/*#define MPZ_MDIV_BUG fixed the (for me) nexessary parts in libgmp.a */
83/*
84** IMO, mpz_get_str() assumes a bit too large target space, if he doesn't
85** allocate it himself
86*/
87#define MPZ_GET_STR_BUG
88
89#include "gmp.h"
90typedef struct {
91 OB_HEAD
92 MP_INT mpz; /* the actual number */
93} mpzobject;
94
Guido van Rossumb6775db1994-08-01 11:34:53 +000095staticforward typeobject MPZtype;
Guido van Rossum5f59d601992-12-14 16:59:51 +000096
97#define is_mpzobject(v) ((v)->ob_type == &MPZtype)
98
99static const char initialiser_name[] = "mpz";
100
101/* #define MPZ_DEBUG */
102
103static mpzobject *
104newmpzobject()
105{
106 mpzobject *mpzp;
107
108
109#ifdef MPZ_DEBUG
110 fputs( "mpz_object() called...\n", stderr );
111#endif /* def MPZ_DEBUG */
112 mpzp = NEWOBJ(mpzobject, &MPZtype);
113 if (mpzp == NULL)
114 return NULL;
115
116 mpz_init(&mpzp->mpz); /* actual initialisation */
117 return mpzp;
118} /* newmpzobject() */
119
120#ifdef MPZ_GET_STR_BUG
121#include "gmp-impl.h"
122#include "longlong.h"
123#endif /* def MPZ_GET_STR_BUG */
124
125static object *
126mpz_format(objp, base, withname)
127 object *objp;
128 int base;
129 unsigned char withname;
130{
131 mpzobject *mpzp = (mpzobject *)objp;
132 stringobject *strobjp;
133 int i;
134 int cmpres;
135 int taglong;
136 char *cp;
137 char prefix[5], *tcp;
138
139
140 tcp = &prefix[0];
141
142 if (mpzp == NULL || !is_mpzobject(mpzp)) {
143 err_badcall();
144 return NULL;
145 }
146
147 assert(base >= 2 && base <= 36);
148
149 if (withname)
150 i = strlen(initialiser_name) + 2; /* e.g. 'mpz(' + ')' */
151 else
152 i = 0;
153
154 if ((cmpres = mpz_cmp_si(&mpzp->mpz, 0L)) == 0)
155 base = 10; /* '0' in every base, right */
156 else if (cmpres < 0) {
157 *tcp++ = '-';
158 i += 1; /* space to hold '-' */
159 }
160
161#ifdef MPZ_DEBUG
162 fprintf(stderr, "mpz_format: mpz_sizeinbase %d\n",
163 (int)mpz_sizeinbase(&mpzp->mpz, base));
164#endif /* def MPZ_DEBUG */
165#ifdef MPZ_GET_STR_BUG
166 i += ((size_t) abs(mpzp->mpz.size) * BITS_PER_MP_LIMB
167 * __mp_bases[base].chars_per_bit_exactly) + 1;
168#else /* def MPZ_GET_STR_BUG */
169 i += (int)mpz_sizeinbase(&mpzp->mpz, base);
170#endif /* def MPZ_GET_STR_BUG else */
171
172 if (base == 16) {
173 *tcp++ = '0';
174 *tcp++ = 'x';
175 i += 2; /* space to hold '0x' */
176 }
177 else if (base == 8) {
178 *tcp++ = '0';
179 i += 1; /* space to hold the extra '0' */
180 }
181 else if (base > 10) {
182 *tcp++ = '0' + base / 10;
183 *tcp++ = '0' + base % 10;
184 *tcp++ = '#';
185 i += 3; /* space to hold e.g. '12#' */
186 }
187 else if (base < 10) {
188 *tcp++ = '0' + base;
189 *tcp++ = '#';
190 i += 2; /* space to hold e.g. '6#' */
191 }
192
193 /*
194 ** the following code looks if we need a 'L' attached to the number
195 ** it will also attach an 'L' to the value -0x80000000
196 */
197 taglong = 0;
198 if (mpz_size(&mpzp->mpz) > 1
199 || (long)mpz_get_ui(&mpzp->mpz) < 0L) {
200 taglong = 1;
201 i += 1; /* space to hold 'L' */
202 }
203
204#ifdef MPZ_DEBUG
205 fprintf(stderr, "mpz_format: requesting string size %d\n", i);
206#endif /* def MPZ_DEBUG */
207 if ((strobjp = (stringobject *)newsizedstringobject((char *)0, i))
208 == NULL)
209 return NULL;
210
211 /* get the beginning of the string memory and start copying things */
212 cp = GETSTRINGVALUE(strobjp);
213 if (withname) {
214 strcpy(cp, initialiser_name);
215 cp += strlen(initialiser_name);
216 *cp++ = '('; /*')'*/
217 }
218
219 /* copy the already prepared prefix; e.g. sign and base indicator */
220 *tcp = '\0';
221 strcpy(cp, prefix);
222 cp += tcp - prefix;
223
224 /* since' we have the sign already, let the lib think it's a positive
225 number */
226 if (cmpres < 0)
227 mpz_neg(&mpzp->mpz,&mpzp->mpz); /* hack Hack HAck HACk HACK */
228 (void)mpz_get_str(cp, base, &mpzp->mpz);
229 if (cmpres < 0)
230 mpz_neg(&mpzp->mpz,&mpzp->mpz); /* hack Hack HAck HACk HACK */
231#ifdef MPZ_DEBUG
232 fprintf(stderr, "mpz_format: base (ultim) %d, mpz_get_str: %s\n",
233 base, cp);
234#endif /* def MPZ_DEBUG */
235 cp += strlen(cp);
236
237 if (taglong)
238 *cp++ = 'L';
239 if (withname)
240 *cp++ = /*'('*/ ')';
241
242 *cp = '\0';
243
244#ifdef MPZ_DEBUG
245 fprintf(stderr,
246 "mpz_format: cp (str end) 0x%x, begin 0x%x, diff %d, i %d\n",
247 cp, GETSTRINGVALUE(strobjp), cp - GETSTRINGVALUE(strobjp), i);
248#endif /* def MPZ_DEBUG */
249 assert(cp - GETSTRINGVALUE(strobjp) <= i);
250
251 if (cp - GETSTRINGVALUE(strobjp) != i) {
252 strobjp->ob_size -= i - (cp - GETSTRINGVALUE(strobjp));
253 }
254
255 return (object *)strobjp;
256} /* mpz_format() */
257
258/* MPZ methods */
259
260static void
261mpz_dealloc(mpzp)
262 mpzobject *mpzp;
263{
264#ifdef MPZ_DEBUG
265 fputs( "mpz_dealloc() called...\n", stderr );
266#endif /* def MPZ_DEBUG */
267 mpz_clear(&mpzp->mpz);
268 DEL(mpzp);
269} /* mpz_dealloc() */
270
Guido van Rossum5f59d601992-12-14 16:59:51 +0000271
272/* pointers to frequently used values 0, 1 and -1 */
273static mpzobject *mpz_value_zero, *mpz_value_one, *mpz_value_mone;
274
275static int
276mpz_compare(a, b)
277 mpzobject *a, *b;
278{
279 int cmpres;
280
281
282 /* guido sez it's better to return -1, 0 or 1 */
283 return (cmpres = mpz_cmp( &a->mpz, &b->mpz )) == 0 ? 0
284 : cmpres > 0 ? 1 : -1;
285} /* mpz_compare() */
286
287static object *
288mpz_addition(a, b)
289 mpzobject *a;
290 mpzobject *b;
291{
292 mpzobject *z;
293
294
295#ifdef MPZ_SPARE_MALLOC
296 if (mpz_cmp_ui(&a->mpz, (unsigned long int)0) == 0) {
297 INCREF(b);
298 return (object *)b;
299 }
300
301 if (mpz_cmp_ui(&b->mpz, (unsigned long int)0) == 0) {
302 INCREF(a);
303 return (object *)a;
304 }
305#endif /* def MPZ_SPARE_MALLOC */
306
307 if ((z = newmpzobject()) == NULL)
308 return NULL;
309
310 mpz_add(&z->mpz, &a->mpz, &b->mpz);
311 return (object *)z;
312} /* mpz_addition() */
313
314static object *
315mpz_substract(a, b)
316 mpzobject *a;
317 mpzobject *b;
318{
319 mpzobject *z;
320
321
322#ifdef MPZ_SPARE_MALLOC
323 if (mpz_cmp_ui(&b->mpz, (unsigned long int)0) == 0) {
324 INCREF(a);
325 return (object *)a;
326 }
327#endif /* MPZ_SPARE_MALLOC */
328
329 if ((z = newmpzobject()) == NULL)
330 return NULL;
331
332 mpz_sub(&z->mpz, &a->mpz, &b->mpz);
333 return (object *)z;
334} /* mpz_substract() */
335
336static object *
337mpz_multiply(a, b)
338 mpzobject *a;
339 mpzobject *b;
340{
341#ifdef MPZ_SPARE_MALLOC
342 int cmpres;
343#endif /* def MPZ_SPARE_MALLOC */
344 mpzobject *z;
345
346
347#ifdef MPZ_SPARE_MALLOC
348 if ((cmpres = mpz_cmp_ui(&a->mpz, (unsigned long int)0)) == 0) {
349 INCREF(mpz_value_zero);
350 return (object *)mpz_value_zero;
351 }
352 if (cmpres > 0 && mpz_cmp_ui(&a->mpz, (unsigned long int)1) == 0) {
353 INCREF(b);
354 return (object *)b;
355 }
356
357 if ((cmpres = mpz_cmp_ui(&b->mpz, (unsigned long_int)0)) == 0) {
358 INCREF(mpz_value_zero);
359 return (object *)mpz_value_zero;
360 }
361 if (cmpres > 0 && mpz_cmp_ui(&b->mpz, (unsigned long int)1) == 0) {
362 INCREF(a);
363 return (object *)a;
364 }
365#endif /* MPZ_SPARE_MALLOC */
366
367 if ((z = newmpzobject()) == NULL)
368 return NULL;
369
370 mpz_mul( &z->mpz, &a->mpz, &b->mpz );
371 return (object *)z;
372
373} /* mpz_multiply() */
374
375static object *
376mpz_divide(a, b)
377 mpzobject *a;
378 mpzobject *b;
379{
380#ifdef MPZ_SPARE_MALLOC
381 int cmpres;
382#endif /* def MPZ_SPARE_MALLOC */
383 mpzobject *z;
384
385
386 if ((
387#ifdef MPZ_SPARE_MALLOC
388 cmpres =
389#endif /* def MPZ_SPARE_MALLOC */
390 mpz_cmp_ui(&b->mpz, (unsigned long int)0)) == 0) {
391 err_setstr(ZeroDivisionError, "mpz./ by zero");
392 return NULL;
393 }
394#ifdef MPZ_SPARE_MALLOC
395 if (cmpres > 0 && mpz_cmp_ui(&b->mpz(unsigned long int)1) == 0) {
396 INCREF(a);
397 return (object *)a;
398 }
399#endif /* def MPZ_SPARE_MALLOC */
400
401 if ((z = newmpzobject()) == NULL)
402 return NULL;
403
404#ifdef MPZ_TEST_DIV
405 fputs("mpz_divide: div result", stderr);
406 mpz_div(&z->mpz, &a->mpz, &b->mpz);
407 mpz_out_str(stderr, 10, &z->mpz);
408 putc('\n', stderr);
409#endif /* def MPZ_TEST_DIV */
410#ifdef MPZ_MDIV_BUG
411 if ((mpz_cmp_ui(&a->mpz, (unsigned long int)0) < 0)
412 != (mpz_cmp_ui(&b->mpz, (unsigned long int)0) < 0)) {
413 /*
414 ** numerator has other sign than denominator: we have
415 ** to look at the remainder for a correction, since mpz_mdiv
416 ** also calls mpz_divmod, I can as well do it myself
417 */
418 MP_INT tmpmpz;
419
420
421 mpz_init(&tmpmpz);
422 mpz_divmod(&z->mpz, &tmpmpz, &a->mpz, &b->mpz);
423
424 if (mpz_cmp_ui(&tmpmpz, (unsigned long int)0) != 0)
425 mpz_sub_ui(&z->mpz, &z->mpz, (unsigned long int)1);
426
427 mpz_clear(&tmpmpz);
428 }
429 else
430 mpz_div(&z->mpz, &a->mpz, &b->mpz);
431 /* the ``naive'' implementation does it right for operands
432 having the same sign */
433
434#else /* def MPZ_MDIV_BUG */
435 mpz_mdiv(&z->mpz, &a->mpz, &b->mpz);
436#endif /* def MPZ_MDIV_BUG else */
437#ifdef MPZ_TEST_DIV
438 fputs("mpz_divide: mdiv result", stderr);
439 mpz_out_str(stderr, 10, &z->mpz);
440 putc('\n', stderr);
441#endif /* def MPZ_TEST_DIV */
442 return (object *)z;
443
444} /* mpz_divide() */
445
446static object *
447mpz_remainder(a, b)
448 mpzobject *a;
449 mpzobject *b;
450{
451#ifdef MPZ_SPARE_MALLOC
452 int cmpres;
453#endif /* def MPZ_SPARE_MALLOC */
454 mpzobject *z;
455
456
457 if ((
458#ifdef MPZ_SPARE_MALLOC
459 cmpres =
460#endif /* def MPZ_SPARE_MALLOC */
461 mpz_cmp_ui(&b->mpz, (unsigned long int)0)) == 0) {
462 err_setstr(ZeroDivisionError, "mpz.% by zero");
463 return NULL;
464 }
465#ifdef MPZ_SPARE_MALLOC
466 if (cmpres > 0) {
467 if ((cmpres = mpz_cmp_ui(&b->mpz, (unsigned long int)2)) == 0) {
468 INCREF(mpz_value_one);
469 return (object *)mpz_value_one;
470 }
471 if (cmpres < 0) {
472 /* b must be 1 now */
473 INCREF(mpz_value_zero);
474 return (object *)mpz_value_zero;
475 }
476 }
477#endif /* def MPZ_SPARE_MALLOC */
478
479 if ((z = newmpzobject()) == NULL)
480 return NULL;
481
482#ifdef MPZ_TEST_DIV
483 fputs("mpz_remain: mod result", stderr);
484 mpz_mod(&z->mpz, &a->mpz, &b->mpz);
485 mpz_out_str(stderr, 10, &z->mpz);
486 putc('\n', stderr);
487#endif /* def MPZ_TEST_DIV */
488#ifdef MPZ_MDIV_BUG
489
490 /* the ``naive'' implementation does it right for operands
491 having the same sign */
492 mpz_mod(&z->mpz, &a->mpz, &b->mpz);
493
494 /* assumption: z, a and b all point to different locations */
495 if ((mpz_cmp_ui(&a->mpz, (unsigned long int)0) < 0)
496 != (mpz_cmp_ui(&b->mpz, (unsigned long int)0) < 0)
497 && mpz_cmp_ui(&z->mpz, (unsigned long int)0) != 0)
498 mpz_add(&z->mpz, &z->mpz, &b->mpz);
499 /*
500 ** numerator has other sign than denominator: we have
501 ** to look at the remainder for a correction, since mpz_mdiv
502 ** also calls mpz_divmod, I can as well do it myself
503 */
504#else /* def MPZ_MDIV_BUG */
505 mpz_mmod(&z->mpz, &a->mpz, &b->mpz);
506#endif /* def MPZ_MDIV_BUG else */
507#ifdef MPZ_TEST_DIV
508 fputs("mpz_remain: mmod result", stderr);
509 mpz_out_str(stderr, 10, &z->mpz);
510 putc('\n', stderr);
511#endif /* def MPZ_TEST_DIV */
512 return (object *)z;
513
514} /* mpz_remainder() */
515
516static object *
517mpz_div_and_mod(a, b)
518 mpzobject *a;
519 mpzobject *b;
520{
521 object *z = NULL;
522 mpzobject *x = NULL, *y = NULL;
523
524
525 if (mpz_cmp_ui(&b->mpz, (unsigned long int)0) == 0) {
526 err_setstr(ZeroDivisionError, "mpz.divmod by zero");
527 return NULL;
528 }
529
530 if ((z = newtupleobject(2)) == NULL
531 || (x = newmpzobject()) == NULL
532 || (y = newmpzobject()) == NULL) {
533 XDECREF(z);
534 XDECREF(x);
535 XDECREF(y);
536 return NULL;
537 }
538
539#ifdef MPZ_TEST_DIV
540 fputs("mpz_divmod: dm result", stderr);
541 mpz_divmod(&x->mpz, &y->mpz, &a->mpz, &b->mpz);
542 mpz_out_str(stderr, 10, &x->mpz);
543 putc('\n', stderr);
544 mpz_out_str(stderr, 10, &y->mpz);
545 putc('\n', stderr);
546#endif /* def MPZ_TEST_DIV */
547#ifdef MPZ_MDIV_BUG
548 mpz_divmod(&x->mpz, &y->mpz, &a->mpz, &b->mpz);
549 if ((mpz_cmp_ui(&a->mpz, (unsigned long int)0) < 0)
550 != (mpz_cmp_ui(&b->mpz, (unsigned long int)0) < 0)
551 && mpz_cmp_ui(&y->mpz, (unsigned long int)0) != 0) {
552 /*
553 ** numerator has other sign than denominator: we have
554 ** to look at the remainder for a correction.
555 */
556 mpz_add(&y->mpz, &y->mpz, &b->mpz);
557 mpz_sub_ui(&x->mpz, &x->mpz, (unsigned long int)1);
558 }
559#else /* def MPZ_MDIV_BUG */
560 mpz_mdivmod( &x->mpz, &y->mpz, &a->mpz, &b->mpz );
561#endif /* def MPZ_MDIV_BUG else */
562#ifdef MPZ_TEST_DIV
563 fputs("mpz_divmod: mdm result", stderr);
564 mpz_out_str(stderr, 10, &x->mpz);
565 putc('\n', stderr);
566 mpz_out_str(stderr, 10, &y->mpz);
567 putc('\n', stderr);
568#endif /* def MPZ_TEST_DIV */
569
570 (void)settupleitem(z, 0, (object *)x);
571 (void)settupleitem(z, 1, (object *)y);
572
573 return z;
574} /* mpz_div_and_mod() */
575
576static object *
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000577mpz_power(a, b, m)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000578 mpzobject *a;
579 mpzobject *b;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000580 mpzobject *m;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000581{
582 mpzobject *z;
583 int cmpres;
584 long int longtmp1, longtmp2;
585
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000586 if ((object *)m!=Py_None)
587 {
588 mpzobject *z2;
589 INCREF(Py_None);
590 z=mpz_power(a, b, (mpzobject *)Py_None);
591 DECREF(Py_None);
592 if (z==NULL) return(z);
593 z2=mpz_remainder(z, m);
594 DECREF(z);
595 return((object *)z2);
596 }
Guido van Rossum5f59d601992-12-14 16:59:51 +0000597
598 if ((cmpres = mpz_cmp_ui(&b->mpz, (unsigned long int)0)) == 0) {
599 /* the gnu-mp lib sets pow(0,0) to 0, we to 1 */
600
601 INCREF(mpz_value_one);
602 return (object *)mpz_value_one;
603 }
604
605 if (cmpres < 0) {
606 err_setstr(ValueError, "mpz.pow to negative exponent");
607 return NULL;
608 }
609
610 if ((cmpres = mpz_cmp_ui(&a->mpz, (unsigned long int)0)) == 0) {
611 /* the base is 0 */
612
613 INCREF(mpz_value_zero);
614 return (object *)mpz_value_zero;
615 }
616 else if (cmpres > 0
617 && mpz_cmp_ui(&a->mpz, (unsigned long int)1) == 0) {
618 /* the base is 1 */
619
620 INCREF(mpz_value_one);
621 return (object *)mpz_value_one;
622 }
623 else if (cmpres < 0
624 && mpz_cmp_si(&a->mpz, (long int)-1) == 0) {
625
626 MP_INT tmpmpz;
627 /* the base is -1: pow(-1, any) == 1,-1 for even,uneven b */
628 /* XXX this code needs to be optimized: what's better?
629 mpz_mmod_ui or mpz_mod_2exp, I choose for the latter
630 for *un*obvious reasons */
631
632 /* is the exponent even? */
633 mpz_init(&tmpmpz);
634
635 /* look to the remainder after a division by (1 << 1) */
636 mpz_mod_2exp(&tmpmpz, &b->mpz, (unsigned long int)1);
637
638 if (mpz_cmp_ui(&tmpmpz, (unsigned int)0) == 0) {
639 mpz_clear(&tmpmpz);
640 INCREF(mpz_value_one);
641 return (object *)mpz_value_one;
642 }
643 mpz_clear(&tmpmpz);
644 INCREF(mpz_value_mone);
645 return (object *)mpz_value_mone;
646 }
647
648#ifdef MPZ_LIB_DOES_CHECKING
649 /* check if it's doable: sizeof(exp) > sizeof(long) &&
650 abs(base) > 1 ?? --> No Way */
651 if (mpz_size(&b->mpz) > 1)
652 return (object *)err_nomem();
653#else /* def MPZ_LIB_DOES_CHECKING */
654 /* wet finger method */
655 if (mpz_cmp_ui(&b->mpz, (unsigned long int)0x10000) >= 0) {
656 err_setstr(ValueError, "mpz.pow outrageous exponent");
657 return NULL;
658 }
659#endif /* def MPZ_LIB_DOES_CHECKING else */
660
661 if ((z = newmpzobject()) == NULL)
662 return NULL;
663
664 mpz_pow_ui(&z->mpz, &a->mpz, mpz_get_ui(&b->mpz));
665
666 return (object *)z;
667} /* mpz_power() */
668
669
670static object *
671mpz_negative(v)
672 mpzobject *v;
673{
674 mpzobject *z;
675
676
677#ifdef MPZ_SPARE_MALLOC
678 if (mpz_cmp_ui(&v->mpz, (unsigned long int)0) == 0) {
679 /* -0 == 0 */
680 INCREF(v);
681 return (object *)v;
682 }
683#endif /* def MPZ_SPARE_MALLOC */
684
685 if ((z = newmpzobject()) == NULL)
686 return NULL;
687
688 mpz_neg(&z->mpz, &v->mpz);
689 return (object *)z;
690} /* mpz_negative() */
691
692
693static object *
694mpz_positive(v)
695 mpzobject *v;
696{
697 INCREF(v);
698 return (object *)v;
699} /* mpz_positive() */
700
701
702static object *
703mpz_absolute(v)
704 mpzobject *v;
705{
706 mpzobject *z;
707
708
709 if (mpz_cmp_ui(&v->mpz, (unsigned long int)0) >= 0) {
710 INCREF(v);
711 return (object *)v;
712 }
713
714 if ((z = newmpzobject()) == NULL)
715 return NULL;
716
717 mpz_neg(&z->mpz, &v->mpz);
718 return (object *)z;
719} /* mpz_absolute() */
720
721static int
722mpz_nonzero(v)
723 mpzobject *v;
724{
725 return mpz_cmp_ui(&v->mpz, (unsigned long int)0) != 0;
726} /* mpz_nonzero() */
727
728static object *
729mpz_invert(v)
730 mpzobject *v;
731{
732 mpzobject *z;
733
734
735 /* I think mpz_com does exactly what needed */
736 if ((z = newmpzobject()) == NULL)
737 return NULL;
738
739 mpz_com(&z->mpz, &v->mpz);
740 return (object *)z;
741} /* mpz_invert() */
742
743static object *
744mpz_lshift(a, b)
745 mpzobject *a;
746 mpzobject *b;
747{
748 int cmpres;
749 mpzobject *z;
750
751
752 if ((cmpres = mpz_cmp_ui(&b->mpz, (unsigned long int)0)) == 0) {
753 /* a << 0 == a */
754 INCREF(a);
755 return (object *)a;
756 }
757
758 if (cmpres < 0) {
759 err_setstr(ValueError, "mpz.<< negative shift count");
760 return NULL;
761 }
762
763#ifdef MPZ_LIB_DOES_CHECKING
764 if (mpz_size(&b->mpz) > 1)
765 return (object *)err_nomem();
766#else /* def MPZ_LIB_DOES_CHECKING */
767 /* wet finger method */
768 if (mpz_cmp_ui(&b->mpz, (unsigned long int)0x10000) >= 0) {
769 err_setstr(ValueError, "mpz.<< outrageous shift count");
770 return NULL;
771 }
772#endif /* def MPZ_LIB_DOES_CHECKING else */
773
774 if ((z = newmpzobject()) == NULL)
775 return NULL;
776
777 mpz_mul_2exp(&z->mpz, &a->mpz, mpz_get_ui(&b->mpz));
778 return (object *)z;
779} /* mpz_lshift() */
780
781static object *
782mpz_rshift(a, b)
783 mpzobject *a;
784 mpzobject *b;
785{
786 int cmpres;
787 mpzobject *z;
788
789
790 if ((cmpres = mpz_cmp_ui(&b->mpz, (unsigned long int)0)) == 0) {
791 /* a >> 0 == a */
792 INCREF(a);
793 return (object *)a;
794 }
795
796 if (cmpres < 0) {
797 err_setstr(ValueError, "mpz.>> negative shift count");
798 return NULL;
799 }
800
801 if (mpz_size(&b->mpz) > 1)
802 return (object *)err_nomem();
803
804 if ((z = newmpzobject()) == NULL)
805 return NULL;
806
807 mpz_div_2exp(&z->mpz, &a->mpz, mpz_get_ui(&b->mpz));
808 return (object *)z;
809} /* mpz_rshift() */
810
811static object *
812mpz_andfunc(a, b)
813 mpzobject *a;
814 mpzobject *b;
815{
816 mpzobject *z;
817
818
819 if ((z = newmpzobject()) == NULL)
820 return NULL;
821
822 mpz_and(&z->mpz, &a->mpz, &b->mpz);
823 return (object *)z;
824} /* mpz_andfunc() */
825
826/* hack Hack HAck HACk HACK, XXX this code is dead slow */
827void
828mpz_xor(res, op1, op2)
829 MP_INT *res;
830 const MP_INT *op1;
831 const MP_INT *op2;
832{
833 MP_INT tmpmpz;
834
835 mpz_init(&tmpmpz);
836
837 mpz_and(res, op1, op2);
838 mpz_com(&tmpmpz, res);
839 mpz_ior(res, op1, op2);
840 mpz_and(res, res, &tmpmpz);
841
842 mpz_clear(&tmpmpz);
843} /* mpz_xor() HACK */
844
845static object *
846mpz_xorfunc(a, b)
847 mpzobject *a;
848 mpzobject *b;
849{
850 mpzobject *z;
851
852
853 if ((z = newmpzobject()) == NULL)
854 return NULL;
855
856 mpz_xor(&z->mpz, &a->mpz, &b->mpz);
857 return (object *)z;
858} /* mpz_xorfunc() */
859
860static object *
861mpz_orfunc(a, b)
862 mpzobject *a;
863 mpzobject *b;
864{
865 mpzobject *z;
866
867
868 if ((z = newmpzobject()) == NULL)
869 return NULL;
870
871 mpz_ior(&z->mpz, &a->mpz, &b->mpz);
872 return (object *)z;
873} /* mpz_orfunc() */
874
875/* MPZ initialisation */
876
877#include "longintrepr.h"
878
879static object *
880MPZ_mpz(self, args)
881 object *self;
882 object *args;
883{
884 mpzobject *mpzp;
885 object *objp;
886
887
888#ifdef MPZ_DEBUG
889 fputs("MPZ_mpz() called...\n", stderr);
890#endif /* def MPZ_DEBUG */
891
892 if (!getargs(args, "O", &objp))
893 return NULL;
894
895 /* at least we know it's some object */
896 /* note DON't DECREF args NEITHER objp */
897
898 if (is_intobject(objp)) {
899 long lval;
900
901 if (!getargs(objp, "l", &lval))
902 return NULL;
903
904 if (lval == (long)0) {
905 INCREF(mpz_value_zero);
906 mpzp = mpz_value_zero;
907 }
908 else if (lval == (long)1) {
909 INCREF(mpz_value_one);
910 mpzp = mpz_value_one;
911 }
912 else if ((mpzp = newmpzobject()) == NULL)
913 return NULL;
914 else mpz_set_si(&mpzp->mpz, lval);
915 }
916 else if (is_longobject(objp)) {
917 MP_INT mplongdigit;
918 int i;
919 unsigned char isnegative;
920
921
922 if ((mpzp = newmpzobject()) == NULL)
923 return NULL;
924
925 mpz_set_si(&mpzp->mpz, 0L);
926 mpz_init(&mplongdigit);
927
928 /* how we're gonna handle this? */
929 if (isnegative = ((i = ((longobject *)objp)->ob_size) < 0) )
930 i = -i;
931
932 while (i--) {
933 mpz_set_ui(&mplongdigit,
934 (unsigned long)
935 ((longobject *)objp)->ob_digit[i]);
936 mpz_mul_2exp(&mplongdigit,&mplongdigit,
937 (unsigned long int)i * SHIFT);
938 mpz_ior(&mpzp->mpz, &mpzp->mpz, &mplongdigit);
939 }
940
941 if (isnegative)
942 mpz_neg(&mpzp->mpz, &mpzp->mpz);
943
944 /* get rid of allocation for tmp variable */
945 mpz_clear(&mplongdigit);
946 }
947 else if (is_stringobject(objp)) {
948 char *cp;
949 int len;
950 MP_INT mplongdigit;
951
952 if (!getargs(objp, "s#", &cp, &len))
953 return NULL;
954
955 if ((mpzp = newmpzobject()) == NULL)
956 return NULL;
957
958 mpz_set_si(&mpzp->mpz, 0L);
959 mpz_init(&mplongdigit);
960
961 /* let's do it the same way as with the long conversion:
962 without thinking how it can be faster (-: :-) */
963
964 cp += len;
965 while (len--) {
966 mpz_set_ui(&mplongdigit, (unsigned long)*--cp );
967 mpz_mul_2exp(&mplongdigit,&mplongdigit,
968 (unsigned long int)len * 8);
969 mpz_ior(&mpzp->mpz, &mpzp->mpz, &mplongdigit);
970 }
971
972 /* get rid of allocation for tmp variable */
973 mpz_clear(&mplongdigit);
974 }
975 else if (is_mpzobject(objp)) {
976 INCREF(objp);
977 mpzp = (mpzobject *)objp;
978 }
979 else {
980 err_setstr(TypeError,
981 "mpz.mpz() expects integer, long, string or mpz object argument");
982 return NULL;
983 }
984
985
986#ifdef MPZ_DEBUG
987 fputs("MPZ_mpz: created mpz=", stderr);
988 mpz_out_str(stderr, 10, &mpzp->mpz);
989 putc('\n', stderr);
990#endif /* def MPZ_DEBUG */
991 return (object *)mpzp;
992} /* MPZ_mpz() */
993
994static mpzobject *
995mpz_mpzcoerce(z)
996 object *z;
997{
998 /* shortcut: 9 out of 10 times the type is already ok */
999 if (is_mpzobject(z)) {
1000 INCREF(z);
1001 return (mpzobject *)z; /* coercion succeeded */
1002 }
1003
1004 /* what types do we accept?: intobjects and longobjects */
1005 if (is_intobject(z) || is_longobject(z))
1006 return (mpzobject *)MPZ_mpz((object *)NULL, z);
1007
1008 err_setstr(TypeError, "number coercion (to mpzobject) failed");
1009 return NULL;
1010} /* mpz_mpzcoerce() */
Guido van Rossumb6775db1994-08-01 11:34:53 +00001011
1012/* Forward */
1013static void mpz_divm PROTO((MP_INT *res, const MP_INT *num,
1014 const MP_INT *den, const MP_INT *mod));
Guido van Rossum67a5fdb1993-12-17 12:09:14 +00001015
Guido van Rossum5f59d601992-12-14 16:59:51 +00001016static object *
1017MPZ_powm(self, args)
1018 object *self;
1019 object *args;
1020{
1021 object *base, *exp, *mod;
1022 mpzobject *mpzbase = NULL, *mpzexp = NULL, *mpzmod = NULL;
1023 mpzobject *z;
1024 int tstres;
1025
1026
1027 if (!getargs(args, "(OOO)", &base, &exp, &mod))
1028 return NULL;
1029
1030 if ((mpzbase = mpz_mpzcoerce(base)) == NULL
1031 || (mpzexp = mpz_mpzcoerce(exp)) == NULL
1032 || (mpzmod = mpz_mpzcoerce(mod)) == NULL
1033 || (z = newmpzobject()) == NULL) {
1034 XDECREF(mpzbase);
1035 XDECREF(mpzexp);
1036 XDECREF(mpzmod);
1037 return NULL;
1038 }
1039
1040 if ((tstres=mpz_cmp_ui(&mpzexp->mpz, (unsigned long int)0)) == 0) {
1041 INCREF(mpz_value_one);
1042 return (object *)mpz_value_one;
1043 }
1044
1045 if (tstres < 0) {
1046 MP_INT absexp;
1047 /* negative exp */
1048
1049 mpz_init_set(&absexp, &mpzexp->mpz);
1050 mpz_abs(&absexp, &absexp);
1051 mpz_powm(&z->mpz, &mpzbase->mpz, &absexp, &mpzmod->mpz);
1052
1053 mpz_divm(&z->mpz, &mpz_value_one->mpz, &z->mpz, &mpzmod->mpz);
1054
1055 mpz_clear(&absexp);
1056 }
1057 else {
1058 mpz_powm(&z->mpz, &mpzbase->mpz, &mpzexp->mpz, &mpzmod->mpz);
1059 }
1060
1061 DECREF(mpzbase);
1062 DECREF(mpzexp);
1063 DECREF(mpzmod);
1064
1065 return (object *)z;
1066} /* MPZ_powm() */
1067
1068
1069static object *
1070MPZ_gcd(self, args)
1071 object *self;
1072 object *args;
1073{
1074 object *op1, *op2;
1075 mpzobject *mpzop1 = NULL, *mpzop2 = NULL;
1076 mpzobject *z;
1077
1078
1079 if (!getargs(args, "(OO)", &op1, &op2))
1080 return NULL;
1081
1082 if ((mpzop1 = mpz_mpzcoerce(op1)) == NULL
1083 || (mpzop2 = mpz_mpzcoerce(op2)) == NULL
1084 || (z = newmpzobject()) == NULL) {
1085 XDECREF(mpzop1);
1086 XDECREF(mpzop2);
1087 return NULL;
1088 }
1089
1090 /* ok, we have three mpzobjects, and an initialised result holder */
1091 mpz_gcd(&z->mpz, &mpzop1->mpz, &mpzop2->mpz);
1092
1093 DECREF(mpzop1);
1094 DECREF(mpzop2);
1095
1096 return (object *)z;
1097} /* MPZ_gcd() */
1098
1099
1100static object *
1101MPZ_gcdext(self, args)
1102 object *self;
1103 object *args;
1104{
1105 object *op1, *op2, *z = NULL;
1106 mpzobject *mpzop1 = NULL, *mpzop2 = NULL;
1107 mpzobject *g = NULL, *s = NULL, *t = NULL;
1108
1109
1110 if (!getargs(args, "(OO)", &op1, &op2))
1111 return NULL;
1112
1113 if ((mpzop1 = mpz_mpzcoerce(op1)) == NULL
1114 || (mpzop2 = mpz_mpzcoerce(op2)) == NULL
1115 || (z = newtupleobject(3)) == NULL
1116 || (g = newmpzobject()) == NULL
1117 || (s = newmpzobject()) == NULL
1118 || (t = newmpzobject()) == NULL) {
1119 XDECREF(mpzop1);
1120 XDECREF(mpzop2);
1121 XDECREF(z);
1122 XDECREF(g);
1123 XDECREF(s);
1124 /*XDECREF(t);*/
1125 return NULL;
1126 }
1127
1128 mpz_gcdext(&g->mpz, &s->mpz, &t->mpz, &mpzop1->mpz, &mpzop2->mpz);
1129
1130 DECREF(mpzop1);
1131 DECREF(mpzop2);
1132
1133 (void)settupleitem(z, 0, (object *)g);
1134 (void)settupleitem(z, 1, (object *)s);
1135 (void)settupleitem(z, 2, (object *)t);
1136
1137 return (object *)z;
1138} /* MPZ_gcdext() */
1139
1140
1141static object *
1142MPZ_sqrt(self, args)
1143 object *self;
1144 object *args;
1145{
1146 object *op;
1147 mpzobject *mpzop = NULL;
1148 mpzobject *z;
1149
1150
1151 if (!getargs(args, "O", &op))
1152 return NULL;
1153
1154 if ((mpzop = mpz_mpzcoerce(op)) == NULL
1155 || (z = newmpzobject()) == NULL) {
1156 XDECREF(mpzop);
1157 return NULL;
1158 }
1159
1160 mpz_sqrt(&z->mpz, &mpzop->mpz);
1161
1162 DECREF(mpzop);
1163
1164 return (object *)z;
1165} /* MPZ_sqrt() */
1166
1167
1168static object *
1169MPZ_sqrtrem(self, args)
1170 object *self;
1171 object *args;
1172{
1173 object *op, *z = NULL;
1174 mpzobject *mpzop = NULL;
1175 mpzobject *root = NULL, *rem = NULL;
1176
1177
1178 if (!getargs(args, "O", &op))
1179 return NULL;
1180
1181 if ((mpzop = mpz_mpzcoerce(op)) == NULL
1182 || (z = newtupleobject(2)) == NULL
1183 || (root = newmpzobject()) == NULL
1184 || (rem = newmpzobject()) == NULL) {
1185 XDECREF(mpzop);
1186 XDECREF(z);
1187 XDECREF(root);
1188 /*XDECREF(rem);*/
1189 return NULL;
1190 }
1191
1192 mpz_sqrtrem(&root->mpz, &rem->mpz, &mpzop->mpz);
1193
1194 DECREF(mpzop);
1195
1196 (void)settupleitem(z, 0, (object *)root);
1197 (void)settupleitem(z, 1, (object *)rem);
1198
1199 return (object *)z;
1200} /* MPZ_sqrtrem() */
1201
1202
Guido van Rossum67a5fdb1993-12-17 12:09:14 +00001203static void
Guido van Rossum5f59d601992-12-14 16:59:51 +00001204#if __STDC__
1205mpz_divm(MP_INT *res, const MP_INT *num, const MP_INT *den, const MP_INT *mod)
1206#else
1207mpz_divm(res, num, den, mod)
1208 MP_INT *res;
1209 const MP_INT *num;
1210 const MP_INT *den;
1211 const MP_INT *mod;
1212#endif
1213{
1214 MP_INT s0, s1, q, r, x, d0, d1;
1215
1216 mpz_init_set(&s0, num);
1217 mpz_init_set_ui(&s1, 0);
1218 mpz_init(&q);
1219 mpz_init(&r);
1220 mpz_init(&x);
1221 mpz_init_set(&d0, den);
1222 mpz_init_set(&d1, mod);
1223
1224 while (d1.size != 0) {
1225 mpz_divmod(&q, &r, &d0, &d1);
1226 mpz_set(&d0, &d1);
1227 mpz_set(&d1, &r);
1228
1229 mpz_mul(&x, &s1, &q);
1230 mpz_sub(&x, &s0, &x);
1231 mpz_set(&s0, &s1);
1232 mpz_set(&s1, &x);
1233 }
1234
1235 if (d0.size != 1 || d0.d[0] != 1)
1236 res->size = 0; /* trouble: the gcd != 1; set s to zero */
1237 else {
1238#ifdef MPZ_MDIV_BUG
1239 /* watch out here! first check the signs, and then perform
1240 the mpz_mod() since mod could point to res */
1241 if ((s0.size < 0) != (mod->size < 0)) {
1242 mpz_mod(res, &s0, mod);
1243
1244 if (res->size)
1245 mpz_add(res, res, mod);
1246 }
1247 else
1248 mpz_mod(res, &s0, mod);
1249
1250#else /* def MPZ_MDIV_BUG */
1251 mpz_mmod(res, &s0, mod);
1252#endif /* def MPZ_MDIV_BUG else */
1253 }
1254
1255 mpz_clear(&s0);
1256 mpz_clear(&s1);
1257 mpz_clear(&q);
1258 mpz_clear(&r);
1259 mpz_clear(&x);
1260 mpz_clear(&d0);
1261 mpz_clear(&d1);
1262} /* mpz_divm() */
1263
1264
1265static object *
1266MPZ_divm(self, args)
1267 object *self;
1268 object *args;
1269{
1270 object *num, *den, *mod;
1271 mpzobject *mpznum, *mpzden, *mpzmod = NULL;
1272 mpzobject *z = NULL;
1273
1274
1275 if (!getargs(args, "(OOO)", &num, &den, &mod))
1276 return NULL;
1277
1278 if ((mpznum = mpz_mpzcoerce(num)) == NULL
1279 || (mpzden = mpz_mpzcoerce(den)) == NULL
1280 || (mpzmod = mpz_mpzcoerce(mod)) == NULL
1281 || (z = newmpzobject()) == NULL ) {
1282 XDECREF(mpznum);
1283 XDECREF(mpzden);
1284 XDECREF(mpzmod);
1285 return NULL;
1286 }
1287
1288 mpz_divm(&z->mpz, &mpznum->mpz, &mpzden->mpz, &mpzmod->mpz);
1289
1290 DECREF(mpznum);
1291 DECREF(mpzden);
1292 DECREF(mpzmod);
1293
1294 if (mpz_cmp_ui(&z->mpz, (unsigned long int)0) == 0) {
1295 DECREF(z);
1296 err_setstr(ValueError, "gcd(den, mod) != 1 or num == 0");
1297 return NULL;
1298 }
1299
1300 return (object *)z;
1301} /* MPZ_divm() */
1302
1303
1304/* MPZ methods-as-attributes */
1305#ifdef MPZ_CONVERSIONS_AS_METHODS
1306static object *
1307mpz_int(self, args)
1308 mpzobject *self;
1309 object *args;
1310#else /* def MPZ_CONVERSIONS_AS_METHODS */
1311static object *
1312mpz_int(self)
1313 mpzobject *self;
1314#endif /* def MPZ_CONVERSIONS_AS_METHODS else */
1315{
1316 long sli;
1317
1318
1319#ifdef MPZ_CONVERSIONS_AS_METHODS
1320 if (!getnoarg(args))
1321 return NULL;
1322#endif /* def MPZ_CONVERSIONS_AS_METHODS */
1323
1324 if (mpz_size(&self->mpz) > 1
1325 || (sli = (long)mpz_get_ui(&self->mpz)) < (long)0 ) {
1326 err_setstr(ValueError, "mpz.int() arg too long to convert");
1327 return NULL;
1328 }
1329
1330 if (mpz_cmp_ui(&self->mpz, (unsigned long)0) < 0)
1331 sli = -sli;
1332
1333 return newintobject(sli);
1334} /* mpz_int() */
1335
1336static object *
1337#ifdef MPZ_CONVERSIONS_AS_METHODS
1338mpz_long(self, args)
1339 mpzobject *self;
1340 object *args;
1341#else /* def MPZ_CONVERSIONS_AS_METHODS */
1342mpz_long(self)
1343 mpzobject *self;
1344#endif /* def MPZ_CONVERSIONS_AS_METHODS else */
1345{
1346 int i, isnegative;
1347 unsigned long int uli;
1348 longobject *longobjp;
1349 int ldcount;
1350 int bitpointer, newbitpointer;
1351 MP_INT mpzscratch;
1352
1353
1354#ifdef MPZ_CONVERSIONS_AS_METHODS
1355 if (!getnoarg(args))
1356 return NULL;
1357#endif /* def MPZ_CONVERSIONS_AS_METHODS */
1358
1359 /* determine length of python-long to be allocated */
1360 if ((longobjp = alloclongobject(i = (int)
1361 ((mpz_size(&self->mpz) * BITS_PER_MP_LIMB
1362 + SHIFT - 1) /
1363 SHIFT))) == NULL)
1364 return NULL;
1365
1366 /* determine sign, and copy self to scratch var */
1367 mpz_init_set(&mpzscratch, &self->mpz);
1368 if (isnegative = (mpz_cmp_ui(&self->mpz, (unsigned long int)0) < 0))
1369 mpz_neg(&mpzscratch, &mpzscratch);
1370
1371 /* let those bits come, let those bits go,
1372 e.g. dismantle mpzscratch, build longobject */
1373
1374 bitpointer = 0; /* the number of valid bits in stock */
1375 newbitpointer = 0;
1376 ldcount = 0; /* the python-long limb counter */
1377 uli = (unsigned long int)0;
1378 while (i--) {
1379 longobjp->ob_digit[ldcount] = uli & MASK;
1380
1381 /* check if we've had enough bits for this digit */
1382 if (bitpointer < SHIFT) {
1383 uli = mpz_get_ui(&mpzscratch);
1384 longobjp->ob_digit[ldcount] |=
1385 (uli << bitpointer) & MASK;
1386 uli >>= SHIFT-bitpointer;
1387 bitpointer += BITS_PER_MP_LIMB;
1388 mpz_div_2exp(&mpzscratch, &mpzscratch,
1389 BITS_PER_MP_LIMB);
1390 }
1391 else
1392 uli >>= SHIFT;
1393 bitpointer -= SHIFT;
1394 ldcount++;
1395 }
1396
1397 assert(mpz_cmp_ui(&mpzscratch, (unsigned long int)0) == 0);
1398 mpz_clear(&mpzscratch);
1399 assert(ldcount <= longobjp->ob_size);
1400
1401 /* long_normalize() is file-static */
1402 /* longobjp = long_normalize(longobjp); */
1403 while (ldcount > 0 && longobjp->ob_digit[ldcount-1] == 0)
1404 ldcount--;
1405 longobjp->ob_size = ldcount;
1406
1407
1408 if (isnegative)
1409 longobjp->ob_size = -longobjp->ob_size;
1410
1411 return (object *)longobjp;
1412
1413} /* mpz_long() */
1414
1415
1416/* I would have avoided pow() anyways, so ... */
1417static const double multiplier = 256.0 * 256.0 * 256.0 * 256.0;
1418
1419#ifdef MPZ_CONVERSIONS_AS_METHODS
1420static object *
1421mpz_float(self, args)
1422 mpzobject *self;
1423 object *args;
1424#else /* def MPZ_CONVERSIONS_AS_METHODS */
1425static object *
1426mpz_float(self)
1427 mpzobject *self;
1428#endif /* def MPZ_CONVERSIONS_AS_METHODS else */
1429{
1430 int i, isnegative;
1431 double x;
1432 double mulstate;
1433 MP_INT mpzscratch;
1434
1435
1436#ifdef MPZ_CONVERSIONS_AS_METHODS
1437 if (!getnoarg(args))
1438 return NULL;
1439#endif /* def MPZ_CONVERSIONS_AS_METHODS */
1440
1441 i = (int)mpz_size(&self->mpz);
1442
1443 /* determine sign, and copy abs(self) to scratch var */
1444 if (isnegative = (mpz_cmp_ui(&self->mpz, (unsigned long int)0) < 0)) {
1445 mpz_init(&mpzscratch);
1446 mpz_neg(&mpzscratch, &self->mpz);
1447 }
1448 else
1449 mpz_init_set(&mpzscratch, &self->mpz);
1450
1451 /* let those bits come, let those bits go,
1452 e.g. dismantle mpzscratch, build floatobject */
1453
1454 x = 0.0;
1455 mulstate = 1.0;
1456 while (i--) {
1457 x += mulstate * mpz_get_ui(&mpzscratch);
1458 mulstate *= multiplier;
1459 mpz_div_2exp(&mpzscratch, &mpzscratch, BITS_PER_MP_LIMB);
1460 }
1461
1462 assert(mpz_cmp_ui(&mpzscratch, (unsigned long int)0) == 0);
1463 mpz_clear(&mpzscratch);
1464
1465 if (isnegative)
1466 x = -x;
1467
1468 return newfloatobject(x);
1469
1470} /* mpz_float() */
1471
1472#ifdef MPZ_CONVERSIONS_AS_METHODS
1473static object *
1474mpz_hex(self, args)
1475 mpzobject *self;
1476 object *args;
1477#else /* def MPZ_CONVERSIONS_AS_METHODS */
1478static object *
1479mpz_hex(self)
1480 mpzobject *self;
1481#endif /* def MPZ_CONVERSIONS_AS_METHODS else */
1482{
1483#ifdef MPZ_CONVERSIONS_AS_METHODS
1484 if (!getnoarg(args))
1485 return NULL;
1486#endif /* def MPZ_CONVERSIONS_AS_METHODS */
1487
1488 return mpz_format(self, 16, (unsigned char)1);
1489} /* mpz_hex() */
1490
1491#ifdef MPZ_CONVERSIONS_AS_METHODS
1492static object *
1493mpz_oct(self, args)
1494 mpzobject *self;
1495 object *args;
1496#else /* def MPZ_CONVERSIONS_AS_METHODS */
1497static object *
1498mpz_oct(self)
1499 mpzobject *self;
1500#endif /* def MPZ_CONVERSIONS_AS_METHODS else */
1501{
1502#ifdef MPZ_CONVERSIONS_AS_METHODS
1503 if (!getnoarg(args))
1504 return NULL;
1505#endif /* def MPZ_CONVERSIONS_AS_METHODS */
1506
1507 return mpz_format(self, 8, (unsigned char)1);
1508} /* mpz_oct() */
1509
1510static object *
1511mpz_binary(self, args)
1512 mpzobject *self;
1513 object *args;
1514{
1515 int size;
1516 stringobject *strobjp;
1517 char *cp;
1518 MP_INT mp;
1519 unsigned long ldigit;
1520
1521 if (!getnoarg(args))
1522 return NULL;
1523
1524 if (mpz_cmp_ui(&self->mpz, (unsigned long int)0) < 0) {
1525 err_setstr(ValueError, "mpz.binary() arg must be >= 0");
1526 return NULL;
1527 }
1528
1529 mpz_init_set(&mp, &self->mpz);
1530 size = (int)mpz_size(&mp);
1531
1532 if ((strobjp = (stringobject *)
1533 newsizedstringobject((char *)0,
1534 size * sizeof (unsigned long int))) == NULL)
1535 return NULL;
1536
1537 /* get the beginning of the string memory and start copying things */
1538 cp = GETSTRINGVALUE(strobjp);
1539
1540 /* this has been programmed using a (fairly) decent lib-i/f it could
1541 be must faster if we looked into the GMP lib */
1542 while (size--) {
1543 ldigit = mpz_get_ui(&mp);
1544 mpz_div_2exp(&mp, &mp, BITS_PER_MP_LIMB);
1545 *cp++ = (unsigned char)(ldigit & 0xFF);
1546 *cp++ = (unsigned char)((ldigit >>= 8) & 0xFF);
1547 *cp++ = (unsigned char)((ldigit >>= 8) & 0xFF);
1548 *cp++ = (unsigned char)((ldigit >>= 8) & 0xFF);
1549 }
1550
1551 while (strobjp->ob_size && !*--cp)
1552 strobjp->ob_size--;
1553
1554 return (object *)strobjp;
1555} /* mpz_binary() */
1556
1557
1558static struct methodlist mpz_methods[] = {
1559#ifdef MPZ_CONVERSIONS_AS_METHODS
1560 {"int", mpz_int},
1561 {"long", mpz_long},
1562 {"float", mpz_float},
1563 {"hex", mpz_hex},
1564 {"oct", mpz_oct},
1565#endif /* def MPZ_CONVERSIONS_AS_METHODS */
Guido van Rossumb6775db1994-08-01 11:34:53 +00001566 {"binary", (object *(*)(object *, object *))mpz_binary},
Guido van Rossum5f59d601992-12-14 16:59:51 +00001567 {NULL, NULL} /* sentinel */
1568};
1569
1570static object *
1571mpz_getattr(self, name)
1572 mpzobject *self;
1573 char *name;
1574{
1575 return findmethod(mpz_methods, (object *)self, name);
1576} /* mpz_getattr() */
1577
1578
1579static int
1580mpz_coerce(pv, pw)
1581 object **pv;
1582 object **pw;
1583{
1584 object *z;
1585
1586#ifdef MPZ_DEBUG
1587 fputs("mpz_coerce() called...\n", stderr);
1588#endif /* def MPZ_DEBUG */
1589
1590 assert(is_mpzobject(*pv));
1591
1592 /* always convert other arg to mpz value, except for floats */
1593 if (!is_floatobject(*pw)) {
1594 if ((z = (object *)mpz_mpzcoerce(*pw)) == NULL)
1595 return -1; /* -1: an error always has been set */
1596
1597 INCREF(*pv);
1598 *pw = z;
1599 }
1600 else {
1601 if ((z = mpz_float(*pv, NULL)) == NULL)
1602 return -1;
1603
1604 INCREF(*pw);
1605 *pv = z;
1606 }
1607 return 0; /* coercion succeeded */
1608
1609} /* mpz_coerce() */
1610
1611
1612static object *
1613mpz_repr(v)
1614 object *v;
1615{
1616 return mpz_format(v, 10, (unsigned char)1);
1617} /* mpz_repr() */
1618
1619
1620
Guido van Rossumb6775db1994-08-01 11:34:53 +00001621#define UF (unaryfunc)
1622#define BF (binaryfunc)
Guido van Rossum3bbc62e1995-01-02 19:30:30 +00001623#define TF (ternaryfunc)
Guido van Rossumb6775db1994-08-01 11:34:53 +00001624#define IF (inquiry)
1625#define CF (coercion)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001626
1627static number_methods mpz_as_number = {
1628 BF mpz_addition, /*nb_add*/
1629 BF mpz_substract, /*nb_subtract*/
1630 BF mpz_multiply, /*nb_multiply*/
1631 BF mpz_divide, /*nb_divide*/
1632 BF mpz_remainder, /*nb_remainder*/
1633 BF mpz_div_and_mod, /*nb_divmod*/
Guido van Rossum3bbc62e1995-01-02 19:30:30 +00001634 TF mpz_power, /*nb_power*/
Guido van Rossum5f59d601992-12-14 16:59:51 +00001635 UF mpz_negative, /*nb_negative*/
1636 UF mpz_positive, /*tp_positive*/
1637 UF mpz_absolute, /*tp_absolute*/
1638 IF mpz_nonzero, /*tp_nonzero*/
1639 UF mpz_invert, /*nb_invert*/
1640 BF mpz_lshift, /*nb_lshift*/
1641 BF mpz_rshift, /*nb_rshift*/
1642 BF mpz_andfunc, /*nb_and*/
1643 BF mpz_xorfunc, /*nb_xor*/
1644 BF mpz_orfunc, /*nb_or*/
Guido van Rossumb6775db1994-08-01 11:34:53 +00001645 CF mpz_coerce, /*nb_coerce*/
Guido van Rossum5f59d601992-12-14 16:59:51 +00001646#ifndef MPZ_CONVERSIONS_AS_METHODS
1647 UF mpz_int, /*nb_int*/
1648 UF mpz_long, /*nb_long*/
1649 UF mpz_float, /*nb_float*/
1650 UF mpz_oct, /*nb_oct*/
1651 UF mpz_hex, /*nb_hex*/
1652#endif /* ndef MPZ_CONVERSIONS_AS_METHODS */
1653};
1654
1655static typeobject MPZtype = {
1656 OB_HEAD_INIT(&Typetype)
1657 0, /*ob_size*/
1658 "mpz", /*tp_name*/
1659 sizeof(mpzobject), /*tp_size*/
1660 0, /*tp_itemsize*/
1661 /* methods */
Guido van Rossumb6775db1994-08-01 11:34:53 +00001662 (destructor)mpz_dealloc, /*tp_dealloc*/
1663 0, /*tp_print*/
1664 (getattrfunc)mpz_getattr, /*tp_getattr*/
1665 0, /*tp_setattr*/
1666 (cmpfunc)mpz_compare, /*tp_compare*/
1667 (reprfunc)mpz_repr, /*tp_repr*/
1668 &mpz_as_number, /*tp_as_number*/
Guido van Rossum5f59d601992-12-14 16:59:51 +00001669};
1670
1671/* List of functions exported by this module */
1672
1673static struct methodlist mpz_functions[] = {
1674#if 0
1675 {initialiser_name, MPZ_mpz},
1676#else /* 0 */
1677 /* until guido ``fixes'' struct methodlist */
1678 {(char *)initialiser_name, MPZ_mpz},
1679#endif /* 0 else */
1680 {"powm", MPZ_powm},
1681 {"gcd", MPZ_gcd},
1682 {"gcdext", MPZ_gcdext},
1683 {"sqrt", MPZ_sqrt},
1684 {"sqrtrem", MPZ_sqrtrem},
1685 {"divm", MPZ_divm},
1686 {NULL, NULL} /* Sentinel */
1687};
1688
1689
1690/* #define MP_TEST_ALLOC */
1691
1692#ifdef MP_TEST_ALLOC
1693#define MP_TEST_SIZE 4
1694static const char mp_test_magic[MP_TEST_SIZE] = {'\xAA','\xAA','\xAA','\xAA'};
1695static mp_test_error( location )
1696 int *location;
1697{
1698 /* assumptions: *alloc returns address dividable by 4,
1699 mpz_* routines allocate in chunks dividable by four */
1700 fprintf(stderr, "MP_TEST_ERROR: location holds 0x%08d\n", *location );
1701 fatal("MP_TEST_ERROR");
1702} /* static mp_test_error() */
1703#define MP_EXTRA_ALLOC(size) ((size) + MP_TEST_SIZE)
1704#define MP_SET_TEST(basep,size) (void)memcpy( ((char *)(basep))+(size), mp_test_magic, MP_TEST_SIZE)
1705#define MP_DO_TEST(basep,size) if ( !memcmp( ((char *)(basep))+(size), mp_test_magic, MP_TEST_SIZE ) ) \
1706 ; \
1707 else \
1708 mp_test_error((int *)((char *)(basep) + size))
1709#else /* def MP_TEST_ALLOC */
1710#define MP_EXTRA_ALLOC(size) (size)
1711#define MP_SET_TEST(basep,size)
1712#define MP_DO_TEST(basep,size)
1713#endif /* def MP_TEST_ALLOC else */
1714
1715void *mp_allocate( alloc_size )
1716 size_t alloc_size;
1717{
1718 void *res;
1719
1720#ifdef MPZ_DEBUG
1721 fprintf(stderr, "mp_allocate : size %ld\n",
1722 alloc_size);
1723#endif /* def MPZ_DEBUG */
1724
1725 if ( (res = malloc(MP_EXTRA_ALLOC(alloc_size))) == NULL )
1726 fatal("mp_allocate failure");
1727
1728#ifdef MPZ_DEBUG
1729 fprintf(stderr, "mp_allocate : address 0x%08x\n", res);
1730#endif /* def MPZ_DEBUG */
1731
1732 MP_SET_TEST(res,alloc_size);
1733
1734 return res;
1735} /* mp_allocate() */
1736
1737
1738void *mp_reallocate( ptr, old_size, new_size )
1739 void *ptr;
1740 size_t old_size;
1741 size_t new_size;
1742{
1743 void *res;
1744
1745#ifdef MPZ_DEBUG
1746 fprintf(stderr, "mp_reallocate: old address 0x%08x, old size %ld\n",
1747 ptr, old_size);
1748#endif /* def MPZ_DEBUG */
1749
1750 MP_DO_TEST(ptr, old_size);
1751
1752 if ( (res = realloc(ptr, MP_EXTRA_ALLOC(new_size))) == NULL )
1753 fatal("mp_reallocate failure");
1754
1755#ifdef MPZ_DEBUG
1756 fprintf(stderr, "mp_reallocate: new address 0x%08x, new size %ld\n",
1757 res, new_size);
1758#endif /* def MPZ_DEBUG */
1759
1760 MP_SET_TEST(res, new_size);
1761
1762 return res;
1763} /* mp_reallocate() */
1764
1765
1766void mp_free( ptr, size )
1767 void *ptr;
1768 size_t size;
1769{
1770
1771#ifdef MPZ_DEBUG
1772 fprintf(stderr, "mp_free : old address 0x%08x, old size %ld\n",
1773 ptr, size);
1774#endif /* def MPZ_DEBUG */
1775
1776 MP_DO_TEST(ptr, size);
1777 free(ptr);
1778} /* mp_free() */
1779
1780
1781
1782/* Initialize this module. */
1783
1784void
1785initmpz()
1786{
1787#ifdef MPZ_DEBUG
1788 fputs( "initmpz() called...\n", stderr );
1789#endif /* def MPZ_DEBUG */
1790
1791 mp_set_memory_functions( mp_allocate, mp_reallocate, mp_free );
1792 (void)initmodule("mpz", mpz_functions);
1793
1794 /* create some frequently used constants */
1795 if ((mpz_value_zero = newmpzobject()) == NULL)
Guido van Rossum3bbc62e1995-01-02 19:30:30 +00001796 fatal("initmpz: can't initialize mpz constants");
Guido van Rossum5f59d601992-12-14 16:59:51 +00001797 mpz_set_ui(&mpz_value_zero->mpz, (unsigned long int)0);
1798
1799 if ((mpz_value_one = newmpzobject()) == NULL)
Guido van Rossum3bbc62e1995-01-02 19:30:30 +00001800 fatal("initmpz: can't initialize mpz constants");
Guido van Rossum5f59d601992-12-14 16:59:51 +00001801 mpz_set_ui(&mpz_value_one->mpz, (unsigned long int)1);
1802
1803 if ((mpz_value_mone = newmpzobject()) == NULL)
Guido van Rossum3bbc62e1995-01-02 19:30:30 +00001804 fatal("initmpz: can't initialize mpz constants");
Guido van Rossum5f59d601992-12-14 16:59:51 +00001805 mpz_set_si(&mpz_value_mone->mpz, (long)-1);
1806
1807} /* initmpz() */
1808#ifdef MAKEDUMMYINT
1809int _mpz_dummy_int; /* XXX otherwise, we're .bss-less (DYNLOAD->Jack?) */
1810#endif /* def MAKEDUMMYINT */