diff --git a/CHANGELOG.md b/CHANGELOG.md index 64f7903f52..66137f2a09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -75,6 +75,7 @@ These are only breaking changes for unformatted code. - Fix issue with integer overflow check https://github.com/rescript-lang/rescript-compiler/pull/6028 - Fix issue with JSX V4 and newtype https://github.com/rescript-lang/rescript-compiler/pull/6029 - Fix issue with JSX V4 when components are nested https://github.com/rescript-lang/rescript-compiler/pull/6031 +- Fix issue where generic compare on `float` values would be different from the compare for type `float` https://github.com/rescript-lang/rescript-compiler/pull/6042 #### :nail_care: Polish diff --git a/jscomp/runtime/caml_obj.ml b/jscomp/runtime/caml_obj.ml index ce7f986d08..f7d1828a97 100644 --- a/jscomp/runtime/caml_obj.ml +++ b/jscomp/runtime/caml_obj.ml @@ -22,22 +22,18 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) - - - - - - -type t = Obj.t +type t = Obj.t module O = struct external isArray : 'a -> bool = "Array.isArray" [@@bs.val] type key = string - let for_in : (Obj.t -> (key -> unit) -> unit) = - [%raw{|function(o,foo){ + let for_in : Obj.t -> (key -> unit) -> unit = + [%raw {|function(o,foo){ for (var x in o) { foo(x) }} |}] - + + external hasOwnProperty : t -> key -> bool = "call" + [@@bs.scope "Object", "prototype", "hasOwnProperty"] [@@bs.val] (** JS objects are not guaranteed to have `Object` in their prototype chain so calling `some_obj.hasOwnProperty(key)` can sometimes throw @@ -45,15 +41,10 @@ module O = struct objects are created via `Object.create(null)`. The only safe way to call this function is directly, e.g. `Object.prototype.hasOwnProperty.call(some_obj, key)`. *) - external hasOwnProperty : - t -> key -> bool = "call" [@@bs.scope ("Object", "prototype", "hasOwnProperty")] [@@bs.val] - external get_value : Obj.t -> key -> Obj.t = ""[@@bs.get_index] + external get_value : Obj.t -> key -> Obj.t = "" [@@bs.get_index] end - - - (** Since now we change it back to use Array representation @@ -81,7 +72,9 @@ end `obj_dup` is a superset of `array_dup` *) -let obj_dup : Obj.t -> Obj.t = [%raw{|function(x){ +let obj_dup : Obj.t -> Obj.t = + [%raw + {|function(x){ if(Array.isArray(x)){ var len = x.length var v = new Array(len) @@ -96,10 +89,6 @@ let obj_dup : Obj.t -> Obj.t = [%raw{|function(x){ return Object.assign({},x) }|}] - - - - (** For the empty dummy object, whether it's [[]] or [{}] depends on how @@ -108,7 +97,9 @@ let obj_dup : Obj.t -> Obj.t = [%raw{|function(x){ In most cases, rec value comes from record/modules, whose tag is 0, we optimize that case *) -let update_dummy : _ -> _ -> unit= [%raw{|function(x,y){ +let update_dummy : _ -> _ -> unit = + [%raw + {|function(x,y){ var k if(Array.isArray(y)){ for(k = 0; k < y.length ; ++k){ @@ -125,10 +116,6 @@ let update_dummy : _ -> _ -> unit= [%raw{|function(x,y){ } |}] - - - - (** TODO: investigate total [compare x y] returns [0] if [x] is equal to [y], a negative integer if [x] is less than [y], @@ -147,212 +134,251 @@ let update_dummy : _ -> _ -> unit= [%raw{|function(x,y){ as well as the [List.sort] and [Array.sort] functions. *) let rec compare (a : Obj.t) (b : Obj.t) : int = - if a == b then 0 else + if a == b then 0 + else (*front and formoest, we do not compare function values*) - let a_type = Js.typeof a in - let b_type = Js.typeof b in - match a_type, b_type with - | "undefined", _ -> - 1 - | _, "undefined" -> 1 + let a_type = Js.typeof a in + let b_type = Js.typeof b in + match (a_type, b_type) with + | "undefined", _ -> -1 + | _, "undefined" -> 1 (* [a] is of type string, b can not be None, [a] could be (Some (Some x)) in that case [b] could be [Some None] or [null] - so [b] has to be of type string or null *) - | "string", "string" -> - Pervasives.compare (Obj.magic a : string) (Obj.magic b ) - | "string", _ -> + so [b] has to be of type string or null *) + | "string", "string" -> + Pervasives.compare (Obj.magic a : string) (Obj.magic b) + | "string", _ -> (* [b] could be [Some None] or [null] *) - 1 - | _, "string" -> -1 - | "boolean", "boolean" -> + 1 + | _, "string" -> -1 + | "boolean", "boolean" -> Pervasives.compare (Obj.magic a : bool) (Obj.magic b) - | "boolean", _ -> 1 + | "boolean", _ -> 1 | _, "boolean" -> -1 - | "function", "function" -> + | "function", "function" -> raise (Invalid_argument "compare: functional value") | "function", _ -> 1 - | _, "function" -> -1 - | "number", "number" -> - Pervasives.compare (Obj.magic a : int) (Obj.magic b : int) - | "number", _ -> - if b == Obj.repr Js.null || Caml_option.isNested b then 1 (* Some (Some ..) < x *) - else - -1 (* Integer < Block in OCaml runtime GPR #1195, except Some.. *) - | _, "number" -> - if a == Obj.repr Js.null || Caml_option.isNested a then -1 - else 1 - | _ -> - if a == Obj.repr Js.null then + | _, "function" -> -1 + | "number", "number" -> + Pervasives.compare (Obj.magic a : float) (Obj.magic b : float) + | "number", _ -> + if b == Obj.repr Js.null || Caml_option.isNested b then 1 + (* Some (Some ..) < x *) + else -1 (* Integer < Block in OCaml runtime GPR #1195, except Some.. *) + | _, "number" -> + if a == Obj.repr Js.null || Caml_option.isNested a then -1 else 1 + | _ -> + if a == Obj.repr Js.null then (* [b] could not be null otherwise would equal *) - if Caml_option.isNested b then 1 else -1 - else if b == Obj.repr Js.null then - if Caml_option.isNested a then -1 else 1 - else - (* double_array_tag: 254 + if Caml_option.isNested b then 1 else -1 + else if b == Obj.repr Js.null then + if Caml_option.isNested a then -1 else 1 + else if (* double_array_tag: 254 *) - if Caml_option.isNested a then - if Caml_option.isNested b then - aux_obj_compare a b + Caml_option.isNested a then + if Caml_option.isNested b then aux_obj_compare a b (* Some None < Some (Some None)) *) - else (* b could not be undefined/None *) - (* Some None < Some ..*) - -1 - else + else + (* b could not be undefined/None *) + (* Some None < Some ..*) + -1 + else let tag_a = Obj.tag a in let tag_b = Obj.tag b in - if tag_a = 248 (* object/exception *) then - Pervasives.compare (Obj.magic (Obj.field a 1) : int) (Obj.magic (Obj.field b 1 )) + if tag_a = 248 (* object/exception *) then + Pervasives.compare + (Obj.magic (Obj.field a 1) : int) + (Obj.magic (Obj.field b 1)) else if tag_a = 251 (* abstract_tag *) then raise (Invalid_argument "equal: abstract value") - else if tag_a <> tag_b then - if tag_a < tag_b then (-1) else 1 + else if tag_a <> tag_b then if tag_a < tag_b then -1 else 1 else let len_a = Obj.size a in let len_b = Obj.size b in if len_a = len_b then - if O.isArray a - then aux_same_length (Obj.magic a : Obj.t array ) (Obj.magic b : Obj.t array) 0 len_a - else if [%raw{|a instanceof Date && b instanceof Date|}] then - [%raw{|a - b|}] + if O.isArray a then + aux_same_length + (Obj.magic a : Obj.t array) + (Obj.magic b : Obj.t array) + 0 len_a + else if [%raw {|a instanceof Date && b instanceof Date|}] then + [%raw {|a - b|}] else aux_obj_compare a b else if len_a < len_b then (* at least one is not zero, so it is an array block*) - aux_length_a_short (Obj.magic a : Obj.t array) (Obj.magic b : Obj.t array) 0 len_a + aux_length_a_short + (Obj.magic a : Obj.t array) + (Obj.magic b : Obj.t array) + 0 len_a else - aux_length_b_short (Obj.magic a : Obj.t array) (Obj.magic b : Obj.t array) 0 len_b -and aux_same_length (a : Obj.t array) (b : Obj.t array) i same_length = - if i = same_length then - 0 + aux_length_b_short + (Obj.magic a : Obj.t array) + (Obj.magic b : Obj.t array) + 0 len_b + +and aux_same_length (a : Obj.t array) (b : Obj.t array) i same_length = + if i = same_length then 0 else - let res = compare (Caml_array_extern.unsafe_get a i) (Caml_array_extern.unsafe_get b i) in - if res <> 0 then res - else aux_same_length a b (i + 1) same_length -and aux_length_a_short (a : Obj.t array) (b : Obj.t array) i short_length = + let res = + compare + (Caml_array_extern.unsafe_get a i) + (Caml_array_extern.unsafe_get b i) + in + if res <> 0 then res else aux_same_length a b (i + 1) same_length + +and aux_length_a_short (a : Obj.t array) (b : Obj.t array) i short_length = if i = short_length then -1 else - let res = compare (Caml_array_extern.unsafe_get a i) (Caml_array_extern.unsafe_get b i) in - if res <> 0 then res - else aux_length_a_short a b (i+1) short_length + let res = + compare + (Caml_array_extern.unsafe_get a i) + (Caml_array_extern.unsafe_get b i) + in + if res <> 0 then res else aux_length_a_short a b (i + 1) short_length + and aux_length_b_short (a : Obj.t array) (b : Obj.t array) i short_length = if i = short_length then 1 else - let res = compare (Caml_array_extern.unsafe_get a i) (Caml_array_extern.unsafe_get b i) in - if res <> 0 then res - else aux_length_b_short a b (i+1) short_length -and aux_obj_compare (a: Obj.t) (b: Obj.t) = + let res = + compare + (Caml_array_extern.unsafe_get a i) + (Caml_array_extern.unsafe_get b i) + in + if res <> 0 then res else aux_length_b_short a b (i + 1) short_length + +and aux_obj_compare (a : Obj.t) (b : Obj.t) = let min_key_lhs = ref None in let min_key_rhs = ref None in let do_key (a, b, min_key) key = - if not (O.hasOwnProperty b key) || - compare (O.get_value a key) (O.get_value b key) > 0 + if + (not (O.hasOwnProperty b key)) + || compare (O.get_value a key) (O.get_value b key) > 0 then match min_key.contents with - | None -> min_key .contents<- Some key - | Some mk -> - if key < mk then min_key .contents<- Some key in + | None -> min_key.contents <- Some key + | Some mk -> if key < mk then min_key.contents <- Some key + in let do_key_a = do_key (a, b, min_key_rhs) in let do_key_b = do_key (b, a, min_key_lhs) in O.for_in a do_key_a; O.for_in b do_key_b; - let res = match min_key_lhs.contents, min_key_rhs.contents with + let res = + match (min_key_lhs.contents, min_key_rhs.contents) with | None, None -> 0 - | (Some _), None -> -1 - | None, (Some _) -> 1 - | (Some x), (Some y) -> Pervasives.compare x y in + | Some _, None -> -1 + | None, Some _ -> 1 + | Some x, Some y -> Pervasives.compare x y + in res type eq = Obj.t -> Obj.t -> bool - (** It is easier to do equality check than comparision, since as long as its basic type is not the same, it will not equal *) let rec equal (a : Obj.t) (b : Obj.t) : bool = (*front and formoest, we do not compare function values*) if a == b then true - else - let a_type = Js.typeof a in - if a_type = "string" - || a_type = "number" - || a_type = "boolean" - || a_type = "undefined" - || a == [%raw {|null|}] + else + let a_type = Js.typeof a in + if + a_type = "string" || a_type = "number" || a_type = "boolean" + || a_type = "undefined" + || a == [%raw {|null|}] then false - else - let b_type = Js.typeof b in - if a_type = "function" || b_type = "function" - then raise (Invalid_argument "equal: functional value") - (* first, check using reference equality *) - else (* a_type = "object" || "symbol" *) - if b_type = "number" || b_type = "undefined" || b == [%raw{|null|}] then false - else + else + let b_type = Js.typeof b in + if a_type = "function" || b_type = "function" then + raise (Invalid_argument "equal: functional value") + (* first, check using reference equality *) + else if + (* a_type = "object" || "symbol" *) + b_type = "number" || b_type = "undefined" || b == [%raw {|null|}] + then false + else (* [a] [b] could not be null, so it can not raise *) let tag_a = Obj.tag a in let tag_b = Obj.tag b in - if tag_a = 248 (* object/exception *) then - (Obj.magic (Obj.field a 1)) == (Obj.magic (Obj.field b 1 )) + if tag_a = 248 (* object/exception *) then + Obj.magic (Obj.field a 1) == Obj.magic (Obj.field b 1) else if tag_a = 251 (* abstract_tag *) then raise (Invalid_argument "equal: abstract value") - else if tag_a <> tag_b then - false - else + else if tag_a <> tag_b then false + else let len_a = Obj.size a in let len_b = Obj.size b in if len_a = len_b then - if O.isArray a - then aux_equal_length (Obj.magic a : Obj.t array) (Obj.magic b : Obj.t array) 0 len_a - else if [%raw{|a instanceof Date && b instanceof Date|}] then - not (Js.unsafe_gt a b || Js.unsafe_lt a b) + if O.isArray a then + aux_equal_length + (Obj.magic a : Obj.t array) + (Obj.magic b : Obj.t array) + 0 len_a + else if [%raw {|a instanceof Date && b instanceof Date|}] then + not (Js.unsafe_gt a b || Js.unsafe_lt a b) else aux_obj_equal a b else false -and aux_equal_length (a : Obj.t array) (b : Obj.t array) i same_length = - if i = same_length then - true + +and aux_equal_length (a : Obj.t array) (b : Obj.t array) i same_length = + if i = same_length then true else equal (Caml_array_extern.unsafe_get a i) (Caml_array_extern.unsafe_get b i) - && aux_equal_length a b (i + 1) same_length -and aux_obj_equal (a: Obj.t) (b: Obj.t) = + && aux_equal_length a b (i + 1) same_length + +and aux_obj_equal (a : Obj.t) (b : Obj.t) = let result = ref true in let do_key_a key = - if not (O.hasOwnProperty b key) - then result .contents<- false in + if not (O.hasOwnProperty b key) then result.contents <- false + in let do_key_b key = - if not (O.hasOwnProperty a key) || - not (equal (O.get_value b key) (O.get_value a key)) - then result .contents<- false in - O.for_in a do_key_a ; + if + (not (O.hasOwnProperty a key)) + || not (equal (O.get_value b key) (O.get_value a key)) + then result.contents <- false + in + O.for_in a do_key_a; if result.contents then O.for_in b do_key_b; result.contents -let equal_null (x : Obj.t) (y : Obj.t Js.null) = - match Js.nullToOption y with - | None -> x == (Obj.magic y) - | Some y -> equal x y - -let equal_undefined (x : Obj.t) (y : Obj.t Js.undefined) = - match Js.undefinedToOption y with - | None -> x == (Obj.magic y) - | Some y -> equal x y - -let equal_nullable ( x: Obj.t) (y : Obj.t Js.nullable) = - match Js.toOption y with - | None -> x == (Obj.magic y) +let equal_null (x : Obj.t) (y : Obj.t Js.null) = + match Js.nullToOption y with + | None -> x == Obj.magic y | Some y -> equal x y -let notequal a b = not (equal a b) - -let greaterequal a b = compare a b >= 0 +let equal_undefined (x : Obj.t) (y : Obj.t Js.undefined) = + match Js.undefinedToOption y with + | None -> x == Obj.magic y + | Some y -> equal x y -let greaterthan a b = compare a b > 0 +let equal_nullable (x : Obj.t) (y : Obj.t Js.nullable) = + match Js.toOption y with + | None -> x == Obj.magic y + | Some y -> equal x y -let lessequal a b = compare a b <= 0 +let notequal a b = + if Js.typeof a = "number" && Js.typeof b = "number" then + (Obj.magic a : float) <> (Obj.magic b : float) + else not (equal a b) -let lessthan a b = compare a b < 0 +let greaterequal a b = + if Js.typeof a = "number" && Js.typeof b = "number" then + (Obj.magic a : float) >= (Obj.magic b : float) + else compare a b >= 0 -let min (x : Obj.t) y = - if compare x y <= 0 then x else y +let greaterthan a b = + if Js.typeof a = "number" && Js.typeof b = "number" then + (Obj.magic a : float) > (Obj.magic b : float) + else compare a b > 0 -let max (x : Obj.t) y = - if compare x y >= 0 then x else y +let lessequal a b = + if Js.typeof a = "number" && Js.typeof b = "number" then + (Obj.magic a : float) <= (Obj.magic b : float) + else compare a b <= 0 +let lessthan a b = + if Js.typeof a = "number" && Js.typeof b = "number" then + (Obj.magic a : float) < (Obj.magic b : float) + else compare a b < 0 +let min (x : Obj.t) y = if compare x y <= 0 then x else y +let max (x : Obj.t) y = if compare x y >= 0 then x else y diff --git a/jscomp/test/float_test.js b/jscomp/test/float_test.js index b3d40a534d..624beb360c 100644 --- a/jscomp/test/float_test.js +++ b/jscomp/test/float_test.js @@ -3,6 +3,7 @@ var Mt = require("./mt.js"); var Caml = require("../../lib/js/caml.js"); var $$Array = require("../../lib/js/array.js"); +var Caml_obj = require("../../lib/js/caml_obj.js"); var Mt_global = require("./mt_global.js"); var Caml_float = require("../../lib/js/caml_float.js"); var Caml_int64 = require("../../lib/js/caml_int64.js"); @@ -138,16 +139,54 @@ function from_pairs(ps) { var float_compare = Caml.float_compare; -Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 47, characters 5-12", Pervasives.classify_float(3), /* FP_normal */0); +var generic_compare = Caml_obj.compare; -Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 48, characters 5-12", Caml_float.modf_float(-3.125), [ +function float_equal(x, y) { + return x === y; +} + +var generic_equal = Caml_obj.equal; + +function float_notequal(x, y) { + return x !== y; +} + +var generic_notequal = Caml_obj.notequal; + +function float_lessthan(x, y) { + return x < y; +} + +var generic_lessthan = Caml_obj.lessthan; + +function float_greaterthan(x, y) { + return x > y; +} + +var generic_greaterthan = Caml_obj.greaterthan; + +function float_lessequal(x, y) { + return x <= y; +} + +var generic_lessequal = Caml_obj.lessequal; + +function float_greaterequal(x, y) { + return x >= y; +} + +var generic_greaterequal = Caml_obj.greaterequal; + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 60, characters 5-12", Pervasives.classify_float(3), /* FP_normal */0); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 61, characters 5-12", Caml_float.modf_float(-3.125), [ -0.125, -3 ]); var match$3 = Caml_float.modf_float(Number.NaN); -Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 49, characters 5-12", [ +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 62, characters 5-12", [ Number.isNaN(match$3[0]), Number.isNaN(match$3[1]) ], [ @@ -155,7 +194,7 @@ Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 49, characte true ]); -Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 52, characters 5-12", $$Array.map((function (x) { +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 65, characters 5-12", $$Array.map((function (x) { if (x > 0) { return 1; } else if (x < 0) { @@ -184,17 +223,101 @@ Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 52, characte 1 ]); -Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 56, characters 5-12", Caml_float.copysign_float(-3, 0), 3); +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 69, characters 5-12", Caml_float.copysign_float(-3, 0), 3); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 70, characters 5-12", Caml_float.copysign_float(3, 0), 3); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 71, characters 5-12", Math.log10(10), 1); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 72, characters 5-12", Caml_float.expm1_float(0), 0); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 73, characters 5-12", Number("3.0"), 3.0); + +Mt_global.collect_approx(test_id, suites, "File \"float_test.ml\", line 74, characters 9-16", Caml_float.expm1_float(2), 6.38905609893065); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 75, characters 5-12", Caml.float_compare(NaN, NaN), 0); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 76, characters 5-12", Caml_obj.compare(NaN, NaN), 0); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 77, characters 5-12", Caml.float_compare(NaN, Pervasives.neg_infinity), -1); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 78, characters 5-12", Caml_obj.compare(NaN, Pervasives.neg_infinity), -1); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 79, characters 5-12", Caml.float_compare(Pervasives.neg_infinity, NaN), 1); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 80, characters 5-12", Caml_obj.compare(Pervasives.neg_infinity, NaN), 1); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 81, characters 5-12", NaN === NaN, false); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 82, characters 5-12", Caml_obj.equal(NaN, NaN), false); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 83, characters 5-12", 4.2 === NaN, false); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 84, characters 5-12", Caml_obj.equal(4.2, NaN), false); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 85, characters 5-12", NaN === 4.2, false); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 86, characters 5-12", Caml_obj.equal(NaN, 4.2), false); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 87, characters 5-12", NaN !== NaN, true); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 88, characters 5-12", Caml_obj.notequal(NaN, NaN), true); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 89, characters 5-12", 4.2 !== NaN, true); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 90, characters 5-12", Caml_obj.notequal(4.2, NaN), true); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 91, characters 5-12", NaN !== 4.2, true); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 92, characters 5-12", Caml_obj.notequal(NaN, 4.2), true); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 93, characters 5-12", NaN < NaN, false); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 94, characters 5-12", Caml_obj.lessthan(NaN, NaN), false); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 95, characters 5-12", 4.2 < NaN, false); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 96, characters 5-12", Caml_obj.lessthan(4.2, NaN), false); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 97, characters 5-12", NaN < 4.2, false); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 98, characters 5-12", Caml_obj.lessthan(NaN, 4.2), false); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 99, characters 5-12", NaN > NaN, false); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 100, characters 5-12", Caml_obj.greaterthan(NaN, NaN), false); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 101, characters 5-12", 4.2 > NaN, false); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 102, characters 5-12", Caml_obj.greaterthan(4.2, NaN), false); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 103, characters 5-12", NaN > 4.2, false); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 104, characters 5-12", Caml_obj.greaterthan(NaN, 4.2), false); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 105, characters 5-12", NaN <= NaN, false); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 106, characters 5-12", Caml_obj.lessequal(NaN, NaN), false); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 107, characters 5-12", 4.2 <= NaN, false); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 108, characters 5-12", Caml_obj.lessequal(4.2, NaN), false); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 109, characters 5-12", NaN <= 4.2, false); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 110, characters 5-12", Caml_obj.lessequal(NaN, 4.2), false); + +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 111, characters 5-12", NaN >= NaN, false); -Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 57, characters 5-12", Caml_float.copysign_float(3, 0), 3); +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 112, characters 5-12", Caml_obj.greaterequal(NaN, NaN), false); -Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 58, characters 5-12", Math.log10(10), 1); +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 113, characters 5-12", 4.2 >= NaN, false); -Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 59, characters 5-12", Caml_float.expm1_float(0), 0); +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 114, characters 5-12", Caml_obj.greaterequal(4.2, NaN), false); -Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 60, characters 5-12", Number("3.0"), 3.0); +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 115, characters 5-12", NaN >= 4.2, false); -Mt_global.collect_approx(test_id, suites, "File \"float_test.ml\", line 61, characters 9-16", Caml_float.expm1_float(2), 6.38905609893065); +Mt_global.collect_eq(test_id, suites, "File \"float_test.ml\", line 116, characters 5-12", Caml_obj.greaterequal(NaN, 4.2), false); var match$4 = Caml_float.modf_float(32.3); @@ -260,4 +383,17 @@ exports.epsilon_float = epsilon_float; exports.results = results; exports.from_pairs = from_pairs; exports.float_compare = float_compare; +exports.generic_compare = generic_compare; +exports.float_equal = float_equal; +exports.generic_equal = generic_equal; +exports.float_notequal = float_notequal; +exports.generic_notequal = generic_notequal; +exports.float_lessthan = float_lessthan; +exports.generic_lessthan = generic_lessthan; +exports.float_greaterthan = float_greaterthan; +exports.generic_greaterthan = generic_greaterthan; +exports.float_lessequal = float_lessequal; +exports.generic_lessequal = generic_lessequal; +exports.float_greaterequal = float_greaterequal; +exports.generic_greaterequal = generic_greaterequal; /* results Not a pure module */ diff --git a/jscomp/test/float_test.ml b/jscomp/test/float_test.ml index c1e1c03376..91afad4589 100644 --- a/jscomp/test/float_test.ml +++ b/jscomp/test/float_test.ml @@ -41,8 +41,21 @@ let from_pairs ps = |> Array.to_list ;; -let float_compare (x : float) y = Pervasives.compare x y - +let float_compare (x : float) y = Pervasives.compare x y +let generic_compare = Pervasives.compare +let float_equal (x : float) y = x = y +let generic_equal = (=) +let float_notequal (x : float) y = x <> y +let generic_notequal = (<>) +let float_lessthan (x: float) y = x < y +let generic_lessthan = (<) +let float_greaterthan (x: float) y = x > y +let generic_greaterthan = (>) +let float_lessequal (x: float) y = x <= y +let generic_lessequal = (<=) +let float_greaterequal (x: float) y = x >= y +let generic_greaterequal = (>=) + let () = eq __LOC__ (classify_float 3. ) FP_normal; eq __LOC__ (modf (-3.125)) (-0.125, -3.); @@ -58,7 +71,49 @@ let () = eq __LOC__ (log10 10.) 1.; eq __LOC__ (expm1 0.) 0. ; eq __LOC__ (Js.Float.fromString "3.0") 3.0; - approx __LOC__ (expm1 2.) 6.38905609893065 + approx __LOC__ (expm1 2.) 6.38905609893065; + eq __LOC__ (float_compare Js.Float._NaN Js.Float._NaN) 0; + eq __LOC__ (generic_compare Js.Float._NaN Js.Float._NaN) 0; + eq __LOC__ (float_compare Js.Float._NaN neg_infinity) (-1); + eq __LOC__ (generic_compare Js.Float._NaN neg_infinity) (-1); + eq __LOC__ (float_compare neg_infinity Js.Float._NaN) 1; + eq __LOC__ (generic_compare neg_infinity Js.Float._NaN) 1; + eq __LOC__ (float_equal Js.Float._NaN Js.Float._NaN) false; + eq __LOC__ (generic_equal Js.Float._NaN Js.Float._NaN) false; + eq __LOC__ (float_equal 4.2 Js.Float._NaN) false; + eq __LOC__ (generic_equal 4.2 Js.Float._NaN) false; + eq __LOC__ (float_equal Js.Float._NaN 4.2) false; + eq __LOC__ (generic_equal Js.Float._NaN 4.2) false; + eq __LOC__ (float_notequal Js.Float._NaN Js.Float._NaN) true; + eq __LOC__ (generic_notequal Js.Float._NaN Js.Float._NaN) true; + eq __LOC__ (float_notequal 4.2 Js.Float._NaN) true; + eq __LOC__ (generic_notequal 4.2 Js.Float._NaN) true; + eq __LOC__ (float_notequal Js.Float._NaN 4.2) true; + eq __LOC__ (generic_notequal Js.Float._NaN 4.2) true; + eq __LOC__ (float_lessthan Js.Float._NaN Js.Float._NaN) false; + eq __LOC__ (generic_lessthan Js.Float._NaN Js.Float._NaN) false; + eq __LOC__ (float_lessthan 4.2 Js.Float._NaN) false; + eq __LOC__ (generic_lessthan 4.2 Js.Float._NaN) false; + eq __LOC__ (float_lessthan Js.Float._NaN 4.2) false; + eq __LOC__ (generic_lessthan Js.Float._NaN 4.2) false; + eq __LOC__ (float_greaterthan Js.Float._NaN Js.Float._NaN) false; + eq __LOC__ (generic_greaterthan Js.Float._NaN Js.Float._NaN) false; + eq __LOC__ (float_greaterthan 4.2 Js.Float._NaN) false; + eq __LOC__ (generic_greaterthan 4.2 Js.Float._NaN) false; + eq __LOC__ (float_greaterthan Js.Float._NaN 4.2) false; + eq __LOC__ (generic_greaterthan Js.Float._NaN 4.2) false; + eq __LOC__ (float_lessequal Js.Float._NaN Js.Float._NaN) false; + eq __LOC__ (generic_lessequal Js.Float._NaN Js.Float._NaN) false; + eq __LOC__ (float_lessequal 4.2 Js.Float._NaN) false; + eq __LOC__ (generic_lessequal 4.2 Js.Float._NaN) false; + eq __LOC__ (float_lessequal Js.Float._NaN 4.2) false; + eq __LOC__ (generic_lessequal Js.Float._NaN 4.2) false; + eq __LOC__ (float_greaterequal Js.Float._NaN Js.Float._NaN) false; + eq __LOC__ (generic_greaterequal Js.Float._NaN Js.Float._NaN) false; + eq __LOC__ (float_greaterequal 4.2 Js.Float._NaN) false; + eq __LOC__ (generic_greaterequal 4.2 Js.Float._NaN) false; + eq __LOC__ (float_greaterequal Js.Float._NaN 4.2) false; + eq __LOC__ (generic_greaterequal Js.Float._NaN 4.2) false; ;; diff --git a/lib/es6/caml_obj.js b/lib/es6/caml_obj.js index 41a8c6ccef..0a24f28b42 100644 --- a/lib/es6/caml_obj.js +++ b/lib/es6/caml_obj.js @@ -59,7 +59,7 @@ function compare(a, b) { break; case "number" : if (b_type === "number") { - return Caml.int_compare(a, b); + return Caml.float_compare(a, b); } break; case "string" : @@ -359,23 +359,43 @@ function equal_nullable(x, y) { } function notequal(a, b) { - return !equal(a, b); + if (typeof a === "number" && typeof b === "number") { + return a !== b; + } else { + return !equal(a, b); + } } function greaterequal(a, b) { - return compare(a, b) >= 0; + if (typeof a === "number" && typeof b === "number") { + return a >= b; + } else { + return compare(a, b) >= 0; + } } function greaterthan(a, b) { - return compare(a, b) > 0; + if (typeof a === "number" && typeof b === "number") { + return a > b; + } else { + return compare(a, b) > 0; + } } function lessequal(a, b) { - return compare(a, b) <= 0; + if (typeof a === "number" && typeof b === "number") { + return a <= b; + } else { + return compare(a, b) <= 0; + } } function lessthan(a, b) { - return compare(a, b) < 0; + if (typeof a === "number" && typeof b === "number") { + return a < b; + } else { + return compare(a, b) < 0; + } } function min(x, y) { diff --git a/lib/js/caml_obj.js b/lib/js/caml_obj.js index 3a7257a30d..7563d79358 100644 --- a/lib/js/caml_obj.js +++ b/lib/js/caml_obj.js @@ -59,7 +59,7 @@ function compare(a, b) { break; case "number" : if (b_type === "number") { - return Caml.int_compare(a, b); + return Caml.float_compare(a, b); } break; case "string" : @@ -359,23 +359,43 @@ function equal_nullable(x, y) { } function notequal(a, b) { - return !equal(a, b); + if (typeof a === "number" && typeof b === "number") { + return a !== b; + } else { + return !equal(a, b); + } } function greaterequal(a, b) { - return compare(a, b) >= 0; + if (typeof a === "number" && typeof b === "number") { + return a >= b; + } else { + return compare(a, b) >= 0; + } } function greaterthan(a, b) { - return compare(a, b) > 0; + if (typeof a === "number" && typeof b === "number") { + return a > b; + } else { + return compare(a, b) > 0; + } } function lessequal(a, b) { - return compare(a, b) <= 0; + if (typeof a === "number" && typeof b === "number") { + return a <= b; + } else { + return compare(a, b) <= 0; + } } function lessthan(a, b) { - return compare(a, b) < 0; + if (typeof a === "number" && typeof b === "number") { + return a < b; + } else { + return compare(a, b) < 0; + } } function min(x, y) {