blob: badc3df0713c5349001e1844fef0663f1bd677f3 [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"
31#include <assert.h>
32
Guido van Rossum23d6f0e1991-05-14 12:06:49 +000033static int ticker; /* XXX Could be shared with ceval? */
34
35#define INTRCHECK(block) \
36 if (--ticker < 0) { \
37 ticker = 100; \
38 if (intrcheck()) { block; } \
39 }
40
Guido van Rossumedcc38a1991-05-05 20:09:44 +000041/* Normalize (remove leading zeros from) a long int object.
42 Doesn't attempt to free the storage--in most cases, due to the nature
43 of the algorithms used, this could save at most be one word anyway. */
44
45longobject *
46long_normalize(v)
47 register longobject *v;
48{
49 int j = ABS(v->ob_size);
50 register int i = j;
51
52 while (i > 0 && v->ob_digit[i-1] == 0)
53 --i;
54 if (i != j)
55 v->ob_size = (v->ob_size < 0) ? -i : i;
56 return v;
57}
58
59/* Allocate a new long int object with size digits.
60 Return NULL and set exception if we run out of memory. */
61
62longobject *
63alloclongobject(size)
64 int size;
65{
66 return NEWVAROBJ(longobject, &Longtype, size);
67}
68
69/* Create a new long int object from a C long int */
70
71object *
72newlongobject(ival)
73 long ival;
74{
75 /* Assume a C long fits in at most 3 'digits' */
76 longobject *v = alloclongobject(3);
77 if (v != NULL) {
78 if (ival < 0) {
79 ival = -ival;
80 v->ob_size = -v->ob_size;
81 }
82 v->ob_digit[0] = ival & MASK;
83 v->ob_digit[1] = (ival >> SHIFT) & MASK;
84 v->ob_digit[2] = (ival >> (2*SHIFT)) & MASK;
85 v = long_normalize(v);
86 }
87 return (object *)v;
88}
89
90/* Get a C long int from a long int object.
91 Returns -1 and sets an error condition if overflow occurs. */
92
93long
94getlongvalue(vv)
95 object *vv;
96{
97 register longobject *v;
98 long x, prev;
99 int i, sign;
100
101 if (vv == NULL || !is_longobject(vv)) {
102 err_badcall();
103 return -1;
104 }
105 v = (longobject *)vv;
106 i = v->ob_size;
107 sign = 1;
108 x = 0;
109 if (i < 0) {
110 sign = -1;
111 i = -i;
112 }
113 while (--i >= 0) {
114 prev = x;
115 x = (x << SHIFT) + v->ob_digit[i];
116 if ((x >> SHIFT) != prev) {
117 err_setstr(RuntimeError,
118 "long int too long to convert");
119 return -1;
120 }
121 }
122 return x * sign;
123}
124
125/* Get a C double from a long int object. No overflow check. */
126
127double
128dgetlongvalue(vv)
129 object *vv;
130{
131 register longobject *v;
132 double x;
133 double multiplier = (double) (1L << SHIFT);
134 int i, sign;
135
136 if (vv == NULL || !is_longobject(vv)) {
137 err_badcall();
138 return -1;
139 }
140 v = (longobject *)vv;
141 i = v->ob_size;
142 sign = 1;
143 x = 0.0;
144 if (i < 0) {
145 sign = -1;
146 i = -i;
147 }
148 while (--i >= 0) {
149 x = x*multiplier + v->ob_digit[i];
150 }
151 return x * sign;
152}
153
154/* Multiply by a single digit, ignoring the sign. */
155
156longobject *
157mul1(a, n)
158 longobject *a;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000159 wdigit n;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000160{
161 return muladd1(a, n, (digit)0);
162}
163
164/* Multiply by a single digit and add a single digit, ignoring the sign. */
165
166longobject *
167muladd1(a, n, extra)
168 longobject *a;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000169 wdigit n;
170 wdigit extra;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000171{
172 int size_a = ABS(a->ob_size);
173 longobject *z = alloclongobject(size_a+1);
174 twodigits carry = extra;
175 int i;
176
177 if (z == NULL)
178 return NULL;
179 for (i = 0; i < size_a; ++i) {
180 carry += (twodigits)a->ob_digit[i] * n;
181 z->ob_digit[i] = carry & MASK;
182 carry >>= SHIFT;
183 }
184 z->ob_digit[i] = carry;
185 return long_normalize(z);
186}
187
188/* Divide a long integer by a digit, returning both the quotient
189 (as function result) and the remainder (through *prem).
190 The sign of a is ignored; n should not be zero. */
191
192longobject *
193divrem1(a, n, prem)
194 longobject *a;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000195 wdigit n;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000196 digit *prem;
197{
198 int size = ABS(a->ob_size);
199 longobject *z;
200 int i;
201 twodigits rem = 0;
202
203 assert(n > 0 && n <= MASK);
204 z = alloclongobject(size);
205 if (z == NULL)
206 return NULL;
207 for (i = size; --i >= 0; ) {
208 rem = (rem << SHIFT) + a->ob_digit[i];
209 z->ob_digit[i] = rem/n;
210 rem %= n;
211 }
212 *prem = rem;
213 return long_normalize(z);
214}
215
216/* Convert a long int object to a string, using a given conversion base.
217 Return a string object. */
218
219stringobject *
220long_format(a, base)
221 longobject *a;
222 int base;
223{
224 stringobject *str;
225 int i;
226 int size_a = ABS(a->ob_size);
227 char *p;
228 int bits;
229 char sign = '\0';
230
231 assert(base >= 2 && base <= 36);
232
233 /* Compute a rough upper bound for the length of the string */
234 i = base;
235 bits = 0;
236 while (i > 1) {
237 ++bits;
238 i >>= 1;
239 }
240 i = 1 + (size_a*SHIFT + bits-1) / bits;
241 str = (stringobject *) newsizedstringobject((char *)0, i);
242 if (str == NULL)
243 return NULL;
244 p = GETSTRINGVALUE(str) + i;
245 *p = '\0';
246 if (a->ob_size < 0)
247 sign = '-';
248
249 INCREF(a);
250 do {
251 digit rem;
252 longobject *temp = divrem1(a, (digit)base, &rem);
253 if (temp == NULL) {
254 DECREF(a);
255 DECREF(str);
256 return NULL;
257 }
258 if (rem < 10)
259 rem += '0';
260 else
261 rem += 'A'-10;
262 assert(p > GETSTRINGVALUE(str));
263 *--p = rem;
264 DECREF(a);
265 a = temp;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000266 INTRCHECK({
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000267 DECREF(a);
268 DECREF(str);
269 err_set(KeyboardInterrupt);
270 return NULL;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000271 })
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000272 } while (a->ob_size != 0);
273 DECREF(a);
274 if (sign)
275 *--p = sign;
276 if (p != GETSTRINGVALUE(str)) {
277 char *q = GETSTRINGVALUE(str);
278 assert(p > q);
279 do {
280 } while ((*q++ = *p++) != '\0');
Guido van Rossumc7ec9c91991-05-28 21:58:16 +0000281 q--;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000282 resizestring((object **)&str, (int) (q - GETSTRINGVALUE(str)));
283 }
284 return str;
285}
286
287/* Convert a string to a long int object, in a given base.
288 Base zero implies a default depending on the number. */
289
290object *
291long_scan(str, base)
292 char *str;
293 int base;
294{
295 int sign = 1;
296 longobject *z;
297
298 assert(base == 0 || base >= 2 && base <= 36);
299 if (*str == '+')
300 ++str;
301 else if (*str == '-') {
302 ++str;
303 sign = -1;
304 }
305 if (base == 0) {
306 if (str[0] != '0')
307 base = 10;
308 else if (str[1] == 'x' || str[1] == 'X')
309 base = 16;
310 else
311 base = 8;
312 }
313 if (base == 16 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
314 str += 2;
315 z = alloclongobject(0);
316 for ( ; z != NULL; ++str) {
317 int k = -1;
318 longobject *temp;
319
320 if (*str <= '9')
321 k = *str - '0';
322 else if (*str >= 'a')
323 k = *str - 'a' + 10;
324 else if (*str >= 'A')
325 k = *str - 'A' + 10;
326 if (k < 0 || k >= base)
327 break;
328 temp = muladd1(z, (digit)base, (digit)k);
329 DECREF(z);
330 z = temp;
331 }
332 if (z != NULL)
333 z->ob_size *= sign;
334 return (object *) z;
335}
336
337static longobject *x_divrem PROTO((longobject *, longobject *, longobject **));
338
339/* Long division with remainder, top-level routine */
340
341longobject *
342long_divrem(a, b, prem)
343 longobject *a, *b;
344 longobject **prem;
345{
346 int size_a = ABS(a->ob_size), size_b = ABS(b->ob_size);
347 longobject *z;
348
349 if (size_b == 0) {
350 if (prem != NULL)
351 *prem = NULL;
352 err_setstr(RuntimeError, "long division by zero");
353 return NULL;
354 }
355 if (size_a < size_b ||
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000356 size_a == size_b &&
357 a->ob_digit[size_a-1] < b->ob_digit[size_b-1]) {
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000358 /* |a| < |b|. */
359 if (prem != NULL) {
360 INCREF(a);
361 *prem = a;
362 }
363 return alloclongobject(0);
364 }
365 if (size_b == 1) {
366 digit rem = 0;
367 z = divrem1(a, b->ob_digit[0], &rem);
368 if (prem != NULL) {
369 if (z == NULL)
370 *prem = NULL;
371 else
372 *prem = (longobject *)
373 newlongobject((long)rem);
374 }
375 }
376 else
377 z = x_divrem(a, b, prem);
378 /* Set the signs.
379 The quotient z has the sign of a*b;
380 the remainder r has the sign of a,
381 so a = b*z + r. */
382 if (z != NULL) {
383 if ((a->ob_size < 0) != (b->ob_size < 0))
384 z->ob_size = - z->ob_size;
385 if (prem != NULL && *prem != NULL && a->ob_size < 0)
386 (*prem)->ob_size = - (*prem)->ob_size;
387 }
388 return z;
389}
390
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000391/* Unsigned long division with remainder -- the algorithm */
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000392
393static longobject *
394x_divrem(v1, w1, prem)
395 longobject *v1, *w1;
396 longobject **prem;
397{
398 int size_v = ABS(v1->ob_size), size_w = ABS(w1->ob_size);
399 digit d = (twodigits)BASE / (w1->ob_digit[size_w-1] + 1);
400 longobject *v = mul1(v1, d);
401 longobject *w = mul1(w1, d);
402 longobject *a;
403 int j, k;
404
405 if (v == NULL || w == NULL) {
406 XDECREF(v);
407 XDECREF(w);
408 if (prem != NULL)
409 *prem = NULL;
410 return NULL;
411 }
412
413 assert(size_v >= size_w && size_w > 1); /* Assert checks by div() */
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000414 assert(v->ob_refcnt == 1); /* Since v will be used as accumulator! */
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000415 assert(size_w == ABS(w->ob_size)); /* That's how d was calculated */
416
417 size_v = ABS(v->ob_size);
418 a = alloclongobject(size_v - size_w + 1);
419
420 for (j = size_v, k = a->ob_size-1; a != NULL && k >= 0; --j, --k) {
421 digit vj = (j >= size_v) ? 0 : v->ob_digit[j];
422 twodigits q;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000423 stwodigits carry = 0;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000424 int i;
425
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000426 INTRCHECK({
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000427 DECREF(a);
428 a = NULL;
429 err_set(KeyboardInterrupt);
430 break;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000431 })
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000432 if (vj == w->ob_digit[size_w-1])
433 q = MASK;
434 else
435 q = (((twodigits)vj << SHIFT) + v->ob_digit[j-1]) /
436 w->ob_digit[size_w-1];
437
438 while (w->ob_digit[size_w-2]*q >
439 ((
440 ((twodigits)vj << SHIFT)
441 + v->ob_digit[j-1]
442 - q*w->ob_digit[size_w-1]
443 ) << SHIFT)
444 + v->ob_digit[j-2])
445 --q;
446
447 for (i = 0; i < size_w && i+k < size_v; ++i) {
448 twodigits z = w->ob_digit[i] * q;
449 digit zz = z >> SHIFT;
450 carry += v->ob_digit[i+k] - z + ((twodigits)zz << SHIFT);
451 v->ob_digit[i+k] = carry & MASK;
452 carry = (carry >> SHIFT) - zz;
453 }
454
455 if (i+k < size_v) {
456 carry += v->ob_digit[i+k];
457 v->ob_digit[i+k] = 0;
458 }
459
460 if (carry == 0)
461 a->ob_digit[k] = q;
462 else {
463 assert(carry == -1);
464 a->ob_digit[k] = q-1;
465 carry = 0;
466 for (i = 0; i < size_w && i+k < size_v; ++i) {
467 carry += v->ob_digit[i+k] + w->ob_digit[i];
468 v->ob_digit[i+k] = carry & MASK;
469 carry >>= SHIFT;
470 }
471 }
472 } /* for j, k */
473
474 if (a != NULL)
475 a = long_normalize(a);
476 if (prem != 0) {
477 if (a == NULL)
478 *prem = NULL;
479 else
480 *prem = divrem1(v, d, &d);
481 /* Using d as a dummy to receive the - unused - remainder */
482 }
483 DECREF(v);
484 DECREF(w);
485 return a;
486}
487
488/* Methods */
489
490static void
491long_dealloc(v)
492 longobject *v;
493{
494 DEL(v);
495}
496
497static void
498long_print(v, fp, flags)
499 longobject *v;
500 FILE *fp;
501 int flags;
502{
503 stringobject *str = long_format(v, 10);
504 if (str == NULL) {
505 err_clear();
506 fprintf(fp, "[err]");
507 }
508 else {
509 fprintf(fp, "%sL", GETSTRINGVALUE(str));
510 DECREF(str);
511 }
512}
513
514static object *
515long_repr(v)
516 longobject *v;
517{
518 stringobject *str = long_format(v, 10);
519 if (str != NULL) {
520 int len = getstringsize((object *)str);
521 resizestring((object **)&str, len + 1);
522 if (str != NULL)
523 GETSTRINGVALUE(str)[len] = 'L';
524 }
525 return (object *)str;
526}
527
528static int
529long_compare(a, b)
530 longobject *a, *b;
531{
532 int sign;
533
534 if (a->ob_size != b->ob_size)
535 sign = a->ob_size - b->ob_size;
536 else {
537 int i = ABS(a->ob_size);
538 while (--i >= 0 && a->ob_digit[i] == b->ob_digit[i])
539 ;
540 if (i < 0)
541 sign = 0;
542 else
543 sign = (int)a->ob_digit[i] - (int)b->ob_digit[i];
544 }
545 return sign;
546}
547
548/* Add the absolute values of two long integers. */
549
550static longobject *x_add PROTO((longobject *, longobject *));
551static longobject *
552x_add(a, b)
553 longobject *a, *b;
554{
555 int size_a = ABS(a->ob_size), size_b = ABS(b->ob_size);
556 longobject *z;
557 int i;
558 digit carry = 0;
559
560 /* Ensure a is the larger of the two: */
561 if (size_a < size_b) {
562 { longobject *temp = a; a = b; b = temp; }
563 { int size_temp = size_a; size_a = size_b; size_b = size_temp; }
564 }
565 z = alloclongobject(size_a+1);
566 if (z == NULL)
567 return NULL;
568 for (i = 0; i < size_b; ++i) {
569 carry += a->ob_digit[i] + b->ob_digit[i];
570 z->ob_digit[i] = carry & MASK;
571 /* The following assumes unsigned shifts don't
572 propagate the sign bit. */
573 carry >>= SHIFT;
574 }
575 for (; i < size_a; ++i) {
576 carry += a->ob_digit[i];
577 z->ob_digit[i] = carry & MASK;
578 carry >>= SHIFT;
579 }
580 z->ob_digit[i] = carry;
581 return long_normalize(z);
582}
583
584/* Subtract the absolute values of two integers. */
585
586static longobject *x_sub PROTO((longobject *, longobject *));
587static longobject *
588x_sub(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 int sign = 1;
595 digit borrow = 0;
596
597 /* Ensure a is the larger of the two: */
598 if (size_a < size_b) {
599 sign = -1;
600 { longobject *temp = a; a = b; b = temp; }
601 { int size_temp = size_a; size_a = size_b; size_b = size_temp; }
602 }
603 else if (size_a == size_b) {
604 /* Find highest digit where a and b differ: */
605 i = size_a;
606 while (--i >= 0 && a->ob_digit[i] == b->ob_digit[i])
607 ;
608 if (i < 0)
609 return alloclongobject(0);
610 if (a->ob_digit[i] < b->ob_digit[i]) {
611 sign = -1;
612 { longobject *temp = a; a = b; b = temp; }
613 }
614 size_a = size_b = i+1;
615 }
616 z = alloclongobject(size_a);
617 if (z == NULL)
618 return NULL;
619 for (i = 0; i < size_b; ++i) {
620 /* The following assumes unsigned arithmetic
621 works module 2**N for some N>SHIFT. */
622 borrow = a->ob_digit[i] - b->ob_digit[i] - borrow;
623 z->ob_digit[i] = borrow & MASK;
624 borrow >>= SHIFT;
625 borrow &= 1; /* Keep only one sign bit */
626 }
627 for (; i < size_a; ++i) {
628 borrow = a->ob_digit[i] - borrow;
629 z->ob_digit[i] = borrow & MASK;
630 borrow >>= SHIFT;
631 }
632 assert(borrow == 0);
633 z->ob_size *= sign;
634 return long_normalize(z);
635}
636
637static object *
638long_add(a, w)
639 longobject *a;
640 object *w;
641{
642 longobject *b;
643 longobject *z;
644
645 if (!is_longobject(w)) {
646 err_badarg();
647 return NULL;
648 }
649 b = (longobject *)w;
650
651 if (a->ob_size < 0) {
652 if (b->ob_size < 0) {
653 z = x_add(a, b);
654 if (z != NULL)
655 z->ob_size = -z->ob_size;
656 }
657 else
658 z = x_sub(b, a);
659 }
660 else {
661 if (b->ob_size < 0)
662 z = x_sub(a, b);
663 else
664 z = x_add(a, b);
665 }
666 return (object *)z;
667}
668
669static object *
670long_sub(a, w)
671 longobject *a;
672 object *w;
673{
674 longobject *b;
675 longobject *z;
676
677 if (!is_longobject(w)) {
678 err_badarg();
679 return NULL;
680 }
681 b = (longobject *)w;
682
683 if (a->ob_size < 0) {
684 if (b->ob_size < 0)
685 z = x_sub(a, b);
686 else
687 z = x_add(a, b);
688 if (z != NULL)
689 z->ob_size = -z->ob_size;
690 }
691 else {
692 if (b->ob_size < 0)
693 z = x_add(a, b);
694 else
695 z = x_sub(a, b);
696 }
697 return (object *)z;
698}
699
700static object *
701long_mul(a, w)
702 longobject *a;
703 object *w;
704{
705 longobject *b;
706 int size_a;
707 int size_b;
708 longobject *z;
709 int i;
710
711 if (!is_longobject(w)) {
712 err_badarg();
713 return NULL;
714 }
715 b = (longobject *)w;
716 size_a = ABS(a->ob_size);
717 size_b = ABS(b->ob_size);
718 z = alloclongobject(size_a + size_b);
719 if (z == NULL)
720 return NULL;
721 for (i = 0; i < z->ob_size; ++i)
722 z->ob_digit[i] = 0;
723 for (i = 0; i < size_a; ++i) {
724 twodigits carry = 0;
725 twodigits f = a->ob_digit[i];
726 int j;
727
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000728 INTRCHECK({
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000729 DECREF(z);
730 err_set(KeyboardInterrupt);
731 return NULL;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000732 })
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000733 for (j = 0; j < size_b; ++j) {
734 carry += z->ob_digit[i+j] + b->ob_digit[j] * f;
735 z->ob_digit[i+j] = carry & MASK;
736 carry >>= SHIFT;
737 }
738 for (; carry != 0; ++j) {
739 assert(i+j < z->ob_size);
740 carry += z->ob_digit[i+j];
741 z->ob_digit[i+j] = carry & MASK;
742 carry >>= SHIFT;
743 }
744 }
745 if (a->ob_size < 0)
746 z->ob_size = -z->ob_size;
747 if (b->ob_size < 0)
748 z->ob_size = -z->ob_size;
749 return (object *) long_normalize(z);
750}
751
752static object *
753long_div(v, w)
754 longobject *v;
755 register object *w;
756{
757 if (!is_longobject(w)) {
758 err_badarg();
759 return NULL;
760 }
761 return (object *) long_divrem(v, (longobject *)w, (longobject **)0);
762}
763
764static object *
765long_rem(v, w)
766 longobject *v;
767 register object *w;
768{
769 longobject *div, *rem = NULL;
770 if (!is_longobject(w)) {
771 err_badarg();
772 return NULL;
773 }
774 div = long_divrem(v, (longobject *)w, &rem);
775 if (div == NULL) {
776 XDECREF(rem);
777 rem = NULL;
778 }
779 else {
780 DECREF(div);
781 }
782 return (object *) rem;
783}
784
785/* The expression a mod b has the value a - b*floor(a/b).
786 The divrem function gives the remainder after division of
787 |a| by |b|, with the sign of a. This is also expressed
788 as a - b*trunc(a/b), if trunc truncates towards zero.
789 Some examples:
790 a b a rem b a mod b
791 13 10 3 3
792 -13 10 -3 7
793 13 -10 3 -7
794 -13 -10 -3 -3
795 So, to get from rem to mod, we have to add b if a and b
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000796 have different signs. We then subtract one from the 'div'
797 part of the outcome to keep the invariant intact. */
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000798
799static object *
800long_divmod(v, w)
801 longobject *v;
802 register object *w;
803{
804 object *z;
805 longobject *div, *rem;
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 return NULL;
814 }
815 if ((v->ob_size < 0) != (((longobject *)w)->ob_size < 0)) {
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000816 longobject *temp;
817 longobject *one;
818 temp = (longobject *) long_add(rem, w);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000819 DECREF(rem);
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000820 rem = temp;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000821 if (rem == NULL) {
822 DECREF(div);
823 return NULL;
824 }
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000825 one = (longobject *) newlongobject(1L);
826 if (one == NULL ||
827 (temp = (longobject *) long_sub(div, one)) == NULL) {
828 DECREF(rem);
829 DECREF(div);
830 return NULL;
831 }
832 DECREF(div);
833 div = temp;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000834 }
835 z = newtupleobject(2);
836 if (z != NULL) {
837 settupleitem(z, 0, (object *) div);
838 settupleitem(z, 1, (object *) rem);
839 }
840 else {
841 DECREF(div);
842 DECREF(rem);
843 }
844 return z;
845}
846
847static object *
Guido van Rossumc7ec9c91991-05-28 21:58:16 +0000848long_pow(a, w)
849 longobject *a;
850 object *w;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000851{
Guido van Rossumc7ec9c91991-05-28 21:58:16 +0000852 register longobject *b;
853 longobject *z;
854 int size_b, i;
855
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000856 if (!is_longobject(w)) {
857 err_badarg();
858 return NULL;
859 }
Guido van Rossumc7ec9c91991-05-28 21:58:16 +0000860
861 b = (longobject *)w;
862 size_b = b->ob_size;
863 if (size_b < 0) {
864 err_setstr(RuntimeError, "long integer to the negative power");
865 return NULL;
866 }
867
868 z = (longobject *)newlongobject(1L);
869
870 INCREF(a);
871 for (i = 0; i < size_b; ++i) {
872 digit bi = b->ob_digit[i];
873 int j;
874
875 for (j = 0; j < SHIFT; ++j) {
876 longobject *temp;
877
878 if (bi & 1) {
879 temp = (longobject *)long_mul(z, (object *)a);
880 DECREF(z);
881 z = temp;
882 if (z == NULL)
883 break;
884 }
885 bi >>= 1;
886 if (bi == 0 && i+1 == size_b)
887 break;
888 temp = (longobject *)long_mul(a, (object *)a);
889 DECREF(a);
890 a = temp;
891 if (a == NULL) {
892 DECREF(z);
893 z = NULL;
894 break;
895 }
896 }
897 if (a == NULL)
898 break;
899 }
900 XDECREF(a);
901 return (object *)z;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000902}
903
904static object *
905long_pos(v)
906 longobject *v;
907{
908 INCREF(v);
909 return (object *)v;
910}
911
912static object *
913long_neg(v)
914 longobject *v;
915{
916 longobject *z;
917 int i = v->ob_size;
918 if (i == 0)
919 return long_pos(v);
920 i = ABS(i);
921 z = alloclongobject(i);
922 if (z != NULL) {
923 z->ob_size = - v->ob_size;
924 while (--i >= 0)
925 z->ob_digit[i] = v->ob_digit[i];
926 }
927 return (object *)z;
928}
929
930static object *
931long_abs(v)
932 longobject *v;
933{
934 if (v->ob_size < 0)
935 return long_neg(v);
936 else
937 return long_pos(v);
938}
939
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000940static int
941long_nonzero(v)
942 longobject *v;
943{
944 return v->ob_size != 0;
945}
946
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000947static number_methods long_as_number = {
948 long_add, /*nb_add*/
949 long_sub, /*nb_subtract*/
950 long_mul, /*nb_multiply*/
951 long_div, /*nb_divide*/
952 long_rem, /*nb_remainder*/
953 long_divmod, /*nb_divmod*/
954 long_pow, /*nb_power*/
955 long_neg, /*nb_negative*/
956 long_pos, /*tp_positive*/
957 long_abs, /*tp_absolute*/
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000958 long_nonzero, /*tp_nonzero*/
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000959};
960
961typeobject Longtype = {
962 OB_HEAD_INIT(&Typetype)
963 0,
964 "long int",
965 sizeof(longobject) - sizeof(digit),
966 sizeof(digit),
967 long_dealloc, /*tp_dealloc*/
968 long_print, /*tp_print*/
969 0, /*tp_getattr*/
970 0, /*tp_setattr*/
971 long_compare, /*tp_compare*/
972 long_repr, /*tp_repr*/
973 &long_as_number,/*tp_as_number*/
974 0, /*tp_as_sequence*/
975 0, /*tp_as_mapping*/
976};