summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKoki Fushimi <paalon1936@gmail.com>2018-06-02 00:19:25 +0900
committerVarriount <Varriount@users.noreply.github.com>2018-06-01 11:19:25 -0400
commit3027ca292c3fbdb5387d0b8834c7e3dc960df75d (patch)
treeebc28d12e9bfe76e573d308ee7a22411c7c963cd
parent829f89d6491302072ec1b1153d34dc07361f9fbb (diff)
downloadNim-3027ca292c3fbdb5387d0b8834c7e3dc960df75d.tar.gz
Support `div`, `mod`, floorDiv and floorMod for Rationals (#7918)
* Support `div`, `mod`, floorDiv and floorMod for Ratinoals.

* Bug fix and add tests.

* Update changelog
-rw-r--r--changelog.md1
-rw-r--r--lib/pure/rationals.nim36
2 files changed, 37 insertions, 0 deletions
diff --git a/changelog.md b/changelog.md
index 2bbfd01f6..514bfbaca 100644
--- a/changelog.md
+++ b/changelog.md
@@ -64,6 +64,7 @@
 - Added inverse hyperbolic functions, ``math.arcsinh``, ``math.arccosh`` and ``math.arctanh`` procs.
 - Added cotangent, secant and cosecant procs ``math.cot``, ``math.sec`` and ``math.csc``; and their hyperbolic, inverse and inverse hyperbolic functions, ``math.coth``, ``math.sech``, ``math.csch``, ``math.arccot``, ``math.arcsec``, ``math.arccsc``, ``math.arccoth``, ``math.arcsech`` and ``math.arccsch`` procs.
 - Added the procs ``math.floorMod`` and ``math.floorDiv`` for floor based integer division.
+- Added the procs ``rationals.`div```, ``rationals.`mod```, ``rationals.floorDiv`` and ``rationals.floorMod`` for rationals.
 
 ### Library changes
 
diff --git a/lib/pure/rationals.nim b/lib/pure/rationals.nim
index 7907b4e6c..3946cf85b 100644
--- a/lib/pure/rationals.nim
+++ b/lib/pure/rationals.nim
@@ -241,6 +241,33 @@ proc abs*[T](x: Rational[T]): Rational[T] =
   result.num = abs x.num
   result.den = abs x.den
 
+proc `div`*[T: SomeInteger](x, y: Rational[T]): T =
+  ## Computes the rational truncated division.
+  (x.num * y.den) div (y.num * x.den)
+
+proc `mod`*[T: SomeInteger](x, y: Rational[T]): Rational[T] =
+  ## Computes the rational modulo by truncated division (remainder).
+  ## This is same as ``x - (x div y) * y``.
+  result = ((x.num * y.den) mod (y.num * x.den)) // (x.den * y.den)
+  reduce(result)
+
+proc floorDiv*[T: SomeInteger](x, y: Rational[T]): T =
+  ## Computes the rational floor division.
+  ##
+  ## Floor division is conceptually defined as ``floor(x / y)``.
+  ## This is different from the ``div`` operator, which is defined
+  ## as ``trunc(x / y)``. That is, ``div`` rounds towards ``0`` and ``floorDiv``
+  ## rounds down.
+  floorDiv(x.num * y.den, y.num * x.den)
+
+proc floorMod*[T: SomeInteger](x, y: Rational[T]): Rational[T] =
+  ## Computes the rational modulo by floor division (modulo).
+  ##
+  ## This is same as ``x - floorDiv(x, y) * y``.
+  ## This proc behaves the same as the ``%`` operator in python.
+  result = floorMod(x.num * y.den, y.num * x.den) // (x.den * y.den)
+  reduce(result)
+
 proc hash*[T](x: Rational[T]): Hash =
   ## Computes hash for rational `x`
   # reduce first so that hash(x) == hash(y) for x == y
@@ -339,3 +366,12 @@ when isMainModule:
   assert toRational(0.33) == 33 // 100
   assert toRational(0.22) == 11 // 50
   assert toRational(10.0) == 10 // 1
+
+  assert (1//1) div (3//10) == 3
+  assert (-1//1) div (3//10) == -3
+  assert (3//10) mod (1//1) == 3//10
+  assert (-3//10) mod (1//1) == -3//10
+  assert floorDiv(1//1, 3//10) == 3
+  assert floorDiv(-1//1, 3//10) == -4
+  assert floorMod(3//10, 1//1) == 3//10
+  assert floorMod(-3//10, 1//1) == 7//10