Module:MOS modes: Difference between revisions

From Xenharmonic Wiki
Jump to navigation Jump to search
Ganaram inukshuk (talk | contribs)
No edit summary
Ganaram inukshuk (talk | contribs)
No edit summary
Line 79: Line 79:
local gens_down = (i - 1) * periods
local gens_down = (i - 1) * periods
local gens_up = (#mos_modes - i) * periods
local gens_up = (#mos_modes - i) * periods
result = result .. "| " .. gens_up .. "<nowiki>|</nowiki>" .. gens_down .. "\n"
result = result .. "| " .. "<nowiki>" .. gens_up .. "|" .. gens_down .. "</nowiki>\n"
end
end

Revision as of 09:33, 24 May 2023

Module documentation[view] [edit] [history] [purge]
Note: Do not invoke this module directly; use the corresponding template instead: Template:MOS modes.

This template is used for mos pages to automatically generate and list that mos's modes, along with the modes' UDP (up-down-period) notation.


local mos = require('Module:MOS')
local rat = require('Module:Rational')
local p = {}

-- Function that takes a mos and produces all of the modes by brightness
-- The mos is entered as a data structure provided by Module:MOS
function p.modes_by_brightness(input_mos)
	-- Default parameter, which corresponds to 5L 2s <2/1>
	local input_mos = input_mos or mos.new(5, 2, 2)
	
	-- Get the number of L's, s's, and periods
	local nL = input_mos.nL
	local ns = input_mos.ns
	local periods = rat.gcd(nL, ns)
	
	-- Find its brightest mode as a string of L's and s's
	local brightest_mode = mos.brightest_mode(input_mos)
	
	-- Find the size of the generator aned period in mossteps
	local gen = mos.bright_gen(input_mos)
	local gen_in_mossteps = gen['L'] + gen['s']
	local period_size  = round((nL + ns) / periods)
	
	-- For a mos xL ys, there are x+y unique modes that can be obtained by the following process:
	-- For a generator g in mossteps (g < x+y) and starting with the brightest mode (as a string
	-- of L's and s's), move the first g steps to the end to get the next-brightest mode.
	-- Repeat this process with the rotated string to get all modes. The x+y-1th time this is done
	-- will be the darkest mode.
	-- In the case of a multiperiod mos nxL nys, consider it as the mos for xL ys and duplicate
	-- each result n times. This way, the number of rotations needed to be performed is still x+y-1.
	local brightest_mode_substr = string.sub(brightest_mode, 1, period_size)
	local modes = { brightest_mode }
	local current_mode = brightest_mode_substr
	
	for i = 1, period_size - 1 do
		-- Move the first g strings from the beginning to the end
		local first_substr = string.sub(current_mode, 1, gen_in_mossteps)
		local second_substr = string.sub(current_mode, gen_in_mossteps + 1, period_size)
		current_mode = second_substr .. first_substr
		
		-- Duplicate the string (just in case) then add it to the array of modes
		local current_mode_duplicated = string.rep(current_mode, periods)
		table.insert(modes, current_mode_duplicated)
	end
	
	return modes
end

-- Test function that produces the modes of a mos as a table
-- TODO:
-- - Allow for mos to be extracted from the page's title for use as a future template
-- - Allow for input of mode names
-- - Expand this (possibly as a separate template) for mos intervals
function p.modes_table(frame)
	-- Mos is entered as "xL ys" since the mos module can parse that format
	local mosstring = "3L 4s"
	local input_mos = mos.parse(mosstring)
	
	local mos_modes = p.modes_by_brightness(input_mos)
	local periods = rat.gcd(input_mos.nL, input_mos.ns)		-- Needed for UDP
	
	-- Make a table with a column for the mode (as a string of L's and s's) and UDP
	local result = '{| class="wikitable"\n'
	result = result .. "|+ " .. "Modes of " .. mosstring .. "\n"
	result = result .. "|-\n"
	result = result .. "! Mode\n"
	result = result .. "! [[UDP]]\n"
	
	-- Enter each row
	for i = 1, #mos_modes do
		result = result .. "|-\n"
		
		-- Add the mode's string
		result = result .. "|" .. mos_modes[i] .. "\n"
		
		-- Add the UDP, formatted as up|dp, where u is the number of bright generators going up,
		-- d is the number of bright generators going down, and p is the number of periods
		-- (slightly different from standard UDP notation of u|d(p))
		local gens_down = (i - 1) * periods
		local gens_up = (#mos_modes - i) * periods
		result = result .. "| " .. "<nowiki>" .. gens_up .. "|" .. gens_down .. "</nowiki>\n"
	end
	
	result = result .. "|}"
	
	return result
end

return p