Skip to content
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

Merged
merged 17 commits into from
Dec 30, 2020
Merged

Add math.copySign #16406

merged 17 commits into from
Dec 30, 2020

Conversation

ringabout
Copy link
Member

@ringabout ringabout commented Dec 20, 2020

lib/pure/math.nim Outdated Show resolved Hide resolved
lib/pure/math.nim Outdated Show resolved Hide resolved
@ringabout
Copy link
Member Author

ringabout commented Dec 21, 2020

  • remove generics C function
  • add VM version

lib/pure/math.nim Outdated Show resolved Hide resolved
@ringabout ringabout marked this pull request as draft December 21, 2020 11:18
@ringabout
Copy link
Member Author

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()

@ringabout
Copy link
Member Author

Why I can't register a VM verision of copySign?
Error: undeclared identifier: 'copySign'
FAILURE
https://builds.sr.ht/~araq/job/377122

@timotheecour
Copy link
Member

timotheecour commented Dec 25, 2020

P1

Why I can't register a VM verision of copySign?

because of bootstrap (building from 0.20.0, which disables {.since: (1,5,1).}), you can reproduce this locally with:

rm bin/nim_csources
rm bin/nim
sh build_all.sh

or even simpler: bin/nim_csources c --lib:lib compiler/nim.nim

solution:
in vmops.nim:

# on top
when declared(math.copySign):
  from math import copySign

# in registerAdditionalOps:
  when declared(copySign):
    wrap2f_math(copySign)

this works.
(refs #11865 and #14648 which would've simplified this a bit)

P2

But after that, there's another issue,

nim r tests/stdlib/tmath.nim will fail at CT with:
doAssert copySign(-1.0, 0.0) == 1.0

after debugging by adding debugEcho (x, y, $T) inside copySign, it shows:
(-1.0, -0.0, "BiggestFloat")

so looks like 0.0 is interpreted as -0.0 in VM for some reason.

EDIT: fixing P2 in #16470

@timotheecour
Copy link
Member

now that P2 was fixed (refs #16406 (comment)), I guess this PR can be continued?

@ringabout
Copy link
Member Author

I will continue this PR soon.

@ringabout ringabout marked this pull request as ready for review December 28, 2020 14:28
@ringabout ringabout marked this pull request as draft December 28, 2020 14:29
@ringabout ringabout marked this pull request as ready for review December 28, 2020 14:30
lib/pure/math.nim Outdated Show resolved Hide resolved
lib/pure/math.nim Outdated Show resolved Hide resolved
lib/pure/math.nim Outdated Show resolved Hide resolved
lib/pure/math.nim Outdated Show resolved Hide resolved
lib/pure/math.nim Outdated Show resolved Hide resolved
@timotheecour timotheecour changed the title Add copysign Add math.copySign Dec 28, 2020
lib/pure/math.nim Outdated Show resolved Hide resolved
discard
else:
when not defined(js):
doAssert copySign(-1.0, -NaN) == 1.0
Copy link
Member

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
Copy link
Member

@timotheecour timotheecour Dec 29, 2020

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)

Copy link
Member Author

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.

Copy link
Member Author

@ringabout ringabout Dec 29, 2020

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.

Copy link
Member

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
Copy link
Member

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

Copy link
Member Author

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)

Copy link
Member

@timotheecour timotheecour left a 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):
Copy link
Member

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)

@Araq Araq merged commit 515cd45 into nim-lang:devel Dec 30, 2020
@timotheecour timotheecour mentioned this pull request Dec 30, 2020
1 task
mildred pushed a commit to mildred/Nim that referenced this pull request Jan 11, 2021
* add math.copySign
* fix + tests
ardek66 pushed a commit to ardek66/Nim that referenced this pull request Mar 26, 2021
* add math.copySign
* fix + tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants