Skip to content

Commit

Permalink
Unify argument checking for some free objects
Browse files Browse the repository at this point in the history
In particular, unify argument processing/error checking in
* FreeSemigroup
* FreeMonoid
* FreeMagma
* FreeMagmaWithOne

Resolves gap-system#1385.
  • Loading branch information
wilfwilson committed Apr 22, 2021
1 parent 51528e2 commit c9b5943
Show file tree
Hide file tree
Showing 9 changed files with 578 additions and 233 deletions.
19 changes: 10 additions & 9 deletions lib/magma.gd
Original file line number Diff line number Diff line change
Expand Up @@ -731,7 +731,7 @@ DeclareOperation( "SquareRoots", [ IsMagma, IsMultiplicativeElement ] );
#F FreeMagma( <rank>[, <name>] )
#F FreeMagma( <name1>, <name2>, ... )
#F FreeMagma( <names> )
#F FreeMagma( infinity, <name>, <init> )
#F FreeMagma( infinity[, <name>[, <init>]] )
##
## <#GAPDoc Label="FreeMagma">
## <ManSection>
Expand All @@ -742,18 +742,19 @@ DeclareOperation( "SquareRoots", [ IsMagma, IsMultiplicativeElement ] );
## Label="for various names"/>
## <Func Name="FreeMagma" Arg='names'
## Label="for a list of names"/>
## <Func Name="FreeMagma" Arg='infinity, name, init'
## <Func Name="FreeMagma" Arg='infinity[, name[, init]]'
## Label="for infinitely many generators"/>
##
## <Description>
## Called with a positive integer <A>rank</A>,
## <Ref Func="FreeMagma" Label="for given rank"/> returns
## a free magma on <A>rank</A> generators.
## If the optional argument <A>name</A> is given then the generators are
## If the optional argument <A>name</A> (a string) is given,
## then the generators are
## printed as <A>name</A><C>1</C>, <A>name</A><C>2</C> etc.,
## that is, each name is the concatenation of the string <A>name</A> and an
## integer from <C>1</C> to <A>range</A>.
## The default for <A>name</A> is the string <C>"m"</C>.
## integer from <C>1</C> to <A>rank</A>.
## The default for <A>name</A> is the string <C>"x"</C>.
## <P/>
## Called in the second form,
## <Ref Func="FreeMagma" Label="for various names"/> returns
Expand Down Expand Up @@ -783,7 +784,7 @@ DeclareGlobalFunction( "FreeMagma" );
#F FreeMagmaWithOne( <rank>[, <name>] )
#F FreeMagmaWithOne( <name1>, <name2>, ... )
#F FreeMagmaWithOne( <names> )
#F FreeMagmaWithOne( infinity, <name>, <init> )
#F FreeMagmaWithOne( infinity[, <name>[, <init>]] )
##
## <#GAPDoc Label="FreeMagmaWithOne">
## <ManSection>
Expand All @@ -794,7 +795,7 @@ DeclareGlobalFunction( "FreeMagma" );
## Label="for various names"/>
## <Func Name="FreeMagmaWithOne" Arg='names'
## Label="for a list of names"/>
## <Func Name="FreeMagmaWithOne" Arg='infinity, name, init'
## <Func Name="FreeMagmaWithOne" Arg='infinity[, name[, init]]'
## Label="for infinitely many generators"/>
##
## <Description>
Expand All @@ -804,8 +805,8 @@ DeclareGlobalFunction( "FreeMagma" );
## If the optional argument <A>name</A> is given then the generators are
## printed as <A>name</A><C>1</C>, <A>name</A><C>2</C> etc.,
## that is, each name is the concatenation of the string <A>name</A> and an
## integer from <C>1</C> to <A>range</A>.
## The default for <A>name</A> is the string <C>"m"</C>.
## integer from <C>1</C> to <A>rank</A>.
## The default for <A>name</A> is the string <C>"x"</C>.
## <P/>
## Called in the second form,
## <Ref Func="FreeMagmaWithOne" Label="for various names"/> returns
Expand Down
221 changes: 157 additions & 64 deletions lib/mgmfree.gi
Original file line number Diff line number Diff line change
Expand Up @@ -273,43 +273,152 @@ InstallMethod( MagmaGeneratorsOfFamily,
F -> List( [ 1 .. Length( F!.names ) ], i -> ObjByExtRep( F, i ) ) );


# Currently used by FreeSemigroup, FreeMagma, FreeMonoid, FreeMagmaWithOne
FreeAlgebraCreatorArgumentProcessor := function(func, lesy, arg)
local rank,
name,
init,
bad_form,
err, # string; helpful error message
form, # string: assumed argument form of call to <func>
names; # list of generators names


# Process and validate the argument list, constructing names if necessary
err := "";
form := fail;
bad_form := false;
names := [];

if Length( arg ) = 0 or arg[1] = 0
or (Length( arg ) = 1 and IsList( arg[1] ) and IsEmpty( arg[1] )) then
# rank 0

# func( <rank>[, <name> ] )
elif IsPosInt( arg[1] ) and Length( arg ) <= 2 then

# Get default and optional arguments
rank := arg[1];
if Length( arg ) = 1 then
if func = "FreeSemigroup" then
name := "s";
elif func = "FreeMagma" or func = "FreeMagmaWithOne" then
name := "x";
else
name := "m";
fi;
else
name := arg[2];
fi;

# Error checking
if not IsString( name ) then
form := "<rank>, <name>";
err := "<name> must be a string";

# Construct names
else
names:= List( [ 1 .. rank ], i -> Concatenation( name, String(i) ) );
MakeImmutable( names );
fi;

# func( <name1>[, <name2>, ...] ), or a list of such arguments
elif ForAll( arg, IsString ) or Length( arg ) = 1 and IsList( arg[1] ) then
if Length( arg ) = 1 and not IsString( arg[1] ) then
form := "[ <name1>, <name2>, ... ]";
names:= arg[1];
else
form := "<name1>, <name2>, ...";
names:= arg;
fi;
if not ForAll( names, s -> IsString(s) and not IsEmpty(s) ) then
err := "the names must be nonempty strings";
fi;

# func( infinity[, <name>[, <init>]] )
elif arg[1] = infinity and Length( arg ) <= 3 then

# Get default and optional arguments
name := "s";
init := [];
if Length( arg ) = 3 then
form := "infinity, <name>, <init>";
name := arg[2];
init := arg[3];
elif Length( arg ) = 2 then
form := "infinity, <name>";
name := arg[2];
fi;

# Error checking
if not IsString( name ) then
err := "<name> must be a string";
fi;
if not ( IsList( init ) and ForAll( init, s -> IsString(s) and not IsEmpty(s) ) ) then
if not IsEmpty(err) then
Append(err, " and ");
fi;
Append(err, "<init> must be a list of nonempty strings");
fi;

# Construct names
if IsEmpty(err) then
names:= InfiniteListOfNames( name, init );
fi;

else
bad_form := true;
fi;

if not IsEmpty(err) then
ErrorNoReturn(StringFormatted("{}( {} ): {}", func, form, err));
fi;

# deal with letter words family types
if lesy <> fail then
if lesy=IsLetterWordsFamily then
if Length(names)>127 then
lesy:=IsWLetterWordsFamily;
else
lesy:=IsBLetterWordsFamily;
fi;
elif lesy=IsBLetterWordsFamily and Length(names)>127 then
lesy:=IsWLetterWordsFamily;
fi;
fi;

return rec(
names := names,
form := form,
lesy := lesy,
bad_form := bad_form,
);
end;


#############################################################################
##
#F FreeMagma( <rank> )
#F FreeMagma( <rank>, <name> )
#F FreeMagma( <rank>[, <name>] )
#F FreeMagma( <name1>, <name2>, ... )
#F FreeMagma( <names> )
#F FreeMagma( infinity, <name>, <init> )
##
InstallGlobalFunction( FreeMagma,
function( arg )
local names, # list of generators names
F, # family of free magma element objects
M; # free magma, result

# Get and check the argument list, and construct names if necessary.
if Length( arg ) = 1 and arg[1] = infinity then
names:= InfiniteListOfNames( "x" );
elif Length( arg ) = 2 and arg[1] = infinity then
names:= InfiniteListOfNames( arg[2] );
elif Length( arg ) = 3 and arg[1] = infinity then
names:= InfiniteListOfNames( arg[2], arg[3] );
elif Length( arg ) = 1 and IsInt( arg[1] ) and 0 < arg[1] then
names:= List( [ 1 .. arg[1] ],
i -> Concatenation( "x", String(i) ) );
MakeImmutable( names );
elif Length( arg ) = 2 and IsInt( arg[1] ) and 0 < arg[1] then
names:= List( [ 1 .. arg[1] ],
i -> Concatenation( arg[2], String(i) ) );
MakeImmutable( names );
elif 1 <= Length( arg ) and ForAll( arg, IsString ) then
names:= arg;
elif Length( arg ) = 1 and IsList( arg[1] )
and not IsEmpty( arg[1] )
and ForAll( arg[1], IsString ) then
names:= arg[1];
else
Error("usage: FreeMagma(<name1>,<name2>..),FreeMagma(<rank>)");
#F FreeMagma( infinity[, <name>[, <init>]] )
##
InstallGlobalFunction( FreeMagma, function( arg )
local names, # list of generators names
F, # family of free magma element objects
M, # free magma, result
processed;

processed := FreeAlgebraCreatorArgumentProcessor("FreeMagma", fail, arg);
names := processed.names;

if processed.bad_form then
ErrorNoReturn("""usage: FreeMagma( <rank>[, <name>] )
FreeMagma( <name1>, <name2>, ... )
FreeMagma( <names> )
FreeMagma( infinity[, <name>[, <init>]] )""");
elif IsEmpty(names) then
ErrorNoReturn("free magmas of rank zero are not supported");
fi;

# Construct the family of element objects of our magma.
Expand All @@ -334,42 +443,26 @@ end );

#############################################################################
##
#F FreeMagmaWithOne( <rank> )
#F FreeMagmaWithOne( <rank>, <name> )
#F FreeMagmaWithOne( <rank>[, <name>] )
#F FreeMagmaWithOne( <name1>, <name2>, ... )
#F FreeMagmaWithOne( <names> )
#F FreeMagmaWithOne( infinity, <name>, <init> )
#F FreeMagmaWithOne( infinity[, <name>[, <init>]] )
##
InstallGlobalFunction( FreeMagmaWithOne,
function( arg )
local names, # list of generators names
F, # family of free magma element objects
M; # free magma, result

# Get and check the argument list, and construct names if necessary.
if Length( arg ) = 1 and arg[1] = infinity then
names:= InfiniteListOfNames( "x" );
elif Length( arg ) = 2 and arg[1] = infinity then
names:= InfiniteListOfNames( arg[2] );
elif Length( arg ) = 3 and arg[1] = infinity then
names:= InfiniteListOfNames( arg[2], arg[3] );
elif Length( arg ) = 1 and IsInt( arg[1] ) and 0 < arg[1] then
names:= List( [ 1 .. arg[1] ],
i -> Concatenation( "x", String(i) ) );
MakeImmutable( names );
elif Length( arg ) = 2 and IsInt( arg[1] ) and 0 < arg[1] then
names:= List( [ 1 .. arg[1] ],
i -> Concatenation( arg[2], String(i) ) );
MakeImmutable( names );
elif 1 <= Length( arg ) and ForAll( arg, IsString ) then
names:= arg;
elif Length( arg ) = 1 and IsList( arg[1] )
and not IsEmpty( arg[1])
and ForAll( arg[1], IsString ) then
names:= arg[1];
else
Error( "usage: FreeMagmaWithOne(<name1>,<name2>..),",
"FreeMagmaWithOne(<rank>)" );
local names, # list of generators names
F, # family of free magma element objects
M, # free magma, result
processed;

processed := FreeAlgebraCreatorArgumentProcessor("FreeMagmaWithOne", fail, arg);
names := processed.names;

if processed.bad_form then
ErrorNoReturn("""usage: FreeMagmaWithOne( <rank>[, <name>] )
FreeMagmaWithOne( <name1>, <name2>, ... )
FreeMagmaWithOne( <names> )
FreeMagmaWithOne( infinity[, <name>[, <init>]] )""");
fi;

# Handle the trivial case.
Expand Down
Loading

0 comments on commit c9b5943

Please sign in to comment.