Support div, mod, floorDiv and floorMod for Rationals (#7918)

* Support `div`, `mod`, floorDiv and floorMod for Ratinoals.

* Bug fix and add tests.

* Update changelog
This commit is contained in:
Koki Fushimi
2018-06-02 00:19:25 +09:00
committed by Varriount
parent 829f89d649
commit 3027ca292c
2 changed files with 37 additions and 0 deletions

View File

@@ -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

View File

@@ -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