make mod on floats available in the VM (#9591)

* make `mod` on floats available in the VM
* add testcase
* removed no longer needed imports
This commit is contained in:
skilchen 2018-11-05 09:36:28 +01:00 • committed by Andreas Rumpf
commit da178e4090
2 changed files with 135 additions and 1 deletions

View file

@ -11,7 +11,7 @@
#import vmdeps, vm #import vmdeps, vm
from math import sqrt, ln, log10, log2, exp, round, arccos, arcsin, from math import sqrt, ln, log10, log2, exp, round, arccos, arcsin,
arctan, arctan2, cos, cosh, hypot, sinh, sin, tan, tanh, pow, trunc, arctan, arctan2, cos, cosh, hypot, sinh, sin, tan, tanh, pow, trunc,
floor, ceil, fmod floor, ceil, `mod`, fmod
from os import getEnv, existsEnv, dirExists, fileExists, putEnv, walkDir from os import getEnv, existsEnv, dirExists, fileExists, putEnv, walkDir
@ -107,6 +107,10 @@ proc registerAdditionalOps*(c: PCtx) =
wrap1f_math(ceil) wrap1f_math(ceil)
wrap2f_math(fmod) wrap2f_math(fmod)
proc `mod Wrapper`(a: VmArgs) {.nimcall.} =
setResult(a, `mod`(getFloat(a, 0), getFloat(a, 1)))
registerCallback(c, "stdlib.math.mod", `mod Wrapper`)
when defined(nimcore): when defined(nimcore):
wrap2s(getEnv, ospathsop) wrap2s(getEnv, ospathsop)
wrap1s(existsEnv, ospathsop) wrap1s(existsEnv, ospathsop)

130
tests/float/tfloatmod.nim Normal file
View file

@ -0,0 +1,130 @@
discard """
targets: "c c++ js"
output: "ok"
exitcode: "0"
"""
# Test `mod` on float64 both at compiletime and at runtime
import math
# Testdata from golang
const testValues: array[10, tuple[f64, expected: float64]] = [
(4.9790119248836735e+00, 4.197615023265299782906368e-02),
(7.7388724745781045e+00, 2.261127525421895434476482e+00),
(-2.7688005719200159e-01, 3.231794108794261433104108e-02),
(-5.0106036182710749e+00, 4.989396381728925078391512e+00),
(9.6362937071984173e+00, 3.637062928015826201999516e-01),
(2.9263772392439646e+00, 1.220868282268106064236690e+00),
(5.2290834314593066e+00, 4.770916568540693347699744e+00),
(2.7279399104360102e+00, 1.816180268691969246219742e+00),
(1.8253080916808550e+00, 8.734595415957246977711748e-01),
(-8.6859247685756013e+00, 1.314075231424398637614104e+00)]
const simpleTestData = [
(5.0, 3.0, 2.0),
(5.0, -3.0, 2.0),
(-5.0, 3.0, -2.0),
(-5.0, -3.0, -2.0),
(10.0, 1.0, 0.0),
(10.0, 0.5, 0.0),
(10.0, 1.5, 1.0),
(-10.0, 1.0, -0.0),
(-10.0, 0.5, -0.0),
(-10.0, 1.5, -1.0),
(1.5, 1.0, 0.5),
(1.25, 1.0, 0.25),
(1.125, 1.0, 0.125)
]
const specialCases = [
(-Inf, -Inf, Nan),
(-Inf, -Pi, Nan),
(-Inf, 0.0, Nan),
(-Inf, Pi, Nan),
(-Inf, Inf, Nan),
(-Inf, Nan, Nan),
(-PI, -Inf, -PI),
(-PI, 0.0, Nan),
(-PI, Inf, -PI),
(-PI, Nan, Nan),
(-0.0, -Inf, -0.0),
(-0.0, 0.0, Nan),
(-0.0, Inf, -0.0),
(-0.0, Nan, Nan),
(0.0, -Inf, 0.0),
(0.0, 0.0, Nan),
(0.0, Inf, 0.0),
(0.0, Nan, Nan),
(PI, -Inf, PI),
(PI, 0.0, Nan),
(PI, Inf, PI),
(PI, Nan, Nan),
(Inf, -Inf, Nan),
(Inf, -PI, Nan),
(Inf, 0.0, Nan),
(Inf, PI, Nan),
(Inf, Inf, Nan),
(Inf, Nan, Nan),
(Nan, -Inf, Nan),
(Nan, -PI, Nan),
(Nan, 0.0, Nan),
(Nan, PI, Nan),
(Nan, Inf, Nan),
(Nan, Nan, Nan)]
const extremeValues = [
(5.9790119248836734e+200, 1.1258465975523544, 0.6447968302508578),
(1.0e-100, 1.0e100, 1.0e-100)]
proc errmsg(x, y, r, expected: float64): string =
$x & " mod " & $y & " == " & $r & " but expected " & $expected
proc golangtest() =
let x = 10.0
for tpl in testValues:
let (y, expected) = tpl
let r = x mod y
doAssert(r == expected, errmsg(x, y, r, expected))
proc simpletest() =
for tpl in simpleTestData:
let(x, y, expected) = tpl
let r = x mod y
doAssert(r == expected, errmsg(x, y, r, expected))
proc testSpecialCases() =
proc isnan(f: float64): bool =
case classify(f)
of fcNan:
result = true
else:
result = false
for tpl in specialCases:
let(x, y, expected) = tpl
let r = x mod y
doAssert((r == expected) or (r.isnan and expected.isnan),
errmsg(x, y, r, expected))
proc testExtremeValues() =
for tpl in extremeValues:
let (x, y, expected) = tpl
let r = x mod y
doAssert(r == expected, errmsg(x, y, r, expected))
static:
# compiletime evaluation
golangtest()
simpletest()
testSpecialCases()
testExtremeValues()
proc main() =
# runtime evaluation
golangtest()
simpletest()
testSpecialCases()
testExtremeValues()
main()
echo "ok"