diff --git a/doc/ref/makedocreldata.g b/doc/ref/makedocreldata.g index e19999cc400..e1f77aabde5 100644 --- a/doc/ref/makedocreldata.g +++ b/doc/ref/makedocreldata.g @@ -148,6 +148,8 @@ GAPInfo.ManualDataRef:= rec( "../../lib/pquot.gd", "../../lib/primality.gd", "../../lib/process.gd", + "../../lib/productdomain.gd", + "../../lib/productdomain.gi", "../../lib/profile.g", "../../lib/proto.gd", "../../lib/randiso.gd", diff --git a/lib/productdomain.gd b/lib/productdomain.gd new file mode 100644 index 00000000000..50e1947a4bc --- /dev/null +++ b/lib/productdomain.gd @@ -0,0 +1,51 @@ +############################################################################# +## +## This file declares everything we need to work with IsDirectProductDomain +## objects. +## +## <#GAPDoc Label="DirectProductFamily"> +## +## +## +## +## args must be a dense list of +## families, otherwise the function raises an error. +##

+## returns a collections family fam +## with the following property: +## Each collection coll in fam is a direct product +## whose i-th factors are collections in args[i]. +## This is modelled on the level of the elements by requiring that each +## elm of coll must be an +## object with elm[i] contained in ElementsFamily(args[i]). +##

+## Note though that not all direct products in &GAP; are created via these +## families, see for example for permutation +## groups. +##

+## D8 := DihedralGroup(IsPermGroup, 8);; +## gap> fam := FamilyObj(D8); +## +## gap> ElementsFamily(fam); +## +## gap> productFamily := DirectProductFamily([fam, fam]); +## +## gap> elmsOfProductFamily := ElementsFamily(productFamily); +## > )"> +## gap> ComponentsOfDirectProductElementsFamily(elmsOfProductFamily); +## [ , ] +## ]]> +## +## +## <#/GAPDoc> +DeclareGlobalFunction( "DirectProductFamily", + "for a dense list of collection families" ); + +DeclareCategory("IsDirectProductDomain", + IsDirectProductElementCollection and IsDomain); + +DeclareOperation("DirectProductDomain", [IsDenseList]); + +DeclareAttribute("ComponentsOfDirectProductDomain", IsDirectProductDomain); +DeclareAttribute("DimensionOfDirectProductDomain", IsDirectProductDomain); diff --git a/lib/productdomain.gi b/lib/productdomain.gi new file mode 100644 index 00000000000..87b6a6d05b0 --- /dev/null +++ b/lib/productdomain.gi @@ -0,0 +1,101 @@ +############################################################################# +## +## The rest of this file implements the operations for IsDirectProductDomain +## domains. +## +InstallGlobalFunction(DirectProductFamily, +function(args) + if not IsDenseList(args) or not ForAll(args, IsCollectionFamily) then + ErrorNoReturn(" must be a dense list of collection families"); + fi; + return CollectionsFamily( + DirectProductElementsFamily(List(args, ElementsFamily)) + ); +end); + + +############################################################################# +## +InstallMethod(DirectProductDomain, +"for a dense list (of domains)", +[IsDenseList], +function(args) + local directProductFamily, type; + if not ForAll(args, IsDomain) then + ErrorNoReturn("args must be a dense list of domains"); + fi; + directProductFamily := DirectProductFamily(List(args, FamilyObj)); + type := NewType(directProductFamily, + IsDirectProductDomain and IsAttributeStoringRep); + return ObjectifyWithAttributes(rec(), type, + ComponentsOfDirectProductDomain, args); +end); + +InstallOtherMethod(DirectProductDomain, +"for a domain and a nonnegative integer", +[IsDomain, IsInt], +function(dom, k) + local directProductFamily, type; + if k < 0 then + ErrorNoReturn(" must be a nonnegative integer"); + fi; + directProductFamily := DirectProductFamily( + ListWithIdenticalEntries(k, FamilyObj(dom)) + ); + type := NewType(directProductFamily, + IsDirectProductDomain and IsAttributeStoringRep); + return ObjectifyWithAttributes(rec(), + type, + ComponentsOfDirectProductDomain, + ListWithIdenticalEntries(k, dom)); +end); + +InstallMethod(PrintObj, +"for an IsDirectProductDomain", +[IsDirectProductDomain], +function(dom) + local components, i; + Print("DirectProductDomain([ "); + components := ComponentsOfDirectProductDomain(dom); + for i in [1 .. Length(components)] do + PrintObj(components[i]); + if i < Length(components) then + Print(", "); + fi; + od; + Print(" ])"); +end); + +InstallMethod(Size, +"for an IsDirectProductDomain", +[IsDirectProductDomain], +function(dom) + local size, comp; + size := 1; + for comp in ComponentsOfDirectProductDomain(dom) do + size := Size(comp) * size; + od; + return size; +end); + +InstallMethod(DimensionOfDirectProductDomain, +"for an IsDirectProductDomain", +[IsDirectProductDomain], +dom -> Length(ComponentsOfDirectProductDomain(dom))); + +InstallMethod(\in, +"for an IsDirectProductDomain", +[IsDirectProductElement, IsDirectProductDomain], +function(elm, dom) + local components, i; + if Length(elm) <> DimensionOfDirectProductDomain(dom) then + return false; + fi; + components := ComponentsOfDirectProductDomain(dom); + for i in [1 .. Length(components)] do + if not elm[i] in components[i] then + return false; + fi; + od; + return true; +end); diff --git a/lib/read3.g b/lib/read3.g index 6cc9804b8a7..436d3eb2fa5 100644 --- a/lib/read3.g +++ b/lib/read3.g @@ -27,6 +27,7 @@ ReadLib( "bitfields.gd" ); ReadLib( "mapping.gd" ); ReadLib( "mapphomo.gd" ); ReadLib( "relation.gd"); +ReadLib( "productdomain.gd" ); ReadLib( "magma.gd" ); ReadLib( "mgmideal.gd" ); diff --git a/lib/read5.g b/lib/read5.g index e36369c75bd..581aed4b228 100644 --- a/lib/read5.g +++ b/lib/read5.g @@ -28,6 +28,7 @@ ReadLib( "mapping.gi" ); ReadLib( "mapprep.gi" ); ReadLib( "mapphomo.gi" ); ReadLib( "relation.gi" ); +ReadLib( "productdomain.gi" ); ReadLib( "magma.gi" ); ReadLib( "mgmideal.gi" ); diff --git a/lib/tuples.gd b/lib/tuples.gd index 09172b5faf3..0982901bf5d 100644 --- a/lib/tuples.gd +++ b/lib/tuples.gd @@ -178,46 +178,3 @@ direct product elements families" ); DeclareOperation( "DirectProductElement", [ IsList ]); DeclareOperation( "DirectProductElementNC", [ IsDirectProductElementFamily, IsList ]); - - -############################################################################# -## -## -## <#GAPDoc Label="DirectProductFamily"> -## -## -## -## -## args must be a dense list of -## families, otherwise the function raises an error. -##

-## returns a collections family fam -## with the following property: -## Each collection coll in fam is a direct product -## whose i-th factors are collections in args[i]. -## This is modelled on the level of the elements by requiring that each -## elm of coll must be an -## object with elm[i] contained in ElementsFamily(args[i]). -##

-## Note though that not all direct products in &GAP; are created via these -## families, see for example for permutation -## groups. -##

-## D8 := DihedralGroup(IsPermGroup, 8);; -## gap> fam := FamilyObj(D8); -## -## gap> ElementsFamily(fam); -## -## gap> productFamily := DirectProductFamily([fam, fam]); -## -## gap> elmsOfProductFamily := ElementsFamily(productFamily); -## > )"> -## gap> ComponentsOfDirectProductElementsFamily(elmsOfProductFamily); -## [ , ] -## ]]> -## -## -## <#/GAPDoc> -DeclareGlobalFunction( "DirectProductFamily", - "for a dense list of collection families" ); diff --git a/lib/tuples.gi b/lib/tuples.gi index a4bb72148fd..15bd75a44ac 100644 --- a/lib/tuples.gi +++ b/lib/tuples.gi @@ -506,17 +506,3 @@ InstallOtherMethod( \*, fi; return DirectProductElement( List( dpelm, entry -> nonlist * entry ) ); end ); - - -############################################################################# -## -## -InstallGlobalFunction( DirectProductFamily, - function( args ) - if not IsDenseList(args) or not ForAll(args, IsCollectionFamily) then - ErrorNoReturn(" must be a dense list of collection families"); - fi; - return CollectionsFamily( - DirectProductElementsFamily( List( args, ElementsFamily ) ) - ); - end ); diff --git a/tst/testinstall/productdomain.tst b/tst/testinstall/productdomain.tst new file mode 100644 index 00000000000..bfac1b79247 --- /dev/null +++ b/tst/testinstall/productdomain.tst @@ -0,0 +1,105 @@ +#@local D8, fam, dpf, d, emptyDPDDim2, emptyDPDDim3, dpdDim0, dpd +#@local range1, range2, g1, g2, dpdOfGroups, bijToRange, inv, tups +#@local dpdNotAttributeStoring +gap> START_TEST("productdomain.tst"); + +# DirectProductFamily +gap> D8 := DihedralGroup(IsPermGroup, 8);; +gap> fam := FamilyObj(D8); + +gap> ElementsFamily(fam); + +gap> dpf := DirectProductFamily([fam, fam]); + +gap> IsDirectProductElementFamily(ElementsFamily(dpf)); +true +gap> DirectProductFamily([CyclotomicsFamily, ]); +Error, must be a dense list of collection families + +# DirectProductDomain +# of empty domains, dim 2 +gap> d := Domain(FamilyObj([1]), []); +Domain([ ]) +gap> emptyDPDDim2 := DirectProductDomain([d, d]); +DirectProductDomain([ Domain([ ]), Domain([ ]) ]) +gap> Size(emptyDPDDim2); +0 +gap> IsEmpty(emptyDPDDim2); +true +gap> DimensionOfDirectProductDomain(emptyDPDDim2); +2 +gap> DirectProductElement([]) in emptyDPDDim2; +false + +# of empty domains, dim 3 +gap> emptyDPDDim3 := DirectProductDomain(d, 3); +DirectProductDomain([ Domain([ ]), Domain([ ]), Domain([ ]) ]) +gap> Size(emptyDPDDim3); +0 +gap> IsEmpty(emptyDPDDim3); +true +gap> DimensionOfDirectProductDomain(emptyDPDDim3); +3 +gap> DirectProductElement([]) in emptyDPDDim3; +false + +# of dimension 0 +gap> range1 := Domain([1..5]); +Domain([ 1 .. 5 ]) +gap> dpdDim0 := DirectProductDomain(range1, 0); +DirectProductDomain([ ]) +gap> Size(dpdDim0); +1 +gap> IsEmpty(dpdDim0); +false +gap> DimensionOfDirectProductDomain(dpdDim0); +0 +gap> DirectProductElement([]) in dpdDim0; +true + +# of domains of ranges +gap> range1; +Domain([ 1 .. 5 ]) +gap> range2 := Domain([3..7]); +Domain([ 3 .. 7 ]) +gap> dpd := DirectProductDomain([range1, range2]); +DirectProductDomain([ Domain([ 1 .. 5 ]), Domain([ 3 .. 7 ]) ]) +gap> Size(dpd); +25 +gap> DimensionOfDirectProductDomain(dpd); +2 +gap> DirectProductElement([]) in dpd; +false +gap> DirectProductElement([6, 3]) in dpd; +false +gap> DirectProductElement([1, 3]) in dpd; +true + +# DirectProductDomain +# of groups +gap> g1 := DihedralGroup(4); + +gap> g2 := DihedralGroup(IsPermGroup, 4); +Group([ (1,2), (3,4) ]) +gap> dpdOfGroups := DirectProductDomain([g1, g2]); +DirectProductDomain([ Group( [ f1, f2 ] ), Group( [ (1,2), (3,4) ] ) ]) +gap> Size(dpdOfGroups); +16 +gap> DimensionOfDirectProductDomain(dpdOfGroups); +2 +gap> DirectProductElement([]) in dpdOfGroups; +false +gap> DirectProductElement([1, 3]) in dpdOfGroups; +false +gap> DirectProductElement([g1.1, g2.1]) in dpdOfGroups; +true + +# DirectProductDomain +# error handling +gap> DirectProductDomain([CyclotomicsFamily]); +Error, args must be a dense list of domains +gap> DirectProductDomain(dpd, -1); +Error, must be a nonnegative integer + +# +gap> STOP_TEST("productdomain.tst"); diff --git a/tst/testinstall/tuples.tst b/tst/testinstall/tuples.tst deleted file mode 100644 index a1f0fe18bc5..00000000000 --- a/tst/testinstall/tuples.tst +++ /dev/null @@ -1,13 +0,0 @@ -gap> START_TEST("tuples.tst"); -gap> D8 := DihedralGroup(IsPermGroup, 8);; -gap> fam := FamilyObj(D8); - -gap> ElementsFamily(fam); - -gap> dpf := DirectProductFamily([fam, fam]); - -gap> IsDirectProductElementFamily(ElementsFamily(dpf)); -true - -# -gap> STOP_TEST("tuples.tst");