mirror of
https://gitlab.com/embeddable-common-lisp/ecl.git
synced 2026-01-04 08:20:45 -08:00
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:
parent
b147bb43e8
commit
c5ec810687
8 changed files with 61 additions and 29 deletions
|
|
@ -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 *
|
||||
*************************************/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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}};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue