Module:Limits: Difference between revisions
Jump to navigation
Jump to search
m Bugfix |
mNo edit summary |
||
Line 3: | Line 3: | ||
-- multiply the ratio by a power of `equave` so that it lies within [1; equave) | -- multiply the ratio by a power of `equave` so that it lies within [1; equave) | ||
function p.canonical(a, equave) | |||
equave = equave or 2 | equave = equave or 2 | ||
if type(a) == 'number' then | if type(a) == 'number' then | ||
Line 24: | Line 24: | ||
for m = 1, q, 2 do | for m = 1, q, 2 do | ||
local a = rat.new(n, m) | local a = rat.new(n, m) | ||
a = canonical(a, equave) | a = p.canonical(a, equave) | ||
local key = rat.as_ratio(a) | local key = rat.as_ratio(a) | ||
ratios[key] = a | ratios[key] = a | ||
Line 55: | Line 55: | ||
local c_approx = approximate(c) | local c_approx = approximate(c) | ||
c = canonical(c, equave) | c = p.canonical(c, equave) | ||
local c_key = rat.as_ratio(c) | local c_key = rat.as_ratio(c) | ||
if ratios[c_key] then | if ratios[c_key] then |
Revision as of 19:14, 1 October 2022
local rat = require('Module:Rational')
local p = {}
-- multiply the ratio by a power of `equave` so that it lies within [1; equave)
function p.canonical(a, equave)
equave = equave or 2
if type(a) == 'number' then
a = rat.new(a)
end
local b = rat.copy(a)
while rat.lt(b, 1) do
b = rat.mul(b, equave)
end
while rat.geq(b, equave) do
b = rat.div(b, equave)
end
return b
end
function p.limit_modulo_equave(q, equave)
equave = equave or 2
local ratios = {}
for n = 1, q, 2 do
for m = 1, q, 2 do
local a = rat.new(n, m)
a = p.canonical(a, equave)
local key = rat.as_ratio(a)
ratios[key] = a
end
end
return ratios
end
function p.additively_consistent(equave, size, ratios, distinct)
distinct = distinct or false
local function approximate(a)
return math.floor(size * math.log(rat.as_float(a)) / math.log(rat.as_float(equave)) + 0.5)
end
if distinct then
local approx_set = {}
for a_key, a in pairs(ratios) do
local a_approx = approximate(a)
if approx_set[a_approx] then
return false
end
approx_set[a_approx] = true
end
end
for a_key, a in pairs(ratios) do
local a_approx = approximate(a)
for b_key, b in pairs(ratios) do
local b_approx = approximate(b)
local c = rat.mul(a, b)
local c_approx = approximate(c)
c = p.canonical(c, equave)
local c_key = rat.as_ratio(c)
if ratios[c_key] then
if c_approx ~= a_approx + b_approx then
return false
end
end
end
end
return true
end
function p.consistency_limit(size, equave, distinct)
equave = equave or 2
distinct = distinct or false
local n = 1
local last_n = 1
while true do
if rat.is_int(rat.div(n, equave)) then
n = n + 1
else
local ratios = p.limit_modulo_equave(n, equave)
local consistent = p.additively_consistent(equave, size, ratios, distinct)
if not consistent then
return last_n
end
last_n = n
n = n + 1
end
end
return n
end
return p