blob: 81463e7d9a4529c350c46b5b3b1eb0a9b78aba5c [file] [log] [blame]
-- The Great Computer Language Shootout
-- http://shootout.alioth.debian.org/
--
-- contributed by Isaac Gouy
-- requires BigNum library
-- http://oss.digirati.com.br/luabignum/
require( "BigNum.lua" ) ;
-- Transformation
local T = {}
function T.bigzero() return BigNum.new(0) end
function T.bigone() return BigNum.new(1) end
function T.bigten() return BigNum.new(10) end
function T.new(q,r,s,t)
return {
q = BigNum.new(q)
,r = BigNum.new(r)
,s = BigNum.new(s)
,t = BigNum.new(t)
,k = 0
}
end
function T.unity() return T.new(1,0,0,1) end
function T.zero() return T.new(0,0,0,0) end
function T.compose(a,b)
local qq = T.bigzero()
local qr = T.bigzero()
local rt = T.bigzero()
local qrrt = T.bigzero()
local sq = T.bigzero()
local ts = T.bigzero()
local sqts = T.bigzero()
local sr = T.bigzero()
local tt = T.bigzero()
local srtt = T.bigzero()
BigNum.mul(a.q,b.q,qq)
BigNum.mul(a.q,b.r,qr)
BigNum.mul(a.r,b.t,rt)
BigNum.add(qr,rt,qrrt)
BigNum.mul(a.s,b.q,sq)
BigNum.mul(a.t,b.s,ts)
BigNum.add(sq,ts,sqts)
BigNum.mul(a.s,b.r,sr)
BigNum.mul(a.t,b.t,tt)
BigNum.add(sr,tt,srtt)
return T.new(qq, qrrt, sqts, srtt)
end
function T.extract(a,j)
local bigj = BigNum.new(j)
local qj = T.bigzero()
local qjr = T.bigzero()
local sj = T.bigzero()
local sjt = T.bigzero()
local n = T.bigzero()
local sjt = T.bigzero()
BigNum.mul(a.q,bigj,qj)
BigNum.add(qj,a.r,qjr)
BigNum.mul(a.s,bigj,sj)
BigNum.add(sj,a.t,sjt)
local d = T.bigzero()
local r = T.bigzero()
BigNum.div(qjr,sjt,d,r)
return math.floor( tonumber( BigNum.mt.tostring(d) ))
end
function T.next(a)
a.k = a.k + 1
a.q = BigNum.new(a.k)
a.r = BigNum.new(4*a.k + 2)
a.s = T.bigzero()
a.t = BigNum.new(2*a.k + 1)
return a
end
-- Pi Digit Stream
local P = {}
function P.new()
return {
z = T.unity()
,x = T.zero()
,inverse = T.zero()
}
end
function P.produce(a,j)
local i = a.inverse
i.q = T.bigten()
i.r = BigNum.new(-10*j)
i.s = T.bigzero()
i.t = T.bigone()
return T.compose(i,a.z)
end
function P.consume(a,b)
return T.compose(a.z,b)
end
function P.digit(a)
return T.extract(a.z,3)
end
function P.isSafe(a,j)
return j == T.extract(a.z,4)
end
function P.next(a)
local y
y = P.digit(a)
if P.isSafe(a,y) then
a.z = P.produce(a,y)
return y
else
a.z = P.consume(a,T.next(a.x))
return P.next(a)
end
end
-- Main
n = tonumber(arg and arg[1]) or 27
i = 0
length = 10
pidigit = P.new()
while n > 0 do
if n < length then
for _ = 1,n do io.write( P.next(pidigit) ) end
for _ = n,length do io.write( ' ' ) end
i = i + n
else
for _ = 1,length do io.write( P.next(pidigit) ) end
i = i + length
end
io.write('\t:', i, '\n')
n = n - length
end