summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--changelog.md5
-rw-r--r--lib/pure/math.nim12
-rw-r--r--tests/stdlib/tmath.nim30
3 files changed, 40 insertions, 7 deletions
diff --git a/changelog.md b/changelog.md
index b97fcdd03..306cf54d3 100644
--- a/changelog.md
+++ b/changelog.md
@@ -84,13 +84,14 @@
 - Added `mimetypes.mimesExtMaxLen` thats equal to the length of the longest "ext" from `mimes`.
 - Added `mimetypes.mimesMaxLen` thats equal to the length of the longest "mime" from `mimes`.
 
-
-
 - Added `posix_utils.osReleaseFile` to get system identification from `os-release` file on Linux and the BSDs.
   https://www.freedesktop.org/software/systemd/man/os-release.html
 
 - Added `BackwardsIndex` overload for `JsonNode`.
 
+- `math.round` now is rounded "away from zero" in JS backend which is consistent
+with other backends. see #9125. Use `-d:nimLegacyJsRound` for previous behavior.
+
 
 ## Language changes
 
diff --git a/lib/pure/math.nim b/lib/pure/math.nim
index 76052ec3b..a6a3676b9 100644
--- a/lib/pure/math.nim
+++ b/lib/pure/math.nim
@@ -847,7 +847,17 @@ else: # JS
   func floor*(x: float64): float64 {.importc: "Math.floor", nodecl.}
   func ceil*(x: float32): float32 {.importc: "Math.ceil", nodecl.}
   func ceil*(x: float64): float64 {.importc: "Math.ceil", nodecl.}
-  func round*(x: float): float {.importc: "Math.round", nodecl.}
+
+  when (NimMajor, NimMinor) < (1, 5) or defined(nimLegacyJsRound):
+    func round*(x: float): float {.importc: "Math.round", nodecl.}
+  else:
+    func jsRound(x: float): float {.importc: "Math.round", nodecl.}
+    func round*[T: float64 | float32](x: T): T =
+      if x >= 0: result = jsRound(x)
+      else:
+        result = ceil(x)
+        if result - x >= T(0.5):
+          result -= T(1.0)
   func trunc*(x: float32): float32 {.importc: "Math.trunc", nodecl.}
   func trunc*(x: float64): float64 {.importc: "Math.trunc", nodecl.}
 
diff --git a/tests/stdlib/tmath.nim b/tests/stdlib/tmath.nim
index fbc6b80ad..e5cb58eba 100644
--- a/tests/stdlib/tmath.nim
+++ b/tests/stdlib/tmath.nim
@@ -10,6 +10,10 @@ import std/[math, random, os]
 import std/[unittest]
 import std/[sets, tables]
 
+
+# Function for approximate comparison of floats
+proc `==~`(x, y: float): bool = (abs(x-y) < 1e-9)
+
 block: # random int
   block: # there might be some randomness
     var set = initHashSet[int](128)
@@ -158,10 +162,6 @@ block:
     doAssert(erf(6.0) > erf(5.0))
     doAssert(erfc(6.0) < erfc(5.0))
 
-    proc `==~`(x, y: float): bool = (abs(x-y) < 1e-9)
-      # Function for approximate comparison of floats
-      # xxx use `almostEqual`
-
     block: # prod
       doAssert prod([1, 2, 3, 4]) == 24
       doAssert prod([1.5, 3.4]).almostEqual 5.1
@@ -349,6 +349,28 @@ template main =
     doAssert copySign(-NaN, 0.0).isNaN
     doAssert copySign(-NaN, -0.0).isNaN
 
+    block: # round() tests
+      # Round to 0 decimal places
+      doAssert round(54.652) == 55.0
+      doAssert round(54.352) == 54.0
+      doAssert round(-54.652) == -55.0
+      doAssert round(-54.352) == -54.0
+      doAssert round(0.0) == 0.0
+      doAssert 1 / round(0.0) == Inf
+      doAssert 1 / round(-0.0) == -Inf
+      doAssert round(Inf) == Inf
+      doAssert round(-Inf) == -Inf
+      doAssert round(NaN).isNaN
+      doAssert round(-NaN).isNaN
+      doAssert round(-0.5) == -1.0
+      doAssert round(0.5) == 1.0
+      doAssert round(-1.5) == -2.0
+      doAssert round(1.5) == 2.0
+      doAssert round(-2.5) == -3.0
+      doAssert round(2.5) == 3.0
+      doAssert round(2.5'f32) == 3.0'f32
+      doAssert round(2.5'f64) == 3.0'f64
+
     when nimvm:
       discard
     else: