Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- function type(x,...)
- if debug.getmetatable(x).__type then
- return debug.getmetatable(x).__type
- else
- return type(x,...)
- end
- end
- function sametype(a,b)
- assert(type(a) == type(b))
- end
- local Nat = {}
- local natMeta = {}
- natMeta.__index = natMeta
- natMeta.__type = "Natural Number"
- local Zero = nil
- function NaturalNumber()
- local nat = {data = Zero}
- setmetatable(nat,natMeta)
- return nat
- end
- NaturalZero = NaturalNumber()
- function natMeta:Succ()
- local ret = self:Copy()
- ret.data = {ret.data}
- return ret
- end
- function natMeta:Copy()
- local dat = Zero
- local t = self.data
- while t ~= Zero do
- t = unpack(t)
- dat = {dat}
- end
- local ret = NaturalNumber()
- ret.data = dat
- return ret
- end
- function natMeta.__add(a,b)
- sametype(a,b)
- local ret = a:Copy()
- local t = b.data
- while t ~= Zero do
- t = unpack(t)
- ret = ret:Succ()
- end
- return ret
- end
- function natMeta.__mul(a,b)
- sametype(a,b)
- local ret = NaturalNumber()
- local t0 = a.data
- while t0 ~= Zero do
- t0 = unpack(t0)
- local t1 = b.data
- while t1 ~= Zero do
- t1 = unpack(t1)
- ret = ret:Succ()
- end
- end
- return ret
- end
- function natMeta.__eq(a,b)
- sametype(a,b)
- local ta = a.data
- local tb = b.data
- while ta ~= Zero and tb ~= Zero do
- ta = unpack(ta)
- tb = unpack(tb)
- end
- return ta == tb
- end
- function natMeta.__lt(a,b)
- sametype(a,b)
- if a == b then return false end
- local ta = a.data
- local tb = b.data
- while ta ~= Zero and tb ~= Zero do
- ta = unpack(ta)
- tb = unpack(tb)
- end
- if ta == Zero then
- return true
- elseif tb == Zero then
- return false
- end
- end
- function natMeta.__le(a,b)
- sametype(a,b)
- return a == b or a < b
- end
- ----------------UTIL STUFF
- --The underlying system would function fine without this code
- function NaturalSet(nat,n)
- local ret = nat
- for i = 1, n do
- ret = ret:Succ()
- end
- return ret
- end
- function natMeta.__tostring(self)
- local count = self:toLuaNumber()
- return "Natural Number (" .. tostring(count) .. ")"
- end
- function natMeta:toLuaNumber()
- local count = 0
- local d = self.data
- while d ~= Zero do
- d = unpack(d)
- count = count + 1
- end
- return count
- end
- function Nat(num)
- return NaturalSet(NaturalNumber(),num)
- end
- --------------------------
- local intMeta = {}
- intMeta.__index = intMeta
- intMeta.__type = "Integer"
- function Integer(nat1,nat2)
- local int = {nat1,nat2}
- return setmetatable(int,intMeta)
- end
- local IntegerZero = Integer(NaturalNumber(),NaturalNumber())
- function intMeta:Copy()
- local a,b = unpack(self)
- return Integer(a:Copy(),b:Copy())
- end
- function intMeta.__add(x,y)
- sametype(x,y)
- local a,b = unpack(x)
- local c,d = unpack(y)
- return Integer(a + c, b + d)
- end
- function intMeta.__unm(x)
- local a,b = unpack(x)
- return Integer(b,a)
- end
- function intMeta.__sub(x,y)
- sametype(x,y)
- return x + (-y)
- end
- function intMeta.__mul(x,y)
- sametype(x,y)
- local a,b = unpack(x)
- local c,d = unpack(y)
- local int1 = Integer(b * c, b * d)
- local int2 = Integer(a * c, a * d)
- return int1 + int2
- end
- function intMeta.__div(x,y)
- sametype(x,y)
- local counter = NaturalNumber()
- local copy = x
- while copy > IntegerZero do
- counter = counter:Succ()
- copy = copy - y
- end
- return Integer(NaturalNumber(),counter)
- end
- function intMeta:reduce()
- local a,b = unpack(self)
- local c,d = a.data,b.data
- while c ~= Zero and d ~= Zero do
- c = unpack(c)
- d = unpack(d)
- end
- local x,y = a:Copy(), b:Copy()
- x.data = c
- y.data = d
- return Integer(x,y)
- end
- function intMeta.__pow(x,y)
- assert(type(x) == intMeta.__type and type(y) == natMeta.__type)
- local ret = Integer(NaturalNumber(),NaturalNumber():Succ())
- local t = y.data
- while t do
- t = unpack(t)
- ret = ret * x
- end
- return ret
- end
- function intMeta.__eq(x,y)
- sametype(x,y)
- local a,b = unpack(x)
- local c,d = unpack(y)
- return b + c == d + a
- end
- function intMeta.__lt(x,y)
- sametype(x,y)
- local a,b = unpack(x)
- local c,d = unpack(y)
- return b + c < d + a
- end
- function intMeta.__le(x,y)
- sametype(x,y)
- return x == y or x < y
- end
- function intMeta.__mod(x,y)
- sametype(x,y)
- if x < y then return x end
- if x == y then return IntegerZero end
- local c = x
- while c >= y do
- c = c - y
- end
- return c
- end
- function intMeta:abs()
- local x = self:reduce()
- local a,b = unpack(x)
- if a == NaturalZero then
- return Integer(NaturalNumber(),b)
- elseif b == NaturalZero then
- return Integer(NaturalNumber(),a)
- end
- end
- function intMeta:sign()
- local a,b = unpack(self)
- if a > b then
- return Integer(NaturalNumber():Succ(),NaturalNumber())
- elseif a < b then
- return Integer(NaturalNumber(),NaturalNumber():Succ())
- else
- return IntegerZero
- end
- end
- ----------------UTIL STUFF
- function intMeta.__tostring(self)
- return "Integer (" .. tostring(self[1]) .. " , " .. tostring(self[2]) .. ") [" .. tostring(self:toLuaNumber()) .. "]"
- end
- function intMeta:toLuaNumber()
- return self[2]:toLuaNumber() - self[1]:toLuaNumber()
- end
- function Int(num)
- if num == 0 then return Integer(NaturalNumber(),NaturalNumber()) end
- if num > 0 then
- return Integer(NaturalNumber(),Nat(num))
- else
- return Integer(Nat(math.abs(num)),NaturalNumber())
- end
- end
- --------------------------
- local ratMeta = {}
- ratMeta.__index = ratMeta
- ratMeta.__type = "Rational Number"
- function RationalNumber(x,y)
- assert(type(x) == intMeta.__type and type(y) == intMeta.__type)
- if y == IntegerZero then error("Division by zero") end
- local rat = {x,y}
- return setmetatable(rat,ratMeta)
- end
- local RationalZero = RationalNumber(IntegerZero,Integer(NaturalNumber(),NaturalNumber():Succ()))
- function ratMeta.__unm(x)
- local a,b = unpack(x)
- return RationalNumber(-a,-b)
- end
- function ratMeta.__add(x,y)
- sametype(x,y)
- local a,b = unpack(x)
- local c,d = unpack(y)
- return RationalNumber(a * d + c * b, b * d)
- end
- function ratMeta.__sub(x,y)
- sametype(x,y)
- return x + (-y)
- end
- function ratMeta.__mul(x,y)
- sametype(x,y)
- local a,b = unpack(x)
- local c,d = unpack(y)
- return RationalNumber(a * c, b * d)
- end
- function ratMeta.__div(x,y)
- sametype(x,y)
- if y == RationalZero then error("Division by zero") end
- local a,b = unpack(y)
- local new = RationalNumber(b,a)
- return x * new
- end
- function ratMeta.__pow(x,y)
- assert(type(x) == ratMeta.__type and type(y) == intMeta.__type)
- local a,b = unpack(x)
- local c,d = unpack(y)
- return RationalNumber(a^d * b^c, a^c * b^d)
- end
- function ratMeta.__eq(x,y)
- sametype(x,y)
- local a,b = unpack(x)
- local c,d = unpack(y)
- return a * d == b * c
- end
- function ratMeta.__lt(x,y)
- sametype(x,y)
- local a,b = unpack(x)
- local c,d = unpack(y)
- return a * d < c * b
- end
- function ratMeta.__le(x,y)
- sametype(x,y)
- return x == y or x < y
- end
- function ratMeta:floor()
- local x,y = unpack(self)
- if y >= x then return RationalZero end
- return RationalNumber((x % y) - x, -y)
- end
- local function IntegerGCD(a,b)
- sametype(a,b)
- if a == b then return a end
- if b == IntegerZero then return a end
- if a > b then
- return IntegerGCD(a - b, b)
- end
- return IntegerGCD(b, a % b)
- end
- function ratMeta:reduce()
- local x,y = unpack(self)
- x = x:reduce()
- y = y:reduce()
- local gcd = IntegerGCD(x:abs(),y:abs())
- return RationalNumber(x / gcd, y / gcd)
- end
- ----------------UTIL STUFF
- function ratMeta.__tostring(self)
- return "Rational Number ( " .. tostring(self[1]:toLuaNumber()) .. " / " .. tostring(self[2]:toLuaNumber()) .. " ) [" .. tostring(self:toLuaNumber()) .. "]"
- end
- function ratMeta:toLuaNumber()
- return self[1]:toLuaNumber() / self[2]:toLuaNumber()
- end
- function Rat(x,y)
- return RationalNumber(Int(x),Int(y))
- end
- --------------------------
- local a = Int(2)
- local b = Nat(8)
- print(a^b) --Integer (Natural Number (0) , Natural Number (256)) [256]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement