mirror of
https://github.com/janet-lang/janet
synced 2025-01-12 16:40:27 +00:00
All tests pass for compare.
This commit is contained in:
parent
3e423722c6
commit
a4178d4b3c
@ -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]);
|
||||
|
@ -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)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user