blob: 7a69238afc582d469b4a3453b9babea7e1aee8b9 [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"
10
11/* Standard Booleans */
12intobject FalseObject = {
13 OB_HEAD_INIT(&Inttype)
14 0
15};
16intobject TrueObject = {
17 OB_HEAD_INIT(&Inttype)
18 1
19};
20
21object *
22newintobject(ival)
23 long ival;
24{
25 /* For efficiency, this code is copied from newobject() */
26 register intobject *op = (intobject *) malloc(sizeof(intobject));
27 if (op == NULL) {
28 errno = ENOMEM;
29 }
30 else {
31 NEWREF(op);
32 op->ob_type = &Inttype;
33 op->ob_ival = ival;
34 }
35 return (object *) op;
36}
37
38long
39getintvalue(op)
40 register object *op;
41{
42 if (!is_intobject(op)) {
43 errno = EBADF;
44 return -1;
45 }
46 else
47 return ((intobject *)op) -> ob_ival;
48}
49
50/* Methods */
51
52static void
53intprint(v, fp, flags)
54 intobject *v;
55 FILE *fp;
56 int flags;
57{
58 fprintf(fp, "%ld", v->ob_ival);
59}
60
61static object *
62intrepr(v)
63 intobject *v;
64{
65 char buf[20];
66 sprintf(buf, "%ld", v->ob_ival);
67 return newstringobject(buf);
68}
69
70static int
71intcompare(v, w)
72 intobject *v, *w;
73{
74 register long i = v->ob_ival;
75 register long j = w->ob_ival;
76 return (i < j) ? -1 : (i > j) ? 1 : 0;
77}
78
79static object *
80intadd(v, w)
81 intobject *v;
82 register object *w;
83{
84 register long a, b, x;
85 if (!is_intobject(w)) {
86 errno = EINVAL;
87 return NULL;
88 }
89 a = v->ob_ival;
90 b = ((intobject *)w) -> ob_ival;
91 x = a + b;
92 if ((x^a) < 0 && (x^b) < 0) {
93 errno = ERANGE;
94 return NULL;
95 }
96 return newintobject(x);
97}
98
99static object *
100intsub(v, w)
101 intobject *v;
102 register object *w;
103{
104 register long a, b, x;
105 if (!is_intobject(w)) {
106 errno = EINVAL;
107 return NULL;
108 }
109 a = v->ob_ival;
110 b = ((intobject *)w) -> ob_ival;
111 x = a - b;
112 if ((x^a) < 0 && (x^~b) < 0) {
113 errno = ERANGE;
114 return NULL;
115 }
116 return newintobject(x);
117}
118
119static object *
120intmul(v, w)
121 intobject *v;
122 register object *w;
123{
124 register long a, b;
125 double x;
126 if (!is_intobject(w)) {
127 errno = EINVAL;
128 return NULL;
129 }
130 a = v->ob_ival;
131 b = ((intobject *)w) -> ob_ival;
132 x = (double)a * (double)b;
133 if (x > 0x7fffffff || x < (double) (long) 0x80000000) {
134 errno = ERANGE;
135 return NULL;
136 }
137 return newintobject(a * b);
138}
139
140static object *
141intdiv(v, w)
142 intobject *v;
143 register object *w;
144{
145 if (!is_intobject(w)) {
146 errno = EINVAL;
147 return NULL;
148 }
149 if (((intobject *)w) -> ob_ival == 0) {
150 errno = EDOM;
151 return NULL;
152 }
153 return newintobject(v->ob_ival / ((intobject *)w) -> ob_ival);
154}
155
156static object *
157intrem(v, w)
158 intobject *v;
159 register object *w;
160{
161 if (!is_intobject(w)) {
162 errno = EINVAL;
163 return NULL;
164 }
165 if (((intobject *)w) -> ob_ival == 0) {
166 errno = EDOM;
167 return NULL;
168 }
169 return newintobject(v->ob_ival % ((intobject *)w) -> ob_ival);
170}
171
172static object *
173intpow(v, w)
174 intobject *v;
175 register object *w;
176{
177 register long iv, iw, ix;
178 register int neg;
179 if (!is_intobject(w)) {
180 errno = EINVAL;
181 return NULL;
182 }
183 iv = v->ob_ival;
184 iw = ((intobject *)w)->ob_ival;
185 neg = 0;
186 if (iw < 0)
187 neg = 1, iw = -iw;
188 ix = 1;
189 for (; iw > 0; iw--)
190 ix = ix * iv;
191 if (neg) {
192 if (ix == 0) {
193 errno = EDOM;
194 return NULL;
195 }
196 ix = 1/ix;
197 }
198 /* XXX How to check for overflow? */
199 return newintobject(ix);
200}
201
202static object *
203intneg(v)
204 intobject *v;
205{
206 register long a, x;
207 a = v->ob_ival;
208 x = -a;
209 if (a < 0 && x < 0) {
210 errno = ERANGE;
211 return NULL;
212 }
213 return newintobject(x);
214}
215
216static object *
217intpos(v)
218 intobject *v;
219{
220 INCREF(v);
221 return (object *)v;
222}
223
224static number_methods int_as_number = {
225 intadd, /*tp_add*/
226 intsub, /*tp_subtract*/
227 intmul, /*tp_multiply*/
228 intdiv, /*tp_divide*/
229 intrem, /*tp_remainder*/
230 intpow, /*tp_power*/
231 intneg, /*tp_negate*/
232 intpos, /*tp_plus*/
233};
234
235typeobject Inttype = {
236 OB_HEAD_INIT(&Typetype)
237 0,
238 "int",
239 sizeof(intobject),
240 0,
241 free, /*tp_dealloc*/
242 intprint, /*tp_print*/
243 0, /*tp_getattr*/
244 0, /*tp_setattr*/
245 intcompare, /*tp_compare*/
246 intrepr, /*tp_repr*/
247 &int_as_number, /*tp_as_number*/
248 0, /*tp_as_sequence*/
249 0, /*tp_as_mapping*/
250};