diff --git a/src/vmath.nim b/src/vmath.nim index 9708863..15fbc88 100644 --- a/src/vmath.nim +++ b/src/vmath.nim @@ -424,10 +424,9 @@ proc toDegrees*[T: SomeFloat](rad: T): T = ## Convert radians to degrees. return fixAngle(180.0 * rad / PI) -proc isNaN*(n: SomeFloat): bool = - ## Returns true if number is a Nan. - n.classify != fcNan - +proc isNaN*(x: float32): bool = + ## Returns true if number is a NaN. + x != 0.0 and (x != x or x * 0.5 == x) template genConstructor(lower, upper, typ: untyped) = proc `lower 2`*(): `upper 2` = gvec2[typ](typ(0), typ(0)) diff --git a/tests/bench_isNan.nim b/tests/bench_isNan.nim new file mode 100644 index 0000000..8a5aedd --- /dev/null +++ b/tests/bench_isNan.nim @@ -0,0 +1,124 @@ +import benchy, vmath + +proc isNaNSlow(f: SomeFloat): bool = + ## Returns true if number is a NaN. + f.classify notin {fcNormal, fcZero, fcSubnormal} + +proc isNaNRyan(x: SomeFloat): bool = + if x == 0.0: + return false + x != x or x * 0.5 == x + +proc isNaN3*(x: SomeFloat): bool = + ## Returns true if number is a NaN. + x != 0.0 and (x != x or x * 0.5 == x) + +assert isNaNSlow(0.3) == false +assert isNaNSlow(0.0) == false +assert isNaNSlow(0.3/0.0) == true +assert isNaNSlow(-0.3/0.0) == true +assert isNaNSlow(5.0e-324) == false + +assert isNaNRyan(0.3) == false +assert isNaNRyan(0.0) == false +assert isNaNRyan(0.3/0.0) == true +assert isNaNRyan(-0.3/0.0) == true +assert isNaNRyan(5.0e-324) == false + +assert isNan(float32(0.3)) == false +assert isNan(float32(0.0)) == false +assert isNan(float32(0.3/0.0)) == true +assert isNan(float32(-0.3/0.0)) == true +assert isNan(float32(5.0e-324)) == false + +assert isNan(float64(0.3)) == false +assert isNan(float64(0.0)) == false +assert isNan(float64(0.3/0.0)) == true +assert isNan(float64(-0.3/0.0)) == true +assert isNan(float64(5.0e-324)) == false + +assert isNan3(float32(0.3)) == false +assert isNan3(float32(0.0)) == false +assert isNan3(float32(0.3/0.0)) == true +assert isNan3(float32(-0.3/0.0)) == true +assert isNan3(float32(5.0e-324)) == false + +assert isNan3(float64(0.3)) == false +assert isNan3(float64(0.0)) == false +assert isNan3(float64(0.3/0.0)) == true +assert isNan3(float64(-0.3/0.0)) == true +assert isNan3(float64(5.0e-324)) == false + +const num = 1_00_000 + +timeIt "isNaNSlow float32": + var x: float32 + var n = 0 + for i in 0 .. num: + if x.isNaNSlow: + n += 1 + x = float32(i) / float32(i) + keep n + +timeIt "isNaNSlow float64": + var x: float64 + var n = 0 + for i in 0 .. num: + if x.isNaNSlow: + n += 1 + x = float64(i) / float64(i) + keep n + +timeIt "isNaNRyan float32": + var x: float32 + var n = 0 + for i in 0 .. num: + if x.isNaNRyan: + n += 1 + x = float32(i) / float32(i) + keep n + +timeIt "isNaNRyan float64": + var x: float64 + var n = 0 + for i in 0 .. num: + if x.isNaNRyan: + n += 1 + x = float64(i) / float64(i) + keep n + +timeIt "isNan float32": + var x: float32 + var n = 0 + for i in 0 .. num: + if x.isNan: + n += 1 + x = float32(i) / float32(i) + keep n + +timeIt "isNan float64": + var x: float64 + var n = 0 + for i in 0 .. num: + if x.isNan: + n += 1 + x = float64(i) / float64(i) + keep n + +timeIt "isNan3 float32": + var x: float32 + var n = 0 + for i in 0 .. num: + if x.isNan3: + n += 1 + x = float32(i) / float32(i) + keep n + +timeIt "isNan3 float64": + var x: float64 + var n = 0 + for i in 0 .. num: + if x.isNan3: + n += 1 + x = float64(i) / float64(i) + keep n diff --git a/tests/test.nim b/tests/test.nim index 37d7d86..62aee1e 100644 --- a/tests/test.nim +++ b/tests/test.nim @@ -82,8 +82,27 @@ block: doAssert turnAngle(0.0, PI, 0.5) ~= 0.5 doAssert turnAngle(0.5, PI, 3.5) ~= PI - var anum = 1.0 / 0.0 - doAssert anum.isNan == true + proc isNaNSlow(f: SomeFloat): bool = + ## Returns true if number is a NaN. + f.classify notin {fcNormal, fcZero, fcSubnormal} + + assert isNaNSlow(0.3) == false + assert isNaNSlow(0.0) == false + assert isNaNSlow(0.3/0.0) == true + assert isNaNSlow(-0.3/0.0) == true + assert isNaNSlow(5.0e-324) == false + + assert isNan(float32(0.3)) == false + assert isNan(float32(0.0)) == false + assert isNan(float32(0.3/0.0)) == true + assert isNan(float32(-0.3/0.0)) == true + assert isNan(float32(5.0e-324)) == false + + assert isNan(float64(0.3)) == false + assert isNan(float64(0.0)) == false + assert isNan(float64(0.3/0.0)) == true + assert isNan(float64(-0.3/0.0)) == true + assert isNan(float64(5.0e-324)) == false block: # Test vec2 cast. diff --git a/vmath.nimble b/vmath.nimble index 91d2225..f1d6081 100644 --- a/vmath.nimble +++ b/vmath.nimble @@ -1,4 +1,4 @@ -version = "1.0.7" +version = "1.0.8" author = "treeform" description = "Your single stop for vector math routines for 2d and 3d graphics." license = "MIT"