Skip to content

Commit

Permalink
Improve InverseMatMod with integer modulus
Browse files Browse the repository at this point in the history
Before:

    gap> m2:=RandomUnimodularMat(100);;
    gap> for i in [1..100] do x:=InverseMatMod(m2,2); od; time;
    277
    gap> for i in [1..100] do x:=InverseMatMod(m2,251); od; time;
    1564
    gap> for i in [1..100] do x:=InverseMatMod(m2,65537); od; time;
    Error, reached the pre-set memory limit

After:

    gap> m2:=RandomUnimodularMat(100);;
    gap> for i in [1..100] do x:=InverseMatMod(m2,2); od; time;
    273
    gap> for i in [1..100] do x:=InverseMatMod(m2,251); od; time;
    1249
    gap> for i in [1..100] do x:=InverseMatMod(m2,65537); od; time;
    1226
  • Loading branch information
fingolfin authored and ChrisJefferson committed May 4, 2018
1 parent a729238 commit b3fafa2
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 34 deletions.
43 changes: 9 additions & 34 deletions lib/zlattice.gi
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ end );
##
#M InverseMatMod( <intmat>, <prime> )
##
#T Is this method really good?
#T (There is a generic method in `matrix.gi' that looks nicer.)
## This method is much faster than the generic method in `matrix.gi'
##
InstallMethod( InverseMatMod,
"method for a matrix, and an integer",
Expand All @@ -49,36 +48,12 @@ InstallMethod( InverseMatMod,
n, # dimension
intmatq, intmatqinv, # matrix & inverse modulo p
x, # solution of one iteration
zline, # help-line for exchange
mult, # multiplication table of the field
inverse; # list of inverses of field elements
zline; # help-line for exchange

n:= Length( intmat );

# inverses modulo `p'; we have `inverse[x] * x = 1'
inverse:= [ 1 ];
for i in [ 2 .. p-1 ] do
inverse[i]:= Inverse( i ) mod p;
#T better?
od;

# multiplication table; we have `mult[i][j]' congruent `i*j' mod `p'
mult:= [];
for i in [ 1 .. p-1 ] do
mult[i]:= [];
for j in [ 1 .. p-1 ] do
mult[i][j]:= ( i*j ) mod p;
od;
od;

# `intmatq': `intmat' reduced mod `p'
intmatq := [];
for i in [ 1 .. n ] do
intmatq[i] := [];
for j in [ 1 .. n ] do
intmatq[i][j]:= intmat[i][j] mod p;
od;
od;
intmatq := intmat mod p;
intmatqinv := IdentityMat( n );

for i in [ 1 .. n ] do
Expand All @@ -105,33 +80,33 @@ InstallMethod( InverseMatMod,
# normalize line `i'
zline:= intmatq[i];
if zline[i] <> 1 then
x:= mult[ inverse[ zline[i] ] ];
x:= (1/zline[i]) mod p;
zline[i]:= 1;
for k in [ i+1 .. n ] do
if zline[k] <> 0 then
zline[k]:= x[ zline[k] ];
zline[k]:= (x * zline[k]) mod p;
fi;
od;
zline:= intmatqinv[i];
for k in [1 .. n] do
if zline[k] <> 0 then
zline[k]:= x[ zline[k] ];
zline[k]:= (x * zline[k]) mod p;
fi;
od;
fi;

# elimination in column `i'
for j in [ 1 .. n ] do
if j <> i and intmatq[j][i] <> 0 then
x:= mult[ intmatq[j][i] ];
x:= intmatq[j][i];
for k in [ 1 .. n ] do
if intmatqinv[i][k] <> 0 then
intmatqinv[j][k]:=
(intmatqinv[j][k] - x[ intmatqinv[i][k] ] ) mod p;
(intmatqinv[j][k] - x * intmatqinv[i][k] ) mod p;
fi;
if intmatq[i][k] <> 0 then
intmatq[j][k]:=
(intmatq[j][k] - x[ intmatq[i][k] ] ) mod p;
(intmatq[j][k] - x * intmatq[i][k] ) mod p;
fi;
od;
fi;
Expand Down
14 changes: 14 additions & 0 deletions tst/testinstall/opers/InverseMatMod.tst
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
gap> START_TEST("InverseMatMod.tst");

#
gap> for d in [1..10] do
> id:=IdentityMat(d);
> m:=RandomUnimodularMat(d);
> for p in [2, 251, 65537] do
> x:=InverseMatMod(m, p);
> Assert(0, (x*m mod p) = id);
> od;
> od;

#
gap> STOP_TEST("InverseMatMod.tst", 1);

0 comments on commit b3fafa2

Please sign in to comment.