fix negative nan (#16628)

This commit is contained in:
flywind 2021-01-11 04:39:38 -06:00 • committed by GitHub
commit be6e8916fa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 5 deletions

View file

@ -2485,7 +2485,10 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
let f = n.floatVal let f = n.floatVal
case classify(f) case classify(f)
of fcNan: of fcNan:
r.res = rope"NaN" if signbit(f):
r.res = rope"-NaN"
else:
r.res = rope"NaN"
of fcNegZero: of fcNegZero:
r.res = rope"-0.0" r.res = rope"-0.0"
of fcZero: of fcZero:

View file

@ -8,7 +8,7 @@
# #
## Serialization utilities for the compiler. ## Serialization utilities for the compiler.
import strutils, math import std/[strutils, math]
# bcc on windows doesn't have C99 functions # bcc on windows doesn't have C99 functions
when defined(windows) and defined(bcc): when defined(windows) and defined(bcc):
@ -33,10 +33,19 @@ when defined(windows) and defined(bcc):
proc c_snprintf(s: cstring; n:uint; frmt: cstring): cint {.importc: "snprintf", header: "<stdio.h>", nodecl, varargs.} proc c_snprintf(s: cstring; n:uint; frmt: cstring): cint {.importc: "snprintf", header: "<stdio.h>", nodecl, varargs.}
when not declared(signbit):
proc c_signbit(x: SomeFloat): cint {.importc: "signbit", header: "<math.h>".}
proc signbit*(x: SomeFloat): bool {.inline.} =
result = c_signbit(x) != 0
proc toStrMaxPrecision*(f: BiggestFloat, literalPostfix = ""): string = proc toStrMaxPrecision*(f: BiggestFloat, literalPostfix = ""): string =
case classify(f) case classify(f)
of fcNan: of fcNan:
result = "NAN" if signbit(f):
result = "-NAN"
else:
result = "NAN"
of fcNegZero: of fcNegZero:
result = "-0.0" & literalPostfix result = "-0.0" & literalPostfix
of fcZero: of fcZero:

View file

@ -319,6 +319,18 @@ template main =
doAssert not Inf.isNaN doAssert not Inf.isNaN
doAssert isNaN(Inf - Inf) doAssert isNaN(Inf - Inf)
block: # signbit
let x1 = NaN
let x2 = -NaN
let x3 = -x1
doAssert isNaN(x1)
doAssert isNaN(x2)
doAssert isNaN(x3)
doAssert not signbit(x1)
doAssert signbit(x2)
doAssert signbit(x3)
block: # copySign block: # copySign
doAssert copySign(10.0, -1.0) == -10.0 doAssert copySign(10.0, -1.0) == -10.0
doAssert copySign(-10.0, -1.0) == -10.0 doAssert copySign(-10.0, -1.0) == -10.0
@ -385,8 +397,8 @@ template main =
discard discard
else: else:
when not defined(js): when not defined(js):
doAssert copySign(-1.0, -NaN) == 1.0 doAssert copySign(-1.0, -NaN) == -1.0
doAssert copySign(10.0, -NaN) == 10.0 doAssert copySign(10.0, -NaN) == -10.0
doAssert copySign(1.0, copySign(NaN, -1.0)) == -1.0 # fails in VM doAssert copySign(1.0, copySign(NaN, -1.0)) == -1.0 # fails in VM
block: block: