rationals.nim: Use func everywhere (#16302)

This commit is contained in:
ee7 2020-12-09 16:17:50 +01:00 • committed by GitHub
commit 87e634aab3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 41 deletions

View file

@ -18,28 +18,28 @@ type Rational*[T] = object
## a rational number, consisting of a numerator and denominator ## a rational number, consisting of a numerator and denominator
num*, den*: T num*, den*: T
proc initRational*[T: SomeInteger](num, den: T): Rational[T] = func initRational*[T: SomeInteger](num, den: T): Rational[T] =
## Create a new rational number. ## Create a new rational number.
assert(den != 0, "a denominator of zero value is invalid") assert(den != 0, "a denominator of zero value is invalid")
result.num = num result.num = num
result.den = den result.den = den
proc `//`*[T](num, den: T): Rational[T] = initRational[T](num, den) func `//`*[T](num, den: T): Rational[T] = initRational[T](num, den)
## A friendlier version of `initRational`. Example usage: ## A friendlier version of `initRational`. Example usage:
## ##
## .. code-block:: nim ## .. code-block:: nim
## var x = 1//3 + 1//5 ## var x = 1//3 + 1//5
proc `$`*[T](x: Rational[T]): string = func `$`*[T](x: Rational[T]): string =
## Turn a rational number into a string. ## Turn a rational number into a string.
result = $x.num & "/" & $x.den result = $x.num & "/" & $x.den
proc toRational*[T: SomeInteger](x: T): Rational[T] = func toRational*[T: SomeInteger](x: T): Rational[T] =
## Convert some integer `x` to a rational number. ## Convert some integer `x` to a rational number.
result.num = x result.num = x
result.den = 1 result.den = 1
proc toRational*(x: float, func toRational*(x: float,
n: int = high(int) shr (sizeof(int) div 2 * 8)): Rational[int] = n: int = high(int) shr (sizeof(int) div 2 * 8)): Rational[int] =
## Calculates the best rational numerator and denominator ## Calculates the best rational numerator and denominator
## that approximates to `x`, where the denominator is ## that approximates to `x`, where the denominator is
@ -74,16 +74,16 @@ proc toRational*(x: float,
ai = int(x) ai = int(x)
result = m11 // m21 result = m11 // m21
proc toFloat*[T](x: Rational[T]): float = func toFloat*[T](x: Rational[T]): float =
## Convert a rational number `x` to a float. ## Convert a rational number `x` to a float.
x.num / x.den x.num / x.den
proc toInt*[T](x: Rational[T]): int = func toInt*[T](x: Rational[T]): int =
## Convert a rational number `x` to an int. Conversion rounds towards 0 if ## Convert a rational number `x` to an int. Conversion rounds towards 0 if
## `x` does not contain an integer value. ## `x` does not contain an integer value.
x.num div x.den x.num div x.den
proc reduce*[T: SomeInteger](x: var Rational[T]) = func reduce*[T: SomeInteger](x: var Rational[T]) =
## Reduce rational `x`. ## Reduce rational `x`.
let common = gcd(x.num, x.den) let common = gcd(x.num, x.den)
if x.den > 0: if x.den > 0:
@ -95,97 +95,97 @@ proc reduce*[T: SomeInteger](x: var Rational[T]) =
else: else:
raise newException(DivByZeroDefect, "division by zero") raise newException(DivByZeroDefect, "division by zero")
proc `+` *[T](x, y: Rational[T]): Rational[T] = func `+` *[T](x, y: Rational[T]): Rational[T] =
## Add two rational numbers. ## Add two rational numbers.
let common = lcm(x.den, y.den) let common = lcm(x.den, y.den)
result.num = common div x.den * x.num + common div y.den * y.num result.num = common div x.den * x.num + common div y.den * y.num
result.den = common result.den = common
reduce(result) reduce(result)
proc `+` *[T](x: Rational[T], y: T): Rational[T] = func `+` *[T](x: Rational[T], y: T): Rational[T] =
## Add rational `x` to int `y`. ## Add rational `x` to int `y`.
result.num = x.num + y * x.den result.num = x.num + y * x.den
result.den = x.den result.den = x.den
proc `+` *[T](x: T, y: Rational[T]): Rational[T] = func `+` *[T](x: T, y: Rational[T]): Rational[T] =
## Add int `x` to rational `y`. ## Add int `x` to rational `y`.
result.num = x * y.den + y.num result.num = x * y.den + y.num
result.den = y.den result.den = y.den
proc `+=` *[T](x: var Rational[T], y: Rational[T]) = func `+=` *[T](x: var Rational[T], y: Rational[T]) =
## Add rational `y` to rational `x`. ## Add rational `y` to rational `x`.
let common = lcm(x.den, y.den) let common = lcm(x.den, y.den)
x.num = common div x.den * x.num + common div y.den * y.num x.num = common div x.den * x.num + common div y.den * y.num
x.den = common x.den = common
reduce(x) reduce(x)
proc `+=` *[T](x: var Rational[T], y: T) = func `+=` *[T](x: var Rational[T], y: T) =
## Add int `y` to rational `x`. ## Add int `y` to rational `x`.
x.num += y * x.den x.num += y * x.den
proc `-` *[T](x: Rational[T]): Rational[T] = func `-` *[T](x: Rational[T]): Rational[T] =
## Unary minus for rational numbers. ## Unary minus for rational numbers.
result.num = -x.num result.num = -x.num
result.den = x.den result.den = x.den
proc `-` *[T](x, y: Rational[T]): Rational[T] = func `-` *[T](x, y: Rational[T]): Rational[T] =
## Subtract two rational numbers. ## Subtract two rational numbers.
let common = lcm(x.den, y.den) let common = lcm(x.den, y.den)
result.num = common div x.den * x.num - common div y.den * y.num result.num = common div x.den * x.num - common div y.den * y.num
result.den = common result.den = common
reduce(result) reduce(result)
proc `-` *[T](x: Rational[T], y: T): Rational[T] = func `-` *[T](x: Rational[T], y: T): Rational[T] =
## Subtract int `y` from rational `x`. ## Subtract int `y` from rational `x`.
result.num = x.num - y * x.den result.num = x.num - y * x.den
result.den = x.den result.den = x.den
proc `-` *[T](x: T, y: Rational[T]): Rational[T] = func `-` *[T](x: T, y: Rational[T]): Rational[T] =
## Subtract rational `y` from int `x`. ## Subtract rational `y` from int `x`.
result.num = x * y.den - y.num result.num = x * y.den - y.num
result.den = y.den result.den = y.den
proc `-=` *[T](x: var Rational[T], y: Rational[T]) = func `-=` *[T](x: var Rational[T], y: Rational[T]) =
## Subtract rational `y` from rational `x`. ## Subtract rational `y` from rational `x`.
let common = lcm(x.den, y.den) let common = lcm(x.den, y.den)
x.num = common div x.den * x.num - common div y.den * y.num x.num = common div x.den * x.num - common div y.den * y.num
x.den = common x.den = common
reduce(x) reduce(x)
proc `-=` *[T](x: var Rational[T], y: T) = func `-=` *[T](x: var Rational[T], y: T) =
## Subtract int `y` from rational `x`. ## Subtract int `y` from rational `x`.
x.num -= y * x.den x.num -= y * x.den
proc `*` *[T](x, y: Rational[T]): Rational[T] = func `*` *[T](x, y: Rational[T]): Rational[T] =
## Multiply two rational numbers. ## Multiply two rational numbers.
result.num = x.num * y.num result.num = x.num * y.num
result.den = x.den * y.den result.den = x.den * y.den
reduce(result) reduce(result)
proc `*` *[T](x: Rational[T], y: T): Rational[T] = func `*` *[T](x: Rational[T], y: T): Rational[T] =
## Multiply rational `x` with int `y`. ## Multiply rational `x` with int `y`.
result.num = x.num * y result.num = x.num * y
result.den = x.den result.den = x.den
reduce(result) reduce(result)
proc `*` *[T](x: T, y: Rational[T]): Rational[T] = func `*` *[T](x: T, y: Rational[T]): Rational[T] =
## Multiply int `x` with rational `y`. ## Multiply int `x` with rational `y`.
result.num = x * y.num result.num = x * y.num
result.den = y.den result.den = y.den
reduce(result) reduce(result)
proc `*=` *[T](x: var Rational[T], y: Rational[T]) = func `*=` *[T](x: var Rational[T], y: Rational[T]) =
## Multiply rationals `y` to `x`. ## Multiply rationals `y` to `x`.
x.num *= y.num x.num *= y.num
x.den *= y.den x.den *= y.den
reduce(x) reduce(x)
proc `*=` *[T](x: var Rational[T], y: T) = func `*=` *[T](x: var Rational[T], y: T) =
## Multiply int `y` to rational `x`. ## Multiply int `y` to rational `x`.
x.num *= y x.num *= y
reduce(x) reduce(x)
proc reciprocal*[T](x: Rational[T]): Rational[T] = func reciprocal*[T](x: Rational[T]): Rational[T] =
## Calculate the reciprocal of `x`. (1/x) ## Calculate the reciprocal of `x`. (1/x)
if x.num > 0: if x.num > 0:
result.num = x.den result.num = x.den
@ -196,63 +196,63 @@ proc reciprocal*[T](x: Rational[T]): Rational[T] =
else: else:
raise newException(DivByZeroDefect, "division by zero") raise newException(DivByZeroDefect, "division by zero")
proc `/`*[T](x, y: Rational[T]): Rational[T] = func `/`*[T](x, y: Rational[T]): Rational[T] =
## Divide rationals `x` by `y`. ## Divide rationals `x` by `y`.
result.num = x.num * y.den result.num = x.num * y.den
result.den = x.den * y.num result.den = x.den * y.num
reduce(result) reduce(result)
proc `/`*[T](x: Rational[T], y: T): Rational[T] = func `/`*[T](x: Rational[T], y: T): Rational[T] =
## Divide rational `x` by int `y`. ## Divide rational `x` by int `y`.
result.num = x.num result.num = x.num
result.den = x.den * y result.den = x.den * y
reduce(result) reduce(result)
proc `/`*[T](x: T, y: Rational[T]): Rational[T] = func `/`*[T](x: T, y: Rational[T]): Rational[T] =
## Divide int `x` by Rational `y`. ## Divide int `x` by Rational `y`.
result.num = x * y.den result.num = x * y.den
result.den = y.num result.den = y.num
reduce(result) reduce(result)
proc `/=`*[T](x: var Rational[T], y: Rational[T]) = func `/=`*[T](x: var Rational[T], y: Rational[T]) =
## Divide rationals `x` by `y` in place. ## Divide rationals `x` by `y` in place.
x.num *= y.den x.num *= y.den
x.den *= y.num x.den *= y.num
reduce(x) reduce(x)
proc `/=`*[T](x: var Rational[T], y: T) = func `/=`*[T](x: var Rational[T], y: T) =
## Divide rational `x` by int `y` in place. ## Divide rational `x` by int `y` in place.
x.den *= y x.den *= y
reduce(x) reduce(x)
proc cmp*(x, y: Rational): int = func cmp*(x, y: Rational): int =
## Compares two rationals. ## Compares two rationals.
(x - y).num (x - y).num
proc `<` *(x, y: Rational): bool = func `<` *(x, y: Rational): bool =
(x - y).num < 0 (x - y).num < 0
proc `<=` *(x, y: Rational): bool = func `<=` *(x, y: Rational): bool =
(x - y).num <= 0 (x - y).num <= 0
proc `==` *(x, y: Rational): bool = func `==` *(x, y: Rational): bool =
(x - y).num == 0 (x - y).num == 0
proc abs*[T](x: Rational[T]): Rational[T] = func abs*[T](x: Rational[T]): Rational[T] =
result.num = abs x.num result.num = abs x.num
result.den = abs x.den result.den = abs x.den
proc `div`*[T: SomeInteger](x, y: Rational[T]): T = func `div`*[T: SomeInteger](x, y: Rational[T]): T =
## Computes the rational truncated division. ## Computes the rational truncated division.
(x.num * y.den) div (y.num * x.den) (x.num * y.den) div (y.num * x.den)
proc `mod`*[T: SomeInteger](x, y: Rational[T]): Rational[T] = func `mod`*[T: SomeInteger](x, y: Rational[T]): Rational[T] =
## Computes the rational modulo by truncated division (remainder). ## Computes the rational modulo by truncated division (remainder).
## This is same as ``x - (x div y) * y``. ## This is same as ``x - (x div y) * y``.
result = ((x.num * y.den) mod (y.num * x.den)) // (x.den * y.den) result = ((x.num * y.den) mod (y.num * x.den)) // (x.den * y.den)
reduce(result) reduce(result)
proc floorDiv*[T: SomeInteger](x, y: Rational[T]): T = func floorDiv*[T: SomeInteger](x, y: Rational[T]): T =
## Computes the rational floor division. ## Computes the rational floor division.
## ##
## Floor division is conceptually defined as ``floor(x / y)``. ## Floor division is conceptually defined as ``floor(x / y)``.
@ -261,15 +261,15 @@ proc floorDiv*[T: SomeInteger](x, y: Rational[T]): T =
## rounds down. ## rounds down.
floorDiv(x.num * y.den, y.num * x.den) floorDiv(x.num * y.den, y.num * x.den)
proc floorMod*[T: SomeInteger](x, y: Rational[T]): Rational[T] = func floorMod*[T: SomeInteger](x, y: Rational[T]): Rational[T] =
## Computes the rational modulo by floor division (modulo). ## Computes the rational modulo by floor division (modulo).
## ##
## This is same as ``x - floorDiv(x, y) * y``. ## This is same as ``x - floorDiv(x, y) * y``.
## This proc behaves the same as the ``%`` operator in python. ## This func behaves the same as the ``%`` operator in python.
result = floorMod(x.num * y.den, y.num * x.den) // (x.den * y.den) result = floorMod(x.num * y.den, y.num * x.den) // (x.den * y.den)
reduce(result) reduce(result)
proc hash*[T](x: Rational[T]): Hash = func hash*[T](x: Rational[T]): Hash =
## Computes hash for rational `x` ## Computes hash for rational `x`
# reduce first so that hash(x) == hash(y) for x == y # reduce first so that hash(x) == hash(y) for x == y
var copy = x var copy = x

View file

@ -10,6 +10,7 @@ import
httpcore, httpcore,
math, math,
nre, nre,
rationals,
sequtils, sequtils,
strutils, strutils,
uri uri