summaryrefslogtreecommitdiffstats
path: root/Objects/intobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/intobject.c')
-rw-r--r--Objects/intobject.c88
1 files changed, 70 insertions, 18 deletions
diff --git a/Objects/intobject.c b/Objects/intobject.c
index 6c700e8..eeb4038 100644
--- a/Objects/intobject.c
+++ b/Objects/intobject.c
@@ -231,30 +231,70 @@ int_rem(v, w)
}
static object *
+int_divmod(x, y)
+ intobject *x;
+ register object *y;
+{
+ object *v, *v0, *v1;
+ long xi, yi, xdivy, xmody;
+ if (!is_intobject(y)) {
+ err_badarg();
+ return NULL;
+ }
+ xi = x->ob_ival;
+ yi = getintvalue(y);
+ if (yi == 0)
+ return err_zdiv();
+ if (yi < 0) {
+ xdivy = -xi / -yi;
+ }
+ else {
+ xdivy = xi / yi;
+ }
+ xmody = xi - xdivy*yi;
+ if (xmody < 0 && yi > 0 || xmody > 0 && yi < 0) {
+ xmody += yi;
+ xdivy -= 1;
+ }
+ v = newtupleobject(2);
+ v0 = newintobject(xdivy);
+ v1 = newintobject(xmody);
+ if (v == NULL || v0 == NULL || v1 == NULL ||
+ settupleitem(v, 0, v0) != 0 ||
+ settupleitem(v, 1, v1) != 0) {
+ XDECREF(v);
+ XDECREF(v0);
+ XDECREF(v1);
+ v = NULL;
+ }
+ return v;
+}
+
+static object *
int_pow(v, w)
intobject *v;
register object *w;
{
register long iv, iw, ix;
- register int neg;
if (!is_intobject(w)) {
err_badarg();
return NULL;
}
iv = v->ob_ival;
iw = ((intobject *)w)->ob_ival;
- neg = 0;
- if (iw < 0)
- neg = 1, iw = -iw;
+ if (iw < 0) {
+ err_setstr(RuntimeError, "integer to the negative power");
+ return NULL;
+ }
ix = 1;
- for (; iw > 0; iw--)
+ while (--iw >= 0) {
+ long prev = ix;
ix = ix * iv;
- if (neg) {
- if (ix == 0)
- return err_zdiv();
- ix = 1/ix;
+ if (iv == 0)
+ break; /* 0 to some power -- avoid ix / 0 */
+ if (ix / iv != prev)
+ return err_ovf();
}
- /* XXX How to check for overflow? */
return newintobject(ix);
}
@@ -278,15 +318,27 @@ int_pos(v)
return (object *)v;
}
+static object *
+int_abs(v)
+ intobject *v;
+{
+ if (v->ob_ival >= 0)
+ return int_pos(v);
+ else
+ return int_neg(v);
+}
+
static number_methods int_as_number = {
- int_add, /*tp_add*/
- int_sub, /*tp_subtract*/
- int_mul, /*tp_multiply*/
- int_div, /*tp_divide*/
- int_rem, /*tp_remainder*/
- int_pow, /*tp_power*/
- int_neg, /*tp_negate*/
- int_pos, /*tp_plus*/
+ int_add, /*nb_add*/
+ int_sub, /*nb_subtract*/
+ int_mul, /*nb_multiply*/
+ int_div, /*nb_divide*/
+ int_rem, /*nb_remainder*/
+ int_divmod, /*nb_divmod*/
+ int_pow, /*nb_power*/
+ int_neg, /*nb_negative*/
+ int_pos, /*nb_positive*/
+ int_abs, /*nb_absolute*/
};
typeobject Inttype = {