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


Quelle  Tools.gi   Sprache: unbekannt

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

####################################
#
# methods for operations (you MUST replace for an external CAS):
#
####################################

################################
##
## operations for ring elements:
##
################################

##
InstallMethod( Zero,
        "for homalg rings",
        [ IsHomalgRing ], 10001,
        
  function( R )
    local RP;
    
    RP := homalgTable( R );
    
    if IsBound(RP!.Zero) then
        if IsFunction( RP!.Zero ) then
            return RP!.Zero( R );
        else
            return RP!.Zero;
        fi;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( One,
        "for homalg rings",
        [ IsHomalgRing ], 1001,
        
  function( R )
    local RP;
    
    RP := homalgTable( R );
    
    if IsBound(RP!.One) then
        if IsFunction( RP!.One ) then
            return RP!.One( R );
        else
            return RP!.One;
        fi;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( MinusOne,
        "for homalg rings",
        [ IsHomalgRing ],
        
  function( R )
    local RP;
    
    RP := homalgTable( R );
    
    if IsBound(RP!.MinusOne) then
        if IsFunction( RP!.MinusOne ) then
            return RP!.MinusOne( R );
        else
            return RP!.MinusOne;
        fi;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( IsZero,
        "for homalg ring elements",
        [ IsHomalgRingElement ],
        
  function( r )
    local R, RP;
    
    R := HomalgRing( r );
    
    RP := homalgTable( R );
    
    if IsBound(RP!.IsZero) then
        return RP!.IsZero( r );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( IsOne,
        "for homalg ring elements",
        [ IsHomalgRingElement ],
        
  function( r )
    local R, RP;
    
    R := HomalgRing( r );
    
    RP := homalgTable( R );
    
    if IsBound(RP!.IsOne) then
        return RP!.IsOne( r );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( IsMinusOne,
        "for ring elements",
        [ IsRingElement ],
        
  function( r )
    
    return IsZero( r + One( r ) );
    
end );

## a synonym of `-<elm>':
InstallMethod( AdditiveInverseMutable,
        "for homalg rings elements",
        [ IsHomalgRingElement ],
        
  function( r )
    local R, RP;
    
    R := HomalgRing( r );
    
    if not HasRingElementConstructor( R ) then
        Error( "no ring element constructor found in the ring\n" );
    fi;
    
    RP := homalgTable( R );
    
    if IsBound(RP!.Minus) and IsBound(RP!.Zero) and HasRingElementConstructor( R ) then
        return RingElementConstructor( R )( RP!.Minus( Zero( R ), r ), R );
    fi;
    
    ## never fall back to:
    ## return Zero( r ) - r;
    ## this will cause an infinite loop with a method for \- in LIRNG.gi
    
    TryNextMethod( );
    
end );

##
InstallMethod( \/,
        "for homalg ring elements",
        [ IsHomalgRingElement, IsHomalgRingElement ],
        
  function( a, u )
    local R, RP, au;
    
    R := HomalgRing( a );
    
    if not HasRingElementConstructor( R ) then
        Error( "no ring element constructor found in the ring\n" );
    fi;
    
    RP := homalgTable( R );
    
    if IsBound(RP!.DivideByUnit) and IsUnit( u ) then
        au := RP!.DivideByUnit( a, u );
        if au = fail then
            return fail;
        fi;
        return RingElementConstructor( R )( au, R );
    fi;
    
    au := RightDivide( HomalgMatrix( [ a ], 1, 1, R ), HomalgMatrix( [ u ], 1, 1, R ) );
    
    if not IsHomalgMatrix( au ) then
        return fail;
    fi;
    
    return au[ 1, 1 ];
    
end );

###########################
##
## operations for matrices:
##
###########################

##  <#GAPDoc Label="IsZeroMatrix:homalgTable_entry">
##  <ManSection>
##    <Func Arg="M" Name="IsZeroMatrix" Label="homalgTable entry"/>
##    <Returns><C>true</C> or <C>false</C></Returns>
##    <Description>
##      Let <M>R :=</M> <C>HomalgRing</C><M>( <A>M</A> )</M> and <M>RP :=</M> <C>homalgTable</C><M>( R )</M>.
##      If the <C>homalgTable</C> component <M>RP</M>!.<C>IsZeroMatrix</C> is bound then the standard method
##      for the property <Ref Prop="IsZero" Label="for matrices"/> shown below returns
##      <M>RP</M>!.<C>IsZeroMatrix</C><M>( <A>M</A> )</M>.
##    <Listing Type="Code"><![CDATA[
InstallMethod( IsZero,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( M )
    local R, RP;
    
    R := HomalgRing( M );
    
    RP := homalgTable( R );
    
    if IsBound(RP!.IsZeroMatrix) then
        ## CAUTION: the external system must be able
        ## to check zero modulo possible ring relations!
        
        return RP!.IsZeroMatrix( M ); ## with this, \= can fall back to IsZero
    fi;
    
    #=====# the fallback method #=====#
    
    ## from the GAP4 documentation: ?Zero
    ## `ZeroSameMutability( <obj> )' is equivalent to `0 * <obj>'.
    
    return M = 0 * M; ## hence, by default, IsZero falls back to \= (see below)
    
end );
##  ]]></Listing>
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##----------------------
## the methods for Eval:
##----------------------

##  <#GAPDoc Label="Eval:IsInitialMatrix">
##  <ManSection>
##    <Meth Arg="C" Name="Eval" Label="for matrices created with HomalgInitialMatrix"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      In case the matrix <A>C</A> was created using
##      <Ref Meth="HomalgInitialMatrix" Label="constructor for initial matrices filled with zeros"/>
##      then the filter <C>IsInitialMatrix</C> for <A>C</A> is set to true and the <C>homalgTable</C> function
##      (&see; <Ref Meth="InitialMatrix" Label="homalgTable entry for initial matrices"/>)
##      will be used to set the attribute <C>Eval</C> and resets the filter <C>IsInitialMatrix</C>.
##    <Listing Type="Code"><![CDATA[
InstallMethod( Eval,
        "for homalg matrices (IsInitialMatrix)",
        [ IsHomalgMatrix and IsInitialMatrix and
          HasNumberRows and HasNumberColumns ],
        
  function( C )
    local R, RP, z, zz;
    
    R := HomalgRing( C );
    
    RP := homalgTable( R );
    
    if IsBound( RP!.InitialMatrix ) then
        ResetFilterObj( C, IsInitialMatrix );
        SetEval( C, RP!.InitialMatrix( C ) );
        return Eval( C );
    fi;
    
    if not IsHomalgInternalMatrixRep( C ) then
        Error( "could not find a procedure called InitialMatrix in the ",
               "homalgTable to evaluate a non-internal initial matrix\n" );
    fi;
    
    #=====# can only work for homalg internal matrices #=====#
    
    z := Zero( HomalgRing( C ) );
    
    ResetFilterObj( C, IsInitialMatrix );
    
    zz := ListWithIdenticalEntries( NumberColumns( C ), z );
    
    SetEval( C, homalgInternalMatrixHull( List( [ 1 .. NumberRows( C ) ], i -> ShallowCopy( zz ) ) ) );
    
    return Eval( C );
    
end );
##  ]]></Listing>
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="InitialMatrix:homalgTable_entry">
##  <ManSection>
##    <Func Arg="C" Name="InitialMatrix" Label="homalgTable entry for initial matrices"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      Let <M>R :=</M> <C>HomalgRing</C><M>( <A>C</A> )</M> and <M>RP :=</M> <C>homalgTable</C><M>( R )</M>.
##      If the <C>homalgTable</C> component <M>RP</M>!.<C>InitialMatrix</C> is bound then the method
##      <Ref Meth="Eval" Label="for matrices created with HomalgInitialMatrix"/>
##      resets the filter <C>IsInitialMatrix</C> and returns <M>RP</M>!.<C>InitialMatrix</C><M>( <A>C</A> )</M>.
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="Eval:IsInitialIdentityMatrix">
##  <ManSection>
##    <Meth Arg="C" Name="Eval" Label="for matrices created with HomalgInitialIdentityMatrix"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      In case the matrix <A>C</A> was created using
##      <Ref Meth="HomalgInitialIdentityMatrix" Label="constructor for initial quadratic matrices with ones on the diagonal"/>
##      then the filter <C>IsInitialIdentityMatrix</C> for <A>C</A> is set to true and the <C>homalgTable</C> function
##      (&see; <Ref Meth="InitialIdentityMatrix" Label="homalgTable entry for initial identity matrices"/>)
##      will be used to set the attribute <C>Eval</C> and resets the filter <C>IsInitialIdentityMatrix</C>.
##    <Listing Type="Code"><![CDATA[
InstallMethod( Eval,
        "for homalg matrices (IsInitialIdentityMatrix)",
        [ IsHomalgMatrix and IsInitialIdentityMatrix and
          HasNumberRows and HasNumberColumns ],
        
  function( C )
    local R, RP, o, z, zz, id;
    
    R := HomalgRing( C );
    
    RP := homalgTable( R );
    
    if IsBound( RP!.InitialIdentityMatrix ) then
        ResetFilterObj( C, IsInitialIdentityMatrix );
        SetEval( C, RP!.InitialIdentityMatrix( C ) );
        return Eval( C );
    fi;
    
    if not IsHomalgInternalMatrixRep( C ) then
        Error( "could not find a procedure called InitialIdentityMatrix in the ",
               "homalgTable to evaluate a non-internal initial identity matrix\n" );
    fi;
    
    #=====# can only work for homalg internal matrices #=====#
    
    z := Zero( HomalgRing( C ) );
    o := One( HomalgRing( C ) );
    
    ResetFilterObj( C, IsInitialIdentityMatrix );
    
    zz := ListWithIdenticalEntries( NumberColumns( C ), z );
    
    id := List( [ 1 .. NumberRows( C ) ],
                function(i)
                  local z;
                  z := ShallowCopy( zz ); z[i] := o; return z;
                end );
    
    SetEval( C, homalgInternalMatrixHull( id ) );
    
    return Eval( C );
    
end );
##  ]]></Listing>
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="InitialIdentityMatrix:homalgTable_entry">
##  <ManSection>
##    <Func Arg="C" Name="InitialIdentityMatrix" Label="homalgTable entry for initial identity matrices"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      Let <M>R :=</M> <C>HomalgRing</C><M>( <A>C</A> )</M> and <M>RP :=</M> <C>homalgTable</C><M>( R )</M>.
##      If the <C>homalgTable</C> component <M>RP</M>!.<C>InitialIdentityMatrix</C> is bound then the method
##      <Ref Meth="Eval" Label="for matrices created with HomalgInitialIdentityMatrix"/>
##      resets the filter <C>IsInitialIdentityMatrix</C> and returns <M>RP</M>!.<C>InitialIdentityMatrix</C><M>( <A>C</A> )</M>.
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##
InstallMethod( Eval,
        "for homalg matrices (HasEvalMatrixOperation)",
        [ IsHomalgMatrix and HasEvalMatrixOperation ],
        
  function( C )
    local func_arg;
    
    func_arg := EvalMatrixOperation( C );
    
    ResetFilterObj( C, HasEvalMatrixOperation );
    
    ## delete the component which was left over by GAP
    Unbind( C!.EvalMatrixOperation );
    
    return CallFuncList( func_arg[1], func_arg[2] );
    
end );

##  <#GAPDoc Label="Eval:HasEvalInvolution">
##  <ManSection>
##    <Meth Arg="C" Name="Eval" Label="for matrices created with Involution"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      In case the matrix was created using
##      <Ref Meth="Involution" Label="for matrices"/>
##      then the filter <C>HasEvalInvolution</C> for <A>C</A> is set to true and the <C>homalgTable</C> function
##      <Ref Meth="Involution" Label="homalgTable entry"/>
##      will be used to set the attribute <C>Eval</C>.
##    <Listing Type="Code"><![CDATA[
InstallMethod( Eval,
        "for homalg matrices (HasEvalInvolution)",
        [ IsHomalgMatrix and HasEvalInvolution ],
        
  function( C )
    local R, RP, M;
    
    R := HomalgRing( C );
    
    RP := homalgTable( R );
    
    M :=  EvalInvolution( C );
    
    if IsBound(RP!.Involution) then
        return RP!.Involution( M );
    fi;
    
    if not IsHomalgInternalMatrixRep( C ) then
        Error( "could not find a procedure called Involution ",
               "in the homalgTable of the non-internal ring\n" );
    fi;
    
    #=====# can only work for homalg internal matrices #=====#
    
    return homalgInternalMatrixHull( TransposedMat( Eval( M )!.matrix ) );
    
end );
##  ]]></Listing>
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="Involution:homalgTable_entry">
##  <ManSection>
##    <Func Arg="M" Name="Involution" Label="homalgTable entry"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      Let <M>R :=</M> <C>HomalgRing</C><M>( <A>C</A> )</M> and <M>RP :=</M> <C>homalgTable</C><M>( R )</M>.
##      If the <C>homalgTable</C> component <M>RP</M>!.<C>Involution</C> is bound then
##      the method <Ref Meth="Eval" Label="for matrices created with Involution"/> returns
##      <M>RP</M>!.<C>Involution</C> applied to the content of the attribute <C>EvalInvolution</C><M>( <A>C</A> ) = <A>M</A></M>.
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="Eval:HasEvalTransposedMatrix">
##  <ManSection>
##    <Meth Arg="C" Name="Eval" Label="for matrices created with TransposedMatrix"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      In case the matrix was created using
##      <Ref Meth="TransposedMatrix" Label="for matrices"/>
##      then the filter <C>HasEvalTransposedMatrix</C> for <A>C</A> is set to true and the <C>homalgTable</C> function
##      <Ref Meth="TransposedMatrix" Label="homalgTable entry"/>
##      will be used to set the attribute <C>Eval</C>.
##    <Listing Type="Code"><![CDATA[
InstallMethod( Eval,
        "for homalg matrices (HasEvalTransposedMatrix)",
        [ IsHomalgMatrix and HasEvalTransposedMatrix ],
        
  function( C )
    local R, RP, M;
    
    R := HomalgRing( C );
    
    RP := homalgTable( R );
    
    M :=  EvalTransposedMatrix( C );
    
    if IsBound(RP!.TransposedMatrix) then
        return RP!.TransposedMatrix( M );
    fi;
    
    if not IsHomalgInternalMatrixRep( C ) then
        Error( "could not find a procedure called TransposedMatrix ",
               "in the homalgTable of the non-internal ring\n" );
    fi;
    
    #=====# can only work for homalg internal matrices #=====#
    
    return homalgInternalMatrixHull( TransposedMat( Eval( M )!.matrix ) );
    
end );
##  ]]></Listing>
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="TransposedMatrix:homalgTable_entry">
##  <ManSection>
##    <Func Arg="M" Name="TransposedMatrix" Label="homalgTable entry"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      Let <M>R :=</M> <C>HomalgRing</C><M>( <A>C</A> )</M> and <M>RP :=</M> <C>homalgTable</C><M>( R )</M>.
##      If the <C>homalgTable</C> component <M>RP</M>!.<C>TransposedMatrix</C> is bound then
##      the method <Ref Meth="Eval" Label="for matrices created with TransposedMatrix"/> returns
##      <M>RP</M>!.<C>TransposedMatrix</C> applied to the content of the attribute <C>EvalTransposedMatrix</C><M>( <A>C</A> ) = <A>M</A></M>.
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="Eval:HasEvalCoercedMatrix">
##  <ManSection>
##    <Meth Arg="C" Name="Eval" Label="for matrices created with CoercedMatrix"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      In case the matrix was created using
##      <Ref Meth="CoercedMatrix" Label="copy a matrix over a different ring"/>
##      then the filter <C>HasEvalCoercedMatrix</C> for <A>C</A> is set to true and the <C>Eval</C> value
##      of a copy of <C>EvalCoercedMatrix(</C><A>C</A><C>)</C> in <C>HomalgRing(</C><A>C</A><C>)</C>
##      will be used to set the attribute <C>Eval</C>.
##    <Listing Type="Code"><![CDATA[
InstallMethod( Eval,
        "for homalg matrices (HasEvalCoercedMatrix)",
        [ IsHomalgMatrix and HasEvalCoercedMatrix ],
        
  function( C )
    local R, RP, m;
    
    R := HomalgRing( C );
    
    RP := homalgTable( R );
    
    m := EvalCoercedMatrix( C );
    
    # delegate to the non-lazy coercening
    return Eval( R * m );
    
end );
##  ]]></Listing>
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="Eval:HasEvalCertainRows">
##  <ManSection>
##    <Meth Arg="C" Name="Eval" Label="for matrices created with CertainRows"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      In case the matrix was created using
##      <Ref Meth="CertainRows" Label="for matrices"/>
##      then the filter <C>HasEvalCertainRows</C> for <A>C</A> is set to true and the <C>homalgTable</C> function
##      <Ref Meth="CertainRows" Label="homalgTable entry"/>
##      will be used to set the attribute <C>Eval</C>.
##    <Listing Type="Code"><![CDATA[
InstallMethod( Eval,
        "for homalg matrices (HasEvalCertainRows)",
        [ IsHomalgMatrix and HasEvalCertainRows ],
        
  function( C )
    local R, RP, e, M, plist;
    
    R := HomalgRing( C );
    
    RP := homalgTable( R );
    
    e :=  EvalCertainRows( C );
    
    M := e[1];
    plist := e[2];
    
    ResetFilterObj( C, HasEvalCertainRows );
    
    ## delete the component which was left over by GAP
    Unbind( C!.EvalCertainRows );
    
    if IsBound(RP!.CertainRows) then
        return RP!.CertainRows( M, plist );
    fi;
    
    if not IsHomalgInternalMatrixRep( C ) then
        Error( "could not find a procedure called CertainRows ",
               "in the homalgTable of the non-internal ring\n" );
    fi;
    
    #=====# can only work for homalg internal matrices #=====#
    
    return homalgInternalMatrixHull( Eval( M )!.matrix{ plist } );
    
end );
##  ]]></Listing>
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="CertainRows:homalgTable_entry">
##  <ManSection>
##    <Func Arg="M, plist" Name="CertainRows" Label="homalgTable entry"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      Let <M>R :=</M> <C>HomalgRing</C><M>( <A>C</A> )</M> and <M>RP :=</M> <C>homalgTable</C><M>( R )</M>.
##      If the <C>homalgTable</C> component <M>RP</M>!.<C>CertainRows</C> is bound then
##      the method <Ref Meth="Eval" Label="for matrices created with CertainRows"/> returns
##      <M>RP</M>!.<C>CertainRows</C> applied to the content of the attribute
##      <C>EvalCertainRows</C><M>( <A>C</A> ) = [ <A>M</A>, <A>plist</A> ]</M>.
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="Eval:HasEvalCertainColumns">
##  <ManSection>
##    <Meth Arg="C" Name="Eval" Label="for matrices created with CertainColumns"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      In case the matrix was created using
##      <Ref Meth="CertainColumns" Label="for matrices"/>
##      then the filter <C>HasEvalCertainColumns</C> for <A>C</A> is set to true and the <C>homalgTable</C> function
##      <Ref Meth="CertainColumns" Label="homalgTable entry"/>
##      will be used to set the attribute <C>Eval</C>.
##    <Listing Type="Code"><![CDATA[
InstallMethod( Eval,
        "for homalg matrices (HasEvalCertainColumns)",
        [ IsHomalgMatrix and HasEvalCertainColumns ],
        
  function( C )
    local R, RP, e, M, plist;
    
    R := HomalgRing( C );
    
    RP := homalgTable( R );
    
    e :=  EvalCertainColumns( C );
    
    M := e[1];
    plist := e[2];
    
    ResetFilterObj( C, HasEvalCertainColumns );
    
    ## delete the component which was left over by GAP
    Unbind( C!.EvalCertainColumns );
    
    if IsBound(RP!.CertainColumns) then
        return RP!.CertainColumns( M, plist );
    fi;
    
    if not IsHomalgInternalMatrixRep( C ) then
        Error( "could not find a procedure called CertainColumns ",
               "in the homalgTable of the non-internal ring\n" );
    fi;
    
    #=====# can only work for homalg internal matrices #=====#
    
    return homalgInternalMatrixHull(
                   Eval( M )!.matrix{[ 1 .. NumberRows( M ) ]}{plist} );
    
end );
##  ]]></Listing>
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="CertainColumns:homalgTable_entry">
##  <ManSection>
##    <Func Arg="M, plist" Name="CertainColumns" Label="homalgTable entry"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      Let <M>R :=</M> <C>HomalgRing</C><M>( <A>C</A> )</M> and <M>RP :=</M> <C>homalgTable</C><M>( R )</M>.
##      If the <C>homalgTable</C> component <M>RP</M>!.<C>CertainColumns</C> is bound then
##      the method <Ref Meth="Eval" Label="for matrices created with CertainColumns"/> returns
##      <M>RP</M>!.<C>CertainColumns</C> applied to the content of the attribute
##      <C>EvalCertainColumns</C><M>( <A>C</A> ) = [ <A>M</A>, <A>plist</A> ]</M>.
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="Eval:HasEvalUnionOfRows">
##  <ManSection>
##    <Meth Arg="C" Name="Eval" Label="for matrices created with UnionOfRows"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      In case the matrix was created using
##      <Ref Func="UnionOfRows" Label="for a homalg ring, an integer and a list of homalg matrices"/>
##      then the filter <C>HasEvalUnionOfRows</C> for <A>C</A> is set to true and the <C>homalgTable</C> function
##      <Ref Meth="UnionOfRows" Label="homalgTable entry"/> or the <C>homalgTable</C> function
##      <Ref Meth="UnionOfRowsPair" Label="homalgTable entry"/>
##      will be used to set the attribute <C>Eval</C>.
##    <Listing Type="Code"><![CDATA[
InstallMethod( Eval,
        "for homalg matrices (HasEvalUnionOfRows)",
        [ IsHomalgMatrix and HasEvalUnionOfRows ],
        
  function( C )
    local R, RP, e, i, combine;
    
    R := HomalgRing( C );
    
    RP := homalgTable( R );
    
    # Make it mutable
    e := ShallowCopy( EvalUnionOfRows( C ) );
    
    # In case of nested UnionOfRows, we try to avoid
    # recursion, since the gap stack is rather small
    # additionally unpack PreEvals
    i := 1;
    while i <= Length( e ) do
        
        if HasPreEval( e[i] ) and not HasEval( e[i] ) then
            
            e[i] := PreEval( e[i] );
            
        elif HasEvalUnionOfRows( e[i] ) and not HasEval( e[i] ) then
            
            e := Concatenation( e{[ 1 .. (i-1) ]}, EvalUnionOfRows( e[i] ), e{[ (i+1) .. Length( e ) ]}  );
            
        else
            
            i := i + 1;
            
        fi;
        
    od;
    
    # Combine zero matrices
    i := 1;
    while i + 1 <= Length( e ) do
        
        if HasIsZero( e[i] ) and IsZero( e[i] ) and HasIsZero( e[i+1] ) and IsZero( e[i+1] ) then
            
            e[i] := HomalgZeroMatrix( NumberRows( e[i] ) + NumberRows( e[i+1] ), NumberColumns( e[i] ), HomalgRing( e[i] ) );
            
            Remove( e, i + 1 );
            
        else
            
            i := i + 1;
            
        fi;
        
    od;
    
    # After combining zero matrices only a single one might be left
    if Length( e ) = 1 then
        
        return e[1];
        
    fi;
    
    # Use RP!.UnionOfRows if available
    if IsBound(RP!.UnionOfRows) then
        
        return RP!.UnionOfRows( e );
        
    fi;
    
    # Fall back to RP!.UnionOfRowsPair or manual fallback for internal matrices
    # Combine the matrices
    # Use a balanced binary tree to keep the sizes small (heuristically)
    # to avoid a huge memory footprint
    
    if not IsBound(RP!.UnionOfRowsPair) and not IsHomalgInternalMatrixRep( C ) then
        Error( "could neither find a procedure called UnionOfRows ",
               "nor a procedure called UnionOfRowsPair ",
               "in the homalgTable of the non-internal ring\n" );
    fi;
    
    combine := function( A, B )
      local result, U;
        
        if IsBound(RP!.UnionOfRowsPair) then
            
            result := RP!.UnionOfRowsPair( A, B );
            
        else
            
            #=====# can only work for homalg internal matrices #=====#
            
            U := ShallowCopy( Eval( A )!.matrix );
            
            U{ [ NumberRows( A ) + 1 .. NumberRows( A ) + NumberRows( B ) ] } := Eval( B )!.matrix;
            
            result := homalgInternalMatrixHull( U );
            
        fi;
        
        return HomalgMatrixWithAttributes( [
                    Eval, result,
                    EvalUnionOfRows, [ A, B ],
                    NumberRows, NumberRows( A ) + NumberRows( B ),
                    NumberColumns, NumberColumns( A ),
                    ], R );
        
    end;
    
    while Length( e ) > 1 do
        
        for i in [ 1 .. Int( Length( e ) / 2 ) ] do
            
            e[ 2 * i - 1 ] := combine( e[ 2 * i - 1 ], e[ 2 * i ] );
            Unbind( e[ 2 * i ] );
            
        od;
        
        e := Compacted( e );
        
    od;
    
    return Eval( e[1] );
    
end );
##  ]]></Listing>
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="UnionOfRows:homalgTable_entry">
##  <ManSection>
##    <Func Arg="L" Name="UnionOfRows" Label="homalgTable entry"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      Let <M>R :=</M> <C>HomalgRing</C><M>( <A>C</A> )</M> and <M>RP :=</M> <C>homalgTable</C><M>( R )</M>.
##      If the <C>homalgTable</C> component <M>RP</M>!.<C>UnionOfRows</C> is bound then
##      the method <Ref Meth="Eval" Label="for matrices created with UnionOfRows"/> returns
##      <M>RP</M>!.<C>UnionOfRows</C> applied to the content of the attribute
##      <C>EvalUnionOfRows</C><M>( <A>C</A> ) = <A>L</A></M>.
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="UnionOfRowsPair:homalgTable_entry">
##  <ManSection>
##    <Func Arg="A, B" Name="UnionOfRowsPair" Label="homalgTable entry"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      Let <M>R :=</M> <C>HomalgRing</C><M>( <A>C</A> )</M> and <M>RP :=</M> <C>homalgTable</C><M>( R )</M>.
##      If the <C>homalgTable</C> component <M>RP</M>!.<C>UnionOfRowsPair</C> is bound
##      and the <C>homalgTable</C> component <M>RP</M>!.<C>UnionOfRows</C> is not bound then
##      the method <Ref Meth="Eval" Label="for matrices created with UnionOfRows"/> returns
##      <M>RP</M>!.<C>UnionOfRowsPair</C> applied recursively to a balanced binary tree created from
##      the content of the attribute <C>EvalUnionOfRows</C><M>( <A>C</A> )</M>.
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="Eval:HasEvalUnionOfColumns">
##  <ManSection>
##    <Meth Arg="C" Name="Eval" Label="for matrices created with UnionOfColumns"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      In case the matrix was created using
##      <Ref Func="UnionOfColumns" Label="for a homalg ring, an integer and a list of homalg matrices"/>
##      then the filter <C>HasEvalUnionOfColumns</C> for <A>C</A> is set to true and the <C>homalgTable</C> function
##      <Ref Meth="UnionOfColumns" Label="homalgTable entry"/> or the <C>homalgTable</C> function
##      <Ref Meth="UnionOfColumnsPair" Label="homalgTable entry"/>
##      will be used to set the attribute <C>Eval</C>.
##    <Listing Type="Code"><![CDATA[
InstallMethod( Eval,
        "for homalg matrices (HasEvalUnionOfColumns)",
        [ IsHomalgMatrix and HasEvalUnionOfColumns ],
        
  function( C )
    local R, RP, e, i, combine;
    
    R := HomalgRing( C );
    
    RP := homalgTable( R );
    
    # Make it mutable
    e := ShallowCopy( EvalUnionOfColumns( C ) );
    
    # In case of nested UnionOfColumns, we try to avoid
    # recursion, since the gap stack is rather small
    # additionally unpack PreEvals
    i := 1;
    while i <= Length( e ) do
        
        if HasPreEval( e[i] ) and not HasEval( e[i] ) then
            
            e[i] := PreEval( e[i] );
            
        elif HasEvalUnionOfColumns( e[i] ) and not HasEval( e[i] ) then
            
            e := Concatenation( e{[ 1 .. (i-1) ]}, EvalUnionOfColumns( e[i] ), e{[ (i+1) .. Length( e ) ]}  );
            
        else
            
            i := i + 1;
            
        fi;
        
    od;
    
    # Combine zero matrices
    i := 1;
    while i + 1 <= Length( e ) do
        
        if HasIsZero( e[i] ) and IsZero( e[i] ) and HasIsZero( e[i+1] ) and IsZero( e[i+1] ) then
            
            e[i] := HomalgZeroMatrix( NumberRows( e[i] ), NumberColumns( e[i] ) + NumberColumns( e[i+1] ), HomalgRing( e[i] ) );
            
            Remove( e, i + 1 );
            
        else
            
            i := i + 1;
            
        fi;
        
    od;
    
    # After combining zero matrices only a single one might be left
    if Length( e ) = 1 then
        
        return e[1];
        
    fi;
    
    # Use RP!.UnionOfColumns if available
    if IsBound(RP!.UnionOfColumns) then
        
        return RP!.UnionOfColumns( e );
        
    fi;
    
    # Fall back to RP!.UnionOfColumnsPair or manual fallback for internal matrices
    # Combine the matrices
    # Use a balanced binary tree to keep the sizes small (heuristically)
    # to avoid a huge memory footprint
    
    if not IsBound(RP!.UnionOfColumnsPair) and not IsHomalgInternalMatrixRep( C ) then
        Error( "could neither find a procedure called UnionOfColumns ",
               "nor a procedure called UnionOfColumnsPair ",
               "in the homalgTable of the non-internal ring\n" );
    fi;
    
    combine := function( A, B )
      local result, U;
        
        if IsBound(RP!.UnionOfColumnsPair) then
            
            result := RP!.UnionOfColumnsPair( A, B );
            
        else
            
            #=====# can only work for homalg internal matrices #=====#
            
            U := List( Eval( A )!.matrix, ShallowCopy );
            
            U{ [ 1 .. NumberRows( A ) ] }
              { [ NumberColumns( A ) + 1 .. NumberColumns( A ) + NumberColumns( B ) ] }
              := Eval( B )!.matrix;
            
            result := homalgInternalMatrixHull( U );
            
        fi;
        
        return HomalgMatrixWithAttributes( [
                    Eval, result,
                    EvalUnionOfColumns, [ A, B ],
                    NumberRows, NumberRows( A ),
                    NumberColumns, NumberColumns( A ) + NumberColumns( B )
                    ], R );
        
    end;
    
    while Length( e ) > 1 do
        
        for i in [ 1 .. Int( Length( e ) / 2 ) ] do
            
            e[ 2 * i - 1 ] := combine( e[ 2 * i - 1 ], e[ 2 * i ] );
            Unbind( e[ 2 * i ] );
            
        od;
        
        e := Compacted( e );
        
    od;
    
    return Eval( e[1] );
    
end );
##  ]]></Listing>
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="UnionOfColumns:homalgTable_entry">
##  <ManSection>
##    <Func Arg="L" Name="UnionOfColumns" Label="homalgTable entry"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      Let <M>R :=</M> <C>HomalgRing</C><M>( <A>C</A> )</M> and <M>RP :=</M> <C>homalgTable</C><M>( R )</M>.
##      If the <C>homalgTable</C> component <M>RP</M>!.<C>UnionOfColumns</C> is bound then
##      the method <Ref Meth="Eval" Label="for matrices created with UnionOfColumns"/> returns
##      <M>RP</M>!.<C>UnionOfColumns</C> applied to the content of the attribute
##      <C>EvalUnionOfColumns</C><M>( <A>C</A> ) = <A>L</A></M>.
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="UnionOfColumnsPair:homalgTable_entry">
##  <ManSection>
##    <Func Arg="A, B" Name="UnionOfColumnsPair" Label="homalgTable entry"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      Let <M>R :=</M> <C>HomalgRing</C><M>( <A>C</A> )</M> and <M>RP :=</M> <C>homalgTable</C><M>( R )</M>.
##      If the <C>homalgTable</C> component <M>RP</M>!.<C>UnionOfColumnsPair</C> is bound
##      and the <C>homalgTable</C> component <M>RP</M>!.<C>UnionOfColumns</C> is not bound then
##      the method <Ref Meth="Eval" Label="for matrices created with UnionOfColumns"/> returns
##      <M>RP</M>!.<C>UnionOfColumnsPair</C> applied recursively to a balanced binary tree created from
##      the content of the attribute <C>EvalUnionOfRows</C><M>( <A>C</A> )</M>.
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="Eval:HasEvalDiagMat">
##  <ManSection>
##    <Meth Arg="C" Name="Eval" Label="for matrices created with DiagMat"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      In case the matrix was created using
##      <Ref Meth="DiagMat" Label="for a homalg ring and a list of homalg matrices"/>
##      then the filter <C>HasEvalDiagMat</C> for <A>C</A> is set to true and the <C>homalgTable</C> function
##      <Ref Meth="DiagMat" Label="homalgTable entry"/>
##      will be used to set the attribute <C>Eval</C>.
##    <Listing Type="Code"><![CDATA[
InstallMethod( Eval,
        "for homalg matrices (HasEvalDiagMat)",
        [ IsHomalgMatrix and HasEvalDiagMat ],
        
  function( C )
    local R, RP, e, l, z, m, n, diag, mat;
    
    R := HomalgRing( C );
    
    RP := homalgTable( R );
    
    e :=  EvalDiagMat( C );
    
    if IsBound(RP!.DiagMat) then
        return RP!.DiagMat( e );
    fi;
    
    l := Length( e );
    
    if not IsHomalgInternalMatrixRep( C ) then
        return UnionOfRows(
                       List( [ 1 .. l ],
                             i -> UnionOfColumns(
                                     List( [ 1 .. l ],
                                           function( j )
                                             if i = j then
                                                 return e[i];
                                             fi;
                                             return HomalgZeroMatrix( NumberRows( e[i] ), NumberColumns( e[j] ), R );
                                           end )
                                     )
                             )
                       );
    fi;
    
    #=====# can only work for homalg internal matrices #=====#
    
    z := Zero( R );
    
    m := Sum( List( e, NumberRows ) );
    n := Sum( List( e, NumberColumns ) );
    
    diag := List( [ 1 .. m ], a -> List( [ 1 .. n ], b -> z ) );
    
    m := 0;
    n := 0;
    
    for mat in e do
        diag{ [ m + 1 .. m + NumberRows( mat ) ] }{ [ n + 1 .. n + NumberColumns( mat ) ] }
          := Eval( mat )!.matrix;
        
        m := m + NumberRows( mat );
        n := n + NumberColumns( mat );
    od;
    
    return homalgInternalMatrixHull( diag );
    
end );
##  ]]></Listing>
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="DiagMat:homalgTable_entry">
##  <ManSection>
##    <Func Arg="e" Name="DiagMat" Label="homalgTable entry"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      Let <M>R :=</M> <C>HomalgRing</C><M>( <A>C</A> )</M> and <M>RP :=</M> <C>homalgTable</C><M>( R )</M>.
##      If the <C>homalgTable</C> component <M>RP</M>!.<C>DiagMat</C> is bound then
##      the method <Ref Meth="Eval" Label="for matrices created with DiagMat"/> returns
##      <M>RP</M>!.<C>DiagMat</C> applied to the content of the attribute
##      <C>EvalDiagMat</C><M>( <A>C</A> ) = <A>e</A></M>.
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="Eval:HasEvalKroneckerMat">
##  <ManSection>
##    <Meth Arg="C" Name="Eval" Label="for matrices created with KroneckerMat"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      In case the matrix was created using
##      <Ref Meth="KroneckerMat" Label="for matrices"/>
##      then the filter <C>HasEvalKroneckerMat</C> for <A>C</A> is set to true and the <C>homalgTable</C> function
##      <Ref Meth="KroneckerMat" Label="homalgTable entry"/>
##      will be used to set the attribute <C>Eval</C>.
##    <Listing Type="Code"><![CDATA[
InstallMethod( Eval,
        "for homalg matrices (HasEvalKroneckerMat)",
        [ IsHomalgMatrix and HasEvalKroneckerMat ],
        
  function( C )
    local R, RP, A, B;
    
    R := HomalgRing( C );
    
    if ( HasIsCommutative( R ) and not IsCommutative( R ) ) and
       ( HasIsSuperCommutative( R ) and not IsSuperCommutative( R ) ) then
        Info( InfoWarning, 1, "\033[01m\033[5;31;47m",
              "the Kronecker product is only defined for (super) commutative rings!",
              "\033[0m" );
    fi;
    
    RP := homalgTable( R );
    
    A :=  EvalKroneckerMat( C )[1];
    B :=  EvalKroneckerMat( C )[2];
    
    if IsBound(RP!.KroneckerMat) then
        return RP!.KroneckerMat( A, B );
    fi;
    
    if not IsHomalgInternalMatrixRep( C ) then
        Error( "could not find a procedure called KroneckerMat ",
               "in the homalgTable of the non-internal ring\n" );
    fi;
    
    #=====# can only work for homalg internal matrices #=====#
    
    return homalgInternalMatrixHull(
                   KroneckerProduct( Eval( A )!.matrix, Eval( B )!.matrix ) );
    ## this was easy, thanks GAP :)
    
end );
##  ]]></Listing>
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="KroneckerMat:homalgTable_entry">
##  <ManSection>
##    <Func Arg="A, B" Name="KroneckerMat" Label="homalgTable entry"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      Let <M>R :=</M> <C>HomalgRing</C><M>( <A>C</A> )</M> and <M>RP :=</M> <C>homalgTable</C><M>( R )</M>.
##      If the <C>homalgTable</C> component <M>RP</M>!.<C>KroneckerMat</C> is bound then
##      the method <Ref Meth="Eval" Label="for matrices created with KroneckerMat"/> returns
##      <M>RP</M>!.<C>KroneckerMat</C> applied to the content of the attribute
##      <C>EvalKroneckerMat</C><M>( <A>C</A> ) = [ <A>A</A>, <A>B</A> ]</M>.
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="Eval:HasEvalDualKroneckerMat">
##  <ManSection>
##    <Meth Arg="C" Name="Eval" Label="for matrices created with DualKroneckerMat"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      In case the matrix was created using
##      <Ref Meth="DualKroneckerMat" Label="for matrices"/>
##      then the filter <C>HasEvalDualKroneckerMat</C> for <A>C</A> is set to true and the <C>homalgTable</C> function
##      <Ref Meth="DualKroneckerMat" Label="homalgTable entry"/>
##      will be used to set the attribute <C>Eval</C>.
##    <Listing Type="Code"><![CDATA[
InstallMethod( Eval,
        "for homalg matrices (HasEvalDualKroneckerMat)",
        [ IsHomalgMatrix and HasEvalDualKroneckerMat ],
        
  function( C )
    local R, RP, A, B;
    
    R := HomalgRing( C );
    
    if ( HasIsCommutative( R ) and not IsCommutative( R ) ) and
       ( HasIsSuperCommutative( R ) and not IsSuperCommutative( R ) ) then
        Info( InfoWarning, 1, "\033[01m\033[5;31;47m",
              "the dual Kronecker product is only defined for (super) commutative rings!",
              "\033[0m" );
    fi;
    
    RP := homalgTable( R );
    
    A :=  EvalDualKroneckerMat( C )[1];
    B :=  EvalDualKroneckerMat( C )[2];
    
    # work around errors in Singular when taking the opposite ring of a ring with ordering lp
    # https://github.com/Singular/Singular/issues/1011
    # fixed in version 4.2.0
    if IsBound(RP!.DualKroneckerMat) and not (
        IsBound( R!.ring ) and
        IsBound( R!.ring!.stream ) and
        IsBound( R!.ring!.stream.cas ) and R!.ring!.stream.cas = "singular" and
        ( not IsBound( R!.ring!.stream.version ) or R!.ring!.stream.version < 4200 ) and
        IsBound( R!.order ) and IsString( R!.order ) and StartsWith( R!.order, "lex" )
    ) then
        
        return RP!.DualKroneckerMat( A, B );
        
    fi;
    
    if HasIsCommutative( R ) and IsCommutative( R ) then
        
        return Eval( KroneckerMat( B, A ) );
        
    else
        
        return Eval(
            TransposedMatrix( Involution(
                KroneckerMat( TransposedMatrix( Involution( B ) ), TransposedMatrix( Involution( A ) ) )
            ) )
        );
        
    fi;
    
end );
##  ]]></Listing>
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="DualKroneckerMat:homalgTable_entry">
##  <ManSection>
##    <Func Arg="A, B" Name="DualKroneckerMat" Label="homalgTable entry"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      Let <M>R :=</M> <C>HomalgRing</C><M>( <A>C</A> )</M> and <M>RP :=</M> <C>homalgTable</C><M>( R )</M>.
##      If the <C>homalgTable</C> component <M>RP</M>!.<C>DualKroneckerMat</C> is bound then
##      the method <Ref Meth="Eval" Label="for matrices created with DualKroneckerMat"/> returns
##      <M>RP</M>!.<C>DualKroneckerMat</C> applied to the content of the attribute
##      <C>EvalDualKroneckerMat</C><M>( <A>C</A> ) = [ <A>A</A>, <A>B</A> ]</M>.
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="Eval:HasEvalMulMat">
##  <ManSection>
##    <Meth Arg="C" Name="Eval" Label="for matrices created with MulMat"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      In case the matrix was created using
##      <Ref Meth="\*" Label="for ring elements and matrices"/>
##      then the filter <C>HasEvalMulMat</C> for <A>C</A> is set to true and the <C>homalgTable</C> function
##      <Ref Meth="MulMat" Label="homalgTable entry"/>
##      will be used to set the attribute <C>Eval</C>.
##    <Listing Type="Code"><![CDATA[
InstallMethod( Eval,
        "for homalg matrices (HasEvalMulMat)",
        [ IsHomalgMatrix and HasEvalMulMat ],
        
  function( C )
    local R, RP, e, a, A;
    
    R := HomalgRing( C );
    
    RP := homalgTable( R );
    
    e :=  EvalMulMat( C );
    
    a := e[1];
    A := e[2];
    
    if IsBound(RP!.MulMat) then
        return RP!.MulMat( a, A );
    fi;
    
    if not IsHomalgInternalMatrixRep( C ) then
        Error( "could not find a procedure called MulMat ",
               "in the homalgTable of the non-internal ring\n" );
    fi;
    
    #=====# can only work for homalg internal matrices #=====#
    
    return a * Eval( A );
    
end );

InstallMethod( Eval,
        "for homalg matrices (HasEvalMulMatRight)",
        [ IsHomalgMatrix and HasEvalMulMatRight ],
        
  function( C )
    local R, RP, e, A, a;
    
    R := HomalgRing( C );
    
    RP := homalgTable( R );
    
    e :=  EvalMulMatRight( C );
    
    A := e[1];
    a := e[2];
    
    if IsBound(RP!.MulMatRight) then
        return RP!.MulMatRight( A, a );
    fi;
    
    if not IsHomalgInternalMatrixRep( C ) then
        Error( "could not find a procedure called MulMatRight ",
               "in the homalgTable of the non-internal ring\n" );
    fi;
    
    #=====# can only work for homalg internal matrices #=====#
    
    return Eval( A ) * a;
    
end );
##  ]]></Listing>
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="MulMat:homalgTable_entry">
##  <ManSection>
##    <Func Arg="a, A" Name="MulMat" Label="homalgTable entry"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      Let <M>R :=</M> <C>HomalgRing</C><M>( <A>C</A> )</M> and <M>RP :=</M> <C>homalgTable</C><M>( R )</M>.
##      If the <C>homalgTable</C> component <M>RP</M>!.<C>MulMat</C> is bound then
##      the method <Ref Meth="Eval" Label="for matrices created with MulMat"/> returns
##      <M>RP</M>!.<C>MulMat</C> applied to the content of the attribute
##      <C>EvalMulMat</C><M>( <A>C</A> ) = [ <A>a</A>, <A>A</A> ]</M>.
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="Eval:HasEvalAddMat">
##  <ManSection>
##    <Meth Arg="C" Name="Eval" Label="for matrices created with AddMat"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      In case the matrix was created using
##      <Ref Meth="\+" Label="for matrices"/>
##      then the filter <C>HasEvalAddMat</C> for <A>C</A> is set to true and the <C>homalgTable</C> function
##      <Ref Meth="AddMat" Label="homalgTable entry"/>
##      will be used to set the attribute <C>Eval</C>.
##    <Listing Type="Code"><![CDATA[
InstallMethod( Eval,
        "for homalg matrices (HasEvalAddMat)",
        [ IsHomalgMatrix and HasEvalAddMat ],
        
  function( C )
    local R, RP, e, A, B;
    
    R := HomalgRing( C );
    
    RP := homalgTable( R );
    
    e :=  EvalAddMat( C );
    
    A := e[1];
    B := e[2];
    
    ResetFilterObj( C, HasEvalAddMat );
    
    ## delete the component which was left over by GAP
    Unbind( C!.EvalAddMat );
    
    if IsBound(RP!.AddMat) then
        return RP!.AddMat( A, B );
    fi;
    
    if not IsHomalgInternalMatrixRep( C ) then
        Error( "could not find a procedure called AddMat ",
               "in the homalgTable of the non-internal ring\n" );
    fi;
    
    #=====# can only work for homalg internal matrices #=====#
    
    return Eval( A ) + Eval( B );
    
end );
##  ]]></Listing>
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="AddMat:homalgTable_entry">
##  <ManSection>
##    <Func Arg="A, B" Name="AddMat" Label="homalgTable entry"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      Let <M>R :=</M> <C>HomalgRing</C><M>( <A>C</A> )</M> and <M>RP :=</M> <C>homalgTable</C><M>( R )</M>.
##      If the <C>homalgTable</C> component <M>RP</M>!.<C>AddMat</C> is bound then
##      the method <Ref Meth="Eval" Label="for matrices created with AddMat"/> returns
##      <M>RP</M>!.<C>AddMat</C> applied to the content of the attribute
##      <C>EvalAddMat</C><M>( <A>C</A> ) = [ <A>A</A>, <A>B</A> ]</M>.
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="Eval:HasEvalSubMat">
##  <ManSection>
##    <Meth Arg="C" Name="Eval" Label="for matrices created with SubMat"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      In case the matrix was created using
##      <Ref Meth="\-" Label="for matrices"/>
##      then the filter <C>HasEvalSubMat</C> for <A>C</A> is set to true and the <C>homalgTable</C> function
##      <Ref Meth="SubMat" Label="homalgTable entry"/>
##      will be used to set the attribute <C>Eval</C>.
##    <Listing Type="Code"><![CDATA[
InstallMethod( Eval,
        "for homalg matrices (HasEvalSubMat)",
        [ IsHomalgMatrix and HasEvalSubMat ],
        
  function( C )
    local R, RP, e, A, B;
    
    R := HomalgRing( C );
    
    RP := homalgTable( R );
    
    e :=  EvalSubMat( C );
    
    A := e[1];
    B := e[2];
    
    ResetFilterObj( C, HasEvalSubMat );
    
    ## delete the component which was left over by GAP
    Unbind( C!.EvalSubMat );
    
    if IsBound(RP!.SubMat) then
        return RP!.SubMat( A, B );
    fi;
    
    if not IsHomalgInternalMatrixRep( C ) then
        Error( "could not find a procedure called SubMat ",
               "in the homalgTable of the non-internal ring\n" );
    fi;
    
    #=====# can only work for homalg internal matrices #=====#
    
    return Eval( A ) - Eval( B );
    
end );
##  ]]></Listing>
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="SubMat:homalgTable_entry">
##  <ManSection>
##    <Func Arg="A, B" Name="SubMat" Label="homalgTable entry"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      Let <M>R :=</M> <C>HomalgRing</C><M>( <A>C</A> )</M> and <M>RP :=</M> <C>homalgTable</C><M>( R )</M>.
##      If the <C>homalgTable</C> component <M>RP</M>!.<C>SubMat</C> is bound then
##      the method <Ref Meth="Eval" Label="for matrices created with SubMat"/> returns
##      <M>RP</M>!.<C>SubMat</C> applied to the content of the attribute
##      <C>EvalSubMat</C><M>( <A>C</A> ) = [ <A>A</A>, <A>B</A> ]</M>.
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="Eval:HasEvalCompose">
##  <ManSection>
##    <Meth Arg="C" Name="Eval" Label="for matrices created with Compose"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      In case the matrix was created using
##      <Ref Meth="\*" Label="for composable matrices"/>
##      then the filter <C>HasEvalCompose</C> for <A>C</A> is set to true and the <C>homalgTable</C> function
##      <Ref Meth="Compose" Label="homalgTable entry"/>
##      will be used to set the attribute <C>Eval</C>.
##    <Listing Type="Code"><![CDATA[
InstallMethod( Eval,
        "for homalg matrices (HasEvalCompose)",
        [ IsHomalgMatrix and HasEvalCompose ],
        
  function( C )
    local R, RP, e, A, B;
    
    R := HomalgRing( C );
    
    RP := homalgTable( R );
    
    e :=  EvalCompose( C );
    
    A := e[1];
    B := e[2];
    
    ResetFilterObj( C, HasEvalCompose );
    
    ## delete the component which was left over by GAP
    Unbind( C!.EvalCompose );
    
    if IsBound(RP!.Compose) then
        return RP!.Compose( A, B );
    fi;
    
    if not IsHomalgInternalMatrixRep( C ) then
        Error( "could not find a procedure called Compose ",
               "in the homalgTable of the non-internal ring\n" );
    fi;
    
    #=====# can only work for homalg internal matrices #=====#
    
    return Eval( A ) * Eval( B );
    
end );
##  ]]></Listing>
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="Compose:homalgTable_entry">
##  <ManSection>
##    <Func Arg="A, B" Name="Compose" Label="homalgTable entry"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      Let <M>R :=</M> <C>HomalgRing</C><M>( <A>C</A> )</M> and <M>RP :=</M> <C>homalgTable</C><M>( R )</M>.
##      If the <C>homalgTable</C> component <M>RP</M>!.<C>Compose</C> is bound then
##      the method <Ref Meth="Eval" Label="for matrices created with Compose"/> returns
##      <M>RP</M>!.<C>Compose</C> applied to the content of the attribute
##      <C>EvalCompose</C><M>( <A>C</A> ) = [ <A>A</A>, <A>B</A> ]</M>.
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="Eval:IsIdentityMatrix">
##  <ManSection>
##    <Meth Arg="C" Name="Eval" Label="for matrices created with HomalgIdentityMatrix"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      In case the matrix <A>C</A> was created using
##      <Ref Meth="HomalgIdentityMatrix" Label="constructor for identity matrices"/>
##      then the filter <C>IsOne</C> for <A>C</A> is set to true and the <C>homalgTable</C> function
##      (&see; <Ref Meth="IdentityMatrix" Label="homalgTable entry"/>)
##      will be used to set the attribute <C>Eval</C>.
##    <Listing Type="Code"><![CDATA[
InstallMethod( Eval,
        "for homalg matrices (IsOne)",
        [ IsHomalgMatrix and IsOne and HasNumberRows and HasNumberColumns ], 10,
        
  function( C )
    local R, id, RP, o, z, zz;
    
    R := HomalgRing( C );
    
    if IsBound( R!.IdentityMatrices ) then
        id := ElmWPObj( R!.IdentityMatrices!.weak_pointers, NumberColumns( C ) );
        if id <> fail then
            R!.IdentityMatrices!.cache_hits := R!.IdentityMatrices!.cache_hits + 1;
            return id;
        fi;
        ## we do not count cache_misses as it is equivalent to counter
    fi;
    
    RP := homalgTable( R );
    
    if IsBound( RP!.IdentityMatrix ) then
        id := RP!.IdentityMatrix( C );
        SetElmWPObj( R!.IdentityMatrices!.weak_pointers, NumberColumns( C ), id );
        R!.IdentityMatrices!.counter := R!.IdentityMatrices!.counter + 1;
        return id;
    fi;
    
    if not IsHomalgInternalMatrixRep( C ) then
        Error( "could not find a procedure called IdentityMatrix ",
               "homalgTable to evaluate a non-internal identity matrix\n" );
    fi;
    
    #=====# can only work for homalg internal matrices #=====#
    
    z := Zero( HomalgRing( C ) );
    o := One( HomalgRing( C ) );
    
    zz := ListWithIdenticalEntries( NumberColumns( C ), z );
    
    id := List( [ 1 .. NumberRows( C ) ],
                function(i)
                  local z;
                  z := ShallowCopy( zz ); z[i] := o; return z;
                end );
    
    id := homalgInternalMatrixHull( id );
    
    SetElmWPObj( R!.IdentityMatrices!.weak_pointers, NumberColumns( C ), id );
    
    return id;
    
end );
##  ]]></Listing>
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="IdentityMatrix:homalgTable_entry">
##  <ManSection>
##    <Func Arg="C" Name="IdentityMatrix" Label="homalgTable entry"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      Let <M>R :=</M> <C>HomalgRing</C><M>( <A>C</A> )</M> and <M>RP :=</M> <C>homalgTable</C><M>( R )</M>.
##      If the <C>homalgTable</C> component <M>RP</M>!.<C>IdentityMatrix</C> is bound then the method
##      <Ref Meth="Eval" Label="for matrices created with HomalgIdentityMatrix"/> returns
##      <M>RP</M>!.<C>IdentityMatrix</C><M>( <A>C</A> )</M>.
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="Eval:IsZeroMatrix">
##  <ManSection>
##    <Meth Arg="C" Name="Eval" Label="for matrices created with HomalgZeroMatrix"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      In case the matrix <A>C</A> was created using
##      <Ref Meth="HomalgZeroMatrix" Label="constructor for zero matrices"/>
##      then the filter <C>IsZeroMatrix</C> for <A>C</A> is set to true and the <C>homalgTable</C> function
##      (&see; <Ref Meth="ZeroMatrix" Label="homalgTable entry"/>)
##      will be used to set the attribute <C>Eval</C>.
##    <Listing Type="Code"><![CDATA[
InstallMethod( Eval,
        "for homalg matrices (IsZero)",
        [ IsHomalgMatrix and IsZero and HasNumberRows and HasNumberColumns ], 40,
        
  function( C )
    local R, RP, z;
    
    R := HomalgRing( C );
    
    RP := homalgTable( R );
    
    if ( NumberRows( C ) = 0 or NumberColumns( C ) = 0 ) and
       not ( IsBound( R!.SafeToEvaluateEmptyMatrices ) and
             R!.SafeToEvaluateEmptyMatrices = true ) then
        Info( InfoWarning, 1, "\033[01m\033[5;31;47m",
              "an empty matrix is about to get evaluated!",
              "\033[0m" );
    fi;
    
    if IsBound( RP!.ZeroMatrix ) then
        return RP!.ZeroMatrix( C );
    fi;
    
    if not IsHomalgInternalMatrixRep( C ) then
        Error( "could not find a procedure called ZeroMatrix ",
               "homalgTable to evaluate a non-internal zero matrix\n" );
    fi;
    
    #=====# can only work for homalg internal matrices #=====#
    
    z := Zero( HomalgRing( C ) );
    
    ## copying the rows saves memory;
    ## we assume that the entries are never modified!!!
    return homalgInternalMatrixHull(
                   ListWithIdenticalEntries( NumberRows( C ),
                           ListWithIdenticalEntries( NumberColumns( C ), z ) ) );
    
end );
##  ]]></Listing>
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="ZeroMatrix:homalgTable_entry">
##  <ManSection>
##    <Func Arg="C" Name="ZeroMatrix" Label="homalgTable entry"/>
##    <Returns>the <C>Eval</C> value of a &homalg; matrix <A>C</A></Returns>
##    <Description>
##      Let <M>R :=</M> <C>HomalgRing</C><M>( <A>C</A> )</M> and <M>RP :=</M> <C>homalgTable</C><M>( R )</M>.
##      If the <C>homalgTable</C> component <M>RP</M>!.<C>ZeroMatrix</C> is bound then the method
##      <Ref Meth="Eval" Label="for matrices created with HomalgZeroMatrix"/> returns
##      <M>RP</M>!.<C>ZeroMatrix</C><M>( <A>C</A> )</M>.
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="NumberRows:homalgTable_entry">
##  <ManSection>
##    <Func Arg="C" Name="NumberRows" Label="homalgTable entry"/>
##    <Returns>a nonnegative integer</Returns>
##    <Description>
##      Let <M>R :=</M> <C>HomalgRing</C><M>( <A>C</A> )</M> and <M>RP :=</M> <C>homalgTable</C><M>( R )</M>.
##      If the <C>homalgTable</C> component <M>RP</M>!.<C>NumberRows</C> is bound then the standard method
##      for the attribute <Ref Attr="NumberRows"/> shown below returns
##      <M>RP</M>!.<C>NumberRows</C><M>( <A>C</A> )</M>.
##    <Listing Type="Code"><![CDATA[
InstallMethod( NumberRows,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( C )
    local R, RP;
    
    R := HomalgRing( C );
    
    RP := homalgTable( R );
    
    if IsBound(RP!.NumberRows) then
        return RP!.NumberRows( C );
    fi;
    
    if not IsHomalgInternalMatrixRep( C ) then
        Error( "could not find a procedure called NumberRows ",
               "in the homalgTable of the non-internal ring\n" );
    fi;
    
    #=====# can only work for homalg internal matrices #=====#
    
    return Length( Eval( C )!.matrix );
    
end );
##  ]]></Listing>
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="NumberColumns:homalgTable_entry">
##  <ManSection>
##    <Func Arg="C" Name="NumberColumns" Label="homalgTable entry"/>
##    <Returns>a nonnegative integer</Returns>
##    <Description>
##      Let <M>R :=</M> <C>HomalgRing</C><M>( <A>C</A> )</M> and <M>RP :=</M> <C>homalgTable</C><M>( R )</M>.
##      If the <C>homalgTable</C> component <M>RP</M>!.<C>NumberColumns</C> is bound then the standard method
##      for the attribute <Ref Attr="NumberColumns"/> shown below returns
##      <M>RP</M>!.<C>NumberColumns</C><M>( <A>C</A> )</M>.
##    <Listing Type="Code"><![CDATA[
InstallMethod( NumberColumns,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( C )
    local R, RP;
    
    R := HomalgRing( C );
    
    RP := homalgTable( R );
    
    if IsBound(RP!.NumberColumns) then
        return RP!.NumberColumns( C );
    fi;
    
    if not IsHomalgInternalMatrixRep( C ) then
        Error( "could not find a procedure called NumberColumns ",
               "in the homalgTable of the non-internal ring\n" );
    fi;
    
    #=====# can only work for homalg internal matrices #=====#
    
    return Length( Eval( C )!.matrix[ 1 ] );
    
end );
##  ]]></Listing>
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="Determinant:homalgTable_entry">
##  <ManSection>
##    <Func Arg="C" Name="Determinant" Label="homalgTable entry"/>
##    <Returns>a ring element</Returns>
##    <Description>
##      Let <M>R :=</M> <C>HomalgRing</C><M>( <A>C</A> )</M> and <M>RP :=</M> <C>homalgTable</C><M>( R )</M>.
##      If the <C>homalgTable</C> component <M>RP</M>!.<C>Determinant</C> is bound then the standard method
##      for the attribute <Ref Attr="DeterminantMat"/> shown below returns
##      <M>RP</M>!.<C>Determinant</C><M>( <A>C</A> )</M>.
##    <Listing Type="Code"><![CDATA[
InstallMethod( DeterminantMat,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( C )
    local R, RP;
    
    R := HomalgRing( C );
    
    RP := homalgTable( R );
    
    if NumberRows( C ) <> NumberColumns( C ) then
        Error( "the matrix is not a square matrix\n" );
    fi;
    
    if IsEmptyMatrix( C ) then
        return One( R );
    elif IsZero( C ) then
        return Zero( R );
    fi;
    
    if IsBound(RP!.Determinant) then
        return RingElementConstructor( R )( RP!.Determinant( C ), R );
    fi;
    
    if not IsHomalgInternalMatrixRep( C ) then
        Error( "could not find a procedure called Determinant ",
               "in the homalgTable of the non-internal ring\n" );
    fi;
    
    #=====# can only work for homalg internal matrices #=====#
    
    return Determinant( Eval( C )!.matrix );
    
end );

##
InstallMethod( Determinant,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( C )
    
    return DeterminantMat( C );
    
end );
##  ]]></Listing>
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

####################################
#
# methods for operations (you probably want to replace for an external CAS):
#
####################################

##
InstallMethod( IsUnit,
        "for homalg ring elements",
        [ IsHomalgRing, IsRingElement ], 100,
        
  function( R, r )
    local RP;
    
    if HasIsZero( r ) and IsZero( r ) then
        return false;
    elif HasIsOne( r ) and IsOne( r ) then
        return true;
    fi;
    
    return not IsBool( LeftInverse( HomalgMatrix( [ r ], 1, 1, R ) ) );
    
end );

##
InstallMethod( IsUnit,
        "for homalg ring elements",
        [ IsHomalgRing, IsHomalgRingElement ], 100,
        
  function( R, r )
    local RP;
    
    if HasIsZero( r ) and IsZero( r ) then
        return false;
    elif HasIsOne( r ) and IsOne( r ) then
        return true;
    elif HasIsMinusOne( r ) and IsMinusOne( r ) then
        return true;
    fi;
    
    RP := homalgTable( R );
    
    if IsBound(RP!.IsUnit) then
        return RP!.IsUnit( R, r );
    fi;
    
    #=====# the fallback method #=====#
    
    return not IsBool( LeftInverse( HomalgMatrix( [ r ], 1, 1, R ) ) );
    
end );

##
InstallMethod( IsUnit,
        "for homalg ring elements",
        [ IsHomalgInternalRingRep, IsRingElement ], 100,
        
  function( R, r )
    
    return IsUnit( R!.ring, r );
    
end );

##
InstallMethod( IsUnit,
        "for homalg ring elements",
        [ IsHomalgRingElement ],
        
  function( r )
    
    if HasIsZero( r ) and IsZero( r ) then
        return false;
    elif HasIsOne( r ) and IsOne( r ) then
        return true;
    elif HasIsMinusOne( r ) and IsMinusOne( r ) then
        return true;
    fi;
    
    if not IsBound( r!.IsUnit ) then
        r!.IsUnit := IsUnit( HomalgRing( r ), r );
    fi;
    
    return r!.IsUnit;
    
end );

##  <#GAPDoc Label="ZeroRows:homalgTable_entry">
##  <ManSection>
##    <Func Arg="C" Name="ZeroRows" Label="homalgTable entry"/>
##    <Returns>a (possibly empty) list of positive integers</Returns>
##    <Description>
##      Let <M>R :=</M> <C>HomalgRing</C><M>( <A>C</A> )</M> and <M>RP :=</M> <C>homalgTable</C><M>( R )</M>.
##      If the <C>homalgTable</C> component <M>RP</M>!.<C>ZeroRows</C> is bound then the standard method
##      of the attribute <Ref Attr="ZeroRows"/> shown below returns
##      <M>RP</M>!.<C>ZeroRows</C><M>( <A>C</A> )</M>.
##    <Listing Type="Code"><![CDATA[
InstallMethod( ZeroRows,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( C )
    local R, RP, z;
    
    R := HomalgRing( C );
    
    RP := homalgTable( R );
    
    if IsBound(RP!.ZeroRows) then
        return RP!.ZeroRows( C );
    fi;
    
    #=====# the fallback method #=====#
    
    z := HomalgZeroMatrix( 1, NumberColumns( C ), R );
    
    return Filtered( [ 1 .. NumberRows( C ) ], a -> CertainRows( C, [ a ] ) = z );
    
end );
##  ]]></Listing>
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##  <#GAPDoc Label="ZeroColumns:homalgTable_entry">
##  <ManSection>
##    <Func Arg="C" Name="ZeroColumns" Label="homalgTable entry"/>
##    <Returns>a (possibly empty) list of positive integers</Returns>
##    <Description>
##      Let <M>R :=</M> <C>HomalgRing</C><M>( <A>C</A> )</M> and <M>RP :=</M> <C>homalgTable</C><M>( R )</M>.
##      If the <C>homalgTable</C> component <M>RP</M>!.<C>ZeroColumns</C> is bound then the standard method
##      of the attribute <Ref Attr="ZeroColumns"/> shown below returns
##      <M>RP</M>!.<C>ZeroColumns</C><M>( <A>C</A> )</M>.
##    <Listing Type="Code"><![CDATA[
InstallMethod( ZeroColumns,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( C )
    local R, RP, z;
    
    R := HomalgRing( C );
    
    RP := homalgTable( R );
    
    if IsBound(RP!.ZeroColumns) then
        return RP!.ZeroColumns( C );
    fi;
    
    #=====# the fallback method #=====#
    
    z := HomalgZeroMatrix( NumberRows( C ), 1, R );
    
    return Filtered( [ 1 .. NumberColumns( C ) ], a -> CertainColumns( C, [ a ] ) = z );
    
end );
##  ]]></Listing>
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##
InstallMethod( GetRidOfObsoleteRows,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( C )
    local R, RP, M;
    
    R := HomalgRing( C );
    
    RP := homalgTable( R );
    
--> --------------------

--> maximum size reached

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

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

                                                                                                                                                                                                                                                                                                                                                                                                     


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