add math.signbit (#16592)

This commit is contained in:
flywind 2021-01-07 01:48:02 -06:00 • committed by GitHub
commit bab0aa6ecf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 45 additions and 1 deletions

View file

@ -93,6 +93,9 @@
with other backends. see #9125. Use `-d:nimLegacyJsRound` for previous behavior. with other backends. see #9125. Use `-d:nimLegacyJsRound` for previous behavior.
- Added `math.signbit`.
## Language changes ## Language changes
- `nimscript` now handles `except Exception as e`. - `nimscript` now handles `except Exception as e`.

View file

@ -16,6 +16,9 @@ from math import sqrt, ln, log10, log2, exp, round, arccos, arcsin,
when declared(math.copySign): when declared(math.copySign):
from math import copySign from math import copySign
when declared(math.signbit):
from math import signbit
from os import getEnv, existsEnv, dirExists, fileExists, putEnv, walkDir, getAppFilename from os import getEnv, existsEnv, dirExists, fileExists, putEnv, walkDir, getAppFilename
from md5 import getMD5 from md5 import getMD5
from sighashes import symBodyDigest from sighashes import symBodyDigest
@ -174,6 +177,9 @@ proc registerAdditionalOps*(c: PCtx) =
when declared(copySign): when declared(copySign):
wrap2f_math(copySign) wrap2f_math(copySign)
when declared(signbit):
wrap1f_math(signbit)
wrap1s(getMD5, md5op) wrap1s(getMD5, md5op)
proc `mod Wrapper`(a: VmArgs) {.nimcall.} = proc `mod Wrapper`(a: VmArgs) {.nimcall.} =

View file

@ -56,7 +56,7 @@ import std/private/since
{.push debugger: off.} # the user does not want to trace a part {.push debugger: off.} # the user does not want to trace a part
# of the standard library! # of the standard library!
import bitops, fenv import std/[bitops, fenv]
when defined(c) or defined(cpp): when defined(c) or defined(cpp):
proc c_isnan(x: float): bool {.importc: "isnan", header: "<math.h>".} proc c_isnan(x: float): bool {.importc: "isnan", header: "<math.h>".}
@ -65,6 +65,8 @@ when defined(c) or defined(cpp):
proc c_copysign(x, y: cfloat): cfloat {.importc: "copysignf", header: "<math.h>".} proc c_copysign(x, y: cfloat): cfloat {.importc: "copysignf", header: "<math.h>".}
proc c_copysign(x, y: cdouble): cdouble {.importc: "copysign", header: "<math.h>".} proc c_copysign(x, y: cdouble): cdouble {.importc: "copysign", header: "<math.h>".}
proc c_signbit(x: SomeFloat): cint {.importc: "signbit", header: "<math.h>".}
func binom*(n, k: int): int = func binom*(n, k: int): int =
## Computes the `binomial coefficient <https://en.wikipedia.org/wiki/Binomial_coefficient>`_. ## Computes the `binomial coefficient <https://en.wikipedia.org/wiki/Binomial_coefficient>`_.
runnableExamples: runnableExamples:
@ -156,6 +158,29 @@ func isNaN*(x: SomeFloat): bool {.inline, since: (1,5,1).} =
when defined(js): fn() when defined(js): fn()
else: result = c_isnan(x) else: result = c_isnan(x)
when defined(js):
proc toBitsImpl(x: float): array[2, uint32] =
asm """
const buffer = new ArrayBuffer(8);
const floatBuffer = new Float64Array(buffer);
const uintBuffer = new Uint32Array(buffer);
floatBuffer[0] = `x`;
`result` = uintBuffer
"""
proc signbit*(x: SomeFloat): bool {.inline, since: (1, 5, 1).} =
## Returns true if `x` is negative, false otherwise.
runnableExamples:
doAssert not signbit(0.0)
doAssert signbit(-0.0)
doAssert signbit(-0.1)
doAssert not signbit(0.1)
when defined(js):
let uintBuffer = toBitsImpl(x)
result = (uintBuffer[1] shr 31) != 0
else:
result = c_signbit(x) != 0
func copySign*[T: SomeFloat](x, y: T): T {.inline, since: (1, 5, 1).} = func copySign*[T: SomeFloat](x, y: T): T {.inline, since: (1, 5, 1).} =
## Returns a value with the magnitude of `x` and the sign of `y`; ## Returns a value with the magnitude of `x` and the sign of `y`;
## this works even if x or y are NaN or zero, both of which can carry a sign. ## this works even if x or y are NaN or zero, both of which can carry a sign.

View file

@ -304,6 +304,16 @@ block:
template main = template main =
# xxx wrap all under `main` so it also gets tested in vm. # xxx wrap all under `main` so it also gets tested in vm.
block: # signbit
doAssert not signbit(0.0)
doAssert signbit(-0.0)
doAssert signbit(-0.1)
doAssert not signbit(0.1)
doAssert not signbit(Inf)
doAssert signbit(-Inf)
doAssert not signbit(NaN)
block: # isNaN block: # isNaN
doAssert NaN.isNaN doAssert NaN.isNaN
doAssert not Inf.isNaN doAssert not Inf.isNaN