blob: 7ede30c0e17e14a11ea60d79b142552f3847d7dd [file] [log] [blame]
Guido van Rossumedcc38a1991-05-05 20:09:44 +00001/***********************************************************
Guido van Rossumbab9d031992-04-05 14:26:55 +00002Copyright 1991, 1992 by Stichting Mathematisch Centrum, Amsterdam, The
Guido van Rossumedcc38a1991-05-05 20:09:44 +00003Netherlands.
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"
Guido van Rossume32e0141992-01-19 16:31:05 +000030#include "intrcheck.h"
Guido van Rossumedcc38a1991-05-05 20:09:44 +000031#include "longintrepr.h"
Guido van Rossum149e9ea1991-06-03 10:58:24 +000032#include <math.h>
Guido van Rossumedcc38a1991-05-05 20:09:44 +000033#include <assert.h>
34
Guido van Rossume32e0141992-01-19 16:31:05 +000035#define ABS(x) ((x) < 0 ? -(x) : (x))
36
37/* Forward */
38static longobject *long_normalize PROTO((longobject *));
39static longobject *mul1 PROTO((longobject *, wdigit));
40static longobject *muladd1 PROTO((longobject *, wdigit, wdigit));
41static longobject *divrem1 PROTO((longobject *, wdigit, digit *));
42
Guido van Rossum23d6f0e1991-05-14 12:06:49 +000043static int ticker; /* XXX Could be shared with ceval? */
44
45#define INTRCHECK(block) \
46 if (--ticker < 0) { \
47 ticker = 100; \
48 if (intrcheck()) { block; } \
49 }
50
Guido van Rossumedcc38a1991-05-05 20:09:44 +000051/* Normalize (remove leading zeros from) a long int object.
52 Doesn't attempt to free the storage--in most cases, due to the nature
53 of the algorithms used, this could save at most be one word anyway. */
54
Guido van Rossum4c260ff1992-01-14 18:36:43 +000055static longobject *
Guido van Rossumedcc38a1991-05-05 20:09:44 +000056long_normalize(v)
57 register longobject *v;
58{
Guido van Rossum4c260ff1992-01-14 18:36:43 +000059 int j = ABS(v->ob_size);
Guido van Rossumedcc38a1991-05-05 20:09:44 +000060 register int i = j;
61
62 while (i > 0 && v->ob_digit[i-1] == 0)
63 --i;
64 if (i != j)
Guido van Rossum4c260ff1992-01-14 18:36:43 +000065 v->ob_size = (v->ob_size < 0) ? -(i) : i;
Guido van Rossumedcc38a1991-05-05 20:09:44 +000066 return v;
67}
68
69/* Allocate a new long int object with size digits.
70 Return NULL and set exception if we run out of memory. */
71
72longobject *
73alloclongobject(size)
74 int size;
75{
76 return NEWVAROBJ(longobject, &Longtype, size);
77}
78
79/* Create a new long int object from a C long int */
80
81object *
82newlongobject(ival)
83 long ival;
84{
85 /* Assume a C long fits in at most 3 'digits' */
86 longobject *v = alloclongobject(3);
87 if (v != NULL) {
88 if (ival < 0) {
89 ival = -ival;
Guido van Rossum4c260ff1992-01-14 18:36:43 +000090 v->ob_size = -(v->ob_size);
Guido van Rossumedcc38a1991-05-05 20:09:44 +000091 }
92 v->ob_digit[0] = ival & MASK;
93 v->ob_digit[1] = (ival >> SHIFT) & MASK;
94 v->ob_digit[2] = (ival >> (2*SHIFT)) & MASK;
95 v = long_normalize(v);
96 }
97 return (object *)v;
98}
99
Guido van Rossum149e9ea1991-06-03 10:58:24 +0000100/* Create a new long int object from a C double */
101
102object *
103dnewlongobject(dval)
104 double dval;
105{
106 longobject *v;
107 double frac;
108 int i, ndig, expo, neg;
109 neg = 0;
110 if (dval < 0.0) {
111 neg = 1;
112 dval = -dval;
113 }
114 frac = frexp(dval, &expo); /* dval = frac*2**expo; 0.0 <= frac < 1.0 */
115 if (expo <= 0)
116 return newlongobject(0L);
117 ndig = (expo-1) / SHIFT + 1; /* Number of 'digits' in result */
118 v = alloclongobject(ndig);
119 if (v == NULL)
120 return NULL;
121 frac = ldexp(frac, (expo-1) % SHIFT + 1);
122 for (i = ndig; --i >= 0; ) {
123 long bits = (long)frac;
124 v->ob_digit[i] = bits;
125 frac = frac - (double)bits;
126 frac = ldexp(frac, SHIFT);
127 }
128 if (neg)
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000129 v->ob_size = -(v->ob_size);
Guido van Rossum149e9ea1991-06-03 10:58:24 +0000130 return (object *)v;
131}
132
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000133/* Get a C long int from a long int object.
134 Returns -1 and sets an error condition if overflow occurs. */
135
136long
137getlongvalue(vv)
138 object *vv;
139{
140 register longobject *v;
141 long x, prev;
142 int i, sign;
143
144 if (vv == NULL || !is_longobject(vv)) {
145 err_badcall();
146 return -1;
147 }
148 v = (longobject *)vv;
149 i = v->ob_size;
150 sign = 1;
151 x = 0;
152 if (i < 0) {
153 sign = -1;
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000154 i = -(i);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000155 }
156 while (--i >= 0) {
157 prev = x;
158 x = (x << SHIFT) + v->ob_digit[i];
159 if ((x >> SHIFT) != prev) {
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000160 err_setstr(ValueError,
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000161 "long int too long to convert");
162 return -1;
163 }
164 }
165 return x * sign;
166}
167
168/* Get a C double from a long int object. No overflow check. */
169
170double
171dgetlongvalue(vv)
172 object *vv;
173{
174 register longobject *v;
175 double x;
176 double multiplier = (double) (1L << SHIFT);
177 int i, sign;
178
179 if (vv == NULL || !is_longobject(vv)) {
180 err_badcall();
181 return -1;
182 }
183 v = (longobject *)vv;
184 i = v->ob_size;
185 sign = 1;
186 x = 0.0;
187 if (i < 0) {
188 sign = -1;
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000189 i = -(i);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000190 }
191 while (--i >= 0) {
192 x = x*multiplier + v->ob_digit[i];
193 }
194 return x * sign;
195}
196
197/* Multiply by a single digit, ignoring the sign. */
198
Guido van Rossume32e0141992-01-19 16:31:05 +0000199static longobject *
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000200mul1(a, n)
201 longobject *a;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000202 wdigit n;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000203{
204 return muladd1(a, n, (digit)0);
205}
206
207/* Multiply by a single digit and add a single digit, ignoring the sign. */
208
Guido van Rossume32e0141992-01-19 16:31:05 +0000209static longobject *
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000210muladd1(a, n, extra)
211 longobject *a;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000212 wdigit n;
213 wdigit extra;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000214{
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000215 int size_a = ABS(a->ob_size);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000216 longobject *z = alloclongobject(size_a+1);
217 twodigits carry = extra;
218 int i;
219
220 if (z == NULL)
221 return NULL;
222 for (i = 0; i < size_a; ++i) {
223 carry += (twodigits)a->ob_digit[i] * n;
224 z->ob_digit[i] = carry & MASK;
225 carry >>= SHIFT;
226 }
227 z->ob_digit[i] = carry;
228 return long_normalize(z);
229}
230
231/* Divide a long integer by a digit, returning both the quotient
232 (as function result) and the remainder (through *prem).
233 The sign of a is ignored; n should not be zero. */
234
Guido van Rossume32e0141992-01-19 16:31:05 +0000235static longobject *
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000236divrem1(a, n, prem)
237 longobject *a;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000238 wdigit n;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000239 digit *prem;
240{
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000241 int size = ABS(a->ob_size);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000242 longobject *z;
243 int i;
244 twodigits rem = 0;
245
246 assert(n > 0 && n <= MASK);
247 z = alloclongobject(size);
248 if (z == NULL)
249 return NULL;
250 for (i = size; --i >= 0; ) {
251 rem = (rem << SHIFT) + a->ob_digit[i];
252 z->ob_digit[i] = rem/n;
253 rem %= n;
254 }
255 *prem = rem;
256 return long_normalize(z);
257}
258
259/* Convert a long int object to a string, using a given conversion base.
Guido van Rossum3d3037d1991-10-24 14:55:57 +0000260 Return a string object.
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000261 If base is 8 or 16, add the proper prefix '0' or '0x'.
262 External linkage: used in bltinmodule.c by hex() and oct(). */
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000263
Guido van Rossume32e0141992-01-19 16:31:05 +0000264object *
265long_format(aa, base)
266 object *aa;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000267 int base;
268{
Guido van Rossume32e0141992-01-19 16:31:05 +0000269 register longobject *a = (longobject *)aa;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000270 stringobject *str;
271 int i;
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000272 int size_a = ABS(a->ob_size);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000273 char *p;
274 int bits;
275 char sign = '\0';
Guido van Rossume32e0141992-01-19 16:31:05 +0000276
277 if (a == NULL || !is_longobject(a)) {
278 err_badcall();
279 return NULL;
280 }
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000281 assert(base >= 2 && base <= 36);
282
283 /* Compute a rough upper bound for the length of the string */
284 i = base;
285 bits = 0;
286 while (i > 1) {
287 ++bits;
288 i >>= 1;
289 }
Guido van Rossumc6913e71991-11-19 20:26:46 +0000290 i = 6 + (size_a*SHIFT + bits-1) / bits;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000291 str = (stringobject *) newsizedstringobject((char *)0, i);
292 if (str == NULL)
293 return NULL;
294 p = GETSTRINGVALUE(str) + i;
295 *p = '\0';
Guido van Rossumc6913e71991-11-19 20:26:46 +0000296 *--p = 'L';
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000297 if (a->ob_size < 0)
298 sign = '-';
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000299
300 INCREF(a);
301 do {
302 digit rem;
303 longobject *temp = divrem1(a, (digit)base, &rem);
304 if (temp == NULL) {
305 DECREF(a);
306 DECREF(str);
307 return NULL;
308 }
309 if (rem < 10)
310 rem += '0';
311 else
312 rem += 'A'-10;
313 assert(p > GETSTRINGVALUE(str));
314 *--p = rem;
315 DECREF(a);
316 a = temp;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000317 INTRCHECK({
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000318 DECREF(a);
319 DECREF(str);
320 err_set(KeyboardInterrupt);
321 return NULL;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000322 })
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000323 } while (ABS(a->ob_size) != 0);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000324 DECREF(a);
Guido van Rossum2c475421992-08-14 15:13:07 +0000325 if (base == 8) {
326 if (size_a != 0)
327 *--p = '0';
328 }
Guido van Rossum3d3037d1991-10-24 14:55:57 +0000329 else if (base == 16) {
330 *--p = 'x';
331 *--p = '0';
332 }
Guido van Rossumc6913e71991-11-19 20:26:46 +0000333 else if (base != 10) {
334 *--p = '#';
335 *--p = '0' + base%10;
336 if (base > 10)
337 *--p = '0' + base/10;
338 }
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000339 if (sign)
340 *--p = sign;
341 if (p != GETSTRINGVALUE(str)) {
342 char *q = GETSTRINGVALUE(str);
343 assert(p > q);
344 do {
345 } while ((*q++ = *p++) != '\0');
Guido van Rossumc7ec9c91991-05-28 21:58:16 +0000346 q--;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000347 resizestring((object **)&str, (int) (q - GETSTRINGVALUE(str)));
348 }
Guido van Rossume32e0141992-01-19 16:31:05 +0000349 return (object *)str;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000350}
351
352/* Convert a string to a long int object, in a given base.
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000353 Base zero implies a default depending on the number.
354 External linkage: used in compile.c for literals. */
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000355
356object *
357long_scan(str, base)
358 char *str;
359 int base;
360{
361 int sign = 1;
362 longobject *z;
363
364 assert(base == 0 || base >= 2 && base <= 36);
365 if (*str == '+')
366 ++str;
367 else if (*str == '-') {
368 ++str;
369 sign = -1;
370 }
371 if (base == 0) {
372 if (str[0] != '0')
373 base = 10;
374 else if (str[1] == 'x' || str[1] == 'X')
375 base = 16;
376 else
377 base = 8;
378 }
379 if (base == 16 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
380 str += 2;
381 z = alloclongobject(0);
382 for ( ; z != NULL; ++str) {
383 int k = -1;
384 longobject *temp;
385
386 if (*str <= '9')
387 k = *str - '0';
388 else if (*str >= 'a')
389 k = *str - 'a' + 10;
390 else if (*str >= 'A')
391 k = *str - 'A' + 10;
392 if (k < 0 || k >= base)
393 break;
394 temp = muladd1(z, (digit)base, (digit)k);
395 DECREF(z);
396 z = temp;
397 }
Guido van Rossumc6913e71991-11-19 20:26:46 +0000398 if (sign < 0 && z != NULL && z->ob_size != 0)
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000399 z->ob_size = -(z->ob_size);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000400 return (object *) z;
401}
402
403static longobject *x_divrem PROTO((longobject *, longobject *, longobject **));
Guido van Rossumc6913e71991-11-19 20:26:46 +0000404static object *long_pos PROTO((longobject *));
Guido van Rossume32e0141992-01-19 16:31:05 +0000405static long_divrem PROTO((longobject *, longobject *,
406 longobject **, longobject **));
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000407
408/* Long division with remainder, top-level routine */
409
Guido van Rossume32e0141992-01-19 16:31:05 +0000410static int
411long_divrem(a, b, pdiv, prem)
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000412 longobject *a, *b;
Guido van Rossume32e0141992-01-19 16:31:05 +0000413 longobject **pdiv;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000414 longobject **prem;
415{
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000416 int size_a = ABS(a->ob_size), size_b = ABS(b->ob_size);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000417 longobject *z;
418
419 if (size_b == 0) {
Guido van Rossume32e0141992-01-19 16:31:05 +0000420 err_setstr(ZeroDivisionError, "long division or modulo");
421 return -1;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000422 }
423 if (size_a < size_b ||
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000424 size_a == size_b &&
425 a->ob_digit[size_a-1] < b->ob_digit[size_b-1]) {
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000426 /* |a| < |b|. */
Guido van Rossume32e0141992-01-19 16:31:05 +0000427 *pdiv = alloclongobject(0);
428 INCREF(a);
429 *prem = (longobject *) a;
430 return 0;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000431 }
432 if (size_b == 1) {
433 digit rem = 0;
434 z = divrem1(a, b->ob_digit[0], &rem);
Guido van Rossume32e0141992-01-19 16:31:05 +0000435 if (z == NULL)
436 return -1;
437 *prem = (longobject *) newlongobject((long)rem);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000438 }
Guido van Rossume32e0141992-01-19 16:31:05 +0000439 else {
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000440 z = x_divrem(a, b, prem);
Guido van Rossume32e0141992-01-19 16:31:05 +0000441 if (z == NULL)
442 return -1;
443 }
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000444 /* Set the signs.
445 The quotient z has the sign of a*b;
446 the remainder r has the sign of a,
447 so a = b*z + r. */
Guido van Rossume32e0141992-01-19 16:31:05 +0000448 if ((a->ob_size < 0) != (b->ob_size < 0))
449 z->ob_size = -(z->ob_size);
450 if (a->ob_size < 0 && (*prem)->ob_size != 0)
451 (*prem)->ob_size = -((*prem)->ob_size);
452 *pdiv = z;
453 return 0;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000454}
455
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000456/* Unsigned long division with remainder -- the algorithm */
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000457
458static longobject *
459x_divrem(v1, w1, prem)
460 longobject *v1, *w1;
461 longobject **prem;
462{
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000463 int size_v = ABS(v1->ob_size), size_w = ABS(w1->ob_size);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000464 digit d = (twodigits)BASE / (w1->ob_digit[size_w-1] + 1);
465 longobject *v = mul1(v1, d);
466 longobject *w = mul1(w1, d);
467 longobject *a;
468 int j, k;
469
470 if (v == NULL || w == NULL) {
471 XDECREF(v);
472 XDECREF(w);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000473 return NULL;
474 }
475
476 assert(size_v >= size_w && size_w > 1); /* Assert checks by div() */
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000477 assert(v->ob_refcnt == 1); /* Since v will be used as accumulator! */
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000478 assert(size_w == ABS(w->ob_size)); /* That's how d was calculated */
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000479
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000480 size_v = ABS(v->ob_size);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000481 a = alloclongobject(size_v - size_w + 1);
482
483 for (j = size_v, k = a->ob_size-1; a != NULL && k >= 0; --j, --k) {
484 digit vj = (j >= size_v) ? 0 : v->ob_digit[j];
485 twodigits q;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000486 stwodigits carry = 0;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000487 int i;
488
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000489 INTRCHECK({
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000490 DECREF(a);
491 a = NULL;
492 err_set(KeyboardInterrupt);
493 break;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000494 })
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000495 if (vj == w->ob_digit[size_w-1])
496 q = MASK;
497 else
498 q = (((twodigits)vj << SHIFT) + v->ob_digit[j-1]) /
499 w->ob_digit[size_w-1];
500
501 while (w->ob_digit[size_w-2]*q >
502 ((
503 ((twodigits)vj << SHIFT)
504 + v->ob_digit[j-1]
505 - q*w->ob_digit[size_w-1]
506 ) << SHIFT)
507 + v->ob_digit[j-2])
508 --q;
509
510 for (i = 0; i < size_w && i+k < size_v; ++i) {
511 twodigits z = w->ob_digit[i] * q;
512 digit zz = z >> SHIFT;
513 carry += v->ob_digit[i+k] - z + ((twodigits)zz << SHIFT);
514 v->ob_digit[i+k] = carry & MASK;
515 carry = (carry >> SHIFT) - zz;
516 }
517
518 if (i+k < size_v) {
519 carry += v->ob_digit[i+k];
520 v->ob_digit[i+k] = 0;
521 }
522
523 if (carry == 0)
524 a->ob_digit[k] = q;
525 else {
526 assert(carry == -1);
527 a->ob_digit[k] = q-1;
528 carry = 0;
529 for (i = 0; i < size_w && i+k < size_v; ++i) {
530 carry += v->ob_digit[i+k] + w->ob_digit[i];
531 v->ob_digit[i+k] = carry & MASK;
532 carry >>= SHIFT;
533 }
534 }
535 } /* for j, k */
536
Guido van Rossume32e0141992-01-19 16:31:05 +0000537 if (a != NULL) {
Guido van Rossumc6913e71991-11-19 20:26:46 +0000538 a = long_normalize(a);
Guido van Rossume32e0141992-01-19 16:31:05 +0000539 *prem = divrem1(v, d, &d);
540 /* d receives the (unused) remainder */
541 if (*prem == NULL) {
542 DECREF(a);
543 a = NULL;
Guido van Rossumc6913e71991-11-19 20:26:46 +0000544 }
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000545 }
546 DECREF(v);
547 DECREF(w);
548 return a;
549}
550
551/* Methods */
552
Guido van Rossume32e0141992-01-19 16:31:05 +0000553/* Forward */
Guido van Rossum8b27d921992-03-27 17:27:05 +0000554static void long_dealloc PROTO((object *));
555static int long_print PROTO((object *, FILE *, int));
556static object *long_repr PROTO((object *));
Guido van Rossume32e0141992-01-19 16:31:05 +0000557static int long_compare PROTO((longobject *, longobject *));
558
559static object *long_add PROTO((longobject *, longobject *));
560static object *long_sub PROTO((longobject *, longobject *));
561static object *long_mul PROTO((longobject *, longobject *));
562static object *long_div PROTO((longobject *, longobject *));
563static object *long_mod PROTO((longobject *, longobject *));
564static object *long_divmod PROTO((longobject *, longobject *));
565static object *long_pow PROTO((longobject *, longobject *));
566static object *long_neg PROTO((longobject *));
567static object *long_pos PROTO((longobject *));
568static object *long_abs PROTO((longobject *));
569static int long_nonzero PROTO((longobject *));
570static object *long_invert PROTO((longobject *));
571static object *long_lshift PROTO((longobject *, longobject *));
572static object *long_rshift PROTO((longobject *, longobject *));
573static object *long_and PROTO((longobject *, longobject *));
574static object *long_xor PROTO((longobject *, longobject *));
575static object *long_or PROTO((longobject *, longobject *));
576
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000577static void
578long_dealloc(v)
Guido van Rossum8b27d921992-03-27 17:27:05 +0000579 object *v;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000580{
581 DEL(v);
582}
583
Guido van Rossum8b27d921992-03-27 17:27:05 +0000584/* ARGSUSED */
Guido van Rossum90933611991-06-07 16:10:43 +0000585static int
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000586long_print(v, fp, flags)
Guido van Rossum8b27d921992-03-27 17:27:05 +0000587 object *v;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000588 FILE *fp;
Guido van Rossum8b27d921992-03-27 17:27:05 +0000589 int flags; /* Not used but required by interface */
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000590{
Guido van Rossum8b27d921992-03-27 17:27:05 +0000591 stringobject *str = (stringobject *) long_format(v, 10);
Guido van Rossum90933611991-06-07 16:10:43 +0000592 if (str == NULL)
593 return -1;
Guido van Rossumc6913e71991-11-19 20:26:46 +0000594 fprintf(fp, "%s", GETSTRINGVALUE(str));
Guido van Rossum90933611991-06-07 16:10:43 +0000595 DECREF(str);
596 return 0;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000597}
598
599static object *
600long_repr(v)
Guido van Rossum8b27d921992-03-27 17:27:05 +0000601 object *v;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000602{
Guido van Rossum8b27d921992-03-27 17:27:05 +0000603 return long_format(v, 10);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000604}
605
606static int
607long_compare(a, b)
608 longobject *a, *b;
609{
610 int sign;
611
Guido van Rossumc6913e71991-11-19 20:26:46 +0000612 if (a->ob_size != b->ob_size) {
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000613 if (ABS(a->ob_size) == 0 && ABS(b->ob_size) == 0)
Guido van Rossumc6913e71991-11-19 20:26:46 +0000614 sign = 0;
615 else
616 sign = a->ob_size - b->ob_size;
617 }
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000618 else {
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000619 int i = ABS(a->ob_size);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000620 while (--i >= 0 && a->ob_digit[i] == b->ob_digit[i])
621 ;
622 if (i < 0)
623 sign = 0;
624 else
625 sign = (int)a->ob_digit[i] - (int)b->ob_digit[i];
626 }
Guido van Rossumc6913e71991-11-19 20:26:46 +0000627 return sign < 0 ? -1 : sign > 0 ? 1 : 0;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000628}
629
630/* Add the absolute values of two long integers. */
631
632static longobject *x_add PROTO((longobject *, longobject *));
633static longobject *
634x_add(a, b)
635 longobject *a, *b;
636{
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000637 int size_a = ABS(a->ob_size), size_b = ABS(b->ob_size);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000638 longobject *z;
639 int i;
640 digit carry = 0;
641
642 /* Ensure a is the larger of the two: */
643 if (size_a < size_b) {
644 { longobject *temp = a; a = b; b = temp; }
645 { int size_temp = size_a; size_a = size_b; size_b = size_temp; }
646 }
647 z = alloclongobject(size_a+1);
648 if (z == NULL)
649 return NULL;
650 for (i = 0; i < size_b; ++i) {
651 carry += a->ob_digit[i] + b->ob_digit[i];
652 z->ob_digit[i] = carry & MASK;
653 /* The following assumes unsigned shifts don't
654 propagate the sign bit. */
655 carry >>= SHIFT;
656 }
657 for (; i < size_a; ++i) {
658 carry += a->ob_digit[i];
659 z->ob_digit[i] = carry & MASK;
660 carry >>= SHIFT;
661 }
662 z->ob_digit[i] = carry;
663 return long_normalize(z);
664}
665
666/* Subtract the absolute values of two integers. */
667
668static longobject *x_sub PROTO((longobject *, longobject *));
669static longobject *
670x_sub(a, b)
671 longobject *a, *b;
672{
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000673 int size_a = ABS(a->ob_size), size_b = ABS(b->ob_size);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000674 longobject *z;
675 int i;
676 int sign = 1;
677 digit borrow = 0;
678
679 /* Ensure a is the larger of the two: */
680 if (size_a < size_b) {
681 sign = -1;
682 { longobject *temp = a; a = b; b = temp; }
683 { int size_temp = size_a; size_a = size_b; size_b = size_temp; }
684 }
685 else if (size_a == size_b) {
686 /* Find highest digit where a and b differ: */
687 i = size_a;
688 while (--i >= 0 && a->ob_digit[i] == b->ob_digit[i])
689 ;
690 if (i < 0)
691 return alloclongobject(0);
692 if (a->ob_digit[i] < b->ob_digit[i]) {
693 sign = -1;
694 { longobject *temp = a; a = b; b = temp; }
695 }
696 size_a = size_b = i+1;
697 }
698 z = alloclongobject(size_a);
699 if (z == NULL)
700 return NULL;
701 for (i = 0; i < size_b; ++i) {
702 /* The following assumes unsigned arithmetic
703 works module 2**N for some N>SHIFT. */
704 borrow = a->ob_digit[i] - b->ob_digit[i] - borrow;
705 z->ob_digit[i] = borrow & MASK;
706 borrow >>= SHIFT;
707 borrow &= 1; /* Keep only one sign bit */
708 }
709 for (; i < size_a; ++i) {
710 borrow = a->ob_digit[i] - borrow;
711 z->ob_digit[i] = borrow & MASK;
712 borrow >>= SHIFT;
713 }
714 assert(borrow == 0);
Guido van Rossumc6913e71991-11-19 20:26:46 +0000715 if (sign < 0)
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000716 z->ob_size = -(z->ob_size);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000717 return long_normalize(z);
718}
719
720static object *
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000721long_add(a, b)
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000722 longobject *a;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000723 longobject *b;
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000724{
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000725 longobject *z;
726
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000727 if (a->ob_size < 0) {
728 if (b->ob_size < 0) {
729 z = x_add(a, b);
Guido van Rossumc6913e71991-11-19 20:26:46 +0000730 if (z != NULL && z->ob_size != 0)
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000731 z->ob_size = -(z->ob_size);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000732 }
733 else
734 z = x_sub(b, a);
735 }
736 else {
737 if (b->ob_size < 0)
738 z = x_sub(a, b);
739 else
740 z = x_add(a, b);
741 }
742 return (object *)z;
743}
744
745static object *
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000746long_sub(a, b)
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000747 longobject *a;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000748 longobject *b;
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000749{
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000750 longobject *z;
751
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000752 if (a->ob_size < 0) {
753 if (b->ob_size < 0)
754 z = x_sub(a, b);
755 else
756 z = x_add(a, b);
Guido van Rossumc6913e71991-11-19 20:26:46 +0000757 if (z != NULL && z->ob_size != 0)
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000758 z->ob_size = -(z->ob_size);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000759 }
760 else {
761 if (b->ob_size < 0)
762 z = x_add(a, b);
763 else
764 z = x_sub(a, b);
765 }
766 return (object *)z;
767}
768
769static object *
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000770long_mul(a, b)
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000771 longobject *a;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000772 longobject *b;
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000773{
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000774 int size_a;
775 int size_b;
776 longobject *z;
777 int i;
778
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000779 size_a = ABS(a->ob_size);
780 size_b = ABS(b->ob_size);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000781 z = alloclongobject(size_a + size_b);
782 if (z == NULL)
783 return NULL;
784 for (i = 0; i < z->ob_size; ++i)
785 z->ob_digit[i] = 0;
786 for (i = 0; i < size_a; ++i) {
787 twodigits carry = 0;
788 twodigits f = a->ob_digit[i];
789 int j;
790
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000791 INTRCHECK({
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000792 DECREF(z);
793 err_set(KeyboardInterrupt);
794 return NULL;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000795 })
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000796 for (j = 0; j < size_b; ++j) {
797 carry += z->ob_digit[i+j] + b->ob_digit[j] * f;
798 z->ob_digit[i+j] = carry & MASK;
799 carry >>= SHIFT;
800 }
801 for (; carry != 0; ++j) {
802 assert(i+j < z->ob_size);
803 carry += z->ob_digit[i+j];
804 z->ob_digit[i+j] = carry & MASK;
805 carry >>= SHIFT;
806 }
807 }
808 if (a->ob_size < 0)
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000809 z->ob_size = -(z->ob_size);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000810 if (b->ob_size < 0)
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000811 z->ob_size = -(z->ob_size);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000812 return (object *) long_normalize(z);
813}
814
Guido van Rossume32e0141992-01-19 16:31:05 +0000815/* The / and % operators are now defined in terms of divmod().
816 The expression a mod b has the value a - b*floor(a/b).
817 The long_divrem function gives the remainder after division of
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000818 |a| by |b|, with the sign of a. This is also expressed
819 as a - b*trunc(a/b), if trunc truncates towards zero.
820 Some examples:
821 a b a rem b a mod b
822 13 10 3 3
823 -13 10 -3 7
824 13 -10 3 -7
825 -13 -10 -3 -3
826 So, to get from rem to mod, we have to add b if a and b
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000827 have different signs. We then subtract one from the 'div'
828 part of the outcome to keep the invariant intact. */
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000829
Guido van Rossume32e0141992-01-19 16:31:05 +0000830static int l_divmod PROTO((longobject *, longobject *,
831 longobject **, longobject **));
832static int
833l_divmod(v, w, pdiv, pmod)
834 longobject *v;
835 longobject *w;
836 longobject **pdiv;
837 longobject **pmod;
838{
839 longobject *div, *mod;
840
841 if (long_divrem(v, w, &div, &mod) < 0)
842 return -1;
843 if (mod->ob_size < 0 && w->ob_size > 0 ||
844 mod->ob_size > 0 && w->ob_size < 0) {
845 longobject *temp;
846 longobject *one;
847 temp = (longobject *) long_add(mod, w);
848 DECREF(mod);
849 mod = temp;
850 if (mod == NULL) {
851 DECREF(div);
852 return -1;
853 }
854 one = (longobject *) newlongobject(1L);
855 if (one == NULL ||
856 (temp = (longobject *) long_sub(div, one)) == NULL) {
857 DECREF(mod);
858 DECREF(div);
859 return -1;
860 }
861 DECREF(div);
862 div = temp;
863 }
864 *pdiv = div;
865 *pmod = mod;
866 return 0;
867}
868
869static object *
870long_div(v, w)
871 longobject *v;
872 longobject *w;
873{
874 longobject *div, *mod;
875 if (l_divmod(v, w, &div, &mod) < 0)
876 return NULL;
877 DECREF(mod);
878 return (object *)div;
879}
880
881static object *
882long_mod(v, w)
883 longobject *v;
884 longobject *w;
885{
886 longobject *div, *mod;
887 if (l_divmod(v, w, &div, &mod) < 0)
888 return NULL;
889 DECREF(div);
890 return (object *)mod;
891}
892
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000893static object *
894long_divmod(v, w)
895 longobject *v;
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000896 longobject *w;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000897{
898 object *z;
Guido van Rossume32e0141992-01-19 16:31:05 +0000899 longobject *div, *mod;
900 if (l_divmod(v, w, &div, &mod) < 0)
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000901 return NULL;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000902 z = newtupleobject(2);
903 if (z != NULL) {
904 settupleitem(z, 0, (object *) div);
Guido van Rossume32e0141992-01-19 16:31:05 +0000905 settupleitem(z, 1, (object *) mod);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000906 }
907 else {
908 DECREF(div);
Guido van Rossume32e0141992-01-19 16:31:05 +0000909 DECREF(mod);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000910 }
911 return z;
912}
913
914static object *
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000915long_pow(a, b)
Guido van Rossumc7ec9c91991-05-28 21:58:16 +0000916 longobject *a;
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000917 longobject *b;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000918{
Guido van Rossumc7ec9c91991-05-28 21:58:16 +0000919 longobject *z;
920 int size_b, i;
921
Guido van Rossumc7ec9c91991-05-28 21:58:16 +0000922 size_b = b->ob_size;
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000923 if (size_b < 0) {
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000924 err_setstr(ValueError, "long integer to the negative power");
Guido van Rossumc7ec9c91991-05-28 21:58:16 +0000925 return NULL;
926 }
927
928 z = (longobject *)newlongobject(1L);
929
930 INCREF(a);
931 for (i = 0; i < size_b; ++i) {
932 digit bi = b->ob_digit[i];
933 int j;
934
935 for (j = 0; j < SHIFT; ++j) {
936 longobject *temp;
937
938 if (bi & 1) {
Guido van Rossume32e0141992-01-19 16:31:05 +0000939 temp = (longobject *)long_mul(z, a);
Guido van Rossumc7ec9c91991-05-28 21:58:16 +0000940 DECREF(z);
941 z = temp;
942 if (z == NULL)
943 break;
944 }
945 bi >>= 1;
946 if (bi == 0 && i+1 == size_b)
947 break;
Guido van Rossume32e0141992-01-19 16:31:05 +0000948 temp = (longobject *)long_mul(a, a);
Guido van Rossumc7ec9c91991-05-28 21:58:16 +0000949 DECREF(a);
950 a = temp;
951 if (a == NULL) {
952 DECREF(z);
953 z = NULL;
954 break;
955 }
956 }
957 if (a == NULL)
958 break;
959 }
960 XDECREF(a);
961 return (object *)z;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000962}
963
964static object *
Guido van Rossumc6913e71991-11-19 20:26:46 +0000965long_invert(v)
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000966 longobject *v;
967{
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000968 /* Implement ~x as -(x+1) */
969 longobject *x;
Guido van Rossume32e0141992-01-19 16:31:05 +0000970 longobject *w;
971 w = (longobject *)newlongobject(1L);
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000972 if (w == NULL)
973 return NULL;
974 x = (longobject *) long_add(v, w);
975 DECREF(w);
976 if (x == NULL)
977 return NULL;
978 if (x->ob_size != 0)
979 x->ob_size = -(x->ob_size);
980 return (object *)x;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000981}
982
983static object *
Guido van Rossumc6913e71991-11-19 20:26:46 +0000984long_pos(v)
985 longobject *v;
986{
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000987 INCREF(v);
988 return (object *)v;
Guido van Rossumc6913e71991-11-19 20:26:46 +0000989}
990
991static object *
992long_neg(v)
993 longobject *v;
994{
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000995 longobject *z;
996 int i, n;
997 n = ABS(v->ob_size);
998 if (n == 0) {
999 /* -0 == 0 */
Guido van Rossumc6913e71991-11-19 20:26:46 +00001000 INCREF(v);
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001001 return (object *) v;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001002 }
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001003 z = alloclongobject(ABS(n));
1004 if (z == NULL)
1005 return NULL;
1006 for (i = 0; i < n; i++)
1007 z->ob_digit[i] = v->ob_digit[i];
1008 z->ob_size = -(v->ob_size);
1009 return (object *)z;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001010}
1011
1012static object *
Guido van Rossumedcc38a1991-05-05 20:09:44 +00001013long_abs(v)
1014 longobject *v;
1015{
1016 if (v->ob_size < 0)
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001017 return long_neg(v);
Guido van Rossumc6913e71991-11-19 20:26:46 +00001018 else {
1019 INCREF(v);
1020 return (object *)v;
1021 }
Guido van Rossumedcc38a1991-05-05 20:09:44 +00001022}
1023
Guido van Rossum23d6f0e1991-05-14 12:06:49 +00001024static int
1025long_nonzero(v)
1026 longobject *v;
1027{
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001028 return ABS(v->ob_size) != 0;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001029}
1030
1031static object *
1032long_rshift(a, b)
1033 longobject *a;
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001034 longobject *b;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001035{
1036 longobject *z;
1037 long shiftby;
1038 int newsize, wordshift, loshift, hishift, i, j;
1039 digit lomask, himask;
1040
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001041 if (a->ob_size < 0) {
1042 /* Right shifting negative numbers is harder */
1043 longobject *a1, *a2, *a3;
1044 a1 = (longobject *) long_invert(a);
1045 if (a1 == NULL) return NULL;
1046 a2 = (longobject *) long_rshift(a1, b);
1047 DECREF(a1);
1048 if (a2 == NULL) return NULL;
1049 a3 = (longobject *) long_invert(a2);
1050 DECREF(a2);
1051 return (object *) a3;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001052 }
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001053
1054 shiftby = getlongvalue((object *)b);
Guido van Rossumc6913e71991-11-19 20:26:46 +00001055 if (shiftby == -1L && err_occurred())
1056 return NULL;
1057 if (shiftby < 0) {
Guido van Rossum87e7ea71991-12-10 14:00:03 +00001058 err_setstr(ValueError, "negative shift count");
Guido van Rossumc6913e71991-11-19 20:26:46 +00001059 return NULL;
1060 }
Guido van Rossumc6913e71991-11-19 20:26:46 +00001061 wordshift = shiftby / SHIFT;
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001062 newsize = ABS(a->ob_size) - wordshift;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001063 if (newsize <= 0) {
1064 z = alloclongobject(0);
Guido van Rossumc6913e71991-11-19 20:26:46 +00001065 return (object *)z;
1066 }
1067 loshift = shiftby % SHIFT;
1068 hishift = SHIFT - loshift;
1069 lomask = ((digit)1 << hishift) - 1;
1070 himask = MASK ^ lomask;
1071 z = alloclongobject(newsize);
1072 if (z == NULL)
1073 return NULL;
1074 if (a->ob_size < 0)
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001075 z->ob_size = -(z->ob_size);
Guido van Rossumc6913e71991-11-19 20:26:46 +00001076 for (i = 0, j = wordshift; i < newsize; i++, j++) {
1077 z->ob_digit[i] = (a->ob_digit[j] >> loshift) & lomask;
1078 if (i+1 < newsize)
1079 z->ob_digit[i] |=
1080 (a->ob_digit[j+1] << hishift) & himask;
1081 }
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001082 return (object *) long_normalize(z);
Guido van Rossumc6913e71991-11-19 20:26:46 +00001083}
1084
1085static object *
1086long_lshift(a, b)
1087 longobject *a;
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001088 longobject *b;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001089{
1090 longobject *z;
1091 long shiftby;
1092 int newsize, wordshift, loshift, hishift, i, j;
1093 digit lomask, himask;
1094
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001095 shiftby = getlongvalue((object *)b);
Guido van Rossumc6913e71991-11-19 20:26:46 +00001096 if (shiftby == -1L && err_occurred())
1097 return NULL;
1098 if (shiftby < 0) {
Guido van Rossum87e7ea71991-12-10 14:00:03 +00001099 err_setstr(ValueError, "negative shift count");
Guido van Rossumc6913e71991-11-19 20:26:46 +00001100 return NULL;
1101 }
1102 if (shiftby > MASK) {
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001103 err_setstr(ValueError, "outrageous left shift count");
Guido van Rossumc6913e71991-11-19 20:26:46 +00001104 return NULL;
1105 }
1106 if (shiftby % SHIFT == 0) {
1107 wordshift = shiftby / SHIFT;
1108 loshift = 0;
1109 hishift = SHIFT;
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001110 newsize = ABS(a->ob_size) + wordshift;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001111 lomask = MASK;
1112 himask = 0;
1113 }
1114 else {
1115 wordshift = shiftby / SHIFT + 1;
1116 loshift = SHIFT - shiftby%SHIFT;
1117 hishift = shiftby % SHIFT;
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001118 newsize = ABS(a->ob_size) + wordshift;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001119 lomask = ((digit)1 << hishift) - 1;
1120 himask = MASK ^ lomask;
1121 }
1122 z = alloclongobject(newsize);
1123 if (z == NULL)
1124 return NULL;
1125 if (a->ob_size < 0)
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001126 z->ob_size = -(z->ob_size);
Guido van Rossumc6913e71991-11-19 20:26:46 +00001127 for (i = 0; i < wordshift; i++)
1128 z->ob_digit[i] = 0;
1129 for (i = wordshift, j = 0; i < newsize; i++, j++) {
1130 if (i > 0)
1131 z->ob_digit[i-1] |=
1132 (a->ob_digit[j] << hishift) & himask;
1133 z->ob_digit[i] =
1134 (a->ob_digit[j] >> loshift) & lomask;
1135 }
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001136 return (object *) long_normalize(z);
Guido van Rossumc6913e71991-11-19 20:26:46 +00001137}
1138
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001139
1140/* Bitwise and/xor/or operations */
1141
Guido van Rossumafbb8db1991-12-31 13:14:13 +00001142#define MAX(x, y) ((x) < (y) ? (y) : (x))
1143#define MIN(x, y) ((x) > (y) ? (y) : (x))
1144
Guido van Rossume32e0141992-01-19 16:31:05 +00001145static object *long_bitwise PROTO((longobject *, int, longobject *));
1146static object *
1147long_bitwise(a, op, b)
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001148 longobject *a;
1149 int op; /* '&', '|', '^' */
1150 longobject *b;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001151{
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001152 digit maska, maskb; /* 0 or MASK */
1153 int negz;
1154 int size_a, size_b, size_z;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001155 longobject *z;
1156 int i;
Guido van Rossum8b27d921992-03-27 17:27:05 +00001157 digit diga, digb;
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001158 object *v;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001159
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001160 if (a->ob_size < 0) {
1161 a = (longobject *) long_invert(a);
1162 maska = MASK;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001163 }
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001164 else {
1165 INCREF(a);
1166 maska = 0;
Guido van Rossumafbb8db1991-12-31 13:14:13 +00001167 }
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001168 if (b->ob_size < 0) {
1169 b = (longobject *) long_invert(b);
1170 maskb = MASK;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001171 }
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001172 else {
1173 INCREF(b);
1174 maskb = 0;
1175 }
Guido van Rossumc6913e71991-11-19 20:26:46 +00001176
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001177 size_a = a->ob_size;
1178 size_b = b->ob_size;
1179 size_z = MAX(size_a, size_b);
1180 z = alloclongobject(size_z);
1181 if (a == NULL || b == NULL || z == NULL) {
1182 XDECREF(a);
1183 XDECREF(b);
1184 XDECREF(z);
Guido van Rossumc6913e71991-11-19 20:26:46 +00001185 return NULL;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001186 }
Guido van Rossumc6913e71991-11-19 20:26:46 +00001187
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001188 negz = 0;
1189 switch (op) {
1190 case '^':
1191 if (maska != maskb) {
1192 maska ^= MASK;
1193 negz = -1;
1194 }
1195 break;
1196 case '&':
1197 if (maska && maskb) {
1198 op = '|';
1199 maska ^= MASK;
1200 maskb ^= MASK;
1201 negz = -1;
1202 }
1203 break;
1204 case '|':
1205 if (maska || maskb) {
1206 op = '&';
1207 maska ^= MASK;
1208 maskb ^= MASK;
1209 negz = -1;
1210 }
1211 break;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001212 }
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001213
1214 for (i = 0; i < size_z; ++i) {
1215 diga = (i < size_a ? a->ob_digit[i] : 0) ^ maska;
1216 digb = (i < size_b ? b->ob_digit[i] : 0) ^ maskb;
1217 switch (op) {
1218 case '&': z->ob_digit[i] = diga & digb; break;
1219 case '|': z->ob_digit[i] = diga | digb; break;
1220 case '^': z->ob_digit[i] = diga ^ digb; break;
1221 }
Guido van Rossumafbb8db1991-12-31 13:14:13 +00001222 }
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001223
1224 DECREF(a);
1225 DECREF(b);
1226 z = long_normalize(z);
1227 if (negz == 0)
1228 return (object *) z;
1229 v = long_invert(z);
1230 DECREF(z);
1231 return v;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001232}
1233
Guido van Rossumc6913e71991-11-19 20:26:46 +00001234static object *
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001235long_and(a, b)
Guido van Rossumc6913e71991-11-19 20:26:46 +00001236 longobject *a;
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001237 longobject *b;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001238{
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001239 return long_bitwise(a, '&', b);
Guido van Rossumc6913e71991-11-19 20:26:46 +00001240}
1241
1242static object *
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001243long_xor(a, b)
Guido van Rossumc6913e71991-11-19 20:26:46 +00001244 longobject *a;
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001245 longobject *b;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001246{
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001247 return long_bitwise(a, '^', b);
Guido van Rossumc6913e71991-11-19 20:26:46 +00001248}
1249
1250static object *
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001251long_or(a, b)
Guido van Rossumc6913e71991-11-19 20:26:46 +00001252 longobject *a;
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001253 longobject *b;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001254{
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001255 return long_bitwise(a, '|', b);
Guido van Rossum23d6f0e1991-05-14 12:06:49 +00001256}
1257
Guido van Rossume6eefc21992-08-14 12:06:52 +00001258int
1259long_coerce(pv, pw)
1260 object **pv;
1261 object **pw;
1262{
1263 if (is_intobject(*pw)) {
1264 *pw = newlongobject(getintvalue(*pw));
1265 INCREF(*pv);
1266 return 0;
1267 }
1268 return 1; /* Can't do it */
1269}
1270
Guido van Rossum8b27d921992-03-27 17:27:05 +00001271#define UF (object* (*) FPROTO((object *))) /* Unary function */
1272#define BF (object* (*) FPROTO((object *, object *))) /* Binary function */
1273#define IF (int (*) FPROTO((object *))) /* Int function */
1274
Guido van Rossumedcc38a1991-05-05 20:09:44 +00001275static number_methods long_as_number = {
Guido van Rossum8b27d921992-03-27 17:27:05 +00001276 BF long_add, /*nb_add*/
1277 BF long_sub, /*nb_subtract*/
1278 BF long_mul, /*nb_multiply*/
1279 BF long_div, /*nb_divide*/
1280 BF long_mod, /*nb_remainder*/
1281 BF long_divmod, /*nb_divmod*/
1282 BF long_pow, /*nb_power*/
1283 UF long_neg, /*nb_negative*/
1284 UF long_pos, /*tp_positive*/
1285 UF long_abs, /*tp_absolute*/
1286 IF long_nonzero,/*tp_nonzero*/
1287 UF long_invert, /*nb_invert*/
1288 BF long_lshift, /*nb_lshift*/
1289 BF long_rshift, /*nb_rshift*/
1290 BF long_and, /*nb_and*/
1291 BF long_xor, /*nb_xor*/
1292 BF long_or, /*nb_or*/
Guido van Rossume6eefc21992-08-14 12:06:52 +00001293 (int (*) FPROTO((object **, object **)))
1294 long_coerce, /*nb_coerce*/
Guido van Rossumedcc38a1991-05-05 20:09:44 +00001295};
1296
1297typeobject Longtype = {
1298 OB_HEAD_INIT(&Typetype)
1299 0,
1300 "long int",
1301 sizeof(longobject) - sizeof(digit),
1302 sizeof(digit),
1303 long_dealloc, /*tp_dealloc*/
1304 long_print, /*tp_print*/
1305 0, /*tp_getattr*/
1306 0, /*tp_setattr*/
Guido van Rossum8b27d921992-03-27 17:27:05 +00001307 (int (*) FPROTO((object *, object *)))
Guido van Rossumedcc38a1991-05-05 20:09:44 +00001308 long_compare, /*tp_compare*/
1309 long_repr, /*tp_repr*/
1310 &long_as_number,/*tp_as_number*/
1311 0, /*tp_as_sequence*/
1312 0, /*tp_as_mapping*/
1313};