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