-
-
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.copySign #16406
Add math.copySign #16406
Conversation
|
Better implementation for JS backend import math
proc copysign(x, y: float): float =
if y > 0.0 or (y == 0.0 and 1.0 / y > 0.0):
result = abs(x)
else:
result = -abs(x)
proc main() =
echo copySign(3.0, 0.0)
echo copySign(3.0, -0.0)
static: main()
main() |
Why I can't register a VM verision of |
P1
because of bootstrap (building from 0.20.0, which disables rm bin/nim_csources
rm bin/nim
sh build_all.sh or even simpler: solution: # on top
when declared(math.copySign):
from math import copySign
# in registerAdditionalOps:
when declared(copySign):
wrap2f_math(copySign) this works. P2But after that, there's another issue,
after debugging by adding so looks like 0.0 is interpreted as -0.0 in VM for some reason. EDIT: fixing P2 in #16470 |
now that P2 was fixed (refs #16406 (comment)), I guess this PR can be continued? |
I will continue this PR soon. |
discard | ||
else: | ||
when not defined(js): | ||
doAssert copySign(-1.0, -NaN) == 1.0 |
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.
until timotheecour#499 is fixed, this test is meaningless:
doAssert copySign(-1.0, -NaN) == 1.0
doAssert copySign(-1.0, NaN) == 1.0
both pass currently, which is not correct behavior IMO
IMO doAssert copySign(-1.0, NaN) == 1.0
is probably correct (we can check with signbit once we have it), but doAssert copySign(-1.0, -NaN) == 1.0
is probably not correct, and should be:
when false: # xxx bug
doAssert copySign(-1.0, -NaN) == -1.0
likewise with doAssert copySign(10.0, -NaN) == 10.0
when not defined(js): | ||
doAssert copySign(-1.0, -NaN) == 1.0 | ||
doAssert copySign(10.0, -NaN) == 10.0 | ||
doAssert copySign(1.0, copySign(NaN, -1.0)) == -1.0 # fails in VM |
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.
this test actually works in VM so long nim is compiled after this PR.
Simplest is to defined nimHasCopySign
in condsyms.nim and then:
template fn() = doAssert copySign(1.0, copySign(NaN, -1.0)) == -1.0
when defined(js): discard # xxx bug
else:
when defined(nimHasCopySign): fn()
else:
when nimvm: discard
else: fn()
(refs timotheecour#498)
note, the same nimHasCopySign
could be re-used in your other math PR's that need vmops to avoid creating too many condsyms symbols (until we finally reconsider the much better nimVersionCT
approach, refs #14648)
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.
I would rather make a follow-up PR to enable this test.
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.
And tmath.nim
should support JS, I could try to enable JS tests(at least for copySign) in the next PR.
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.
ya we definitely need this (in another PR as you say); refs timotheecour#494 (comment) ; it just requires a few disabling's for js to work (and vm already works)
doAssert copySign(-1.0, NaN) == 1.0 | ||
doAssert copySign(10.0, NaN) == 10.0 | ||
|
||
doAssert copySign(NaN, 0.0).isNaN | ||
doAssert copySign(NaN, -0.0).isNaN | ||
|
||
# fails in VM and JS backend |
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.
it won't fail in VM for a nim binary compiled after your PR
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.
The same story as #16406 (comment)
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.
LGTM, remaining comments can be addressed in followup PR's
|
||
# TODO use signbit for examples | ||
template impl() = | ||
if y > 0.0 or (y == 0.0 and 1.0 / y > 0.0): |
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.
better code for js via Object.is, see #16505 (comment)
* add math.copySign * fix + tests
* add math.copySign * fix + tests
ref nim-lang/RFCs#92
C99 function
http://www.cplusplus.com/reference/cmath/copysign/
Python:
https://docs.python.org/3/library/math.html#math.copysign
Crystal:
https://github.com/crystal-lang/crystal/blob/5999ae29beacf4cfd54e232ca83c1a46b79f26a5/src/math/math.cr#L95
Dlang:
https://dlang.org/library/std/math/copysign.html
Rust:
https://doc.rust-lang.org/beta/std/primitive.f64.html#method.copysign
sgn
is uglyhttps://stackoverflow.com/questions/1986152/why-doesnt-python-have-a-sign-function
And
copysign
is more usefulhttps://bugs.python.org/msg59154