Files
EWF/library/crypto/eapml/facilities/special_number_theoretic.e
jvelilla c9343688f3 Added eel and eapml in EWF libraries.
Removed them from gitmodule
2011-10-27 08:29:01 -03:00

850 lines
25 KiB
Plaintext

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