-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add math.isNaN #16179
add math.isNaN #16179
Conversation
228f7a6
to
fa7b18d
Compare
It needs some benchmarks. proc isNaN*(x: SomeFloat): bool {.inline.} =
## Returns whether `x` is a `NaN`, more efficiently than via `classify(x) == fcNan`.
## Does not work with: `--passc:-ffast-math`.
result = x != x
proc cisNAN*(x: float): bool {.importc: "isnan", header: "<math.h>".}
import criterion
var cfg = newDefaultConfig()
benchmark cfg:
proc tisNaN() {.measure.} =
doAssert not isNaN(1.0)
doAssert isNaN(NaN)
proc tcisNan() {.measure.} =
doAssert not cisNAN(1.0)
doAssert cisNAN(NaN) |
It seems to generate the same asm codes in release build. sub rsp, 56 #,
xor ecx, ecx #
mov QWORD PTR 40[rsp], 0 # MEM[(void *)&T1_], |
import math
proc isNaN*(x: SomeFloat): bool {.inline.} =
## Returns whether `x` is a `NaN`, more efficiently than via `classify(x) == fcNan`.
## Does not work with: `--passc:-ffast-math`.
result = x != x
proc cisNAN*(x: float): bool {.importc: "isnan", header: "<math.h>".}
proc isNaN2*(x: float): bool {.inline.} = classify(x) == fcNan
when true:
import math
import times
import random
template mainAux(fn) =
let n = 100_000_000
var x = 0
var list: seq[float]
for i in 0..<n:
let i2 = rand(int.high)
let a = cast[float](i2)
list.add a
let t = cpuTime()
for i in 0..<n:
let a = list[i]
x += cast[int](fn(a))
let t2 = cpuTime()
doAssert x != -1
echo (astToStr(fn), t2 - t, x, x / n)
proc main() =
for i in 0..<3:
echo (i,)
mainAux(cisNAN)
mainAux(isNaN)
mainAux(isNaN2)
main() nim r -d:danger main
one interesting point is that cisNAN works with --passc:-ffast-math; I'll need to see whether i can "disable" locally -ffast-math with push/pop Note: there's some slight statistical flaw in this benchmark, because whichever is first ( |
I look at the generated asm, they are the same proc tcisNan() =
let x1 = cisNaN(1.0)
echo x1
proc tisNaN() =
let x2 = isNaN(1.0)
echo x2
tisNaN()
tcisNan() asm codes sub rsp, 56 #,
xor ecx, ecx #
mov QWORD PTR 40[rsp], 0 # MEM[(void *)&T1_], |
PTAL
|
It seems to cause less friction if you also add |
based on #16179 (comment) this can be done in future work |
lib/std/cmath.nim
Outdated
Low level wrappers around C math functions. | ||
]## | ||
|
||
proc isnan*(x: float): bool {.importc: "isnan", header: "<math.h>".} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put this declaration in math.nim
and don't export it. And name it cisnan
or better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done (with c_isnan
) to unblock this PR but my plan is nim-lang/RFCs#92 (comment), can we continue this conversation there ? (already in an RFC)
2d21d34
to
949263a
Compare
PTAL |
949263a
to
ce1d6ff
Compare
ping (rebased after bitrot conflicts) |
8e22534
to
54d6e80
Compare
It's not clear to me if the CI failures are related. |
CI failure is related to #16297 (comment) |
54d6e80
to
40ca641
Compare
@Araq PTAL
I've reported the problem upstream and it's now fixed: https://todo.sr.ht/~sircmpwn/builds.sr.ht/312/#event-61438 |
* add math.isNaN * isNaN now works with --passc:-ffast-math; tests * Update lib/pure/math.nim Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
* add math.isNaN * isNaN now works with --passc:-ffast-math; tests * Update lib/pure/math.nim Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
as:
https://en.cppreference.com/w/c/numeric/math/isnan
https://numpy.org/doc/stable/reference/generated/numpy.isnan.html
etc
note
making isNaN work with
--passc:-ffast-math
is tricky (see also https://bugs.launchpad.net/mixxx/+bug/1524561); I made it work by wrapping cmath.isnan which I've added to a new module cmath, intended to grow (refs: nim-lang/RFCs#92)in particular:
{.localpassc:"-fno-fast-math”.}
would apply to whole module, and moving it to a different module with different compilation options would prevent inlining.So wrapping cmath.isnan was the simplest, and is also the most efficient in benchmark below.
future work
classify
work with--passc:-ffast-math
targets:"c js"
to tmath after fixing js bugsisFinite
etc)CI failure unrelated:
timotheecour#442