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

Quelle  cvec.gi   Sprache: unbekannt

 
#############################################################################
##
#W  cvec.gi               GAP 4 package `cvec'                Max Neunhoeffer
##
##  Copyright (C) 2007  Max Neunhoeffer, Lehrstuhl D f. Math., RWTH Aachen
##  This file is free software, see license information at the end.
##
##  This file contains the higher levels for compact vectors over finite 
##  fields. 
##

#############################################################################
## Info Class:
#############################################################################

SetInfoLevel(InfoCVec,1);


#############################################################################
## The technical stuff for typing:
#############################################################################

# A set holding all q's for which we have cvec classes:
BindGlobal( "CVEC_q", [] );
# A list holding field infos:
BindGlobal( "CVEC_F", [] );
# A list holding lengths of vectors existing for each q:
BindGlobal( "CVEC_lens", [] );
# A list holding cvec classes (which are pairs [fieldinfo,len])
BindGlobal( "CVEC_classes", [] );


#############################################################################
## Administration of field info and cvec class data:
#############################################################################

BindGlobal( "CVEC_BestGreaseTab",
  [ ,            # q=1
    8,           # q=2
    5,           # q=3
    4,           # q=4
    3,           # q=5  
                 # No longer valid:
                 #      Note that we reduce here the grease level to 2 such
                 #      that elsperword (= 8) is divisible by the grease level,
                 #      this is used to make the multiplication function much
                 #      simpler (no bad case at right edge of A!)
    ,            # q=6
    3,           # q=7
    3,           # q=8
    3,           # q=9
    ,            # q=10
    2,           # q=11
    ,            # q=12
    2,           # q=13
    ,            # q=14
    ,            # q=15
    2,           # q=16
  ] );

InstallGlobalFunction( CVEC_NewCVecClass, function(p,d,len)
  # Creates a new class of cvecs or returns a cached one:
  local bestgrease,bitsperel,cl,elsperword,filts,greasetabl,j,l,po,pos,pos2,
        q,s,scafam,size,tab1,tab2,ty,wordlen,filtscmat;

  # First check the arguments:
  if d <= 0 then 
      Error("CVEC_NewCVecClass: Degree must be positive."); 
      return fail;
  fi;
  if d >= CVEC_MAXDEGREE then 
      Error("CVEC_NewCVecClass: Degree must be < ",CVEC_MAXDEGREE,"."); 
      return fail;
  fi;
  if not(IsPrime(p)) then 
      Error("CVEC_MakeField: p must be a prime."); 
      return fail;
  fi; 
  if not(IsSmallIntRep(p)) then 
      Error("CVEC_NewCVecClass: p must be a prime that is an immediate int .");
      return fail;
  fi;
  if not(IsSmallIntRep(len)) then
      Error("CVEC_NewCVecClass: len must be an immediate integer.");
      return fail;
  fi;
  q := p^d;
  if q <= MAXSIZE_GF_INTERNAL then size := 0;
  elif IsSmallIntRep(q) then size := 1;
  else size := 2; fi;

  # First try to find q:
  pos := Position(CVEC_q,q);
  if pos = fail then
      l := [];    # Here we collect the information
      l[CVEC_IDX_p] := p;
      l[CVEC_IDX_d] := d;
      l[CVEC_IDX_q] := q;
      l[CVEC_IDX_size] := size;

      # We have to make the new field info structure:
      po := -CoefficientsOfLaurentPolynomial(ConwayPolynomial(p,d));
      if po[2] <> 0 then Error("Unexpected case #1"); fi;
      po := List(po[1],IntFFE);
      s := CVEC_COEFF_LIST_TO_C(po,"");
      l[CVEC_IDX_conway] := s;
      
      # Bits per element, will be increased in the following loop:
      if IsOddInt(p) then
          bitsperel := 1;
      else
          bitsperel := 0;
      fi;
      j := p-1;
      while j > 0 do
          bitsperel := bitsperel + 1;
          j := QuoInt(j,2);
      od;
      l[CVEC_IDX_bitsperel] := bitsperel;

      # Prime field elements per Word:
      # Note that for 64 bit machines we always put only twice as much
      # prime field elements into a Word than for 32 bit machines (even if
      # one more would fit!) such that conversion between binary formats
      # is easier later on.
      elsperword := QuoInt(32,bitsperel);
      if CVEC_BYTESPERWORD = 8 then
          elsperword := elsperword * 2;
      fi;
      l[CVEC_IDX_elsperword] := elsperword;

      # Set up best greasing level:
      if q <= 16 and IsBound(CVEC_BestGreaseTab[q]) then
          bestgrease := CVEC_BestGreaseTab[q];
          greasetabl := q^bestgrease;
      elif q <= 256 then
          bestgrease := 1;
          greasetabl := q;
      else
          bestgrease := 0;  # no grease
          greasetabl := 0;
      fi;
      l[CVEC_IDX_bestgrease] := bestgrease;
      l[CVEC_IDX_greasetabl] := greasetabl; 

      # Now the starting filter list:
      filts := IsCVecRep;
      filtscmat := IsCMatRep;
      if size = 0 then
          filts := filts and IsCVecRepOverSmallField;
          filtscmat := filtscmat and IsCVecRepOverSmallField;
      fi;
      if d = 1 then
          filts := filts and IsCVecRepOverPrimeField;
          filtscmat := filtscmat and IsCVecRepOverPrimeField;
      fi;

      # Note that IsMutable is added below, when we create the vector type
      l[CVEC_IDX_filts] := filts;
      l[CVEC_IDX_filtscmat] := filtscmat;

      # We use the "official" families:
      scafam := FFEFamily(p);
      l[CVEC_IDX_scafam] := scafam;

      # Now for small finite fields two tables for conversion:
      if q <= MAXSIZE_GF_INTERNAL then
          tab1 := 0*[1..q];
          tab2 := 0*[1..q];
          CVEC_INIT_SMALL_GFQ_TABS(p,ConwayPol(p,d),tab1,tab2);
      else
          # If p is < 65536, we need access to the prime field:
          if p < MAXSIZE_GF_INTERNAL then
              tab1 := 0*[1..p];
              tab2 := 0*[1..p];
              CVEC_INIT_SMALL_GFQ_TABS(p,ConwayPol(p,1),tab1,tab2);
          else
              tab1 := [];
              tab2 := [];
          fi;
      fi;
      l[CVEC_IDX_tab1] := tab1;
      l[CVEC_IDX_tab2] := tab2;

      # Now l is nearly ready!
      #l := [p,d,q,s,bitsperel,elsperword,0,bestgrease,greasetabl,filts,
      #      tab1,tab2,size,scafam];
      Objectify(NewType(CVecFieldInfoFamily,IsCVecFieldInfo),l);

      # Do the internal part: This does index CVEC_IDX_wordinfo:
      CVEC_FINALIZE_FIELDINFO(l);

      pos := PositionSorted(CVEC_q,q);
      Add(CVEC_q,q,pos);
      Add(CVEC_F,l,pos);
      Add(CVEC_lens,[],pos);
      Add(CVEC_classes,[],pos);
  else   # pos <> fail
      elsperword := CVEC_F[pos]![CVEC_IDX_elsperword];  # for later use
      filts := CVEC_F[pos]![CVEC_IDX_filts];            # for later use
      filtscmat := CVEC_F[pos]![CVEC_IDX_filtscmat];    # for later use
      scafam := CVEC_F[pos]![CVEC_IDX_scafam];          # for later use
  fi;

  # Now we know that the field info is at position pos:
  pos2 := Position(CVEC_lens[pos],len);
  if pos2 <> fail then
      return CVEC_classes[pos][pos2];
  fi;

  # Build the class object, note that we need elsperword and filts from above:
  cl := [];
  cl[CVEC_IDX_fieldinfo] := CVEC_F[pos];
  cl[CVEC_IDX_len] := len;
  wordlen := d * (QuoInt( len + elsperword - 1, elsperword ));
  cl[CVEC_IDX_wordlen] := wordlen;
  ty := NewType(CollectionsFamily(scafam),filts and IsMutable,cl);
  cl[CVEC_IDX_type] := ty;
  cl[CVEC_IDX_GF] := GF(p,d);
  cl[CVEC_IDX_lens] := CVEC_lens[pos];
  cl[CVEC_IDX_classes] := CVEC_classes[pos];
  ty := NewType(CollectionsFamily(CollectionsFamily(scafam)),
                filtscmat and IsMutable);
  cl[CVEC_IDX_typecmat] := ty;

  Objectify(NewType(CVecClassFamily,IsCVecClass),cl);

  # Put it into the cache:
  pos2 := PositionSorted(CVEC_lens[pos],len);
  Add(CVEC_lens[pos],len,pos2);
  Add(CVEC_classes[pos],cl,pos2);
  
  # Now add zero, one, and primitive root for the case d=1:
  return CVEC_classes[pos][pos2];
end );
 
InstallGlobalFunction( CVEC_NewCVecClassSameField, function(c,len)
  # Creates a new class in the case that another length is already known:
  local pos;
  pos := Position(c![CVEC_IDX_lens],len);
  if pos = fail then 
      return CVEC_NewCVecClass(c![CVEC_IDX_fieldinfo]![CVEC_IDX_p],
                               c![CVEC_IDX_fieldinfo]![CVEC_IDX_d],len);
  else
      return c![CVEC_IDX_classes][pos];
  fi;
end );

InstallMethod( CVecClass, "for a cvec", [IsCVecRep],
  DataObj);

InstallMethod( CVecClass, "for a cvec and a length", [IsCVecRep, IsInt],
  function(v,l)
    return CVEC_NewCVecClassSameField(DataObj(v),l);
  end );

InstallMethod( CVecClass, "for a cvecclass and a length", [IsCVecClass, IsInt],
  function(c,l)
    return CVEC_NewCVecClassSameField(c,l);
  end );

InstallMethod( CVecClass, "for three integers", [IsPosInt, IsPosInt, IsInt],
  function(p,d,l)
    return CVEC_NewCVecClass(p,d,l);
  end );

InstallMethod( CVecClass, "for a finite field and an integer", 
  [IsField and IsFinite, IsInt],
  function(f,l)
    local p,d;
    p := Characteristic(f);
    d := DegreeOverPrimeField(f);
    return CVEC_NewCVecClass(p,d,l);
  end );

InstallGlobalFunction( CVEC_New, function(arg)
  local c,d,l,p;
  if Length(arg) = 1 then
      c := arg[1];
      if IsCVecRep(c) then
          c := DataObj(c);
      fi;
      if IsCVecClass(c) then
          return CVEC_NEW(c,c![CVEC_IDX_type]);
      fi;
  elif Length(arg) = 2 then
      p := Characteristic(arg[1]);
      d := DegreeOverPrimeField(arg[1]);
      l := arg[2];
      
  elif Length(arg) = 3 then
      p := arg[1];
      d := arg[2];
      l := arg[3];
      if IsInt(p) and IsPrime(p) and p > 0 and IsInt(d) and d >= 1 and
         IsInt(l) and l >= 1 then
          c := CVEC_NewCVecClass(p,d,l);
          return CVEC_NEW(c,c![CVEC_IDX_type]);
      fi;
  fi;
  Error("Usage: CVEC_New( [ cvec | cvecclass | field,l | p,d,l ] )");
end );

##############################
# Some nice viewing methods: #
##############################

InstallMethod( ViewObj, "for a cvec field info", [IsCVecFieldInfo], 
function(f)
  Print("<cvec-fieldinfo p=",f![CVEC_IDX_p],
        " d=",f![CVEC_IDX_d]," q=",f![CVEC_IDX_q],
        " bpl=",f![CVEC_IDX_bitsperel]," epw=",f![CVEC_IDX_elsperword],
        " grease=",f![CVEC_IDX_bestgrease],
        " gtablen=",f![CVEC_IDX_greasetabl],">");
end);

InstallMethod( ViewObj, "for a cvec class", [IsCVecClass], 
function(c)
  local f;
  f := c![CVEC_IDX_fieldinfo];
  Print("<cvec-class field=GF(",f![CVEC_IDX_p],",",f![CVEC_IDX_d],
        ") len=",c![CVEC_IDX_len]," wordlen=",c![CVEC_IDX_wordlen],">");
end);

InstallMethod( ViewObj, "for a cvec", [IsCVecRep], 
function(v)
  local c;
  c := DataObj(v);
  Print("<");
  if not(IsMutable(v)) then Print("immutable "); fi;
  Print("cvec over GF(",c![CVEC_IDX_fieldinfo]![CVEC_IDX_p],",",
        c![CVEC_IDX_fieldinfo]![CVEC_IDX_d],") of length ",
        c![CVEC_IDX_len],">");
end);

InstallMethod( PrintObj, "for a cvec class", [IsCVecClass], 
function(c)
  Print("CVEC_NewCVecClass(",c![CVEC_IDX_fieldinfo]![CVEC_IDX_p],",",
        c![CVEC_IDX_fieldinfo]![CVEC_IDX_d],",",c![CVEC_IDX_len],")");
end);

InstallMethod( PrintObj, "for a cvec", [IsCVecRep], 
function(v)
  local l,c,i;
  c := DataObj(v);
  Print("NewVector(IsCVecRep,GF(",c![CVEC_IDX_fieldinfo]![CVEC_IDX_p],",",
        c![CVEC_IDX_fieldinfo]![CVEC_IDX_d],"),[");
  if c![CVEC_IDX_fieldinfo]![CVEC_IDX_size] = 0 then   # GAP FFEs
      l := Unpack(v);
      for i in l do Print(i,","); od;
  else
      l := Unpack(v);
      for i in l do Print(i,","); od;
  fi;
  Print("])");
end);

InstallMethod( String, "for a cvec", [IsCVecRep], 
function(v)
  local l,c,i,res;
  c := DataObj(v);
  res := "NewVector(IsCVecRep,GF(";
  Append(res,String(c![CVEC_IDX_fieldinfo]![CVEC_IDX_p]));
  Add(res,',');
  Append(res,String(c![CVEC_IDX_fieldinfo]![CVEC_IDX_d]));
  Append(res,"),[");
  if c![CVEC_IDX_fieldinfo]![CVEC_IDX_size] = 0 then   # GAP FFEs
      l := Unpack(v);
      for i in l do Append(res,String(i)); Append(res,","); od;
  else
      l := Unpack(v);
      for i in l do Append(res,String(i)); Append(res,","); od;
  fi;
  Append(res,"])");
  return res;
end);

BindGlobal( "CVEC_CharactersForDisplay",
              ".123456789abcdefghijklmnopqrstuvwxyz" );

InstallMethod( Display, "for a cvec", [IsCVecRep], 
function(v)
  local i,l,c,q,lo;
  c := DataObj(v);
  Print("[");
  q := c![CVEC_IDX_fieldinfo]![CVEC_IDX_q];
  if q <= 36 then
      l := IntegerRep(v);
      Print(CVEC_CharactersForDisplay{l+1},"]\n");
  elif c![CVEC_IDX_fieldinfo]![CVEC_IDX_size] = 1 then
      l := Unpack(v);
      lo := LogInt(q,10)+7;   # This is the number of digits needed plus 6
      for i in l do Print(String(i,lo)); od;
      Print("]\n");
  else
      l := Unpack(v);
      for i in l do Print(i,","); od;
      Print("]\n");
  fi;
end);


#########################################
# Handling of scalars on the GAP level: # 
#########################################

InstallGlobalFunction( CVEC_HandleScalar, function(cl,s)
  # cl is a cvecclass and s a scalar
  local v,d;
  if   IsInternalRep(s) then return s;
    # Note that this case also covers integers!
  elif IsZmodnZObj(s) then return s![1];
  fi;
  # Now we have to check, whether the field element is over the right field:
  d := cl![CVEC_IDX_fieldinfo]![CVEC_IDX_d];
  if s![2] < d then
      s := FFECONWAY.WriteOverLargerField(s,d);
  elif s![2] > d then
      s := FFECONWAY.TryToWriteInSmallerField(s,d);
      # s now could be internal
      if IsInternalRep(s) then return s; fi;
      if s = fail then Error("input vector not defined over the expected field"); fi;
  fi;
  if IsGF2VectorRep(s![1]) then
    v := ShallowCopy(s![1]);
    PLAIN_GF2VEC(v);
    return v;
  elif Is8BitVectorRep(s![1]) then
    v := ShallowCopy(s![1]);
    PLAIN_VEC8BIT(v);
    return v;
  elif cl![CVEC_IDX_fieldinfo]![CVEC_IDX_p] < MAXSIZE_GF_INTERNAL then
    return s![1];
  else
    return List(s![1],x->x![1]);   # this unpacks ZmodnZObjs
  fi;
end );

#################################################
# Now to the installation of methods for cvecs: #
#################################################

# Length:

InstallOtherMethod( Length, "for cvecs", [IsCVecRep], 
function(v)
  return DataObj(v)![CVEC_IDX_len];
end);

# AddRowVector(v,w [,s][,fr,to]) where s is integer or FFE:

InstallOtherMethod( AddRowVector, "for cvecs",
  [IsMutable and IsCVecRep, IsCVecRep],
  function(v,w) CVEC_ADD2(v,w,0,0); end);

InstallOtherMethod( AddRowVector, "for cvecs",
  [IsMutable and IsCVecRep, IsCVecRep, IsInt, IsInt],
  function(v,w,fr,to) CVEC_ADD2(v,w,fr,to); end);

InstallOtherMethod( AddRowVector, "for cvecs",
  [IsMutable and IsCVecRep, IsCVecRep, IsFFE and IsInternalRep],
  function(v,w,s)
    CVEC_ADDMUL(v,w,s,0,0);
  end );
InstallOtherMethod( AddRowVector, "for cvecs",
  [IsMutable and IsCVecRep, IsCVecRep, IsFFE],
  function(v,w,s) 
    CVEC_ADDMUL(v,w,CVEC_HandleScalar(DataObj(v),s),0,0);
  end);
InstallOtherMethod( AddRowVector, "for cvecs",
  [IsMutable and IsCVecRep, IsCVecRep, IsInt and IsSmallIntRep],
  function(v,w,s) CVEC_ADDMUL(v,w,s,0,0); end);

InstallOtherMethod( AddRowVector, "for cvecs",
  [IsMutable and IsCVecRep, IsCVecRep, IsFFE and IsInternalRep, IsInt, IsInt],
  function(v,w,s,fr,to) 
    CVEC_ADDMUL(v,w,s,fr,to); 
  end);
InstallOtherMethod( AddRowVector, "for cvecs",
  [IsMutable and IsCVecRep, IsCVecRep, IsFFE, IsInt, IsInt],
  function(v,w,s,fr,to) 
    CVEC_ADDMUL(v,w,CVEC_HandleScalar(DataObj(v),s),fr,to);
  end);
InstallOtherMethod( AddRowVector, "for cvecs",
  [IsMutable and IsCVecRep,IsCVecRep,IsInt and IsSmallIntRep,IsInt,IsInt],
  CVEC_ADDMUL );
InstallOtherMethod( AddRowVector, "for cvecs",
  [IsMutable and IsCVecRep,IsCVecRep,IsFFE and IsInternalRep,IsInt,IsInt],
  CVEC_ADDMUL );

# MultVector(v,s [,fr,to]) where s is integer or FFE:
# Note that we do not give a method for MultVector with 5 arguments!

InstallOtherMethod( MultVector, "for cvecs",
  [IsMutable and IsCVecRep, IsInt and IsSmallIntRep],
  function(v,s) CVEC_MUL1(v,s,0,0); end);
InstallOtherMethod( MultVector, "for cvecs",
  [IsMutable and IsCVecRep, IsInt and IsSmallIntRep, IsInt, IsInt],
  CVEC_MUL1 );

InstallOtherMethod( MultVector, "for cvecs",
  [IsMutable and IsCVecRep, IsFFE and IsInternalRep],
  function(v,s) CVEC_MUL1(v,s,0,0); end);
InstallOtherMethod( MultVector, "for cvecs",
  [IsMutable and IsCVecRep, IsFFE and IsInternalRep, IsInt, IsInt],
  CVEC_MUL1 );

InstallOtherMethod( MultVector, "for cvecs",
  [IsMutable and IsCVecRep, IsFFE],
  function(v,s) 
    CVEC_MUL1(v,CVEC_HandleScalar(DataObj(v),s),0,0);
  end);
InstallOtherMethod( MultVector, "for cvecs",
  [IsMutable and IsCVecRep, IsFFE, IsInt, IsInt],
  function(v,s,fr,to) 
    CVEC_MUL1(v,CVEC_HandleScalar(DataObj(v),s),fr,to);
  end);

# Addition of vectors:

InstallOtherMethod( \+, "for cvecs", [IsCVecRep, IsCVecRep],
  function(v,w)
    local u,vcl;
    vcl := DataObj(v);
    u := CVEC_NEW(vcl,vcl![CVEC_IDX_type]);
    CVEC_ADD3(u,v,w);
    if not(IsMutable(v)) and not(IsMutable(w)) then MakeImmutable(u); fi;
    return u;
  end);

# Subtraction of vectors:

InstallOtherMethod( \-, "for cvecs", [IsCVecRep, IsCVecRep],
  function(v,w)
    local u,vcl,p;
    vcl := DataObj(v);
    p := vcl![CVEC_IDX_fieldinfo]![CVEC_IDX_p];
    u := CVEC_NEW(vcl,vcl![CVEC_IDX_type]);
    CVEC_COPY(v,u);
    CVEC_ADDMUL(u,w,p-1,0,0);
    if not(IsMutable(v)) and not(IsMutable(w)) then MakeImmutable(u); fi;
    return u;
  end);

# Additive inverse of vectors:

InstallOtherMethod( AdditiveInverseMutable, "for cvecs", [IsCVecRep],
  function(v)
    local u,vcl,p;
    vcl := DataObj(v);
    p := vcl![CVEC_IDX_fieldinfo]![CVEC_IDX_p];
    u := CVEC_NEW(vcl,vcl![CVEC_IDX_type]);
    CVEC_MUL2(u,v,p-1);
    return u;
  end);
InstallOtherMethod( AdditiveInverseSameMutability, "for cvecs", [IsCVecRep],
  function(v)
    local u,vcl,p;
    vcl := DataObj(v);
    p := vcl![CVEC_IDX_fieldinfo]![CVEC_IDX_p];
    u := CVEC_NEW(vcl,vcl![CVEC_IDX_type]);
    CVEC_MUL2(u,v,p-1);
    if not(IsMutable(v)) then MakeImmutable(u); fi;
    return u;
  end);

# Multiplication of vectors by scalars:

BindGlobal( "CVEC_VECTOR_TIMES_SCALAR", function(v,s)
    # The scalar here must already be run through CVEC_HandleScalar 
    # if necessary! Of course, integers and FFEs in internal representation
    # of course is allowed.
    local u,vcl;
    vcl := DataObj(v);
    u := CVEC_NEW(vcl,vcl![CVEC_IDX_type]);
    CVEC_MUL2(u,v,s);
    if not(IsMutable(v)) then MakeImmutable(u); fi;
    return u;
  end );
InstallOtherMethod( \*, "for cvecs", [IsCVecRep, IsInt], 
  CVEC_VECTOR_TIMES_SCALAR);
InstallOtherMethod( \*, "for cvecs", [IsCVecRep, IsFFE and IsInternalRep], 
  CVEC_VECTOR_TIMES_SCALAR);
InstallOtherMethod( \*, "for cvecs", [IsCVecRep, IsFFE], 
  function (v,s) 
    return CVEC_VECTOR_TIMES_SCALAR(v,
                CVEC_HandleScalar(DataObj(v),s));
  end);
InstallOtherMethod( \*, "for cvecs", [IsInt,IsCVecRep], 
  function(s,v) return CVEC_VECTOR_TIMES_SCALAR(v,s); end);
InstallOtherMethod( \*, "for cvecs", [IsFFE and IsInternalRep,IsCVecRep], 
  function(s,v) return CVEC_VECTOR_TIMES_SCALAR(v,s); end);
InstallOtherMethod( \*, "for cvecs", [IsFFE, IsCVecRep], 
  function (s,v) 
    return CVEC_VECTOR_TIMES_SCALAR(v,
                CVEC_HandleScalar(DataObj(v),s));
  end);

#############################################################################
# Applying Frobenius automorphisms element-wise:
#############################################################################


InstallOtherMethod( \^, "for a cvec and a trivial frobenius automorphism",
  [IsCVecRep and IsFFECollection, IsMapping and IsOne],
  function( v, f )
    return v;
  end );

InstallOtherMethod( \^, 
  "for a mutable cvec and a trivial frobenius automorphism",
  [IsCVecRep and IsFFECollection and IsMutable, IsMapping and IsOne],
  function( v, f )
    return ShallowCopy(v);
  end );

InstallOtherMethod( \^, "for a mutable cvec and a frobenius automorphism",
  [IsCVecRep and IsFFECollection and IsMutable, IsFrobeniusAutomorphism],
  function( v, f )
    local w,i;
    w := ShallowCopy(v);
    for i in [1..Length(w)] do
        w[i] := v[i]^f;
    od;
    return w;
  end );

InstallOtherMethod( \^, "for a cvec and a frobenius automorphism",
  [IsCVecRep and IsFFECollection, IsFrobeniusAutomorphism],
  function( v, f )
    local w,i;
    w := ShallowCopy(v);
    for i in [1..Length(w)] do
        w[i] := v[i]^f;
    od;
    return MakeImmutable(w);
  end );

InstallOtherMethod( ScalarProduct, "for two cvecs, kernel method", 
  [ IsCVecRep and IsCVecRepOverSmallField and IsCVecRepOverPrimeField, 
    IsCVecRep and IsCVecRepOverSmallField and IsCVecRepOverPrimeField], 
    1, CVEC_SCALAR_PRODUCT );
InstallOtherMethod( ScalarProduct, "for two cvecs, GAP method", 
  [ IsCVecRep, IsCVecRep ], 
  function( v,w )
    return PROD_LIST_LIST_DEFAULT( Unpack(v), Unpack(w), 0 );
  end );

# Comparison of vectors:

InstallOtherMethod( \=, "for cvecs", [IsCVecRep, IsCVecRep], CVEC_CVEC_EQ );
InstallOtherMethod( \<, "for cvecs", [IsCVecRep, IsCVecRep], CVEC_CVEC_LT );
InstallOtherMethod( IsZero, "for cvecs", [IsCVecRep], CVEC_CVEC_ISZERO);

# Element access for vectors:

InstallOtherMethod( \[\]\:\=, "for a cvec, a pos, and an int",
  [IsCVecRep and IsMutable, IsPosInt, IsInt and IsSmallIntRep], CVEC_ASS_CVEC );
InstallOtherMethod( \[\]\:\=, "for a cvec, a pos, and an int",
  [IsCVecRep and IsMutable, IsPosInt, IsFFE and IsInternalRep], CVEC_ASS_CVEC );
InstallOtherMethod( \[\]\:\=, "for a cvec, a pos, and a ffe",
  [IsCVecRep and IsMutable, IsPosInt, IsFFE], 
  function(v,pos,s)
    CVEC_ASS_CVEC(v,pos,CVEC_HandleScalar(DataObj(v),s));
  end);
InstallOtherMethod( \[\]\:\=, "for cvecs", [IsCVecRep, IsPosInt, IsInt],
  function(v,p,o) Error("cvec is immutable"); end);
InstallOtherMethod( \[\]\:\=, "for cvecs", [IsCVecRep, IsPosInt, IsFFE],
  function(v,p,o) Error("cvec is immutable"); end);

InstallOtherMethod( \[\], "for cvecs", 
  [IsCVecRep and IsCVecRepOverSmallField, IsPosInt],CVEC_ELM_CVEC );
InstallOtherMethod( \[\], "for cvecs", [IsCVecRep, IsPosInt], 
  function(v,pos)
    local d,fam,i,p,s,size,vcl;
    vcl := DataObj(v);
    size := vcl![CVEC_IDX_fieldinfo]![CVEC_IDX_size];
    s := CVEC_ELM_CVEC(v,pos);
    if size = 0 then return s; fi;
    d := vcl![CVEC_IDX_fieldinfo]![CVEC_IDX_d];
    if d = 1 then
        if IsFFE(s) then
            return s;
        else
            p := vcl![CVEC_IDX_fieldinfo]![CVEC_IDX_p];
            return ZmodnZObj(s,p);
        fi;
    else
        p := vcl![CVEC_IDX_fieldinfo]![CVEC_IDX_p];
        if p > 65536 then
            for i in [1..d] do
                s[i] := ZmodnZObj(s[i],p);
            od;
        fi;
        ConvertToVectorRep(s,p);
        s := [s,d,fail];
        fam := FFEFamily(p);
        Objectify(fam!.ConwayFldEltDefaultType,s);
        return s;
    fi;
  end);

# PositionNonZero and friends:

InstallOtherMethod( PositionNonZero, "for cvecs",
  [IsCVecRep], CVEC_POSITION_NONZERO_CVEC);
InstallOtherMethod( PositionLastNonZero, "for cvecs",
  [IsCVecRep], CVEC_POSITION_LAST_NONZERO_CVEC);
InstallOtherMethod( PositionNot, "for cvecs",
  [IsCVecRep, IsFFE], 
  function(v,z)
    local j;
    if z <> Zero(z) then
        for j in [1..Length(v)] do
            if v[j] <> z then
                return j;
            fi;
        od;
        return Length(v)+1;
    fi;
    return PositionNonZero(v);
  end);
InstallOtherMethod( PositionNot, "for cvecs",
  [IsCVecRep, IsFFE, IsInt], 
  function(v,z,i)
    local j;
    if not(IsZero(z)) or i <> 0 then
        for j in [i+1..Length(v)] do
            if v[j] <> z then
                return j;
            fi;
        od;
        return Length(v)+1;
    fi;
    return PositionNonZero(v);
  end);

# Copying:

InstallOtherMethod( ShallowCopy, "for cvecs", [IsCVecRep],
  function(v)
    local u,vcl;
    vcl := DataObj(v);
    u := CVEC_NEW(vcl,vcl![CVEC_IDX_type]);
    CVEC_COPY(v,u);
    return u;
  end);

# Zeroing:

InstallOtherMethod( ZeroMutable, "for cvecs", [IsCVecRep],
  function(v)
    local u,vcl;
    vcl := DataObj(v);
    u := CVEC_NEW(vcl,vcl![CVEC_IDX_type]);
    return u;
  end);
InstallOtherMethod( ZeroSameMutability, "for cvecs", [IsCVecRep],
  function(v)
    local u,vcl;
    vcl := DataObj(v);
    u := CVEC_NEW(vcl,vcl![CVEC_IDX_type]);
    if not(IsMutable(v)) then
        MakeImmutable(u);
    fi;
    return u;
  end);

InstallMethod( ZeroVector, "for an integer and a cvec",
  [IsInt, IsCVecRep],
  function(len,v)
    local cl;
    cl := DataObj(v);
    if cl![CVEC_IDX_len] <> len then
        cl := CVEC_NewCVecClassSameField(cl,len);
    fi;
    return CVEC_NEW(cl,cl![CVEC_IDX_type]);
  end);

InstallMethod( ZeroVector, "for an integer and a cmat",
  [IsInt, IsCMatRep],
  function(len,m)
    local cl;
    cl := m!.vecclass;
    if cl![CVEC_IDX_len] <> len then
        cl := CVEC_NewCVecClassSameField(cl,len);
    fi;
    return CVEC_NEW(cl,cl![CVEC_IDX_type]);
  end);

# The making of:

InstallMethod( CVec, "for a cvec class",
  [IsCVecClass],
  function(c)
    return CVEC_NEW(c,c![CVEC_IDX_type]);
  end);
InstallMethod( CVec, "for a homogeneous list and two posints", 
  [IsList, IsPosInt, IsPosInt],
  function(l,p,d)
    local c,v;
    if IsSmallIntRep(p^d) then
        c := CVEC_NewCVecClass(p,d,Length(l));
    else
        c := CVEC_NewCVecClass(p,d,Length(l)/d);
    fi;
    return CVec(l,c);  # Delegate to the following routine
  end);
InstallMethod( CVec, "for a homogeneous list and a finite field", 
  [IsList, IsField and IsFinite],
  function(l,f)
    local c,p,d,v;
    p := Characteristic(f);
    d := DegreeOverPrimeField(f);
    if IsSmallIntRep(p^d) then
        c := CVEC_NewCVecClass(p,d,Length(l));
    else
        c := CVEC_NewCVecClass(p,d,Length(l)/d);
    fi;
    return CVec(l,c);  # Delegate to the following routine
  end);
InstallMethod( CVec, "for a homogeneous list and a cvec class",
  [IsList, IsCVecClass],
  function(l,c)
    local v;
    v := CVEC_NEW(c,c![CVEC_IDX_type]);
    # We recognise the type of entries by looking at the first one:
    if Length(l) > 0 then
        if IsZmodnZObj(l[1]) then
            CVEC_INTREP_TO_CVEC(List(l,x->x![1]),v);
            return v;
        elif IsFFE(l[1]) and not(IsInternalRep(l[1])) then  # large scalars:
            CVEC_INTREP_TO_CVEC(List(l,x->CVEC_HandleScalar(c,x)),v);
            return v;
        fi;
    fi;
    # This can only handle integers and internal FFEs:
    CVEC_INTREP_TO_CVEC(l,v);
    return v;
  end);
InstallOtherMethod( CVec, "for a compressed gf2 vector",
  [IsList and IsGF2VectorRep],
  function(v)
    local c,w;
    v := ShallowCopy(v);
    PLAIN_GF2VEC(v);
    c := CVEC_NewCVecClass(2,1,Length(v));
    w := CVEC_NEW(c,c![CVEC_IDX_type]);
    CVEC_INTREP_TO_CVEC(v,w);
    return w;
  end);
InstallOtherMethod( CVec, "for a compressed 8bit vector",
  [IsList and Is8BitVectorRep],
  function(v)
    local c,pd,w;
    pd := Factors(Size(Field(v)));
    v := ShallowCopy(v);
    PLAIN_VEC8BIT(v);
    c := CVEC_NewCVecClass(pd[1],Length(pd),Length(v));
    w := CVEC_NEW(c,c![CVEC_IDX_type]);
    CVEC_INTREP_TO_CVEC(v,w);
    return w;
  end);

InstallMethod( ConstructingFilter, "for a cvec",
  [IsCVecRep],
  function(v)
    return IsCVecRep;
  end );

# `NewVector` was a constructor
# in GAP <= 4.12 but is a tag based operation in GAP 4.13.
Perform( [ function( filt, f, l )
    local p,d,c;
    p := Characteristic(f);
    d := DegreeOverPrimeField(f);
    if IsSmallIntRep(p^d) then
        c := CVEC_NewCVecClass(p,d,Length(l));
    else
        c := CVEC_NewCVecClass(p,d,Length(l)/d);
    fi;
    return CVec(l,c);  # Delegate to another routine
  end ],
  function( method )
    if IS_CONSTRUCTOR( NewVector ) then
      # This holds in GAP <= 4.12.
      InstallMethod( NewVector,
        ["IsCVecRep", "IsField and IsFinite", "IsList"], method );
    elif IsBoundGlobal( "InstallTagBasedMethod" ) then
      # This should hold in GAP 4.13.
      ValueGlobal("InstallTagBasedMethod")( NewVector, IsCVecRep, method );
    else
      # This should not happen.
      Error( "NewVector is neither a constructor not a tag based operation" );
    fi;
  end );

# `NewZeroVector` was a constructor
# in GAP <= 4.12 but is a tag based operation in GAP 4.13.
Perform( [ function( filt, f, l )
    local p,d,cl;
    p := Characteristic(f);
    d := DegreeOverPrimeField(f);
    cl := CVEC_NewCVecClass(p,d,l);
    return CVEC_NEW(cl,cl![CVEC_IDX_type]);
  end ],
  function( method )
    if IS_CONSTRUCTOR( NewZeroVector ) then
      # This holds in GAP <= 4.12.
      InstallMethod( NewZeroVector,
        ["IsCVecRep", "IsField and IsFinite", "IsInt"], method );
    elif IsBoundGlobal( "InstallTagBasedMethod" ) then
      # This should hold in GAP 4.13.
      ValueGlobal("InstallTagBasedMethod")( NewZeroVector, IsCVecRep, method );
    else
      # This should not happen.
      Error( "NewZeroVector is neither a constructor not a tag based operation" );
    fi;
  end );

InstallMethod( Vector, "for a list of finite field elements, and a cvec",
  [IsList, IsCVecRep],
  function( l, v )
    local c;
    if Length(l) = Length(v) then
        return CVec(l,DataObj(v));
    else
        c := CVEC_NewCVecClassSameField(DataObj(v),Length(l));
        return CVec(l,c);
    fi;
  end );

InstallMethod( ChangedBaseDomain, "for a cvec and a finite field",
  [IsCVecRep,IsField and IsFinite],
  function( v, f )
    local cl;
    cl := CVEC_NewCVecClass(Characteristic(f),DegreeOverPrimeField(f),
                            Length(v));
    return CVec(Unpack(v),cl);
  end );

# And the way back:

InstallMethod( Unpack, "for cvecs", [IsCVecRep],
  function(v)
    local d,f,fam,i,l,p,q,vcl;
    vcl := DataObj(v);
    f := vcl![CVEC_IDX_fieldinfo];
    p := f![CVEC_IDX_p];
    d := f![CVEC_IDX_d];
    q := f![CVEC_IDX_q];
    if q <= MAXSIZE_GF_INTERNAL or d = 1 then
        l := 0*[1..Length(v)];
    else
        l := List([1..Length(v)],i->0*[1..d]);
    fi;
    CVEC_CVEC_TO_INTREP(v,l);
    # Now convert things to FFEs:
    if q <= MAXSIZE_GF_INTERNAL then
        # We return internal FFEs:
        CVEC_INTLI_TO_FFELI(f,l);
    elif d = 1 then
        # We return ZmodnZObjs:
        for i in [1..Length(l)] do
            l[i] := ZmodnZObj(l[i],p);
        od;
    elif p < MAXSIZE_GF_INTERNAL then
        # We build a large FFE with GF2 or 8bit coeffs
        fam := FFEFamily(p);
        for i in [1..Length(l)] do
            CVEC_INTLI_TO_FFELI(f,l[i]);
            ConvertToVectorRep(l[i],p);
            l[i] := [l[i],d,fail];
            Objectify(fam!.ConwayFldEltDefaultType,l[i]);
        od;
    else
        # We build a large FFE with ZmodnZObj coeffs
        fam := FFEFamily(p);
        for i in [1..Length(l)] do
            l[i] := [List(l[i],x->ZmodnZObj(x,p)),d,fail];
            Objectify(fam!.ConwayFldEltDefaultType,l[i]);
        od;
    fi;
    return l;
  end);

InstallMethod( IntegerRep, "for cvecs", [IsCVecRep],
  function(v)
    local d,l,p,q,vcl;
    vcl := DataObj(v);
    p := vcl![CVEC_IDX_fieldinfo]![CVEC_IDX_p];
    d := vcl![CVEC_IDX_fieldinfo]![CVEC_IDX_d];
    q := vcl![CVEC_IDX_fieldinfo]![CVEC_IDX_q];
    if q <= MAXSIZE_GF_INTERNAL or d = 1 then
        l := 0*[1..Length(v)];
    else
        l := List([1..Length(v)],i->0*[1..d]);
    fi;
    CVEC_CVEC_TO_INTREP(v,l);
    return l;
  end);

InstallOtherMethod( NumberFFVector, "for a cvec, and a field size",
  [IsCVecRep and IsRowVector and IsFFECollection, IsPosInt],
  function(v,sz)
    local bas,c,f,halfword,i,l,res,wordlen;
    c := DataObj(v);
    f := c![CVEC_IDX_fieldinfo];
    if sz <> f![CVEC_IDX_q] then
        ErrorNoReturn("CVEC_NumberFFVector: vector over wrong field");
    fi;
    wordlen := c![CVEC_IDX_wordlen];
    bas := f![CVEC_IDX_p] ^ f![CVEC_IDX_elsperword];
    if IsSmallIntRep(bas) then
        l := 0*[1..wordlen];
        CVEC_CVEC_TO_NUMBERFFLIST(v,l,false);
        res := l[1];
        for i in [2..wordlen] do
            res := res * bas + l[i];
        od;
    else
        l := 0*[1..2*wordlen];
        CVEC_CVEC_TO_NUMBERFFLIST(v,l,true);
        halfword := 2^(CVEC_BYTESPERWORD*4);
        res := l[1] + l[2]*halfword;
        for i in [3,5..2*wordlen-1] do
            res := res * bas + l[i] + halfword * l[i+1];
        od;
    fi;
    return res;
  end);

InstallOtherMethod( NumberFFVector, "for a cvec", 
  [IsCVecRep and IsRowVector and IsFFECollection],
  function(v)
    local c;
    c := DataObj(v);
    return NumberFFVector(v,c![CVEC_IDX_fieldinfo]![CVEC_IDX_q]);
  end);

InstallMethod( CVecNumber, "for four integers", 
  [IsInt,IsPosInt,IsPosInt,IsPosInt],
  function(nr,p,d,l)
    local c;
    c := CVEC_NewCVecClass(p,d,l);
    return CVecNumber(nr,c);
  end );

InstallMethod( CVecNumber, "for an integer, and a cvecclass",
  [IsInt, IsCVecClass],
  function(nr,c)
    local bas,f,halfword,i,l,q,qq,v,wordlen;
    v := CVEC_NEW(c,c![CVEC_IDX_type]);
    wordlen := c![CVEC_IDX_wordlen];
    f := c![CVEC_IDX_fieldinfo];
    bas := f![CVEC_IDX_p] ^ f![CVEC_IDX_elsperword];
    if IsSmallIntRep(bas) then
        l := 0*[1..wordlen];
        for i in [wordlen,wordlen-1..1] do
            q := QuotientRemainder(nr,bas);
            l[i] := q[2];
            nr := q[1];
        od;
        CVEC_NUMBERFFLIST_TO_CVEC(l,v,false);
    else
        l := 0*[1..2*wordlen];
        halfword := 2^(CVEC_BYTESPERWORD*4);
        for i in [2*wordlen-1,2*wordlen-3..1] do
            q := QuotientRemainder(nr,bas);
            qq := QuotientRemainder(q[2],halfword);
            l[i] := qq[2];
            l[i+1] := qq[1];
            nr := q[1];
        od;
        CVEC_NUMBERFFLIST_TO_CVEC(l,v,true);
    fi;
    return v;
  end );
    

#############################################################################
# Access to the base field:
#############################################################################

InstallOtherMethod( Characteristic, "for cvecs", [IsCVecRep],
  function(v)
    local c;
    c := DataObj(v);
    return c![CVEC_IDX_fieldinfo]![CVEC_IDX_p];
  end);
    
InstallOtherMethod( DegreeFFE, "for cvecs", [IsCVecRep],
  function(v)
    local c;
    c := DataObj(v);
    return c![CVEC_IDX_fieldinfo]![CVEC_IDX_d];
  end);
    
InstallMethod( BaseDomain, "for cvecs", [IsCVecRep],
  function(v)
    local c;
    c := DataObj(v);
    return c![CVEC_IDX_GF];
  end);

# compatibility with GAP <= 4.11
if IsBound(BaseField) and not IsIdenticalObj(BaseDomain, BaseField) then
InstallMethod( BaseField, "for cvecs", [IsCVecRep],
  function(v)
    local c;
    c := DataObj(v);
    return c![CVEC_IDX_GF];
  end);
fi;

#############################################################################
# Slicing:
#############################################################################

InstallGlobalFunction( CVEC_Slice, function(src,dst,srcpos,len,dstpos)
  local cdst,csrc;
  csrc := DataObj(src);
  cdst := DataObj(dst);
  if not(IsIdenticalObj(csrc![CVEC_IDX_fieldinfo],
                        cdst![CVEC_IDX_fieldinfo])) then
      ErrorNoReturn("CVEC_Slice: vectors not over common field");
  fi;
  if srcpos < 1 or srcpos+len-1 > csrc![CVEC_IDX_len] or len <= 0 then
      ErrorNoReturn("CVEC_Slice: source area not valid");
  fi;
  if dstpos < 1 or dstpos+len-1 > cdst![CVEC_IDX_len] then
      ErrorNoReturn("CVEC_Slice: destination area not valid");
  fi;
  if not(IsMutable(dst)) then
      ErrorNoReturn("CVEC_Slice: destination vector immutable");
  fi;
  CVEC_SLICE(src,dst,srcpos,len,dstpos);
end );

InstallGlobalFunction( CVEC_SliceList, function(src,dst,srcposs,dstposs)
  if not(IsMutable(dst)) then
      ErrorNoReturn("CVEC_SliceList: destination vector immutable");
  fi;
  CVEC_SLICE_LIST(src,dst,srcposs,dstposs);
end );

InstallOtherMethod( \{\}, "for a cvec and a range", 
  [IsCVecRep, IsList and IsRangeRep],
  function(v,r)
    # note that ranges in IsRangeRep always have length at least 2!
    local c,cl,w;
    cl := DataObj(v);
    c := CVEC_NewCVecClassSameField(cl,Length(r));
    w := CVEC_NEW(c,c![CVEC_IDX_type]);
    CVEC_SLICE_LIST(v,w,r,[1..Length(r)]);
    if not(IsMutable(v)) then
        MakeImmutable(w);
    fi;
    return w;
  end);

InstallOtherMethod( \{\}, "for a cvec and a list", 
  [IsCVecRep, IsList],
  function(v,l)
    local c,cl,w;
    cl := DataObj(v);
    c := CVEC_NewCVecClassSameField(cl,Length(l));
    w := CVEC_NEW(c,c![CVEC_IDX_type]);
    CVEC_SLICE_LIST(v,w,l,[1..Length(l)]);
    if not(IsMutable(v)) then
        MakeImmutable(w);
    fi;

    return w;
  end);

InstallOtherMethod( CopySubVector, "for two cvecs and stuff",
  [IsCVecRep, IsCVecRep and IsMutable, IsList, IsList],
  function(src,dst,scols,dcols)
    if Length(scols) = 0 then return; fi;  # a little speedup
    CVEC_SLICE_LIST(src,dst,scols,dcols);
  end );

# Note that slicing assignment is intentionally not supported, because
# this will usually be used only by inefficient code. Use CVEC_Slice
# or even CVEC_SLICE instead.

# Concatenation of vectors:

InstallGlobalFunction( CVEC_Concatenation, function(arg)
  local c,cc,i,len,pos,v;
  if Length(arg) = 0 or not(IsCVecRep(arg[1])) then
      ErrorNoReturn("CVEC_Concatenation: Need at least one cvec");
  fi;
  c := DataObj(arg[1]);
  len := Length(arg[1]);
  for i in [2..Length(arg)] do
      if not(IsCVecRep(arg[i])) or 
         not(IsIdenticalObj(c,DataObj(arg[i]))) then
          ErrorNoReturn("CVEC_Concatenation: Arguments must all be cvecs ",
                "over the same field ");
      fi;
      len := len + Length(arg[i]);
  od;
  cc := CVEC_NewCVecClassSameField(c,len);
  v := CVEC_New(cc);
  pos := 1;
  for i in [1..Length(arg)] do
      CVEC_SLICE(arg[i],v,1,Length(arg[i]),pos);
      pos := pos + Length(arg[i]);
  od;
  return v;
end );


############################################################################
# For polynomial arithmetic: 
############################################################################

InstallOtherMethod( ProductCoeffs, "for cvecs",
  [IsCVecRep, IsCVecRep],
  function(v,w)
  local cl,u,vcl,wcl;
  vcl := DataObj(v);
  if vcl![CVEC_IDX_fieldinfo]![CVEC_IDX_d] > 1 then
      ErrorNoReturn("Non-prime fields not yet implemented (doable)!");
  fi;
  wcl := DataObj(w);
  if not(IsIdenticalObj(vcl![CVEC_IDX_fieldinfo],wcl![CVEC_IDX_fieldinfo])) then
      ErrorNoReturn("ProductCoeffs: Not over same field!");
  fi;
  cl := CVEC_NewCVecClassSameField(vcl,vcl![CVEC_IDX_len]+wcl![CVEC_IDX_len]-1);
  u := CVEC_NEW(cl,cl![CVEC_IDX_type]);
  CVEC_PROD_COEFFS_CVEC_PRIMEFIELD(u,v,w);
  return u;
end);


############################################################################
# For (pseudo) random vectors: 
############################################################################

InstallMethod( Randomize, "for cvecs", [IsCVecRep and IsMutable],
    v -> Randomize(GlobalMersenneTwister, v) );

InstallOtherMethod( Randomize, "for a random source and a cvec",
  [IsRandomSource, IsCVecRep and IsMutable],
  function( rs, v )
    local cl,d,j,len,li,p,q,size;
    cl := DataObj(v);
    len := Length(v);
    size := cl![CVEC_IDX_fieldinfo]![CVEC_IDX_size];
    d := cl![CVEC_IDX_fieldinfo]![CVEC_IDX_d];
    if size <= 1 then
        q := cl![CVEC_IDX_fieldinfo]![CVEC_IDX_q];
        li := 0*[1..len];
        for j in [1..len] do
            li[j] := Random(rs,0,q-1);
        od;
        CVEC_INTREP_TO_CVEC(li,v);
    else    # big scalars!
        li := 0*[1..len*d];
        p := cl![CVEC_IDX_fieldinfo]![CVEC_IDX_p];
        for j in [1..len*d] do
            li[j] := Random(rs,0,p-1);
        od;
        CVEC_INTREP_TO_CVEC(li,v);
    fi;
    return v;
  end );

# for compatibility with GAP < 4.11
InstallOtherMethod( Randomize, "for a cvec and a random source",
  [IsCVecRep and IsMutable, IsRandomSource],
    { v, rs } -> Randomize( rs, v ) );


#############################################################################
# The making of good hash functions:
#############################################################################

InstallGlobalFunction( CVEC_HashFunctionForCVecs, function(v,data)
  return HashKeyBag(v,257,CVEC_BYTESPERWORD,data[2]) mod data[1] + 1;
end );

InstallMethod( ChooseHashFunction, "for cvecs",
  [IsCVecRep,IsInt],
  function(p,hashlen)
    local bytelen,c;
    c := CVecClass(p);
    bytelen := c![CVEC_IDX_wordlen] * CVEC_BYTESPERWORD;
    return rec( func := CVEC_HashFunctionForCVecs,
                data := [hashlen,bytelen] );
  end );


#############################################################################
# (Un-)Pickling:
#############################################################################

CVEC_CMatMaker := fail;   # this is to get rid of a warning in this method
InstallMethod( IO_Pickle, "for cvecs",
  [IsFile, IsCVecRep and IsList],
  function( f, v )
    local m,tag;
    if IsMutable(v) then tag := "MCVC";
    else tag := "ICVC"; fi;
    if IO_Write(f,tag) = fail then return IO_Error; fi;
    m := CVEC_CMatMaker( [0,v], DataObj(v) );
    if CVEC_WriteMat( f, m ) = fail then return IO_Error; fi;
    return IO_OK;
  end );
Unbind(CVEC_CMatMaker);

IO_Unpicklers.MCVC :=
  function( f )
    local m;
    m := CVEC_ReadMat( f ); if m = fail then return IO_Error; fi;
    return m[1];
  end;

IO_Unpicklers.ICVC :=
  function( f )
    local m;
    m := CVEC_ReadMat( f ); if m = fail then return IO_Error; fi;
    MakeImmutable(m);
    return m[1];
  end;


#############################################################################
# Memory usage information:
#############################################################################

InstallOtherMethod( Memory, "for a cvec", [ IsCVecRep ],
  function( v )
    # the header is 2 words on 64bit and 3 words on 32bit machines:
    # we count the master pointer!
    return SIZE_OBJ(v) + 8 + 2 * GAPInfo.BytesPerVariable;
  end );

##
##  This program is free software; you can redistribute it and/or modify
##  it under the terms of the GNU General Public License as published by
##  the Free Software Foundation; either version 2 of the License,
##  or (at your option) any later version.
##
##  This program is distributed in the hope that it will be useful,
##  but WITHOUT ANY WARRANTY; without even the implied warranty of
##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
##  GNU General Public License for more details.
##
##  You should have received a copy of the GNU General Public License
##  along with this program; if not, write to the Free Software
##  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
##

[ zur Elbe Produktseite wechseln0.64Quellennavigators  Analyse erneut starten  ]