Add prototypes.

Change / and % to match divmod.
This commit is contained in:
Guido van Rossum 1992-01-19 16:31:05 +00:00
parent 3d09543472
commit e32e014c7e

View file

@ -27,10 +27,19 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* XXX The functional organization of this file is terrible */ /* XXX The functional organization of this file is terrible */
#include "allobjects.h" #include "allobjects.h"
#include "intrcheck.h"
#include "longintrepr.h" #include "longintrepr.h"
#include <math.h> #include <math.h>
#include <assert.h> #include <assert.h>
#define ABS(x) ((x) < 0 ? -(x) : (x))
/* Forward */
static longobject *long_normalize PROTO((longobject *));
static longobject *mul1 PROTO((longobject *, wdigit));
static longobject *muladd1 PROTO((longobject *, wdigit, wdigit));
static longobject *divrem1 PROTO((longobject *, wdigit, digit *));
static int ticker; /* XXX Could be shared with ceval? */ static int ticker; /* XXX Could be shared with ceval? */
#define INTRCHECK(block) \ #define INTRCHECK(block) \
@ -187,7 +196,7 @@ dgetlongvalue(vv)
/* Multiply by a single digit, ignoring the sign. */ /* Multiply by a single digit, ignoring the sign. */
longobject * static longobject *
mul1(a, n) mul1(a, n)
longobject *a; longobject *a;
wdigit n; wdigit n;
@ -197,7 +206,7 @@ mul1(a, n)
/* Multiply by a single digit and add a single digit, ignoring the sign. */ /* Multiply by a single digit and add a single digit, ignoring the sign. */
longobject * static longobject *
muladd1(a, n, extra) muladd1(a, n, extra)
longobject *a; longobject *a;
wdigit n; wdigit n;
@ -223,7 +232,7 @@ muladd1(a, n, extra)
(as function result) and the remainder (through *prem). (as function result) and the remainder (through *prem).
The sign of a is ignored; n should not be zero. */ The sign of a is ignored; n should not be zero. */
longobject * static longobject *
divrem1(a, n, prem) divrem1(a, n, prem)
longobject *a; longobject *a;
wdigit n; wdigit n;
@ -252,11 +261,12 @@ divrem1(a, n, prem)
If base is 8 or 16, add the proper prefix '0' or '0x'. If base is 8 or 16, add the proper prefix '0' or '0x'.
External linkage: used in bltinmodule.c by hex() and oct(). */ External linkage: used in bltinmodule.c by hex() and oct(). */
stringobject * object *
long_format(a, base) long_format(aa, base)
longobject *a; object *aa;
int base; int base;
{ {
register longobject *a = (longobject *)aa;
stringobject *str; stringobject *str;
int i; int i;
int size_a = ABS(a->ob_size); int size_a = ABS(a->ob_size);
@ -264,6 +274,10 @@ long_format(a, base)
int bits; int bits;
char sign = '\0'; char sign = '\0';
if (a == NULL || !is_longobject(a)) {
err_badcall();
return NULL;
}
assert(base >= 2 && base <= 36); assert(base >= 2 && base <= 36);
/* Compute a rough upper bound for the length of the string */ /* Compute a rough upper bound for the length of the string */
@ -330,7 +344,7 @@ long_format(a, base)
q--; q--;
resizestring((object **)&str, (int) (q - GETSTRINGVALUE(str))); resizestring((object **)&str, (int) (q - GETSTRINGVALUE(str)));
} }
return str; return (object *)str;
} }
/* Convert a string to a long int object, in a given base. /* Convert a string to a long int object, in a given base.
@ -386,58 +400,55 @@ long_scan(str, base)
static longobject *x_divrem PROTO((longobject *, longobject *, longobject **)); static longobject *x_divrem PROTO((longobject *, longobject *, longobject **));
static object *long_pos PROTO((longobject *)); static object *long_pos PROTO((longobject *));
static long_divrem PROTO((longobject *, longobject *,
longobject **, longobject **));
/* Long division with remainder, top-level routine */ /* Long division with remainder, top-level routine */
static longobject * static int
long_divrem(a, b, prem) long_divrem(a, b, pdiv, prem)
longobject *a, *b; longobject *a, *b;
longobject **pdiv;
longobject **prem; longobject **prem;
{ {
int size_a = ABS(a->ob_size), size_b = ABS(b->ob_size); int size_a = ABS(a->ob_size), size_b = ABS(b->ob_size);
longobject *z; longobject *z;
if (size_b == 0) { if (size_b == 0) {
if (prem != NULL) err_setstr(ZeroDivisionError, "long division or modulo");
*prem = NULL; return -1;
err_setstr(ZeroDivisionError, "long division or remainder");
return NULL;
} }
if (size_a < size_b || if (size_a < size_b ||
size_a == size_b && size_a == size_b &&
a->ob_digit[size_a-1] < b->ob_digit[size_b-1]) { a->ob_digit[size_a-1] < b->ob_digit[size_b-1]) {
/* |a| < |b|. */ /* |a| < |b|. */
if (prem != NULL) { *pdiv = alloclongobject(0);
INCREF(a); INCREF(a);
*prem = (longobject *) a; *prem = (longobject *) a;
} return 0;
return alloclongobject(0);
} }
if (size_b == 1) { if (size_b == 1) {
digit rem = 0; digit rem = 0;
z = divrem1(a, b->ob_digit[0], &rem); z = divrem1(a, b->ob_digit[0], &rem);
if (prem != NULL) {
if (z == NULL) if (z == NULL)
*prem = NULL; return -1;
else *prem = (longobject *) newlongobject((long)rem);
*prem = (longobject *)
newlongobject((long)rem);
} }
} else {
else
z = x_divrem(a, b, prem); z = x_divrem(a, b, prem);
if (z == NULL)
return -1;
}
/* Set the signs. /* Set the signs.
The quotient z has the sign of a*b; The quotient z has the sign of a*b;
the remainder r has the sign of a, the remainder r has the sign of a,
so a = b*z + r. */ so a = b*z + r. */
if (z != NULL) {
if ((a->ob_size < 0) != (b->ob_size < 0)) if ((a->ob_size < 0) != (b->ob_size < 0))
z->ob_size = -(z->ob_size); z->ob_size = -(z->ob_size);
if (prem != NULL && *prem != NULL && a->ob_size < 0 && if (a->ob_size < 0 && (*prem)->ob_size != 0)
(*prem)->ob_size != 0)
(*prem)->ob_size = -((*prem)->ob_size); (*prem)->ob_size = -((*prem)->ob_size);
} *pdiv = z;
return z; return 0;
} }
/* Unsigned long division with remainder -- the algorithm */ /* Unsigned long division with remainder -- the algorithm */
@ -457,8 +468,6 @@ x_divrem(v1, w1, prem)
if (v == NULL || w == NULL) { if (v == NULL || w == NULL) {
XDECREF(v); XDECREF(v);
XDECREF(w); XDECREF(w);
if (prem != NULL)
*prem = NULL;
return NULL; return NULL;
} }
@ -523,13 +532,8 @@ x_divrem(v1, w1, prem)
} }
} /* for j, k */ } /* for j, k */
if (a == NULL) { if (a != NULL) {
if (prem != NULL)
*prem = NULL;
}
else {
a = long_normalize(a); a = long_normalize(a);
if (prem != NULL) {
*prem = divrem1(v, d, &d); *prem = divrem1(v, d, &d);
/* d receives the (unused) remainder */ /* d receives the (unused) remainder */
if (*prem == NULL) { if (*prem == NULL) {
@ -537,7 +541,6 @@ x_divrem(v1, w1, prem)
a = NULL; a = NULL;
} }
} }
}
DECREF(v); DECREF(v);
DECREF(w); DECREF(w);
return a; return a;
@ -545,6 +548,30 @@ x_divrem(v1, w1, prem)
/* Methods */ /* Methods */
/* Forward */
static void long_dealloc PROTO((longobject *));
static int long_print PROTO((longobject *, FILE *, int));
static object *long_repr PROTO((longobject *));
static int long_compare PROTO((longobject *, longobject *));
static object *long_add PROTO((longobject *, longobject *));
static object *long_sub PROTO((longobject *, longobject *));
static object *long_mul PROTO((longobject *, longobject *));
static object *long_div PROTO((longobject *, longobject *));
static object *long_mod PROTO((longobject *, longobject *));
static object *long_divmod PROTO((longobject *, longobject *));
static object *long_pow PROTO((longobject *, longobject *));
static object *long_neg PROTO((longobject *));
static object *long_pos PROTO((longobject *));
static object *long_abs PROTO((longobject *));
static int long_nonzero PROTO((longobject *));
static object *long_invert PROTO((longobject *));
static object *long_lshift PROTO((longobject *, longobject *));
static object *long_rshift PROTO((longobject *, longobject *));
static object *long_and PROTO((longobject *, longobject *));
static object *long_xor PROTO((longobject *, longobject *));
static object *long_or PROTO((longobject *, longobject *));
static void static void
long_dealloc(v) long_dealloc(v)
longobject *v; longobject *v;
@ -558,7 +585,7 @@ long_print(v, fp, flags)
FILE *fp; FILE *fp;
int flags; int flags;
{ {
stringobject *str = long_format(v, 10); stringobject *str = (stringobject *) long_format((object *)v, 10);
if (str == NULL) if (str == NULL)
return -1; return -1;
fprintf(fp, "%s", GETSTRINGVALUE(str)); fprintf(fp, "%s", GETSTRINGVALUE(str));
@ -570,7 +597,7 @@ static object *
long_repr(v) long_repr(v)
longobject *v; longobject *v;
{ {
return (object *) long_format(v, 10); return long_format((object *)v, 10);
} }
static int static int
@ -782,34 +809,9 @@ long_mul(a, b)
return (object *) long_normalize(z); return (object *) long_normalize(z);
} }
static object * /* The / and % operators are now defined in terms of divmod().
long_div(v, w) The expression a mod b has the value a - b*floor(a/b).
longobject *v; The long_divrem function gives the remainder after division of
longobject *w;
{
return (object *) long_divrem(v, w, (longobject **)0);
}
static object *
long_rem(v, w)
longobject *v;
longobject *w;
{
longobject *div, *rem = NULL;
div = long_divrem(v, w, &rem);
if (div == NULL) {
XDECREF(rem);
rem = NULL;
}
else {
DECREF(div);
}
return (object *) rem;
}
/* The expression a mod b has the value a - b*floor(a/b).
The divrem function gives the remainder after division of
|a| by |b|, with the sign of a. This is also expressed |a| by |b|, with the sign of a. This is also expressed
as a - b*trunc(a/b), if trunc truncates towards zero. as a - b*trunc(a/b), if trunc truncates towards zero.
Some examples: Some examples:
@ -822,47 +824,86 @@ long_rem(v, w)
have different signs. We then subtract one from the 'div' have different signs. We then subtract one from the 'div'
part of the outcome to keep the invariant intact. */ part of the outcome to keep the invariant intact. */
static int l_divmod PROTO((longobject *, longobject *,
longobject **, longobject **));
static int
l_divmod(v, w, pdiv, pmod)
longobject *v;
longobject *w;
longobject **pdiv;
longobject **pmod;
{
longobject *div, *mod;
if (long_divrem(v, w, &div, &mod) < 0)
return -1;
if (mod->ob_size < 0 && w->ob_size > 0 ||
mod->ob_size > 0 && w->ob_size < 0) {
longobject *temp;
longobject *one;
temp = (longobject *) long_add(mod, w);
DECREF(mod);
mod = temp;
if (mod == NULL) {
DECREF(div);
return -1;
}
one = (longobject *) newlongobject(1L);
if (one == NULL ||
(temp = (longobject *) long_sub(div, one)) == NULL) {
DECREF(mod);
DECREF(div);
return -1;
}
DECREF(div);
div = temp;
}
*pdiv = div;
*pmod = mod;
return 0;
}
static object *
long_div(v, w)
longobject *v;
longobject *w;
{
longobject *div, *mod;
if (l_divmod(v, w, &div, &mod) < 0)
return NULL;
DECREF(mod);
return (object *)div;
}
static object *
long_mod(v, w)
longobject *v;
longobject *w;
{
longobject *div, *mod;
if (l_divmod(v, w, &div, &mod) < 0)
return NULL;
DECREF(div);
return (object *)mod;
}
static object * static object *
long_divmod(v, w) long_divmod(v, w)
longobject *v; longobject *v;
longobject *w; longobject *w;
{ {
object *z; object *z;
longobject *div, *rem; longobject *div, *mod;
div = long_divrem(v, w, &rem); if (l_divmod(v, w, &div, &mod) < 0)
if (div == NULL) {
XDECREF(rem);
return NULL; return NULL;
}
if (rem->ob_size < 0 && w->ob_size > 0 ||
rem->ob_size > 0 && w->ob_size < 0) {
longobject *temp;
longobject *one;
temp = (longobject *) long_add(rem, (object *)w);
DECREF(rem);
rem = temp;
if (rem == NULL) {
DECREF(div);
return NULL;
}
one = (longobject *) newlongobject(1L);
if (one == NULL ||
(temp = (longobject *) long_sub(div, one)) == NULL) {
DECREF(rem);
DECREF(div);
return NULL;
}
DECREF(div);
div = temp;
}
z = newtupleobject(2); z = newtupleobject(2);
if (z != NULL) { if (z != NULL) {
settupleitem(z, 0, (object *) div); settupleitem(z, 0, (object *) div);
settupleitem(z, 1, (object *) rem); settupleitem(z, 1, (object *) mod);
} }
else { else {
DECREF(div); DECREF(div);
DECREF(rem); DECREF(mod);
} }
return z; return z;
} }
@ -892,7 +933,7 @@ long_pow(a, b)
longobject *temp; longobject *temp;
if (bi & 1) { if (bi & 1) {
temp = (longobject *)long_mul(z, (object *)a); temp = (longobject *)long_mul(z, a);
DECREF(z); DECREF(z);
z = temp; z = temp;
if (z == NULL) if (z == NULL)
@ -901,7 +942,7 @@ long_pow(a, b)
bi >>= 1; bi >>= 1;
if (bi == 0 && i+1 == size_b) if (bi == 0 && i+1 == size_b)
break; break;
temp = (longobject *)long_mul(a, (object *)a); temp = (longobject *)long_mul(a, a);
DECREF(a); DECREF(a);
a = temp; a = temp;
if (a == NULL) { if (a == NULL) {
@ -923,8 +964,8 @@ long_invert(v)
{ {
/* Implement ~x as -(x+1) */ /* Implement ~x as -(x+1) */
longobject *x; longobject *x;
object *w; longobject *w;
w = newlongobject(1L); w = (longobject *)newlongobject(1L);
if (w == NULL) if (w == NULL)
return NULL; return NULL;
x = (longobject *) long_add(v, w); x = (longobject *) long_add(v, w);
@ -1098,7 +1139,9 @@ long_lshift(a, b)
#define MAX(x, y) ((x) < (y) ? (y) : (x)) #define MAX(x, y) ((x) < (y) ? (y) : (x))
#define MIN(x, y) ((x) > (y) ? (y) : (x)) #define MIN(x, y) ((x) > (y) ? (y) : (x))
static object *long_bitwise(a, op, b) static object *long_bitwise PROTO((longobject *, int, longobject *));
static object *
long_bitwise(a, op, b)
longobject *a; longobject *a;
int op; /* '&', '|', '^' */ int op; /* '&', '|', '^' */
longobject *b; longobject *b;
@ -1214,7 +1257,7 @@ static number_methods long_as_number = {
long_sub, /*nb_subtract*/ long_sub, /*nb_subtract*/
long_mul, /*nb_multiply*/ long_mul, /*nb_multiply*/
long_div, /*nb_divide*/ long_div, /*nb_divide*/
long_rem, /*nb_remainder*/ long_mod, /*nb_remainder*/
long_divmod, /*nb_divmod*/ long_divmod, /*nb_divmod*/
long_pow, /*nb_power*/ long_pow, /*nb_power*/
long_neg, /*nb_negative*/ long_neg, /*nb_negative*/