discard """ matrix: "-d:nimPreviewFloatRoundtrip; -u:nimPreviewFloatRoundtrip" targets: "c cpp js" """ #[ xxx merge all or most float tests into this file ]# import std/[fenv, math, strutils] import stdtest/testutils proc equalsOrNaNs(a, b: float): bool = if isNaN(a): isNaN(b) elif a == 0: b == 0 and signbit(a) == signbit(b) else: a == b template reject(a) = doAssertRaises(ValueError): discard parseFloat(a) template main = block: proc test(a: string, b: float) = let a2 = a.parseFloat doAssert equalsOrNaNs(a2, b), $(a, a2, b) test "0.00_0001", 1E-6 test "0.00__00_01", 1E-6 test "0.0_01", 0.001 test "0.00_000_1", 1E-6 test "0.00000_1", 1E-6 test "1_0.00_0001", 10.000001 test "1__00.00_0001", 1_00.000001 test "inf", Inf test "-inf", -Inf test "-Inf", -Inf test "-INF", -Inf test "NaN", NaN test "-nan", NaN test ".1", 0.1 test "-.1", -0.1 test "-0", -0.0 when false: # pending bug #18246 test "-0", -0.0 test ".1e-1", 0.1e-1 test "0_1_2_3.0_1_2_3E+0_1_2", 123.0123e12 test "0_1_2.e-0", 12e0 test "0_1_2e-0", 12e0 test "-0e0", -0.0 test "-0e-0", -0.0 reject "a" reject "" reject "e1" reject "infa" reject "infe1" reject "_" reject "1e" when false: # gray area; these numbers should probably be invalid reject "1_" reject "1_.0" reject "1.0_" block: # bugs mentioned in https://github.com/nim-lang/Nim/pull/18504#issuecomment-881635317 block: # example 1 let a = 0.1+0.2 doAssert a != 0.3 when defined(nimPreviewFloatRoundtrip): doAssert $a == "0.30000000000000004" else: whenRuntimeJs: discard do: doAssert $a == "0.3" block: # example 2 const a = 0.1+0.2 when defined(nimPreviewFloatRoundtrip): doAssert $($a, a) == """("0.30000000000000004", 0.30000000000000004)""" else: whenRuntimeJs: discard do: doAssert $($a, a) == """("0.3", 0.3)""" block: # example 3 const a1 = 0.1+0.2 let a2 = a1 doAssert a1 != 0.3 when defined(nimPreviewFloatRoundtrip): doAssert $[$a1, $a2] == """["0.30000000000000004", "0.30000000000000004"]""" else: whenRuntimeJs: discard do: doAssert $[$a1, $a2] == """["0.3", "0.3"]""" when defined(nimPreviewFloatRoundtrip): block: # bug #18148 var a = 1.1'f32 doAssert $a == "1.1", $a # was failing block: # bug #18400 block: let a1 = 0.1'f32 let a2 = 0.2'f32 let a3 = a1 + a2 var s = "" s.addFloat(a3) whenVMorJs: discard # xxx refs #12884 do: doAssert a3 == 0.3'f32 doAssert $a3 == "0.3" block: let a1 = 0.1 let a2 = 0.2 let a3 = a1 + a2 var s = "" s.addFloat(a3) doAssert a3 != 0.3 doAssert $a3 == "0.30000000000000004" block: var s = [-13.888888'f32] whenRuntimeJs: discard do: doAssert $s == "[-13.888888]" doAssert $s[0] == "-13.888888" block: # bug #7717 proc test(f: float) = let f2 = $f let f3 = parseFloat(f2) doAssert equalsOrNaNs(f, f3), $(f, f2, f3) test 1.0 + epsilon(float64) test 1000000.0000000123 test log2(100000.0) test maximumPositiveValue(float32) test maximumPositiveValue(float64) test minimumPositiveValue(float32) test minimumPositiveValue(float64) block: # bug #12884 block: # example 1 const x0: float32 = 1.32 let x1 = 1.32 let x2 = 1.32'f32 var x3: float32 = 1.32 doAssert $(x0, x1, x2, x3) == "(1.32, 1.32, 1.32, 1.32)" block: # example https://github.com/nim-lang/Nim/issues/12884#issuecomment-564967962 let x = float(1.32'f32) when nimvm: discard # xxx prints 1.3 else: when not defined(js): doAssert $x == "1.3200000524520874" doAssert $1.32 == "1.32" doAssert $1.32'f32 == "1.32" let x2 = 1.32'f32 doAssert $x2 == "1.32" block: var x = 1.23456789012345'f32 when nimvm: discard # xxx, refs #12884 else: when not defined(js): doAssert x == 1.2345679'f32 doAssert $x == "1.2345679" static: main() main()