diff --git a/changelog.md b/changelog.md index c2a146c01c..a74e06373a 100644 --- a/changelog.md +++ b/changelog.md @@ -73,6 +73,8 @@ - Added `sequtils` import to `prelude`. +- Added `euclDiv` and `euclMod` to `math`. + ## Language changes - `nimscript` now handles `except Exception as e`. diff --git a/lib/pure/math.nim b/lib/pure/math.nim index c05e47545e..5b19a8ec00 100644 --- a/lib/pure/math.nim +++ b/lib/pure/math.nim @@ -882,6 +882,32 @@ func floorMod*[T: SomeNumber](x, y: T): T = result = x mod y if (result > 0 and y < 0) or (result < 0 and y > 0): result += y +func euclDiv*[T: SomeInteger](x, y: T): T {.since: (1, 5, 1).} = + ## Returns euclidean division of `x` by `y`. + runnableExamples: + assert euclDiv(13, 3) == 4 + assert euclDiv(-13, 3) == -5 + assert euclDiv(13, -3) == -4 + assert euclDiv(-13, -3) == 5 + result = x div y + if x mod y < 0: + if y > 0: + dec result + else: + inc result + +func euclMod*[T: SomeNumber](x, y: T): T {.since: (1, 5, 1).} = + ## Returns euclidean modulo of `x` by `y`. + ## `euclMod(x, y)` is non-negative. + runnableExamples: + assert euclMod(13, 3) == 1 + assert euclMod(-13, 3) == 2 + assert euclMod(13, -3) == 1 + assert euclMod(-13, -3) == 2 + result = x mod y + if result < 0: + result += abs(y) + when not defined(js): func c_frexp*(x: float32, exponent: var int32): float32 {. importc: "frexp", header: "".} diff --git a/tests/stdlib/tmath.nim b/tests/stdlib/tmath.nim index 18e42cbdcb..43d19f9e0b 100644 --- a/tests/stdlib/tmath.nim +++ b/tests/stdlib/tmath.nim @@ -270,6 +270,34 @@ block: doAssert floorMod(8.0, -3.0) ==~ -1.0 doAssert floorMod(-8.5, 3.0) ==~ 0.5 + block: # euclDiv/euclMod + doAssert euclDiv(8, 3) == 2 + doAssert euclMod(8, 3) == 2 + + doAssert euclDiv(8, -3) == -2 + doAssert euclMod(8, -3) == 2 + + doAssert euclDiv(-8, 3) == -3 + doAssert euclMod(-8, 3) == 1 + + doAssert euclDiv(-8, -3) == 3 + doAssert euclMod(-8, -3) == 1 + + doAssert euclMod(8.0, -3.0) ==~ 2.0 + doAssert euclMod(-8.5, 3.0) ==~ 0.5 + + doAssert euclDiv(9, 3) == 3 + doAssert euclMod(9, 3) == 0 + + doAssert euclDiv(9, -3) == -3 + doAssert euclMod(9, -3) == 0 + + doAssert euclDiv(-9, 3) == -3 + doAssert euclMod(-9, 3) == 0 + + doAssert euclDiv(-9, -3) == 3 + doAssert euclMod(-9, -3) == 0 + block: # log doAssert log(4.0, 3.0) ==~ ln(4.0) / ln(3.0) doAssert log2(8.0'f64) == 3.0'f64