From 9eae2bbbcef37bbea19f8992ea3a862d09a49bc8 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 25 Jan 2018 12:38:28 +0100 Subject: [PATCH] lib: use InstallMethodWithRandomSource in more places --- hpcgap/lib/ffeconway.gi | 9 ++-- lib/algfld.gi | 9 ++-- lib/ffeconway.gi | 9 ++-- lib/fieldfin.gi | 4 +- lib/grpffmat.gi | 36 +++++++--------- lib/grpfp.gi | 8 ++-- lib/grpfree.gi | 18 ++++---- lib/grpnice.gi | 9 ++-- lib/grppc.gi | 13 +++--- lib/mgmfree.gi | 18 ++++---- lib/modulmat.gi | 10 ++--- lib/modulrow.gi | 10 ++--- lib/monofree.gi | 18 ++++---- lib/vspchom.gi | 11 ++--- lib/wordrep.gi | 11 +++-- lib/zmodnze.gi | 10 ++--- tst/testinstall/random.tst | 84 ++++++++++++++++++++++++++++++++++++++ 17 files changed, 186 insertions(+), 101 deletions(-) diff --git a/hpcgap/lib/ffeconway.gi b/hpcgap/lib/ffeconway.gi index b580765614..22b41465f4 100644 --- a/hpcgap/lib/ffeconway.gi +++ b/hpcgap/lib/ffeconway.gi @@ -1562,9 +1562,10 @@ end); #M Random -- use Rowspace ## -InstallMethod(Random, - [IsField and IsFFECollection and IsFinite], - function(f) +InstallMethodWithRandomSource( Random, + "for a random source and a large non-prime finite field", + [IsRandomSource, IsField and IsFFECollection and IsFinite], + function(rs, f) local d, p, v, fam; if Size(f) <= MAXSIZE_GF_INTERNAL then TryNextMethod(); @@ -1574,7 +1575,7 @@ InstallMethod(Random, fi; d := DegreeOverPrimeField(f); p := Characteristic(f); - v := Random(RowSpace(GF(p,1),d)); + v := Random(rs, RowSpace(GF(p,1),d)); fam := FFEFamily(Characteristic(f)); return Objectify(fam!.ConwayFldEltDefaultType, [v,d,fail]); end); diff --git a/lib/algfld.gi b/lib/algfld.gi index 9fa5c1a1b3..9cf4f5a8bc 100644 --- a/lib/algfld.gi +++ b/lib/algfld.gi @@ -895,12 +895,13 @@ end); ## #M Random ## -InstallMethod(Random,"Alg",true, - [IsAlgebraicExtension],0, -function(e) +InstallMethodWithRandomSource( Random, + "for a random source and an algebraic extension", + [IsRandomSource, IsAlgebraicExtension], +function(rs,e) local fam,l; fam:=e!.extFam; - l:=List([1..fam!.deg],i->Random(fam!.baseField)); + l:=List([1..fam!.deg],i->Random(rs,fam!.baseField)); l:=ImmutableVector(fam!.rchar,l,true); return AlgExtElm(fam,l); end); diff --git a/lib/ffeconway.gi b/lib/ffeconway.gi index 43666eb815..24ab129d0f 100644 --- a/lib/ffeconway.gi +++ b/lib/ffeconway.gi @@ -1532,9 +1532,10 @@ end); #M Random -- use Rowspace ## -InstallMethod(Random, - [IsField and IsFFECollection and IsFinite], - function(f) +InstallMethodWithRandomSource( Random, + "for a random source and a large non-prime finite field", + [IsRandomSource, IsField and IsFFECollection and IsFinite], + function(rs, f) local d, p, v, fam; if Size(f) <= MAXSIZE_GF_INTERNAL then TryNextMethod(); @@ -1544,7 +1545,7 @@ InstallMethod(Random, fi; d := DegreeOverPrimeField(f); p := Characteristic(f); - v := Random(RowSpace(GF(p,1),d)); + v := Random(rs, RowSpace(GF(p,1),d)); fam := FFEFamily(Characteristic(f)); return Objectify(fam!.ConwayFldEltDefaultType, [v,d,fail]); end); diff --git a/lib/fieldfin.gi b/lib/fieldfin.gi index d2fe70c162..bcae34fc13 100644 --- a/lib/fieldfin.gi +++ b/lib/fieldfin.gi @@ -52,12 +52,12 @@ InstallMethod( GeneratorsOfLeftModule, ## primitive root, for efficiency reasons. ## All other cases are handled by the vector space methods. ## -InstallMethod( Random, +InstallMethodWithRandomSource( Random, "for a random source and a finite prime field", [ IsRandomSource, IsField and IsPrimeField and IsFinite ], { rs, F } -> Random(rs,1,Size(F)) * One( F ) ); -InstallMethod( Random, +InstallMethodWithRandomSource( Random, "for a random source and a finite field with known primitive root", [ IsRandomSource, IsField and IsFinite and HasPrimitiveRoot ], function ( rs, F ) diff --git a/lib/grpffmat.gi b/lib/grpffmat.gi index cc072ae035..8681b1fc32 100644 --- a/lib/grpffmat.gi +++ b/lib/grpffmat.gi @@ -470,19 +470,15 @@ end); ## #M Random( ) . . . . . . . . . . . . . . . . . . . . . . for natural GL ## -InstallMethod( Random, - "for natural GL", - true, - [ IsFFEMatrixGroup and IsFinite and IsNaturalGL ], - 0, - function(G) +InstallMethodWithRandomSource( Random, + "for a random source and natural GL", + [ IsRandomSource, IsFFEMatrixGroup and IsFinite and IsNaturalGL ], +function(rs, G) local m; - m := RandomInvertibleMat( DimensionOfMatrixGroup( G ), + m := RandomInvertibleMat( rs, DimensionOfMatrixGroup( G ), FieldOfMatrixGroup( G ) ); - MakeImmutable(m); - ConvertToMatrixRep(m, FieldOfMatrixGroup(G)); - return m; - end ); + return ImmutableMatrix(FieldOfMatrixGroup(G), m, true); +end); ############################################################################# @@ -493,20 +489,16 @@ InstallMethod( Random, ## entry in the upper left corner to arbitrary nonzero values in the field ## $F$ form a set of coset representatives of $SL(n,F)$ in $GL(n,F)$. ## -InstallMethod( Random, - "for natural SL", - true, - [ IsFFEMatrixGroup and IsFinite and IsNaturalSL ], - 0, - function( G ) +InstallMethodWithRandomSource( Random, + "for a random source and natural SL", + [ IsRandomSource, IsFFEMatrixGroup and IsFinite and IsNaturalSL ], +function(rs, G) local m; - m:= RandomInvertibleMat( DimensionOfMatrixGroup( G ), + m:= RandomInvertibleMat( rs, DimensionOfMatrixGroup( G ), FieldOfMatrixGroup( G ) ); MultRowVector(m[1], DeterminantMat(m)^-1); - MakeImmutable(m); - ConvertToMatrixRep(m, FieldOfMatrixGroup(G)); - return m; - end ); + return ImmutableMatrix(FieldOfMatrixGroup(G), m, true); +end); ############################################################################# ## diff --git a/lib/grpfp.gi b/lib/grpfp.gi index 245b8fd1ce..be6a7855db 100644 --- a/lib/grpfp.gi +++ b/lib/grpfp.gi @@ -291,15 +291,17 @@ end ); ## #M Random ) ## -InstallMethod( Random,"fp group", [ IsSubgroupFpGroup and IsFinite],0, -function( gp ) +InstallMethodWithRandomSource( Random, + "for a random source and an fp group", + [ IsRandomSource, IsSubgroupFpGroup and IsFinite], +function( rs, gp ) local fam,hom; fam:=ElementsFamily(FamilyObj(gp)); hom:=FPFaithHom(fam); if hom=fail then TryNextMethod(); fi; - return PreImagesRepresentative(hom,Random(Image(hom,gp))); + return PreImagesRepresentative(hom,Random(rs, Image(hom,gp))); end ); ############################################################################# diff --git a/lib/grpfree.gi b/lib/grpfree.gi index 99abe8dcb5..608f9c869e 100644 --- a/lib/grpfree.gi +++ b/lib/grpfree.gi @@ -297,14 +297,18 @@ InstallMethod( IsWholeFamily, ## #T isn't this a generic group method? (without guarantee about distribution) ## -InstallMethod( Random, - "for a free group", - [ IsAssocWordWithInverseCollection and IsGroup ], - function( M ) +InstallMethodWithRandomSource( Random, + "for a random source and a free group", + [ IsRandomSource, IsAssocWordWithInverseCollection and IsGroup ], + function( rs, M ) local len, result, gens, i; + if IsTrivial( M ) then + return One( M ); + fi; + # Get a random length for the word. - len:= Random( Integers ); + len:= Random( rs, Integers ); if 0 < len then len:= 2 * len; elif len < 0 then @@ -315,9 +319,9 @@ InstallMethod( Random, # Multiply 'len' random generator powers. gens:= GeneratorsOfGroup( M ); - result:= Random( gens ) ^ Random( Integers ); + result:= Random( rs, gens ) ^ Random( rs, Integers ); for i in [ 2 .. len ] do - result:= result * Random( gens ) ^ Random( Integers ); + result:= result * Random( rs, gens ) ^ Random( rs, Integers ); od; # Return the result. diff --git a/lib/grpnice.gi b/lib/grpnice.gi index 5e61bdc461..5b78712b30 100644 --- a/lib/grpnice.gi +++ b/lib/grpnice.gi @@ -782,11 +782,10 @@ SubgroupMethodByNiceMonomorphism( RadicalGroup, #M Random( ) ## InstallMethod( Random, - "handled by nice monomorphism", - true, - [ IsGroup and IsHandledByNiceMonomorphism ], 0, - G -> PreImagesRepresentative( NiceMonomorphism( G ), - Random( NiceObject( G ) ) ) ); + "for a random source and a group handled by nice monomorphism", + [ IsRandomSource, IsGroup and IsHandledByNiceMonomorphism ], 0, + {rs, G} -> PreImagesRepresentative( NiceMonomorphism( G ), + Random( rs, NiceObject( G ) ) ) ); ############################################################################# diff --git a/lib/grppc.gi b/lib/grppc.gi index 18bc0560a5..e7e9e1726a 100644 --- a/lib/grppc.gi +++ b/lib/grppc.gi @@ -1283,20 +1283,17 @@ end ); ## #M Random( ) ## -InstallMethod( Random, - "pcgs computable groups", - true, - [ IsGroup and CanEasilyComputePcgs and IsFinite ], - 0, - -function(grp) +InstallMethodWithRandomSource( Random, + "for a random source and a pcgs computable groups", + [ IsRandomSource, IsGroup and CanEasilyComputePcgs and IsFinite ], +function(rs, grp) local p; p := Pcgs(grp); if Length( p ) = 0 then return One( grp ); else - return Product( p, x -> x^Random(1,RelativeOrderOfPcElement(p,x)) ); + return Product( p, x -> x^Random(rs, 1, RelativeOrderOfPcElement(p,x)) ); fi; end ); diff --git a/lib/mgmfree.gi b/lib/mgmfree.gi index d03ea05435..bbf7a0fdf8 100644 --- a/lib/mgmfree.gi +++ b/lib/mgmfree.gi @@ -233,14 +233,14 @@ InstallMethod( Size, ## #T use better method for the whole family ## -InstallMethod( Random, - "for a free magma", - [ IsMagma and IsNonassocWordCollection ], - function( M ) +InstallMethodWithRandomSource( Random, + "for a random source and a free magma", + [ IsRandomSource, IsMagma and IsNonassocWordCollection ], + function( rs, M ) local len, result, gens, i; # Get a random length for the word. - len:= Random( Integers ); + len:= Random( rs, Integers ); if 0 <= len then len:= 2 * len; else @@ -249,12 +249,12 @@ InstallMethod( Random, # Multiply $'len' + 1$ random generators. gens:= GeneratorsOfMagma( M ); - result:= Random( gens ); + result:= Random( rs, gens ); for i in [ 1 .. len ] do - if Random( [ 0, 1 ] ) = 0 then - result:= result * Random( gens ); + if Random( rs, 0, 1 ) = 0 then + result:= result * Random( rs, gens ); else - result:= Random( gens ) * result; + result:= Random( rs, gens ) * result; fi; od; diff --git a/lib/modulmat.gi b/lib/modulmat.gi index 8949a14572..0fa6d4cdbc 100644 --- a/lib/modulmat.gi +++ b/lib/modulmat.gi @@ -147,13 +147,13 @@ InstallMethod( Dimension, ## #M Random( ) ## -InstallMethod( Random, - "for full matrix module", - [ IsFreeLeftModule and IsFullMatrixModule ], - function( M ) +InstallMethodWithRandomSource( Random, + "for a random source and a full matrix module", + [ IsRandomSource, IsFreeLeftModule and IsFullMatrixModule ], + function( rs, M ) local random; random:= DimensionOfVectors( M ); - random:= RandomMat( random[1], random[2], + random:= RandomMat( rs, random[1], random[2], LeftActingDomain( M ) ); if IsLieObjectCollection( M ) then random:= LieObject( random ); diff --git a/lib/modulrow.gi b/lib/modulrow.gi index ca49f72209..645823dce4 100644 --- a/lib/modulrow.gi +++ b/lib/modulrow.gi @@ -111,13 +111,13 @@ InstallMethod( Dimension, ## #M Random( ) ##1 -InstallMethod( Random, - "for full row module", - [ IsFreeLeftModule and IsFullRowModule ], - function( M ) +InstallMethodWithRandomSource( Random, + "for a random source and a full row module", + [ IsRandomSource, IsFreeLeftModule and IsFullRowModule ], + function( rs, M ) local R,v; R:= LeftActingDomain( M ); - v := List( [ 1 .. DimensionOfVectors( M ) ], x -> Random( R ) ); + v := List( [ 1 .. DimensionOfVectors( M ) ], x -> Random( rs, R ) ); if IsField(R) then if IsHPCGAP then if Size(R) <= 256 then diff --git a/lib/monofree.gi b/lib/monofree.gi index 13ee77fc40..9d43571fc1 100644 --- a/lib/monofree.gi +++ b/lib/monofree.gi @@ -89,14 +89,18 @@ InstallMethod( Enumerator, ## #T use better method for the whole family, and for abelian monoids ## -InstallMethod( Random, - "for a free monoid", - [ IsMonoid and IsAssocWordWithOneCollection ], - function( M ) +InstallMethodWithRandomSource( Random, + "for a random source and a free monoid", + [ IsRandomSource, IsMonoid and IsAssocWordWithOneCollection ], + function( rs, M ) local len, result, gens, i; + if IsTrivial( M ) then + return One( M ); + fi; + # Get a random length for the word. - len:= Random( Integers ); + len:= Random( rs, Integers ); if 0 < len then len:= 2 * len; elif len < 0 then @@ -107,9 +111,9 @@ InstallMethod( Random, # Multiply 'len' random generators. gens:= GeneratorsOfMagmaWithOne( M ); - result:= Random( gens ); + result:= Random( rs, gens ); for i in [ 2 .. len ] do - result:= result * Random( gens ); + result:= result * Random( rs, gens ); od; # Return the result. diff --git a/lib/vspchom.gi b/lib/vspchom.gi index edc54867eb..71f9973c67 100644 --- a/lib/vspchom.gi +++ b/lib/vspchom.gi @@ -1869,11 +1869,11 @@ InstallMethod( Dimension, ## #M Random( ) . . . . . . . . . . . for full hom space of linear mappings ## -InstallMethod( Random, - "for full hom space of linear mappings", - [ IsFreeLeftModule and IsGeneralMappingCollection +InstallMethodWithRandomSource( Random, + "for a random source and full hom space of linear mappings", + [ IsRandomSource, IsFreeLeftModule and IsGeneralMappingCollection and IsFullHomModule ], - function( M ) + function( rs, M ) local BS, BR; BR:= NiceFreeLeftModuleInfo( M ); @@ -1881,7 +1881,8 @@ InstallMethod( Random, BR:= BR.basisrange; return LeftModuleHomomorphismByMatrix( BS, - RandomMat( Dimension( UnderlyingLeftModule( BS ) ), + RandomMat( rs, + Dimension( UnderlyingLeftModule( BS ) ), Dimension( UnderlyingLeftModule( BR ) ), LeftActingDomain( M ) ), BR ); diff --git a/lib/wordrep.gi b/lib/wordrep.gi index 2f2ccea647..c5af4ea4cc 100644 --- a/lib/wordrep.gi +++ b/lib/wordrep.gi @@ -1282,13 +1282,12 @@ InstallMethod( Position, ## #M Random( ) . . . . . . . . . . for an infinite list of generators ## -InstallMethod( Random, - "for an infinite list of generators", - true, - [ IsList and IsInfiniteListOfGeneratorsRep ], 0, - function( list ) +InstallMethodWithRandomSource( Random, + "for a random source and an infinite list of generators", + [ IsRandomSource, IsList and IsInfiniteListOfGeneratorsRep ], 0, + function( rs, list ) local pos; - pos:= Random( Integers ); + pos:= Random( rs, Integers ); if 0 <= pos then return list[ 2 * pos + 1 ]; else diff --git a/lib/zmodnze.gi b/lib/zmodnze.gi index f0f2b7cda6..74deb7f1f0 100644 --- a/lib/zmodnze.gi +++ b/lib/zmodnze.gi @@ -340,14 +340,14 @@ CategoryCollections( IsZmodnZepsObj ) and IsDomain ); # # Random # -InstallMethod( Random, - "zmodnze : for full collection Z/nZ(m)", - [ CategoryCollections( IsZmodnZepsObj ) and IsWholeFamily ], -function(R) +InstallMethodWithRandomSource( Random, + "for a random source and the full collection Z/nZ(m)", + [ IsRandomSource, CategoryCollections( IsZmodnZepsObj ) and IsWholeFamily ], +function(rs, R) local m, n, coeffs, elt; m:=FamilyObj(One(R))!.degree; n:=FamilyObj(One(R))!.modulus; - coeffs := List([1..m], x -> Random([0..n-1])); + coeffs := List([1..m], x -> Random(rs, 0, n-1)); elt := coeffs * List( [1..m], j -> E(m)^(j-1) ); return ZmodnZepsObj( FamilyObj(One(R)) , elt ); end ); diff --git a/tst/testinstall/random.tst b/tst/testinstall/random.tst index dd2e366909..fcace2ba5c 100644 --- a/tst/testinstall/random.tst +++ b/tst/testinstall/random.tst @@ -2,8 +2,49 @@ gap> START_TEST("random.tst"); gap> Read( Filename( DirectoriesLibrary( "tst" ), "testrandom.g" ) ); # +# fields and rings +# + +# cyclotomics gap> randomTest(Integers, Random); gap> randomTest(Rationals, Random); +gap> randomTest(GaussianIntegers, Random); +gap> randomTest(GaussianRationals, Random); + +# finite fields +gap> randomTest(GF(2), Random); +gap> randomTest(GF(3), Random); +gap> randomTest(GF(4), Random); +gap> randomTest(GF(257), Random); +gap> randomTest(GF(65537), Random); +gap> randomTest(GF(257^2), Random); +gap> randomTest(GF(2^20), Random); + +# ZmodnZ +gap> randomTestForSizeOneCollection(Integers mod 1, Random); +gap> randomTest(Integers mod 4, Random); +gap> randomTest(Integers mod 100, Random); + +# ZmodnZe +gap> randomTest(RingInt(CF(4)) mod 5, Random); + +# +# magmas, monoids, ... +# + +# +gap> randomTest(FreeMagma(1), Random); +gap> randomTest(FreeMagma(2), Random); + +# +gap> randomTestForSizeOneCollection(FreeMonoid(0), Random); +gap> randomTest(FreeMonoid(1), Random); +gap> randomTest(FreeMonoid(2), Random); + +# +# permutation groups +# +gap> randomTestForSizeOneCollection(TrivialGroup(IsPermGroup), Random); # gap> randomTest(SymmetricGroup(2), Random); @@ -21,16 +62,59 @@ gap> randomTest(Group((1,2),(3,4))*(1,2,3), Random); gap> randomTest(PrimitiveGroup(5,2)*(1,2,6), Random); gap> randomTest(PrimitiveGroup(5,3)*(1,4,6), Random); +# +# pc groups +# +gap> randomTestForSizeOneCollection(TrivialGroup(IsPcGroup), Random); +gap> randomTest(AbelianGroup(IsPcGroup, [2]), Random); +gap> randomTest(AbelianGroup(IsPcGroup, [2,3,4,5]), Random); + +# +# fp groups +# +gap> randomTestForSizeOneCollection(TrivialGroup(IsFpGroup), Random); +gap> randomTestForSizeOneCollection(FreeGroup(0), Random); +gap> randomTest(FreeGroup(1), Random); +gap> randomTest(FreeGroup(2), Random); +gap> randomTest(FreeGroup(infinity), Random); +gap> randomTest(DihedralGroup(IsFpGroup, 6), Random); + +# +# matrix groups +# +gap> randomTestForSizeOneCollection(CyclicGroup(IsMatrixGroup, GF(2), 1), Random); +gap> randomTestForSizeOneCollection(CyclicGroup(IsMatrixGroup, GF(9), 1), Random); +gap> randomTestForSizeOneCollection(CyclicGroup(IsMatrixGroup, Rationals, 1), Random); + +# +gap> randomTest(CyclicGroup(IsMatrixGroup, GF(2), 3), Random); +gap> randomTest(CyclicGroup(IsMatrixGroup, GF(3), 3), Random); + +# +gap> randomTest(SL(2,2), Random); +gap> randomTest(SL(3,3), Random); + +# +gap> randomTest(GL(2,2), Random); +gap> randomTest(GL(3,3), Random); + +# +# other stuff +# + # gap> randomTest(DoubleCoset(Group((1,2),(3,4)), (1,2,3,4,5,6), Group((1,2,3)) ), Random); gap> randomTest(DoubleCoset(Group(()), (1,2), Group((1,2,3)) ), Random); gap> randomTest(DoubleCoset(Group((1,2),(3,4)), (), Group((1,2,3)) ), Random); # +gap> randomTestForSizeOneCollection([1], Random); gap> randomTest([1..10], Random); gap> randomTest([1,-6,"cheese", Group(())], Random); # gap> randomTest(PadicExtensionNumberFamily(3, 5, [1,1,1], [1,1]), Random, function(x,y) return IsPadicExtensionNumber(x); end); gap> randomTest(PurePadicNumberFamily(2,20), Random, function(x,y) return IsPurePadicNumber(x); end); + +# gap> STOP_TEST("random.tst", 1);