Module:Uniform map: Difference between revisions

m More p fixing...
ArrowHead294 (talk | contribs)
mNo edit summary
 
(27 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 = {}


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
p.lower = {0, 0 ,0} -- List of smallest sizes that match a map for each prime
local utils = require("Module:Utils")
p.upper = {0, 0, 0} -- List of largest sizes that match a map for each prime
local yesno = require("Module:Yesno")
p.pbi = 0           -- Index of the prime that defines the boundary
 
-- 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
-- Find the minimum size that corresponds to a given map
function p.lowerbound(map)
function p.lower_bound(m)
local lowermax
local lowermax
for i=1, #map do
for i = 1, #m.map do
p.lower[i] = (map[i]-1/2)/u._log(p.primes[i])
m.lower[i] = (m.map[i] - 0.5) / utils.log2(utils.primes[i])
lowermax = math.max(unpack(p.lower))
lowermax = math.max(unpack(m.lower))
end
end
return math.max(0, lowermax)
return math.max(0, lowermax)
Line 19: Line 32:


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


-- Find the p-limit just intonation point (JIP) corresponding to a given size
-- Find the p-limit just tuning map corresponding to a given size
function p.JIP(size, prime)
function p.just_tuning_map(size, prime)
local JIP_table = {}
prime = tonumber(prime)
for i=1, u.index_of(p.primes, prime) do
local p_index = utils.index_of(utils.primes, prime)
JIP_table[i] = size*u._log(p.primes[i])
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
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 p.simple_map(size, prime)
function p.simple_map(size, prime)
local simple_map_table = {}
prime = tonumber(prime)
for i=1, u.index_of(p.primes, prime) do
local p_index = utils.index_of(utils.primes, prime)
simple_map_table[i] = u._round_dec(size*u._log(p.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


Line 50: Line 69:
function p.wart(map)
function p.wart(map)
local edo = map[1]
local edo = map[1]
local simple_map_edo = p.simple_map(edo, primes[#map])
local simple_map_edo = p.simple_map(edo, utils.primes[#map])
local JIP_edo = p.JIP(edo, primes[#map])
local just_tuning_map_edo = p.just_tuning_map(edo, utils.primes[#map])
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'}
local wart_notation = edo
local 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
local direction = math.ceil(JIP_edo[i]-simple_map_edo[i])
local direction = math.ceil(just_tuning_map_edo[i] - simple_map_edo[i])
local 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 (but could potentially be used standalone for raw data with headers)
-- Generate table of p-limit uniform maps between min and max, for use with print_table
function p.make_table(prime, min, max)
-- Could potentially be used standalone for raw data with headers
local map = {}
function p.make_table(prime, prec, min, max)
local maptable = {}                     -- Table of uniform maps with boundaries and wart notation
local maptable = {} -- Table of uniform maps with boundaries and wart notation
for i=1, u.index_of(p.primes, prime) do
local map_table = p.new()
map[i] = 0                        -- Reset to p-limit null map
map_table.map = p.simple_map(min, prime) -- Set p-limit map for minimum size
p.lower[i] = 0
local lb = p.lower_bound(map_table) -- Minimum size for the current map
p.upper[i] = 0
local ub = p.upper_bound(map_table) -- Maximum size for the current map
end
local row = { "Min. size", "Max. size", "[[Wart notation]]" }
map = p.simple_map(min, prime)               -- Set p-limit map for minimum size
for i = 1, #map_table.map do
local lb = lowerbound(map) -- Minimum size for the current map
table.insert(row, utils.primes[i])
local ub = upperbound(map) -- Maximum size for the current map
local row = {'Min. size', 'Max. size', '[[Wart notation]]'}
for i=1, #map do
table.insert(row, p.primes[i])
end
end
table.insert(maptable, row)
table.insert(maptable, row)
while lb < max do
while lb < max do
row = {string.format("%.4f", lb), string.format("%.4f", ub), p.wart(map)}
row = { string.format(string.format("%%.%df", tonumber(prec)), lb), string.format(string.format("%%.%df", tonumber(prec)), ub), p.wart(map_table.map) }
for j=1, #map do
for j = 1, #map_table.map do
table.insert(row, map[j])
table.insert(row, map_table.map[j])
end
end
table.insert(maptable, row)
table.insert(maptable, row)
map[pbi] = map[pbi] + 1
map_table.map[map_table.pbi] = map_table.map[map_table.pbi] + 1
lb = lowerbound(map)
lb = p.lower_bound(map_table)
ub = upperbound(map)
ub = p.upper_bound(map_table)
end
end
return maptable
return maptable
Line 101: Line 115:
function p.print_table(frame)
function p.print_table(frame)
local args = getArgs(frame)
local args = getArgs(frame)
return p._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"])
 
-- Default to 13-limit
prime = utils.eval_num_arg(prime, 13)
if utils.index_of(utils.primes, prime) == nil then
prime = 13
end
assert(prime, "Prime limit undefined.")
 
min = utils.eval_num_arg(min, nil)
max = utils.eval_num_arg(max, nil)


function p._print_table(prime, min, max)
if max == nil or min == nil then
if u.index_of(p.primes, u.eval_num_arg(prime, 5)) == nil then
assert(edo, "Must provide edo if not min or max given.")
prime = 5                          -- Default to 5-limit
-- default to +/- 0.2
min = edo - 0.2
max = edo + 0.2
end
end
luatable = p.make_table(p, u.eval_num_arg(min, 11.5), u.eval_num_arg(max, 12.5))
 
wikitable = string.format('{| class="wikitable"\n|+ %d-limit [[uniform map]]s between %f and %f', prime, min, max)
local luatable = p.make_table(prime, prec, min, max)
for i=1, 3 do
local result = '{| class="wikitable"\n'
wikitable = wikitable .. '\n! ' .. luatable[1][i]
.. '|+ style="font-size: 105%; | '
.. 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
end
wikitable = wikitable .. '\n! Map'
result = result .. "! Map\n"
for i=2, #luatable do
for i = 2, #luatable do
wikitable = wikitable .. '\n|-'
result = result .. "|-\n"
for j=1, 3 do
for j = 1, 3 do
wikitable = wikitable .. '\n| ' .. luatable[i][j]
result = result .. "| " .. luatable[i][j] .. "\n"
end
end
wikitable = wikitable .. '\n| {{map|'
local wikimap = ""
for j=4, #luatable do
for j = 4, #luatable[i] do
wikitable = wikitable .. ' ' .. luatable[i][j]
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