1038 lines
27 KiB
Plaintext
1038 lines
27 KiB
Plaintext
note
|
|
description: "Summary description for {INTEGER_X_LOGIC}."
|
|
author: "Colin LeMahieu"
|
|
date: "$Date$"
|
|
revision: "$Revision$"
|
|
quote: "The politicians don't just want your money. They want your soul. They want you to be worn down by taxes until you are dependent and helpless. - James Dale Davidson, National Taxpayers Union"
|
|
|
|
deferred class
|
|
INTEGER_X_LOGIC
|
|
|
|
inherit
|
|
INTEGER_X_FACILITIES
|
|
SPECIAL_ARITHMETIC
|
|
rename
|
|
bit_xor_lshift as bit_xor_lshift_special,
|
|
bit_xor as bit_xor_special
|
|
end
|
|
SPECIAL_UTILITY
|
|
|
|
feature
|
|
|
|
bit_and (target: READABLE_INTEGER_X; op1_a: READABLE_INTEGER_X; op2_a: READABLE_INTEGER_X)
|
|
local
|
|
op1_ptr: SPECIAL [NATURAL_32]
|
|
op1_ptr_offset: INTEGER
|
|
op2_ptr: SPECIAL [NATURAL_32]
|
|
op2_ptr_offset: INTEGER
|
|
op1_size: INTEGER
|
|
op2_size: INTEGER
|
|
res_ptr: SPECIAL [NATURAL_32]
|
|
res_ptr_offset: INTEGER
|
|
res_size: INTEGER
|
|
i: INTEGER
|
|
junk: NATURAL_32
|
|
done: BOOLEAN
|
|
opx: SPECIAL [NATURAL_32]
|
|
opx_offset: INTEGER
|
|
cy: NATURAL_32
|
|
res_alloc: INTEGER
|
|
tmp_special: SPECIAL [NATURAL_32]
|
|
tmp_integer: INTEGER
|
|
tmp_integer_x: READABLE_INTEGER_X
|
|
op1: READABLE_INTEGER_X
|
|
op2: READABLE_INTEGER_X
|
|
carry: CELL [NATURAL_32]
|
|
do
|
|
create carry.put (0)
|
|
op1 := op1_a
|
|
op2 := op2_a
|
|
op1_size := op1.count
|
|
op2_size := op2.count
|
|
op1_ptr := op1.item
|
|
op2_ptr := op2.item
|
|
res_ptr := target.item
|
|
if op1_size >= 0 then
|
|
if op2_size >= 0 then
|
|
res_size := op1_size.min (op2_size)
|
|
from
|
|
i := res_size - 1
|
|
until
|
|
i < 0 or else op1_ptr [op1_ptr_offset + i].bit_and (op2_ptr [op2_ptr_offset + i]) /= 0
|
|
loop
|
|
i := i - 1
|
|
end
|
|
res_size := i + 1
|
|
target.resize (res_size)
|
|
res_ptr := target.item
|
|
op1_ptr := op1.item
|
|
op2_ptr := op2.item
|
|
target.count := res_size
|
|
if res_size /= 0 then
|
|
add_n (res_ptr, res_ptr_offset, op1_ptr, op1_ptr_offset, op2_ptr, op2_ptr_offset, res_size, carry)
|
|
junk := carry.item
|
|
end
|
|
done := True
|
|
end
|
|
else
|
|
if op2_size < 0 then
|
|
op1_size := -op1_size
|
|
op2_size := -op2_size
|
|
res_alloc := 1 + op1_size.max (op2_size)
|
|
create opx.make_filled (0, op1_size)
|
|
sub_1 (opx, opx_offset, op1_ptr, op1_ptr_offset, op1_size, 1, carry)
|
|
junk := carry.item
|
|
op1_ptr := opx
|
|
create opx.make_filled (0, op2_size)
|
|
sub_1 (opx, opx_offset, op2_ptr, op2_ptr_offset, op2_size, 1, carry)
|
|
junk := carry.item
|
|
op2_ptr := opx
|
|
target.resize (res_alloc)
|
|
res_ptr := target.item
|
|
if op1_size >= op2_size then
|
|
res_ptr.copy_data (op1_ptr, op1_ptr_offset + op2_size, res_ptr_offset + op2_size, op1_size - op2_size)
|
|
from
|
|
i := op2_size - 1
|
|
until
|
|
i < 0
|
|
loop
|
|
res_ptr [res_ptr_offset + i] := op1_ptr [op1_ptr_offset + i].bit_or (op2_ptr [op2_ptr_offset + i])
|
|
i := i - 1
|
|
end
|
|
res_size := op1_size
|
|
else
|
|
res_ptr.copy_data (op2_ptr, op2_ptr_offset + op1_size, res_ptr_offset + op1_size, op2_size - op1_size)
|
|
from
|
|
i := op1_size - 1
|
|
until
|
|
i < 0
|
|
loop
|
|
res_ptr [res_ptr_offset + i] := op1_ptr [op1_ptr_offset + i].bit_or (op2_ptr [op2_ptr_offset + i])
|
|
i := i - 1
|
|
end
|
|
res_size := op2_size
|
|
end
|
|
add_1 (res_ptr, res_ptr_offset, res_ptr, res_ptr_offset, res_size, 1, carry)
|
|
cy := carry.item
|
|
if cy /= 0 then
|
|
res_ptr [res_ptr_offset + res_size] := cy
|
|
res_size := res_size + 1
|
|
end
|
|
target.count := -res_size
|
|
done := True
|
|
else
|
|
tmp_integer_x := op1
|
|
op1 := op2
|
|
op2 := tmp_integer_x
|
|
tmp_special := op1_ptr
|
|
op1_ptr := op2_ptr
|
|
op2_ptr := tmp_special
|
|
tmp_integer := op1_ptr_offset
|
|
op1_ptr_offset := op2_ptr_offset
|
|
op2_ptr_offset := tmp_integer
|
|
end
|
|
end
|
|
if not done then
|
|
op2_size := -op2_size
|
|
create opx.make_filled (0, op2_size)
|
|
sub_1 (opx, opx_offset, op2_ptr, op2_ptr_offset, op2_size, 1, carry)
|
|
junk := carry.item
|
|
op2_ptr := opx
|
|
if op1_size > op2_size then
|
|
res_size := op1_size
|
|
target.resize (res_size)
|
|
res_ptr := target.item
|
|
op1_ptr := op1.item
|
|
res_ptr.copy_data (op1_ptr, op1_ptr_offset + op2_size, res_ptr_offset + op2_size, res_size - op2_size)
|
|
from
|
|
i := op2_size - 1
|
|
until
|
|
i < 0
|
|
loop
|
|
res_ptr [res_ptr_offset + i] := op1_ptr [op1_ptr_offset + i].bit_and (op2_ptr [op2_ptr_offset + i].bit_not)
|
|
i := i - 1
|
|
end
|
|
target.count := res_size
|
|
else
|
|
from
|
|
i := op1_size - 1
|
|
until
|
|
i < 0 or else op1_ptr [op1_ptr_offset + i].bit_and (op2_ptr [op2_ptr_offset + i].bit_not) /= 0
|
|
loop
|
|
i := i - 1
|
|
end
|
|
res_size := i + 1
|
|
target.resize (res_size)
|
|
res_ptr := target.item
|
|
op1_ptr := op1.item
|
|
from
|
|
i := res_size - 1
|
|
until
|
|
i < 0
|
|
loop
|
|
res_ptr [res_ptr_offset + i] := op1_ptr [op1_ptr_offset + i].bit_and (op2_ptr [op2_ptr_offset + i].bit_not)
|
|
i := i - 1
|
|
end
|
|
target.count := res_size
|
|
end
|
|
end
|
|
end
|
|
|
|
bit_clear (op: READABLE_INTEGER_X; bit_index: INTEGER_32)
|
|
-- Clear bit `bit_index' in `rop'.
|
|
local
|
|
dsize: INTEGER_32
|
|
dp: SPECIAL [NATURAL_32]
|
|
dp_offset: INTEGER
|
|
limb_index: INTEGER
|
|
dlimb: NATURAL_32
|
|
zero_bound: INTEGER
|
|
i: INTEGER_32
|
|
done: BOOLEAN
|
|
do
|
|
dsize := op.count
|
|
dp := op.item
|
|
limb_index := bit_index // limb_bits
|
|
if dsize >= 0 then
|
|
if limb_index < dsize then
|
|
dlimb := dp [dp_offset + limb_index]
|
|
dlimb := dlimb.bit_and (((1) |<< (bit_index \\ limb_bits)).bit_not.to_natural_32)
|
|
dp [dp_offset + limb_index] := dlimb
|
|
if dlimb = 0 and limb_index = dsize - 1 then
|
|
from
|
|
dsize := dsize - 1
|
|
until
|
|
dsize <= 0 or dp [dp_offset + dsize - 1] /= 0
|
|
loop
|
|
dsize := dsize - 1
|
|
end
|
|
op.count := dsize
|
|
end
|
|
end
|
|
else
|
|
dsize := -dsize
|
|
from
|
|
zero_bound := 0
|
|
until
|
|
dp [dp_offset + zero_bound] /= 0
|
|
loop
|
|
zero_bound := zero_bound + 1
|
|
end
|
|
if limb_index > zero_bound then
|
|
if limb_index < dsize then
|
|
dp [dp_offset + limb_index] := dp [dp_offset + limb_index].bit_or (((1) |<< (bit_index \\ limb_bits)).to_natural_32)
|
|
else
|
|
op.resize (limb_index + 1)
|
|
dp := op.item
|
|
dp.fill_with (0, dp_offset + dsize, dp_offset + dsize + (limb_index - dsize) - 1)
|
|
dp [dp_offset + limb_index] := ((1) |<< (bit_index \\ (limb_bits))).to_natural_32
|
|
op.count := - (limb_index + 1)
|
|
end
|
|
elseif limb_index = zero_bound then
|
|
dp [dp_offset + limb_index] := (dp [dp_offset + limb_index] - 1).bit_or (((1) |<< (bit_index \\ limb_bits)).to_natural_32)
|
|
if dp [dp_offset + limb_index] = 0 then
|
|
from
|
|
i := limb_index + 1
|
|
until
|
|
i >= dsize or done
|
|
loop
|
|
dp [dp_offset + 1] := dp [dp_offset + 1] + 1
|
|
if dp [dp_offset + i] = 0 then
|
|
done := True
|
|
else
|
|
i := i + 1
|
|
end
|
|
end
|
|
if not done then
|
|
dsize := dsize + 1
|
|
op.resize (dsize)
|
|
dp [dp_offset + i] := 1
|
|
op.count := -dsize
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
bit_one_complement (target: READABLE_INTEGER_X; op: READABLE_INTEGER_X)
|
|
-- Set `rop' to the one's complement of `op'.
|
|
local
|
|
src: READABLE_INTEGER_X
|
|
size: INTEGER_32
|
|
cy: NATURAL_32
|
|
junk2: NATURAL_32
|
|
carry: CELL [NATURAL_32]
|
|
do
|
|
create carry.put (0)
|
|
src := op
|
|
size := src.count
|
|
if size >= 0 then
|
|
target.resize (size + 1)
|
|
if size = 0 then
|
|
target.item [0] := 1
|
|
target.count := -1
|
|
else
|
|
add_1 (target.item, 0, src.item, 0, size, 1, carry)
|
|
cy := carry.item
|
|
if cy /= 0 then
|
|
target.item [size] := cy
|
|
size := size + 1
|
|
end
|
|
target.count := -size
|
|
end
|
|
else
|
|
size := -size
|
|
target.resize (size)
|
|
sub_1 (target.item, 0, src.item, 0, size, 1, carry)
|
|
junk2 := carry.item
|
|
if target.item [size - 1] = 0 then
|
|
size := size - 1
|
|
end
|
|
target.count := size
|
|
end
|
|
end
|
|
|
|
bit_complement (d: READABLE_INTEGER_X; bit_index: INTEGER_32)
|
|
local
|
|
dsize: INTEGER
|
|
dp: SPECIAL [NATURAL_32]
|
|
limb_index: INTEGER
|
|
bit_l: NATURAL_32
|
|
x: NATURAL_32
|
|
i: INTEGER
|
|
c: NATURAL_32
|
|
junk: NATURAL_32
|
|
carry: CELL [NATURAL_32]
|
|
do
|
|
create carry.put (0)
|
|
dsize := d.count.abs
|
|
dp := d.item
|
|
limb_index := bit_index // limb_bits
|
|
bit_l := (1).to_natural_32 |<< (bit_index \\ limb_bits)
|
|
if limb_index >= dsize then
|
|
d.resize (limb_index + 1)
|
|
dp := d.item
|
|
dsize := limb_index + 1
|
|
end
|
|
if d.count >= 0 then
|
|
dp [limb_index] := dp [limb_index].bit_xor (bit_l)
|
|
dsize := normalize (dp, 0, dsize)
|
|
d.count := dsize
|
|
else
|
|
x := 0 - dp [limb_index]
|
|
from
|
|
i := limb_index - 1
|
|
until
|
|
i < 0
|
|
loop
|
|
if dp [i] /= 0 then
|
|
x := x - 1
|
|
i := 0
|
|
end
|
|
i := i - 1
|
|
end
|
|
if x.bit_and (bit_l) /= 0 then
|
|
d.resize (dsize + 1)
|
|
dp := d.item
|
|
add_1 (dp, limb_index, dp, limb_index, dsize - limb_index, bit_l, carry)
|
|
c := carry.item
|
|
dp [dsize] := c
|
|
dsize := dsize + c.to_integer_32
|
|
else
|
|
sub_1 (dp, limb_index, dp, limb_index, dsize + limb_index, bit_l, carry)
|
|
junk := carry.item
|
|
dsize := normalize (dp, 0, dsize)
|
|
d.count := -dsize
|
|
end
|
|
end
|
|
end
|
|
|
|
bit_or (res: READABLE_INTEGER_X; op1_a: READABLE_INTEGER_X; op2_a: READABLE_INTEGER_X)
|
|
local
|
|
op1_ptr: SPECIAL [NATURAL_32]
|
|
op1_ptr_offset: INTEGER
|
|
op2_ptr: SPECIAL [NATURAL_32]
|
|
op2_ptr_offset: INTEGER
|
|
op1_size: INTEGER
|
|
op2_size: INTEGER
|
|
res_ptr: SPECIAL [NATURAL_32]
|
|
res_ptr_offset: INTEGER
|
|
res_size: INTEGER
|
|
i: INTEGER
|
|
done: BOOLEAN
|
|
opx: SPECIAL [NATURAL_32]
|
|
opx_offset: INTEGER
|
|
cy: NATURAL_32
|
|
junk: NATURAL_32
|
|
tmp_special: SPECIAL [NATURAL_32]
|
|
tmp_integer: INTEGER
|
|
tmp_integer_x: READABLE_INTEGER_X
|
|
op1: READABLE_INTEGER_X
|
|
op2: READABLE_INTEGER_X
|
|
res_alloc: INTEGER
|
|
count: INTEGER
|
|
carry: CELL [NATURAL_32]
|
|
do
|
|
create carry.put (0)
|
|
op1 := op1_a
|
|
op2 := op2_a
|
|
op1_size := op1.count
|
|
op2_size := op2.count
|
|
op1_ptr := op1.item
|
|
op2_ptr := op2.item
|
|
res_ptr := res.item
|
|
if op1_size >= 0 then
|
|
if op2_size >= 0 then
|
|
if op1_size >= op2_size then
|
|
res.resize (op1_size)
|
|
op1_ptr := op1.item
|
|
op2_ptr := op2.item
|
|
res_ptr := res.item
|
|
if res_ptr /= op1_ptr then
|
|
res_ptr.copy_data (op1_ptr, op1_ptr_offset + op2_size, res_ptr_offset + op2_size, op1_size - op2_size)
|
|
end
|
|
from
|
|
i := op2_size - 1
|
|
until
|
|
i < 0
|
|
loop
|
|
res_ptr [res_ptr_offset + i] := op1_ptr [op1_ptr_offset + i].bit_or (op2_ptr [op2_ptr_offset + i])
|
|
i := i - 1
|
|
end
|
|
res_size := op1_size
|
|
else
|
|
res.resize (op2_size)
|
|
op1_ptr := op1.item
|
|
op2_ptr := op2.item
|
|
res_ptr := res.item
|
|
if res_ptr /= op2_ptr then
|
|
res_ptr.copy_data (op2_ptr, op2_ptr_offset + op1_size, res_ptr_offset + op1_size, op2_size - op1_size)
|
|
end
|
|
from
|
|
i := op1_size - 1
|
|
until
|
|
i < 0
|
|
loop
|
|
res_ptr [res_ptr_offset + i] := op1_ptr [op1_ptr_offset + i].bit_or (op2_ptr [op2_ptr_offset + i])
|
|
i := i - 1
|
|
end
|
|
end
|
|
res_size := op2_size
|
|
done := True
|
|
end
|
|
else
|
|
if op2_size < 0 then
|
|
op1_size := -op1_size
|
|
op2_size := -op2_size
|
|
res_size := op1_size.min (op2_size)
|
|
create opx.make_filled (0, res_size)
|
|
sub_1 (opx, opx_offset, op1_ptr, op1_ptr_offset, res_size, 1, carry)
|
|
junk := carry.item
|
|
op1_ptr := opx
|
|
create opx.make_filled (0, res_size)
|
|
sub_1 (opx, opx_offset, op2_ptr, op2_ptr_offset, res_size, 1, carry)
|
|
junk := carry.item
|
|
op2_ptr := opx
|
|
res.resize (res_size)
|
|
res_ptr := res.item
|
|
from
|
|
i := res_size - 1
|
|
until
|
|
i < 0 or else op1_ptr [op1_ptr_offset + i].bit_and (op2_ptr [op2_ptr_offset + i]) /= 0
|
|
loop
|
|
i := i - 1
|
|
end
|
|
res_size := i + 1
|
|
if res_size /= 0 then
|
|
from
|
|
i := res_size - 1
|
|
until
|
|
i < 0
|
|
loop
|
|
res_ptr [res_ptr_offset + i] := op1_ptr [op1_ptr_offset + i].bit_and (op2_ptr [op2_ptr_offset + i])
|
|
i := i - 1
|
|
end
|
|
add_1 (res_ptr, res_ptr_offset, res_ptr, res_ptr_offset, res_size, 1, carry)
|
|
cy := carry.item
|
|
if cy /= 0 then
|
|
res_ptr [res_ptr_offset + res_size] := cy
|
|
res_size := res_size + 1
|
|
end
|
|
else
|
|
res_ptr [res_ptr_offset] := 1
|
|
res_size := 1
|
|
end
|
|
res.count := -res_size
|
|
done := True
|
|
else
|
|
tmp_integer_x := op1
|
|
op1 := op2
|
|
op2 := tmp_integer_x
|
|
tmp_special := op1_ptr
|
|
op1_ptr := op2_ptr
|
|
op2_ptr := tmp_special
|
|
tmp_integer := op1_ptr_offset
|
|
op1_ptr_offset := op2_ptr_offset
|
|
op2_ptr_offset := tmp_integer
|
|
end
|
|
end
|
|
if not done then
|
|
op2_size := -op2_size
|
|
res_alloc := op2_size
|
|
create opx.make_filled (0, op2_size)
|
|
sub_1 (opx, opx_offset, op2_ptr, op2_ptr_offset, op2_size, 1, carry)
|
|
junk := carry.item
|
|
op2_ptr := opx
|
|
op2_size := op2_size - (op2_ptr [op2_ptr_offset + op2_size - 1] = 0).to_integer
|
|
res.resize (res_alloc)
|
|
op1_ptr := op1.item
|
|
res_ptr := res.item
|
|
if op1_size >= op2_size then
|
|
from
|
|
i := op2_size - 1
|
|
until
|
|
i < 0 or else op1_ptr [op1_ptr_offset + i].bit_not.bit_and (op2_ptr [op2_ptr_offset + i]) /= 0
|
|
loop
|
|
i := i - 1
|
|
end
|
|
res_size := i + 1
|
|
count := res_size
|
|
else
|
|
res_size := op2_size
|
|
res_ptr.copy_data (op2_ptr, op2_ptr_offset + op1_size, res_ptr_offset + op1_size, op2_size - op1_size)
|
|
count := op1_size
|
|
end
|
|
if res_size /= 0 then
|
|
from
|
|
i := count - 1
|
|
until
|
|
i < 0
|
|
loop
|
|
res_ptr [res_ptr_offset + i] := op1_ptr [op1_ptr_offset + i].bit_not.bit_and (op2_ptr [op2_ptr_offset + i])
|
|
i := i - 1
|
|
end
|
|
add_1 (res_ptr, res_ptr_offset, res_ptr, res_ptr_offset, res_size, 1, carry)
|
|
cy := carry.item
|
|
if cy /= 0 then
|
|
res_ptr [res_ptr_offset + res_size] := cy
|
|
res_size := res_size + 1
|
|
else
|
|
res_ptr [res_ptr_offset] := 1
|
|
res_size := 1
|
|
end
|
|
res.count := -res_size
|
|
end
|
|
end
|
|
end
|
|
|
|
bit_scan_0 (op: READABLE_INTEGER_X; starting_bit: INTEGER_32): INTEGER
|
|
-- Scan `op', starting from bit `starting_bit', towards more significant bits, until the first 0
|
|
-- bit is found.
|
|
-- Return the index of the found bit.
|
|
-- The least significant bit is number 0.
|
|
-- If the bit at `starting_bit' is already what's sought, then `starting_bit' is returned.
|
|
-- If there's no bit found, then ULONG_MAX is returned.
|
|
-- This will happen past the end of a negative number.
|
|
local
|
|
u_ptr: INTEGER_32
|
|
size: INTEGER_32
|
|
abs_size: INTEGER_32
|
|
u_end: INTEGER_32
|
|
starting_limb: INTEGER_32
|
|
p: INTEGER_32
|
|
limb: NATURAL_32
|
|
cnt: INTEGER_32
|
|
done: BOOLEAN
|
|
q: INTEGER_32
|
|
do
|
|
size := op.count
|
|
abs_size := size.abs
|
|
u_end := abs_size
|
|
starting_limb := starting_bit // (4 |<< 3)
|
|
p := starting_limb
|
|
if starting_limb >= abs_size then
|
|
if size >= 0 then
|
|
Result := starting_bit
|
|
else
|
|
Result := Result.max_value
|
|
end
|
|
else
|
|
limb := op.item [p]
|
|
if size >= 0 then
|
|
limb := limb.bit_or (((1) |<< (starting_bit \\ (4 |<< 3))).to_natural_32)
|
|
from
|
|
until
|
|
limb /= (0).to_natural_32.bit_not or done
|
|
loop
|
|
p := p + 1
|
|
if p = u_end then
|
|
done := true
|
|
Result := (abs_size * 4 |<< 3)
|
|
else
|
|
limb := op.item [p]
|
|
end
|
|
end
|
|
if not done then
|
|
limb := limb.bit_not
|
|
end
|
|
else
|
|
q := p
|
|
from
|
|
until
|
|
q = u_ptr or done
|
|
loop
|
|
q := q - 1
|
|
if op.item [q] /= 0 then
|
|
done := true
|
|
end
|
|
end
|
|
if not done then
|
|
limb := limb - 1
|
|
end
|
|
limb := limb.bit_and (((0).to_natural_32.bit_not |<< (starting_bit \\ (4 |<< 3))))
|
|
if limb = 0 then
|
|
p := p + 1
|
|
if p = u_end then
|
|
Result := Result.max_value
|
|
else
|
|
from
|
|
limb := op.item [p]
|
|
until
|
|
limb /= 0
|
|
loop
|
|
p := p + 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
cnt := trailing_zeros (op.item [limb.to_integer_32])
|
|
Result := p - u_ptr + cnt
|
|
end
|
|
end
|
|
|
|
bit_scan_1 (op1: READABLE_INTEGER_X; starting_bit: INTEGER): INTEGER
|
|
local
|
|
u_ptr: SPECIAL [NATURAL_32]
|
|
u_ptr_offset: INTEGER
|
|
size: INTEGER
|
|
abs_size: INTEGER
|
|
u_end: INTEGER
|
|
starting_limb: INTEGER
|
|
p: INTEGER
|
|
limb: NATURAL_32
|
|
count: INTEGER
|
|
q: INTEGER
|
|
inverted: NATURAL_32
|
|
got_limb: BOOLEAN
|
|
do
|
|
u_ptr := op1.item
|
|
size := op1.count
|
|
abs_size := size.abs
|
|
u_end := u_ptr_offset + abs_size
|
|
starting_limb := starting_bit // limb_bits
|
|
p := u_ptr_offset + starting_limb
|
|
if starting_limb >= abs_size then
|
|
if size >= 0 then
|
|
Result := Result.max_value
|
|
else
|
|
Result := starting_bit
|
|
end
|
|
end
|
|
limb := u_ptr [p]
|
|
if size >= 0 and limb.bit_and (limb.max_value |<< (starting_bit \\ limb_bits)) = 0 and p + 1 = u_end then
|
|
Result := Result.max_value
|
|
else
|
|
if size >= 0 then
|
|
limb := limb.bit_and (limb.max_value |<< (starting_bit \\ limb_bits))
|
|
if limb = 0 then
|
|
p := p + 1
|
|
from
|
|
limb := u_ptr [p]
|
|
p := p + 1
|
|
until
|
|
limb /= 0
|
|
loop
|
|
limb := u_ptr [p]
|
|
p := p + 1
|
|
end
|
|
end
|
|
else
|
|
q := p
|
|
from
|
|
inverted := 0
|
|
until
|
|
q = u_ptr_offset or inverted /= 0
|
|
loop
|
|
q := q - 1
|
|
inverted := u_ptr [q]
|
|
end
|
|
if inverted = 0 then
|
|
if limb = 0 then
|
|
from
|
|
limb := 1
|
|
until
|
|
limb = 0
|
|
loop
|
|
p := p + 1
|
|
limb := u_ptr [p]
|
|
end
|
|
limb := 0 - limb
|
|
got_limb := True
|
|
else
|
|
limb := limb - 1
|
|
end
|
|
end
|
|
if not got_limb then
|
|
limb := limb.bit_or ((1).to_natural_32 |<< (starting_bit \\ limb_bits) - 1)
|
|
from
|
|
limb := 0
|
|
p := p + 1
|
|
if p /= u_end then
|
|
limb := u_ptr [p]
|
|
end
|
|
until
|
|
p = u_end or limb = limb.max_value
|
|
loop
|
|
p := p + 1
|
|
if p /= u_end then
|
|
limb := u_ptr [p]
|
|
end
|
|
end
|
|
if p = u_end then
|
|
Result := abs_size * limb_bits
|
|
else
|
|
limb := limb.bit_not
|
|
count := trailing_zeros (limb)
|
|
Result := (p - u_ptr_offset) * limb_bits + count
|
|
end
|
|
else
|
|
count := trailing_zeros (limb)
|
|
Result := (p - u_ptr_offset) * limb_bits + count
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
bit_set (op: READABLE_INTEGER_X; bit_index: INTEGER_32)
|
|
-- Set bit `bit_index' in `rop'.
|
|
local
|
|
dsize: INTEGER_32
|
|
dp: INTEGER_32
|
|
limb_index: INTEGER_32
|
|
dst: INTEGER_32
|
|
n: INTEGER_32
|
|
zero_bound: INTEGER_32
|
|
dlimb: NATURAL_32
|
|
i: INTEGER_32
|
|
done: BOOLEAN
|
|
x: NATURAL_32
|
|
p: INTEGER_32
|
|
last_p: NATURAL_32
|
|
do
|
|
dsize := op.count
|
|
dp := 0
|
|
limb_index := bit_index // limb_bits
|
|
if dsize >= 0 then
|
|
if limb_index < dsize then
|
|
op.item [dp + limb_index] := op.item [dp + limb_index].bit_or ((1).to_natural_32 |<< (bit_index \\ limb_bits))
|
|
op.count := dsize
|
|
else
|
|
op.resize (limb_index + 1)
|
|
if limb_index - dsize /= 0 then
|
|
dst := dp + dsize
|
|
n := limb_index - dsize
|
|
from
|
|
op.item [dst] := 0
|
|
dst := dst + 1
|
|
n := n - 1
|
|
until
|
|
n = 0
|
|
loop
|
|
op.item [dst] := 0
|
|
dst := dst + 1
|
|
n := n - 1
|
|
end
|
|
end
|
|
op.item [dp + limb_index] := ((1) |<< (bit_index \\ limb_bits)).to_natural_32
|
|
op.count := limb_index + 1
|
|
end
|
|
else
|
|
dsize := -dsize
|
|
from
|
|
zero_bound := 0
|
|
until
|
|
op.item [dp + zero_bound] /= 0
|
|
loop
|
|
zero_bound := zero_bound + 1
|
|
end
|
|
if limb_index > zero_bound then
|
|
if limb_index < dsize then
|
|
dlimb := op.item [dp + limb_index]
|
|
dlimb := dlimb.bit_and (((1) |<< (bit_index \\ limb_bits)).bit_not.to_natural_32)
|
|
op.item [dp + limb_index] := dlimb
|
|
if dlimb = 0 and limb_index = dsize - 1 then
|
|
from
|
|
dsize := dsize - 1
|
|
until
|
|
dsize <= 0 or op.item [dp + dsize - 1] /= 0
|
|
loop
|
|
dsize := dsize - 1
|
|
end
|
|
op.count := -dsize
|
|
end
|
|
end
|
|
elseif limb_index = zero_bound then
|
|
op.item [dp + limb_index] := (op.item [dp + limb_index] - 1).bit_and (((1).to_natural_32 |<< (bit_index \\ limb_bits)).bit_not) - 1
|
|
if op.item [dp + limb_index] = 0 then
|
|
from
|
|
i := limb_index + 1
|
|
until
|
|
i >= dsize or done
|
|
loop
|
|
op.item [dp + i] := op.item [dp + i] + 1
|
|
if op.item [dp + i] /= 0 then
|
|
done := true
|
|
else
|
|
i := i + 1
|
|
end
|
|
end
|
|
if not done then
|
|
dsize := dsize + 1
|
|
op.resize (dsize)
|
|
op.item [dp + i] := 1
|
|
op.count := -dsize
|
|
end
|
|
end
|
|
else
|
|
p := dp + limb_index
|
|
x := op.item [p]
|
|
op.item [p] := x - ((1) |<< (bit_index \\ limb_bits)).to_natural_32
|
|
if x < ((1) |<< (bit_index \\ limb_bits)).to_natural_32 then
|
|
from
|
|
p := p + 1
|
|
last_p := op.item [p]
|
|
op.item [p] := last_p - 1
|
|
until
|
|
last_p = 0
|
|
loop
|
|
p := p + 1
|
|
last_p := op.item [p]
|
|
op.item [p] := last_p - 1
|
|
end
|
|
end
|
|
if op.item [dp + dsize - 1] = 0 then
|
|
dsize := dsize - 1
|
|
end
|
|
op.count := -dsize
|
|
end
|
|
end
|
|
end
|
|
|
|
bit_test (op: READABLE_INTEGER_X; bit_index: INTEGER): BOOLEAN
|
|
local
|
|
u_ptr: SPECIAL [NATURAL_32]
|
|
size: INTEGER
|
|
abs_size: INTEGER
|
|
limb_index: INTEGER
|
|
p_offset: INTEGER
|
|
limb: NATURAL_32
|
|
do
|
|
u_ptr := op.item
|
|
size := op.count
|
|
abs_size := size.abs
|
|
limb_index := bit_index // limb_bits
|
|
p_offset := 0 + limb_index
|
|
if limb_index >= abs_size then
|
|
Result := size < 0
|
|
else
|
|
limb := u_ptr [p_offset]
|
|
if size < 0 then
|
|
limb := 0 - limb
|
|
from
|
|
until
|
|
p_offset = 0
|
|
loop
|
|
p_offset := p_offset - 1
|
|
if u_ptr [p_offset] /= 0 then
|
|
limb := limb - 1
|
|
p_offset := 0
|
|
end
|
|
end
|
|
end
|
|
Result := limb.bit_test (bit_index \\ limb_bits)
|
|
end
|
|
end
|
|
|
|
bit_xor (res: READABLE_INTEGER_X; op1_a: READABLE_INTEGER_X op2_a: READABLE_INTEGER_X)
|
|
local
|
|
op1_ptr: SPECIAL [NATURAL_32]
|
|
op1_ptr_offset: INTEGER
|
|
op2_ptr: SPECIAL [NATURAL_32]
|
|
op2_ptr_offset: INTEGER
|
|
op1_size: INTEGER
|
|
op2_size: INTEGER
|
|
res_ptr: SPECIAL [NATURAL_32]
|
|
res_ptr_offset: INTEGER
|
|
res_size: INTEGER
|
|
res_alloc: INTEGER
|
|
i: INTEGER
|
|
opx: SPECIAL [NATURAL_32]
|
|
opx_offset: INTEGER
|
|
junk: NATURAL_32
|
|
done: BOOLEAN
|
|
tmp_special: SPECIAL [NATURAL_32]
|
|
tmp_integer: INTEGER
|
|
tmp_integer_x: READABLE_INTEGER_X
|
|
op1: READABLE_INTEGER_X
|
|
op2: READABLE_INTEGER_X
|
|
cy: NATURAL_32
|
|
carry: CELL [NATURAL_32]
|
|
do
|
|
create carry.put (0)
|
|
op1 := op1_a
|
|
op2 := op2_a
|
|
op1_size := op1.count
|
|
op2_size := op2.count
|
|
op1_ptr := op1.item
|
|
op2_ptr := op2.item
|
|
res_ptr := res.item
|
|
if op1_size >= 0 then
|
|
if op2_size >= 0 then
|
|
res_size := op1_size.max (op2_size)
|
|
res.resize (res_size)
|
|
res_ptr := res.item
|
|
op1_ptr := op1.item
|
|
op2_ptr := op2.item
|
|
bit_xor_special (res_ptr, 0, op1_ptr, 0, op1_size, op2_ptr, 0, op2_size)
|
|
res_size := normalize (res_ptr, res_ptr_offset, res_size)
|
|
res.count := res_size
|
|
done := True
|
|
end
|
|
else
|
|
if op2_size < 0 then
|
|
op1_size := -op1_size
|
|
op2_size := -op2_size
|
|
create opx.make_filled (0, op1_size)
|
|
sub_1 (opx, opx_offset, op1_ptr, op1_ptr_offset, op1_size, 1, carry)
|
|
junk := carry.item
|
|
op1_ptr := opx
|
|
op1_ptr_offset := opx_offset
|
|
create opx.make_filled (0, op2_size)
|
|
sub_1 (opx, opx_offset, op2_ptr, op2_ptr_offset, op2_size, 1, carry)
|
|
junk := carry.item
|
|
op2_ptr := opx
|
|
op2_ptr_offset := opx_offset
|
|
res_alloc := op1_size.max (op2_size)
|
|
res.resize (res_alloc)
|
|
res_ptr := res.item
|
|
if op1_size > op2_size then
|
|
res_ptr.copy_data (op1_ptr, op1_ptr_offset + op2_size, res_ptr_offset + op2_size, op1_size - op2_size)
|
|
from
|
|
i := op2_size - 1
|
|
until
|
|
i < 0
|
|
loop
|
|
res_ptr [res_ptr_offset + i] := op1_ptr [op1_ptr_offset + i].bit_xor (op2_ptr [op2_ptr_offset + i])
|
|
i := i - 1
|
|
end
|
|
res_size := op1_size
|
|
else
|
|
res_ptr.copy_data (op2_ptr, op2_ptr_offset + op1_size, res_ptr_offset + op1_size, op2_size - op1_size)
|
|
from
|
|
i := op1_size - 1
|
|
until
|
|
i < 0
|
|
loop
|
|
res_ptr [res_ptr_offset + i] := op1_ptr [op1_ptr_offset + i].bit_xor (op2_ptr [op2_ptr_offset + i])
|
|
i := i - 1
|
|
end
|
|
res_size := op2_size
|
|
end
|
|
res_size := normalize (res_ptr, res_ptr_offset, res_size)
|
|
res.count := res_size
|
|
done := True
|
|
else
|
|
tmp_integer_x := op1
|
|
op1 := op2
|
|
op2 := tmp_integer_x
|
|
tmp_special := op1_ptr
|
|
op1_ptr := op2_ptr
|
|
op2_ptr := tmp_special
|
|
tmp_integer := op1_ptr_offset
|
|
op1_ptr_offset := op2_ptr_offset
|
|
op2_ptr_offset := tmp_integer
|
|
tmp_integer := op1_size
|
|
op1_size := op2_size
|
|
op2_size := tmp_integer
|
|
end
|
|
end
|
|
if not done then
|
|
op2_size := -op2_size
|
|
create opx.make_filled (0, op2_size)
|
|
sub_1 (opx, opx_offset, op2_ptr, op2_ptr_offset, op2_size, 1, carry)
|
|
junk := carry.item
|
|
op2_ptr := opx
|
|
op2_ptr_offset := opx_offset
|
|
res_alloc := op1_size.max (op2_size) + 1
|
|
res.resize (res_alloc)
|
|
res_ptr := res.item
|
|
if op1_size > op2_size then
|
|
res_ptr.copy_data (op1_ptr, op1_ptr_offset + op2_size, res_ptr_offset + op2_size, op1_size - op2_size)
|
|
from
|
|
i := op2_size - 1
|
|
until
|
|
i < 0
|
|
loop
|
|
res_ptr [res_ptr_offset + i] := op1_ptr [op1_ptr_offset + i].bit_xor (op2_ptr [op2_ptr_offset + i])
|
|
i := i - 1
|
|
end
|
|
res_size := op1_size
|
|
else
|
|
res_ptr.copy_data (op2_ptr, op2_ptr_offset + op1_size, res_ptr_offset + op1_size, op2_size - op1_size)
|
|
from
|
|
i := op1_size - 1
|
|
until
|
|
i < 0
|
|
loop
|
|
res_ptr [res_ptr_offset + i] := op1_ptr [op1_ptr_offset + i].bit_xor (op2_ptr [op2_ptr_offset + i])
|
|
i := i - 1
|
|
end
|
|
res_size := op2_size
|
|
end
|
|
add_1 (res_ptr, res_ptr_offset, res_ptr, res_ptr_offset, res_size, 1, carry)
|
|
cy := carry.item
|
|
if cy /= 0 then
|
|
res_ptr [res_ptr_offset + res_size] := cy
|
|
res_size := res_size + 1
|
|
end
|
|
res_size := normalize (res_ptr, res_ptr_offset, res_size)
|
|
res.count := - res_size
|
|
end
|
|
end
|
|
|
|
bit_xor_lshift (target: READABLE_INTEGER_X; op1: READABLE_INTEGER_X op2_a: READABLE_INTEGER_X left_shift_bits: INTEGER)
|
|
-- Bit XOR `op1' with (`op2' left shifted `left_shift_bits' bits)
|
|
local
|
|
op2: READABLE_INTEGER_X
|
|
target_special: SPECIAL [NATURAL_32]
|
|
op1_special: SPECIAL [NATURAL_32]
|
|
op1_count: INTEGER
|
|
op2_count: INTEGER
|
|
target_count_max: INTEGER
|
|
do
|
|
if target = op2_a or op1 = op2_a then
|
|
op2 := op2_a.identity
|
|
else
|
|
op2 := op2_a
|
|
end
|
|
op1_special := op1.item
|
|
op1_count := op1.count
|
|
op2_count := op2.count
|
|
target_count_max := op1_count + op2_count + bits_to_limbs (left_shift_bits)
|
|
target.resize (target_count_max)
|
|
target_special := target.item
|
|
bit_xor_lshift_special (target_special, 0, op1_special, 0, op1_count, op2.item, 0, op2_count, left_shift_bits)
|
|
target.count := normalize (target_special, 0, target_count_max)
|
|
end
|
|
end
|