blob: 391cd80817040bfc923cca33777979456b4b3a63 [file] [log] [blame]
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001/* Integer object implementation */
2
3#include <stdio.h>
4
5#include "PROTO.h"
6#include "object.h"
7#include "intobject.h"
8#include "stringobject.h"
9#include "objimpl.h"
Guido van Rossum165e67e1990-10-14 20:02:26 +000010#include "errors.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000011
12/* Standard Booleans */
13intobject FalseObject = {
14 OB_HEAD_INIT(&Inttype)
15 0
16};
17intobject TrueObject = {
18 OB_HEAD_INIT(&Inttype)
19 1
20};
21
Guido van Rossum165e67e1990-10-14 20:02:26 +000022static object *
23err_ovf()
24{
25 err_setstr(RuntimeError, "integer overflow");
26 return NULL;
27}
28
29static object *
30err_zdiv()
31{
32 err_setstr(RuntimeError, "division by zero");
33 return NULL;
34}
35
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000036object *
37newintobject(ival)
38 long ival;
39{
40 /* For efficiency, this code is copied from newobject() */
41 register intobject *op = (intobject *) malloc(sizeof(intobject));
42 if (op == NULL) {
Guido van Rossum165e67e1990-10-14 20:02:26 +000043 err_nomem();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000044 }
45 else {
46 NEWREF(op);
47 op->ob_type = &Inttype;
48 op->ob_ival = ival;
49 }
50 return (object *) op;
51}
52
53long
54getintvalue(op)
55 register object *op;
56{
57 if (!is_intobject(op)) {
Guido van Rossum165e67e1990-10-14 20:02:26 +000058 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000059 return -1;
60 }
61 else
62 return ((intobject *)op) -> ob_ival;
63}
64
65/* Methods */
66
67static void
68intprint(v, fp, flags)
69 intobject *v;
70 FILE *fp;
71 int flags;
72{
73 fprintf(fp, "%ld", v->ob_ival);
74}
75
76static object *
77intrepr(v)
78 intobject *v;
79{
80 char buf[20];
81 sprintf(buf, "%ld", v->ob_ival);
82 return newstringobject(buf);
83}
84
85static int
86intcompare(v, w)
87 intobject *v, *w;
88{
89 register long i = v->ob_ival;
90 register long j = w->ob_ival;
91 return (i < j) ? -1 : (i > j) ? 1 : 0;
92}
93
94static object *
95intadd(v, w)
96 intobject *v;
97 register object *w;
98{
99 register long a, b, x;
100 if (!is_intobject(w)) {
Guido van Rossum165e67e1990-10-14 20:02:26 +0000101 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000102 return NULL;
103 }
104 a = v->ob_ival;
105 b = ((intobject *)w) -> ob_ival;
106 x = a + b;
Guido van Rossum165e67e1990-10-14 20:02:26 +0000107 if ((x^a) < 0 && (x^b) < 0)
108 return err_ovf();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000109 return newintobject(x);
110}
111
112static object *
113intsub(v, w)
114 intobject *v;
115 register object *w;
116{
117 register long a, b, x;
118 if (!is_intobject(w)) {
Guido van Rossum165e67e1990-10-14 20:02:26 +0000119 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000120 return NULL;
121 }
122 a = v->ob_ival;
123 b = ((intobject *)w) -> ob_ival;
124 x = a - b;
Guido van Rossum165e67e1990-10-14 20:02:26 +0000125 if ((x^a) < 0 && (x^~b) < 0)
126 return err_ovf();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000127 return newintobject(x);
128}
129
130static object *
131intmul(v, w)
132 intobject *v;
133 register object *w;
134{
135 register long a, b;
136 double x;
137 if (!is_intobject(w)) {
Guido van Rossum165e67e1990-10-14 20:02:26 +0000138 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000139 return NULL;
140 }
141 a = v->ob_ival;
142 b = ((intobject *)w) -> ob_ival;
143 x = (double)a * (double)b;
Guido van Rossum165e67e1990-10-14 20:02:26 +0000144 if (x > 0x7fffffff || x < (double) (long) 0x80000000)
145 return err_ovf();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000146 return newintobject(a * b);
147}
148
149static object *
150intdiv(v, w)
151 intobject *v;
152 register object *w;
153{
154 if (!is_intobject(w)) {
Guido van Rossum165e67e1990-10-14 20:02:26 +0000155 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000156 return NULL;
157 }
Guido van Rossum165e67e1990-10-14 20:02:26 +0000158 if (((intobject *)w) -> ob_ival == 0)
159 err_zdiv();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000160 return newintobject(v->ob_ival / ((intobject *)w) -> ob_ival);
161}
162
163static object *
164intrem(v, w)
165 intobject *v;
166 register object *w;
167{
168 if (!is_intobject(w)) {
Guido van Rossum165e67e1990-10-14 20:02:26 +0000169 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000170 return NULL;
171 }
Guido van Rossum165e67e1990-10-14 20:02:26 +0000172 if (((intobject *)w) -> ob_ival == 0)
173 err_zdiv();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000174 return newintobject(v->ob_ival % ((intobject *)w) -> ob_ival);
175}
176
177static object *
178intpow(v, w)
179 intobject *v;
180 register object *w;
181{
182 register long iv, iw, ix;
183 register int neg;
184 if (!is_intobject(w)) {
Guido van Rossum165e67e1990-10-14 20:02:26 +0000185 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000186 return NULL;
187 }
188 iv = v->ob_ival;
189 iw = ((intobject *)w)->ob_ival;
190 neg = 0;
191 if (iw < 0)
192 neg = 1, iw = -iw;
193 ix = 1;
194 for (; iw > 0; iw--)
195 ix = ix * iv;
196 if (neg) {
Guido van Rossum165e67e1990-10-14 20:02:26 +0000197 if (ix == 0)
198 err_zdiv();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000199 ix = 1/ix;
200 }
201 /* XXX How to check for overflow? */
202 return newintobject(ix);
203}
204
205static object *
206intneg(v)
207 intobject *v;
208{
209 register long a, x;
210 a = v->ob_ival;
211 x = -a;
Guido van Rossum165e67e1990-10-14 20:02:26 +0000212 if (a < 0 && x < 0)
213 return err_ovf();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000214 return newintobject(x);
215}
216
217static object *
218intpos(v)
219 intobject *v;
220{
221 INCREF(v);
222 return (object *)v;
223}
224
225static number_methods int_as_number = {
226 intadd, /*tp_add*/
227 intsub, /*tp_subtract*/
228 intmul, /*tp_multiply*/
229 intdiv, /*tp_divide*/
230 intrem, /*tp_remainder*/
231 intpow, /*tp_power*/
232 intneg, /*tp_negate*/
233 intpos, /*tp_plus*/
234};
235
236typeobject Inttype = {
237 OB_HEAD_INIT(&Typetype)
238 0,
239 "int",
240 sizeof(intobject),
241 0,
242 free, /*tp_dealloc*/
243 intprint, /*tp_print*/
244 0, /*tp_getattr*/
245 0, /*tp_setattr*/
246 intcompare, /*tp_compare*/
247 intrepr, /*tp_repr*/
248 &int_as_number, /*tp_as_number*/
249 0, /*tp_as_sequence*/
250 0, /*tp_as_mapping*/
251};