Division by integer 0 signal a DIVIDE-BY-ZERO error. (- (- MOST-NEGATIVE-FIXNUM)) now works. Fixed CEILING and FLOOR with arguments MOST-NEGATIVE-FIXNUM (- MOST-NEGATIVE-FIXNUM). (EXPT x y) now returns 1 coerced to the right type when (ZEROP y)=>T.

This commit is contained in:
jjgarcia 2003-12-09 09:34:33 +00:00
parent b147bb43e8
commit c5ec810687
8 changed files with 61 additions and 29 deletions

View file

@ -228,6 +228,12 @@ FEtype_error_symbol(cl_object obj)
FEwrong_type_argument(@'symbol', obj);
}
void
FEdivision_by_zero(void)
{
cl_error(3, @'division-by-zero', @':operation', @'/');
}
/*************************************
* Errors generated by the C library *
*************************************/

View file

@ -519,7 +519,7 @@ cl_conjugate(cl_object c)
cl_object
number_negate(cl_object x)
{
cl_object z, z1;
cl_object z, z1;
switch (type_of(x)) {
case t_fixnum: {
@ -536,7 +536,7 @@ number_negate(cl_object x)
case t_bignum:
z = big_register0_get();
mpz_neg(z->big.big_num, x->big.big_num);
return(big_register_copy(z));
return big_register_normalize(z);
case t_ratio:
z1 = number_negate(x->ratio.num);
@ -589,6 +589,8 @@ number_divide(cl_object x, cl_object y)
case t_bignum:
switch (type_of(y)) {
case t_fixnum:
if (y == MAKE_FIXNUM(0))
FEdivision_by_zero();
case t_bignum:
if (number_minusp(y) == TRUE) {
x = number_negate(x);
@ -612,6 +614,8 @@ number_divide(cl_object x, cl_object y)
case t_ratio:
switch (type_of(y)) {
case t_fixnum:
if (y == MAKE_FIXNUM(0))
FEdivision_by_zero();
case t_bignum:
z = number_times(x->ratio.den, y);
z = make_ratio(x->ratio.num, z);
@ -633,6 +637,8 @@ number_divide(cl_object x, cl_object y)
case t_shortfloat:
switch (type_of(y)) {
case t_fixnum:
if (y == MAKE_FIXNUM(0))
FEdivision_by_zero();
return make_shortfloat(sf(x) / fix(y));
case t_bignum:
case t_ratio:
@ -649,6 +655,8 @@ number_divide(cl_object x, cl_object y)
case t_longfloat:
switch (type_of(y)) {
case t_fixnum:
if (y == MAKE_FIXNUM(0))
FEdivision_by_zero();
return make_longfloat(lf(x) / fix(y));
case t_bignum:
case t_ratio:
@ -696,8 +704,11 @@ integer_divide(cl_object x, cl_object y)
tx = type_of(x);
ty = type_of(y);
if (tx == t_fixnum) {
if (ty == t_fixnum)
if (ty == t_fixnum) {
if (y == MAKE_FIXNUM(0))
FEdivision_by_zero();
return MAKE_FIXNUM(fix(x) / fix(y));
}
if (ty == t_bignum) {
/* The only number "x" which can be a bignum and be
* as large as "-x" is -MOST_NEGATIVE_FIXNUM. However

View file

@ -206,13 +206,18 @@ floor2(cl_object x, cl_object y)
break;
}
case t_bignum: { /* FIX / BIG */
if (number_plusp(x) != number_plusp(y)) {
VALUES(0) = MAKE_FIXNUM(-1);
VALUES(1) = number_plus(y, x);
} else {
VALUES(0) = MAKE_FIXNUM(0);
VALUES(1) = x;
}
/* We must perform the division because there is the
* pathological case
* x = MOST_NEGATIVE_FIXNUM
* y = - MOST_NEGATIVE_FIXNUM
*/
cl_object q = big_register0_get();
cl_object r = big_register1_get();
cl_object j = big_register2_get();
mpz_set_si(j->big.big_num, fix(x));
mpz_fdiv_qr(q->big.big_num, r->big.big_num, y->big.big_num, j->big.big_num);
VALUES(0) = big_register_normalize(q);
VALUES(1) = big_register_normalize(r);
break;
}
case t_ratio: /* FIX / RAT */
@ -380,13 +385,18 @@ ceiling2(cl_object x, cl_object y)
break;
}
case t_bignum: { /* FIX / BIG */
if (number_plusp(x) != number_plusp(y)) {
VALUES(0) = MAKE_FIXNUM(0);
VALUES(1) = x;
} else {
VALUES(0) = MAKE_FIXNUM(1);
VALUES(1) = number_minus(x, y);
}
/* We must perform the division because there is the
* pathological case
* x = MOST_NEGATIVE_FIXNUM
* y = - MOST_NEGATIVE_FIXNUM
*/
cl_object q = big_register0_get();
cl_object r = big_register1_get();
cl_object j = big_register2_get();
mpz_set_si(j->big.big_num, fix(x));
mpz_cdiv_qr(q->big.big_num, r->big.big_num, y->big.big_num, j->big.big_num);
VALUES(0) = big_register_normalize(q);
VALUES(1) = big_register_normalize(r);
break;
}
case t_ratio: /* FIX / RAT */

View file

@ -93,21 +93,22 @@ cl_expt(cl_object x, cl_object y)
cl_object z;
if (number_zerop(y)) {
switch (type_of(y)) {
case t_fixnum: case t_bignum: case t_ratio:
/* INV: The most specific numeric types come first. */
cl_type tx = type_of(x);
ty = type_of(y);
switch ((ty > tx)? ty : tx) {
case t_fixnum:
case t_bignum:
case t_ratio:
return1(MAKE_FIXNUM(1));
case t_shortfloat:
return1(make_shortfloat(1.0));
case t_longfloat:
return1(make_longfloat(1.0));
case t_complex:
z = cl_expt(x->complex.real, y);
z = cl_float(2, MAKE_FIXNUM(1), x->complex.real);
z = make_complex(z, MAKE_FIXNUM(0));
return1(z);
default:
FEtype_error_number(x);
}

View file

@ -86,11 +86,10 @@ make_ratio(cl_object num, cl_object den)
{
cl_object g, r;
if (number_zerop(den))
FEerror("Zero denominator.", 0);
if (number_zerop(num))
return(MAKE_FIXNUM(0));
if (den == MAKE_FIXNUM(1))
/* INV: the arguments NUM & DEN are integers */
if (den == MAKE_FIXNUM(0))
FEdivision_by_zero();
if (num == MAKE_FIXNUM(0) || den == MAKE_FIXNUM(1))
return(num);
if (number_minusp(den)) {
num = number_negate(num);

View file

@ -1378,6 +1378,8 @@ cl_symbols[] = {
{SYS_ "STEPPER", SI_ORDINARY, OBJNULL, -1, OBJNULL},
{SYS_ "COERCE-TO-FILENAME", SI_ORDINARY, si_coerce_to_filename, 1, OBJNULL},
{KEY_ "OPERATION", KEYWORD, NULL, -1, OBJNULL},
/* Tag for end of list */
{NULL, CL_ORDINARY, NULL, -1, OBJNULL}};

View file

@ -1396,6 +1396,7 @@ extern void FEtype_error_stream(cl_object x) __attribute__((noreturn));
extern void FEcircular_list(cl_object x) __attribute__((noreturn));
extern void FEtype_error_index(cl_object seq, cl_object ndx) __attribute__((noreturn));
extern void FEtype_error_string(cl_object x) __attribute__((noreturn));
extern void FEdivision_by_zero(void) __attribute__((noreturn));
/* unixfsys.c */

View file

@ -485,6 +485,8 @@ union cl_lispunion {
typedef enum {
t_cons = 0,
t_start = 0,
/* The most specific numeric types come first. Assumed by
some routines, like cl_expt */
t_fixnum, /* 1 immediate fixnum */
t_character, /* 2 immediate character */
t_bignum = 4, /* 4 */