blob: 85d1c661459620be1924f24fdaa96451153081f3 [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 Rossumedcc38a1991-05-05 20:09:44 +0000584static object *
585long_repr(v)
Guido van Rossum8b27d921992-03-27 17:27:05 +0000586 object *v;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000587{
Guido van Rossum8b27d921992-03-27 17:27:05 +0000588 return long_format(v, 10);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000589}
590
591static int
592long_compare(a, b)
593 longobject *a, *b;
594{
595 int sign;
596
Guido van Rossumc6913e71991-11-19 20:26:46 +0000597 if (a->ob_size != b->ob_size) {
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000598 if (ABS(a->ob_size) == 0 && ABS(b->ob_size) == 0)
Guido van Rossumc6913e71991-11-19 20:26:46 +0000599 sign = 0;
600 else
601 sign = a->ob_size - b->ob_size;
602 }
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000603 else {
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000604 int i = ABS(a->ob_size);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000605 while (--i >= 0 && a->ob_digit[i] == b->ob_digit[i])
606 ;
607 if (i < 0)
608 sign = 0;
Guido van Rossum0b0db8e1993-01-21 16:07:51 +0000609 else {
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000610 sign = (int)a->ob_digit[i] - (int)b->ob_digit[i];
Guido van Rossum0b0db8e1993-01-21 16:07:51 +0000611 if (a->ob_size < 0)
612 sign = -sign;
613 }
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000614 }
Guido van Rossumc6913e71991-11-19 20:26:46 +0000615 return sign < 0 ? -1 : sign > 0 ? 1 : 0;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000616}
617
618/* Add the absolute values of two long integers. */
619
620static longobject *x_add PROTO((longobject *, longobject *));
621static longobject *
622x_add(a, b)
623 longobject *a, *b;
624{
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000625 int size_a = ABS(a->ob_size), size_b = ABS(b->ob_size);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000626 longobject *z;
627 int i;
628 digit carry = 0;
629
630 /* Ensure a is the larger of the two: */
631 if (size_a < size_b) {
632 { longobject *temp = a; a = b; b = temp; }
633 { int size_temp = size_a; size_a = size_b; size_b = size_temp; }
634 }
635 z = alloclongobject(size_a+1);
636 if (z == NULL)
637 return NULL;
638 for (i = 0; i < size_b; ++i) {
639 carry += a->ob_digit[i] + b->ob_digit[i];
640 z->ob_digit[i] = carry & MASK;
641 /* The following assumes unsigned shifts don't
642 propagate the sign bit. */
643 carry >>= SHIFT;
644 }
645 for (; i < size_a; ++i) {
646 carry += a->ob_digit[i];
647 z->ob_digit[i] = carry & MASK;
648 carry >>= SHIFT;
649 }
650 z->ob_digit[i] = carry;
651 return long_normalize(z);
652}
653
654/* Subtract the absolute values of two integers. */
655
656static longobject *x_sub PROTO((longobject *, longobject *));
657static longobject *
658x_sub(a, b)
659 longobject *a, *b;
660{
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000661 int size_a = ABS(a->ob_size), size_b = ABS(b->ob_size);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000662 longobject *z;
663 int i;
664 int sign = 1;
665 digit borrow = 0;
666
667 /* Ensure a is the larger of the two: */
668 if (size_a < size_b) {
669 sign = -1;
670 { longobject *temp = a; a = b; b = temp; }
671 { int size_temp = size_a; size_a = size_b; size_b = size_temp; }
672 }
673 else if (size_a == size_b) {
674 /* Find highest digit where a and b differ: */
675 i = size_a;
676 while (--i >= 0 && a->ob_digit[i] == b->ob_digit[i])
677 ;
678 if (i < 0)
679 return alloclongobject(0);
680 if (a->ob_digit[i] < b->ob_digit[i]) {
681 sign = -1;
682 { longobject *temp = a; a = b; b = temp; }
683 }
684 size_a = size_b = i+1;
685 }
686 z = alloclongobject(size_a);
687 if (z == NULL)
688 return NULL;
689 for (i = 0; i < size_b; ++i) {
690 /* The following assumes unsigned arithmetic
691 works module 2**N for some N>SHIFT. */
692 borrow = a->ob_digit[i] - b->ob_digit[i] - borrow;
693 z->ob_digit[i] = borrow & MASK;
694 borrow >>= SHIFT;
695 borrow &= 1; /* Keep only one sign bit */
696 }
697 for (; i < size_a; ++i) {
698 borrow = a->ob_digit[i] - borrow;
699 z->ob_digit[i] = borrow & MASK;
700 borrow >>= SHIFT;
701 }
702 assert(borrow == 0);
Guido van Rossumc6913e71991-11-19 20:26:46 +0000703 if (sign < 0)
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000704 z->ob_size = -(z->ob_size);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000705 return long_normalize(z);
706}
707
708static object *
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000709long_add(a, b)
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000710 longobject *a;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000711 longobject *b;
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000712{
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000713 longobject *z;
714
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000715 if (a->ob_size < 0) {
716 if (b->ob_size < 0) {
717 z = x_add(a, b);
Guido van Rossumc6913e71991-11-19 20:26:46 +0000718 if (z != NULL && z->ob_size != 0)
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000719 z->ob_size = -(z->ob_size);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000720 }
721 else
722 z = x_sub(b, a);
723 }
724 else {
725 if (b->ob_size < 0)
726 z = x_sub(a, b);
727 else
728 z = x_add(a, b);
729 }
730 return (object *)z;
731}
732
733static object *
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000734long_sub(a, b)
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000735 longobject *a;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000736 longobject *b;
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000737{
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000738 longobject *z;
739
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000740 if (a->ob_size < 0) {
741 if (b->ob_size < 0)
742 z = x_sub(a, b);
743 else
744 z = x_add(a, b);
Guido van Rossumc6913e71991-11-19 20:26:46 +0000745 if (z != NULL && z->ob_size != 0)
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000746 z->ob_size = -(z->ob_size);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000747 }
748 else {
749 if (b->ob_size < 0)
750 z = x_add(a, b);
751 else
752 z = x_sub(a, b);
753 }
754 return (object *)z;
755}
756
757static object *
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000758long_mul(a, b)
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000759 longobject *a;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000760 longobject *b;
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000761{
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000762 int size_a;
763 int size_b;
764 longobject *z;
765 int i;
766
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000767 size_a = ABS(a->ob_size);
768 size_b = ABS(b->ob_size);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000769 z = alloclongobject(size_a + size_b);
770 if (z == NULL)
771 return NULL;
772 for (i = 0; i < z->ob_size; ++i)
773 z->ob_digit[i] = 0;
774 for (i = 0; i < size_a; ++i) {
775 twodigits carry = 0;
776 twodigits f = a->ob_digit[i];
777 int j;
778
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000779 INTRCHECK({
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000780 DECREF(z);
781 err_set(KeyboardInterrupt);
782 return NULL;
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000783 })
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000784 for (j = 0; j < size_b; ++j) {
785 carry += z->ob_digit[i+j] + b->ob_digit[j] * f;
786 z->ob_digit[i+j] = carry & MASK;
787 carry >>= SHIFT;
788 }
789 for (; carry != 0; ++j) {
790 assert(i+j < z->ob_size);
791 carry += z->ob_digit[i+j];
792 z->ob_digit[i+j] = carry & MASK;
793 carry >>= SHIFT;
794 }
795 }
796 if (a->ob_size < 0)
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000797 z->ob_size = -(z->ob_size);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000798 if (b->ob_size < 0)
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000799 z->ob_size = -(z->ob_size);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000800 return (object *) long_normalize(z);
801}
802
Guido van Rossume32e0141992-01-19 16:31:05 +0000803/* The / and % operators are now defined in terms of divmod().
804 The expression a mod b has the value a - b*floor(a/b).
805 The long_divrem function gives the remainder after division of
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000806 |a| by |b|, with the sign of a. This is also expressed
807 as a - b*trunc(a/b), if trunc truncates towards zero.
808 Some examples:
809 a b a rem b a mod b
810 13 10 3 3
811 -13 10 -3 7
812 13 -10 3 -7
813 -13 -10 -3 -3
814 So, to get from rem to mod, we have to add b if a and b
Guido van Rossum23d6f0e1991-05-14 12:06:49 +0000815 have different signs. We then subtract one from the 'div'
816 part of the outcome to keep the invariant intact. */
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000817
Guido van Rossume32e0141992-01-19 16:31:05 +0000818static int l_divmod PROTO((longobject *, longobject *,
819 longobject **, longobject **));
820static int
821l_divmod(v, w, pdiv, pmod)
822 longobject *v;
823 longobject *w;
824 longobject **pdiv;
825 longobject **pmod;
826{
827 longobject *div, *mod;
828
829 if (long_divrem(v, w, &div, &mod) < 0)
830 return -1;
831 if (mod->ob_size < 0 && w->ob_size > 0 ||
832 mod->ob_size > 0 && w->ob_size < 0) {
833 longobject *temp;
834 longobject *one;
835 temp = (longobject *) long_add(mod, w);
836 DECREF(mod);
837 mod = temp;
838 if (mod == NULL) {
839 DECREF(div);
840 return -1;
841 }
842 one = (longobject *) newlongobject(1L);
843 if (one == NULL ||
844 (temp = (longobject *) long_sub(div, one)) == NULL) {
845 DECREF(mod);
846 DECREF(div);
847 return -1;
848 }
849 DECREF(div);
850 div = temp;
851 }
852 *pdiv = div;
853 *pmod = mod;
854 return 0;
855}
856
857static object *
858long_div(v, w)
859 longobject *v;
860 longobject *w;
861{
862 longobject *div, *mod;
863 if (l_divmod(v, w, &div, &mod) < 0)
864 return NULL;
865 DECREF(mod);
866 return (object *)div;
867}
868
869static object *
870long_mod(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(div);
878 return (object *)mod;
879}
880
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000881static object *
882long_divmod(v, w)
883 longobject *v;
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000884 longobject *w;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000885{
886 object *z;
Guido van Rossume32e0141992-01-19 16:31:05 +0000887 longobject *div, *mod;
888 if (l_divmod(v, w, &div, &mod) < 0)
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000889 return NULL;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000890 z = newtupleobject(2);
891 if (z != NULL) {
892 settupleitem(z, 0, (object *) div);
Guido van Rossume32e0141992-01-19 16:31:05 +0000893 settupleitem(z, 1, (object *) mod);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000894 }
895 else {
896 DECREF(div);
Guido van Rossume32e0141992-01-19 16:31:05 +0000897 DECREF(mod);
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000898 }
899 return z;
900}
901
902static object *
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000903long_pow(a, b)
Guido van Rossumc7ec9c91991-05-28 21:58:16 +0000904 longobject *a;
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000905 longobject *b;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000906{
Guido van Rossumc7ec9c91991-05-28 21:58:16 +0000907 longobject *z;
908 int size_b, i;
909
Guido van Rossumc7ec9c91991-05-28 21:58:16 +0000910 size_b = b->ob_size;
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000911 if (size_b < 0) {
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000912 err_setstr(ValueError, "long integer to the negative power");
Guido van Rossumc7ec9c91991-05-28 21:58:16 +0000913 return NULL;
914 }
915
916 z = (longobject *)newlongobject(1L);
917
918 INCREF(a);
919 for (i = 0; i < size_b; ++i) {
920 digit bi = b->ob_digit[i];
921 int j;
922
923 for (j = 0; j < SHIFT; ++j) {
924 longobject *temp;
925
926 if (bi & 1) {
Guido van Rossume32e0141992-01-19 16:31:05 +0000927 temp = (longobject *)long_mul(z, a);
Guido van Rossumc7ec9c91991-05-28 21:58:16 +0000928 DECREF(z);
929 z = temp;
930 if (z == NULL)
931 break;
932 }
933 bi >>= 1;
934 if (bi == 0 && i+1 == size_b)
935 break;
Guido van Rossume32e0141992-01-19 16:31:05 +0000936 temp = (longobject *)long_mul(a, a);
Guido van Rossumc7ec9c91991-05-28 21:58:16 +0000937 DECREF(a);
938 a = temp;
939 if (a == NULL) {
940 DECREF(z);
941 z = NULL;
942 break;
943 }
944 }
945 if (a == NULL)
946 break;
947 }
948 XDECREF(a);
949 return (object *)z;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000950}
951
952static object *
Guido van Rossumc6913e71991-11-19 20:26:46 +0000953long_invert(v)
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000954 longobject *v;
955{
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000956 /* Implement ~x as -(x+1) */
957 longobject *x;
Guido van Rossume32e0141992-01-19 16:31:05 +0000958 longobject *w;
959 w = (longobject *)newlongobject(1L);
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000960 if (w == NULL)
961 return NULL;
962 x = (longobject *) long_add(v, w);
963 DECREF(w);
964 if (x == NULL)
965 return NULL;
966 if (x->ob_size != 0)
967 x->ob_size = -(x->ob_size);
968 return (object *)x;
Guido van Rossumedcc38a1991-05-05 20:09:44 +0000969}
970
971static object *
Guido van Rossumc6913e71991-11-19 20:26:46 +0000972long_pos(v)
973 longobject *v;
974{
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000975 INCREF(v);
976 return (object *)v;
Guido van Rossumc6913e71991-11-19 20:26:46 +0000977}
978
979static object *
980long_neg(v)
981 longobject *v;
982{
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000983 longobject *z;
984 int i, n;
985 n = ABS(v->ob_size);
986 if (n == 0) {
987 /* -0 == 0 */
Guido van Rossumc6913e71991-11-19 20:26:46 +0000988 INCREF(v);
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000989 return (object *) v;
Guido van Rossumc6913e71991-11-19 20:26:46 +0000990 }
Guido van Rossum4c260ff1992-01-14 18:36:43 +0000991 z = alloclongobject(ABS(n));
992 if (z == NULL)
993 return NULL;
994 for (i = 0; i < n; i++)
995 z->ob_digit[i] = v->ob_digit[i];
996 z->ob_size = -(v->ob_size);
997 return (object *)z;
Guido van Rossumc6913e71991-11-19 20:26:46 +0000998}
999
1000static object *
Guido van Rossumedcc38a1991-05-05 20:09:44 +00001001long_abs(v)
1002 longobject *v;
1003{
1004 if (v->ob_size < 0)
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001005 return long_neg(v);
Guido van Rossumc6913e71991-11-19 20:26:46 +00001006 else {
1007 INCREF(v);
1008 return (object *)v;
1009 }
Guido van Rossumedcc38a1991-05-05 20:09:44 +00001010}
1011
Guido van Rossum23d6f0e1991-05-14 12:06:49 +00001012static int
1013long_nonzero(v)
1014 longobject *v;
1015{
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001016 return ABS(v->ob_size) != 0;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001017}
1018
1019static object *
1020long_rshift(a, b)
1021 longobject *a;
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001022 longobject *b;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001023{
1024 longobject *z;
1025 long shiftby;
1026 int newsize, wordshift, loshift, hishift, i, j;
1027 digit lomask, himask;
1028
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001029 if (a->ob_size < 0) {
1030 /* Right shifting negative numbers is harder */
1031 longobject *a1, *a2, *a3;
1032 a1 = (longobject *) long_invert(a);
1033 if (a1 == NULL) return NULL;
1034 a2 = (longobject *) long_rshift(a1, b);
1035 DECREF(a1);
1036 if (a2 == NULL) return NULL;
1037 a3 = (longobject *) long_invert(a2);
1038 DECREF(a2);
1039 return (object *) a3;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001040 }
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001041
1042 shiftby = getlongvalue((object *)b);
Guido van Rossumc6913e71991-11-19 20:26:46 +00001043 if (shiftby == -1L && err_occurred())
1044 return NULL;
1045 if (shiftby < 0) {
Guido van Rossum87e7ea71991-12-10 14:00:03 +00001046 err_setstr(ValueError, "negative shift count");
Guido van Rossumc6913e71991-11-19 20:26:46 +00001047 return NULL;
1048 }
Guido van Rossumc6913e71991-11-19 20:26:46 +00001049 wordshift = shiftby / SHIFT;
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001050 newsize = ABS(a->ob_size) - wordshift;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001051 if (newsize <= 0) {
1052 z = alloclongobject(0);
Guido van Rossumc6913e71991-11-19 20:26:46 +00001053 return (object *)z;
1054 }
1055 loshift = shiftby % SHIFT;
1056 hishift = SHIFT - loshift;
1057 lomask = ((digit)1 << hishift) - 1;
1058 himask = MASK ^ lomask;
1059 z = alloclongobject(newsize);
1060 if (z == NULL)
1061 return NULL;
1062 if (a->ob_size < 0)
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001063 z->ob_size = -(z->ob_size);
Guido van Rossumc6913e71991-11-19 20:26:46 +00001064 for (i = 0, j = wordshift; i < newsize; i++, j++) {
1065 z->ob_digit[i] = (a->ob_digit[j] >> loshift) & lomask;
1066 if (i+1 < newsize)
1067 z->ob_digit[i] |=
1068 (a->ob_digit[j+1] << hishift) & himask;
1069 }
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001070 return (object *) long_normalize(z);
Guido van Rossumc6913e71991-11-19 20:26:46 +00001071}
1072
1073static object *
1074long_lshift(a, b)
1075 longobject *a;
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001076 longobject *b;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001077{
1078 longobject *z;
1079 long shiftby;
1080 int newsize, wordshift, loshift, hishift, i, j;
1081 digit lomask, himask;
1082
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001083 shiftby = getlongvalue((object *)b);
Guido van Rossumc6913e71991-11-19 20:26:46 +00001084 if (shiftby == -1L && err_occurred())
1085 return NULL;
1086 if (shiftby < 0) {
Guido van Rossum87e7ea71991-12-10 14:00:03 +00001087 err_setstr(ValueError, "negative shift count");
Guido van Rossumc6913e71991-11-19 20:26:46 +00001088 return NULL;
1089 }
1090 if (shiftby > MASK) {
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001091 err_setstr(ValueError, "outrageous left shift count");
Guido van Rossumc6913e71991-11-19 20:26:46 +00001092 return NULL;
1093 }
1094 if (shiftby % SHIFT == 0) {
1095 wordshift = shiftby / SHIFT;
1096 loshift = 0;
1097 hishift = SHIFT;
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001098 newsize = ABS(a->ob_size) + wordshift;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001099 lomask = MASK;
1100 himask = 0;
1101 }
1102 else {
1103 wordshift = shiftby / SHIFT + 1;
1104 loshift = SHIFT - shiftby%SHIFT;
1105 hishift = shiftby % SHIFT;
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001106 newsize = ABS(a->ob_size) + wordshift;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001107 lomask = ((digit)1 << hishift) - 1;
1108 himask = MASK ^ lomask;
1109 }
1110 z = alloclongobject(newsize);
1111 if (z == NULL)
1112 return NULL;
1113 if (a->ob_size < 0)
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001114 z->ob_size = -(z->ob_size);
Guido van Rossumc6913e71991-11-19 20:26:46 +00001115 for (i = 0; i < wordshift; i++)
1116 z->ob_digit[i] = 0;
1117 for (i = wordshift, j = 0; i < newsize; i++, j++) {
1118 if (i > 0)
1119 z->ob_digit[i-1] |=
1120 (a->ob_digit[j] << hishift) & himask;
1121 z->ob_digit[i] =
1122 (a->ob_digit[j] >> loshift) & lomask;
1123 }
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001124 return (object *) long_normalize(z);
Guido van Rossumc6913e71991-11-19 20:26:46 +00001125}
1126
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001127
1128/* Bitwise and/xor/or operations */
1129
Guido van Rossumafbb8db1991-12-31 13:14:13 +00001130#define MAX(x, y) ((x) < (y) ? (y) : (x))
1131#define MIN(x, y) ((x) > (y) ? (y) : (x))
1132
Guido van Rossume32e0141992-01-19 16:31:05 +00001133static object *long_bitwise PROTO((longobject *, int, longobject *));
1134static object *
1135long_bitwise(a, op, b)
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001136 longobject *a;
1137 int op; /* '&', '|', '^' */
1138 longobject *b;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001139{
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001140 digit maska, maskb; /* 0 or MASK */
1141 int negz;
1142 int size_a, size_b, size_z;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001143 longobject *z;
1144 int i;
Guido van Rossum8b27d921992-03-27 17:27:05 +00001145 digit diga, digb;
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001146 object *v;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001147
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001148 if (a->ob_size < 0) {
1149 a = (longobject *) long_invert(a);
1150 maska = MASK;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001151 }
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001152 else {
1153 INCREF(a);
1154 maska = 0;
Guido van Rossumafbb8db1991-12-31 13:14:13 +00001155 }
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001156 if (b->ob_size < 0) {
1157 b = (longobject *) long_invert(b);
1158 maskb = MASK;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001159 }
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001160 else {
1161 INCREF(b);
1162 maskb = 0;
1163 }
Guido van Rossumc6913e71991-11-19 20:26:46 +00001164
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001165 size_a = a->ob_size;
1166 size_b = b->ob_size;
1167 size_z = MAX(size_a, size_b);
1168 z = alloclongobject(size_z);
1169 if (a == NULL || b == NULL || z == NULL) {
1170 XDECREF(a);
1171 XDECREF(b);
1172 XDECREF(z);
Guido van Rossumc6913e71991-11-19 20:26:46 +00001173 return NULL;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001174 }
Guido van Rossumc6913e71991-11-19 20:26:46 +00001175
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001176 negz = 0;
1177 switch (op) {
1178 case '^':
1179 if (maska != maskb) {
1180 maska ^= MASK;
1181 negz = -1;
1182 }
1183 break;
1184 case '&':
1185 if (maska && maskb) {
1186 op = '|';
1187 maska ^= MASK;
1188 maskb ^= MASK;
1189 negz = -1;
1190 }
1191 break;
1192 case '|':
1193 if (maska || maskb) {
1194 op = '&';
1195 maska ^= MASK;
1196 maskb ^= MASK;
1197 negz = -1;
1198 }
1199 break;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001200 }
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001201
1202 for (i = 0; i < size_z; ++i) {
1203 diga = (i < size_a ? a->ob_digit[i] : 0) ^ maska;
1204 digb = (i < size_b ? b->ob_digit[i] : 0) ^ maskb;
1205 switch (op) {
1206 case '&': z->ob_digit[i] = diga & digb; break;
1207 case '|': z->ob_digit[i] = diga | digb; break;
1208 case '^': z->ob_digit[i] = diga ^ digb; break;
1209 }
Guido van Rossumafbb8db1991-12-31 13:14:13 +00001210 }
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001211
1212 DECREF(a);
1213 DECREF(b);
1214 z = long_normalize(z);
1215 if (negz == 0)
1216 return (object *) z;
1217 v = long_invert(z);
1218 DECREF(z);
1219 return v;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001220}
1221
Guido van Rossumc6913e71991-11-19 20:26:46 +00001222static object *
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001223long_and(a, b)
Guido van Rossumc6913e71991-11-19 20:26:46 +00001224 longobject *a;
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001225 longobject *b;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001226{
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001227 return long_bitwise(a, '&', b);
Guido van Rossumc6913e71991-11-19 20:26:46 +00001228}
1229
1230static object *
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001231long_xor(a, b)
Guido van Rossumc6913e71991-11-19 20:26:46 +00001232 longobject *a;
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001233 longobject *b;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001234{
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001235 return long_bitwise(a, '^', b);
Guido van Rossumc6913e71991-11-19 20:26:46 +00001236}
1237
1238static object *
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001239long_or(a, b)
Guido van Rossumc6913e71991-11-19 20:26:46 +00001240 longobject *a;
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001241 longobject *b;
Guido van Rossumc6913e71991-11-19 20:26:46 +00001242{
Guido van Rossum4c260ff1992-01-14 18:36:43 +00001243 return long_bitwise(a, '|', b);
Guido van Rossum23d6f0e1991-05-14 12:06:49 +00001244}
1245
Guido van Rossume6eefc21992-08-14 12:06:52 +00001246int
1247long_coerce(pv, pw)
1248 object **pv;
1249 object **pw;
1250{
1251 if (is_intobject(*pw)) {
1252 *pw = newlongobject(getintvalue(*pw));
1253 INCREF(*pv);
1254 return 0;
1255 }
1256 return 1; /* Can't do it */
1257}
1258
Guido van Rossum1899c2e1992-09-12 11:09:23 +00001259static object *
1260long_int(v)
1261 object *v;
1262{
1263 long x;
1264 x = getlongvalue(v);
1265 if (err_occurred())
1266 return NULL;
1267 return newintobject(x);
1268}
1269
1270static object *
1271long_long(v)
1272 object *v;
1273{
1274 INCREF(v);
1275 return v;
1276}
1277
1278static object *
1279long_float(v)
1280 object *v;
1281{
1282 return newfloatobject(dgetlongvalue(v));
1283}
1284
1285static object *
1286long_oct(v)
1287 object *v;
1288{
1289 return long_format(v, 8);
1290}
1291
1292static object *
1293long_hex(v)
1294 object *v;
1295{
1296 return long_format(v, 16);
1297}
1298
1299
Guido van Rossum8b27d921992-03-27 17:27:05 +00001300#define UF (object* (*) FPROTO((object *))) /* Unary function */
1301#define BF (object* (*) FPROTO((object *, object *))) /* Binary function */
1302#define IF (int (*) FPROTO((object *))) /* Int function */
1303
Guido van Rossumedcc38a1991-05-05 20:09:44 +00001304static number_methods long_as_number = {
Guido van Rossum8b27d921992-03-27 17:27:05 +00001305 BF long_add, /*nb_add*/
1306 BF long_sub, /*nb_subtract*/
1307 BF long_mul, /*nb_multiply*/
1308 BF long_div, /*nb_divide*/
1309 BF long_mod, /*nb_remainder*/
1310 BF long_divmod, /*nb_divmod*/
1311 BF long_pow, /*nb_power*/
1312 UF long_neg, /*nb_negative*/
1313 UF long_pos, /*tp_positive*/
1314 UF long_abs, /*tp_absolute*/
1315 IF long_nonzero,/*tp_nonzero*/
1316 UF long_invert, /*nb_invert*/
1317 BF long_lshift, /*nb_lshift*/
1318 BF long_rshift, /*nb_rshift*/
1319 BF long_and, /*nb_and*/
1320 BF long_xor, /*nb_xor*/
1321 BF long_or, /*nb_or*/
Guido van Rossume6eefc21992-08-14 12:06:52 +00001322 (int (*) FPROTO((object **, object **)))
1323 long_coerce, /*nb_coerce*/
Guido van Rossum1899c2e1992-09-12 11:09:23 +00001324 UF long_int, /*nb_int*/
1325 UF long_long, /*nb_long*/
1326 UF long_float, /*nb_float*/
1327 UF long_oct, /*nb_oct*/
1328 UF long_hex, /*nb_hex*/
Guido van Rossumedcc38a1991-05-05 20:09:44 +00001329};
1330
1331typeobject Longtype = {
1332 OB_HEAD_INIT(&Typetype)
1333 0,
1334 "long int",
1335 sizeof(longobject) - sizeof(digit),
1336 sizeof(digit),
1337 long_dealloc, /*tp_dealloc*/
Guido van Rossum7066dd71992-09-17 17:54:56 +00001338 0, /*tp_print*/
Guido van Rossumedcc38a1991-05-05 20:09:44 +00001339 0, /*tp_getattr*/
1340 0, /*tp_setattr*/
Guido van Rossum8b27d921992-03-27 17:27:05 +00001341 (int (*) FPROTO((object *, object *)))
Guido van Rossumedcc38a1991-05-05 20:09:44 +00001342 long_compare, /*tp_compare*/
1343 long_repr, /*tp_repr*/
1344 &long_as_number,/*tp_as_number*/
1345 0, /*tp_as_sequence*/
1346 0, /*tp_as_mapping*/
1347};