Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quellverzeichnis  COLEM.gi   Interaktion und
Portierbarkeitunbekannt

 
Spracherkennung für: .gi vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

# 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

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

[ Original von:0.74Diese Quellcodebibliothek enthält Beispiele in vielen Programmiersprachen. Man kann per Verzeichnistruktur darin navigieren. Der Code wird farblich markiert angezeigt.  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge