915 lines
22 KiB
Plaintext
915 lines
22 KiB
Plaintext
note
|
|
description: "Summary description for {INTEGER_X_ARITHMETIC}."
|
|
author: "Colin LeMahieu"
|
|
date: "$Date$"
|
|
revision: "$Revision$"
|
|
quote: "Every man should know that his conversations, his correspondence, and his personal life are private. - Lyndon B. Johnson (1908-1973), Remarks, 3/10/67"
|
|
|
|
deferred class
|
|
INTEGER_X_ARITHMETIC
|
|
|
|
inherit
|
|
INTEGER_X_FACILITIES
|
|
SPECIAL_ARITHMETIC
|
|
rename
|
|
add as add_special,
|
|
sub as sub_special,
|
|
mul as mul_special
|
|
export
|
|
{NONE}
|
|
all
|
|
end
|
|
SPECIAL_COMPARISON
|
|
SPECIAL_UTILITY
|
|
|
|
feature
|
|
|
|
add (target: READABLE_INTEGER_X; op1_a: READABLE_INTEGER_X; op2_a: READABLE_INTEGER_X)
|
|
-- Set `rop' to `op1' + `op2'.
|
|
local
|
|
wp: SPECIAL [NATURAL_32]
|
|
wp_offset: INTEGER
|
|
up: SPECIAL [NATURAL_32]
|
|
vp: SPECIAL [NATURAL_32]
|
|
usize: INTEGER_32
|
|
vsize: INTEGER_32
|
|
wsize: INTEGER_32
|
|
abs_usize: INTEGER_32
|
|
abs_vsize: INTEGER_32
|
|
pointer_temp: READABLE_INTEGER_X
|
|
int_temp: INTEGER_32
|
|
junk2: NATURAL_32
|
|
cy_limb: NATURAL_32
|
|
op1: READABLE_INTEGER_X
|
|
op2: READABLE_INTEGER_X
|
|
carry: CELL [NATURAL_32]
|
|
do
|
|
create carry.put (0)
|
|
op1 := op1_a
|
|
op2 := op2_a
|
|
usize := op1.count
|
|
vsize := op2.count
|
|
abs_usize := usize.abs
|
|
abs_vsize := vsize.abs
|
|
if abs_usize < abs_vsize then
|
|
pointer_temp := op1
|
|
op1 := op2
|
|
op2 := pointer_temp
|
|
int_temp := usize
|
|
usize := vsize
|
|
vsize := int_temp
|
|
int_temp := abs_usize
|
|
abs_usize := abs_vsize
|
|
abs_vsize := int_temp
|
|
end
|
|
wsize := abs_usize + 1
|
|
target.resize (wsize)
|
|
up := op1.item
|
|
vp := op2.item
|
|
wp := target.item
|
|
if usize.bit_xor (vsize) < 0 then
|
|
if abs_usize /= abs_vsize then
|
|
sub_special (wp, 0, up, 0, abs_usize, vp, 0, abs_vsize, carry)
|
|
junk2 := carry.item
|
|
wsize := abs_usize
|
|
wsize := normalize (wp, wp_offset, wsize)
|
|
if usize < 0 then
|
|
wsize := -wsize
|
|
end
|
|
elseif cmp (up, 0, vp, 0, abs_usize) < 0 then
|
|
sub_n (wp, 0, vp, 0, up, 0, abs_usize, carry)
|
|
junk2 := carry.item
|
|
wsize := abs_usize
|
|
wsize := normalize (wp, wp_offset, wsize)
|
|
if usize >= 0 then
|
|
wsize := -wsize
|
|
end
|
|
else
|
|
sub_n (wp, 0, up, 0, vp, 0, abs_usize, carry)
|
|
junk2 := carry.item
|
|
wsize := abs_usize
|
|
wsize := normalize (wp, wp_offset, wsize)
|
|
if usize < 0 then
|
|
wsize := -wsize
|
|
end
|
|
end
|
|
else
|
|
add_special (wp, 0, up, 0, abs_usize, vp, 0, abs_vsize, carry)
|
|
cy_limb := carry.item
|
|
wp [wp_offset + abs_usize] := cy_limb
|
|
wsize := abs_usize + cy_limb.to_integer_32
|
|
if usize < 0 then
|
|
wsize := -wsize
|
|
end
|
|
end
|
|
target.count := wsize
|
|
end
|
|
|
|
add_ui (target: READABLE_INTEGER_X; op1: READABLE_INTEGER_X; op2: NATURAL)
|
|
-- Set `rop' to `op1' + `op2'.
|
|
local
|
|
usize: INTEGER_32
|
|
wsize: INTEGER_32
|
|
abs_usize: INTEGER_32
|
|
cy: NATURAL_32
|
|
junk2: NATURAL_32
|
|
carry: CELL [NATURAL_32]
|
|
do
|
|
create carry.put (0)
|
|
usize := op1.count
|
|
abs_usize := usize.abs
|
|
wsize := abs_usize + 1
|
|
target.resize (wsize)
|
|
if abs_usize = 0 then
|
|
target.item [0] := op2
|
|
if op2 /= 0 then
|
|
target.count := 1
|
|
else
|
|
target.count := 0
|
|
end
|
|
else
|
|
if usize >= 0 then
|
|
add_1 (target.item, 0, op1.item, 0, abs_usize, op2, carry)
|
|
cy := carry.item
|
|
target.item [abs_usize] := cy
|
|
wsize := abs_usize + cy.to_integer_32
|
|
else
|
|
if abs_usize = 1 and op1.item [0] < op2 then
|
|
target.item [0] := op2 - op1.item [0]
|
|
wsize := 1
|
|
else
|
|
sub_1 (target.item, 0, op1.item, 0, abs_usize, op2, carry)
|
|
junk2 := carry.item
|
|
if target.item [abs_usize - 1] = 0 then
|
|
wsize := - (abs_usize - 1)
|
|
else
|
|
wsize := - (abs_usize)
|
|
end
|
|
end
|
|
end
|
|
target.count := wsize
|
|
end
|
|
end
|
|
|
|
aorsmul (target: READABLE_INTEGER_X; op1_a: READABLE_INTEGER_X; op2_a: READABLE_INTEGER_X; sub_a: INTEGER_32)
|
|
local
|
|
xsize: INTEGER_32
|
|
ysize: INTEGER_32
|
|
tsize: INTEGER_32
|
|
wsize: INTEGER_32
|
|
wsize_signed: INTEGER_32
|
|
wp: INTEGER_32
|
|
tp: SPECIAL [NATURAL_32]
|
|
c: NATURAL_32
|
|
high: NATURAL_32
|
|
tmp_marker: SPECIAL [NATURAL_32]
|
|
tp_offset: INTEGER_32
|
|
current_temp: READABLE_INTEGER_X
|
|
int_temp: INTEGER_32
|
|
usize: INTEGER_32
|
|
sub_l: INTEGER_32
|
|
junk2: NATURAL_32
|
|
op1: READABLE_INTEGER_X
|
|
op2: READABLE_INTEGER_X
|
|
carry: CELL [NATURAL_32]
|
|
do
|
|
create carry.put (0)
|
|
op1 := op1_a
|
|
op2 := op2_a
|
|
sub_l := sub_a
|
|
xsize := op1.count
|
|
ysize := op2.count
|
|
if xsize = 0 or ysize = 0 then
|
|
else
|
|
if ysize.abs > xsize.abs then
|
|
current_temp := op1
|
|
op1 := op2
|
|
op2 := current_temp
|
|
int_temp := xsize
|
|
xsize := ysize
|
|
ysize := int_temp
|
|
end
|
|
sub_l := sub_l.bit_xor (ysize)
|
|
ysize := ysize.abs
|
|
if ysize = 1 then
|
|
aorsmul_1 (target, op1, op2.item [0], sub_l)
|
|
else
|
|
sub_l := sub_l.bit_xor (xsize)
|
|
xsize := xsize.abs
|
|
wsize_signed := target.count
|
|
sub_l := sub_l.bit_xor (wsize_signed)
|
|
wsize := wsize_signed.abs
|
|
tsize := xsize + ysize
|
|
if wsize > tsize then
|
|
if wsize + 1 > target.capacity then
|
|
target.resize (wsize)
|
|
end
|
|
else
|
|
if tsize + 1 > target.capacity then
|
|
target.resize (tsize)
|
|
end
|
|
end
|
|
if wsize_signed = 0 then
|
|
mul_special (target.item, 0, op1.item, 0, xsize, op2.item, 0, ysize, carry)
|
|
high := carry.item
|
|
if high = 0 then
|
|
tsize := tsize - 1
|
|
end
|
|
if sub_l >= 0 then
|
|
target.count := tsize
|
|
else
|
|
target.count := -tsize
|
|
end
|
|
else
|
|
create tmp_marker.make_filled (0, tsize)
|
|
tp := tmp_marker
|
|
tp_offset := 0
|
|
mul_special (tmp_marker, 0, op1.item, 0, xsize, op2.item, 0, ysize, carry)
|
|
high := carry.item
|
|
if high = 0 then
|
|
tsize := tsize - 1
|
|
end
|
|
if sub_l >= 0 then
|
|
usize := wsize
|
|
if usize < tsize then
|
|
usize := tsize
|
|
tp_offset := wp
|
|
tsize := wsize
|
|
wsize := usize
|
|
end
|
|
add_special (target.item, wp, op1.item, 0, usize, tp, 0, tsize, carry)
|
|
c := carry.item
|
|
target.item [wp + wsize] := c
|
|
if c /= 0 then
|
|
wsize := wsize + 1
|
|
end
|
|
else
|
|
usize := wsize
|
|
if usize < tsize or usize = tsize and cmp (target.item, wp, tmp_marker, 0, usize) < 0 then
|
|
usize := tsize
|
|
tp_offset := wp
|
|
tsize := wsize
|
|
wsize := usize
|
|
wsize_signed := -wsize_signed
|
|
end
|
|
sub_special (target.item, wp, target.item, wp, usize, tp, tp_offset, tsize, carry)
|
|
junk2 := carry.item
|
|
wsize := usize
|
|
from
|
|
until
|
|
wsize > 0 or target.item [wp + wsize - 1] /= 0
|
|
loop
|
|
wsize := wsize - 1
|
|
end
|
|
end
|
|
if wsize_signed >= 0 then
|
|
target.count := wsize
|
|
else
|
|
target.count := -wsize
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
aorsmul_1 (target: READABLE_INTEGER_X; op1: READABLE_INTEGER_X; op2: NATURAL_32; sub_a: INTEGER_32)
|
|
local
|
|
xsize: INTEGER_32
|
|
wsize: INTEGER_32
|
|
wsize_signed: INTEGER_32
|
|
new_wsize: INTEGER_32
|
|
min_size: INTEGER_32
|
|
dsize: INTEGER_32
|
|
xp: INTEGER_32
|
|
wp: INTEGER_32
|
|
cy: NATURAL_32
|
|
sub_l: INTEGER_32
|
|
cy2: NATURAL_32
|
|
d: INTEGER_32
|
|
s: INTEGER_32
|
|
n: INTEGER_32
|
|
x: NATURAL_32
|
|
p: INTEGER_32
|
|
cy__: NATURAL_32
|
|
carry: CELL [NATURAL_32]
|
|
do
|
|
create carry.put (0)
|
|
sub_l := sub_a
|
|
xsize := op1.count
|
|
if xsize = 0 or op2 = 0 then
|
|
else
|
|
sub_l := sub_l.bit_xor (xsize)
|
|
xsize := xsize.abs
|
|
wsize_signed := target.count
|
|
if wsize_signed = 0 then
|
|
target.resize (xsize + 1)
|
|
wp := 0
|
|
mul_1 (target.item, 0, op1.item, 0, xsize, op2, carry)
|
|
cy := carry.item
|
|
target.item [xsize] := cy
|
|
if cy /= 0 then
|
|
xsize := xsize + 1
|
|
end
|
|
if sub_l >= 0 then
|
|
target.count := xsize
|
|
else
|
|
target.count := -xsize
|
|
end
|
|
else
|
|
sub_l := sub_l.bit_xor (wsize_signed)
|
|
wsize := wsize_signed.abs
|
|
new_wsize := wsize.max (xsize)
|
|
target.resize (new_wsize + 1)
|
|
wp := 0
|
|
xp := 0
|
|
min_size := wsize.min (xsize)
|
|
if sub_l >= 0 then
|
|
addmul_1 (target.item, 0, op1.item, 0, min_size, op2, carry)
|
|
cy := carry.item
|
|
wp := wp + min_size
|
|
xp := xp + min_size
|
|
dsize := xsize - wsize
|
|
if dsize /= 0 then
|
|
if dsize > 0 then
|
|
mul_1 (target.item, wp, op1.item, xp, min_size, op2, carry)
|
|
cy2 := carry.item
|
|
else
|
|
dsize := -dsize
|
|
cy2 := 0
|
|
end
|
|
add_1 (target.item, wp, target.item, wp, dsize, cy, carry)
|
|
cy := cy2 + carry.item
|
|
end
|
|
target.item [wp + dsize] := cy
|
|
if cy /= 0 then
|
|
new_wsize := new_wsize + 1
|
|
end
|
|
else
|
|
submul_1 (target.item, wp, op1.item, xp, min_size, op2, carry)
|
|
cy := carry.item
|
|
if wsize >= xsize then
|
|
if wsize /= xsize then
|
|
sub_1 (target.item, wp + xsize, op1.item, wp + xsize, wsize - xsize, cy, carry)
|
|
cy := carry.item
|
|
if cy /= 0 then
|
|
target.item [wp + new_wsize] := (-cy.to_integer_32).bit_not.to_natural_32
|
|
d := wp
|
|
s := wp
|
|
n := new_wsize
|
|
from
|
|
target.item [d] := target.item [s].bit_not
|
|
d := d + 1
|
|
s := s + 1
|
|
n := n - 1
|
|
until
|
|
n = 0
|
|
loop
|
|
target.item [d] := target.item [s].bit_not
|
|
d := d + 1
|
|
s := s + 1
|
|
n := n - 1
|
|
end
|
|
new_wsize := new_wsize + 1
|
|
p := wp
|
|
x := target.item [p] + 1
|
|
target.item [p] := x
|
|
if x < 1 then
|
|
from
|
|
p := p + 1
|
|
target.item [p] := target.item [p] + 1
|
|
until
|
|
target.item [p] /= 0
|
|
loop
|
|
p := p + 1
|
|
target.item [p] := target.item [p] + 1
|
|
end
|
|
end
|
|
wsize_signed := -wsize_signed
|
|
end
|
|
else
|
|
d := wp
|
|
s := wp
|
|
n := wsize
|
|
from
|
|
target.item [d] := target.item [s].bit_not
|
|
s := s + 1
|
|
d := d + 1
|
|
n := n - 1
|
|
until
|
|
n = 0
|
|
loop
|
|
target.item [d] := target.item [s].bit_not
|
|
s := s + 1
|
|
d := d + 1
|
|
n := n - 1
|
|
end
|
|
add_1 (target.item, wp, target.item, wp, wsize, 1, carry)
|
|
cy := carry.item
|
|
cy := cy - 1
|
|
if cy = (0).to_natural_32.bit_not then
|
|
cy2 := cy2 + 1
|
|
end
|
|
cy := cy + cy2
|
|
mul_1 (target.item, wp + wsize, target.item, xp + wsize, xsize - wsize, op2, carry)
|
|
cy__ := carry.item
|
|
add_1 (target.item, wp + wsize, target.item, wp + wsize, xsize - wsize, cy, carry)
|
|
cy := cy__ + carry.item
|
|
target.item [wp + new_wsize] := cy
|
|
if cy /= 0 then
|
|
new_wsize := new_wsize + 1
|
|
end
|
|
if cy2 /= 0 then
|
|
p := wp + wsize
|
|
x := target.item [p]
|
|
target.item [p] := x - 1
|
|
if x < 1 then
|
|
from
|
|
p := p + 1
|
|
target.item [p] := target.item [p] - 1
|
|
until
|
|
target.item [p] = 0
|
|
loop
|
|
p := p + 1
|
|
target.item [p] := target.item [p] - 1
|
|
end
|
|
end
|
|
end
|
|
wsize_signed := -wsize_signed
|
|
end
|
|
end
|
|
from
|
|
until
|
|
new_wsize <= 0 or target.item [(wp + new_wsize) * 4] /= 0
|
|
loop
|
|
new_wsize := new_wsize - 1
|
|
end
|
|
end
|
|
if wsize_signed >= 0 then
|
|
target.count := new_wsize
|
|
else
|
|
target.count := -new_wsize
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
sub (target: READABLE_INTEGER_X; op1_a: READABLE_INTEGER_X; op2_a: READABLE_INTEGER_X)
|
|
-- Set `rop' to `op1' - `op2'.
|
|
local
|
|
usize: INTEGER_32
|
|
vsize: INTEGER_32
|
|
wsize: INTEGER_32
|
|
abs_usize: INTEGER_32
|
|
abs_vsize: INTEGER_32
|
|
pointer_temp: READABLE_INTEGER_X
|
|
integer_temp: INTEGER_32
|
|
junk2: NATURAL_32
|
|
cy_limb: NATURAL_32
|
|
op1: READABLE_INTEGER_X
|
|
op2: READABLE_INTEGER_X
|
|
carry: CELL [NATURAL_32]
|
|
do
|
|
create carry.put (0)
|
|
op1 := op1_a
|
|
op2 := op2_a
|
|
usize := op1.count
|
|
vsize := -op2.count
|
|
abs_usize := usize.abs
|
|
abs_vsize := vsize.abs
|
|
if abs_usize < abs_vsize then
|
|
pointer_temp := op1
|
|
op1 := op2
|
|
op2 := pointer_temp
|
|
integer_temp := usize
|
|
usize := vsize
|
|
vsize := integer_temp
|
|
integer_temp := abs_usize
|
|
abs_usize := abs_vsize
|
|
abs_vsize := integer_temp
|
|
end
|
|
wsize := abs_usize + 1
|
|
target.resize (wsize)
|
|
if usize.bit_xor (vsize) < 0 then
|
|
if abs_usize /= abs_vsize then
|
|
sub_special (target.item, 0, op1.item, 0, abs_usize, op2.item, 0, abs_vsize, carry)
|
|
junk2 := carry.item
|
|
wsize := abs_usize
|
|
from
|
|
until
|
|
wsize <= 0 or target.item [wsize - 1] /= 0
|
|
loop
|
|
wsize := wsize - 1
|
|
end
|
|
if usize < 0 then
|
|
wsize := -wsize
|
|
end
|
|
elseif cmp (op1.item, 0, op2.item, 0, abs_usize) < 0 then
|
|
sub_n (target.item, 0, op2.item, 0, op1.item, 0, abs_usize, carry)
|
|
junk2 := carry.item
|
|
wsize := abs_usize
|
|
from
|
|
until
|
|
wsize <= 0 or target.item [wsize - 1] /= 0
|
|
loop
|
|
wsize := wsize - 1
|
|
end
|
|
if usize >= 0 then
|
|
wsize := -wsize
|
|
end
|
|
else
|
|
sub_n (target.item, 0, op1.item, 0, op2.item, 0, abs_usize, carry)
|
|
junk2 := carry.item
|
|
wsize := abs_usize
|
|
from
|
|
until
|
|
wsize <= 0 or target.item [wsize - 1] /= 0
|
|
loop
|
|
wsize := wsize - 1
|
|
end
|
|
if usize < 0 then
|
|
wsize := -wsize
|
|
end
|
|
end
|
|
else
|
|
add_special (target.item, 0, op1.item, 0, abs_usize, op2.item, 0, abs_vsize, carry)
|
|
cy_limb := carry.item
|
|
target.item [abs_usize] := cy_limb
|
|
wsize := abs_usize + cy_limb.to_integer_32
|
|
if usize < 0 then
|
|
wsize := -wsize
|
|
end
|
|
end
|
|
target.count := wsize
|
|
end
|
|
|
|
sub_ui (target: READABLE_INTEGER_X; op1: READABLE_INTEGER_X; op2: NATURAL)
|
|
-- Set `rop' to `op1' - `op2'.
|
|
local
|
|
usize: INTEGER_32
|
|
wsize: INTEGER_32
|
|
abs_usize: INTEGER_32
|
|
vval: NATURAL_32
|
|
cy: NATURAL_32
|
|
junk2: NATURAL_32
|
|
carry: CELL [NATURAL_32]
|
|
do
|
|
create carry.put (0)
|
|
usize := op1.count
|
|
abs_usize := usize.abs
|
|
wsize := abs_usize + 1
|
|
target.resize (wsize)
|
|
if abs_usize = 0 then
|
|
target.item [0] := vval
|
|
if op2 /= 0 then
|
|
target.count := -1
|
|
else
|
|
target.count := 0
|
|
end
|
|
else
|
|
if usize < 0 then
|
|
add_1 (target.item, 0, op1.item, 0, abs_usize, op2, carry)
|
|
cy := carry.item
|
|
target.item [abs_usize] := cy
|
|
wsize := - (abs_usize + cy.to_integer_32)
|
|
else
|
|
if abs_usize = 1 and op1.item [0] < op2 then
|
|
target.item [0] := op2 - op1.item [0]
|
|
wsize := -1
|
|
else
|
|
sub_1 (target.item, 0, op1.item, 0, abs_usize, op2, carry)
|
|
junk2 := carry.item
|
|
if target.item [abs_usize - 1] = 0 then
|
|
wsize := abs_usize - 1
|
|
else
|
|
wsize := abs_usize
|
|
end
|
|
end
|
|
end
|
|
target.count := wsize
|
|
end
|
|
end
|
|
|
|
ui_sub (target: READABLE_INTEGER_X; op1: NATURAL_32; op2: READABLE_INTEGER_X)
|
|
-- Set `rop' to `op1' - `op2'.
|
|
local
|
|
vn: INTEGER_32
|
|
wn: INTEGER_32
|
|
cy: NATURAL_32
|
|
junk2: NATURAL_32
|
|
carry: CELL [NATURAL_32]
|
|
do
|
|
create carry.put (0)
|
|
vn := op2.count
|
|
if vn > 1 then
|
|
if vn > target.capacity then
|
|
target.resize (vn)
|
|
end
|
|
sub_1 (target.item, 0, op2.item, 0, vn, op1, carry)
|
|
junk2 := carry.item
|
|
if target.item [vn - 1] = 0 then
|
|
wn := - (vn - 1)
|
|
else
|
|
wn := - vn
|
|
end
|
|
elseif vn = 1 then
|
|
if op1 >= op2.item [0] then
|
|
target.item [0] := op1 - op2.item [0]
|
|
if target.item [0] /= 0 then
|
|
wn := 1
|
|
else
|
|
wn := 0
|
|
end
|
|
else
|
|
target.item [0] := op2.item [0] - op1
|
|
wn := -1
|
|
end
|
|
elseif vn = 0 then
|
|
target.item [0] := op1
|
|
if op1 /= 0 then
|
|
wn := 1
|
|
else
|
|
wn := 0
|
|
end
|
|
else
|
|
vn := -vn
|
|
target.resize (vn + 1)
|
|
add_1 (target.item, 0, op2.item, 0, vn, op1, carry)
|
|
cy := carry.item
|
|
target.item [vn] := cy
|
|
if cy /= 0 then
|
|
wn := vn + 1
|
|
else
|
|
wn := vn
|
|
end
|
|
end
|
|
target.count := wn
|
|
end
|
|
|
|
addmul (target: READABLE_INTEGER_X; op1: READABLE_INTEGER_X; op2: READABLE_INTEGER_X)
|
|
-- Set `rop' to `rop' + `op1' times `op2'.
|
|
do
|
|
aorsmul (target, op1, op2, 0)
|
|
end
|
|
|
|
addmul_ui (target: READABLE_INTEGER_X; op1: READABLE_INTEGER_X; op2: NATURAL)
|
|
-- Set `rop' to `rop' + `op1' times `op2'.
|
|
do
|
|
aorsmul_1 (target, op1, op2, 0)
|
|
end
|
|
|
|
submul (target: READABLE_INTEGER_X; op1: READABLE_INTEGER_X; op2: READABLE_INTEGER_X)
|
|
-- Set `rop' to `rop' - `op1' times `op2'.
|
|
do
|
|
aorsmul (target, op1, op2, -1)
|
|
end
|
|
|
|
submul_ui (target: READABLE_INTEGER_X; op1: READABLE_INTEGER_X; op2: NATURAL)
|
|
-- Set `rop' to `rop' - `op1' times `op2'.
|
|
do
|
|
aorsmul_1 (target, op1, op2, -1)
|
|
end
|
|
|
|
mul (target: READABLE_INTEGER_X; op1_a: READABLE_INTEGER_X; op2_a: READABLE_INTEGER_X)
|
|
-- Set `rop' to `op1' times `op2'.
|
|
local
|
|
usize: INTEGER
|
|
vsize: INTEGER
|
|
wsize: INTEGER
|
|
sign_product: INTEGER
|
|
vp: SPECIAL [NATURAL_32]
|
|
vp_offset: INTEGER
|
|
up: SPECIAL [NATURAL_32]
|
|
up_offset: INTEGER
|
|
wp: SPECIAL [NATURAL_32]
|
|
wp_offset: INTEGER
|
|
cy_limb: NATURAL_32
|
|
op_temp: READABLE_INTEGER_X
|
|
size_temp: INTEGER_32
|
|
op1: READABLE_INTEGER_X
|
|
op2: READABLE_INTEGER_X
|
|
carry: CELL [NATURAL_32]
|
|
do
|
|
create carry.put (0)
|
|
op1 := op1_a
|
|
op2 := op2_a
|
|
usize := op1.count
|
|
vsize := op2.count
|
|
sign_product := usize.bit_xor (vsize)
|
|
usize := usize.abs
|
|
vsize := vsize.abs
|
|
if usize = 0 or vsize = 0 then
|
|
target.count := 0
|
|
else
|
|
if vsize = 1 then
|
|
if usize + 1 > target.capacity then
|
|
target.resize (usize + 1)
|
|
end
|
|
wp := target.item
|
|
mul_1 (target.item, 0, op1.item, 0, usize, op2.item [0], carry)
|
|
cy_limb := carry.item
|
|
target.item [usize] := cy_limb
|
|
if cy_limb /= 0 then
|
|
usize := usize + 1
|
|
end
|
|
if sign_product >= 0 then
|
|
target.count := usize
|
|
else
|
|
target.count := -usize
|
|
end
|
|
else
|
|
wsize := usize + vsize
|
|
if wsize <= 32 and target /= op1 and target /= op2 then
|
|
target.resize (wsize)
|
|
wp := target.item
|
|
if usize > vsize then
|
|
mul_basecase (wp, 0, op1.item, 0, usize, op2.item, 0, vsize)
|
|
else
|
|
mul_basecase (wp, 0, op2.item, 0, vsize, op1.item, 0, usize)
|
|
end
|
|
wsize := wsize - (wp [wp_offset + wsize - 1] = 0).to_integer
|
|
if sign_product >= 0 then
|
|
target.count := wsize
|
|
else
|
|
target.count := -wsize
|
|
end
|
|
else
|
|
if usize < vsize then
|
|
op_temp := op1
|
|
op1 := op2
|
|
op2 := op_temp
|
|
size_temp := usize
|
|
usize := vsize
|
|
vsize := size_temp
|
|
end
|
|
up := op1.item
|
|
up_offset := 0
|
|
vp := op2.item
|
|
vp_offset := 0
|
|
wp := target.item
|
|
wp_offset := 0
|
|
if target.capacity < wsize then
|
|
create wp.make_filled (0, wsize)
|
|
target.item := wp
|
|
else
|
|
if wp = up then
|
|
create up.make_filled (0, usize)
|
|
if wp = vp then
|
|
vp := up
|
|
end
|
|
up.copy_data (wp, 0, 0, usize)
|
|
elseif wp = vp then
|
|
create vp.make_filled (0, vsize)
|
|
vp.copy_data (wp, 0, 0, vsize)
|
|
end
|
|
end
|
|
mul_special (wp, 0, up, 0, usize, vp, 0, vsize, carry)
|
|
cy_limb := carry.item
|
|
wsize := usize + vsize
|
|
wsize := wsize - (cy_limb = 0).to_integer
|
|
if sign_product < 0 then
|
|
target.count := -wsize
|
|
else
|
|
target.count := wsize
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
mul_2exp (target: READABLE_INTEGER_X; op1: READABLE_INTEGER_X; count_a: INTEGER)
|
|
local
|
|
usize: INTEGER
|
|
abs_usize: INTEGER
|
|
wsize: INTEGER
|
|
limb_count: INTEGER
|
|
wp: SPECIAL [NATURAL_32]
|
|
wp_offset: INTEGER
|
|
wlimb: NATURAL_32
|
|
count: INTEGER
|
|
carry: CELL [NATURAL_32]
|
|
do
|
|
create carry.put (0)
|
|
count := count_a
|
|
usize := op1.count
|
|
abs_usize := usize.abs
|
|
if usize = 0 then
|
|
target.count := 0
|
|
else
|
|
limb_count := count // limb_bits
|
|
wsize := abs_usize + limb_count + 1
|
|
target.resize (wsize)
|
|
wp := target.item
|
|
wsize := abs_usize + limb_count
|
|
count := count \\ limb_bits
|
|
if count /= 0 then
|
|
lshift (wp, wp_offset + limb_count, op1.item, 0, abs_usize, count, carry)
|
|
wlimb := carry.item
|
|
if wlimb /= 0 then
|
|
wp [wp_offset + wsize] := wlimb
|
|
wsize := wsize + 1
|
|
end
|
|
else
|
|
wp.copy_data (op1.item, 0, wp_offset + limb_count, abs_usize)
|
|
end
|
|
wp.fill_with (0, wp_offset, wp_offset + limb_count - 1)
|
|
if usize >= 0 then
|
|
target.count := wsize
|
|
else
|
|
target.count := -wsize
|
|
end
|
|
end
|
|
end
|
|
|
|
mul_si (target: READABLE_INTEGER_X; op1: READABLE_INTEGER_X; op2: INTEGER)
|
|
local
|
|
size: INTEGER
|
|
sign_product: INTEGER
|
|
sml: NATURAL_32
|
|
cy: NATURAL_32
|
|
pp: SPECIAL [NATURAL_32]
|
|
pp_offset: INTEGER
|
|
carry: CELL [NATURAL_32]
|
|
do
|
|
create carry.put (0)
|
|
size := op1.count
|
|
sign_product := size
|
|
if size = 0 or op2 = 0 then
|
|
target.count := 0
|
|
else
|
|
size := size.abs
|
|
sml := op2.abs.to_natural_32
|
|
target.resize (size + 1)
|
|
pp := target.item
|
|
mul_1 (pp, pp_offset, op1.item, 0, size, sml, carry)
|
|
cy := carry.item
|
|
pp [pp_offset + size] := cy
|
|
size := size + (cy /= 0).to_integer
|
|
end
|
|
if sign_product < 0 xor op2 < 0 then
|
|
target.count := -size
|
|
else
|
|
target.count := size
|
|
end
|
|
end
|
|
|
|
mul_ui (target: READABLE_INTEGER_X; op1: READABLE_INTEGER_X; op2: NATURAL_32)
|
|
local
|
|
size: INTEGER
|
|
sign_product: INTEGER
|
|
sml: NATURAL_32
|
|
cy: NATURAL_32
|
|
pp: SPECIAL [NATURAL_32]
|
|
pp_offset: INTEGER
|
|
carry: CELL [NATURAL_32]
|
|
do
|
|
create carry.put (0)
|
|
size := op1.count
|
|
sign_product := size
|
|
if size = 0 or op2 = 0 then
|
|
target.count := 0
|
|
else
|
|
size := size.abs
|
|
sml := op2
|
|
target.resize (size + 1)
|
|
pp := target.item
|
|
mul_1 (pp, pp_offset, op1.item, 0, size, sml, carry)
|
|
cy := carry.item
|
|
pp [pp_offset + size] := cy
|
|
size := size + (cy /= 0).to_integer
|
|
end
|
|
if sign_product < 0 xor op2 < 0 then
|
|
target.count := -size
|
|
else
|
|
target.count := size
|
|
end
|
|
end
|
|
|
|
neg (target: READABLE_INTEGER_X; op: READABLE_INTEGER_X)
|
|
-- Set `rop' to -`op'.
|
|
local
|
|
usize: INTEGER_32
|
|
size: INTEGER_32
|
|
do
|
|
usize := op.count
|
|
if target /= op then
|
|
size := usize.abs
|
|
target.resize (size)
|
|
target.item.copy_data (op.item, 0, 0, size)
|
|
end
|
|
target.count := -usize
|
|
end
|
|
|
|
abs (target: READABLE_INTEGER_X; op: READABLE_INTEGER_X)
|
|
-- Set `rop' to the absolute value of `op'.
|
|
local
|
|
size: INTEGER_32
|
|
do
|
|
size := op.count.abs
|
|
if op /= target then
|
|
target.resize (size)
|
|
target.item.copy_data (op.item, 0, 0, size)
|
|
end
|
|
target.count := size
|
|
end
|
|
end
|