diff --git a/doc/ref/matobj.xml b/doc/ref/matobj.xml index 2818815902..de2be4121b 100644 --- a/doc/ref/matobj.xml +++ b/doc/ref/matobj.xml @@ -348,6 +348,16 @@ and for those methods of that do not delegate to and , respectively. +
+ +For the implementation of new vector and matrix object types, +we recommend that the low level function gets called +only by some helper functions that handle the choice of the type of +the desired object and the consistency checks for the internal data. +An example can be found in the file is out of bounds" );
+ fi;
+ fi;
+ if IsInt( ob ) then
+ v![ZELSPOS][p]:= ob mod Size( v![ZBDPOS] );
+ else
+ v![ZELSPOS][p]:= Int( ob );
+ fi;
end );
-InstallMethod( PositionNonZero, "for a zmodnz vector", [ IsZmodnZVectorRep ],
- function( v )
- return PositionNonZero( v![ELSPOS] );
- end );
+InstallMethod( \{\},
+ [ "IsZmodnZVectorRep", "IsList" ],
+ { v, list } -> MakeIsZmodnZVectorRep( v![ZBDPOS], v![ZELSPOS]{ list }, false ) );
-InstallOtherMethod( PositionNonZero, "for a zmodnz vector and start",
- [ IsZmodnZVectorRep,IsInt ],
- function( v,s )
- return PositionNonZero( v![ELSPOS],s );
- end );
-InstallMethod( PositionLastNonZero, "for a zmodnz vector", [ IsZmodnZVectorRep ],
+InstallMethod( Unpack,
+ [ "IsZmodnZVectorRep" ],
function( v )
- local els,i;
- els := v![ELSPOS];
- i := Length(els);
- while i > 0 and IsZero(els[i]) do i := i - 1; od;
- return i;
+ local fam;
+ fam:= ElementsFamily( FamilyObj( v ) );
+ return List( v![ZELSPOS], x -> ZmodnZObj( fam, x ) );
end );
-InstallMethod( ListOp, "for a zmodnz vector", [ IsZmodnZVectorRep ],
-function( v )
-local fam;
- fam:=ElementsFamily(FamilyObj(v));
- return List([1..Length(v![ELSPOS])],x->ZmodnZObj(fam,v![ELSPOS][x]));
-end );
-
-InstallMethod( ListOp, "for a zmodnz vector and a function",
- [ IsZmodnZVectorRep, IsFunction ],
-function( v, f )
-local fam;
- fam:=ElementsFamily(FamilyObj(v));
- return List(List([1..Length(v![ELSPOS])],x->ZmodnZObj(fam,v![ELSPOS][x])),f);
-end );
-
-InstallMethod( Unpack, "for a zmodnz vector",
- [ IsZmodnZVectorRep ],
-function( v )
-local fam;
- fam:=ElementsFamily(FamilyObj(v));
- return List([1..Length(v![ELSPOS])],x->ZmodnZObj(fam,v![ELSPOS][x]));
-end );
-
-############################################################################
-# Arithmetical operations:
-############################################################################
-
-InstallMethod( \+, "for two zmodnz vectors",IsIdenticalObj,
- [ IsZmodnZVectorRep, IsZmodnZVectorRep ],
-function( a, b )
-local ty,i,m,mu;
- if not IsMutable(a) and IsMutable(b) then
- ty := TypeObj(b);
- else
- ty := TypeObj(a);
- fi;
- m:=Size(a![BDPOS]);
- b:=SUM_LIST_LIST_DEFAULT(a![ELSPOS],b![ELSPOS]);
- if not IsMutable(b) then mu:=true;b:=ShallowCopy(b);
- else mu:=false;fi;
- for i in [1..Length(b)] do if b[i]>=m then b[i]:=b[i] mod m;fi;od;
- if mu then MakeImmutable(b);fi;
- return Objectify(ty,[a![BDPOS],b]);
-end );
-
-InstallOtherMethod( \+, "for zmodnz vector and plist",IsIdenticalObj,
- [ IsZmodnZVectorRep, IsList ],
-function( a, b )
- return a+Vector(BaseDomain(a),b);
-end );
+InstallMethod( ShallowCopy, [ "IsZmodnZVectorRep" ],
+ v -> MakeIsZmodnZVectorRep( v![ZBDPOS], ShallowCopy( v![ZELSPOS] ), false ) );
-InstallOtherMethod( \+, "for plist and zmodnz vector",IsIdenticalObj,
- [ IsList,IsZmodnZVectorRep ],
-function( a, b )
- return Vector(BaseDomain(b),a)+b;
-end );
-
-InstallMethod( \-, "for two zmodnz vectors",IsIdenticalObj,
- [ IsZmodnZVectorRep, IsZmodnZVectorRep ],
-function( a, b )
-local ty,i,m,mu;
- if not IsMutable(a) and IsMutable(b) then
- ty := TypeObj(b);
- else
- ty := TypeObj(a);
- fi;
- m:=Size(a![BDPOS]);
- b:=a![ELSPOS] - b![ELSPOS];
- if not IsMutable(b) then mu:=true;b:=ShallowCopy(b);
- else mu:=false;fi;
- for i in [1..Length(b)] do if b[i]<0 then b[i]:=b[i] mod m;fi;od;
- if mu then MakeImmutable(b);fi;
- return Objectify(ty,[a![BDPOS],b]);
-end );
-
-InstallOtherMethod( \-, "for zmodnz vector and plist",IsIdenticalObj,
- [ IsZmodnZVectorRep, IsList ],
-function( a, b )
- return a-Vector(BaseDomain(a),b);
-end );
-
-InstallOtherMethod( \-, "for plist and zmodnz vector",IsIdenticalObj,
- [ IsList,IsZmodnZVectorRep ],
-function( a, b )
- return Vector(BaseDomain(b),a)-b;
-end );
-
-InstallMethod( \=, "for two zmodnz vectors",IsIdenticalObj,
- [ IsZmodnZVectorRep, IsZmodnZVectorRep ],
+InstallMethod( \+,
+ [ "IsZmodnZVectorRep", "IsZmodnZVectorRep" ],
function( a, b )
- return EQ_LIST_LIST_DEFAULT(a![ELSPOS],b![ELSPOS]);
+ local R, mu, n, i;
+ R:= a![ZBDPOS];
+ if ValueOption( "check" ) <> false and
+ not IsIdenticalObj( R, b![ZBDPOS] ) then
+ Error( " and are not compatible" );
+ fi;
+ b:= SUM_LIST_LIST_DEFAULT(a![ZELSPOS],b![ZELSPOS]);
+ if not IsMutable( b ) then
+ mu:= true;
+ b:= ShallowCopy( b );
+ else
+ mu:= false;
+ fi;
+ n:= Size( R );
+ for i in [ 1 .. Length( b ) ] do
+ if b[i] >= n then
+ b[i]:= b[i] mod n;
+ fi;
+ od;
+ if mu then
+ MakeImmutable( b );
+ fi;
+ return MakeIsZmodnZVectorRep( R, b, false );
end );
-InstallMethod( \=, "for zmodnz vector and plist",IsIdenticalObj,
- [ IsZmodnZVectorRep, IsPlistRep ],
-function( a, b )
- return a![ELSPOS]=List(b,x->x![1]);
-end );
+InstallOtherMethod( \+,
+ IsIdenticalObj,
+ [ "IsZmodnZVectorRep", "IsList" ],
+ { a, b } -> a + Vector( BaseDomain( a ), b ) );
+#TODO: Do we want this? If yes then it should be documented.
-InstallMethod( \=, "for plist an zmodnz vector",IsIdenticalObj,
- [ IsPlistRep,IsZmodnZVectorRep],
-function(b,a)
- return a![ELSPOS]=List(b,x->x![1]);
-end );
+InstallOtherMethod( \+,
+ IsIdenticalObj,
+ [ "IsList", "IsZmodnZVectorRep" ],
+ { a, b } -> Vector( BaseDomain( b ), a ) + b );
+#TODO: Do we want this? If yes then it should be documented.
-InstallMethod( \<, "for two zmodnz vectors",IsIdenticalObj,
- [ IsZmodnZVectorRep, IsZmodnZVectorRep ],
+InstallMethod( \-,
+ [ "IsZmodnZVectorRep", "IsZmodnZVectorRep" ],
function( a, b )
- return LT_LIST_LIST_DEFAULT(a![ELSPOS],b![ELSPOS]);
- end );
-
-InstallMethod( AddRowVector, "for two zmodnz vectors",
- [ IsZmodnZVectorRep and IsMutable, IsZmodnZVectorRep ],
-function( a, b )
-local i,m;
- a:=a![ELSPOS];
- ADD_ROW_VECTOR_2_FAST( a, b![ELSPOS] );
- m:=Size(b![BDPOS]);
- for i in [1..Length(a)] do if a[i]>=m then a[i]:=a[i] mod m;fi;od;
-end );
-
-InstallMethod( AddRowVector, "for two zmodnz vectors, and a scalar",
- [ IsZmodnZVectorRep and IsMutable, IsZmodnZVectorRep, IsObject ],
-function( a, b, s )
-local i,m;
- if IsZmodnZObj(s) then s:=Int(s);fi;
- a:=a![ELSPOS];
- if IsSmallIntRep(s) then
- ADD_ROW_VECTOR_3_FAST( a, b![ELSPOS], s );
- else
- ADD_ROW_VECTOR_3( a, b![ELSPOS], s );
- fi;
- m:=Size(b![BDPOS]);
- if s>=0 then
- for i in [1..Length(a)] do if a[i]>=m then a[i]:=a[i] mod m;fi;od;
+ local R, mu, n, i;
+ R:= a![ZBDPOS];
+ if ValueOption( "check" ) <> false and
+ not IsIdenticalObj( a![ZBDPOS], b![ZBDPOS] ) then
+ Error( " and are not compatible" );
+ fi;
+ b:= DIFF_LIST_LIST_DEFAULT( a![ZELSPOS], b![ZELSPOS]);
+ if not IsMutable( b ) then
+ mu:= true;
+ b:= ShallowCopy( b );
+ else
+ mu:= false;
+ fi;
+ n:= Size( R );
+ for i in [ 1 .. Length( b ) ] do
+ if b[i] < 0 then
+ b[i]:= b[i] mod n;
+ fi;
+ od;
+ if mu then
+ MakeImmutable( b );
+ fi;
+ return MakeIsZmodnZVectorRep( R, b, false );
+ end );
+
+InstallOtherMethod( \-,
+ IsIdenticalObj,
+ [ "IsZmodnZVectorRep", "IsList" ],
+ { a, b } -> a-Vector(BaseDomain(a),b) );
+#TODO: Do we want this? If yes then it should be documented.
+
+InstallOtherMethod( \-,
+ IsIdenticalObj,
+ [ "IsList", "IsZmodnZVectorRep" ],
+ { a, b } -> Vector(BaseDomain(b),a)-b );
+#TODO: Do we want this? If yes then it should be documented.
+
+BindGlobal( "ZMODNZVECADDINVCLEANUP", function( m, l )
+ local i;
+ if IsMutable( l ) then
+ for i in [ 1 .. Length( l ) ] do
+ if l[i] < 0 then
+ l[i]:= l[i] mod m;
+ fi;
+ od;
else
- for i in [1..Length(a)] do if a[i]<0 then a[i]:=a[i] mod m;fi;od;
+ l:= ShallowCopy( l );
+ for i in [ 1 .. Length( l ) ] do
+ if l[i] < 0 then
+ l[i]:= l[i] mod m;
+ fi;
+ od;
+ MakeImmutable( l );
fi;
-end );
+ return l;
+ end );
-InstallOtherMethod( AddRowVector, "for zmodnz vector, plist, and a scalar",
- [ IsZmodnZVectorRep and IsMutable, IsPlistRep, IsObject ],
-function( a, b, s )
-local i,m;
- if not ForAll(b,IsModulusRep) then TryNextMethod();fi;
- if IsZmodnZObj(s) then s:=Int(s);fi;
- m:=Size(a![BDPOS]);
- a:=a![ELSPOS];
- b:=List(b,x->x![1]);
-
- if IsSmallIntRep(s) then
- ADD_ROW_VECTOR_3_FAST( a, b, s );
- else
- ADD_ROW_VECTOR_3( a, b, s );
- fi;
- if s>=0 then
- for i in [1..Length(a)] do if a[i]>=m then a[i]:=a[i] mod m;fi;od;
- else
- for i in [1..Length(a)] do if a[i]<0 then a[i]:=a[i] mod m;fi;od;
- fi;
-end );
+# Avoid 'Unpack'.
+InstallMethod( AdditiveInverseMutable,
+ [ "IsZmodnZVectorRep" ],
+ function( v )
+ local res;
+ res:= MakeIsZmodnZVectorRep( v![ZBDPOS],
+ ZMODNZVECADDINVCLEANUP(Size(v![ZBDPOS]),
+ AdditiveInverseMutable(v![ZELSPOS])), true );
+ return res;
+ end );
-InstallOtherMethod( AddRowVector, "for plist, zmodnz vector, and a scalar",
- [ IsPlistRep and IsMutable, IsZmodnZVectorRep, IsObject ],
-function( a, b, s )
-local i;
- if not ForAll(a,IsModulusRep) then TryNextMethod();fi;
- for i in [1..Length(a)] do
- a[i]:=a[i]+b[i]*s;
- od;
-end);
+InstallMethod( ZeroMutable, [ "IsZmodnZVectorRep" ],
+ v -> MakeIsZmodnZVectorRep( v![ZBDPOS], ZeroMutable(v![ZELSPOS]), false ) );
+
+BindGlobal( "ZMODNZVECSCAMULT",
+ function( w, s )
+ local i,m,b,v;
+ b:= w![ZBDPOS];
+ m:= Size( b );
+ if not IsInt( s ) then
+ if IsRat( s ) then
+ s:= s mod m;
+ elif s in b then
+ s:= Int( s );
+ else
+ Error( "multiplication with is out of bounds" );
+ fi;
v![ELSPOS][p] := ob;
end );
@@ -699,7 +704,7 @@ InstallMethod( Matrix,
else
l := [];
fi;
- # The result shall be mutable iff 'rows' is mutable.
+ # The result shall be mutable iff 'list' is mutable.
if not IsMutable( list ) then
MakeImmutable( l );
fi;
diff --git a/lib/matrix.gi b/lib/matrix.gi
index 956cd1b41b..a07cb740df 100644
--- a/lib/matrix.gi
+++ b/lib/matrix.gi
@@ -3040,8 +3040,7 @@ InstallOtherMethod( SolutionMatDestructive,
local i,ncols,sem, vno, z,x, sol;
ncols := Length(vec);
z := ZeroOfBaseDomain(mat);
- sol := ListWithIdenticalEntries(NrRows(mat),z);
- ConvertToVectorRepNC(sol);
+ sol:= ZeroVector( NrRows( mat ), vec );
if ncols <> NrCols(mat) then
Error("SolutionMat: matrix and vector incompatible");
fi;
diff --git a/lib/vec8bit.gi b/lib/vec8bit.gi
index 5d4cddcae1..658f6180f9 100644
--- a/lib/vec8bit.gi
+++ b/lib/vec8bit.gi
@@ -1094,10 +1094,16 @@ InstallMethod( BaseField, "for a compressed 8bit vector",
InstallTagBasedMethod( NewVector,
Is8BitVectorRep,
function( filter, f, l )
- if ValueOption( "check" ) <> false and not Size(f) in [3..256] then
+ local check, res;
+ check:= ValueOption( "check" ) <> false;
+ if check and not Size(f) in [3..256] then
Error("Is8BitVectorRep only supports base fields with 3 to 256 elements");
fi;
- return CopyToVectorRep(l,Size(f));
+ res:= CopyToVectorRep( l, Size( f ) );
+ if check and res = fail then
+ Error( "cannot copy is out of bounds
gap> STOP_TEST("ListOp.tst");
diff --git a/tst/testinstall/MatrixObj/matobjnz.tst b/tst/testinstall/MatrixObj/matobjnz.tst
new file mode 100644
index 0000000000..1cdce60061
--- /dev/null
+++ b/tst/testinstall/MatrixObj/matobjnz.tst
@@ -0,0 +1,458 @@
+#@local R, p, z, pol, M, v, w, s, c, MM, S, T
+gap> START_TEST( "matobjnz.tst" );
+
+#
+gap> ReadGapRoot( "tst/testinstall/MatrixObj/testmatobj.g" );
+
+# vectors over a prime field
+gap> R:= Integers mod 5;;
+gap> TestZeroVector( IsZmodnZVectorRep, R, 0 );;
+gap> TestZeroVector( IsZmodnZVectorRep, R, 3 );;
+gap> Vector( IsZmodnZVectorRep, GF(5), [ 1/5 ] );
+Error, is out of bounds
+gap> Unpack( v );
+[ ZmodnZObj( 1, 6 ), ZmodnZObj( 2, 6 ), ZmodnZObj( 3, 6 ) ]
+gap> v{ [ 2, 3 ] };
+ is not supported" );
+ fi;
+ fi;
+ v:= PROD_LIST_SCL_DEFAULT( w![ZELSPOS], s );
+ if not IsMutable( v ) then
+ v:= ShallowCopy( v );
+ fi;
+ if s >= 0 then
+ for i in [ 1 .. Length( v ) ] do
+ if v[i] >= m then
+ v[i]:= v[i] mod m;
+ fi;
+ od;
+ else
+ for i in [ 1 .. Length( v ) ] do
+ if v[i] < 0 then
+ v[i]:= v[i] mod m;
+ fi;
+ od;
+ fi;
+ if not IsMutable( w![ZELSPOS] ) then
+ MakeImmutable( v );
+ fi;
+ return MakeIsZmodnZVectorRep( w![ZBDPOS], v, true );
+ end );
-InstallOtherMethod( AddRowVector, "for plist, plist vector, and a scalar",
- [ IsPlistRep and IsMutable, IsPlistVectorRep, IsObject ],
-function( a, b, s )
-local i;
- for i in [1..Length(a)] do
- a[i]:=a[i]+b[i]*s;
- od;
-end);
+# Requiring 'IsScalar' for scalar multiplication/division is dangerous
+# without prescribed family relation if matrix objects are scalars.
+# Here the situation is easier than in general
+# because we want to restrict the scalars to 'IsRat' or
+# elements of the base domain of the vector.
+# (We need the 'IsScalar' to get a rank that is higher than the one
+# for the generic method that is based on 'Unpack'.)
+InstallOtherMethod( \*,
+ [ "IsZmodnZVectorRep", "IsRat" ],
+ ZMODNZVECSCAMULT );
-InstallMethod( AddRowVector,
- "for two zmodnz vectors, a scalar, and two positions",
- [ IsZmodnZVectorRep and IsMutable, IsZmodnZVectorRep,
- IsObject, IsPosInt, IsPosInt ],
-function( a, b, s, from, to )
-local i,m;
- if IsZmodnZObj(s) then s:=Int(s);fi;
- a:=a![ELSPOS];
- if IsSmallIntRep(s) then
- ADD_ROW_VECTOR_5_FAST( a, b![ELSPOS], s, from, to );
- else
- ADD_ROW_VECTOR_5( a, b![ELSPOS], s, from, to );
- fi;
- m:=Size(b![BDPOS]);
- if s>=0 then
- for i in [1..Length(a)] do if a[i]>=m then a[i]:=a[i] mod m;fi;od;
- else
- for i in [1..Length(a)] do if a[i]<0 then a[i]:=a[i] mod m;fi;od;
- fi;
-end );
+InstallOtherMethod( \*,
+ IsCollsElms,
+ [ "IsZmodnZVectorRep", "IsScalar" ],
+ ZMODNZVECSCAMULT );
-InstallMethod( MultVectorLeft,
- "for a zmodnz vector, and an object",
- [ IsZmodnZVectorRep and IsMutable, IsObject ],
-function( v, s )
-local i,m;
- m:=Size(v![BDPOS]);
- if IsZmodnZObj(s) then s:=Int(s);fi;
- v:=v![ELSPOS];
- MULT_VECTOR_2_FAST(v,s);
- if s>=0 then
- for i in [1..Length(v)] do if v[i]>=m then v[i]:=v[i] mod m;fi;od;
- else
- for i in [1..Length(v)] do if v[i]<0 then v[i]:=v[i] mod m;fi;od;
- fi;
-end );
+InstallOtherMethod( \*,
+ [ "IsRat", "IsZmodnZVectorRep" ],
+ { s, v } -> ZMODNZVECSCAMULT( v, s ) );
-# The four argument version of MultVectorLeft / ..Right uses the generic
-# implementation in matobj.gi
-
-BindGlobal("ZMODNZVECSCAMULT",
-function( w, s )
-local i,m,t,b,v;
- t:=TypeObj(w);
- b:=w![BDPOS];
- m:=Size(b);
- if IsZmodnZObj(s) then s:=Int(s);fi;
- v:=PROD_LIST_SCL_DEFAULT(w![ELSPOS],s);
- if not IsMutable(v) then
- v:=ShallowCopy(v);
- fi;
- if s>=0 then
- for i in [1..Length(v)] do if v[i]>=m then v[i]:=v[i] mod m;fi;od;
- else
- for i in [1..Length(v)] do if v[i]<0 then v[i]:=v[i] mod m;fi;od;
- fi;
- if not IsMutable(w![ELSPOS]) then MakeImmutable(v);fi;
- return Objectify(t,[b,v]);
-end );
+InstallOtherMethod( \*,
+ IsElmsColls,
+ [ "IsScalar", "IsZmodnZVectorRep" ],
+ { s, v } -> ZMODNZVECSCAMULT( v, s ) );
-InstallMethod( \*, "for a zmodnz vector and a scalar",
- [ IsZmodnZVectorRep, IsScalar ],ZMODNZVECSCAMULT);
+InstallOtherMethod( \/,
+ [ "IsZmodnZVectorRep", "IsRat" ],
+ { v, s } -> ZMODNZVECSCAMULT( v, s^-1 ) );
-InstallMethod( \*, "for a scalar and a zmodnz vector",
- [ IsScalar, IsZmodnZVectorRep ],
-function( s, v )
- return ZMODNZVECSCAMULT(v,s);
-end );
+InstallOtherMethod( \/,
+ IsCollsElms,
+ [ "IsZmodnZVectorRep", "IsScalar" ],
+ { v, s } -> ZMODNZVECSCAMULT( v, s^-1 ) );
-InstallMethod( \/, "for a zmodnz vector and a scalar",
- [ IsZmodnZVectorRep, IsScalar ],
-function( v, s )
- return ZMODNZVECSCAMULT(v,s^-1);
-end );
-BindGlobal("ZMODNZVECADDINVCLEANUP",function(m,l)
-local i;
- if IsMutable(l) then
- for i in [1..Length(l)] do if l[i]<0 then l[i]:=l[i] mod m;fi;od;
- else
- l:=ShallowCopy(l);
- for i in [1..Length(l)] do if l[i]<0 then l[i]:=l[i] mod m;fi;od;
- MakeImmutable(l);
- fi;
- return l;
-end);
+InstallMethod( PostMakeImmutable,
+ [ "IsZmodnZVectorRep" ],
+ v -> MakeImmutable( v![ZELSPOS] ) );
-InstallMethod( AdditiveInverseSameMutability, "for a zmodnz vector",
- [ IsZmodnZVectorRep ],
- function( v )
- return Objectify( TypeObj(v),
- [v![BDPOS],ZMODNZVECADDINVCLEANUP(Size(v![BDPOS]),
- AdditiveInverseSameMutability(v![ELSPOS]))] );
- end );
-InstallMethod( AdditiveInverseImmutable, "for a zmodnz vector",
- [ IsZmodnZVectorRep ],
+InstallMethod( ViewObj,
+ [ "IsZmodnZVectorRep" ],
function( v )
- local res;
- res := Objectify( TypeObj(v),
- [v![BDPOS],ZMODNZVECADDINVCLEANUP(Size(v![BDPOS]),
- AdditiveInverseSameMutability(v![ELSPOS]))] );
- MakeImmutable(res);
- return res;
+ Print( "<" );
+ if not IsMutable( v ) then
+ Print( "immutable " );
+ fi;
+ Print( "vector over ", v![ZBDPOS], " of length ", Length( v![ZELSPOS] ),
+ ">" );
end );
-InstallMethod( AdditiveInverseMutable, "for a zmodnz vector",
- [ IsZmodnZVectorRep ],
+InstallMethod( PrintObj,
+ [ "IsZmodnZVectorRep" ],
function( v )
- local res;
- res := Objectify(TypeObj(v),
- [v![BDPOS],ZMODNZVECADDINVCLEANUP(Size(v![BDPOS]),
- AdditiveInverseMutable(v![ELSPOS]))]);
- if not IsMutable(v) then SetFilterObj(res,IsMutable); fi;
- return res;
+ Print( "NewVector(IsZmodnZVectorRep" );
+ if IsField( v![ZBDPOS] ) then
+ Print( ",GF(", Size( v![ZBDPOS] ), "),", v![ZELSPOS], ")" );
+ else
+ Print( ",", String( v![ZBDPOS] ), ",", v![ZELSPOS], ")" );
+ fi;
end );
-# redundant according to MH
-# InstallMethod( ZeroSameMutability, "for a zmodnz vector", [ IsZmodnZVectorRep ],
-# function( v )
-# return Objectify(TypeObj(v),[v![BDPOS],ZeroSameMutability(v![ELSPOS])]);
-# end );
-#
-# InstallMethod( ZeroImmutable, "for a zmodnz vector", [ IsZmodnZVectorRep ],
-# function( v )
-# local res;
-# res := Objectify(TypeObj(v),[v![BDPOS],ZeroImmutable(v![ELSPOS])]);
-# MakeImmutable(res);
-# return res;
-# end );
-
-InstallMethod( ZeroMutable, "for a zmodnz vector", [ IsZmodnZVectorRep ],
+InstallMethod( Display,
+ [ "IsZmodnZVectorRep" ],
function( v )
- local res;
- res := Objectify(TypeObj(v),
- [v![BDPOS],ZeroMutable(v![ELSPOS])]);
- if not IsMutable(v) then SetFilterObj(res,IsMutable); fi;
- return res;
+ Print( "\n" );
end );
-InstallMethod( IsZero, "for a zmodnz vector", [ IsZmodnZVectorRep ],
+InstallMethod( String,
+ [ "IsZmodnZVectorRep" ],
function( v )
- return IsZero( v![ELSPOS] );
- end );
-
-#InstallMethodWithRandomSource( Randomize,
-# "for a random source and a mutable zmodnz vector",
-# [ IsRandomSource, IsZmodnZVectorRep and IsMutable ],
-# function( rs, v )
-# local bd,i;
-# bd := v![BDPOS];
-# for i in [1..Length(v![ELSPOS])] do
-# v![ELSPOS][i] := Random( rs, bd );
-# od;
-# return v;
-# end );
-
-InstallMethod( CopySubVector, "for two zmodnz vectors and two lists",
- [ IsZmodnZVectorRep, IsZmodnZVectorRep and IsMutable, IsList, IsList ],
- function( a,b,pa,pb )
- # The following should eventually go into the kernel:
- if ValueOption( "check" ) <> false and a![BDPOS] <> b![BDPOS] then
- Error( " and have different base domains" );
+ local st;
+ st := "NewVector(IsZmodnZVectorRep,";
+ if IsField( v![ZBDPOS] ) then
+ Append( st, "GF(" );
+ Append( st, String( Size( v![ZBDPOS] ) ) );
+ Append( st, ")," );
+ else
+ Append( st, String( v![ZBDPOS] ) );
+ Append( st, "," );
fi;
- b![ELSPOS]{pb} := a![ELSPOS]{pa};
+ Append( st, String( v![ZELSPOS] ) );
+ Add( st, ')' );
+ return st;
end );
-InstallOtherMethod( ProductCoeffs,
- "zmodmat: call PRODUCT_COEFFS_GENERIC_LISTS with lengths",
- true, [ IsZmodnZVectorRep, IsZmodnZVectorRep], 0,
-function( l1, l2 )
- return PRODUCT_COEFFS_GENERIC_LISTS(l1,Length(l1),l2,Length(l2));
-end);
-
-############################################################################
-# Matrices
-############################################################################
-InstallTagBasedMethod( NewMatrix,
- IsZmodnZMatrixRep,
- function( filter, basedomain, rl, l )
- local check, nd, filterVectors, m, e, filter2, i;
+# Avoid element access.
+InstallMethod( PositionNonZero,
+ [ "IsZmodnZVectorRep" ],
+ v -> PositionNonZero( v![ZELSPOS] ) );
- check:= ValueOption( "check" ) <> false;
- if check and not ( IsZmodnZObjNonprimeCollection( basedomain ) or
- ( IsFinite( basedomain ) and IsPrimeField( basedomain ) ) ) then
- Error( " is not supported" );
+ fi;
+ fi;
+ a:= a![ZELSPOS];
+ if IsSmallIntRep( s ) then
+ ADD_ROW_VECTOR_3_FAST( a, b![ZELSPOS], s );
+ else
+ ADD_ROW_VECTOR_3( a, b![ZELSPOS], s );
+ fi;
+ m:= Size( b![ZBDPOS] );
+ if s >= 0 then
+ for i in [ 1 .. Length( a ) ] do
+ if a[i] >= m then
+ a[i]:= a[i] mod m;
+ fi;
+ od;
+ else
+ for i in [ 1 .. Length( a ) ] do
+ if a[i] < 0 then
+ a[i]:= a[i] mod m;
+ fi;
+ od;
+ fi;
end );
-InstallOtherMethod( BaseDomain, "for a zmodnz matrix",
- [ IsZmodnZMatrixRep ],
- M -> M![BDPOS] );
-
-InstallMethod( NumberRows, "for a zmodnz matrix",
- [ IsZmodnZMatrixRep ],
- M -> Length( M![ROWSPOS] ) );
-
-InstallMethod( NumberColumns, "for a zmodnz matrix",
- [ IsZmodnZMatrixRep ],
- M -> M![RLPOS] );
-
+InstallOtherMethod( AddRowVector,
+ [ "IsZmodnZVectorRep and IsMutable", "IsPlistRep", "IsObject" ],
+ function( a, b, s )
+ local bd, i, m;
+ if not ForAll( b, IsModulusRep ) then
+ TryNextMethod();
+ fi;
+ bd:= a![ZBDPOS];
+ if not IsInt( s ) then
+ if IsRat( s ) then
+ s:= s mod m;
+ elif s in bd then
+ s:= Int( s );
+ else
+ Error( "multiplication with is not supported" );
+ fi;
+ fi;
+ m:= Size( a![ZBDPOS] );
+ a:= a![ZELSPOS];
+ b:= List( b, x -> x![1] );
-############################################################################
-# Representation preserving constructors:
-############################################################################
+ if IsSmallIntRep( s ) then
+ ADD_ROW_VECTOR_3_FAST( a, b, s );
+ else
+ ADD_ROW_VECTOR_3( a, b, s );
+ fi;
+ if s >= 0 then
+ for i in [ 1 .. Length( a ) ] do
+ if a[i] >= m then
+ a[i]:= a[i] mod m;
+ fi;
+ od;
+ else
+ for i in [ 1 .. Length( a ) ] do
+ if a[i] < 0 then
+ a[i]:= a[i] mod m;
+ fi;
+ od;
+ fi;
+ end );
+#TODO: Do we want this? If yes then it should be documented.
-# redundant according to MH
-# InstallMethod( ZeroMatrix, "for two integers and a zmodnz matrix",
-# [ IsInt, IsInt, IsZmodnZMatrixRep ],
-# function( rows,cols,m )
-# local l,t,res;
-# t := m![EMPOS];
-# l := List([1..rows],i->ZeroVector(cols,t));
-# res := Objectify( TypeObj(m), [m![BDPOS],t,cols,l] );
-# if not IsMutable(m) then
-# SetFilterObj(res,IsMutable);
-# fi;
-# return res;
-# end );
-
-InstallMethod( IdentityMatrix, "for an integer and a zmodnz matrix",
- [ IsInt, IsZmodnZMatrixRep ],
- function( rows,m )
- local i,l,o,t,res;
- t := m![EMPOS];
- l := List([1..rows],i->ZeroVector(rows,t));
- o := One(m![BDPOS]);
- for i in [1..rows] do
- l[i][i] := o;
- od;
- res := Objectify( TypeObj(m), [m![BDPOS],t,rows,l] );
- if not IsMutable(m) then
- SetFilterObj(res,IsMutable);
+InstallOtherMethod( AddRowVector,
+ [ "IsPlistRep and IsMutable", "IsZmodnZVectorRep", "IsObject" ],
+ function( a, b, s )
+ local i;
+ if not ForAll( a, IsModulusRep ) then
+ TryNextMethod();
fi;
- return res;
+ for i in [ 1 .. Length( a ) ] do
+ a[i]:= a[i] + b[i] * s;
+ od;
end );
+#TODO: Do we want this? If yes then it should be documented.
-InstallMethod( Matrix, "for a list and a zmodnz matrix",
- [ IsList, IsInt, IsZmodnZMatrixRep ],
- function( rows,rowlen,m )
- local i,l,nrrows,res,t;
- t := m![EMPOS];
- if Length(rows) > 0 then
- if IsVectorObj(rows[1]) and IsZmodnZVectorRep(rows[1]) then
- nrrows := Length(rows);
- l := rows;
- elif IsList(rows[1]) then
- nrrows := Length(rows);
- l := ListWithIdenticalEntries(Length(rows),0);
- for i in [1..Length(rows)] do
- l[i] := Vector(rows[i],t);
- od;
- else # a flat initializer:
- nrrows := Length(rows)/rowlen;
- l := ListWithIdenticalEntries(nrrows,0);
- for i in [1..nrrows] do
- l[i] := Vector(rows{[(i-1)*rowlen+1..i*rowlen]},t);
- od;
- fi;
+InstallMethod( AddRowVector,
+ [ "IsZmodnZVectorRep and IsMutable", "IsZmodnZVectorRep",
+ "IsObject", "IsPosInt", "IsPosInt" ],
+ function( a, b, s, from, to )
+ local bd, i, m;
+ bd:= a![ZBDPOS];
+ if ValueOption( "check" ) <> false and
+ not IsIdenticalObj( bd, b![ZBDPOS] ) then
+ Error( " and are not compatible" );
+ fi;
+ if not IsInt( s ) then
+ if IsRat( s ) then
+ s:= s mod m;
+ elif s in bd then
+ s:= Int( s );
+ else
+ Error( "multiplication with is not supported" );
+ fi;
+ fi;
+ a:= a![ZELSPOS];
+ if IsSmallIntRep( s ) then
+ ADD_ROW_VECTOR_5_FAST( a, b![ZELSPOS], s, from, to );
else
- l := [];
- nrrows := 0;
+ ADD_ROW_VECTOR_5( a, b![ZELSPOS], s, from, to );
fi;
- res := Objectify( TypeObj(m), [m![BDPOS],t,rowlen,l] );
- if not IsMutable(m) then
- SetFilterObj(res,IsMutable);
+ m:= Size( b![ZBDPOS] );
+ if s>=0 then
+ for i in [ 1 .. Length( a ) ] do
+ if a[i] >= m then
+ a[i]:= a[i] mod m;
+ fi;
+ od;
+ else
+ for i in [ 1 .. Length( a ) ] do
+ if a[i] < 0 then
+ a[i]:= a[i] mod m;
+ fi;
+ od;
fi;
- return res;
end );
-############################################################################
-# Printing and viewing methods:
-############################################################################
-
-InstallMethod( ViewObj, "for a zmodnz matrix", [ IsZmodnZMatrixRep ],
- function( m )
- local l;
- Print("<");
- if not IsMutable(m) then Print("immutable "); fi;
- l:=[Length(m![ROWSPOS]),m![RLPOS]];
- if Product(l)<=9 and Product(l)<>0 then
- Print("matrix mod ",Size(m![BDPOS]),": ",
- List(m![ROWSPOS],x->x![ELSPOS]),">");
+InstallMethod( MultVectorLeft,
+ [ "IsZmodnZVectorRep and IsMutable", "IsObject" ],
+ function( v, s )
+ local b, m, i;
+ b:= v![ZBDPOS];
+ m:= Size( b );
+ if not IsInt( s ) then
+ if IsRat( s ) then
+ s:= s mod m;
+ elif s in b then
+ s:= Int( s );
+ else
+ Error( "multiplication with is not supported" );
+ fi;
+ fi;
+ v:= v![ZELSPOS];
+ MULT_VECTOR_2_FAST( v, s );
+ if s >= 0 then
+ for i in [ 1 .. Length( v ) ] do
+ if v[i] >= m then
+ v[i]:= v[i] mod m;
+ fi;
+ od;
else
- Print(l[1],"x",l[2],"-matrix mod ",Size(m![BDPOS]),">");
+ for i in [ 1 .. Length( v ) ] do
+ if v[i] < 0 then
+ v[i]:= v[i] mod m;
+ fi;
+ od;
fi;
end );
-InstallMethod( PrintObj, "for a zmodnz matrix", [ IsZmodnZMatrixRep ],
- function( m )
- Print("NewMatrix(IsZmodnZMatrixRep");
- if IsFinite(m![BDPOS]) and IsField(m![BDPOS]) then
- Print(",GF(",Size(m![BDPOS]),"),");
+InstallMethod( MultVectorRight,
+ [ "IsZmodnZVectorRep and IsMutable", "IsObject" ],
+ MultVectorLeft );
+
+InstallMethod( MultVectorLeft,
+ [ "IsZmodnZVectorRep and IsMutable", "IsObject", "IsInt", "IsInt" ],
+ function( v, s, from, to )
+ local b, m, i;
+ b:= v![ZBDPOS];
+ m:= Size( b );
+ if not IsInt( s ) then
+ if IsRat( s ) then
+ s:= s mod m;
+ elif s in b then
+ s:= Int( s );
+ else
+ Error( "multiplication with is not supported" );
+ fi;
+ fi;
+ v:= v![ZELSPOS];
+ for i in [ from .. to ] do
+ v[i]:= s * v[i];
+ od;
+ if s >= 0 then
+ for i in [ from .. to ] do
+ if v[i] >= m then
+ v[i]:= v[i] mod m;
+ fi;
+ od;
else
- Print(",",String(m![BDPOS]),",");
+ for i in [ from .. to ] do
+ if v[i] < 0 then
+ v[i]:= v[i] mod m;
+ fi;
+ od;
fi;
- Print(NumberColumns(m),",",Unpack(m),")");
end );
-InstallMethod( Display, "for a zmodnz matrix", [ IsZmodnZMatrixRep ],
- function( m )
- Print("<");
- if not IsMutable(m) then Print("immutable "); fi;
- Print(Length(m![ROWSPOS]),"x",m![RLPOS],"-matrix over ",m![BDPOS],":\n");
- Display(List(m![ROWSPOS],x->x![ELSPOS]));
-# for i in [1..Length(m![ROWSPOS])] do
-# if i = 1 then
-# Print("[");
-# else
-# Print(" ");
-# fi;
-# Print(m![ROWSPOS][i]![ELSPOS],"\n");
-# od;
- Print("]>\n");
- end );
+InstallMethod( MultVectorRight,
+ [ "IsZmodnZVectorRep and IsMutable", "IsObject", "IsInt", "IsInt" ],
+ MultVectorLeft );
-InstallMethod( String, "for zmodnz matrix", [ IsZmodnZMatrixRep ],
- function( m )
- local st;
- st := "NewMatrix(IsZmodnZMatrixRep";
- Add(st,',');
- if IsFinite(m![BDPOS]) and IsField(m![BDPOS]) then
- Append(st,"GF(");
- Append(st,String(Size(m![BDPOS])));
- Append(st,"),");
- else
- Append(st,String(m![BDPOS]));
- Append(st,",");
+InstallMethod( IsZero, [ "IsZmodnZVectorRep" ],
+ v -> IsZero( v![ZELSPOS] ) );
+
+InstallMethod( CopySubVector,
+ [ "IsZmodnZVectorRep", "IsZmodnZVectorRep and IsMutable", "IsList", "IsList" ],
+ function( a, b, pa, pb )
+ if ValueOption( "check" ) <> false and
+ not IsIdenticalObj( a![ZBDPOS], b![ZBDPOS] ) then
+ Error( " and have different base domains" );
fi;
- Append(st,String(NumberColumns(m)));
- Add(st,',');
- Append(st,String(Unpack(m)));
- Add(st,')');
- return st;
+ # The following should eventually go into the kernel:
+ b![ZELSPOS]{pb}:= a![ZELSPOS]{pa};
end );
+# This is used in the 'MinimalPolynomial' method below.
+InstallOtherMethod( ProductCoeffs,
+ [ "IsZmodnZVectorRep", "IsZmodnZVectorRep" ],
+ { l1, l2 } -> PRODUCT_COEFFS_GENERIC_LISTS( l1, Length( l1 ), l2, Length( l2 ) ) );
+
############################################################################
-# A selection of list operations:
+##
+## Dense matrix objects over rings 'Integers mod n',
+## backed by plain lists of plain lists of integers.
+##
+## - Use the default 'Matrix' methods that delegate to 'NewMatrix'.
+## - Use the default 'ZeroMatrix( rows, cols, mat )' method
+## that delegates to 'NewZeroMatrix'.
+## - Use the default 'IdentityMatrix' methods that delegate to
+## 'NewIdentityMatrix'.
+## - Use the default 'OneMutable', 'OneImmutable', 'OneSameMutability'
+## methods, which call 'IdentityMatrix'.
+## - Use the default 'InverseImmutable', 'InverseSameMutability' methods.
+
+
############################################################################
+##
+#F MakeIsZmodnZMatrixRep( ,
.
+## Each entry of
must have length
are plain lists of length
+##
must be plain lists" );
+ elif Length( row ) <> ncols then
+ Error( "the entries of
must have length
[", i, "] must be a list of reduced integers ",
+ "or of elements in
[", i, "] must be a list of reduced integers ",
+ "or of elements in
is not a multiple of
must lie in
must be in 'IsPlistRep'" );
fi;
fi;
@@ -177,7 +179,7 @@ BindGlobal( "MakeIsPlistMatrixRep",
InstallTagBasedMethod( NewVector,
IsPlistVectorRep,
function( filter, basedomain, list )
- return MakeIsPlistVectorRep(basedomain, ShallowCopy(list), true);
+ return MakeIsPlistVectorRep(basedomain, PlainListCopy( list ), true);
end );
InstallTagBasedMethod( NewZeroVector,
@@ -343,6 +345,9 @@ InstallMethod( \[\],
InstallMethod( \[\]\:\=,
[ "IsPlistVectorRep", "IsPosInt", "IsObject" ],
function( v, p, ob )
+ if ValueOption( "check" ) <> false and Length( v![ELSPOS] ) < p then
+ Error( "
must be a list of reduced integers or of elements in
must be a list of reduced integers or of elements in
must lie in
must be a list of reduced integers or of elements in
must be a list of reduced integers or of elements in
must be a list of reduced integers or of elements in
[
+1] must be a list of reduced integers or of elements in
[
+1] must be a list of reduced integers or of elements in
must have length
is not a multiple of
must lie in
[
+1] must be a list of reduced integers or of elements in
[
+1] must be a list of reduced integers or of elements in
must have length
is not a multiple of
[
+1] must be a list of reduced integers or of elements in
mod /gcd() and [3] must have an assigned value
+gap> M[3,1];
+Error, List Element:
[3] must have an assigned value
+gap> M[1,1]:= 0;;
+gap> M[1,1];
+ZmodnZObj( 0, 6 )
+gap> M[1,1]:= One( R );;
+gap> M[1,1];
+ZmodnZObj( 1, 6 )
+gap> M[1,3]:= 0;;
+Error,
must be in 'IsPlistRep'
gap> v:= MakeIsPlistVectorRep( Integers, [ 1 ], true );;
gap> MakeIsPlistVectorRep( Integers, [ 1/2 ], true );;
Error, the elements in
must lie in