blob: a2fccc51067202b231178c1c04fb56dad5a66d16 [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');
281 resizestring((object **)&str, (int) (q - GETSTRINGVALUE(str)));
282 }
283 return str;
284}
285
286/* Convert a string to a long int object, in a given base.
287 Base zero implies a default depending on the number. */
288
289object *
290long_scan(str, base)
291 char *str;
292 int base;
293{
294 int sign = 1;
295 longobject *z;
296
297 assert(base == 0 || base >= 2 && base <= 36);
298 if (*str == '+')
299 ++str;
300 else if (*str == '-') {
301 ++str;
302 sign = -1;
303 }
304 if (base == 0) {
305 if (str[0] != '0')
306 base = 10;
307 else if (str[1] == 'x' || str[1] == 'X')
308 base = 16;
309 else
310 base = 8;
311 }
312 if (base == 16 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
313 str += 2;
314 z = alloclongobject(0);
315 for ( ; z != NULL; ++str) {
316 int k = -1;
317 longobject *temp;
318
319 if (*str <= '9')
320 k = *str - '0';
321 else if (*str >= 'a')
322 k = *str - 'a' + 10;
323 else if (*str >= 'A')
324 k = *str - 'A' + 10;
325 if (k < 0 || k >= base)
326 break;
327 temp = muladd1(z, (digit)base, (digit)k);
328 DECREF(z);
329 z = temp;
330 }
331 if (z != NULL)
332 z->ob_size *= sign;
333 return (object *) z;
334}
335
336static longobject *x_divrem PROTO((longobject *, longobject *, longobject **));
337
338/* Long division with remainder, top-level routine */
339
340longobject *
341long_divrem(a, b, prem)
342 longobject *a, *b;
343 longobject **prem;
344{
345 int size_a = ABS(a->ob_size), size_b = ABS(b->ob_size);
346 longobject *z;
347
348 if (size_b == 0) {
349 if (prem != NULL)
350 *prem = NULL;
351 err_setstr(RuntimeError, "long division by zero");
352 return NULL;
353 }
354 if (size_a < size_b ||
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000355 size_a == size_b &&
356 a->ob_digit[size_a-1] < b->ob_digit[size_b-1]) {
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000357 /* |a| < |b|. */
358 if (prem != NULL) {
359 INCREF(a);
360 *prem = a;
361 }
362 return alloclongobject(0);
363 }
364 if (size_b == 1) {
365 digit rem = 0;
366 z = divrem1(a, b->ob_digit[0], &rem);
367 if (prem != NULL) {
368 if (z == NULL)
369 *prem = NULL;
370 else
371 *prem = (longobject *)
372 newlongobject((long)rem);
373 }
374 }
375 else
376 z = x_divrem(a, b, prem);
377 /* Set the signs.
378 The quotient z has the sign of a*b;
379 the remainder r has the sign of a,
380 so a = b*z + r. */
381 if (z != NULL) {
382 if ((a->ob_size < 0) != (b->ob_size < 0))
383 z->ob_size = - z->ob_size;
384 if (prem != NULL && *prem != NULL && a->ob_size < 0)
385 (*prem)->ob_size = - (*prem)->ob_size;
386 }
387 return z;
388}
389
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000390/* Unsigned long division with remainder -- the algorithm */
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000391
392static longobject *
393x_divrem(v1, w1, prem)
394 longobject *v1, *w1;
395 longobject **prem;
396{
397 int size_v = ABS(v1->ob_size), size_w = ABS(w1->ob_size);
398 digit d = (twodigits)BASE / (w1->ob_digit[size_w-1] + 1);
399 longobject *v = mul1(v1, d);
400 longobject *w = mul1(w1, d);
401 longobject *a;
402 int j, k;
403
404 if (v == NULL || w == NULL) {
405 XDECREF(v);
406 XDECREF(w);
407 if (prem != NULL)
408 *prem = NULL;
409 return NULL;
410 }
411
412 assert(size_v >= size_w && size_w > 1); /* Assert checks by div() */
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000413 assert(v->ob_refcnt == 1); /* Since v will be used as accumulator! */
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000414 assert(size_w == ABS(w->ob_size)); /* That's how d was calculated */
415
416 size_v = ABS(v->ob_size);
417 a = alloclongobject(size_v - size_w + 1);
418
419 for (j = size_v, k = a->ob_size-1; a != NULL && k >= 0; --j, --k) {
420 digit vj = (j >= size_v) ? 0 : v->ob_digit[j];
421 twodigits q;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000422 stwodigits carry = 0;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000423 int i;
424
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000425 INTRCHECK({
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000426 DECREF(a);
427 a = NULL;
428 err_set(KeyboardInterrupt);
429 break;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000430 })
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000431 if (vj == w->ob_digit[size_w-1])
432 q = MASK;
433 else
434 q = (((twodigits)vj << SHIFT) + v->ob_digit[j-1]) /
435 w->ob_digit[size_w-1];
436
437 while (w->ob_digit[size_w-2]*q >
438 ((
439 ((twodigits)vj << SHIFT)
440 + v->ob_digit[j-1]
441 - q*w->ob_digit[size_w-1]
442 ) << SHIFT)
443 + v->ob_digit[j-2])
444 --q;
445
446 for (i = 0; i < size_w && i+k < size_v; ++i) {
447 twodigits z = w->ob_digit[i] * q;
448 digit zz = z >> SHIFT;
449 carry += v->ob_digit[i+k] - z + ((twodigits)zz << SHIFT);
450 v->ob_digit[i+k] = carry & MASK;
451 carry = (carry >> SHIFT) - zz;
452 }
453
454 if (i+k < size_v) {
455 carry += v->ob_digit[i+k];
456 v->ob_digit[i+k] = 0;
457 }
458
459 if (carry == 0)
460 a->ob_digit[k] = q;
461 else {
462 assert(carry == -1);
463 a->ob_digit[k] = q-1;
464 carry = 0;
465 for (i = 0; i < size_w && i+k < size_v; ++i) {
466 carry += v->ob_digit[i+k] + w->ob_digit[i];
467 v->ob_digit[i+k] = carry & MASK;
468 carry >>= SHIFT;
469 }
470 }
471 } /* for j, k */
472
473 if (a != NULL)
474 a = long_normalize(a);
475 if (prem != 0) {
476 if (a == NULL)
477 *prem = NULL;
478 else
479 *prem = divrem1(v, d, &d);
480 /* Using d as a dummy to receive the - unused - remainder */
481 }
482 DECREF(v);
483 DECREF(w);
484 return a;
485}
486
487/* Methods */
488
489static void
490long_dealloc(v)
491 longobject *v;
492{
493 DEL(v);
494}
495
496static void
497long_print(v, fp, flags)
498 longobject *v;
499 FILE *fp;
500 int flags;
501{
502 stringobject *str = long_format(v, 10);
503 if (str == NULL) {
504 err_clear();
505 fprintf(fp, "[err]");
506 }
507 else {
508 fprintf(fp, "%sL", GETSTRINGVALUE(str));
509 DECREF(str);
510 }
511}
512
513static object *
514long_repr(v)
515 longobject *v;
516{
517 stringobject *str = long_format(v, 10);
518 if (str != NULL) {
519 int len = getstringsize((object *)str);
520 resizestring((object **)&str, len + 1);
521 if (str != NULL)
522 GETSTRINGVALUE(str)[len] = 'L';
523 }
524 return (object *)str;
525}
526
527static int
528long_compare(a, b)
529 longobject *a, *b;
530{
531 int sign;
532
533 if (a->ob_size != b->ob_size)
534 sign = a->ob_size - b->ob_size;
535 else {
536 int i = ABS(a->ob_size);
537 while (--i >= 0 && a->ob_digit[i] == b->ob_digit[i])
538 ;
539 if (i < 0)
540 sign = 0;
541 else
542 sign = (int)a->ob_digit[i] - (int)b->ob_digit[i];
543 }
544 return sign;
545}
546
547/* Add the absolute values of two long integers. */
548
549static longobject *x_add PROTO((longobject *, longobject *));
550static longobject *
551x_add(a, b)
552 longobject *a, *b;
553{
554 int size_a = ABS(a->ob_size), size_b = ABS(b->ob_size);
555 longobject *z;
556 int i;
557 digit carry = 0;
558
559 /* Ensure a is the larger of the two: */
560 if (size_a < size_b) {
561 { longobject *temp = a; a = b; b = temp; }
562 { int size_temp = size_a; size_a = size_b; size_b = size_temp; }
563 }
564 z = alloclongobject(size_a+1);
565 if (z == NULL)
566 return NULL;
567 for (i = 0; i < size_b; ++i) {
568 carry += a->ob_digit[i] + b->ob_digit[i];
569 z->ob_digit[i] = carry & MASK;
570 /* The following assumes unsigned shifts don't
571 propagate the sign bit. */
572 carry >>= SHIFT;
573 }
574 for (; i < size_a; ++i) {
575 carry += a->ob_digit[i];
576 z->ob_digit[i] = carry & MASK;
577 carry >>= SHIFT;
578 }
579 z->ob_digit[i] = carry;
580 return long_normalize(z);
581}
582
583/* Subtract the absolute values of two integers. */
584
585static longobject *x_sub PROTO((longobject *, longobject *));
586static longobject *
587x_sub(a, b)
588 longobject *a, *b;
589{
590 int size_a = ABS(a->ob_size), size_b = ABS(b->ob_size);
591 longobject *z;
592 int i;
593 int sign = 1;
594 digit borrow = 0;
595
596 /* Ensure a is the larger of the two: */
597 if (size_a < size_b) {
598 sign = -1;
599 { longobject *temp = a; a = b; b = temp; }
600 { int size_temp = size_a; size_a = size_b; size_b = size_temp; }
601 }
602 else if (size_a == size_b) {
603 /* Find highest digit where a and b differ: */
604 i = size_a;
605 while (--i >= 0 && a->ob_digit[i] == b->ob_digit[i])
606 ;
607 if (i < 0)
608 return alloclongobject(0);
609 if (a->ob_digit[i] < b->ob_digit[i]) {
610 sign = -1;
611 { longobject *temp = a; a = b; b = temp; }
612 }
613 size_a = size_b = i+1;
614 }
615 z = alloclongobject(size_a);
616 if (z == NULL)
617 return NULL;
618 for (i = 0; i < size_b; ++i) {
619 /* The following assumes unsigned arithmetic
620 works module 2**N for some N>SHIFT. */
621 borrow = a->ob_digit[i] - b->ob_digit[i] - borrow;
622 z->ob_digit[i] = borrow & MASK;
623 borrow >>= SHIFT;
624 borrow &= 1; /* Keep only one sign bit */
625 }
626 for (; i < size_a; ++i) {
627 borrow = a->ob_digit[i] - borrow;
628 z->ob_digit[i] = borrow & MASK;
629 borrow >>= SHIFT;
630 }
631 assert(borrow == 0);
632 z->ob_size *= sign;
633 return long_normalize(z);
634}
635
636static object *
637long_add(a, w)
638 longobject *a;
639 object *w;
640{
641 longobject *b;
642 longobject *z;
643
644 if (!is_longobject(w)) {
645 err_badarg();
646 return NULL;
647 }
648 b = (longobject *)w;
649
650 if (a->ob_size < 0) {
651 if (b->ob_size < 0) {
652 z = x_add(a, b);
653 if (z != NULL)
654 z->ob_size = -z->ob_size;
655 }
656 else
657 z = x_sub(b, a);
658 }
659 else {
660 if (b->ob_size < 0)
661 z = x_sub(a, b);
662 else
663 z = x_add(a, b);
664 }
665 return (object *)z;
666}
667
668static object *
669long_sub(a, w)
670 longobject *a;
671 object *w;
672{
673 longobject *b;
674 longobject *z;
675
676 if (!is_longobject(w)) {
677 err_badarg();
678 return NULL;
679 }
680 b = (longobject *)w;
681
682 if (a->ob_size < 0) {
683 if (b->ob_size < 0)
684 z = x_sub(a, b);
685 else
686 z = x_add(a, b);
687 if (z != NULL)
688 z->ob_size = -z->ob_size;
689 }
690 else {
691 if (b->ob_size < 0)
692 z = x_add(a, b);
693 else
694 z = x_sub(a, b);
695 }
696 return (object *)z;
697}
698
699static object *
700long_mul(a, w)
701 longobject *a;
702 object *w;
703{
704 longobject *b;
705 int size_a;
706 int size_b;
707 longobject *z;
708 int i;
709
710 if (!is_longobject(w)) {
711 err_badarg();
712 return NULL;
713 }
714 b = (longobject *)w;
715 size_a = ABS(a->ob_size);
716 size_b = ABS(b->ob_size);
717 z = alloclongobject(size_a + size_b);
718 if (z == NULL)
719 return NULL;
720 for (i = 0; i < z->ob_size; ++i)
721 z->ob_digit[i] = 0;
722 for (i = 0; i < size_a; ++i) {
723 twodigits carry = 0;
724 twodigits f = a->ob_digit[i];
725 int j;
726
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000727 INTRCHECK({
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000728 DECREF(z);
729 err_set(KeyboardInterrupt);
730 return NULL;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000731 })
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000732 for (j = 0; j < size_b; ++j) {
733 carry += z->ob_digit[i+j] + b->ob_digit[j] * f;
734 z->ob_digit[i+j] = carry & MASK;
735 carry >>= SHIFT;
736 }
737 for (; carry != 0; ++j) {
738 assert(i+j < z->ob_size);
739 carry += z->ob_digit[i+j];
740 z->ob_digit[i+j] = carry & MASK;
741 carry >>= SHIFT;
742 }
743 }
744 if (a->ob_size < 0)
745 z->ob_size = -z->ob_size;
746 if (b->ob_size < 0)
747 z->ob_size = -z->ob_size;
748 return (object *) long_normalize(z);
749}
750
751static object *
752long_div(v, w)
753 longobject *v;
754 register object *w;
755{
756 if (!is_longobject(w)) {
757 err_badarg();
758 return NULL;
759 }
760 return (object *) long_divrem(v, (longobject *)w, (longobject **)0);
761}
762
763static object *
764long_rem(v, w)
765 longobject *v;
766 register object *w;
767{
768 longobject *div, *rem = NULL;
769 if (!is_longobject(w)) {
770 err_badarg();
771 return NULL;
772 }
773 div = long_divrem(v, (longobject *)w, &rem);
774 if (div == NULL) {
775 XDECREF(rem);
776 rem = NULL;
777 }
778 else {
779 DECREF(div);
780 }
781 return (object *) rem;
782}
783
784/* The expression a mod b has the value a - b*floor(a/b).
785 The divrem function gives the remainder after division of
786 |a| by |b|, with the sign of a. This is also expressed
787 as a - b*trunc(a/b), if trunc truncates towards zero.
788 Some examples:
789 a b a rem b a mod b
790 13 10 3 3
791 -13 10 -3 7
792 13 -10 3 -7
793 -13 -10 -3 -3
794 So, to get from rem to mod, we have to add b if a and b
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000795 have different signs. We then subtract one from the 'div'
796 part of the outcome to keep the invariant intact. */
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000797
798static object *
799long_divmod(v, w)
800 longobject *v;
801 register object *w;
802{
803 object *z;
804 longobject *div, *rem;
805 if (!is_longobject(w)) {
806 err_badarg();
807 return NULL;
808 }
809 div = long_divrem(v, (longobject *)w, &rem);
810 if (div == NULL) {
811 XDECREF(rem);
812 return NULL;
813 }
814 if ((v->ob_size < 0) != (((longobject *)w)->ob_size < 0)) {
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000815 longobject *temp;
816 longobject *one;
817 temp = (longobject *) long_add(rem, w);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000818 DECREF(rem);
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000819 rem = temp;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000820 if (rem == NULL) {
821 DECREF(div);
822 return NULL;
823 }
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000824 one = (longobject *) newlongobject(1L);
825 if (one == NULL ||
826 (temp = (longobject *) long_sub(div, one)) == NULL) {
827 DECREF(rem);
828 DECREF(div);
829 return NULL;
830 }
831 DECREF(div);
832 div = temp;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000833 }
834 z = newtupleobject(2);
835 if (z != NULL) {
836 settupleitem(z, 0, (object *) div);
837 settupleitem(z, 1, (object *) rem);
838 }
839 else {
840 DECREF(div);
841 DECREF(rem);
842 }
843 return z;
844}
845
846static object *
847long_pow(v, w)
848 longobject *v;
849 register object *w;
850{
851 if (!is_longobject(w)) {
852 err_badarg();
853 return NULL;
854 }
855 err_setstr(SystemError, "long power not implemented");
856 return NULL;
857}
858
859static object *
860long_pos(v)
861 longobject *v;
862{
863 INCREF(v);
864 return (object *)v;
865}
866
867static object *
868long_neg(v)
869 longobject *v;
870{
871 longobject *z;
872 int i = v->ob_size;
873 if (i == 0)
874 return long_pos(v);
875 i = ABS(i);
876 z = alloclongobject(i);
877 if (z != NULL) {
878 z->ob_size = - v->ob_size;
879 while (--i >= 0)
880 z->ob_digit[i] = v->ob_digit[i];
881 }
882 return (object *)z;
883}
884
885static object *
886long_abs(v)
887 longobject *v;
888{
889 if (v->ob_size < 0)
890 return long_neg(v);
891 else
892 return long_pos(v);
893}
894
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000895static int
896long_nonzero(v)
897 longobject *v;
898{
899 return v->ob_size != 0;
900}
901
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000902static number_methods long_as_number = {
903 long_add, /*nb_add*/
904 long_sub, /*nb_subtract*/
905 long_mul, /*nb_multiply*/
906 long_div, /*nb_divide*/
907 long_rem, /*nb_remainder*/
908 long_divmod, /*nb_divmod*/
909 long_pow, /*nb_power*/
910 long_neg, /*nb_negative*/
911 long_pos, /*tp_positive*/
912 long_abs, /*tp_absolute*/
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000913 long_nonzero, /*tp_nonzero*/
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000914};
915
916typeobject Longtype = {
917 OB_HEAD_INIT(&Typetype)
918 0,
919 "long int",
920 sizeof(longobject) - sizeof(digit),
921 sizeof(digit),
922 long_dealloc, /*tp_dealloc*/
923 long_print, /*tp_print*/
924 0, /*tp_getattr*/
925 0, /*tp_setattr*/
926 long_compare, /*tp_compare*/
927 long_repr, /*tp_repr*/
928 &long_as_number,/*tp_as_number*/
929 0, /*tp_as_sequence*/
930 0, /*tp_as_mapping*/
931};