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

Quelle  HomalgMatrix.gi   Sprache: unbekannt

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

####################################
#
# representations:
#
####################################

##
DeclareRepresentation( "IshomalgInternalMatrixHullRep",
        IsInternalMatrixHull,
        [ ] );

##  <#GAPDoc Label="IsHomalgInternalMatrixRep">
##  <ManSection>
##    <Filt Type="Representation" Arg="A" Name="IsHomalgInternalMatrixRep"/>
##    <Returns><C>true</C> or <C>false</C></Returns>
##    <Description>
##      The internal representation of &homalg; matrices. <P/>
##      (It is a representation of the &GAP; category <Ref Filt="IsHomalgMatrix"/>.)
##    </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareRepresentation( "IsHomalgInternalMatrixRep",
        IsHomalgMatrix,
        [ ] );

####################################
#
# families and types:
#
####################################

# two new family:
BindGlobal( "TheFamilyOfInternalMatrixHulls",
        NewFamily( "TheFamilyOfInternalMatrixHulls" ) );

BindGlobal( "TheFamilyOfHomalgMatrices",
        NewFamily( "TheFamilyOfHomalgMatrices" ) );

# two new types:
BindGlobal( "TheTypeInternalMatrixHull",
        NewType( TheFamilyOfInternalMatrixHulls,
                IshomalgInternalMatrixHullRep ) );

BindGlobal( "TheTypeHomalgInternalMatrix",
        NewType( TheFamilyOfHomalgMatrices,
                IsHomalgInternalMatrixRep ) );

####################################
#
# compatibility code for the new
# IsMatrixObj interface
#
####################################

InstallMethod( Length,
        [ IsHomalgMatrix ], 0,

  NumberColumns );

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

##-----------------------------------------------------------------------------
#
# put all methods to trace errors in LIMAT.gi with the very high priority 10001
#
##-----------------------------------------------------------------------------

##
InstallMethod( Rank,
        "for homalg matrices",
        [ IsInternalMatrixHull ],
        
  function( M )
    
    return Rank( M!.matrix );
    
end );

##  <#GAPDoc Label="HomalgRing:matrix">
##  <ManSection>
##    <Oper Arg="mat" Name="HomalgRing" Label="for matrices"/>
##    <Returns>a &homalg; ring</Returns>
##    <Description>
##      The &homalg; ring of the &homalg; matrix <A>mat</A>.
##      <Example><![CDATA[
##  gap> zz := HomalgRingOfIntegers( );
##  Z
##  gap> d := HomalgDiagonalMatrix( [ 2 .. 4 ], zz );
##  <An unevaluated diagonal 3 x 3 matrix over an internal ring>
##  gap> R := HomalgRing( d );
##  Z
##  gap> IsIdenticalObj( R, zz );
##  true
##  ]]></Example>
##    </Description>
##  </ManSection>
##  <#/GAPDoc>
##
InstallMethod( HomalgRing,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( M )
    
    return M!.ring;
    
end );

##
InstallMethod( BaseDomain,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  HomalgRing );

##
InstallMethod( BlindlyCopyMatrixProperties, ## under construction
        "for homalg matrices",
        [ IsHomalgMatrix, IsHomalgMatrix ],
        
  function( S, T )
    
    ## if the new ring only interprets the 1x1 submatrices as elements
    ## then it is safe to at least copy the following attributes
    
    if HasNumberRows( S ) then
        SetNumberRows( T, NumberRows( S ) );
    fi;
    
    if HasNumberColumns( S ) then
        SetNumberColumns( T, NumberColumns( S ) );
    fi;
    
end );

##
InstallMethod( ShallowCopy,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( M )
    local R, RP, MM;
    
    R := HomalgRing( M );
    RP := homalgTable( R );
    
    if IsBound(RP!.ShallowCopy) then
        
        MM := HomalgMatrixWithAttributes( [
                      Eval, RP!.ShallowCopy( M ),
                      NumberRows, NumberRows( M ),
                      NumberColumns, NumberColumns( M ),
                      ], R );
        
        MatchPropertiesAndAttributes( M, MM,
                LIMAT.intrinsic_properties,
                LIMAT.intrinsic_attributes,
                LIMAT.intrinsic_components,
                LIMAT.intrinsic_attributes_do_not_check_their_equality
                );
        
        return MM;
    fi;
    
    ## we have no other choice
    return M;
    
end );

##
InstallMethod( MutableCopyMat,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( M )
    local R, RP, MM;
    
    R := HomalgRing( M );
    RP := homalgTable( R );
    
    if IsBound(RP!.ShallowCopy) then
        
        MM := HomalgMatrixWithAttributes( [
                      Eval, RP!.ShallowCopy( M ),
                      NumberRows, NumberRows( M ),
                      NumberColumns, NumberColumns( M ),
                      ], R );
        
        SetIsMutableMatrix( MM, true );
        
        return MM;
    fi;
    
    ## we have no other choice
    TryNextMethod( );
    
end );

##
InstallMethod( ShallowCopy,
        "for homalg internal matrices",
        [ IsHomalgInternalMatrixRep ],
        
  function( M )
    local R, RP, MM;
    
    R := HomalgRing( M );
    RP := homalgTable( R );
    
    if IsBound(RP!.ShallowCopy) then
        
        MM := HomalgMatrixWithAttributes( [
                      Eval, RP!.ShallowCopy( M ),
                      NumberRows, NumberRows( M ),
                      NumberColumns, NumberColumns( M ),
                      ], R );
        
        if not IsIdenticalObj( Eval( M ), Eval( MM ) ) then
            
            MatchPropertiesAndAttributes( M, MM,
                    LIMAT.intrinsic_properties,
                    LIMAT.intrinsic_attributes,
                    LIMAT.intrinsic_components,
                    LIMAT.intrinsic_attributes_do_not_check_their_equality
                    );
            
            return MM;
            
        fi;
    fi;
    
    if not IsInternalMatrixHull( Eval( M ) ) then
        TryNextMethod( );
    fi;
    
    return HomalgMatrix( One( R ) * Eval( M )!.matrix, NumberRows( M ), NumberColumns( M ), R );
    
end );

##
InstallMethod( MutableCopyMat,
        "for homalg internal matrices",
        [ IsHomalgInternalMatrixRep ],
        
  function( M )
    local R, RP, MM;
    
    R := HomalgRing( M );
    RP := homalgTable( R );
    
    if IsBound(RP!.ShallowCopy) then
        
        MM := HomalgMatrixWithAttributes( [
                      Eval, RP!.ShallowCopy( M ),
                      NumberRows, NumberRows( M ),
                      NumberColumns, NumberColumns( M ),
                      ], R );
        
        if not IsIdenticalObj( Eval( M ), Eval( MM ) ) then
            
            SetIsMutableMatrix( MM, true );
            
            return MM;
            
        fi;
    fi;
    
    if not IsInternalMatrixHull( Eval( M ) ) then
        TryNextMethod( );
    fi;
    
    MM := HomalgMatrix( One( R ) * Eval( M )!.matrix, NumberRows( M ), NumberColumns( M ), R );
    
    SetIsMutableMatrix( MM, true );
    
    return MM;
    
end );

##
InstallMethod( ShallowCopy,
        "for homalg matrices",
        [ IsHomalgMatrix and IsOne ],
        
  function( M )
    
    return HomalgIdentityMatrix( NumberRows( M ), HomalgRing( M ) );
    
end );

##
InstallMethod( MutableCopyMat,
        "for homalg matrices",
        [ IsHomalgMatrix and IsOne ],
        
  function( M )
    
    ## do not use HomalgIdentityMatrix since
    ## we might want to alter the result
    return HomalgInitialIdentityMatrix( NumberRows( M ), HomalgRing( M ) );
    
end );

##
InstallMethod( ShallowCopy,
        "for homalg matrices",
        [ IsHomalgMatrix and IsZero ],
        
  function( M )
    
    return HomalgZeroMatrix( NumberRows( M ), NumberColumns( M ), HomalgRing( M ) );
    
end );

##
InstallMethod( MutableCopyMat,
        "for homalg matrices",
        [ IsHomalgMatrix and IsZero ],
        
  function( M )
    
    ## do not use HomalgZeroMatrix since
    ## we might want to alter the result
    return HomalgInitialMatrix( NumberRows( M ), NumberColumns( M ), HomalgRing( M ) );
    
end );

##
InstallMethod( SetConvertHomalgMatrixViaSparseString,
        "for homalg matrices",
        [ IsHomalgMatrix, IsBool ],
        
  function( M, b )
    
    M!.ConvertHomalgMatrixViaSparseString := b;
    
end );

##
InstallMethod( SetConvertHomalgMatrixViaFile,
        "for homalg matrices",
        [ IsHomalgMatrix, IsBool ],
        
  function( M, b )
    
    M!.ConvertHomalgMatrixViaFile := b;
    
end );

##
InstallMethod( SetMatElm,
        "for homalg matrices",
        [ IsHomalgMatrix and IsMutable, IsPosInt, IsPosInt, IsString, IsHomalgRing ],
        
  function( M, r, c, s, R )
    
    SetMatElm( M, r, c, s / R, R );
    
end );

##
InstallMethod( SetMatElm,
        "for homalg internal matrices",
        [ IsHomalgInternalMatrixRep and IsMutable, IsPosInt, IsPosInt, IsString, IsHomalgInternalRingRep ],
        
  function( M, r, c, s, R )
    
    SetMatElm( M, r, c, One( R ) * EvalString( s ), R );
    
end );

##
InstallMethod( SetMatElm,
        "for homalg matrices",
        [ IsHomalgMatrix, IsPosInt, IsPosInt, IsString ],
        
  function( M, r, c, s )
    
    Error( "the homalg matrix is write-protected\n" );
    
end );

##
InstallMethod( SetMatElm,
        "for homalg matrices",
        [ IsHomalgMatrix and IsMutable, IsPosInt, IsPosInt, IsString ],
        
  function( M, r, c, s )
    
    SetMatElm( M, r, c, s, HomalgRing( M ) );
    
end );

##
InstallMethod( SetMatElm,
        "for homalg internal matrices",
        [ IsHomalgInternalMatrixRep and IsMutable, IsPosInt, IsPosInt, IsRingElement, IsHomalgInternalRingRep ],
        
  function( M, r, c, a, R )
    
    if not IsInternalMatrixHull( Eval( M ) ) then
        TryNextMethod( );
    fi;
    
    Eval( M )!.matrix[r][c] := One( R ) * a;
    
end );

##
InstallMethod( SetMatElm,
        "for homalg matrices",
        [ IsHomalgMatrix, IsPosInt, IsPosInt, IsRingElement ],
        
  function( M, r, c, a )
    
    Error( "the homalg matrix is write-protected\n" );
    
end );

##
InstallMethod( SetMatElm,
        "for homalg matrices",
        [ IsHomalgMatrix and IsMutable, IsPosInt, IsPosInt, IsRingElement ],
        
  function( M, r, c, a )
    
    SetMatElm( M, r, c, a, HomalgRing( M ) );
    
end );

##
InstallMethod( AddToMatElm,
        "for homalg matrices",
        [ IsHomalgMatrix, IsPosInt, IsPosInt, IsRingElement ],
        
  function( M, r, c, a )
    
    Error( "the homalg matrix is write-protected\n" );
    
end );

##
InstallMethod( AddToMatElm,
        "for homalg matrices",
        [ IsHomalgMatrix and IsMutable, IsPosInt, IsPosInt, IsRingElement, IsHomalgRing ],
        
  function( M, r, c, a, R )
    
    SetMatElm( M, r, c, a + MatElm( M, r, c, R ), R );
    
end );

##
InstallMethod( AddToMatElm,
        "for homalg matrices",
        [ IsHomalgMatrix and IsMutable, IsPosInt, IsPosInt, IsRingElement ],
        
  function( M, r, c, a )
    
    AddToMatElm( M, r, c, a, HomalgRing( M ) );
    
end );

##
InstallMethod( MatElmAsString,
        "for homalg internal matrices",
        [ IsHomalgInternalMatrixRep, IsPosInt, IsPosInt, IsHomalgInternalRingRep ],
        
  function( M, r, c, R )
    
    return String( M[ r, c ] );
    
end );

##
InstallMethod( MatElmAsString,
        "for homalg matrices",
        [ IsHomalgMatrix, IsPosInt, IsPosInt ],
        
  function( M, r, c )
    
    return MatElmAsString( M, r, c, HomalgRing( M ) );
    
end );

##
InstallMethod( MatElm,
        "for homalg internal matrices",
        [ IsHomalgInternalMatrixRep, IsPosInt, IsPosInt, IsHomalgInternalRingRep ],
        
  function( M, r, c, R )
    
    if IsInternalMatrixHull( Eval( M ) ) then
        return Eval( M )!.matrix[r][c];
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( MatElm,
        "for homalg matrices",
        [ IsHomalgMatrix, IsPosInt, IsPosInt ],
        
  function( M, r, c )
    
    return MatElm( M, r, c, HomalgRing( M ) );
    
end );

if not CompareVersionNumbers( GAPInfo.Version, "4.10" ) then

## copied from gap-4.10.2/lib/matobj.gi

# Install fallback methods for m[i,j] which delegate MatElm resp. SetMatElm,
# for old MatrixObj implementation which don't provide them. We lower the rank
# so that these are only used as a last resort.
InstallMethod( \[\], "for a matrix object and two positions",
  [ IsMatrixObj, IsPosInt, IsPosInt ],
  -RankFilter(IsMatrixObj),
  function( m, row, col )
    return MatElm( m, row, col );
end );


InstallMethod( \[\]\:\=, "for a matrix object, two positions, and an object",
  [ IsMatrixObj and IsMutable, IsPosInt, IsPosInt, IsObject ],
  -RankFilter(IsMatrixObj),
  function( m, row, col, obj )
    SetMatElm( m, row, col, obj );
end );

fi;

##
InstallMethod( GetListOfMatrixAsString,
        "for matrices",
        [ IsList ],
        
  function( M )
    
    M := List( M, row -> List( row, String ) );
    
    M := List( M, JoinStringsWithSeparator );
    
    M := JoinStringsWithSeparator( M );
    
    return Concatenation( "[", M, "]" );
    
end );

##
InstallMethod( GetListListOfStringsOfMatrix,
        "for matrices and a homalg internal ring",
        [ IsList, IsHomalgInternalRingRep ],
        
  function( M, R )
    local c, d, z;
    
    if not ForAll( M, IsList ) then
        TryNextMethod( );
    fi;
    
    if not HasCharacteristic( R ) then
        Error( "characteristic not set\n" );
    fi;
    
    c := Characteristic( R );
    
    if c = 0 then
        return List( M, a -> List( a, String ) );
    elif IsPrime( c ) then
        if HasDegreeOverPrimeField( R ) and DegreeOverPrimeField( R ) > 1 then
            d := DegreeOverPrimeField( R );
            z := R!.NameOfPrimitiveElement;
            return List( M, a -> List( a, b -> FFEToString( b, c, d, z ) ) );
        fi;
        
        return List( M, a -> List( a, b -> String( IntFFE( b ) ) ) );
    fi;
    
    return List( M, a -> List( a, b -> String( b![1] ) ) );
    
end );

##
InstallMethod( GetListListOfStringsOfHomalgMatrix,
        "for homalg internal matrices",
        [ IsHomalgInternalMatrixRep, IsHomalgInternalRingRep ],
        
  function( M, R )
    
    if not IsInternalMatrixHull( Eval( M ) ) then
        TryNextMethod( );
    fi;
    
    return GetListListOfStringsOfMatrix( Eval( M )!.matrix, R );
    
end );

##
InstallMethod( GetListOfHomalgMatrixAsString,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( M )
    
    return GetListOfHomalgMatrixAsString( M, HomalgRing( M ) );
    
end );

##
InstallMethod( GetListOfHomalgMatrixAsString,
        "for homalg matrices",
        [ IsHomalgMatrix, IsHomalgRing ],
        
  function( M, R )
    local c, s;
    
    c := NumberColumns( M );
    
    s := List( [ 1 .. NumberRows( M ) ], i -> List( [ 1 .. c ], j -> MatElmAsString( M, i, j ) ) );
    
    s := JoinStringsWithSeparator( Concatenation( s ) );
    
    return Concatenation( "[", s, "]" );
    
end );

##
InstallMethod( GetListOfHomalgMatrixAsString,
        "for homalg internal matrices",
        [ IsHomalgInternalMatrixRep, IsHomalgInternalRingRep ],
        
  function( M, R )
    local s, m;
    
    if not IsInternalMatrixHull( Eval( M ) ) then
        TryNextMethod( );
    fi;
    
    s := Eval( M )!.matrix;
    
    if HasCharacteristic( R ) then
        m := Characteristic( R );
        if m > 0 and not HasCoefficientsRing( R ) then ## FIXME: we can only deal with Z/mZ and GF(p): m = Size( R ) !!!
            if IsPrime( m ) then
                s := List( s, a -> List( a, IntFFE ) );
            else
                s := List( s, a -> List( a, b -> b![1] ) );
            fi;
        fi;
    fi;
    
    s := String( Concatenation( s ) );
    
    RemoveCharacters( s, "\\\n " );
    
    return s;
    
end );

##
InstallMethod( GetListListOfHomalgMatrixAsString,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( M )
    
    return GetListListOfHomalgMatrixAsString( M, HomalgRing( M ) );
    
end );

##
InstallMethod( GetListListOfHomalgMatrixAsString,
        "for homalg matrices",
        [ IsHomalgMatrix, IsHomalgRing ],
        
  function( M, R )
    local c, s;
    
    c := NumberColumns( M );
    
    s := List( [ 1 .. NumberRows( M ) ], i -> List( [ 1 .. c ], j -> MatElmAsString( M, i, j ) ) );
    
    s := JoinStringsWithSeparator( List( s, JoinStringsWithSeparator ), "],[" );
    
    return Concatenation( "[[", s, "]]" );
    
end );

##
InstallMethod( GetListListOfHomalgMatrixAsString,
        "for homalg internal matrices",
        [ IsHomalgInternalMatrixRep, IsHomalgInternalRingRep ],
        
  function( M, R )
    local s;
    
    s := GetListListOfStringsOfHomalgMatrix( M, R );
    
    s := List( List( s, JoinStringsWithSeparator ), r -> Concatenation( "[", r, "]" ) );
    
    s := JoinStringsWithSeparator( s );
    
    return Concatenation( "[", s, "]" );
    
end );

##
InstallMethod( GetSparseListOfHomalgMatrixAsString,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( M )
    
    return GetSparseListOfHomalgMatrixAsString( M, HomalgRing( M ) );
    
end );

##
InstallMethod( GetSparseListOfHomalgMatrixAsString,
        "for homalg matrices",
        [ IsHomalgMatrix, IsHomalgRing ],
        
  function( M, R )
    local c, s, i, j, e;
    
    c := NumberColumns( M );
    
    s := [ ];
    
    for i in [ 1 .. NumberRows( M ) ] do
        for j in [ 1 .. c ] do
            e := M[ i, j ];
            if not IsZero( e ) then
                Add( s, [ String( i ), String( j ), String( e ) ] );
            fi;
        od;
    od;
    
    s := JoinStringsWithSeparator( List( s, JoinStringsWithSeparator ), "],[" );
    
    return Concatenation( "[[", s, "]]" );
    
end );

##
InstallMethod( GetSparseListOfHomalgMatrixAsString,
        "for homalg internal matrices",
        [ IsHomalgInternalMatrixRep, IsHomalgInternalRingRep ],
        
  function( M, R )
    local s, m, r, c, z;
    
    if not IsInternalMatrixHull( Eval( M ) ) then
        TryNextMethod( );
    fi;
    
    s := Eval( M )!.matrix;
    
    if HasCharacteristic( R ) then
        m := Characteristic( R );
        if m > 0 and not HasCoefficientsRing( R ) then ## FIXME: we can only deal with Z/mZ and GF(p): m = Size( R ) !!!
            if IsPrime( m ) then
                s := List( s, a -> List( a, IntFFE ) );
            else
                s := List( s, a -> List( a, b -> b![1] ) );
            fi;
        fi;
    fi;
    
    r := NumberRows( M );
    c := NumberColumns( M );
    z := Zero( R );
    
    s := List( [ 1 .. r ], a -> Filtered( List( [ 1 .. c ], function( b ) if s[a][b] <> z then return [ a, b, s[a][b] ]; else return 0; fi; end ), x -> x <> 0 ) );
    
    s := Concatenation( s );
    
    s := String( s );
    
    RemoveCharacters( s, "\\\n " );
    
    return s;
    
end );

##
InstallMethod( EntriesOfHomalgMatrixAsListList,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( M )
    local cols;
    
    cols := [ 1 .. NumberColumns( M ) ];
    
    return List( [ 1 .. NumberRows( M ) ], r -> List( cols, c -> M[ r, c ] ) );
    
end );

##
InstallMethod( EntriesOfHomalgMatrixAsListList,
        "for homalg matrices",
        [ IsHomalgMatrix and IsHomalgInternalMatrixRep ],
        
  function( M )
    local mat;
    
    if IsEmptyMatrix( M ) then
        TryNextMethod( );
    fi;
    
    mat := Eval( M );
    
    if not IshomalgInternalMatrixHullRep( mat ) then
        TryNextMethod( );
    fi;
    
    mat := mat!.matrix;
    
    if not IsList( mat ) then
        TryNextMethod( );
    fi;
    
    return mat;
    
end );

##
InstallMethod( EntriesOfHomalgMatrix,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( M )
    
    return Flat( EntriesOfHomalgMatrixAsListList( M ) );
    
end );

##
InstallMethod( EntriesOfHomalgRowVector,
        "for a homalg row vector",
        [ IsHomalgMatrix ],
        
  function( M )
    
    Assert( 0, NumberRows( M ) = 1 );
    
    return EntriesOfHomalgMatrix( M );
    
end );

##
InstallMethod( EntriesOfHomalgColumnVector,
        "for a homalg column vector",
        [ IsHomalgMatrix ],
        
  function( M )
    
    Assert( 0, NumberColumns( M ) = 1 );
    
    return EntriesOfHomalgMatrix( M );
    
end );

##
InstallMethod( GetUnitPosition,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( M )
    
    return GetUnitPosition( M, [ ] );
    
end );

##
InstallMethod( GetCleanRowsPositions,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( M )
    
    return GetCleanRowsPositions( M, [ 1 .. NumberColumns( M ) ] );
    
end );

##
InstallMethod( GetColumnIndependentUnitPositions,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( M )
    
    return GetColumnIndependentUnitPositions( M, [ ] );
    
end );

##
InstallMethod( GetRowIndependentUnitPositions,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( M )
    
    return GetRowIndependentUnitPositions( M, [ ] );
    
end );

##
InstallMethod( AreComparableMatrices,
        "for homalg matrices",
        [ IsHomalgMatrix, IsHomalgMatrix ],
        
  function( M1, M2 )
    
    if HasNumberRows( M1 ) or HasNumberRows( M2 ) then ## trigger as few as possible operations
        return IsIdenticalObj( HomalgRing( M1 ), HomalgRing( M2 ) )
               and NumberRows( M1 ) = NumberRows( M2 ) and NumberColumns( M1 ) = NumberColumns( M2 );
    else ## no other choice
        return IsIdenticalObj( HomalgRing( M1 ), HomalgRing( M2 ) )
               and NumberColumns( M1 ) = NumberColumns( M2 ) and NumberRows( M1 ) = NumberRows( M2 );
    fi;
    
end );

##
InstallMethod( \=,
        "for internal matrix hulls",
        [ IsInternalMatrixHull, IsInternalMatrixHull ],
        
  function( M1, M2 )
    
    if M1!.matrix = M2!.matrix then
        return true;
    fi;
    
    return false;
    
end );

##  <#GAPDoc Label="EQ:matrix">
##  <ManSection>
##    <Oper Arg="A, B" Name="\=" Label="for matrices"/>
##    <Returns><C>true</C> or <C>false</C></Returns>
##    <Description>
##      Check if the &homalg; matrices <A>A</A> and <A>B</A> are equal (enter: <A>A</A> <C>=</C> <A>B</A>;),
##      taking possible ring relations into account.<P/>
##      (for the installed standard method see <Ref Meth="AreEqualMatrices" Label="homalgTable entry"/>)
##      <Example><![CDATA[
##  gap> zz := HomalgRingOfIntegers( );
##  Z
##  gap> A := HomalgMatrix( "[ 1 ]", zz );
##  <A 1 x 1 matrix over an internal ring>
##  gap> B := HomalgMatrix( "[ 3 ]", zz );
##  <A 1 x 1 matrix over an internal ring>
##  gap> Z2 := zz / 2;
##  Z/( 2 )
##  gap> A := Z2 * A;
##  <A 1 x 1 matrix over a residue class ring>
##  gap> B := Z2 * B;
##  <A 1 x 1 matrix over a residue class ring>
##  gap> Display( A );
##  [ [  1 ] ]
##  
##  modulo [ 2 ]
##  gap> Display( B );
##  [ [  3 ] ]
##  
##  modulo [ 2 ]
##  gap> A = B;
##  true
##  ]]></Example>
##    </Description>
##  </ManSection>
##  <#/GAPDoc>
##
InstallMethod( \=,
        "for homalg comparable matrices",
        [ IsHomalgMatrix, IsHomalgMatrix ], 10001,
        
  function( M1, M2 )
    
    if not AreComparableMatrices( M1, M2 ) then
        return false;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( \=,
        "for homalg comparable internal matrices",
        [ IsHomalgInternalMatrixRep, IsHomalgInternalMatrixRep ],
        
  function( M1, M2 )
    local RP;
    
    RP := homalgTable( HomalgRing( M1 ) );
    
    if IsBound( RP!.AreEqualMatrices ) then
        
        if RP!.AreEqualMatrices( M1, M2 ) then
            
            ## do not touch mutable matrices
            if not ( IsMutable( M1 ) or IsMutable( M2 ) ) then
                MatchPropertiesAndAttributes( M1, M2,
                        LIMAT.intrinsic_properties,
                        LIMAT.intrinsic_attributes,
                        LIMAT.intrinsic_components,
                        LIMAT.intrinsic_attributes_do_not_check_their_equality
                        );
            fi;
            
            return true;
            
        fi;
        
    elif Eval( M1 ) = Eval( M2 ) then
    
        ## do not touch mutable matrices
        if not ( IsMutable( M1 ) or IsMutable( M2 ) ) then
            MatchPropertiesAndAttributes( M1, M2,
                    LIMAT.intrinsic_properties,
                    LIMAT.intrinsic_attributes,
                    LIMAT.intrinsic_components,
                    LIMAT.intrinsic_attributes_do_not_check_their_equality
                    );
        fi;
        
        return true;
    fi;
    
    return false;
    
end );

##
InstallMethod( ZeroMutable,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( M )
    
    return HomalgZeroMatrix( NumberRows( M ), NumberColumns( M ), HomalgRing( M ) );
    
end );

##  <#GAPDoc Label="Involution">
##  <ManSection>
##    <Meth Arg="M" Name="Involution" Label="for matrices"/>
##    <Returns>a &homalg; matrix</Returns>
##    <Description>
##      The twisted transpose of the &homalg; matrix <A>M</A>. If the underlying ring is commutative, the twist is the identity.<P/>
##      (for the installed standard method see <Ref Meth="Eval" Label="for matrices created with Involution"/>)
##    </Description>
##  </ManSection>
##  <#/GAPDoc>
##
InstallMethod( Involution,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( M )
    local C;
    
    C := HomalgMatrixWithAttributes( [
                 EvalInvolution, M,
                 NumberRows, NumberColumns( M ),
                 NumberColumns, NumberRows( M ),
                 ], HomalgRing( M ) );
    
    SetItsInvolution( M, C );
    SetItsInvolution( C, M );
    
    return C;
    
end );

##
InstallMethod( Involution,
        "for homalg matrices",
        [ IsHomalgMatrix and HasItsInvolution ],
        
  function( M )
    
    return ItsInvolution( M );
    
end );

##  <#GAPDoc Label="TransposedMatrix">
##  <ManSection>
##    <Meth Arg="M" Name="TransposedMatrix" Label="for matrices"/>
##    <Returns>a &homalg; matrix</Returns>
##    <Description>
##      The transpose of the &homalg; matrix <A>M</A>.<P/>
##      (for the installed standard method see <Ref Meth="Eval" Label="for matrices created with TransposedMatrix"/>)
##    </Description>
##  </ManSection>
##  <#/GAPDoc>
##
InstallMethod( TransposedMatrix,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( M )
    local C;
    
    C := HomalgMatrixWithAttributes( [
                 EvalTransposedMatrix, M,
                 NumberRows, NumberColumns( M ),
                 NumberColumns, NumberRows( M ),
                 ], HomalgRing( M ) );
    
    SetItsTransposedMatrix( M, C );
    SetItsTransposedMatrix( C, M );
    
    return C;
    
end );

##
InstallMethod( TransposedMatrix,
        "for homalg matrices",
        [ IsHomalgMatrix and HasItsTransposedMatrix ],
        
  function( M )
    
    return ItsTransposedMatrix( M );
    
end );

##  <#GAPDoc Label="CertainRows">
##  <ManSection>
##    <Meth Arg="M, plist" Name="CertainRows" Label="for matrices"/>
##    <Returns>a &homalg; matrix</Returns>
##    <Description>
##      The matrix of which the <M>i</M>-th row is the <M>k</M>-th row of the &homalg; matrix <A>M</A>,
##      where <M>k=</M><A>plist</A><M>[i]</M>.<P/>
##      (for the installed standard method see <Ref Meth="Eval" Label="for matrices created with CertainRows"/>)
##    </Description>
##  </ManSection>
##  <#/GAPDoc>
##
InstallMethod( CertainRows,
        "for homalg matrices",
        [ IsHomalgMatrix, IsList ],
        
  function( M, plist )
    
    plist := ShallowCopy( plist );
    ConvertToRangeRep( plist );
    
    return HomalgMatrixWithAttributes( [
                   EvalCertainRows, [ M, plist ],
                   NumberRows, Length( plist ),
                   NumberColumns, NumberColumns( M )
                   ], HomalgRing( M ) );
    
end );

##
InstallOtherMethod( \[\],
        "for a homalg matrix and a positive integer",
        [ IsHomalgMatrix, IsInt ],
        
  function( M, r )
    
    return CertainRows( M, [ r ] );
    
end );

##
InstallOtherMethod( \{\},
        "for a homalg matrix and a positive integer",
        [ IsHomalgMatrix, IsList ],
        
  CertainRows );

##  <#GAPDoc Label="CertainColumns">
##  <ManSection>
##    <Meth Arg="M, plist" Name="CertainColumns" Label="for matrices"/>
##    <Returns>a &homalg; matrix</Returns>
##    <Description>
##      The matrix of which the <M>j</M>-th column is the <M>l</M>-th column of the &homalg; matrix <A>M</A>,
##      where <M>l=</M><A>plist</A><M>[j]</M>.<P/>
##      (for the installed standard method see <Ref Meth="Eval" Label="for matrices created with CertainColumns"/>)
##    </Description>
##  </ManSection>
##  <#/GAPDoc>
##
InstallMethod( CertainColumns,
        "for homalg matrices",
        [ IsHomalgMatrix, IsList ],
        
  function( M, plist )
    
    plist := ShallowCopy( plist );
    ConvertToRangeRep( plist );
    
    return HomalgMatrixWithAttributes( [
                   EvalCertainColumns, [ M, plist ],
                   NumberColumns, Length( plist ),
                   NumberRows, NumberRows( M )
                   ], HomalgRing( M ) );
    
end );

##  <#GAPDoc Label="UnionOfRows">
##  <ManSection>
##    <Func Arg="[R, nr_cols, ]L" Name="UnionOfRows" Label="for a homalg ring, an integer and a list of homalg matrices"/>
##    <Returns>a &homalg; matrix</Returns>
##    <Description>
##      Stack the &homalg; matrices in the list <A>L</A>. The entries of <A>L</A> must be matrices over the &homalg; ring <A>R</A> with <A>nr_cols</A> columns.
##      If <A>L</A> is non-empty, <A>R</A> and <A>nr_cols</A> can be omitted.<P/>
##      
##      (for the installed standard method see <Ref Meth="Eval" Label="for matrices created with UnionOfRows"/>)
##    </Description>
##  </ManSection>
##  <#/GAPDoc>
##
InstallGlobalFunction( UnionOfRows,
function( arg )
    local R, nr_cols, list;
    
    if IsEmpty( arg ) then
        Error( "<arg> must be nonempty" );
    elif IsHomalgMatrix( arg[1] ) then
        # UnionOfRows( mat1, mat2, ... )
        list := arg;
        R := HomalgRing( list[1] );
        nr_cols := NumberColumns( list[1] );
    elif Length( arg ) = 1 and IsList( arg[1] )  then
        # UnionOfRows( [ mat1, mat2, ... ] )
        if IsEmpty( arg[1] )  then
            Error( "<arg>[1] must be nonempty" );
        fi;
        list := arg[1];
        R := HomalgRing( list[1] );
        nr_cols := NumberColumns( list[1] );
    elif Length( arg ) = 3 and IsHomalgRing( arg[1] ) and IsInt( arg[2] ) and IsList( arg[3] ) then
        # UnionOfRows( ring, nr_cols, [ mat1, mat2, ... ] )
        R := arg[1];
        nr_cols := arg[2];
        list := arg[3];
    else
        Error("usage: UnionOfRows( mat1, mat2, ... ) or UnionOfRows( [ mat1, mat2, ... ] ) or UnionOfRows( ring, nr_cols, [ mat1, mat2, ... ] )");
    fi;
    
    return UnionOfRowsOp( R, nr_cols, list );
    
end );

##
InstallMethod( UnionOfRowsOp,
        "of a homalg ring, an integer and a list of homalg matrices",
        [ IsHomalgRing, IsInt, IsList ],

  function( R, nr_cols, L )
    local result;
    
    result := HomalgMatrixWithAttributes( [
         EvalUnionOfRows, L,
         NumberRows, Sum( List( L, NumberRows ) ),
         NumberColumns, nr_cols
         ], R );
    
    if IsBound( HOMALG_MATRICES.UnionOfRowsEager ) and HOMALG_MATRICES.UnionOfRowsEager = true then
        Eval( result );
    fi;
    
    return result;
    
end );

##
InstallGlobalFunction( UnionOfRowsEager,
  function( arg )
    local nargs;
    
    nargs := Length( arg );
    
    if nargs = 0  then
        Error( "<arg> must be nonempty" );
    elif Length( arg ) = 1 and IsList( arg[1] )  then
        if IsEmpty( arg[1] )  then
            Error( "<arg>[1] must be nonempty" );
        fi;
        arg := arg[1];
    fi;
    
    return UnionOfRowsEagerOp( arg, arg[1] );
    
end );

##
InstallMethod( UnionOfRowsEagerOp,
        "of a list of homalg matrices and a homalg matrix",
        [ IsList, IsHomalgMatrix ],

  function( L, M )
    local result;
    
    result := HomalgMatrixWithAttributes( [
         EvalUnionOfRows, L,
         NumberRows, Sum( List( L, NumberRows ) ),
         NumberColumns, NumberColumns( L[1] )
         ], HomalgRing( L[1] ) );
    
    Eval( result );
    
    return result;
    
end );

##  <#GAPDoc Label="UnionOfColumns">
##  <ManSection>
##    <Func Arg="[R, nr_rows, ]L" Name="UnionOfColumns" Label="for a homalg ring, an integer and a list of homalg matrices"/>
##    <Returns>a &homalg; matrix</Returns>
##    <Description>
##      Augment the &homalg; matrices in the list <A>L</A>. The entries of <A>L</A> must be matrices over the &homalg; ring <A>R</A> with <A>nr_rows</A> rows.
##      If <A>L</A> is non-empty, <A>R</A> and <A>nr_rows</A> can be omitted.<P/>
##      
##      (for the installed standard method see <Ref Meth="Eval" Label="for matrices created with UnionOfColumns"/>)
##    </Description>
##  </ManSection>
##  <#/GAPDoc>
##
InstallGlobalFunction( UnionOfColumns,
function( arg )
    local R, nr_rows, list;
    
    if IsEmpty( arg ) then
        Error( "<arg> must be nonempty" );
    elif IsHomalgMatrix( arg[1] ) then
        # UnionOfColumns( mat1, mat2, ... )
        list := arg;
        R := HomalgRing( list[1] );
        nr_rows := NumberRows( list[1] );
    elif Length( arg ) = 1 and IsList( arg[1] )  then
        # UnionOfColumns( [ mat1, mat2, ... ] )
        if IsEmpty( arg[1] )  then
            Error( "<arg>[1] must be nonempty" );
        fi;
        list := arg[1];
        R := HomalgRing( list[1] );
        nr_rows := NumberRows( list[1] );
    elif Length( arg ) = 3 and IsHomalgRing( arg[1] ) and IsInt( arg[2] ) and IsList( arg[3] ) then
        # UnionOfColumns( ring, nr_rows, [ mat1, mat2, ... ] )
        R := arg[1];
        nr_rows := arg[2];
        list := arg[3];
    else
        Error("usage: UnionOfColumns( mat1, mat2, ... ) or UnionOfColumns( [ mat1, mat2, ... ] ) or UnionOfColumns( ring, nr_rows, [ mat1, mat2, ... ] )");
    fi;
    
    return UnionOfColumnsOp( R, nr_rows, list );
    
end );

##
InstallMethod( UnionOfColumnsOp,
        "of a list of homalg matrices and a homalg matrix",
        [ IsHomalgRing, IsInt, IsList ],

  function( R, nr_rows, L )
    local result;
    
    result := HomalgMatrixWithAttributes( [
         EvalUnionOfColumns, L,
         NumberRows, nr_rows,
         NumberColumns, Sum( List( L, NumberColumns ) )
         ], R );
    
    if IsBound( HOMALG_MATRICES.UnionOfColumnsEager ) and HOMALG_MATRICES.UnionOfColumnsEager = true then
        Eval( result );
    fi;
    
    return result;
    
end );

##
InstallGlobalFunction( UnionOfColumnsEager,
  function( arg )
    local nargs;
    
    nargs := Length( arg );
    
    if nargs = 0  then
        Error( "<arg> must be nonempty" );
    elif Length( arg ) = 1 and IsList( arg[1] )  then
        if IsEmpty( arg[1] )  then
            Error( "<arg>[1] must be nonempty" );
        fi;
        arg := arg[1];
    fi;
    
    return UnionOfColumnsEagerOp( arg, arg[1] );
    
end );

##
InstallMethod( UnionOfColumnsEagerOp,
        "of a list of homalg matrices and a homalg matrix",
        [ IsList, IsHomalgMatrix ],

  function( L, M )
    local result;
    
    result := HomalgMatrixWithAttributes( [
         EvalUnionOfColumns, L,
         NumberRows, NumberRows( L[1] ),
         NumberColumns, Sum( List( L, NumberColumns ) )
         ], HomalgRing( L[1] ) );
    
    Eval( result );
    
    return result;
    
end );

##  <#GAPDoc Label="ConvertRowToMatrix">
##  <ManSection>
##    <Meth Arg="M, r, c" Name="ConvertRowToMatrix" Label="for matrices"/>
##    <Returns>a &homalg; matrix</Returns>
##    <Description>
##      Fold the row <A>M</A> to an <A>r</A>x<A>c</A>-matrix.
##    </Description>
##  </ManSection>
##  <#/GAPDoc>
##
InstallMethod( ConvertRowToMatrix,
        "for a homalg matrix and two integers",
        [ IsHomalgMatrix, IsInt, IsInt ],
        
  function( M, r, c )
    local R, C;
    
    if NumberRows( M ) <> 1 then
        Error( "expecting a single row matrix as a first argument\n" );
    fi;
    
    if NumberColumns( M ) <> r * c then
        Error( "the row has not the expected length\n" );
    fi;
    
    R := HomalgRing( M );
    
    if r = 1 then
        return M;
    elif r * c = 0 or ( HasIsZero( M ) and IsZero( M ) ) then
        return HomalgZeroMatrix( r, c, R );
    fi;
    
    C := HomalgMatrixWithAttributes( [
                 EvalConvertRowToMatrix, [ M, r, c ],
                 NumberRows, r,
                 NumberColumns, c,
                 ], R );
    
    return C;
    
end );

##  <#GAPDoc Label="ConvertColumnToMatrix">
##  <ManSection>
##    <Meth Arg="M, r, c" Name="ConvertColumnToMatrix" Label="for matrices"/>
##    <Returns>a &homalg; matrix</Returns>
##    <Description>
##      Fold the column <A>M</A> to an <A>r</A>x<A>c</A>-matrix.
##    </Description>
##  </ManSection>
##  <#/GAPDoc>
##
InstallMethod( ConvertColumnToMatrix,
        "for a homalg matrix and two integers",
        [ IsHomalgMatrix, IsInt, IsInt ],
        
  function( M, r, c )
    local R, C;
    
    if NumberColumns( M ) <> 1 then
        Error( "expecting a single column matrix as a first argument\n" );
    fi;
    
    if NumberRows( M ) <> r * c then
        Error( "the column has not the expected height\n" );
    fi;
    
    R := HomalgRing( M );
    
    if c = 1 then
        return M;
    elif r * c = 0 or ( HasIsZero( M ) and IsZero( M ) ) then
        return HomalgZeroMatrix( r, c, R );
    fi;
    
    C := HomalgMatrixWithAttributes( [
                 EvalConvertColumnToMatrix, [ M, r, c ],
                 NumberRows, r,
                 NumberColumns, c,
                 ], R );
    
    return C;
    
end );

##  <#GAPDoc Label="ConvertMatrixToRow">
##  <ManSection>
##    <Meth Arg="M" Name="ConvertMatrixToRow" Label="for matrices"/>
##    <Returns>a &homalg; matrix</Returns>
##    <Description>
##      Unfold the matrix <A>M</A> row-wise into a row.
##    </Description>
##  </ManSection>
##  <#/GAPDoc>
##
InstallMethod( ConvertMatrixToRow,
        "for a homalg matrix",
        [ IsHomalgMatrix ],
        
  function( M )
    local r, c, R, C;
    
    r := NumberRows( M );
    
    if r = 1 then
        return M;
    fi;
    
    c := NumberColumns( M );
    
    R := HomalgRing( M );
    
    if r = 0 or ( HasIsZero( M ) and IsZero( M ) ) then
        return HomalgZeroMatrix( 1, r * c, R );
    fi;
    
    C := HomalgMatrixWithAttributes( [
                 EvalConvertMatrixToRow, M,
                 NumberRows, 1,
                 NumberColumns, r * c,
                 ], R );
    
    return C;
    
end );

##  <#GAPDoc Label="ConvertMatrixToColumn">
##  <ManSection>
##    <Meth Arg="M" Name="ConvertMatrixToColumn" Label="for matrices"/>
##    <Returns>a &homalg; matrix</Returns>
##    <Description>
##      Unfold the matrix <A>M</A> column-wise into a column.
##    </Description>
##  </ManSection>
##  <#/GAPDoc>
##
InstallMethod( ConvertMatrixToColumn,
        "for a homalg matrix",
        [ IsHomalgMatrix ],
        
  function( M )
    local c, r, R, C;
    
    c := NumberColumns( M );
    
    if c = 1 then
        return M;
    fi;
    
    r := NumberRows( M );
    
    R := HomalgRing( M );
    
    if c = 0 or ( HasIsZero( M ) and IsZero( M ) ) then
        return HomalgZeroMatrix( r * c, 1, R );
    fi;
    
    C := HomalgMatrixWithAttributes( [
                 EvalConvertMatrixToColumn, M,
                 NumberRows, r * c,
                 NumberColumns, 1,
                 ], R );
    
    return C;
    
end );

##  <#GAPDoc Label="DiagMat">
##  <ManSection>
##    <Meth Arg="[R, ]list" Name="DiagMat" Label="for a homalg ring and a list of homalg matrices"/>
##    <Returns>a &homalg; matrix</Returns>
##    <Description>
##      Build the block diagonal matrix out of the &homalg; matrices listed in <A>list</A>.
##      If <A>list</A> is non-empty, <A>R</A> can be omitted.<P/>
##      
##      (for the installed standard method see <Ref Meth="Eval" Label="for matrices created with DiagMat"/>)
##    </Description>
##  </ManSection>
##  <#/GAPDoc>
##
InstallMethod( DiagMat,
        "of a homalg ring and a list of homalg matrices",
        [ IsHomalgRing, IsHomogeneousList ],
        
  function( R, list )
    
    return HomalgMatrixWithAttributes( [
                   EvalDiagMat, list,
                   NumberRows, Sum( List( list, NumberRows ) ),
                   NumberColumns, Sum( List( list, NumberColumns ) )
                   ], R );
    
end );

##
# convenience
InstallOtherMethod( DiagMat,
        "of a list of homalg matrices",
        [ IsHomogeneousList ],
        
  function( list )
    
    if IsEmpty( list ) then
        Error( "the given list of diagonal blocks is empty\n" );
    fi;
    
    return DiagMat( HomalgRing( list[1] ), list );
    
end );

##  <#GAPDoc Label="KroneckerMat">
##  <ManSection>
##    <Meth Arg="A, B" Name="KroneckerMat" Label="for matrices"/>
##    <Returns>a &homalg; matrix</Returns>
##    <Description>
##      The Kronecker (or tensor) product of the two &homalg; matrices <A>A</A> and <A>B</A>.<P/>
##      (for the installed standard method see <Ref Meth="Eval" Label="for matrices created with KroneckerMat"/>)
##    </Description>
##  </ManSection>
##  <#/GAPDoc>
##
InstallMethod( KroneckerMat,
        "of two homalg matrices",
        [ IsHomalgMatrix, IsHomalgMatrix ],
        
  function( A, B )
    
    return HomalgMatrixWithAttributes( [
                   EvalKroneckerMat, [ A, B ],
                   NumberRows, NumberRows( A ) * NumberRows( B ),
                   NumberColumns, NumberColumns( A ) * NumberColumns ( B )
                   ], HomalgRing( A ) );
    
end );

##  <#GAPDoc Label="DualKroneckerMat">
##  <ManSection>
##    <Meth Arg="A, B" Name="DualKroneckerMat" Label="for matrices"/>
##    <Returns>a &homalg; matrix</Returns>
##    <Description>
##      The dual Kronecker product of the two &homalg; matrices <A>A</A> and <A>B</A>.<P/>
##      (for the installed standard method see <Ref Meth="Eval" Label="for matrices created with DualKroneckerMat"/>)
##    </Description>
##  </ManSection>
##  <#/GAPDoc>
##
InstallMethod( DualKroneckerMat,
        "of two homalg matrices",
        [ IsHomalgMatrix, IsHomalgMatrix ],
        
  function( A, B )
    
    return HomalgMatrixWithAttributes( [
                   EvalDualKroneckerMat, [ A, B ],
                   NumberRows, NumberRows( A ) * NumberRows( B ),
                   NumberColumns, NumberColumns( A ) * NumberColumns ( B )
                   ], HomalgRing( A ) );
    
end );

##
InstallMethod( \*,
        "for internal matrix hulls",
        [ IsRingElement, IsInternalMatrixHull ], 1001, ## it could otherwise run into the method ``PROD: negative integer * additive element with inverse'', value: 24
        
  function( a, A )
    
    return homalgInternalMatrixHull( a * A!.matrix );
    
end );

##  <#GAPDoc Label="MulMat">
##  <ManSection>
##    <Meth Arg="a, A" Name="\*" Label="for ring elements and matrices"/>
##    <Returns>a &homalg; matrix</Returns>
##    <Description>
##      The product of the ring element <A>a</A> with the &homalg; matrix <A>A</A> (enter: <A>a</A> <C>*</C> <A>A</A>;).<P/>
##      (for the installed standard method see <Ref Meth="Eval" Label="for matrices created with MulMat"/>)
##    </Description>
##  </ManSection>
##  <#/GAPDoc>
##
InstallMethod( \*,
        "for a homalg matrix and a homalg ring element",
        [ IsHomalgMatrix, IsRingElement ], 1001, ## it could otherwise run into the method ``PROD: negative integer * additive element with inverse'', value: 24 (if this value is increased, the corresonding values for \* in LIMAT, COLEM, and below must be increased as well!!!)
        
  function( A, a )
    
    return HomalgMatrixWithAttributes( [
                   EvalMulMatRight, [ A, a ],
                   NumberRows, NumberRows( A ),
                   NumberColumns, NumberColumns( A )
                   ], HomalgRing( A ) );
    
end );

##
InstallMethod( \*,
        "for a homalg ring element and a homalg matrix",
        [ IsRingElement, IsHomalgMatrix ], 1001, ## it could otherwise run into the method ``PROD: negative integer * additive element with inverse'', value: 24 (if this value is increased, the corresonding values for \* in LIMAT, COLEM, and below must be increased as well!!!)
        
  function( a, A )
    
    return HomalgMatrixWithAttributes( [
                   EvalMulMat, [ a, A ],
                   NumberRows, NumberRows( A ),
                   NumberColumns, NumberColumns( A )
                   ], HomalgRing( A ) );
    
end );

##
InstallMethod( \+,
        "for pairs of internal matrix hulls",
        [ IsInternalMatrixHull, IsInternalMatrixHull ],
        
  function( A, B )
    
    return homalgInternalMatrixHull( A!.matrix + B!.matrix );
    
end );

##  <#GAPDoc Label="AddMat">
##  <ManSection>
##    <Meth Arg="A, B" Name="\+" Label="for matrices"/>
##    <Returns>a &homalg; matrix</Returns>
##    <Description>
##      The sum of the two &homalg; matrices <A>A</A> and <A>B</A> (enter: <A>A</A> <C>+</C> <A>B</A>;).<P/>
##      (for the installed standard method see <Ref Meth="Eval" Label="for matrices created with AddMat"/>)
##    </Description>
##  </ManSection>
##  <#/GAPDoc>
##
InstallMethod( \+,
        "for pairs of homalg matrices",
        [ IsHomalgMatrix, IsHomalgMatrix ],
        
  function( A, B )
    
    return HomalgMatrixWithAttributes( [
                   EvalAddMat, [ A, B ],
                   NumberRows, NumberRows( A ),
                   NumberColumns, NumberColumns( A )
                   ], HomalgRing( A ) );
    
end );

## a synonym of `-<elm>':
InstallMethod( AdditiveInverseMutable,
        "for internal matrix hulls",
        [ IsInternalMatrixHull ],
        
  function( A )
    
    return homalgInternalMatrixHull( -A!.matrix );
    
end );

## a synonym of `-<elm>':
InstallMethod( AdditiveInverseMutable,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( A )
    local R, C;
    
    R := HomalgRing( A );
    
    C := MinusOne( R ) * A;
    
    if HasIsZero( A ) then
        SetIsZero( C, IsZero( A ) );
    fi;
    
    return C;
    
end );

## a synonym of `-<elm>':
InstallMethod( AdditiveInverseMutable,
        "for homalg matrices",
        [ IsHomalgMatrix and IsZero ],
        
  function( A )
    
    return A;
    
end );

##
InstallMethod( \-,
        "for pairs of internal matrix hulls",
        [ IsInternalMatrixHull, IsInternalMatrixHull ],
        
  function( A, B )
    
    return homalgInternalMatrixHull( A!.matrix - B!.matrix );
    
end );

##  <#GAPDoc Label="SubMat">
##  <ManSection>
##    <Meth Arg="A, B" Name="\-" Label="for matrices"/>
##    <Returns>a &homalg; matrix</Returns>
##    <Description>
##      The difference of the two &homalg; matrices <A>A</A> and <A>B</A> (enter: <A>A</A> <C>-</C> <A>B</A>;).<P/>
##      (for the installed standard method see <Ref Meth="Eval" Label="for matrices created with SubMat"/>)
##    </Description>
##  </ManSection>
##  <#/GAPDoc>
##
InstallMethod( \-,
        "for pairs of of homalg matrices",
        [ IsHomalgMatrix, IsHomalgMatrix ],
        
  function( A, B )
    
    return HomalgMatrixWithAttributes( [
                   EvalSubMat, [ A, B ],
                   NumberRows, NumberRows( A ),
                   NumberColumns, NumberColumns( A )
                   ], HomalgRing( A ) );
    
end );

##
InstallMethod( \*,
        "for pairs of internal matrix hulls",
        [ IsInternalMatrixHull, IsInternalMatrixHull ],
        
  function( A, B )
    
    return homalgInternalMatrixHull( A!.matrix * B!.matrix );
    
end );

##  <#GAPDoc Label="Compose:matrix">
##  <ManSection>
##    <Meth Arg="A, B" Name="\*" Label="for composable matrices"/>
##    <Returns>a &homalg; matrix</Returns>
##    <Description>
##      The matrix product of the two &homalg; matrices <A>A</A> and <A>B</A> (enter: <A>A</A> <C>*</C> <A>B</A>;).<P/>
##      (for the installed standard method see <Ref Meth="Eval" Label="for matrices created with Compose"/>)
##    </Description>
##  </ManSection>
##  <#/GAPDoc>
##
InstallMethod( \*,
        "for pairs of homalg matrices",
        [ IsHomalgMatrix, IsHomalgMatrix ], 14001, ## it could otherwise run into the method ``PROD: IsRingElement * IsHomalgMatrix'', value: 1001 (if this value is increased, the corresonding values in LIMAT must be increased as well!!!)
        
  function( A, B )
    
    return HomalgMatrixWithAttributes( [
                   EvalCompose, [ A, B ],
                   NumberRows, NumberRows( A ),
                   NumberColumns, NumberColumns( B )
                   ], HomalgRing( A ) );
    
end );

##
InstallMethod( \^,
        "for homalg maps",
        [ IsHomalgMatrix, IsInt ],
        
  function( A, pow )
    local R;
    
    if NumberRows( A ) <> NumberColumns( A ) then
        Error( "the matrix is not quadratic\n" );
    fi;
    
    R := HomalgRing( A );
    
    if pow < 0 then
        
        Error( "not implemented yet\n" );
        
    elif pow = 0 then
        
        return HomalgIdentityMatrix( NumberRows( A ), R );
        
    elif pow = 1 then
        
        return A;
        
    else
        
        return Iterated( ListWithIdenticalEntries( pow, A ), \* );
        
    fi;
    
end );

##
InstallMethod( NonZeroRows,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( C )
    local zero_rows;
    
    zero_rows := ZeroRows( C );
    
    return Filtered( [ 1 .. NumberRows( C ) ], x -> not x in zero_rows );
    
end );

##
InstallMethod( NonZeroColumns,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( C )
    local zero_columns;
    
    zero_columns := ZeroColumns( C );
    
    return Filtered( [ 1 .. NumberColumns( C ) ], x -> not x in zero_columns );
    
end );

##
InstallMethod( AdjunctMatrix,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( C )
    local R, m, A;
    
    R := HomalgRing( C );
    
    if not HasIsCommutative( R ) then
        Error( "the ring is not known to be commutative\n" );
    elif not IsCommutative( R ) then
        Error( "the ring is not commutative\n" );
    fi;
    
    m := NumberRows( C );
    
    if not m = NumberColumns( C ) then
        Error( "the input ", m, "x", NumberColumns( C ), "-matrix is not quadratic\n" );
    fi;
    
    m := [ 1 .. m ];
    
    A := List( m, c -> List( m, r -> (-1)^(r+c) * Determinant( CertainRows( CertainColumns( C, Difference( m, [ c ] ) ),  Difference( m, [ r ] ) ) ) ) );
    
    return HomalgMatrix( A, R );
    
end );

##  <#GAPDoc Label="LeftInverseLazy">
##  <ManSection>
##    <Oper Arg="M" Name="LeftInverseLazy" Label="for matrices"/>
##    <Returns>a &homalg; matrix</Returns>
##    <Description>
##      A lazy evaluated left inverse <M>C</M> of the matrix <A>M</A>. If no left inverse exists then
##      <C>Eval</C>( <A>C</A> ) will issue an error.<P/>
##      (for the installed standard method see <Ref Meth="Eval" Label="for matrices created with LeftInverseLazy"/>)
##    </Description>
##  </ManSection>
##  <#/GAPDoc>
##
InstallMethod( LeftInverseLazy,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( M )
    local C;
    
    ## we assume the LeftInverse exists
    C := HomalgMatrixWithAttributes( [
                 EvalLeftInverse, M,
                 NumberRows, NumberColumns( M ),
                 NumberColumns, NumberRows( M )
                 ], HomalgRing( M ) );
    
    ## check assertion
    Assert( 6, not IsBool( Eval( C ) ) );
    
    ## SetLeftInverse( M, C ) will cause a infinite loop
    
    return C;
    
end );

##  <#GAPDoc Label="RightInverseLazy">
##  <ManSection>
##    <Oper Arg="M" Name="RightInverseLazy" Label="for matrices"/>
##    <Returns>a &homalg; matrix</Returns>
##    <Description>
##      A lazy evaluated right inverse <M>C</M> of the matrix <A>M</A>. If no right inverse exists then
##      <C>Eval</C>( <A>C</A> ) will issue an error.<P/>
##      (for the installed standard method see <Ref Meth="Eval" Label="for matrices created with RightInverseLazy"/>)
##    </Description>
##  </ManSection>
##  <#/GAPDoc>
##
InstallMethod( RightInverseLazy,
        "for homalg matrices",
        [ IsHomalgMatrix ],
        
  function( M )
    local C;
    
    ## we assume the RightInverse exists
    C := HomalgMatrixWithAttributes( [
                 EvalRightInverse, M,
                 NumberColumns, NumberRows( M ),
                 NumberRows, NumberColumns( M )
                 ], HomalgRing( M ) );
    
    ## check assertion
    Assert( 6, not IsBool( Eval( C ) ) );
    
    ## SetRightInverse( M, C )  will cause a infinite loop
    
    return C;
    
end );

##
InstallMethod( DiagonalEntries,
        "of homalg matrices",
        [ IsHomalgMatrix ],
        
  function( M )
    local m;
    
    m := Minimum( NumberRows( M ), NumberColumns( M ) );
    
    return List( [ 1 .. m ], a -> M[ a, a ] );
    
end );

##
InstallMethod( Minors,
        "of homalg matrices",
        [ IsInt, IsHomalgMatrix ],
        
  function( d, M )
    local R, r, c, l;
    
    R := HomalgRing( M );
    
    if not HasIsCommutative( R ) then
        Error( "the ring is not known to be commutative\n" );
    elif not IsCommutative( R ) then
        Error( "the ring is not commutative\n" );
    fi;
    
    if d <= 0 then
        return [ One( R ) ];
    fi;
    
    r := NumberRows( M );
    c := NumberColumns( M );
    
    if d > Minimum( r, c ) then
        return [ Zero( R ) ];
    fi;
    
    l := Cartesian( Combinations( [ 1 .. r ], d ), Combinations( [ 1 .. c ], d ) );
    
    l := List( l, rc -> Determinant( CertainColumns( CertainRows( M, rc[1] ), rc[2] ) ) );
    
    if l = [ ] then
        return [ Zero( R ) ];
    fi;
    
    return l;
    
end );

##
InstallMethod( MaximalMinors,
        "of homalg matrices",
        [ IsHomalgMatrix ],
        
  function( M )
    
    return Minors( Minimum( NumberRows( M ), NumberColumns( M ) ), M );
    
end );

##
InstallMethod( PostMakeImmutable,
        "for homalg internal matrices",
        [ IsHomalgInternalMatrixRep and HasEval ],
        
  function( A )
    
    MakeImmutable( Eval( A )!.matrix );
    
end );

##
InstallMethod( SetIsMutableMatrix,
        "for homalg matrices and a Boolean",
        [ IsHomalgMatrix, IsBool ],
        
  function( M, b )
    
    if b = true then;
        SetFilterObj( M, IsMutable );
    else
        ResetFilterObj( M, IsMutable );
    fi;
    
end );

##
InstallMethod( SetIsMutableMatrix,
        "for homalg matrices and a Boolean",
        [ IsHomalgMatrix and IsEmptyMatrix, IsBool ], 1001,
        
  function( M, b )
    
    ## do nothing
    
end );

##
InstallMethod( Iterator,
        "of homalg matrices",
        [ IsHomalgMatrix ],
        
  function( M )
    local R, c, d, rank, iter, save, F, r;
    
    R := HomalgRing( M );
    
    if not IsFieldForHomalg( R ) or
       ( not HasCharacteristic( R ) or Characteristic( R ) = 0 ) or
       ( not HasDegreeOverPrimeField( R ) or not IsInt( DegreeOverPrimeField( R ) ) ) then
        TryNextMethod( );
    fi;
    
    c := Characteristic( R );
    d := DegreeOverPrimeField( R );
    
    M := BasisOfRows( M );
    
    if not IsLeftRegular( M ) then
        TryNextMethod( );
    fi;
    
    rank := RowRankOfMatrix( M );
    
    iter := Iterator( GF(c^d)^rank );
    
    if IsHomalgInternalRingRep( R ) then
        F := R;
    else
        F := HomalgRingOfIntegers( c, d );
    fi;
    
    r := rec(
             ring := R,
             iter := iter,
             matrix := M,
             rank := rank,
             GF := F,
             
             NextIterator :=
             function( i )
               local mat;
               mat := HomalgMatrix( NextIterator( i!.iter ), 1, i!.rank, i!.GF );
               SetNumberRows( mat, 1 );          ## should be obsolete
               SetNumberColumns( mat, i!.rank ); ## should be obsolete
               return ( i!.ring * mat ) * i!.matrix;
             end,
             
             IsDoneIterator :=
             function( i )
               return IsDoneIterator( i!.iter );
             end,
             
             ShallowCopy :=
             function( i );
                 return
                   rec(
                       ring := i!.ring,
                       iter := ShallowCopy( i!.iter ),
                       matrix := i!.matrix,
                       rank := i!.rank,
                       GF := i!.GF,
                       NextIterator := i!.NextIterator,
                       IsDoneIterator := i!.IsDoneIterator,
                       ShallowCopy := i!.ShallowCopy
                       );
             end
             );
    
    return IteratorByFunctions( r );
    
end );

##
InstallMethod( Select,
        "for a matrix and a list",
        [ IsHomalgMatrix, IsList ],
        
  function( M, L )
    local R, indets, zero, map, N;
    
    R := HomalgRing( M );
    
    if HasRelativeIndeterminatesOfPolynomialRing( R ) then
        indets := RelativeIndeterminatesOfPolynomialRing( R );
    elif HasIndeterminatesOfPolynomialRing( R ) then
        indets := IndeterminatesOfPolynomialRing( R );
    else
        TryNextMethod( );
    fi;
    
    if not IsSubset( indets, L ) then
        Error( "the second argument is not a subset of the list of indeterminates\n" );
    fi;
    
    zero := Zero( R );
    
    map := List( indets, function( a ) if a in L then return a; else return zero; fi; end );
    
    map := RingMap( map, R, R );
    
    N := Pullback( map, M );
    
    return CertainRows( M, ZeroRows( M - N ) );
    
end );

####################################
#
# constructor functions and methods:
#
####################################

##
InstallGlobalFunction( homalgInternalMatrixHull,
  function( M )
    
    return Objectify( TheTypeInternalMatrixHull, rec( matrix := M ) );
    
end );

##
InstallMethod( ConvertHomalgMatrixViaListListString,
        "for homalg matrices",
        [ IsHomalgMatrix, IsHomalgRing ],
        
  function( M, R )
    local s;
    
    s := GetListListOfHomalgMatrixAsString( M );
    
    return CreateHomalgMatrixFromString( s, R );
    
end );

##
InstallMethod( ConvertHomalgMatrixViaListListString,
        "for homalg matrices",
        [ IsHomalgMatrix, IsInt, IsInt, IsHomalgRing ],
        
  function( M, r, c, R )
    local s;
    
    s := GetListListOfHomalgMatrixAsString( M );
    
    return CreateHomalgMatrixFromString( s, R );
    
end );

##
InstallMethod( ConvertHomalgMatrixViaListString,
        "for homalg matrices",
        [ IsHomalgMatrix, IsHomalgRing ],
        
  function( M, R )
    local r, c, s;
    
    r := NumberRows( M );
    c := NumberColumns( M );
    
    s := GetListOfHomalgMatrixAsString( M );
    
    return CreateHomalgMatrixFromString( s, r, c, R );
    
end );

##
InstallMethod( ConvertHomalgMatrixViaListString,
        "for homalg matrices",
        [ IsHomalgMatrix, IsInt, IsInt, IsHomalgRing ],
        
  function( M, r, c, R )
    local s;
    
    s := GetListOfHomalgMatrixAsString( M );
    
    return CreateHomalgMatrixFromString( s, r, c, R );
    
end );

##
InstallMethod( ConvertHomalgMatrixViaSparseString,
        "for homalg matrices",
        [ IsHomalgMatrix, IsHomalgRing ],
        
  function( M, R )
    local r, c, s;
    
    r := NumberRows( M );
    c := NumberColumns( M );
    
    s := GetSparseListOfHomalgMatrixAsString( M );
    
    return CreateHomalgMatrixFromSparseString( s, r, c, R );
    
end );

##
InstallMethod( ConvertHomalgMatrixViaSparseString,
        "for homalg matrices",
        [ IsHomalgMatrix, IsInt, IsInt, IsHomalgRing ],
        
  function( M, r, c, R )
    local s;
    
    s := GetSparseListOfHomalgMatrixAsString( M );
    
    return CreateHomalgMatrixFromSparseString( s, r, c, R );
    
end );

##
InstallMethod( ConvertHomalgMatrix,
        "for homalg matrices",
        [ IsHomalgMatrix, IsHomalgRing ],
        
  function( M, R )
    
    if IsBound( M!.ConvertHomalgMatrixViaSparseString ) and M!.ConvertHomalgMatrixViaSparseString = true then
        
        return ConvertHomalgMatrixViaSparseString( M, R );
        
    fi;
    
    return ConvertHomalgMatrixViaListListString( M, R );
    
end );

##
InstallMethod( ConvertHomalgMatrix,
        "for homalg matrices",
        [ IsHomalgMatrix, IsInt, IsInt, IsHomalgRing ],
        
  function( M, r, c, R )
    
    if IsBound( M!.ConvertHomalgMatrixViaSparseString ) and M!.ConvertHomalgMatrixViaSparseString = true then
        
        return ConvertHomalgMatrixViaSparseString( M, r, c, R );
        
    fi;
    
    return ConvertHomalgMatrixViaListString( M, r, c, R );
    
end );

##
InstallMethod( CreateHomalgMatrixFromString,
        "constructor for homalg matrices",
        [ IsString, IsHomalgInternalRingRep ],
        
  function( S, R )
    local s;
    
    s := ShallowCopy( S );
    
    RemoveCharacters( s, "\\\n\" " );
    
    return HomalgMatrix( EvalString( s ), R );
    
end );

##
InstallMethod( CreateHomalgMatrixFromString,
        "constructor for homalg matrices",
        [ IsString, IsInt, IsInt, IsHomalgInternalRingRep ],
        
  function( S, r, c, R )
    local s;
    
    s := ShallowCopy( S );
    
    RemoveCharacters( s, "\\\n\" " );
    
    s := EvalString( s );
    
    if IsMatrix( s ) then
        return HomalgMatrix( s, r, c, R );
    elif IsList( s ) then
        return HomalgMatrix( ListToListList( s, r, c ), r, c, R );
    else
        Error( "the evaluated string is not in {IsMatrix, IsList}\n" );
    fi;
    
end );

##
InstallMethod( CreateHomalgMatrixFromSparseString,
        "constructor for homalg matrices",
        [ IsString, IsInt, IsInt, IsHomalgRing ],
        
  function( S, r, c, R )
    local s, M, e;
    
    s := ShallowCopy( S );
    
    RemoveCharacters( s, "[]\\\n\" " );
    
    M := HomalgInitialMatrix( r, c, R );
    
    s := SplitString( s, "," );
    
    s := ListToListList( s, Length( s ) / 3, 3 );
    
    Perform( s, function( a ) SetMatElm( M, Int( a[1] ), Int( a[2] ), a[3], R ); end );
    
    ResetFilterObj( M, IsMutable );
    
    return M;
    
end );

##
InstallMethod( CreateHomalgMatrixFromSparseString,
        "constructor for homalg matrices",
        [ IsString, IsInt, IsInt, IsHomalgInternalRingRep ],
        
  function( S, r, c, R )
    local s, M, e;
    
    s := ShallowCopy( S );
    
    RemoveCharacters( s, "\\\n\" " );
    
    M := List( [ 1 .. r ], a -> List( [ 1 .. c ], b -> Zero( R ) ) );
    
    for e in EvalString( s ) do
        M[e[1]][e[2]] := e[3];
    od;
    
    return HomalgMatrix( M, r, c, R );
    
end );

##
InstallMethod( CreateHomalgMatrixFromList,
        "constructor for homalg matrices",
        [ IsList, IsHomalgRing ],
        
  function( L, R )
    local M;
    
    if IsList( L[1] ) then
        M := List( L, r -> List( r, String ) );
        M := Concatenation( "[[", JoinStringsWithSeparator( List( M, r -> JoinStringsWithSeparator( r ) ), "],[" ), "]]" );
    else
        ## this resembles NormalizeInput in Maple's homalg ( a legacy ;) )
        M := Concatenation( "[[", JoinStringsWithSeparator( List( L, String ), "],[" ), "]]" );
        ## What is the use case for this? Wouldn't it be better to replace this by an error message?
        # Error( "the number of rows and columns must be specified to construct a matrix from a list" );
    fi;
    
    return CreateHomalgMatrixFromString( M, R );
    
end );

##
InstallMethod( CreateHomalgMatrixFromList,
        "constructor for homalg matrices",
        [ IsList, IsInt, IsInt, IsHomalgRing ],
        
  function( L, r, c, R )
    local M;
    
    if IsList( L[1] ) then
        M := List( Concatenation( L ), String );
        M := Concatenation( "[", JoinStringsWithSeparator( M ), "]" );
    else
        M := Concatenation( "[", JoinStringsWithSeparator( List( L, String ) ), "]" );
    fi;
    
    return CreateHomalgMatrixFromString( M, r, c, R );
    
end );

##  <#GAPDoc Label="HomalgMatrix">
##  <ManSection>
##    <Func Arg="llist, R" Name="HomalgMatrix" Label="constructor for matrices using a listlist"/>
##    <Func Arg="llist, m, n, R" Name="HomalgMatrix" Label="constructor for matrices using a listlist with given dimensions"/>
##    <Func Arg="list, m, n, R" Name="HomalgMatrix" Label="constructor for matrices using a list"/>
##    <Func Arg="str_llist, R" Name="HomalgMatrix" Label="constructor for matrices using a string of a listlist"/>
##    <Func Arg="str_list, m, n, R" Name="HomalgMatrix" Label="constructor for matrices using a string of a list"/>
##    <Returns>a &homalg; matrix</Returns>
##    <Description>
--> --------------------

--> maximum size reached

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

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