Skip to content

Commit

Permalink
MatrixObj: matrix manipulation ops for IsMatrix
Browse files Browse the repository at this point in the history
Before this, e.g. `SwapMatrixRows(IdentityMat(10,Integers), 1, 2)`
resulted in a "no method found" error.

In addition, use `InstallEarlyMethod` to provide fast methods for classical
lists-of-list matrices.

Before the new early methods (but after enabling everything for `IsMatrix`):

    gap> mat:=IdentityMat(10,Integers);;
    gap> for i in [1..1000000] do SwapMatrixRows(mat,1,2); od; time;
    874
    gap> for i in [1..1000000] do tmp:=mat[1];mat[1]:=mat[2];mat[2]:=tmp; od; time;
    38
    gap> mat:=IdentityMat(10,GF(2));; ConvertToMatrixRep(mat);; mat;
    <a 10x10 matrix over GF2>
    gap> for i in [1..1000000] do SwapMatrixRows(mat,1,2); od; time;
    137
    gap> for i in [1..1000000] do tmp:=mat[1];mat[1]:=mat[2];mat[2]:=tmp; od; time;
    107

After:

    gap> mat:=IdentityMat(10,Integers);;
    gap> for i in [1..1000000] do SwapMatrixRows(mat,1,2); od; time;
    132
    gap> for i in [1..1000000] do tmp:=mat[1];mat[1]:=mat[2];mat[2]:=tmp; od; time;
    37
    gap> mat:=IdentityMat(10,GF(2));; ConvertToMatrixRep(mat);; mat;
    <a 10x10 matrix over GF2>
    gap> for i in [1..1000000] do SwapMatrixRows(mat,1,2); od; time;
    163
    gap> for i in [1..1000000] do tmp:=mat[1];mat[1]:=mat[2];mat[2]:=tmp; od; time;
    102

Note that `SwapMatrixRows` got slightly slower for the compressed matrix over GF(2),
due to the extra overhead caused by the early method. I think for now this is
acceptable. If we are concerned about this, we could probably get rid of most or
all of it by using a "classic" early method, i.e., a kernel one.
  • Loading branch information
fingolfin committed Apr 20, 2022
1 parent 977fb05 commit b9435f9
Show file tree
Hide file tree
Showing 4 changed files with 269 additions and 37 deletions.
140 changes: 113 additions & 27 deletions lib/matobj.gi
Original file line number Diff line number Diff line change
Expand Up @@ -1490,59 +1490,77 @@ InstallMethod( \[\,\]\:\=, "for a matrix object, two positions, and an object",
############################################################################

InstallMethod( MultMatrixRowLeft, "for a mutable matrix object, a row number, and a scalar",
[ IsMatrixObj and IsMutable, IsInt, IsObject ],
[ IsMatrixOrMatrixObj and IsMutable, IsInt, IsObject ],
function( mat, row, scalar )
local i;

for i in [1..NrCols(mat)] do
mat[row,i] := scalar * mat[row,i];
od;


end );

InstallEarlyMethod( MultMatrixRowLeft,
function( mat, i, scalar )
if IsPlistRep(mat) then
mat[i] := scalar * mat[i];
else
TryNextMethod();
fi;
end );

############################################################################

InstallMethod( MultMatrixColumnRight, "for a mutable matrix object, a column number, and a scalar",
[ IsMatrixObj and IsMutable, IsInt, IsObject ],
[ IsMatrixOrMatrixObj and IsMutable, IsInt, IsObject ],
function( mat, column, scalar )
local i;

for i in [1..NrRows(mat)] do
mat[i,column] := mat[i,column] * scalar;
od;

end );

############################################################################

InstallMethod( MultMatrixRowRight, "for a mutable matrix object, a row number, and a scalar",
[ IsMatrixObj and IsMutable, IsInt, IsObject ],
[ IsMatrixOrMatrixObj and IsMutable, IsInt, IsObject ],
function( mat, row, scalar )
local i;

for i in [1..NrCols(mat)] do
mat[row,i] := mat[row,i] * scalar;
od;


end );

InstallEarlyMethod( MultMatrixRowRight,
function( mat, i, scalar )
if IsPlistRep(mat) then
mat[i] := mat[i] * scalar;
else
TryNextMethod();
fi;
end );

############################################################################

InstallMethod( MultMatrixColumnLeft, "for a mutable matrix object, a column number, and a scalar",
[ IsMatrixObj and IsMutable, IsInt, IsObject ],
[ IsMatrixOrMatrixObj and IsMutable, IsInt, IsObject ],
function( mat, column, scalar )
local i;

for i in [1..NrRows(mat)] do
mat[i,column] := scalar * mat[i,column];
od;

end );

############################################################################

InstallMethod( AddMatrixRowsLeft, "for a mutable matrix object, two row numbers, and a scalar",
[ IsMatrixObj and IsMutable, IsInt, IsInt, IsObject ] ,
[ IsMatrixOrMatrixObj and IsMutable, IsInt, IsInt, IsObject ] ,
function( mat, row1, row2, scalar )
local i;

Expand All @@ -1551,24 +1569,42 @@ InstallMethod( AddMatrixRowsLeft, "for a mutable matrix object, two row numbers,
od;

end );


InstallEarlyMethod( AddMatrixRowsLeft,
function( mat, i, j, scalar )
if IsPlistRep(mat) then
mat[i] := mat[i] + scalar * mat[j];
else
TryNextMethod();
fi;
end );

############################################################################

InstallMethod( AddMatrixRowsRight, "for a mutable matrix object, two row numbers, and a scalar",
[ IsMatrixObj and IsMutable, IsInt, IsInt, IsObject ] ,
[ IsMatrixOrMatrixObj and IsMutable, IsInt, IsInt, IsObject ] ,
function( mat, row1, row2, scalar )
local i;

for i in [1..NrCols(mat)] do
mat[row1,i] := mat[row1,i] + mat[row2,i] * scalar;
od;

end );

InstallEarlyMethod( AddMatrixRowsRight,
function( mat, i, j, scalar )
if IsPlistRep(mat) then
mat[i] := mat[i] + mat[j] * scalar;
else
TryNextMethod();
fi;
end );

############################################################################

InstallMethod( AddMatrixColumnsRight, "for a mutable matrix object, two column numbers, and a scalar",
[ IsMatrixObj and IsMutable, IsInt, IsInt, IsObject ] ,
[ IsMatrixOrMatrixObj and IsMutable, IsInt, IsInt, IsObject ] ,
function( mat, column1, column2, scalar )
local i;

Expand All @@ -1578,49 +1614,99 @@ InstallMethod( AddMatrixColumnsRight, "for a mutable matrix object, two column n

end );

InstallEarlyMethod( AddMatrixColumnsRight,
function( mat, i, j, scalar )
local row;
if IsPlistRep(mat) then
for row in mat do
row[i] := row[i] + row[j] * scalar;
od;
else
TryNextMethod();
fi;
end );

############################################################################

InstallMethod( AddMatrixColumnsLeft, "for a mutable matrix object, two column numbers, and a scalar",
[ IsMatrixObj and IsMutable, IsInt, IsInt, IsObject ] ,
[ IsMatrixOrMatrixObj and IsMutable, IsInt, IsInt, IsObject ] ,
function( mat, column1, column2, scalar )
local i;

for i in [1..NrRows(mat)] do
mat[i,column1] := mat[i,column1] + scalar * mat[i,column2] ;
mat[i,column1] := mat[i,column1] + scalar * mat[i,column2];
od;

end );

############################################################################
InstallEarlyMethod( AddMatrixColumnsLeft,
function( mat, i, j, scalar )
local row;
if IsPlistRep(mat) then
for row in mat do
row[i] := row[i] + scalar * row[j];
od;
else
TryNextMethod();
fi;
end );

############################################################################

InstallMethod( SwapMatrixRows, "for a mutable matrix object, and two row numbers",
[ IsMatrixObj and IsMutable, IsInt, IsInt ],
[ IsMatrixOrMatrixObj and IsMutable, IsInt, IsInt ],
function( mat, row1, row2 )
local temp, i;

if row1 <> row2 then
for i in [1..NrCols(mat)] do
temp := mat[row1,i];
mat[row1,i] := mat[row2,i];
mat[row2,i] := temp;
od;
od;
fi;

end );

InstallEarlyMethod( SwapMatrixRows,
function( mat, i, j )
local tmp;
if IsPlistRep(mat) then
tmp := mat[i];
mat[i] := mat[j];
mat[j] := tmp;
else
TryNextMethod();
fi;
end );

############################################################################

InstallMethod( SwapMatrixColumns, "for a mutable matrix object, and two column numbers",
[ IsMatrixObj and IsMutable, IsInt, IsInt ],
[ IsMatrixOrMatrixObj and IsMutable, IsInt, IsInt ],
function( mat, column1, column2 )
local temp, i;

if column1 <> column2 then
for i in [1..NrRows(mat)] do
temp := mat[i,column1];
mat[i,column1] := mat[i,column2];
mat[i,column2] := temp;
od;
od;
fi;

end );

InstallEarlyMethod( SwapMatrixColumns,
function( mat, i, j )
local row, tmp;
if IsPlistRep(mat) then
for row in mat do
tmp := row[i];
row[i] := row[j];
row[j] := tmp;
od;
else
TryNextMethod();
fi;

end );
20 changes: 10 additions & 10 deletions lib/matobj2.gd
Original file line number Diff line number Diff line change
Expand Up @@ -1847,7 +1847,7 @@ DeclareOperation( "[]:=", [ IsMatrixOrMatrixObj, IsPosInt, IsPosInt, IsObject ]
## </ManSection>
## <#/GAPDoc>
##
DeclareOperation( "MultMatrixRowLeft", [ IsMatrixObj and IsMutable, IsInt, IsObject ] );
DeclareOperation( "MultMatrixRowLeft", [ IsMatrixOrMatrixObj and IsMutable, IsInt, IsObject ] );
DeclareSynonym( "MultMatrixRow", MultMatrixRowLeft);

############################################################################
Expand All @@ -1866,7 +1866,7 @@ DeclareSynonym( "MultMatrixRow", MultMatrixRowLeft);
## </ManSection>
## <#/GAPDoc>
##
DeclareOperation( "MultMatrixRowRight", [ IsMatrixObj and IsMutable, IsInt, IsObject ]);
DeclareOperation( "MultMatrixRowRight", [ IsMatrixOrMatrixObj and IsMutable, IsInt, IsObject ]);

############################################################################
##
Expand All @@ -1889,7 +1889,7 @@ DeclareOperation( "MultMatrixRowRight", [ IsMatrixObj and IsMutable, IsInt, IsOb
## </ManSection>
## <#/GAPDoc>
##
DeclareOperation( "MultMatrixColumnRight", [ IsMatrixObj and IsMutable, IsInt, IsObject ] );
DeclareOperation( "MultMatrixColumnRight", [ IsMatrixOrMatrixObj and IsMutable, IsInt, IsObject ] );
DeclareSynonym( "MultMatrixColumn", MultMatrixColumnRight);

############################################################################
Expand All @@ -1908,7 +1908,7 @@ DeclareSynonym( "MultMatrixColumn", MultMatrixColumnRight);
## </ManSection>
## <#/GAPDoc>
##
DeclareOperation( "MultMatrixColumnLeft", [ IsMatrixObj and IsMutable, IsInt, IsObject ] );
DeclareOperation( "MultMatrixColumnLeft", [ IsMatrixOrMatrixObj and IsMutable, IsInt, IsObject ] );

############################################################################
##
Expand All @@ -1931,7 +1931,7 @@ DeclareOperation( "MultMatrixColumnLeft", [ IsMatrixObj and IsMutable, IsInt, Is
## </ManSection>
## <#/GAPDoc>
##
DeclareOperation( "AddMatrixRowsLeft", [ IsMatrixObj and IsMutable, IsInt, IsInt, IsObject ] );
DeclareOperation( "AddMatrixRowsLeft", [ IsMatrixOrMatrixObj and IsMutable, IsInt, IsInt, IsObject ] );
DeclareSynonym( "AddMatrixRows", AddMatrixRowsLeft);

############################################################################
Expand All @@ -1950,7 +1950,7 @@ DeclareSynonym( "AddMatrixRows", AddMatrixRowsLeft);
## </ManSection>
## <#/GAPDoc>
##
DeclareOperation( "AddMatrixRowsRight", [ IsMatrixObj and IsMutable, IsInt, IsInt, IsObject ] );
DeclareOperation( "AddMatrixRowsRight", [ IsMatrixOrMatrixObj and IsMutable, IsInt, IsInt, IsObject ] );

############################################################################
##
Expand All @@ -1973,7 +1973,7 @@ DeclareOperation( "AddMatrixRowsRight", [ IsMatrixObj and IsMutable, IsInt, IsIn
## </ManSection>
## <#/GAPDoc>
##
DeclareOperation( "AddMatrixColumnsRight", [ IsMatrixObj and IsMutable, IsInt, IsInt, IsObject ] );
DeclareOperation( "AddMatrixColumnsRight", [ IsMatrixOrMatrixObj and IsMutable, IsInt, IsInt, IsObject ] );
DeclareSynonym( "AddMatrixColumns", AddMatrixColumnsRight);

############################################################################
Expand All @@ -1992,7 +1992,7 @@ DeclareSynonym( "AddMatrixColumns", AddMatrixColumnsRight);
## </ManSection>
## <#/GAPDoc>
##
DeclareOperation( "AddMatrixColumnsLeft", [ IsMatrixObj and IsMutable, IsInt, IsInt, IsObject ] );
DeclareOperation( "AddMatrixColumnsLeft", [ IsMatrixOrMatrixObj and IsMutable, IsInt, IsInt, IsObject ] );

############################################################################
##
Expand All @@ -2009,7 +2009,7 @@ DeclareOperation( "AddMatrixColumnsLeft", [ IsMatrixObj and IsMutable, IsInt, Is
## </ManSection>
## <#/GAPDoc>
##
DeclareOperation( "SwapMatrixRows", [ IsMatrixObj and IsMutable, IsInt, IsInt ] );
DeclareOperation( "SwapMatrixRows", [ IsMatrixOrMatrixObj and IsMutable, IsInt, IsInt ] );

############################################################################
##
Expand All @@ -2026,4 +2026,4 @@ DeclareOperation( "SwapMatrixRows", [ IsMatrixObj and IsMutable, IsInt, IsInt ]
## </ManSection>
## <#/GAPDoc>
##
DeclareOperation( "SwapMatrixColumns", [ IsMatrixObj and IsMutable, IsInt, IsInt ] );
DeclareOperation( "SwapMatrixColumns", [ IsMatrixOrMatrixObj and IsMutable, IsInt, IsInt ] );
36 changes: 36 additions & 0 deletions tst/testinstall/MatrixObj/ElementaryMatrices.tst
Original file line number Diff line number Diff line change
@@ -1,5 +1,41 @@
gap> START_TEST("ElementaryMatrices.tst");

#
gap> ReadGapRoot("tst/testinstall/MatrixObj/testmatobj.g");

#
gap> TestElementaryTransforms( [[2,4,5],[7,11,-4],[-3,20,0]], -1 );
gap> TestElementaryTransforms( Matrix( [[2,4,5],[7,11,-4],[-3,20,0]]), -1 );

#
gap> F := GF(2);;
gap> mat := RandomInvertibleMat(4, F);; # list of compressed vectors
gap> TestElementaryTransforms( mat, PrimitiveRoot(F) );
gap> ConvertToMatrixRep(mat);; # proper matrix obj
gap> TestElementaryTransforms( mat, PrimitiveRoot(F) );

#
gap> F := GF(3);;
gap> mat := RandomInvertibleMat(4, F);; # list of compressed vectors
gap> TestElementaryTransforms( mat, PrimitiveRoot(F) );
gap> ConvertToMatrixRep(mat);; # proper matrix obj
gap> TestElementaryTransforms( mat, PrimitiveRoot(F) );

#
gap> F := GF(4);;
gap> mat := RandomInvertibleMat(4, F);; # list of compressed vectors
gap> TestElementaryTransforms( mat, PrimitiveRoot(F) );
gap> ConvertToMatrixRep(mat);; # proper matrix obj
gap> TestElementaryTransforms( mat, PrimitiveRoot(F) );

#
gap> F := GF(5);;
gap> mat := RandomInvertibleMat(4, F);; # list of compressed vectors
gap> TestElementaryTransforms( mat, PrimitiveRoot(F) );
gap> ConvertToMatrixRep(mat);; # proper matrix obj
gap> TestElementaryTransforms( mat, PrimitiveRoot(F) );

##########
#
gap> mat := Matrix( [[2,4,5],[7,11,-4],[-3,20,0]]);;
gap> SwapMatrixRows(mat,1,3);
Expand Down
Loading

0 comments on commit b9435f9

Please sign in to comment.