- This module should not be invoked directly; use its corresponding template instead: Template:Temperament data.
|
Module:Temperament data is a draft module. It is incomplete and may not be in active development. If possible, editors are encouraged to help with its development. In the meantime, editors should avoid using this module across the Xenharmonic Wiki, except for testing.
|
| Introspection summary for Module:Temperament data
|
Functions provided (1)
| Line
|
Function
|
Params
|
| 229
|
temperament_data (invokable)
|
(frame)
|
|
|
No function descriptions were provided. The Lua code may have further information.
local rat = require('Module:Rational')
local p = {}
local u = require('Module:Utils')
local function gcd(a,b)
if type(a) == "number" and type(b) == "number" and
a == math.floor(a) and b == math.floor(b) then
if b == 0 then
return a
else
return gcd(b, a % b) -- tail recursion
end
else
error("Invalid argument to gcd (" .. tostring(a) .. "," ..
tostring(b) .. ")", 2)
end
end
-- Linear algebra and RTT functions
local function matadd(a, b)
local result = {}
for i = 1, #a do
result[i] = {}
for j = 1, #(b[1]) do
result[i][j] = a[i][j] + b[i][j]
end
end
return result
end
local function matsub(a, b)
local result = {}
for i = 1, #a do
result[i] = {}
for j = 1, #(b[1]) do
result[i][j] = a[i][j] - b[i][j]
end
end
return result
end
local function matmul(a, b)
local result = {}
for i = 1, #a do
result[i] = {}
for j = 1, #(b[1]) do
result[i][j] = 0
for k = 1, #(a[1]) do
result[i][j] = result[i][j] + (a[i][k] * b[k][j])
end
end
end
return result
end
local function scalarmatmul(a, b)
local result = {}
for i = 1, #a do
result[i] = {}
for j = 1, #(a[1]) do
result[i][j] = a[i][j] * b
end
end
return result
end
local function matinv(a)
local dbl_identity = {}
for i = 1, #a do
dbl_identity[i] = {}
for j = 1, #a do
if i == j then
dbl_identity[i][j] = 2
else
dbl_identity[i][j] = 0
end
end
end
local xn = scalarmatmul(a, 0.00000001)
for i = 1, 30 do
xn = matmul(xn, matsub(dbl_identity, matmul(a, xn)))
end
return xn
end
local function transpose(a)
local result = {}
for i = 1, #a[1] do
result[i] = {}
for j = 1, #a do
result[i][j] = a[j][i]
end
end
return result
end
local function antitranspose(a)
local result = {}
for i = 1, #a[1] do
result[i] = {}
for j = 1, #a do
result[i][j] = a[#a - j + 1][#a[1] - i + 1]
end
end
return result
end
local function pseudoinv(a)
return matmul(transpose(a), matinv(matmul(a, transpose(a))))
end
local function nullspace(mapping)
local identity = {}
for i = 1, #mapping[1] do
identity[i] = {}
for j = 1, #mapping[1] do
if i == j then
identity[i][j] = 1
else
identity[i][j] = 0
end
end
end
-- local w = {{0},{1},{0}}
-- for i = 1, #mapping[1] do
-- w[i] = {10}
-- end
return matsub(identity, matmul(pseudoinv(mapping), mapping))
end
local function unreduced_mapping_from_basis(comma_basis)
return antitranspose(nullspace(antitranspose(comma_basis)))
end
local function get_te_tuning_map(subgroup, comma_basis)
local v = unreduced_mapping_from_basis(comma_basis)
local w = {}
for i = 1, #subgroup do
w[i] = {}
for j = 1, #subgroup do
if i == j then
w[i][j] = math.log(2)/math.log(subgroup[i])
else
w[i][j] = 0
end
end
end
local jw = {{}}
for i = 1, #subgroup do
jw[1][i] = 1
end
local vw = matmul(v, w)
local g = matmul(jw, pseudoinv(vw))
return g
end
local function get_te_generator(subgroup, comma_basis, preimage)
return matmul(get_te_tuning_map(subgroup, comma_basis), preimage)
end
-- Parsing/display functions
local function int_to_subgroup_monzo(subgroup, x)
local result = {}
local x2 = x
for i = 1, #subgroup do
result[i] = 0
while true do
x2 = x2 / subgroup[i]
if x2 ~= math.floor(x2) then
break
end
result[i] = result[i] + 1
end
x2 = x
end
return result
end
local function rat_to_subgroup_monzo(subgroup, x)
local n, d = rat.as_pair(x)
return matsub({int_to_subgroup_monzo(subgroup, n)}, {int_to_subgroup_monzo(subgroup, d)})[1]
end
local function rat_list_to_matrix(subgroup, list)
local result = {}
for j = 1, #subgroup do
result[j] = {}
end
for i = 1, #list do
local smonzo = rat_to_subgroup_monzo(subgroup, list[i])
for j = 1, #subgroup do
result[j][i] = smonzo[j]
end
end
return result
end
local function mysplit (inputstr, sep)
if sep == nil then
sep = "%s"
end
local t={}
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
table.insert(t, str)
end
return t
end
local function trim(x)
local str = x
str = str:gsub("%s+", "")
str = string.gsub(str, "%s+", "")
return str
end
function p.temperament_data(frame)
local subgroup = mysplit(frame.args['subgroup'], ".")
for i = 1, #subgroup do
subgroup[i] = tonumber(subgroup[i])
end
local comma_matrix = mysplit(frame.args['comma_list'], ",")
for i = 1, #comma_matrix do
comma_matrix[i] = rat.parse(comma_matrix[i])
end
comma_matrix = rat_list_to_matrix(subgroup, comma_matrix)
local unparsed_gens = mysplit(frame.args['generators'], ",")
local generators = mysplit(frame.args['generators'], ",")
for i = 1, #generators do
generators[i] = rat.parse(generators[i])
end
generators = rat_list_to_matrix(subgroup, generators)
local te_generator = get_te_generator(subgroup, comma_matrix, generators)
local result = "[[Subgroup]]: " .. frame.args['subgroup']
result = result .. "\n\n[[Comma list]]: " .. frame.args['comma_list']
result = result .. "\n\n: mapping generators: "
for i = 1, #unparsed_gens do
result = result .. '~' .. trim(unparsed_gens[i]) .. ", "
end
result = result:sub(0,-3)
result = result .. "\n\n[[Optimal tuning]] ([[TE]]): "
for i = 1, #(te_generator[1]) do
result = result .. '~' .. trim(unparsed_gens[i]) .. ' = ' .. u._round(te_generator[1][i] * 1200, 7) .. ", "
end
result = result:sub(0,-3)
return result
end
return p