1
0
mirror of https://github.com/janet-lang/janet synced 2024-06-14 01:16:48 +00:00

All tests pass for compare.

This commit is contained in:
Mike Beller 2020-06-05 10:51:35 -04:00
parent 3e423722c6
commit a4178d4b3c
2 changed files with 74 additions and 39 deletions

View File

@ -197,10 +197,52 @@ static Janet cfun_it_u64_new(int32_t argc, Janet *argv) {
return janet_wrap_u64(janet_unwrap_u64(argv[0]));
}
static int64_t compare_double(double x, double y) {
// Code to support polymorphic comparison.
//
// int/u64 and int/s64 support a "compare" method that allows
// comparison to each other, and to Janet numbers, using the
// "compare" "compare<" ... functions.
//
// In the following code explicit casts are sometimes used to help
// make it clear when int/float conversions are happening.
//
static int64_t compare_double_double(double x, double y) {
return (x < y) ? -1 : ((x > y) ? 1 : 0);
}
static int64_t compare_int64_double(int64_t x, double y) {
if (isnan(y)) {
return 0; // clojure and python do this
} else if ((y > ((double) -MAX_INT_IN_DBL)) && (y < ((double) MAX_INT_IN_DBL))) {
double dx = (double) x;
return compare_double_double(dx, y);
} else if (y > ((double) INT64_MAX)) {
return -1;
} else if (y < ((double) INT64_MIN)) {
return 1;
} else {
int64_t yi = (int64_t) y;
return (x < yi) ? -1 : ((x > yi) ? 1 : 0);
}
}
static int64_t compare_uint64_double(uint64_t x, double y) {
if (isnan(y)) {
return 0; // clojure and python do this
} else if (y < 0) {
return 1;
} else if ((y >= 0) && (y < ((double) MAX_INT_IN_DBL))) {
double dx = (double) x;
return compare_double_double(dx, y);
} else if (y > ((double) UINT64_MAX)) {
return -1;
} else {
uint64_t yi = (uint64_t) y;
return (x < yi) ? -1 : ((x > yi) ? 1 : 0);
}
}
static Janet cfun_it_s64_compare(int32_t argc, Janet *argv) {
janet_fixarity(argc, 2);
if (janet_is_int(argv[0]) != JANET_INT_S64)
@ -211,19 +253,7 @@ static Janet cfun_it_s64_compare(int32_t argc, Janet *argv) {
break;
case JANET_NUMBER : {
double y = janet_unwrap_number(argv[1]);
if (isnan(y)) {
return janet_wrap_number(0); // per python compare function
} else if ((y > ((double) -MAX_INT_IN_DBL)) && (y < ((double) MAX_INT_IN_DBL))) {
double dx = (double) x;
return janet_wrap_number(compare_double(dx, y));
} else if (y > ((double) INT64_MAX)) {
return janet_wrap_number(1);
} else if (y < ((double) INT64_MIN)) {
return janet_wrap_number(-1);
} else {
int64_t yi = (int64_t) y;
return janet_wrap_number((x < yi) ? -1 : ((x > yi) ? 1 : 0));
}
return janet_wrap_number(compare_int64_double(x, y));
}
case JANET_ABSTRACT: {
void *abst = janet_unwrap_abstract(argv[1]);
@ -258,10 +288,7 @@ static Janet cfun_it_u64_compare(int32_t argc, Janet *argv) {
break;
case JANET_NUMBER : {
double y = round(janet_unwrap_number(argv[1]));
if (y < 0) // unsigned int x has to be greater
return janet_wrap_number(1);
double dx = round((double) x); //double trouble?
return janet_wrap_number(dx < y ? -1 : (dx > y ? 1 : 0));
return janet_wrap_number(compare_uint64_double(x, y));
}
case JANET_ABSTRACT: {
void *abst = janet_unwrap_abstract(argv[1]);

View File

@ -390,27 +390,35 @@
(def MAX_INT_64_STRING "9223372036854775807")
(def MAX_UINT_64_STRING "18446744073709551615")
(def MAX_INT_IN_DBL_STRING "9007199254740991")
(assert (= 0 (compare (int/u64 3) 3)) "compare number to int/u64")
(assert (= -1 (compare (int/u64 3) 4)) "compare number to int/u64 less")
(assert (= 0 (compare 3 (int/u64 3))) "compare number to int/u64")
(assert (= 1 (compare 4 (int/u64 3))) "compare number to int/u64 greater")
(assert (= 0 (compare (int/u64 3) (int/u64 3))) "compare int/u64 to int/u64")
(assert (= 1 (compare (int/u64 4) (int/u64 3))) "compare int/u64 to int/u64 greater")
(assert (= 0 (compare (int/s64 3) 3)) "compare number to int/s64")
(assert (= -1 (compare (int/s64 3) 4)) "compare number to int/s64 less")
(assert (= 0 (compare 3 (int/s64 3))) "compare number to int/s64")
(assert (= 1 (compare 4 (int/s64 3))) "compare number to int/s64 greater")
(assert (= 0 (compare (int/s64 3) (int/s64 3))) "compare int/s64 to int/s64")
(assert (= 1 (compare (int/s64 4) (int/s64 3))) "compare int/s64 to int/s64 greater")
(assert (= 0 (compare (int/u64 3) (int/s64 3))) "compare int/u64 to int/s64 (1)")
(assert (= -1 (compare (int/u64 3) (int/s64 4))) "compare int/u64 to int/s64 (2)")
(assert (= 1 (compare (int/u64 1) (int/s64 -1))) "compare int/u64 to int/s64 (3)")
(assert (= 1 (compare (int/s64 4) (int/u64 3))) "compare int/s64 to int/u64")
(assert (= -1 (compare (int/s64 -1) (int/u64 0))) "compare int/s64 to int/u64 negative")
(assert (= -1 (compare (int/s64 MAX_INT_64_STRING) (int/u64 MAX_UINT_64_STRING))) "compare big ints")
(assert (= 0 (compare (int/s64 MAX_INT_IN_DBL_STRING) (scan-number MAX_INT_IN_DBL_STRING))) "compare max int in double (1)")
(assert (= 0 (compare (int/u64 MAX_INT_IN_DBL_STRING) (scan-number MAX_INT_IN_DBL_STRING))) "compare max int in double (2)")
(assert (= 1 (compare (+ 1 (int/u64 MAX_INT_IN_DBL_STRING)) (scan-number MAX_INT_IN_DBL_STRING))) "compare max int in double (3)")
(let [
MAX_INT_64_STRING "9223372036854775807"
MAX_UINT_64_STRING "18446744073709551615"
MAX_INT_IN_DBL_STRING "9007199254740991"
NAN (math/log -1)
INF (/ 1 0)
MINUS_INF (/ -1 0)
compare-poly-tests
[
[(int/s64 3) (int/u64 3) 0]
[(int/s64 -3) (int/u64 3) -1]
[(int/s64 3) (int/u64 2) 1]
[(int/s64 3) 3 0] [(int/s64 3) 4 -1] [(int/s64 3) -9 1]
[(int/u64 3) 3 0] [(int/u64 3) 4 -1] [(int/u64 3) -9 1]
[3 (int/s64 3) 0] [3 (int/s64 4) -1] [3 (int/s64 -5) 1]
[3 (int/u64 3) 0] [3 (int/u64 4) -1] [3 (int/u64 2) 1]
[(int/s64 MAX_INT_64_STRING) (int/u64 MAX_UINT_64_STRING) -1]
[(int/s64 MAX_INT_IN_DBL_STRING) (scan-number MAX_INT_IN_DBL_STRING) 0]
[(int/u64 MAX_INT_IN_DBL_STRING) (scan-number MAX_INT_IN_DBL_STRING) 0]
[(+ 1 (int/u64 MAX_INT_IN_DBL_STRING)) (scan-number MAX_INT_IN_DBL_STRING) 1]
[(int/s64 0) INF -1] [(int/u64 0) INF -1]
[MINUS_INF (int/u64 0) -1] [MINUS_INF (int/s64 0) -1]
[(int/s64 1) NAN 0] [NAN (int/u64 1) 0]
]]
(each [x y c] compare-poly-tests
(assert (= c (compare x y)) (string/format "compare polymorphic %q %q %d" x y c)))
)
(end-suite)