Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


SSL mgmring.gi   Sprache: unbekannt

 
#############################################################################
##
##  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 contains the methods for magma rings and their elements.
##
##  1. methods for elements of magma rings in default representation
##  2. methods for free magma rings
##  3. methods for free left modules in magma ring modulo relations
##  4. methods for free magma rings modulo the span of a ``zero'' element
##  5. methods for groups of free magma ring elements
##


#T > Dear Craig,
#T >
#T > you asked for the implementation of magma rings modulo the identification
#T > of a ``zero element'' in the magma with zero.
#T >
#T > Here is my proposal for the basic stuff.
#T > (I have mainly taken the implementation of free magma rings plus the
#T > ideas used for `FreeLieAlgebra'.)
#T > It does not cover the vector space functionality (computing bases etc.),
#T > but I will rearrange the code in `mgmring.gd' and `mgmring.gi' in such a way
#T > that your generalized magma rings can use the mechanisms provided there.


#T get rid of `!.zeroRing'
#T (provide uniform access to the zero coeff. stored in the element;
#T this is also possible for polynomials etc.)


#T get rid of !.defaultType
#T get rid of !.oneMagma

#T best get rid of the families distinction for magma rings ?
#T (would solve problems such as relation between GroupRing( Integers, G )
#T and GroupRing( Rationals, G ))


#############################################################################
##
##  1. methods for elements of magma rings in default representation
##

#############################################################################
##
#R  IsMagmaRingObjDefaultRep( <obj> )
##
##  <#GAPDoc Label="IsMagmaRingObjDefaultRep">
##  <ManSection>
##  <Filt Name="IsMagmaRingObjDefaultRep" Arg='obj' Type='Representation'/>
##
##  <Description>
##  The default representation of a magma ring element is a list of length 2,
##  at first position the zero coefficient, at second position a list with
##  the coefficients at the even positions, and the magma elements at the
##  odd positions, with the ordering as defined for the magma elements.
##  <P/>
##  It is assumed that arithmetic operations on magma rings produce only
##  normalized elements.
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
if IsHPCGAP then
DeclareRepresentation( "IsMagmaRingObjDefaultRep", IsAtomicPositionalObjectRep,
    [ 1, 2 ] );
else
DeclareRepresentation( "IsMagmaRingObjDefaultRep", IsPositionalObjectRep,
    [ 1, 2 ] );
fi;

#############################################################################
##
#M  NormalizedElementOfMagmaRingModuloRelations( <Fam>, <descr> )
##
##  A free magma ring element is normalized if <descr> is sorted according to
##  the involved magma elements.
##  Thus normalization is trivial.
##
InstallMethod( NormalizedElementOfMagmaRingModuloRelations,
    "for a family of elements in a *free* magma ring, and a list",
    [ IsElementOfFreeMagmaRingFamily, IsList ],
    function( Fam, descr )
    return Immutable(descr);
    end );


#############################################################################
##
#F  FMRRemoveZero( <coeffs_and_words>, <zero> )
##
##  removes all pairs from <coeffs_and_words> where the coefficient
##  is <zero>.
##  Note that <coeffs_and_words> is assumed to be sorted.
##
BindGlobal( "FMRRemoveZero", function( coeffs_and_words, zero )

    local i,    # offset of old and new position
          lenw, # length of `words' and `coeff'
          pos;  # loop over the lists

    i:= 0;
    lenw:= Length( coeffs_and_words );
    for pos in [ 2, 4 .. lenw ] do
      if   coeffs_and_words[ pos ] = zero then
        i:= i + 2;
      elif i < pos then
        coeffs_and_words[ pos-i-1 ]:= coeffs_and_words[ pos-1 ];
        coeffs_and_words[ pos-i   ]:= coeffs_and_words[ pos   ];
      fi;
    od;
    for pos in [ lenw-i+1 .. lenw ] do
      Unbind( coeffs_and_words[ pos ] );
    od;
    return coeffs_and_words;
end );


#############################################################################
##
#M  ElementOfMagmaRing( <Fam>, <zerocoeff>, <coeff>, <words> )
##
##  check whether <coeff> and <words> lie in the correct domains,
##  and remove zeroes.
##
InstallMethod( ElementOfMagmaRing,
    "for family, ring element, and two homogeneous lists",
    [ IsFamily, IsRingElement, IsHomogeneousList, IsHomogeneousList ],
    function( Fam, zerocoeff, coeff, words )
    local rep, i, j;

    # Check that the data is admissible.
    if not IsBound( Fam!.defaultType ) then
      TryNextMethod();
    elif IsEmpty( coeff ) and IsEmpty( words ) then
      return Objectify( Fam!.defaultType, [ zerocoeff, [] ] );
    elif not IsIdenticalObj( FamilyObj( coeff ), Fam!.familyRing ) then
      Error( "<coeff> are not all in the correct domain" );
    elif not IsIdenticalObj( FamilyObj( words ), Fam!.familyMagma ) then
      Error( "<words> are not all in the correct domain" );
    elif Length( coeff ) <> Length( words ) then
      Error( "<coeff> and <words> must have same length" );
    fi;

    # Make sure that the list of words is strictly sorted.
    if not IsSSortedList( words ) then
      words:= ShallowCopy( words );
      coeff:= ShallowCopy( coeff );
      SortParallel( words, coeff );
      if not IsSSortedList( words ) then
        j:= 1;
        for i in [ 2 .. Length( coeff ) ] do
          if words[i] = words[j] then
            coeff[j]:= coeff[j] + coeff[i];
          else
            j:= j+1;
            words[j]:= words[i];
            coeff[j]:= coeff[i];
          fi;
        od;
        for i in [ j+1 .. Length( coeff ) ] do
          Unbind( words[i] );
          Unbind( coeff[i] );
        od;
      fi;
    fi;

    # Create the default representation, and remove zeros.
    rep:= [];
    j:= 1;
    for i in [ 1 .. Length( coeff ) ] do
      if coeff[i] <> zerocoeff then
        rep[  j  ]:= words[i];
        rep[ j+1 ]:= coeff[i];
        j:= j+2;
      fi;
    od;

    # Normalize the result.
    rep:= NormalizedElementOfMagmaRingModuloRelations( Fam,
              [ zerocoeff, rep ] );

    # Return the result.
    return Objectify( Fam!.defaultType, rep );
    end );


#############################################################################
##
#M  ZeroCoefficient( <elm> )
##
InstallMethod( ZeroCoefficient,
    "for magma ring element in default repr.",
    [ IsElementOfMagmaRingModuloRelations and IsMagmaRingObjDefaultRep ],
    elm -> FamilyObj( elm )!.zeroRing );


#############################################################################
##
#M  CoefficientsAndMagmaElements( <elm> )
##
InstallMethod( CoefficientsAndMagmaElements,
    "for magma ring element in default repr.",
    [ IsElementOfMagmaRingModuloRelations and IsMagmaRingObjDefaultRep ],
    elm -> elm![2] );


#############################################################################
##
#M  PrintObj( <elm> ) . . . . . . . . for magma ring element in default repr.
##
InstallMethod( PrintObj,
    "for magma ring element",
    [ IsElementOfMagmaRingModuloRelations ],
    function( elm )

    local coeffs_and_words,
          i;

    coeffs_and_words:= CoefficientsAndMagmaElements( elm );
    for i in [ 1, 3 .. Length( coeffs_and_words ) - 3 ] do
      Print( "(", coeffs_and_words[i+1], ")*", coeffs_and_words[i], "+" );
    od;
    i:= Length( coeffs_and_words );
    if i = 0 then
      Print( "<zero> of ..." );
    else
      Print( "(", coeffs_and_words[i], ")*", coeffs_and_words[i-1] );
    fi;
    end );

#############################################################################
##
#M  String( <elm> ) . . . . . . . . for magma ring element in default repr.
##
InstallMethod( String,
    "for magma ring element",
    [ IsElementOfMagmaRingModuloRelations ],
function( elm )
local coeffs_and_words,s,i;

  s:="";
  coeffs_and_words:= CoefficientsAndMagmaElements( elm );
  for i in [ 1, 3 .. Length( coeffs_and_words ) - 3 ] do
    Append(s,Concatenation("(",String(coeffs_and_words[i+1]), ")*", String(coeffs_and_words[i]),
    "+" ));
  od;
  i:= Length( coeffs_and_words );
  if i = 0 then
    Append(s, "<zero> of ..." );
  else
    Append(s, Concatenation("(", String(coeffs_and_words[i]), ")*",
    String(coeffs_and_words[i-1]) ));
  fi;
  return s;
end );


#############################################################################
##
#M  \=( <x>, <y> )  . . . . for two free magma ring elements in default repr.
##
InstallMethod( \=,
    "for two free magma ring elements",
    IsIdenticalObj,
    [ IsElementOfMagmaRingModuloRelations,
      IsElementOfMagmaRingModuloRelations ],
    function( x, y )
    return   CoefficientsAndMagmaElements( x )
           = CoefficientsAndMagmaElements( y );
    end );


#############################################################################
##
#M  \<( <x>, <y> )  . . . . for two free magma ring elements in default repr.
##
InstallMethod( \<,
    "for two free magma ring elements",
    IsIdenticalObj,
    [ IsElementOfMagmaRingModuloRelations,
      IsElementOfMagmaRingModuloRelations ],
    function( x, y )
    local i;
    x:= CoefficientsAndMagmaElements( x );
    y:= CoefficientsAndMagmaElements( y );
    for i in [ 1 .. Minimum( Length( x ), Length( y ) ) ] do
      if   x[i] < y[i] then
        return true;
      elif y[i] < x[i] then
        return false;
      fi;
    od;
    return Length( x ) < Length( y );
    end );


#############################################################################
##
#M  \+( <x>, <y> )  . . . . . .  for two magma ring elements in default repr.
##
InstallMethod( \+,
    "for two magma ring elements",
    IsIdenticalObj,
    [ IsElementOfMagmaRingModuloRelations,
      IsElementOfMagmaRingModuloRelations ],
    function( x, y )
    local F, sum, z;
    F := FamilyObj( x );
    z := ZeroCoefficient( x );
    x := CoefficientsAndMagmaElements( x );
    y := CoefficientsAndMagmaElements( y );
    sum:= ZippedSum( x, y, z, [ \<, \+ ] );
    sum:= NormalizedElementOfMagmaRingModuloRelations( F, [ z, sum ] );
    return Objectify( F!.defaultType, sum );
    end );


#############################################################################
##
#M  AdditiveInverseOp( <x> )  . . . . for magma ring element in default repr.
##
InstallMethod( AdditiveInverseOp,
    "for magma ring element",
    [ IsElementOfMagmaRingModuloRelations ],
    function( x )
    local ext, i, Fam, inv;
    ext:= ShallowCopy( CoefficientsAndMagmaElements( x ) );
    for i in [ 2, 4 .. Length( ext ) ] do
      ext[i]:= AdditiveInverse( ext[i] );
    od;
    Fam:= FamilyObj( x );
    inv:= NormalizedElementOfMagmaRingModuloRelations( Fam,
              [ ZeroCoefficient( x ), ext ] );
    return Objectify( Fam!.defaultType, inv );
    end );


#############################################################################
##
#M  \*( <x>, <y> )  . . . . . .  for two magma ring elements in default repr.
##
InstallMethod( \*,
    "for two magma ring elements",
    IsIdenticalObj,
    [ IsElementOfMagmaRingModuloRelations,
      IsElementOfMagmaRingModuloRelations ],
    function( x, y )
    local F, prod, z;
    F := FamilyObj( x );
    z := ZeroCoefficient( x );
    x := CoefficientsAndMagmaElements( x );
    y := CoefficientsAndMagmaElements( y );
    prod:= ZippedProduct( x, y, z, [ \*, \<, \+, \* ] );
    prod:= NormalizedElementOfMagmaRingModuloRelations( F, [ z, prod ] );
    return Objectify( F!.defaultType, prod );
    end );


#############################################################################
##
#M  \*( x, r )  . . . . . . . . . . .  for magma ring element and coefficient
##
##  Note that multiplication with zero or zero divisors
##  may cause zero coefficients in the result.
##  So we must normalize the elements.
#T  (But we can avoid the argument check)
#T  Should these two aspects be treated separately in general?
#T  Should multiplication with zero be avoided (store the zero)?
#T  Should the nonexistence of zero divisors be known/used?
##
BindGlobal( "ElmTimesRingElm", function( x, y )
    local F, i, prod, z;
    F:= FamilyObj( x );
    z:= ZeroCoefficient( x );
    x:= ShallowCopy( CoefficientsAndMagmaElements( x ) );
    for i in [ 2, 4 .. Length(x) ] do
      x[i]:= x[i] * y;
    od;
    prod:= NormalizedElementOfMagmaRingModuloRelations( F,
               [ z, FMRRemoveZero( x, z ) ] );
    return Objectify( F!.defaultType, prod );
end );

InstallMethod( \*,
    "for magma ring element, and ring element",
    IsMagmaRingsRings,
    [ IsElementOfMagmaRingModuloRelations, IsRingElement ],
    ElmTimesRingElm );

InstallMethod( \*,
    "for magma ring element, and rational",
    [ IsElementOfMagmaRingModuloRelations, IsRat ],
    ElmTimesRingElm );


#############################################################################
##
#M  \*( <r>, <x> )  . . . . . . . . .  for coefficient and magma ring element
#M  \*( <r>, <x> )  . . . . . . . . . . .  for integer and magma ring element
##
BindGlobal( "RingElmTimesElm", function( x, y )
    local F, i, prod, z;
    F:= FamilyObj( y );
    z:= ZeroCoefficient( y );
    y:= ShallowCopy( CoefficientsAndMagmaElements( y ) );
    for i in [ 2, 4 .. Length(y) ] do
      y[i]:= x * y[i];
    od;
    prod:= NormalizedElementOfMagmaRingModuloRelations( F,
               [ z, FMRRemoveZero( y, z ) ] );
    return Objectify( F!.defaultType, prod );
end );

InstallMethod( \*,
    "for ring element, and magma ring element",
    IsRingsMagmaRings,
    [ IsRingElement, IsElementOfMagmaRingModuloRelations ],
    RingElmTimesElm );

InstallMethod( \*,
    "for rational, and magma ring element",
    [ IsRat, IsElementOfMagmaRingModuloRelations ],
    RingElmTimesElm );


#############################################################################
##
#M  InverseOp( <x> )  . . . . . . . . for magma ring element in default repr.
##
InstallOtherMethod( InverseOp,
    "for magma ring element",
    [ IsElementOfMagmaRingModuloRelations ],
    function( x )
    local coeffs, inv1, inv2, one, R, B, T;

    coeffs:= CoefficientsAndMagmaElements( x );

    if IsEmpty( coeffs ) then
      # The zero element is not invertible.
      return fail;
    elif Length( coeffs ) = 2 then
      # Inverting a scalar multiple of a magma element
      # means to invert the scalar and the magma element.
      inv1:= Inverse( coeffs[1] );
      if inv1 = fail then
        return fail;
      fi;
      inv2:= Inverse( coeffs[2] );
      if inv2 = fail then
        return fail;
      fi;
      return Objectify( FamilyObj( x )!.defaultType,
                        [ ZeroCoefficient( x ), [ inv1, inv2 ] ] );
    fi;

    # An invertible element has an identity.
    one:= One( x );
    if one = fail then
      return fail;
    fi;

    # Get the necessary coefficient ring,
    # and a basis for the algebra spanned by `x'.
    coeffs:= coeffs{ [ 2, 4 .. Length( coeffs ) ] };
    if IsCyclotomicCollection( coeffs ) then
      R:= DefaultField( coeffs );
    else
      R:= DefaultRing( coeffs );
    fi;
    B:= Basis( FLMLORByGenerators( R, [ x ] ) );
    T:= StructureConstantsTable( B );

    # If `one' is not in the algebra spanned by `x' then there is no inverse.
    coeffs:= Coefficients( B, one );
    if coeffs = fail then
      return fail;
    fi;

    # Solve the equation system.
    one:= QuotientFromSCTable( T, coeffs, Coefficients( B, x ) );

    # If there is a solution then form the inverse.
    if one <> fail then
      one:= LinearCombination( B, one );
    fi;
    return one;
    end );


#############################################################################
##
#M  \* <m>, <x> )  . . . . . . . .  for magma element and magma ring element
#M  \*( <x>, <m> )  . . . . . . . .  for magma ring element and magma element
##
InstallMethod( \*,
    "for magma element and magma ring element",
    IsMagmasMagmaRings,
    [ IsMultiplicativeElement, IsElementOfMagmaRingModuloRelations ],
    function( m, x )
    local F, z;
    F:= FamilyObj( x );
    z:= ZeroCoefficient( x );
    x:= ZippedProduct( [ m, One( z ) ],
                       CoefficientsAndMagmaElements( x ),
                       z,
                       [ \*, \<, \+, \* ] );
    x:= NormalizedElementOfMagmaRingModuloRelations( F, [ z, x ] );
    return Objectify( F!.defaultType, x );
    end );

InstallMethod( \*,
    "for magma ring element and magma element",
    IsMagmaRingsMagmas,
    [ IsElementOfMagmaRingModuloRelations, IsMultiplicativeElement ],
    function( x, m )
    local F, z;
    F:= FamilyObj( x );
    z:= ZeroCoefficient( x );
    x:= ZippedProduct( CoefficientsAndMagmaElements( x ),
                       [ m, One( z ) ],
                       z,
                       [ \*, \<, \+, \* ] );
    x:= NormalizedElementOfMagmaRingModuloRelations( F,
            [ z, x ] );
    return Objectify( F!.defaultType, x );
    end );


#############################################################################
##
#M  \+( <m>, <x> )  . . . . . . . .  for magma element and magma ring element
#M  \+( <x>, <m> )  . . . . . . . .  for magma ring element and magma element
##
InstallOtherMethod( \+,
    "for magma element and magma ring element",
    IsMagmasMagmaRings,
    [ IsMultiplicativeElement, IsElementOfMagmaRingModuloRelations ],
    function( m, x )
    local F, z;
    F:= FamilyObj( x );
    z:= ZeroCoefficient( x );
    x:= ZippedSum( [ m, One( z ) ],
                   CoefficientsAndMagmaElements( x ),
                   z, [ \<, \+ ] );
    x:= NormalizedElementOfMagmaRingModuloRelations( F, [ z, x ] );
    return Objectify( F!.defaultType, x );
    end );

InstallOtherMethod( \+,
    "for magma ring element and magma element",
    IsMagmaRingsMagmas,
    [ IsElementOfMagmaRingModuloRelations, IsMultiplicativeElement ],
    function( x, m )
    local F, z;
    F:= FamilyObj( x );
    z:= ZeroCoefficient( x );
    x:= ZippedSum( CoefficientsAndMagmaElements( x ),
                   [ m, One( z ) ],
                   z, [ \<, \+ ] );
    x:= NormalizedElementOfMagmaRingModuloRelations( F, [ z, x ] );
    return Objectify( F!.defaultType, x );
    end );


#############################################################################
##
#M  \-( <x>, <m> )  . . . . . . . .  for magma ring element and magma element
#M  \-( <m>, <x> )  . . . . . . . .  for magma ring element and magma element
##
InstallOtherMethod( \-,
    "for magma ring element and magma element",
    IsMagmaRingsMagmas,
    [ IsElementOfMagmaRingModuloRelations, IsMultiplicativeElement ],
    function( x, m )
    local F, z;
    F:= FamilyObj( x );
    z:= ZeroCoefficient( x );
    return x - ElementOfMagmaRing( F, z, [ One( z ) ], [ m ] );
    end );

InstallOtherMethod( \-,
    "for magma ring element and magma element",
    IsMagmasMagmaRings,
    [ IsMultiplicativeElement, IsElementOfMagmaRingModuloRelations ],
    function( m, x )
    local F, z;
    F:= FamilyObj( x );
    z:= ZeroCoefficient( x );
    return ElementOfMagmaRing( F, z, [ One( z ) ], [ m ] ) - x;
    end );


#############################################################################
##
#M  \/( x, r )  . . . . . . . . . . .  for magma ring element and coefficient
##
BindGlobal( "ElmDivRingElm", function( x, y )
    local F, i, z;
    F:= FamilyObj( x );
    z:= ZeroCoefficient( x );
    x:= ShallowCopy( CoefficientsAndMagmaElements( x ) );
    for i in [ 2, 4 .. Length(x) ] do
      x[i]:= x[i] / y;
    od;
    return Objectify( F!.defaultType, [ z, x ] );
end );

InstallOtherMethod( \/,
    "for magma ring element, and ring element",
    IsMagmaRingsRings,
    [ IsElementOfMagmaRingModuloRelations, IsRingElement ],
    ElmDivRingElm );

InstallMethod( \/,
    "for magma ring element, and integer",
    [ IsElementOfMagmaRingModuloRelations, IsInt ],
    ElmDivRingElm );


#############################################################################
##
#M  OneOp( <elm> )
##
InstallMethod( OneOp,
    "for magma ring element",
    [ IsElementOfMagmaRingModuloRelations ],
    function( elm )
    local F, z;
    F:= FamilyObj( elm );
    if not IsBound( F!.oneMagma ) then
      return fail;
    fi;
    z:= ZeroCoefficient( elm );
    return Objectify( F!.defaultType, [ z, MakeImmutable([ F!.oneMagma, One( z ) ]) ] );
    end );


#############################################################################
##
#M  ZeroOp( <elm> )
##
InstallMethod( ZeroOp,
    "for magma ring element",
    [ IsElementOfMagmaRingModuloRelations ],
    x -> Objectify( FamilyObj(x)!.defaultType,
             [ ZeroCoefficient( x ), [] ] ) );


#############################################################################
##
##  2. methods for free magma rings
##


#############################################################################
##
#M  IsGroupRing( <RM> ) . . . . . . . . . . . . . . . . . for free magma ring
##
InstallMethod( IsGroupRing,
    "for free magma ring",
    [ IsFreeMagmaRing ],
    RM -> IsGroup( UnderlyingMagma( RM ) ) );


#############################################################################
##
#M  PrintObj( <MR> )  . . . . . . . . . . . . . . . . . for a free magma ring
##
InstallMethod( PrintObj,
    "for a free magma ring",
    [ IsFreeMagmaRing ],
    function( MR )
    Print( "FreeMagmaRing( ", LeftActingDomain( MR ), ", ",
                              UnderlyingMagma( MR ), " )" );
    end );


#############################################################################
##
#F  FreeMagmaRing( <R>, <M> )
##
InstallGlobalFunction( FreeMagmaRing, function( R, M )
    local filter,  # implied filter of all elements in the new domain
          F,       # family of magma ring elements
          one,     # identity of `R'
          zero,    # zero of `R'
          m,       # one element of `M'
          RM,      # free magma ring, result
          gens;    # generators of the magma ring

    # Check the arguments.
    if not IsRing( R ) or One( R ) = fail then
      Error( "<R> must be a ring with identity" );
    fi;

    # Construct the family of elements of our ring.
    if   IsMultiplicativeElementWithInverseCollection( M ) then
      filter:= IsMultiplicativeElementWithInverse;
    elif IsMultiplicativeElementWithOneCollection( M ) then
      filter:= IsMultiplicativeElementWithOne;
    else
      filter:= IsMultiplicativeElement;
    fi;
    if IsAssociativeElementCollection( M ) and
       IsAssociativeElementCollection( R ) then
      filter:= filter and IsAssociativeElement;
    fi;

    F:= NewFamily( "FreeMagmaRingObjFamily",
                   IsElementOfFreeMagmaRing,
                   filter );

    one:= One( R );
    zero:= Zero( R );

    F!.defaultType := NewType( F, IsMagmaRingObjDefaultRep );
    F!.familyRing  := FamilyObj( R );
    F!.familyMagma := FamilyObj( M );
    F!.zeroRing    := zero;
#T no !!

    # Set the characteristic.
    if HasCharacteristic( R ) or HasCharacteristic( FamilyObj( R ) ) then
      SetCharacteristic( F, Characteristic( R ) );
    fi;

    # Just taking `Representative( M )' doesn't work if generators are not
    # yet computed (we need them anyway below).
    m := GeneratorsOfMagma( M );
    if Length(m) > 0 then
      m := m[1];
    else
      m:= Representative( M );
    fi;
    if IsMultiplicativeElementWithOne( m ) then
      F!.oneMagma:= One( m );
#T no !!
    fi;

    # Make the magma ring object.
    if IsMagmaWithOne( M ) then
      RM:= Objectify( NewType( CollectionsFamily( F ),
                                   IsFreeMagmaRingWithOne
                               and IsAttributeStoringRep ),
                      rec() );
    else
      RM:= Objectify( NewType( CollectionsFamily( F ),
                                   IsFreeMagmaRing
                               and IsAttributeStoringRep ),
                      rec() );
    fi;

    # Set the necessary attributes.
    SetLeftActingDomain( RM, R );
    SetUnderlyingMagma(  RM, M );

    # Deduce useful information.
    if HasIsFinite( M ) then
      SetIsFiniteDimensional( RM, IsFinite( M ) );
    fi;
    if HasIsAssociative( M ) then
      if IsMagmaWithInverses( M ) then
        SetIsGroupRing( RM, IsGroup( M ) );
      fi;
      if HasIsAssociative( R ) then
        SetIsAssociative( RM, IsAssociative( R ) and IsAssociative( M ) );
      fi;
    fi;
    if HasIsCommutative( R ) and HasIsCommutative( M ) then
      SetIsCommutative( RM, IsCommutative( R ) and IsCommutative( M ) );
    fi;
    if HasIsWholeFamily( R ) and HasIsWholeFamily( M ) then
      SetIsWholeFamily( RM, IsWholeFamily( R ) and IsWholeFamily( M ) );
    fi;

    # Construct the generators.
    # To get meaningful generators,
    # we have to handle the case that the magma is trivial.
    if IsMagmaWithOne( M ) then

      gens:= GeneratorsOfMagmaWithOne( M );
      SetGeneratorsOfLeftOperatorRingWithOne( RM,
          List( gens,
                x -> ElementOfMagmaRing( F, zero, [ one ], [ x ] ) ) );
      if IsEmpty( gens ) then
        SetGeneratorsOfLeftOperatorRing( RM,
                [ ElementOfMagmaRing( F, zero, [ one ], [ One( M ) ] ) ] );
      fi;

      SetOne(F, One(RM));

    else

      SetGeneratorsOfLeftOperatorRing( RM,
          List( GeneratorsOfMagma( M ),
                x -> ElementOfMagmaRing( F, zero, [ one ], [ x ] ) ) );

    fi;
    SetZero(F, Zero(RM));

    # Return the ring.
    return RM;
end );


#############################################################################
##
#F  GroupRing( <R>, <G> )
##
InstallGlobalFunction( GroupRing, function( R, G )

    if not IsGroup( G ) then
      Error( "<G> must be a group" );
    fi;
    R:= FreeMagmaRing( R, G );
    SetIsGroupRing( R, true );
    return R;
end );


#############################################################################
##
#M  AugmentationIdeal( <RG> ) . . . . . . . . . . . . . for a free magma ring
##
InstallMethod( AugmentationIdeal,
    "for a free magma ring",
    [ IsFreeMagmaRing ],
    function( RG )
    local one, G, gens, I;
    one:= One( RG );
    if one = fail then
      TryNextMethod();
    fi;
    G:= UnderlyingMagma( RG );
    gens:= List( GeneratorsOfMagma( G ), g -> g - one );
    I:= TwoSidedIdealByGenerators( RG, gens );
    SetGeneratorsOfAlgebra( I, gens );
    return I;
    end );


#############################################################################
##
#R  IsCanonicalBasisFreeMagmaRingRep( <B> )
##
DeclareRepresentation( "IsCanonicalBasisFreeMagmaRingRep",
    IsCanonicalBasis and IsAttributeStoringRep,
    [ "zerovector" ] );


#############################################################################
##
#M  Coefficients( <B>, <v> )  . . . . . . for canon. basis of free magma ring
##
InstallMethod( Coefficients,
    "for canon. basis of a free magma ring, and a vector",
    IsCollsElms,
    [ IsCanonicalBasisFreeMagmaRingRep, IsElementOfFreeMagmaRing ],
    function( B, v )

    local coeffs,
          data,
          elms,
          i;

    data:= CoefficientsAndMagmaElements( v );
    coeffs:= ShallowCopy( B!.zerovector );
    elms:= EnumeratorSorted( UnderlyingMagma( UnderlyingLeftModule( B ) ) );
    for i in [ 1, 3 .. Length( data )-1 ] do
      coeffs[ Position( elms, data[i] ) ]:= data[i+1];
    od;
    return coeffs;
    end );


#############################################################################
##
#M  Basis( <RM> ) . . . . . . . . . . . . . . . . . . . for a free magma ring
##
InstallMethod( Basis,
    "for a free magma ring (delegate to `CanonicalBasis')",
    [ IsFreeMagmaRing ], CANONICAL_BASIS_FLAGS,
    CanonicalBasis );


#############################################################################
##
#M  CanonicalBasis( <RM> )  . . . . . . . . . . . . . . for a free magma ring
##
InstallMethod( CanonicalBasis,
    "for a free magma ring",
    [ IsFreeMagmaRing ],
    function( RM )

    local B, one, zero, F;

    F:= ElementsFamily( FamilyObj( RM ) );
    if not IsBound( F!.defaultType ) then
      TryNextMethod();
    fi;

    one  := One(  LeftActingDomain( RM ) );
    zero := Zero( LeftActingDomain( RM ) );

    B:= Objectify( NewType( FamilyObj( RM ),
                                IsFiniteBasisDefault
                            and IsCanonicalBasisFreeMagmaRingRep ),
                   rec() );

    SetUnderlyingLeftModule( B, RM );
    if IsFiniteDimensional( RM ) then
      SetBasisVectors( B,
          List( EnumeratorSorted( UnderlyingMagma( RM ) ),
                x -> ElementOfMagmaRing( F, zero, [ one ], [ x ] ) ) );
      B!.zerovector:= List( BasisVectors( B ), x -> zero );
      MakeImmutable( B!.zerovector );
    fi;

    return B;
    end );


#############################################################################
##
#M  IsFinite( <RM> )  . . . . . . . . . . . . . . . . . for a free magma ring
##
InstallMethod( IsFinite,
    "for a free magma ring",
    [ IsFreeMagmaRing ],
    RM ->     IsFinite( LeftActingDomain( RM ) )
          and IsFinite( UnderlyingMagma( RM ) ) );


#############################################################################
##
#M  IsFiniteDimensional( <RM> ) . . . . . . . . . . . . for a free magma ring
##
InstallMethod( IsFiniteDimensional,
    "for a free magma ring",
    [ IsFreeMagmaRing ],
    RM -> IsFinite( UnderlyingMagma( RM ) ) );


#############################################################################
##
#M  IsFiniteDimensional( <R> )  . .  for left module of free magma ring elms.
##
InstallMethod( IsFiniteDimensional,
    "for a left module of free magma ring elements",
    [ IsFreeLeftModule and IsElementOfFreeMagmaRingCollection
                       and HasGeneratorsOfLeftOperatorRing ],
    function( R )
    local gens;
    gens:= Concatenation( List( GeneratorsOfLeftOperatorRing( R ),
                                CoefficientsAndMagmaElements ) );
    gens:= gens{ [ 1, 3 .. Length( gens ) - 1 ] };
    if IsEmpty( gens ) or IsFinite( Magma( gens ) ) then
      return true;
    else
      TryNextMethod();
    fi;
    end );


#############################################################################
##
#M  Dimension( <RM> ) . . . . . . . . . . . . . . . . . for a free magma ring
##
InstallMethod( Dimension,
    "for a free magma ring",
    [ IsFreeMagmaRing ],
    RM -> Size( UnderlyingMagma( RM ) ) );


#############################################################################
##
#M  GeneratorsOfLeftModule( <RM> )  . . . . . . . . . . for a free magma ring
##
InstallMethod( GeneratorsOfLeftModule,
    "for a free magma ring",
    [ IsFreeMagmaRing ],
    function( RM )
    local F, one, zero;
    if IsFiniteDimensional( RM ) then
      F:= ElementsFamily( FamilyObj( RM ) );
      one:= One( LeftActingDomain( RM ) );
      zero:= Zero( LeftActingDomain( RM ) );
      return List( Enumerator( UnderlyingMagma( RM ) ),
                   m -> ElementOfMagmaRing( F, zero, [ one ], [ m ] ) );
    else
      Error( "<RM> is not finite dimensional" );
    fi;
    end );


#############################################################################
##
#M  Centre( <RM> )  . . . . . . . . . . . . . . . . . . . .  for a group ring
##
##  The centre of a group ring $RG$ of a finite group $G$ is the FLMLOR
##  over the centre of $R$ generated by the conjugacy class sums in $G$.
##
##  Note that this ring is clearly contained in the centre of $RG$.
##  On the other hand, if an element $x = \sum_{g \in G} r_g g$ lies in the
##  centre of $RG$ then $( r h ) \cdot x = x \cdot ( r h )$ for each
##  $r \in R$ and $h \in G$.
##  This means that
##  $\sum_{g \in G} (r r_g ) ( h g ) = \sum_{g \in G} (r_g r ) ( g h )$,
##  which means that for $k = h g_1 = g_2 h$, the coefficients on both sides,
##  which are $r r_{g_1} = r r_{h^{-1} k}$ and $r_{g_2} r = r_{k h^{-1}} r$,
##  must be equal.
##  Setting $r = 1$ forces $r_g$ to be constant on conjugacy classes of $G$,
##  and leaving $r$ arbitrary forces the coefficients to lie in the centre
##  of $R$.
##
InstallMethod( Centre,
    "for a group ring",
    [ IsGroupRing ],
    function( RG )

    local F,      # family of elements of `RG'
          one,    # identity of the coefficients ring
          zero,   # zero of the coefficients ring
          gens,   # list of (module) generators of the result
          c,      # loop over `ccl'
          elms,   # set of elements of a conjugacy class
          coeff;  # coefficients vector

    if not IsFiniteDimensional( RG ) then
      TryNextMethod();
    fi;
    F:= ElementsFamily( FamilyObj( RG ) );
    one:= One( LeftActingDomain( RG ) );
    zero:= Zero( LeftActingDomain( RG ) );
    gens:= [];
    for c in ConjugacyClasses( UnderlyingMagma( RG ) ) do
      elms:= EnumeratorSorted( c );
      coeff:= List( elms, x -> one );
      Add( gens, ElementOfMagmaRing( F, zero, coeff, elms ) );
    od;
    c:= FLMLORWithOne( Centre( LeftActingDomain( RG ) ), gens, "basis" );
    Assert( 1, IsAbelian( c ) );
    SetIsAbelian( c, true );
    return c;
    end );


#############################################################################
##
#M  \in( <r>, <RM> )  . . . . . . . . .  for ring element and free magma ring
##
InstallMethod( \in,
    "for ring element, and magma ring",
    IsElmsColls,
    [ IsElementOfMagmaRingModuloRelations, IsMagmaRingModuloRelations ],
    function( r, RM )
    r:= CoefficientsAndMagmaElements( r );
    if (    ForAll( [ 2, 4 .. Length( r ) ],
                    i -> r[i] in LeftActingDomain( RM ) )
        and ForAll( [ 1, 3 .. Length( r ) - 1 ],
                    i -> r[i] in UnderlyingMagma( RM ) ) ) then
      return true;
    elif IsFreeMagmaRing( RM ) then
      return false;
    else
      TryNextMethod();
    fi;
    end );


#############################################################################
##
#M  IsAssociative( <RM> ) . . . . . . . . . . . . . . . for a free magma ring
##
InstallMethod( IsAssociative,
    "for a free magma ring",
    [ IsFreeMagmaRing ],
    RM ->     IsAssociative( LeftActingDomain( RM ) )
          and IsAssociative( UnderlyingMagma( RM ) ) );


#############################################################################
##
#M  IsCommutative( <RM> ) . . . . . . . . . . . . . . . for a free magma ring
##
InstallMethod( IsCommutative,
    "for a free magma ring",
    [ IsFreeMagmaRing ],
    RM ->     IsCommutative( LeftActingDomain( RM ) )
          and IsCommutative( UnderlyingMagma( RM ) ) );


#############################################################################
##
#M  IsWholeFamily( <RM> ) . . . . . . . . . . . . . . . for a free magma ring
##
InstallMethod( IsWholeFamily,
    "for a free magma ring",
    [ IsFreeMagmaRing ],
    RM ->     IsWholeFamily( LeftActingDomain( RM ) )
          and IsWholeFamily( UnderlyingMagma( RM ) ) );


#############################################################################
##
#M  GeneratorsOfRing( <RM> )  . . . . . . . . . . . . . for a free magma ring
#M  GeneratorsOfRingWithOne( <RM> ) . . . . .  for a free magma ring-with-one
##
##  If the underlying magma has an identity and if we know ring generators
##  for the ring <R>, we take the left operator ring generators together
##  with the images of the ring generators under the natural embedding.
##
InstallMethod( GeneratorsOfRing,
    "for a free magma ring",
    [ IsFreeMagmaRing ],
    function( RM )
    local R, emb;
    R:= LeftActingDomain( RM );
    emb:= Embedding( R, RM );
    if emb = fail then
      TryNextMethod();
    else
      return Concatenation( GeneratorsOfLeftOperatorRing( RM ),
                            List( GeneratorsOfRing( R ),
                                  r -> ImageElm( emb, r ) ) );
    fi;
    end );

InstallMethod( GeneratorsOfRingWithOne,
    "for a free magma ring-with-one",
    [ IsFreeMagmaRingWithOne ],
    function( RM )
    local R, emb;
    R:= LeftActingDomain( RM );
    emb:= Embedding( R, RM );
    if emb = fail then
      TryNextMethod();
    else
      return Concatenation( GeneratorsOfLeftOperatorRingWithOne( RM ),
                            List( GeneratorsOfRingWithOne( R ),
                                  r -> ImageElm( emb, r ) ) );
    fi;
    end );


#############################################################################
##
#R  IsEmbeddingRingMagmaRing( <R>, <RM> )
##
DeclareRepresentation( "IsEmbeddingRingMagmaRing",
        IsSPGeneralMapping
    and IsMapping
    and IsInjective
    and RespectsAddition
    and RespectsZero
    and RespectsMultiplication
    and RespectsOne
    and IsAttributeStoringRep,
    [] );


#############################################################################
##
#M  Embedding( <R>, <RM> )  . . . . . . . . . . . . . for ring and magma ring
##
InstallMethod( Embedding,
    "for ring and magma ring",
    IsRingCollsMagmaRingColls,
    [ IsRing, IsFreeMagmaRing ],
    function( R, RM )

    local   emb;

    # Check that this is the right method.
    if Parent( R ) <> LeftActingDomain( RM ) then
      TryNextMethod();
    elif One( UnderlyingMagma( RM ) ) = fail then
      return fail;
    fi;

    # Make the mapping object.
    emb := Objectify( TypeOfDefaultGeneralMapping( R, RM,
                               IsEmbeddingRingMagmaRing ),
                      rec() );

    # Return the embedding.
    return emb;
    end );


InstallMethod( ImagesElm,
    "for embedding of ring into magma ring, and ring element",
    FamSourceEqFamElm,
    [ IsEmbeddingRingMagmaRing, IsRingElement ],
    function ( emb, elm )
    local F;
    F:= ElementsFamily( FamilyObj( Range( emb ) ) );
    return [ ElementOfMagmaRing( F, Zero( elm ), [ elm ],
                 [ One( UnderlyingMagma( Range( emb ) ) ) ] ) ];
    end );

InstallMethod( ImagesRepresentative,
    "for embedding of ring into magma ring, and ring element",
    FamSourceEqFamElm,
    [ IsEmbeddingRingMagmaRing, IsRingElement ],
    function ( emb, elm )
    local F;
    F:= ElementsFamily( FamilyObj( Range( emb ) ) );
    return ElementOfMagmaRing( F, Zero( elm ), [ elm ],
               [ One( UnderlyingMagma( Range( emb ) ) ) ] );
    end );


InstallMethod( PreImagesElm,
    "for embedding of ring into magma ring, and free magma ring element",
    FamRangeEqFamElm,
    [ IsEmbeddingRingMagmaRing, IsElementOfFreeMagmaRing ],
    function ( emb, elm )
    local R, extrep;
    R:= Range( emb );
    extrep:= CoefficientsAndMagmaElements( elm );
    if     Length( extrep ) = 2
       and extrep[1] = One( UnderlyingMagma( R ) ) then
      return [ extrep[2] ];
    else
      return [];
    fi;
    end );

InstallMethod( PreImagesRepresentative,
    "for embedding of ring into magma ring, and free magma ring element",
    FamRangeEqFamElm,
    [ IsEmbeddingRingMagmaRing, IsElementOfFreeMagmaRing ],
    function ( emb, elm )
    local R, extrep;
    R:= Range( emb );
    extrep:= CoefficientsAndMagmaElements( elm );
    if     Length( extrep ) = 2
       and extrep[1] = One( UnderlyingMagma( R ) ) then
      return extrep[2];
    else
      return fail;
    fi;
    end );


#############################################################################
##
#R  IsEmbeddingMagmaMagmaRing( <M>, <RM> )
##
DeclareRepresentation( "IsEmbeddingMagmaMagmaRing",
        IsSPGeneralMapping
    and IsMapping
    and IsInjective
    and RespectsMultiplication
    and IsAttributeStoringRep,
    [] );


#############################################################################
##
#F  Embedding( <M>, <RM> )  . . . . . . . . . . . .  for magma and magma ring
##
InstallMethod( Embedding,
    "for magma and magma ring",
    IsMagmaCollsMagmaRingColls,
    [ IsMagma, IsFreeMagmaRing ],
    function( M, RM )

    local   emb;

    # Check that this is the right method.
    if not IsSubset( UnderlyingMagma( RM ), M ) then
      TryNextMethod();
    fi;

    # Make the mapping object.
    emb := Objectify( TypeOfDefaultGeneralMapping( M, RM,
                               IsEmbeddingMagmaMagmaRing ),
                      rec() );

    if IsMagmaWithInverses( M ) then
      SetRespectsInverses( emb, true );
    elif IsMagmaWithOne( M ) then
      SetRespectsOne( emb, true );
    fi;

    # Return the embedding.
    return emb;
    end );


InstallMethod( ImagesElm,
    "for embedding of magma into magma ring, and mult. element",
    FamSourceEqFamElm,
    [ IsEmbeddingMagmaMagmaRing, IsMultiplicativeElement ],
    function ( emb, elm )
    local R, F;
    R:= Range( emb );
    F:= ElementsFamily( FamilyObj( R ) );
    return [ ElementOfMagmaRing( F, Zero( LeftActingDomain( R ) ),
                 [ One( LeftActingDomain( R ) ) ], [ elm ] ) ];
    end );

InstallMethod( ImagesRepresentative,
    "for embedding of magma into magma ring, and mult. element",
    FamSourceEqFamElm,
    [ IsEmbeddingMagmaMagmaRing, IsMultiplicativeElement ],
    function ( emb, elm )
    local R, F;
    R:= Range( emb );
    F:= ElementsFamily( FamilyObj( R ) );
    return ElementOfMagmaRing( F, Zero( LeftActingDomain( R ) ),
               [ One( LeftActingDomain( R ) ) ], [ elm ] );
    end );


InstallMethod( PreImagesElm,
    "for embedding of magma into magma ring, and free magma ring element",
    FamRangeEqFamElm,
    [ IsEmbeddingMagmaMagmaRing, IsElementOfFreeMagmaRing ],
    function ( emb, elm )
    local R, extrep;
    R:= Range( emb );
    extrep:= CoefficientsAndMagmaElements( elm );
    if     Length( extrep ) = 2
       and extrep[2] = One( LeftActingDomain( R ) ) then
      return [ extrep[1] ];
    else
      return [];
    fi;
    end );

InstallMethod( PreImagesRepresentative,
    "for embedding of magma into magma ring, and free magma ring element",
    FamRangeEqFamElm,
    [ IsEmbeddingMagmaMagmaRing, IsElementOfFreeMagmaRing ],
    function ( emb, elm )
    local R, extrep;
    R:= Range( emb );
    extrep:= CoefficientsAndMagmaElements( elm );
    if     Length( extrep ) = 2
       and extrep[2] = One( LeftActingDomain( R ) ) then
      return extrep[1];
    else
      return fail;
    fi;
    end );


#############################################################################
##
#M  ExtRepOfObj( <elm> )  . . . . . . . . . . . . . .  for magma ring element
##
##  The external representation of elements in a free magma ring is defined
##  as a list of length 2, the first entry being the zero coefficient,
##  the second being a zipped list containing the external representations
##  of the monomials and their coefficients.
##
InstallMethod( ExtRepOfObj,
    "for magma ring element",
#T eventually more specific!
#T allow this only if the magma elements have an external representation!
#T (make this explicit!)
    [ IsElementOfMagmaRingModuloRelations ],
    function( elm )
    local zero, i;
    zero:= ZeroCoefficient( elm );
    elm:= ShallowCopy( CoefficientsAndMagmaElements( elm ) );
    for i in [ 1, 3 .. Length( elm ) - 1 ] do
      elm[i]:= ExtRepOfObj( elm[i] );
    od;
    return [ zero, elm ];
    end );


#############################################################################
##
#M  ObjByExtRep( <Fam>, <descr> ) . . . . for free magma ring elements family
##
##  This is well-defined only if the magma elements of the free magma ring
##  have an external representation.
##
##  We need this mainly for free and f.p. algebras.
##
##  Note that <descr> must describe a *normalized* element (sorted w.r.t. the
##  magma elements, normalized w.r.t. the relations if there are some).
##
InstallMethod( ObjByExtRep,
    "for magma ring elements family, and list",
    [ IsElementOfMagmaRingModuloRelationsFamily, IsList ],
    function( Fam, descr )
    local FM, elm, i;
    FM:= ElementsFamily( Fam!.familyMagma );
    elm:= ShallowCopy( descr[2] );
    for i in [ 1, 3 .. Length( elm ) - 1 ] do
      elm[i]:= ObjByExtRep( FM, elm[i] );
    od;
    return Objectify( Fam!.defaultType, [ descr[1], elm ] );
    end );


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


#############################################################################
##
#M  NiceFreeLeftModuleInfo( <V> )
#M  NiceVector( <V>, <v> )
#M  UglyVector( <V>, <r> )
##
InstallHandlingByNiceBasis( "IsSpaceOfElementsOfMagmaRing", rec(
    detect := function( F, gens, V, zero )
      return IsElementOfMagmaRingModuloRelationsCollection( V );
      end,

    NiceFreeLeftModuleInfo := function( V )
      local gens,
            monomials,
            gen,
            list,
            i,
            zero,
            info;

      gens:= GeneratorsOfLeftModule( V );
      monomials:= [];

      for gen in gens do
        list:= CoefficientsAndMagmaElements( gen );
        for i in [ 1, 3 .. Length( list ) - 1 ] do
          AddSet( monomials, list[i] );
        od;
      od;

      zero:= Zero( V )![1];
      info:= rec( monomials := monomials,
                  zerocoeff := zero,
                  family    := ElementsFamily( FamilyObj( V ) ) );

      # For the zero row vector, catch the case of empty `monomials' list.
      if IsEmpty( monomials ) then
        info.zerovector := [ Zero( LeftActingDomain( V ) ) ];
      else
        info.zerovector := ListWithIdenticalEntries( Length( monomials ),
                                                     zero );
      fi;
      MakeImmutable( info.zerovector );

      return info;
      end,

    NiceVector := function( V, v )
      local info, c, monomials, i, pos;
      info:= NiceFreeLeftModuleInfo( V );
      c:= ShallowCopy( info.zerovector );
      v:= CoefficientsAndMagmaElements( v );
      monomials:= info.monomials;
      for i in [ 2, 4 .. Length( v ) ] do
        pos:= Position( monomials, v[ i-1 ] );
        if pos = fail then return fail; fi;
        c[ pos ]:= v[i];
      od;
      return c;
      end,

    UglyVector := function( V, r )
      local info;
      info:= NiceFreeLeftModuleInfo( V );
      if Length( r ) <> Length( info.zerovector ) then
        return fail;
      elif IsEmpty( info.monomials ) then
        if IsZero( r ) then
          return Zero( V );
        else
          return fail;
        fi;
      fi;
      return ElementOfMagmaRing( info.family, info.zerocoeff,
                 r, info.monomials );
      end ) );


#############################################################################
##
##  4. methods for free magma rings modulo the span of a ``zero'' element
##


#############################################################################
##
#F  MagmaRingModuloSpanOfZero( <R>, <M>, <z> )
##
InstallGlobalFunction( MagmaRingModuloSpanOfZero, function( R, M, z )

    local RM,         # result
          F,          # family of magma ring elements
          one,        # identity of `R'
          zero;       # zero of `R'

    # Construct the family of elements of our ring.
    F:= NewFamily( "MagmaRingModuloSpanOfZeroObjFamily",
                   IsElementOfMagmaRingModuloRelations );
    SetFilterObj( F, IsElementOfMagmaRingModuloSpanOfZeroFamily );

    one:= One( R );
    zero:= Zero( R );

    F!.defaultType := NewType( F, IsMagmaRingObjDefaultRep );
    F!.familyRing  := FamilyObj( R );
    F!.familyMagma := FamilyObj( M );
    F!.zeroRing    := zero;
#T no!
    F!.zeroOfMagma := z;

    # Do not set the characteristic since we do not know whether we are
    # 0-dimensional and the characteristic would then be 0.

    # Make the magma ring object.
    RM:= Objectify( NewType( CollectionsFamily( F ),
                                 IsMagmaRingModuloSpanOfZero
                             and IsAttributeStoringRep ),
                    rec() );

    # Store it in its elements family:
    F!.magmaring := RM;

    # Set the necessary attributes.
    SetLeftActingDomain( RM, R );
    SetUnderlyingMagma(  RM, M );

    # Deduce useful information.
    if HasIsFinite( M ) then
      SetIsFiniteDimensional( RM, IsFinite( M ) );
    fi;
    if HasIsWholeFamily( R ) and HasIsWholeFamily( M ) then
      SetIsWholeFamily( RM, IsWholeFamily( R ) and IsWholeFamily( M ) );
    fi;

    # Construct the generators.
    SetGeneratorsOfLeftOperatorRing( RM,
        List( GeneratorsOfMagma( M ),
              x -> ElementOfMagmaRing( F, zero, [ one ], [ x ] ) ) );

    # Return the ring.
    return RM;
end );


#############################################################################
##
#M  Characteristic( <A> )
#M  Characteristic( <algelm> )
#M  Characteristic( <algelmfam> )
##
##  (via delegations)
##
InstallMethod( Characteristic,
  "for an elements family of a magma ring quotient",
  [ IsElementOfMagmaRingModuloSpanOfZeroFamily ],
  function( fam )
    local A,one;
    A := fam!.magmaring;
    one := One(A);
    if Zero(A) = one then
        return 1;
    else
        return Characteristic(LeftActingDomain(A));
    fi;
  end );


#############################################################################
##
#M  NormalizedElementOfMagmaRingModuloRelations( <Fam>, <descr> )
#M                     . . . for a magma ring modulo the span of the ``zero''
##
##  <Fam> is a family of elements of a magma ring modulo the span of the
##  ``zero element'' of the magma.
##  <descr> is a list of the form `[ <z>, <list> ]', <z> being the zero
##  coefficient of the ring, and <list> being the list of monomials and
##  their coefficients.
##
##  The function returns the element described by <descr> in normal form,
##  that is, with zero coefficient of the ``zero element'' of the magma.
##
InstallMethod( NormalizedElementOfMagmaRingModuloRelations,
    "for family of magma rings modulo the span of ``zero'', and list",
    [ IsElementOfMagmaRingModuloSpanOfZeroFamily, IsList ],
    function( Fam, descr )

    local zeromagma, len, i;

    zeromagma:= Fam!.zeroOfMagma;
    len:= Length( descr[2] );
    for i in [ 1, 3 .. len - 1 ] do
      if descr[2][i] = zeromagma then
        descr:= [ descr[1], Concatenation( descr[2]{ [ 1 .. i-1 ] },
                                           descr[2]{ [ i+2 .. len ] } ) ];
        break;
      fi;
    od;

    MakeImmutable( descr );
    return descr;
    end );


#############################################################################
##
#M  IsFinite( <RM> )  . . . . . . . .  for magma ring modulo span of ``zero''
##
InstallMethod( IsFinite,
    "for a magma ring modulo the span of ``zero''",
    [ IsMagmaRingModuloSpanOfZero ],
    RM ->     IsFinite( LeftActingDomain( RM ) )
          and IsFinite( UnderlyingMagma( RM ) ) );


#############################################################################
##
#M  IsFiniteDimensional( <RM> ) . . .  for magma ring modulo span of ``zero''
##
InstallMethod( IsFiniteDimensional,
    "for a magma ring modulo the span of ``zero''",
    [ IsMagmaRingModuloSpanOfZero ],
    RM -> IsFinite( UnderlyingMagma( RM ) ) );


#############################################################################
##
#M  Dimension( <RM> ) . . . . . . . .  for magma ring modulo span of ``zero''
##
InstallMethod( Dimension,
    "for a magma ring modulo the span of ``zero''",
    [ IsMagmaRingModuloSpanOfZero ],
    RM -> Size( UnderlyingMagma( RM ) ) - 1 );


#############################################################################
##
#M  GeneratorsOfLeftModule( <RM> )  .  for magma ring modulo span of ``zero''
##
InstallMethod( GeneratorsOfLeftModule,
    "for a magma ring modulo the span of ``zero''",
    [ IsMagmaRingModuloSpanOfZero ],
    function( RM )
    local F, one, zero;
    if IsFiniteDimensional( RM ) then
      F:= ElementsFamily( FamilyObj( RM ) );
      one:= One( LeftActingDomain( RM ) );
      zero:= Zero( LeftActingDomain( RM ) );
      return List( Difference( AsSSortedList( UnderlyingMagma( RM ) ),
                               [ F!.zeroOfMagma ] ),
                   m -> ElementOfMagmaRing( F, zero, [ one ], [ m ] ) );
    else
      Error( "<RM> is not finite dimensional" );
    fi;
    end );


#############################################################################
##
##  5. methods for groups of free magma ring elements
##


#############################################################################
##
#M  IsGeneratorsOfMagmaWithInverses( <mgmringelms> )
##
##  Check that all elements are in fact invertible.
##
InstallMethod( IsGeneratorsOfMagmaWithInverses,
    "for a collection of free magma ring elements",
    [ IsElementOfMagmaRingModuloRelationsCollection ],
    mgmringelms -> ForAll( mgmringelms, x -> Inverse( x ) <> fail ) );

[ Verzeichnis aufwärts0.68unsichere Verbindung  Übersetzung europäischer Sprachen durch Browser  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge