Module:Rational: Difference between revisions

Document this mess, starting with the first function
ArrowHead294 (talk | contribs)
mNo edit summary
 
(8 intermediate revisions by 3 users not shown)
Line 1: Line 1:
local p = {}
local seq = require("Module:Sequence")
local seq = require("Module:Sequence")
local utils = require("Module:Utils")
local utils = require("Module:Utils")
local p = {}


-- enter a numerator n and denominator m
-- enter a numerator n and denominator m
Line 332: Line 333:


-- compute a canonical representation of `a` modulo powers of `b`
-- compute a canonical representation of `a` modulo powers of `b`
-- TODO: describe the exact behavior
--      it seems bugged when the equave is a fraction
function p.modulo_mul(a, b)
function p.modulo_mul(a, b)
if type(a) == "number" then
if type(a) == "number" then
Line 552: Line 555:
end
end


-- determine whether a rational number represents a harmonic
-- determine whether a rational number represents a harmonic.
-- reduced: check for reduced harmonic instead.
function p.is_harmonic(a, reduced, large)
function p.is_harmonic(a, reduced, large)
if type(a) == "number" then
if type(a) == "number" then
Line 562: Line 566:
for factor, power in pairs(a) do
for factor, power in pairs(a) do
if type(factor) == "number" then
if type(factor) == "number" then
if power < 0 then
if factor == 2 and reduced then
-- pass (ignore factors of 2 for reduced harmonic check)
elseif power < 0 then
return false
return false
end
end
Line 573: Line 579:
end
end


-- determine whether a rational number represents a subharmonic
-- determine whether a rational number represents a subharmonic.
-- reduced: check for reduced subharmonic instead.
function p.is_subharmonic(a, reduced, large)
function p.is_subharmonic(a, reduced, large)
if type(a) == "number" then
if type(a) == "number" then
Line 583: Line 590:
for factor, power in pairs(a) do
for factor, power in pairs(a) do
if type(factor) == "number" then
if type(factor) == "number" then
if power > 0 then
if factor == 2 and reduced then
-- pass (ignore factors of 2 for reduced subharmonic check)
elseif power > 0 then
return false
return false
end
end
Line 655: Line 664:
end
end


-- check if an integer is highly composite
-- check if an integer is prime
function p.is_highly_composite(a)
function p.is_prime(a)
if type(a) == "number" then
if type(a) == "number" then
a = p.new(a)
a = p.new(a)
end
end
if a.nan or a.inf or a.zero then
-- nan, inf, zero, and negative numbers are not prime
if a.nan or a.inf or a.zero or a.sign < 0 then
return false
return false
end
end
-- negative numbers are not highly composite
if a.sign == -1 then
local flag = false -- flag for having exactly one prime factor
return false
end
-- non-integers are not highly composite
for factor, power in pairs(a) do
for factor, power in pairs(a) do
if type(factor) == "number" then
if type(factor) == "number" and power then
if power < 0 then
if flag or power ~= 1 then
return false
return false
else
flag = true
end
end
end
end
end
end
local last_power = 1 / 0
return flag
local max_prime = p.max_prime(a)
end
for i = 2, max_prime do
 
-- check if an integer is highly composite
function p.is_highly_composite(a)
if type(a) == "number" then
a = p.new(a)
end
-- nan, inf, zero, and negative numbers are not highly composite
if a.nan or a.inf or a.zero or a.sign == -1 then
return false
end
-- non-integers are not highly composite
for factor, power in pairs(a) do
if type(factor) == "number" then
if power < 0 then
return false
end
end
end
local last_power = 1 / 0
local max_prime = p.max_prime(a)
for i = 2, max_prime do
if utils.is_prime(i) then
if utils.is_prime(i) then
-- factors must be the first N primes
-- factors must be the first N primes
Line 863: Line 896:
end
end


-- find max prime involved in the factorisation
-- Check if ratio is within an int limit; that is, neither its numerator nor
-- (a.k.a. prime limit or harmonic class) of a rational number
-- denominator exceed that limit.
function p.max_prime(a)
function p.is_within_int_limit(a, lim)
return p.int_limit(a) <= lim
end
 
-- Find integer limit of a ratio
-- For a ratio p/q, this is simply max(p, q)
function p.int_limit(a)
if type(a) == "number" then
if type(a) == "number" then
a = p.new(a)
a = p.new(a)
Line 872: Line 911:
return nil
return nil
end
end
local max_factor = 0
local a_copy = p.copy(a)
for factor, _ in pairs(a) do
local num, den = p.as_pair(a_copy)
if type(factor) == "number" then
return math.max(num, den)
if factor > max_factor then
max_factor = factor
end
end
end
return max_factor
end
end


Line 898: Line 931:
local num, den = p.as_pair(a_copy)
local num, den = p.as_pair(a_copy)
return math.max(num, den)
return math.max(num, den)
end
-- find max prime involved in the factorisation
-- (a.k.a. prime limit or harmonic class) of a rational number
function p.max_prime(a)
if type(a) == "number" then
a = p.new(a)
end
if a.nan or a.inf or a.zero then
return nil
end
local max_factor = 0
for factor, _ in pairs(a) do
if type(factor) == "number" then
if factor > max_factor then
max_factor = factor
end
end
end
return max_factor
end
end


Line 1,482: Line 1,535:
function p.ket(frame)
function p.ket(frame)
local unparsed = frame.args[1] or "1"
local unparsed = frame.args[1] or "1"
local result = ""
local a = p.parse(unparsed)
local a = p.parse(unparsed)
if a == nil then
if a == nil then
return '<span style="color:red;">Invalid rational number: ' .. unparsed .. ".</span>"
result = '{{error|Invalid rational number: ' .. unparsed .. ".}}"
else
result = p.as_ket(a, frame)
end
end
return p.as_ket(a, frame)
return frame:preprocess(result)
end
end
p.monzo = p.ket
p.monzo = p.ket


return p
return p