summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorRyan McConnell <rammcconnell@gmail.com>2023-06-20 07:04:34 -0400
committerGitHub <noreply@github.com>2023-06-20 13:04:34 +0200
commitdb41f04ab0734b0ac5267b46f306b0a311f7fc71 (patch)
tree3ceaa2f63c45bfd498f7fa3c747b6c813a6b7c0e
parentf524d60fa1e1c3a3722632e2a01bf93c6cb02e88 (diff)
downloadNim-db41f04ab0734b0ac5267b46f306b0a311f7fc71.tar.gz
Amend divmod (#22131)
* Add Overflow checks & test adjust

* Avoiding nimvm differences in tests

* distinguish DivByZeroDefect
-rw-r--r--lib/pure/math.nim7
-rw-r--r--tests/stdlib/tmath.nim15
2 files changed, 17 insertions, 5 deletions
diff --git a/lib/pure/math.nim b/lib/pure/math.nim
index 7ed84fa71..4bc720a46 100644
--- a/lib/pure/math.nim
+++ b/lib/pure/math.nim
@@ -101,6 +101,11 @@ when defined(c) or defined(cpp):
       doAssert divmod(5, 2) == (2, 1)
       doAssert divmod(5, -3) == (-1, 2)
     when T is cint | clong | clonglong:
+      when compileOption("overflowChecks"):
+        if y == 0:
+          raise new(DivByZeroDefect)
+        elif (x == T.low and y == -1.T):
+          raise new(OverflowDefect)
       let res = divmod_c(x, y)
       result[0] = res.quot
       result[1] = res.rem
@@ -824,7 +829,7 @@ else: # JS
       doAssert  6.5 mod -2.5 ==  1.5
       doAssert -6.5 mod -2.5 == -1.5
   
-  func divmod*(num, denom: int): (int, int) = 
+  func divmod*[T:SomeInteger](num, denom: T): (T, T) = 
     runnableExamples:
       doAssert  divmod(5, 2) ==  (2, 1)
       doAssert divmod(5, -3) == (-1, 2)
diff --git a/tests/stdlib/tmath.nim b/tests/stdlib/tmath.nim
index 3fcc42ae8..22e5f7d88 100644
--- a/tests/stdlib/tmath.nim
+++ b/tests/stdlib/tmath.nim
@@ -190,10 +190,17 @@ template main() =
   block: # divmod
     doAssert divmod(int.high, 1) == (int.high, 0)
     doAssert divmod(-1073741823, 17) == (-63161283, -12)
-    when not defined(js):
-      doAssert divmod(int32.high, 1.int32) == (int32.high, 0.int32)
-      doAssert divmod(1073741823.int32, 5.int32) == (214748364.int32, 3.int32)
-      doAssert divmod(4611686018427387903.int64, 5.int64) == (922337203685477580.int64, 3.int64)
+    doAssert divmod(int32.high, 1.int32) == (int32.high, 0.int32)
+    doAssert divmod(1073741823.int32, 5.int32) == (214748364.int32, 3.int32)
+    doAssert divmod(4611686018427387903.int64, 5.int64) == (922337203685477580.int64, 3.int64)
+    when not defined(js) and (not compileOption("panics")) and compileOption("overflowChecks"):
+      when nimvm:
+        discard # cannot catch OverflowDefect here
+      else:
+        doAssertRaises(OverflowDefect, (discard divmod(cint.low, -1.cint)))
+        doAssertRaises(OverflowDefect, (discard divmod(clong.low, -1.clong)))
+        doAssertRaises(OverflowDefect, (discard divmod(clonglong.low, -1.clonglong)))
+        doAssertRaises(DivByZeroDefect, (discard divmod(1, 0)))
   
   block: # log
     doAssert log(4.0, 3.0) ==~ ln(4.0) / ln(3.0)