Quellcode durchsuchen

Merge pull request #2209 from deltaluca/dev_float_fixes

Change all uses of string_of_float to float_repres.
Simon Krajewski vor 12 Jahren
Ursprung
Commit
2f29aa264b
6 geänderte Dateien mit 36 neuen und 8 gelöschten Zeilen
  1. 28 0
      common.ml
  2. 2 2
      genswf.ml
  3. 2 2
      interp.ml
  4. 1 1
      libs
  5. 1 1
      main.ml
  6. 2 2
      optimizer.ml

+ 28 - 0
common.ml

@@ -880,3 +880,31 @@ let rec close_times() =
 
 ;;
 Ast.Meta.to_string_ref := fun m -> fst (MetaInfo.to_string m)
+
+(*  Taken from OCaml source typing/oprint.ml
+
+    This is a better version of string_of_float which prints without loss of precision
+    so that float_of_string (float_repres x) = x for all floats x
+*)
+let valid_float_lexeme s =
+	let l = String.length s in
+	let rec loop i =
+		if i >= l then s ^ "." else
+		match s.[i] with
+		| '0' .. '9' | '-' -> loop (i+1)
+		| _ -> s
+	in loop 0
+
+let float_repres f =
+	match classify_float f with
+	| FP_nan -> "nan"
+	| FP_infinite ->
+		if f < 0.0 then "neg_infinity" else "infinity"
+	| _ ->
+		let float_val =
+			let s1 = Printf.sprintf "%.12g" f in
+			if f = float_of_string s1 then s1 else
+			let s2 = Printf.sprintf "%.15g" f in
+			if f = float_of_string s2 then s2 else
+			Printf.sprintf "%.18g" f
+		in valid_float_lexeme float_val

+ 2 - 2
genswf.ml

@@ -243,7 +243,7 @@ let build_class com c file =
 							| HVInt i | HVUInt i ->
 								Some (Int (Int32.to_string i))
 							| HVFloat f ->
-								Some (Float (string_of_float f))
+								Some (Float (float_repres f))
 							) in
 							match v with
 							| None -> None
@@ -542,7 +542,7 @@ let swf_ver = function
 	| 11.6 -> 19
 	| 11.7 -> 20
 	| 11.8 -> 21
-	| v -> failwith ("Invalid SWF version " ^ string_of_float v)
+	| v -> failwith ("Invalid SWF version " ^ float_repres v)
 
 let convert_header com (w,h,fps,bg) =
 	let high = (max w h) * 20 in

+ 2 - 2
interp.ml

@@ -2050,7 +2050,7 @@ let haxe_float f p =
     else if (f <> f) then
         (Ast.EField (math, "NaN"), p)
     else
-        (Ast.EConst (Ast.Float (string_of_float f)), p)
+        (Ast.EConst (Ast.Float (float_repres f)), p)
 
 let macro_lib =
 	let error() =
@@ -3251,7 +3251,7 @@ let rec to_string ctx n v =
 	| VInt i -> string_of_int i
 	| VInt32 i -> Int32.to_string i
 	| VFloat f ->
-		let s = string_of_float f in
+		let s = float_repres f in
 		let len = String.length s in
 		if String.unsafe_get s (len - 1) = '.' then String.sub s 0 (len - 1) else s
 	| VString s -> s

+ 1 - 1
libs

@@ -1 +1 @@
-Subproject commit 34232d03b0ec836170379a3f82afde51485f549f
+Subproject commit ff2e0f209eb9fcec663437e66b5f76b8e730130b

+ 1 - 1
main.ml

@@ -796,7 +796,7 @@ try
 	let force_typing = ref false in
 	let pre_compilation = ref [] in
 	let interp = ref false in
-	Common.define_value com Define.HaxeVer (string_of_float (float_of_int version /. 100.));
+	Common.define_value com Define.HaxeVer (float_repres (float_of_int version /. 100.));
 	Common.raw_define com (if ((version / 10) land 1 == 0) then "haxe_release" else "haxe_svn");
 	Common.raw_define com "haxe3";
 	Common.define_value com Define.Dce "std";

+ 2 - 2
optimizer.ml

@@ -807,7 +807,7 @@ let rec reduce_loop ctx e =
 	let e = Type.map_expr (reduce_loop ctx) e in
 	let check_float op f1 f2 =
 		let f = op f1 f2 in
-		let fstr = string_of_float f in
+		let fstr = float_repres f in
 		if (match classify_float f with FP_nan | FP_infinite -> false | _ -> float_of_string fstr = f) then { e with eexpr = TConst (TFloat fstr) } else e
 	in
 	sanitize_expr ctx.com (match e.eexpr with
@@ -946,7 +946,7 @@ let rec reduce_loop ctx e =
 		| NegBits, TConst (TInt i) -> { e with eexpr = TConst (TInt (Int32.lognot i)) }
 		| Neg, TConst (TFloat f) ->
 			let v = 0. -. float_of_string f in
-			let vstr = string_of_float v in
+			let vstr = float_repres v in
 			if float_of_string vstr = v then
 				{ e with eexpr = TConst (TFloat vstr) }
 			else