making = a builtin
fixing = and eqv? to work properly on NaNs fixing other comparison predicates to be consistent
This commit is contained in:
parent
81641a2240
commit
36a209cd5f
|
@ -17,7 +17,7 @@
|
||||||
:cons :list :car :cdr :set-car! :set-cdr!
|
:cons :list :car :cdr :set-car! :set-cdr!
|
||||||
:eval :apply
|
:eval :apply
|
||||||
|
|
||||||
:+ :- :* :/ :< :compare
|
:+ :- :* :/ := :< :compare
|
||||||
|
|
||||||
:vector :aref :aset! :for
|
:vector :aref :aset! :for
|
||||||
|
|
||||||
|
@ -40,7 +40,8 @@
|
||||||
:set-cdr! 2 :eval 1
|
:set-cdr! 2 :eval 1
|
||||||
:apply 2 :< 2
|
:apply 2 :< 2
|
||||||
:for 3 :compare 2
|
:for 3 :compare 2
|
||||||
:aref 2 :aset! 3))
|
:aref 2 :aset! 3
|
||||||
|
:= 2))
|
||||||
|
|
||||||
(define 1/Instructions (table.invert Instructions))
|
(define 1/Instructions (table.invert Instructions))
|
||||||
|
|
||||||
|
|
|
@ -34,17 +34,23 @@ static void eq_union(htable_t *table, value_t a, value_t b,
|
||||||
}
|
}
|
||||||
|
|
||||||
// a is a fixnum, b is a cprim
|
// a is a fixnum, b is a cprim
|
||||||
static value_t compare_num_cprim(value_t a, value_t b, int eq)
|
static value_t compare_num_cprim(value_t a, value_t b, int eq, int swap)
|
||||||
{
|
{
|
||||||
cprim_t *bcp = (cprim_t*)ptr(b);
|
cprim_t *bcp = (cprim_t*)ptr(b);
|
||||||
numerictype_t bt = cp_numtype(bcp);
|
numerictype_t bt = cp_numtype(bcp);
|
||||||
fixnum_t ia = numval(a);
|
fixnum_t ia = numval(a);
|
||||||
void *bptr = cp_data(bcp);
|
void *bptr = cp_data(bcp);
|
||||||
if (cmp_eq(&ia, T_FIXNUM, bptr, bt))
|
if (cmp_eq(&ia, T_FIXNUM, bptr, bt, 1))
|
||||||
return fixnum(0);
|
return fixnum(0);
|
||||||
if (eq) return fixnum(1);
|
if (eq) return fixnum(1);
|
||||||
|
if (swap) {
|
||||||
|
if (cmp_lt(bptr, bt, &ia, T_FIXNUM))
|
||||||
|
return fixnum(-1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
if (cmp_lt(&ia, T_FIXNUM, bptr, bt))
|
if (cmp_lt(&ia, T_FIXNUM, bptr, bt))
|
||||||
return fixnum(-1);
|
return fixnum(-1);
|
||||||
|
}
|
||||||
return fixnum(1);
|
return fixnum(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +93,7 @@ static value_t bounded_compare(value_t a, value_t b, int bound, int eq)
|
||||||
return (numval(a) < numval(b)) ? fixnum(-1) : fixnum(1);
|
return (numval(a) < numval(b)) ? fixnum(-1) : fixnum(1);
|
||||||
}
|
}
|
||||||
if (iscprim(b)) {
|
if (iscprim(b)) {
|
||||||
return compare_num_cprim(a, b, eq);
|
return compare_num_cprim(a, b, eq, 0);
|
||||||
}
|
}
|
||||||
return fixnum(-1);
|
return fixnum(-1);
|
||||||
case TAG_SYM:
|
case TAG_SYM:
|
||||||
|
@ -104,7 +110,7 @@ static value_t bounded_compare(value_t a, value_t b, int bound, int eq)
|
||||||
cprim_t *acp=(cprim_t*)ptr(a), *bcp=(cprim_t*)ptr(b);
|
cprim_t *acp=(cprim_t*)ptr(a), *bcp=(cprim_t*)ptr(b);
|
||||||
numerictype_t at=cp_numtype(acp), bt=cp_numtype(bcp);
|
numerictype_t at=cp_numtype(acp), bt=cp_numtype(bcp);
|
||||||
void *aptr=cp_data(acp), *bptr=cp_data(bcp);
|
void *aptr=cp_data(acp), *bptr=cp_data(bcp);
|
||||||
if (cmp_eq(aptr, at, bptr, bt))
|
if (cmp_eq(aptr, at, bptr, bt, 1))
|
||||||
return fixnum(0);
|
return fixnum(0);
|
||||||
if (eq) return fixnum(1);
|
if (eq) return fixnum(1);
|
||||||
if (cmp_lt(aptr, at, bptr, bt))
|
if (cmp_lt(aptr, at, bptr, bt))
|
||||||
|
@ -112,7 +118,7 @@ static value_t bounded_compare(value_t a, value_t b, int bound, int eq)
|
||||||
return fixnum(1);
|
return fixnum(1);
|
||||||
}
|
}
|
||||||
else if (isfixnum(b)) {
|
else if (isfixnum(b)) {
|
||||||
return fixnum(-numval(compare_num_cprim(b, a, eq)));
|
return compare_num_cprim(b, a, eq, 1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TAG_CVALUE:
|
case TAG_CVALUE:
|
||||||
|
|
|
@ -68,7 +68,7 @@ static char *builtin_names[] =
|
||||||
"eval", "apply",
|
"eval", "apply",
|
||||||
|
|
||||||
// arithmetic
|
// arithmetic
|
||||||
"+", "-", "*", "/", "<", "compare",
|
"+", "-", "*", "/", "=", "<", "compare",
|
||||||
|
|
||||||
// sequences
|
// sequences
|
||||||
"vector", "aref", "aset!", "for",
|
"vector", "aref", "aset!", "for",
|
||||||
|
@ -649,6 +649,33 @@ int isnumber(value_t v)
|
||||||
return (isfixnum(v) || iscprim(v));
|
return (isfixnum(v) || iscprim(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int numeric_equals(value_t a, value_t b)
|
||||||
|
{
|
||||||
|
value_t tmp;
|
||||||
|
if (isfixnum(b)) {
|
||||||
|
tmp=a; a=b; b=tmp;
|
||||||
|
}
|
||||||
|
void *aptr, *bptr;
|
||||||
|
numerictype_t at, bt;
|
||||||
|
if (!iscprim(b)) type_error("=", "number", b);
|
||||||
|
cprim_t *cp = (cprim_t*)ptr(b);
|
||||||
|
fixnum_t fv;
|
||||||
|
bt = cp_numtype(cp);
|
||||||
|
bptr = cp_data(cp);
|
||||||
|
if (isfixnum(a)) {
|
||||||
|
fv = numval(a);
|
||||||
|
at = T_FIXNUM;
|
||||||
|
aptr = &fv;
|
||||||
|
}
|
||||||
|
else if (iscprim(a)) {
|
||||||
|
cp = (cprim_t*)ptr(a);
|
||||||
|
at = cp_numtype(cp);
|
||||||
|
aptr = cp_data(cp);
|
||||||
|
}
|
||||||
|
else type_error("=", "number", a);
|
||||||
|
return cmp_eq(aptr, at, bptr, bt, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// read -----------------------------------------------------------------------
|
// read -----------------------------------------------------------------------
|
||||||
|
|
||||||
#include "read.c"
|
#include "read.c"
|
||||||
|
@ -1289,6 +1316,16 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail, uint32_t envsz)
|
||||||
argcount("compare", nargs, 2);
|
argcount("compare", nargs, 2);
|
||||||
v = compare(Stack[SP-2], Stack[SP-1]);
|
v = compare(Stack[SP-2], Stack[SP-1]);
|
||||||
break;
|
break;
|
||||||
|
case F_NUMEQ:
|
||||||
|
argcount("=", nargs, 2);
|
||||||
|
v = Stack[SP-2]; e = Stack[SP-1];
|
||||||
|
if (bothfixnums(v, e)) {
|
||||||
|
v = (v == e) ? FL_T : FL_F;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
v = numeric_equals(v, e) ? FL_T : FL_F;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case F_LT:
|
case F_LT:
|
||||||
argcount("<", nargs, 2);
|
argcount("<", nargs, 2);
|
||||||
if (bothfixnums(Stack[SP-2], Stack[SP-1])) {
|
if (bothfixnums(Stack[SP-2], Stack[SP-1])) {
|
||||||
|
@ -1857,6 +1894,17 @@ static value_t apply_cl(uint32_t nargs)
|
||||||
PUSH(v);
|
PUSH(v);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case F_NUMEQ:
|
||||||
|
v = Stack[SP-2]; e = Stack[SP-1];
|
||||||
|
if (bothfixnums(v, e)) {
|
||||||
|
v = (v == e) ? FL_T : FL_F;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
v = numeric_equals(v, e) ? FL_T : FL_F;
|
||||||
|
}
|
||||||
|
POPN(1);
|
||||||
|
Stack[SP-1] = v;
|
||||||
|
break;
|
||||||
case OP_LT:
|
case OP_LT:
|
||||||
if (bothfixnums(Stack[SP-2], Stack[SP-1])) {
|
if (bothfixnums(Stack[SP-2], Stack[SP-1])) {
|
||||||
v = (numval(Stack[SP-2]) < numval(Stack[SP-1])) ? FL_T : FL_F;
|
v = (numval(Stack[SP-2]) < numval(Stack[SP-1])) ? FL_T : FL_F;
|
||||||
|
|
|
@ -125,7 +125,7 @@ enum {
|
||||||
|
|
||||||
F_CONS, F_LIST, F_CAR, F_CDR, F_SETCAR, F_SETCDR,
|
F_CONS, F_LIST, F_CAR, F_CDR, F_SETCAR, F_SETCDR,
|
||||||
F_EVAL, F_APPLY,
|
F_EVAL, F_APPLY,
|
||||||
F_ADD, F_SUB, F_MUL, F_DIV, F_LT, F_COMPARE,
|
F_ADD, F_SUB, F_MUL, F_DIV, F_NUMEQ, F_LT, F_COMPARE,
|
||||||
|
|
||||||
F_VECTOR, F_AREF, F_ASET, F_FOR,
|
F_VECTOR, F_AREF, F_ASET, F_FOR,
|
||||||
F_TRUE, F_FALSE, F_NIL,
|
F_TRUE, F_FALSE, F_NIL,
|
||||||
|
|
|
@ -12,7 +12,7 @@ enum {
|
||||||
OP_CONS, OP_LIST, OP_CAR, OP_CDR, OP_SETCAR, OP_SETCDR,
|
OP_CONS, OP_LIST, OP_CAR, OP_CDR, OP_SETCAR, OP_SETCDR,
|
||||||
OP_EVAL, OP_APPLY,
|
OP_EVAL, OP_APPLY,
|
||||||
|
|
||||||
OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_LT, OP_COMPARE,
|
OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_NUMEQ, OP_LT, OP_COMPARE,
|
||||||
|
|
||||||
OP_VECTOR, OP_AREF, OP_ASET, OP_FOR,
|
OP_VECTOR, OP_AREF, OP_ASET, OP_FOR,
|
||||||
|
|
||||||
|
|
|
@ -86,11 +86,10 @@
|
||||||
((eqv? (caar lst) item) (car lst))
|
((eqv? (caar lst) item) (car lst))
|
||||||
(#t (assv item (cdr lst)))))
|
(#t (assv item (cdr lst)))))
|
||||||
|
|
||||||
(define = eqv?)
|
(define (/= a b) (not (= a b)))
|
||||||
(define (/= a b) (not (eqv? a b)))
|
|
||||||
(define (> a b) (< b a))
|
(define (> a b) (< b a))
|
||||||
(define (<= a b) (not (< b a)))
|
(define (<= a b) (or (< a b) (= a b)))
|
||||||
(define (>= a b) (not (< a b)))
|
(define (>= a b) (or (< b a) (= a b)))
|
||||||
(define (negative? x) (< x 0))
|
(define (negative? x) (< x 0))
|
||||||
(define (zero? x) (= x 0))
|
(define (zero? x) (= x 0))
|
||||||
(define (positive? x) (> x 0))
|
(define (positive? x) (> x 0))
|
||||||
|
|
|
@ -171,7 +171,6 @@ value_t fl_table_foldl(value_t *args, uint32_t nargs)
|
||||||
htable_t *h = totable(args[2], "table.foldl");
|
htable_t *h = totable(args[2], "table.foldl");
|
||||||
size_t i, n = h->size;
|
size_t i, n = h->size;
|
||||||
void **table = h->table;
|
void **table = h->table;
|
||||||
value_t c;
|
|
||||||
for(i=0; i < n; i+=2) {
|
for(i=0; i < n; i+=2) {
|
||||||
if (table[i+1] != HT_NOTFOUND) {
|
if (table[i+1] != HT_NOTFOUND) {
|
||||||
args[1] = applyn(3, args[0],
|
args[1] = applyn(3, args[0],
|
||||||
|
|
|
@ -69,6 +69,20 @@
|
||||||
|
|
||||||
(assert (equal (string 'sym #byte(65) #wchar(945) "blah") "symA\u03B1blah"))
|
(assert (equal (string 'sym #byte(65) #wchar(945) "blah") "symA\u03B1blah"))
|
||||||
|
|
||||||
|
; NaNs
|
||||||
|
(assert (equal? +nan.0 +nan.0))
|
||||||
|
(assert (not (= +nan.0 +nan.0)))
|
||||||
|
(assert (not (= +nan.0 -nan.0)))
|
||||||
|
(assert (equal? (< +nan.0 3) (> 3 +nan.0)))
|
||||||
|
(assert (equal? (< +nan.0 (double 3)) (> (double 3) +nan.0)))
|
||||||
|
(assert (equal? (< +nan.0 3) (> (double 3) +nan.0)))
|
||||||
|
(assert (equal? (< +nan.0 (double 3)) (> 3 +nan.0)))
|
||||||
|
(assert (equal? (< +nan.0 3) (< +nan.0 (double 3))))
|
||||||
|
(assert (equal? (> +nan.0 3) (> +nan.0 (double 3))))
|
||||||
|
(assert (equal? (< 3 +nan.0) (> +nan.0 (double 3))))
|
||||||
|
(assert (equal? (> 3 +nan.0) (> (double 3) +nan.0)))
|
||||||
|
(assert (not (>= +nan.0 +nan.0)))
|
||||||
|
|
||||||
; this crashed once
|
; this crashed once
|
||||||
(for 1 10 (lambda (i) 0))
|
(for 1 10 (lambda (i) 0))
|
||||||
|
|
||||||
|
|
|
@ -116,6 +116,7 @@ typedef u_ptrint_t uptrint_t;
|
||||||
#define LABS(n) (((n)^((n)>>(NBITS-1))) - ((n)>>(NBITS-1)))
|
#define LABS(n) (((n)^((n)>>(NBITS-1))) - ((n)>>(NBITS-1)))
|
||||||
#define NBABS(n,nb) (((n)^((n)>>((nb)-1))) - ((n)>>((nb)-1)))
|
#define NBABS(n,nb) (((n)^((n)>>((nb)-1))) - ((n)>>((nb)-1)))
|
||||||
#define DFINITE(d) (((*(int64_t*)&(d))&0x7ff0000000000000LL)!=0x7ff0000000000000LL)
|
#define DFINITE(d) (((*(int64_t*)&(d))&0x7ff0000000000000LL)!=0x7ff0000000000000LL)
|
||||||
|
#define DNAN(d) (((*(int64_t*)&(d))&0x7ff8000000000000LL)==0x7ff8000000000000LL)
|
||||||
|
|
||||||
extern double D_PNAN;
|
extern double D_PNAN;
|
||||||
extern double D_NNAN;
|
extern double D_NNAN;
|
||||||
|
|
|
@ -93,11 +93,11 @@ void llt_init()
|
||||||
ios_init_stdstreams();
|
ios_init_stdstreams();
|
||||||
|
|
||||||
D_PNAN = strtod("+NaN",NULL);
|
D_PNAN = strtod("+NaN",NULL);
|
||||||
D_NNAN = strtod("-NaN",NULL);
|
D_NNAN = -strtod("+NaN",NULL);
|
||||||
D_PINF = strtod("+Inf",NULL);
|
D_PINF = strtod("+Inf",NULL);
|
||||||
D_NINF = strtod("-Inf",NULL);
|
D_NINF = strtod("-Inf",NULL);
|
||||||
F_PNAN = strtof("+NaN",NULL);
|
F_PNAN = strtof("+NaN",NULL);
|
||||||
F_NNAN = strtof("-NaN",NULL);
|
F_NNAN = -strtof("+NaN",NULL);
|
||||||
F_PINF = strtof("+Inf",NULL);
|
F_PINF = strtof("+Inf",NULL);
|
||||||
F_NINF = strtof("-Inf",NULL);
|
F_NINF = strtof("-Inf",NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -235,16 +235,21 @@ int cmp_lt(void *a, numerictype_t atag, void *b, numerictype_t btag)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cmp_eq(void *a, numerictype_t atag, void *b, numerictype_t btag)
|
int cmp_eq(void *a, numerictype_t atag, void *b, numerictype_t btag,
|
||||||
|
int equalnans)
|
||||||
{
|
{
|
||||||
if (atag==btag)
|
if (atag==btag && !equalnans)
|
||||||
return cmp_same_eq(a, b, atag);
|
return cmp_same_eq(a, b, atag);
|
||||||
|
|
||||||
double da = conv_to_double(a, atag);
|
double da = conv_to_double(a, atag);
|
||||||
double db = conv_to_double(b, btag);
|
double db = conv_to_double(b, btag);
|
||||||
|
|
||||||
if ((int)atag >= T_FLOAT && (int)btag >= T_FLOAT)
|
if ((int)atag >= T_FLOAT && (int)btag >= T_FLOAT) {
|
||||||
|
if (equalnans && DNAN(da)) {
|
||||||
|
return *(uint64_t*)&da == *(uint64_t*)&db;
|
||||||
|
}
|
||||||
return (da == db);
|
return (da == db);
|
||||||
|
}
|
||||||
|
|
||||||
if (da != db)
|
if (da != db)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -339,8 +344,8 @@ void test_operators()
|
||||||
assert(cmp_lt(&d, T_DOUBLE, &i64, T_INT64));
|
assert(cmp_lt(&d, T_DOUBLE, &i64, T_INT64));
|
||||||
assert(!cmp_lt(&i64, T_INT64, &d, T_DOUBLE));
|
assert(!cmp_lt(&i64, T_INT64, &d, T_DOUBLE));
|
||||||
|
|
||||||
assert(!cmp_eq(&d, T_DOUBLE, &i64, T_INT64));
|
assert(!cmp_eq(&d, T_DOUBLE, &i64, T_INT64, 0));
|
||||||
i64 = DBL_MAXINT;
|
i64 = DBL_MAXINT;
|
||||||
assert(cmp_eq(&d, T_DOUBLE, &i64, T_INT64));
|
assert(cmp_eq(&d, T_DOUBLE, &i64, T_INT64, 0));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -75,7 +75,8 @@ uint32_t conv_to_uint32(void *data, numerictype_t tag);
|
||||||
int cmp_same_lt(void *a, void *b, numerictype_t tag);
|
int cmp_same_lt(void *a, void *b, numerictype_t tag);
|
||||||
int cmp_same_eq(void *a, void *b, numerictype_t tag);
|
int cmp_same_eq(void *a, void *b, numerictype_t tag);
|
||||||
int cmp_lt(void *a, numerictype_t atag, void *b, numerictype_t btag);
|
int cmp_lt(void *a, numerictype_t atag, void *b, numerictype_t btag);
|
||||||
int cmp_eq(void *a, numerictype_t atag, void *b, numerictype_t btag);
|
int cmp_eq(void *a, numerictype_t atag, void *b, numerictype_t btag,
|
||||||
|
int equalnans);
|
||||||
|
|
||||||
#ifdef ARCH_X86_64
|
#ifdef ARCH_X86_64
|
||||||
# define LEGACY_REGS "=Q"
|
# define LEGACY_REGS "=Q"
|
||||||
|
|
Loading…
Reference in New Issue