|
|
| (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 |