Module:Rational

From Wavu Wiki, the 🌊 wavy Tekken wiki

Documentation for this module may be created at Module:Rational/doc

-- From http://rosettacode.org/wiki/Arithmetic/Rational#Lua
-- GNU Free Documentation License 1.2
--
-- TODO: Get a bignum library so this doesn't fail when we go past the limits of a double

function gcd(a,b) return a == 0 and b or gcd(b % a, a) end
 
do
  local function coerce(a, b)
    if type(a) == "number" then return rational(a, 1), b end
    if type(b) == "number" then return a, rational(b, 1) end
    return a, b
  end
  rational = setmetatable({
  __add = function(a, b)
      local a, b = coerce(a, b)
      return rational(a.num * b.den + a.den * b.num, a.den * b.den)
    end,
  __sub = function(a, b)
      local a, b = coerce(a, b)
      return rational(a.num * b.den - a.den * b.num, a.den * b.den)
    end,
  __mul = function(a, b)
      local a, b = coerce(a, b)
      return rational(a.num * b.num, a.den * b.den)
    end,
  __div = function(a, b)
      local a, b = coerce(a, b)
      return rational(a.num * b.den, a.den * b.num)
    end,
  __pow = function(a, b)
      if type(a) == "number" then return a ^ (b.num / b.den) end
      return rational(a.num ^ b, a.den ^ b) --runs into a problem if these aren't integers
    end,
  __concat = function(a, b)
      if getmetatable(a) == rational then return a.num .. "/" .. a.den .. b end
      return a .. b.num .. "/" .. b.den
    end,
  __unm = function(a) return rational(-a.num, -a.den) end}, {
  __call = function(z, a, b) return setmetatable({num = a / gcd(a, b),den = b / gcd(a, b)}, z) end} )
end

return rational