Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/GAP/pkg/matricesforhomalg/gap/   (Algebra von RWTH Aachen Version 4.15.1©)  Datei vom 7.8.2025 mit Größe 78 kB image not shown  

SSL COLEM.gi   Sprache: unbekannt

 
# SPDX-License-Identifier: GPL-2.0-or-later
# MatricesForHomalg: Matrices for the homalg project
#
# Implementations
#

##         COLEM = Clever Operations for Lazy Evaluated Matrices

####################################
#
# global variables:
#
####################################

# a central place for configuration variables:

InstallValue( COLEM,
        rec(
            color := "\033[4;30;46m",
            level := 10,
            single_operations := 10,
            )
        );

####################################
#
# logical implications methods:
#
####################################

##
InstallImmediateMethod( IsEmptyMatrix,
        IsHomalgMatrix and HasPreEval, 0,
        
  function( M )
    local e;
    
    e := PreEval( M );
    
    if HasIsEmptyMatrix( e ) then
        return IsEmptyMatrix( e );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsZero,
        IsHomalgMatrix and HasPreEval, 0,
        
  function( M )
    local e;
    
    e := PreEval( M );
    
    if HasIsZero( e ) then
        return IsZero( e );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsZero,
        IsHomalgMatrix and HasEvalInvolution, 0,
        
  function( M )
    local MI;
    
    MI := EvalInvolution( M );
    
    if HasIsZero( MI ) then
        return IsZero( MI );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsZero,
        IsHomalgMatrix and HasEvalTransposedMatrix, 0,
        
  function( M )
    local MI;
    
    MI := EvalTransposedMatrix( M );
    
    if HasIsZero( MI ) then
        return IsZero( MI );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsZero,
        IsHomalgMatrix and HasEvalLeftInverse, 0,
        
  function( M )
    local MI;
    
    MI := EvalLeftInverse( M );
    
    if HasIsZero( MI ) then
        return IsZero( MI );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsZero,
        IsHomalgMatrix and HasEvalRightInverse, 0,
        
  function( M )
    local MI;
    
    MI := EvalRightInverse( M );
    
    if HasIsZero( MI ) then
        return IsZero( MI );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsZero,
        IsHomalgMatrix and HasEvalInverse, 0,
        
  function( M )
    local MI;
    
    MI := EvalInverse( M );
    
    if HasIsZero( MI ) then
        return IsZero( MI );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsZero,
        IsHomalgMatrix and HasEvalCertainRows, 0,
        
  function( M )
    local e;
    
    e := EvalCertainRows( M )[1];
    
    if HasIsZero( e ) and IsZero( e ) then
        return true;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsZero,
        IsHomalgMatrix and HasEvalCertainColumns, 0,
        
  function( M )
    local e;
    
    e := EvalCertainColumns( M )[1];
    
    if HasIsZero( e ) and IsZero( e ) then
        return true;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsZero,
        IsHomalgMatrix and HasEvalUnionOfRows, 0,
        
  function( M )
    local e, A, B;
    
    e := EvalUnionOfRows( M );
    
    if ForAny( e, A -> HasIsZero( A ) and not IsZero( A ) ) then
        return false;
    fi;
    
    if ForAll( e, A -> HasIsZero( A ) and IsZero( A ) ) then
        return true;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsZero,
        IsHomalgMatrix and HasEvalUnionOfColumns, 0,
        
  function( M )
    local e, A, B;
    
    e := EvalUnionOfColumns( M );
    
    if ForAny( e, A -> HasIsZero( A ) and not IsZero( A ) ) then
        return false;
    fi;
    
    if ForAll( e, A -> HasIsZero( A ) and IsZero( A ) ) then
        return true;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsZero,
        IsHomalgMatrix and HasEvalDiagMat, 0,
        
  function( M )
    local e;
    
    e := EvalDiagMat( M );
    
    if ForAll( e, B -> HasIsZero( B ) and IsZero( B ) ) then
        return true;
    elif ForAny( e, B -> HasIsZero( B ) and not IsZero( B ) ) then
        return false;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsZero,
        IsHomalgMatrix and HasEvalMulMatRight, 0,
        
  function( M )
    local e, A, a, R;
    
    e := EvalMulMatRight( M );
    
    A := e[1];
    a := e[2];
    
    if HasIsZero( a ) and IsZero( a ) then
        return true;
    elif HasIsZero( A ) then
        if IsZero( A ) then
            return true;
        elif IsHomalgRingElement( a ) and HasIsRegular( a ) and IsRegular( a ) then
            ## A is not zero
            return false;
        else
            R := HomalgRing( A );
            if HasIsIntegralDomain( R ) and IsIntegralDomain( R ) then
                ## A is not zero
                return IsZero( a );
            elif IsHomalgRingElement( a ) and IsBound( a!.IsUnit ) and a!.IsUnit then
                ## A is not zero
                return false;
            fi;
        fi;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsZero,
        IsHomalgMatrix and HasEvalMulMat, 0,
        
  function( M )
    local e, a, A, R;
    
    e := EvalMulMat( M );
    
    a := e[1];
    A := e[2];
    
    if HasIsZero( a ) and IsZero( a ) then
        return true;
    elif HasIsZero( A ) then
        if IsZero( A ) then
            return true;
        elif IsHomalgRingElement( a ) and HasIsRegular( a ) and IsRegular( a ) then
            ## A is not zero
            return false;
        else
            R := HomalgRing( A );
            if HasIsIntegralDomain( R ) and IsIntegralDomain( R ) then
                ## A is not zero
                return IsZero( a );
            elif IsHomalgRingElement( a ) and IsBound( a!.IsUnit ) and a!.IsUnit then
                ## A is not zero
                return false;
            fi;
        fi;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsOne,
        IsHomalgMatrix and HasPreEval, 0,
        
  function( M )
    local e;
    
    e := PreEval( M );
    
    if HasIsOne( e ) then
        return IsOne( e );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsPermutationMatrix,
        IsHomalgMatrix and HasPreEval, 0,
        
  function( M )
    local e;
    
    e := PreEval( M );
    
    if HasIsPermutationMatrix( e ) then
        return IsPermutationMatrix( e );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsSubidentityMatrix,
        IsHomalgMatrix and HasPreEval, 0,
        
  function( M )
    local e;
    
    e := PreEval( M );
    
    if HasIsSubidentityMatrix( e ) then
        return IsSubidentityMatrix( e );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsSubidentityMatrix,
        IsHomalgMatrix and HasEvalCertainRows, 0,
        
  function( M )
    local mat, plist, pos, pos_non_zero;
    
    mat := EvalCertainRows( M );
    
    plist := mat[2];
    mat := mat[1];
    
    if HasIsSubidentityMatrix( mat ) and IsSubidentityMatrix( mat ) then
        
        if HasNumberRows( mat ) and HasNumberColumns( mat )
           and NumberRows( mat ) <= NumberColumns( mat ) then
            
            return IsDuplicateFree( plist );
            
        fi;
        
        if HasPositionOfFirstNonZeroEntryPerRow( mat ) and HasNumberColumns( mat ) then
            
            pos := PositionOfFirstNonZeroEntryPerRow( mat );
            
            pos := pos{ plist };
            
            pos_non_zero := Filtered( pos, i -> i <> 0 );
            
            if not IsDuplicateFree( pos_non_zero ) then
                return false;
            fi;
            
            if not 0 in pos                                  ## NumberRows( M ) <= NumberColumns( M )
               or  Length( pos_non_zero ) = NumberColumns( mat ) ## NumberColumns( M ) <= NumberRows( M )
               then
                return true;
            fi;
            
            return false;
            
        fi;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsSubidentityMatrix,
        IsHomalgMatrix and HasEvalCertainRows, 0,
        
  function( M )
    local mat, plist, pos, plist_non_zero;
    
    mat := EvalCertainRows( M );
    
    plist := mat[2];
    mat := mat[1];
    
    if HasIsSubidentityMatrix( mat ) and IsSubidentityMatrix( mat ) then
        
        if HasNumberRows( mat ) and HasNumberColumns( mat )
           and NumberRows( mat ) <= NumberColumns( mat ) then
            
            return IsDuplicateFree( plist );
            
        fi;
        
        if HasPositionOfFirstNonZeroEntryPerColumn( mat ) and HasNumberColumns( mat ) then
            
            pos := PositionOfFirstNonZeroEntryPerColumn( mat );
            
            plist := List( plist, function( i ) if i in pos then return i; else return 0; fi; end );
            
            plist_non_zero := Filtered( plist, i -> i <> 0 );
            
            if not IsDuplicateFree( plist_non_zero ) then
                return false;
            fi;
            
            if not 0 in plist                                 ## NumberRows( M ) <= NumberColumns( M )
               or Length( plist_non_zero ) = NumberColumns( mat ) ## NumberColumns( M ) <= NumberRows( M )
               then
                return true;
            fi;
            
            return false;
            
        fi;
        
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsSubidentityMatrix,
        IsHomalgMatrix and HasEvalCertainColumns, 0,
        
  function( M )
    local mat, plist, pos, pos_non_zero;
    
    mat := EvalCertainColumns( M );
    
    plist := mat[2];
    mat := mat[1];
    
    if HasIsSubidentityMatrix( mat ) and IsSubidentityMatrix( mat ) then
        
        if HasNumberColumns( mat ) and HasNumberRows( mat )
           and NumberColumns( mat ) <= NumberRows( mat ) then
            
            return IsDuplicateFree( plist );
            
        fi;
        
        if HasPositionOfFirstNonZeroEntryPerColumn( mat ) and HasNumberRows( mat ) then
            
            pos := PositionOfFirstNonZeroEntryPerColumn( mat );
            
            pos := pos{ plist };
            
            pos_non_zero := Filtered( pos, i -> i <> 0 );
            
            if not IsDuplicateFree( pos_non_zero ) then
                return false;
            fi;
            
            if not 0 in pos                               ## NumberColumns( M ) <= NumberRows( M )
               or  Length( pos_non_zero ) = NumberRows( mat ) ## NumberRows( M ) <= NumberColumns( M )
               then
                return true;
            fi;
            
            return false;
            
        fi;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsSubidentityMatrix,
        IsHomalgMatrix and HasEvalCertainColumns, 0,
        
  function( M )
    local mat, plist, pos, plist_non_zero;
    
    mat := EvalCertainColumns( M );
    
    plist := mat[2];
    mat := mat[1];
    
    if HasIsSubidentityMatrix( mat ) and IsSubidentityMatrix( mat ) then
        
        if HasNumberColumns( mat ) and HasNumberRows( mat )
           and NumberColumns( mat ) <= NumberRows( mat ) then
            
            return IsDuplicateFree( plist );
            
        fi;
        
        if HasPositionOfFirstNonZeroEntryPerRow( mat ) and HasNumberRows( mat ) then
            
            pos := PositionOfFirstNonZeroEntryPerRow( mat );
            
            plist := List( plist, function( i ) if i in pos then return i; else return 0; fi; end );
            
            plist_non_zero := Filtered( plist, i -> i <> 0 );
            
            if not IsDuplicateFree( plist_non_zero ) then
                return false;
            fi;
            
            if not 0 in plist                              ## NumberColumns( M ) <= NumberRows( M )
               or Length( plist_non_zero ) = NumberRows( mat ) ## NumberRows( M ) <= NumberColumns( M )
               then
                return true;
            fi;
            
            return false;
            
        fi;
        
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsRightInvertibleMatrix,
        IsHomalgMatrix and HasPreEval, 0,
        
  function( M )
    local e;
    
    e := PreEval( M );
    
    if HasIsRightInvertibleMatrix( e ) then
        return IsRightInvertibleMatrix( e );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsRightInvertibleMatrix,
        IsHomalgMatrix and HasEvalInvolution, 0,
        
  function( M )
    local MI;
    
    MI := EvalInvolution( M );
    
    if HasIsLeftInvertibleMatrix( MI ) then
        return IsLeftInvertibleMatrix( MI );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsRightInvertibleMatrix,
        IsHomalgMatrix and HasEvalUnionOfColumns, 0,
        
  function( M )
    local e;
    
    e := EvalUnionOfColumns( M );
    
    if ForAny( e, A -> HasIsRightInvertibleMatrix( A ) and IsRightInvertibleMatrix( A ) ) then
        return true;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsLeftInvertibleMatrix,
        IsHomalgMatrix and HasPreEval, 0,
        
  function( M )
    local e;
    
    e := PreEval( M );
    
    if HasIsLeftInvertibleMatrix( e ) then
        return IsLeftInvertibleMatrix( e );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsLeftInvertibleMatrix,
        IsHomalgMatrix and HasEvalInvolution, 0,
        
  function( M )
    local MI;
    
    MI := EvalInvolution( M );
    
    if HasIsRightInvertibleMatrix( MI ) then
        return IsRightInvertibleMatrix( MI );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsLeftInvertibleMatrix,
        IsHomalgMatrix and HasEvalUnionOfRows, 0,
        
  function( M )
    local e;
    
    e := EvalUnionOfRows( M );
    
    if ForAny( e, A -> HasIsLeftInvertibleMatrix( A ) and IsLeftInvertibleMatrix( A ) ) then
        return true;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsLeftRegular,
        IsHomalgMatrix and HasPreEval, 0,
        
  function( M )
    local e;
    
    e := PreEval( M );
    
    if HasIsLeftRegular( e ) then
        return IsLeftRegular( e );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsLeftRegular,
        IsHomalgMatrix and HasEvalInvolution, 0,
        
  function( M )
    local MI;
    
    MI := EvalInvolution( M );
    
    if HasIsRightRegular( MI ) then
        return IsRightRegular( MI );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsRightRegular,
        IsHomalgMatrix and HasPreEval, 0,
        
  function( M )
    local e;
    
    e := PreEval( M );
    
    if HasIsRightRegular( e ) then
        return IsRightRegular( e );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsRightRegular,
        IsHomalgMatrix and HasEvalInvolution, 0,
        
  function( M )
    local MI;
    
    MI := EvalInvolution( M );
    
    if HasIsLeftRegular( MI ) then
        return IsLeftRegular( MI );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsUpperTriangularMatrix,
        IsHomalgMatrix and HasEvalInvolution, 0,
        
  function( M )
    local MI;
    
    MI := EvalInvolution( M );
    
    if HasIsLowerTriangularMatrix( MI ) then
        return IsLowerTriangularMatrix( MI );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsUpperTriangularMatrix,
        IsHomalgMatrix and HasEvalTransposedMatrix, 0,
        
  function( M )
    local MI;
    
    MI := EvalTransposedMatrix( M );
    
    if HasIsLowerTriangularMatrix( MI ) then
        return IsLowerTriangularMatrix( MI );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsUpperTriangularMatrix,
        IsHomalgMatrix and HasEvalCertainRows, 0,
        
  function( M )
    local C, plist;
    
    C := EvalCertainRows( M );
    
    plist := C[2];
    C := C[1];
    
    if HasIsUpperTriangularMatrix( C ) and IsUpperTriangularMatrix( C ) and
       ( plist = NumberRows( C ) + [ -Length( plist ) .. 0 ] or plist = [ 1 .. Length( plist ) ] ) then
        return true;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsUpperTriangularMatrix,
        IsHomalgMatrix and HasPreEval, 0,
        
  function( M )
    local e;
    
    e := PreEval( M );
    
    if HasIsUpperTriangularMatrix( e ) then
        return IsUpperTriangularMatrix( e );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsLowerTriangularMatrix,
        IsHomalgMatrix and HasEvalInvolution, 0,
        
  function( M )
    local MI;
    
    MI := EvalInvolution( M );
    
    if HasIsUpperTriangularMatrix( MI ) then
        return IsUpperTriangularMatrix( MI );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsLowerTriangularMatrix,
        IsHomalgMatrix and HasEvalTransposedMatrix, 0,
        
  function( M )
    local MI;
    
    MI := EvalTransposedMatrix( M );
    
    if HasIsUpperTriangularMatrix( MI ) then
        return IsUpperTriangularMatrix( MI );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsLowerTriangularMatrix,
        IsHomalgMatrix and HasEvalCertainColumns, 0,
        
  function( M )
    local C, plist;
    
    C := EvalCertainColumns( M );
    
    plist := C[2];
    C := C[1];
    
    if HasIsLowerTriangularMatrix( C ) and IsLowerTriangularMatrix( C ) and
       ( plist = NumberColumns( C ) + [ -Length( plist ) .. 0 ] or plist = [ 1 .. Length( plist ) ] ) then
        return true;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsLowerTriangularMatrix,
        IsHomalgMatrix and HasPreEval, 0,
        
  function( M )
    local e;
    
    e := PreEval( M );
    
    if HasIsLowerTriangularMatrix( e ) then
        return IsLowerTriangularMatrix( e );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsUpperStairCaseMatrix,
        IsHomalgMatrix and HasEvalInvolution, 0,
        
  function( M )
    local MI;
    
    MI := EvalInvolution( M );
    
    if HasIsLowerStairCaseMatrix( MI ) then
        return IsLowerStairCaseMatrix( MI );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsUpperStairCaseMatrix,
        IsHomalgMatrix and HasEvalTransposedMatrix, 0,
        
  function( M )
    local MI;
    
    MI := EvalTransposedMatrix( M );
    
    if HasIsLowerStairCaseMatrix( MI ) then
        return IsLowerStairCaseMatrix( MI );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsUpperStairCaseMatrix,
        IsHomalgMatrix and HasEvalCertainRows, 0,
        
  function( M )
    local C, plist;
    
    C := EvalCertainRows( M );
    
    plist := C[2];
    C := C[1];
    
    if HasIsUpperStairCaseMatrix( C ) and IsUpperStairCaseMatrix( C ) and
       ( plist = NumberRows( C ) + [ -Length( plist ) .. 0 ] or plist = [ 1 .. Length( plist ) ] ) then
        return true;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsUpperStairCaseMatrix,
        IsHomalgMatrix and HasPreEval, 0,
        
  function( M )
    local e;
    
    e := PreEval( M );
    
    if HasIsUpperStairCaseMatrix( e ) then
        return IsUpperStairCaseMatrix( e );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsLowerStairCaseMatrix,
        IsHomalgMatrix and HasEvalInvolution, 0,
        
  function( M )
    local MI;
    
    MI := EvalInvolution( M );
    
    if HasIsUpperStairCaseMatrix( MI ) then
        return IsUpperStairCaseMatrix( MI );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsLowerStairCaseMatrix,
        IsHomalgMatrix and HasEvalTransposedMatrix, 0,
        
  function( M )
    local MI;
    
    MI := EvalTransposedMatrix( M );
    
    if HasIsUpperStairCaseMatrix( MI ) then
        return IsUpperStairCaseMatrix( MI );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsLowerStairCaseMatrix,
        IsHomalgMatrix and HasEvalCertainColumns, 0,
        
  function( M )
    local C, plist;
    
    C := EvalCertainColumns( M );
    
    plist := C[2];
    C := C[1];
    
    if HasIsLowerStairCaseMatrix( C ) and IsLowerStairCaseMatrix( C ) and
       ( plist = NumberColumns( C ) + [ -Length( plist ) .. 0 ] or plist = [ 1 .. Length( plist ) ] ) then
        return true;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsLowerStairCaseMatrix,
        IsHomalgMatrix and HasPreEval, 0,
        
  function( M )
    local e;
    
    e := PreEval( M );
    
    if HasIsLowerStairCaseMatrix( e ) then
        return IsLowerStairCaseMatrix( e );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsDiagonalMatrix,
        IsHomalgMatrix and HasEvalCertainRows, 0,
        
  function( M )
    local C;
    
    C := EvalCertainRows( M );
    
    if HasIsDiagonalMatrix( C[1] ) and IsDiagonalMatrix( C[1] ) and
       C[2] = [ 1 .. Length( C[2] ) ] then
        return true;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsDiagonalMatrix,
        IsHomalgMatrix and HasEvalCertainColumns, 0,
        
  function( M )
    local C;
    
    C := EvalCertainColumns( M );
    
    if HasIsDiagonalMatrix( C[1] ) and IsDiagonalMatrix( C[1] ) and
       C[2] = [ 1 .. Length( C[2] ) ] then
        return true;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsDiagonalMatrix,
        IsHomalgMatrix and HasEvalUnionOfRows, 0,
        
  function( M )
    local e, A;
    
    e := EvalUnionOfRows( M );
    
    A := e[1];
    
    if HasIsDiagonalMatrix( A ) and IsDiagonalMatrix( A )
       and ForAll( e{[ 2 .. Length( e ) ]}, B -> HasIsZero( B ) and IsZero( B ) ) then
        return true;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsDiagonalMatrix,
        IsHomalgMatrix and HasEvalUnionOfColumns, 0,
        
  function( M )
    local e, A;
    
    e := EvalUnionOfColumns( M );
    
    A := e[1];
    
    if HasIsDiagonalMatrix( A ) and IsDiagonalMatrix( A )
       and ForAll( e{[ 2 .. Length( e ) ]}, B -> HasIsZero( B ) and IsZero( B ) ) then
        return true;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsDiagonalMatrix,
        IsHomalgMatrix and HasPreEval, 0,
        
  function( M )
    local e;
    
    e := PreEval( M );
    
    if HasIsDiagonalMatrix( e ) then
        return IsDiagonalMatrix( e );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsDiagonalMatrix,
        IsHomalgMatrix and HasEvalDiagMat, 0,
        
  function( M )
    local e;
    
    e := EvalDiagMat( M );
    
    if ForAll( e, HasIsDiagonalMatrix ) then
        return ForAll( List( e, IsDiagonalMatrix ), a -> a = true );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsStrictUpperTriangularMatrix,
        IsHomalgMatrix and HasPreEval, 0,
        
  function( M )
    local e;
    
    e := PreEval( M );
    
    if HasIsStrictUpperTriangularMatrix( e ) then
        return IsStrictUpperTriangularMatrix( e );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsStrictLowerTriangularMatrix,
        IsHomalgMatrix and HasPreEval, 0,
        
  function( M )
    local e;
    
    e := PreEval( M );
    
    if HasIsStrictLowerTriangularMatrix( e ) then
        return IsStrictLowerTriangularMatrix( e );
    fi;
    
    TryNextMethod( );
    
end );

####################################
#
# immediate methods for attributes:
#
####################################

##
InstallImmediateMethod( NumberRows,
        IsHomalgMatrix and HasPreEval, 0,
        
  function( M )
    local e;
    
    e := PreEval( M );
    
    if HasNumberRows( e ) then
        return NumberRows( e );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( NumberColumns,
        IsHomalgMatrix and HasPreEval, 0,
        
  function( M )
    local e;
    
    e := PreEval( M );
    
    if HasNumberColumns( e ) then
        return NumberColumns( e );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( RowRankOfMatrix,
        IsHomalgMatrix and HasPreEval, 0,
        
  function( M )
    local e;
    
    e := PreEval( M );
    
    if HasRowRankOfMatrix( e ) then
        return RowRankOfMatrix( e );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( RowRankOfMatrix,
        IsHomalgMatrix and HasEvalInvolution, 0,
        
  function( M )
    local MI;
    
    MI := EvalInvolution( M );
    
    if HasColumnRankOfMatrix( MI ) then
        return ColumnRankOfMatrix( MI );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( RowRankOfMatrix,
        IsHomalgMatrix and HasEvalTransposedMatrix, 0,
        
  function( M )
    local MI;
    
    MI := EvalTransposedMatrix( M );
    
    if HasColumnRankOfMatrix( MI ) then
        return ColumnRankOfMatrix( MI );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( RowRankOfMatrix,
        IsHomalgMatrix and HasEvalUnionOfColumns, 0,
        
  function( M )
    local e, r;
    
    e := EvalUnionOfColumns( M );
    
    if ForAll( e, HasRowRankOfMatrix ) then
        r := List( e, RowRankOfMatrix );
        if Maximum( r ) = Sum( r ) then
            return Maximum( r );
        fi;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( RowRankOfMatrix,
        IsHomalgMatrix and HasEvalUnionOfRows, 0,
        
  function( M )
    local e, r, A;
    
    e := EvalUnionOfRows( M );
    
    if ForAll( e, HasRowRankOfMatrix ) then
        r := List( e, RowRankOfMatrix );
        if Maximum( r ) = Sum( r ) then
            return Maximum( r );
        fi;
    fi;
    
    for A in e do
        if HasRowRankOfMatrix( A ) and RowRankOfMatrix( A ) = NumberColumns( A ) then
            return NumberColumns( A );
        fi;
    od;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( RowRankOfMatrix,
        IsHomalgMatrix and HasEvalDiagMat, 0,
        
  function( M )
    local e;
    
    e := EvalDiagMat( M );
    
    if ForAll( e, HasRowRankOfMatrix ) then
        return Sum( List( e, RowRankOfMatrix ) );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( ColumnRankOfMatrix,
        IsHomalgMatrix and HasPreEval, 0,
        
  function( M )
    local e;
    
    e := PreEval( M );
    
    if HasColumnRankOfMatrix( e ) then
        return ColumnRankOfMatrix( e );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( ColumnRankOfMatrix,
        IsHomalgMatrix and HasEvalInvolution, 0,
        
  function( M )
    local MI;
    
    MI := EvalInvolution( M );
    
    if HasRowRankOfMatrix( MI ) then
        return RowRankOfMatrix( MI );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( ColumnRankOfMatrix,
        IsHomalgMatrix and HasEvalTransposedMatrix, 0,
        
  function( M )
    local MI;
    
    MI := EvalTransposedMatrix( M );
    
    if HasRowRankOfMatrix( MI ) then
        return RowRankOfMatrix( MI );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( ColumnRankOfMatrix,
        IsHomalgMatrix and HasEvalUnionOfRows, 0,
        
  function( M )
    local e, r;
    
    e := EvalUnionOfRows( M );
    
    if ForAll( e, HasColumnRankOfMatrix ) then
        r := List( e, ColumnRankOfMatrix );
        if Maximum( r ) = Sum( r ) then
            return Maximum( r );
        fi;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( ColumnRankOfMatrix,
        IsHomalgMatrix and HasEvalUnionOfColumns, 0,
        
  function( M )
    local e, r, A;
    
    e := EvalUnionOfColumns( M );
    
    if ForAll( e, HasColumnRankOfMatrix ) then
        r := List( e, ColumnRankOfMatrix );
        if Maximum( r ) = Sum( r ) then
            return Maximum( r );
        fi;
    fi;
    
    for A in e do
        if HasColumnRankOfMatrix( A ) and ColumnRankOfMatrix( A ) = NumberRows( A ) then
            return NumberRows( A );
        fi;
    od;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( ColumnRankOfMatrix,
        IsHomalgMatrix and HasEvalDiagMat, 0,
        
  function( M )
    local e;
    
    e := EvalDiagMat( M );
    
    if ForAll( e, HasColumnRankOfMatrix ) then
        return Sum( List( e, ColumnRankOfMatrix ) );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( PositionOfFirstNonZeroEntryPerRow,
        IsHomalgMatrix and HasPreEval, 0,
        
  function( M )
    local e;
    
    e := PreEval( M );
    
    if HasPositionOfFirstNonZeroEntryPerRow( e ) then
        return PositionOfFirstNonZeroEntryPerRow( e );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( PositionOfFirstNonZeroEntryPerRow,
        IsHomalgMatrix and HasEvalCertainRows, 0,
        
  function( M )
    local e, mat, pos;
    
    e := EvalCertainRows( M );
    
    mat := e[1];
    
    if HasPositionOfFirstNonZeroEntryPerRow( mat ) then
        
        pos := PositionOfFirstNonZeroEntryPerRow( mat );
        
        return pos{ e[2] };
        
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( PositionOfFirstNonZeroEntryPerRow,
        IsHomalgMatrix and HasEvalUnionOfRows, 0,
        
  function( M )
    local e;
    
    e := EvalUnionOfRows( M );
    
    if ForAll( e, HasPositionOfFirstNonZeroEntryPerRow ) then
        return Concatenation( List( e, PositionOfFirstNonZeroEntryPerRow ) );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( PositionOfFirstNonZeroEntryPerRow,
        IsHomalgMatrix and HasEvalUnionOfColumns, 0,
        
  function( M )
    local e, c, p, result, i;
    
    e := EvalUnionOfColumns( M );
    
    if ForAll( e, HasPositionOfFirstNonZeroEntryPerRow ) then
        
        c := 0;
        
        p := List( e, PositionOfFirstNonZeroEntryPerRow );

        p := List( p, a -> List( a, function(x) if x = 0 then return infinity; else return x; fi; end ) );
        
        result := ListWithIdenticalEntries( Length( p[1] ), infinity );
        
        for i in [ 1 .. Length( e ) ] do
        
            result := ListN( result, p[i], function( a, b ) return Minimum( a, b + c ); end );
        
            c := c + NumberColumns( e[i] );
        
        od;
        
        return List( result, function( a ) if a = infinity then return 0; else return a; fi; end );
        
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( PositionOfFirstNonZeroEntryPerColumn,
        IsHomalgMatrix and HasPreEval, 0,
        
  function( M )
    local e;
    
    e := PreEval( M );
    
    if HasPositionOfFirstNonZeroEntryPerColumn( e ) then
        return PositionOfFirstNonZeroEntryPerColumn( e );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( PositionOfFirstNonZeroEntryPerColumn,
        IsHomalgMatrix and HasEvalCertainColumns, 0,
        
  function( M )
    local e, mat, pos;
    
    e := EvalCertainColumns( M );
    
    mat := e[1];
    
    if HasPositionOfFirstNonZeroEntryPerColumn( mat ) then
        
        pos := PositionOfFirstNonZeroEntryPerColumn( mat );
        
        return pos{ e[2] };
        
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( PositionOfFirstNonZeroEntryPerColumn,
        IsHomalgMatrix and HasEvalUnionOfColumns, 0,
        
  function( M )
    local e;
    
    e := EvalUnionOfColumns( M );
    
    if ForAll( e, HasPositionOfFirstNonZeroEntryPerColumn ) then
        return Concatenation( List( e, PositionOfFirstNonZeroEntryPerColumn ) );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( PositionOfFirstNonZeroEntryPerColumn,
        IsHomalgMatrix and HasEvalUnionOfRows, 0,
        
  function( M )
    local e, r, p, result, i;
    
    e := EvalUnionOfRows( M );
    
    if ForAll( e, HasPositionOfFirstNonZeroEntryPerColumn ) then
        
        r := 0;
        
        p := List( e, PositionOfFirstNonZeroEntryPerColumn );

        p := List( p, a -> List( a, function(x) if x = 0 then return infinity; else return x; fi; end ) );
        
        result := ListWithIdenticalEntries( Length( p[1] ), infinity );
        
        for i in [ 1 .. Length( e ) ] do
        
            result := ListN( result, p[i], function( a, b ) return Minimum( a, b + r ); end );
        
            r := r + NumberRows( e[i] );
        
        od;
        
        return List( result, function( a ) if a = infinity then return 0; else return a; fi; end );
        
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( ZeroRows,
        IsHomalgMatrix and HasEvalInvolution, 0,
        
  function( M )
    local MI;
    
    MI := EvalInvolution( M );
    
    if HasZeroColumns( MI ) then
        return ZeroColumns( MI );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( ZeroRows,
        IsHomalgMatrix and HasEvalTransposedMatrix, 0,
        
  function( M )
    local MI;
    
    MI := EvalTransposedMatrix( M );
    
    if HasZeroColumns( MI ) then
        return ZeroColumns( MI );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( ZeroColumns,
        IsHomalgMatrix and HasEvalInvolution, 0,
        
  function( M )
    local MI;
    
    MI := EvalInvolution( M );
    
    if HasZeroRows( MI ) then
        return ZeroRows( MI );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( ZeroColumns,
        IsHomalgMatrix and HasEvalTransposedMatrix, 0,
        
  function( M )
    local MI;
    
    MI := EvalTransposedMatrix( M );
    
    if HasZeroRows( MI ) then
        return ZeroRows( MI );
    fi;
    
    TryNextMethod( );
    
end );

####################################
#
# methods for properties:
#
####################################
    
##
InstallMethod( IsZero,
        "COLEM: for homalg matrices",
        [ IsHomalgMatrix and HasEvalUnionOfRows ],
        
  function( M )
    local e;
    
    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "IsZero( UnionOfRows )", "\033[0m" );
    
    e := EvalUnionOfRows( M );
    
    return ForAll( e, IsZero );
    
end );

##
InstallMethod( IsZero,
        "COLEM: for homalg matrices",
        [ IsHomalgMatrix and HasEvalUnionOfColumns ],
        
  function( M )
    local e;
    
    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "IsZero( UnionOfColumns )", "\033[0m" );
    
    e := EvalUnionOfColumns( M );
    
    return ForAll( e, IsZero );
    
end );

##
InstallMethod( IsZero,
        "COLEM: for homalg matrices",
        [ IsHomalgMatrix and HasEvalDiagMat ],
        
  function( M )
    local e;
    
    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "IsZero( DiagMat )", "\033[0m" );
    
    e := EvalDiagMat( M );
    
    return ForAll( e, IsZero );
    
end );

##
InstallMethod( IsZero,
        "COLEM: for homalg matrices",
        [ IsHomalgMatrix and HasEvalMulMatRight ],
        
  function( M )
    local e, A, a;
    
    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "IsZero( A * a )", "\033[0m" );
    
    e := EvalMulMatRight( M );
    
    A := e[1];
    a := e[2];
    
    if IsZero( a ) then
        return true;
    elif IsZero( A ) then
        return true;
    elif HasIsMinusOne( a ) and IsMinusOne( a ) then
        ## A is not zero
        return false;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( IsZero,
        "COLEM: for homalg matrices",
        [ IsHomalgMatrix and HasEvalMulMat ],
        
  function( M )
    local e, a, A;
    
    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "IsZero( a * A )", "\033[0m" );
    
    e := EvalMulMat( M );
    
    a := e[1];
    A := e[2];
    
    if IsZero( a ) then
        return true;
    elif IsZero( A ) then
        return true;
    elif HasIsMinusOne( a ) and IsMinusOne( a ) then
        ## A is not zero
        return false;
    fi;
    
    TryNextMethod( );
    
end );

####################################
#
# methods for attributes:
#
####################################

#-----------------------------------
# ZeroRows
#-----------------------------------

##
InstallMethod( ZeroRows,
        "COLEM: for homalg matrices (HasEvalInvolution)",
        [ IsHomalgMatrix and HasEvalInvolution ],
        
  function( M )
    
    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "ZeroRows( Involution( M ) ) = ZeroColumns( M )", "\033[0m" );
    
    return ZeroColumns( EvalInvolution( M ) );
    
end );

##
InstallMethod( ZeroRows,
        "COLEM: for homalg matrices (HasEvalTransposedMatrix)",
        [ IsHomalgMatrix and HasEvalTransposedMatrix ],
        
  function( M )
    
    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "ZeroRows( TransposedMatrix( M ) ) = ZeroColumns( M )", "\033[0m" );
    
    return ZeroColumns( EvalTransposedMatrix( M ) );
    
end );

#-----------------------------------
# ZeroColumns
#-----------------------------------

##
InstallMethod( ZeroColumns,
        "COLEM: for homalg matrices (HasEvalInvolution)",
        [ IsHomalgMatrix and HasEvalInvolution ],
        
  function( M )
    
    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "ZeroColumns( Involution( M ) ) = ZeroRows( M )", "\033[0m" );
    
    return ZeroRows( EvalInvolution( M ) );
    
end );

##
InstallMethod( ZeroColumns,
        "COLEM: for homalg matrices (HasEvalTransposedMatrix)",
        [ IsHomalgMatrix and HasEvalTransposedMatrix ],
        
  function( M )
    
    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "ZeroColumns( TransposedMatrix( M ) ) = ZeroRows( M )", "\033[0m" );
    
    return ZeroRows( EvalTransposedMatrix( M ) );
    
end );

#-----------------------------------
# IndicatorMatrixOfNonZeroEntries
#-----------------------------------

##
InstallMethod( IndicatorMatrixOfNonZeroEntries,
        "COLEM: for homalg matrices (HasEvalCertainRows)",
        [ IsHomalgMatrix and HasEvalCertainRows ],
        
  function( mat )
    local eval;
    
    eval := EvalCertainRows( mat );
    
    if not HasIndicatorMatrixOfNonZeroEntries( eval ) then
        
        TryNextMethod( );
        
    else
        
        Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "IndicatorMatrixOfNonZeroEntries(CertainRows)", "\033[0m" );
        
        return IndicatorMatrixOfNonZeroEntries( eval[1] ){ eval[2] };
        
    fi;
    
end );

##
InstallMethod( IndicatorMatrixOfNonZeroEntries,
        "COLEM: for homalg matrices (HasEvalCertainColumns)",
        [ IsHomalgMatrix and HasEvalCertainColumns ],
        
  function( mat )
    local eval;
    
    eval := EvalCertainColumns( mat );
    
    if not HasIndicatorMatrixOfNonZeroEntries( eval ) then
        
        TryNextMethod( );
        
    else
        
        Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "IndicatorMatrixOfNonZeroEntries(CertainColumns)", "\033[0m" );
        
        return List( IndicatorMatrixOfNonZeroEntries( eval[1] ), a -> a{ eval[2] } );
        
    fi;
    
end );

##
InstallMethod( IndicatorMatrixOfNonZeroEntries,
        "COLEM: for homalg matrices (HasEvalUnionOfRows)",
        [ IsHomalgMatrix and HasEvalUnionOfRows ],
        
  function( mat )
    local eval;
    
    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "IndicatorMatrixOfNonZeroEntries(UnionOfRows)", "\033[0m" );
    
    eval := EvalUnionOfRows( mat );
    
    return Concatenation( List( eval, IndicatorMatrixOfNonZeroEntries ) );;
    
end );

##
InstallMethod( IndicatorMatrixOfNonZeroEntries,
        "COLEM: for homalg matrices (HasEvalUnionOfColumns)",
        [ IsHomalgMatrix and HasEvalUnionOfColumns ],
        
  function( mat )
    local e, n;
    
    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "IndicatorMatrixOfNonZeroEntries(UnionOfColumns)", "\033[0m" );
    
    e := EvalUnionOfColumns( mat );
    
    n := List( e, IndicatorMatrixOfNonZeroEntries );
    
    return List( [ 1 .. Length( n[1] ) ], a -> Concatenation( List( n, b -> b[a] ) ) );
    
end );

#-----------------------------------
# PositionOfFirstNonZeroEntryPerRow
#-----------------------------------

##
InstallMethod( PositionOfFirstNonZeroEntryPerRow,
        "COLEM: for homalg matrices (HasEvalCertainRows)",
        [ IsHomalgMatrix and HasEvalCertainRows ],
        
  function( M )
    local e, mat, pos;
    
    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "PositionOfFirstNonZeroEntryPerRow( CertainRows )", "\033[0m" );
    
    e := EvalCertainRows( M );
    
    mat := e[1];
    
    pos := PositionOfFirstNonZeroEntryPerRow( mat );
    
    return pos{ e[2] };
    
end );

##
InstallMethod( PositionOfFirstNonZeroEntryPerRow,
        "COLEM: for homalg matrices (HasEvalUnionOfRows)",
        [ IsHomalgMatrix and HasEvalUnionOfRows ],
        
  function( M )
    local e;
    
    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "PositionOfFirstNonZeroEntryPerRow( UnionOfRows )", "\033[0m" );
    
    e := EvalUnionOfRows( M );
    
    return Concatenation( List( e, PositionOfFirstNonZeroEntryPerRow ) );
    
end );

##
InstallMethod( PositionOfFirstNonZeroEntryPerRow,
        "COLEM: for homalg matrices (HasEvalUnionOfColumns)",
        [ IsHomalgMatrix and HasEvalUnionOfColumns ],
        
  function( M )
    local e, c, p, result, i;
    
    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "PositionOfFirstNonZeroEntryPerRow( UnionOfColumns )", "\033[0m" );
    
    e := EvalUnionOfColumns( M );
    
    c := 0;
        
    p := List( e, PositionOfFirstNonZeroEntryPerRow );

    p := List( p, a -> List( a, function(x) if x = 0 then return infinity; else return x; fi; end ) );
        
    result := ListWithIdenticalEntries( Length( p[1] ), infinity );
        
    for i in [ 1 .. Length( e ) ] do
        
        result := ListN( result, p[i], function( a, b ) return Minimum( a, b + c ); end );
       
        c := c + NumberColumns( e[i] );
      
    od;
        
    return List( result, function( a ) if a = infinity then return 0; else return a; fi; end );
        
end );

#-----------------------------------
# PositionOfFirstNonZeroEntryPerColumn
#-----------------------------------

##
InstallMethod( PositionOfFirstNonZeroEntryPerColumn,
        "COLEM: for homalg matrices (HasEvalCertainColumns)",
        [ IsHomalgMatrix and HasEvalCertainColumns ],
        
  function( M )
    local e, mat, pos;
    
    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "PositionOfFirstNonZeroEntryPerColumn( CertainColumns )", "\033[0m" );
    
    e := EvalCertainColumns( M );
    
    mat := e[1];
    
    pos := PositionOfFirstNonZeroEntryPerColumn( mat );
    
    return pos{ e[2] };
    
end );

##
InstallMethod( PositionOfFirstNonZeroEntryPerColumn,
        "COLEM: for homalg matrices (HasEvalUnionOfColumns)",
        [ IsHomalgMatrix and HasEvalUnionOfColumns ],
        
  function( M )
    local e;
    
    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "PositionOfFirstNonZeroEntryPerColumn( UnionOfColumns )", "\033[0m" );
    
    e := EvalUnionOfColumns( M );
    
    return Concatenation( List( e, PositionOfFirstNonZeroEntryPerColumn ) );
    
end );

##
InstallMethod( PositionOfFirstNonZeroEntryPerColumn,
        "COLEM: for homalg matrices (HasEvalUnionOfRows)",
        [ IsHomalgMatrix and HasEvalUnionOfRows ],
        
  function( M )
    local e, r, p, result, i;
    
    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "PositionOfFirstNonZeroEntryPerColumn( UnionOfRows )", "\033[0m" );
    
    e := EvalUnionOfRows( M );
    
    r := 0;
        
    p := List( e, PositionOfFirstNonZeroEntryPerColumn );

    p := List( p, a -> List( a, function(x) if x = 0 then return infinity; else return x; fi; end ) );
    
    result := ListWithIdenticalEntries( Length( p[1] ), infinity );
    
    for i in [ 1 .. Length( e ) ] do
    
        result := ListN( result, p[i], function( a, b ) return Minimum( a, b + r ); end );
    
        r := r + NumberRows( e[i] );
    
    od;
    
    return List( result, function( a ) if a = infinity then return 0; else return a; fi; end );
    
end );

####################################
#
# methods for operations:
#
####################################

#-----------------------------------
# Involution
#-----------------------------------

##
InstallMethod( Involution,
        "COLEM: for homalg matrices (HasPreEval)",
        [ IsHomalgMatrix and HasPreEval ],
        
  function( M )
    
    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "Involution( PreEval )", "\033[0m" );
    
    return Involution( PreEval( M ) );
    
end );

##
InstallMethod( Involution,
        "COLEM: for homalg matrices (HasEvalInvolution)",
        [ IsHomalgMatrix and HasEvalInvolution ],
        
  function( M )
    
    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "Involution( Involution )", "\033[0m" );
    
    return EvalInvolution( M );
    
end );

##
InstallMethod( Involution,
        "COLEM: for homalg matrices (HasEvalDiagMat)",
        [ IsHomalgMatrix and HasEvalDiagMat ],
        
  function( M )
    local e;
    
    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "Involution( DiagMat )", "\033[0m" );
    
    e := EvalDiagMat( M );
    
    e := List( e, Involution );
    
    return DiagMat( e );
    
end );

#-----------------------------------
# TransposedMatrix
#-----------------------------------

##
InstallMethod( TransposedMatrix,
        "COLEM: for homalg matrices (HasPreEval)",
        [ IsHomalgMatrix and HasPreEval ],
        
  function( M )
    
    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "TransposedMatrix( PreEval )", "\033[0m" );
    
    return TransposedMatrix( PreEval( M ) );
    
end );

##
InstallMethod( TransposedMatrix,
        "COLEM: for homalg matrices (HasEvalTransposedMatrix)",
        [ IsHomalgMatrix and HasEvalTransposedMatrix ],
        
  function( M )
    
    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "TransposedMatrix( TransposedMatrix )", "\033[0m" );
    
    return EvalTransposedMatrix( M );
    
end );

##
InstallMethod( TransposedMatrix,
        "COLEM: for homalg matrices (HasEvalDiagMat)",
        [ IsHomalgMatrix and HasEvalDiagMat ],
        
  function( M )
    local e;
    
    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "TransposedMatrix( DiagMat )", "\033[0m" );
    
    e := EvalDiagMat( M );
    
    e := List( e, TransposedMatrix );
    
    return DiagMat( e );
    
end );

#-----------------------------------
# CertainRows
#-----------------------------------

##
InstallMethod( CertainRows,
        "COLEM: for homalg matrices (HasPreEval)",
        [ IsHomalgMatrix and HasPreEval, IsList ],
        
  function( M, plist )
    
    Info( InfoCOLEM, 3, COLEM.color, "colem: CertainRows( PreEval )", "\033[0m" );
    
    return CertainRows( PreEval( M ), plist );
    
end );

##
InstallMethod( CertainRows,
        "COLEM: for homalg matrices (HasEvalCertainRows)",
        [ IsHomalgMatrix and HasEvalCertainRows, IsList ],
        
  function( M, plist )
    local A;
    
    if not HasEval( M ) ## otherwise we would take CertainRows of a bigger matrix
       and COLEM.level >= COLEM.single_operations then
        
        Info( InfoCOLEM, 4, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "CertainRows( CertainRows )", "\033[0m" );
        
        A := EvalCertainRows( M );
        
        return CertainRows( A[1], A[2]{plist} );
        
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( CertainRows,
        "COLEM: for homalg matrices (HasEvalCertainColumns)",
        [ IsHomalgMatrix and HasEvalCertainColumns, IsList ],
        
  function( M, plist )
    local A, plistA;
    
    ## this rule CertainRows( CertainColumns( M, [ ... ] ), [ i ] ) = CertainColumns( CertainRows( M, [ i ] ), [ ... ] )
    ## might be potentially expensive once we end up computing the rhs for the entire range of rows of M
    ## instead of computing CertainColumns( M, [ ... ] ) once and for all
    
    if not HasEval( M ) ## otherwise we would take CertainRows of a bigger matrix
       and COLEM.level >= 2 * COLEM.single_operations then ## this line disables this method by default
        
        A := EvalCertainColumns( M );
        
        plistA := A[2];
        A := A[1];
        
        if Length( plist ) * NumberColumns( A ) < Length( plistA ) * NumberRows( A ) then
            
            Info( InfoCOLEM, 4, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "CertainRows( CertainColumns )", "\033[0m" );
            
            return CertainColumns( CertainRows( A, plist ), plistA );
            
        fi;
        
    fi;
    
    TryNextMethod( );
    
end );

## wrong
#InstallMethod( CertainRows,
#        "COLEM: for homalg matrices (HasEvalUnionOfRows)",
#        [ IsHomalgMatrix and HasEvalUnionOfRows, IsList ],
#        
#  function( M, plist )
#    local e, A, B, a, rowsA, rowsB, plistA, plistB;
#    
#    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "CertainRows( UnionOfRows )", "\033[0m" );
#    
#    e := EvalUnionOfRows( M );
#    
#    A := e[1];
#    B := e[2];
#    
#    a := NumberRows( A );
#    
#    rowsA := [ 1 .. a ];
#    rowsB := [ 1 .. NumberRows( B ) ];
#    
#    plistA := Filtered( plist, x -> x in rowsA );     ## CAUTION: don't use Intersection(2)
#    plistB := Filtered( plist - a, x -> x in rowsB ); ## CAUTION: don't use Intersection(2)
#    
#    return UnionOfRows( CertainRows( A, plistA ), CertainRows( B, plistB ) );
#    
#end );

##
InstallMethod( CertainRows,
        "COLEM: for homalg matrices (HasEvalUnionOfColumns)",
        [ IsHomalgMatrix and HasEvalUnionOfColumns, IsList ],
        
  function( M, plist )
    local e;
    
    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "CertainRows( UnionOfColumns )", "\033[0m" );
    
    e := EvalUnionOfColumns( M );
    
    return UnionOfColumns( List( e, a -> CertainRows( a, plist ) ) );
    
end );

##
InstallMethod( CertainRows,
        "COLEM: for homalg matrices (HasEvalCompose)",
        [ IsHomalgMatrix and HasEvalCompose, IsList ],
        
  function( M, plist )
    local AB;
    
    ## this rule CertainRows( A * B, [ i ] ) = CertainRows( A, [ i ] ) * B
    ## might be potentially expensive once we end up computing the rhs of
    ## for the entire range of rows of A
    
    if not HasEval( M ) and COLEM.level >= COLEM.single_operations then
        
        Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "CertainRows( Compose )", "\033[0m" );
        
        AB := EvalCompose( M );
        
        return CertainRows( AB[1], plist ) * AB[2];
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( CertainRows,
        "COLEM: for homalg matrices (IsEmpty)",
        [ IsHomalgMatrix, IsList and IsEmpty ], 1001,
        
  function( M, plist )
    
    ## forgetting M may save memory
    return HomalgZeroMatrix( 0, NumberColumns( M ), HomalgRing( M ) );
    
end );

#-----------------------------------
# CertainColumns
#-----------------------------------

##
InstallMethod( CertainColumns,
        "COLEM: for homalg matrices (HasPreEval)",
        [ IsHomalgMatrix and HasPreEval, IsList ],
        
  function( M, plist )
    
    Info( InfoCOLEM, 3, COLEM.color, "colem: CertainColumns( PreEval )", "\033[0m" );
    
    return CertainColumns( PreEval( M ), plist );
    
end );

##
InstallMethod( CertainColumns,
        "COLEM: for homalg matrices (HasEvalCertainColumns)",
        [ IsHomalgMatrix and HasEvalCertainColumns, IsList ],
        
  function( M, plist )
    local A;
    
    if not HasEval( M ) ## otherwise we would take CertainColumns of a bigger matrix
       and COLEM.level >= COLEM.single_operations then
        
        Info( InfoCOLEM, 4, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "CertainColumns( CertainColumns )", "\033[0m" );
        
        A := EvalCertainColumns( M );
        
        return CertainColumns( A[1], A[2]{plist} );
        
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( CertainColumns,
        "COLEM: for homalg matrices (HasEvalCertainRows)",
        [ IsHomalgMatrix and HasEvalCertainRows, IsList ],
        
  function( M, plist )
    local A, plistA;
    
    ## this rule CertainColumns( CertainRows( M, [ ... ] ), [ i ] ) = CertainRows( CertainColumns( M, [ i ] ), [ ... ] )
    ## might be potentially expensive once we end up computing the rhs for the entire range of rows of M
    ## instead of computing CertainRows( M, [ ... ] ) once and for all
    
    if not HasEval( M ) ## otherwise we would take CertainColumns of a bigger matrix
       and COLEM.level >= 2 * COLEM.single_operations then ## this line disables this method by default
        
        A := EvalCertainRows( M );
        
        plistA := A[2];
        A := A[1];
        
        if Length( plist ) * NumberRows( A ) < Length( plistA ) * NumberColumns( A ) then
            
            Info( InfoCOLEM, 4, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "CertainColumns( CertainRows )", "\033[0m" );
            
            return CertainRows( CertainColumns( A, plist ), plistA );
            
        fi;
        
    fi;
    
    TryNextMethod( );
    
end );

## wrong
#InstallMethod( CertainColumns,
#        "COLEM: for homalg matrices (HasEvalUnionOfColumns)",
#        [ IsHomalgMatrix and HasEvalUnionOfColumns, IsList ],
#        
#  function( M, plist )
#    local e, A, B, a, columnsA, columnsB, plistA, plistB;
#    
#    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "CertainColumns( UnionOfColumns )", "\033[0m" );
#    
#    e := EvalUnionOfColumns( M );
#    
#    A := e[1];
#    B := e[2];
#    
#    a := NumberColumns( A );
#    
#    columnsA := [ 1 .. a ];
#    columnsB := [ 1 .. NumberColumns( B ) ];
#    
#    plistA := Filtered( plist, x -> x in columnsA );     ## CAUTION: don't use Intersection(2)
#    plistB := Filtered( plist - a, x -> x in columnsB ); ## CAUTION: don't use Intersection(2)
#    
#    return UnionOfColumns( CertainColumns( A, plistA ), CertainColumns( B, plistB ) );
#    
#end );

##
InstallMethod( CertainColumns,
        "COLEM: for homalg matrices (HasEvalUnionOfRows)",
        [ IsHomalgMatrix and HasEvalUnionOfRows, IsList ],
        
  function( M, plist )
    local e;
    
    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "CertainColumns( UnionOfRows )", "\033[0m" );
    
    e := EvalUnionOfRows( M );
    
    return UnionOfRows( List( e, a -> CertainColumns( a, plist ) ) );
    
end );

##
InstallMethod( CertainColumns,
        "COLEM: for homalg matrices (HasEvalCompose)",
        [ IsHomalgMatrix and HasEvalCompose, IsList ],
        
  function( M, plist )
    local AB;
    
    ## this rule CertainColumns( A * B, [ i ] ) = A CertainColumns( B, [ i ] )
    ## might be potentially expensive once we end up computing the rhs of
    ## for the entire range of columns of B
    
    if not HasEval( M ) and COLEM.level >= COLEM.single_operations then
        
        Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "CertainColumns( Compose )", "\033[0m" );
        
        AB := EvalCompose( M );
        
        return AB[1] * CertainColumns( AB[2], plist );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( CertainColumns,
        "COLEM: for homalg matrices (IsEmpty)",
        [ IsHomalgMatrix, IsList and IsEmpty ], 1001,
        
  function( M, plist )
    
    ## forgetting M may save memory
    return HomalgZeroMatrix( NumberRows( M ), 0, HomalgRing( M ) );
    
end );

#-----------------------------------
# DiagMat
#-----------------------------------

##
InstallMethod( DiagMat,
        "COLEM: of a homalg ring and a list of homalg matrices",
        [ IsHomalgRing, IsHomogeneousList ], 1,
        
  function( R, l )
    local pos, r, c, len, L, k, diag;
    
    pos := PositionProperty( l, HasIsEmptyMatrix and IsEmptyMatrix );
    
    if pos <> fail then
        
        r := NumberRows( l[pos] );
        c := NumberColumns( l[pos] );
        
        len := Length( l ); ## we can assume l >= 2, since other methods would then apply
        
        if pos = 1 then
            L := l{[ 2 .. len ]};
            if r = 0 then
                k := Sum( List( L, NumberRows ) );
                diag := UnionOfColumns( HomalgZeroMatrix( k, c, R ), DiagMat( R, L ) );
            else
                k := Sum( List( L, NumberColumns ) );
                diag := UnionOfRows( HomalgZeroMatrix( r, k, R ), DiagMat( R, L ) );
            fi;
        elif pos = len then
            L := l{[ 1 .. len - 1 ]};
            if r = 0 then
                k := Sum( List( L, NumberRows ) );
                diag := UnionOfColumns( DiagMat( R, L ), HomalgZeroMatrix( k, c, R ) );
            else
                k := Sum( List( L, NumberColumns ) );
                diag := UnionOfRows( DiagMat( R, L ), HomalgZeroMatrix( r, k, R ) );
            fi;
        else
            L := l{[ 1 .. pos ]};
            diag := DiagMat( R, [ DiagMat( L ), DiagMat( l{[ pos + 1 .. len ]} ) ] );
        fi;
        
        Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "DiagMat( [ ..., empty matrix, ... ] )", "\033[0m" );
        
        return diag;
        
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( DiagMat,
        "COLEM: of a homalg ring and a list of homalg matrices",
        [ IsHomalgRing, IsHomogeneousList ], 1,
        
  function( R, l )
    
    if PositionProperty( l, m -> HasEvalDiagMat( m ) and not HasEval( m ) ) = fail then
        TryNextMethod( );
    fi;
    
    l := List( l, function( m ) if HasEvalDiagMat( m ) and not HasEval( m ) then return EvalDiagMat( m ); fi; return [ m ]; end  );
    
    l := Concatenation( l );
    
    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "DiagMat( [ ..., DiagMat, ... ] )", "\033[0m" );
    
    return DiagMat( R, l );
    
end );

#-----------------------------------
# AddMat
#-----------------------------------

##
InstallMethod( \+,
        "COLEM: for homalg matrices (HasPreEval)",
        [ IsHomalgMatrix and HasPreEval, IsHomalgMatrix ],
        
  function( A, B )
    
    Info( InfoCOLEM, 3, COLEM.color, "colem: PreEval + IsHomalgMatrix", "\033[0m" );
    
    return PreEval( A ) + B;
    
end );

##
InstallMethod( \+,
        "COLEM: for homalg matrices (HasPreEval)",
        [ IsHomalgMatrix, IsHomalgMatrix and HasPreEval ],
        
  function( A, B )
    
    Info( InfoCOLEM, 3, COLEM.color, "colem: IsHomalgMatrix + PreEval", "\033[0m" );
    
    return A + PreEval( B );
    
end );

##
InstallMethod( \+,
        "COLEM: for two homalg matrices (HasEvalCompose)",
        [ IsHomalgMatrix and HasEvalCompose, IsHomalgMatrix and HasEvalCompose ],
        
  function( A, B )
    local AA, BB, C;
    
    AA := EvalCompose( A );
    BB := EvalCompose( B );
    
    C := AA[1];
    
    if IsIdenticalObj( C , BB[1] ) then
        
        Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "C * E + C * F", "\033[0m" );
        
        return C * ( AA[2] + BB[2] );
        
    fi;
    
    C := AA[2];
    
    if IsIdenticalObj( C , BB[2] ) then
        
        Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "E * C + F * C", "\033[0m" );
        
        return ( AA[1] + BB[1] ) * C;
        
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( \+,
        "COLEM: for two homalg matrices (HasEvalMulMatRight)",
        [ IsHomalgMatrix and HasEvalMulMatRight, IsHomalgMatrix ],
        
  function( A, B )
    local R, AA;
    
    R := HomalgRing( A );
    
    AA := EvalMulMatRight( A );
    
    if IsMinusOne( AA[2] ) then
        
        Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "-A + B", "\033[0m" );
        
        return B - AA[1];
        
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( \+,
        "COLEM: for two homalg matrices (HasEvalMulMat)",
        [ IsHomalgMatrix and HasEvalMulMat, IsHomalgMatrix ],
        
  function( A, B )
    local R, AA;
    
    R := HomalgRing( A );
    
    AA := EvalMulMat( A );
    
    if IsMinusOne( AA[1] ) then
        
        Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "-A + B", "\033[0m" );
        
        return B - AA[2];
        
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( \+,
        "COLEM: for two homalg matrices (HasEvalMulMatRight)",
        [ IsHomalgMatrix, IsHomalgMatrix and HasEvalMulMatRight ],
        
  function( A, B )
    local R, BB;
    
    R := HomalgRing( B );
    
    BB := EvalMulMatRight( B );
    
    if IsMinusOne( BB[2] ) then
        
        Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "A + (-B)", "\033[0m" );
        
        return A - BB[1];
        
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( \+,
        "COLEM: for two homalg matrices (HasEvalMulMat)",
        [ IsHomalgMatrix, IsHomalgMatrix and HasEvalMulMat ],
        
  function( A, B )
    local R, BB;
    
    R := HomalgRing( B );
    
    BB := EvalMulMat( B );
    
    if IsMinusOne( BB[1] ) then
        
        Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "A + (-B)", "\033[0m" );
        
        return A - BB[2];
        
    fi;
    
    TryNextMethod( );
    
end );

#-----------------------------------
# MulMatRight
#-----------------------------------

##
InstallMethod( \*,
        "COLEM: for homalg matrices with ring elements (HasPreEval)",
        [ IsHomalgMatrix and HasPreEval, IsRingElement ],
        
  function( a, A )
    
    Info( InfoCOLEM, 3, COLEM.color, "colem: PreEval * IsRingElement", "\033[0m" );
    
    return PreEval( A ) * a;
    
end );

#-----------------------------------
# MulMat
#-----------------------------------

##
InstallMethod( \*,
        "COLEM: for homalg matrices with ring elements (HasPreEval)",
        [ IsRingElement, IsHomalgMatrix and HasPreEval ],
        
  function( a, A )
    
    Info( InfoCOLEM, 3, COLEM.color, "colem: IsRingElement * PreEval", "\033[0m" );
    
    return a * PreEval( A );
    
end );

##
InstallMethod( \*,
        "COLEM: for homalg matrices with ring elements (HasEvalMulMat)",
        [ IsRingElement, IsHomalgMatrix and HasEvalMulMat ],
        
  function( a, A )
    local e;
    
    e := EvalMulMat( A );
    
    Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "a * ( b * IsHomalgMatrix )", "\033[0m" );
    
    return ( a * e[1] ) * e[2];
    
end );

#-----------------------------------
# AdditiveInverseMutable
#-----------------------------------

## a synonym of `-<elm>':
InstallMethod( AdditiveInverseMutable,
        "COLEM: for homalg matrices (HasPreEval)",
        [ IsHomalgMatrix and HasPreEval ],
        
  function( A )
    
    Info( InfoCOLEM, 3, COLEM.color, "colem: -PreEval", "\033[0m" );
    
    return -PreEval( A );
    
end );

## a synonym of `-<elm>':
InstallMethod( AdditiveInverseMutable,
        "COLEM: for homalg matrices (HasEvalMulMatRight)",
        [ IsHomalgMatrix and HasEvalMulMatRight ],
        
  function( A )
    local R, AA;
    
    R := HomalgRing( A );
    
    AA := EvalMulMatRight( A );
    
    if IsMinusOne( AA[2] ) then
        
        Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "-(-IsHomalgMatrix)", "\033[0m" );
        
        return AA[1];
    fi;
    
    TryNextMethod( );
    
end );

## a synonym of `-<elm>':
InstallMethod( AdditiveInverseMutable,
        "COLEM: for homalg matrices (HasEvalMulMat)",
        [ IsHomalgMatrix and HasEvalMulMat ],
        
  function( A )
    local R, AA;
    
    R := HomalgRing( A );
    
    AA := EvalMulMat( A );
    
    if IsMinusOne( AA[1] ) then
        
        Info( InfoCOLEM, 2, COLEM.color, "\033[01mCOLEM\033[0m ", COLEM.color, "-(-IsHomalgMatrix)", "\033[0m" );
        
        return AA[2];
    fi;
    
    TryNextMethod( );
    
end );

#-----------------------------------
# SubMat
#-----------------------------------

##
InstallMethod( \-,
        "COLEM: for homalg matrices (HasPreEval)",
--> --------------------

--> maximum size reached

--> --------------------

[ Verzeichnis aufwärts0.146unsichere Verbindung  Übersetzung europäischer Sprachen durch Browser  ]