rapport/enumerations.lua

88 lines
2.2 KiB
Lua

local enum = require 'enumeration'
local function CalkinWilf()
local n, d = 1, 1
return enum( function()
repeat n, d = d, ( 2 * d * math.floor( n / d ) - n + d )
until n < d
return n / d
end )
end
local function Random()
return enum( math.random )
end
--Breadth first traversal of the open left subtree of the Stern-Brocot tree.
--Formed by inserting the mediants of previous rationals in the tree.
local function SternBrocot()
--Rational numbers.
local R
do
local rationals = {}
local rmt = {
__lt = function(a, b) return a[1]/a[2] < b[1]/b[2] end,
__eq = function(a, b) return a[1] == b[1] and a[2] == b[2] end,
__pow = function(a, b) return R( a[1] + b[1], a[2] + b[2] ) end, --mediant
__call = function(t) return t[1]/t[2] end,
__tostring = function(t) return string.format( "%d / %d", t[1], t[2] ) end }
R = function( n, d )
if not rationals[d] then rationals[d] = {} end
local den = rationals[d]
if den[n] then return den[n] end
local r = setmetatable( { n , d }, rmt )
den[n] = r
return r
end
end
--Flat list of all entries traversed so far.
local seq = { R(0, 1), R(1, 2), R(1, 1) }
local idx = 0
local len = 3
local function nextRational()
--Return every other entry: these are the most recently added mediants.
idx = idx + 2
if idx < len then return seq[idx] end
--We have finished iterating over the current level of the tree.
--Create a new level by adding all the new mediants.
local nSeq = {}
for i = 1, len - 1 do
nSeq[ 2 * i - 1 ] = seq[i]
nSeq[ 2 * i ] = seq[i] ^ seq[i + 1]
end
nSeq[ 2 * len - 1 ] = seq[ len ]
seq = nSeq
len = #seq
--print( "RATIONALS: NEW LEVEL", len, unpack( nSeq ) )
idx = 0
return nextRational()
end
return enum( nextRational )
end
--Enumeration of dyadic rationals in the open unit interval, ascending lexicographic.
local function Dyad()
local n, d = -1, 2
return enum( function()
n = n + 2
if n > d then n, d = 1, d * 2 end
return n / d
end )
end
return {
Dyad = Dyad,
SternBrocot = SternBrocot,
CalkinWilf = CalkinWilf,
Random = Random,
QuadIrr = false,
}