Module:Limits: Difference between revisions
Jump to navigation
Jump to search
Module created |
Distinct consistency limit implemented |
||
Line 32: | Line 32: | ||
end | end | ||
function p.additively_consistent(equave, size, ratios) | function p.additively_consistent(equave, size, ratios, distinct) | ||
distinct = distinct or false | |||
local function approximate(a) | local function approximate(a) | ||
return math.floor(size * math.log(rat.as_float(a)) / math.log(equave) + 0.5) | return math.floor(size * math.log(rat.as_float(a)) / math.log(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 | end | ||
for a_key, a in pairs(ratios) do | for a_key, a in pairs(ratios) do | ||
Line 56: | Line 67: | ||
end | end | ||
function p.consistency_limit(size, equave) | function p.consistency_limit(size, equave, distinct) | ||
equave = equave or 2 | equave = equave or 2 | ||
distinct = distinct or false | |||
local n = 1 | local n = 1 | ||
local last_n = 1 | local last_n = 1 | ||
Line 65: | Line 77: | ||
else | else | ||
local ratios = p.limits_modulo_equave(n, equave) | local ratios = p.limits_modulo_equave(n, equave) | ||
local consistent = p.additively_consistent(equave, size, ratios) | local consistent = p.additively_consistent(equave, size, ratios, distinct) | ||
if not consistent then | if not consistent then | ||
return last_n | return last_n |
Revision as of 15:52, 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)
local function 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.limits_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 = 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(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 = 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.limits_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