blob: d4a7370c67813bf8f7a1ef13c6195595c57dbe09 [file] [log] [blame]
Guido van Rossumb6775db1994-08-01 11:34:53 +00001
Guido van Rossum5f59d601992-12-14 16:59:51 +00002/* MPZ module */
3
4/* This module provides an interface to an alternate Multi-Precision
5 library, GNU MP in this case */
6
7/* XXX note: everywhere where mpz_size is called,
8 sizeof (limb) == sizeof (long) has been assumed. */
9
10
11/* MPZ objects */
12
Barry Warsaw3bdf7461996-12-09 23:16:31 +000013#include "Python.h"
Guido van Rossuma597dde1995-01-10 20:56:29 +000014
Guido van Rossum5f59d601992-12-14 16:59:51 +000015#include <assert.h>
Guido van Rossumb6775db1994-08-01 11:34:53 +000016#include <sys/types.h> /* For size_t */
Guido van Rossum5f59d601992-12-14 16:59:51 +000017
18/*
19** These are the cpp-flags used in this file...
20**
21**
22** MPZ_MDIV_BUG works around the mpz_m{div,mod,...} routines.
23** This bug has been fixed in a later release of
24** GMP.
25**
26** MPZ_GET_STR_BUG mpz_get_str corrupts memory, seems to be fixed
27** in a later release
28**
29** MPZ_DEBUG generates a bunch of diagnostic messages
30**
31** MPZ_SPARE_MALLOC if set, results in extra code that tries to
32** minimize the creation of extra objects.
33**
34** MPZ_TEST_DIV extra diagnostic output on stderr, when division
35** routines are involved
36**
37** MPZ_LIB_DOES_CHECKING if set, assumes that mpz library doesn't call
38** alloca with arg < 0 (when casted to a signed
39** integral type).
40**
41** MPZ_CONVERSIONS_AS_METHODS if set, presents the conversions as
42** methods. e.g., `mpz(5).long() == 5L'
43** Later, Guido provided an interface to the
44** standard functions. So this flag has no been
45** cleared, and `long(mpz(5)) == 5L'
46**
47** MP_TEST_ALLOC If set, you would discover why MPZ_GET_STR_BUG
48** is needed
49**
50** MAKEDUMMYINT Must be set if dynamic linking will be used
51*/
52
53
54/*
55** IMHO, mpz_m{div,mod,divmod}() do the wrong things when the denominator < 0
Guido van Rossum272841c1996-08-19 23:06:45 +000056** This has been fixed with gmp release 2.0
Guido van Rossum5f59d601992-12-14 16:59:51 +000057*/
58/*#define MPZ_MDIV_BUG fixed the (for me) nexessary parts in libgmp.a */
59/*
60** IMO, mpz_get_str() assumes a bit too large target space, if he doesn't
61** allocate it himself
62*/
Guido van Rossum5f59d601992-12-14 16:59:51 +000063
64#include "gmp.h"
Guido van Rossume7ef74d2000-02-24 15:26:30 +000065
Guido van Rossum57e846f1997-08-17 19:08:33 +000066#if __GNU_MP__ + 0 == 2
Guido van Rossum272841c1996-08-19 23:06:45 +000067#define GMP2
Andrew M. Kuchlingb6f6e952000-02-25 22:23:31 +000068#define BITS_PER_MP_LIMB mp_bits_per_limb
Guido van Rossum272841c1996-08-19 23:06:45 +000069#else
70#define MPZ_GET_STR_BUG
Andrew M. Kuchlingb6f6e952000-02-25 22:23:31 +000071#include "gmp-mparam.h"
Guido van Rossum272841c1996-08-19 23:06:45 +000072#endif
73
Guido van Rossum5f59d601992-12-14 16:59:51 +000074typedef struct {
Barry Warsaw3bdf7461996-12-09 23:16:31 +000075 PyObject_HEAD
Guido van Rossum5f59d601992-12-14 16:59:51 +000076 MP_INT mpz; /* the actual number */
77} mpzobject;
78
Barry Warsaw3bdf7461996-12-09 23:16:31 +000079staticforward PyTypeObject MPZtype;
Guido van Rossum5f59d601992-12-14 16:59:51 +000080
81#define is_mpzobject(v) ((v)->ob_type == &MPZtype)
82
83static const char initialiser_name[] = "mpz";
84
85/* #define MPZ_DEBUG */
86
87static mpzobject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +000088newmpzobject(void)
Guido van Rossum5f59d601992-12-14 16:59:51 +000089{
90 mpzobject *mpzp;
91
92
93#ifdef MPZ_DEBUG
94 fputs( "mpz_object() called...\n", stderr );
95#endif /* def MPZ_DEBUG */
Guido van Rossumb18618d2000-05-03 23:44:39 +000096 mpzp = PyObject_New(mpzobject, &MPZtype);
Guido van Rossum5f59d601992-12-14 16:59:51 +000097 if (mpzp == NULL)
98 return NULL;
99
100 mpz_init(&mpzp->mpz); /* actual initialisation */
101 return mpzp;
102} /* newmpzobject() */
103
104#ifdef MPZ_GET_STR_BUG
Guido van Rossum5f59d601992-12-14 16:59:51 +0000105#include "longlong.h"
106#endif /* def MPZ_GET_STR_BUG */
107
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000108static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +0000109mpz_format(PyObject *objp, int base, unsigned char withname)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000110{
111 mpzobject *mpzp = (mpzobject *)objp;
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000112 PyStringObject *strobjp;
Guido van Rossum2650a422000-06-28 21:29:47 +0000113 size_t i;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000114 int cmpres;
115 int taglong;
116 char *cp;
117 char prefix[5], *tcp;
118
119
120 tcp = &prefix[0];
121
122 if (mpzp == NULL || !is_mpzobject(mpzp)) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000123 PyErr_BadInternalCall();
Guido van Rossum5f59d601992-12-14 16:59:51 +0000124 return NULL;
125 }
126
127 assert(base >= 2 && base <= 36);
128
129 if (withname)
130 i = strlen(initialiser_name) + 2; /* e.g. 'mpz(' + ')' */
131 else
132 i = 0;
133
134 if ((cmpres = mpz_cmp_si(&mpzp->mpz, 0L)) == 0)
135 base = 10; /* '0' in every base, right */
136 else if (cmpres < 0) {
137 *tcp++ = '-';
138 i += 1; /* space to hold '-' */
139 }
140
141#ifdef MPZ_DEBUG
142 fprintf(stderr, "mpz_format: mpz_sizeinbase %d\n",
143 (int)mpz_sizeinbase(&mpzp->mpz, base));
144#endif /* def MPZ_DEBUG */
145#ifdef MPZ_GET_STR_BUG
Guido van Rossum272841c1996-08-19 23:06:45 +0000146#ifdef GMP2
147 i += ((size_t) abs(mpzp->mpz._mp_size) * BITS_PER_MP_LIMB
148 * __mp_bases[base].chars_per_bit_exactly) + 1;
149#else
Guido van Rossum5f59d601992-12-14 16:59:51 +0000150 i += ((size_t) abs(mpzp->mpz.size) * BITS_PER_MP_LIMB
151 * __mp_bases[base].chars_per_bit_exactly) + 1;
Guido van Rossum272841c1996-08-19 23:06:45 +0000152#endif
Guido van Rossum5f59d601992-12-14 16:59:51 +0000153#else /* def MPZ_GET_STR_BUG */
154 i += (int)mpz_sizeinbase(&mpzp->mpz, base);
155#endif /* def MPZ_GET_STR_BUG else */
156
157 if (base == 16) {
158 *tcp++ = '0';
159 *tcp++ = 'x';
160 i += 2; /* space to hold '0x' */
161 }
162 else if (base == 8) {
163 *tcp++ = '0';
164 i += 1; /* space to hold the extra '0' */
165 }
166 else if (base > 10) {
167 *tcp++ = '0' + base / 10;
168 *tcp++ = '0' + base % 10;
169 *tcp++ = '#';
170 i += 3; /* space to hold e.g. '12#' */
171 }
172 else if (base < 10) {
173 *tcp++ = '0' + base;
174 *tcp++ = '#';
175 i += 2; /* space to hold e.g. '6#' */
176 }
177
178 /*
179 ** the following code looks if we need a 'L' attached to the number
180 ** it will also attach an 'L' to the value -0x80000000
181 */
182 taglong = 0;
183 if (mpz_size(&mpzp->mpz) > 1
184 || (long)mpz_get_ui(&mpzp->mpz) < 0L) {
185 taglong = 1;
186 i += 1; /* space to hold 'L' */
187 }
188
189#ifdef MPZ_DEBUG
190 fprintf(stderr, "mpz_format: requesting string size %d\n", i);
191#endif /* def MPZ_DEBUG */
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000192 if ((strobjp =
193 (PyStringObject *)PyString_FromStringAndSize((char *)0, i))
Guido van Rossum5f59d601992-12-14 16:59:51 +0000194 == NULL)
195 return NULL;
196
197 /* get the beginning of the string memory and start copying things */
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000198 cp = PyString_AS_STRING(strobjp);
Guido van Rossum5f59d601992-12-14 16:59:51 +0000199 if (withname) {
200 strcpy(cp, initialiser_name);
201 cp += strlen(initialiser_name);
202 *cp++ = '('; /*')'*/
203 }
204
205 /* copy the already prepared prefix; e.g. sign and base indicator */
206 *tcp = '\0';
207 strcpy(cp, prefix);
208 cp += tcp - prefix;
209
210 /* since' we have the sign already, let the lib think it's a positive
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000211 number */
Guido van Rossum5f59d601992-12-14 16:59:51 +0000212 if (cmpres < 0)
213 mpz_neg(&mpzp->mpz,&mpzp->mpz); /* hack Hack HAck HACk HACK */
214 (void)mpz_get_str(cp, base, &mpzp->mpz);
215 if (cmpres < 0)
216 mpz_neg(&mpzp->mpz,&mpzp->mpz); /* hack Hack HAck HACk HACK */
217#ifdef MPZ_DEBUG
218 fprintf(stderr, "mpz_format: base (ultim) %d, mpz_get_str: %s\n",
219 base, cp);
220#endif /* def MPZ_DEBUG */
221 cp += strlen(cp);
222
223 if (taglong)
224 *cp++ = 'L';
225 if (withname)
226 *cp++ = /*'('*/ ')';
227
228 *cp = '\0';
229
230#ifdef MPZ_DEBUG
231 fprintf(stderr,
Fred Drakea44d3532000-06-30 15:01:00 +0000232 "mpz_format: cp (str end) %p, begin %p, diff %d, i %d\n",
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000233 cp, PyString_AS_STRING(strobjp),
234 cp - PyString_AS_STRING(strobjp), i);
Guido van Rossum5f59d601992-12-14 16:59:51 +0000235#endif /* def MPZ_DEBUG */
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000236 assert(cp - PyString_AS_STRING(strobjp) <= i);
Guido van Rossum5f59d601992-12-14 16:59:51 +0000237
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000238 if (cp - PyString_AS_STRING(strobjp) != i) {
239 strobjp->ob_size -= i - (cp - PyString_AS_STRING(strobjp));
Guido van Rossum5f59d601992-12-14 16:59:51 +0000240 }
241
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000242 return (PyObject *)strobjp;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000243} /* mpz_format() */
244
245/* MPZ methods */
246
247static void
Peter Schneider-Kamp36463662000-07-10 17:14:00 +0000248mpz_dealloc(mpzobject *mpzp)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000249{
250#ifdef MPZ_DEBUG
251 fputs( "mpz_dealloc() called...\n", stderr );
252#endif /* def MPZ_DEBUG */
253 mpz_clear(&mpzp->mpz);
Guido van Rossumb18618d2000-05-03 23:44:39 +0000254 PyObject_Del(mpzp);
Guido van Rossum5f59d601992-12-14 16:59:51 +0000255} /* mpz_dealloc() */
256
Guido van Rossum5f59d601992-12-14 16:59:51 +0000257
258/* pointers to frequently used values 0, 1 and -1 */
259static mpzobject *mpz_value_zero, *mpz_value_one, *mpz_value_mone;
260
261static int
Peter Schneider-Kamp36463662000-07-10 17:14:00 +0000262mpz_compare(mpzobject *a, mpzobject *b)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000263{
264 int cmpres;
265
266
267 /* guido sez it's better to return -1, 0 or 1 */
268 return (cmpres = mpz_cmp( &a->mpz, &b->mpz )) == 0 ? 0
269 : cmpres > 0 ? 1 : -1;
270} /* mpz_compare() */
271
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000272static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +0000273mpz_addition(mpzobject *a, mpzobject *b)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000274{
275 mpzobject *z;
276
277
278#ifdef MPZ_SPARE_MALLOC
279 if (mpz_cmp_ui(&a->mpz, (unsigned long int)0) == 0) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000280 Py_INCREF(b);
281 return (PyObject *)b;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000282 }
283
284 if (mpz_cmp_ui(&b->mpz, (unsigned long int)0) == 0) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000285 Py_INCREF(a);
286 return (PyObject *)a;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000287 }
288#endif /* def MPZ_SPARE_MALLOC */
289
290 if ((z = newmpzobject()) == NULL)
291 return NULL;
292
293 mpz_add(&z->mpz, &a->mpz, &b->mpz);
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000294 return (PyObject *)z;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000295} /* mpz_addition() */
296
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000297static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +0000298mpz_substract(mpzobject *a, mpzobject *b)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000299{
300 mpzobject *z;
301
302
303#ifdef MPZ_SPARE_MALLOC
304 if (mpz_cmp_ui(&b->mpz, (unsigned long int)0) == 0) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000305 Py_INCREF(a);
306 return (PyObject *)a;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000307 }
308#endif /* MPZ_SPARE_MALLOC */
309
310 if ((z = newmpzobject()) == NULL)
311 return NULL;
312
313 mpz_sub(&z->mpz, &a->mpz, &b->mpz);
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000314 return (PyObject *)z;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000315} /* mpz_substract() */
316
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000317static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +0000318mpz_multiply(mpzobject *a, mpzobject *b)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000319{
320#ifdef MPZ_SPARE_MALLOC
321 int cmpres;
322#endif /* def MPZ_SPARE_MALLOC */
323 mpzobject *z;
324
325
326#ifdef MPZ_SPARE_MALLOC
327 if ((cmpres = mpz_cmp_ui(&a->mpz, (unsigned long int)0)) == 0) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000328 Py_INCREF(mpz_value_zero);
329 return (PyObject *)mpz_value_zero;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000330 }
331 if (cmpres > 0 && mpz_cmp_ui(&a->mpz, (unsigned long int)1) == 0) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000332 Py_INCREF(b);
333 return (PyObject *)b;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000334 }
335
336 if ((cmpres = mpz_cmp_ui(&b->mpz, (unsigned long_int)0)) == 0) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000337 Py_INCREF(mpz_value_zero);
338 return (PyObject *)mpz_value_zero;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000339 }
340 if (cmpres > 0 && mpz_cmp_ui(&b->mpz, (unsigned long int)1) == 0) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000341 Py_INCREF(a);
342 return (PyObject *)a;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000343 }
344#endif /* MPZ_SPARE_MALLOC */
345
346 if ((z = newmpzobject()) == NULL)
347 return NULL;
348
349 mpz_mul( &z->mpz, &a->mpz, &b->mpz );
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000350 return (PyObject *)z;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000351
352} /* mpz_multiply() */
353
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000354static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +0000355mpz_divide(mpzobject *a, mpzobject *b)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000356{
357#ifdef MPZ_SPARE_MALLOC
358 int cmpres;
359#endif /* def MPZ_SPARE_MALLOC */
360 mpzobject *z;
361
362
363 if ((
364#ifdef MPZ_SPARE_MALLOC
365 cmpres =
366#endif /* def MPZ_SPARE_MALLOC */
367 mpz_cmp_ui(&b->mpz, (unsigned long int)0)) == 0) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000368 PyErr_SetString(PyExc_ZeroDivisionError, "mpz./ by zero");
Guido van Rossum5f59d601992-12-14 16:59:51 +0000369 return NULL;
370 }
371#ifdef MPZ_SPARE_MALLOC
372 if (cmpres > 0 && mpz_cmp_ui(&b->mpz(unsigned long int)1) == 0) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000373 Py_INCREF(a);
374 return (PyObject *)a;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000375 }
376#endif /* def MPZ_SPARE_MALLOC */
377
378 if ((z = newmpzobject()) == NULL)
379 return NULL;
380
381#ifdef MPZ_TEST_DIV
382 fputs("mpz_divide: div result", stderr);
383 mpz_div(&z->mpz, &a->mpz, &b->mpz);
384 mpz_out_str(stderr, 10, &z->mpz);
385 putc('\n', stderr);
386#endif /* def MPZ_TEST_DIV */
387#ifdef MPZ_MDIV_BUG
388 if ((mpz_cmp_ui(&a->mpz, (unsigned long int)0) < 0)
389 != (mpz_cmp_ui(&b->mpz, (unsigned long int)0) < 0)) {
390 /*
391 ** numerator has other sign than denominator: we have
392 ** to look at the remainder for a correction, since mpz_mdiv
393 ** also calls mpz_divmod, I can as well do it myself
394 */
395 MP_INT tmpmpz;
396
397
398 mpz_init(&tmpmpz);
399 mpz_divmod(&z->mpz, &tmpmpz, &a->mpz, &b->mpz);
400
401 if (mpz_cmp_ui(&tmpmpz, (unsigned long int)0) != 0)
402 mpz_sub_ui(&z->mpz, &z->mpz, (unsigned long int)1);
403
404 mpz_clear(&tmpmpz);
405 }
406 else
407 mpz_div(&z->mpz, &a->mpz, &b->mpz);
408 /* the ``naive'' implementation does it right for operands
409 having the same sign */
410
411#else /* def MPZ_MDIV_BUG */
412 mpz_mdiv(&z->mpz, &a->mpz, &b->mpz);
413#endif /* def MPZ_MDIV_BUG else */
414#ifdef MPZ_TEST_DIV
415 fputs("mpz_divide: mdiv result", stderr);
416 mpz_out_str(stderr, 10, &z->mpz);
417 putc('\n', stderr);
418#endif /* def MPZ_TEST_DIV */
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000419 return (PyObject *)z;
Fred Drakec17b3cf2001-02-12 16:48:13 +0000420
Guido van Rossum5f59d601992-12-14 16:59:51 +0000421} /* mpz_divide() */
422
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000423static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +0000424mpz_remainder(mpzobject *a, mpzobject *b)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000425{
426#ifdef MPZ_SPARE_MALLOC
427 int cmpres;
428#endif /* def MPZ_SPARE_MALLOC */
429 mpzobject *z;
430
Fred Drakec17b3cf2001-02-12 16:48:13 +0000431
Guido van Rossum5f59d601992-12-14 16:59:51 +0000432 if ((
433#ifdef MPZ_SPARE_MALLOC
434 cmpres =
435#endif /* def MPZ_SPARE_MALLOC */
436 mpz_cmp_ui(&b->mpz, (unsigned long int)0)) == 0) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000437 PyErr_SetString(PyExc_ZeroDivisionError, "mpz.% by zero");
Guido van Rossum5f59d601992-12-14 16:59:51 +0000438 return NULL;
439 }
440#ifdef MPZ_SPARE_MALLOC
441 if (cmpres > 0) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000442 if ((cmpres = mpz_cmp_ui(&b->mpz, (unsigned long int)2)) == 0)
443 {
444 Py_INCREF(mpz_value_one);
445 return (PyObject *)mpz_value_one;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000446 }
447 if (cmpres < 0) {
448 /* b must be 1 now */
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000449 Py_INCREF(mpz_value_zero);
450 return (PyObject *)mpz_value_zero;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000451 }
452 }
453#endif /* def MPZ_SPARE_MALLOC */
454
455 if ((z = newmpzobject()) == NULL)
456 return NULL;
457
458#ifdef MPZ_TEST_DIV
459 fputs("mpz_remain: mod result", stderr);
460 mpz_mod(&z->mpz, &a->mpz, &b->mpz);
461 mpz_out_str(stderr, 10, &z->mpz);
462 putc('\n', stderr);
463#endif /* def MPZ_TEST_DIV */
464#ifdef MPZ_MDIV_BUG
465
466 /* the ``naive'' implementation does it right for operands
467 having the same sign */
468 mpz_mod(&z->mpz, &a->mpz, &b->mpz);
469
470 /* assumption: z, a and b all point to different locations */
471 if ((mpz_cmp_ui(&a->mpz, (unsigned long int)0) < 0)
472 != (mpz_cmp_ui(&b->mpz, (unsigned long int)0) < 0)
473 && mpz_cmp_ui(&z->mpz, (unsigned long int)0) != 0)
474 mpz_add(&z->mpz, &z->mpz, &b->mpz);
475 /*
476 ** numerator has other sign than denominator: we have
477 ** to look at the remainder for a correction, since mpz_mdiv
478 ** also calls mpz_divmod, I can as well do it myself
479 */
480#else /* def MPZ_MDIV_BUG */
481 mpz_mmod(&z->mpz, &a->mpz, &b->mpz);
482#endif /* def MPZ_MDIV_BUG else */
483#ifdef MPZ_TEST_DIV
484 fputs("mpz_remain: mmod result", stderr);
485 mpz_out_str(stderr, 10, &z->mpz);
486 putc('\n', stderr);
487#endif /* def MPZ_TEST_DIV */
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000488 return (PyObject *)z;
Fred Drakec17b3cf2001-02-12 16:48:13 +0000489
Guido van Rossum5f59d601992-12-14 16:59:51 +0000490} /* mpz_remainder() */
491
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000492static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +0000493mpz_div_and_mod(mpzobject *a, mpzobject *b)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000494{
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000495 PyObject *z = NULL;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000496 mpzobject *x = NULL, *y = NULL;
497
498
499 if (mpz_cmp_ui(&b->mpz, (unsigned long int)0) == 0) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000500 PyErr_SetString(PyExc_ZeroDivisionError, "mpz.divmod by zero");
Guido van Rossum5f59d601992-12-14 16:59:51 +0000501 return NULL;
502 }
503
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000504 if ((z = PyTuple_New(2)) == NULL
Guido van Rossum5f59d601992-12-14 16:59:51 +0000505 || (x = newmpzobject()) == NULL
506 || (y = newmpzobject()) == NULL) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000507 Py_XDECREF(z);
508 Py_XDECREF(x);
509 Py_XDECREF(y);
Guido van Rossum5f59d601992-12-14 16:59:51 +0000510 return NULL;
511 }
512
513#ifdef MPZ_TEST_DIV
514 fputs("mpz_divmod: dm result", stderr);
515 mpz_divmod(&x->mpz, &y->mpz, &a->mpz, &b->mpz);
516 mpz_out_str(stderr, 10, &x->mpz);
517 putc('\n', stderr);
518 mpz_out_str(stderr, 10, &y->mpz);
519 putc('\n', stderr);
520#endif /* def MPZ_TEST_DIV */
521#ifdef MPZ_MDIV_BUG
522 mpz_divmod(&x->mpz, &y->mpz, &a->mpz, &b->mpz);
523 if ((mpz_cmp_ui(&a->mpz, (unsigned long int)0) < 0)
524 != (mpz_cmp_ui(&b->mpz, (unsigned long int)0) < 0)
525 && mpz_cmp_ui(&y->mpz, (unsigned long int)0) != 0) {
526 /*
527 ** numerator has other sign than denominator: we have
528 ** to look at the remainder for a correction.
529 */
530 mpz_add(&y->mpz, &y->mpz, &b->mpz);
531 mpz_sub_ui(&x->mpz, &x->mpz, (unsigned long int)1);
532 }
533#else /* def MPZ_MDIV_BUG */
534 mpz_mdivmod( &x->mpz, &y->mpz, &a->mpz, &b->mpz );
535#endif /* def MPZ_MDIV_BUG else */
536#ifdef MPZ_TEST_DIV
537 fputs("mpz_divmod: mdm result", stderr);
538 mpz_out_str(stderr, 10, &x->mpz);
539 putc('\n', stderr);
540 mpz_out_str(stderr, 10, &y->mpz);
541 putc('\n', stderr);
542#endif /* def MPZ_TEST_DIV */
543
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000544 (void)PyTuple_SetItem(z, 0, (PyObject *)x);
545 (void)PyTuple_SetItem(z, 1, (PyObject *)y);
Fred Drakec17b3cf2001-02-12 16:48:13 +0000546
Guido van Rossum5f59d601992-12-14 16:59:51 +0000547 return z;
548} /* mpz_div_and_mod() */
549
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000550static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +0000551mpz_power(mpzobject *a, mpzobject *b, mpzobject *m)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000552{
553 mpzobject *z;
554 int cmpres;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000555
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000556 if ((PyObject *)m != Py_None) {
557 mpzobject *z2;
558 Py_INCREF(Py_None);
559 z=(mpzobject *)mpz_power(a, b, (mpzobject *)Py_None);
560 Py_DECREF(Py_None);
561 if (z==NULL) return((PyObject *)z);
562 z2=(mpzobject *)mpz_remainder(z, m);
563 Py_DECREF(z);
564 return((PyObject *)z2);
565 }
Guido van Rossum5f59d601992-12-14 16:59:51 +0000566
567 if ((cmpres = mpz_cmp_ui(&b->mpz, (unsigned long int)0)) == 0) {
568 /* the gnu-mp lib sets pow(0,0) to 0, we to 1 */
569
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000570 Py_INCREF(mpz_value_one);
571 return (PyObject *)mpz_value_one;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000572 }
Fred Drakec17b3cf2001-02-12 16:48:13 +0000573
Guido van Rossum5f59d601992-12-14 16:59:51 +0000574 if (cmpres < 0) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000575 PyErr_SetString(PyExc_ValueError,
576 "mpz.pow to negative exponent");
Guido van Rossum5f59d601992-12-14 16:59:51 +0000577 return NULL;
578 }
579
580 if ((cmpres = mpz_cmp_ui(&a->mpz, (unsigned long int)0)) == 0) {
581 /* the base is 0 */
582
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000583 Py_INCREF(mpz_value_zero);
584 return (PyObject *)mpz_value_zero;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000585 }
586 else if (cmpres > 0
587 && mpz_cmp_ui(&a->mpz, (unsigned long int)1) == 0) {
588 /* the base is 1 */
589
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000590 Py_INCREF(mpz_value_one);
591 return (PyObject *)mpz_value_one;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000592 }
593 else if (cmpres < 0
594 && mpz_cmp_si(&a->mpz, (long int)-1) == 0) {
595
596 MP_INT tmpmpz;
597 /* the base is -1: pow(-1, any) == 1,-1 for even,uneven b */
598 /* XXX this code needs to be optimized: what's better?
599 mpz_mmod_ui or mpz_mod_2exp, I choose for the latter
600 for *un*obvious reasons */
601
602 /* is the exponent even? */
603 mpz_init(&tmpmpz);
604
605 /* look to the remainder after a division by (1 << 1) */
606 mpz_mod_2exp(&tmpmpz, &b->mpz, (unsigned long int)1);
607
608 if (mpz_cmp_ui(&tmpmpz, (unsigned int)0) == 0) {
609 mpz_clear(&tmpmpz);
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000610 Py_INCREF(mpz_value_one);
611 return (PyObject *)mpz_value_one;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000612 }
613 mpz_clear(&tmpmpz);
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000614 Py_INCREF(mpz_value_mone);
615 return (PyObject *)mpz_value_mone;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000616 }
617
618#ifdef MPZ_LIB_DOES_CHECKING
619 /* check if it's doable: sizeof(exp) > sizeof(long) &&
620 abs(base) > 1 ?? --> No Way */
621 if (mpz_size(&b->mpz) > 1)
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000622 return (PyObject *)PyErr_NoMemory();
Guido van Rossum5f59d601992-12-14 16:59:51 +0000623#else /* def MPZ_LIB_DOES_CHECKING */
624 /* wet finger method */
625 if (mpz_cmp_ui(&b->mpz, (unsigned long int)0x10000) >= 0) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000626 PyErr_SetString(PyExc_ValueError,
627 "mpz.pow outrageous exponent");
Guido van Rossum5f59d601992-12-14 16:59:51 +0000628 return NULL;
629 }
630#endif /* def MPZ_LIB_DOES_CHECKING else */
631
632 if ((z = newmpzobject()) == NULL)
633 return NULL;
Fred Drakec17b3cf2001-02-12 16:48:13 +0000634
Guido van Rossum5f59d601992-12-14 16:59:51 +0000635 mpz_pow_ui(&z->mpz, &a->mpz, mpz_get_ui(&b->mpz));
Fred Drakec17b3cf2001-02-12 16:48:13 +0000636
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000637 return (PyObject *)z;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000638} /* mpz_power() */
639
640
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000641static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +0000642mpz_negative(mpzobject *v)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000643{
644 mpzobject *z;
645
Fred Drakec17b3cf2001-02-12 16:48:13 +0000646
Guido van Rossum5f59d601992-12-14 16:59:51 +0000647#ifdef MPZ_SPARE_MALLOC
648 if (mpz_cmp_ui(&v->mpz, (unsigned long int)0) == 0) {
649 /* -0 == 0 */
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000650 Py_INCREF(v);
651 return (PyObject *)v;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000652 }
653#endif /* def MPZ_SPARE_MALLOC */
654
655 if ((z = newmpzobject()) == NULL)
656 return NULL;
657
658 mpz_neg(&z->mpz, &v->mpz);
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000659 return (PyObject *)z;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000660} /* mpz_negative() */
661
662
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000663static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +0000664mpz_positive(mpzobject *v)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000665{
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000666 Py_INCREF(v);
667 return (PyObject *)v;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000668} /* mpz_positive() */
669
670
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000671static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +0000672mpz_absolute(mpzobject *v)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000673{
674 mpzobject *z;
675
Fred Drakec17b3cf2001-02-12 16:48:13 +0000676
Guido van Rossum5f59d601992-12-14 16:59:51 +0000677 if (mpz_cmp_ui(&v->mpz, (unsigned long int)0) >= 0) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000678 Py_INCREF(v);
679 return (PyObject *)v;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000680 }
681
682 if ((z = newmpzobject()) == NULL)
683 return NULL;
684
685 mpz_neg(&z->mpz, &v->mpz);
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000686 return (PyObject *)z;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000687} /* mpz_absolute() */
688
689static int
Peter Schneider-Kamp36463662000-07-10 17:14:00 +0000690mpz_nonzero(mpzobject *v)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000691{
692 return mpz_cmp_ui(&v->mpz, (unsigned long int)0) != 0;
693} /* mpz_nonzero() */
694
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000695static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +0000696py_mpz_invert(mpzobject *v)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000697{
698 mpzobject *z;
699
700
701 /* I think mpz_com does exactly what needed */
702 if ((z = newmpzobject()) == NULL)
703 return NULL;
704
705 mpz_com(&z->mpz, &v->mpz);
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000706 return (PyObject *)z;
Guido van Rossum272841c1996-08-19 23:06:45 +0000707} /* py_mpz_invert() */
Guido van Rossum5f59d601992-12-14 16:59:51 +0000708
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000709static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +0000710mpz_lshift(mpzobject *a, mpzobject *b)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000711{
712 int cmpres;
713 mpzobject *z;
714
715
716 if ((cmpres = mpz_cmp_ui(&b->mpz, (unsigned long int)0)) == 0) {
717 /* a << 0 == a */
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000718 Py_INCREF(a);
719 return (PyObject *)a;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000720 }
721
722 if (cmpres < 0) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000723 PyErr_SetString(PyExc_ValueError,
724 "mpz.<< negative shift count");
Guido van Rossum5f59d601992-12-14 16:59:51 +0000725 return NULL;
726 }
727
728#ifdef MPZ_LIB_DOES_CHECKING
729 if (mpz_size(&b->mpz) > 1)
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000730 return (PyObject *)PyErr_NoMemory();
Guido van Rossum5f59d601992-12-14 16:59:51 +0000731#else /* def MPZ_LIB_DOES_CHECKING */
732 /* wet finger method */
733 if (mpz_cmp_ui(&b->mpz, (unsigned long int)0x10000) >= 0) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000734 PyErr_SetString(PyExc_ValueError,
735 "mpz.<< outrageous shift count");
Guido van Rossum5f59d601992-12-14 16:59:51 +0000736 return NULL;
737 }
738#endif /* def MPZ_LIB_DOES_CHECKING else */
739
740 if ((z = newmpzobject()) == NULL)
741 return NULL;
742
743 mpz_mul_2exp(&z->mpz, &a->mpz, mpz_get_ui(&b->mpz));
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000744 return (PyObject *)z;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000745} /* mpz_lshift() */
746
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000747static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +0000748mpz_rshift(mpzobject *a, mpzobject *b)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000749{
750 int cmpres;
751 mpzobject *z;
752
753
754 if ((cmpres = mpz_cmp_ui(&b->mpz, (unsigned long int)0)) == 0) {
755 /* a >> 0 == a */
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000756 Py_INCREF(a);
757 return (PyObject *)a;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000758 }
759
760 if (cmpres < 0) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000761 PyErr_SetString(PyExc_ValueError,
762 "mpz.>> negative shift count");
Guido van Rossum5f59d601992-12-14 16:59:51 +0000763 return NULL;
764 }
765
766 if (mpz_size(&b->mpz) > 1)
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000767 return (PyObject *)PyErr_NoMemory();
Guido van Rossum5f59d601992-12-14 16:59:51 +0000768
769 if ((z = newmpzobject()) == NULL)
770 return NULL;
771
772 mpz_div_2exp(&z->mpz, &a->mpz, mpz_get_ui(&b->mpz));
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000773 return (PyObject *)z;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000774} /* mpz_rshift() */
775
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000776static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +0000777mpz_andfunc(mpzobject *a, mpzobject *b)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000778{
779 mpzobject *z;
780
781
782 if ((z = newmpzobject()) == NULL)
783 return NULL;
784
785 mpz_and(&z->mpz, &a->mpz, &b->mpz);
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000786 return (PyObject *)z;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000787} /* mpz_andfunc() */
788
789/* hack Hack HAck HACk HACK, XXX this code is dead slow */
790void
Peter Schneider-Kamp36463662000-07-10 17:14:00 +0000791mpz_xor(MP_INT *res, const MP_INT *op1, const MP_INT *op2)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000792{
793 MP_INT tmpmpz;
Fred Drakec17b3cf2001-02-12 16:48:13 +0000794
Guido van Rossum5f59d601992-12-14 16:59:51 +0000795 mpz_init(&tmpmpz);
796
797 mpz_and(res, op1, op2);
798 mpz_com(&tmpmpz, res);
799 mpz_ior(res, op1, op2);
800 mpz_and(res, res, &tmpmpz);
801
802 mpz_clear(&tmpmpz);
803} /* mpz_xor() HACK */
804
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000805static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +0000806mpz_xorfunc(mpzobject *a, mpzobject *b)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000807{
808 mpzobject *z;
809
810
811 if ((z = newmpzobject()) == NULL)
812 return NULL;
813
814 mpz_xor(&z->mpz, &a->mpz, &b->mpz);
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000815 return (PyObject *)z;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000816} /* mpz_xorfunc() */
817
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000818static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +0000819mpz_orfunc(mpzobject *a, mpzobject *b)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000820{
821 mpzobject *z;
822
823
824 if ((z = newmpzobject()) == NULL)
825 return NULL;
826
827 mpz_ior(&z->mpz, &a->mpz, &b->mpz);
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000828 return (PyObject *)z;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000829} /* mpz_orfunc() */
830
831/* MPZ initialisation */
832
833#include "longintrepr.h"
834
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000835static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +0000836MPZ_mpz(PyObject *self, PyObject *args)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000837{
838 mpzobject *mpzp;
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000839 PyObject *objp;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000840
841
842#ifdef MPZ_DEBUG
843 fputs("MPZ_mpz() called...\n", stderr);
844#endif /* def MPZ_DEBUG */
845
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000846 if (!PyArg_Parse(args, "O", &objp))
Guido van Rossum5f59d601992-12-14 16:59:51 +0000847 return NULL;
848
849 /* at least we know it's some object */
Barry Warsawabb7efe1996-12-09 23:22:35 +0000850 /* note DON't Py_DECREF args NEITHER objp */
Guido van Rossum5f59d601992-12-14 16:59:51 +0000851
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000852 if (PyInt_Check(objp)) {
Guido van Rossum5f59d601992-12-14 16:59:51 +0000853 long lval;
854
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000855 if (!PyArg_Parse(objp, "l", &lval))
Guido van Rossum5f59d601992-12-14 16:59:51 +0000856 return NULL;
Fred Drakec17b3cf2001-02-12 16:48:13 +0000857
Guido van Rossum5f59d601992-12-14 16:59:51 +0000858 if (lval == (long)0) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000859 Py_INCREF(mpz_value_zero);
Guido van Rossum5f59d601992-12-14 16:59:51 +0000860 mpzp = mpz_value_zero;
861 }
862 else if (lval == (long)1) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000863 Py_INCREF(mpz_value_one);
Guido van Rossum5f59d601992-12-14 16:59:51 +0000864 mpzp = mpz_value_one;
865 }
866 else if ((mpzp = newmpzobject()) == NULL)
867 return NULL;
868 else mpz_set_si(&mpzp->mpz, lval);
869 }
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000870 else if (PyLong_Check(objp)) {
Guido van Rossum5f59d601992-12-14 16:59:51 +0000871 MP_INT mplongdigit;
872 int i;
873 unsigned char isnegative;
Fred Drakec17b3cf2001-02-12 16:48:13 +0000874
Guido van Rossum5f59d601992-12-14 16:59:51 +0000875
876 if ((mpzp = newmpzobject()) == NULL)
877 return NULL;
878
879 mpz_set_si(&mpzp->mpz, 0L);
880 mpz_init(&mplongdigit);
Fred Drakec17b3cf2001-02-12 16:48:13 +0000881
Guido van Rossum5f59d601992-12-14 16:59:51 +0000882 /* how we're gonna handle this? */
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000883 if ((isnegative =
884 ((i = ((PyLongObject *)objp)->ob_size) < 0) ))
Guido van Rossum5f59d601992-12-14 16:59:51 +0000885 i = -i;
886
887 while (i--) {
888 mpz_set_ui(&mplongdigit,
889 (unsigned long)
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000890 ((PyLongObject *)objp)->ob_digit[i]);
Guido van Rossum5f59d601992-12-14 16:59:51 +0000891 mpz_mul_2exp(&mplongdigit,&mplongdigit,
892 (unsigned long int)i * SHIFT);
893 mpz_ior(&mpzp->mpz, &mpzp->mpz, &mplongdigit);
894 }
895
896 if (isnegative)
897 mpz_neg(&mpzp->mpz, &mpzp->mpz);
898
899 /* get rid of allocation for tmp variable */
900 mpz_clear(&mplongdigit);
901 }
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000902 else if (PyString_Check(objp)) {
Andrew M. Kuchling4c07f811998-12-14 19:36:14 +0000903 unsigned char *cp = (unsigned char *)PyString_AS_STRING(objp);
Guido van Rossum7e488981998-10-08 02:25:24 +0000904 int len = PyString_GET_SIZE(objp);
Guido van Rossum5f59d601992-12-14 16:59:51 +0000905 MP_INT mplongdigit;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000906
907 if ((mpzp = newmpzobject()) == NULL)
908 return NULL;
909
910 mpz_set_si(&mpzp->mpz, 0L);
911 mpz_init(&mplongdigit);
Fred Drakec17b3cf2001-02-12 16:48:13 +0000912
Guido van Rossum5f59d601992-12-14 16:59:51 +0000913 /* let's do it the same way as with the long conversion:
914 without thinking how it can be faster (-: :-) */
915
916 cp += len;
917 while (len--) {
918 mpz_set_ui(&mplongdigit, (unsigned long)*--cp );
919 mpz_mul_2exp(&mplongdigit,&mplongdigit,
920 (unsigned long int)len * 8);
921 mpz_ior(&mpzp->mpz, &mpzp->mpz, &mplongdigit);
922 }
923
924 /* get rid of allocation for tmp variable */
925 mpz_clear(&mplongdigit);
926 }
927 else if (is_mpzobject(objp)) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000928 Py_INCREF(objp);
Guido van Rossum5f59d601992-12-14 16:59:51 +0000929 mpzp = (mpzobject *)objp;
930 }
931 else {
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000932 PyErr_SetString(PyExc_TypeError,
933"mpz.mpz() expects integer, long, string or mpz object argument");
Guido van Rossum5f59d601992-12-14 16:59:51 +0000934 return NULL;
935 }
936
937
938#ifdef MPZ_DEBUG
939 fputs("MPZ_mpz: created mpz=", stderr);
940 mpz_out_str(stderr, 10, &mpzp->mpz);
941 putc('\n', stderr);
942#endif /* def MPZ_DEBUG */
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000943 return (PyObject *)mpzp;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000944} /* MPZ_mpz() */
945
946static mpzobject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +0000947mpz_mpzcoerce(PyObject *z)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000948{
949 /* shortcut: 9 out of 10 times the type is already ok */
950 if (is_mpzobject(z)) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000951 Py_INCREF(z);
Guido van Rossum5f59d601992-12-14 16:59:51 +0000952 return (mpzobject *)z; /* coercion succeeded */
953 }
954
955 /* what types do we accept?: intobjects and longobjects */
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000956 if (PyInt_Check(z) || PyLong_Check(z))
957 return (mpzobject *)MPZ_mpz((PyObject *)NULL, z);
Guido van Rossum5f59d601992-12-14 16:59:51 +0000958
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000959 PyErr_SetString(PyExc_TypeError,
960 "number coercion (to mpzobject) failed");
Guido van Rossum5f59d601992-12-14 16:59:51 +0000961 return NULL;
962} /* mpz_mpzcoerce() */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000963
964/* Forward */
Tim Petersdbd9ba62000-07-09 03:09:57 +0000965static void mpz_divm(MP_INT *res, const MP_INT *num,
966 const MP_INT *den, const MP_INT *mod);
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000967
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000968static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +0000969MPZ_powm(PyObject *self, PyObject *args)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000970{
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000971 PyObject *base, *exp, *mod;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000972 mpzobject *mpzbase = NULL, *mpzexp = NULL, *mpzmod = NULL;
973 mpzobject *z;
974 int tstres;
975
Fred Drakec17b3cf2001-02-12 16:48:13 +0000976
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000977 if (!PyArg_Parse(args, "(OOO)", &base, &exp, &mod))
Guido van Rossum5f59d601992-12-14 16:59:51 +0000978 return NULL;
979
980 if ((mpzbase = mpz_mpzcoerce(base)) == NULL
981 || (mpzexp = mpz_mpzcoerce(exp)) == NULL
982 || (mpzmod = mpz_mpzcoerce(mod)) == NULL
983 || (z = newmpzobject()) == NULL) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000984 Py_XDECREF(mpzbase);
985 Py_XDECREF(mpzexp);
986 Py_XDECREF(mpzmod);
Guido van Rossum5f59d601992-12-14 16:59:51 +0000987 return NULL;
988 }
989
990 if ((tstres=mpz_cmp_ui(&mpzexp->mpz, (unsigned long int)0)) == 0) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +0000991 Py_INCREF(mpz_value_one);
992 return (PyObject *)mpz_value_one;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000993 }
994
995 if (tstres < 0) {
996 MP_INT absexp;
997 /* negative exp */
998
999 mpz_init_set(&absexp, &mpzexp->mpz);
1000 mpz_abs(&absexp, &absexp);
1001 mpz_powm(&z->mpz, &mpzbase->mpz, &absexp, &mpzmod->mpz);
1002
1003 mpz_divm(&z->mpz, &mpz_value_one->mpz, &z->mpz, &mpzmod->mpz);
1004
1005 mpz_clear(&absexp);
1006 }
1007 else {
1008 mpz_powm(&z->mpz, &mpzbase->mpz, &mpzexp->mpz, &mpzmod->mpz);
1009 }
Fred Drakec17b3cf2001-02-12 16:48:13 +00001010
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001011 Py_DECREF(mpzbase);
1012 Py_DECREF(mpzexp);
1013 Py_DECREF(mpzmod);
Guido van Rossum5f59d601992-12-14 16:59:51 +00001014
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001015 return (PyObject *)z;
Guido van Rossum5f59d601992-12-14 16:59:51 +00001016} /* MPZ_powm() */
1017
1018
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001019static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +00001020MPZ_gcd(PyObject *self, PyObject *args)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001021{
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001022 PyObject *op1, *op2;
Guido van Rossum5f59d601992-12-14 16:59:51 +00001023 mpzobject *mpzop1 = NULL, *mpzop2 = NULL;
1024 mpzobject *z;
1025
Fred Drakec17b3cf2001-02-12 16:48:13 +00001026
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001027 if (!PyArg_Parse(args, "(OO)", &op1, &op2))
Guido van Rossum5f59d601992-12-14 16:59:51 +00001028 return NULL;
1029
1030 if ((mpzop1 = mpz_mpzcoerce(op1)) == NULL
1031 || (mpzop2 = mpz_mpzcoerce(op2)) == NULL
1032 || (z = newmpzobject()) == NULL) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001033 Py_XDECREF(mpzop1);
1034 Py_XDECREF(mpzop2);
Guido van Rossum5f59d601992-12-14 16:59:51 +00001035 return NULL;
1036 }
1037
1038 /* ok, we have three mpzobjects, and an initialised result holder */
1039 mpz_gcd(&z->mpz, &mpzop1->mpz, &mpzop2->mpz);
1040
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001041 Py_DECREF(mpzop1);
1042 Py_DECREF(mpzop2);
Guido van Rossum5f59d601992-12-14 16:59:51 +00001043
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001044 return (PyObject *)z;
Guido van Rossum5f59d601992-12-14 16:59:51 +00001045} /* MPZ_gcd() */
1046
1047
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001048static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +00001049MPZ_gcdext(PyObject *self, PyObject *args)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001050{
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001051 PyObject *op1, *op2, *z = NULL;
Guido van Rossum5f59d601992-12-14 16:59:51 +00001052 mpzobject *mpzop1 = NULL, *mpzop2 = NULL;
1053 mpzobject *g = NULL, *s = NULL, *t = NULL;
1054
Fred Drakec17b3cf2001-02-12 16:48:13 +00001055
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001056 if (!PyArg_Parse(args, "(OO)", &op1, &op2))
Guido van Rossum5f59d601992-12-14 16:59:51 +00001057 return NULL;
1058
1059 if ((mpzop1 = mpz_mpzcoerce(op1)) == NULL
1060 || (mpzop2 = mpz_mpzcoerce(op2)) == NULL
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001061 || (z = PyTuple_New(3)) == NULL
Guido van Rossum5f59d601992-12-14 16:59:51 +00001062 || (g = newmpzobject()) == NULL
1063 || (s = newmpzobject()) == NULL
1064 || (t = newmpzobject()) == NULL) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001065 Py_XDECREF(mpzop1);
1066 Py_XDECREF(mpzop2);
1067 Py_XDECREF(z);
1068 Py_XDECREF(g);
1069 Py_XDECREF(s);
Barry Warsawabb7efe1996-12-09 23:22:35 +00001070 /*Py_XDECREF(t);*/
Guido van Rossum5f59d601992-12-14 16:59:51 +00001071 return NULL;
1072 }
1073
1074 mpz_gcdext(&g->mpz, &s->mpz, &t->mpz, &mpzop1->mpz, &mpzop2->mpz);
1075
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001076 Py_DECREF(mpzop1);
1077 Py_DECREF(mpzop2);
Guido van Rossum5f59d601992-12-14 16:59:51 +00001078
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001079 (void)PyTuple_SetItem(z, 0, (PyObject *)g);
1080 (void)PyTuple_SetItem(z, 1, (PyObject *)s);
1081 (void)PyTuple_SetItem(z, 2, (PyObject *)t);
Guido van Rossum5f59d601992-12-14 16:59:51 +00001082
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001083 return (PyObject *)z;
Guido van Rossum5f59d601992-12-14 16:59:51 +00001084} /* MPZ_gcdext() */
1085
1086
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001087static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +00001088MPZ_sqrt(PyObject *self, PyObject *args)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001089{
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001090 PyObject *op;
Guido van Rossum5f59d601992-12-14 16:59:51 +00001091 mpzobject *mpzop = NULL;
1092 mpzobject *z;
1093
Fred Drakec17b3cf2001-02-12 16:48:13 +00001094
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001095 if (!PyArg_Parse(args, "O", &op))
Guido van Rossum5f59d601992-12-14 16:59:51 +00001096 return NULL;
1097
1098 if ((mpzop = mpz_mpzcoerce(op)) == NULL
1099 || (z = newmpzobject()) == NULL) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001100 Py_XDECREF(mpzop);
Guido van Rossum5f59d601992-12-14 16:59:51 +00001101 return NULL;
1102 }
1103
1104 mpz_sqrt(&z->mpz, &mpzop->mpz);
1105
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001106 Py_DECREF(mpzop);
Guido van Rossum5f59d601992-12-14 16:59:51 +00001107
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001108 return (PyObject *)z;
Guido van Rossum5f59d601992-12-14 16:59:51 +00001109} /* MPZ_sqrt() */
1110
1111
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001112static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +00001113MPZ_sqrtrem(PyObject *self, PyObject *args)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001114{
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001115 PyObject *op, *z = NULL;
Guido van Rossum5f59d601992-12-14 16:59:51 +00001116 mpzobject *mpzop = NULL;
1117 mpzobject *root = NULL, *rem = NULL;
1118
Fred Drakec17b3cf2001-02-12 16:48:13 +00001119
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001120 if (!PyArg_Parse(args, "O", &op))
Guido van Rossum5f59d601992-12-14 16:59:51 +00001121 return NULL;
1122
1123 if ((mpzop = mpz_mpzcoerce(op)) == NULL
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001124 || (z = PyTuple_New(2)) == NULL
Guido van Rossum5f59d601992-12-14 16:59:51 +00001125 || (root = newmpzobject()) == NULL
1126 || (rem = newmpzobject()) == NULL) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001127 Py_XDECREF(mpzop);
1128 Py_XDECREF(z);
1129 Py_XDECREF(root);
Barry Warsawabb7efe1996-12-09 23:22:35 +00001130 /*Py_XDECREF(rem);*/
Guido van Rossum5f59d601992-12-14 16:59:51 +00001131 return NULL;
1132 }
1133
1134 mpz_sqrtrem(&root->mpz, &rem->mpz, &mpzop->mpz);
1135
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001136 Py_DECREF(mpzop);
Guido van Rossum5f59d601992-12-14 16:59:51 +00001137
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001138 (void)PyTuple_SetItem(z, 0, (PyObject *)root);
1139 (void)PyTuple_SetItem(z, 1, (PyObject *)rem);
Guido van Rossum5f59d601992-12-14 16:59:51 +00001140
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001141 return (PyObject *)z;
Guido van Rossum5f59d601992-12-14 16:59:51 +00001142} /* MPZ_sqrtrem() */
1143
1144
Guido van Rossum67a5fdb1993-12-17 12:09:14 +00001145static void
Guido van Rossum5f59d601992-12-14 16:59:51 +00001146mpz_divm(MP_INT *res, const MP_INT *num, const MP_INT *den, const MP_INT *mod)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001147{
1148 MP_INT s0, s1, q, r, x, d0, d1;
1149
1150 mpz_init_set(&s0, num);
1151 mpz_init_set_ui(&s1, 0);
1152 mpz_init(&q);
1153 mpz_init(&r);
1154 mpz_init(&x);
1155 mpz_init_set(&d0, den);
1156 mpz_init_set(&d1, mod);
1157
Guido van Rossum272841c1996-08-19 23:06:45 +00001158#ifdef GMP2
1159 while (d1._mp_size != 0) {
1160#else
Guido van Rossum5f59d601992-12-14 16:59:51 +00001161 while (d1.size != 0) {
Guido van Rossum272841c1996-08-19 23:06:45 +00001162#endif
Guido van Rossum5f59d601992-12-14 16:59:51 +00001163 mpz_divmod(&q, &r, &d0, &d1);
1164 mpz_set(&d0, &d1);
1165 mpz_set(&d1, &r);
1166
1167 mpz_mul(&x, &s1, &q);
1168 mpz_sub(&x, &s0, &x);
1169 mpz_set(&s0, &s1);
1170 mpz_set(&s1, &x);
1171 }
1172
Guido van Rossum272841c1996-08-19 23:06:45 +00001173#ifdef GMP2
1174 if (d0._mp_size != 1 || d0._mp_d[0] != 1)
1175 res->_mp_size = 0; /* trouble: the gcd != 1; set s to zero */
1176#else
Guido van Rossum5f59d601992-12-14 16:59:51 +00001177 if (d0.size != 1 || d0.d[0] != 1)
1178 res->size = 0; /* trouble: the gcd != 1; set s to zero */
Guido van Rossum272841c1996-08-19 23:06:45 +00001179#endif
Guido van Rossum5f59d601992-12-14 16:59:51 +00001180 else {
1181#ifdef MPZ_MDIV_BUG
1182 /* watch out here! first check the signs, and then perform
1183 the mpz_mod() since mod could point to res */
1184 if ((s0.size < 0) != (mod->size < 0)) {
1185 mpz_mod(res, &s0, mod);
1186
1187 if (res->size)
1188 mpz_add(res, res, mod);
1189 }
1190 else
1191 mpz_mod(res, &s0, mod);
Fred Drakec17b3cf2001-02-12 16:48:13 +00001192
Guido van Rossum5f59d601992-12-14 16:59:51 +00001193#else /* def MPZ_MDIV_BUG */
1194 mpz_mmod(res, &s0, mod);
1195#endif /* def MPZ_MDIV_BUG else */
1196 }
1197
1198 mpz_clear(&s0);
1199 mpz_clear(&s1);
1200 mpz_clear(&q);
1201 mpz_clear(&r);
1202 mpz_clear(&x);
1203 mpz_clear(&d0);
1204 mpz_clear(&d1);
1205} /* mpz_divm() */
1206
1207
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001208static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +00001209MPZ_divm(PyObject *self, PyObject *args)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001210{
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001211 PyObject *num, *den, *mod;
Fred Drake06fdd2d2000-10-11 21:53:34 +00001212 mpzobject *mpznum, *mpzden = NULL, *mpzmod = NULL;
Guido van Rossum5f59d601992-12-14 16:59:51 +00001213 mpzobject *z = NULL;
1214
Fred Drakec17b3cf2001-02-12 16:48:13 +00001215
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001216 if (!PyArg_Parse(args, "(OOO)", &num, &den, &mod))
Guido van Rossum5f59d601992-12-14 16:59:51 +00001217 return NULL;
1218
1219 if ((mpznum = mpz_mpzcoerce(num)) == NULL
1220 || (mpzden = mpz_mpzcoerce(den)) == NULL
1221 || (mpzmod = mpz_mpzcoerce(mod)) == NULL
1222 || (z = newmpzobject()) == NULL ) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001223 Py_XDECREF(mpznum);
1224 Py_XDECREF(mpzden);
1225 Py_XDECREF(mpzmod);
Guido van Rossum5f59d601992-12-14 16:59:51 +00001226 return NULL;
1227 }
Fred Drakec17b3cf2001-02-12 16:48:13 +00001228
Guido van Rossum5f59d601992-12-14 16:59:51 +00001229 mpz_divm(&z->mpz, &mpznum->mpz, &mpzden->mpz, &mpzmod->mpz);
1230
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001231 Py_DECREF(mpznum);
1232 Py_DECREF(mpzden);
1233 Py_DECREF(mpzmod);
Guido van Rossum5f59d601992-12-14 16:59:51 +00001234
1235 if (mpz_cmp_ui(&z->mpz, (unsigned long int)0) == 0) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001236 Py_DECREF(z);
1237 PyErr_SetString(PyExc_ValueError,
1238 "gcd(den, mod) != 1 or num == 0");
Guido van Rossum5f59d601992-12-14 16:59:51 +00001239 return NULL;
1240 }
1241
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001242 return (PyObject *)z;
Guido van Rossum5f59d601992-12-14 16:59:51 +00001243} /* MPZ_divm() */
1244
1245
1246/* MPZ methods-as-attributes */
1247#ifdef MPZ_CONVERSIONS_AS_METHODS
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001248static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +00001249mpz_int(mpzobject *self, PyObject *args)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001250#else /* def MPZ_CONVERSIONS_AS_METHODS */
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001251static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +00001252mpz_int(mpzobject *self)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001253#endif /* def MPZ_CONVERSIONS_AS_METHODS else */
1254{
1255 long sli;
1256
1257
1258#ifdef MPZ_CONVERSIONS_AS_METHODS
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001259 if (!PyArg_NoArgs(args))
Guido van Rossum5f59d601992-12-14 16:59:51 +00001260 return NULL;
1261#endif /* def MPZ_CONVERSIONS_AS_METHODS */
1262
1263 if (mpz_size(&self->mpz) > 1
1264 || (sli = (long)mpz_get_ui(&self->mpz)) < (long)0 ) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001265 PyErr_SetString(PyExc_ValueError,
1266 "mpz.int() arg too long to convert");
Guido van Rossum5f59d601992-12-14 16:59:51 +00001267 return NULL;
1268 }
1269
1270 if (mpz_cmp_ui(&self->mpz, (unsigned long)0) < 0)
1271 sli = -sli;
1272
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001273 return PyInt_FromLong(sli);
Guido van Rossum5f59d601992-12-14 16:59:51 +00001274} /* mpz_int() */
1275
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001276static PyObject *
Guido van Rossum5f59d601992-12-14 16:59:51 +00001277#ifdef MPZ_CONVERSIONS_AS_METHODS
Peter Schneider-Kamp36463662000-07-10 17:14:00 +00001278mpz_long(mpzobject *self, PyObject *args)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001279#else /* def MPZ_CONVERSIONS_AS_METHODS */
Peter Schneider-Kamp36463662000-07-10 17:14:00 +00001280mpz_long(mpzobject *self)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001281#endif /* def MPZ_CONVERSIONS_AS_METHODS else */
1282{
1283 int i, isnegative;
1284 unsigned long int uli;
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001285 PyLongObject *longobjp;
Guido van Rossum5f59d601992-12-14 16:59:51 +00001286 int ldcount;
1287 int bitpointer, newbitpointer;
1288 MP_INT mpzscratch;
1289
1290
1291#ifdef MPZ_CONVERSIONS_AS_METHODS
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001292 if (!PyArg_NoArgs(args))
Guido van Rossum5f59d601992-12-14 16:59:51 +00001293 return NULL;
1294#endif /* def MPZ_CONVERSIONS_AS_METHODS */
1295
1296 /* determine length of python-long to be allocated */
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001297 if ((longobjp = _PyLong_New(i = (int)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001298 ((mpz_size(&self->mpz) * BITS_PER_MP_LIMB
1299 + SHIFT - 1) /
1300 SHIFT))) == NULL)
1301 return NULL;
1302
1303 /* determine sign, and copy self to scratch var */
1304 mpz_init_set(&mpzscratch, &self->mpz);
Guido van Rossum272841c1996-08-19 23:06:45 +00001305 if ((isnegative = (mpz_cmp_ui(&self->mpz, (unsigned long int)0) < 0)))
Guido van Rossum5f59d601992-12-14 16:59:51 +00001306 mpz_neg(&mpzscratch, &mpzscratch);
1307
1308 /* let those bits come, let those bits go,
Barry Warsawabb7efe1996-12-09 23:22:35 +00001309 e.g. dismantle mpzscratch, build PyLongObject */
Guido van Rossum5f59d601992-12-14 16:59:51 +00001310
1311 bitpointer = 0; /* the number of valid bits in stock */
1312 newbitpointer = 0;
1313 ldcount = 0; /* the python-long limb counter */
1314 uli = (unsigned long int)0;
1315 while (i--) {
1316 longobjp->ob_digit[ldcount] = uli & MASK;
1317
1318 /* check if we've had enough bits for this digit */
1319 if (bitpointer < SHIFT) {
1320 uli = mpz_get_ui(&mpzscratch);
1321 longobjp->ob_digit[ldcount] |=
1322 (uli << bitpointer) & MASK;
1323 uli >>= SHIFT-bitpointer;
1324 bitpointer += BITS_PER_MP_LIMB;
1325 mpz_div_2exp(&mpzscratch, &mpzscratch,
1326 BITS_PER_MP_LIMB);
1327 }
1328 else
1329 uli >>= SHIFT;
1330 bitpointer -= SHIFT;
1331 ldcount++;
1332 }
1333
1334 assert(mpz_cmp_ui(&mpzscratch, (unsigned long int)0) == 0);
1335 mpz_clear(&mpzscratch);
1336 assert(ldcount <= longobjp->ob_size);
1337
1338 /* long_normalize() is file-static */
1339 /* longobjp = long_normalize(longobjp); */
1340 while (ldcount > 0 && longobjp->ob_digit[ldcount-1] == 0)
1341 ldcount--;
1342 longobjp->ob_size = ldcount;
Fred Drakec17b3cf2001-02-12 16:48:13 +00001343
Guido van Rossum5f59d601992-12-14 16:59:51 +00001344
1345 if (isnegative)
1346 longobjp->ob_size = -longobjp->ob_size;
1347
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001348 return (PyObject *)longobjp;
Fred Drakec17b3cf2001-02-12 16:48:13 +00001349
Guido van Rossum5f59d601992-12-14 16:59:51 +00001350} /* mpz_long() */
1351
1352
1353/* I would have avoided pow() anyways, so ... */
1354static const double multiplier = 256.0 * 256.0 * 256.0 * 256.0;
Fred Drakec17b3cf2001-02-12 16:48:13 +00001355
Guido van Rossum5f59d601992-12-14 16:59:51 +00001356#ifdef MPZ_CONVERSIONS_AS_METHODS
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001357static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +00001358mpz_float(mpzobject *self, PyObject *args)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001359#else /* def MPZ_CONVERSIONS_AS_METHODS */
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001360static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +00001361mpz_float(mpzobject *self)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001362#endif /* def MPZ_CONVERSIONS_AS_METHODS else */
1363{
1364 int i, isnegative;
1365 double x;
1366 double mulstate;
1367 MP_INT mpzscratch;
1368
1369
1370#ifdef MPZ_CONVERSIONS_AS_METHODS
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001371 if (!PyArg_NoArgs(args))
Guido van Rossum5f59d601992-12-14 16:59:51 +00001372 return NULL;
1373#endif /* def MPZ_CONVERSIONS_AS_METHODS */
1374
1375 i = (int)mpz_size(&self->mpz);
Fred Drakec17b3cf2001-02-12 16:48:13 +00001376
Guido van Rossum5f59d601992-12-14 16:59:51 +00001377 /* determine sign, and copy abs(self) to scratch var */
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001378 if ((isnegative = (mpz_cmp_ui(&self->mpz, (unsigned long int)0) < 0)))
1379 {
Guido van Rossum5f59d601992-12-14 16:59:51 +00001380 mpz_init(&mpzscratch);
1381 mpz_neg(&mpzscratch, &self->mpz);
1382 }
1383 else
1384 mpz_init_set(&mpzscratch, &self->mpz);
1385
1386 /* let those bits come, let those bits go,
Barry Warsawabb7efe1996-12-09 23:22:35 +00001387 e.g. dismantle mpzscratch, build PyFloatObject */
Guido van Rossum5f59d601992-12-14 16:59:51 +00001388
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001389 /* Can this overflow? Dunno, protect against that possibility. */
1390 PyFPE_START_PROTECT("mpz_float", return 0)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001391 x = 0.0;
1392 mulstate = 1.0;
1393 while (i--) {
1394 x += mulstate * mpz_get_ui(&mpzscratch);
1395 mulstate *= multiplier;
1396 mpz_div_2exp(&mpzscratch, &mpzscratch, BITS_PER_MP_LIMB);
1397 }
Guido van Rossum45b83911997-03-14 04:32:50 +00001398 PyFPE_END_PROTECT(mulstate)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001399
1400 assert(mpz_cmp_ui(&mpzscratch, (unsigned long int)0) == 0);
1401 mpz_clear(&mpzscratch);
1402
1403 if (isnegative)
1404 x = -x;
1405
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001406 return PyFloat_FromDouble(x);
Fred Drakec17b3cf2001-02-12 16:48:13 +00001407
Guido van Rossum5f59d601992-12-14 16:59:51 +00001408} /* mpz_float() */
1409
1410#ifdef MPZ_CONVERSIONS_AS_METHODS
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001411static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +00001412mpz_hex(mpzobject *self, PyObject *args)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001413#else /* def MPZ_CONVERSIONS_AS_METHODS */
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001414static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +00001415mpz_hex(mpzobject *self)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001416#endif /* def MPZ_CONVERSIONS_AS_METHODS else */
1417{
1418#ifdef MPZ_CONVERSIONS_AS_METHODS
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001419 if (!PyArg_NoArgs(args))
Guido van Rossum5f59d601992-12-14 16:59:51 +00001420 return NULL;
1421#endif /* def MPZ_CONVERSIONS_AS_METHODS */
Fred Drakec17b3cf2001-02-12 16:48:13 +00001422
Peter Schneider-Kamp36463662000-07-10 17:14:00 +00001423 return mpz_format((PyObject *)self, 16, (unsigned char)1);
Guido van Rossum5f59d601992-12-14 16:59:51 +00001424} /* mpz_hex() */
Fred Drakec17b3cf2001-02-12 16:48:13 +00001425
Guido van Rossum5f59d601992-12-14 16:59:51 +00001426#ifdef MPZ_CONVERSIONS_AS_METHODS
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001427static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +00001428mpz_oct(mpzobject *self, PyObject *args)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001429#else /* def MPZ_CONVERSIONS_AS_METHODS */
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001430static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +00001431mpz_oct(mpzobject *self)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001432#endif /* def MPZ_CONVERSIONS_AS_METHODS else */
1433{
1434#ifdef MPZ_CONVERSIONS_AS_METHODS
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001435 if (!PyArg_NoArgs(args))
Guido van Rossum5f59d601992-12-14 16:59:51 +00001436 return NULL;
1437#endif /* def MPZ_CONVERSIONS_AS_METHODS */
1438
Peter Schneider-Kamp36463662000-07-10 17:14:00 +00001439 return mpz_format((PyObject *)self, 8, (unsigned char)1);
Guido van Rossum5f59d601992-12-14 16:59:51 +00001440} /* mpz_oct() */
Fred Drakec17b3cf2001-02-12 16:48:13 +00001441
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001442static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +00001443mpz_binary(mpzobject *self, PyObject *args)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001444{
1445 int size;
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001446 PyStringObject *strobjp;
Guido van Rossum5f59d601992-12-14 16:59:51 +00001447 char *cp;
1448 MP_INT mp;
1449 unsigned long ldigit;
Fred Drakec17b3cf2001-02-12 16:48:13 +00001450
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001451 if (!PyArg_NoArgs(args))
Guido van Rossum5f59d601992-12-14 16:59:51 +00001452 return NULL;
1453
1454 if (mpz_cmp_ui(&self->mpz, (unsigned long int)0) < 0) {
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001455 PyErr_SetString(PyExc_ValueError,
1456 "mpz.binary() arg must be >= 0");
Guido van Rossum5f59d601992-12-14 16:59:51 +00001457 return NULL;
1458 }
1459
1460 mpz_init_set(&mp, &self->mpz);
1461 size = (int)mpz_size(&mp);
1462
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001463 if ((strobjp = (PyStringObject *)
1464 PyString_FromStringAndSize(
1465 (char *)0, size * sizeof (unsigned long int))) == NULL)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001466 return NULL;
1467
1468 /* get the beginning of the string memory and start copying things */
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001469 cp = PyString_AS_STRING(strobjp);
Guido van Rossum5f59d601992-12-14 16:59:51 +00001470
1471 /* this has been programmed using a (fairly) decent lib-i/f it could
1472 be must faster if we looked into the GMP lib */
1473 while (size--) {
1474 ldigit = mpz_get_ui(&mp);
1475 mpz_div_2exp(&mp, &mp, BITS_PER_MP_LIMB);
1476 *cp++ = (unsigned char)(ldigit & 0xFF);
1477 *cp++ = (unsigned char)((ldigit >>= 8) & 0xFF);
1478 *cp++ = (unsigned char)((ldigit >>= 8) & 0xFF);
1479 *cp++ = (unsigned char)((ldigit >>= 8) & 0xFF);
Fred Drakec17b3cf2001-02-12 16:48:13 +00001480 if (sizeof(ldigit) == 8 && BITS_PER_MP_LIMB == 64) {
1481 *cp++ = (unsigned char)((ldigit >>= 8) & 0xFF);
1482 *cp++ = (unsigned char)((ldigit >>= 8) & 0xFF);
1483 *cp++ = (unsigned char)((ldigit >>= 8) & 0xFF);
1484 *cp++ = (unsigned char)((ldigit >>= 8) & 0xFF);
1485 }
Guido van Rossum5f59d601992-12-14 16:59:51 +00001486 }
1487
1488 while (strobjp->ob_size && !*--cp)
1489 strobjp->ob_size--;
1490
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001491 return (PyObject *)strobjp;
Guido van Rossum5f59d601992-12-14 16:59:51 +00001492} /* mpz_binary() */
Fred Drakec17b3cf2001-02-12 16:48:13 +00001493
Guido van Rossum5f59d601992-12-14 16:59:51 +00001494
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001495static PyMethodDef mpz_methods[] = {
Guido van Rossum5f59d601992-12-14 16:59:51 +00001496#ifdef MPZ_CONVERSIONS_AS_METHODS
1497 {"int", mpz_int},
1498 {"long", mpz_long},
1499 {"float", mpz_float},
1500 {"hex", mpz_hex},
1501 {"oct", mpz_oct},
1502#endif /* def MPZ_CONVERSIONS_AS_METHODS */
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001503 {"binary", (PyCFunction)mpz_binary},
Guido van Rossum5f59d601992-12-14 16:59:51 +00001504 {NULL, NULL} /* sentinel */
1505};
1506
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001507static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +00001508mpz_getattr(mpzobject *self, char *name)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001509{
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001510 return Py_FindMethod(mpz_methods, (PyObject *)self, name);
Guido van Rossum5f59d601992-12-14 16:59:51 +00001511} /* mpz_getattr() */
1512
1513
1514static int
Peter Schneider-Kamp36463662000-07-10 17:14:00 +00001515mpz_coerce(PyObject **pv, PyObject **pw)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001516{
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001517 PyObject *z;
Guido van Rossum5f59d601992-12-14 16:59:51 +00001518
1519#ifdef MPZ_DEBUG
1520 fputs("mpz_coerce() called...\n", stderr);
1521#endif /* def MPZ_DEBUG */
1522
1523 assert(is_mpzobject(*pv));
1524
1525 /* always convert other arg to mpz value, except for floats */
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001526 if (!PyFloat_Check(*pw)) {
1527 if ((z = (PyObject *)mpz_mpzcoerce(*pw)) == NULL)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001528 return -1; /* -1: an error always has been set */
1529
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001530 Py_INCREF(*pv);
Guido van Rossum5f59d601992-12-14 16:59:51 +00001531 *pw = z;
1532 }
1533 else {
Peter Schneider-Kamp36463662000-07-10 17:14:00 +00001534#ifdef MPZ_CONVERSIONS_AS_METHODS
1535 if ((z = mpz_float((mpzobject *)(*pv), NULL)) == NULL)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001536 return -1;
Peter Schneider-Kamp36463662000-07-10 17:14:00 +00001537#else /* def MPZ_CONVERSIONS_AS_METHODS */
1538 if ((z = mpz_float((mpzobject *)(*pv))) == NULL)
1539 return -1;
1540#endif /* def MPZ_CONVERSIONS_AS_METHODS else */
Guido van Rossum5f59d601992-12-14 16:59:51 +00001541
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001542 Py_INCREF(*pw);
Guido van Rossum5f59d601992-12-14 16:59:51 +00001543 *pv = z;
1544 }
1545 return 0; /* coercion succeeded */
1546
1547} /* mpz_coerce() */
1548
1549
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001550static PyObject *
Peter Schneider-Kamp36463662000-07-10 17:14:00 +00001551mpz_repr(PyObject *v)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001552{
1553 return mpz_format(v, 10, (unsigned char)1);
1554} /* mpz_repr() */
1555
1556
1557
Guido van Rossumb6775db1994-08-01 11:34:53 +00001558#define UF (unaryfunc)
1559#define BF (binaryfunc)
Guido van Rossum3bbc62e1995-01-02 19:30:30 +00001560#define TF (ternaryfunc)
Guido van Rossumb6775db1994-08-01 11:34:53 +00001561#define IF (inquiry)
1562#define CF (coercion)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001563
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001564static PyNumberMethods mpz_as_number = {
Guido van Rossum5f59d601992-12-14 16:59:51 +00001565 BF mpz_addition, /*nb_add*/
1566 BF mpz_substract, /*nb_subtract*/
1567 BF mpz_multiply, /*nb_multiply*/
1568 BF mpz_divide, /*nb_divide*/
1569 BF mpz_remainder, /*nb_remainder*/
1570 BF mpz_div_and_mod, /*nb_divmod*/
Guido van Rossum3bbc62e1995-01-02 19:30:30 +00001571 TF mpz_power, /*nb_power*/
Guido van Rossum5f59d601992-12-14 16:59:51 +00001572 UF mpz_negative, /*nb_negative*/
1573 UF mpz_positive, /*tp_positive*/
1574 UF mpz_absolute, /*tp_absolute*/
1575 IF mpz_nonzero, /*tp_nonzero*/
Guido van Rossum272841c1996-08-19 23:06:45 +00001576 UF py_mpz_invert, /*nb_invert*/
Guido van Rossum5f59d601992-12-14 16:59:51 +00001577 BF mpz_lshift, /*nb_lshift*/
1578 BF mpz_rshift, /*nb_rshift*/
1579 BF mpz_andfunc, /*nb_and*/
1580 BF mpz_xorfunc, /*nb_xor*/
1581 BF mpz_orfunc, /*nb_or*/
Guido van Rossumb6775db1994-08-01 11:34:53 +00001582 CF mpz_coerce, /*nb_coerce*/
Guido van Rossum5f59d601992-12-14 16:59:51 +00001583#ifndef MPZ_CONVERSIONS_AS_METHODS
1584 UF mpz_int, /*nb_int*/
1585 UF mpz_long, /*nb_long*/
1586 UF mpz_float, /*nb_float*/
1587 UF mpz_oct, /*nb_oct*/
1588 UF mpz_hex, /*nb_hex*/
1589#endif /* ndef MPZ_CONVERSIONS_AS_METHODS */
1590};
1591
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001592static PyTypeObject MPZtype = {
Andrew M. Kuchling22aa6442001-02-06 22:33:45 +00001593 PyObject_HEAD_INIT(NULL)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001594 0, /*ob_size*/
1595 "mpz", /*tp_name*/
1596 sizeof(mpzobject), /*tp_size*/
1597 0, /*tp_itemsize*/
1598 /* methods */
Guido van Rossumb6775db1994-08-01 11:34:53 +00001599 (destructor)mpz_dealloc, /*tp_dealloc*/
1600 0, /*tp_print*/
1601 (getattrfunc)mpz_getattr, /*tp_getattr*/
1602 0, /*tp_setattr*/
1603 (cmpfunc)mpz_compare, /*tp_compare*/
1604 (reprfunc)mpz_repr, /*tp_repr*/
1605 &mpz_as_number, /*tp_as_number*/
Guido van Rossum5f59d601992-12-14 16:59:51 +00001606};
1607
1608/* List of functions exported by this module */
1609
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001610static PyMethodDef mpz_functions[] = {
Guido van Rossum5f59d601992-12-14 16:59:51 +00001611#if 0
1612 {initialiser_name, MPZ_mpz},
1613#else /* 0 */
Barry Warsawabb7efe1996-12-09 23:22:35 +00001614 /* until guido ``fixes'' struct PyMethodDef */
Guido van Rossum5f59d601992-12-14 16:59:51 +00001615 {(char *)initialiser_name, MPZ_mpz},
1616#endif /* 0 else */
1617 {"powm", MPZ_powm},
1618 {"gcd", MPZ_gcd},
1619 {"gcdext", MPZ_gcdext},
1620 {"sqrt", MPZ_sqrt},
1621 {"sqrtrem", MPZ_sqrtrem},
1622 {"divm", MPZ_divm},
1623 {NULL, NULL} /* Sentinel */
1624};
1625
1626
1627/* #define MP_TEST_ALLOC */
1628
1629#ifdef MP_TEST_ALLOC
1630#define MP_TEST_SIZE 4
1631static const char mp_test_magic[MP_TEST_SIZE] = {'\xAA','\xAA','\xAA','\xAA'};
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00001632static mp_test_error(int *location)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001633{
Thomas Wouters7e474022000-07-16 12:04:32 +00001634 /* assumptions: *alloc returns address divisible by 4,
1635 mpz_* routines allocate in chunks divisible by four */
Guido van Rossum5f59d601992-12-14 16:59:51 +00001636 fprintf(stderr, "MP_TEST_ERROR: location holds 0x%08d\n", *location );
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001637 Py_FatalError("MP_TEST_ERROR");
Guido van Rossum5f59d601992-12-14 16:59:51 +00001638} /* static mp_test_error() */
1639#define MP_EXTRA_ALLOC(size) ((size) + MP_TEST_SIZE)
1640#define MP_SET_TEST(basep,size) (void)memcpy( ((char *)(basep))+(size), mp_test_magic, MP_TEST_SIZE)
1641#define MP_DO_TEST(basep,size) if ( !memcmp( ((char *)(basep))+(size), mp_test_magic, MP_TEST_SIZE ) ) \
1642 ; \
1643 else \
1644 mp_test_error((int *)((char *)(basep) + size))
1645#else /* def MP_TEST_ALLOC */
1646#define MP_EXTRA_ALLOC(size) (size)
1647#define MP_SET_TEST(basep,size)
1648#define MP_DO_TEST(basep,size)
1649#endif /* def MP_TEST_ALLOC else */
1650
Peter Schneider-Kamp36463662000-07-10 17:14:00 +00001651void *mp_allocate(size_t alloc_size)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001652{
1653 void *res;
1654
1655#ifdef MPZ_DEBUG
1656 fprintf(stderr, "mp_allocate : size %ld\n",
1657 alloc_size);
1658#endif /* def MPZ_DEBUG */
1659
1660 if ( (res = malloc(MP_EXTRA_ALLOC(alloc_size))) == NULL )
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001661 Py_FatalError("mp_allocate failure");
Guido van Rossum5f59d601992-12-14 16:59:51 +00001662
1663#ifdef MPZ_DEBUG
Fred Drakea44d3532000-06-30 15:01:00 +00001664 fprintf(stderr, "mp_allocate : address %08p\n", res);
Guido van Rossum5f59d601992-12-14 16:59:51 +00001665#endif /* def MPZ_DEBUG */
1666
1667 MP_SET_TEST(res,alloc_size);
1668
1669 return res;
1670} /* mp_allocate() */
1671
1672
Peter Schneider-Kamp36463662000-07-10 17:14:00 +00001673void *mp_reallocate(void *ptr, size_t old_size, size_t new_size)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001674{
1675 void *res;
1676
1677#ifdef MPZ_DEBUG
Fred Drakea44d3532000-06-30 15:01:00 +00001678 fprintf(stderr, "mp_reallocate: old address %08p, old size %ld\n",
Guido van Rossum5f59d601992-12-14 16:59:51 +00001679 ptr, old_size);
1680#endif /* def MPZ_DEBUG */
1681
1682 MP_DO_TEST(ptr, old_size);
1683
1684 if ( (res = realloc(ptr, MP_EXTRA_ALLOC(new_size))) == NULL )
Barry Warsaw3bdf7461996-12-09 23:16:31 +00001685 Py_FatalError("mp_reallocate failure");
Guido van Rossum5f59d601992-12-14 16:59:51 +00001686
1687#ifdef MPZ_DEBUG
Fred Drakea44d3532000-06-30 15:01:00 +00001688 fprintf(stderr, "mp_reallocate: new address %08p, new size %ld\n",
Guido van Rossum5f59d601992-12-14 16:59:51 +00001689 res, new_size);
1690#endif /* def MPZ_DEBUG */
1691
1692 MP_SET_TEST(res, new_size);
1693
1694 return res;
1695} /* mp_reallocate() */
1696
1697
Peter Schneider-Kamp36463662000-07-10 17:14:00 +00001698void mp_free(void *ptr, size_t size)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001699{
1700
1701#ifdef MPZ_DEBUG
Fred Drakea44d3532000-06-30 15:01:00 +00001702 fprintf(stderr, "mp_free : old address %08p, old size %ld\n",
Guido van Rossum5f59d601992-12-14 16:59:51 +00001703 ptr, size);
1704#endif /* def MPZ_DEBUG */
1705
1706 MP_DO_TEST(ptr, size);
1707 free(ptr);
1708} /* mp_free() */
1709
1710
1711
1712/* Initialize this module. */
1713
Guido van Rossum3886bb61998-12-04 18:50:17 +00001714DL_EXPORT(void)
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00001715initmpz(void)
Guido van Rossum5f59d601992-12-14 16:59:51 +00001716{
Fred Drakefcc6c681998-04-03 15:33:43 +00001717 PyObject *module;
1718 PyObject *dict;
1719
Guido van Rossum5f59d601992-12-14 16:59:51 +00001720#ifdef MPZ_DEBUG
1721 fputs( "initmpz() called...\n", stderr );
1722#endif /* def MPZ_DEBUG */
1723
1724 mp_set_memory_functions( mp_allocate, mp_reallocate, mp_free );
Andrew M. Kuchling22aa6442001-02-06 22:33:45 +00001725 MPZtype.ob_type = &PyType_Type;
Fred Drakefcc6c681998-04-03 15:33:43 +00001726 module = Py_InitModule("mpz", mpz_functions);
Guido van Rossum5f59d601992-12-14 16:59:51 +00001727
1728 /* create some frequently used constants */
1729 if ((mpz_value_zero = newmpzobject()) == NULL)
Barry Warsaw9bfd2bf2000-09-01 09:01:32 +00001730 goto finally;
Guido van Rossum5f59d601992-12-14 16:59:51 +00001731 mpz_set_ui(&mpz_value_zero->mpz, (unsigned long int)0);
1732
1733 if ((mpz_value_one = newmpzobject()) == NULL)
Barry Warsaw9bfd2bf2000-09-01 09:01:32 +00001734 goto finally;
Guido van Rossum5f59d601992-12-14 16:59:51 +00001735 mpz_set_ui(&mpz_value_one->mpz, (unsigned long int)1);
1736
1737 if ((mpz_value_mone = newmpzobject()) == NULL)
Barry Warsaw9bfd2bf2000-09-01 09:01:32 +00001738 goto finally;
Guido van Rossum5f59d601992-12-14 16:59:51 +00001739 mpz_set_si(&mpz_value_mone->mpz, (long)-1);
1740
Fred Drakefcc6c681998-04-03 15:33:43 +00001741 dict = PyModule_GetDict(module);
1742 if (dict != NULL) {
1743 PyDict_SetItemString(dict, "MPZType", (PyObject*)&MPZtype);
1744 }
Barry Warsaw9bfd2bf2000-09-01 09:01:32 +00001745 finally:
1746 return;
Guido van Rossum5f59d601992-12-14 16:59:51 +00001747} /* initmpz() */
Barry Warsaw9bfd2bf2000-09-01 09:01:32 +00001748
Guido van Rossum5f59d601992-12-14 16:59:51 +00001749#ifdef MAKEDUMMYINT
1750int _mpz_dummy_int; /* XXX otherwise, we're .bss-less (DYNLOAD->Jack?) */
1751#endif /* def MAKEDUMMYINT */