Module:Rational: Difference between revisions

Plumtree (talk | contribs)
mNo edit summary
Plumtree (talk | contribs)
m pow() and modulo_mul() implemented
Line 112: Line 112:
function p.div(a, b)
function p.div(a, b)
return p.mul(a, p.inv(b))
return p.mul(a, p.inv(b))
end
-- compute a^b; b must be an integer
function p.pow(a, b)
if type(a) == 'number' then
a = p.new(a)
end
if type(b) ~= 'number' then
return nil
end
if a.nan then
return { nan = true }
end
if a.inf then
if b == 0 then
return { nan = true }
elseif b > 0 then
return { inf = true, sign = math.pow(a.sign, b) }
else
return { zero = true, sign = math.pow(a.sign, b) }
end
end
if a.zero then
if b == 0 then
return p.new(1)
elseif b > 0 then
return { zero = true, sign = math.pow(a.sign, b) }
else
return { inf = true, sign = math.pow(a.sign, b) }
end
end
local c = p.new(1)
for i = 1, math.abs(b) do
if b > 0 then
c = p.mul(c, a)
else
c = p.div(c, a)
end
end
return c
end
-- compute a canonical representation of `a` modulo powers of `b`
function p.modulo_mul(a, b)
if type(a) == 'number' then
a = p.new(a)
end
if type(b) == 'number' then
b = p.new(b)
end
if a.nan or b.nan or a.inf or b.inf or a.zero or b.zero then
return p.copy(a)
end
local neg_power = -1/0
local pos_power = 1/0
for factor, power in pairs(b) do
if type(factor) == 'number' then
if (power > 0 and (a[factor] or 0) >= 0) or (power < 0 and (a[factor] or 0) <= 0) then
pos_power = math.min(pos_power,
math.floor((a[factor] or 0) / power)
)
else
neg_power = math.max(neg_power,
-math.ceil(math.abs(a[factor] or 0) / math.abs(power))
)
end
end
end
local power = 0
if neg_power ~= neg_power + 1 and neg_power < 0 then
power = neg_power
end
if pos_power ~= pos_power + 1 and pos_power > 0 then
power = pos_power
end
return p.div(a, p.pow(b, power))
end
end