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


Quelle  vecmat.gi   Sprache: unbekannt

 
#############################################################################
##
##  This file is part of GAP, a system for computational discrete algebra.
##  This file's authors include Frank Celler.
##
##  Copyright of GAP belongs to its developers, whose names are too numerous
##  to list here. Please refer to the COPYRIGHT file for details.
##
##  SPDX-License-Identifier: GPL-2.0-or-later
##
##  This file contains  the basic methods for  creating and doing  arithmetic
##  with GF2 vectors and matrices.
##

#############################################################################
##
#F IsLockedRepresentationVector . . filter used by GF2 and GF(q)
##                                  matrix reps to stop their rows
##                                  changing representation

DeclareFilter( "IsLockedRepresentationVector" );

#############################################################################
##
#V  TYPE_LIST_GF2VEC  . . . . . . . . . . . . . . type of mutable GF2 vectors
##
BindGlobal( "TYPE_LIST_GF2VEC",
  NewType( CollectionsFamily( FFEFamily(2) ),
           IsHomogeneousList and IsListDefault and IsNoImmediateMethodsObject
           and IsMutable and IsCopyable and IsGF2VectorRep )
);


#############################################################################
##
#V  TYPE_LIST_GF2VEC_IMM  . . . . . . . . . . . type of immutable GF2 vectors
##
BindGlobal( "TYPE_LIST_GF2VEC_IMM",
  NewType( CollectionsFamily( FFEFamily(2) ),
          IsHomogeneousList and IsListDefault and IsNoImmediateMethodsObject
           and IsCopyable and IsGF2VectorRep )
);


#############################################################################
##
#V  TYPE_LIST_GF2VEC_IMM_LOCKED  . . . . type of immutable locked GF2 vectors
##
BindGlobal( "TYPE_LIST_GF2VEC_IMM_LOCKED",
  NewType( CollectionsFamily( FFEFamily(2) ),
          IsHomogeneousList and IsListDefault and IsNoImmediateMethodsObject
           and IsCopyable and IsGF2VectorRep and IsLockedRepresentationVector)
);


#############################################################################
##
#V  TYPE_LIST_GF2VEC_LOCKED  . . . . type of mutable locked GF2 vectors
##
BindGlobal( "TYPE_LIST_GF2VEC_LOCKED",
  NewType( CollectionsFamily( FFEFamily(2) ),
          IsHomogeneousList and IsListDefault and IsNoImmediateMethodsObject
           and IsCopyable and IsGF2VectorRep and
          IsLockedRepresentationVector and IsMutable)
);


#############################################################################
##
#V  TYPE_LIST_GF2MAT  . . . . . . . . . . . . .  type of mutable GF2 matrices
##
BindGlobal( "TYPE_LIST_GF2MAT",
  NewType( CollectionsFamily(CollectionsFamily(FFEFamily(2))),
           IsMatrix and IsListDefault and IsSmallList and
          IsFFECollColl and IsNoImmediateMethodsObject
           and IsMutable and IsCopyable and IsGF2MatrixRep and
          HasIsRectangularTable and IsRectangularTable )
);


#############################################################################
##
#V  TYPE_LIST_GF2MAT_IMM  . . . . . . . . . .  type of immutable GF2 matrices
##
BindGlobal( "TYPE_LIST_GF2MAT_IMM",
  NewType( CollectionsFamily(CollectionsFamily(FFEFamily(2))),
          IsMatrix and IsListDefault and IsCopyable and IsGF2MatrixRep
          and IsNoImmediateMethodsObject
          and IsSmallList and IsFFECollColl and
          HasIsRectangularTable and IsRectangularTable)
);


#############################################################################
##
## HPC-GAP serialization
##
if IsHPCGAP then
    InstallTypeSerializationTag(TYPE_LIST_GF2VEC,
      SERIALIZATION_BASE_GF2VEC + SERIALIZATION_TAG_BASE * 1);

    InstallTypeSerializationTag(TYPE_LIST_GF2VEC_IMM,
      SERIALIZATION_BASE_GF2VEC + SERIALIZATION_TAG_BASE * 2);

    InstallTypeSerializationTag(TYPE_LIST_GF2VEC_IMM_LOCKED,
      SERIALIZATION_BASE_GF2VEC + SERIALIZATION_TAG_BASE * 3);

    InstallTypeSerializationTag(TYPE_LIST_GF2VEC_LOCKED,
      SERIALIZATION_BASE_GF2VEC + SERIALIZATION_TAG_BASE * 4);

    InstallTypeSerializationTag(TYPE_LIST_GF2MAT,
      SERIALIZATION_BASE_GF2MAT + SERIALIZATION_TAG_BASE * 1);

    InstallTypeSerializationTag(TYPE_LIST_GF2MAT_IMM,
      SERIALIZATION_BASE_GF2MAT + SERIALIZATION_TAG_BASE * 2);
fi;


#############################################################################
##
#M  Length( <gf2vec> )  . . . . . . . . . . . . . . .  length of a GF2 vector
##
InstallOtherMethod( Length,
    "for GF2 vector",
    true,
    [ IsList and IsGF2VectorRep ],
    0,
    LEN_GF2VEC );


#############################################################################
##
#M  ELM_LIST( <gf2vec>, <pos> ) . . . . . select an element from a GF2 vector
##
InstallOtherMethod( ELM_LIST,
    "for GF2 vector",
    true,
    [ IsList and IsGF2VectorRep,
      IsPosInt ],
    0,
    ELM_GF2VEC );


#############################################################################
##
#M  ELMS_LIST( <gf2vec>, <poss> ) . . . . . select elements from a GF2 vector
##
InstallOtherMethod( ELMS_LIST,
    "for GF2 vector",
    true,
    [ IsList and IsGF2VectorRep,
      IsList and IsDenseList and IsInternalRep ],
    0,
    ELMS_GF2VEC );


#############################################################################
##
#M  ASS_LIST( <gf2vec>, <pos>, <elm> )  . . assign an element to a GF2 vector
##
##  We use an OtherMethod and trap assignment to immutable vectors in
##  the kernel method.

InstallOtherMethod( ASS_LIST,
    "for GF2 vector",
    true,
    [ IsList and IsGF2VectorRep,
      IsPosInt,
      IsObject ],
    0,
    ASS_GF2VEC );


#############################################################################
##
#M  ASS_LIST( <empty-list>, <pos>, <ffe> )  . . . . .  start a new GF2 vector
##
#InstallMethod( ASS_LIST,
#    "for empty plain list and finite field element",
#    true,
#    [ IsMutable and IsList and IsPlistRep and IsEmpty,
#      IsPosInt,
#      IsFFE ],
#    0,

#function( list, pos, val )
#    if pos = 1 and ( val = GF2Zero or val = GF2One )  then
#        CONV_GF2VEC(list);
#        ASS_GF2VEC( list, pos, val );
#    else
#        ASS_PLIST_DEFAULT( list, pos, val );
#        # force kernel to notice that this is now a list of FFEs
#        ConvertToVectorRep( list );
#    fi;
#end );


#############################################################################
##
#M  UNB_LIST( <gf2vec>, <pos> ) . . . . . . unbind a position of a GF2 vector
##
##  We use an OtherMethod and trap assignment to immutable vectors in
##  the kernel method.

InstallOtherMethod( UNB_LIST,
    "for GF2 vector",
    true,
    [ IsList and IsGF2VectorRep,
      IsPosInt ],
    0,
    UNB_GF2VEC );


#############################################################################
##
#M  PrintObj( <gf2vec> )  . . . . . . . . . . . . . . . .  print a GF2 vector
##
InstallMethod( PrintObj,
    "for GF2 vector",
    true,
    [ IsGF2VectorRep ],
    0,

function( vec )
    local   i;

    Print( "[ " );
    for i  in [ 1 .. Length(vec) ]  do
        if 1 < i  then Print( ", " );  fi;
        Print( vec[i] );
    od;
    Print( " ]" );
end );


#############################################################################
##
#M  ViewObj( <gf2vec> ) . . . . . . . . . . . . . . . . . . view a GF2 vector
##
InstallMethod( ViewObj,
    "for GF2 vector",
    true,
    [ IsRowVector and IsFinite and IsGF2VectorRep ],
    0,

function( vec )
    if IsMutable(vec)  then
        Print( "<a GF2 vector of length ", Length(vec), ">" );
    else
        Print( "<an immutable GF2 vector of length ", Length(vec), ">" );
    fi;
end );


#############################################################################
##
#M  AdditiveInverseOp( <gf2vec> ) .  mutable additive inverse of a GF2 vector
##
InstallMethod( AdditiveInverseMutable,
    "for GF2 vector",
    true,
    [ IsRowVector and IsListDefault and IsGF2VectorRep ],
    0,
    ShallowCopy );

InstallMethod( AdditiveInverseSameMutability,
    "for GF2 vector, mutable",
    true,
    [ IsRowVector and IsListDefault and IsGF2VectorRep and IsMutable],
    0,
    ShallowCopy );

InstallMethod( AdditiveInverseSameMutability,
    "for GF2 vector, immutable",
    true,
    [ IsRowVector and IsListDefault and IsGF2VectorRep],
    0,
        function(v)
    if IsMutable(v) then
       TryNextMethod();
    fi;
    return v;
    end );


#############################################################################
##
#M  AdditiveInverse( <gf2vec> ) . . . . . .  additive inverse of a GF2 vector
##
InstallMethod( AdditiveInverse,
    "for GF2 vector",
    true,
    [ IsRowVector and IsListDefault and IsGF2VectorRep ],
    0,
    Immutable );


#############################################################################
##
#M  ZeroOp( <gf2vec> )  . . . . . . . . . . . . . . . mutable zero GF2 vector
##
InstallMethod( ZeroOp,
    "for GF2 vector",
    true,
    [ IsRowVector and IsListDefault and IsGF2VectorRep ],
    0,
    ZERO_GF2VEC );

#############################################################################
##
#M  ZeroSameMutability( <gf2vec> ) . . . . .  same mutability zero GF2 vector
##
InstallMethod( ZeroSameMutability,
    "for GF2 vector, mutable",
    true,
    [ IsRowVector and IsListDefault and IsGF2VectorRep and IsMutable],
    0,
    ZERO_GF2VEC );

InstallMethod( ZeroSameMutability,
    "for GF2 vector, immutable",
    true,
    [ IsRowVector and IsListDefault and IsGF2VectorRep],
        0,
        function(v)
    local z;
    if IsMutable(v) then
        TryNextMethod();
    fi;
    z :=    ZERO_GF2VEC(v);
    MakeImmutable(z);
    return z;
end);


#############################################################################
##
#M  \=( <gf2vec>, <gf2vec> )  . . . . . . . . . . . . equality of GF2 vectors
##
InstallMethod( \=,"for GF2 vectors",IsIdenticalObj,
    [ IsRowVector and IsGF2VectorRep,
      IsRowVector and IsGF2VectorRep ], 0, EQ_GF2VEC_GF2VEC );

#############################################################################
##
#M  \<( <gf2vec>, <gf2vec> )  . . . . . . . . . . . . equality of GF2 vectors
##
InstallMethod( \<,"for GF2 vectors",IsIdenticalObj,
    [ IsRowVector and IsGF2VectorRep,
      IsRowVector and IsGF2VectorRep ], 0, LT_GF2VEC_GF2VEC );


#############################################################################
##
#M  \+( <gf2vec>, <gf2vec> )  . . . . . . . . . . . .  sum of two GF2 vectors
##
InstallMethod( \+,
    "for GF2 vectors",
    IsIdenticalObj,
    [ IsRowVector and IsListDefault and IsGF2VectorRep,
      IsRowVector and IsListDefault and IsGF2VectorRep ],
    0,
    SUM_GF2VEC_GF2VEC );


#############################################################################
##
#M  \-( <gf2vec>, <gf2vec> )  . . . . . . . . . difference of two GF2 vectors
##
InstallMethod( \-,
    "for GF2 vectors",
    IsIdenticalObj,
    [ IsRowVector and IsListDefault and IsGF2VectorRep,
      IsRowVector and IsListDefault and IsGF2VectorRep ],
    0,
    # we are in GF(2)
    SUM_GF2VEC_GF2VEC );


#############################################################################
##
#M  \*( <gf2vec>, <gf2vec> )  . . . . . . . . . .  product of two GF2 vectors
##
InstallMethod( \*,
    "for GF2 vectors",
    IsIdenticalObj,
    [ IsRingElementList and IsListDefault and IsRowVector and IsGF2VectorRep,
      IsRingElementList and IsListDefault and IsRowVector and IsGF2VectorRep ],
    0,
    PROD_GF2VEC_GF2VEC );


#############################################################################
##
#M  \*( <ffe>, <gf2vec> ) . . . . . . . . . . . product of FFE and GF2 vector
##
##  This method is installed with positive rank because it is the
##  specialised method for GF(2) elements and should fall through to
##  the general method for GF(2^k).
##
InstallMethod( \*,
    "for FFE and GF2 vector",
    IsElmsColls,
    [ IsFFE,
      IsRingElementList and IsRowVector and IsGF2VectorRep ],
    10,

function( a, b )
    if a = GF2Zero  then
        return ZeroSameMutability(b);
    elif a = GF2One  then
        if IsMutable(b) then
            return ShallowCopy(b);
        else
            return b;
        fi;
    else
        TryNextMethod();
    fi;
end );



#############################################################################
##
#M  \*( <gf2vec>, <ffe> ) . . . . . . . . . . . product of GF2 vector and FFE
##
##  This method is installed with positive rank because it is the
##  specialised method for GF(2) elements and should fall through to
##  the general method for GF(2^k).
##

InstallMethod( \*,
    "for GF2 vector and FFE",
    IsCollsElms,
    [ IsRingElementList and IsRowVector and IsGF2VectorRep,
      IsFFE ],
    10,

function( a, b )
    if b = GF2Zero  then
        return ZeroSameMutability(a);
    elif b = GF2One  then
        if IsMutable(a) then
            return ShallowCopy(a);
            else
                return a;
            fi;
    else
        TryNextMethod();
    fi;
end );


#############################################################################
##
#M  AddCoeffs( <gf2vec>, <gf2vec>, <mul> )  . . . . . . . .  add coefficients
##
InstallOtherMethod( AddCoeffs,
    "for GF2 vectors and FFE",
    function(a,b,c) return IsIdenticalObj(a,b); end,
    [ IsRowVector and IsGF2VectorRep and IsMutable,
      IsRowVector and IsGF2VectorRep,
      IsFFE ],
    0,
    ADDCOEFFS_GF2VEC_GF2VEC_MULT );


#############################################################################
##
#M  AddCoeffs( <gf2vec>, <gf2vec> ) . . . . . . . . . . . .  add coefficients
##
InstallOtherMethod( AddCoeffs,
    "for GF2 vectors",
    IsIdenticalObj,
    [ IsRowVector and IsGF2VectorRep and IsMutable,
      IsRowVector and IsGF2VectorRep ],
    0,
    ADDCOEFFS_GF2VEC_GF2VEC );


#############################################################################
##
#M  AddCoeffs( <empty-list>, <gf2vec>, <mul> )  . . . . . .  add coefficients
##
InstallOtherMethod( AddCoeffs,
    "for empty list, GF2 vector and FFE",
    true,
    [ IsList and IsEmpty and IsMutable,
      IsRowVector and IsGF2VectorRep,
      IsFFE ],
    0,

function( a, b, c )
    a:=COPY_GF2VEC(a);
    return ADDCOEFFS_GF2VEC_GF2VEC_MULT( a, b, c );
end );



#############################################################################
##
#M  AddCoeffs( <empty-list>, <gf2vec> ) . . . . . . . . . .  add coefficients
##
InstallOtherMethod( AddCoeffs,
    "for empty list, GF2 vector",
    true,
    [ IsList and IsEmpty and IsMutable,
      IsRowVector and IsGF2VectorRep ],
    0,

function( a, b )
    a:=COPY_GF2VEC(a);
    return ADDCOEFFS_GF2VEC_GF2VEC(a,b);
end );


#############################################################################
##
#M  PadCoeffs( <gf2vec>, <len> )  . . . . . . . . . . . expand a GF2 vector
##
InstallMethod( PadCoeffs,
    "for GF2 vector",
    true,
        [ IsMutable and IsRowVector and IsAdditiveElementWithZeroCollection and IsGF2VectorRep,
          IsPosInt ],
        0,
        function(v,len)
    if len > LEN_GF2VEC(v) then
        RESIZE_GF2VEC(v,len);
    fi;
end);

#############################################################################
##
#M  QuotRemCoeffs( <gf2vec>, <len>, <gf2vec>, <len> )
##
InstallMethod( QuotRemCoeffs,
        "GF2 vectors",
        [ IsRowVector and IsGF2VectorRep, IsInt, IsRowVector and IsGF2VectorRep, IsInt],
        QUOTREM_COEFFS_GF2VEC);

#############################################################################
##
#M  NormedRowVector( <v> )
##
InstallMethod( NormedRowVector, "for GF(2) vector", true,
    [ IsRowVector and IsGF2VectorRep and IsScalarCollection ],0,
 # Over GF(2) one can norm only to 1
 x->x);

#############################################################################
##
#M  Length( <list> )  . . . . . . . . . . . . . . . .  length of a GF2 matrix
##
InstallOtherMethod( Length,
    "for GF2 matrix",
    true,
    [ IsMatrix and IsGF2MatrixRep ],
    0,

function( list )
    return list![1];
end );


#############################################################################
##
#M  <list> [ <pos> ] . . . . . . . . . . .  select an element of a GF2 matrix
##
InstallOtherMethod( \[\], "for GF2 matrix",
    [ IsMatrix and IsGF2MatrixRep,
      IsPosInt ],
    ELM_GF2MAT );

InstallMethod( \[\,\], "for GF2 matrix",
    [ IsGF2MatrixRep,
      IsPosInt, IsPosInt ],
    MAT_ELM_GF2MAT );


#############################################################################
##
#M  <gf2mat> [ <pos> ] := <elm> . . . . . . assign an element to a GF2 matrix
##
InstallOtherMethod( \[\]\:\=,
    "for GF2 matrix",
    [ IsList and IsGF2MatrixRep and IsMutable,
      IsPosInt,
      IsObject ],
    ASS_GF2MAT );

InstallOtherMethod( \[\]\:\=,
    "for GF2 matrix",
    [ IsList and IsGF2MatrixRep,
      IsPosInt,
      IsObject ],
    ASS_GF2MAT );

InstallMethod( \[\,\]\:\=,
    "for GF2 matrix",
    [ IsGF2MatrixRep and IsMutable,
      IsPosInt, IsPosInt,
      IsObject ],
    SET_MAT_ELM_GF2MAT );


#############################################################################
##
#M  ASS_LIST( <empty-list>, <pos>, <gf2vec> ) . . . .  start a new GF2 matrix
##
#InstallMethod( ASS_LIST,
#    "for empty plain list and GF2 vector",
#    true,
#    [ IsMutable and IsList and IsPlistRep and IsEmpty,
#      IsPosInt,
#      IsGF2VectorRep ],
#    0,

#function( list, pos, val )
#    if pos = 1 and not IsMutable(val) then
#        list[1] := 1;
#        list[2] := val;
#        SetFilterObj(val, IsLockedRepresentationVector);
#        Objectify( TYPE_LIST_GF2MAT, list );
#    else
#        ASS_PLIST_DEFAULT( list, pos, val );
#    fi;
#end );

#############################################################################
##
#M  UNB_LIST( <gf2mat>, <pos> ) . . . . . . unbind a position of a GF2 matrix
##
InstallOtherMethod( UNB_LIST,
    "for GF2 matrix",
    true,
    [ IsList and IsGF2MatrixRep and IsMutable,
      IsPosInt ],
    0,
    UNB_GF2MAT );

InstallOtherMethod( UNB_LIST,
        "for GF2 matrix",
        true,
        [ IsList and IsGF2MatrixRep,
          IsPosInt ],
        0,
        function(m, pos)
    if IsMutable(m) then
        TryNextMethod();
    elif pos <= Length(m) then
        Error("Unbind: can't unbind an entry of an immutable GF2 Matrix" );
    fi;
end);


#############################################################################
##
#M  PrintObj( <gf2mat> )  . . . . . . . . . . . . . . . .  print a GF2 matrix
##
InstallMethod( PrintObj,
    "for GF2 matrix",
    true,
    [ IsGF2MatrixRep ],
    0,

function( mat )
    local   i, j;
    Print( "\>\>[ \>\>" );
    for i  in [ 1 .. NrRows(mat) ]  do
        if 1 < i  then Print( "\<,\< \>\>" );  fi;
        Print( "\>\>[ \>\>" );
        for j  in [ 1 .. NrCols(mat) ]  do
            if 1 < j  then Print( "\<,\< \>\>" );  fi;
            Print( mat[i,j] );
        od;
        Print( " \<\<\<\<]" );
    od;
    Print( " \<\<\<\<]" );
end );


#############################################################################
##
#M  ViewObj( <gf2mat> )   . . . . . . . . . . . . . . . .   view a GF2 matrix
##
InstallMethod( ViewObj,
    "for GF2 matrix",
    true,
    [ IsMatrix and IsFinite and IsGF2MatrixRep ],
    0,

function( mat )
    if IsMutable(mat)  then
        Print("<a ",NrRows(mat),"x",NrCols(mat)," matrix over GF2>");
    else
        Print( "<an immutable ", NrRows(mat), "x", NrCols(mat),
               " matrix over GF2>" );
    fi;
end );

#############################################################################
##
#M  ShallowCopy( <gf2mat> ) . . . . . .  mutable shallow copy of a GF2 matrix
##
BindGlobal("SHALLOWCOPY_GF2MAT",
function(mat)
    local   copy,  i, len;

    len := mat![1];
    copy := [ len ];
    for i  in [2..len+1] do
        copy[i] := mat![i];
    od;
    Objectify( TYPE_LIST_GF2MAT, copy );
    return copy;
end);

InstallMethod( ShallowCopy,
        "for GF2 matrix",
        true,
        [ IsMatrix and IsGF2MatrixRep ],
        0,
        SHALLOWCOPY_GF2MAT);

InstallOtherMethod(TransposedMat,"GF2 matrix",true,
  [IsMatrix and IsGF2MatrixRep],0,TRANSPOSED_GF2MAT);

InstallOtherMethod(MutableTransposedMat,"GF2 matrix",true,
  [IsMatrix and IsGF2MatrixRep],0,TRANSPOSED_GF2MAT);


#############################################################################
##
#M  AdditiveInverseOp( <gf2mat> ) .  mutable additive inverse of a GF2 matrix
##
InstallMethod( AdditiveInverseOp,
    "for GF2 matrix",
    true,
    [ IsMatrix and IsListDefault and IsGF2MatrixRep ],
        0,
        function(mat)
    local   copy,  i, len;

    len := mat![1];
    copy := [ len ];
    for i  in [2..len+1] do
        copy[i] := ShallowCopy(mat![i]);
        SetFilterObj(copy[i],IsLockedRepresentationVector);
    od;
    Objectify( TYPE_LIST_GF2MAT, copy );
    return copy;
end);

#############################################################################
##
#M  AdditiveInverseSameMutability( <gf2mat> ) .  same mutability additive inverse
##
InstallMethod( AdditiveInverseSameMutability,
    "for GF2 matrix",
    true,
    [ IsMatrix and IsListDefault and IsGF2MatrixRep ],
        0,
        function(mat)
    local   copy,  i, len,r ;

    if not IsMutable(mat) then
        return mat;
    fi;
    len := mat![1];
    copy := [ len ];
    for i  in [2..len+1] do
        r := mat![i];
        if IsMutable(r) then
            copy[i] := ShallowCopy(mat![i]);
            SetFilterObj(copy[i],IsLockedRepresentationVector);
        else
            copy[i] := r;
        fi;
    od;
    Objectify( TYPE_LIST_GF2MAT, copy );
    return copy;
end);



#############################################################################
##
#M  AdditiveInverse( <gf2mat> ) . . . . . .  additive inverse of a GF2 matrix
##
InstallMethod( AdditiveInverse,
    "for GF2 matrix",
    true,
    [ IsMatrix and IsListDefault and IsGF2MatrixRep ],
    0,
    # we are in GF2
    Immutable );


#############################################################################
##
#M  InverseOp( <gf2mat> ) . . . . . . . . . . mutable inverse of a GF2 matrix
##
InstallMethod( InverseOp,
    "for GF2 matrix",
    true,
    [ IsMultiplicativeElementWithInverse and IsOrdinaryMatrix and
      IsSmallList and IsFFECollColl
      and IsGF2MatrixRep ],
    0,
    INV_GF2MAT_MUTABLE );

#############################################################################
##
#M  InverseSameMutability( <gf2mat> ) same mutability inverse of a GF2 matrix
##
InstallMethod( InverseSameMutability,
    "for GF2 matrix",
    true,
    [ IsMultiplicativeElementWithInverse and IsOrdinaryMatrix and
      IsSmallList and IsFFECollColl
      and IsGF2MatrixRep ],
    0,
        INV_GF2MAT_SAME_MUTABILITY );


#############################################################################
##
#M  InverseOp( <list of gf2 vectors> ) .  . . mutable inverse of a GF2 matrix
##

InstallMethod( InverseOp,
    "for plain list of GF2 vectors",
    true,
    [ IsPlistRep and IsFFECollColl and IsMatrix],
    0,
    m->INV_PLIST_GF2VECS_DESTRUCTIVE(List(m, ShallowCopy)) );

#############################################################################
##
#M  InverseSameMutability( <list of gf2 vectors> ) .  same mutability inverse of a GF2 matrix
##

InstallMethod( InverseSameMutability,
    "for plain list of GF2 vectors",
    true,
    [ IsPlistRep and IsFFECollColl and IsMatrix],
        0,
        function(m)
    local inv,i;
    inv := INV_PLIST_GF2VECS_DESTRUCTIVE(List(m, ShallowCopy));
    if inv = TRY_NEXT_METHOD then
        TryNextMethod();
    fi;
    if IsMutable(m) then
        if not IsMutable(m[1]) then
            for i in [1..NrRows(m)] do
                MakeImmutable(inv[i]);
            od;
        fi;
    else
        MakeImmutable(inv);
    fi;
    return inv;
end );


#############################################################################
##
#M  OneOp( <gf2mat> ) . . . . . . . . . . . . . . mutable identity GF2 matrix
##
##  A fully mutable GF2 matrix cannot be in the special compressed rep.
##  so return it as a plain list
##

BindGlobal("GF2IdentityMatrix", function(n, imm)
    local i,id,line,o;
    o := Z(2);
    id := [n];
    for i in [1..n] do
        line := ZERO_GF2VEC_2(n);
        line[i] := o;
        SetFilterObj(line,IsLockedRepresentationVector);
        if imm > 0 then
            MakeImmutable(line);
        fi;
        Add(id, line);
    od;
    if imm > 1 then
        Objectify(TYPE_LIST_GF2MAT_IMM, id);
    else
        Objectify(TYPE_LIST_GF2MAT, id);
    fi;
    return id;
end);




InstallMethod( OneOp,
    "for GF2 Matrix",
    true,
    [ IsOrdinaryMatrix and IsGF2MatrixRep and IsMultiplicativeElementWithOne],
        0,
        function(mat)
    local len;
    len := NrRows(mat);
    if len <> NrCols(mat) then
        return fail;
    fi;
    return GF2IdentityMatrix(len, 0);
end);


#############################################################################
##
#M  One( <gf2mat> ) . . . . . . . . . . . . . . . . . . . identity GF2 matrix
##
InstallMethod( One,
    "for GF2 Matrix",
    true,
    [ IsOrdinaryMatrix and IsGF2MatrixRep and IsMultiplicativeElementWithOne],
    0,
        function(mat)
    local len;
    len := NrRows(mat);
    if len <> NrCols(mat) then
        return fail;
    fi;
    return GF2IdentityMatrix(len, 2);
end );


#############################################################################
##
#M  OneSameMutability( <gf2mat> ) . . . . . . . . . . . . identity GF2 matrix
##
InstallMethod( OneSameMutability,
    "for GF2 Matrix",
    true,
    [ IsOrdinaryMatrix and IsGF2MatrixRep and IsMultiplicativeElementWithOne],
    0,
        function(mat)
    local len,row1;
    len := NrRows(mat);
    if len <> NrCols(mat) then
        return fail;
    fi;
    row1 := mat[1];
    if not IsMutable(mat) then
        return GF2IdentityMatrix(len, 2);
    elif IsMutable(mat) and not IsMutable(row1) then
        return GF2IdentityMatrix(len, 1);
    else
        return GF2IdentityMatrix(len, 0);
    fi;
end );


#############################################################################
##
#M  ZeroOp( <gf2mat> )  . . . . . . . . . . . . . . . mutable zero GF2 matrix
##
##

InstallMethod( ZeroOp,
    "for GF2 Matrix",
    true,
    [ IsMatrix and IsListDefault and IsGF2MatrixRep ],
    0,

function( mat )
    local   new,  zero,  i;

    new := [ Length(mat) ];
    if 0 < new[1]   then
        for i in [ 1 .. new[1] ]  do
            zero := ZeroOp(mat[1]);
            SetFilterObj(zero, IsLockedRepresentationVector);
            Add( new, zero );
        od;
    fi;
    Objectify( TYPE_LIST_GF2MAT, new );
    return new;
end );


#############################################################################
##
#M  ZeroSameMutability( <gf2mat> ) . . . . . . . . . . .  matching mutability
##
InstallMethod( ZeroSameMutability,
    "for GF2 Matrix",
    true,
    [ IsMatrix and IsListDefault and IsGF2MatrixRep ],
    0,

function( mat )
    local   new,  zero,  i;

    new := [ Length(mat) ];
    if 0 < new[1]   then
        if  IsMutable(mat![2]) then
            for i in [ 1 .. new[1] ]  do
                zero := ZeroSameMutability(mat![2]);
                SetFilterObj(zero, IsLockedRepresentationVector);
                Add( new, zero );
            od;
        else
            zero := ZeroSameMutability(mat![2]);
            SetFilterObj(zero, IsLockedRepresentationVector);
            for i in [ 1 .. new[1] ]  do
                Add( new, zero );
            od;
        fi;
    fi;
    Objectify( TypeObj(mat), new );
    return new;
end );



#############################################################################
##
#M  Zero( <gf2mat> )  . . . . . . . . . . . . . . . . . . . . zero GF2 matrix
##
InstallMethod( Zero,
    "for GF2 Matrix",
    true,
    [ IsMatrix and IsListDefault and IsGF2MatrixRep ],
    0,

function( mat )
    local   new,  zero,  i;

    new := [ Length(mat) ];
    if 0 < new[1]   then
        zero := Zero(mat[1]);
        SetFilterObj(zero, IsLockedRepresentationVector);
        for i in [ 1 .. new[1] ]  do
            Add( new, zero );
        od;
    fi;
    Objectify( TYPE_LIST_GF2MAT_IMM, new );
    return new;
end );


#############################################################################
##
#M  \+( <gf2mat>, <gf2mat> )  . . .  . . sum of a GF2 matrix and a GF2 matrix
##

InstallMethod( \+,
    "for GF2 matrix and GF2 matrix",
    IsIdenticalObj,
    [ IsMatrix and IsListDefault and IsGF2MatrixRep,
      IsMatrix and IsListDefault and IsGF2MatrixRep ],
    0,
    SUM_GF2MAT_GF2MAT );

#############################################################################
##
#M  \<( <gf2mat>, <gf2mat> )  . . . . . . . . . . .comparison of GF2 matrices
##

InstallMethod( \<,
    "for GF2 matrix and GF2 matrix",
    IsIdenticalObj,
    [ IsMatrix and IsListDefault and IsGF2MatrixRep,
      IsMatrix and IsListDefault and IsGF2MatrixRep ],
    0,
        LT_GF2MAT_GF2MAT);

#############################################################################
##
#M  \=( <gf2mat>, <gf2mat> )  . . . . . . . . . . .comparison of GF2 matrices
##

InstallMethod( \=,
    "for GF2 matrix and GF2 matrix",
    IsIdenticalObj,
    [ IsMatrix and IsListDefault and IsGF2MatrixRep,
      IsMatrix and IsListDefault and IsGF2MatrixRep ],
    0,
        EQ_GF2MAT_GF2MAT);


#############################################################################
##
#M  \-( <gf2mat>, <gf2mat> )  . . .  . . sum of a GF2 matrix and a GF2 matrix
##
InstallMethod( \-,
    "for GF2 matrix and GF2 matrix",
    IsIdenticalObj,
    [ IsMatrix and IsListDefault and IsGF2MatrixRep,
      IsMatrix and IsListDefault and IsGF2MatrixRep ],
    0,
    # we are in GF2
    SUM_GF2MAT_GF2MAT );


#############################################################################
##
#M  \*( <gf2vec>, <gf2mat> )  . . .  product of a GF2 vector and a GF2 matrix
##
InstallMethod( \*,
    "for GF2 vector and GF2 matrix",
    true,
    [ IsRingElementList and IsRowVector and IsListDefault and IsGF2VectorRep,
      IsMatrix and IsListDefault and IsGF2MatrixRep ],
    0,
    PROD_GF2VEC_GF2MAT );


#############################################################################
##
#M  <vec>*<mat> . . . general method for GF2 vector and a matrix
##                    works fast when the matrix is a plain list
##                    of compressed GF2 vectors, otherwise falls through
##

InstallMethod(\*, "for a GF2 vector and a compatible matrix",
        IsElmsColls, [IsRowVector and IsGF2VectorRep and IsSmallList
                and IsRingElementList,
                IsRingElementTable and IsPlistRep], 0,
        PROD_GF2VEC_ANYMAT);


#############################################################################
##
#M  \*( <gf2mat>, <gf2vec> )  . . .  product of a GF2 matrix and a GF2 vector
##
InstallMethod( \*,
    "for GF2 matrix and GF2 vector",
    true,
    [ IsMatrix and IsListDefault and IsGF2MatrixRep,
      IsRowVector and IsListDefault and IsGF2VectorRep ],
    0,
    PROD_GF2MAT_GF2VEC );


#############################################################################
##
#M  \*( <gf2mat>, <gf2mat> )  . . .  product of a GF2 matrix and a GF2 matrix
##
InstallMethod( \*,
    "for GF2 matrix and GF2 matrix",
    IsIdenticalObj,
    [ IsMatrix and IsListDefault and IsGF2MatrixRep,
      IsMatrix and IsListDefault and IsGF2MatrixRep ],
    0,

        PROD_GF2MAT_GF2MAT );

#############################################################################
##
#M  \*( <gf2elm>, <gf2mat> )  . . .  product of a GF2 element and a GF2 matrix
##
InstallMethod( \*,
    "for GF2 element and GF2 matrix",
    IsElmsCollColls,
    [ IsFFE,
      IsMatrix and IsListDefault and IsGF2MatrixRep ],
    0,
        function(s,m)
    if s = Z(2) then
        return AdditiveInverseSameMutability(m);
    elif IsZero(s) then
        return ZeroSameMutability(m);
    else
        TryNextMethod();
    fi;
end);

#############################################################################
##
#M  \*( <gf2mat>, <gf2elm> )  . . .  product of a GF2 matrix  and a GF2 element
##
InstallMethod( \*,
    "for GF2 matrix and GF2 element",
    IsCollCollsElms,
        [       IsMatrix and IsListDefault and IsGF2MatrixRep,
                IsFFE ],
    0,
        function(m,s)
    if s = Z(2) then
        return AdditiveInverseSameMutability(m);
    elif IsZero(s) then
        return ZeroSameMutability(m);
    else
        TryNextMethod();
    fi;
end);

#############################################################################
##
#F  ConvertToVectorRep(<v>)
##

BindGlobal("LOCAL_COPY_GF2", GF(2));
BindGlobal("SMALL_PRIME_POWERS", Immutable(Filtered([2..256], IsPrimePowerInt)));

InstallGlobalFunction(ConvertToVectorRepNC,function( arg )
    local v, q, vc, common, field, q0;
    if Length(arg) < 1 then
        Error("ConvertToVectorRep: one or two arguments required");
    fi;
    v := arg[1];
#
# Handle fast, certain cases where there is no work. Microseconds count here
#
    if IsGF2VectorRep(v) and (Length(arg) = 1 or arg[2] = 2 or arg[2] = LOCAL_COPY_GF2) then
        return 2;
    fi;

    if Is8BitVectorRep(v) then
        q0 := Q_VEC8BIT(v);
        if Length(arg) = 1 then
            return q0;
        fi;
        if IsPosInt(arg[2]) then
            q := arg[2];
        elif IsField(arg[2]) then
            q := Size(arg[2]);
        else
            return fail;
        fi;
        if q = q0 then
            return q;
        fi;
        if IsLockedRepresentationVector(v) then
            Error("Vector is locked over current field");
        else
            if q = 2 then
                CONV_GF2VEC(v);
                return 2;
            elif q <= 256 then
                if not q in SMALL_PRIME_POWERS then
                    return fail;
                fi;
                CONV_VEC8BIT(v,q);
                return q;
            else
                if q mod q0 <> 0 then
                    Error("New field size incompatible with vector entries");
                else
                    PLAIN_VEC8BIT(v);
                    return q;
                fi;

            fi;
        fi;
    fi;


    if (Length(v) = 0 and Length(arg) = 1) or
      (Length(v) >0 and not IsRowVector(v))  then
        return fail;
    fi;

    # if the representation of v is already locked, then
    # we ignore a second arguments and just report on the vector

    if IsLockedRepresentationVector(v) then
        if IsGF2VectorRep(v) then
            q := 2;
        elif Is8BitVectorRep(v) then
            q := Q_VEC8BIT(v);
        else
            Error("vector is locked in an unknown representation");
        fi;
        if not IsInt(arg[2]) then
            arg[2] := Size(arg[2]);
        fi;
        if Length(arg) = 2 and q <> arg[2] then
          Info(InfoWarning, 1,
          "ConvertToVectorRep: locked vector not converted to different field");
        fi;
        return q;
    fi;


    #
    # Ask the kernel to check the list for us.
    # We have to do this, even in an NC version because the list might contain
    # elements of large finite fields
    #

    if not IS_VECFFE(v) then
        if IsFFECollection(v) then
            # now we might have some elements in a large field representation
            # or possibly a totally bad list
            vc := ShallowCopy(v);
            common := FFECONWAY.WriteOverSmallestCommonField(vc);
            #
            # FFECONWAY.WriteOverSmallestCommonField returns an integer or fail.
            # When integer is returned, it also may modify entries of vc
            #
            if common = fail or common  > 256 then
                #
                # vector needs a field > 256, so can't be compressed
                # or vector contains non-ffes or no common characteristic
                #
                return fail;
            fi;
            # Switching the object below can change the mutability of v, so we
            # make sure that if v is immutable it stays immutable.
            if not IsMutable(v) then
                MakeImmutable(vc);
            fi;
            # We need to force the switch, because v (and vc) might
            # be in the public region, with all caveats that might have.
            # ConvertToVectorRep should not be used in HPC-GAP
            FORCE_SWITCH_OBJ(v,vc); # horrible hack.
        else
            return fail;
        fi;
    else
        common := COMMON_FIELD_VECFFE(v);
    fi;

    #
    # see if the user gave us q
    #
    if Length(arg) > 1 then
        field := arg[2];
        if IsPosInt(field) then
            q := field;
            Assert(2,IsPrimePowerInt(q));
        elif IsField(field) then
            q := Size(field);
        else
            Error("q not a field or positive integer");
        fi;
    else
        q := fail;
    fi;

    #
    # if there is a field, we go to work
    #
    if q = fail then
        if common = fail then
            return fail;
        fi;
        if not IsPrimeInt(common) then
            common := SMALLEST_FIELD_VECFFE(v);
        fi;
        if common = 2 then
            CONV_GF2VEC(v);
            return 2;
        elif common <= 256 then
            CONV_VEC8BIT(v,common);
            return common;
        else
            return fail;
        fi;
    elif q = 2 then
        if common > 2 and common mod 2 = 0 then
            common := SMALLEST_FIELD_VECFFE(v);
        fi;
        if common <> 2 then
            Error("ConvertToVectorRepNC: Vector cannot be written over GF(2)");
        fi;
        CONV_GF2VEC(v); # safe to call this even with an invalid argument
        return 2;
    elif q <= 256 then
        if common <> q then
            if IsPlistRep(v) and  GcdInt(common,q) > 1  then
                common := SMALLEST_FIELD_VECFFE(v);
            fi;
            if common ^ LogInt(q, common) <> q then
                Error("ConvertToVectorRepNC: Vector cannot be written over GF(",q,")");
            fi;
        fi;
        Assert(2, ForAll(v, elm -> elm in GF(q)));
        CONV_VEC8BIT(v,q);
        return q;
    else
        return fail;
    fi;
end);


#############################################################################
##
#F  CopyToVectorRep( <v>, <q> )
##
InstallGlobalFunction(CopyToVectorRep,function( v, q )
    local vc, common, res;

    # Handle fast, certain cases where there is no work. Microseconds count here

    if Length(v) = 0 then
        return v;
    fi;

    if IsGF2VectorRep(v) and q=2 then
        if IsMutable(v) then
          return(ShallowCopy(v));
        else
          return v;
        fi;
    fi;

    if Is8BitVectorRep(v) then
        if q = Q_VEC8BIT(v) then
            if IsMutable(v) then
                return(ShallowCopy(v));
            else
                return v;
            fi;
        fi;
    fi;

    # Ask the kernel to check the list for us.
    # We have to do this, even in an NC version because the list might contain
    # elements of large finite fields.
    # Calling IS_VECFFE may force a full inspection of the list.

    if not IS_VECFFE(v) then
        # TODO: no need of the next 'if' block in the NC-version
        if IsFFECollection(v) then
            # Now we might have some elements in a large field representation
            # or possibly a totally bad list. We will examine the shallow copy
            # of v to avoid side effects when CopyToVectorRep modifies v and
            # then returns fail
            vc := ShallowCopy(v);
            common := FFECONWAY.WriteOverSmallestCommonField(vc);
            #
            # FFECONWAY.WriteOverSmallestCommonField returns an integer or fail.
            # When it returns an integer, it may modify individual entries of vc
            #
            if common = fail or common  > 256 then
                #
                # vector needs a field > 256, so can't be compressed
                # or vector contains non-ffes or no common characteristic
                #
                return fail; # v cannot be written over GF(q)
            fi;
            if not IsMutable(v) then
                MakeImmutable(vc);
            fi;
        else
            return fail; # v cannot be written over GF(q)
        fi;
    else
        common := COMMON_FIELD_VECFFE(v);
        vc := v;
    fi;

    if q = 2 then
        Assert(2, ForAll(vc, elm -> elm in GF(2)));
        if common > 2 and common mod 2 = 0 then
            common := SMALLEST_FIELD_VECFFE(vc);
        fi;
        if common <> 2 then
            Error("CopyToVectorRep: Vector cannot be written over GF(2)");
        fi;
        res := COPY_GF2VEC(vc);
        if not IsMutable(v) then MakeImmutable(res); fi;
        return res;
    elif q <= 256 then
        if common <> q then
            Assert(2, ForAll(vc, elm -> elm in GF(q)));
            if IsPlistRep(vc) and  GcdInt(common,q) > 1  then
                common := SMALLEST_FIELD_VECFFE(vc);
            fi;
            if common ^ LogInt(q, common) <> q then
                Error("CopyToVectorRep: Vector cannot be written over GF(",q,")");
            fi;
        fi;
        res := COPY_VEC8BIT(vc,q);
        if not IsMutable(v) then MakeImmutable(res); fi;
        return res;
    else
        return fail; # vector cannot be written over GF(q)
    fi;
end);


#############################################################################
##
#F  CopyToVectorRepNC( <v>, <q> )
##
##  This is the NC-version of CopyToVectorRep. It is forbidden to call it
##  unless v is a plain list or a row vector, q<=256 is a valid size of a
##  finite field, and all elements of v lie in this field.
##
InstallGlobalFunction(CopyToVectorRepNC,function( v, q )
    local common, res;

    # Handle fast, certain cases where there is no work. Microseconds count here

    if Length(v) = 0 then
        return v;
    fi;

    if IsGF2VectorRep(v) and q=2 then
        if IsMutable(v) then
          return(ShallowCopy(v));
        else
          return v;
        fi;
    fi;

    if Is8BitVectorRep(v) then
        if q = Q_VEC8BIT(v) then
            if IsMutable(v) then
                return(ShallowCopy(v));
            else
                return v;
            fi;
        fi;
    fi;

    # Calling COMMON_FIELD_VECFFE may force a full inspection of the list.
    common := COMMON_FIELD_VECFFE(v);
    if common = fail then
        common := SMALLEST_FIELD_VECFFE(v);
        if common = fail then
            Error("CopyToVectorRepNC: Vector cannot be written over GF(",q,").\n",
                  "You may try to use CopyToVectorRep instead\n");
        fi;

    fi;

    if q = 2 then
        Assert(2, ForAll(v, elm -> elm in GF(2)));
        if common > 2 and common mod 2 = 0 then
            common := SMALLEST_FIELD_VECFFE(v);
        fi;
        if common <> 2 then
            Error("CopyToVectorRepNC: Vector cannot be written over GF(2)");
        fi;
        res := COPY_GF2VEC(v);
        if not IsMutable(v) then MakeImmutable(res); fi;
        return res;
    elif q <= 256 then
        if common <> q then
            Assert(2, ForAll(v, elm -> elm in GF(q)));
            if IsPlistRep(v) and  GcdInt(common,q) > 1  then
                common := SMALLEST_FIELD_VECFFE(v);
            fi;
            if common ^ LogInt(q, common) <> q then
                Error("CopyToVectorRepNC: Vector cannot be written over GF(",q,")");
            fi;
        fi;
        res :=COPY_VEC8BIT(v,q);
        if not IsMutable(v) then MakeImmutable(res); fi;
        return res;
    else
        Error("CopyToVectorRepNC: Vector cannot be written over GF(",q,")");
    fi;
end);


#############################################################################
##
#F  ImmutableMatrix( <field>, <matrix> [,<change>] )
##
BindGlobal("DoImmutableMatrix", function(field,matrix,change)
local sf, rep, ind, ind2, row, i,big,l,nr;
  if IsMatrixObj(matrix) then
    # result is a matrix object iff 'matrix' is
    if field=BaseDomain(matrix) then
      return Immutable(matrix);
    else
      return ImmutableMatrix(field,Unpack(matrix));
    fi;
  elif not (IsPlistRep(matrix) or IsGF2MatrixRep(matrix) or
    Is8BitMatrixRep(matrix)) then
    # if empty or not list based, simply return `Immutable'.
    return Immutable(matrix);
  fi;
  if IsPosInt(field) then
    sf:=field;
  elif IsField(field) then
    sf:=Size(field);
  elif IsZmodnZObjNonprimeCollection(field) then
    # slight abuse of ``field'' variable name
    sf:=Size(field);
  else
    # not a field
    return Immutable(matrix);
  fi;

  big:=sf>256 or sf=0 or not IsFFECollColl(matrix);

  # the representation we want the rows to be in
  if sf=2 then
    rep:=IsGF2VectorRep;
  elif not big then
    rep:=function(v) return Is8BitVectorRep(v) and Q_VEC8BIT(v) = sf; end;
  else
    rep:=IsPlistRep;
  fi;

  # cannot use NrRows consistently, as input might be mixed format
  if IsList(matrix) then
    nr:=Length(matrix);
  else
    nr:=NrRows(matrix);
  fi;

  # get the indices of the rows that need changing the representation.
  ind:=[]; # rows to convert
  ind2:=[]; # rows to rebuild
  for i in [1..nr] do
    if not rep(matrix[i]) then
      if big or IsLockedRepresentationVector(matrix[i])
        or (IsMutable(matrix[i]) and not change) then
        Add(ind2,i);
      else
        # wrong rep, but can be converted
        Add(ind,i);
      fi;
    elif (IsMutable(matrix[i]) and not change) then
      # right rep but wrong mutability
      Add(ind2,i);
    fi;
  od;

  # do we need to rebuild outer matrix layer?
  if not IsMutable(matrix) # matrix was immutable
    or (IsMutable(matrix) and not change) # matrix was mutable
    or (Length(ind2)>0 and   # we want to change rows
      not IsMutable(matrix)) #but cannot change entries
    or (Is8BitMatrixRep(matrix) # matrix is be compact rep
       and (Length(ind)>0 or Length(ind2)>0) ) # and we change rows
       then
    l:=matrix;
    matrix:=[];
    for i in l do
      Add(matrix,i);
    od;
  fi;

  # rebuild some rows
  if IsZmodnZObjNonprimeCollection(field) then
    big:=true;
  elif big then
    if sf<>infinity and IsPrimeInt(sf) and sf>MAXSIZE_GF_INTERNAL then
      if not (IsMatrixObj(matrix) and not IsMutable(matrix)) then
        if field=sf then field:=Integers mod sf;fi;
        for i in ind2 do
          matrix[i]:=List(matrix[i],j->j); # plist conversion
        od;
      fi;
    else
      for i in ind2 do
        matrix[i]:=List(matrix[i],j->j); # plist conversion
      od;
    fi;
  else
    for i in ind2 do
      row := CopyToVectorRep(matrix[i], sf);
      if row <> fail then
        matrix[i] := row;
      fi;
    od;
    for i in ind do
      matrix[i]:=CopyToVectorRep(matrix[i],sf);
    od;
  fi;

  MakeImmutable(matrix);
  if not big and sf=2 and not IsGF2MatrixRep(matrix) then
    CONV_GF2MAT(matrix);
  elif not big and sf>2 and sf<=256 and not Is8BitMatrixRep(matrix) then
    CONV_MAT8BIT(matrix,sf);
  fi;
  return matrix;
end);

InstallOtherMethod( ImmutableMatrix,"general,2",
[IsObject,IsMatrixOrMatrixObj],0,
function(f,m)
  return DoImmutableMatrix(f,m,false);
end);

InstallOtherMethod( ImmutableMatrix,"List of vectors",
[IsObject,IsList],0,
function(f,m)
  if not ForAll(m,x->IsList(x) or IsVector(x)) then TryNextMethod();fi;
  return DoImmutableMatrix(f,m,false);
end);

InstallOtherMethod(ImmutableMatrix,"general,3",[IsObject,IsMatrixOrMatrixObj,IsBool],0,
  DoImmutableMatrix);

InstallOtherMethod( ImmutableMatrix,"field,8bit",[IsField,Is8BitMatrixRep],0,
function(f,m)
  if Q_VEC8BIT(m[1])<>Size(f) then
    TryNextMethod();
  fi;
  return Immutable(m);
end);

InstallOtherMethod( ImmutableMatrix,"field,gf2",[IsField,IsGF2MatrixRep],0,
function(f,m)
  if 2<>Size(f) then
    TryNextMethod();
  fi;
  return Immutable(m);
end);

InstallOtherMethod( ImmutableMatrix,"fieldsize,8bit",[IsPosInt,Is8BitMatrixRep],0,
function(f,m)
  if Q_VEC8BIT(m[1])<>f then
    TryNextMethod();
  fi;
  return Immutable(m);
end);

InstallOtherMethod( ImmutableMatrix,"fieldsize,gf2",[IsPosInt,IsGF2MatrixRep],0,
function(f,m)
  if 2<>f then
    TryNextMethod();
  fi;
  return Immutable(m);
end);

InstallOtherMethod( ImmutableMatrix,"empty",[IsObject,IsEmpty],0,
function(f,m)
  return Immutable(m);
end);

InstallOtherMethod( ImmutableMatrix,"transposed empty",[IsObject,IsList],0,
function(f,m)
  if not ForAll(m,i->IsList(i) and Length(i)=0) then
    TryNextMethod();
  fi;
  return Immutable(m);
end);


#############################################################################
##
#F  ImmutableVector( <field>, <vector> )
##
InstallMethod( ImmutableVector,"general,2",[IsObject,IsRowVector],0,
function(f,v)
  local v2;
  if not IsInt(f) then f := Size(f); fi;
  # 'IsRowVector' implies 'IsList'.
  # We are not allowed to return a non-list,
  # thus we are not allowed to call 'Vector'.
  # Since there is a method for 'IsVectorObj' as the second argument,
  # we do not deal with proper vector objects here.
  if f <= 256 then
    v2 := CopyToVectorRep(v,f);
    if v2 <> fail then v := v2; fi;
  fi;
  return Immutable(v);
end);

InstallOtherMethod( ImmutableVector,"vectorObj,2",[IsObject,IsVectorObj],0,
function(f,v)
  return MakeImmutable( ChangedBaseDomain( v, f ) );
end);

InstallOtherMethod( ImmutableVector,"general,3",[IsObject,IsRowVector,IsBool],0,
function(f,v,change)
  local v2;
  if not IsInt(f) then f := Size(f); fi;
  if f <= 256 then
    v2 := CopyToVectorRep(v,f);
    if v2 <> fail then v := v2; fi;
  fi;
  return Immutable(v);
end);

InstallOtherMethod( ImmutableVector,"field,8bit",[IsField,Is8BitVectorRep],0,
function(f,v)
  if Q_VEC8BIT(v)<>Size(f) then
    TryNextMethod();
  fi;
  return Immutable(v);
end);

InstallOtherMethod( ImmutableVector,"field,gf2",[IsField,IsGF2VectorRep],0,
function(f,v)
  if 2<>Size(f) then
    TryNextMethod();
  fi;
  return Immutable(v);
end);

InstallOtherMethod( ImmutableVector,"fieldsize,8bit",[IsPosInt,Is8BitVectorRep],0,
function(f,v)
  if Q_VEC8BIT(v)<>f then
    TryNextMethod();
  fi;
  return Immutable(v);
end);

InstallOtherMethod( ImmutableVector,"fieldsize,gf2",[IsPosInt,IsGF2VectorRep],0,
function(f,v)
  if 2<>f then
    TryNextMethod();
  fi;
  return Immutable(v);
end);

InstallOtherMethod( ImmutableVector,"empty",[IsObject,IsEmpty],0,
function(f,v)
  return Immutable(v);
end);

#############################################################################
##
#M  MultVector( <vl>, <mul>)
##

InstallOtherMethod( MultVector, "for GF(2) vector and char 2 scalar",
        IsCollsElms, [IsGF2VectorRep and IsRowVector and IsMutable,
                IsFFE], 0,
        MULT_VECTOR_GF2VECS_2);

#############################################################################
##
#M  PositionNot( <vec>, GF2Zero )
#M  PositionNot( <vec>, GF2Zero, 0)
##
InstallOtherMethod( PositionNot, "for GF(2) vector and 0*Z(2)",
        IsCollsElms, [IsGF2VectorRep and IsRowVector , IsFFE and
                IsZero], 0,
        POSITION_NONZERO_GF2VEC);

InstallMethod( PositionNot, "for GF(2) vector and 0*Z(2) and offset",
        IsCollsElmsX, [IsGF2VectorRep and IsRowVector , IsFFE and
                IsZero, IsInt], 0,
        function(v,z,z1)
    return POSITION_NONZERO_GF2VEC3(v,z,z1);
end);

#############################################################################
##
#M  Append( <vecl>, <vecr> )
##

InstallMethod( Append, "for GF2 vectors",
        true, [IsGF2VectorRep and IsMutable and IsList,
               IsGF2VectorRep and IsList], 0,
        APPEND_GF2VEC);

#############################################################################
##
#M  ShallowCopy( <vec> ) . . . for GF2 vectors
##
InstallMethod( ShallowCopy,
        "for GF2 vectors",
        true, [ IsGF2VectorRep and IsList and IsRowVector ], 0,
        SHALLOWCOPY_GF2VEC);

#############################################################################
##
#M  PositionNonZero( <vec> )
##
InstallOtherMethod(PositionNonZero, "for GF(2) vector",true,
        [IsGF2VectorRep and IsRowVector],0,
  # POSITION_NONZERO_GF2VEC ignores the second argument
  v-> POSITION_NONZERO_GF2VEC(v,0));

InstallOtherMethod(PositionNonZero, "for GF(2) vector and offset",true,
        [IsGF2VectorRep and IsRowVector, IsInt],0,
        # POSITION_NONZERO_GF2VEC3 ignores the second argument
        function(v, from)
    return  POSITION_NONZERO_GF2VEC3(v,0,from);
end);

#############################################################################
##
#M  PositionNonZero( <vec> )
##
InstallOtherMethod(PositionNonZero,
  "General method for a row vector",
  true,[IsRowVector],0,
  function(vec)
  local i,z;
  if Length(vec)=0 then return 1;fi;
  z:=Zero(vec[1]);
  for i in [1..Length(vec)] do
    if vec[i]<>z then return i;fi;
  od;
  return Length(vec)+1;
end);


#############################################################################
##
#M  NumberFFVector(<<vec>,<sz>)
##
InstallMethod(NumberFFVector,"GF2-Vector",true,
  [IsGF2VectorRep and IsRowVector and IsFFECollection,IsPosInt],0,
function(v,n)
  if n<>2 then TryNextMethod();fi;
  return NUMBER_GF2VEC(v);
end);

#############################################################################
##
#M  NumberFFVector(<vec>,<sz>)
##
InstallMethod(NumberFFVector,"uncompressed vecffe",
  [IsRowVector and IsFFECollection,IsPosInt],
        function(v,n)
    local qels, sy, p, x;
    qels:= EnumeratorSorted( GF(n) );
    sy := 0;
    for x in v do
        p := Position(qels, x);
        if p = fail then
            Info(InfoWarning,2,
              "NumberFFVector: Vector not over specified field");
            return fail;
        fi;
        sy := n*sy + (p-1);
    od;
    return sy;
end);

#############################################################################
##
#M  IsSubset(<finfield>,<gf2vec>)
##
InstallMethod(IsSubset,"field, 8bit-vector",IsIdenticalObj,
  [ IsField and IsFinite and IsFFECollection,
    IsGF2VectorRep and IsRowVector and IsFFECollection],0,
function(F,v)
  # the family ensures the field is in the correct characteristic.
  return true;
end);


#############################################################################
##
#M  DefaultFieldOfMatrix( <ffe-mat> )
##
InstallMethod( DefaultFieldOfMatrix,
    "method for a matrix over GF(2)", true,
    [ IsMatrix and IsFFECollColl and IsGF2MatrixRep ], 0,
function( mat )
  return GF(2);
end );

#############################################################################
##
#M  DegreeFFE( <ffe-mat> )
##
InstallOtherMethod( DegreeFFE,
    "method for a matrix over GF(2)", true,
    [ IsMatrix and IsFFECollColl and IsGF2MatrixRep ], 0,
function( mat )
  return 1;
end );

#############################################################################
##
#M  DegreeFFE( <vector> )
##
InstallOtherMethod( DegreeFFE, "for GF(2) vectors", true,
    [ IsRowVector and IsFFECollection and IsGF2VectorRep ], 0, v->1);


#############################################################################
##
#M  LeftShiftRowVector( <vec>, <shift> )
##
InstallMethod( LeftShiftRowVector, "gf2 vector", true,
        [IsMutable and IsRowVector and IsGF2VectorRep,
         IsPosInt], 0,
        SHIFT_LEFT_GF2VEC);

#############################################################################
##
#M  RightShiftRowVector( <vec>, <shift>, <zero> )
##
InstallMethod( RightShiftRowVector, "gf2 vector, fill with zeros", IsCollsXElms,
        [IsMutable and IsRowVector and IsGF2VectorRep,
         IsPosInt,
         IsFFE and IsZero], 0,
        SHIFT_RIGHT_GF2VEC);

#############################################################################
##
#M  ShrinkRowVector( <vec> )

InstallMethod( ShrinkRowVector, "GF2 vector", true,
        [IsMutable and IsRowVector and IsGF2VectorRep ],
        0,
        function(vec)
    local r;
    r := RIGHTMOST_NONZERO_GF2VEC(vec);
    RESIZE_GF2VEC(vec, r);
end);

#############################################################################
##
#M  RemoveOuterCoeffs( <vec>, <zero> )
##

InstallMethod( RemoveOuterCoeffs, "gf2vec and zero", IsCollsElms,
        [ IsMutable and IsGF2VectorRep and IsRowVector, IsFFE and
          IsZero], 0,
        function (v,z)
    local shift;
    shift := POSITION_NONZERO_GF2VEC(v,z) -1;
    if shift <> 0 then
        SHIFT_LEFT_GF2VEC( v, shift);
    fi;
    if v <> [] then
        RESIZE_GF2VEC(v, RIGHTMOST_NONZERO_GF2VEC(v));
    fi;
    return shift;
end);

#############################################################################
##
#M  ProductCoeffs( <vec>, <len>, <vec>, <len>)
##
##

InstallMethod( ProductCoeffs, "GF2 vectors, kernel method", IsFamXFamY,
        [IsGF2VectorRep and IsRowVector, IsInt, IsGF2VectorRep and
         IsRowVector, IsInt ], 0,
        PROD_COEFFS_GF2VEC);

InstallOtherMethod( ProductCoeffs, "Gf2 vectors, kernel method (2 arg)",
        IsIdenticalObj,
        [IsGF2VectorRep and IsRowVector, IsGF2VectorRep and
         IsRowVector ], 0,
        function(v,w)
    return PROD_COEFFS_GF2VEC(v, Length(v), w, Length(w));
end);

#############################################################################
##
#M  ReduceCoeffs( <vec>, <len>, <vec>, <len>)
##
##

InstallMethod( ReduceCoeffs, "GF2 vectors, kernel method", IsFamXFamY,
        [IsGF2VectorRep and IsRowVector and IsMutable, IsInt, IsGF2VectorRep and
         IsRowVector, IsInt ], 0,
        REDUCE_COEFFS_GF2VEC);

InstallOtherMethod( ReduceCoeffs, "Gf2 vectors, kernel method (2 arg)",
        IsIdenticalObj,
        [IsGF2VectorRep and IsRowVector and IsMutable, IsGF2VectorRep and
         IsRowVector ], 0,
        function(v,w)
    return REDUCE_COEFFS_GF2VEC(v, Length(v), w, Length(w));
end);

#############################################################################
##
#M PowerModCoeffs( <vec1>, <len1>, <exp>, <vec2>, <len2> )
##

InstallMethod( PowerModCoeffs, "for gf2vectors", IsFamXYFamZ,
        [IsGF2VectorRep and IsRowVector, IsInt, IsPosInt,
         IsGF2VectorRep and IsRowVector, IsInt], 0,
        function( v, lv, exp, w, lw)

    local pow, lpow, bits, i;
    if exp = 1 then
        pow := ShallowCopy(v);
        ReduceCoeffs(pow,lv,w,lw);
        return pow;
    fi;
    pow := v;
    lpow := lv;
    bits := [];
    while exp > 0 do
        Add(bits, exp mod 2);
        exp := QuoInt(exp,2);
    od;
    bits := Reversed(bits);
    for i in [2..Length(bits)] do
        pow := PROD_COEFFS_GF2VEC(pow,lpow, pow, lpow);
        lpow := Length(pow);
        lpow := REDUCE_COEFFS_GF2VEC( pow, lpow, w, lw);
        if lpow = 0 then
            return pow;
        fi;
        if bits[i] = 1 then
            pow := PROD_COEFFS_GF2VEC(pow, lpow, v, lv);
            lpow := Length(pow);
            lpow := REDUCE_COEFFS_GF2VEC( pow, lpow, w, lw);
            if lpow = 0 then
                return pow;
            fi;
        fi;
    od;
    return pow;
end);

#############################################################################
##
#M  DomainForAction( <pnt>, <acts> )
##
InstallMethod(DomainForAction,"FFE vector/matrix",IsElmsCollCollsX,
  # for technical reasons a matrix list is not automatically
  # IsMatrixCollection -- thus we cannot use this filter here. AH

  #T this method is only installed for finite fields. There ought to be a
  #T method for finite rings and there could be one for infinite fields. AH
  [IsVector and IsFFECollection,IsList,IsFunction],0,
function(pnt,acts,act)
  if (not ForAll(acts,IsMatrix)) or
    (act<>OnPoints and act<>OnLines and act<>OnRight
                   and act<>OnSubspacesByCanonicalBasisConcatenations) or
     CollectionsFamily(CollectionsFamily(FamilyObj(pnt)))<>FamilyObj(acts) then
    TryNextMethod(); # strange operation, might extend the domain
  fi;
  return NaturalActedSpace(acts,[pnt]);
#  if Length(pnt)=0 or Length(acts)=0 then
#    return fail;
#  fi;
#  l:=Concatenation(acts);
#  Add(l,pnt);
#  f:=DefaultFieldOfMatrix(l);
#  if f = fail then
#    return fail;
#  fi;
#  return f^Length(pnt);
end);

#############################################################################
##
#M  DomainForAction( <pnt>, <acts> )
##
InstallMethod(DomainForAction,"matrix/matrix",IsElmsCollsX,
  # for technical reasons a matrix list is not automatically
  # IsMatrixCollection -- thus we cannot use this filter here. AH

  #T this method is only installed for finite fields. There ought to be a
  #T method for finite rings and there could be one for infinite fields. AH
  [IsMatrix and IsFFECollColl,IsList,IsFunction],0,
function(pnt,acts,act)
local l,f;
  if (not ForAll(acts,IsMatrix)) or
    (act<>OnPoints and act<>OnSubspacesByCanonicalBasis and act<>OnRight) then
    TryNextMethod(); # strange operation, might extend the domain
  fi;
  l:=NaturalActedSpace(acts,pnt);
  f:=Size(LeftActingDomain(l));
  l:=Size(l);
  return rec(hashfun:=function(b)
             local h,i;
               h:=0;
               for i in b do
                 h:=h*l+NumberFFVector(i,f);
               od;
               return h;
              end);
end);

InstallMethod(DomainForAction,"vector/permgrp",true,
  [IsList,IsList,IsFunction],0,
function(pnt,acts,act)
  if (not (ForAll(acts,IsPerm) and ForAll(pnt,IsScalar)))
     or (act<>Permuted) then
    TryNextMethod(); # strange operation, might extend the domain
  fi;
  return DefaultField(pnt)^Length(pnt);
end);

#############################################################################
##
#M  SemiEchelonMat( <GF2 matrix> )
#M  SemiEchelonMatTransformation( <GF2 matrix> )
#M  SemiEchelonMatDestructive( <plain list of GF2 vectors> )
#M  SemiEchelonMatTransformationDestructive( <plain list of GF2 vectors> )
##
#

#
#  This is the rank by which we increase the GF2 kernel methods,
#  so that they get tried before the 8bit ones, as they will fall
#  through faster.
#
#
BindGlobal("GF2_AHEAD_OF_8BIT_RANK", 10);

#
# If mat is in the GF2 special representation, then we do
# have to copy it, but we know that the rows of the result will
# already be in GF2 special representation, so we skip the conversion
# step in the generic method
#


InstallMethod(SemiEchelonMat, "shortcut method for GF2 matrices",
        true,
        [ IsMatrix and IsGF2MatrixRep and IsFFECollColl ],
        0,
        function(mat)
    local res;
    res :=  SemiEchelonMatDestructive( List(mat, ShallowCopy) ) ;
    ConvertToMatrixRepNC(res.vectors,2);
    return res;
    end );

InstallMethod(SemiEchelonMatTransformation,
        "kernel method for plain lists of GF2 vectors",
        true,
        [ IsMatrix and IsFFECollColl and IsGF2MatrixRep],
        0,
        function(mat)
    local res;
    res := SemiEchelonMatTransformationDestructive( List( mat, ShallowCopy) );
    ConvertToMatrixRepNC(res.vectors,2);
    ConvertToMatrixRepNC(res.coeffs,2);
    ConvertToMatrixRepNC(res.relations,2);
    return res;
    end );


#
# The real kernel methods, which are destructive and want plain lists
# of GF2 vectors as their arguments, but will try next if they get other
# plain lists
#

InstallMethod(SemiEchelonMatDestructive,
        "kernel method for plain lists of GF2 vectors",
        true,
        [ IsPlistRep and IsMatrix and IsMutable and IsFFECollColl ],
        GF2_AHEAD_OF_8BIT_RANK,
        SEMIECHELON_LIST_GF2VECS);


InstallMethod(SemiEchelonMatTransformationDestructive,
        "kernel method for plain lists of GF2 vectors",
        true,
        [ IsMatrix and IsPlistRep and IsFFECollColl and IsMutable],
        GF2_AHEAD_OF_8BIT_RANK,
        SEMIECHELON_LIST_GF2VECS_TRANSFORMATIONS);



#############################################################################
##
#M  TriangulizeMat( <plain list of GF2 vectors> )
##
##  The method will fall through if the matrix is not a plain list of
##  GF2 vectors

InstallMethod(TriangulizeMat,
        "kernel method for plain list of GF2 vectors",
        true,
        [IsMatrix and IsPlistRep and IsFFECollColl and IsMutable],
        GF2_AHEAD_OF_8BIT_RANK,
        TRIANGULIZE_LIST_GF2VECS);

##
#T Really should sort this one in the kernel
## but this should fix the major inefficiency for now
##


InstallMethod(TriangulizeMat,
        "for GF2 matrices",
        true,
        [IsMatrix and IsMutable and IsFFECollColl and IsGF2MatrixRep],
        0,
        function(m)
    local i,imms;
    PLAIN_GF2MAT(m);
    imms := [];
    for i in [1..Length(m)] do
        if not IsMutable(m[i]) then
            m[i] := ShallowCopy(m[i]);
            imms[i] := true;
        else
            imms[i] := false;
        fi;
    od;
    TRIANGULIZE_LIST_GF2VECS(m);
    for i in [1..Length(m)] do
        if not IsMutable(m[i]) then
            m[i] := ShallowCopy(m[i]);
            imms[i] := true;
        else
            imms[i] := false;
        fi;
    od;
    CONV_GF2MAT(m);
end);

#############################################################################
##
#M  DeterminantMatDestructive ( <plain list of GF2 vectors> )
##

InstallMethod(DeterminantMatDestructive,
        "kernel method for plain list of GF2 vectors",
        true,
        [IsMatrix and IsPlistRep and IsFFECollColl and IsMutable],
        GF2_AHEAD_OF_8BIT_RANK,
        DETERMINANT_LIST_GF2VECS);

#############################################################################
##
#M  RankMatDestructive ( <plain list of GF2 vectors> )
##


InstallOtherMethod(RankMatDestructive,
        "kernel method for plain list of GF2 vectors",
        [IsMatrix and IsPlistRep and IsFFECollColl and IsMutable],
        GF2_AHEAD_OF_8BIT_RANK,
        RANK_LIST_GF2VECS);


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

--> maximum size reached

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

[ Dauer der Verarbeitung: 0.23 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


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