Module:Q-odd-limit intervals: Difference between revisions
gcd no longer needs to be defined here |
ArrowHead294 (talk | contribs) No edit summary |
||
| Line 1: | Line 1: | ||
bit32 = require ( | bit32 = require("bit32") | ||
utils = require ( | utils = require("Module:Utils") | ||
local p = {} | local p = {} | ||
| Line 6: | Line 6: | ||
local PRIME_LIST = {2, 3, 5, 7, 11, 13, 17, 19, 23} | local PRIME_LIST = {2, 3, 5, 7, 11, 13, 17, 19, 23} | ||
local function is_in (v, t) | local function is_in(v, t) | ||
for i = 1, #t do | for i = 1, #t do | ||
if v == t[i] then | if v == t[i] then | ||
| Line 15: | Line 15: | ||
end | end | ||
local function table_filter (t, thres) | local function table_filter(t, thres) | ||
for i = 1, #t do | for i = 1, #t do | ||
if t[i] > thres then | if t[i] > thres then | ||
return {unpack (t, 1, i - 1)} | return {unpack(t, 1, i - 1)} | ||
end | end | ||
end | end | ||
| Line 24: | Line 24: | ||
end | end | ||
local function inner_product (val, monzo) | local function inner_product(val, monzo) | ||
local result = 0 | local result = 0 | ||
for i = 1, #val do | for i = 1, #val do | ||
result = result + val[i]*monzo[i] | result = result + val[i] * monzo[i] | ||
end | end | ||
return result | return result | ||
end | end | ||
local function monzo2ratio (monzo, subgroup) | local function monzo2ratio(monzo, subgroup) | ||
local num = 1 | local num = 1 | ||
local den = 1 | local den = 1 | ||
for i = 1, #subgroup do | for i = 1, #subgroup do | ||
if monzo[i] > 0 then | if monzo[i] > 0 then | ||
num = num*subgroup[i]^monzo[i] | num = num * subgroup[i]^monzo[i] | ||
elseif monzo[i] < 0 then | elseif monzo[i] < 0 then | ||
den = den*subgroup[i]^(-monzo[i]) | den = den * subgroup[i]^(-monzo[i]) | ||
end | end | ||
end | end | ||
| Line 45: | Line 45: | ||
end | end | ||
local function ratio2monzo (ratio, subgroup) | local function ratio2monzo(ratio, subgroup) | ||
local monzo = {} | local monzo = {} | ||
for i = 1, #subgroup do | for i = 1, #subgroup do | ||
| Line 60: | Line 60: | ||
end | end | ||
local function monzo2cent (monzo, subgroup) | local function monzo2cent(monzo, subgroup) | ||
local jip = {} | local jip = {} | ||
for i = 1, #subgroup do | for i = 1, #subgroup do | ||
jip[i] = 1200*utils._log (subgroup[i], 2) | jip[i] = 1200 * utils._log(subgroup[i], 2) | ||
end | end | ||
return inner_product (jip, monzo) | return inner_product(jip, monzo) | ||
end | end | ||
local function ratio_8ve_reduction (ratio) | local function ratio_8ve_reduction(ratio) | ||
local oct = math.floor (utils._log (ratio.num/ratio.den, 2)) | local oct = math.floor(utils._log(ratio.num / ratio.den, 2)) | ||
if oct > 0 then | if oct > 0 then | ||
ratio.den = ratio.den * 2^oct | ratio.den = ratio.den * 2^oct | ||
| Line 78: | Line 78: | ||
end | end | ||
local function odd_limit_monzo_list_gen (limit) | local function odd_limit_monzo_list_gen(limit) | ||
local monzo_list = {} | local monzo_list = {} | ||
local subgroup = table_filter (PRIME_LIST, limit) | local subgroup = table_filter(PRIME_LIST, limit) | ||
for num = 1, limit, 2 do | for num = 1, limit, 2 do | ||
for den = 1, num, 2 do | for den = 1, num, 2 do | ||
if utils._gcd (num, den) == 1 then | if utils._gcd(num, den) == 1 then | ||
ratio = ratio_8ve_reduction ({num = num, den = den}) | ratio = ratio_8ve_reduction({num = num, den = den}) | ||
table.insert (monzo_list, ratio2monzo (ratio, subgroup)) | table.insert(monzo_list, ratio2monzo(ratio, subgroup)) | ||
end | end | ||
end | end | ||
| Line 92: | Line 92: | ||
end | end | ||
local function find_error (val, subgroup, monzo_list) | local function find_error(val, subgroup, monzo_list) | ||
local step_size = 1200/val[1] | local step_size = 1200/val[1] | ||
local true_size | local true_size | ||
| Line 98: | Line 98: | ||
local error_list = {} | local error_list = {} | ||
for i = 1, #monzo_list do | for i = 1, #monzo_list do | ||
ratio = monzo2ratio (monzo_list[i], subgroup) | ratio = monzo2ratio(monzo_list[i], subgroup) | ||
comp = {2*ratio.den, ratio.num} | comp = {2 * ratio.den, ratio.num} | ||
true_size = monzo2cent (monzo_list[i], subgroup) | true_size = monzo2cent(monzo_list[i], subgroup) | ||
approx_size = step_size*inner_product (val, monzo_list[i]) | approx_size = step_size * inner_product(val, monzo_list[i]) | ||
error_abs = math.abs (approx_size - true_size) | error_abs = math.abs(approx_size - true_size) | ||
error_rel = 100*error_abs/step_size | error_rel = 100 * error_abs / step_size | ||
error_list[i] = | error_list[i] = | ||
{ | { | ||
| Line 112: | Line 112: | ||
} | } | ||
end | end | ||
table.sort (error_list, function (a, b) return a.error_abs < b.error_abs end) | table.sort(error_list, function(a, b) return a.error_abs < b.error_abs end) | ||
return error_list | return error_list | ||
end | end | ||
local function approx (steps, subgroup, monzo_list, t_title) | local function approx(steps, subgroup, monzo_list, t_title) | ||
local t_body = {} | local t_body = {} | ||
local val = {} | local val = {} | ||
for i = 1, #subgroup do | for i = 1, #subgroup do | ||
val[i] = utils._round_dec (steps*utils._log (subgroup[i], 2)) | val[i] = utils._round_dec(steps*utils._log(subgroup[i], 2)) | ||
end | end | ||
error_list = find_error (val, subgroup, monzo_list) | error_list = find_error(val, subgroup, monzo_list) | ||
for i = 1, #error_list do | 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) | 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) | error_abs = string.format("%.3f", error_list[i].error_abs) | ||
error_rel = string.format ("%.1f", error_list[i].error_rel) | error_rel = string.format("%.1f", error_list[i].error_rel) | ||
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 | 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 .. "'''" | ratiocomp = "'''" .. ratiocomp .. "'''" | ||
error_abs = "'''" .. error_abs .. "'''" | error_abs = "'''" .. error_abs .. "'''" | ||
error_rel = "'''" .. error_rel .. "'''" | error_rel = "'''" .. error_rel .. "'''" | ||
end if error_list[i].error_rel > 50 then | end if error_list[i].error_rel > 50 then | ||
ratiocomp = "''" .. ratiocomp .. "''" | ratiocomp = "''<span style=\"background-color: #aaaaaa;\">" .. ratiocomp .. "<\/span>''" | ||
error_abs = "''" .. error_abs .. "''" | error_abs = "''<span style=\"background-color: #aaaaaa;\">" .. error_abs .. "<\/span>''" | ||
error_rel = "''" .. error_rel .. "''" | error_rel = "''<span style=\"background-color: #aaaaaa;\">" .. error_rel .. "<\/span>''" | ||
end | end | ||
t_body[i] = string.format ("|-\n| %s\n| %s\n| %s", ratiocomp, error_abs, error_rel) | t_body[i] = string.format("|-\n| %s\n| %s\n| %s", ratiocomp, error_abs, error_rel) | ||
end | end | ||
return "{| class=\"wikitable center-all mw-collapsible mw-collapsed\"\n" .. | return "{| class=\"wikitable center-all mw-collapsible mw-collapsed\"\n" .. | ||
"|+style=white-space:nowrap| " .. t_title .. "\n" .. | "|+ style=\"white-space: nowrap;\" | " .. t_title .. "\n" .. | ||
"|-\n" .. | "|-\n" .. | ||
"! Interval, complement\n" .. | "! Interval, complement\n" .. | ||
"! Error (abs, [[Cent|¢]])\n" .. | "! Error (abs, [[Cent|¢]])\n" .. | ||
"! Error (rel, [[Relative cent|%]])\n" .. | "! Error (rel, [[Relative cent|%]])\n" .. | ||
table.concat (t_body, "\n") .. | table.concat(t_body, "\n") .. | ||
"\n|}" | "\n|}" | ||
end | end | ||
| Line 153: | Line 153: | ||
-- end | -- end | ||
function p.odd_limit (frame) | function p.odd_limit(frame) | ||
local steps = tonumber (frame.args[ | local steps = tonumber(frame.args["steps"]) | ||
local limit = math.max (tonumber (frame.args[ | local limit = math.max(tonumber (frame.args["limit"]), 2) | ||
-- local prec = tonumber (frame.args['prec']) or prec_by_equal (steps) | -- local prec = tonumber (frame.args['prec']) or prec_by_equal (steps) | ||
local title = frame.args[ | local title = frame.args["title"] | ||
if title == nil or #title == 0 then | if title == nil or #title == 0 then | ||
title = string.format ("%d-odd-limit intervals by patent val mapping", limit) | title = string.format("%d-odd-limit intervals by patent val mapping", limit) | ||
end | end | ||
local subgroup = table_filter (PRIME_LIST, limit) | local subgroup = table_filter(PRIME_LIST, limit) | ||
local monzo_list = odd_limit_monzo_list_gen (limit) | local monzo_list = odd_limit_monzo_list_gen(limit) | ||
return approx (steps, subgroup, monzo_list, title) | return approx(steps, subgroup, monzo_list, title) | ||
end | end | ||
return p; | return p; | ||