B The Matrix Tool Operations The functions listed below are components of the homalgTable object stored in the ring. They are only indirectly accessible through standard methods that invoke them. B.1 The Tool Operations without a Fallback Method There are matrix methods for which homalg needs a homalgTable entry for non-internal rings, as it cannot provide a suitable fallback. Below is the list of these homalgTable entries. B.1-1 InitialMatrix InitialMatrix( C )  function Returns: the Eval value of a homalg matrix C Let R := HomalgRing( C ) and RP := homalgTable( R ). If the homalgTable component RP!.InitialMatrix is bound then the method Eval (C.4-1) resets the filter IsInitialMatrix and returns RP!.InitialMatrix( C ). B.1-2 InitialIdentityMatrix InitialIdentityMatrix( C )  function Returns: the Eval value of a homalg matrix C Let R := HomalgRing( C ) and RP := homalgTable( R ). If the homalgTable component RP!.InitialIdentityMatrix is bound then the method Eval (C.4-2) resets the filter IsInitialIdentityMatrix and returns RP!.InitialIdentityMatrix( C ). B.1-3 ZeroMatrix ZeroMatrix( C )  function Returns: the Eval value of a homalg matrix C Let R := HomalgRing( C ) and RP := homalgTable( R ). If the homalgTable component RP!.ZeroMatrix is bound then the method Eval (C.4-3) returns RP!.ZeroMatrix( C ). B.1-4 IdentityMatrix IdentityMatrix( C )  function Returns: the Eval value of a homalg matrix C Let R := HomalgRing( C ) and RP := homalgTable( R ). If the homalgTable component RP!.IdentityMatrix is bound then the method Eval (C.4-4) returns RP!.IdentityMatrix( C ). B.1-5 Involution Involution( M )  function Returns: the Eval value of a homalg matrix C Let R := HomalgRing( C ) and RP := homalgTable( R ). If the homalgTable component RP!.Involution is bound then the method Eval (C.4-7) returns RP!.Involution applied to the content of the attribute EvalInvolution( C ) = M. B.1-6 CertainRows CertainRows( M, plist )  function Returns: the Eval value of a homalg matrix C Let R := HomalgRing( C ) and RP := homalgTable( R ). If the homalgTable component RP!.CertainRows is bound then the method Eval (C.4-8) returns RP!.CertainRows applied to the content of the attribute EvalCertainRows( C ) = [ M, plist ]. B.1-7 CertainColumns CertainColumns( M, plist )  function Returns: the Eval value of a homalg matrix C Let R := HomalgRing( C ) and RP := homalgTable( R ). If the homalgTable component RP!.CertainColumns is bound then the method Eval (C.4-9) returns RP!.CertainColumns applied to the content of the attribute EvalCertainColumns( C ) = [ M, plist ]. B.1-8 UnionOfRows UnionOfRows( A, B )  function Returns: the Eval value of a homalg matrix C Let R := HomalgRing( C ) and RP := homalgTable( R ). If the homalgTable component RP!.UnionOfRows is bound then the method Eval (C.4-10) returns RP!.UnionOfRows applied to the content of the attribute EvalUnionOfRows( C ) = [ A, B ]. B.1-9 UnionOfColumns UnionOfColumns( A, B )  function Returns: the Eval value of a homalg matrix C Let R := HomalgRing( C ) and RP := homalgTable( R ). If the homalgTable component RP!.UnionOfColumns is bound then the method Eval (C.4-11) returns RP!.UnionOfColumns applied to the content of the attribute EvalUnionOfColumns( C ) = [ A, B ]. B.1-10 DiagMat DiagMat( e )  function Returns: the Eval value of a homalg matrix C Let R := HomalgRing( C ) and RP := homalgTable( R ). If the homalgTable component RP!.DiagMat is bound then the method Eval (C.4-12) returns RP!.DiagMat applied to the content of the attribute EvalDiagMat( C ) = e. B.1-11 KroneckerMat KroneckerMat( A, B )  function Returns: the Eval value of a homalg matrix C Let R := HomalgRing( C ) and RP := homalgTable( R ). If the homalgTable component RP!.KroneckerMat is bound then the method Eval (C.4-13) returns RP!.KroneckerMat applied to the content of the attribute EvalKroneckerMat( C ) = [ A, B ]. B.1-12 MulMat MulMat( a, A )  function Returns: the Eval value of a homalg matrix C Let R := HomalgRing( C ) and RP := homalgTable( R ). If the homalgTable component RP!.MulMat is bound then the method Eval (C.4-14) returns RP!.MulMat applied to the content of the attribute EvalMulMat( C ) = [ a, A ]. B.1-13 AddMat AddMat( A, B )  function Returns: the Eval value of a homalg matrix C Let R := HomalgRing( C ) and RP := homalgTable( R ). If the homalgTable component RP!.AddMat is bound then the method Eval (C.4-15) returns RP!.AddMat applied to the content of the attribute EvalAddMat( C ) = [ A, B ]. B.1-14 SubMat SubMat( A, B )  function Returns: the Eval value of a homalg matrix C Let R := HomalgRing( C ) and RP := homalgTable( R ). If the homalgTable component RP!.SubMat is bound then the method Eval (C.4-16) returns RP!.SubMat applied to the content of the attribute EvalSubMat( C ) = [ A, B ]. B.1-15 Compose Compose( A, B )  function Returns: the Eval value of a homalg matrix C Let R := HomalgRing( C ) and RP := homalgTable( R ). If the homalgTable component RP!.Compose is bound then the method Eval (C.4-17) returns RP!.Compose applied to the content of the attribute EvalCompose( C ) = [ A, B ]. B.1-16 IsZeroMatrix IsZeroMatrix( M )  function Returns: true or false Let R := HomalgRing( M ) and RP := homalgTable( R ). If the homalgTable component RP!.IsZeroMatrix is bound then the standard method for the property IsZero (5.3-1) shown below returns RP!.IsZeroMatrix( M ).  Code  InstallMethod( IsZero,  "for homalg matrices",  [ IsHomalgMatrix ],    function( M )  local R, RP;    R := HomalgRing( M );    RP := homalgTable( R );    if IsBound(RP!.IsZeroMatrix) then  ## CAUTION: the external system must be able  ## to check zero modulo possible ring relations!    return RP!.IsZeroMatrix( M ); ## with this, \= can fall back to IsZero  fi;    #=====# the fallback method #=====#    ## from the GAP4 documentation: ?Zero  ## `ZeroSameMutability( )' is equivalent to `0 * '.    return M = 0 * M; ## hence, by default, IsZero falls back to \= (see below)   end );  B.1-17 NrRows NrRows( C )  function Returns: a nonnegative integer Let R := HomalgRing( C ) and RP := homalgTable( R ). If the homalgTable component RP!.NrRows is bound then the standard method for the attribute NrRows (5.4-1) shown below returns RP!.NrRows( C ).  Code  InstallMethod( NrRows,  "for homalg matrices",  [ IsHomalgMatrix ],    function( C )  local R, RP;    R := HomalgRing( C );    RP := homalgTable( R );    if IsBound(RP!.NrRows) then  return RP!.NrRows( C );  fi;    if not IsHomalgInternalMatrixRep( C ) then  Error( "could not find a procedure called NrRows ",  "in the homalgTable of the non-internal ring\n" );  fi;    #=====# can only work for homalg internal matrices #=====#    return Length( Eval( C )!.matrix );   end );  B.1-18 NrColumns NrColumns( C )  function Returns: a nonnegative integer Let R := HomalgRing( C ) and RP := homalgTable( R ). If the homalgTable component RP!.NrColumns is bound then the standard method for the attribute NrColumns (5.4-2) shown below returns RP!.NrColumns( C ).  Code  InstallMethod( NrColumns,  "for homalg matrices",  [ IsHomalgMatrix ],    function( C )  local R, RP;    R := HomalgRing( C );    RP := homalgTable( R );    if IsBound(RP!.NrColumns) then  return RP!.NrColumns( C );  fi;    if not IsHomalgInternalMatrixRep( C ) then  Error( "could not find a procedure called NrColumns ",  "in the homalgTable of the non-internal ring\n" );  fi;    #=====# can only work for homalg internal matrices #=====#    return Length( Eval( C )!.matrix[ 1 ] );   end );  B.1-19 Determinant Determinant( C )  function Returns: a ring element Let R := HomalgRing( C ) and RP := homalgTable( R ). If the homalgTable component RP!.Determinant is bound then the standard method for the attribute DeterminantMat (5.4-3) shown below returns RP!.Determinant( C ).  Code  InstallMethod( DeterminantMat,  "for homalg matrices",  [ IsHomalgMatrix ],    function( C )  local R, RP;    R := HomalgRing( C );    RP := homalgTable( R );    if NrRows( C ) <> NrColumns( C ) then  Error( "the matrix is not a square matrix\n" );  fi;    if IsEmptyMatrix( C ) then  return One( R );  elif IsZero( C ) then  return Zero( R );  fi;    if IsBound(RP!.Determinant) then  return RingElementConstructor( R )( RP!.Determinant( C ), R );  fi;    if not IsHomalgInternalMatrixRep( C ) then  Error( "could not find a procedure called Determinant ",  "in the homalgTable of the non-internal ring\n" );  fi;    #=====# can only work for homalg internal matrices #=====#    return Determinant( Eval( C )!.matrix );   end );   InstallMethod( Determinant,  "for homalg matrices",  [ IsHomalgMatrix ],    function( C )    return DeterminantMat( C );   end );  B.2 The Tool Operations with a Fallback Method These are the methods for which it is recommended for performance reasons to have a homalgTable entry for non-internal rings. homalg only provides a generic fallback method. B.2-1 AreEqualMatrices AreEqualMatrices( M1, M2 )  function Returns: true or false Let R := HomalgRing( M1 ) and RP := homalgTable( R ). If the homalgTable component RP!.AreEqualMatrices is bound then the standard method for the operation \= (5.5-17) shown below returns RP!.AreEqualMatrices( M1, M2 ).  Code  InstallMethod( \=,  "for homalg comparable matrices",  [ IsHomalgMatrix, IsHomalgMatrix ],    function( M1, M2 )  local R, RP, are_equal;    ## do not touch mutable matrices  if not ( IsMutable( M1 ) or IsMutable( M2 ) ) then    if IsBound( M1!.AreEqual ) then  are_equal := _ElmWPObj_ForHomalg( M1!.AreEqual, M2, fail );  if are_equal <> fail then  return are_equal;  fi;  else  M1!.AreEqual :=  ContainerForWeakPointers(  TheTypeContainerForWeakPointersOnComputedValues,  [ "operation", "AreEqual" ] );  fi;    if IsBound( M2!.AreEqual ) then  are_equal := _ElmWPObj_ForHomalg( M2!.AreEqual, M1, fail );  if are_equal <> fail then  return are_equal;  fi;  fi;  ## do not store things symmetrically below to ``save'' memory    fi;    R := HomalgRing( M1 );    RP := homalgTable( R );    if IsBound(RP!.AreEqualMatrices) then  ## CAUTION: the external system must be able to check equality  ## modulo possible ring relations (known to the external system)!  are_equal := RP!.AreEqualMatrices( M1, M2 );  elif IsBound(RP!.Equal) then  ## CAUTION: the external system must be able to check equality  ## modulo possible ring relations (known to the external system)!  are_equal := RP!.Equal( M1, M2 );  elif IsBound(RP!.IsZeroMatrix) then ## ensuring this avoids infinite loops  are_equal := IsZero( M1 - M2 );  fi;    if IsBound( are_equal ) then    ## do not touch mutable matrices  if not ( IsMutable( M1 ) or IsMutable( M2 ) ) then    if are_equal then  MatchPropertiesAndAttributes( M1, M2,  LIMAT.intrinsic_properties,  LIMAT.intrinsic_attributes,  LIMAT.intrinsic_components  );  fi;    ## do not store things symmetrically to ``save'' memory  _AddTwoElmWPObj_ForHomalg( M1!.AreEqual, M2, are_equal );    fi;    return are_equal;  fi;    TryNextMethod( );   end );  B.2-2 IsIdentityMatrix IsIdentityMatrix( M )  function Returns: true or false Let R := HomalgRing( M ) and RP := homalgTable( R ). If the homalgTable component RP!.IsIdentityMatrix is bound then the standard method for the property IsOne (5.3-2) shown below returns RP!.IsIdentityMatrix( M ).  Code  InstallMethod( IsOne,  "for homalg matrices",  [ IsHomalgMatrix ],    function( M )  local R, RP;    if NrRows( M ) <> NrColumns( M ) then  return false;  fi;    R := HomalgRing( M );    RP := homalgTable( R );    if IsBound(RP!.IsIdentityMatrix) then  return RP!.IsIdentityMatrix( M );  fi;    #=====# the fallback method #=====#    return M = HomalgIdentityMatrix( NrRows( M ), HomalgRing( M ) );   end );  B.2-3 IsDiagonalMatrix IsDiagonalMatrix( M )  function Returns: true or false Let R := HomalgRing( M ) and RP := homalgTable( R ). If the homalgTable component RP!.IsDiagonalMatrix is bound then the standard method for the property IsDiagonalMatrix (5.3-13) shown below returns RP!.IsDiagonalMatrix( M ).  Code  InstallMethod( IsDiagonalMatrix,  "for homalg matrices",  [ IsHomalgMatrix ],    function( M )  local R, RP, diag;    R := HomalgRing( M );    RP := homalgTable( R );    if IsBound(RP!.IsDiagonalMatrix) then  return RP!.IsDiagonalMatrix( M );  fi;    #=====# the fallback method #=====#    diag := DiagonalEntries( M );    return M = HomalgDiagonalMatrix( diag, NrRows( M ), NrColumns( M ), R );   end );  B.2-4 ZeroRows ZeroRows( C )  function Returns: a (possibly empty) list of positive integers Let R := HomalgRing( C ) and RP := homalgTable( R ). If the homalgTable component RP!.ZeroRows is bound then the standard method of the attribute ZeroRows (5.4-4) shown below returns RP!.ZeroRows( C ).  Code  InstallMethod( ZeroRows,  "for homalg matrices",  [ IsHomalgMatrix ],    function( C )  local R, RP, z;    R := HomalgRing( C );    RP := homalgTable( R );    if IsBound(RP!.ZeroRows) then  return RP!.ZeroRows( C );  fi;    #=====# the fallback method #=====#    z := HomalgZeroMatrix( 1, NrColumns( C ), R );    return Filtered( [ 1 .. NrRows( C ) ], a -> CertainRows( C, [ a ] ) = z );   end );  B.2-5 ZeroColumns ZeroColumns( C )  function Returns: a (possibly empty) list of positive integers Let R := HomalgRing( C ) and RP := homalgTable( R ). If the homalgTable component RP!.ZeroColumns is bound then the standard method of the attribute ZeroColumns (5.4-5) shown below returns RP!.ZeroColumns( C ).  Code  InstallMethod( ZeroColumns,  "for homalg matrices",  [ IsHomalgMatrix ],    function( C )  local R, RP, z;    R := HomalgRing( C );    RP := homalgTable( R );    if IsBound(RP!.ZeroColumns) then  return RP!.ZeroColumns( C );  fi;    #=====# the fallback method #=====#    z := HomalgZeroMatrix( NrRows( C ), 1, R );    return Filtered( [ 1 .. NrColumns( C ) ], a -> CertainColumns( C, [ a ] ) = z );   end );  B.2-6 GetColumnIndependentUnitPositions GetColumnIndependentUnitPositions( M, poslist )  function Returns: a (possibly empty) list of pairs of positive integers Let R := HomalgRing( M ) and RP := homalgTable( R ). If the homalgTable component RP!.GetColumnIndependentUnitPositions is bound then the standard method of the operation GetColumnIndependentUnitPositions (5.5-18) shown below returns RP!.GetColumnIndependentUnitPositions( M, poslist ).  Code  InstallMethod( GetColumnIndependentUnitPositions,  "for homalg matrices",  [ IsHomalgMatrix, IsHomogeneousList ],    function( M, poslist )  local cache, R, RP, rest, pos, i, j, k;    if IsBound( M!.GetColumnIndependentUnitPositions ) then  cache := M!.GetColumnIndependentUnitPositions;  if IsBound( cache.(String( poslist )) ) then  return cache.(String( poslist ));  fi;  else  cache := rec( );  M!.GetColumnIndependentUnitPositions := cache;  fi;    R := HomalgRing( M );    RP := homalgTable( R );    if IsBound(RP!.GetColumnIndependentUnitPositions) then  pos := RP!.GetColumnIndependentUnitPositions( M, poslist );  if pos <> [ ] then  SetIsZero( M, false );  fi;  cache.(String( poslist )) := pos;  return pos;  fi;    #=====# the fallback method #=====#    rest := [ 1 .. NrColumns( M ) ];    pos := [ ];    for i in [ 1 .. NrRows( M ) ] do  for k in Reversed( rest ) do  if not [ i, k ] in poslist and  IsUnit( R, MatElm( M, i, k ) ) then  Add( pos, [ i, k ] );  rest := Filtered( rest,  a -> IsZero( MatElm( M, i, a ) ) );  break;  fi;  od;  od;    if pos <> [ ] then  SetIsZero( M, false );  fi;    cache.(String( poslist )) := pos;    return pos;   end );  B.2-7 GetRowIndependentUnitPositions GetRowIndependentUnitPositions( M, poslist )  function Returns: a (possibly empty) list of pairs of positive integers Let R := HomalgRing( M ) and RP := homalgTable( R ). If the homalgTable component RP!.GetRowIndependentUnitPositions is bound then the standard method of the operation GetRowIndependentUnitPositions (5.5-19) shown below returns RP!.GetRowIndependentUnitPositions( M, poslist ).  Code  InstallMethod( GetRowIndependentUnitPositions,  "for homalg matrices",  [ IsHomalgMatrix, IsHomogeneousList ],    function( M, poslist )  local cache, R, RP, rest, pos, j, i, k;    if IsBound( M!.GetRowIndependentUnitPositions ) then  cache := M!.GetRowIndependentUnitPositions;  if IsBound( cache.(String( poslist )) ) then  return cache.(String( poslist ));  fi;  else  cache := rec( );  M!.GetRowIndependentUnitPositions := cache;  fi;    R := HomalgRing( M );    RP := homalgTable( R );    if IsBound(RP!.GetRowIndependentUnitPositions) then  pos := RP!.GetRowIndependentUnitPositions( M, poslist );  if pos <> [ ] then  SetIsZero( M, false );  fi;  cache.( String( poslist ) ) := pos;  return pos;  fi;    #=====# the fallback method #=====#    rest := [ 1 .. NrRows( M ) ];    pos := [ ];    for j in [ 1 .. NrColumns( M ) ] do  for k in Reversed( rest ) do  if not [ j, k ] in poslist and  IsUnit( R, MatElm( M, k, j ) ) then  Add( pos, [ j, k ] );  rest := Filtered( rest,  a -> IsZero( MatElm( M, a, j ) ) );  break;  fi;  od;  od;    if pos <> [ ] then  SetIsZero( M, false );  fi;    cache.( String( poslist ) ) := pos;    return pos;   end );  B.2-8 GetUnitPosition GetUnitPosition( M, poslist )  function Returns: a (possibly empty) list of pairs of positive integers Let R := HomalgRing( M ) and RP := homalgTable( R ). If the homalgTable component RP!.GetUnitPosition is bound then the standard method of the operation GetUnitPosition (5.5-20) shown below returns RP!.GetUnitPosition( M, poslist ).  Code  InstallMethod( GetUnitPosition,  "for homalg matrices",  [ IsHomalgMatrix, IsHomogeneousList ],    function( M, poslist )  local R, RP, pos, m, n, i, j;    R := HomalgRing( M );    RP := homalgTable( R );    if IsBound(RP!.GetUnitPosition) then  pos := RP!.GetUnitPosition( M, poslist );  if IsList( pos ) and IsPosInt( pos[1] ) and IsPosInt( pos[2] ) then  SetIsZero( M, false );  fi;  return pos;  fi;    #=====# the fallback method #=====#    m := NrRows( M );  n := NrColumns( M );    for i in [ 1 .. m ] do  for j in [ 1 .. n ] do  if not [ i, j ] in poslist and not j in poslist and  IsUnit( R, MatElm( M, i, j ) ) then  SetIsZero( M, false );  return [ i, j ];  fi;  od;  od;    return fail;   end );  B.2-9 PositionOfFirstNonZeroEntryPerRow PositionOfFirstNonZeroEntryPerRow( M, poslist )  function Returns: a list of nonnegative integers Let R := HomalgRing( M ) and RP := homalgTable( R ). If the homalgTable component RP!.PositionOfFirstNonZeroEntryPerRow is bound then the standard method of the attribute PositionOfFirstNonZeroEntryPerRow (5.4-8) shown below returns RP!.PositionOfFirstNonZeroEntryPerRow( M ).  Code  InstallMethod( PositionOfFirstNonZeroEntryPerRow,  "for homalg matrices",  [ IsHomalgMatrix ],    function( M )  local R, RP, pos, entries, r, c, i, k, j;    R := HomalgRing( M );    RP := homalgTable( R );    if IsBound(RP!.PositionOfFirstNonZeroEntryPerRow) then  return RP!.PositionOfFirstNonZeroEntryPerRow( M );  elif IsBound(RP!.PositionOfFirstNonZeroEntryPerColumn) then  return PositionOfFirstNonZeroEntryPerColumn( Involution( M ) );  fi;    #=====# the fallback method #=====#    entries := EntriesOfHomalgMatrix( M );    r := NrRows( M );  c := NrColumns( M );    pos := ListWithIdenticalEntries( r, 0 );    for i in [ 1 .. r ] do  k := (i - 1) * c;  for j in [ 1 .. c ] do  if not IsZero( entries[k + j] ) then  pos[i] := j;  break;  fi;  od;  od;    return pos;   end );  B.2-10 PositionOfFirstNonZeroEntryPerColumn PositionOfFirstNonZeroEntryPerColumn( M, poslist )  function Returns: a list of nonnegative integers Let R := HomalgRing( M ) and RP := homalgTable( R ). If the homalgTable component RP!.PositionOfFirstNonZeroEntryPerColumn is bound then the standard method of the attribute PositionOfFirstNonZeroEntryPerColumn (5.4-9) shown below returns RP!.PositionOfFirstNonZeroEntryPerColumn( M ).  Code  InstallMethod( PositionOfFirstNonZeroEntryPerColumn,  "for homalg matrices",  [ IsHomalgMatrix ],    function( M )  local R, RP, pos, entries, r, c, j, i, k;    R := HomalgRing( M );    RP := homalgTable( R );    if IsBound(RP!.PositionOfFirstNonZeroEntryPerColumn) then  return RP!.PositionOfFirstNonZeroEntryPerColumn( M );  elif IsBound(RP!.PositionOfFirstNonZeroEntryPerRow) then  return PositionOfFirstNonZeroEntryPerRow( Involution( M ) );  fi;    #=====# the fallback method #=====#    entries := EntriesOfHomalgMatrix( M );    r := NrRows( M );  c := NrColumns( M );    pos := ListWithIdenticalEntries( c, 0 );    for j in [ 1 .. c ] do  for i in [ 1 .. r ] do  k := (i - 1) * c;  if not IsZero( entries[k + j] ) then  pos[j] := i;  break;  fi;  od;  od;    return pos;   end );