Module:JI ratios: Difference between revisions
Jump to navigation
Jump to search
m m.member_name -> med.member_name; use standalone int-limit search function |
Rename/reorganize functions; add prime-limit search by reusing subgroup-search code |
||
| Line 6: | Line 6: | ||
-- TODO: | -- TODO: | ||
-- | -- Replace old int-limit search function with new one | ||
-- 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 | ||
| Line 15: | Line 13: | ||
-- JI ratios are searched by the following params in a hierarchy: | -- JI ratios are searched by the following params in a hierarchy: | ||
-- - | -- - Search by prime limit. Int limit is used to limit the num/den of ratios. | ||
-- | -- Prime limit takes precedence over subgroup. | ||
-- - | -- - Search by subgroup. (Subgroup may contain nonprime numbers, but ratios are | ||
-- | -- currently not supported.) Int limit is used to limit the num/den of ratios. | ||
-- - If neither prime limit or subgroup is present, search by prime limit. This | |||
-- is considered the absolute minimum requirement for ratio searching. | |||
-- - If prime limit is present, | |||
-- | |||
-- NOTES: | -- NOTES: | ||
-- - Prime limits are infinite sets, so int limit is used to restrain the set | -- - Prime limits are infinite sets, so int limit is used to restrain the set | ||
-- to a finite size. The same is true for subgroup. | -- to a finite size. The same is true for subgroup. | ||
-- - Tenney height is used for further filtering of ratios, and is considered | -- - Tenney height is used for further filtering of ratios, and is considered | ||
-- optional. | -- optional. If omitted, tenney height defaults to infinity. | ||
-- INT_LIMIT_MAX is hardcoded to limit the size of output. | -- INT_LIMIT_MAX is hardcoded to limit the size of output. This only applies to | ||
-- int limit search, as other search functions (subgroup, prime-limit) may allow | |||
-- higher search maxima. For reference, searching within the octave yields this | |||
-- many ratios: | |||
-- 400 -> ~24000 ratios | -- 400 -> ~24000 ratios | ||
-- 300 -> ~14000 ratios | -- 300 -> ~14000 ratios | ||
| Line 44: | Line 43: | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
-- | -- Function to be replaced with new one | ||
function p.search_by_int_limit(integer_limit, max_cents) | function p.search_by_int_limit(integer_limit, max_cents) | ||
local max_cents = max_cents or 1200 | local max_cents = max_cents or 1200 | ||
| Line 92: | Line 89: | ||
end | end | ||
---- | -- Int-limit-based search; finds ratios between 1/1 and an equave, within an int | ||
-- | -- limit. An optional tenney height can be passed in. | ||
-- | -- Int limit is hardcoded to a max size to restrict the size of output, to avoid | ||
-- risk of out-of-memory operations or the like. | |||
-- | function p.search_by_int_limit_within_equave(int_limit, equave, tenney_height) | ||
- | local int_limit = int_limit or DEFAULT_INT_LIMIT | ||
local equave = equave or rat.new(2,1) -- Defualt equave is 2/1. | |||
function p. | local tenney_height = tenney_height or 1/0 -- Defualt tenney height is infinity. | ||
local int_limit = int_limit or | int_limit = math.max(0, math.min(INT_LIMIT_MAX, int_limit)) | ||
local equave = equave or | |||
local | local init_ratios = {{1,1}, {2,1}} | ||
local ratios = | local search_func = p.int_limit_mediant_search | ||
local search_args = { ["equave"] = equave, ["int_limit"] = int_limit, ["tenney_height"] = tenney_height } | |||
local ratios = med.find_only_mediants_by_search_func(init_ratios, search_func, search_args) | |||
-- Convert to ratios that Module:Rational can work with | -- Convert to ratios that Module:Rational can work with | ||
| Line 115: | Line 113: | ||
end | end | ||
-- | -- Int limit search function, with equave and tenney height cutoffs. | ||
-- | -- If nil is passed in for the tenney height, it will defualt to infinity. | ||
function p. | -- To be passed into mediant-search function, as part of int-limit-search | ||
local | -- function call. | ||
local | function p.int_limit_mediant_search(mediant_data, search_args) | ||
local mediant = mediant_data["mediant"] | |||
local ratio_1 = mediant_data["ratio_1"] | |||
local equave = search_args["equave"] | |||
local int_limit = search_args["int_limit"] | |||
local tenney_height = search_args["tenney_height"] | |||
local equave_as_float = rat.as_float(equave) | |||
local rat_1_as_float = ratio_1[1] / ratio_1[2] | |||
local mediant_th = math.log(mediant[1] * mediant[2]) / math.log(2) | |||
-- | return math.max(mediant[1], mediant[2]) <= int_limit and rat_1_as_float < equave_as_float and mediant_th <= tenney_height | ||
end | |||
-------------------------------------------------------------------------------- | |||
------------------------ SUBGROUP-BASED SEARCH FUNCTION ------------------------ | |||
-------------------------------------------------------------------------------- | |||
-- Int-limit-based search; finds ratios between 1/1 and an equave, within a sub- | |||
-- group. An int limit is passed in to limit the size of output, since subgroups | |||
-- are infinite sets. An optional tenney height can be passed in to further | |||
-- | -- limit output. | ||
-- | -- Unlike int limit search, subgroup search can allow for very high int limits, | ||
-- | -- as long as the subgroup is reasonably small and has reasonably small terms. | ||
-- | -- Note that members in a subgroup need not be prime, as long as the terms are, | ||
-- for the most part, relatively prime. | |||
function p.search_by_subgroup_within_equave(subgroup, int_limit, equave, tenney_height) | |||
local subgroup = subgroup or { 2, 3, 7 } | |||
local int_limit = int_limit or 50 | |||
local equave = equave or rat.new(2,1) -- Defualt equave is 2/1. | |||
local tenney_height = tenney_height or 1/0 -- Defualt tenney height is infinity. | |||
-- Be absolutely sure the subgroup's members are sorted! | |||
table.sort(subgroup) | |||
-- Find all possible products given the factors in the subgroup. | |||
-- These will be used to find all possible ratios. | |||
local products = {{1}} | local products = {{1}} | ||
local new_products_found = true | local new_products_found = true | ||
while new_products_found do | while new_products_found do | ||
local new_products = {} | local new_products = {} | ||
for i = 1, # | for i = 1, #subgroup do | ||
for j = 1, #products[#products] do | for j = 1, #products[#products] do | ||
local new_product = products[#products][j] * | local new_product = products[#products][j] * subgroup[i] | ||
if new_product <= | if new_product <= int_limit then | ||
local product_already_added = false | local product_already_added = false | ||
for k = 1, #new_products do | for k = 1, #new_products do | ||
| Line 170: | Line 189: | ||
products = consolidated_products | products = consolidated_products | ||
table.sort(products) | table.sort(products) | ||
-- | -- Using the products produced earlier, combine them to make all possible | ||
- | -- ratios from 1/1 to the equave. Ratios with non-coprime numerator and | ||
-- | -- denominator, or exceed the tenney height, are omitted. | ||
local ratios = {} | local ratios = {} | ||
for i = 1, # | local equave_as_float = rat.as_float(equave) | ||
local denominator = | for i = 1, #products do | ||
for j = i, # | local denominator = products[i] | ||
local numerator = | for j = i, #products do | ||
local numerator = products[j] | |||
local gcd = utils._gcd(numerator, denominator) | local gcd = utils._gcd(numerator, denominator) | ||
if gcd == 1 then | if gcd == 1 then | ||
local within_equave = numerator / denominator <= equave_as_float | local within_equave = numerator / denominator <= equave_as_float | ||
if within_equave then | local within_tenney_height = math.log(numerator * denominator) / math.log(2) <= tenney_height | ||
if within_equave and within_tenney_height then | |||
table.insert(ratios, {numerator, denominator}) | table.insert(ratios, {numerator, denominator}) | ||
else | else | ||
| Line 198: | Line 210: | ||
end | end | ||
end | end | ||
end | |||
-- Convert to ratios that Module:Rational can work with | |||
for i = 1, #ratios do | |||
ratios[i] = rat.new(ratios[i][1], ratios[i][2]) | |||
end | end | ||
| Line 203: | Line 220: | ||
end | end | ||
-------------------------------------------------------------------------------- | |||
---------------------- PRIME-LIMIT-BASED SEARCH FUNCTION ----------------------- | |||
-------------------------------------------------------------------------------- | |||
-- Int-limit-based search; finds ratios between 1/1 and an equave, within a | |||
-- prime limit. An int limit is passed in to limit the size of output, since | |||
-- prime limits are inifinite sets. An optional tenney height can be passed in | |||
-- to further limit output. | |||
-- Like subgroup search, prime limit search can also allow for very high int | |||
-- limits, as long as the prime is reasonably small. | |||
function p.search_by_prime_limit_within_equave(prime_limit, int_limit, equave, tenney_height) | |||
local prime_limit = 3 | |||
local int_limit = int_limit or 1000 | |||
local equave = equave or rat.new(2,1) -- Defualt equave is 2/1. | |||
local tenney_height = tenney_height or 1/0 -- Defualt tenney height is infinity. | |||
-- Find all primes up to the prime limit. | |||
local primes = {} | |||
for i = 2, prime_limit do | |||
local is_prime = true | |||
for j = 2, math.floor(math.sqrt(i)) do | |||
if i % j == 0 then | |||
is_prime = false | |||
break | |||
end | |||
end | |||
if is_prime then | |||
table.insert(primes, i) | |||
end | |||
end | |||
-- Perform subgroup search on the primes found, as subgroup-search code can | |||
-- be reused for prime-limit search. | |||
return p.search_by_subgroup_within_equave(primes, int_limit, equave, tenney_height) | |||
end | |||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
| Line 371: | Line 423: | ||
end | end | ||
-- Convert a table of tables into a | -- Convert a table of ratios (tables, as defined by rational module) into a | ||
-- line of text, with options for delimiters. | |||
function p.ratios_as_texts(ratios, add_links, delimiter) | function p.ratios_as_texts(ratios, add_links, delimiter) | ||
local add_links = add_links == true | local add_links = add_links == true | ||
| Line 384: | Line 437: | ||
end | end | ||
function p.tester() | |||
function p. | |||
local ratios = p.search_by_prime_limit_within_equave() | |||
return p.ratios_as_text(ratios) | return p.ratios_as_text(ratios) | ||
Revision as of 07:55, 18 September 2024
- This module may be invoked by templates using its corresponding template Template:JI ratios, or used directly from other modules.
| Introspection summary for Module:JI ratios | |||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
| ||||||||||||||||||
No function descriptions were provided. The Lua code may have further information.
local rat = require("Module:Rational")
local utils = require("Module:Utils")
local tip = require("Module:Template input parse")
local med = require("Module:Mediants")
p = {}
-- TODO:
-- Replace old int-limit search function with new one
-- Template for handling multiple entry of JI ratios into a template, and for
-- searching for JI ratios if automatic entry is desired.
-- This is a successor/replacement for JI ratio finder.
-- JI ratios are searched by the following params in a hierarchy:
-- - Search by prime limit. Int limit is used to limit the num/den of ratios.
-- Prime limit takes precedence over subgroup.
-- - Search by subgroup. (Subgroup may contain nonprime numbers, but ratios are
-- currently not supported.) Int limit is used to limit the num/den of ratios.
-- - If neither prime limit or subgroup is present, search by prime limit. This
-- is considered the absolute minimum requirement for ratio searching.
-- NOTES:
-- - Prime limits are infinite sets, so int limit is used to restrain the set
-- to a finite size. The same is true for subgroup.
-- - Tenney height is used for further filtering of ratios, and is considered
-- optional. If omitted, tenney height defaults to infinity.
-- INT_LIMIT_MAX is hardcoded to limit the size of output. This only applies to
-- int limit search, as other search functions (subgroup, prime-limit) may allow
-- higher search maxima. For reference, searching within the octave yields this
-- many ratios:
-- 400 -> ~24000 ratios
-- 300 -> ~14000 ratios
-- 250 -> ~9500 ratios
-- 200 -> ~6000 ratios
-- 150 -> ~3400 ratios
-- 128 -> ~2500 ratios
-- 100 -> ~1500 ratios
local INT_LIMIT_MAX = 200
local DEFAULT_INT_LIMIT = 50
--------------------------------------------------------------------------------
----------------------- INT-LIMIT-BASED SEARCH FUNCTION ------------------------
--------------------------------------------------------------------------------
-- Function to be replaced with new one
function p.search_by_int_limit(integer_limit, max_cents)
local max_cents = max_cents or 1200
local integer_limit = integer_limit or DEFAULT_INT_LIMIT
integer_limit = math.max(0, math.min(INT_LIMIT_MAX, integer_limit))
local init_ratios = {{1,1}, {2,1}}
local ratios = med.find_only_mediants_by_int_limit(init_ratios, integer_limit)
-- If the max cents is greater than the octave, duplicate all existing
-- ratios and raise them by the required number of octaves.
if max_cents > 1200 then
local new_ratios = {}
local num_octaves_up = math.ceil(max_cents / 1200)
for j = 1, num_octaves_up do
for i = 2, #ratios do
local num = ratios[i][1] * math.pow(2, j)
local den = ratios[i][2]
local gcd = utils._gcd(num, den)
num = num / gcd
den = den / gcd
if math.max(num, den) <= integer_limit then
table.insert(new_ratios, {num, den})
end
end
end
for i = 1, #new_ratios do
table.insert(ratios, new_ratios[i])
end
end
-- Remove any ratios that exceed the max cents
-- Convert to ratios that Module:Rational can work with
for i = 1, #ratios do
ratios[i] = rat.new(ratios[i][1], ratios[i][2])
end
return ratios
end
-- Int-limit-based search; finds ratios between 1/1 and an equave, within an int
-- limit. An optional tenney height can be passed in.
-- Int limit is hardcoded to a max size to restrict the size of output, to avoid
-- risk of out-of-memory operations or the like.
function p.search_by_int_limit_within_equave(int_limit, equave, tenney_height)
local int_limit = int_limit or DEFAULT_INT_LIMIT
local equave = equave or rat.new(2,1) -- Defualt equave is 2/1.
local tenney_height = tenney_height or 1/0 -- Defualt tenney height is infinity.
int_limit = math.max(0, math.min(INT_LIMIT_MAX, int_limit))
local init_ratios = {{1,1}, {2,1}}
local search_func = p.int_limit_mediant_search
local search_args = { ["equave"] = equave, ["int_limit"] = int_limit, ["tenney_height"] = tenney_height }
local ratios = med.find_only_mediants_by_search_func(init_ratios, search_func, search_args)
-- Convert to ratios that Module:Rational can work with
for i = 1, #ratios do
ratios[i] = rat.new(ratios[i][1], ratios[i][2])
end
return ratios
end
-- Int limit search function, with equave and tenney height cutoffs.
-- If nil is passed in for the tenney height, it will defualt to infinity.
-- To be passed into mediant-search function, as part of int-limit-search
-- function call.
function p.int_limit_mediant_search(mediant_data, search_args)
local mediant = mediant_data["mediant"]
local ratio_1 = mediant_data["ratio_1"]
local equave = search_args["equave"]
local int_limit = search_args["int_limit"]
local tenney_height = search_args["tenney_height"]
local equave_as_float = rat.as_float(equave)
local rat_1_as_float = ratio_1[1] / ratio_1[2]
local mediant_th = math.log(mediant[1] * mediant[2]) / math.log(2)
return math.max(mediant[1], mediant[2]) <= int_limit and rat_1_as_float < equave_as_float and mediant_th <= tenney_height
end
--------------------------------------------------------------------------------
------------------------ SUBGROUP-BASED SEARCH FUNCTION ------------------------
--------------------------------------------------------------------------------
-- Int-limit-based search; finds ratios between 1/1 and an equave, within a sub-
-- group. An int limit is passed in to limit the size of output, since subgroups
-- are infinite sets. An optional tenney height can be passed in to further
-- limit output.
-- Unlike int limit search, subgroup search can allow for very high int limits,
-- as long as the subgroup is reasonably small and has reasonably small terms.
-- Note that members in a subgroup need not be prime, as long as the terms are,
-- for the most part, relatively prime.
function p.search_by_subgroup_within_equave(subgroup, int_limit, equave, tenney_height)
local subgroup = subgroup or { 2, 3, 7 }
local int_limit = int_limit or 50
local equave = equave or rat.new(2,1) -- Defualt equave is 2/1.
local tenney_height = tenney_height or 1/0 -- Defualt tenney height is infinity.
-- Be absolutely sure the subgroup's members are sorted!
table.sort(subgroup)
-- Find all possible products given the factors in the subgroup.
-- These will be used to find all possible ratios.
local products = {{1}}
local new_products_found = true
while new_products_found do
local new_products = {}
for i = 1, #subgroup do
for j = 1, #products[#products] do
local new_product = products[#products][j] * subgroup[i]
if new_product <= int_limit then
local product_already_added = false
for k = 1, #new_products do
product_already_added = product_already_added or new_product == new_products[k]
if product_already_added then break end
end
if not product_already_added then
table.insert(new_products, new_product)
end
end
end
end
if #new_products == 0 then
new_products_found = false
else
table.insert(products, new_products)
end
end
-- Consolidate and sort products
local consolidated_products = {}
for i = 1, #products do
for j = 1, #products[i] do
table.insert(consolidated_products, products[i][j])
end
end
products = consolidated_products
table.sort(products)
-- Using the products produced earlier, combine them to make all possible
-- ratios from 1/1 to the equave. Ratios with non-coprime numerator and
-- denominator, or exceed the tenney height, are omitted.
local ratios = {}
local equave_as_float = rat.as_float(equave)
for i = 1, #products do
local denominator = products[i]
for j = i, #products do
local numerator = products[j]
local gcd = utils._gcd(numerator, denominator)
if gcd == 1 then
local within_equave = numerator / denominator <= equave_as_float
local within_tenney_height = math.log(numerator * denominator) / math.log(2) <= tenney_height
if within_equave and within_tenney_height then
table.insert(ratios, {numerator, denominator})
else
break
end
end
end
end
-- Convert to ratios that Module:Rational can work with
for i = 1, #ratios do
ratios[i] = rat.new(ratios[i][1], ratios[i][2])
end
return ratios
end
--------------------------------------------------------------------------------
---------------------- PRIME-LIMIT-BASED SEARCH FUNCTION -----------------------
--------------------------------------------------------------------------------
-- Int-limit-based search; finds ratios between 1/1 and an equave, within a
-- prime limit. An int limit is passed in to limit the size of output, since
-- prime limits are inifinite sets. An optional tenney height can be passed in
-- to further limit output.
-- Like subgroup search, prime limit search can also allow for very high int
-- limits, as long as the prime is reasonably small.
function p.search_by_prime_limit_within_equave(prime_limit, int_limit, equave, tenney_height)
local prime_limit = 3
local int_limit = int_limit or 1000
local equave = equave or rat.new(2,1) -- Defualt equave is 2/1.
local tenney_height = tenney_height or 1/0 -- Defualt tenney height is infinity.
-- Find all primes up to the prime limit.
local primes = {}
for i = 2, prime_limit do
local is_prime = true
for j = 2, math.floor(math.sqrt(i)) do
if i % j == 0 then
is_prime = false
break
end
end
if is_prime then
table.insert(primes, i)
end
end
-- Perform subgroup search on the primes found, as subgroup-search code can
-- be reused for prime-limit search.
return p.search_by_subgroup_within_equave(primes, int_limit, equave, tenney_height)
end
--------------------------------------------------------------------------------
------------------------- PARAM-BASED SEARCH FUNCTIONS -------------------------
--------------------------------------------------------------------------------
-- Search for ratios based on params passed in. Each param is its own
-- function call. Params must be parsed first.
function p.search_by_params(params, max_cents)
local max_cents = max_cents or 1200
-- First get ratios up to an int limit. If no int limit was passed in, it
-- will default to the hardcoded default value.
local ratios = {}
if params["Int Limit"] ~= nil then
ratios = p.search_by_int_limit(params["Int Limit"], max_cents)
end
if params["Prime Limit"] ~= nil then
ratios = p.filter_by_prime_limit(ratios, params["Prime Limit"])
end
if params["Tenney Height"] ~= nil then
ratios = p.filter_by_tenney_height(ratios, params["Tenney Height"])
end
return ratios
end
-- Parse search params.
function p.parse_search_params(search_params)
local parsed = tip.parse_kv_pairs(search_params)
if parsed["Int Limit"] ~= nil then
parsed["Int Limit"] = tonumber(parsed["Int Limit"])
end
if parsed["Tenney Height"] ~= nil then
parsed["Tenney Height"] = tonumber(parsed["Tenney Height"])
end
if parsed["Prime Limit"] ~= nil then
parsed["Prime Limit"] = tonumber(parsed["Prime Limit"])
end
return parsed
end
function p.search_param_footnotes(search_params)
local result = "Not all notable ratios may be shown, and other interpretations are possible."
if search_params["Prime Limit"] ~= nil then
result = string.format("Ratios shown are within the [[%s-limit]]. %s", search_params["Prime Limit"], result)
elseif search_params["Int Limit"] ~= nil then
result = string.format("Ratios shown are %s-[[integer-limit|integer limit]]. %s", search_params["Int Limit"], result)
end
return result
end
--------------------------------------------------------------------------------
---------------------------- RATIO FILTER FUNCTIONS ----------------------------
--------------------------------------------------------------------------------
-- Filter ratios by Tenney height.
function p.filter_by_tenney_height(ratios, tenney_height)
local tenney_height = tenney_height or 10
local filtered_ratios = {}
for i = 1, #ratios do
local curr_tenney_height = rat.tenney_height(ratios[i])
if curr_tenney_height <= tenney_height then
table.insert(filtered_ratios, ratios[i])
end
end
return filtered_ratios
end
-- Filter ratios by prime limit.
function p.filter_by_prime_limit(ratios, prime_limit)
local prime_limit = prime_limit or 41
local filtered_ratios = {}
for i = 1, #ratios do
local curr_max_prime = rat.max_prime(ratios[i])
if curr_max_prime <= prime_limit then
table.insert(filtered_ratios, ratios[i])
end
end
return filtered_ratios
end
-- Filter ratios by (prime) subgroup. EG: 2.3.5.7
function p.filter_by_subgroup(ratios, subgroup)
end
-- Filter ratios by rational/nonprime subgroup. EG, 2.7/2.11/2, or 2.5.7.9
-- Does not support irrational subgroups.
function p.filter_by_nonprime_subgroup(ratios, subgroup)
end
--------------------------------------------------------------------------------
--------------------------- RATIO SORTING FUNCTIONS ----------------------------
--------------------------------------------------------------------------------
-- Sorts ratios by closeness to cent values.
function p.sort_by_closeness_to_cent_values(ratios, cent_values, tolerance)
local tolerance = tolerance or 30
local sorted_ratios = {}
local curr_index = 1 -- Index of current_ratio
for i = 1, #cent_values do
local lower_bound = cent_values[i] - tolerance
local upper_bound = cent_values[i] + tolerance
local cents_within_range = true
local curr_ratios = {}
for j = curr_index, #ratios do
local curr_ratio = ratios[j]
local curr_cents = rat.cents(curr_ratio)
if lower_bound < curr_cents and curr_cents < upper_bound then
table.insert(curr_ratios, curr_ratio)
--elseif curr_cents > upper_bound then
-- curr_index = j
-- break
end
end
table.insert(sorted_ratios, curr_ratios)
end
return sorted_ratios
end
--------------------------------------------------------------------------------
------------------------ RATIO PARSING/INPUT FUNCTIONS -------------------------
--------------------------------------------------------------------------------
-- Parse a list of ratios from a string. String is formatted as follows:
-- "a/b; c/d; e/f; g/h"
function p.parse_ratios(unparsed)
local parsed = tip.parse_numeric_pairs(unparsed)
for i = 1, #parsed do
parsed[i] = rat.new(parsed[i][1], parsed[i][2])
end
return parsed
end
--------------------------------------------------------------------------------
---------------------------- RATIO STRING FUNCTIONS ----------------------------
--------------------------------------------------------------------------------
-- Convert a table of ratios into a string, with options for links and delimiter
function p.ratios_as_text(ratios, add_links, delimiter)
local add_links = add_links == true
local delimiter = delimiter or ", "
local text = ""
if #ratios ~= 0 then
text = add_links and string.format("[[%s]]", rat.as_ratio(ratios[1])) or rat.as_ratio(ratios[1])
for i = 2, #ratios do
text = text .. (add_links and string.format("%s[[%s]]", delimiter, rat.as_ratio(ratios[i])) or string.format("%s%s", delimiter, rat.as_ratio(ratios[i])))
end
end
return text
end
-- Convert a table of ratios (tables, as defined by rational module) into a
-- line of text, with options for delimiters.
function p.ratios_as_texts(ratios, add_links, delimiter)
local add_links = add_links == true
local delimiter = delimiter or ", "
local texts = {}
for i = 1, #ratios do
local text = p.ratios_as_text(ratios[i], add_links, delimiter)
table.insert(texts, text)
end
return texts
end
function p.tester()
local ratios = p.search_by_prime_limit_within_equave()
return p.ratios_as_text(ratios)
end
return p