#############################################################################
##
##  This file is part of GAP, a system for computational discrete algebra.
##  This file's authors include Thomas Breuer.
##
##  Copyright of GAP belongs to its developers, whose names are too numerous
##  to list here. Please refer to the COPYRIGHT file for details.
##
##  SPDX-License-Identifier: GPL-2.0-or-later
##
##  This file declares operations for magma rings.
##
##  <#GAPDoc Label="[1]{mgmring}">
##  <Index>group algebra</Index>
##  <Index>group ring</Index>
##  Given a magma <M>M</M> then the <E>free magma ring</E>
##  (or <E>magma ring</E> for short) <M>RM</M> of <M>M</M>
##  over a ring-with-one <M>R</M> is the set of finite sums
##  <M>\sum_{{i \in I}} r_i m_i</M> with <M>r_i \in R</M>,
##  and <M>m_i \in M</M>.
##  With the obvious addition and <M>R</M>-action from the left,
##  <M>RM</M> is a free <M>R</M>-module with <M>R</M>-basis <M>M</M>,
##  and with the usual convolution product, <M>RM</M> is a ring.
##  <P/>
##  Typical examples of free magma rings are
##  <P/>
##  <List>
##  <Item>
##      (multivariate) polynomial rings
##      (see&nbsp;<Ref Chap="Polynomial Rings and Function Fields"/>),
##      where the magma is a free abelian monoid generated by the
##      indeterminates,
##  </Item>
##  <Item>
##      group rings (see&nbsp;<Ref Prop="IsGroupRing"/>),
##      where the magma is a group,
##  </Item>
##  <Item>
##      Laurent polynomial rings, which are group rings of the free abelian
##      <!-- #T (see~???) -->
##      groups generated by the indeterminates,
##  </Item>
##  <Item>
##      free algebras and free associative algebras, with or without one,
##      where the magma is a free magma or a free semigroup,
##      or a free magma-with-one or a free monoid, respectively.
##  </Item>
##  </List>
##  Note that formally, polynomial rings in &GAP; are not constructed 
##  as free magma rings.
##  <P/>
##  Furthermore, a free Lie algebra is <E>not</E> a magma ring,
##  because of the additional relations given by the Jacobi identity;
##  see&nbsp;<Ref Sect="Magma Rings modulo Relations"/> for a generalization
##  of magma rings that covers such structures.
##  <P/>
##  The coefficient ring <M>R</M> and the magma <M>M</M> cannot be regarded
##  as subsets of <M>RM</M>,
##  hence the natural <E>embeddings</E> of <M>R</M> and <M>M</M> into
##  <M>RM</M> must be handled via explicit embedding maps
##  (see&nbsp;<Ref Sect="Natural Embeddings related to Magma Rings"/>).
##  Note that in a magma ring, the addition of elements is in general
##  different from an addition that may be defined already for the elements
##  of the magma;
##  for example, the addition in the group ring of a matrix group does in
##  general <E>not</E> coincide with the addition of matrices.
##  <P/>
##  <Example><![CDATA[
##  gap> a:= Algebra( GF(2), [ [ [ Z(2) ] ] ] );;  Size( a );
##  2
##  gap> rm:= FreeMagmaRing( GF(2), a );;
##  gap> emb:= Embedding( a, rm );;
##  gap> z:= Zero( a );;  o:= One( a );;
##  gap> imz:= z ^ emb;  IsZero( imz );
##  (Z(2)^0)*[ [ 0*Z(2) ] ]
##  false
##  gap> im1:= ( z + o ) ^ emb;
##  (Z(2)^0)*[ [ Z(2)^0 ] ]
##  gap> im2:= z ^ emb + o ^ emb;
##  (Z(2)^0)*[ [ 0*Z(2) ] ]+(Z(2)^0)*[ [ Z(2)^0 ] ]
##  gap> im1 = im2;
##  false
##  ]]></Example>
##  <#/GAPDoc>
##
##  <#GAPDoc Label="[2]{mgmring}">
##  In order to treat elements of free magma rings uniformly,
##  also without an external representation, the attributes
##  <Ref Attr="CoefficientsAndMagmaElements"/>
##  and <Ref Attr="ZeroCoefficient"/>
##  were introduced that allow one to <Q>take an element of an arbitrary
##  magma ring into pieces</Q>.
##  <P/>
##  Conversely, for constructing magma ring elements from coefficients
##  and magma elements, <Ref Oper="ElementOfMagmaRing"/> can be used.
##  (Of course one can also embed each magma element into the magma ring,
##  see&nbsp;<Ref Sect="Natural Embeddings related to Magma Rings"/>,
##  and then form the linear combination,
##  but many unnecessary intermediate elements are created this way.)
##  <#/GAPDoc>
##
##  <#GAPDoc Label="[3]{mgmring}">
##  <Index Key="Embedding" Subkey="for magma rings"><C>Embedding</C></Index>
##  Neither the coefficient ring <M>R</M> nor the magma <M>M</M>
##  are regarded as subsets of the magma ring <M>RM</M>,
##  so one has to use <E>embeddings</E>
##  (see&nbsp;<Ref Oper="Embedding" Label="for two domains"/>)
##  explicitly whenever one needs for example the magma ring element
##  corresponding to a given magma element.
##  <P/>
##  <Example><![CDATA[
##  gap> f:= Rationals;;  g:= SymmetricGroup( 3 );;
##  gap> fg:= FreeMagmaRing( f, g );
##  <algebra-with-one over Rationals, with 2 generators>
##  gap> Dimension( fg );
##  6
##  gap> gens:= GeneratorsOfAlgebraWithOne( fg );
##  [ (1)*(1,2,3), (1)*(1,2) ]
##  gap> ( 3*gens[1] - 2*gens[2] ) * ( gens[1] + gens[2] );
##  (-2)*()+(3)*(2,3)+(3)*(1,3,2)+(-2)*(1,3)
##  gap> One( fg );
##  (1)*()
##  gap> emb:= Embedding( g, fg );;
##  gap> elm:= (1,2,3)^emb;  elm in fg;
##  (1)*(1,2,3)
##  true
##  gap> new:= elm + One( fg );
##  (1)*()+(1)*(1,2,3)
##  gap> new^2;
##  (1)*()+(2)*(1,2,3)+(1)*(1,3,2)
##  gap> emb2:= Embedding( f, fg );;
##  gap> elm:= One( f )^emb2;  elm in fg;
##  (1)*()
##  true
##  ]]></Example>
##  <#/GAPDoc>
##
##  <#GAPDoc Label="[4]{mgmring}">
##  A more general construction than that of free magma rings allows one
##  to create rings that are not free <M>R</M>-modules on a given magma
##  <M>M</M> but arise from the magma ring <M>RM</M> by factoring out certain
##  identities.
##  Examples for such structures are finitely presented (associative)
##  algebras and free Lie algebras
##  (see&nbsp;<Ref Func="FreeLieAlgebra" Label="for ring, rank (and name)"/>).
##  <!-- #T see ... ? -->
##  <P/>
##  In &GAP;, the use of magma rings modulo relations is limited to
##  situations where a normal form of the elements is known and where
##  one wants to guarantee that all elements actually constructed are
##  in normal form.
##  (In particular, the computation of the normal form must be cheap.)
##  This is because the methods for comparing elements in magma rings
##  modulo relations via <C>\=</C> and <C>\&lt;</C>
##  just compare the involved coefficients and magma elements,
##  and also the vector space functions regard those monomials as
##  linearly independent over the coefficients ring that actually occur
##  in the representation of an element of a magma ring modulo relations.
##  <P/>
##  Thus only very special finitely presented algebras will be represented
##  as magma rings modulo relations,
##  in general finitely presented algebras are dealt with via the
##  mechanism described in
##  Chapter&nbsp;<Ref Chap="Finitely Presented Algebras"/>.
##  <#/GAPDoc>
##
##  <#GAPDoc Label="[5]{mgmring}">
##  The <E>family</E> containing elements in the magma ring <M>RM</M>
##  in fact contains all elements with coefficients in the family of elements
##  of <M>R</M> and magma elements in the family of elements of <M>M</M>.
##  So arithmetic operations with coefficients outside <M>R</M> or with
##  magma elements outside <M>M</M> might create elements outside <M>RM</M>.
##  <P/>
##  It should be mentioned that each call of <Ref Func="FreeMagmaRing"/>
##  creates a new family of elements,
##  so for example the elements of two group rings of permutation groups
##  over the same ring lie in different families and therefore are regarded
##  as different.
##  <P/>
##  <Example><![CDATA[
##  gap> g:= SymmetricGroup( 3 );;
##  gap> h:= AlternatingGroup( 3 );;
##  gap> IsSubset( g, h );
##  true
##  gap> f:= GF(2);;
##  gap> fg:= GroupRing( f, g );
##  <algebra-with-one over GF(2), with 2 generators>
##  gap> fh:= GroupRing( f, h );
##  <algebra-with-one over GF(2), with 1 generator>
##  gap> IsSubset( fg, fh );
##  false
##  gap> o1:= One( fh );  o2:= One( fg );  o1 = o2;
##  (Z(2)^0)*()
##  (Z(2)^0)*()
##  false
##  gap> emb:= Embedding( g, fg );;
##  gap> im:= Image( emb, h );
##  <group of size 3 with 1 generator>
##  gap> IsSubset( fg, im );
##  true
##  ]]></Example>
##  <P/>
##  There is <E>no</E> generic <E>external representation</E> for elements
##  in an arbitrary free magma ring.
##  For example, polynomials are elements of a free magma ring,
##  and they have an external representation relying on the special form
##  of the underlying monomials.
##  On the other hand, elements in a group ring of a permutation group
##  do not admit such an external representation.
##  <P/>
##  For convenience, magma rings constructed with
##  <Ref Func="FreeAlgebra" Label="for ring, rank (and name)"/>,
##  <Ref Func="FreeAssociativeAlgebra" Label="for ring, rank (and name)"/>,
##  <Ref Func="FreeAlgebraWithOne" Label="for ring, rank (and name)"/>, and
##  <Ref Func="FreeAssociativeAlgebraWithOne"
##  Label="for ring, rank (and name)"/>
##  support an external representation of their elements,
##  which is defined as a list of length 2,
##  the first entry being the zero coefficient, the second being a list with
##  the external representations of the magma elements at the odd positions
##  and the corresponding coefficients at the even positions.
##  <P/>
##  As the above examples show, there are several possible representations
##  of magma ring elements, the representations used for polynomials
##  (see Chapter &nbsp;<Ref Sect="Polynomials and Rational Functions"/>)
##  as well as the default representation <Ref Filt="IsMagmaRingObjDefaultRep"/>
##  of magma ring elements.
##  The latter simply stores the zero coefficient and a list containing
##  the coefficients of the element at the even positions
##  and the corresponding magma elements at the odd positions,
##  where the succession is compatible with the ordering of magma elements
##  via <C>\&lt;</C>.
##  <#/GAPDoc>
##


#############################################################################
##
#C  IsElementOfMagmaRingModuloRelations( <obj> )
#C  IsElementOfMagmaRingModuloRelationsCollection( <obj> )
##
##  <#GAPDoc Label="IsElementOfMagmaRingModuloRelations">
##  <ManSection>
##  <Filt Name="IsElementOfMagmaRingModuloRelations" Arg='obj'
##   Type='Category'/>
##  <Filt Name="IsElementOfMagmaRingModuloRelationsCollection" Arg='obj'
##   Type='Category'/>
##
##  <Description>
##  This category is used, e.&nbsp;g., for elements of free Lie algebras.
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareCategory( "IsElementOfMagmaRingModuloRelations", IsScalar );

DeclareCategoryCollections( "IsElementOfMagmaRingModuloRelations" );


#############################################################################
##
#C  IsElementOfMagmaRingModuloRelationsFamily( <Fam> )
##
##  <#GAPDoc Label="IsElementOfMagmaRingModuloRelationsFamily">
##  <ManSection>
##  <Filt Name="IsElementOfMagmaRingModuloRelationsFamily" Arg='Fam'
##   Type='Category'/>
##
##  <Description>
##  The family category for the category 
##  <Ref Filt="IsElementOfMagmaRingModuloRelations" />.
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareCategoryFamily( "IsElementOfMagmaRingModuloRelations" );


#############################################################################
##
#C  IsElementOfFreeMagmaRing( <obj> )
#C  IsElementOfFreeMagmaRingCollection( <obj> )
##
##  <#GAPDoc Label="IsElementOfFreeMagmaRing">
##  <ManSection>
##  <Filt Name="IsElementOfFreeMagmaRing" Arg='obj' Type='Category'/>
##  <Filt Name="IsElementOfFreeMagmaRingCollection" Arg='obj'
##   Type='Category'/>
##
##  <Description>
##  The category of elements of a free magma ring
##  (See <Ref Filt="IsFreeMagmaRing"/>).
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareCategory( "IsElementOfFreeMagmaRing",
    IsElementOfMagmaRingModuloRelations );

DeclareCategoryCollections( "IsElementOfFreeMagmaRing" );


#############################################################################
##
#C  IsElementOfFreeMagmaRingFamily( <Fam> )
##
##  <#GAPDoc Label="IsElementOfFreeMagmaRingFamily">
##  <ManSection>
##  <Filt Name="IsElementOfFreeMagmaRingFamily" Arg='Fam' Type='Category'/>
##
##  <Description>
##  Elements of families in this category have trivial normalisation, i.e.,
##  efficient methods for <C>\=</C> and <C>\&lt;</C>.
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareCategoryFamily( "IsElementOfFreeMagmaRing" );


#############################################################################
##
#A  CoefficientsAndMagmaElements( <elm> ) . . . . .  for elm. in a magma ring
##
##  <#GAPDoc Label="CoefficientsAndMagmaElements">
##  <ManSection>
##  <Attr Name="CoefficientsAndMagmaElements" Arg='elm'/>
##
##  <Description>
##  is a list that contains at the odd positions the magma elements,
##  and at the even positions their coefficients in the element <A>elm</A>.
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareAttribute( "CoefficientsAndMagmaElements",
    IsElementOfMagmaRingModuloRelations );


#############################################################################
##
#A  ZeroCoefficient( <elm> )
##
##  <#GAPDoc Label="ZeroCoefficient">
##  <ManSection>
##  <Attr Name="ZeroCoefficient" Arg='elm'/>
##
##  <Description>
##  For an element <A>elm</A> of a magma ring (modulo relations) <M>RM</M>,
##  <Ref Attr="ZeroCoefficient"/> returns the zero element
##  of the coefficient ring <M>R</M>.
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareAttribute( "ZeroCoefficient", IsElementOfMagmaRingModuloRelations );


#############################################################################
##
#O  NormalizedElementOfMagmaRingModuloRelations( <F>, <descr> )
##
##  <#GAPDoc Label="NormalizedElementOfMagmaRingModuloRelations">
##  <ManSection>
##  <Oper Name="NormalizedElementOfMagmaRingModuloRelations" Arg='F, descr'/>
##
##  <Description>
##  Let <A>F</A> be a family of magma ring elements modulo relations,
##  and <A>descr</A> the description of an element in a magma ring modulo
##  relations.
##  <Ref Oper="NormalizedElementOfMagmaRingModuloRelations"/> returns
##  a description of the same element,
##  but normalized w.r.t.&nbsp;the relations.
##  So two elements are equal if and only if the result of
##  <Ref Oper="NormalizedElementOfMagmaRingModuloRelations"/> is equal for
##  their internal data, that is,
##  <Ref Attr="CoefficientsAndMagmaElements"/> will return the same
##  for the corresponding two elements.
##  <P/>
##  <Ref Oper="NormalizedElementOfMagmaRingModuloRelations"/> is allowed
##  to return <A>descr</A> itself, it need not make a copy.
##  This is the case for example in the case of free magma rings.
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareOperation( "NormalizedElementOfMagmaRingModuloRelations",
    [ IsElementOfMagmaRingModuloRelationsFamily, IsList ] );


#############################################################################
##
#C  IsMagmaRingModuloRelations( <obj> )
##
##  <#GAPDoc Label="IsMagmaRingModuloRelations">
##  <ManSection>
##  <Filt Name="IsMagmaRingModuloRelations" Arg='obj' Type='Category'/>
##
##  <Description>
##  A &GAP; object lies in the category
##  <Ref Filt="IsMagmaRingModuloRelations"/>
##  if it has been constructed as a magma ring modulo relations.
##  Each element of such a ring has a unique normal form,
##  so <Ref Attr="CoefficientsAndMagmaElements"/> is well-defined for it.
##  <P/>
##  This category is not inherited to factor structures,
##  which are in general best described as finitely presented algebras,
##  see Chapter&nbsp;<Ref Chap="Finitely Presented Algebras"/>.
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareCategory( "IsMagmaRingModuloRelations", IsFLMLOR );


#############################################################################
##
#C  IsFreeMagmaRing( <D> )
##
##  <#GAPDoc Label="IsFreeMagmaRing">
##  <ManSection>
##  <Filt Name="IsFreeMagmaRing" Arg='D' Type='Category'/>
##
##  <Description>
##  A domain lies in the category <Ref Filt="IsFreeMagmaRing"/>
##  if it has been constructed as a free magma ring.
##  In particular, if <A>D</A> lies in this category then the operations
##  <Ref Attr="LeftActingDomain"/> and
##  <Ref Attr="UnderlyingMagma"/> are applicable to <A>D</A>,
##  and yield the ring <M>R</M> and the magma <M>M</M>
##  such that <A>D</A> is the magma ring <M>RM</M>.
##  <P/>
##  So being a magma ring in &GAP; includes the knowledge of the ring and
##  the magma.
##  Note that a magma ring <M>RM</M> may abstractly be generated as a
##  magma ring by a magma different from the underlying magma <M>M</M>.
##  For example, the group ring of the dihedral group of order <M>8</M>
##  over the field with <M>3</M> elements is also spanned by a quaternion
##  group of order <M>8</M> over the same field.
##  <P/>
##  <Example><![CDATA[
##  gap> d8:= DihedralGroup( 8 );
##  <pc group of size 8 with 3 generators>
##  gap> rm:= FreeMagmaRing( GF(3), d8 );
##  <algebra-with-one over GF(3), with 3 generators>
##  gap> emb:= Embedding( d8, rm );;
##  gap> gens:= List( GeneratorsOfGroup( d8 ), x -> x^emb );;
##  gap> x1:= gens[1] + gens[2];;
##  gap> x2:= ( gens[1] - gens[2] ) * gens[3];;
##  gap> x3:= gens[1] * gens[2] * ( One( rm ) - gens[3] );;
##  gap> g1:= x1 - x2 + x3;;
##  gap> g2:= x1 + x2;;
##  gap> q8:= Group( g1, g2 );;
##  gap> Size( q8 );
##  8
##  gap> ForAny( [ d8, q8 ], IsAbelian );
##  false
##  gap> List( [ d8, q8 ], g -> Number( AsList( g ), x -> Order( x ) = 2 ) );
##  [ 5, 1 ]
##  gap> Dimension( Subspace( rm, q8 ) );
##  8
##  ]]></Example>
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareCategory( "IsFreeMagmaRing", IsMagmaRingModuloRelations );


#############################################################################
##
#C  IsFreeMagmaRingWithOne( <obj> )
##
##  <#GAPDoc Label="IsFreeMagmaRingWithOne">
##  <ManSection>
##  <Filt Name="IsFreeMagmaRingWithOne" Arg='obj' Type='Category'/>
##
##  <Description>
##  <Ref Filt="IsFreeMagmaRingWithOne"/> is just a synonym for the meet of
##  <Ref Filt="IsFreeMagmaRing"/> and
##  <Ref Filt="IsMagmaWithOne"/>.
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareSynonym( "IsFreeMagmaRingWithOne",
    IsFreeMagmaRing and IsMagmaWithOne );


#############################################################################
##
#P  IsGroupRing( <obj> )
##
##  <#GAPDoc Label="IsGroupRing">
##  <ManSection>
##  <Prop Name="IsGroupRing" Arg='obj'/>
##
##  <Description>
##  A <E>group ring</E> is a magma ring where the underlying magma is a group.
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareProperty( "IsGroupRing", IsFreeMagmaRing );
InstallTrueMethod( IsRing, IsGroupRing );


#############################################################################
##
#A  UnderlyingMagma( <RM> )
##
##  <#GAPDoc Label="UnderlyingMagma">
##  <ManSection>
##  <Attr Name="UnderlyingMagma" Arg='RM'/>
##
##  <Description>
##  stores the underlying magma of a free magma ring.
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareAttribute( "UnderlyingMagma", IsFreeMagmaRing );


#############################################################################
##
#O  ElementOfMagmaRing( <Fam>, <zerocoeff>, <coeffs>, <mgmelms> )
##
##  <#GAPDoc Label="ElementOfMagmaRing">
##  <ManSection>
##  <Oper Name="ElementOfMagmaRing" Arg='Fam, zerocoeff, coeffs, mgmelms'/>
##
##  <Description>
##  <Ref Oper="ElementOfMagmaRing"/> returns the element
##  <M>\sum_{{i = 1}}^n c_i m_i'</M>,
##  where <M><A>coeffs</A> = [ c_1, c_2, \ldots, c_n ]</M> is a list of
##  coefficients, <M><A>mgmelms</A> = [ m_1, m_2, \ldots, m_n ]</M> is a list
##  of magma elements,
##  and <M>m_i'</M> is the image of <M>m_i</M> under an embedding
##  of a magma containing <M>m_i</M> into a magma ring
##  whose elements lie in the family <A>Fam</A>.
##  <A>zerocoeff</A> must be the zero of the coefficient ring
##  containing the <M>c_i</M>.
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareOperation( "ElementOfMagmaRing",
    [ IsFamily, IsRingElement, IsHomogeneousList, IsHomogeneousList ] );


#############################################################################
##
#F  FreeMagmaRing( <R>, <M> )
##
##  <#GAPDoc Label="FreeMagmaRing">
##  <ManSection>
##  <Func Name="FreeMagmaRing" Arg='R, M'/>
##
##  <Description>
##  is a free magma ring over the ring <A>R</A>, free on the magma <A>M</A>.
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareGlobalFunction( "FreeMagmaRing" );


#############################################################################
##
#F  GroupRing( <R>, <G> )
##
##  <#GAPDoc Label="GroupRing">
##  <ManSection>
##  <Func Name="GroupRing" Arg='R, G'/>
##
##  <Description>
##  is the group ring of the group <A>G</A>, over the ring <A>R</A>.
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareGlobalFunction( "GroupRing" );


#############################################################################
##
#A  AugmentationIdeal( <RG> )
##
##  <#GAPDoc Label="AugmentationIdeal">
##  <ManSection>
##  <Attr Name="AugmentationIdeal" Arg='RG'/>
##
##  <Description>
##  is the augmentation ideal of the group ring <A>RG</A>,
##  i.e., the kernel of the trivial representation of <A>RG</A>.
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareAttribute( "AugmentationIdeal", IsFreeMagmaRing );


#############################################################################
##
#F  MagmaRingModuloSpanOfZero( <R>, <M>, <z> )
##
##  <#GAPDoc Label="MagmaRingModuloSpanOfZero">
##  <ManSection>
##  <Func Name="MagmaRingModuloSpanOfZero" Arg='R, M, z'/>
##
##  <Description>
##  Let <A>R</A> be a ring, <A>M</A> a magma, and <A>z</A> an element of
##  <A>M</A> with the property that <M><A>z</A> * m = <A>z</A></M> holds
##  for all <M>m \in M</M>.
##  The element <A>z</A> could be called a <Q>zero element</Q> of <A>M</A>,
##  but note that in general <A>z</A> cannot be obtained as
##  <C>Zero( </C><M>m</M><C> )</C> for each <M>m \in M</M>,
##  so this situation does not match the definition of <Ref Attr="Zero"/>.
##  <P/>
##  <Ref Func="MagmaRingModuloSpanOfZero"/> returns the magma ring
##  <M><A>R</A><A>M</A></M> modulo the relation given by the identification
##  of <A>z</A> with zero.
##  This is an example of a magma ring modulo relations,
##  see&nbsp;<Ref Sect="Magma Rings modulo Relations"/>.
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareGlobalFunction( "MagmaRingModuloSpanOfZero" );


#############################################################################
##
#C  IsMagmaRingModuloSpanOfZero( <RM> )
##
##  <#GAPDoc Label="IsMagmaRingModuloSpanOfZero">
##  <ManSection>
##  <Filt Name="IsMagmaRingModuloSpanOfZero" Arg='RM' Type='Category'/>
##
##  <Description>
##  The category of magma rings modulo the span of a zero element.
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareCategory( "IsMagmaRingModuloSpanOfZero", IsMagmaRingModuloRelations );


#############################################################################
##
#C  IsElementOfMagmaRingModuloSpanOfZeroFamily( <Fam> )
##
##  <#GAPDoc Label="IsElementOfMagmaRingModuloSpanOfZeroFamily">
##  <ManSection>
##  <Filt Name="IsElementOfMagmaRingModuloSpanOfZeroFamily" Arg='Fam'
##   Type='Category'/>
##
##  <Description>
##  We need this for the normalization method, which takes a family as first
##  argument.
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareCategory( "IsElementOfMagmaRingModuloSpanOfZeroFamily",
    IsElementOfMagmaRingModuloRelationsFamily );


#############################################################################
##
##  3. Free left modules in magma rings modulo relations
##


#############################################################################
##
#F  IsSpaceOfElementsOfMagmaRing( <V> )
##
##  <ManSection>
##  <Func Name="IsSpaceOfElementsOfMagmaRing" Arg='V'/>
##
##  <Description>
##  If an <M>F</M>-vector space <A>V</A> is in the filter
##  <Ref Func="IsSpaceOfElementsOfMagmaRing"/> then this expresses that
##  <A>V</A> consists of elements in a magma ring modulo relations,
##  and that <A>V</A> is handled via the mechanism of nice bases
##  (see&nbsp;<Ref ???="..."/>) in the following way.
##  Let <M>V</M> be a free <M>F</M>-module of elements in a magma ring modulo
##  relations <M>FM</M>, and let <M>S</M> be the set of magma elements that
##  occur in the vector space generators of <M>V</M>.
##  Then the <Ref Func="NiceFreeLeftModuleInfo"/> value of <A>V</A> is
##  a record with the following components.
##  <List>
##  <Mark><C>family</C></Mark>
##  <Item>
##     the elements family of <A>V</A>,
##  </Item>
##  <Mark><C>monomials</C></Mark>
##  <Item>
##     the list <M>S</M> of magma elements that occur in elements of <A>V</A>,
##  </Item>
##  <Mark><C>zerocoeff</C></Mark>
##  <Item>
##     the zero coefficient of elements in <A>V</A>,
##  </Item>
##  <Mark><C>zerovector</C></Mark>
##  <Item>
##     the zero row vector in the nice left module.
##  </Item>
##  </List>
##  The <Ref Func="NiceVector"/> value of <M>v \in</M> <A>V</A> is defined as
##  the row vector of coefficients of <M>v</M> w.r.t.&nbsp;<M>S</M>.
##  <P/>
##  Finite dimensional free left modules of elements in a magma ring modulo
##  relations
##  (<E>not</E> the magma rings themselves, they have special methods)
##  are by default handled via the mechanism of nice bases.
##  </Description>
##  </ManSection>
##
DeclareHandlingByNiceBasis( "IsSpaceOfElementsOfMagmaRing",
    "for free left modules of magma rings modulo relations" );
