Module:JI ratio finder: Difference between revisions

From Xenharmonic Wiki
Jump to navigation Jump to search
Ganaram inukshuk (talk | contribs)
Added ratios-to-text
Ganaram inukshuk (talk | contribs)
m find_ratio_for_cents now returns ratios (as lua tables), not text
Line 43: Line 43:
if within_min_tolerance and is_simplified and within_prime_limit and within_max_tolerance and within_odd_limit then
if within_min_tolerance and is_simplified and within_prime_limit and within_max_tolerance and within_odd_limit then
table.insert(found_ratios, rat.as_ratio(current_ratio))
table.insert(found_ratios, current_ratio)
end
end

Revision as of 08:21, 11 January 2024

Module documentation[view] [edit] [history] [purge]

Todo: add documentation


local utils = require('Module:Utils')
local interval = require('Module:Interval')
local rat = require('Module:Rational')
local p = {}

-- Main function
-- Finds approximated JI ratios for a cent value for a prime and odd limit
function p.find_ratios_for_cents(cents, tolerance, prime_limit, odd_limit)
	local cents = cents or 700
	local tolerance = tolerance or 20
	local prime_limit = prime_limit or 5
	local odd_limit = odd_limit or 49
	
	local num = 1
	local den = 1
	
	local within_min_tolerance = true
	local within_max_tolerance = true
	local within_odd_limit = true
	local within_prime_limit = true
	local is_simplified = true
	
	local found_ratios = {}
	
	-- Algorithm is as follows:
	-- Start with a unison p/q, where p=q and check whether it's within the
	-- range of the target ratio. If so, record it. Increment p by 1 and repeat
	-- until p/q exceeds the target range.
	-- Once p/q exceeds the range of the target ratio, increment q and repeat
	-- the process described above. End this process once p or q exceed a
	-- specified limit (the odd limit, in this case).
	repeat
		repeat
			local current_ratio = rat.new(num, den)
			local ratio_in_cents = rat.cents(current_ratio)
			
			-- Check conditions
			within_min_tolerance = ratio_in_cents > cents - tolerance
			within_max_tolerance = ratio_in_cents < cents + tolerance
			within_odd_limit = rat.odd_limit(current_ratio) <= odd_limit
			within_prime_limit = rat.max_prime(current_ratio) <= prime_limit
			is_simplified = utils._gcd(num, den) == 1
			
			if within_min_tolerance and is_simplified and within_prime_limit and within_max_tolerance and within_odd_limit then
				table.insert(found_ratios, current_ratio)
			end
			
			-- Increment numerator
			num = num + 1

		until not within_max_tolerance
		
		den = den + 1
		num = den
		
	until not within_odd_limit
	
	return found_ratios
end

function p.ratios_to_text(ratios)
	local ratios = ratios or { rat.new(5, 4), rat.new (81, 64) }

	local text = ""
	for i = 1, #ratios do
		text = text .. rat.as_ratio(ratios[i])
		if i ~= #ratios then
			text = text .. ", "
		end
	end
	return text
end


return p