blob: ca4088c93dd3d999985536f773b98fc0165e71f4 [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.
256 Return a string object. */
257
258stringobject *
259long_format(a, base)
260 longobject *a;
261 int base;
262{
263 stringobject *str;
264 int i;
265 int size_a = ABS(a->ob_size);
266 char *p;
267 int bits;
268 char sign = '\0';
269
270 assert(base >= 2 && base <= 36);
271
272 /* Compute a rough upper bound for the length of the string */
273 i = base;
274 bits = 0;
275 while (i > 1) {
276 ++bits;
277 i >>= 1;
278 }
279 i = 1 + (size_a*SHIFT + bits-1) / bits;
280 str = (stringobject *) newsizedstringobject((char *)0, i);
281 if (str == NULL)
282 return NULL;
283 p = GETSTRINGVALUE(str) + i;
284 *p = '\0';
285 if (a->ob_size < 0)
286 sign = '-';
287
288 INCREF(a);
289 do {
290 digit rem;
291 longobject *temp = divrem1(a, (digit)base, &rem);
292 if (temp == NULL) {
293 DECREF(a);
294 DECREF(str);
295 return NULL;
296 }
297 if (rem < 10)
298 rem += '0';
299 else
300 rem += 'A'-10;
301 assert(p > GETSTRINGVALUE(str));
302 *--p = rem;
303 DECREF(a);
304 a = temp;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000305 INTRCHECK({
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000306 DECREF(a);
307 DECREF(str);
308 err_set(KeyboardInterrupt);
309 return NULL;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000310 })
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000311 } while (a->ob_size != 0);
312 DECREF(a);
313 if (sign)
314 *--p = sign;
315 if (p != GETSTRINGVALUE(str)) {
316 char *q = GETSTRINGVALUE(str);
317 assert(p > q);
318 do {
319 } while ((*q++ = *p++) != '\0');
Guido van Rossumc7ec9c91991-05-28 21:58:16 +0000320 q--;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000321 resizestring((object **)&str, (int) (q - GETSTRINGVALUE(str)));
322 }
323 return str;
324}
325
326/* Convert a string to a long int object, in a given base.
327 Base zero implies a default depending on the number. */
328
329object *
330long_scan(str, base)
331 char *str;
332 int base;
333{
334 int sign = 1;
335 longobject *z;
336
337 assert(base == 0 || base >= 2 && base <= 36);
338 if (*str == '+')
339 ++str;
340 else if (*str == '-') {
341 ++str;
342 sign = -1;
343 }
344 if (base == 0) {
345 if (str[0] != '0')
346 base = 10;
347 else if (str[1] == 'x' || str[1] == 'X')
348 base = 16;
349 else
350 base = 8;
351 }
352 if (base == 16 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
353 str += 2;
354 z = alloclongobject(0);
355 for ( ; z != NULL; ++str) {
356 int k = -1;
357 longobject *temp;
358
359 if (*str <= '9')
360 k = *str - '0';
361 else if (*str >= 'a')
362 k = *str - 'a' + 10;
363 else if (*str >= 'A')
364 k = *str - 'A' + 10;
365 if (k < 0 || k >= base)
366 break;
367 temp = muladd1(z, (digit)base, (digit)k);
368 DECREF(z);
369 z = temp;
370 }
371 if (z != NULL)
372 z->ob_size *= sign;
373 return (object *) z;
374}
375
376static longobject *x_divrem PROTO((longobject *, longobject *, longobject **));
377
378/* Long division with remainder, top-level routine */
379
380longobject *
381long_divrem(a, b, prem)
382 longobject *a, *b;
383 longobject **prem;
384{
385 int size_a = ABS(a->ob_size), size_b = ABS(b->ob_size);
386 longobject *z;
387
388 if (size_b == 0) {
389 if (prem != NULL)
390 *prem = NULL;
391 err_setstr(RuntimeError, "long division by zero");
392 return NULL;
393 }
394 if (size_a < size_b ||
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000395 size_a == size_b &&
396 a->ob_digit[size_a-1] < b->ob_digit[size_b-1]) {
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000397 /* |a| < |b|. */
398 if (prem != NULL) {
399 INCREF(a);
400 *prem = a;
401 }
402 return alloclongobject(0);
403 }
404 if (size_b == 1) {
405 digit rem = 0;
406 z = divrem1(a, b->ob_digit[0], &rem);
407 if (prem != NULL) {
408 if (z == NULL)
409 *prem = NULL;
410 else
411 *prem = (longobject *)
412 newlongobject((long)rem);
413 }
414 }
415 else
416 z = x_divrem(a, b, prem);
417 /* Set the signs.
418 The quotient z has the sign of a*b;
419 the remainder r has the sign of a,
420 so a = b*z + r. */
421 if (z != NULL) {
422 if ((a->ob_size < 0) != (b->ob_size < 0))
423 z->ob_size = - z->ob_size;
424 if (prem != NULL && *prem != NULL && a->ob_size < 0)
425 (*prem)->ob_size = - (*prem)->ob_size;
426 }
427 return z;
428}
429
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000430/* Unsigned long division with remainder -- the algorithm */
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000431
432static longobject *
433x_divrem(v1, w1, prem)
434 longobject *v1, *w1;
435 longobject **prem;
436{
437 int size_v = ABS(v1->ob_size), size_w = ABS(w1->ob_size);
438 digit d = (twodigits)BASE / (w1->ob_digit[size_w-1] + 1);
439 longobject *v = mul1(v1, d);
440 longobject *w = mul1(w1, d);
441 longobject *a;
442 int j, k;
443
444 if (v == NULL || w == NULL) {
445 XDECREF(v);
446 XDECREF(w);
447 if (prem != NULL)
448 *prem = NULL;
449 return NULL;
450 }
451
452 assert(size_v >= size_w && size_w > 1); /* Assert checks by div() */
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000453 assert(v->ob_refcnt == 1); /* Since v will be used as accumulator! */
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000454 assert(size_w == ABS(w->ob_size)); /* That's how d was calculated */
455
456 size_v = ABS(v->ob_size);
457 a = alloclongobject(size_v - size_w + 1);
458
459 for (j = size_v, k = a->ob_size-1; a != NULL && k >= 0; --j, --k) {
460 digit vj = (j >= size_v) ? 0 : v->ob_digit[j];
461 twodigits q;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000462 stwodigits carry = 0;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000463 int i;
464
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000465 INTRCHECK({
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000466 DECREF(a);
467 a = NULL;
468 err_set(KeyboardInterrupt);
469 break;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000470 })
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000471 if (vj == w->ob_digit[size_w-1])
472 q = MASK;
473 else
474 q = (((twodigits)vj << SHIFT) + v->ob_digit[j-1]) /
475 w->ob_digit[size_w-1];
476
477 while (w->ob_digit[size_w-2]*q >
478 ((
479 ((twodigits)vj << SHIFT)
480 + v->ob_digit[j-1]
481 - q*w->ob_digit[size_w-1]
482 ) << SHIFT)
483 + v->ob_digit[j-2])
484 --q;
485
486 for (i = 0; i < size_w && i+k < size_v; ++i) {
487 twodigits z = w->ob_digit[i] * q;
488 digit zz = z >> SHIFT;
489 carry += v->ob_digit[i+k] - z + ((twodigits)zz << SHIFT);
490 v->ob_digit[i+k] = carry & MASK;
491 carry = (carry >> SHIFT) - zz;
492 }
493
494 if (i+k < size_v) {
495 carry += v->ob_digit[i+k];
496 v->ob_digit[i+k] = 0;
497 }
498
499 if (carry == 0)
500 a->ob_digit[k] = q;
501 else {
502 assert(carry == -1);
503 a->ob_digit[k] = q-1;
504 carry = 0;
505 for (i = 0; i < size_w && i+k < size_v; ++i) {
506 carry += v->ob_digit[i+k] + w->ob_digit[i];
507 v->ob_digit[i+k] = carry & MASK;
508 carry >>= SHIFT;
509 }
510 }
511 } /* for j, k */
512
513 if (a != NULL)
514 a = long_normalize(a);
515 if (prem != 0) {
516 if (a == NULL)
517 *prem = NULL;
518 else
519 *prem = divrem1(v, d, &d);
520 /* Using d as a dummy to receive the - unused - remainder */
521 }
522 DECREF(v);
523 DECREF(w);
524 return a;
525}
526
527/* Methods */
528
529static void
530long_dealloc(v)
531 longobject *v;
532{
533 DEL(v);
534}
535
Guido van Rossum90933611991-06-07 16:10:43 +0000536static int
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000537long_print(v, fp, flags)
538 longobject *v;
539 FILE *fp;
540 int flags;
541{
542 stringobject *str = long_format(v, 10);
Guido van Rossum90933611991-06-07 16:10:43 +0000543 if (str == NULL)
544 return -1;
545 fprintf(fp, "%sL", GETSTRINGVALUE(str));
546 DECREF(str);
547 return 0;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000548}
549
550static object *
551long_repr(v)
552 longobject *v;
553{
554 stringobject *str = long_format(v, 10);
555 if (str != NULL) {
556 int len = getstringsize((object *)str);
557 resizestring((object **)&str, len + 1);
558 if (str != NULL)
559 GETSTRINGVALUE(str)[len] = 'L';
560 }
561 return (object *)str;
562}
563
564static int
565long_compare(a, b)
566 longobject *a, *b;
567{
568 int sign;
569
570 if (a->ob_size != b->ob_size)
571 sign = a->ob_size - b->ob_size;
572 else {
573 int i = ABS(a->ob_size);
574 while (--i >= 0 && a->ob_digit[i] == b->ob_digit[i])
575 ;
576 if (i < 0)
577 sign = 0;
578 else
579 sign = (int)a->ob_digit[i] - (int)b->ob_digit[i];
580 }
581 return sign;
582}
583
584/* Add the absolute values of two long integers. */
585
586static longobject *x_add PROTO((longobject *, longobject *));
587static longobject *
588x_add(a, b)
589 longobject *a, *b;
590{
591 int size_a = ABS(a->ob_size), size_b = ABS(b->ob_size);
592 longobject *z;
593 int i;
594 digit carry = 0;
595
596 /* Ensure a is the larger of the two: */
597 if (size_a < size_b) {
598 { longobject *temp = a; a = b; b = temp; }
599 { int size_temp = size_a; size_a = size_b; size_b = size_temp; }
600 }
601 z = alloclongobject(size_a+1);
602 if (z == NULL)
603 return NULL;
604 for (i = 0; i < size_b; ++i) {
605 carry += a->ob_digit[i] + b->ob_digit[i];
606 z->ob_digit[i] = carry & MASK;
607 /* The following assumes unsigned shifts don't
608 propagate the sign bit. */
609 carry >>= SHIFT;
610 }
611 for (; i < size_a; ++i) {
612 carry += a->ob_digit[i];
613 z->ob_digit[i] = carry & MASK;
614 carry >>= SHIFT;
615 }
616 z->ob_digit[i] = carry;
617 return long_normalize(z);
618}
619
620/* Subtract the absolute values of two integers. */
621
622static longobject *x_sub PROTO((longobject *, longobject *));
623static longobject *
624x_sub(a, b)
625 longobject *a, *b;
626{
627 int size_a = ABS(a->ob_size), size_b = ABS(b->ob_size);
628 longobject *z;
629 int i;
630 int sign = 1;
631 digit borrow = 0;
632
633 /* Ensure a is the larger of the two: */
634 if (size_a < size_b) {
635 sign = -1;
636 { longobject *temp = a; a = b; b = temp; }
637 { int size_temp = size_a; size_a = size_b; size_b = size_temp; }
638 }
639 else if (size_a == size_b) {
640 /* Find highest digit where a and b differ: */
641 i = size_a;
642 while (--i >= 0 && a->ob_digit[i] == b->ob_digit[i])
643 ;
644 if (i < 0)
645 return alloclongobject(0);
646 if (a->ob_digit[i] < b->ob_digit[i]) {
647 sign = -1;
648 { longobject *temp = a; a = b; b = temp; }
649 }
650 size_a = size_b = i+1;
651 }
652 z = alloclongobject(size_a);
653 if (z == NULL)
654 return NULL;
655 for (i = 0; i < size_b; ++i) {
656 /* The following assumes unsigned arithmetic
657 works module 2**N for some N>SHIFT. */
658 borrow = a->ob_digit[i] - b->ob_digit[i] - borrow;
659 z->ob_digit[i] = borrow & MASK;
660 borrow >>= SHIFT;
661 borrow &= 1; /* Keep only one sign bit */
662 }
663 for (; i < size_a; ++i) {
664 borrow = a->ob_digit[i] - borrow;
665 z->ob_digit[i] = borrow & MASK;
666 borrow >>= SHIFT;
667 }
668 assert(borrow == 0);
669 z->ob_size *= sign;
670 return long_normalize(z);
671}
672
673static object *
674long_add(a, w)
675 longobject *a;
676 object *w;
677{
678 longobject *b;
679 longobject *z;
680
681 if (!is_longobject(w)) {
682 err_badarg();
683 return NULL;
684 }
685 b = (longobject *)w;
686
687 if (a->ob_size < 0) {
688 if (b->ob_size < 0) {
689 z = x_add(a, b);
690 if (z != NULL)
691 z->ob_size = -z->ob_size;
692 }
693 else
694 z = x_sub(b, a);
695 }
696 else {
697 if (b->ob_size < 0)
698 z = x_sub(a, b);
699 else
700 z = x_add(a, b);
701 }
702 return (object *)z;
703}
704
705static object *
706long_sub(a, w)
707 longobject *a;
708 object *w;
709{
710 longobject *b;
711 longobject *z;
712
713 if (!is_longobject(w)) {
714 err_badarg();
715 return NULL;
716 }
717 b = (longobject *)w;
718
719 if (a->ob_size < 0) {
720 if (b->ob_size < 0)
721 z = x_sub(a, b);
722 else
723 z = x_add(a, b);
724 if (z != NULL)
725 z->ob_size = -z->ob_size;
726 }
727 else {
728 if (b->ob_size < 0)
729 z = x_add(a, b);
730 else
731 z = x_sub(a, b);
732 }
733 return (object *)z;
734}
735
736static object *
737long_mul(a, w)
738 longobject *a;
739 object *w;
740{
741 longobject *b;
742 int size_a;
743 int size_b;
744 longobject *z;
745 int i;
746
747 if (!is_longobject(w)) {
748 err_badarg();
749 return NULL;
750 }
751 b = (longobject *)w;
752 size_a = ABS(a->ob_size);
753 size_b = ABS(b->ob_size);
754 z = alloclongobject(size_a + size_b);
755 if (z == NULL)
756 return NULL;
757 for (i = 0; i < z->ob_size; ++i)
758 z->ob_digit[i] = 0;
759 for (i = 0; i < size_a; ++i) {
760 twodigits carry = 0;
761 twodigits f = a->ob_digit[i];
762 int j;
763
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000764 INTRCHECK({
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000765 DECREF(z);
766 err_set(KeyboardInterrupt);
767 return NULL;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000768 })
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000769 for (j = 0; j < size_b; ++j) {
770 carry += z->ob_digit[i+j] + b->ob_digit[j] * f;
771 z->ob_digit[i+j] = carry & MASK;
772 carry >>= SHIFT;
773 }
774 for (; carry != 0; ++j) {
775 assert(i+j < z->ob_size);
776 carry += z->ob_digit[i+j];
777 z->ob_digit[i+j] = carry & MASK;
778 carry >>= SHIFT;
779 }
780 }
781 if (a->ob_size < 0)
782 z->ob_size = -z->ob_size;
783 if (b->ob_size < 0)
784 z->ob_size = -z->ob_size;
785 return (object *) long_normalize(z);
786}
787
788static object *
789long_div(v, w)
790 longobject *v;
791 register object *w;
792{
793 if (!is_longobject(w)) {
794 err_badarg();
795 return NULL;
796 }
797 return (object *) long_divrem(v, (longobject *)w, (longobject **)0);
798}
799
800static object *
801long_rem(v, w)
802 longobject *v;
803 register object *w;
804{
805 longobject *div, *rem = NULL;
806 if (!is_longobject(w)) {
807 err_badarg();
808 return NULL;
809 }
810 div = long_divrem(v, (longobject *)w, &rem);
811 if (div == NULL) {
812 XDECREF(rem);
813 rem = NULL;
814 }
815 else {
816 DECREF(div);
817 }
818 return (object *) rem;
819}
820
821/* The expression a mod b has the value a - b*floor(a/b).
822 The divrem function gives the remainder after division of
823 |a| by |b|, with the sign of a. This is also expressed
824 as a - b*trunc(a/b), if trunc truncates towards zero.
825 Some examples:
826 a b a rem b a mod b
827 13 10 3 3
828 -13 10 -3 7
829 13 -10 3 -7
830 -13 -10 -3 -3
831 So, to get from rem to mod, we have to add b if a and b
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000832 have different signs. We then subtract one from the 'div'
833 part of the outcome to keep the invariant intact. */
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000834
835static object *
836long_divmod(v, w)
837 longobject *v;
838 register object *w;
839{
840 object *z;
841 longobject *div, *rem;
842 if (!is_longobject(w)) {
843 err_badarg();
844 return NULL;
845 }
846 div = long_divrem(v, (longobject *)w, &rem);
847 if (div == NULL) {
848 XDECREF(rem);
849 return NULL;
850 }
851 if ((v->ob_size < 0) != (((longobject *)w)->ob_size < 0)) {
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000852 longobject *temp;
853 longobject *one;
854 temp = (longobject *) long_add(rem, w);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000855 DECREF(rem);
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000856 rem = temp;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000857 if (rem == NULL) {
858 DECREF(div);
859 return NULL;
860 }
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000861 one = (longobject *) newlongobject(1L);
862 if (one == NULL ||
863 (temp = (longobject *) long_sub(div, one)) == NULL) {
864 DECREF(rem);
865 DECREF(div);
866 return NULL;
867 }
868 DECREF(div);
869 div = temp;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000870 }
871 z = newtupleobject(2);
872 if (z != NULL) {
873 settupleitem(z, 0, (object *) div);
874 settupleitem(z, 1, (object *) rem);
875 }
876 else {
877 DECREF(div);
878 DECREF(rem);
879 }
880 return z;
881}
882
883static object *
Guido van Rossumc7ec9c91991-05-28 21:58:16 +0000884long_pow(a, w)
885 longobject *a;
886 object *w;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000887{
Guido van Rossumc7ec9c91991-05-28 21:58:16 +0000888 register longobject *b;
889 longobject *z;
890 int size_b, i;
891
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000892 if (!is_longobject(w)) {
893 err_badarg();
894 return NULL;
895 }
Guido van Rossumc7ec9c91991-05-28 21:58:16 +0000896
897 b = (longobject *)w;
898 size_b = b->ob_size;
899 if (size_b < 0) {
900 err_setstr(RuntimeError, "long integer to the negative power");
901 return NULL;
902 }
903
904 z = (longobject *)newlongobject(1L);
905
906 INCREF(a);
907 for (i = 0; i < size_b; ++i) {
908 digit bi = b->ob_digit[i];
909 int j;
910
911 for (j = 0; j < SHIFT; ++j) {
912 longobject *temp;
913
914 if (bi & 1) {
915 temp = (longobject *)long_mul(z, (object *)a);
916 DECREF(z);
917 z = temp;
918 if (z == NULL)
919 break;
920 }
921 bi >>= 1;
922 if (bi == 0 && i+1 == size_b)
923 break;
924 temp = (longobject *)long_mul(a, (object *)a);
925 DECREF(a);
926 a = temp;
927 if (a == NULL) {
928 DECREF(z);
929 z = NULL;
930 break;
931 }
932 }
933 if (a == NULL)
934 break;
935 }
936 XDECREF(a);
937 return (object *)z;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000938}
939
940static object *
941long_pos(v)
942 longobject *v;
943{
944 INCREF(v);
945 return (object *)v;
946}
947
948static object *
949long_neg(v)
950 longobject *v;
951{
952 longobject *z;
953 int i = v->ob_size;
954 if (i == 0)
955 return long_pos(v);
956 i = ABS(i);
957 z = alloclongobject(i);
958 if (z != NULL) {
959 z->ob_size = - v->ob_size;
960 while (--i >= 0)
961 z->ob_digit[i] = v->ob_digit[i];
962 }
963 return (object *)z;
964}
965
966static object *
967long_abs(v)
968 longobject *v;
969{
970 if (v->ob_size < 0)
971 return long_neg(v);
972 else
973 return long_pos(v);
974}
975
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000976static int
977long_nonzero(v)
978 longobject *v;
979{
980 return v->ob_size != 0;
981}
982
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000983static number_methods long_as_number = {
984 long_add, /*nb_add*/
985 long_sub, /*nb_subtract*/
986 long_mul, /*nb_multiply*/
987 long_div, /*nb_divide*/
988 long_rem, /*nb_remainder*/
989 long_divmod, /*nb_divmod*/
990 long_pow, /*nb_power*/
991 long_neg, /*nb_negative*/
992 long_pos, /*tp_positive*/
993 long_abs, /*tp_absolute*/
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000994 long_nonzero, /*tp_nonzero*/
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000995};
996
997typeobject Longtype = {
998 OB_HEAD_INIT(&Typetype)
999 0,
1000 "long int",
1001 sizeof(longobject) - sizeof(digit),
1002 sizeof(digit),
1003 long_dealloc, /*tp_dealloc*/
1004 long_print, /*tp_print*/
1005 0, /*tp_getattr*/
1006 0, /*tp_setattr*/
1007 long_compare, /*tp_compare*/
1008 long_repr, /*tp_repr*/
1009 &long_as_number,/*tp_as_number*/
1010 0, /*tp_as_sequence*/
1011 0, /*tp_as_mapping*/
1012};