Module:JI ratio finder: Difference between revisions
Removed exact-ratio filtering (ji-ratios-in-ed doesn't need it anymore) |
Added subgroup search and filtering |
||
| Line 22: | Line 22: | ||
local equave = equave or rat.new(2) | local equave = equave or rat.new(2) | ||
return rat.mul(rat.inv(ratio), equave) | return rat.mul(rat.inv(ratio), equave) | ||
end | |||
-- Determines whether a ratios is within a subgroup; for a subgroup p1.p2..pn, | |||
-- a ratio p/q is in that subgroup if its prime factorization contains any prime | |||
-- factors p1, p2, .. pn. | |||
function p.within_subgroup(ratio, subgroup) | |||
local ratio = ratio or rat.new(5, 2) | |||
local subgroup = subgroup or { 2, 3, 5 } | |||
local within_subgroup = "" | |||
for key, value in pairs(ratio) do | |||
if key ~= "sign" then | |||
within_subgroup = within_subgroup and utils.table_contains(subgroup, key) | |||
end | |||
end | |||
return within_subgroup | |||
end | end | ||
| Line 47: | Line 64: | ||
if is_simplified and is_within_cents and is_within_prime_limit then | if is_simplified and is_within_cents and is_within_prime_limit then | ||
table.insert(candidate_ratios, current_ratio) | |||
end | |||
numerator = numerator + 1 | |||
until not is_within_cents | |||
end | |||
return candidate_ratios | |||
end | |||
-- Finds candidate ratios up to a cent value, up to a denominator limit, and | |||
-- within a prime subgroup. | |||
-- These ratios should be filtered as needed. | |||
function p.find_candidate_ratios_within_subgroup(cents, denominator_limit, subgroup) | |||
local cents = cents or 1200 | |||
local denominator_limit = denominator_limit or 99 | |||
local subgroup = subgroup or { 2, 3, 7, 11 } | |||
local candidate_ratios = {} | |||
for i = 1, denominator_limit do | |||
local denominator = i | |||
local numerator = i | |||
local is_within_cents = true | |||
repeat | |||
local current_ratio = rat.new(numerator, denominator) | |||
local is_simplified = utils._gcd(numerator, denominator) == 1 | |||
local is_within_subgroup = p.within_subgroup(current_ratio, subgroup) | |||
is_within_cents = rat.cents(current_ratio) <= cents | |||
if is_simplified and is_within_cents and is_within_subgroup then | |||
table.insert(candidate_ratios, current_ratio) | table.insert(candidate_ratios, current_ratio) | ||
end | end | ||
| Line 120: | Line 170: | ||
if rat.max_prime(ratios[i]) == harmonic_class then | if rat.max_prime(ratios[i]) == harmonic_class then | ||
table.insert(filtered_ratios, ratios[i]) | table.insert(filtered_ratios, ratios[i]) | ||
end | |||
end | |||
return filtered_ratios | |||
end | |||
-- Filters ratios by prime subgroup (such as 2.3.5) | |||
-- Filters out ratios whose factors are not in the given subgroup; this requires | |||
-- filtering by each prime as a harmonic class | |||
function p.filter_ratios_by_subgroup(ratios, subgroup) | |||
local ratios = ratios or { rat.new(1), rat.new(5, 4), rat.new(81, 64), rat.new(9, 7) } | |||
local subgroup = subgroup or { 2, 3, 5 } | |||
local candidate_ratios = p.filter_ratios_by_prime_limit(ratios, subgroup[#subgroup]) | |||
local filtered_ratios = {} | |||
for i = 1, #subgroup do | |||
local prime_filtered_ratios = p.filter_ratios_by_harmonic_class(candidate_ratios, subgroup[i]) | |||
for j = 1, #prime_filtered_ratios do | |||
table.insert(filtered_ratios, prime_filtered_ratios[j]) | |||
end | end | ||
end | end | ||