Module:Rational: Difference between revisions

Plumtree (talk | contribs)
mNo edit summary
Plumtree (talk | contribs)
mNo edit summary
Line 658: Line 658:
end
end
return max_factor
return max_factor
end
-- compute log2 of a rational number
function p.log(a, base)
base = base or 2
if type(a) == 'number' then
a = p.new(a)
end
if a.inf and a.sign > 0 then
return 1/0
end
if a.nan or a.inf then
return nil
end
if a.zero then
return -1/0
end
if a.sign < 0 then
return nil
end
local logarithm = 0
for factor, power in pairs(a) do
if type(factor) == 'number' then
logarithm = logarithm + power * math.log(factor) / math.log(base)
end
end
return logarithm
end
end


Line 669: Line 696:
end
end
local b = p.copy(a)
local b = p.copy(a)
-- start with an approximation
local log2 = p.log(b)
b = p.div(b, p.pow(2, math.floor(log2)))
while p.lt(b, 1) do
while p.lt(b, 1) do
b = p.mul(b, 2)
b = p.mul(b, 2)
Line 742: Line 774:
table.sort(utonal)
table.sort(utonal)
local fifths = b[3] or 0
local fifths = b[3] or 0
mw.log(p.as_ratio(b))
mw.log('fifths=' .. fifths)


-- does not work well when `fifths` is 12+7*n or -12-7*n, n>=0
local red3 = red(p.pow(3, fifths))
-- b = p.div(b, red(p.pow(3, fifths)))
mw.log('dividing by ' .. p.as_ratio(red3))
-- local octaves = b[2] or 0
b = p.div(b, red3)
local octaves = b[2] or 0
mw.log('octaves=' .. octaves)
if math.abs(fifths) >= 12 and math.abs(fifths) % 7 == 5 then
-- still wrong results with 4096/2187: d1 instead of d8
octaves = octaves - u.signum(fifths)
mw.log('octaves=' .. octaves)
end
-- a terrible hack, I have no idea how/why this is supposed to work
-- a terrible hack, I have no idea how/why this is supposed to work
local octaves = (b[2] or 0) + fifths + 4 * math.floor(fifths / 7) + math.floor((fifths % 7) / 2)
-- local octaves = (b[2] or 0) + fifths + 4 * math.floor(fifths / 7) + math.floor((fifths % 7) / 2)
local noshift = {1, 5, 2, 6, 3, 7, 4}
local noshift = {1, 5, 2, 6, 3, 7, 4}
local num = noshift[1 + (fifths % 7)] + octaves * 7
local num = noshift[1 + (fifths % 7)] + octaves * 7
if octaves < 0 then
if octaves < 0 then
mw.log('octaves < 0, inverting')
fifths = -fifths
fifths = -fifths
-- wrong results on 3^53/2^84, which should be AAAAAAA3 but is computed as ddddddd-6
-- wrong results on 3^53/2^84, which should be AAAAAAA3 but is computed as ddddddd-6
octaves = -(b[2] or 0) + fifths + 4 * math.floor(fifths / 7) + math.floor((fifths % 7) / 2)
-- octaves = -(b[2] or 0) + fifths + 4 * math.floor(fifths / 7) + math.floor((fifths % 7) / 2)
num = -noshift[1 + (fifths % 7)] - octaves * 7
-- num = -noshift[1 + (fifths % 7)] - octaves * 7
if fifths ~= 0 then
num = num - 2
else
num = num + 5
end
end
end
Line 786: Line 832:
FJS = FJS .. '_{' .. table.concat(utonal, ',') .. '}'
FJS = FJS .. '_{' .. table.concat(utonal, ',') .. '}'
end
end
-- TODO: 531441/262144 should result in A7, not A14
return FJS
return FJS
end
end