Moved eel and eapml under the contrib folder.

This commit is contained in:
Jocelyn Fiat
2012-06-15 14:24:23 +02:00
parent 12d56861e6
commit 0203e0fdc7
166 changed files with 3 additions and 3 deletions

View File

@@ -0,0 +1,224 @@
note
description: "Convert between character codes and numbers ignoring case"
author: "Colin LeMahieu"
date: "$Date$"
revision: "$Revision$"
quote: "There can be no freedom without freedom to fail. - Eric Hoffer (1902-1983), The Ordeal of Change, 1964"
class
CASE_INSENSITIVE_STRATEGY
inherit
CHARACTER_STRATEGY
feature
text_to_number (in: NATURAL_8): NATURAL_8
do
inspect
in
when 0x30 then
Result := 0x0
when 0x31 then
Result := 1
when 0x32 then
Result := 2
when 0x33 then
Result := 3
when 0x34 then
Result := 4
when 0x35 then
Result := 5
when 0x36 then
Result := 6
when 0x37 then
Result := 7
when 0x38 then
Result := 8
when 0x39 then
Result := 9
when 0x41 then
Result := 10
when 0x42 then
Result := 11
when 0x43 then
Result := 12
when 0x44 then
Result := 13
when 0x45 then
Result := 14
when 0x46 then
Result := 15
when 0x47 then
Result := 16
when 0x48 then
Result := 17
when 0x49 then
Result := 18
when 0x4a then
Result := 19
when 0x4b then
Result := 20
when 0x4c then
Result := 21
when 0x4d then
Result := 22
when 0x4e then
Result := 23
when 0x4f then
Result := 24
when 0x50 then
Result := 25
when 0x51 then
Result := 26
when 0x52 then
Result := 27
when 0x53 then
Result := 28
when 0x54 then
Result := 29
when 0x55 then
Result := 30
when 0x56 then
Result := 31
when 0x57 then
Result := 32
when 0x58 then
Result := 33
when 0x59 then
Result := 34
when 0x5a then
Result := 35
when 0x61 then
Result := 10
when 0x62 then
Result := 11
when 0x63 then
Result := 12
when 0x64 then
Result := 13
when 0x65 then
Result := 14
when 0x66 then
Result := 15
when 0x67 then
Result := 16
when 0x68 then
Result := 17
when 0x69 then
Result := 18
when 0x6a then
Result := 19
when 0x6b then
Result := 20
when 0x6c then
Result := 21
when 0x6d then
Result := 22
when 0x6e then
Result := 23
when 0x6f then
Result := 24
when 0x70 then
Result := 25
when 0x71 then
Result := 26
when 0x72 then
Result := 27
when 0x73 then
Result := 28
when 0x74 then
Result := 29
when 0x75 then
Result := 30
when 0x76 then
Result := 31
when 0x77 then
Result := 32
when 0x78 then
Result := 33
when 0x79 then
Result := 34
when 0x7a then
Result := 35
end
end
number_to_text (in: NATURAL_8): NATURAL_8
do
inspect in
when 0 then
Result := 0x30
when 1 then
Result := 0x31
when 2 then
Result := 0x32
when 3 then
Result := 0x33
when 4 then
Result := 0x34
when 5 then
Result := 0x35
when 6 then
Result := 0x36
when 7 then
Result := 0x37
when 8 then
Result := 0x38
when 9 then
Result := 0x39
when 10 then
Result := 0x61
when 11 then
Result := 0x62
when 12 then
Result := 0x63
when 13 then
Result := 0x64
when 14 then
Result := 0x65
when 15 then
Result := 0x66
when 16 then
Result := 0x67
when 17 then
Result := 0x68
when 18 then
Result := 0x69
when 19 then
Result := 0x6a
when 20 then
Result := 0x6b
when 21 then
Result := 0x6c
when 22 then
Result := 0x6d
when 23 then
Result := 0x6e
when 24 then
Result := 0x6f
when 25 then
Result := 0x70
when 26 then
Result := 0x71
when 27 then
Result := 0x72
when 28 then
Result := 0x73
when 29 then
Result := 0x74
when 30 then
Result := 0x75
when 31 then
Result := 0x76
when 32 then
Result := 0x77
when 33 then
Result := 0x78
when 34 then
Result := 0x79
when 35 then
Result := 0x7a
end
end
end

View File

@@ -0,0 +1,276 @@
note
description: "Convert between character codes and numbers case-sensitive"
author: "Colin LeMahieu"
date: "$Date$"
revision: "$Revision$"
quote: "I believe the State exists for the development of individual lives, not individuals for the development of the state. - Julian Huxley (1878-1975)"
class
CASE_SENSITIVE_STRATEGY
inherit
CHARACTER_STRATEGY
feature
text_to_number (in: NATURAL_8): NATURAL_8
do
inspect
in
when 0x30 then
Result := 0x0
when 0x31 then
Result := 1
when 0x32 then
Result := 2
when 0x33 then
Result := 3
when 0x34 then
Result := 4
when 0x35 then
Result := 5
when 0x36 then
Result := 6
when 0x37 then
Result := 7
when 0x38 then
Result := 8
when 0x39 then
Result := 9
when 0x41 then
Result := 10
when 0x42 then
Result := 11
when 0x43 then
Result := 12
when 0x44 then
Result := 13
when 0x45 then
Result := 14
when 0x46 then
Result := 15
when 0x47 then
Result := 16
when 0x48 then
Result := 17
when 0x49 then
Result := 18
when 0x4a then
Result := 19
when 0x4b then
Result := 20
when 0x4c then
Result := 21
when 0x4d then
Result := 22
when 0x4e then
Result := 23
when 0x4f then
Result := 24
when 0x50 then
Result := 25
when 0x51 then
Result := 26
when 0x52 then
Result := 27
when 0x53 then
Result := 28
when 0x54 then
Result := 29
when 0x55 then
Result := 30
when 0x56 then
Result := 31
when 0x57 then
Result := 32
when 0x58 then
Result := 33
when 0x59 then
Result := 34
when 0x5a then
Result := 35
when 0x61 then
Result := 36
when 0x62 then
Result := 37
when 0x63 then
Result := 38
when 0x64 then
Result := 39
when 0x65 then
Result := 40
when 0x66 then
Result := 41
when 0x67 then
Result := 42
when 0x68 then
Result := 43
when 0x69 then
Result := 44
when 0x6a then
Result := 45
when 0x6b then
Result := 46
when 0x6c then
Result := 47
when 0x6d then
Result := 48
when 0x6e then
Result := 49
when 0x6f then
Result := 50
when 0x70 then
Result := 51
when 0x71 then
Result := 52
when 0x72 then
Result := 53
when 0x73 then
Result := 54
when 0x74 then
Result := 55
when 0x75 then
Result := 56
when 0x76 then
Result := 57
when 0x77 then
Result := 58
when 0x78 then
Result := 59
when 0x79 then
Result := 60
when 0x7a then
Result := 61
end
end
number_to_text (in: NATURAL_8): NATURAL_8
do
inspect in
when 0 then
Result := 0x30
when 1 then
Result := 0x31
when 2 then
Result := 0x32
when 3 then
Result := 0x33
when 4 then
Result := 0x34
when 5 then
Result := 0x35
when 6 then
Result := 0x36
when 7 then
Result := 0x37
when 8 then
Result := 0x38
when 9 then
Result := 0x39
when 10 then
Result := 0x41
when 11 then
Result := 0x42
when 12 then
Result := 0x43
when 13 then
Result := 0x44
when 14 then
Result := 0x45
when 15 then
Result := 0x46
when 16 then
Result := 0x47
when 17 then
Result := 0x48
when 18 then
Result := 0x49
when 19 then
Result := 0x4a
when 20 then
Result := 0x4b
when 21 then
Result := 0x4c
when 22 then
Result := 0x4d
when 23 then
Result := 0x4e
when 24 then
Result := 0x4f
when 25 then
Result := 0x50
when 26 then
Result := 0x51
when 27 then
Result := 0x52
when 28 then
Result := 0x53
when 29 then
Result := 0x54
when 30 then
Result := 0x55
when 31 then
Result := 0x56
when 32 then
Result := 0x57
when 33 then
Result := 0x58
when 34 then
Result := 0x59
when 35 then
Result := 0x5a
when 36 then
Result := 0x61
when 37 then
Result := 0x62
when 38 then
Result := 0x63
when 39 then
Result := 0x64
when 40 then
Result := 0x65
when 41 then
Result := 0x66
when 42 then
Result := 0x67
when 43 then
Result := 0x68
when 44 then
Result := 0x69
when 45 then
Result := 0x6a
when 46 then
Result := 0x6b
when 47 then
Result := 0x6c
when 48 then
Result := 0x6d
when 49 then
Result := 0x6e
when 50 then
Result := 0x6f
when 51 then
Result := 0x70
when 52 then
Result := 0x71
when 53 then
Result := 0x72
when 54 then
Result := 0x73
when 55 then
Result := 0x74
when 56 then
Result := 0x75
when 57 then
Result := 0x76
when 58 then
Result := 0x77
when 59 then
Result := 0x78
when 60 then
Result := 0x79
when 61 then
Result := 0x7a
end
end
end

View File

@@ -0,0 +1,20 @@
note
description: "A strategy for converting character codes to numbers and vica-versa"
author: "Colin LeMahieu"
date: "$Date$"
revision: "$Revision$"
quote: "Free speech is meaningless unless it tolerates the speech that we hate. - Henry J. Hyde, U.S. Congressman, Speech, 5/3/91"
deferred class
CHARACTER_STRATEGY
feature
text_to_number (in: NATURAL_8): NATURAL_8
deferred
end
number_to_text (in: NATURAL_8): NATURAL_8
deferred
end
end

View File

@@ -0,0 +1,77 @@
note
description: "Summary description for {INTEGER_X_ACCESS}."
author: "Colin LeMahieu"
date: "$Date$"
revision: "$Revision$"
quote: "It is error alone which needs the support of government. Truth can stand by itself. - Thomas Jefferson (1743-1846), U.S. President, Notes on the State of Virginia, 1782"
deferred class
INTEGER_X_ACCESS
inherit
INTEGER_X_FACILITIES
SPECIAL_SIZING
SPECIAL_ACCESS
rename
get_str as get_str_special
end
feature
get_string (op: READABLE_INTEGER_X; base: INTEGER): STRING_8
require
base >= 2
base <= 62
local
xp: SPECIAL [NATURAL_32]
xp_offset: INTEGER
x_size: INTEGER
str: STRING_8
str_offset: INTEGER
return_str: STRING_8
return_str_offset: INTEGER
str_size: INTEGER
alloc_size: INTEGER
num_to_text: CHARACTER_STRATEGY
i: INTEGER
do
x_size := op.count
if base <= 35 then
create {CASE_INSENSITIVE_STRATEGY}num_to_text
else
create {CASE_SENSITIVE_STRATEGY}num_to_text
end
alloc_size := sizeinbase (op.item, 0, x_size.abs, base)
alloc_size := alloc_size + (x_size < 0).to_integer
create Result.make_filled ('%U', alloc_size)
return_str := Result
return_str_offset := 1
if x_size < 0 then
return_str [return_str_offset] := '-'
return_str_offset := return_str_offset + 1
x_size := -x_size
end
xp := op.item
xp_offset := 0
if not pow2_p (base.to_natural_32) then
create xp.make_filled (0, x_size + 1)
xp.copy_data (op.item, 0, 0, x_size)
end
str_size := get_str_special (return_str, return_str_offset, base, xp, xp_offset, x_size)
str := return_str
str.remove_tail (alloc_size - str_size - (return_str_offset - 1))
str_offset := return_str_offset
if str [str_offset] = (0x0).to_character_8 and str_size /= 1 then
str_size := str_size - 1
str_offset := str_offset + 1
end
from
i := 0
until
i >= str_size
loop
return_str [return_str_offset + i] := num_to_text.number_to_text (str [str_offset + i].code.to_natural_8).to_character_8
i := i + 1
end
end
end

View File

@@ -0,0 +1,914 @@
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

View File

@@ -0,0 +1,155 @@
note
description: "Summary description for {INTEGER_X_ASSIGNMENT}."
author: "Colin LeMahieu"
date: "$Date$"
revision: "$Revision$"
quote: "The object and practice of liberty lies in the limitation of governmental power. - General Douglas MacArthur"
deferred class
INTEGER_X_ASSIGNMENT
inherit
INTEGER_X_FACILITIES
SPECIAL_ASSIGNMENT
rename
set_str as set_str_special
end
MP_BASES
feature
swap (target: READABLE_INTEGER_X; other_a: READABLE_INTEGER_X)
-- Swap the values `rop1' and `rop2' efficiently.
local
other_size: INTEGER_32
other_pointer: SPECIAL [NATURAL_32]
do
other_size := other_a.count
other_pointer := other_a.item
other_a.count := target.count
other_a.item := target.item
target.count := other_size
target.item := other_pointer
end
set_str (target: READABLE_INTEGER_X; str: READABLE_STRING_8; base_a: INTEGER)
-- Set the value of `rop' from `str', a null-terminated C string in base `base'.
-- White space is allowed in the string, and is simply ignored.
-- The base may vary from 2 to 62, or if base is 0, then the leading characters
-- are used: 0x and 0X for hexadecimal, 0b and 0B for binary, 0 for octal, or
-- decimal otherwise.
-- For bases up to 36, case is ignored; upper-case and lower-case letters have
-- the same value.
-- For bases 37 to 62, upper-case letter represent the usual 10..35 while
-- lower-case letter represent 36..61.
-- This function returns 0 if the entire string is a valid number in base base.
-- Otherwise it returns -1.
require
base_a <= 62
base_a >= 2 or base_a = 0
local
base: INTEGER
str_offset: INTEGER
s: SPECIAL [NATURAL_8]
s_offset: INTEGER
begs: INTEGER
i: INTEGER
xsize: INTEGER
c: CHARACTER
negative: BOOLEAN
digit_value: CHARACTER_STRATEGY
str_size: INTEGER
dig: NATURAL_8
do
base := base_a
if base > 36 then
create {CASE_SENSITIVE_STRATEGY}digit_value
else
create {CASE_INSENSITIVE_STRATEGY}digit_value
end
from
str_offset := 1
c := ' '
until
not c.is_space or not str.valid_index (str_offset)
loop
c := str [str_offset]
str_offset := str_offset + 1
end
if c = '-' then
negative := True
c := str [str_offset]
str_offset := str_offset + 1
end
if base = 0 then
if digit_value.text_to_number (c.code.to_natural_8) >= 10 then
(create {INTEGER_X_STRING_EXCEPTION}).raise
end
else
if digit_value.text_to_number (c.code.to_natural_8) >= base then
(create {INTEGER_X_STRING_EXCEPTION}).raise
end
end
if base = 0 then
base := 10
if c = '0' then
base := 8
if str.valid_index (str_offset) then
c := str [str_offset]
end
str_offset := str_offset + 1
if c = 'x' or c = 'X' then
base := 16
c := str [str_offset]
str_offset := str_offset + 1
elseif c = 'b' or c = 'B' then
base := 2
c := str [str_offset]
str_offset := str_offset + 1
end
end
end
from
until
c /= '0' and not c.is_space or not str.valid_index (str_offset)
loop
c := str [str_offset]
str_offset := str_offset + 1
end
if c.code = 0 then
target.count := 0
target.item [0] := 0
else
str_size := str.count - str_offset + 2
create s.make_filled (0, str_size)
from
i := 0
until
i >= str_size
loop
if not c.is_space then
dig := digit_value.text_to_number (c.code.to_natural_8)
if dig.to_integer_32 >= base then
(create {INTEGER_X_STRING_EXCEPTION}).raise
end
s [s_offset] := dig
s_offset := s_offset + 1
end
if str.valid_index (str_offset) then
c := str [str_offset]
end
str_offset := str_offset + 1
i := i + 1
end
str_size := s_offset - begs
xsize := (str_size / chars_per_bit_exactly (base)).truncated_to_integer // 32 + 2
target.resize (xsize)
xsize := set_str_special (target.item, 0, s, begs, str_size, base)
if negative then
target.count := -xsize
else
target.count := xsize
end
end
end
end

View File

@@ -0,0 +1,200 @@
note
description: "Summary description for {INTEGER_X_COMPARISON}."
author: "Colin LeMahieu"
date: "$Date$"
revision: "$Revision$"
quote: "The marvel of all history is the patience with which men and women submit to burdens unnecessarily laid upon them by their governments. - U.S. Senator William Borah"
deferred class
INTEGER_X_COMPARISON
inherit
INTEGER_X_FACILITIES
SPECIAL_COMPARISON
rename
cmp as cmp_special
end
feature
compare (op1: READABLE_INTEGER_X; op2: READABLE_INTEGER_X): INTEGER
-- Compare `op1' and `op2'.
-- Return a positive value if `op1' > `op2', zero if `op1' = `op2', or a negative value if `op1' < `op2'.
local
usize: INTEGER_32
vsize: INTEGER_32
dsize: INTEGER_32
asize: INTEGER_32
cmp_l: INTEGER_32
do
usize := op1.count
vsize := op2.count
dsize := usize - vsize
if dsize /= 0 then
Result := dsize
else
asize := usize.abs
cmp_l := cmp_special (op1.item, 0, op2.item, 0, asize)
if usize >= 0 then
Result := cmp_l
else
Result := -cmp_l
end
end
end
cmp_si (op1: READABLE_INTEGER_X; op: INTEGER_32): INTEGER
-- Compare `op1' and `op2'.
-- Return a positive value if `op1' > `op2', zero if `op1' = `op2', or a negative value if `op1' < `op2'.
-- Is a macro and will evaluate their arguments more than once.
local
v_digit: INTEGER_32
usize: INTEGER_32
vsize: INTEGER_32
u_digit: NATURAL_32
do
v_digit := op
usize := op1.count
vsize := 0
if v_digit > 0 then
vsize := 1
elseif v_digit < 0 then
vsize := -1
v_digit := -v_digit
end
if usize /= vsize then
Result := usize - vsize
else
if usize = 0 then
Result := 0
else
u_digit := op1.item [0]
if u_digit = v_digit.to_natural_32 then
Result := 0
else
if u_digit > v_digit.to_natural_32 then
Result := usize
else
Result := -usize
end
end
end
end
end
cmp_ui (op1: READABLE_INTEGER_X; op: NATURAL): INTEGER
-- Compare `op1' and `op2'.
-- Return a positive value if `op1' > `op2', zero if `op1' = `op2', or a negative value if `op1' < `op2'.
-- Is a macro and will evaluate their arguments more than once.
local
un: INTEGER_32
ul: NATURAL_32
v_digit: NATURAL_32
do
v_digit := op
un := op1.count
if un = 0 then
if v_digit /= 0 then
Result := -1
else
Result := 0
end
else
if un = 1 then
ul := op1.item [0]
if ul > v_digit then
Result := 1
else
if ul < v_digit then
Result := -1
else
Result := 0
end
end
else
if un > 0 then
Result := 1
else
Result := -1
end
end
end
end
cmpabs (op1: READABLE_INTEGER_X ;op2: READABLE_INTEGER_X): INTEGER
-- Compare the absolute values of `op1' and `op2'.
-- Return a positive value if abs(`op1') > abs(`op2'), zero if abs(`op1') = abs(`op2'),
-- or a negative value if abs(`op1') < abs(`op2').
local
usize: INTEGER_32
vsize: INTEGER_32
dsize: INTEGER_32
cmp_l: INTEGER_32
i: INTEGER_32
x: NATURAL_32
y: NATURAL_32
do
usize := op1.count.abs
vsize := op2.count.abs
dsize := usize - vsize
if dsize /= 0 then
Result := dsize
else
cmp_l := 0
from
i := usize - 1
until
i < 0 or cmp_l /= 0
loop
x := op1.item [i]
y := op2.item [i]
if x /= y then
if x > y then
Result := 1
else
Result := -1
end
end
i := i - 1
variant
i + 2
end
end
end
cmpabs_ui (op1: READABLE_INTEGER_X; op: NATURAL_32): INTEGER
-- Compare the absolute values of `op1' and `op2'.
-- Return a positive value if abs(`op1') > abs(`op2'), zero if abs(`op1') = abs(`op2'),
-- or a negative value if abs(`op1') < abs(`op2').
local
un: INTEGER_32
ul: NATURAL_32
v_digit: NATURAL_32
do
v_digit := op
un := op1.count
if un = 0 then
if v_digit /= 0 then
Result := -1
else
Result := 0
end
else
un := un.abs
if un = 1 then
ul := op1.item [0]
if ul > v_digit then
Result := 1
else
if ul < v_digit then
Result := -1
else
Result := 0
end
end
else
Result := 1
end
end
end
end

View File

@@ -0,0 +1,429 @@
note
description: "Summary description for {INTEGER_X_DIVISION}."
author: "Colin LeMahieu"
date: "$Date$"
revision: "$Revision$"
quote: "Collecting more taxes than is absolutely necessary is legalized robbery. - President Calvin Coolidge"
deferred class
INTEGER_X_DIVISION
inherit
INTEGER_X_FACILITIES
SPECIAL_UTILITY
export
{NONE}
all
end
SPECIAL_DIVISION
rename
add as add_special,
sub as sub_special,
mul as mul_special,
tdiv_qr as tdiv_qr_special
export
{NONE}
all
end
INTEGER_X_ARITHMETIC
INTEGER_X_ASSIGNMENT
rename
add as add_special,
sub as sub_special,
mul as mul_special
export
{NONE}
all
end
feature
fdiv_r_2exp (target: READABLE_INTEGER_X; u: READABLE_INTEGER_X; count: INTEGER)
do
cfdiv_r_2exp (target, u, count, -1)
end
cdiv_r_2exp (target: READABLE_INTEGER_X; u: READABLE_INTEGER_X; count: INTEGER)
do
cfdiv_r_2exp (target, u, count, 1)
end
cfdiv_r_2exp (target: READABLE_INTEGER_X; u: READABLE_INTEGER_X; count_a: INTEGER; direction: INTEGER)
local
usize: INTEGER
abs_usize: INTEGER
limb_count: INTEGER
i: INTEGER
up: SPECIAL [NATURAL_32]
up_offset: INTEGER
wp: SPECIAL [NATURAL_32]
wp_offset: INTEGER
high: NATURAL_32
count: INTEGER
returned: BOOLEAN
negate: BOOLEAN
do
create wp.make_empty (0)
count := count_a
usize := u.count
if usize = 0 then
target.count := 0
else
limb_count := count // 32
count := count \\ 32
abs_usize := usize.abs
up := u.item
if usize.bit_xor (direction) < 0 and Current = u and abs_usize <= limb_count then
returned := True
else
if usize.bit_xor (direction) < 0 then
if Current = u then
wp := target.item
else
i := abs_usize.min (limb_count + 1)
target.resize (i)
wp := target.item
wp.copy_data (up, up_offset, wp_offset, i)
if abs_usize <= limb_count then
target.count := usize
returned := True
end
end
else
if abs_usize <= limb_count then
negate := True
else
from
i := 0
until
i < limb_count or negate
loop
negate := up [up_offset + i] /= 0
i := i + 1
end
if not negate then
if up [up_offset + limb_count].bit_and (((1).to_natural_32 |<< count) - 1) /= 0 then
negate := True
else
target.count := 0
returned := True
end
end
end
if not returned and negate then
target.resize (limb_count + 1)
up := u.item
up_offset := 0
wp := target.item
wp_offset := 0
i := abs_usize.min (limb_count + 1)
com_n (wp, wp_offset, up, up_offset, i)
from
until
i > limb_count
loop
wp [wp_offset + i] := high.max_value
i := i + 1
end
incr_u (wp, wp_offset, 1)
usize := -usize
end
end
end
if not returned then
high := wp [wp_offset + limb_count]
high := high.bit_and (((1).to_natural_32 |<< count) - 1)
wp [wp_offset + limb_count] := high
from
limb_count := limb_count - 1
until
high /= 0 or limb_count < 0
loop
high := wp [wp_offset + limb_count]
end
if limb_count < 0 then
target.count := 0
else
limb_count := limb_count + 1
if usize >= 0 then
target.count := limb_count
else
target.count := -limb_count
end
end
end
end
end
mod (target: READABLE_INTEGER_X; dividend: READABLE_INTEGER_X; divisor_a: READABLE_INTEGER_X)
local
divisor_size: INTEGER
temp_divisor: INTEGER_X
divisor: READABLE_INTEGER_X
do
divisor := divisor_a
divisor_size := divisor.count
if target = divisor then
create temp_divisor.make_limbs (divisor_size.abs)
temp_divisor.set_from_other (divisor)
divisor := temp_divisor
end
tdiv_r (target, dividend, divisor)
if target.count /= 0 then
if dividend.count < 0 then
if divisor.count < 0 then
sub (target, target, divisor)
else
add (target, target, divisor)
end
end
end
end
tdiv_q (target: READABLE_INTEGER_X; numerator: READABLE_INTEGER_X; denominator: READABLE_INTEGER_X)
local
ql: INTEGER
ns: INTEGER
ds: INTEGER
nl: INTEGER
dl: INTEGER
np: SPECIAL [NATURAL_32]
np_offset: INTEGER
dp: SPECIAL [NATURAL_32]
dp_offset: INTEGER
qp: SPECIAL [NATURAL_32]
qp_offset: INTEGER
rp: SPECIAL [NATURAL_32]
rp_offset: INTEGER
tp: SPECIAL [NATURAL_32]
tp_offset: INTEGER
do
ns := numerator.count
ds := denominator.count
nl := ns.abs
dl := ds.abs
ql := nl - dl + 1
if dl = 0 then
(create {DIVIDE_BY_ZERO}).raise
end
if ql <= 0 then
target.count := 0
else
target.resize (ql)
qp := target.item
create rp.make_filled (0, dl)
np := numerator.item
dp := denominator.item
if dp = qp then
create tp.make_filled (0, dl)
tp.copy_data (dp, dp_offset, tp_offset, dl)
dp := tp
end
if np = qp then
create tp.make_filled (0, nl)
tp.copy_data (np, np_offset, tp_offset, nl)
np := tp
end
tdiv_qr_special (qp, qp_offset, rp, rp_offset, np, np_offset, nl, dp, dp_offset, dl)
ql := ql - (qp [qp_offset + ql - 1] = 0).to_integer
if ns.bit_xor (ds) >= 0 then
target.count := ql
else
target.count := -ql
end
end
end
tdiv_q_2exp (target: READABLE_INTEGER_X; op: READABLE_INTEGER_X; count_a: INTEGER_32)
local
usize: INTEGER
wsize: INTEGER
limb_count: INTEGER
wp: SPECIAL [NATURAL_32]
wp_offset: INTEGER
up: SPECIAL [NATURAL_32]
up_offset: INTEGER
junk: NATURAL_32
count: INTEGER_32
carry: CELL [NATURAL_32]
do
create carry.put (0)
count := count_a
usize := op.count
limb_count := count // 32
wsize := usize.abs - limb_count
if wsize <= 0 then
target.count := 0
else
target.resize (wsize)
wp := target.item
up := op.item
count := count \\ 32
if count /= 0 then
rshift (wp, wp_offset, up, up_offset + limb_count, wsize, count, carry)
junk := carry.item
wsize := wsize - (wp [wp_offset + wsize - 1] = 0).to_integer
else
wp.copy_data (up, up_offset + limb_count, wp_offset, wsize)
end
if usize >= 0 then
target.count := wsize
else
target.count := -wsize
end
end
end
tdiv_qr (target: READABLE_INTEGER_X; remainder: READABLE_INTEGER_X; numerator: READABLE_INTEGER_X; denominator: READABLE_INTEGER_X)
local
ql: INTEGER_32
ns: INTEGER_32
ds: INTEGER_32
nl: INTEGER_32
dl: INTEGER_32
temp_dp: SPECIAL [NATURAL_32]
temp_np: SPECIAL [NATURAL_32]
do
ns := numerator.count
ds := denominator.count
nl := ns.abs
dl := ds.abs
ql := nl - dl + 1
if dl = 0 then
(create {DIVIDE_BY_ZERO}).raise
end
remainder.resize (dl)
if ql <= 0 then
if numerator /= remainder then
remainder.item.copy_data (numerator.item, 0, 0, nl)
remainder.count := numerator.count
end
target.count := 0
else
target.resize (ql)
if denominator = remainder or denominator = Current then
create temp_dp.make_empty (dl)
temp_dp.copy_data (denominator.item, 0, 0, dl)
else
temp_dp := denominator.item
end
if numerator = remainder or numerator = Current then
create temp_np.make_empty (nl)
temp_np.copy_data (numerator.item, 0, 0, nl)
else
temp_np := numerator.item
end
tdiv_qr_special (target.item, 0, remainder.item, 0, temp_np, 0, nl, temp_dp, 0, dl)
if target.item [ql - 1] = 0 then
ql := ql - 1
end
remainder.count := normalize (remainder.item, 0, remainder.count)
dl := remainder.count
if ns.bit_xor (ds) >= 0 then
target.count := ql
else
target.count := -ql
end
if ns >= 0 then
remainder.count := dl
else
remainder.count := -dl
end
end
end
tdiv_r (remainder: READABLE_INTEGER_X; numerator: READABLE_INTEGER_X; denominator: READABLE_INTEGER_X)
local
ql: INTEGER
ns: INTEGER
ds: INTEGER
nl: INTEGER
dl: INTEGER
np: SPECIAL [NATURAL_32]
np_offset: INTEGER
dp: SPECIAL [NATURAL_32]
dp_offset: INTEGER
qp: SPECIAL [NATURAL_32]
qp_offset: INTEGER
rp: SPECIAL [NATURAL_32]
rp_offset: INTEGER
tp: SPECIAL [NATURAL_32]
tp_offset: INTEGER
do
ns := numerator.count
ds := denominator.count
nl := ns.abs
dl := ds.abs
ql := nl - dl + 1
if dl = 0 then
(create {DIVIDE_BY_ZERO}).raise
end
remainder.resize (dl)
if ql <= 0 then
if numerator /= remainder then
np := numerator.item
rp := remainder.item
rp.copy_data (np, 0, 0, nl)
remainder.count := numerator.count
end
else
create qp.make_filled (0, ql)
rp := remainder.item
np := numerator.item
dp := denominator.item
if dp = rp then
create tp.make_filled (0, nl)
tp.copy_data (np, np_offset, tp_offset, nl)
np := tp
np_offset := tp_offset
end
tdiv_qr_special (qp, qp_offset, rp, rp_offset, np, np_offset, nl, dp, dp_offset, dl)
dl := normalize (rp, rp_offset, dl)
if ns >= 0 then
remainder.count := dl
else
remainder.count := -dl
end
end
end
tdiv_r_2exp (target: READABLE_INTEGER_X; op: READABLE_INTEGER_X; count: INTEGER)
local
in_size: INTEGER
res_size: INTEGER
limb_count: INTEGER
in_ptr: SPECIAL [NATURAL_32]
in_ptr_offset: INTEGER
x: NATURAL_32
do
in_size := op.count.abs
limb_count := count // 32
in_ptr := op.item
if in_size > limb_count then
x := in_ptr [in_ptr_offset + limb_count].bit_and (((1).to_natural_32 |<< (count \\ 32)- 1))
if x /= 0 then
res_size := limb_count + 1
target.resize (res_size)
target.item [limb_count] := x
else
res_size := limb_count
res_size := normalize (in_ptr, in_ptr_offset, res_size)
target.resize (res_size)
limb_count := res_size
end
else
res_size := in_size
target.resize (res_size)
limb_count := res_size
end
if target /= op then
target.item.copy_data (op.item, 0, 0, limb_count)
end
if op.count >= 0 then
target.count := res_size
else
target.count := -res_size
end
end
end

View File

@@ -0,0 +1,11 @@
note
description: "Summary description for {INTEGER_X_FACILITIES}."
author: "Colin LeMahieu"
date: "$Date$"
revision: "$Revision$"
quote: "Concentrated power is not rendered harmless by the good intentions of those who create it. - Milton Friedman, Nobel prize-winning economist"
deferred class
INTEGER_X_FACILITIES
end

View File

@@ -0,0 +1,145 @@
note
description: "Summary description for {INTEGER_X_GCD}."
author: "Colin LeMahieu"
date: "$Date$"
revision: "$Revision$"
quote: "'Need' now means wanting someone else's money. 'Greed' means wanting to keep your own. 'Compassion' is when a politician arranges the transfer. - Joseph Sobran, columnist."
deferred class
INTEGER_X_GCD
inherit
INTEGER_X_FACILITIES
SPECIAL_GCD
rename
gcd as gcd_special
export
{NONE}
all
end
feature
gcd (g: READABLE_INTEGER_X; u: READABLE_INTEGER_X; v: READABLE_INTEGER_X)
local
g_zero_bits: INTEGER
u_zero_bits: INTEGER
v_zero_bits: INTEGER
g_zero_limbs: INTEGER
u_zero_limbs: INTEGER
v_zero_limbs: INTEGER
tp: SPECIAL [NATURAL_32]
tp_offset: INTEGER
up: SPECIAL [NATURAL_32]
up_offset: INTEGER
usize: INTEGER
vp: SPECIAL [NATURAL_32]
vp_offset: INTEGER
vsize: INTEGER
gsize: INTEGER
junk: NATURAL_32
cy_limb: NATURAL_32
carry: CELL [NATURAL_32]
do
create carry.put (0)
up := u.item
usize := u.count.abs
vp := v.item
vsize := v.count.abs
if usize = 0 then
g.count := vsize
if g = v then
else
g.resize (vsize)
g.item.copy_data (vp, 0, 0, vsize)
end
elseif vsize = 0 then
g.count := usize
if g = u then
else
g.resize (usize)
g.item.copy_data (up, up_offset, 0, usize)
end
elseif usize = 1 then
g.count := 1
g.item [0] := gcd_1 (vp, vp_offset, vsize, up [up_offset])
elseif vsize = 1 then
g.count := 1
g.item [0] := gcd_1 (up, up_offset, usize, vp [vp_offset])
else
from
until
up [up_offset] /= 0
loop
up_offset := up_offset + 1
end
u_zero_limbs := up_offset - 0
usize := usize - u_zero_limbs
u_zero_bits := trailing_zeros (up [up_offset])
tp := up
tp_offset := up_offset
create up.make_filled (0, usize)
if u_zero_bits /= 0 then
rshift (up, up_offset, tp, tp_offset, usize, u_zero_bits, carry)
junk := carry.item
usize := usize - (up [up_offset + usize - 1] = 0).to_integer
else
up.copy_data (tp, tp_offset, up_offset, usize)
end
from
until
vp [vp_offset] /= 0
loop
vp_offset := vp_offset + 1
end
v_zero_limbs := vp_offset - 0
vsize := vsize - v_zero_limbs
v_zero_bits := trailing_zeros (vp [vp_offset])
tp := vp
tp_offset := vp_offset
create vp.make_filled (0, vsize)
if v_zero_bits /= 0 then
rshift (vp, vp_offset, tp, tp_offset, vsize, v_zero_bits, carry)
junk := carry.item
vsize := vsize - (vp [vp_offset + vsize - 1] = 0).to_integer
else
vp.copy_data (tp, tp_offset, vp_offset, vsize)
end
if u_zero_limbs > v_zero_limbs then
g_zero_limbs := v_zero_limbs
g_zero_bits := v_zero_bits
elseif u_zero_limbs < v_zero_limbs then
g_zero_limbs := u_zero_limbs
g_zero_bits := u_zero_bits
else
g_zero_limbs := u_zero_limbs
g_zero_bits := u_zero_bits.min (v_zero_bits)
end
if usize < vsize or (usize = vsize and up [up_offset + usize - 1] < vp [vp_offset + vsize - 1]) then
vsize := gcd_special (vp, vp_offset, vp, vp_offset, vsize, up, up_offset, usize)
else
vsize := gcd_special (vp, vp_offset, up, up_offset, usize, vp, vp_offset, vsize)
end
gsize := vsize + g_zero_limbs
if g_zero_bits /= 0 then
gsize := gsize + ((vp [vp_offset + vsize - 1] |>> (32 - g_zero_bits)) /= 0).to_integer
g.resize (gsize)
g.item.fill_with (0, 0, g_zero_limbs)
tp := g.item
tp_offset := g_zero_limbs
lshift (tp, tp_offset, vp, vp_offset, vsize, g_zero_bits, carry)
cy_limb := carry.item
if cy_limb /= 0 then
tp [tp_offset + vsize] := cy_limb
end
else
g.resize (gsize)
g.item.fill_with (0, 0, g_zero_limbs)
g.item.copy_data (vp, vp_offset, g_zero_limbs, vsize)
end
g.count := gsize
end
ensure
g.count /= 0
end
end

View File

@@ -0,0 +1,335 @@
note
description: "Summary description for {INTEGER_X_IO}."
author: "Colin LeMahieu"
date: "$Date$"
revision: "$Revision$"
quote: "I personally call the type of government which can be removed without violence 'democracy,' and the other, 'tyranny.' - Karl Popper"
deferred class
INTEGER_X_IO
inherit
INTEGER_X_FACILITIES
SPECIAL_SIZING
SPECIAL_UTILITY
LIMB_MANIPULATION
feature
output (target: SPECIAL [NATURAL_8]; target_offset: INTEGER; countp: TUPLE [countp: INTEGER]; order: INTEGER; size: INTEGER; endian_a: INTEGER; z: READABLE_INTEGER_X)
local
zsize: INTEGER
zp: SPECIAL [NATURAL_32]
zp_offset: INTEGER
count: INTEGER
numb: INTEGER
endian: INTEGER
i: INTEGER
j: INTEGER
limb: NATURAL_32
wbitsmask: NATURAL_32
wbytes: INTEGER
woffset: INTEGER
dp: SPECIAL [NATURAL_8]
dp_offset: INTEGER
lbits: INTEGER
wbits: INTEGER
zend: INTEGER
newlimb: NATURAL_32
done: BOOLEAN
do
endian := endian_a
zsize := z.count
if zsize = 0 then
countp.countp := 0
else
zsize := zsize.abs
zp := z.item
numb := 8 * size
count := sizeinbase_2exp (zp, zp_offset, zsize, numb)
countp.countp := count
if endian = 0 then
endian := -1
end
if size = 4 then
if order = -1 and endian = -1 then
from
i := target_offset
j := zp_offset
until
j >= zp_offset + count - 1
loop
write_limb (zp [zp_offset + j], target, target_offset + i)
i := i + 4
j := j + 1
end
done := True
elseif order = 1 and endian = -1 then
from
i := target_offset
j := zp_offset + count - 1
until
j < zp_offset
loop
write_limb (zp [zp_offset + j], target, target_offset + i)
j := j - 1
i := i + 4
end
done := True
elseif order = -1 and endian = 1 then
from
i := target_offset
j := zp_offset
until
j >= zp_offset + count - 1
loop
write_limb_be (zp [zp_offset + j], target, target_offset + i)
j := j + 1
i := i + 4
end
done := True
elseif order = 1 and endian = 1 then
from
i := target_offset
j := zp_offset + count - 1
until
j < zp_offset
loop
write_limb_be (zp [zp_offset + j], target, target_offset + i)
j := j - 1
i := i + 4
end
done := True
end
end
if not done then
numb := size * 8
wbytes := numb // 8
wbits := numb \\ 8
wbitsmask := ((1).to_natural_8 |<< wbits) - 1
if endian >= 0 then
woffset := size
else
woffset := -size
end
if order < 0 then
woffset := woffset + size
else
woffset := woffset + -size
end
dp := target
dp_offset := target_offset
if order >= 0 then
dp_offset := dp_offset + (count - 1) * size
else
dp_offset := dp_offset + 0
end
if endian >= 0 then
dp_offset := dp_offset + size - 1
else
dp_offset := dp_offset + 0
end
zend := zp_offset + zsize
lbits := 0
limb := 0
from
i := 0
until
i >= count
loop
from
j := 0
until
j >= wbytes
loop
if lbits >= 8 then
dp [dp_offset] := limb.to_natural_8
limb := limb |>> 8
lbits := lbits - 8
else
if zp_offset = zend then
newlimb := 0
else
newlimb := zp [zp_offset]
zp_offset := zp_offset + 1
end
dp [dp_offset] := (limb.bit_or (newlimb |<< lbits)).to_natural_8
limb := newlimb |>> (8 - lbits)
lbits := lbits + limb_bits - 8
end
dp_offset := dp_offset - endian
j := j + 1
end
if wbits /= 0 then
if lbits >= wbits then
dp [dp_offset] := limb.bit_and (wbitsmask).to_natural_8
limb := limb |>> wbits
lbits := lbits - wbits
else
if zp_offset = zend then
newlimb := 0
else
newlimb := zp [zp_offset]
zp_offset := zp_offset + 1
end
dp [dp_offset] := (limb.bit_or (newlimb |<< lbits)).bit_and (wbitsmask).to_natural_8
limb := newlimb |>> (wbits - lbits)
lbits := lbits + limb_bits - wbits
end
end
from
until
j >= size
loop
dp [dp_offset] := 0
dp_offset := dp_offset - endian
j := j + 1
end
dp_offset := dp_offset + woffset
i := i + 1
end
end
end
end
input (z: READABLE_INTEGER_X; count: INTEGER; order: INTEGER; size: INTEGER; endian_a: INTEGER; source: SPECIAL [NATURAL_8]; source_offset: INTEGER)
local
zsize: INTEGER
zp: SPECIAL [NATURAL_32]
zp_offset: INTEGER
i: INTEGER
j: INTEGER
done: BOOLEAN
limb: NATURAL_32
byte: NATURAL_32
wbitsmask: NATURAL_8
numb: INTEGER
wbytes: INTEGER
woffset: INTEGER
dp: SPECIAL [NATURAL_8]
dp_offset: INTEGER
lbits: INTEGER
wbits: INTEGER
endian: INTEGER
do
endian := endian_a
zsize := (count * (8 * size) + limb_bits - 1) // limb_bits
z.resize (zsize)
zp := z.item
if endian = 0 then
endian := -1
end
if order = -1 and size = 4 and endian = -1 then
from
i := zp_offset
j := source_offset
until
i >= count + zp_offset - 1
loop
zp [zp_offset + i] := read_limb (source, source_offset + j)
j := j + 4
i := i + 1
end
done := True
elseif order = -1 and size = 4 and endian = 1 then
from
i := zp_offset
j := source_offset
until
i >= count + zp_offset - 1
loop
zp [zp_offset + i] := read_limb_be (source, source_offset + j)
j := j + 4
i := i + 1
end
done := True
elseif order = 1 and size = 4 and endian = -1 then
from
i := zp_offset + count - 1
j := source_offset
until
i < zp_offset
loop
zp [zp_offset + i] := read_limb (source, source_offset + j)
j := j + 4
i := i - 1
end
done := True
end
if not done then
numb := size * 8
wbytes := numb // 8
wbits := numb \\ 8
wbitsmask := ((1).to_natural_8 |<< wbits) - 1
woffset := (numb + 7) // 8
if endian >= 0 then
woffset := woffset
else
woffset := -woffset
end
if order < 0 then
woffset := woffset + size
else
woffset := woffset + -size
end
dp := source
dp_offset := source_offset
if order >= 0 then
dp_offset := dp_offset + (count - 1) * size
else
dp_offset := dp_offset + 0
end
if endian >= 0 then
dp_offset := dp_offset + size - 1
else
dp_offset := dp_offset + 0
end
limb := 0
lbits := 0
from
i := 0
until
i >= count
loop
from
j := 0
until
j >= wbytes
loop
byte := dp [dp_offset]
dp_offset := dp_offset - endian
limb := limb.bit_or (byte |<< lbits)
lbits := lbits + 8
if lbits >= limb_bits then
zp [zp_offset] := limb
zp_offset := zp_offset + 1
lbits := lbits - limb_bits
limb := byte |>> (8 - lbits)
end
j := j + 1
end
if wbits /= 0 then
byte := dp [dp_offset].bit_and (wbitsmask)
dp_offset := dp_offset - endian
limb := limb.bit_or (byte |<< lbits)
lbits := lbits + wbits
if lbits >= limb_bits then
zp [zp_offset] := limb
zp_offset := zp_offset + 1
lbits := lbits - limb_bits
limb := byte |>> (wbits - lbits)
end
end
dp_offset := dp_offset + woffset
i := i + 1
end
if lbits /= 0 then
zp [zp_offset] := limb
zp_offset := zp_offset + 1
end
end
zp := z.item
zsize := normalize (zp, 0, zsize)
z.count := zsize
end
end

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,967 @@
note
description: "Summary description for {INTEGER_X_NUMBER_THEORY}."
author: "Colin LeMahieu"
date: "$Date$"
revision: "$Revision$"
quote: "Gun registration is a gateway drug. - Mark Gilmore"
deferred class
INTEGER_X_NUMBER_THEORY
inherit
INTEGER_X_FACILITIES
SPECIAL_ARITHMETIC
rename
add as add_special,
sub as sub_special,
mul as mul_special,
bit_xor_lshift as bit_xor_lshift_special,
bit_xor as bit_xor_special
export
{NONE}
all
end
SPECIAL_DIVISION
rename
add as add_special,
sub as sub_special,
mul as mul_special,
cmp as cmp_special,
tdiv_qr as tdiv_qr_special,
bit_xor_lshift as bit_xor_lshift_special,
bit_xor as bit_xor_special
export
{NONE}
all
end
SPECIAL_NUMBER_THEORETIC
rename
add as add_special,
sub as sub_special,
mul as mul_special,
cmp as cmp_special,
tdiv_qr as tdiv_qr_special,
gcdext as gcdext_special,
bit_xor_lshift as bit_xor_lshift_special,
bit_xor as bit_xor_special,
invert_gf as invert_gf_special
export
{NONE}
all
end
INTEGER_X_ACCESS
rename
add as add_special,
sub as sub_special,
mul as mul_special,
cmp as cmp_special,
tdiv_qr as tdiv_qr_special,
sizeinbase as sizeinbase_special,
bit_xor_lshift as bit_xor_lshift_special,
bit_xor as bit_xor_special
end
INTEGER_X_ARITHMETIC
rename
cmp as cmp_special,
bit_xor_lshift as bit_xor_lshift_special,
bit_xor as bit_xor_special
end
INTEGER_X_ASSIGNMENT
rename
add as add_special,
sub as sub_special,
mul as mul_special,
bit_xor_lshift as bit_xor_lshift_special,
bit_xor as bit_xor_special
end
INTEGER_X_COMPARISON
INTEGER_X_LOGIC
rename
add as add_special,
sub as sub_special,
mul as mul_special
end
INTEGER_X_DIVISION
rename
cmp as cmp_special,
bit_xor_lshift as bit_xor_lshift_special,
bit_xor as bit_xor_special
end
INTEGER_X_RANDOM
rename
add as add_special,
sub as sub_special,
mul as mul_special,
cmp as cmp_special,
bit_xor_lshift as bit_xor_lshift_special,
bit_xor as bit_xor_special
end
INTEGER_X_GCD
rename
add as add_special,
sub as sub_special,
mul as mul_special,
cmp as cmp_special,
tdiv_qr as tdiv_qr_special,
bit_xor_lshift as bit_xor_lshift_special,
bit_xor as bit_xor_special
end
INTEGER_X_SIZING
feature
millerrabin_test (n: READABLE_INTEGER_X; nm1: READABLE_INTEGER_X; x: READABLE_INTEGER_X; y: READABLE_INTEGER_X; q: READABLE_INTEGER_X; k: INTEGER): INTEGER
local
i: INTEGER
do
powm (y, x, q, n)
if cmp_ui (y, 1) = 0 or compare (y, nm1) = 0 then
Result := 1
else
from
i := 1
Result := -1
until
Result /= -1 or i >= k
loop
powm_ui (y, y, 2, n)
if compare (y, nm1) = 0 then
Result := 1
elseif cmp_ui (y, 1) = 0 then
Result := 0
end
i := i + 1
end
if Result = -1 then
Result := 0
end
end
end
bin_uiui (target: READABLE_INTEGER_X; n_a: NATURAL_32; k_a: NATURAL_32)
-- Compute the binomial coefficient `n' over `k' and store the result in `rop'.
local
i: NATURAL_32
j: NATURAL_32
cnt: NATURAL_32
n1: CELL [NATURAL_32]
n0: CELL [NATURAL_32]
k0: NATURAL_32
-- t: NATURAL_64
k: NATURAL_32
n: NATURAL_32
rsize: CELL [INTEGER]
ralloc: CELL [INTEGER]
nacc: CELL [NATURAL_32]
kacc: CELL [NATURAL_32]
do
create n0.put (0)
create n1.put (0)
create rsize.put (0)
create ralloc.put (0)
create nacc.put (0)
create kacc.put (0)
n := n_a
k := k_a
if n < k then
target.count := 0
else
k := k.min (n - k)
if k = 0 then
target.count := 1
target.item [0] := 1
else
j := n - k + 1
target.item [0] := j
target.count := 1
ralloc.put (target.capacity)
nacc.put (1)
kacc.put (1)
cnt := 0
from
i := 2
until
i > k
loop
j := j + 1
cnt := nacc.item.bit_or (kacc.item).bit_and (1).bit_xor (1)
nacc.put (nacc.item |>> cnt.to_integer_32)
kacc.put (kacc.item |>> cnt.to_integer_32)
umul_ppmm (n1, n0, nacc.item, j)
k0 := kacc.item * i
if n1.item /= 0 then
muldiv (target, 32, rsize, ralloc, nacc, kacc)
nacc.put (j)
kacc.put (i)
else
nacc.put (n0.item)
kacc.put (k0)
end
i := i + 1
end
muldiv (target, 1, rsize, ralloc, nacc, kacc)
target.count := rsize.item
end
end
end
gcdext (g: READABLE_INTEGER_X; s: detachable READABLE_INTEGER_X; t: detachable READABLE_INTEGER_X; a: READABLE_INTEGER_X; b: READABLE_INTEGER_X)
-- Set `g' to the greatest common divisor of `a' and `b', and in addition set `s' and `t' to
-- coefficients satisfying `a*s + b*t = g'.
-- `g' is always positive, even if one or both of `a' and `b' are negative.
-- If `t' is NULL then that value is not computed.
local
asize: INTEGER
bsize: INTEGER
usize: INTEGER
vsize: INTEGER
ap: SPECIAL [NATURAL_32]
ap_offset: INTEGER
bp: SPECIAL [NATURAL_32]
bp_offset: INTEGER
up: SPECIAL [NATURAL_32]
up_offset: INTEGER
vp: SPECIAL [NATURAL_32]
vp_offset: INTEGER
gsize: INTEGER
ssize: INTEGER
tmp_ssize: TUPLE [tmp_ssize: INTEGER]
gp: SPECIAL [NATURAL_32]
sp: SPECIAL [NATURAL_32]
tmp_gp: SPECIAL [NATURAL_32]
tmp_gp_offset: INTEGER
tmp_sp: SPECIAL [NATURAL_32]
tmp_sp_offset: INTEGER
u: READABLE_INTEGER_X
v: READABLE_INTEGER_X
ss: detachable READABLE_INTEGER_X
tt: detachable READABLE_INTEGER_X
gtmp: INTEGER_X
stmp: INTEGER_X
x: INTEGER_X
do
create tmp_ssize
asize := a.count.abs
bsize := b.count.abs
ap := a.item
bp := b.item
if asize > bsize or (asize = bsize and cmp_special (ap, ap_offset, bp, bp_offset, asize) > 0) then
usize := asize
vsize := bsize
create up.make_filled (0, usize + 1)
create vp.make_filled (0, vsize + 1)
up.copy_data (ap, ap_offset, up_offset, usize)
vp.copy_data (bp, bp_offset, vp_offset, vsize)
u := a
v := b
ss := s
tt := t
else
usize := bsize
vsize := asize
create up.make_filled (0, usize + 1)
create vp.make_filled (0, vsize + 1)
up.copy_data (bp, bp_offset, up_offset, usize)
vp.copy_data (ap, ap_offset, vp_offset, vsize)
u := b
v := a
ss := t
tt := s
end
create tmp_gp.make_filled (0, usize + 1)
create tmp_sp.make_filled (0, usize + 1)
if vsize = 0 then
tmp_sp [tmp_sp_offset] := 1
tmp_ssize.tmp_ssize := 1
tmp_gp.copy_data (up, up_offset, tmp_gp_offset, usize)
gsize := usize
else
gsize := gcdext_special (tmp_gp, tmp_gp_offset, tmp_sp, tmp_sp_offset, tmp_ssize, up, up_offset, usize, vp, vp_offset, vsize)
end
ssize := tmp_ssize.tmp_ssize.abs
create gtmp
gtmp.item := tmp_gp
gtmp.count := gsize
create stmp
stmp.item := tmp_sp
if tmp_ssize.tmp_ssize.bit_xor (u.count) >= 0 then
stmp.count := ssize
else
stmp.count := -ssize
end
if attached {READABLE_INTEGER_X} tt as tt_l then
if v.count = 0 then
tt_l.count := 0
else
create x.make_limbs (ssize + usize + 1)
mul (x, stmp, u)
sub (x, gtmp, x)
tdiv_q (tt_l, x, v)
end
end
if attached {READABLE_INTEGER_X} ss as ss_l then
ss_l.resize (ssize)
sp := ss_l.item
sp.copy_data (tmp_sp, tmp_sp_offset, 0, ssize)
ss_l.count := stmp.count
end
g.resize (gsize)
gp := g.item
gp.copy_data (tmp_gp, tmp_gp_offset, 0, gsize)
g.count := gsize
end
invert (target: READABLE_INTEGER_X; x: READABLE_INTEGER_X; n: READABLE_INTEGER_X): BOOLEAN
local
gcd_l: INTEGER_X
tmp: INTEGER_X
xsize: INTEGER_32
nsize: INTEGER_32
size: INTEGER_32
do
xsize := x.count.abs
nsize := n.count.abs
size := xsize.max (nsize) + 1
if xsize = 0 or (nsize = 1 and n.item [0] = 1) then
Result := False
else
create gcd_l.make_limbs (size)
create tmp.make_limbs (size)
gcdext (gcd_l, tmp, void, x, n)
if gcd_l.count /= 1 or gcd_l.item [0] /= 1 then
Result := False
else
if tmp.count < 0 then
if n.count < 0 then
sub (target, tmp, n)
else
add (target, tmp, n)
end
else
target.copy (tmp)
end
Result := True
end
end
end
millerrabin (source: READABLE_INTEGER_X; reps: INTEGER): INTEGER
local
r: INTEGER
nm1: INTEGER_X
nm3: INTEGER_X
x: INTEGER_X
y: INTEGER_X
q: INTEGER_X
k: INTEGER
is_prime: INTEGER
rstate: MERSENNE_TWISTER_RNG
do
create nm1.make_limbs (source.count + 1)
sub_ui (nm1, source, 1)
create x.make_limbs (source.count + 1)
create y.make_limbs (2 * source.count)
x.set_from_natural_32 (210)
powm (y, x, nm1, source)
if cmp_ui (y, 1) /= 0 then
Result := 0
else
create q.make_limbs (source.count)
k := bit_scan_1 (nm1, 0)
tdiv_q_2exp (q, nm1, k)
create nm3.make_limbs (source.count + 1)
sub_ui (nm3, source, 3)
create rstate.make
is_prime := 1
from
r := 0
until
r >= reps or is_prime = 0
loop
urandomm (x, rstate, nm3)
add_ui (x, x, 2)
is_prime := millerrabin_test (source, nm1, x, y, q, k)
r := r + 1
end
Result := is_prime
end
end
powm (r: READABLE_INTEGER_X; b_a: READABLE_INTEGER_X; e: READABLE_INTEGER_X; m: READABLE_INTEGER_X)
local
xp: SPECIAL [NATURAL_32]
xp_offset: INTEGER
tp: SPECIAL [NATURAL_32]
tp_offset: INTEGER
qp: SPECIAL [NATURAL_32]
qp_offset: INTEGER
gp: SPECIAL [NATURAL_32]
gp_offset: INTEGER
this_gp: SPECIAL [NATURAL_32]
this_gp_offset: INTEGER
bp: SPECIAL [NATURAL_32]
bp_offset: INTEGER
ep: SPECIAL [NATURAL_32]
ep_offset: INTEGER
mp: SPECIAL [NATURAL_32]
mp_offset: INTEGER
bn: INTEGER
es: INTEGER
en: INTEGER
mn: INTEGER
xn: INTEGER
invm: NATURAL_32
c: NATURAL_32
enb: INTEGER
i: INTEGER
big_k: INTEGER
j: INTEGER
l: INTEGER
small_k: INTEGER
m_zero_cnt: INTEGER
e_zero_cnt: INTEGER
sh: INTEGER
use_redc: BOOLEAN
new_b: INTEGER_X
b: READABLE_INTEGER_X
new_mp: SPECIAL [NATURAL_32]
new_mp_offset: INTEGER
junk: NATURAL_32
cy: NATURAL_32
carry: CELL [NATURAL_32]
do
create carry.put (0)
b := b_a
mp := m.item
mn := m.count.abs
if mn = 0 then
(create {DIVIDE_BY_ZERO}).raise
end
es := e.count
if es = 0 then
if mn = 1 and mp [mp_offset] = 1 then
r.count := 0
else
r.count := 1
end
r.item [0] := 1
else
if es < 0 then
create new_b.make_limbs (mn + 1)
if not invert (new_b, b, m) then
(create {INVERSE_EXCEPTION}).raise
end
b := new_b
es := -es
end
en := es
use_redc := (mn < 170) and (mp [mp_offset] \\ 2 /= 0)
if use_redc then
invm := modlimb_invert (mp [mp_offset])
invm := 0 - invm
else
m_zero_cnt := leading_zeros (mp [mp_offset + mn - 1])
if m_zero_cnt /= 0 then
create new_mp.make_filled (0, mn)
lshift (new_mp, new_mp_offset, mp, mp_offset, mn, m_zero_cnt, carry)
junk := carry.item
mp := new_mp
mp_offset := new_mp_offset
end
end
e_zero_cnt := leading_zeros (e.item [en - 1])
enb := en * limb_bits - e_zero_cnt
small_k := 1
big_k := 2
from
until
small_k = 10 or 2 * enb <= big_k * (2 + small_k * (3 + small_k))
loop
small_k := small_k + 1
big_k := big_k * 2
end
create tp.make_filled (0, 2 * mn)
create qp.make_filled (0, mn + 1)
create gp.make_filled (0, big_k // 2 * mn)
bn := b.count.abs
bp := b.item
if bn > mn or (bn = mn and cmp_special (bp, bp_offset, mp, mp_offset, mn) >= 0) then
if use_redc then
reduce (tp, tp_offset + mn, bp, bp_offset, bn, mp, mp_offset, mn)
tp.fill_with (0, tp_offset, mn - tp_offset - 1)
tdiv_qr_special (qp, qp_offset, gp, gp_offset, tp, tp_offset, 2 * mn, mp, mp_offset, mn)
else
reduce (gp, gp_offset, bp, bp_offset, bn, mp, mp_offset, mn)
end
else
if use_redc then
tp.copy_data (bp, bp_offset, tp_offset + mn, bn)
tdiv_qr_special (qp, qp_offset, gp, gp_offset, tp, tp_offset, 2 * mn, mp, mp_offset, mn)
else
gp.copy_data (bp, bp_offset, gp_offset, bn)
gp.fill_with (0, gp_offset + bn, mn - bn - gp_offset - 1)
end
end
create xp.make_filled (0, mn)
sqr_n (tp, tp_offset, gp, gp_offset, mn)
if use_redc then
redc_basecase (xp, xp_offset, mp, mp_offset, mn, invm, tp, tp_offset)
else
tdiv_qr_special (qp, qp_offset, xp, xp_offset, tp, tp_offset, 2 * mn, mp, mp_offset, mn)
end
this_gp := gp
this_gp_offset := gp_offset
from
i := 1
until
i >= big_k // 2
loop
mul_n (tp, tp_offset, this_gp, this_gp_offset, xp, xp_offset, mn)
this_gp_offset := this_gp_offset + mn
if use_redc then
redc_basecase (this_gp, this_gp_offset, mp, mp_offset, mn, invm, tp, tp_offset)
else
tdiv_qr_special (qp, qp_offset, this_gp, this_gp_offset, tp, tp_offset, 2 * mn, mp, mp_offset, mn)
end
i := i + 1
end
ep := e.item
i := en - 1
c := ep [ep_offset + i]
sh := limb_bits - e_zero_cnt
sh := sh - small_k
if sh < 0 then
if i > 0 then
i := i - 1
c := c |<< (-sh)
sh := sh + limb_bits
c := c.bit_or (ep [ep_offset + i] |>> sh)
end
else
c := c |>> sh
end
from
j := 0
until
c \\ 2 /= 0
loop
c := c |>> 1
j := j + 1
end
xp.copy_data (gp, gp_offset + mn * (c |>> 1).to_integer_32, xp_offset, mn)
from
j := j - 1
until
j < 0
loop
sqr_n (tp, tp_offset, xp, xp_offset, mn)
if use_redc then
redc_basecase (xp, xp_offset, mp, mp_offset, mn, invm, tp, tp_offset)
else
tdiv_qr_special (qp, qp_offset, xp, xp_offset, tp, tp_offset, 2 * mn, mp, mp_offset, mn)
end
j := j - 1
end
from
until
i <= 0 and sh <= 0
loop
c := ep [ep_offset + i]
l := small_k
sh := sh - l
if sh < 0 then
if i > 0 then
i := i - 1
c := c |<< (-sh)
sh := sh + limb_bits
c := c.bit_or (ep [ep_offset + i] |>> sh)
else
l := l + sh
end
else
c := c |>> sh
end
c := c.bit_and (((1).to_natural_32 |<< l) - 1)
from
until
(c |>> (l - 1)) /= 0 or (i <= 0 and sh <= 0)
loop
sqr_n (tp, tp_offset, xp, xp_offset, mn)
if use_redc then
redc_basecase (xp, xp_offset, mp, mp_offset, mn, invm, tp, tp_offset)
else
tdiv_qr_special (qp, qp_offset, xp, xp_offset, tp, tp_offset, 2 * mn, mp, mp_offset, mn)
end
if sh /= 0 then
sh := sh - 1
c := (c |<< 1) + ((ep [ep_offset + i] |>> sh).bit_and (1))
else
i := i - 1
sh := limb_bits - 1
c := (c |<< 1) + (ep [ep_offset + i] |>> sh)
end
end
if c /= 0 then
from
j := 0
until
c \\ 2 /= 0
loop
c := c |>> 1
j := j + 1
end
l := l - j
from
l := l - 1
until
l < 0
loop
sqr_n (tp, tp_offset, xp, xp_offset, mn)
if use_redc then
redc_basecase (xp, xp_offset, mp, mp_offset, mn, invm, tp, tp_offset)
else
tdiv_qr_special (qp, qp_offset, xp, xp_offset, tp, tp_offset, 2 * mn, mp, mp_offset, mn)
end
l := l - 1
end
mul_n (tp, tp_offset, xp, xp_offset, gp, gp_offset + mn * (c |>> 1).to_integer_32, mn)
if use_redc then
redc_basecase (xp, xp_offset, mp, mp_offset, mn, invm, tp, tp_offset)
else
tdiv_qr_special (qp, qp_offset, xp, xp_offset, tp, tp_offset, 2 * mn, mp, mp_offset, mn)
end
else
j := l
end
from
j := j - 1
until
j < 0
loop
sqr_n (tp, tp_offset, xp, xp_offset, mn)
if use_redc then
redc_basecase (xp, xp_offset, mp, mp_offset, mn, invm, tp, tp_offset)
else
tdiv_qr_special (qp, qp_offset, xp, xp_offset, tp, tp_offset, 2 * mn, mp, mp_offset, mn)
end
j := j - 1
end
end
if use_redc then
tp.copy_data (xp, xp_offset, tp_offset, mn)
tp.fill_with (0, tp_offset + mn, tp_offset + mn + mn - 1)
redc_basecase (xp, xp_offset, mp, mp_offset, mn, invm, tp, tp_offset)
if cmp_special (xp, xp_offset, mp, mp_offset, mn) >= 0 then
sub_n (xp, xp_offset, xp, xp_offset, mp, mp_offset, mn, carry)
junk := carry.item
end
else
if m_zero_cnt /= 0 then
lshift (tp, tp_offset, xp, xp_offset, mn, m_zero_cnt, carry)
cy := carry.item
tp [tp_offset + mn] := cy
tdiv_qr_special (qp, qp_offset, xp, xp_offset, tp, tp_offset, mn + (cy /= 0).to_integer, mp, mp_offset, mn)
rshift (xp, xp_offset, xp, xp_offset, mn, m_zero_cnt, carry)
junk := carry.item
end
end
xn := mn
xn := normalize (xp, xp_offset, xn)
if ep [ep_offset].bit_and (1) /= 0 and b.count < 0 and xn /= 0 then
mp := m.item
sub_special (xp, xp_offset, mp, mp_offset, mn, xp, xp_offset, xn, carry)
junk := carry.item
xn := mn
xn := normalize (xp, xp_offset, xn)
end
r.resize (xn)
r.count := xn
r.item.copy_data (xp, xp_offset, 0, xn)
end
end
powm_ui (target: READABLE_INTEGER_X; b: READABLE_INTEGER_X; el: NATURAL_32; m: READABLE_INTEGER_X)
local
xp: SPECIAL [NATURAL_32]
xp_offset: INTEGER
tp: SPECIAL [NATURAL_32]
tp_offset: INTEGER
qp: SPECIAL [NATURAL_32]
qp_offset: INTEGER
mp: SPECIAL [NATURAL_32]
mp_offset: INTEGER
bp: SPECIAL [NATURAL_32]
bp_offset: INTEGER
xn: INTEGER
tn: INTEGER
mn: INTEGER
bn: INTEGER
m_zero_count: INTEGER
c: INTEGER
e: NATURAL_32
new_mp: SPECIAL [NATURAL_32]
junk: NATURAL_32
new_bp: SPECIAL [NATURAL_32]
cy: NATURAL_32
carry: CELL [NATURAL_32]
do
create carry.put (0)
mp := m.item
mn := m.count.abs
if mn = 0 then
(create {DIVIDE_BY_ZERO}).raise
end
if el = 0 then
target.count := (not (mn = 1 and then mp [mp_offset] = 1)).to_integer
target.item [0] := 1
else
m_zero_count := leading_zeros (mp [mp_offset + mn - 1])
if m_zero_count /= 0 then
create new_mp.make_filled (0, mn)
lshift (new_mp, 0, mp, mp_offset, mn, m_zero_count, carry)
junk := carry.item
mp := new_mp
end
bn := b.count.abs
bp := b.item
if bn > mn then
create new_bp.make_filled (0, mn)
reduce (new_bp, 0, bp, bp_offset, bn, mp, mp_offset, mn)
bp := new_bp
bn := mn
bn := normalize (bp, 0, bn)
end
if bn = 0 then
target.count := 0
else
create tp.make_filled (0, 2 * mn + 1)
create xp.make_filled (0, mn)
create qp.make_filled (0, mn + 1)
xp.copy_data (bp, bp_offset, xp_offset, bn)
xn := bn
e := el
c := leading_zeros (e)
e := (e |<< c) |<< 1
c := limb_bits - 1 - c
if c = 0 and then xn = mn and cmp_special (xp, xp_offset, mp, mp_offset, mn) >= 0 then
sub_n (xp, xp_offset, xp, xp_offset, mp, mp_offset, mn, carry)
junk := carry.item
else
from
until
c = 0
loop
sqr_n (tp, tp_offset, xp, xp_offset, xn)
tn := 2 * xn
tn := tn - (tp [tp_offset + tn - 1] = 0).to_integer
if tn < mn then
xp.copy_data (tp, tp_offset, xp_offset, tn)
xn := tn
else
tdiv_qr_special (qp, qp_offset, xp, xp_offset, tp, tp_offset, tn, mp, mp_offset, mn)
xn := mn
end
if e.to_integer_32 < 0 then
mul_special (tp, tp_offset, xp, xp_offset, xn, bp, bp_offset, bn, carry)
junk := carry.item
tn := xn + bn
tn := tn - (tp [tp_offset + tn - 1] = 0).to_integer
if tn < mn then
xp.copy_data (tp, tp_offset, xp_offset, tn)
xn := tn
else
tdiv_qr_special (qp, qp_offset, xp, xp_offset, tp, tp_offset, tn, mp, mp_offset, mn)
xn := mn
end
end
e := e |<< 1
c := c - 1
end
end
if m_zero_count /= 0 then
lshift (tp, tp_offset, xp, xp_offset, xn, m_zero_count, carry)
cy := carry.item
tp [tp_offset + xn] := cy
xn := xn + (cy /= 0).to_integer
if xn < mn then
xp.copy_data (tp, tp_offset, xp_offset, xn)
else
tdiv_qr_special (qp, qp_offset, xp, xp_offset, tp, tp_offset, xn, mp, mp_offset, mn)
xn := mn
end
rshift (xp, xp_offset, xp, xp_offset, xn, m_zero_count, carry)
junk := carry.item
end
xn := normalize (xp, xp_offset, xn)
if el.bit_test (0) and b.count < 0 and xn /= 0 then
mp := m.item
mp_offset := 0
sub_special (xp, xp_offset, mp, mp_offset, mn, xp, xp_offset, xn, carry)
junk := carry.item
xn := mn
xn := normalize (xp, xp_offset, xn)
end
target.resize (xn)
target.count := xn
target.item.copy_data (xp, xp_offset, 0, xn)
end
end
end
probab_prime_isprime (t: NATURAL_32): BOOLEAN
local
q: NATURAL_32
r: NATURAL_32
d: NATURAL_32
do
if t < 3 or not t.bit_test (0) then
Result := t = 2
else
from
d := 3
r := 1
q := d
until
Result or r = 0
loop
q := t // d
r := t - q * d
Result := (q < d)
d := d + 2
end
end
end
probab_prime_p (op1_a: READABLE_INTEGER_X; reps: INTEGER): INTEGER
local
r: NATURAL_32
n2: INTEGER_X
is_prime: BOOLEAN
op1: READABLE_INTEGER_X
done: BOOLEAN
ln2: NATURAL_32
q: NATURAL_32
p1: CELL [NATURAL_32]
p0: CELL [NATURAL_32]
p: NATURAL_32
primes: SPECIAL [NATURAL_32]
nprimes: INTEGER
do
create p1.put (0)
create p0.put (0)
create primes.make_filled (0, 15)
op1 := op1_a
create n2
if cmp_ui (op1, 1_000_000) <= 0 then
if cmpabs_ui (op1, 1_000_000) <= 0 then
is_prime := probab_prime_isprime (op1.as_natural_32)
if is_prime then
Result := 2
else
Result := 0
end
done := True
else
n2.item := op1.item
n2.count := -op1.count
op1 := n2
end
end
if not done then
if not op1.as_natural_32.bit_test (0) then
done := True
end
end
if not done then
r := preinv_mod_1 (op1.item, 0, op1.count, pp, pp_inverted)
if r \\ 3 = 0 or r \\ 5 = 0 or r \\ 7 = 0 or r \\ 11 = 0 or r \\ 13 = 0 or r \\ 17 = 0 or r \\ 19 = 0 or r \\ 23 = 0 or r \\ 29 = 0 then
Result := 0
done := True
end
end
if not done then
nprimes := 0
p := 1
ln2 := sizeinbase (op1, 2).to_natural_32
from
q := pp_first_omitted.to_natural_32
until
q >= ln2 or done
loop
if probab_prime_isprime (q) then
umul_ppmm (p1, p0, p, q)
if p1.item /= 0 then
r := modexact_1c_odd (op1.item, 0, op1.count, p, 0)
from
nprimes := nprimes - 1
until
nprimes < 0 or done
loop
if r \\ primes [nprimes] = 0 then
Result := 0
done := True
end
nprimes := nprimes - 1
end
p := q
nprimes := 0
else
p := p0.item
end
primes [nprimes] := q
nprimes := nprimes + 1
end
q := q + 2
end
end
if not done then
Result := millerrabin (op1, reps)
end
end
pp: NATURAL_32 = 0xC0CFD797
pp_inverted: NATURAL_32 = 0x53E5645C
pp_first_omitted: INTEGER = 31
reduce (target: SPECIAL [NATURAL_32]; target_offset: INTEGER; ap: SPECIAL [NATURAL_32]; ap_offset: INTEGER; ap_count: INTEGER; mp: SPECIAL [NATURAL_32]; mp_offset: INTEGER; mp_count: INTEGER)
local
tmp: SPECIAL [NATURAL_32]
do
create tmp.make_filled (0, ap_count - mp_count + 1)
tdiv_qr_special (tmp, 0, target, target_offset, ap, ap_offset, ap_count, mp, mp_offset, mp_count)
end
muldiv (target: READABLE_INTEGER_X; inc: INTEGER_32; rsize: CELL [INTEGER_32]; ralloc: CELL [INTEGER_32]; nacc: CELL [NATURAL_32]; kacc: CELL [NATURAL_32])
local
new_ralloc: INTEGER_32
carry: CELL [NATURAL_32]
do
create carry.put (0)
if rsize.item <= ralloc.item then
new_ralloc := ralloc.item + inc
target.resize (new_ralloc)
ralloc.put (new_ralloc)
end
mul_1 (target.item, 0, target.item, 0, rsize.item, nacc.item, carry)
target.item [rsize.item] := carry.item
divexact_1 (target.item, 0, target.item, 0, rsize.item + 1, kacc.item)
if target.item [rsize.item] /= 0 then
rsize.put (rsize.item + 1)
end
end
invert_gf (target: READABLE_INTEGER_X op1: READABLE_INTEGER_X op2: READABLE_INTEGER_X)
require
not op1.is_negative
not op2.is_negative
local
target_special: SPECIAL [NATURAL_32]
op2_count: INTEGER
do
target.resize (op2.count)
op2_count := op2.count
target_special := target.item
invert_gf_special (target_special, 0, op1.item, 0, op1.count, op2.item, 0, op2_count)
target.count := normalize (target_special, 0, op2_count)
end
end

View File

@@ -0,0 +1,108 @@
note
description: "Summary description for {INTEGER_X_RANDOM}."
author: "Colin LeMahieu"
date: "$Date$"
revision: "$Revision$"
quote: "Letting lawyers make laws is like letting doctors make diseases. - Anonymous"
deferred class
INTEGER_X_RANDOM
inherit
INTEGER_X_FACILITIES
LIMB_MANIPULATION
SPECIAL_COMPARISON
SPECIAL_ARITHMETIC
SPECIAL_UTILITY
feature
urandomb (target: READABLE_INTEGER_X; state: RANDOM_NUMBER_GENERATOR; nbits: INTEGER)
-- Generate a uniformly distributed random integer in the range 0 to 2^`n'-1, inclusive.
-- `state' must be initialized by calling one of the randinit functions before invoking this function.
local
size: INTEGER_32
do
size := bits_to_limbs (nbits)
target.resize (size)
state.randget (target.item, 0, nbits)
size := normalize (target.item, 0, size)
target.count := size
ensure
target.bits <= nbits
end
urandomm (target: READABLE_INTEGER_X; state: RANDOM_NUMBER_GENERATOR; n: READABLE_INTEGER_X)
-- Generate a uniform random integer in the range 0 to n-1, inclusive.
-- `state' must be initialized by calling one of the randinit functions before invoking this function.
local
rp: SPECIAL [NATURAL_32]
rp_offset: INTEGER
np: SPECIAL [NATURAL_32]
np_offset: INTEGER
nlast: INTEGER
nbits: INTEGER
size: INTEGER
count: INTEGER
pow2: BOOLEAN
cmp_l: INTEGER
overlap: BOOLEAN
junk: NATURAL_32
carry: CELL [NATURAL_32]
do
create carry.put (0)
size := n.count.abs
if size = 0 then
(create {DIVIDE_BY_ZERO}).raise
end
np := n.item
nlast := size - 1
pow2 := pow2_p (n.item [nlast])
if pow2 then
from
np := n.item
until
not pow2 or np_offset >= nlast
loop
if np [np_offset] /= 0 then
pow2 := False
end
np_offset := np_offset + 1
end
end
count := leading_zeros (np [nlast])
nbits := size * limb_bits - (count) - pow2.to_integer
if nbits = 0 then
target.count := 0
else
np := n.item
np_offset := 0
rp := target.item
rp_offset := 0
if np = rp then
overlap := True
create np.make_filled (0, size)
np.copy_data (n.item, 0, 0, size)
end
target.resize (size)
rp := target.item
rp [rp_offset + size - 1] := 0
count := 80
from
cmp_l := 0
until
cmp_l < 0 or count = 0
loop
state.randget (rp, rp_offset, nbits)
cmp_l := cmp (rp, rp_offset, np, np_offset, size)
count := count - 1
end
if count = 0 then
sub_n (rp, rp_offset, rp, rp_offset, np, np_offset, size, carry)
junk := carry.item
end
size := normalize (rp, rp_offset, size)
target.count := size
end
end
end

View File

@@ -0,0 +1,49 @@
note
description: "Summary description for {INTEGER_X_SIZING}."
author: "Colin LeMahieu"
date: "$Date$"
revision: "$Revision$"
quote: "My freedom is more important than your great idea. - Anonymous"
deferred class
INTEGER_X_SIZING
inherit
INTEGER_X_FACILITIES
LIMB_BIT_SCANNING
LIMB_MANIPULATION
MP_BASES
feature
sizeinbase (op: READABLE_INTEGER_X; base: INTEGER): INTEGER_32
-- Return the size of `op' measured in number of digits in the given base.
-- `base' can vary from 2 to 62.
-- The sign of `op' is ignored, just the absolute value is used.
-- The result will be either exact or 1 too big.
-- If `base' is a power of 2, the result is always exact.
-- If `op' is zero the return value is always 1.
-- This function can be used to determine the space required when converting `op' to a string.
-- The right amount of allocation is normally two more than the value returned, one extra for
-- a minus sign and one for the null-terminator.
-- It will be noted that `sizeinbase(op,2)' can be used to locate the most significant 1
-- bit in `op', counting from 1. (Unlike the bitwise functions which start from 0.
local
lb_base: NATURAL_32
cnt: INTEGER_32
totbits: INTEGER_32
do
if op.count.abs = 0 then
Result := 1
else
cnt := leading_zeros (op.item [op.count.abs - 1])
totbits := op.count.abs * limb_bits - cnt
if pow2_p (base.to_natural_32) then
lb_base := big_base (base)
Result := (totbits + lb_base.to_integer_32 - 1) // lb_base.to_integer_32
else
Result := ((totbits.to_double * chars_per_bit_exactly (base)) + 1).truncated_to_integer
end
end
end
end

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,32 @@
note
description: "Summary description for {POWERS}."
author: "Colin LeMahieu"
date: "$Date$"
revision: "$Revision$"
quote: "Giving a politician access to your wallet is like giving a dog access to your refrigerator. - Tim Barber"
class
POWERS
create
make
feature
make (digits_in_base_a: INTEGER; p_a: SPECIAL [NATURAL_32]; p_offset_a: INTEGER; n_a: INTEGER; base_a: INTEGER)
do
digits_in_base := digits_in_base_a
p := p_a
p_offset := p_offset_a
n := n_a
base := base_a
end
feature
digits_in_base: INTEGER
p: SPECIAL [NATURAL_32]
p_offset: INTEGER
n: INTEGER
base: INTEGER
end

View File

@@ -0,0 +1,44 @@
note
description: "Summary description for {RAND_LC_STRUCT}."
author: "Colin LeMahieu"
date: "$Date$"
revision: "$Revision$"
quote: "Everyone wants to save the planet but no one wants to help Mom clean the dishes. - P.J. O'Rourke, in All the Trouble in the World "
class
RAND_LC_STRUCT
inherit
INTEGER_X_DIVISION
LIMB_MANIPULATION
create
make
feature
make (m2exp_a: INTEGER; a_a: READABLE_INTEGER_X; seedn: INTEGER; c: NATURAL_32)
do
create cp.make_filled (0, 1)
m2exp := m2exp_a
create seed.make_limbs (bits_to_limbs (m2exp))
seed.count := seedn
seed.item [0] := 1
create a
fdiv_r_2exp (a, a_a, m2exp)
if a.count = 0 then
a.count := 1
a.item [0] := 0
end
cp [0] := c
cn := (c /= 0).to_integer
end
feature
seed: INTEGER_X
a: INTEGER_X
cn: INTEGER
cp: SPECIAL [NATURAL_32]
m2exp: INTEGER
end

View File

@@ -0,0 +1,262 @@
note
description: "Summary description for {NUMBER_ACCESS}."
author: "Colin LeMahieu"
date: "$Date$"
revision: "$Revision$"
quote: "State-mandated compassion produces, not love for ones fellow man, but hatred and resentment. - Lizard"
deferred class
SPECIAL_ACCESS
inherit
LIMB_MANIPULATION
MP_BASES
SPECIAL_ARITHMETIC
SPECIAL_DIVISION
feature
dc_get_str (target_a: STRING_8; target_offset_a: INTEGER; len_a: INTEGER; op1: SPECIAL [NATURAL_32]; op1_offset: INTEGER; op1_count: INTEGER; powtab: SPECIAL [POWERS]; powtab_offset: INTEGER; tmp: SPECIAL [NATURAL_32]; tmp_offset: INTEGER): INTEGER
local
target: STRING_8
len: INTEGER
pwp: SPECIAL [NATURAL_32]
pwp_offset: INTEGER
qp: SPECIAL [NATURAL_32]
qp_offset: INTEGER
rp: SPECIAL [NATURAL_32]
rp_offset: INTEGER
pwn: INTEGER
qn: INTEGER
target_offset: INTEGER
do
target := target_a
len := len_a
target_offset := target_offset_a
if op1_count < 15 then
if op1_count /= 0 then
target_offset := sb_get_str (target, target_offset, len, op1, op1_offset, op1_count, powtab, powtab_offset)
else
from
until
len /= 0
loop
target [target_offset] := '%U'
target_offset := target_offset + 1
len := len - 1
end
end
else
pwp := powtab [powtab_offset].p
pwn := powtab [powtab_offset].n
if op1_count < pwn or (op1_count = pwn and cmp (op1, op1_offset, pwp, pwp_offset, op1_count) < 0) then
target_offset := dc_get_str (target, target_offset, len, op1, op1_offset, op1_count, powtab, powtab_offset - 1, tmp, tmp_offset)
else
qp := tmp
qp_offset := tmp_offset
rp := op1
rp_offset := op1_offset
tdiv_qr (qp, qp_offset, rp, rp_offset, op1, op1_offset, op1_count, pwp, pwp_offset, pwn)
qn := op1_count - pwn
qn := qn + (qp [qp_offset + qn] /= 0).to_integer
if len /= 0 then
len := len - powtab [powtab_offset].digits_in_base
end
target_offset := dc_get_str (target, target_offset, len, qp, qp_offset, qn, powtab, powtab_offset - 1, tmp, tmp_offset + op1_count - pwn + 1)
target_offset := dc_get_str (target, target_offset, powtab [powtab_offset].digits_in_base, rp, rp_offset, pwn, powtab, powtab_offset - 1, tmp, tmp_offset)
end
end
Result := target_offset
end
get_str (target: STRING_8; target_offset: INTEGER; base: INTEGER; op1: SPECIAL [NATURAL_32]; op1_offset: INTEGER; op1_count: INTEGER): INTEGER
local
powtab_mem_ptr: SPECIAL [NATURAL_32]
powtab_mem_ptr_offset: INTEGER
big_base_l: NATURAL_32
digits_in_base: INTEGER
powtab: SPECIAL [POWERS]
pi: INTEGER
n: INTEGER
t: INTEGER
p: SPECIAL [NATURAL_32]
p_offset: INTEGER
n1: NATURAL_32
n0: NATURAL_32
bits_per_digit: INTEGER
count: INTEGER
bit_pos: INTEGER
i: INTEGER
s: INTEGER
bits: INTEGER
do
if op1_count = 0 then
target [target_offset] := '%U'
Result := 1
else
if pow2_p (base.to_natural_32) then
bits_per_digit := big_base (base).to_integer_32
s := target_offset
n1 := op1 [op1_offset + op1_count - 1]
count := leading_zeros (n1)
bits := limb_bits * op1_count - count
count := bits \\ bits_per_digit
if count /= 0 then
bits := bits + bits_per_digit - count
end
bit_pos := bits - (op1_count - 1) * limb_bits
from
i := op1_count - 1
until
i < 0
loop
bit_pos := bit_pos - bits_per_digit
from
until
bit_pos < 0
loop
target [s] := ((n1 |>> bit_pos).bit_and (((1).to_natural_32 |<< bits_per_digit) - 1)).to_character_8
s := s + 1
bit_pos := bit_pos - bits_per_digit
end
i := i - 1
if i >= 0 then
n0 := (n1 |<< -bit_pos).bit_and (((1).to_natural_32 |<< bits_per_digit) - 1)
n1 := op1 [op1_offset + i]
bit_pos := bit_pos + limb_bits
target [s] := (n0.bit_or (n1 |>> bit_pos)).to_character_8
s := s + 1
end
end
Result := s - target_offset
else
if op1_count < 30 then
create powtab.make_empty (1)
create p.make_empty (0)
powtab.extend (create {POWERS}.make (0, p, 0, 0, base))
Result := sb_get_str (target, target_offset, 0, op1, op1_offset, op1_count, powtab, 0)
else
create powtab_mem_ptr.make_filled (0, 2 * op1_count + 30)
big_base_l := big_base (base)
digits_in_base := chars_per_limb (base)
create powtab.make_empty (30)
create p.make_filled (0, 0)
powtab.extend (create {POWERS}.make (0, p, 0, 0, base))
create p.make_filled (big_base_l, 1)
powtab.extend (create {POWERS}.make (digits_in_base, p, 0, 1, base))
create p.make_filled (big_base_l, 1)
powtab.extend (create {POWERS}.make (digits_in_base, p, 0, 1, base))
n := 1
pi := 2
create p.make_filled (big_base_l, 1)
p_offset := 0
from
until
2 * n > op1_count
loop
pi := pi + 1
t := powtab_mem_ptr_offset
powtab_mem_ptr_offset := powtab_mem_ptr_offset + 2 * n
sqr_n (powtab_mem_ptr, t, p, p_offset, n)
n := n * 2
n := n - (powtab_mem_ptr [t + n - 1] = 0).to_integer
digits_in_base := digits_in_base * 2
powtab_mem_ptr_offset := t
powtab.extend (create {POWERS}.make (digits_in_base, p, 0, n, base))
end
end
end
end
end
sb_get_str (target: STRING_8; target_offset_a: INTEGER; len_a: INTEGER; op1: SPECIAL [NATURAL_32]; op1_offset: INTEGER; op1_count_a: INTEGER; powtab: SPECIAL [POWERS]; powtab_offset: INTEGER): INTEGER
local
rl: CELL [NATURAL_32]
ul: CELL [NATURAL_32]
s: INTEGER
base: INTEGER
l: INTEGER
buf: SPECIAL [NATURAL_8]
buf_offset: INTEGER
rp: SPECIAL [NATURAL_32]
rp_offset: INTEGER
buff_alloc: INTEGER
op1_count: INTEGER
i: INTEGER
frac: CELL [NATURAL_32]
digit: CELL [NATURAL_32]
junk: NATURAL_32
chars_per_limb_l: INTEGER
big_base_l: NATURAL_32
big_base_inverted_l: NATURAL_32
normalization_steps: INTEGER
target_offset: INTEGER
len: INTEGER
do
create digit.put (0)
create frac.put (0)
create ul.put (0)
create rl.put (0)
len := len_a
target_offset := target_offset_a
op1_count := op1_count_a
buff_alloc := 30 * 8 * 4 * 7 // 11
create buf.make_filled (0, buff_alloc)
create rp.make_filled (0, 30)
base := powtab [powtab_offset].base
chars_per_limb_l := chars_per_limb (base)
big_base_l := big_base (base)
big_base_inverted_l := big_base_inverted (base)
normalization_steps := leading_zeros (big_base_l)
rp.copy_data (op1, op1_offset, rp_offset + 1, op1_count)
s := buf_offset + buff_alloc
from
until
op1_count <= 1
loop
junk := preinv_divrem_1 (rp, rp_offset, 1, rp, rp_offset + 1, op1_count, big_base_l, big_base_inverted_l, normalization_steps)
op1_count := op1_count - (rp [rp_offset + op1_count] = 0).to_integer
frac.put (rp [rp_offset] + 1)
s := s - chars_per_limb_l
i := chars_per_limb_l
from
until
i = 0
loop
umul_ppmm (digit, frac, frac.item, base.to_natural_32)
buf [s] := digit.item.to_natural_8
s := s + 1
i := i - 1
end
s := s - chars_per_limb_l
end
ul.put (rp [rp_offset + 1])
from
until
ul.item = 0
loop
udiv_qrnd_unnorm (ul, rl, ul.item, base.to_natural_32)
s := s - 1
buf [s] := rl.item.to_natural_8
end
l := buf_offset + buff_alloc - s
from
until
l >= len
loop
target [target_offset] := '%U'
target_offset := target_offset + 1
len := len - 1
end
from
until
l = 0
loop
target [target_offset] := buf [s].to_character_8
s := s + 1
target_offset := target_offset + 1
l := l - 1
end
Result := target_offset - target_offset_a
end
end

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,159 @@
note
description: "Summary description for {NUMBER_ASSIGNMENT}."
author: "Colin LeMahieu"
date: "$Date$"
revision: "$Revision$"
quote: "Concentrated political power is the most dangerous thing on earth. - Rudolph Rummel"
deferred class
SPECIAL_ASSIGNMENT
inherit
MP_BASES
LIMB_MANIPULATION
SPECIAL_ARITHMETIC
feature
set_str (target: SPECIAL [NATURAL_32]; target_offset: INTEGER; str: SPECIAL [NATURAL_8]; str_offset_a: INTEGER; str_len: INTEGER; base: INTEGER): INTEGER
require
base >= 2
-- str_len >= 1
local
str_offset: INTEGER
size: INTEGER
big_base_l: NATURAL_32
chars_per_limb_l: INTEGER
res_digit: NATURAL_32
s: INTEGER
next_bitpos: INTEGER
bits_per_indigit: INTEGER
inp_digit: NATURAL_8
i: INTEGER
j: INTEGER
cy_limb: NATURAL_32
carry: CELL [NATURAL_32]
do
create carry.put (0)
str_offset := str_offset_a
big_base_l := big_base (base)
chars_per_limb_l := chars_per_limb (base)
size := 0
if pow2_p (base.to_natural_32) then
bits_per_indigit := big_base_l.to_integer_32
res_digit := 0
next_bitpos := 0
from
s := str_offset + str_len - 1
until
s < str_offset
loop
inp_digit := str [s]
res_digit := res_digit.bit_or (inp_digit.to_natural_32 |<< next_bitpos)
next_bitpos := next_bitpos + bits_per_indigit
if next_bitpos >= limb_bits then
target [target_offset + size] := res_digit
size := size + 1
next_bitpos := next_bitpos - limb_bits
res_digit := inp_digit |>> (bits_per_indigit - next_bitpos)
end
s := s - 1
end
if res_digit /= 0 then
target [target_offset + size] := res_digit
size := size + 1
end
Result := size
else
if str_len < str_len.max_value then
from
i := chars_per_limb_l
until
i >= str_len
loop
res_digit := str [str_offset]
str_offset := str_offset + 1
if base = 10 then
from
j := 9 - 1
until
j = 0
loop
res_digit := res_digit * 10 + str [str_offset].to_natural_32
str_offset := str_offset + 1
j := j - 1
end
else
from
j := chars_per_limb_l - 1
until
j = 0
loop
res_digit := res_digit * base.to_natural_32 + str [str_offset].to_natural_32
str_offset := str_offset + 1
j := j - 1
end
end
if size = 0 then
if res_digit /= 0 then
target [target_offset] := res_digit
size := 1
end
else
mul_1 (target, target_offset, target, target_offset, size, big_base_l, carry)
cy_limb := carry.item
add_1 (target, target_offset, target, target_offset, size, res_digit, carry)
cy_limb := cy_limb + carry.item
if cy_limb /= 0 then
target [target_offset + size] := cy_limb
size := size + 1
end
end
i := i + chars_per_limb_l
end
big_base_l := base.to_natural_32
res_digit := str [str_offset]
str_offset := str_offset + 1
if base = 10 then
from
j := str_len - (i - 9) - 1
until
j <= 0
loop
res_digit := res_digit * 10 + str [str_offset]
str_offset := str_offset + 1
big_base_l := big_base_l * 10
j := j - 1
end
else
from
j := str_len - (i - chars_per_limb_l) - 1
until
j <= 0
loop
res_digit := res_digit * base.to_natural_32 + str [str_offset].to_natural_32
str_offset := str_offset + 1
big_base_l := big_base_l * base.to_natural_32
j := j - 1
end
end
if size = 0 then
if res_digit /= 0 then
target [target_offset] := res_digit
size := 1
end
else
mul_1 (target, target_offset, target, target_offset, size, big_base_l, carry)
cy_limb := carry.item
add_1 (target, target_offset, target, target_offset, size, res_digit, carry)
cy_limb := cy_limb + carry.item
if cy_limb /= 0 then
target [target_offset + size] := cy_limb
size := size + 1
end
end
Result := size
end
end
end
end

View File

@@ -0,0 +1,39 @@
note
description: "Summary description for {NUMBER_COMPARISON}."
author: "Colin LeMahieu"
date: "$Date$"
revision: "$Revision$"
quote: "No nation was ever ruined by trade. - Benjamin Franklin"
deferred class
SPECIAL_COMPARISON
feature
cmp (op1: SPECIAL [NATURAL_32]; op1_offset: INTEGER; op2: SPECIAL [NATURAL_32]; op2_offset: INTEGER; size: INTEGER): INTEGER
local
i: INTEGER
x: NATURAL_32
y: NATURAL_32
do
Result := 0
from
i := size - 1
until
i < 0 or Result /= 0
loop
x := op1 [op1_offset + i]
y := op2 [op2_offset + i]
if x /= y then
if x > y then
Result := 1
else
Result := -1
end
end
i := i - 1
variant
i + 2
end
end
end

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,332 @@
note
description: "Summary description for {NUMBER_LOGIC}."
author: "Colin LeMahieu"
date: "$Date$"
revision: "$Revision$"
quote: "It is a free market that makes monopolies impossible. - Ayn Rand"
deferred class
SPECIAL_LOGIC
inherit
LIMB_MANIPULATION
feature
com_n (target: SPECIAL [NATURAL_32]; target_offset_a: INTEGER; op1: SPECIAL [NATURAL_32]; op1_offset_a: INTEGER; op1_count_a: INTEGER)
require
op1_count_a >= 1
local
target_offset: INTEGER
op1_offset: INTEGER
op1_count: INTEGER
do
target_offset := target_offset_a
op1_offset := op1_offset_a
op1_count := op1_count_a
from
until
op1_count = 0
loop
target [target_offset] := op1 [op1_offset].bit_not
target_offset := target_offset + 1
op1_offset := op1_offset + 1
op1_count := op1_count - 1
end
end
hamdist (op1: SPECIAL [NATURAL_32]; op1_offset_a: INTEGER; op2: SPECIAL [NATURAL_32]; op2_offset_a: INTEGER; n_a: INTEGER): INTEGER
local
p0: NATURAL_32
p1: NATURAL_32
p2: NATURAL_32
p3: NATURAL_32
x: NATURAL_32
p01: NATURAL_32
p23: NATURAL_32
i: INTEGER
op1_offset: INTEGER
n: INTEGER
op2_offset: INTEGER
do
op2_offset := op2_offset_a
n := n_a
op1_offset := op1_offset_a
from
i := n |>> 2
until
i = 0
loop
p0 := op1 [op1_offset].bit_xor (op2 [op2_offset])
p0 := p0 - (p0 |>> 1).bit_and (limb_max // 3)
p0 := (p0 |>> 2).bit_and (limb_max // 5) + p0.bit_and (limb_max // 5)
p1 := op1 [op1_offset + 1].bit_xor (op2 [op2_offset + 1])
p1 := p1 - (p1 |>> 1).bit_and (limb_max // 3)
p1 := (p1 |>> 2).bit_and (limb_max // 5) + p1.bit_and (limb_max // 5)
p01 := p0 + p1
p01 := (p01 |>> 4).bit_and (limb_max // 17) + p01.bit_and (limb_max // 17)
p2 := op1 [op1_offset + 2].bit_xor (op2 [op2_offset + 2])
p2 := p2 - (p2 |>> 1).bit_and (limb_max // 3)
p2 := (p2 |>> 2).bit_and (limb_max // 5) + p2.bit_and (limb_max // 5)
p3 := op1 [op1_offset + 3].bit_xor (op2 [op2_offset + 3])
p3 := p3 - (p3 |>> 1).bit_and (limb_max // 3)
p3 := (p3 |>> 2).bit_and (limb_max // 5) + p3.bit_and (limb_max // 5)
p23 := p2 + p3
p23 := (p23 |>> 4).bit_and (limb_max // 17) + p23.bit_and (limb_max // 17)
x := p01 + p23
x := (x |>> 8) + x
x := (x |>> 16) + x
Result := Result + x.bit_and (0xff).to_integer_32
op1_offset := op1_offset + 4
op2_offset := op2_offset + 4
i := i - 1
end
n := n.bit_and (3)
if n /= 0 then
x := 0
from
until
n = 0
loop
p0 := op1 [op1_offset].bit_xor (op2 [op2_offset])
p0 := p0 - (p0 |>> 1).bit_and (limb_max // 3)
p0 := (p0 |>> 2).bit_and (limb_max // 5) + p0.bit_and (limb_max // 5)
p0 := ((p0 |>> 4) | p0).bit_and (limb_max // 17)
x := x + p0
op1_offset := op1_offset + 1
op2_offset := op2_offset + 1
n := n - 1
end
x := (x |>> 8) + x
x := (x |>> 16) + x
Result := Result + x.bit_and (0xff).to_integer_32
end
end
lshift (target: SPECIAL [NATURAL_32]; target_offset: INTEGER_32; op1: SPECIAL [NATURAL_32]; op1_offset: INTEGER_32; n: INTEGER_32; count: INTEGER_32; carry: CELL [NATURAL_32])
require
target.valid_index (target_offset)
target.valid_index (target_offset + n - 1)
op1.valid_index (op1_offset)
op1.valid_index (op1_offset + n - 1)
count > 0
count < 32
local
high_limb: NATURAL_32
low_limb: NATURAL_32
tnc: INTEGER_32
i: INTEGER_32
up: INTEGER_32
rp: INTEGER_32
do
up := op1_offset + n
rp := target_offset + n
tnc := 32 - count
up := up - 1
low_limb := op1 [up]
carry.put (low_limb |>> tnc)
high_limb := low_limb |<< count
from
i := n - 1
until
i = 0
loop
up := up - 1
low_limb := op1 [up]
rp := rp - 1
target [rp] := high_limb.bit_or (low_limb |>> tnc)
high_limb := low_limb |<< count
i := i - 1
end
rp := rp - 1
target [rp] := high_limb
end
rshift (target: SPECIAL [NATURAL_32]; target_offset: INTEGER_32; op1: SPECIAL [NATURAL_32]; op1_offset: INTEGER_32; n: INTEGER_32; count: INTEGER_32; carry: CELL [NATURAL_32])
local
high_limb: NATURAL_32
low_limb: NATURAL_32
tnc: INTEGER_32
i: INTEGER_32
op1_cursor: INTEGER_32
target_cursor: INTEGER_32
do
tnc := 32 - count
op1_cursor := op1_offset
high_limb := op1 [op1_cursor]
op1_cursor := op1_cursor + 1
carry.put (high_limb |<< tnc)
low_limb := high_limb |>> count
from
i := n - 1
until
i = 0
loop
high_limb := op1 [op1_cursor]
op1_cursor := op1_cursor + 1
target [target_cursor] := low_limb.bit_or (high_limb |<< tnc)
target_cursor := target_cursor + 1
low_limb := high_limb |>> count
i := i - 1
end
target [target_cursor] := low_limb
end
popcount (op1: SPECIAL [NATURAL_32]; op1_offset_a: INTEGER; n_a: INTEGER): INTEGER
local
p0: NATURAL_32
p1: NATURAL_32
p2: NATURAL_32
p3: NATURAL_32
x: NATURAL_32
p01: NATURAL_32
p23: NATURAL_32
i: INTEGER
op1_offset: INTEGER
n: INTEGER
do
n := n_a
op1_offset := op1_offset_a
from
i := n |>> 2
until
i = 0
loop
p0 := op1 [op1_offset]
p0 := p0 - (p0 |>> 1).bit_and (limb_max // 3)
p0 := (p0 |>> 2).bit_and (limb_max // 5) + p0.bit_and (limb_max // 5)
p1 := op1 [op1_offset + 1]
p1 := p1 - (p1 |>> 1).bit_and (limb_max // 3)
p1 := (p1 |>> 2).bit_and (limb_max // 5) + p1.bit_and (limb_max // 5)
p01 := p0 + p1
p01 := (p01 |>> 4).bit_and (limb_max // 17) + p01.bit_and (limb_max // 17)
p2 := op1 [op1_offset + 2]
p2 := p2 - (p2 |>> 1).bit_and (limb_max // 3)
p2 := (p2 |>> 2).bit_and (limb_max // 5) + p2.bit_and (limb_max // 5)
p3 := op1 [op1_offset + 3]
p3 := p3 - (p3 |>> 1).bit_and (limb_max // 3)
p3 := (p3 |>> 2).bit_and (limb_max // 5) + p3.bit_and (limb_max // 5)
p23 := p2 + p3
p23 := (p23 |>> 4).bit_and (limb_max // 17) + p23.bit_and (limb_max // 17)
x := p01 + p23
x := (x |>> 8) + x
x := (x |>> 16) + x
Result := Result + x.bit_and (0xff).to_integer_32
op1_offset := op1_offset + 4
i := i - 1
end
n := n.bit_and (3)
if n /= 0 then
x := 0
from
until
n = 0
loop
p0 := op1 [op1_offset]
p0 := p0 - (p0 |>> 1).bit_and (limb_max // 3)
p0 := (p0 |>> 2).bit_and (limb_max // 5) + p0.bit_and (limb_max // 5)
p0 := ((p0 |>> 4) | p0).bit_and (limb_max // 17)
x := x + p0
op1_offset := op1_offset + 1
n := n - 1
end
x := (x |>> 8) + x
x := (x |>> 16) + x
Result := Result + x.bit_and (0xff).to_integer_32
end
end
bit_xor_lshift (target: SPECIAL [NATURAL_32] target_offset: INTEGER op1: SPECIAL [NATURAL_32] op1_offset: INTEGER op1_count: INTEGER op2: SPECIAL [NATURAL_32] op2_offset: INTEGER op2_count: INTEGER op2_lshift: INTEGER)
require
op2_lshift >= 0
op1 /= op2
target /= op2
op1_count = 0 or op1.valid_index (op1_offset)
op1_count = 0 or op1.valid_index (op1_offset + op1_count - 1)
op2_count = 0 or op2.valid_index (op2_offset)
op2_count = 0 or op2.valid_index (op2_offset + op2_count - 1)
(op1_count = 0 and op2_count = 0) or target.valid_index (target_offset)
(op1_count = 0 and op2_count = 0) or target.valid_index (target_offset + op1_count.max (op2_count + bits_to_limbs (op2_lshift)) - 1)
local
op2_limb_high: NATURAL_32
op2_limb_low: NATURAL_32
op2_limb: NATURAL_32
cursor: INTEGER
shift_limbs: INTEGER
shift_bits: INTEGER
do
shift_limbs := op2_lshift // limb_bits
shift_bits := op2_lshift \\ limb_bits
target.copy_data (op1, op1_offset, target_offset, shift_limbs)
from
until
cursor >= op2_count or cursor >= op1_count - shift_limbs
loop
op2_limb_low := op2_limb_high
op2_limb_high := op2 [op2_offset + cursor]
op2_limb := extract_limb (shift_bits, op2_limb_high, op2_limb_low)
target [target_offset + shift_limbs + cursor] := op2_limb.bit_xor (op1 [op1_offset + shift_limbs + cursor])
cursor := cursor + 1
end
if cursor >= op2_count then
op2_limb_low := op2_limb_high
op2_limb := extract_limb (shift_bits, 0, op2_limb_low)
if cursor >= op1_count - shift_limbs then
target [target_offset + shift_limbs + cursor] := op2_limb
else
target [target_offset + shift_limbs + cursor] := op2_limb.bit_xor (op1 [op1_offset + shift_limbs + cursor])
cursor := cursor + 1
target.copy_data (op1, op1_offset + shift_limbs + cursor, target_offset + shift_limbs + cursor, op1_count - cursor - shift_limbs)
end
else
from
until
cursor >= op2_count
loop
op2_limb_low := op2_limb_high
op2_limb_high := op2 [op2_offset + cursor]
op2_limb := extract_limb (shift_bits, op2_limb_high, op2_limb_low)
target [target_offset + shift_limbs + cursor] := op2_limb
cursor := cursor + 1
end
op2_limb_low := op2_limb_high
op2_limb := extract_limb (shift_bits, 0, op2_limb_low)
target [target_offset + shift_limbs + cursor] := op2_limb
end
end
bit_xor (target: SPECIAL [NATURAL_32]; target_offset: INTEGER; op1: SPECIAL [NATURAL_32]; op1_offset: INTEGER; op1_count: INTEGER; op2: SPECIAL [NATURAL_32]; op2_offset: INTEGER; op2_count: INTEGER)
require
(op1_count = 0 and op2_count = 0) or target.valid_index (target_offset)
(op1_count = 0 and op2_count = 0) or target.valid_index (target_offset + op1_count.max (op2_count) - 1)
local
cursor: INTEGER
min: INTEGER
do
from
min := op1_count.min (op2_count)
until
cursor >= min
loop
target [target_offset + cursor] := op1 [op1_offset + cursor].bit_xor (op2 [op2_offset + cursor])
cursor := cursor + 1
end
if op1_count > op2_count then
target.copy_data (op1, op1_offset + cursor, target_offset + cursor, op1_count - cursor)
elseif op2_count > op1_count then
target.copy_data (op2, op2_offset + cursor, target_offset + cursor, op2_count - cursor)
end
end
end

View File

@@ -0,0 +1,849 @@
note
description: "Summary description for {NUMBER_NUMBER_THEORETIC}."
author: "Colin LeMahieu"
date: "$Date$"
revision: "$Revision$"
quote: "The best argument against democracy is a five-minute conversation with the average voter. - Winston Churchill"
deferred class
SPECIAL_NUMBER_THEORETIC
inherit
SPECIAL_DIVISION
SPECIAL_UTILITY
SPECIAL_LOGIC
LIMB_MANIPULATION
feature
gcdext_div2 (n1_a: NATURAL_32; n0_a: NATURAL_32; d1_a: NATURAL_32; d0_a: NATURAL_32): NATURAL_32
require
d1_a /= 0 or d0_a /= 0
local
q: NATURAL_32
count: INTEGER
d1: NATURAL_32
d0: NATURAL_32
n1: CELL [NATURAL_32]
n0: CELL [NATURAL_32]
do
create n1.put (n1_a)
create n0.put (n0_a)
d1 := d1_a
d0 := d0_a
if n1.item.bit_test (limb_high_bit) then
from
count := 1
invariant
d1 /= 0 or d0 /= 0
until
d1.bit_test (limb_high_bit)
loop
d1 := (d1 |<< 1).bit_or (d0 |>> (limb_bits - 1))
d0 := d0 |<< 1
count := count + 1
end
q := 0
from
until
count = 0
loop
q := q |<< 1
if n1.item > d1 or (n1.item = d1 and n0.item >= d0) then
sub_ddmmss (n1, n0, n1.item, n0.item, d1, d0)
q := q.bit_or (1)
end
d0 := (d1 |<< (limb_bits - 1)).bit_or (d0 |>> 1)
d1 := d1 |>> 1
count := count - 1
end
Result := q
else
from
count := 0
until
n1.item <= d1 and (n1.item /= d1 or n0.item < d0)
loop
d1 := (d1 |<< 1).bit_or (d0 |>> (limb_bits - 1))
d0 := d0 |<< 1
count := count + 1
end
q := 0
from
until
count = 0
loop
d0 := (d1 |<< (limb_bits - 1)).bit_or (d0 |>> 1)
d1 := d1 |>> 1
q := q |<< 1
if n1.item > d1 or (n1.item = d1 and n0.item >= d0) then
sub_ddmmss (n1, n0, n1.item, n0.item, d1, d0)
q := q.bit_or (1)
end
count := count - 1
end
Result := q
end
end
basic_gcdext (target: SPECIAL [NATURAL_32]; target_offset: INTEGER_32; cofactor: SPECIAL [NATURAL_32]; cofactor_offset: INTEGER_32; cofactor_count: TUPLE [cofactor_count: INTEGER_32]; op1: SPECIAL [NATURAL_32]; op1_offset: INTEGER_32; op1_count: INTEGER_32; op2: SPECIAL [NATURAL_32]; op2_offset: INTEGER_32; op2_count: INTEGER_32): INTEGER
require
op1_count >= op2_count
target.valid_index (target_offset)
target.valid_index (target_offset + op1_count - 1)
cofactor.valid_index (cofactor_offset)
cofactor.valid_index (cofactor_offset + op1_count - 1)
op1.valid_index (op1_offset)
op1.valid_index (op1_offset + op1_count - 0)
op1 [op1_offset + op1_count - 1] /= 0
op2.valid_index (op2_offset)
op2.valid_index (op2_offset + op2_count - 0)
op2 [op2_offset + op2_count - 1] /= 0
op2_count >= 1
local
tp: SPECIAL [NATURAL_32]
tp_offset: INTEGER_32
s1p: SPECIAL [NATURAL_32]
s1p_offset: INTEGER
do
create tp.make_filled (0, op1_count + 1)
tp_offset := 0
create s1p.make_filled (0, op1_count + 1)
s1p_offset := 0
cofactor.fill_with (0, cofactor_offset, cofactor_offset + op1_count - 1)
s1p.fill_with (0, s1p_offset, s1p_offset + op1_count - 1)
cofactor [cofactor_offset] := 1
s1p [s1p_offset] := 0
if op1_count > op2_count then
tdiv_qr (tp, tp_offset, op1, op1_offset, op1, op1_offset, op1_count, op2, op2_offset, op2_count)
cofactor [cofactor_offset] := 0
s1p [s1p_offset] := 1
Result := basic_gcdext_arranged (target, target_offset, cofactor, cofactor_offset, cofactor_count, op2, op2_offset, op2_count, op1, op1_offset, op1_count, -1, s1p, s1p_offset, tp, tp_offset)
else
Result := basic_gcdext_arranged (target, target_offset, cofactor, cofactor_offset, cofactor_count, op1, op1_offset, op1_count, op2, op2_offset, op2_count, 1, s1p, s1p_offset, tp, tp_offset)
end
end
basic_gcdext_arranged (target: SPECIAL [NATURAL_32]; target_offset: INTEGER_32; cofactor_a: SPECIAL [NATURAL_32]; cofactor_offset_a: INTEGER_32; cofactor_count: TUPLE [cofactor_count: INTEGER_32]; op1_a: SPECIAL [NATURAL_32]; op1_offset_a: INTEGER_32; op1_count_a: INTEGER_32; op2_a: SPECIAL [NATURAL_32]; op2_offset_a: INTEGER_32; op2_count_a: INTEGER_32; sign_a: INTEGER; s1p_a: SPECIAL [NATURAL_32]; s1p_offset_a: INTEGER; tp_a: SPECIAL [NATURAL_32]; tp_offset_a: INTEGER): INTEGER
local
a: NATURAL_32
b: NATURAL_32
c: NATURAL_32
d: NATURAL_32
wp: SPECIAL [NATURAL_32]
wp_offset: INTEGER_32
orig_s0p: SPECIAL [NATURAL_32]
orig_s0p_offset: INTEGER
use_double_flag: BOOLEAN
cnt: INTEGER_32
assign_l: NATURAL_32
op2_count: INTEGER
done: BOOLEAN
done_2: BOOLEAN
uh: NATURAL_32
vh: NATURAL_32
ul: NATURAL_32
vl: NATURAL_32
tac: NATURAL_32
tbd: NATURAL_32
q1: NATURAL_32
q2: NATURAL_32
nh: CELL [NATURAL_32]
nl: CELL [NATURAL_32]
dh: CELL [NATURAL_32]
dl: CELL [NATURAL_32]
t1: CELL [NATURAL_32]
t0: CELL [NATURAL_32]
thigh: CELL [NATURAL_32]
tlow: CELL [NATURAL_32]
sign: INTEGER
q: NATURAL_32
t: NATURAL_32
ssize: INTEGER_32
qsize: INTEGER_32
i: INTEGER_32
cy: NATURAL_32
cofactor: SPECIAL [NATURAL_32]
cofactor_offset: INTEGER_32
op1: SPECIAL [NATURAL_32]
op1_offset: INTEGER_32
op2: SPECIAL [NATURAL_32]
op2_offset: INTEGER_32
tp: SPECIAL [NATURAL_32]
tp_offset: INTEGER_32
s1p: SPECIAL [NATURAL_32]
s1p_offset: INTEGER_32
temp_special: SPECIAL [NATURAL_32]
temp_integer: INTEGER_32
op1_count: INTEGER
tsize: INTEGER
wsize: INTEGER
junk: NATURAL_32
cy1: NATURAL_32
cy2: NATURAL_32
carry: CELL [NATURAL_32]
do
create carry.put (0)
cofactor := cofactor_a
cofactor_offset := cofactor_offset_a
op1 := op1_a
op1_offset := op1_offset_a
op1_count := op1_count_a
op2 := op2_a
op2_offset := op2_offset_a
tp := tp_a
tp_offset := tp_offset_a
s1p := s1p_a
s1p_offset := s1p_offset_a
ssize := 1
sign := sign_a
op2_count := op2_count_a
orig_s0p := cofactor
orig_s0p_offset := cofactor_offset
create wp.make_filled (0, op1_count + 1)
wp_offset := 0
use_double_flag := op1_count > 17
from
until
done
loop
op2_count := op1_count
op2_count := normalize (op2, op2_offset, op2_count)
if op2_count <= 1 then
done := True
else
if use_double_flag then
uh := op1 [op1_count - 1]
vh := op2 [op1_count - 1]
ul := op1 [op1_count - 2]
vl := op2 [op1_count - 2]
cnt := leading_zeros (uh)
if cnt /= 0 then
uh := (uh |<< cnt).bit_or (ul |>> (32 - cnt))
vh := (vh |<< cnt).bit_or (vl |>> (32 - cnt))
vl := vl |<< cnt
ul := ul |<< cnt
if op1_count >= 3 then
ul := ul.bit_or (op1 [op1_offset + op1_count - 3] |>> (32 - cnt))
vl := vl.bit_or (op2 [op2_offset + op1_count - 3] |>> (32 - cnt))
end
end
a := 1
b := 0
c := 0
d := 1
assign_l := 0
from
done_2 := False
create nh.put (0)
create nl.put (0)
create dh.put (0)
create dl.put (0)
create thigh.put (0)
create tlow.put (0)
create t1.put (0)
create t0.put (0)
until
done_2
loop
sub_ddmmss (dh, dl, vh, vl, 0, c)
if dh.item = 0 then
done_2 := True
else
add_ssaaaa (nh, nl, uh, ul, 0, a)
q1 := gcdext_div2 (nh.item, nl.item, dh.item, dl.item)
add_ssaaaa (dh, dl, vh, vl, 0, d)
if dh.item = 0 then
done_2 := True
else
sub_ddmmss (nh, nl, uh, ul, 0, b)
q2 := gcdext_div2 (nh.item, nl.item, dh.item, dl.item)
if q1 /= q2 then
done_2 := True
else
tac := a + q1 * c
tbd := b + q1 * d
a := c
c := tac
b := d
d := tbd
umul_ppmm (t1, t0, q1, vl)
t1.put (t1.item + q1 * vh)
sub_ddmmss (thigh, tlow, uh, ul, t1.item, t0.item)
uh := vh
ul := vl
vh := thigh.item
vl := tlow.item
assign_l := assign_l.bit_not
add_ssaaaa (dh, dl, vh, vl, 0, c)
sub_ddmmss (nh, nl, uh, ul, 0, a)
q1 := gcdext_div2 (nh.item, nl.item, dh.item, dl.item)
sub_ddmmss (dh, dl, vh, vl, 0, d)
if dh.item = 0 then
done_2 := True
else
add_ssaaaa (nh, nl, uh, ul, 0, b)
q2 := gcdext_div2 (nh.item, nl.item, dh.item, dl.item)
if q1 /= q2 then
done_2 := True
else
tac := a + q1 * c
tbd := b + q1 * d
a := c
c := tac
b := d
d := tbd
umul_ppmm (t1, t0, q1, vl)
t1.put (t1.item + (q1 * vh))
sub_ddmmss (thigh, tlow, uh, ul, t1.item, t0.item)
uh := vh
ul := vl
vh := thigh.item
vl := tlow.item
assign_l := assign_l.bit_not
end
end
end
end
end
end
if assign_l /= 0 then
sign := -sign
end
else
uh := op1 [op1_offset + op1_count - 1]
vh := op2 [op2_offset + op1_count - 1]
cnt := leading_zeros (uh)
if cnt /= 0 then
uh := (uh |<< cnt).bit_or (op1 [op1_offset + op1_count - 2] |>> (limb_bits - cnt))
vh := (vh |<< cnt).bit_or (op2 [op2_offset + op1_count - 2] |>> (limb_bits - cnt))
end
a := 1
b := 0
c := 0
d := 1
assign_l := 0
from
done_2 := False
until
done_2
loop
if vh - c = 0 or vh + d = 0 then
done_2 := True
else
q := (uh + a) // (vh - c)
if q /= (uh - b) // (vh + d) then
done_2 := True
else
t := a + q * c
a := c
c := t
t := b + q * d
b := d
d := t
t := uh - q * vh
uh := vh
vh := t
assign_l := assign_l.bit_not
if vh - d = 0 then
done_2 := True
else
q := (uh - a) // (vh + c)
if q /= (uh + b) // (vh - d) then
done_2 := True
else
t := a + q * c
a := c
c := t
t := b + q * d
b := d
d := t
t := uh - q * vh
uh := vh
vh := t
assign_l := assign_l.bit_not
end
end
end
end
end
if assign_l /= 0 then
sign := -sign
end
end
if b = 0 then
tdiv_qr (wp, wp_offset, op1, op1_offset, op1, op1_offset, op1_count, op2, op2_offset, op2_count)
tp.copy_data (cofactor, cofactor_offset, tp_offset, ssize)
qsize := op1_count - op2_count + 1
s1p.fill_with (0, s1p_offset + ssize, s1p_offset + ssize + qsize - 1)
from
i := 0
until
i >= qsize
loop
addmul_1 (tp, tp_offset + i, s1p, s1p_offset, ssize, wp [wp_offset + i], carry)
cy := carry.item
tp [tp_offset + ssize + i] := cy
i := i + 1
end
ssize := ssize + qsize
ssize := ssize - (tp [tp_offset + ssize - 1] = 0).to_integer
sign := -sign
temp_special := cofactor
temp_integer := cofactor_offset
cofactor := s1p
cofactor_offset := s1p_offset
s1p := temp_special
s1p_offset := temp_integer
temp_special := s1p
temp_integer := s1p_offset
s1p := tp
s1p_offset := tp_offset
tp := temp_special
tp_offset := temp_integer
op1_count := op2_count
temp_special := op1
temp_integer := op1_offset
op1 := op2
op1_offset := op2_offset
op2 := temp_special
op2_offset := temp_integer
else
if a = 0 then
tp.copy_data (op2, op2_offset, tp_offset, op1_count)
wp.copy_data (op1, op1_offset, wp_offset, op1_count)
submul_1 (wp, wp_offset, op2, op2_offset, op1_count, d, carry)
junk := carry.item
temp_special := tp
temp_integer := tp_offset
tp := op1
tp_offset := op1_offset
op1 := temp_special
op1_offset := temp_integer
temp_special := wp
temp_integer := wp_offset
wp := op2
wp_offset := op2_offset
op2 := temp_special
op2_offset := temp_integer
tp.copy_data (s1p, s1p_offset, tp_offset, ssize)
tsize := ssize
tp [tp_offset + ssize] := 0
wp.copy_data (cofactor, cofactor_offset, wp_offset, ssize)
addmul_1 (wp, wp_offset, s1p, s1p_offset, ssize, d, carry)
cy := carry.item
wp [wp_offset + ssize] := cy
wsize := ssize + (cy /= 0).to_integer
temp_special := tp
temp_integer := tp_offset
tp := cofactor
tp_offset := cofactor_offset
cofactor := temp_special
cofactor_offset := temp_integer
temp_special := wp
temp_integer := wp_offset
wp := s1p
wp_offset := s1p_offset
s1p := temp_special
s1p_offset := temp_integer
ssize := wsize.max (tsize)
else
if assign_l /= 0 then
mul_1 (tp, tp_offset, op2, op2_offset, op1_count, b, carry)
junk := carry.item
submul_1 (tp, tp_offset, op1, op1_offset, op1_count, a, carry)
junk := carry.item
mul_1 (wp, wp_offset, op1, op1_offset, op1_count, c, carry)
junk := carry.item
submul_1 (wp, wp_offset, op2, op2_offset, op1_count, d, carry)
junk := carry.item
else
mul_1 (tp, tp_offset, op1, op1_offset, op1_count, a, carry)
junk := carry.item
submul_1 (tp, tp_offset, op2, op2_offset, op1_count, b, carry)
junk := carry.item
mul_1 (wp, wp_offset, op2, op2_offset, op1_count, d, carry)
junk := carry.item
submul_1 (wp, wp_offset, op1, op1_offset, op1_count, c, carry)
junk := carry.item
end
temp_special := tp
temp_integer := tp_offset
tp := op1
tp_offset := op1_offset
op1 := temp_special
op1_offset := temp_integer
temp_special := wp
temp_integer := wp_offset
wp := op2
wp_offset := op2_offset
op2 := temp_special
op2_offset := temp_integer
mul_1 (tp, tp_offset, cofactor, cofactor_offset, ssize, a, carry)
cy1 := carry.item
addmul_1 (tp, tp_offset, s1p, s1p_offset, ssize, b, carry)
cy2 := carry.item
cy := cy1 + cy2
tp [tp_offset + ssize] := cy
tsize := ssize + (cy /= 0).to_integer
if cy < cy1 then
tp [tp_offset + tsize] := 1
wp [wp_offset + tsize] := 0
tsize := tsize + 1
end
mul_1 (wp, wp_offset, s1p, s1p_offset, ssize, d, carry)
cy1 := carry.item
addmul_1 (wp, wp_offset, cofactor, cofactor_offset, ssize, c, carry)
cy2 := carry.item
cy := cy1 + cy2
wp [wp_offset + ssize] := cy
wsize := ssize + (cy /= 0).to_integer
if cy < cy1 then
wp [wp_offset + wsize] := 1
if wsize >= tsize then
tp [tp_offset + wsize] := 0
end
wsize := wsize + 1
end
temp_special := tp
temp_integer := tp_offset
tp := cofactor
tp_offset := cofactor_offset
cofactor := temp_special
cofactor_offset := temp_integer
temp_special := wp
temp_integer := wp_offset
wp := s1p
wp_offset := s1p_offset
s1p := temp_special
s1p_offset := temp_integer
ssize := wsize.max (tsize)
end
op1_count := op1_count - (op1 [op1_offset + op1_count - 1] = 0).to_integer
end
end
end
if op2_count = 0 then
if target /= op1 then
target.copy_data (op1, op1_offset, target_offset, op1_count)
end
ssize := normalize (cofactor, cofactor_offset, ssize)
if orig_s0p /= cofactor then
orig_s0p.copy_data (cofactor, cofactor_offset, orig_s0p_offset, ssize)
end
if sign >= 0 then
cofactor_count.cofactor_count := ssize
else
cofactor_count.cofactor_count := -ssize
end
Result := op1_count
else
vl := op2 [op2_offset]
t := divrem_1 (wp, wp_offset, op1, op1_offset, op1_count, vl)
tp.copy_data (cofactor, cofactor_offset, tp_offset, ssize)
qsize := op1_count - (wp [wp_offset + op1_count - 1] = 0).to_integer
if ssize < qsize then
tp.fill_with (0, tp_offset + ssize, qsize - ssize)
s1p.fill_with (0, s1p_offset + ssize, qsize)
from
i := 0
until
i >= ssize
loop
addmul_1 (tp, tp_offset + i, wp, wp_offset, qsize, s1p [s1p_offset + i], carry)
cy := carry.item
tp [tp_offset + qsize + i] := cy
i := i + 1
end
else
s1p.fill_with (0, s1p_offset + ssize, s1p_offset + ssize + qsize - 1)
from
i := 0
until
i >= qsize
loop
addmul_1 (tp, tp_offset + i, s1p, s1p_offset, ssize, wp [wp_offset + i], carry)
cy := carry.item
tp [tp_offset + ssize + i] := cy
i := i + 1
end
end
ssize := ssize + qsize
ssize := ssize - (tp [tp_offset + ssize - 1] = 0).to_integer
sign := -sign
temp_special := cofactor
temp_integer := cofactor_offset
cofactor := s1p
cofactor_offset := s1p_offset
s1p := temp_special
s1p_offset := temp_integer
temp_special := s1p
temp_integer := s1p_offset
s1p := tp
s1p_offset := tp_offset
tp := temp_special
tp_offset := temp_integer
ul := vl
vl := t
from
until
vl = 0
loop
q := ul // vl
t := ul - q * vl
tp.copy_data (cofactor, cofactor_offset, tp_offset, ssize)
s1p.fill_with (0, s1p_offset + ssize, s1p_offset + ssize)
addmul_1 (tp, tp_offset, s1p, s1p_offset, ssize, q, carry)
cy := carry.item
tp [tp_offset + ssize] := cy
ssize := ssize + 1
ssize := ssize - (tp [tp_offset + ssize - 1] = 0).to_integer
sign := -sign
temp_special := cofactor
temp_integer := cofactor_offset
cofactor := s1p
cofactor_offset := s1p_offset
s1p := temp_special
s1p_offset := temp_integer
temp_special := s1p
temp_integer := s1p_offset
s1p := tp
s1p_offset := tp_offset
tp := temp_special
tp_offset := temp_integer
ul := vl
vl := t
end
target [target_offset] := ul
ssize := normalize (cofactor, cofactor_offset, ssize)
if orig_s0p /= cofactor then
orig_s0p.copy_data (cofactor, cofactor_offset, orig_s0p_offset, ssize)
end
if sign >= 0 then
cofactor_count.cofactor_count := ssize
else
cofactor_count.cofactor_count := -ssize
end
Result := 1
end
end
gcdext (target: SPECIAL [NATURAL_32]; target_offset: INTEGER; cofactor: SPECIAL [NATURAL_32]; cofactor_offset: INTEGER; cofactor_count: TUPLE [cofactor_count: INTEGER]; op1: SPECIAL [NATURAL_32]; op1_offset: INTEGER; op1_count: INTEGER; op2: SPECIAL [NATURAL_32]; op2_offset: INTEGER; op2_count: INTEGER): INTEGER
require
op1_count >= op2_count
op2_count >= 0
op1.valid_index (op1_offset)
op1.valid_index (op1_offset + op1_count - 0)
op1 [op1_offset + op1_count - 1] /= 0
op2.valid_index (op2_offset)
op2.valid_index (op2_offset + op2_count - 0)
op1 [op1_offset + op1_count - 1] /= 0
target.valid_index (target_offset)
target.valid_index (target_offset + op1_count - 1)
cofactor.valid_index (cofactor_offset)
cofactor.valid_index (cofactor_offset + op1_count - 1)
local
orig_n: INTEGER
do
orig_n := op2_count
Result := basic_gcdext (target, target_offset, cofactor, cofactor_offset, cofactor_count, op1, op1_offset, op1_count, op2, op2_offset, op2_count)
end
modexact_1c_odd (op1: SPECIAL [NATURAL_32]; op1_offset: INTEGER; op1_count: INTEGER; d: NATURAL_32; orig_c: NATURAL_32): NATURAL_32
require
op1_count >= 1
d.bit_test (0)
local
s: NATURAL_32
h: CELL [NATURAL_32]
l: CELL [NATURAL_32]
inverse: NATURAL_32
dummy: CELL [NATURAL_32]
dmul: NATURAL_32
c: CELL [NATURAL_32]
i: INTEGER
do
create l.put (0)
create c.put (orig_c)
create h.put (0)
create dummy.put (0)
if op1_count = 1 then
s := op1 [op1_offset]
if s > c.item then
l.put (s - c.item)
h.put (l.item \\ d)
if h.item /= 0 then
h.put (d - h.item)
end
else
l.put (c.item - s)
h.put (l.item \\ d)
end
Result := h.item
else
inverse := modlimb_invert (d)
dmul := d
from
i := 0
until
i >= op1_count - 1
loop
s := op1 [op1_offset + i]
subc_limb (c, l, s, c.item)
l.put (l.item * inverse)
umul_ppmm (h, dummy, l.item, dmul)
c.put (c.item + h.item)
i := i + 1
end
s := op1 [op1_offset + i]
if s <= d then
l.put (c.item - s)
if c.item < s then
l.put (l.item + d)
end
Result := l.item
else
subc_limb (c, l, s, c.item)
l.put (l.item * inverse)
umul_ppmm (h, dummy, l.item, dmul)
c.put (c.item + h.item)
Result := c.item
end
end
ensure
orig_c < d implies Result < d
orig_c >= d implies Result <= d
end
preinv_mod_1 (up: SPECIAL [NATURAL_32]; up_offset: INTEGER; un: INTEGER; d: NATURAL_32; dinv: NATURAL_32): NATURAL_32
require
un >= 1
d.bit_test (31)
local
i: INTEGER
n0: NATURAL_32
r: CELL [NATURAL_32]
dummy: CELL [NATURAL_32]
do
create r.put (up [up_offset + un - 1])
create dummy.put (0)
if r.item >= d then
r.put (r.item - d)
end
from
i := un - 2
until
i < 0
loop
n0 := up [up_offset + i]
udiv_qrnnd_preinv (dummy, r, r.item, n0, d, dinv)
i := i - 1
end
Result := r.item
end
redc_basecase (cp: SPECIAL [NATURAL_32]; cp_offset: INTEGER; mp: SPECIAL [NATURAL_32]; mp_offset: INTEGER; n: INTEGER; n_prim: NATURAL_32; tp: SPECIAL [NATURAL_32]; tp_offset_a: INTEGER)
local
cy: NATURAL_32
q: NATURAL_32
j: INTEGER
tp_offset: INTEGER
junk: NATURAL_32
carry: CELL [NATURAL_32]
do
create carry.put (0)
tp_offset := tp_offset_a
from
j := 0
until
j >= n
loop
q := tp [tp_offset] * n_prim
addmul_1 (tp, tp_offset, mp, mp_offset, n, q, carry)
tp [tp_offset] := carry.item
tp_offset := tp_offset + 1
j := j + 1
end
add_n (cp, cp_offset, tp, tp_offset, tp, tp_offset - n, n, carry)
cy := carry.item
if cy /= 0 then
sub_n (cp, cp_offset, cp, cp_offset, mp, mp_offset, n, carry)
junk := carry.item
end
end
subc_limb (cout: CELL [NATURAL_32]; w: CELL [NATURAL_32]; x: NATURAL_32; y: NATURAL_32)
do
w.put (x - y)
cout.put ((w.item > x).to_integer.to_natural_32)
end
invert_gf (target: SPECIAL [NATURAL_32] target_offset: INTEGER op1_a: SPECIAL [NATURAL_32] op1_offset: INTEGER op1_count_a: INTEGER op2_a: SPECIAL [NATURAL_32] op2_offset: INTEGER op2_count_a: INTEGER)
-- Invert `op1' over `op2' using the extended euclidian algorithm in F2M
require
op2_count_a > 0
op1_count_a >= 0
op1_count_a <= op2_count_a;
(op1_count_a = op2_count_a) implies cmp (op1_a, op1_offset, op2_a, op2_offset, op2_count_a) <= 0
local
op1: SPECIAL [NATURAL_32]
op1_count: INTEGER
op1_leading_zeros: INTEGER
op2: SPECIAL [NATURAL_32]
op2_count: INTEGER
op2_leading_zeros: INTEGER
tmp_special: SPECIAL [NATURAL_32]
tmp_integer: INTEGER
g1: SPECIAL [NATURAL_32]
g1_count: INTEGER
g2: SPECIAL [NATURAL_32]
g2_count: INTEGER
operand_sizes: INTEGER
left_shift_amount: INTEGER
do
operand_sizes := op2_count_a
op1_count := op1_count_a
op2_count := op2_count_a
create op1.make_filled (0, operand_sizes + operand_sizes)
create op2.make_filled (0, operand_sizes + operand_sizes)
op1.copy_data (op1_a, op1_offset, 0, op1_count.min (operand_sizes))
op2.copy_data (op2_a, op2_offset, 0, op2_count.min (operand_sizes))
create g1.make_filled (0, operand_sizes + operand_sizes)
create g2.make_filled (0, operand_sizes + operand_sizes)
g1 [0] := 1
g1_count := 1
g2_count := 0
from
until
op1_count = 0
loop
op1_leading_zeros := leading_zeros (op1 [op1_count - 1])
op2_leading_zeros := leading_zeros (op2 [op2_count - 1])
if op1_count < op2_count or (op1_count = op2_count and op1_leading_zeros > op2_leading_zeros) then
tmp_special := op1
op1 := op2
op2 := tmp_special
tmp_special := g1
g1 := g2
g2 := tmp_special
tmp_integer := op1_count
op1_count := op2_count
op2_count := tmp_integer
tmp_integer := op1_leading_zeros
op1_leading_zeros := op2_leading_zeros
op2_leading_zeros := tmp_integer
end
if op1_count /= op2_count or (op1_count = op2_count and op1_leading_zeros /= op2_leading_zeros) then
left_shift_amount := (op1_count - op2_count) * limb_bits + op2_leading_zeros - op1_leading_zeros
bit_xor_lshift (op1, 0, op1, 0, op1_count, op2, 0, op2_count, left_shift_amount)
bit_xor_lshift (g1, 0, g1, 0, operand_sizes, g2, 0, operand_sizes, left_shift_amount)
else
bit_xor (op1, 0, op1, 0, op1_count, op2, 0, op2_count)
bit_xor (g1, 0, g1, 0, operand_sizes, g2, 0, operand_sizes)
end
op1_count := normalize (op1, 0, op1_count)
op2_count := normalize (op2, 0, op2_count)
end
target.copy_data (g2, 0, target_offset, operand_sizes)
end
end

View File

@@ -0,0 +1,52 @@
note
description: "Summary description for {NUMBER_SIZING}."
author: "Colin LeMahieu"
date: "$Date$"
revision: "$Revision$"
quote: "Whatever you do will be insignificant, but it is very important that you do it. - Mahatma Gandhi"
deferred class
SPECIAL_SIZING
inherit
LIMB_MANIPULATION
MP_BASES
feature
sizeinbase (source: SPECIAL [NATURAL_32]; source_offset: INTEGER; size: INTEGER; base: INTEGER): INTEGER
require
size >= 0
base >= 2
local
lb_base: INTEGER
count: INTEGER
total_bits: INTEGER
do
if size = 0 then
Result := 1
else
count := leading_zeros (source [source_offset + size - 1])
total_bits := size * limb_bits - count
if pow2_p (base.to_natural_32) then
lb_base := big_base (base).to_integer_32
Result := (total_bits + lb_base - 1) // lb_base
else
Result := ((total_bits * chars_per_bit_exactly (base)) + 1).truncated_to_integer
end
end
end
sizeinbase_2exp (ptr: SPECIAL [NATURAL_32]; ptr_offset: INTEGER; ptr_count: INTEGER; base2exp: INTEGER): INTEGER
require
ptr_count > 0
ptr [ptr_offset + ptr_count - 1] /= 0
local
count: INTEGER
totbits: INTEGER
do
count := leading_zeros (ptr [ptr_offset + ptr_count - 1])
totbits := ptr_count * limb_bits - count
Result := (totbits + base2exp - 1) // base2exp
end
end

View File

@@ -0,0 +1,37 @@
note
description: "Summary description for {NUMBER_UTILITY}."
author: "Colin LeMahieu"
date: "$Date$"
revision: "$Revision$"
quote: "If a law is unjust, a man is not only right to disobey it, he is obligated to do so. - Thomas Jefferson"
deferred class
SPECIAL_UTILITY
feature
normalize (op1: SPECIAL [NATURAL_32]; op1_offset: INTEGER; op1_count: INTEGER): INTEGER
do
from
Result := op1_count
until
Result <= 0 or op1 [op1_offset + Result - 1] /= 0
loop
Result := Result - 1
end
end
reverse (target: SPECIAL [NATURAL_32]; target_offset: INTEGER; source: SPECIAL [NATURAL_32]; source_offset: INTEGER; count: INTEGER)
local
i: INTEGER
do
from
i := 0
until
i >= count
loop
target [target_offset + i] := source [source_offset + count - 1 - i]
i := i + 1
end
end
end