Module:Chord consistency: Difference between revisions

Dummy index (talk | contribs)
division by zero
Dummy index (talk | contribs)
delete additively_consistent_int() and use new version of Module:Limits.additively_consistent()
 
(3 intermediate revisions by 2 users not shown)
Line 1: Line 1:
local limits = require('Module:Limits')
local ET = require('Module:ET')
local rat = require('Module:Rational')
local rat = require('Module:Rational')
local utils = require("Module:Utils")
local utils = require("Module:Utils")
local ET = require('Module:ET')
local p = {}
local p = {}
-- check additive consistency for a set of ratios (equave-free version):
--  approx(a*b) = approx(a) + approx(b) forall a, b: a, b, ab in ratios
-- `distinct`: whether distinct ratios are required to be mapped to distinct approximations
-- `previous`: already computed ratios for the previous iteraton
function p.additively_consistent_int(et, ratios, distinct, previous)
distinct = distinct or false
previous = previous or {}
if distinct then
local approx_set = {}
for a_key, a in pairs(previous) do
local a_approx = ET.approximate(et, rat.as_float(a)) % et.size
if approx_set[a_approx] then
if not rat.eq(rat.div(a, approx_set[a_approx]), 1) then
mw.log(a_key .. ' -> ' .. a_approx .. ': conflict!')
return false
end
end
approx_set[a_approx] = a
mw.log(a_key .. ' -> ' .. a_approx)
end
for a_key, a in pairs(ratios) do
local a_approx = ET.approximate(et, rat.as_float(a)) % et.size
if approx_set[a_approx] then
if not rat.eq(rat.div(a, approx_set[a_approx]), 1) then
mw.log(a_key .. ' -> ' .. a_approx .. ': conflict!')
return false
end
end
approx_set[a_approx] = a
mw.log(a_key .. ' -> ' .. a_approx)
end
end
if type(distinct) == 'number' then
return true
end
local previous_ordered = {}
for a_key, a in pairs(previous) do
table.insert(previous_ordered, a)
end
local ratios_ordered = {}
for a_key, a in pairs(ratios) do
table.insert(ratios_ordered, a)
end
for i, a in ipairs(ratios_ordered) do
local a_approx = ET.approximate(et, rat.as_float(a))
for j, b in ipairs(previous_ordered) do
local b_approx = ET.approximate(et, rat.as_float(b))
local c = rat.mul(a, b)
local c_approx = ET.approximate(et, rat.as_float(c))
local c_key = rat.as_ratio(c)
if previous[c_key] or ratios[c_key] then
if c_approx ~= a_approx + b_approx then
mw.log('a = ' .. rat.as_ratio(a) .. '; b = ' .. rat.as_ratio(b) .. '; ab = ' .. c_key)
mw.log(a_approx .. ' + ' .. b_approx .. ' != ' .. c_approx)
return false
end
end
end
for j, b in ipairs(ratios_ordered) do
if i <= j then
local b_approx = ET.approximate(et, rat.as_float(b))
local c = rat.mul(a, b)
local c_approx = ET.approximate(et, rat.as_float(c))
local c_key = rat.as_ratio(c)
if previous[c_key] or ratios[c_key] then
if c_approx ~= a_approx + b_approx then
mw.log('a = ' .. rat.as_ratio(a) .. '; b = ' .. rat.as_ratio(b) .. '; ab = ' .. c_key)
mw.log(a_approx .. ' + ' .. b_approx .. ' != ' .. c_approx)
return false
end
end
end
end
end
return true
end


-- determine maximum error
-- determine maximum error
Line 101: Line 21:
distance = distance or 1.0
distance = distance or 1.0
ed = ed or 'edo'
ed = ed or 'edo'
maxlen = maxlen or 72
local max_n = 72
maxlen = maxlen or max_n
if max_n < maxlen then max_n = maxlen end
local all_interval = {}
local all_interval = {}


Line 115: Line 37:


local vals = {}
local vals = {}
for i = 1, 72 do
for i = 1, max_n do
local et = ET.parse('' .. i .. ed)
local et = ET.parse('' .. i .. ed)
local consistent = p.additively_consistent_int(et, all_interval, false, previous)
local consistent = limits.additively_consistent(et, all_interval, false, false, nil)
if consistent then
if consistent then
local maxe = p.max_error(et, all_interval)
local maxe = p.max_error(et, all_interval)
if maxe <= 0.0 then
if maxe <= 5.0e-11 then
table.insert(vals, "[[" .. i .. ed .. "]]" .. "(just)")
table.insert(vals, "[[" .. i .. ed .. "]]" .. "(just)")
break
break