diff options
author | def <dennis@felsin9.de> | 2015-02-19 20:44:13 +0100 |
---|---|---|
committer | def <dennis@felsin9.de> | 2015-02-20 12:21:09 +0100 |
commit | f710a31344e0df9f7ee9cafc3ffba44e9b3227c6 (patch) | |
tree | c318aeb23f1794380d943e43d8276d0b79185297 | |
parent | f6c83c32f32d69cd3681a42d01e440c11894f2c2 (diff) | |
download | Nim-f710a31344e0df9f7ee9cafc3ffba44e9b3227c6.tar.gz |
Make rationals generic
-rw-r--r-- | lib/pure/rationals.nim | 61 |
1 files changed, 33 insertions, 28 deletions
diff --git a/lib/pure/rationals.nim b/lib/pure/rationals.nim index 968279b2b..3affd3cf3 100644 --- a/lib/pure/rationals.nim +++ b/lib/pure/rationals.nim @@ -13,24 +13,24 @@ import math -type Rational* = tuple[num, den: int] +type Rational*[T] = tuple[num, den: T] ## a rational number, consisting of a numerator and denominator -proc toRational*(x: SomeInteger): Rational = +proc toRational*[T](x: SomeInteger): Rational[T] = ## Convert some integer `x` to a rational number. result.num = x result.den = 1 -proc toFloat*(x: Rational): float = +proc toFloat*[T](x: Rational[T]): float = ## Convert a rational number `x` to a float. x.num / x.den -proc toInt*(x: Rational): int = +proc toInt*[T](x: Rational[T]): int = ## Convert a rational number `x` to an int. Conversion rounds towards 0 if ## `x` does not contain an integer value. x.num div x.den -proc reduce*(x: var Rational) = +proc reduce*[T](x: var Rational[T]) = ## Reduce rational `x`. let common = gcd(x.num, x.den) if x.den > 0: @@ -42,97 +42,97 @@ proc reduce*(x: var Rational) = else: raise newException(DivByZeroError, "division by zero") -proc `+` *(x, y: Rational): Rational = +proc `+` *[T](x, y: Rational[T]): Rational[T] = ## Add two rational numbers. let common = lcm(x.den, y.den) result.num = common div x.den * x.num + common div y.den * y.num result.den = common reduce(result) -proc `+` *(x: Rational, y: int): Rational = +proc `+` *[T](x: Rational[T], y: T): Rational[T] = ## Add rational `x` to int `y`. result.num = x.num + y * x.den result.den = x.den -proc `+` *(x: int, y: Rational): Rational = +proc `+` *[T](x: T, y: Rational[T]): Rational[T] = ## Add int `x` to rational `y`. result.num = x * y.den + y.num result.den = y.den -proc `+=` *(x: var Rational, y: Rational) = +proc `+=` *[T](x: var Rational[T], y: Rational[T]) = ## Add rational `y` to rational `x`. let common = lcm(x.den, y.den) x.num = common div x.den * x.num + common div y.den * y.num x.den = common reduce(x) -proc `+=` *(x: var Rational, y: int) = +proc `+=` *[T](x: var Rational[T], y: T) = ## Add int `y` to rational `x`. x.num += y * x.den -proc `-` *(x: Rational): Rational = +proc `-` *[T](x: Rational[T]): Rational[T] = ## Unary minus for rational numbers. result.num = -x.num result.den = x.den -proc `-` *(x, y: Rational): Rational = +proc `-` *[T](x, y: Rational[T]): Rational[T] = ## Subtract two rational numbers. let common = lcm(x.den, y.den) result.num = common div x.den * x.num - common div y.den * y.num result.den = common reduce(result) -proc `-` *(x: Rational, y: int): Rational = +proc `-` *[T](x: Rational[T], y: T): Rational[T] = ## Subtract int `y` from rational `x`. result.num = x.num - y * x.den result.den = x.den -proc `-` *(x: int, y: Rational): Rational = +proc `-` *[T](x: T, y: Rational[T]): Rational[T] = ## Subtract rational `y` from int `x`. result.num = - x * y.den + y.num result.den = y.den -proc `-=` *(x: var Rational, y: Rational) = +proc `-=` *[T](x: var Rational[T], y: Rational[T]) = ## Subtract rational `y` from rational `x`. let common = lcm(x.den, y.den) x.num = common div x.den * x.num - common div y.den * y.num x.den = common reduce(x) -proc `-=` *(x: var Rational, y: int) = +proc `-=` *[T](x: var Rational[T], y: T) = ## Subtract int `y` from rational `x`. x.num -= y * x.den -proc `*` *(x, y: Rational): Rational = +proc `*` *[T](x, y: Rational[T]): Rational[T] = ## Multiply two rational numbers. result.num = x.num * y.num result.den = x.den * y.den reduce(result) -proc `*` *(x: Rational, y: int): Rational = +proc `*` *[T](x: Rational[T], y: T): Rational[T] = ## Multiply rational `x` with int `y`. result.num = x.num * y result.den = x.den reduce(result) -proc `*` *(x: int, y: Rational): Rational = +proc `*` *[T](x: T, y: Rational[T]): Rational[T] = ## Multiply int `x` with rational `y`. result.num = x * y.num result.den = y.den reduce(result) -proc `*=` *(x: var Rational, y: Rational) = +proc `*=` *[T](x: var Rational[T], y: Rational[T]) = ## Multiply rationals `y` to `x`. x.num *= y.num x.den *= y.den reduce(x) -proc `*=` *(x: var Rational, y: int) = +proc `*=` *[T](x: var Rational[T], y: T) = ## Multiply int `y` to rational `x`. x.num *= y reduce(x) -proc reciprocal*(x: Rational): Rational = +proc reciprocal*[T](x: Rational[T]): Rational[T] = ## Calculate the reciprocal of `x`. (1/x) if x.num > 0: result.num = x.den @@ -143,31 +143,31 @@ proc reciprocal*(x: Rational): Rational = else: raise newException(DivByZeroError, "division by zero") -proc `/`*(x, y: Rational): Rational = +proc `/`*[T](x, y: Rational[T]): Rational[T] = ## Divide rationals `x` by `y`. result.num = x.num * y.den result.den = x.den * y.num reduce(result) -proc `/`*(x: Rational, y: int): Rational = +proc `/`*[T](x: Rational[T], y: T): Rational[T] = ## Divide rational `x` by int `y`. result.num = x.num result.den = x.den * y reduce(result) -proc `/`*(x: int, y: Rational): Rational = +proc `/`*[T](x: T, y: Rational[T]): Rational[T] = ## Divide int `x` by Rational `y`. result.num = x * y.den result.den = y.num reduce(result) -proc `/=`*(x: var Rational, y: Rational) = +proc `/=`*[T](x: var Rational[T], y: Rational[T]) = ## Divide rationals `x` by `y` in place. x.num *= y.den x.den *= y.num reduce(x) -proc `/=`*(x: var Rational, y: int) = +proc `/=`*[T](x: var Rational[T], y: T) = ## Divide rational `x` by int `y` in place. x.den *= y reduce(x) @@ -185,7 +185,7 @@ proc `<=` *(x, y: Rational): bool = proc `==` *(x, y: Rational): bool = (x - y).num == 0 -proc abs*(x: Rational): Rational = +proc abs*[T](x: Rational[T]): Rational[T] = result.num = abs x.num result.den = abs x.den @@ -253,3 +253,8 @@ when isMainModule: assert( y == (13,3) ) y /= 9 assert( y == (13,27) ) + + assert toRational[int, int](5) == (5,1) + assert abs(toFloat(y) - 0.4814814814814815) < 1.0e-7 + assert toInt(z) == 0 + echo 2 + (4,3) |