Module:Rational: Difference between revisions
mNo edit summary |
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 | ||