Module:Rational: Difference between revisions

All the special cases in as_ket make no sense
ArrowHead294 (talk | contribs)
mNo edit summary
 
(9 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 = {}


-- construct a rational number n/m
-- enter a numerator n and denominator m
-- returns a table of prime factors
-- similar to a monzo, but the indices are prime numbers.
function p.new(n, m)
function p.new(n, m)
m = m or 1
m = m or 1
Line 14: Line 17:
end
end
local sign = utils.signum(n) * utils.signum(m)
local sign = utils.signum(n) * utils.signum(m)
-- ensure n and m are positive
n = n * utils.signum(n)
n = n * utils.signum(n)
m = m * utils.signum(m)
m = m * utils.signum(m)
-- factorize n and m separately
local n_factors = utils.prime_factorization_raw(n)
local n_factors = utils.prime_factorization_raw(n)
local m_factors = utils.prime_factorization_raw(m)
local m_factors = utils.prime_factorization_raw(m)
local factors = n_factors
local factors = n_factors
factors.sign = sign
factors.sign = sign
-- subtract the factors of m from the factors of n
for factor, power in pairs(m_factors) do
for factor, power in pairs(m_factors) do
factors[factor] = factors[factor] or 0
factors[factor] = factors[factor] or 0
factors[factor] = factors[factor] - power
factors[factor] = factors[factor] - power
if factors[factor] == 0 then
if factors[factor] == 0 then
factors[factor] = nil
factors[factor] = nil -- clear the zeros
end
end
end
end
Line 327: 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 547: 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 557: 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 568: 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 578: 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 650: 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 858: 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 867: 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 893: 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,477: 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