diff --git a/CHANGES.md b/CHANGES.md index 50a0499..c2422f7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,10 @@ This file describes changes in the smallgrp package. # 1.6dev - Require GAP 4.12 + - `NumberSmallGroups` now accepts a list of orders and the selection + criteria of `AllSmallGroups`, as in `NumberSmallGroups(96, IsAbelian)`. + It counts by listing the ids, so it costs what `IdsOfAllSmallGroups` + costs (issue #68) - Selection by `IsAbelian`, `IsNilpotentGroup`, `IsSupersolvableGroup`, `IsSolvableGroup`, `RankPGroup` and `PClassPGroup` now avoids constructing the groups for most orders which had no precomputed data, diff --git a/gap/small.gd b/gap/small.gd index 4ef887f..63b2698 100644 --- a/gap/small.gd +++ b/gap/small.gd @@ -703,6 +703,10 @@ DeclareGlobalFunction( "SelectSmallGroups" ); ##

## reports which criteria are indexed ## for a given order. +##

+## returns the ids of these groups instead +## of the groups themselves, and just their +## number. ## AllSmallGroups( 6 ); ## [ , @@ -790,11 +794,12 @@ DeclareSynonym( "IdsOfAllGroups", IdsOfAllSmallGroups ); ############################################################################# ## #F NumberSmallGroups( ) +#F NumberSmallGroups( ) ## ## <#GAPDoc Label="NumberSmallGroups"> ## -## -## +## +## ## ## ## returns the number of groups of order order. @@ -806,6 +811,21 @@ DeclareSynonym( "IdsOfAllGroups", IdsOfAllSmallGroups ); ## gap> NumberSmallGroups( 4096 ); ## Error, the library of groups of size 4096 is not available ## ]]> +##

+## The function also accepts the arguments of +## and counts the groups that function would +## return. +## NumberSmallGroups( [ 1 .. 100 ] ); +## 1048 +## gap> NumberSmallGroups( 96, IsAbelian ); +## 7 +## ]]> +##

+## Orders alone are answered from the numbers of groups. Otherwise the +## cost is that of : the indexed criteria +## are applied first, whatever order the criteria are given in, and only +## the groups a remaining criterion must be tested on are constructed. ## ## ## <#/GAPDoc> diff --git a/gap/small.gi b/gap/small.gi index a396f17..ccdae55 100644 --- a/gap/small.gi +++ b/gap/small.gi @@ -638,16 +638,12 @@ end ); ############################################################################# ## -#F NumberSmallGroups() +#F SMALL_GROUPS_NUMBER( ) ## -## returns the number of groups of the order . -InstallGlobalFunction( NumberSmallGroups, function( size ) +SMALL_GROUPS_NUMBER := function( size ) local inforec; - if not IsPosInt( size ) then - Error( "usage: NumberSmallGroups( order )" ); - fi; - if size = 1024 then + if size = 1024 then return 49487367289; fi; @@ -656,10 +652,51 @@ InstallGlobalFunction( NumberSmallGroups, function( size ) Error( "the library of groups of size ", size, " is not available" ); fi; - if IsBound( inforec.number ) then + if IsBound( inforec.number ) then return inforec.number; fi; return NUMBER_SMALL_GROUPS_FUNCS[ inforec.func ]( size, inforec ).number; +end; + +############################################################################# +## +#F NumberSmallGroups() +#F NumberSmallGroups() +## +## returns the number of the groups 'AllSmallGroups' would return for . +InstallGlobalFunction( NumberSmallGroups, function( arg ) + local argl, sizes; + + # the classical form, just an order + if Length( arg ) = 1 and IsPosInt( arg[ 1 ] ) then + return SMALL_GROUPS_NUMBER( arg[ 1 ] ); + fi; + + # 'Size' may precede the orders + argl := arg; + if Length( argl ) > 0 and argl[ 1 ] = Size then + argl := argl{ [ 2 .. Length( argl ) ] }; + fi; + + # without a criterion the numbers of the orders just add up. A single + # list argument is the orders; a second one would be group numbers and + # is left to 'SelectSmallGroups'. + sizes := fail; + if Length( argl ) = 1 and IsList( argl[ 1 ] ) then + sizes := argl[ 1 ]; + elif Length( argl ) > 0 and ForAll( argl, IsPosInt ) then + sizes := argl; + fi; + if sizes <> fail and ForAll( sizes, IsPosInt ) then + return Sum( sizes, SMALL_GROUPS_NUMBER ); + fi; + + if Length( arg ) <= 1 then + Error( "usage: NumberSmallGroups( order )" ); + fi; + + # so far counting the groups is not cheaper than listing their ids + return Length( SelectSmallGroups( arg, true, true ) ); end ); ############################################################################# diff --git a/tst/small.tst b/tst/small.tst index 95d9064..7ceb05d 100644 --- a/tst/small.tst +++ b/tst/small.tst @@ -104,10 +104,18 @@ gap> IdGroup(G); ################################################################################ # NumberSmallGroups GlobalFunction ################################################################################ +gap> NumberSmallGroups(); +Error, usage: NumberSmallGroups( order ) gap> NumberSmallGroups(fail); Error, usage: NumberSmallGroups( order ) gap> NumberSmallGroups(0); Error, usage: NumberSmallGroups( order ) +gap> NumberSmallGroups(Size); +Error, usage: NumberSmallGroups( order ) +gap> NumberSmallGroups("abc"); +Error, usage: NumberSmallGroups( order ) +gap> NumberSmallGroups([ 1, fail ]); +Error, usage: NumberSmallGroups( order ) gap> NumberSmallGroups(19); 1 gap> NumberSmallGroups(1024); @@ -121,6 +129,50 @@ gap> NumberSmallGroups(5^6); gap> NumberSmallGroups(5*7*9*11*13); 22 +# orders alone need no group at all +gap> NumberSmallGroups([]); +0 +gap> NumberSmallGroups([ 1 .. 100 ]); +1048 +gap> NumberSmallGroups(Size, [ 1 .. 100 ]); +1048 +gap> NumberSmallGroups(60, 1024); +49487367302 +gap> NumberSmallGroups(Size, [ 1000, 3996 ]); +Error, the library of groups of size 3996 is not available + +# with selection criteria +gap> NumberSmallGroups(96, IsAbelian); +7 +gap> NumberSmallGroups(96, IsAbelian, false); +224 +gap> NrSmallGroups(96, IsAbelian) + NrSmallGroups(96, IsAbelian, false) +> = NrSmallGroups(96); +true +gap> NumberSmallGroups(Size, [ 1 .. 100 ], IsSolvableGroup, false); +1 +gap> NumberSmallGroups(Size, 60, IsSupersolvableGroup, true); +11 +gap> ForAll([ 1 .. 100 ], n -> NumberSmallGroups(n, IsNilpotentGroup) +> = Length(IdsOfAllSmallGroups(n, IsNilpotentGroup))); +true + +# the indexed criteria come first, whatever order they are given in +gap> NumberSmallGroups(512, IsAbelian, true, Exponent, 2); +1 +gap> NumberSmallGroups(512, Exponent, 2, IsAbelian, true); +1 + +# a list of group numbers may narrow down the selection +gap> NumberSmallGroups(60, [ 1 .. 10 ]); +10 +gap> NumberSmallGroups(60, [ 1 .. 10 ], IsNilpotentGroup); +1 + +# selection criteria need the library, even where the number does not +gap> NumberSmallGroups(1024, IsAbelian); +Error, AllSmallGroups / OneSmallGroup: groups of order 1024 not available + ################################################################################ # SelectSmallGroups GlobalFunction (called by AllSmallGroups or OneSmallGroup) ################################################################################