Module:Infobox regtemp: Difference between revisions

From Xenharmonic Wiki
Jump to navigation Jump to search
+ a constant (12) above which we stop converting numbers to greek
Support for wart notation
Line 13: Line 13:
local basis = frame.args["commas"]
local basis = frame.args["commas"]
local edo_first = frame.args["edo_first"]
local et_first = frame.args["edo_first"]
local edo1 = tonumber(edo_first)
local et_second = frame.args["edo_second"]
local edo_second = frame.args["edo_second"]
local edo2 = tonumber(edo_second)
local tuning = frame.args["tuning"]
local tuning = frame.args["tuning"]
Line 38: Line 36:
local data = {}
local data = {}
table.insert(data, {
"Subgroups",
subgroup
})
table.insert(data, {
"Comma basis",
basis
})
table.insert(data, {
"Reduced mapping",
"⟨" .. mapping .. "]"
})
-- process mapping
-- process mapping
local map = {}
local map = {}
Line 75: Line 58:
local equave = u.eval_num_arg(subgroup_basis[1])
local equave = u.eval_num_arg(subgroup_basis[1])
local referent = u.eval_num_arg(subgroup_basis[2])
local referent = u.eval_num_arg(subgroup_basis[2])
local equave_letter
local cot = tonumber(genchain_mapping[2])
local cot = tonumber(genchain_mapping[2])
local suffix = "cleft"
local suffix = "cleft"
if equave == 3 then -- twelfth-based temp
if equave == 2 then -- octave-based temp
equave_letter = "t"
if referent == 3 then
suffix = "cot"
elseif referent == 5 then
suffix = "seph"
end
elseif equave == 3 then -- twelfth-based temp
if referent == 5 then
if referent == 5 then
referent_candidate = u.eval_num_arg(subgroup_basis[3])
referent_candidate = u.eval_num_arg(subgroup_basis[3])
Line 88: Line 75:
end
end
end
end
elseif equave == 1.5 then -- fifth-based temp
equave_letter = "f"
elseif equave == 2 then
equave_letter = "o"
if referent == 3 then
suffix = "cot"
elseif referent == 5 then
suffix = "seph"
end
else
equave_letter = equave
end
end
Line 161: Line 137:
end
end
-- edo join
-- process et join
local et_eq_first, et_num_first = p.warts2ed (et_first)
local et_eq_letter_first = p.equave2letter (et_eq_first)
local et_eq_second, et_num_second = p.warts2ed (et_second)
local et_eq_letter_second = p.equave2letter (et_eq_second)
-- construct the table
table.insert(data, {
"Subgroups",
subgroup
})
 
table.insert(data, {
"Comma basis",
basis
})
 
table.insert(data, {
"Reduced mapping",
"⟨" .. mapping .. "]"
})
 
table.insert(data, {
table.insert(data, {
"Edo join",
"ET join",
"[[" .. edo_first .. "ed" .. equave_letter .. "|" .. edo_first .. "]] & [[" .. edo_second .. "ed" .. equave_letter .. "|" .. edo_second .. "]]"
"[[" .. et_num_first .. "ed" .. et_eq_letter_first .. "|" .. et_first .. "]] & [["  
.. et_num_second .. "ed" .. et_eq_letter_second .. "|" .. et_second .. "]]"
})
})


Line 198: Line 196:
-- error and stuff
-- error and stuff
local limit_text
local limit_text
if equave_letter == "o" then
if equave == 2 then
limit_text = "-odd-limit"
limit_text = "-odd-limit"
elseif equave_letter == "t" then
elseif equave == 3 then
limit_text = "-throdd-limit"
limit_text = "-throdd-limit"
else
else
Line 407: Line 405:
end
end
return greek
return greek
end
function p.equave2letter(et_eq)
-- converts an equave string to a letter
local et_eq_letter
if et_eq == "2" then
et_eq_letter = "o"
elseif et_eq == "3" then
et_eq_letter = "t"
elseif et_eq == "3/2" then
et_eq_letter = "f"
else
et_eq_letter = eq
end
return et_eq_letter
end
function p.warts2ed(warts)
-- converts a wart notation to an equal division
local wart_prefix, et_num = warts:match ("(%a?)(%d+)")
local et_eq = "2"
if wart_prefix == "a" then
et_eq = "2"
elseif wart_prefix == "b" then
et_eq = "3"
elseif wart_prefix == "c" then
et_eq = "5"
elseif wart_prefix == "d" then
et_eq = "7"
elseif wart_prefix == "e" then
et_eq = "11"
elseif wart_prefix == "f" then
et_eq = "13"
elseif wart_prefix == "g" then
et_eq = "17"
elseif wart_prefix == "h" then
et_eq = "19"
elseif wart_prefix == "i" then
et_eq = "23"
end
return et_eq, et_num
end
end


return p
return p

Revision as of 14:00, 6 December 2025

Module documentation[view] [edit] [history] [purge]
This module should not be invoked directly; use its corresponding template instead: Template:Infobox regtemp.
Module:Infobox regtemp 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.

This module generates an infobox providing information about a given regular temperament.

Introspection summary for Module:Infobox regtemp 
Functions provided (7)
Line Function Params
7 infobox_RT (invokable) (frame)
230 digit2greek (number, purpose)
312 num2greek (number, purpose)
327 digit2greeklet (number, purpose)
394 num2greeklet (number)
409 equave2letter (et_eq)
424 warts2ed (warts)
Lua modules required (3)
Variable Module Functions used
infobox Module:Infobox build
u Module:Utils eval_num_arg
log2
value_provided
yesno Module:Yesno dependency not used

No function descriptions were provided. The Lua code may have further information.


local p = {}

local infobox = require("Module:Infobox")
local u = require("Module:Utils")
local yesno = require("Module:Yesno")

function p.infobox_RT(frame)
	
	-- no real math functionality... yet
	local name = frame.args["tempname"]
	
	local subgroup = frame.args["subgroup"]
	local basis = frame.args["commas"]
	
	local et_first = frame.args["edo_first"]
	local et_second = frame.args["edo_second"]
	
	local tuning = frame.args["tuning"]
	local genfrac = frame.args["genfrac"]
	local method = frame.args["method"]
	local mapping = frame.args["mapping"]
	
	local mos = frame.args["mosses"]
	local ploidacot_override = frame.args["ploidacot"]
	local colorname = frame.args["colorname"]
	local pergen = frame.args["pergen"]
	
	local limit1 = frame.args["lim1"]
	local comp1 = frame.args["comp1"]
	local acc1 = frame.args["acc1"]
	local limit2 = frame.args["lim2"]
	local comp2 = frame.args["comp2"]
	local acc2 = frame.args["acc2"]
	local debugg = frame.args["debug"]
	
	local data = {}
	
	-- process mapping
	local map = {}
	for str in mapping:gmatch("(-?%d+);") do
		table.insert(map, str)
	end
	local genchain_mapping = {}
	for str in mapping:gmatch("(-?%d+)") do
		table.insert(genchain_mapping, str)
	end
	genchain_mapping[1] = 0
	
	-- interpret subgroup
	local subgroup_basis = {}
	for str in subgroup:gmatch("(%d+/?%d*)") do
		table.insert(subgroup_basis, str)
	end
	
	-- autocalculating ploidacot
	local ploid = tonumber (map[1])
	
	local equave = u.eval_num_arg(subgroup_basis[1])
	local referent = u.eval_num_arg(subgroup_basis[2])
	local cot = tonumber(genchain_mapping[2])
	local suffix = "cleft"
	if equave == 2 then -- octave-based temp
		if referent == 3 then
			suffix = "cot"
		elseif referent == 5 then
			suffix = "seph"
		end
	elseif equave == 3 then -- twelfth-based temp
		if referent == 5 then
			referent_candidate = u.eval_num_arg(subgroup_basis[3])
			if referent_candidate == 7 then
				referent = referent_candidate
				cot = tonumber(genchain_mapping[3])
				suffix = "gem"
			end
		end
	end
	
	if suffix == "cleft" then
		suffix = referent .. suffix
	end
	
	local equave_size = 1200 * u.log2(equave)
	local referent_size = 1200 * u.log2(referent)
	local period_size = equave_size / ploid
	local generator_size = tonumber(tuning)
	if cot < 0 then
		generator_size = equave_size - generator_size
		cot = -cot
	end
	
	-- find the shear
	local shear
	if cot ~= 0 then
		shear = (math.floor(generator_size * cot / period_size) 
			- math.floor(referent_size % equave_size / period_size)) % cot
	else
		shear = 0
	end
	
	-- omega extension
	if ploid == 1 and cot > 2 and shear == cot - ploid then
		shear = shear - cot
	end
	
	-- construct the ploidacot signature
	local MAX_GREEK_NUMERAL = 12 -- max number to convert to greek letters/numerals
	
	local ploid_sig
	if ploid == 1 then
		ploid_sig = "" -- omit the ploid part
	elseif ploid <= MAX_GREEK_NUMERAL then
		ploid_sig = p.num2greek(tostring(ploid), "ploid") .. "ploid "
	else
		ploid_sig = tostring (ploid) .. "-ploid "
	end
	
	local shear_sig
	if shear <= MAX_GREEK_NUMERAL then
		shear_sig = p.num2greeklet(tostring(shear))
	else
		shear_sig = tostring(shear) .. "-sheared "
	end
	
	local cot_sig
	if cot <= MAX_GREEK_NUMERAL then
		cot_sig = p.num2greek(tostring(cot), "cot") .. suffix
	else
		cot_sig = tostring(cot) .. "-" .. suffix
	end
	
	ploidacot = ploid_sig .. shear_sig .. cot_sig
	
	-- user override
	if u.value_provided (ploidacot_override) then
		ploidacot = ploidacot_override
	end
	
	-- process et join
	local et_eq_first, et_num_first = p.warts2ed (et_first)
	local et_eq_letter_first = p.equave2letter (et_eq_first)
	local et_eq_second, et_num_second = p.warts2ed (et_second)
	local et_eq_letter_second = p.equave2letter (et_eq_second)
	
	-- construct the table
	table.insert(data, {
		"Subgroups",
		subgroup
	})

	table.insert(data, {
		"Comma basis",
		basis
	})

	table.insert(data, {
		"Reduced mapping",
		"⟨" .. mapping .. "]"
	})

	table.insert(data, {
		"ET join",
		"[[" .. et_num_first .. "ed" .. et_eq_letter_first .. "|" .. et_first .. "]] & [[" 
			.. et_num_second .. "ed" .. et_eq_letter_second .. "|" .. et_second .. "]]"
	})

	table.insert(data, {
		"Generator ([[" .. method .. "]])",
		"~" .. genfrac .. " = " .. tuning .. "{{c}}"
	})

	table.insert(data, {
		"MOS scales",
		mos
	})

	table.insert(data, {
		"Ploidacot",
		ploidacot
	})
	
	if u.value_provided (pergen) then
		table.insert(data, {
			"Pergen",
			pergen
		})
	end

	if u.value_provided (colorname) then
		table.insert(data, {
			"Color name",
			colorname
		})
	end
	
	-- error and stuff
	local limit_text
	if equave == 2 then
		limit_text = "-odd-limit"
	elseif equave == 3 then
		limit_text = "-throdd-limit"
	else
		limit_text = "-integer-limit"
	end
	local string1 = limit1 .. limit_text .. ": " .. acc1 .. "{{c}}"
	local string2 = limit1 .. limit_text .. ": " .. comp1 .. " notes"
	if u.value_provided (limit2) then
		string1 = string1 .. "; <br>" .. limit2 .. limit_text .. ": " .. acc2 .. "{{c}}"
		string2 = string2 .. "; <br>" .. limit2 .. limit_text .. ": " .. comp2 .. " notes"
	end

	table.insert(data, {
		"Minimax error",
		string1
	})

	table.insert(data, {
		"Target scale size",
		string2
	})

	local result = infobox.build(
		name,
		data
	)
	
	return frame:preprocess(debugg == true and "<pre>" .. result .. "</pre>" or result)
end

function p.digit2greek(number, purpose)

	local greek
	
	if number == "1" then
		if purpose == "ploid" then
			greek = "ha"
		elseif purpose == "cot" then
			greek = "mono"
		elseif purpose == "decade" then
			greek = "deca"
		else
			greek = "hen"
		end
	elseif number == "2" then
		if purpose == "decade" then
			greek = "icosa"
		elseif purpose == "unit" then
			greek = "do"
		else
			greek = "di"
		end
	elseif number == "0" then
		if purpose == "unit" then
			greek = ""
		else
			greek = "a"
		end
	else
		if number == "3" then
			if purpose == "decade" then
				greek = "tria"
			else
				greek = "tri"
			end
		elseif number == "4" then
			if purpose == "decade" then
				greek = "tessera"
			else
				greek = "tetra"
			end
		elseif number == "5" then
			if purpose == "decade" then
				greek = "pente"
			else
				greek = "penta"
			end
		elseif number == "6" then
			if purpose == "decade" then
				greek = "hexe"
			else
				greek = "hexa"
			end
		elseif number == "7" then
			if purpose == "decade" then
				greek = "hebdome"
			else
				greek = "hepta"
			end
		elseif number == "8" then
			if purpose == "decade" then
				greek = "ogdoe"
			elseif purpose == "unit" then
				greek = "octo"
			else
				greek = "octa"
			end
		elseif number == "9" then
			if purpose == "decade" then
				greek = "enene"
			else
				greek = "ennea"
			end
		end
		if purpose == "decade" then
			greek = greek .. "conta"
		end
	end

	return greek
end

function p.num2greek(number, purpose)

	local greek
	
	if string.len(number) == 1 then
		greek = p.digit2greek(number, purpose)
	elseif string.len(number) == 2 then
		local unit = string.char(string.byte(number, 2))
		local decade = string.char(string.byte(number, 1))
		
		greek = p.digit2greek(unit, "unit") .. p.digit2greek(decade, "decade")
	end
	return greek
end

function p.digit2greeklet(number, purpose)

	local greek
	
	if number == "1" then
		if purpose == "decade" then
			greek = "iota-"
		elseif purpose == "unit" then
			greek = "alpha-"
		end
	elseif number == "2" then
		if purpose == "decade" then
			greek = "kappa-"
		elseif purpose == "unit" then
			greek = "beta-"
		end
	elseif number == "3" then
		if purpose == "decade" then
			greek = "lambda-"
		elseif purpose == "unit" then
			greek = "gamma-"
		end
	elseif number == "4" then
		if purpose == "decade" then
			greek = "mu-"
		elseif purpose == "unit" then
			greek = "delta-"
		end
	elseif number == "5" then
		if purpose == "decade" then
			greek = "nu-"
		elseif purpose == "unit" then
			greek = "epsilon-"
		end
	elseif number == "6" then
		if purpose == "decade" then
			greek = "xi-"
		elseif purpose == "unit" then
			greek = "wau-"
		end
	elseif number == "7" then
		if purpose == "decade" then
			greek = "omicron-"
		elseif purpose == "unit" then
			greek = "zeta-"
		end
	elseif number == "8" then
		if purpose == "decade" then
			greek = "pi-"
		elseif purpose == "unit" then
			greek = "eta-"
		end
	elseif number == "9" then
		if purpose == "decade" then
			greek = "qoppa-"
		elseif purpose == "unit" then
			greek = "theta-"
		end	
	elseif number == "0" then
		greek = ""
	elseif number == "-1" then
		greek = "omega-"
	end

	return greek
end

function p.num2greeklet(number)

	local greek
	
	if string.len(string.match(number, "(%d+)")) == 1 then
		greek = p.digit2greeklet(number, "unit")
	elseif string.len(string.match(number, "(%d+)")) == 2 then
		local unit = string.char(string.byte(number, 2))
		local decade = string.char(string.byte(number, 1))
		
		greek = p.digit2greeklet(decade, "decade") .. p.digit2greeklet(unit, "unit")
	end
	return greek
end

function p.equave2letter(et_eq)
	-- converts an equave string to a letter
	local et_eq_letter
	if et_eq == "2" then
		et_eq_letter = "o"
	elseif et_eq == "3" then
		et_eq_letter = "t"
	elseif et_eq == "3/2" then
		et_eq_letter = "f"
	else
		et_eq_letter = eq
	end
	return et_eq_letter
end

function p.warts2ed(warts)
	-- converts a wart notation to an equal division
	local wart_prefix, et_num = warts:match ("(%a?)(%d+)")
	local et_eq = "2"
	if wart_prefix == "a" then
		et_eq = "2"
	elseif wart_prefix == "b" then
		et_eq = "3"
	elseif wart_prefix == "c" then
		et_eq = "5"
	elseif wart_prefix == "d" then
		et_eq = "7"
	elseif wart_prefix == "e" then
		et_eq = "11"
	elseif wart_prefix == "f" then
		et_eq = "13"
	elseif wart_prefix == "g" then
		et_eq = "17"
	elseif wart_prefix == "h" then
		et_eq = "19"
	elseif wart_prefix == "i" then
		et_eq = "23"
	end
	return et_eq, et_num
end

return p