Module:Uniform map: Difference between revisions

m Fix typo
ArrowHead294 (talk | contribs)
mNo edit summary
 
(36 intermediate revisions by 3 users not shown)
Line 1: Line 1:
local getArgs = require('Module:Arguments').getArgs
local u = require('Module:Utils')
local p = {}
local p = {}


primes = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97}
local getArgs = require("Module:Arguments").getArgs
map = {0, 0, 0}
local utils = require("Module:Utils")
lower = {0, 0 ,0} -- List of smallest sizes that match a map for each prime
local yesno = require("Module:Yesno")
upper = {0, 0, 0} -- List of largest sizes that match a map for each prime
 
pbi = 0           -- Index of the prime that defines the boundary
-- stylua: ignore
maptable = {}      -- Table of uniform maps with boundaries and wart notation
local warts = {
"a", "b", "c", "d", "e", "f", "g", "h", "i",
    "j", "k", "l", "m", "n", "o", "p", "q", "r",
    "s", "t", "u", "v", "w", "x", "y", "z"
}
 
function p.new()
local m = {}
m.map = {} -- The prime map
m.lower = {} -- List of smallest sizes that match a map for each prime
m.upper = {} -- List of largest sizes that match a map for each prime
m.pbi = 0 -- Index of the prime that defines the boundary
return m
end


-- Find the minimum size that corresponds to a given map
-- Find the minimum size that corresponds to a given map
function lowerbound(map)
function p.lower_bound(m)
for i=1, #map do
local lowermax
lower[i] = (map[i]-1/2)/u._log(primes[i])
for i = 1, #m.map do
lowermax = math.max(unpack(lower))
m.lower[i] = (m.map[i] - 0.5) / utils.log2(utils.primes[i])
lowermax = math.max(unpack(m.lower))
end
end
return math.max(0, lowermax)
return math.max(0, lowermax)
Line 20: Line 32:


-- Find the maximum size that corresponds to a given map
-- Find the maximum size that corresponds to a given map
function upperbound(map)
function p.upper_bound(m)
for i=1, #map do
local uppermin
upper[i] = (map[i]+1/2)/u._log(primes[i])
for i = 1, #m.map do
uppermin = math.min(unpack(upper))
m.upper[i] = (m.map[i] + 1 / 2) / utils.log2(utils.primes[i])
pbi = u.index_of(upper, uppermin)
uppermin = math.min(unpack(m.upper))
m.pbi = utils.index_of(m.upper, uppermin)
end
end
return math.max(0, uppermin)
return math.max(0, uppermin)
end
end


lb = lowerbound(map)  -- Minimum size for the current map
-- Find the p-limit just tuning map corresponding to a given size
ub = upperbound(map)  -- Maximum size for the current map
function p.just_tuning_map(size, prime)
 
prime = tonumber(prime)
-- Find the p-limit just intonation point (JIP) corresponding to a given size
local p_index = utils.index_of(utils.primes, prime)
function JIP(size, p)
assert(p_index ~= nil, "index of prime " .. prime .. " not found")
JIP_table = {}
local just_tuning_map = {}
for i=1, u.index_of(primes, p) do
for i = 1, utils.index_of(utils.primes, prime) do
JIP_table[i] = size*u._log(primes[i])
just_tuning_map[i] = size * utils.log2(utils.primes[i])
end
end
return JIP_table
return just_tuning_map
end
end


-- Find the p-limit simple map corresponding to a given size
-- Find the p-limit simple map corresponding to a given size
function simple_map(size, p)
function p.simple_map(size, prime)
simple_map_table = {}
prime = tonumber(prime)
for i=1, u.index_of(primes, p) do
local p_index = utils.index_of(utils.primes, prime)
simple_map_table[i] = u._round_dec(size*u._log(primes[i]))
assert(p_index ~= nil, "index of prime " .. prime .. " not found")
local simple_map = {}
for i = 1, p_index do
simple_map[i] = math.floor(0.5 + size * utils.log2(utils.primes[i]))
end
end
return simple_map_table
return simple_map
end
end


-- Find the wart notation corresponding to a given map
-- Find the wart notation corresponding to a given map
function wart(map)
function p.wart(map)
edo = map[1]
local edo = map[1]
simple_map_edo = simple_map(edo, primes[#map])
local simple_map_edo = p.simple_map(edo, utils.primes[#map])
JIP_edo = JIP(edo, primes[#map])
local just_tuning_map_edo = p.just_tuning_map(edo, utils.primes[#map])
warts = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}
local wart_notation = edo
wart_notation = edo
for i = 2, #map do
for i=2, #map do
-- direction is 1 if current harmonic mapped flatter than just, otherwise 0
-- direction is 1 if current harmonic mapped flatter than just, otherwise 0
direction = math.ceil(JIP_edo[i]-simple_map_edo[i])
local direction = math.ceil(just_tuning_map_edo[i] - simple_map_edo[i])
difference = map[i]-simple_map_edo[i]
local difference = map[i] - simple_map_edo[i]
if difference ~= 0 then
if difference ~= 0 then
number_warts = (2*math.abs(difference)+(u.signum((-1)^direction*difference)-1)/2)
local number_warts = (2 * math.abs(difference) + (utils.signum((-1) ^ direction * difference) - 1) / 2)
for j=1,number_warts do
for _ = 1, number_warts do
wart_notation = wart_notation .. warts[i]
wart_notation = wart_notation .. warts[i]
end
end
end
end
end
end
    return wart_notation
return wart_notation
end
end


-- Generate table of p-limit uniform maps between min and max, for use with print_table
-- Generate table of p-limit uniform maps between min and max, for use with print_table
function make_table(p, min, max)
-- Could potentially be used standalone for raw data with headers
if u.index_of(primes, p) == nil then
function p.make_table(prime, prec, min, max)
print(p .. ' is not prime!')
local maptable = {} -- Table of uniform maps with boundaries and wart notation
return
local map_table = p.new()
else
map_table.map = p.simple_map(min, prime) -- Set p-limit map for minimum size
maptable = {}                         -- Reset table
local lb = p.lower_bound(map_table) -- Minimum size for the current map
for i=1, u.index_of(primes, p) do
local ub = p.upper_bound(map_table) -- Maximum size for the current map
map[i] = 0                        -- Reset to p-limit null map
local row = { "Min. size", "Max. size", "[[Wart notation]]" }
lower[i] = 0
for i = 1, #map_table.map do
upper[i] = 0
table.insert(row, utils.primes[i])
end
end
map = simple_map(min, p)               -- Set p-limit map for minimum size
table.insert(maptable, row)
lb = lowerbound(map)                   -- Update minimum size for new map
while lb < max do
ub = upperbound(map)                   -- Update maximum size for new map
row = { string.format(string.format("%%.%df", tonumber(prec)), lb), string.format(string.format("%%.%df", tonumber(prec)), ub), p.wart(map_table.map) }
row = {'Min. size', 'Max. size', '[[Wart notation]]'}
for j = 1, #map_table.map do
for i=1, #map do
table.insert(row, map_table.map[j])
table.insert(row, primes[i])
end
end
table.insert(maptable, row)
table.insert(maptable, row)
while lb < max do
map_table.map[map_table.pbi] = map_table.map[map_table.pbi] + 1
row = {string.format("%.4f", lb), string.format("%.4f", ub), wart(map)}
lb = p.lower_bound(map_table)
for j=1, #map do
ub = p.upper_bound(map_table)
table.insert(row, map[j])
end
table.insert(maptable, row)
map[pbi] = map[pbi] + 1
lb = lowerbound(map)
ub = upperbound(map)
end
return maptable
end
end
return maptable
end
end


Line 108: Line 115:
function p.print_table(frame)
function p.print_table(frame)
local args = getArgs(frame)
local args = getArgs(frame)
return u._print_table(args[1], args[2], args[3])
local prime = args["limit"]
end
local min = args["min"]
local max = args["max"]
local edo = args["edo"]
local prec = args["prec"]
local debugg = yesno(args["debug"])


function p._print_table(p, min, max)
-- Default to 13-limit
if u.index_of(primes, u.eval_num_arg(p, 5)) == nil then
prime = utils.eval_num_arg(prime, 13)
print(p .. ' is not prime!')
if utils.index_of(utils.primes, prime) == nil then
return
prime = 13
end
end
luatable = make_table(p, u.eval_num_arg(min, 11.5), u.eval_num_arg(max, 12.5))
assert(prime, "Prime limit undefined.")
wikitable = string.format('{| class="wikitable"\n|+ %d-limit [[uniform map]]s between %f and %f', p, min, max)
 
for i=1, 3 do
min = utils.eval_num_arg(min, nil)
wikitable = wikitable .. '\n! ' .. luatable[1][i]
max = utils.eval_num_arg(max, nil)
 
if max == nil or min == nil then
assert(edo, "Must provide edo if not min or max given.")
-- default to +/- 0.2
min = edo - 0.2
max = edo + 0.2
end
end
wikitable = wikitable .. '\n! Map'
 
for i=2, #luatable do
local luatable = p.make_table(prime, prec, min, max)
wikitable = wikitable .. '\n|-'
local result = '{| class="wikitable"\n'
for j=1, 3 do
.. '|+ style="font-size: 105%; | '
wikitable = wikitable .. '\n| ' .. luatable[i][j]
.. string.format("%d-limit [[uniform map]]s between %g and %g\n", prime, min, max)
.. "|-\n"
for i = 1, 3 do
result = result .. "! " .. luatable[1][i] .. "\n"
end
result = result .. "! Map\n"
for i = 2, #luatable do
result = result .. "|-\n"
for j = 1, 3 do
result = result .. "| " .. luatable[i][j] .. "\n"
end
end
wikitable = wikitable .. '\n| {{map|'
local wikimap = ""
for j=1, #map do
for j = 4, #luatable[i] do
wikitable = wikitable .. ' ' .. luatable[i][j+3]
wikimap = wikimap .. " " .. luatable[i][j]
end
end
wikitable = wikitable .. '}}'
result = result .. string.format("| {{map|%s}}\n", wikimap)
end
result = result .. "|}"
 
-- Debugger option
if debugg == true then
result = "<syntaxhighlight lang=\"wikitext\">" .. result .. "</syntaxhighlight>"
end
end
wikitable = wikitable .. '\n|}'
    return print(wikitable)
return frame:preprocess(result)
end
end


return p
return p