1
0
mirror of https://github.com/janet-lang/janet synced 2024-09-29 15:30:41 +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])); 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); 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) { static Janet cfun_it_s64_compare(int32_t argc, Janet *argv) {
janet_fixarity(argc, 2); janet_fixarity(argc, 2);
if (janet_is_int(argv[0]) != JANET_INT_S64) 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; break;
case JANET_NUMBER : { case JANET_NUMBER : {
double y = janet_unwrap_number(argv[1]); double y = janet_unwrap_number(argv[1]);
if (isnan(y)) { return janet_wrap_number(compare_int64_double(x, 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));
}
} }
case JANET_ABSTRACT: { case JANET_ABSTRACT: {
void *abst = janet_unwrap_abstract(argv[1]); void *abst = janet_unwrap_abstract(argv[1]);
@ -258,10 +288,7 @@ static Janet cfun_it_u64_compare(int32_t argc, Janet *argv) {
break; break;
case JANET_NUMBER : { case JANET_NUMBER : {
double y = round(janet_unwrap_number(argv[1])); double y = round(janet_unwrap_number(argv[1]));
if (y < 0) // unsigned int x has to be greater return janet_wrap_number(compare_uint64_double(x, y));
return janet_wrap_number(1);
double dx = round((double) x); //double trouble?
return janet_wrap_number(dx < y ? -1 : (dx > y ? 1 : 0));
} }
case JANET_ABSTRACT: { case JANET_ABSTRACT: {
void *abst = janet_unwrap_abstract(argv[1]); void *abst = janet_unwrap_abstract(argv[1]);

View File

@ -390,27 +390,35 @@
(def MAX_INT_64_STRING "9223372036854775807") (def MAX_INT_64_STRING "9223372036854775807")
(def MAX_UINT_64_STRING "18446744073709551615") (def MAX_UINT_64_STRING "18446744073709551615")
(def MAX_INT_IN_DBL_STRING "9007199254740991") (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") (let [
(assert (= 0 (compare 3 (int/u64 3))) "compare number to int/u64") MAX_INT_64_STRING "9223372036854775807"
(assert (= 1 (compare 4 (int/u64 3))) "compare number to int/u64 greater") MAX_UINT_64_STRING "18446744073709551615"
(assert (= 0 (compare (int/u64 3) (int/u64 3))) "compare int/u64 to int/u64") MAX_INT_IN_DBL_STRING "9007199254740991"
(assert (= 1 (compare (int/u64 4) (int/u64 3))) "compare int/u64 to int/u64 greater") NAN (math/log -1)
(assert (= 0 (compare (int/s64 3) 3)) "compare number to int/s64") INF (/ 1 0)
(assert (= -1 (compare (int/s64 3) 4)) "compare number to int/s64 less") MINUS_INF (/ -1 0)
(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") compare-poly-tests
(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") [(int/s64 3) (int/u64 3) 0]
(assert (= 0 (compare (int/u64 3) (int/s64 3))) "compare int/u64 to int/s64 (1)") [(int/s64 -3) (int/u64 3) -1]
(assert (= -1 (compare (int/u64 3) (int/s64 4))) "compare int/u64 to int/s64 (2)") [(int/s64 3) (int/u64 2) 1]
(assert (= 1 (compare (int/u64 1) (int/s64 -1))) "compare int/u64 to int/s64 (3)") [(int/s64 3) 3 0] [(int/s64 3) 4 -1] [(int/s64 3) -9 1]
(assert (= 1 (compare (int/s64 4) (int/u64 3))) "compare int/s64 to int/u64") [(int/u64 3) 3 0] [(int/u64 3) 4 -1] [(int/u64 3) -9 1]
(assert (= -1 (compare (int/s64 -1) (int/u64 0))) "compare int/s64 to int/u64 negative") [3 (int/s64 3) 0] [3 (int/s64 4) -1] [3 (int/s64 -5) 1]
(assert (= -1 (compare (int/s64 MAX_INT_64_STRING) (int/u64 MAX_UINT_64_STRING))) "compare big ints") [3 (int/u64 3) 0] [3 (int/u64 4) -1] [3 (int/u64 2) 1]
(assert (= 0 (compare (int/s64 MAX_INT_IN_DBL_STRING) (scan-number MAX_INT_IN_DBL_STRING))) "compare max int in double (1)") [(int/s64 MAX_INT_64_STRING) (int/u64 MAX_UINT_64_STRING) -1]
(assert (= 0 (compare (int/u64 MAX_INT_IN_DBL_STRING) (scan-number MAX_INT_IN_DBL_STRING))) "compare max int in double (2)") [(int/s64 MAX_INT_IN_DBL_STRING) (scan-number MAX_INT_IN_DBL_STRING) 0]
(assert (= 1 (compare (+ 1 (int/u64 MAX_INT_IN_DBL_STRING)) (scan-number MAX_INT_IN_DBL_STRING))) "compare max int in double (3)") [(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) (end-suite)