blob: c9c0dbfc774da3ce6fe801775b2912f64f6ed34a [file] [log] [blame]
Guido van Rossumedcc38a1991-05-05 20:09:44 +00001/***********************************************************
2Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
3Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
25/* Long (arbitrary precision) integer object implementation */
26
Guido van Rossum23d6f0e1991-05-14 12:06:49 +000027/* XXX The functional organization of this file is terrible */
28
Guido van Rossumedcc38a1991-05-05 20:09:44 +000029#include "allobjects.h"
30#include "longintrepr.h"
Guido van Rossum149e9ea1991-06-03 10:58:24 +000031#include <math.h>
Guido van Rossumedcc38a1991-05-05 20:09:44 +000032#include <assert.h>
33
Guido van Rossum149e9ea1991-06-03 10:58:24 +000034/* Forward: */
35extern object *long_mul PROTO((longobject *, object *));
36extern object *long_add PROTO((longobject *, object *));
37extern object *long_neg PROTO((longobject *));
38
Guido van Rossum23d6f0e1991-05-14 12:06:49 +000039static int ticker; /* XXX Could be shared with ceval? */
40
41#define INTRCHECK(block) \
42 if (--ticker < 0) { \
43 ticker = 100; \
44 if (intrcheck()) { block; } \
45 }
46
Guido van Rossumedcc38a1991-05-05 20:09:44 +000047/* Normalize (remove leading zeros from) a long int object.
48 Doesn't attempt to free the storage--in most cases, due to the nature
49 of the algorithms used, this could save at most be one word anyway. */
50
51longobject *
52long_normalize(v)
53 register longobject *v;
54{
55 int j = ABS(v->ob_size);
56 register int i = j;
57
58 while (i > 0 && v->ob_digit[i-1] == 0)
59 --i;
60 if (i != j)
61 v->ob_size = (v->ob_size < 0) ? -i : i;
62 return v;
63}
64
65/* Allocate a new long int object with size digits.
66 Return NULL and set exception if we run out of memory. */
67
68longobject *
69alloclongobject(size)
70 int size;
71{
72 return NEWVAROBJ(longobject, &Longtype, size);
73}
74
75/* Create a new long int object from a C long int */
76
77object *
78newlongobject(ival)
79 long ival;
80{
81 /* Assume a C long fits in at most 3 'digits' */
82 longobject *v = alloclongobject(3);
83 if (v != NULL) {
84 if (ival < 0) {
85 ival = -ival;
86 v->ob_size = -v->ob_size;
87 }
88 v->ob_digit[0] = ival & MASK;
89 v->ob_digit[1] = (ival >> SHIFT) & MASK;
90 v->ob_digit[2] = (ival >> (2*SHIFT)) & MASK;
91 v = long_normalize(v);
92 }
93 return (object *)v;
94}
95
Guido van Rossum149e9ea1991-06-03 10:58:24 +000096/* Create a new long int object from a C double */
97
98object *
99dnewlongobject(dval)
100 double dval;
101{
102 longobject *v;
103 double frac;
104 int i, ndig, expo, neg;
105 neg = 0;
106 if (dval < 0.0) {
107 neg = 1;
108 dval = -dval;
109 }
110 frac = frexp(dval, &expo); /* dval = frac*2**expo; 0.0 <= frac < 1.0 */
111 if (expo <= 0)
112 return newlongobject(0L);
113 ndig = (expo-1) / SHIFT + 1; /* Number of 'digits' in result */
114 v = alloclongobject(ndig);
115 if (v == NULL)
116 return NULL;
117 frac = ldexp(frac, (expo-1) % SHIFT + 1);
118 for (i = ndig; --i >= 0; ) {
119 long bits = (long)frac;
120 v->ob_digit[i] = bits;
121 frac = frac - (double)bits;
122 frac = ldexp(frac, SHIFT);
123 }
124 if (neg)
125 v->ob_size = -v->ob_size;
126 return (object *)v;
127}
128
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000129/* Get a C long int from a long int object.
130 Returns -1 and sets an error condition if overflow occurs. */
131
132long
133getlongvalue(vv)
134 object *vv;
135{
136 register longobject *v;
137 long x, prev;
138 int i, sign;
139
140 if (vv == NULL || !is_longobject(vv)) {
141 err_badcall();
142 return -1;
143 }
144 v = (longobject *)vv;
145 i = v->ob_size;
146 sign = 1;
147 x = 0;
148 if (i < 0) {
149 sign = -1;
150 i = -i;
151 }
152 while (--i >= 0) {
153 prev = x;
154 x = (x << SHIFT) + v->ob_digit[i];
155 if ((x >> SHIFT) != prev) {
156 err_setstr(RuntimeError,
157 "long int too long to convert");
158 return -1;
159 }
160 }
161 return x * sign;
162}
163
164/* Get a C double from a long int object. No overflow check. */
165
166double
167dgetlongvalue(vv)
168 object *vv;
169{
170 register longobject *v;
171 double x;
172 double multiplier = (double) (1L << SHIFT);
173 int i, sign;
174
175 if (vv == NULL || !is_longobject(vv)) {
176 err_badcall();
177 return -1;
178 }
179 v = (longobject *)vv;
180 i = v->ob_size;
181 sign = 1;
182 x = 0.0;
183 if (i < 0) {
184 sign = -1;
185 i = -i;
186 }
187 while (--i >= 0) {
188 x = x*multiplier + v->ob_digit[i];
189 }
190 return x * sign;
191}
192
193/* Multiply by a single digit, ignoring the sign. */
194
195longobject *
196mul1(a, n)
197 longobject *a;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000198 wdigit n;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000199{
200 return muladd1(a, n, (digit)0);
201}
202
203/* Multiply by a single digit and add a single digit, ignoring the sign. */
204
205longobject *
206muladd1(a, n, extra)
207 longobject *a;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000208 wdigit n;
209 wdigit extra;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000210{
211 int size_a = ABS(a->ob_size);
212 longobject *z = alloclongobject(size_a+1);
213 twodigits carry = extra;
214 int i;
215
216 if (z == NULL)
217 return NULL;
218 for (i = 0; i < size_a; ++i) {
219 carry += (twodigits)a->ob_digit[i] * n;
220 z->ob_digit[i] = carry & MASK;
221 carry >>= SHIFT;
222 }
223 z->ob_digit[i] = carry;
224 return long_normalize(z);
225}
226
227/* Divide a long integer by a digit, returning both the quotient
228 (as function result) and the remainder (through *prem).
229 The sign of a is ignored; n should not be zero. */
230
231longobject *
232divrem1(a, n, prem)
233 longobject *a;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000234 wdigit n;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000235 digit *prem;
236{
237 int size = ABS(a->ob_size);
238 longobject *z;
239 int i;
240 twodigits rem = 0;
241
242 assert(n > 0 && n <= MASK);
243 z = alloclongobject(size);
244 if (z == NULL)
245 return NULL;
246 for (i = size; --i >= 0; ) {
247 rem = (rem << SHIFT) + a->ob_digit[i];
248 z->ob_digit[i] = rem/n;
249 rem %= n;
250 }
251 *prem = rem;
252 return long_normalize(z);
253}
254
255/* Convert a long int object to a string, using a given conversion base.
Guido van Rossum3d3037d1991-10-24 14:55:57 +0000256 Return a string object.
257 If base is 8 or 16, add the proper prefix '0' or '0x'. */
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000258
259stringobject *
260long_format(a, base)
261 longobject *a;
262 int base;
263{
264 stringobject *str;
265 int i;
266 int size_a = ABS(a->ob_size);
267 char *p;
268 int bits;
269 char sign = '\0';
270
271 assert(base >= 2 && base <= 36);
272
273 /* Compute a rough upper bound for the length of the string */
274 i = base;
275 bits = 0;
276 while (i > 1) {
277 ++bits;
278 i >>= 1;
279 }
Guido van Rossum3d3037d1991-10-24 14:55:57 +0000280 i = 3 + (size_a*SHIFT + bits-1) / bits;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000281 str = (stringobject *) newsizedstringobject((char *)0, i);
282 if (str == NULL)
283 return NULL;
284 p = GETSTRINGVALUE(str) + i;
285 *p = '\0';
286 if (a->ob_size < 0)
287 sign = '-';
288
289 INCREF(a);
290 do {
291 digit rem;
292 longobject *temp = divrem1(a, (digit)base, &rem);
293 if (temp == NULL) {
294 DECREF(a);
295 DECREF(str);
296 return NULL;
297 }
298 if (rem < 10)
299 rem += '0';
300 else
301 rem += 'A'-10;
302 assert(p > GETSTRINGVALUE(str));
303 *--p = rem;
304 DECREF(a);
305 a = temp;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000306 INTRCHECK({
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000307 DECREF(a);
308 DECREF(str);
309 err_set(KeyboardInterrupt);
310 return NULL;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000311 })
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000312 } while (a->ob_size != 0);
313 DECREF(a);
Guido van Rossum3d3037d1991-10-24 14:55:57 +0000314 if (base == 8)
315 *--p = '0';
316 else if (base == 16) {
317 *--p = 'x';
318 *--p = '0';
319 }
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000320 if (sign)
321 *--p = sign;
322 if (p != GETSTRINGVALUE(str)) {
323 char *q = GETSTRINGVALUE(str);
324 assert(p > q);
325 do {
326 } while ((*q++ = *p++) != '\0');
Guido van Rossumc7ec9c91991-05-28 21:58:16 +0000327 q--;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000328 resizestring((object **)&str, (int) (q - GETSTRINGVALUE(str)));
329 }
330 return str;
331}
332
333/* Convert a string to a long int object, in a given base.
334 Base zero implies a default depending on the number. */
335
336object *
337long_scan(str, base)
338 char *str;
339 int base;
340{
341 int sign = 1;
342 longobject *z;
343
344 assert(base == 0 || base >= 2 && base <= 36);
345 if (*str == '+')
346 ++str;
347 else if (*str == '-') {
348 ++str;
349 sign = -1;
350 }
351 if (base == 0) {
352 if (str[0] != '0')
353 base = 10;
354 else if (str[1] == 'x' || str[1] == 'X')
355 base = 16;
356 else
357 base = 8;
358 }
359 if (base == 16 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
360 str += 2;
361 z = alloclongobject(0);
362 for ( ; z != NULL; ++str) {
363 int k = -1;
364 longobject *temp;
365
366 if (*str <= '9')
367 k = *str - '0';
368 else if (*str >= 'a')
369 k = *str - 'a' + 10;
370 else if (*str >= 'A')
371 k = *str - 'A' + 10;
372 if (k < 0 || k >= base)
373 break;
374 temp = muladd1(z, (digit)base, (digit)k);
375 DECREF(z);
376 z = temp;
377 }
378 if (z != NULL)
379 z->ob_size *= sign;
380 return (object *) z;
381}
382
383static longobject *x_divrem PROTO((longobject *, longobject *, longobject **));
384
385/* Long division with remainder, top-level routine */
386
387longobject *
388long_divrem(a, b, prem)
389 longobject *a, *b;
390 longobject **prem;
391{
392 int size_a = ABS(a->ob_size), size_b = ABS(b->ob_size);
393 longobject *z;
394
395 if (size_b == 0) {
396 if (prem != NULL)
397 *prem = NULL;
398 err_setstr(RuntimeError, "long division by zero");
399 return NULL;
400 }
401 if (size_a < size_b ||
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000402 size_a == size_b &&
403 a->ob_digit[size_a-1] < b->ob_digit[size_b-1]) {
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000404 /* |a| < |b|. */
405 if (prem != NULL) {
406 INCREF(a);
407 *prem = a;
408 }
409 return alloclongobject(0);
410 }
411 if (size_b == 1) {
412 digit rem = 0;
413 z = divrem1(a, b->ob_digit[0], &rem);
414 if (prem != NULL) {
415 if (z == NULL)
416 *prem = NULL;
417 else
418 *prem = (longobject *)
419 newlongobject((long)rem);
420 }
421 }
422 else
423 z = x_divrem(a, b, prem);
424 /* Set the signs.
425 The quotient z has the sign of a*b;
426 the remainder r has the sign of a,
427 so a = b*z + r. */
428 if (z != NULL) {
429 if ((a->ob_size < 0) != (b->ob_size < 0))
430 z->ob_size = - z->ob_size;
431 if (prem != NULL && *prem != NULL && a->ob_size < 0)
432 (*prem)->ob_size = - (*prem)->ob_size;
433 }
434 return z;
435}
436
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000437/* Unsigned long division with remainder -- the algorithm */
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000438
439static longobject *
440x_divrem(v1, w1, prem)
441 longobject *v1, *w1;
442 longobject **prem;
443{
444 int size_v = ABS(v1->ob_size), size_w = ABS(w1->ob_size);
445 digit d = (twodigits)BASE / (w1->ob_digit[size_w-1] + 1);
446 longobject *v = mul1(v1, d);
447 longobject *w = mul1(w1, d);
448 longobject *a;
449 int j, k;
450
451 if (v == NULL || w == NULL) {
452 XDECREF(v);
453 XDECREF(w);
454 if (prem != NULL)
455 *prem = NULL;
456 return NULL;
457 }
458
459 assert(size_v >= size_w && size_w > 1); /* Assert checks by div() */
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000460 assert(v->ob_refcnt == 1); /* Since v will be used as accumulator! */
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000461 assert(size_w == ABS(w->ob_size)); /* That's how d was calculated */
462
463 size_v = ABS(v->ob_size);
464 a = alloclongobject(size_v - size_w + 1);
465
466 for (j = size_v, k = a->ob_size-1; a != NULL && k >= 0; --j, --k) {
467 digit vj = (j >= size_v) ? 0 : v->ob_digit[j];
468 twodigits q;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000469 stwodigits carry = 0;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000470 int i;
471
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000472 INTRCHECK({
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000473 DECREF(a);
474 a = NULL;
475 err_set(KeyboardInterrupt);
476 break;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000477 })
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000478 if (vj == w->ob_digit[size_w-1])
479 q = MASK;
480 else
481 q = (((twodigits)vj << SHIFT) + v->ob_digit[j-1]) /
482 w->ob_digit[size_w-1];
483
484 while (w->ob_digit[size_w-2]*q >
485 ((
486 ((twodigits)vj << SHIFT)
487 + v->ob_digit[j-1]
488 - q*w->ob_digit[size_w-1]
489 ) << SHIFT)
490 + v->ob_digit[j-2])
491 --q;
492
493 for (i = 0; i < size_w && i+k < size_v; ++i) {
494 twodigits z = w->ob_digit[i] * q;
495 digit zz = z >> SHIFT;
496 carry += v->ob_digit[i+k] - z + ((twodigits)zz << SHIFT);
497 v->ob_digit[i+k] = carry & MASK;
498 carry = (carry >> SHIFT) - zz;
499 }
500
501 if (i+k < size_v) {
502 carry += v->ob_digit[i+k];
503 v->ob_digit[i+k] = 0;
504 }
505
506 if (carry == 0)
507 a->ob_digit[k] = q;
508 else {
509 assert(carry == -1);
510 a->ob_digit[k] = q-1;
511 carry = 0;
512 for (i = 0; i < size_w && i+k < size_v; ++i) {
513 carry += v->ob_digit[i+k] + w->ob_digit[i];
514 v->ob_digit[i+k] = carry & MASK;
515 carry >>= SHIFT;
516 }
517 }
518 } /* for j, k */
519
520 if (a != NULL)
521 a = long_normalize(a);
522 if (prem != 0) {
523 if (a == NULL)
524 *prem = NULL;
525 else
526 *prem = divrem1(v, d, &d);
527 /* Using d as a dummy to receive the - unused - remainder */
528 }
529 DECREF(v);
530 DECREF(w);
531 return a;
532}
533
534/* Methods */
535
536static void
537long_dealloc(v)
538 longobject *v;
539{
540 DEL(v);
541}
542
Guido van Rossum90933611991-06-07 16:10:43 +0000543static int
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000544long_print(v, fp, flags)
545 longobject *v;
546 FILE *fp;
547 int flags;
548{
549 stringobject *str = long_format(v, 10);
Guido van Rossum90933611991-06-07 16:10:43 +0000550 if (str == NULL)
551 return -1;
552 fprintf(fp, "%sL", GETSTRINGVALUE(str));
553 DECREF(str);
554 return 0;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000555}
556
557static object *
558long_repr(v)
559 longobject *v;
560{
561 stringobject *str = long_format(v, 10);
562 if (str != NULL) {
563 int len = getstringsize((object *)str);
564 resizestring((object **)&str, len + 1);
565 if (str != NULL)
566 GETSTRINGVALUE(str)[len] = 'L';
567 }
568 return (object *)str;
569}
570
571static int
572long_compare(a, b)
573 longobject *a, *b;
574{
575 int sign;
576
577 if (a->ob_size != b->ob_size)
578 sign = a->ob_size - b->ob_size;
579 else {
580 int i = ABS(a->ob_size);
581 while (--i >= 0 && a->ob_digit[i] == b->ob_digit[i])
582 ;
583 if (i < 0)
584 sign = 0;
585 else
586 sign = (int)a->ob_digit[i] - (int)b->ob_digit[i];
587 }
588 return sign;
589}
590
591/* Add the absolute values of two long integers. */
592
593static longobject *x_add PROTO((longobject *, longobject *));
594static longobject *
595x_add(a, b)
596 longobject *a, *b;
597{
598 int size_a = ABS(a->ob_size), size_b = ABS(b->ob_size);
599 longobject *z;
600 int i;
601 digit carry = 0;
602
603 /* Ensure a is the larger of the two: */
604 if (size_a < size_b) {
605 { longobject *temp = a; a = b; b = temp; }
606 { int size_temp = size_a; size_a = size_b; size_b = size_temp; }
607 }
608 z = alloclongobject(size_a+1);
609 if (z == NULL)
610 return NULL;
611 for (i = 0; i < size_b; ++i) {
612 carry += a->ob_digit[i] + b->ob_digit[i];
613 z->ob_digit[i] = carry & MASK;
614 /* The following assumes unsigned shifts don't
615 propagate the sign bit. */
616 carry >>= SHIFT;
617 }
618 for (; i < size_a; ++i) {
619 carry += a->ob_digit[i];
620 z->ob_digit[i] = carry & MASK;
621 carry >>= SHIFT;
622 }
623 z->ob_digit[i] = carry;
624 return long_normalize(z);
625}
626
627/* Subtract the absolute values of two integers. */
628
629static longobject *x_sub PROTO((longobject *, longobject *));
630static longobject *
631x_sub(a, b)
632 longobject *a, *b;
633{
634 int size_a = ABS(a->ob_size), size_b = ABS(b->ob_size);
635 longobject *z;
636 int i;
637 int sign = 1;
638 digit borrow = 0;
639
640 /* Ensure a is the larger of the two: */
641 if (size_a < size_b) {
642 sign = -1;
643 { longobject *temp = a; a = b; b = temp; }
644 { int size_temp = size_a; size_a = size_b; size_b = size_temp; }
645 }
646 else if (size_a == size_b) {
647 /* Find highest digit where a and b differ: */
648 i = size_a;
649 while (--i >= 0 && a->ob_digit[i] == b->ob_digit[i])
650 ;
651 if (i < 0)
652 return alloclongobject(0);
653 if (a->ob_digit[i] < b->ob_digit[i]) {
654 sign = -1;
655 { longobject *temp = a; a = b; b = temp; }
656 }
657 size_a = size_b = i+1;
658 }
659 z = alloclongobject(size_a);
660 if (z == NULL)
661 return NULL;
662 for (i = 0; i < size_b; ++i) {
663 /* The following assumes unsigned arithmetic
664 works module 2**N for some N>SHIFT. */
665 borrow = a->ob_digit[i] - b->ob_digit[i] - borrow;
666 z->ob_digit[i] = borrow & MASK;
667 borrow >>= SHIFT;
668 borrow &= 1; /* Keep only one sign bit */
669 }
670 for (; i < size_a; ++i) {
671 borrow = a->ob_digit[i] - borrow;
672 z->ob_digit[i] = borrow & MASK;
673 borrow >>= SHIFT;
674 }
675 assert(borrow == 0);
676 z->ob_size *= sign;
677 return long_normalize(z);
678}
679
680static object *
681long_add(a, w)
682 longobject *a;
683 object *w;
684{
685 longobject *b;
686 longobject *z;
687
688 if (!is_longobject(w)) {
689 err_badarg();
690 return NULL;
691 }
692 b = (longobject *)w;
693
694 if (a->ob_size < 0) {
695 if (b->ob_size < 0) {
696 z = x_add(a, b);
697 if (z != NULL)
698 z->ob_size = -z->ob_size;
699 }
700 else
701 z = x_sub(b, a);
702 }
703 else {
704 if (b->ob_size < 0)
705 z = x_sub(a, b);
706 else
707 z = x_add(a, b);
708 }
709 return (object *)z;
710}
711
712static object *
713long_sub(a, w)
714 longobject *a;
715 object *w;
716{
717 longobject *b;
718 longobject *z;
719
720 if (!is_longobject(w)) {
721 err_badarg();
722 return NULL;
723 }
724 b = (longobject *)w;
725
726 if (a->ob_size < 0) {
727 if (b->ob_size < 0)
728 z = x_sub(a, b);
729 else
730 z = x_add(a, b);
731 if (z != NULL)
732 z->ob_size = -z->ob_size;
733 }
734 else {
735 if (b->ob_size < 0)
736 z = x_add(a, b);
737 else
738 z = x_sub(a, b);
739 }
740 return (object *)z;
741}
742
743static object *
744long_mul(a, w)
745 longobject *a;
746 object *w;
747{
748 longobject *b;
749 int size_a;
750 int size_b;
751 longobject *z;
752 int i;
753
754 if (!is_longobject(w)) {
755 err_badarg();
756 return NULL;
757 }
758 b = (longobject *)w;
759 size_a = ABS(a->ob_size);
760 size_b = ABS(b->ob_size);
761 z = alloclongobject(size_a + size_b);
762 if (z == NULL)
763 return NULL;
764 for (i = 0; i < z->ob_size; ++i)
765 z->ob_digit[i] = 0;
766 for (i = 0; i < size_a; ++i) {
767 twodigits carry = 0;
768 twodigits f = a->ob_digit[i];
769 int j;
770
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000771 INTRCHECK({
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000772 DECREF(z);
773 err_set(KeyboardInterrupt);
774 return NULL;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000775 })
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000776 for (j = 0; j < size_b; ++j) {
777 carry += z->ob_digit[i+j] + b->ob_digit[j] * f;
778 z->ob_digit[i+j] = carry & MASK;
779 carry >>= SHIFT;
780 }
781 for (; carry != 0; ++j) {
782 assert(i+j < z->ob_size);
783 carry += z->ob_digit[i+j];
784 z->ob_digit[i+j] = carry & MASK;
785 carry >>= SHIFT;
786 }
787 }
788 if (a->ob_size < 0)
789 z->ob_size = -z->ob_size;
790 if (b->ob_size < 0)
791 z->ob_size = -z->ob_size;
792 return (object *) long_normalize(z);
793}
794
795static object *
796long_div(v, w)
797 longobject *v;
798 register object *w;
799{
800 if (!is_longobject(w)) {
801 err_badarg();
802 return NULL;
803 }
804 return (object *) long_divrem(v, (longobject *)w, (longobject **)0);
805}
806
807static object *
808long_rem(v, w)
809 longobject *v;
810 register object *w;
811{
812 longobject *div, *rem = NULL;
813 if (!is_longobject(w)) {
814 err_badarg();
815 return NULL;
816 }
817 div = long_divrem(v, (longobject *)w, &rem);
818 if (div == NULL) {
819 XDECREF(rem);
820 rem = NULL;
821 }
822 else {
823 DECREF(div);
824 }
825 return (object *) rem;
826}
827
828/* The expression a mod b has the value a - b*floor(a/b).
829 The divrem function gives the remainder after division of
830 |a| by |b|, with the sign of a. This is also expressed
831 as a - b*trunc(a/b), if trunc truncates towards zero.
832 Some examples:
833 a b a rem b a mod b
834 13 10 3 3
835 -13 10 -3 7
836 13 -10 3 -7
837 -13 -10 -3 -3
838 So, to get from rem to mod, we have to add b if a and b
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000839 have different signs. We then subtract one from the 'div'
840 part of the outcome to keep the invariant intact. */
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000841
842static object *
843long_divmod(v, w)
844 longobject *v;
845 register object *w;
846{
847 object *z;
848 longobject *div, *rem;
849 if (!is_longobject(w)) {
850 err_badarg();
851 return NULL;
852 }
853 div = long_divrem(v, (longobject *)w, &rem);
854 if (div == NULL) {
855 XDECREF(rem);
856 return NULL;
857 }
858 if ((v->ob_size < 0) != (((longobject *)w)->ob_size < 0)) {
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000859 longobject *temp;
860 longobject *one;
861 temp = (longobject *) long_add(rem, w);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000862 DECREF(rem);
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000863 rem = temp;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000864 if (rem == NULL) {
865 DECREF(div);
866 return NULL;
867 }
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000868 one = (longobject *) newlongobject(1L);
869 if (one == NULL ||
870 (temp = (longobject *) long_sub(div, one)) == NULL) {
871 DECREF(rem);
872 DECREF(div);
873 return NULL;
874 }
875 DECREF(div);
876 div = temp;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000877 }
878 z = newtupleobject(2);
879 if (z != NULL) {
880 settupleitem(z, 0, (object *) div);
881 settupleitem(z, 1, (object *) rem);
882 }
883 else {
884 DECREF(div);
885 DECREF(rem);
886 }
887 return z;
888}
889
890static object *
Guido van Rossumc7ec9c91991-05-28 21:58:16 +0000891long_pow(a, w)
892 longobject *a;
893 object *w;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000894{
Guido van Rossumc7ec9c91991-05-28 21:58:16 +0000895 register longobject *b;
896 longobject *z;
897 int size_b, i;
898
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000899 if (!is_longobject(w)) {
900 err_badarg();
901 return NULL;
902 }
Guido van Rossumc7ec9c91991-05-28 21:58:16 +0000903
904 b = (longobject *)w;
905 size_b = b->ob_size;
906 if (size_b < 0) {
907 err_setstr(RuntimeError, "long integer to the negative power");
908 return NULL;
909 }
910
911 z = (longobject *)newlongobject(1L);
912
913 INCREF(a);
914 for (i = 0; i < size_b; ++i) {
915 digit bi = b->ob_digit[i];
916 int j;
917
918 for (j = 0; j < SHIFT; ++j) {
919 longobject *temp;
920
921 if (bi & 1) {
922 temp = (longobject *)long_mul(z, (object *)a);
923 DECREF(z);
924 z = temp;
925 if (z == NULL)
926 break;
927 }
928 bi >>= 1;
929 if (bi == 0 && i+1 == size_b)
930 break;
931 temp = (longobject *)long_mul(a, (object *)a);
932 DECREF(a);
933 a = temp;
934 if (a == NULL) {
935 DECREF(z);
936 z = NULL;
937 break;
938 }
939 }
940 if (a == NULL)
941 break;
942 }
943 XDECREF(a);
944 return (object *)z;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000945}
946
947static object *
948long_pos(v)
949 longobject *v;
950{
951 INCREF(v);
952 return (object *)v;
953}
954
955static object *
956long_neg(v)
957 longobject *v;
958{
959 longobject *z;
960 int i = v->ob_size;
961 if (i == 0)
962 return long_pos(v);
963 i = ABS(i);
964 z = alloclongobject(i);
965 if (z != NULL) {
966 z->ob_size = - v->ob_size;
967 while (--i >= 0)
968 z->ob_digit[i] = v->ob_digit[i];
969 }
970 return (object *)z;
971}
972
973static object *
974long_abs(v)
975 longobject *v;
976{
977 if (v->ob_size < 0)
978 return long_neg(v);
979 else
980 return long_pos(v);
981}
982
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000983static int
984long_nonzero(v)
985 longobject *v;
986{
987 return v->ob_size != 0;
988}
989
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000990static number_methods long_as_number = {
991 long_add, /*nb_add*/
992 long_sub, /*nb_subtract*/
993 long_mul, /*nb_multiply*/
994 long_div, /*nb_divide*/
995 long_rem, /*nb_remainder*/
996 long_divmod, /*nb_divmod*/
997 long_pow, /*nb_power*/
998 long_neg, /*nb_negative*/
999 long_pos, /*tp_positive*/
1000 long_abs, /*tp_absolute*/
Guido van Rossum23d6f0e1991-05-14 12:06:49 +00001001 long_nonzero, /*tp_nonzero*/
Guido van Rossum3d3037d1991-10-24 14:55:57 +00001002 0, /*nb_invert*/
1003 0, /*nb_lshift*/
1004 0, /*nb_rshift*/
1005 0, /*nb_and*/
1006 0, /*nb_xor*/
1007 0, /*nb_or*/
Guido van Rossumedcc38a1991-05-05 20:09:44 +00001008};
1009
1010typeobject Longtype = {
1011 OB_HEAD_INIT(&Typetype)
1012 0,
1013 "long int",
1014 sizeof(longobject) - sizeof(digit),
1015 sizeof(digit),
1016 long_dealloc, /*tp_dealloc*/
1017 long_print, /*tp_print*/
1018 0, /*tp_getattr*/
1019 0, /*tp_setattr*/
1020 long_compare, /*tp_compare*/
1021 long_repr, /*tp_repr*/
1022 &long_as_number,/*tp_as_number*/
1023 0, /*tp_as_sequence*/
1024 0, /*tp_as_mapping*/
1025};