Added divmod and abs, fixed negative powers
This commit is contained in:
parent
175a9ea8c8
commit
0046695d0c
@ -230,31 +230,71 @@ int_rem(v, w)
|
|||||||
return newintobject(v->ob_ival % ((intobject *)w) -> ob_ival);
|
return newintobject(v->ob_ival % ((intobject *)w) -> ob_ival);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 *
|
static object *
|
||||||
int_pow(v, w)
|
int_pow(v, w)
|
||||||
intobject *v;
|
intobject *v;
|
||||||
register object *w;
|
register object *w;
|
||||||
{
|
{
|
||||||
register long iv, iw, ix;
|
register long iv, iw, ix;
|
||||||
register int neg;
|
|
||||||
if (!is_intobject(w)) {
|
if (!is_intobject(w)) {
|
||||||
err_badarg();
|
err_badarg();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
iv = v->ob_ival;
|
iv = v->ob_ival;
|
||||||
iw = ((intobject *)w)->ob_ival;
|
iw = ((intobject *)w)->ob_ival;
|
||||||
neg = 0;
|
if (iw < 0) {
|
||||||
if (iw < 0)
|
err_setstr(RuntimeError, "integer to the negative power");
|
||||||
neg = 1, iw = -iw;
|
return NULL;
|
||||||
ix = 1;
|
}
|
||||||
for (; iw > 0; iw--)
|
ix = 1;
|
||||||
ix = ix * iv;
|
while (--iw >= 0) {
|
||||||
if (neg) {
|
long prev = ix;
|
||||||
if (ix == 0)
|
ix = ix * iv;
|
||||||
return err_zdiv();
|
if (iv == 0)
|
||||||
ix = 1/ix;
|
break; /* 0 to some power -- avoid ix / 0 */
|
||||||
|
if (ix / iv != prev)
|
||||||
|
return err_ovf();
|
||||||
}
|
}
|
||||||
/* XXX How to check for overflow? */
|
|
||||||
return newintobject(ix);
|
return newintobject(ix);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,15 +318,27 @@ int_pos(v)
|
|||||||
return (object *)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 = {
|
static number_methods int_as_number = {
|
||||||
int_add, /*tp_add*/
|
int_add, /*nb_add*/
|
||||||
int_sub, /*tp_subtract*/
|
int_sub, /*nb_subtract*/
|
||||||
int_mul, /*tp_multiply*/
|
int_mul, /*nb_multiply*/
|
||||||
int_div, /*tp_divide*/
|
int_div, /*nb_divide*/
|
||||||
int_rem, /*tp_remainder*/
|
int_rem, /*nb_remainder*/
|
||||||
int_pow, /*tp_power*/
|
int_divmod, /*nb_divmod*/
|
||||||
int_neg, /*tp_negate*/
|
int_pow, /*nb_power*/
|
||||||
int_pos, /*tp_plus*/
|
int_neg, /*nb_negative*/
|
||||||
|
int_pos, /*nb_positive*/
|
||||||
|
int_abs, /*nb_absolute*/
|
||||||
};
|
};
|
||||||
|
|
||||||
typeobject Inttype = {
|
typeobject Inttype = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user