blob: c8b2fac4e376e518b1897ffc64796d445e10d174 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
2Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
3Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000025/* Integer object implementation */
26
Guido van Rossum3f5da241990-12-20 15:06:42 +000027#include "allobjects.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000028
29/* Standard Booleans */
Guido van Rossum3f5da241990-12-20 15:06:42 +000030
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000031intobject FalseObject = {
32 OB_HEAD_INIT(&Inttype)
33 0
34};
Guido van Rossum3f5da241990-12-20 15:06:42 +000035
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000036intobject TrueObject = {
37 OB_HEAD_INIT(&Inttype)
38 1
39};
40
Guido van Rossum165e67e1990-10-14 20:02:26 +000041static object *
42err_ovf()
43{
Guido van Rossum5c52b6a1990-10-21 22:11:03 +000044 err_setstr(OverflowError, "integer overflow");
Guido van Rossum165e67e1990-10-14 20:02:26 +000045 return NULL;
46}
47
48static object *
49err_zdiv()
50{
Guido van Rossum5c52b6a1990-10-21 22:11:03 +000051 err_setstr(ZeroDivisionError, "integer division by zero");
Guido van Rossum165e67e1990-10-14 20:02:26 +000052 return NULL;
53}
54
Guido van Rossum3f5da241990-12-20 15:06:42 +000055/* Integers are quite normal objects, to make object handling uniform.
56 (Using odd pointers to represent integers would save much space
57 but require extra checks for this special case throughout the code.)
58 Since, a typical Python program spends much of its time allocating
59 and deallocating integers, these operations should be very fast.
60 Therefore we use a dedicated allocation scheme with a much lower
61 overhead (in space and time) than straight malloc(): a simple
62 dedicated free list, filled when necessary with memory from malloc().
63*/
64
65#define BLOCK_SIZE 1000 /* 1K less typical malloc overhead */
66#define N_INTOBJECTS (BLOCK_SIZE / sizeof(intobject))
67
68static intobject *
69fill_free_list()
70{
71 intobject *p, *q;
72 p = NEW(intobject, N_INTOBJECTS);
73 if (p == NULL)
74 return (intobject *)err_nomem();
75 q = p + N_INTOBJECTS;
76 while (--q > p)
77 *(intobject **)q = q-1;
78 *(intobject **)q = NULL;
79 return p + N_INTOBJECTS - 1;
80}
81
82static intobject *free_list = NULL;
83
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000084object *
85newintobject(ival)
86 long ival;
87{
Guido van Rossum3f5da241990-12-20 15:06:42 +000088 register intobject *v;
89 if (free_list == NULL) {
90 if ((free_list = fill_free_list()) == NULL)
91 return NULL;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000092 }
Guido van Rossum3f5da241990-12-20 15:06:42 +000093 v = free_list;
94 free_list = *(intobject **)free_list;
95 NEWREF(v);
96 v->ob_type = &Inttype;
97 v->ob_ival = ival;
98 return (object *) v;
99}
100
101static void
102int_dealloc(v)
103 intobject *v;
104{
105 *(intobject **)v = free_list;
106 free_list = v;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000107}
108
109long
110getintvalue(op)
111 register object *op;
112{
113 if (!is_intobject(op)) {
Guido van Rossum5c52b6a1990-10-21 22:11:03 +0000114 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000115 return -1;
116 }
117 else
118 return ((intobject *)op) -> ob_ival;
119}
120
121/* Methods */
122
Guido van Rossum90933611991-06-07 16:10:43 +0000123static int
Guido van Rossum3f5da241990-12-20 15:06:42 +0000124int_print(v, fp, flags)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000125 intobject *v;
126 FILE *fp;
127 int flags;
128{
129 fprintf(fp, "%ld", v->ob_ival);
Guido van Rossum90933611991-06-07 16:10:43 +0000130 return 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000131}
132
133static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000134int_repr(v)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000135 intobject *v;
136{
137 char buf[20];
138 sprintf(buf, "%ld", v->ob_ival);
139 return newstringobject(buf);
140}
141
142static int
Guido van Rossum3f5da241990-12-20 15:06:42 +0000143int_compare(v, w)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000144 intobject *v, *w;
145{
146 register long i = v->ob_ival;
147 register long j = w->ob_ival;
148 return (i < j) ? -1 : (i > j) ? 1 : 0;
149}
150
151static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000152int_add(v, w)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000153 intobject *v;
154 register object *w;
155{
156 register long a, b, x;
157 if (!is_intobject(w)) {
Guido van Rossum165e67e1990-10-14 20:02:26 +0000158 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000159 return NULL;
160 }
161 a = v->ob_ival;
162 b = ((intobject *)w) -> ob_ival;
163 x = a + b;
Guido van Rossum165e67e1990-10-14 20:02:26 +0000164 if ((x^a) < 0 && (x^b) < 0)
165 return err_ovf();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000166 return newintobject(x);
167}
168
169static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000170int_sub(v, w)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000171 intobject *v;
172 register object *w;
173{
174 register long a, b, x;
175 if (!is_intobject(w)) {
Guido van Rossum165e67e1990-10-14 20:02:26 +0000176 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000177 return NULL;
178 }
179 a = v->ob_ival;
180 b = ((intobject *)w) -> ob_ival;
181 x = a - b;
Guido van Rossum165e67e1990-10-14 20:02:26 +0000182 if ((x^a) < 0 && (x^~b) < 0)
183 return err_ovf();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000184 return newintobject(x);
185}
186
187static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000188int_mul(v, w)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000189 intobject *v;
190 register object *w;
191{
192 register long a, b;
193 double x;
194 if (!is_intobject(w)) {
Guido van Rossum165e67e1990-10-14 20:02:26 +0000195 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000196 return NULL;
197 }
198 a = v->ob_ival;
199 b = ((intobject *)w) -> ob_ival;
200 x = (double)a * (double)b;
Guido van Rossum165e67e1990-10-14 20:02:26 +0000201 if (x > 0x7fffffff || x < (double) (long) 0x80000000)
202 return err_ovf();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000203 return newintobject(a * b);
204}
205
206static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000207int_div(v, w)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000208 intobject *v;
209 register object *w;
210{
Guido van Rossum7928cd71991-10-24 14:59:31 +0000211 register long a, b, x;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000212 if (!is_intobject(w)) {
Guido van Rossum165e67e1990-10-14 20:02:26 +0000213 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000214 return NULL;
215 }
Guido van Rossum165e67e1990-10-14 20:02:26 +0000216 if (((intobject *)w) -> ob_ival == 0)
Guido van Rossumabbda161990-10-26 14:58:41 +0000217 return err_zdiv();
Guido van Rossum7928cd71991-10-24 14:59:31 +0000218 a = v->ob_ival;
219 b = ((intobject *)w) -> ob_ival;
220 /* Make sure we always truncate towards zero */
221 /* XXX What if a == -0x80000000? */
222 if (a < 0) {
223 if (b < 0)
224 x = -a / -b;
225 else
226 x = -(-a / b);
227 }
228 else {
229 if (b < 0)
230 x = -(a / -b);
231 else
232 x = a / b;
233 }
234 return newintobject(x);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000235}
236
237static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000238int_rem(v, w)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000239 intobject *v;
240 register object *w;
241{
242 if (!is_intobject(w)) {
Guido van Rossum165e67e1990-10-14 20:02:26 +0000243 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000244 return NULL;
245 }
Guido van Rossum165e67e1990-10-14 20:02:26 +0000246 if (((intobject *)w) -> ob_ival == 0)
Guido van Rossumabbda161990-10-26 14:58:41 +0000247 return err_zdiv();
Guido van Rossum7928cd71991-10-24 14:59:31 +0000248 /* XXX Need to fix this similar to int_div */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000249 return newintobject(v->ob_ival % ((intobject *)w) -> ob_ival);
250}
251
252static object *
Guido van Rossum00466951991-05-05 20:08:27 +0000253int_divmod(x, y)
254 intobject *x;
255 register object *y;
256{
257 object *v, *v0, *v1;
258 long xi, yi, xdivy, xmody;
259 if (!is_intobject(y)) {
260 err_badarg();
261 return NULL;
262 }
263 xi = x->ob_ival;
264 yi = getintvalue(y);
265 if (yi == 0)
266 return err_zdiv();
267 if (yi < 0) {
268 xdivy = -xi / -yi;
269 }
270 else {
271 xdivy = xi / yi;
272 }
273 xmody = xi - xdivy*yi;
274 if (xmody < 0 && yi > 0 || xmody > 0 && yi < 0) {
275 xmody += yi;
276 xdivy -= 1;
277 }
278 v = newtupleobject(2);
279 v0 = newintobject(xdivy);
280 v1 = newintobject(xmody);
281 if (v == NULL || v0 == NULL || v1 == NULL ||
282 settupleitem(v, 0, v0) != 0 ||
283 settupleitem(v, 1, v1) != 0) {
284 XDECREF(v);
285 XDECREF(v0);
286 XDECREF(v1);
287 v = NULL;
288 }
289 return v;
290}
291
292static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000293int_pow(v, w)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000294 intobject *v;
295 register object *w;
296{
297 register long iv, iw, ix;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000298 if (!is_intobject(w)) {
Guido van Rossum165e67e1990-10-14 20:02:26 +0000299 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000300 return NULL;
301 }
302 iv = v->ob_ival;
303 iw = ((intobject *)w)->ob_ival;
Guido van Rossum00466951991-05-05 20:08:27 +0000304 if (iw < 0) {
305 err_setstr(RuntimeError, "integer to the negative power");
306 return NULL;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000307 }
Guido van Rossum00466951991-05-05 20:08:27 +0000308 ix = 1;
309 while (--iw >= 0) {
310 long prev = ix;
311 ix = ix * iv;
312 if (iv == 0)
313 break; /* 0 to some power -- avoid ix / 0 */
314 if (ix / iv != prev)
315 return err_ovf();
316 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000317 return newintobject(ix);
318}
319
320static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000321int_neg(v)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000322 intobject *v;
323{
324 register long a, x;
325 a = v->ob_ival;
326 x = -a;
Guido van Rossum165e67e1990-10-14 20:02:26 +0000327 if (a < 0 && x < 0)
328 return err_ovf();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000329 return newintobject(x);
330}
331
332static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000333int_pos(v)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000334 intobject *v;
335{
336 INCREF(v);
337 return (object *)v;
338}
339
Guido van Rossum00466951991-05-05 20:08:27 +0000340static object *
341int_abs(v)
342 intobject *v;
343{
344 if (v->ob_ival >= 0)
345 return int_pos(v);
346 else
347 return int_neg(v);
348}
349
Guido van Rossum0bff0151991-05-14 12:05:32 +0000350static int
351int_nonzero(v)
352 intobject *v;
353{
354 return v->ob_ival != 0;
355}
356
Guido van Rossum7928cd71991-10-24 14:59:31 +0000357static object *
358int_invert(v)
359 intobject *v;
360{
361 return newintobject(~v->ob_ival);
362}
363
364static object *
365int_lshift(v, w)
366 intobject *v;
367 register object *w;
368{
369 register long a, b;
370 if (!is_intobject(w)) {
371 err_badarg();
372 return NULL;
373 }
374 a = v->ob_ival;
375 b = ((intobject *)w) -> ob_ival;
376 return newintobject((unsigned long)a << b);
377}
378
379static object *
380int_rshift(v, w)
381 intobject *v;
382 register object *w;
383{
384 register long a, b;
385 if (!is_intobject(w)) {
386 err_badarg();
387 return NULL;
388 }
389 a = v->ob_ival;
390 b = ((intobject *)w) -> ob_ival;
391 return newintobject((unsigned long)a >> b);
392}
393
394static object *
395int_and(v, w)
396 intobject *v;
397 register object *w;
398{
399 register long a, b;
400 if (!is_intobject(w)) {
401 err_badarg();
402 return NULL;
403 }
404 a = v->ob_ival;
405 b = ((intobject *)w) -> ob_ival;
406 return newintobject(a & b);
407}
408
409static object *
410int_xor(v, w)
411 intobject *v;
412 register object *w;
413{
414 register long a, b;
415 if (!is_intobject(w)) {
416 err_badarg();
417 return NULL;
418 }
419 a = v->ob_ival;
420 b = ((intobject *)w) -> ob_ival;
421 return newintobject(a ^ b);
422}
423
424static object *
425int_or(v, w)
426 intobject *v;
427 register object *w;
428{
429 register long a, b;
430 if (!is_intobject(w)) {
431 err_badarg();
432 return NULL;
433 }
434 a = v->ob_ival;
435 b = ((intobject *)w) -> ob_ival;
436 return newintobject(a | b);
437}
438
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000439static number_methods int_as_number = {
Guido van Rossum00466951991-05-05 20:08:27 +0000440 int_add, /*nb_add*/
441 int_sub, /*nb_subtract*/
442 int_mul, /*nb_multiply*/
443 int_div, /*nb_divide*/
444 int_rem, /*nb_remainder*/
445 int_divmod, /*nb_divmod*/
446 int_pow, /*nb_power*/
447 int_neg, /*nb_negative*/
448 int_pos, /*nb_positive*/
449 int_abs, /*nb_absolute*/
Guido van Rossum0bff0151991-05-14 12:05:32 +0000450 int_nonzero, /*nb_nonzero*/
Guido van Rossum7928cd71991-10-24 14:59:31 +0000451 int_invert, /*nb_invert*/
452 int_lshift, /*nb_lshift*/
453 int_rshift, /*nb_rshift*/
454 int_and, /*nb_and*/
455 int_xor, /*nb_xor*/
456 int_or, /*nb_or*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000457};
458
459typeobject Inttype = {
460 OB_HEAD_INIT(&Typetype)
461 0,
462 "int",
463 sizeof(intobject),
464 0,
Guido van Rossum3f5da241990-12-20 15:06:42 +0000465 int_dealloc, /*tp_dealloc*/
466 int_print, /*tp_print*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000467 0, /*tp_getattr*/
468 0, /*tp_setattr*/
Guido van Rossum3f5da241990-12-20 15:06:42 +0000469 int_compare, /*tp_compare*/
470 int_repr, /*tp_repr*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000471 &int_as_number, /*tp_as_number*/
472 0, /*tp_as_sequence*/
473 0, /*tp_as_mapping*/
474};