fix division and modulo giving incorrect results

cvs
Slava Pestov 2004-08-27 03:05:48 +00:00
parent 39779666a3
commit 8b8741d262
5 changed files with 13 additions and 28 deletions

View File

@ -23,3 +23,4 @@ unit-test
[ 1/268435456 ] [ -1 -268435456 >fixnum / ] unit-test [ 1/268435456 ] [ -1 -268435456 >fixnum / ] unit-test
[ 0 ] [ -1 -268435456 >fixnum /i ] unit-test [ 0 ] [ -1 -268435456 >fixnum /i ] unit-test
[ 0 -1 ] [ -1 -268435456 >fixnum /mod ] unit-test [ 0 -1 ] [ -1 -268435456 >fixnum /mod ] unit-test
[ 14355 ] [ 1591517158873146351817850880000000 32769 mod ] unit-test

View File

@ -120,10 +120,7 @@ CELL divide_bignum(ARRAY* x, ARRAY* y)
CELL divint_bignum(ARRAY* x, ARRAY* y) CELL divint_bignum(ARRAY* x, ARRAY* y)
{ {
ARRAY* q = s48_bignum_quotient(x,y); return tag_object(s48_bignum_quotient(x,y));
if(q == NULL)
raise(SIGFPE);
return tag_object(q);
} }
CELL divfloat_bignum(ARRAY* x, ARRAY* y) CELL divfloat_bignum(ARRAY* x, ARRAY* y)
@ -135,20 +132,15 @@ CELL divfloat_bignum(ARRAY* x, ARRAY* y)
CELL divmod_bignum(ARRAY* x, ARRAY* y) CELL divmod_bignum(ARRAY* x, ARRAY* y)
{ {
ARRAY* q; ARRAY *q, *r;
ARRAY* r; s48_bignum_divide(x,y,&q,&r);
if(s48_bignum_divide(x,y,&q,&r))
raise(SIGFPE);
dpush(tag_object(q)); dpush(tag_object(q));
return tag_object(r); return tag_object(r);
} }
CELL mod_bignum(ARRAY* x, ARRAY* y) CELL mod_bignum(ARRAY* x, ARRAY* y)
{ {
ARRAY* r = s48_bignum_remainder(x,y); return tag_object(s48_bignum_remainder(x,y));
if(r == NULL)
raise(SIGFPE);
return tag_object(r);
} }
CELL and_bignum(ARRAY* x, ARRAY* y) CELL and_bignum(ARRAY* x, ARRAY* y)

View File

@ -177,12 +177,15 @@ s48_bignum_multiply(bignum_type x, bignum_type y)
return (bignum_multiply_unsigned (x, y, negative_p)); return (bignum_multiply_unsigned (x, y, negative_p));
} }
int void
bignum_divide(bignum_type numerator, bignum_type denominator, s48_bignum_divide(bignum_type numerator, bignum_type denominator,
bignum_type * quotient, bignum_type * remainder) bignum_type * quotient, bignum_type * remainder)
{ {
if (BIGNUM_ZERO_P (denominator)) if (BIGNUM_ZERO_P (denominator))
return (1); {
raise(SIGFPE);
return;
}
if (BIGNUM_ZERO_P (numerator)) if (BIGNUM_ZERO_P (numerator))
{ {
(*quotient) = (BIGNUM_MAYBE_COPY (numerator)); (*quotient) = (BIGNUM_MAYBE_COPY (numerator));
@ -244,15 +247,6 @@ bignum_divide(bignum_type numerator, bignum_type denominator,
} }
} }
} }
return (0);
}
int
s48_bignum_divide(bignum_type numerator, bignum_type denominator,
void* quotient, void * remainder)
{
return bignum_divide(numerator, denominator,
(bignum_type *)quotient, (bignum_type *)remainder);
} }
bignum_type bignum_type

View File

@ -60,8 +60,6 @@ bignum_type s48_bignum_add(bignum_type, bignum_type);
bignum_type s48_bignum_subtract(bignum_type, bignum_type); bignum_type s48_bignum_subtract(bignum_type, bignum_type);
bignum_type s48_bignum_negate(bignum_type); bignum_type s48_bignum_negate(bignum_type);
bignum_type s48_bignum_multiply(bignum_type, bignum_type); bignum_type s48_bignum_multiply(bignum_type, bignum_type);
int s48_bignum_divide(bignum_type numerator, bignum_type denominator,
void * quotient, void * remainder);
bignum_type s48_bignum_quotient(bignum_type, bignum_type); bignum_type s48_bignum_quotient(bignum_type, bignum_type);
bignum_type s48_bignum_remainder(bignum_type, bignum_type); bignum_type s48_bignum_remainder(bignum_type, bignum_type);
bignum_type s48_long_to_bignum(long); bignum_type s48_long_to_bignum(long);

View File

@ -42,8 +42,8 @@ MIT in each case. */
definition is `CHAR_BIT', which is defined in the Ansi C header definition is `CHAR_BIT', which is defined in the Ansi C header
file "limits.h". */ file "limits.h". */
typedef CELL bignum_digit_type; typedef long bignum_digit_type;
typedef CELL bignum_length_type; typedef long bignum_length_type;
/* BIGNUM_ALLOCATE allocates a (length + 1)-element array of /* BIGNUM_ALLOCATE allocates a (length + 1)-element array of
`bignum_digit_type'; deallocation is the responsibility of the `bignum_digit_type'; deallocation is the responsibility of the