I need another set of eyes to tell me what is wrong with my Eiffel implementation of Burnikel and Ziegler's division, specifically "Algorithm 2 - 3n/2n". The Eiffel feature is shown below. The type "like Current" is an ARRAYED_LIST [NATURAL_8]. In other words, the implementation uses digits (i.e. limbs) containing 8-bit values, so numbers are in base-256. A manual trace of a failing call follows. (Sorry the arguments are so large, but I cannot reproduce the error with shorter values.) Execution follows step 3b in this case.
Here's the problem. The algorithm seems to be fine to Step 5, where the remainder "r" ends up with more digits then the divisor. I believe the error is in step 3b, perhaps with the call to feature `ones' which is "supposed" to supply a value that is "Beta^n - 1". (Maybe I do not understand B&Z's "Beta^n" notation.
Here is the Eiffel code:
three_by_two_divide (a, a3, b: like Current): TUPLE [quot, rem: like Current]
-- Called by `two_by_one_divide'. It has similar structure as
-- `div_three_halves_by_two_halfs', but the arguments to this
-- function have type {JJ_BIG_NATURAL} instead of like `digit'.
-- See Burnikel & Zieler, "Fast Recursive Division", pp 4-8,
-- Algorithm 2.
require
n_not_odd: b.count >= div_limit and b.count \\ 2 = 0
b_has_2n_digits: b.count = a3.count * 2
a_has_2n_digits: a.count = a3.count * 2
local
n: INTEGER
a1, a2: like Current
b1, b2: like Current
tup: TUPLE [quot, rem: like Current]
q, q1, q2, r, r1: like Current
c, d: like Current
do
n := b.count // 2
-- 1) Split `a'
a1 := new_sub_number (n + 1, a.count, a)
a2 := new_sub_number (1, n.max (1), a)
-- 2) Split `b'.
b1 := new_sub_number (n + 1, b.count, b)
b2 := new_sub_number (1, n.max (1), b)
-- 3) Distinguish cases.
if a1 < b1 then
-- 3a) compute Q = floor ([A1,A2] / B1 with remainder.
if b1.count < div_limit then
tup := school_divide (a, b1)
else
tup := two_by_one_divide (a, b1)
end
q := tup.quot
r1 := tup.rem
else
-- 3b) Q = beta^n - 1 and ...
q := ones (n)
-- ... R1 = [A1,A2] - [B1,0] + [0,B1] = [A1,A2] - QB1.
r1 := a + b1
if n > 1 then
b1.shift_left (n)
else
b1.bit_shift_left (zero_digit.bit_count // 2)
end
r1.subtract (b1)
end
-- 4) D = Q * B2
d := q * b2
-- 5) R1 * B^n + A3 - D. (The paper says "a4".)
r1.shift_left (n)
r := r1 + a3 - d
-- 6) As long as R < 0, repeat
from
until not r.is_negative
loop
r := r + b
q.decrement
end
check
remainder_small_enough: r.count <= b.count
-- because remainder must be less than divisor.
end
Result := [q, r]
ensure
-- n_digit_remainder: Result.rem.count = b.count // 2
quotient_has_correct_count: Result.quot.count <= b.count // 2
end
In the trace, the arrow points to a line I believe is bad, but I don't know what to do with it. Here is the trace:
three_by_two_divide (a = [227,26,41,95,169,93,135,110],
a3 = [92,164,19,39],
b = [161,167,158,41,164,0,0,0])
n := b.count // 2 = 4
-- 1) Split `a'.
a1 := new_sub_number (n + 1, a.count, a) = [227,26,41,95]
a2 := new_sub_number (1, n.max (1), a) = [169,93,135,110]
-- 2) Split `b'.
b1 := new_sub_number (n + 1, b.count, b) = [161,167,158,41]
b2 := new_sub_number (1, n.max (1), b) = [164,0,0,0]
-- 3b) Q = beta^n -1 and ...
--> q := ones (4) = [255,255,255,255] <-- Is this the error?
-- ... R1 = [A1,A2] - [B1,0] + [0,B1].
r1 := a + b1 = [227,26,41,96,75,5,37,151]
b1.shift_left (n) = [161,167,158,41,0,0,0,0]
r1.subtract (b1) = [65,114,139,55,75,5,37,151]
d := q * b2 = [163,255,255,255,92,0,0,0]
r1.shift_left (n) = [227,25,135,184,172,220,37,151,0,0,0,0] -- too big!
r := r1 + a3 - d -= [227,25,135,184,8,220,37,152,0,164,19,39] -- too big!
I know this is long, but any help is appreciated.