  
  [1XB [33X[0;0YThe Matrix Tool Operations[133X[101X
  
  [33X[0;0YThe  functions  listed below are components of the [10XhomalgTable[110X object stored
  in  the  ring.  They are only indirectly accessible through standard methods
  that invoke them.[133X
  
  
  [1XB.1 [33X[0;0YThe Tool Operations [13Xwithout[113X[101X[1X a Fallback Method[133X[101X
  
  [33X[0;0YThere  are  matrix  methods  for  which [5Xhomalg[105X needs a [10XhomalgTable[110X entry for
  non-internal  rings,  as it cannot provide a suitable fallback. Below is the
  list of these [10XhomalgTable[110X entries.[133X
  
  [1XB.1-1 InitialMatrix[101X
  
  [33X[1;0Y[29X[2XInitialMatrix[102X( [3XC[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ythe [10XEval[110X value of a [5Xhomalg[105X matrix [3XC[103X[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XC[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component [22XRP[122X!.[10XInitialMatrix[110X is bound then the method [2XEval[102X ([14XC.4-1[114X) resets the
  filter [10XIsInitialMatrix[110X and returns [22XRP[122X!.[10XInitialMatrix[110X[22X( [3XC[103X )[122X.[133X
  
  [1XB.1-2 InitialIdentityMatrix[101X
  
  [33X[1;0Y[29X[2XInitialIdentityMatrix[102X( [3XC[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ythe [10XEval[110X value of a [5Xhomalg[105X matrix [3XC[103X[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XC[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component  [22XRP[122X!.[10XInitialIdentityMatrix[110X  is  bound then the method [2XEval[102X ([14XC.4-2[114X)
  resets      the      filter      [10XIsInitialIdentityMatrix[110X     and     returns
  [22XRP[122X!.[10XInitialIdentityMatrix[110X[22X( [3XC[103X )[122X.[133X
  
  [1XB.1-3 ZeroMatrix[101X
  
  [33X[1;0Y[29X[2XZeroMatrix[102X( [3XC[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ythe [10XEval[110X value of a [5Xhomalg[105X matrix [3XC[103X[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XC[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component  [22XRP[122X!.[10XZeroMatrix[110X  is  bound  then  the  method [2XEval[102X ([14XC.4-3[114X) returns
  [22XRP[122X!.[10XZeroMatrix[110X[22X( [3XC[103X )[122X.[133X
  
  [1XB.1-4 IdentityMatrix[101X
  
  [33X[1;0Y[29X[2XIdentityMatrix[102X( [3XC[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ythe [10XEval[110X value of a [5Xhomalg[105X matrix [3XC[103X[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XC[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component  [22XRP[122X!.[10XIdentityMatrix[110X  is bound then the method [2XEval[102X ([14XC.4-4[114X) returns
  [22XRP[122X!.[10XIdentityMatrix[110X[22X( [3XC[103X )[122X.[133X
  
  [1XB.1-5 Involution[101X
  
  [33X[1;0Y[29X[2XInvolution[102X( [3XM[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ythe [10XEval[110X value of a [5Xhomalg[105X matrix [3XC[103X[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XC[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component  [22XRP[122X!.[10XInvolution[110X  is  bound  then  the  method [2XEval[102X ([14XC.4-7[114X) returns
  [22XRP[122X!.[10XInvolution[110X applied to the content of the attribute [10XEvalInvolution[110X[22X( [3XC[103X ) =
  [3XM[103X[122X.[133X
  
  [1XB.1-6 TransposedMatrix[101X
  
  [33X[1;0Y[29X[2XTransposedMatrix[102X( [3XM[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ythe [10XEval[110X value of a [5Xhomalg[105X matrix [3XC[103X[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XC[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component [22XRP[122X!.[10XTransposedMatrix[110X is bound then the method [2XEval[102X ([14XC.4-8[114X) returns
  [22XRP[122X!.[10XTransposedMatrix[110X    applied    to   the   content   of   the   attribute
  [10XEvalTransposedMatrix[110X[22X( [3XC[103X ) = [3XM[103X[122X.[133X
  
  [1XB.1-7 CertainRows[101X
  
  [33X[1;0Y[29X[2XCertainRows[102X( [3XM[103X, [3Xplist[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ythe [10XEval[110X value of a [5Xhomalg[105X matrix [3XC[103X[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XC[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component  [22XRP[122X!.[10XCertainRows[110X  is  bound  then  the method [2XEval[102X ([14XC.4-9[114X) returns
  [22XRP[122X!.[10XCertainRows[110X applied to the content of the attribute [10XEvalCertainRows[110X[22X( [3XC[103X )
  = [ [3XM[103X, [3Xplist[103X ][122X.[133X
  
  [1XB.1-8 CertainColumns[101X
  
  [33X[1;0Y[29X[2XCertainColumns[102X( [3XM[103X, [3Xplist[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ythe [10XEval[110X value of a [5Xhomalg[105X matrix [3XC[103X[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XC[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component  [22XRP[122X!.[10XCertainColumns[110X is bound then the method [2XEval[102X ([14XC.4-10[114X) returns
  [22XRP[122X!.[10XCertainColumns[110X    applied    to    the    content   of   the   attribute
  [10XEvalCertainColumns[110X[22X( [3XC[103X ) = [ [3XM[103X, [3Xplist[103X ][122X.[133X
  
  [1XB.1-9 UnionOfRows[101X
  
  [33X[1;0Y[29X[2XUnionOfRows[102X( [3XA[103X, [3XB[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ythe [10XEval[110X value of a [5Xhomalg[105X matrix [3XC[103X[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XC[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component  [22XRP[122X!.[10XUnionOfRows[110X  is  bound  then the method [2XEval[102X ([14XC.4-11[114X) returns
  [22XRP[122X!.[10XUnionOfRows[110X applied to the content of the attribute [10XEvalUnionOfRows[110X[22X( [3XC[103X )
  = [ [3XA[103X, [3XB[103X ][122X.[133X
  
  [1XB.1-10 UnionOfColumns[101X
  
  [33X[1;0Y[29X[2XUnionOfColumns[102X( [3XA[103X, [3XB[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ythe [10XEval[110X value of a [5Xhomalg[105X matrix [3XC[103X[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XC[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component  [22XRP[122X!.[10XUnionOfColumns[110X is bound then the method [2XEval[102X ([14XC.4-12[114X) returns
  [22XRP[122X!.[10XUnionOfColumns[110X    applied    to    the    content   of   the   attribute
  [10XEvalUnionOfColumns[110X[22X( [3XC[103X ) = [ [3XA[103X, [3XB[103X ][122X.[133X
  
  [1XB.1-11 DiagMat[101X
  
  [33X[1;0Y[29X[2XDiagMat[102X( [3Xe[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ythe [10XEval[110X value of a [5Xhomalg[105X matrix [3XC[103X[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XC[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component  [22XRP[122X!.[10XDiagMat[110X  is  bound  then  the  method  [2XEval[102X  ([14XC.4-13[114X) returns
  [22XRP[122X!.[10XDiagMat[110X applied to the content of the attribute [10XEvalDiagMat[110X[22X( [3XC[103X ) = [3Xe[103X[122X.[133X
  
  [1XB.1-12 KroneckerMat[101X
  
  [33X[1;0Y[29X[2XKroneckerMat[102X( [3XA[103X, [3XB[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ythe [10XEval[110X value of a [5Xhomalg[105X matrix [3XC[103X[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XC[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component  [22XRP[122X!.[10XKroneckerMat[110X  is  bound then the method [2XEval[102X ([14XC.4-14[114X) returns
  [22XRP[122X!.[10XKroneckerMat[110X applied to the content of the attribute [10XEvalKroneckerMat[110X[22X( [3XC[103X
  ) = [ [3XA[103X, [3XB[103X ][122X.[133X
  
  [1XB.1-13 MulMat[101X
  
  [33X[1;0Y[29X[2XMulMat[102X( [3Xa[103X, [3XA[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ythe [10XEval[110X value of a [5Xhomalg[105X matrix [3XC[103X[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XC[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component  [22XRP[122X!.[10XMulMat[110X  is  bound  then  the  method  [2XEval[102X  ([14XC.4-15[114X)  returns
  [22XRP[122X!.[10XMulMat[110X  applied to the content of the attribute [10XEvalMulMat[110X[22X( [3XC[103X ) = [ [3Xa[103X, [3XA[103X
  ][122X.[133X
  
  [1XB.1-14 AddMat[101X
  
  [33X[1;0Y[29X[2XAddMat[102X( [3XA[103X, [3XB[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ythe [10XEval[110X value of a [5Xhomalg[105X matrix [3XC[103X[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XC[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component  [22XRP[122X!.[10XAddMat[110X  is  bound  then  the  method  [2XEval[102X  ([14XC.4-16[114X)  returns
  [22XRP[122X!.[10XAddMat[110X  applied to the content of the attribute [10XEvalAddMat[110X[22X( [3XC[103X ) = [ [3XA[103X, [3XB[103X
  ][122X.[133X
  
  [1XB.1-15 SubMat[101X
  
  [33X[1;0Y[29X[2XSubMat[102X( [3XA[103X, [3XB[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ythe [10XEval[110X value of a [5Xhomalg[105X matrix [3XC[103X[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XC[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component  [22XRP[122X!.[10XSubMat[110X  is  bound  then  the  method  [2XEval[102X  ([14XC.4-17[114X)  returns
  [22XRP[122X!.[10XSubMat[110X  applied to the content of the attribute [10XEvalSubMat[110X[22X( [3XC[103X ) = [ [3XA[103X, [3XB[103X
  ][122X.[133X
  
  [1XB.1-16 Compose[101X
  
  [33X[1;0Y[29X[2XCompose[102X( [3XA[103X, [3XB[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ythe [10XEval[110X value of a [5Xhomalg[105X matrix [3XC[103X[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XC[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component  [22XRP[122X!.[10XCompose[110X  is  bound  then  the  method  [2XEval[102X  ([14XC.4-18[114X) returns
  [22XRP[122X!.[10XCompose[110X  applied to the content of the attribute [10XEvalCompose[110X[22X( [3XC[103X ) = [ [3XA[103X,
  [3XB[103X ][122X.[133X
  
  [1XB.1-17 IsZeroMatrix[101X
  
  [33X[1;0Y[29X[2XIsZeroMatrix[102X( [3XM[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Y[10Xtrue[110X or [10Xfalse[110X[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XM[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component  [22XRP[122X!.[10XIsZeroMatrix[110X  is  bound  then  the  standard  method  for the
  property [2XIsZero[102X ([14X5.3-1[114X) shown below returns [22XRP[122X!.[10XIsZeroMatrix[110X[22X( [3XM[103X )[122X.[133X
  
  [4X[32X  Code  [32X[104X
    [4XInstallMethod( IsZero,[104X
    [4X        "for homalg matrices",[104X
    [4X        [ IsHomalgMatrix ],[104X
    [4X        [104X
    [4X  function( M )[104X
    [4X    local R, RP;[104X
    [4X    [104X
    [4X    R := HomalgRing( M );[104X
    [4X    [104X
    [4X    RP := homalgTable( R );[104X
    [4X    [104X
    [4X    if IsBound(RP!.IsZeroMatrix) then[104X
    [4X        ## CAUTION: the external system must be able[104X
    [4X        ## to check zero modulo possible ring relations![104X
    [4X        [104X
    [4X        return RP!.IsZeroMatrix( M ); ## with this, \= can fall back to IsZero[104X
    [4X    fi;[104X
    [4X    [104X
    [4X    #=====# the fallback method #=====#[104X
    [4X    [104X
    [4X    ## from the GAP4 documentation: ?Zero[104X
    [4X    ## `ZeroSameMutability( <obj> )' is equivalent to `0 * <obj>'.[104X
    [4X    [104X
    [4X    return M = 0 * M; ## hence, by default, IsZero falls back to \= (see below)[104X
    [4X    [104X
    [4Xend );[104X
  [4X[32X[104X
  
  [1XB.1-18 NrRows[101X
  
  [33X[1;0Y[29X[2XNrRows[102X( [3XC[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ya nonnegative integer[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XC[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component  [22XRP[122X!.[10XNrRows[110X  is  bound  then the standard method for the attribute
  [2XNrRows[102X ([14X5.4-1[114X) shown below returns [22XRP[122X!.[10XNrRows[110X[22X( [3XC[103X )[122X.[133X
  
  [4X[32X  Code  [32X[104X
    [4XInstallMethod( NrRows,[104X
    [4X        "for homalg matrices",[104X
    [4X        [ IsHomalgMatrix ],[104X
    [4X        [104X
    [4X  function( C )[104X
    [4X    local R, RP;[104X
    [4X    [104X
    [4X    R := HomalgRing( C );[104X
    [4X    [104X
    [4X    RP := homalgTable( R );[104X
    [4X    [104X
    [4X    if IsBound(RP!.NrRows) then[104X
    [4X        return RP!.NrRows( C );[104X
    [4X    fi;[104X
    [4X    [104X
    [4X    if not IsHomalgInternalMatrixRep( C ) then[104X
    [4X        Error( "could not find a procedure called NrRows ",[104X
    [4X               "in the homalgTable of the non-internal ring\n" );[104X
    [4X    fi;[104X
    [4X    [104X
    [4X    #=====# can only work for homalg internal matrices #=====#[104X
    [4X    [104X
    [4X    return Length( Eval( C )!.matrix );[104X
    [4X    [104X
    [4Xend );[104X
  [4X[32X[104X
  
  [1XB.1-19 NrColumns[101X
  
  [33X[1;0Y[29X[2XNrColumns[102X( [3XC[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ya nonnegative integer[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XC[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component  [22XRP[122X!.[10XNrColumns[110X is bound then the standard method for the attribute
  [2XNrColumns[102X ([14X5.4-2[114X) shown below returns [22XRP[122X!.[10XNrColumns[110X[22X( [3XC[103X )[122X.[133X
  
  [4X[32X  Code  [32X[104X
    [4XInstallMethod( NrColumns,[104X
    [4X        "for homalg matrices",[104X
    [4X        [ IsHomalgMatrix ],[104X
    [4X        [104X
    [4X  function( C )[104X
    [4X    local R, RP;[104X
    [4X    [104X
    [4X    R := HomalgRing( C );[104X
    [4X    [104X
    [4X    RP := homalgTable( R );[104X
    [4X    [104X
    [4X    if IsBound(RP!.NrColumns) then[104X
    [4X        return RP!.NrColumns( C );[104X
    [4X    fi;[104X
    [4X    [104X
    [4X    if not IsHomalgInternalMatrixRep( C ) then[104X
    [4X        Error( "could not find a procedure called NrColumns ",[104X
    [4X               "in the homalgTable of the non-internal ring\n" );[104X
    [4X    fi;[104X
    [4X    [104X
    [4X    #=====# can only work for homalg internal matrices #=====#[104X
    [4X    [104X
    [4X    return Length( Eval( C )!.matrix[ 1 ] );[104X
    [4X    [104X
    [4Xend );[104X
  [4X[32X[104X
  
  [1XB.1-20 Determinant[101X
  
  [33X[1;0Y[29X[2XDeterminant[102X( [3XC[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ya ring element[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XC[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component  [22XRP[122X!.[10XDeterminant[110X  is  bound  then  the  standard  method  for  the
  attribute [2XDeterminantMat[102X ([14X5.4-3[114X) shown below returns [22XRP[122X!.[10XDeterminant[110X[22X( [3XC[103X )[122X.[133X
  
  [4X[32X  Code  [32X[104X
    [4XInstallMethod( DeterminantMat,[104X
    [4X        "for homalg matrices",[104X
    [4X        [ IsHomalgMatrix ],[104X
    [4X        [104X
    [4X  function( C )[104X
    [4X    local R, RP;[104X
    [4X    [104X
    [4X    R := HomalgRing( C );[104X
    [4X    [104X
    [4X    RP := homalgTable( R );[104X
    [4X    [104X
    [4X    if NrRows( C ) <> NrColumns( C ) then[104X
    [4X        Error( "the matrix is not a square matrix\n" );[104X
    [4X    fi;[104X
    [4X    [104X
    [4X    if IsEmptyMatrix( C ) then[104X
    [4X        return One( R );[104X
    [4X    elif IsZero( C ) then[104X
    [4X        return Zero( R );[104X
    [4X    fi;[104X
    [4X    [104X
    [4X    if IsBound(RP!.Determinant) then[104X
    [4X        return RingElementConstructor( R )( RP!.Determinant( C ), R );[104X
    [4X    fi;[104X
    [4X    [104X
    [4X    if not IsHomalgInternalMatrixRep( C ) then[104X
    [4X        Error( "could not find a procedure called Determinant ",[104X
    [4X               "in the homalgTable of the non-internal ring\n" );[104X
    [4X    fi;[104X
    [4X    [104X
    [4X    #=====# can only work for homalg internal matrices #=====#[104X
    [4X    [104X
    [4X    return Determinant( Eval( C )!.matrix );[104X
    [4X    [104X
    [4Xend );[104X
    [4X[104X
    [4X[104X
    [4XInstallMethod( Determinant,[104X
    [4X        "for homalg matrices",[104X
    [4X        [ IsHomalgMatrix ],[104X
    [4X        [104X
    [4X  function( C )[104X
    [4X    [104X
    [4X    return DeterminantMat( C );[104X
    [4X    [104X
    [4Xend );[104X
  [4X[32X[104X
  
  
  [1XB.2 [33X[0;0YThe Tool Operations with a Fallback Method[133X[101X
  
  [33X[0;0YThese are the methods for which it is recommended for performance reasons to
  have  a  [10XhomalgTable[110X  entry  for  non-internal rings. [5Xhomalg[105X only provides a
  generic fallback method.[133X
  
  [1XB.2-1 AreEqualMatrices[101X
  
  [33X[1;0Y[29X[2XAreEqualMatrices[102X( [3XM1[103X, [3XM2[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Y[10Xtrue[110X or [10Xfalse[110X[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XM1[103X )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component  [22XRP[122X!.[10XAreEqualMatrices[110X  is  bound  then the standard method for the
  operation [2X\=[102X ([14X5.5-18[114X) shown below returns [22XRP[122X!.[10XAreEqualMatrices[110X[22X( [3XM1[103X, [3XM2[103X )[122X.[133X
  
  [4X[32X  Code  [32X[104X
    [4XInstallMethod( \=,[104X
    [4X        "for homalg comparable matrices",[104X
    [4X        [ IsHomalgMatrix, IsHomalgMatrix ],[104X
    [4X        [104X
    [4X  function( M1, M2 )[104X
    [4X    local R, RP, are_equal;[104X
    [4X    [104X
    [4X    ## do not touch mutable matrices[104X
    [4X    if not ( IsMutable( M1 ) or IsMutable( M2 ) ) then[104X
    [4X        [104X
    [4X        if IsBound( M1!.AreEqual ) then[104X
    [4X            are_equal := _ElmWPObj_ForHomalg( M1!.AreEqual, M2, fail );[104X
    [4X            if are_equal <> fail then[104X
    [4X                return are_equal;[104X
    [4X            fi;[104X
    [4X        else[104X
    [4X            M1!.AreEqual :=[104X
    [4X              ContainerForWeakPointers([104X
    [4X                      TheTypeContainerForWeakPointersOnComputedValues,[104X
    [4X                      [ "operation", "AreEqual" ] );[104X
    [4X        fi;[104X
    [4X        [104X
    [4X        if IsBound( M2!.AreEqual ) then[104X
    [4X            are_equal := _ElmWPObj_ForHomalg( M2!.AreEqual, M1, fail );[104X
    [4X            if are_equal <> fail then[104X
    [4X                return are_equal;[104X
    [4X            fi;[104X
    [4X        fi;[104X
    [4X        ## do not store things symmetrically below to ``save'' memory[104X
    [4X        [104X
    [4X    fi;[104X
    [4X    [104X
    [4X    R := HomalgRing( M1 );[104X
    [4X    [104X
    [4X    RP := homalgTable( R );[104X
    [4X    [104X
    [4X    if IsBound(RP!.AreEqualMatrices) then[104X
    [4X        ## CAUTION: the external system must be able to check equality[104X
    [4X        ## modulo possible ring relations (known to the external system)![104X
    [4X        are_equal := RP!.AreEqualMatrices( M1, M2 );[104X
    [4X    elif IsBound(RP!.Equal) then[104X
    [4X        ## CAUTION: the external system must be able to check equality[104X
    [4X        ## modulo possible ring relations (known to the external system)![104X
    [4X        are_equal := RP!.Equal( M1, M2 );[104X
    [4X    elif IsBound(RP!.IsZeroMatrix) then   ## ensuring this avoids infinite loops[104X
    [4X        are_equal := IsZero( M1 - M2 );[104X
    [4X    fi;[104X
    [4X    [104X
    [4X    if IsBound( are_equal ) then[104X
    [4X        [104X
    [4X        ## do not touch mutable matrices[104X
    [4X        if not ( IsMutable( M1 ) or IsMutable( M2 ) ) then[104X
    [4X            [104X
    [4X            if are_equal then[104X
    [4X                MatchPropertiesAndAttributes( M1, M2,[104X
    [4X                        LIMAT.intrinsic_properties,[104X
    [4X                        LIMAT.intrinsic_attributes,[104X
    [4X                        LIMAT.intrinsic_components,[104X
    [4X                        LIMAT.intrinsic_attributes_do_not_check_their_equality[104X
    [4X                        );[104X
    [4X            fi;[104X
    [4X            [104X
    [4X            ## do not store things symmetrically to ``save'' memory[104X
    [4X            _AddTwoElmWPObj_ForHomalg( M1!.AreEqual, M2, are_equal );[104X
    [4X            [104X
    [4X        fi;[104X
    [4X        [104X
    [4X        return are_equal;[104X
    [4X    fi;[104X
    [4X    [104X
    [4X    TryNextMethod( );[104X
    [4X    [104X
    [4Xend );[104X
  [4X[32X[104X
  
  [1XB.2-2 IsIdentityMatrix[101X
  
  [33X[1;0Y[29X[2XIsIdentityMatrix[102X( [3XM[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Y[10Xtrue[110X or [10Xfalse[110X[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XM[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component  [22XRP[122X!.[10XIsIdentityMatrix[110X  is  bound  then the standard method for the
  property [2XIsOne[102X ([14X5.3-2[114X) shown below returns [22XRP[122X!.[10XIsIdentityMatrix[110X[22X( [3XM[103X )[122X.[133X
  
  [4X[32X  Code  [32X[104X
    [4XInstallMethod( IsOne,[104X
    [4X        "for homalg matrices",[104X
    [4X        [ IsHomalgMatrix ],[104X
    [4X        [104X
    [4X  function( M )[104X
    [4X    local R, RP;[104X
    [4X    [104X
    [4X    if NrRows( M ) <> NrColumns( M ) then[104X
    [4X        return false;[104X
    [4X    fi;[104X
    [4X    [104X
    [4X    R := HomalgRing( M );[104X
    [4X    [104X
    [4X    RP := homalgTable( R );[104X
    [4X    [104X
    [4X    if IsBound(RP!.IsIdentityMatrix) then[104X
    [4X        return RP!.IsIdentityMatrix( M );[104X
    [4X    fi;[104X
    [4X    [104X
    [4X    #=====# the fallback method #=====#[104X
    [4X    [104X
    [4X    return M = HomalgIdentityMatrix( NrRows( M ), HomalgRing( M ) );[104X
    [4X    [104X
    [4Xend );[104X
  [4X[32X[104X
  
  [1XB.2-3 IsDiagonalMatrix[101X
  
  [33X[1;0Y[29X[2XIsDiagonalMatrix[102X( [3XM[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Y[10Xtrue[110X or [10Xfalse[110X[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XM[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component  [22XRP[122X!.[10XIsDiagonalMatrix[110X  is  bound  then the standard method for the
  property [2XIsDiagonalMatrix[102X ([14X5.3-13[114X) shown below returns [22XRP[122X!.[10XIsDiagonalMatrix[110X[22X(
  [3XM[103X )[122X.[133X
  
  [4X[32X  Code  [32X[104X
    [4XInstallMethod( IsDiagonalMatrix,[104X
    [4X        "for homalg matrices",[104X
    [4X        [ IsHomalgMatrix ],[104X
    [4X        [104X
    [4X  function( M )[104X
    [4X    local R, RP, diag;[104X
    [4X    [104X
    [4X    R := HomalgRing( M );[104X
    [4X    [104X
    [4X    RP := homalgTable( R );[104X
    [4X    [104X
    [4X    if IsBound(RP!.IsDiagonalMatrix) then[104X
    [4X        return RP!.IsDiagonalMatrix( M );[104X
    [4X    fi;[104X
    [4X    [104X
    [4X    #=====# the fallback method #=====#[104X
    [4X    [104X
    [4X    diag := DiagonalEntries( M );[104X
    [4X    [104X
    [4X    return M = HomalgDiagonalMatrix( diag, NrRows( M ), NrColumns( M ), R );[104X
    [4X    [104X
    [4Xend );[104X
  [4X[32X[104X
  
  [1XB.2-4 ZeroRows[101X
  
  [33X[1;0Y[29X[2XZeroRows[102X( [3XC[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ya (possibly empty) list of positive integers[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XC[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component  [22XRP[122X!.[10XZeroRows[110X  is  bound then the standard method of the attribute
  [2XZeroRows[102X ([14X5.4-4[114X) shown below returns [22XRP[122X!.[10XZeroRows[110X[22X( [3XC[103X )[122X.[133X
  
  [4X[32X  Code  [32X[104X
    [4XInstallMethod( ZeroRows,[104X
    [4X        "for homalg matrices",[104X
    [4X        [ IsHomalgMatrix ],[104X
    [4X        [104X
    [4X  function( C )[104X
    [4X    local R, RP, z;[104X
    [4X    [104X
    [4X    R := HomalgRing( C );[104X
    [4X    [104X
    [4X    RP := homalgTable( R );[104X
    [4X    [104X
    [4X    if IsBound(RP!.ZeroRows) then[104X
    [4X        return RP!.ZeroRows( C );[104X
    [4X    fi;[104X
    [4X    [104X
    [4X    #=====# the fallback method #=====#[104X
    [4X    [104X
    [4X    z := HomalgZeroMatrix( 1, NrColumns( C ), R );[104X
    [4X    [104X
    [4X    return Filtered( [ 1 .. NrRows( C ) ], a -> CertainRows( C, [ a ] ) = z );[104X
    [4X    [104X
    [4Xend );[104X
  [4X[32X[104X
  
  [1XB.2-5 ZeroColumns[101X
  
  [33X[1;0Y[29X[2XZeroColumns[102X( [3XC[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ya (possibly empty) list of positive integers[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XC[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component [22XRP[122X!.[10XZeroColumns[110X is bound then the standard method of the attribute
  [2XZeroColumns[102X ([14X5.4-5[114X) shown below returns [22XRP[122X!.[10XZeroColumns[110X[22X( [3XC[103X )[122X.[133X
  
  [4X[32X  Code  [32X[104X
    [4XInstallMethod( ZeroColumns,[104X
    [4X        "for homalg matrices",[104X
    [4X        [ IsHomalgMatrix ],[104X
    [4X        [104X
    [4X  function( C )[104X
    [4X    local R, RP, z;[104X
    [4X    [104X
    [4X    R := HomalgRing( C );[104X
    [4X    [104X
    [4X    RP := homalgTable( R );[104X
    [4X    [104X
    [4X    if IsBound(RP!.ZeroColumns) then[104X
    [4X        return RP!.ZeroColumns( C );[104X
    [4X    fi;[104X
    [4X    [104X
    [4X    #=====# the fallback method #=====#[104X
    [4X    [104X
    [4X    z := HomalgZeroMatrix( NrRows( C ), 1, R );[104X
    [4X    [104X
    [4X    return Filtered( [ 1 .. NrColumns( C ) ], a -> CertainColumns( C, [ a ] ) = z );[104X
    [4X    [104X
    [4Xend );[104X
  [4X[32X[104X
  
  [1XB.2-6 GetColumnIndependentUnitPositions[101X
  
  [33X[1;0Y[29X[2XGetColumnIndependentUnitPositions[102X( [3XM[103X, [3Xposlist[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ya (possibly empty) list of pairs of positive integers[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XM[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component  [22XRP[122X!.[10XGetColumnIndependentUnitPositions[110X  is bound then the standard
  method  of  the  operation  [2XGetColumnIndependentUnitPositions[102X ([14X5.5-19[114X) shown
  below returns [22XRP[122X!.[10XGetColumnIndependentUnitPositions[110X[22X( [3XM[103X, [3Xposlist[103X )[122X.[133X
  
  [4X[32X  Code  [32X[104X
    [4XInstallMethod( GetColumnIndependentUnitPositions,[104X
    [4X        "for homalg matrices",[104X
    [4X        [ IsHomalgMatrix, IsHomogeneousList ],[104X
    [4X        [104X
    [4X  function( M, poslist )[104X
    [4X    local cache, R, RP, rest, pos, i, j, k;[104X
    [4X    [104X
    [4X    if IsBound( M!.GetColumnIndependentUnitPositions ) then[104X
    [4X        cache := M!.GetColumnIndependentUnitPositions;[104X
    [4X        if IsBound( cache.(String( poslist )) ) then[104X
    [4X            return cache.(String( poslist ));[104X
    [4X        fi;[104X
    [4X    else[104X
    [4X        cache := rec( );[104X
    [4X        M!.GetColumnIndependentUnitPositions := cache;[104X
    [4X    fi;[104X
    [4X    [104X
    [4X    R := HomalgRing( M );[104X
    [4X    [104X
    [4X    RP := homalgTable( R );[104X
    [4X    [104X
    [4X    if IsBound(RP!.GetColumnIndependentUnitPositions) then[104X
    [4X        pos := RP!.GetColumnIndependentUnitPositions( M, poslist );[104X
    [4X        if pos <> [ ] then[104X
    [4X            SetIsZero( M, false );[104X
    [4X        fi;[104X
    [4X        cache.(String( poslist )) := pos;[104X
    [4X        return pos;[104X
    [4X    fi;[104X
    [4X    [104X
    [4X    #=====# the fallback method #=====#[104X
    [4X    [104X
    [4X    rest := [ 1 .. NrColumns( M ) ];[104X
    [4X    [104X
    [4X    pos := [ ];[104X
    [4X    [104X
    [4X    for i in [ 1 .. NrRows( M ) ] do[104X
    [4X        for k in Reversed( rest ) do[104X
    [4X            if not [ i, k ] in poslist and[104X
    [4X               IsUnit( R, MatElm( M, i, k ) ) then[104X
    [4X                Add( pos, [ i, k ] );[104X
    [4X                rest := Filtered( rest,[104X
    [4X                                a -> IsZero( MatElm( M, i, a ) ) );[104X
    [4X                break;[104X
    [4X            fi;[104X
    [4X        od;[104X
    [4X    od;[104X
    [4X    [104X
    [4X    if pos <> [ ] then[104X
    [4X        SetIsZero( M, false );[104X
    [4X    fi;[104X
    [4X    [104X
    [4X    cache.(String( poslist )) := pos;[104X
    [4X    [104X
    [4X    return pos;[104X
    [4X    [104X
    [4Xend );[104X
  [4X[32X[104X
  
  [1XB.2-7 GetRowIndependentUnitPositions[101X
  
  [33X[1;0Y[29X[2XGetRowIndependentUnitPositions[102X( [3XM[103X, [3Xposlist[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ya (possibly empty) list of pairs of positive integers[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XM[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component  [22XRP[122X!.[10XGetRowIndependentUnitPositions[110X  is  bound  then  the standard
  method  of the operation [2XGetRowIndependentUnitPositions[102X ([14X5.5-20[114X) shown below
  returns [22XRP[122X!.[10XGetRowIndependentUnitPositions[110X[22X( [3XM[103X, [3Xposlist[103X )[122X.[133X
  
  [4X[32X  Code  [32X[104X
    [4XInstallMethod( GetRowIndependentUnitPositions,[104X
    [4X        "for homalg matrices",[104X
    [4X        [ IsHomalgMatrix, IsHomogeneousList ],[104X
    [4X        [104X
    [4X  function( M, poslist )[104X
    [4X    local cache, R, RP, rest, pos, j, i, k;[104X
    [4X    [104X
    [4X    if IsBound( M!.GetRowIndependentUnitPositions ) then[104X
    [4X        cache := M!.GetRowIndependentUnitPositions;[104X
    [4X        if IsBound( cache.(String( poslist )) ) then[104X
    [4X            return cache.(String( poslist ));[104X
    [4X        fi;[104X
    [4X    else[104X
    [4X        cache := rec( );[104X
    [4X        M!.GetRowIndependentUnitPositions := cache;[104X
    [4X    fi;[104X
    [4X    [104X
    [4X    R := HomalgRing( M );[104X
    [4X    [104X
    [4X    RP := homalgTable( R );[104X
    [4X    [104X
    [4X    if IsBound(RP!.GetRowIndependentUnitPositions) then[104X
    [4X        pos := RP!.GetRowIndependentUnitPositions( M, poslist );[104X
    [4X        if pos <> [ ] then[104X
    [4X            SetIsZero( M, false );[104X
    [4X        fi;[104X
    [4X        cache.( String( poslist ) ) := pos;[104X
    [4X        return pos;[104X
    [4X    fi;[104X
    [4X    [104X
    [4X    #=====# the fallback method #=====#[104X
    [4X    [104X
    [4X    rest := [ 1 .. NrRows( M ) ];[104X
    [4X    [104X
    [4X    pos := [ ];[104X
    [4X    [104X
    [4X    for j in [ 1 .. NrColumns( M ) ] do[104X
    [4X        for k in Reversed( rest ) do[104X
    [4X            if not [ j, k ] in poslist and[104X
    [4X               IsUnit( R, MatElm( M, k, j ) ) then[104X
    [4X                Add( pos, [ j, k ] );[104X
    [4X                rest := Filtered( rest,[104X
    [4X                                a -> IsZero( MatElm( M, a, j ) ) );[104X
    [4X                break;[104X
    [4X            fi;[104X
    [4X        od;[104X
    [4X    od;[104X
    [4X    [104X
    [4X    if pos <> [ ] then[104X
    [4X        SetIsZero( M, false );[104X
    [4X    fi;[104X
    [4X    [104X
    [4X    cache.( String( poslist ) ) := pos;[104X
    [4X    [104X
    [4X    return pos;[104X
    [4X    [104X
    [4Xend );[104X
  [4X[32X[104X
  
  [1XB.2-8 GetUnitPosition[101X
  
  [33X[1;0Y[29X[2XGetUnitPosition[102X( [3XM[103X, [3Xposlist[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ya (possibly empty) list of pairs of positive integers[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XM[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component  [22XRP[122X!.[10XGetUnitPosition[110X  is  bound  then  the  standard method of the
  operation  [2XGetUnitPosition[102X ([14X5.5-21[114X) shown below returns [22XRP[122X!.[10XGetUnitPosition[110X[22X(
  [3XM[103X, [3Xposlist[103X )[122X.[133X
  
  [4X[32X  Code  [32X[104X
    [4XInstallMethod( GetUnitPosition,[104X
    [4X        "for homalg matrices",[104X
    [4X        [ IsHomalgMatrix, IsHomogeneousList ],[104X
    [4X        [104X
    [4X  function( M, poslist )[104X
    [4X    local R, RP, pos, m, n, i, j;[104X
    [4X    [104X
    [4X    R := HomalgRing( M );[104X
    [4X    [104X
    [4X    RP := homalgTable( R );[104X
    [4X    [104X
    [4X    if IsBound(RP!.GetUnitPosition) then[104X
    [4X        pos := RP!.GetUnitPosition( M, poslist );[104X
    [4X        if IsList( pos ) and IsPosInt( pos[1] ) and IsPosInt( pos[2] ) then[104X
    [4X            SetIsZero( M, false );[104X
    [4X        fi;[104X
    [4X        return pos;[104X
    [4X    fi;[104X
    [4X    [104X
    [4X    #=====# the fallback method #=====#[104X
    [4X    [104X
    [4X    m := NrRows( M );[104X
    [4X    n := NrColumns( M );[104X
    [4X    [104X
    [4X    for i in [ 1 .. m ] do[104X
    [4X        for j in [ 1 .. n ] do[104X
    [4X            if not [ i, j ] in poslist and not j in poslist and[104X
    [4X               IsUnit( R, MatElm( M, i, j ) ) then[104X
    [4X                SetIsZero( M, false );[104X
    [4X                return [ i, j ];[104X
    [4X            fi;[104X
    [4X        od;[104X
    [4X    od;[104X
    [4X    [104X
    [4X    return fail;[104X
    [4X    [104X
    [4Xend );[104X
  [4X[32X[104X
  
  [1XB.2-9 PositionOfFirstNonZeroEntryPerRow[101X
  
  [33X[1;0Y[29X[2XPositionOfFirstNonZeroEntryPerRow[102X( [3XM[103X, [3Xposlist[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ya list of nonnegative integers[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XM[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component  [22XRP[122X!.[10XPositionOfFirstNonZeroEntryPerRow[110X  is bound then the standard
  method  of  the  attribute  [2XPositionOfFirstNonZeroEntryPerRow[102X  ([14X5.4-8[114X) shown
  below returns [22XRP[122X!.[10XPositionOfFirstNonZeroEntryPerRow[110X[22X( [3XM[103X )[122X.[133X
  
  [4X[32X  Code  [32X[104X
    [4XInstallMethod( PositionOfFirstNonZeroEntryPerRow,[104X
    [4X        "for homalg matrices",[104X
    [4X        [ IsHomalgMatrix ],[104X
    [4X        [104X
    [4X  function( M )[104X
    [4X    local R, RP, pos, entries, r, c, i, k, j;[104X
    [4X    [104X
    [4X    R := HomalgRing( M );[104X
    [4X    [104X
    [4X    RP := homalgTable( R );[104X
    [4X    [104X
    [4X    if IsBound(RP!.PositionOfFirstNonZeroEntryPerRow) then[104X
    [4X        return RP!.PositionOfFirstNonZeroEntryPerRow( M );[104X
    [4X    elif IsBound(RP!.PositionOfFirstNonZeroEntryPerColumn) then[104X
    [4X        return PositionOfFirstNonZeroEntryPerColumn( Involution( M ) );[104X
    [4X    fi;[104X
    [4X    [104X
    [4X    #=====# the fallback method #=====#[104X
    [4X    [104X
    [4X    entries := EntriesOfHomalgMatrix( M );[104X
    [4X    [104X
    [4X    r := NrRows( M );[104X
    [4X    c := NrColumns( M );[104X
    [4X    [104X
    [4X    pos := ListWithIdenticalEntries( r, 0 );[104X
    [4X    [104X
    [4X    for i in [ 1 .. r ] do[104X
    [4X        k := (i - 1) * c;[104X
    [4X        for j in [ 1 .. c ] do[104X
    [4X            if not IsZero( entries[k + j] ) then[104X
    [4X                pos[i] := j;[104X
    [4X                break;[104X
    [4X            fi;[104X
    [4X        od;[104X
    [4X    od;[104X
    [4X    [104X
    [4X    return pos;[104X
    [4X    [104X
    [4Xend );[104X
  [4X[32X[104X
  
  [1XB.2-10 PositionOfFirstNonZeroEntryPerColumn[101X
  
  [33X[1;0Y[29X[2XPositionOfFirstNonZeroEntryPerColumn[102X( [3XM[103X, [3Xposlist[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ya list of nonnegative integers[133X
  
  [33X[0;0YLet  [22XR  :=[122X  [10XHomalgRing[110X[22X(  [3XM[103X  )[122X and [22XRP :=[122X [10XhomalgTable[110X[22X( R )[122X. If the [10XhomalgTable[110X
  component   [22XRP[122X!.[10XPositionOfFirstNonZeroEntryPerColumn[110X   is   bound  then  the
  standard   method   of  the  attribute  [2XPositionOfFirstNonZeroEntryPerColumn[102X
  ([14X5.4-9[114X) shown below returns [22XRP[122X!.[10XPositionOfFirstNonZeroEntryPerColumn[110X[22X( [3XM[103X )[122X.[133X
  
  [4X[32X  Code  [32X[104X
    [4XInstallMethod( PositionOfFirstNonZeroEntryPerColumn,[104X
    [4X        "for homalg matrices",[104X
    [4X        [ IsHomalgMatrix ],[104X
    [4X        [104X
    [4X  function( M )[104X
    [4X    local R, RP, pos, entries, r, c, j, i, k;[104X
    [4X    [104X
    [4X    R := HomalgRing( M );[104X
    [4X    [104X
    [4X    RP := homalgTable( R );[104X
    [4X    [104X
    [4X    if IsBound(RP!.PositionOfFirstNonZeroEntryPerColumn) then[104X
    [4X        return RP!.PositionOfFirstNonZeroEntryPerColumn( M );[104X
    [4X    elif IsBound(RP!.PositionOfFirstNonZeroEntryPerRow) then[104X
    [4X        return PositionOfFirstNonZeroEntryPerRow( Involution( M ) );[104X
    [4X    fi;[104X
    [4X    [104X
    [4X    #=====# the fallback method #=====#[104X
    [4X    [104X
    [4X    entries := EntriesOfHomalgMatrix( M );[104X
    [4X    [104X
    [4X    r := NrRows( M );[104X
    [4X    c := NrColumns( M );[104X
    [4X    [104X
    [4X    pos := ListWithIdenticalEntries( c, 0 );[104X
    [4X    [104X
    [4X    for j in [ 1 .. c ] do[104X
    [4X        for i in [ 1 .. r ] do[104X
    [4X            k := (i - 1) * c;[104X
    [4X            if not IsZero( entries[k + j] ) then[104X
    [4X                pos[j] := i;[104X
    [4X                break;[104X
    [4X            fi;[104X
    [4X        od;[104X
    [4X    od;[104X
    [4X    [104X
    [4X    return pos;[104X
    [4X    [104X
    [4Xend );[104X
  [4X[32X[104X
  
