summaryrefslogtreecommitdiffstats
path: root/Objects/intobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/intobject.c')
-rw-r--r--Objects/intobject.c250
1 files changed, 250 insertions, 0 deletions
diff --git a/Objects/intobject.c b/Objects/intobject.c
new file mode 100644
index 0000000..7a69238
--- /dev/null
+++ b/Objects/intobject.c
@@ -0,0 +1,250 @@
+/* Integer object implementation */
+
+#include <stdio.h>
+
+#include "PROTO.h"
+#include "object.h"
+#include "intobject.h"
+#include "stringobject.h"
+#include "objimpl.h"
+
+/* Standard Booleans */
+intobject FalseObject = {
+ OB_HEAD_INIT(&Inttype)
+ 0
+};
+intobject TrueObject = {
+ OB_HEAD_INIT(&Inttype)
+ 1
+};
+
+object *
+newintobject(ival)
+ long ival;
+{
+ /* For efficiency, this code is copied from newobject() */
+ register intobject *op = (intobject *) malloc(sizeof(intobject));
+ if (op == NULL) {
+ errno = ENOMEM;
+ }
+ else {
+ NEWREF(op);
+ op->ob_type = &Inttype;
+ op->ob_ival = ival;
+ }
+ return (object *) op;
+}
+
+long
+getintvalue(op)
+ register object *op;
+{
+ if (!is_intobject(op)) {
+ errno = EBADF;
+ return -1;
+ }
+ else
+ return ((intobject *)op) -> ob_ival;
+}
+
+/* Methods */
+
+static void
+intprint(v, fp, flags)
+ intobject *v;
+ FILE *fp;
+ int flags;
+{
+ fprintf(fp, "%ld", v->ob_ival);
+}
+
+static object *
+intrepr(v)
+ intobject *v;
+{
+ char buf[20];
+ sprintf(buf, "%ld", v->ob_ival);
+ return newstringobject(buf);
+}
+
+static int
+intcompare(v, w)
+ intobject *v, *w;
+{
+ register long i = v->ob_ival;
+ register long j = w->ob_ival;
+ return (i < j) ? -1 : (i > j) ? 1 : 0;
+}
+
+static object *
+intadd(v, w)
+ intobject *v;
+ register object *w;
+{
+ register long a, b, x;
+ if (!is_intobject(w)) {
+ errno = EINVAL;
+ return NULL;
+ }
+ a = v->ob_ival;
+ b = ((intobject *)w) -> ob_ival;
+ x = a + b;
+ if ((x^a) < 0 && (x^b) < 0) {
+ errno = ERANGE;
+ return NULL;
+ }
+ return newintobject(x);
+}
+
+static object *
+intsub(v, w)
+ intobject *v;
+ register object *w;
+{
+ register long a, b, x;
+ if (!is_intobject(w)) {
+ errno = EINVAL;
+ return NULL;
+ }
+ a = v->ob_ival;
+ b = ((intobject *)w) -> ob_ival;
+ x = a - b;
+ if ((x^a) < 0 && (x^~b) < 0) {
+ errno = ERANGE;
+ return NULL;
+ }
+ return newintobject(x);
+}
+
+static object *
+intmul(v, w)
+ intobject *v;
+ register object *w;
+{
+ register long a, b;
+ double x;
+ if (!is_intobject(w)) {
+ errno = EINVAL;
+ return NULL;
+ }
+ a = v->ob_ival;
+ b = ((intobject *)w) -> ob_ival;
+ x = (double)a * (double)b;
+ if (x > 0x7fffffff || x < (double) (long) 0x80000000) {
+ errno = ERANGE;
+ return NULL;
+ }
+ return newintobject(a * b);
+}
+
+static object *
+intdiv(v, w)
+ intobject *v;
+ register object *w;
+{
+ if (!is_intobject(w)) {
+ errno = EINVAL;
+ return NULL;
+ }
+ if (((intobject *)w) -> ob_ival == 0) {
+ errno = EDOM;
+ return NULL;
+ }
+ return newintobject(v->ob_ival / ((intobject *)w) -> ob_ival);
+}
+
+static object *
+intrem(v, w)
+ intobject *v;
+ register object *w;
+{
+ if (!is_intobject(w)) {
+ errno = EINVAL;
+ return NULL;
+ }
+ if (((intobject *)w) -> ob_ival == 0) {
+ errno = EDOM;
+ return NULL;
+ }
+ return newintobject(v->ob_ival % ((intobject *)w) -> ob_ival);
+}
+
+static object *
+intpow(v, w)
+ intobject *v;
+ register object *w;
+{
+ register long iv, iw, ix;
+ register int neg;
+ if (!is_intobject(w)) {
+ errno = EINVAL;
+ return NULL;
+ }
+ iv = v->ob_ival;
+ iw = ((intobject *)w)->ob_ival;
+ neg = 0;
+ if (iw < 0)
+ neg = 1, iw = -iw;
+ ix = 1;
+ for (; iw > 0; iw--)
+ ix = ix * iv;
+ if (neg) {
+ if (ix == 0) {
+ errno = EDOM;
+ return NULL;
+ }
+ ix = 1/ix;
+ }
+ /* XXX How to check for overflow? */
+ return newintobject(ix);
+}
+
+static object *
+intneg(v)
+ intobject *v;
+{
+ register long a, x;
+ a = v->ob_ival;
+ x = -a;
+ if (a < 0 && x < 0) {
+ errno = ERANGE;
+ return NULL;
+ }
+ return newintobject(x);
+}
+
+static object *
+intpos(v)
+ intobject *v;
+{
+ INCREF(v);
+ return (object *)v;
+}
+
+static number_methods int_as_number = {
+ intadd, /*tp_add*/
+ intsub, /*tp_subtract*/
+ intmul, /*tp_multiply*/
+ intdiv, /*tp_divide*/
+ intrem, /*tp_remainder*/
+ intpow, /*tp_power*/
+ intneg, /*tp_negate*/
+ intpos, /*tp_plus*/
+};
+
+typeobject Inttype = {
+ OB_HEAD_INIT(&Typetype)
+ 0,
+ "int",
+ sizeof(intobject),
+ 0,
+ free, /*tp_dealloc*/
+ intprint, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ intcompare, /*tp_compare*/
+ intrepr, /*tp_repr*/
+ &int_as_number, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+};