Module:Q-odd-limit intervals
- This module should not be invoked directly; use its corresponding template instead: Template:Q-odd-limit intervals.
This module automatically calculates a given equal-tempered tuning's approximations of intervals in a given odd limit, and lists them in a table.
Currently, odd limits up to and including 63 and prime limits up to and including 61 are supported.
| Introspection summary for Module:Q-odd-limit intervals | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
| |||||||||
No function descriptions were provided. The Lua code may have further information.
bit32 = require( 'bit32' )
local p = {}
local PRIME_LIST = {2, 3, 5, 7, 11, 13, 17, 19}
local function get_monzo_list (limit)
local monzo_list = {}
if limit >= 3 then
table.insert (monzo_list, {-1, 1, 0, 0, 0, 0, 0, 0})
end if limit >= 5 then
table.insert (monzo_list, {-2, 0, 1, 0, 0, 0, 0, 0})
table.insert (monzo_list, {0, -1, 1, 0, 0, 0, 0, 0})
end if limit >= 7 then
table.insert (monzo_list, {-2, 0, 0, 1, 0, 0, 0, 0})
table.insert (monzo_list, {-1, -1, 0, 1, 0, 0, 0, 0})
table.insert (monzo_list, {0, 0, -1, 1, 0, 0, 0, 0})
end if limit >= 9 then
table.insert (monzo_list, {-3, 2, 0, 0, 0, 0, 0, 0})
table.insert (monzo_list, {0, 2, -1, 0, 0, 0, 0, 0})
table.insert (monzo_list, {0, 2, 0, -1, 0, 0, 0, 0})
end if limit >= 11 then
table.insert (monzo_list, {-3, 0, 0, 0, 1, 0, 0, 0})
table.insert (monzo_list, {-1, -1, 0, 0, 1, 0, 0, 0})
table.insert (monzo_list, {0, -2, 0, 0, 1, 0, 0, 0})
table.insert (monzo_list, {-1, 0, -1, 0, 1, 0, 0, 0})
table.insert (monzo_list, {0, 0, 0, -1, 1, 0, 0, 0})
end if limit >= 13 then
table.insert (monzo_list, {-3, 0, 0, 0, 0, 1, 0, 0})
table.insert (monzo_list, {-2, -1, 0, 0, 0, 1, 0, 0})
table.insert (monzo_list, {0, -2, 0, 0, 0, 1, 0, 0})
table.insert (monzo_list, {-1, 0, -1, 0, 0, 1, 0, 0})
table.insert (monzo_list, {0, 0, 0, -1, 0, 1, 0, 0})
table.insert (monzo_list, {0, 0, 0, 0, -1, 1, 0, 0})
end if limit >= 15 then
table.insert (monzo_list, {-3, 1, 1, 0, 0, 0, 0, 0})
table.insert (monzo_list, {-1, 1, 1, -1, 0, 0, 0, 0})
table.insert (monzo_list, {0, 1, 1, 0, -1, 0, 0, 0})
table.insert (monzo_list, {0, 1, 1, 0, 0, -1, 0, 0})
end if limit >= 17 then
table.insert (monzo_list, {-4, 0, 0, 0, 0, 0, 1, 0})
table.insert (monzo_list, {-2, -1, 0, 0, 0, 0, 1, 0})
table.insert (monzo_list, {0, -2, 0, 0, 0, 0, 1, 0})
table.insert (monzo_list, {-1, 0, -1, 0, 0, 0, 1, 0})
table.insert (monzo_list, {-1, 0, 0, -1, 0, 0, 1, 0})
table.insert (monzo_list, {0, 0, 0, 0, -1, 0, 1, 0})
table.insert (monzo_list, {0, 0, 0, 0, 0, -1, 1, 0})
table.insert (monzo_list, {0, -1, -1, 0, 0, 0, 1, 0})
end if limit >= 19 then
table.insert (monzo_list, {-4, 0, 0, 0, 0, 0, 0, 1})
table.insert (monzo_list, {-2, -1, 0, 0, 0, 0, 0, 1})
table.insert (monzo_list, {-1, -2, 0, 0, 0, 0, 0, 1})
table.insert (monzo_list, {-1, 0, -1, 0, 0, 0, 0, 1})
table.insert (monzo_list, {-1, 0, 0, -1, 0, 0, 0, 1})
table.insert (monzo_list, {0, 0, 0, 0, -1, 0, 0, 1})
table.insert (monzo_list, {0, 0, 0, 0, 0, -1, 0, 1})
table.insert (monzo_list, {0, 0, 0, 0, 0, 0, -1, 1})
table.insert (monzo_list, {0, -1, -1, 0, 0, 0, 1, 0})
end if limit >= 21 then
table.insert (monzo_list, {-4, 1, 0, 1, 0, 0, 0, 0})
table.insert (monzo_list, {-2, 1, -1, 1, 0, 0, 0, 0})
table.insert (monzo_list, {0, 1, 0, 1, -1, 0, 0, 0})
table.insert (monzo_list, {0, 1, 0, 1, 0, -1, 0, 0})
table.insert (monzo_list, {0, 1, 0, 1, 0, 0, -1, 0})
table.insert (monzo_list, {0, 1, 0, 1, 0, 0, 0, -1})
end
return monzo_list
end
local function round (n)
return math.floor (n + 0.5)
end
local function is_in (v, t)
for i = 1, #t do
if v == t[i] then
return true
end
end
return false
end
local function table_filter (t, thres)
for i = 1, #t do
if t[i] > thres then
return {unpack (t, 1, i - 1)}
end
end
return t
end
local function inner_product (val, monzo)
local result = 0
for i = 1, #val do
result = result + val[i]*monzo[i]
end
return result
end
local function monzo2ratio (monzo, subgroup)
local num = 1
local den = 1
for i = 1, #subgroup do
if monzo[i] > 0 then
num = num*subgroup[i]^monzo[i]
elseif monzo[i] < 0 then
den = den*subgroup[i]^(-monzo[i])
end
end
return {num = num, den = den}
end
local function monzo2cent (monzo, subgroup)
local jip = {}
for i = 1, #subgroup do
jip[i] = 1200*math.log (subgroup[i]) / math.log (2)
end
return inner_product (jip, monzo)
end
local function find_error (val, subgroup, monzo_list)
local step_size = 1200/val[1]
local true_size
local approx_size
local error_list = {}
for i = 1, #monzo_list do
ratio = monzo2ratio (monzo_list[i], subgroup)
comp = {2*ratio.den, ratio.num}
true_size = monzo2cent (monzo_list[i], subgroup)
approx_size = step_size*inner_product (val, monzo_list[i])
error_abs = math.abs (approx_size - true_size)
error_rel = 100*error_abs/step_size
error_list[i] =
{
ratio = ratio,
comp = comp,
error_abs = error_abs,
error_rel = error_rel
}
end
table.sort (error_list, function (a, b) return a.error_abs < b.error_abs end)
return error_list
end
local function approx (steps, subgroup, monzo_list, t_title)
local t_body = {}
local val = {}
for i = 1, #subgroup do
val[i] = round (steps*math.log (subgroup[i])/math.log (2))
end
error_list = find_error (val, subgroup, monzo_list)
for i = 1, #error_list do
ratiocomp = string.format ("%d/%d, %d/%d", error_list[i].ratio.num, error_list[i].ratio.den, 2*error_list[i].ratio.den, error_list[i].ratio.num)
error_abs = string.format ("%.3f", error_list[i].error_abs)
if bit32.band (error_list[i].ratio.den, error_list[i].ratio.den - 1) == 0 and is_in (error_list[i].ratio.num, subgroup) then -- check power of 2 for den and prime for num
ratiocomp = "'''" .. ratiocomp .. "'''"
error_abs = "'''" .. error_abs .. "'''"
end if error_list[i].error_rel > 50 then
ratiocomp = "''" .. ratiocomp .. "''"
error_abs = "''" .. error_abs .. "''"
end
t_body[i] = string.format ("|-\n| %s\n| %s", ratiocomp, error_abs)
end
return "{| class=\"wikitable center-all mw-collapsible mw-collapsed\"\n" ..
"|+style=white-space:nowrap| " .. t_title .. "\n" ..
"|-\n" ..
"! Interval, complement\n" ..
"! Error (abs, [[Cent|¢]])\n" ..
table.concat (t_body, "\n") ..
"\n|}"
end
-- local function prec_by_equal (steps)
-- return math.floor (math.log (steps*1.9)/math.log (10))
-- end
function p.odd_limit (frame)
local steps = tonumber (frame.args['steps'])
local limit = math.max (tonumber (frame.args['limit']), 2)
-- local prec = tonumber (frame.args['prec']) or prec_by_equal (steps)
local title = frame.args['title']
if title == nil or #title == 0 then
title = string.format ("Approximation of %d-odd-limit intervals by patent val mapping", limit)
end
local subgroup = table_filter (PRIME_LIST, limit)
local monzo_list = get_monzo_list (limit)
return approx (steps, subgroup, monzo_list, title)
end
return p;