Module:JI ratios: Difference between revisions
No edit summary |
m comments |
||
| (5 intermediate revisions by 2 users not shown) | |||
| Line 1: | Line 1: | ||
-- This module follows [[User:Ganaram inukshuk/Provisional style guide for Lua]] | |||
local getArgs = require("Module:Arguments").getArgs | |||
local med = require("Module:Mediants") | |||
local rat = require("Module:Rational") | local rat = require("Module:Rational") | ||
local tip = require("Module:Template input parse") | |||
local utils = require("Module:Utils") | local utils = require("Module:Utils") | ||
local yesno = require("Module:Yesno") | local yesno = require("Module:Yesno") | ||
local | |||
p = {} | local p = {} | ||
-- Template for handling multiple entry of JI ratios into a template, and for | -- Template for handling multiple entry of JI ratios into a template, and for | ||
-- searching for JI ratios if automatic entry is desired. | -- searching for JI ratios if automatic entry is desired. | ||
-- This is a successor/replacement for JI ratio finder. | -- This is a successor/replacement for JI ratio finder. | ||
-- TODO: Refactor code such that: | |||
-- - For int-limit search, int limit is the first arg, and equave and min/max | |||
-- cents default to 2/1, 0c, and 1200c respectively. | |||
-- (int_limit, equave) | |||
-- (int_limit, min_cents, max_cents) | |||
-- - For odd-limit search, odd limit is the first arg, int limit defaults to | |||
-- twice the odd limit, and equave and min/max cents default to 2/1, 0c, and | |||
-- 1200c respectively. | |||
-- (odd_limit, int_limit, equave) | |||
-- (odd_limit, int_limit, min_cents, max_cents) | |||
-- - For prime-limit search, prime-limit is the first arg, int limit defaults to | |||
-- twice the largest prime, and equave and min/max cents default to 2/1, 0c, | |||
-- and 1200c respectively. | |||
-- (prime_limit, int_limit, equave) | |||
-- (prime_limit, int_limit, min_cents, max_cents) | |||
-- - For subgroup search, subgroup is the first arg, there's no default value | |||
-- for int limit (due to complexity of subgroups), and equave and min/max | |||
-- cents default to 2/1, 0c, and 1200c respectively. | |||
-- (subgroup, int_limit, equave) | |||
-- (subgroup, int_limit, min_cents, max_cents) | |||
-- - Filter ratios function is split into two: | |||
-- - Filter ratios by complement removes ratios from a table if its complement | |||
-- is missing. Complements are octave-complements by default. | |||
-- - Filter ratios by tenney height removes ratios from a table if its tenney | |||
-- height exceeds a passed-in value. | |||
-- TODO: write filter function for cent range | |||
-- Module searches for ratios that are, at the minimum, up to an equave and are | -- Module searches for ratios that are, at the minimum, up to an equave and are | ||
-- up to some integer limit. Search hierarchy is as follows: | -- up to some integer limit. Search hierarchy is as follows: | ||
-- - Search by subgroup ( | -- - Search by subgroup (subgroup elements may be nonprime or rational) | ||
-- - Then search by prime limit | -- - Then search by prime limit | ||
-- - Then search by odd limit | -- - Then search by odd limit | ||
-- - Then search by int limit | -- - Then search by int limit | ||
| Line 38: | Line 68: | ||
-- - Removing ratios whose complement would exceed a max Tenney height or int limit | -- - Removing ratios whose complement would exceed a max Tenney height or int limit | ||
function p.filter_ratios(ratios, equave, int_limit, tenney_height, complements_only) | function p.filter_ratios(ratios, equave, int_limit, tenney_height, complements_only) | ||
local filtered_ratios = {} | local filtered_ratios = {} | ||
| Line 67: | Line 95: | ||
return filtered_ratios | return filtered_ratios | ||
end | |||
-- Filters ratios from a table of ratios, returning an array of ratios within | |||
-- the cent range and preserving the original table. Meant for searching for | |||
-- multiple ranges. TODO: write | |||
function p.filter_ratios_within_cent_range(ratios, min_cents, max_cents) | |||
end | end | ||
| Line 85: | Line 120: | ||
local init_ratios = {{1,1}, {1,0}} | local init_ratios = {{1,1}, {1,0}} | ||
local ratios = med. | local ratios = med.find_only_mediants(init_ratios, 2) | ||
for i = 3, int_limit do | |||
ratios = med.find_mediants_by_int_limit(ratios, i) | |||
-- Purge ratios from the beginning. | |||
-- If the first and second ratio are smaller than min_cents, and smaller | |||
-- than max_cents, then remove the first ratio. Keeping the first ratio | |||
-- would add mediants outside the cent range. | |||
local cents_1 = utils.log2(ratios[1][1] / ratios[1][2]) * 1200 | |||
local cents_2 = utils.log2(ratios[2][1] / ratios[2][2]) * 1200 | |||
if cents_1 < min_cents and cents_2 <= min_cents and cents_1 < max_cents and cents_2 < max_cents then | |||
table.remove(ratios, 1) | |||
end | |||
-- Purge ratios from the end. | |||
-- If the 2nd-last ratio and last ratio are greater than max_cents, and | |||
-- larger than min_cents, then remove the last ratio. Keeping the last | |||
-- ratio would add mediants outside the cent range. | |||
local cents_3 = utils.log2(ratios[#ratios-1][1] / ratios[#ratios-1][2]) * 1200 | |||
local cents_4 = utils.log2(ratios[#ratios ][1] / ratios[#ratios ][2]) * 1200 | |||
if cents_3 > max_cents and cents_4 >= max_cents and cents_3 > min_cents and cents_4 > min_cents then | |||
table.remove(ratios, #ratios) | |||
end | |||
end | |||
-- Convert to ratios that Module:Rational can work with | -- Convert to ratios that Module:Rational can work with | ||
| Line 95: | Line 150: | ||
end | end | ||
-- Remove ratios that fall outside the cent range. | -- Remove any remaining ratios that fall outside the cent range. | ||
while rat.cents(ratios[1]) < min_cents do | while rat.cents(ratios[1]) < min_cents do | ||
table.remove(ratios, 1) | table.remove(ratios, 1) | ||
| Line 110: | Line 165: | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
-- | -- Convert odd limit into equivalent subgroup. | ||
-- EG, 11-odd-limit becomes 2.3.5.7.9.11 | |||
-- 2 is part of the subgroup by definition. | |||
function p.odd_limit_to_subgroup(odd_limit) | |||
local subgroup = { rat.new(2) } | |||
for i = 3, odd_limit, 2 do | |||
table.insert(subgroup, rat.new(i)) | |||
end | |||
return subgroup | |||
end | |||
function p.search_by_odd_limit(equave, int_limit, odd_limit) | |||
local subgroup = p.odd_limit_to_subgroup(odd_limit) | |||
return p.search_by_subgroup_within_cents(0, rat.cents(equave), int_limit, subgroup) | |||
end | |||
function p.search_by_odd_limit_within_cents(min_cents, max_cents, odd_limit) | |||
local subgroup = p.odd_limit_to_subgroup(odd_limit) | |||
return p.search_by_subgroup_within_cents(min_cents, max_cents, int_limit, subgroup) | |||
end | |||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
| Line 116: | Line 190: | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
-- Convert prime limit into equivalent subgroup. | |||
-- EG, 11-prime-limit becomes 2.3.5.7.11 | |||
function p.prime_limit_to_subgroup(prime_limit) | function p.prime_limit_to_subgroup(prime_limit) | ||
local subgroup = {} | local subgroup = {} | ||
for i = | for i = 3, prime_limit do | ||
local is_prime = true | local is_prime = true | ||
for j = 2, math.floor(math.sqrt(i)) do | for j = 2, math.floor(math.sqrt(i)) do | ||
| Line 227: | Line 303: | ||
return ratios | return ratios | ||
end | end | ||
-------------------------------------------------------------------------------- | |||
------------------------------- HELPER FUNCTIONS ------------------------------- | |||
-------------------------------------------------------------------------------- | |||
-- Heleper function; merges elements from source table with destination table | -- Heleper function; merges elements from source table with destination table | ||
| Line 329: | Line 409: | ||
function p._ji_ratios(args) | function p._ji_ratios(args) | ||
-- Args for ease of access | -- Args for ease of access | ||
equave = args["Equave"] | equave = args["Equave" ] or DEFAULT_EQUAVE | ||
int_limit = args["Int Limit"] | int_limit = args["Int Limit" ] or DEFAULT_INT_LIMIT | ||
odd_limit = args["Odd Limit"] | odd_limit = args["Odd Limit" ] | ||
prime_limit = args["Prime Limit"] | prime_limit = args["Prime Limit"] | ||
subgroup = args["Subgroup"] | subgroup = args["Subgroup" ] | ||
-- Filtering args | -- Filtering args | ||
tenney_height = args["Tenney Height"] | tenney_height = args["Tenney Height" ] or 1/0 -- Default Tenney height is infinity | ||
complements_only = args["Complements Only"] or false -- Default is to include all ratios | complements_only = args["Complements Only"] or false -- Default is to include all ratios | ||
| Line 355: | Line 435: | ||
-- Invokable function; for templates | -- Invokable function; for templates | ||
-- Ratios are returned as a comma-delimited list, | -- Ratios are returned as a comma-delimited list. For finer control, it's | ||
-- | -- necessary to call the "main" function, then further process the results. | ||
function p.ji_ratios(frame) | function p.ji_ratios(frame) | ||
args = getArgs(frame) | args = getArgs(frame) | ||
| Line 394: | Line 474: | ||
-- Find and return ratios | -- Find and return ratios | ||
local result = p.ratios_as_string(p._ji_ratios(args)) | |||
local debugg = yesno(frame.args["debug"]) | local debugg = yesno(frame.args["debug"]) | ||
if debugg == true then | |||
result = "<syntaxhighlight lang=\"wikitext\">" .. result .. "</syntaxhighlight>" | |||
end | |||
return frame:preprocess(result) | |||
end | end | ||
| Line 403: | Line 488: | ||
--return p.ratios_as_string(p._ji_ratios(p.parse_args("Int Limit: 16; Equave: 3/1; Complements Only: 0"))) | --return p.ratios_as_string(p._ji_ratios(p.parse_args("Int Limit: 16; Equave: 3/1; Complements Only: 0"))) | ||
--return p.ratios_as_string(p.search_by_prime_limit_within_cents(372, 440, 17, 30)) | --return p.ratios_as_string(p.search_by_prime_limit_within_cents(372, 440, 17, 30)) | ||
return p.ratios_as_string(p. | return p.ratios_as_string(p.search_by_odd_limit(rat.new(2), 15, 15*2)) | ||
end | end | ||