Module:Uniform map
Jump to navigation
Jump to search
Documentation transcluded from /doc
Note: Do not invoke this module directly; use the corresponding template instead: Template:Uniform map.
Documentation transcluded from /doc
Note: Do not invoke this module directly; use the corresponding template instead: Template:Uniform map.
This module is called by Template:Uniform map to produce a table of p-limit uniform maps between two size boundaries.
local getArgs = require("Module:Arguments").getArgs
local utils = require("Module:Utils")
local p = {}
-- stylua: ignore
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
function p.lower_bound(m)
local lowermax
for i = 1, #m.map do
m.lower[i] = (m.map[i] - 0.5) / utils.log2(utils.primes[i])
lowermax = math.max(unpack(m.lower))
end
return math.max(0, lowermax)
end
-- Find the maximum size that corresponds to a given map
function p.upper_bound(m)
local uppermin
for i = 1, #m.map do
m.upper[i] = (m.map[i] + 1 / 2) / utils.log2(utils.primes[i])
uppermin = math.min(unpack(m.upper))
m.pbi = utils.index_of(m.upper, uppermin)
end
return math.max(0, uppermin)
end
-- Find the p-limit just tuning map corresponding to a given size
function p.just_tuning_map(size, prime)
prime = tonumber(prime)
local p_index = utils.index_of(utils.primes, prime)
assert(p_index ~= nil, "index of prime " .. prime .. " not found")
local just_tuning_map = {}
for i = 1, utils.index_of(utils.primes, prime) do
just_tuning_map[i] = size * utils.log2(utils.primes[i])
end
return just_tuning_map
end
-- Find the p-limit simple map corresponding to a given size
function p.simple_map(size, prime)
prime = tonumber(prime)
local p_index = utils.index_of(utils.primes, prime)
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
return simple_map
end
-- Find the wart notation corresponding to a given map
function p.wart(map)
local edo = map[1]
local simple_map_edo = p.simple_map(edo, utils.primes[#map])
local just_tuning_map_edo = p.just_tuning_map(edo, utils.primes[#map])
local wart_notation = edo
for i = 2, #map do
-- direction is 1 if current harmonic mapped flatter than just, otherwise 0
local direction = math.ceil(just_tuning_map_edo[i] - simple_map_edo[i])
local difference = map[i] - simple_map_edo[i]
if difference ~= 0 then
local number_warts = (2 * math.abs(difference) + (utils.signum((-1) ^ direction * difference) - 1) / 2)
for _ = 1, number_warts do
wart_notation = wart_notation .. warts[i]
end
end
end
return wart_notation
end
-- Generate table of p-limit uniform maps between min and max, for use with print_table
-- Could potentially be used standalone for raw data with headers
function p.make_table(prime, min, max)
local maptable = {} -- Table of uniform maps with boundaries and wart notation
local map_table = p.new()
map_table.map = p.simple_map(min, prime) -- Set p-limit map for minimum size
local lb = p.lower_bound(map_table) -- Minimum size for the current map
local ub = p.upper_bound(map_table) -- Maximum size for the current map
local row = {"Min. size", "Max. size", "[[Wart notation]]"}
for i = 1, #map_table.map do
table.insert(row, utils.primes[i])
end
table.insert(maptable, row)
while lb < max do
row = {string.format("%.4f", lb), string.format("%.4f", ub), p.wart(map_table.map)}
for j = 1, #map_table.map do
table.insert(row, map_table.map[j])
end
table.insert(maptable, row)
map_table.map[map_table.pbi] = map_table.map[map_table.pbi] + 1
lb = p.lower_bound(map_table)
ub = p.upper_bound(map_table)
end
return maptable
end
-- Print wiki-formatted table (string) of p-limit uniform maps between min and max
function p.print_table(frame)
local args = getArgs(frame)
local prime = args[1]
local min = args[2]
local max = args[3]
if utils.index_of(utils.primes, utils.eval_num_arg(prime, 5)) == nil then
prime = 5 -- Default to 5-limit
end
local luatable = p.make_table(prime, utils.eval_num_arg(min, 11.5), utils.eval_num_arg(max, 12.5))
local wtable = "{| class=\"wikitable\"\n"
.. "|+ style=\"font-size: 105%; | "
.. string.format("%d-limit [[uniform map]]s between %g and %g", prime, min, max)
for i = 1, 3 do
wtable = wtable .. "\n! " .. luatable[1][i]
end
wtable = wtable .. "\n! Map"
for i = 2, #luatable do
wtable = wtable .. "\n|-"
for j = 1, 3 do
wtable = wtable .. "\n| " .. luatable[i][j]
end
local wikimap = ""
for j = 4, #luatable[i] do
wikimap = wikimap .. " " .. luatable[i][j]
end
wtable = wtable .. "\n| " .. frame:expandTemplate({ title = "map", args = { wikimap } })
end
wtable = wtable .. "\n|}"
return wtable
end
return p