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


Quelle  ringsc.gi   Sprache: unbekannt

 
#############################################################################
##
##  This file is part of GAP, a system for computational discrete algebra.
##  This file's authors include Alexander Hulpke.
##
##  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 methods for elements of rings, given as Z-modules with
##  structure constants for multiplication. It is based on algsc.gi
##


BindGlobal("SCRingReducedModuli",function(moduli,l)
local i;
  if not IsMutable(l) then l:=ShallowCopy(l);fi;
  for i in [1..Length(l)] do
    if moduli[i]<>0 then
      l[i]:=l[i] mod moduli[i];
    fi;
  od;
  return l;
end);

#############################################################################
##
#M  ObjByExtRep( <Fam>, <descr> ) . . . . . . . .  for s.~c. ring elements
##
##  Check whether the coefficients list <coeffs> has the right length,
##  and has integer entries bound by the moduli
##
InstallMethod( ObjByExtRep,
    "for s. c. ring elements family",
    [ IsSCRingObjFamily, IsHomogeneousList ],
    function( Fam, coeffs )
    if Length( coeffs ) <> Length( Fam!.names ) then
      Error( "<coeffs> must be a list of length ", Length( Fam!.names ) );
    elif not ForAll( [1..Length(coeffs)], IsInt ) and
      ForAll([1..Length(coeffs)],p->Fam!.moduli[p]=0 or
        (0<=coeffs[p] and coeffs[p]<Fam!.moduli[p])) then
      Error( "all in <coeffs> must be integers bounded by `moduli'" );
    fi;
    return Objectify( Fam!.defaultTypeDenseCoeffVectorRep,
                      [ Immutable( coeffs ) ] );
    end );

#############################################################################
##
#M  ExtRepOfObj( <elm> )  . . . . . . . . . . . .  for s.~c. ring elements
##
InstallMethod( ExtRepOfObj,
    "for s. c. ring element in dense coeff. vector rep.",
    [ IsSCRingObj and IsDenseCoeffVectorRep ], elm -> elm![1] );

#############################################################################
##
#M  Print( <elm> )  . . . . . . . . . . . . . . .  for s.~c. ring elements
##
InstallMethod( PrintObj,
    "for s. c. ring element",
    [ IsSCRingObj ],
    function( elm )

    local F,      # family of `elm'
          names,  # generators names
          moduli,
          len,    # dimension of the ring
          zero,   # zero element of the ring
          depth,  # first nonzero position in coefficients list
          i;      # loop over the coefficients list

    F     := FamilyObj( elm );
    names := F!.names;
    moduli:= F!.moduli;
    elm   := ExtRepOfObj( elm );
    len   := Length( elm );

    # Treat the case that the ring is trivial.
    if len = 0 then
      Print( "<zero of trivial s.c. ring>" );
      return;
    fi;

    depth := PositionNonZero( elm );

    if len < depth then

      # Print the zero element.
      # (Note that the unique element of a zero ring has a name.)
      Print( "0*", names[1] );

    else

      if elm[depth]<>1 and elm[depth]-moduli[depth] =-1 then
          Print("-");
      elif elm[ depth ] <> 1 then
        Print( elm[ depth ], "*" );
      fi;
      Print( names[ depth ] );

      for i in [ depth+1 .. len ] do
        if elm[i] <> 0 then
          if elm[i]=1 then
            Print( "+" );
          elif elm[i]-moduli[i] =-1 then
            Print("-");
          elif elm[i] <> 1 then
            Print("+", elm[i], "*" );
          fi;
          Print( names[i] );
        fi;
      od;
    fi;
end);

#############################################################################
##
#M  String( <elm> )  . . . . . . . . . . . . . . .  for s.~c. ring elements
##
InstallMethod( String, "for s. c. ring element", [ IsSCRingObj ],
function( elm )

    local s,      # string
          names,  # generators names
          moduli,
          len,    # dimension of the ring
          zero,   # zero element of the ring
          depth,  # first nonzero position in coefficients list
          i;      # loop over the coefficients list

    names := FamilyObj(elm)!.names;
    moduli:= FamilyObj(elm)!.moduli;
    elm   := ExtRepOfObj( elm );
    len   := Length( elm );

    # Treat the case that the ring is trivial.
    if len = 0 then
      return "<zero of trivial s.c. ring>";
    fi;

    depth := PositionNonZero( elm );

    if len < depth then

      # Print the zero element.
      # (Note that the unique element of a zero ring has a name.)
      return Concatenation( "0*", names[1] );

    else

      s:="";
      if elm[depth]<>1 and elm[depth]-moduli[depth] =-1 then
        Add(s,'-');
      elif elm[ depth ] <> 1 then
        Append(s,String(elm[ depth ]));
        Add(s,'*');
      fi;
      Append(s, names[ depth ] );

      for i in [ depth+1 .. len ] do
        if elm[i] <> 0 then
          if elm[i]=1 then
            Add(s,'+');
          elif elm[i]-moduli[i] =-1 then
            Add(s,'-');
          elif elm[i] <> 1 then
            Add(s,'+');
            Append(s,String( elm[i]));
            Add(s,'*');
          fi;
          Append(s, names[i] );
        fi;
      od;

  fi;
  return s;
end );

#############################################################################
##
#M  \=( <x>, <y> )  . . . . . . . . . . equality of two s.~c. ring objects
#M  \<( <x>, <y> )  . . . . . . . . . comparison of two s.~c. ring objects
#M  \+( <x>, <y> )  . . . . . . . . . . . .  sum of two s.~c. ring objects
#M  \-( <x>, <y> )  . . . . . . . . . difference of two s.~c. ring objects
#M  \*( <x>, <y> )  . . . . . . . . . .  product of two s.~c. ring objects
#M  Zero( <x> ) . . . . . . . . . . . . . .  zero of an s.~c. ring element
#M  AdditiveInverse( <x> )  . .  additive inverse of an s.~c. ring element
#M  Inverse( <x> )  . . . . . . . . . . . inverse of an s.~c. ring element
##
InstallMethod( \=,
    "for s. c. ring elements in dense vector rep.",
    IsIdenticalObj,
    [ IsSCRingObj and IsDenseCoeffVectorRep,
      IsSCRingObj and IsDenseCoeffVectorRep ],
    function( x, y ) return x![1] = y![1]; end );

InstallMethod( \<,
    "for s. c. ring elements in dense vector rep.",
    IsIdenticalObj,
    [ IsSCRingObj and IsDenseCoeffVectorRep,
      IsSCRingObj and IsDenseCoeffVectorRep ], 0,
    function( x, y ) return x![1] < y![1]; end );

InstallMethod( \+,
    "for s. c. ring elements in dense vector rep.",
    IsIdenticalObj,
    [ IsSCRingObj and IsDenseCoeffVectorRep,
      IsSCRingObj and IsDenseCoeffVectorRep ],
function( x, y )
  local fam;
  fam:=FamilyObj(x);
  return Objectify( fam!.defaultTypeDenseCoeffVectorRep,
            [ Immutable( SCRingReducedModuli(fam!.moduli,x![1]+y![1])) ] );
end );

InstallMethod( \-,
    "for s. c. ring elements in dense vector rep.",
    IsIdenticalObj,
    [ IsSCRingObj and IsDenseCoeffVectorRep,
      IsSCRingObj and IsDenseCoeffVectorRep ],
function( x, y )
local fam;
  fam:=FamilyObj(x);
  return Objectify( fam!.defaultTypeDenseCoeffVectorRep,
            [ Immutable( SCRingReducedModuli(fam!.moduli,x![1]-y![1])) ] );
end );

InstallMethod( \*,
    "for s. c. ring elements in dense vector rep.",
    IsIdenticalObj,
    [ IsSCRingObj and IsDenseCoeffVectorRep,
      IsSCRingObj and IsDenseCoeffVectorRep ],
    function( x, y )
local fam;
  fam:= FamilyObj( x );
  return Objectify( fam!.defaultTypeDenseCoeffVectorRep,
            [ Immutable( SCRingReducedModuli(fam!.moduli,
                        SCTableProduct( fam!.sctable, x![1], y![1] ) )) ] );
  end );

InstallMethod( \*,
    "for integer and s. c. ring element in dense vector rep.",
    IsCoeffsElms,
    [ IsInt, IsSCRingObj and IsDenseCoeffVectorRep ],
function( x, y )
local fam;
  fam:=FamilyObj(y);
  return Objectify( fam!.defaultTypeDenseCoeffVectorRep,
            [ Immutable( SCRingReducedModuli(fam!.moduli,x*y![1])) ] );
end );

InstallMethod( \*,
    "for s. c. ring element in dense vector rep. and integer",
    IsElmsCoeffs,
    [ IsSCRingObj and IsDenseCoeffVectorRep, IsInt ],
function( x, y )
local fam;
  fam:=FamilyObj(x);
  return Objectify( fam!.defaultTypeDenseCoeffVectorRep,
            [ Immutable( SCRingReducedModuli(fam!.moduli,x![1]*y)) ] );
end );

InstallMethod( ZeroOp, "for s. c. ring element", [ IsSCRingObj ],
function( x )
local fam;
  fam:=FamilyObj(x);
  return Objectify( fam!.defaultTypeDenseCoeffVectorRep,
            [ Immutable( SCRingReducedModuli(fam!.moduli,0*x![1])) ] );
end );

InstallMethod( AdditiveInverseOp, "for s. c. ring element", [ IsSCRingObj ],
function( x )
local fam;
  fam:=FamilyObj(x);
  return Objectify( fam!.defaultTypeDenseCoeffVectorRep,
            [ Immutable( SCRingReducedModuli(fam!.moduli,-x![1])) ] );
end );

InstallMethod( OneOp, "for s. c. ring element", [ IsSCRingObj ],
function( x )
local fam,r;
  fam:=FamilyObj(x);
  r:=fam!.fullSCRing;
  return One(r);
end );

InstallMethod( InverseOp, "for s. c. ring element", [ IsSCRingObj ],
function( x )
local fam,r,w,l,o;
  fam:=FamilyObj(x);
  r:=fam!.fullSCRing;
  if One(r)=fail then return fail;fi;
  if IsFinite(r) then
    r:=Filtered(AsSSortedList(r),y->x*y=One(r) and y*x=One(r));
    if Length(r)>0 then
      return r[1];
    else
      return fail;
    fi;
  else
    o:=One(r);
    if x=o then return x;fi;
    # try powering
    w:=x;
    l:=[w];
    repeat
      w:=w*x;
      if w=o then
        # last entry was inverse
        return Last(l);
      fi;
      if w in l then
        # loop without inverse -- not invertible
        return fail;
      fi;
      Add(l,w);
    until Length(l)>10^6;
    Error("cannot find inverse");
  fi;
end );

#############################################################################
##
#F  RingByStructureConstants( <moduli>, <sctable> )
#F  RingByStructureConstants( <moduli>, <sctable>, <name> )
#F  RingByStructureConstants( <moduli>, <sctable>, <names> )
#F  RingByStructureConstants( <moduli>, <sctable>, <name1>, <name2>, ... )
##
##  is an Z-module $M$ defined by the structure constants
##  table <sctable> of length $n$.
##
##  The generators of $M$ are linearly independent abstract space generators
##  $x_1, x_2, \ldots, x_n$ whose additive orders is given by the list
##  <moduli>.  They are multiplied according to the formula
##  $ x_i x_j = \sum_{k=1}^n c_{ijk} x_k$
##  where `$c_{ijk}$ = <sctable>[i][j][1][i_k]'
##  and `<sctable>[i][j][2][i_k] = k'.
##
InstallGlobalFunction( RingByStructureConstants, function( arg )
    local T,      # structure constants table
          n,      # dimensions of structure matrices
          moduli, # additive orders of generators
          names,  # names of the ring generators
          Fam,    # the family of ring elements
          A,      # the ring, result
          filter,
          gens;   # ring generators of `A'

    # Check the argument list.
    if not 1 < Length( arg ) and IsList( arg[1] )
                                 and Length(arg[1])>0
                                 and IsList( arg[2] ) then
      Error( "usage: RingByStructureConstants([<moduli>,<sctable>]) or \n",
             "RingByStructureConstants([<moduli>,<sctable>,<name1>,...])" );
    fi;

    moduli := arg[1];
    n:=Length(moduli);
    T    := Immutable(arg[2]);

    # Construct names of generators (used for printing only).
    if   Length( arg ) = 2 then
      names:= List( [ 1 .. n ],
                    x -> Concatenation( "r.", String(x) ) );
      MakeImmutable( names );
    elif Length( arg ) = 3 and IsString( arg[3] ) then
      names:= List( [ 1 .. n ],
                    x -> Concatenation( arg[3], String(x) ) );
      MakeImmutable( names );
    elif Length( arg ) = 3 and IsHomogeneousList( arg[3] )
                               and Length( arg[3] ) = n
                               and ForAll( arg[3], IsString ) then
      names:= Immutable( arg[3] );
    elif Length( arg ) = 2 + n then
      names:= Immutable( arg{ [ 3 .. Length( arg ) ] } );
    else
      Error( "usage: RingByStructureConstants([<moduli>,<sctable>]) or \n",
             "RingByStructureConstants([<moduli>,<sctable>,<name1>,...])" );
    fi;

    filter:= IsSCRingObj and IsAdditivelyCommutativeElement;

    # Construct the family of elements of our ring.
    Fam:= NewFamily( "SCRingObjFamily", filter );

#X    # If the elements family of `R' has a uniquely determined zero element,
#X    # then all coefficients in this family are admissible.
#X    # Otherwise only coefficients from `R' itself are allowed.
#X    if Zero( ElementsFamily( FamilyObj( R ) ) ) <> fail then
#X      SetFilterObj( Fam, IsFamilyOverFullCoefficientsFamily );
#X    else
#X      Fam!.coefficientsDomain:= R;
#X    fi;

    Fam!.moduli    := moduli;
    Fam!.sctable   := T;
    Fam!.names     := names;

    # Construct the default type of the family.
    Fam!.defaultTypeDenseCoeffVectorRep :=
        NewType( Fam, IsSCRingObj and IsDenseCoeffVectorRep );

    SetCoefficientsFamily( Fam, ElementsFamily( FamilyObj( Integers ) ) );

    # Make the generators and the ring.
    SetZero( Fam, ObjByExtRep( Fam, List( [ 1 .. n ], x -> 0 ) ) );
    gens:= Immutable( List( IdentityMat( n, Integers ),
                            x -> ObjByExtRep( Fam, x ) ) );
    A:= RingByGenerators( gens );
    SetIsWholeFamily(A,true);

    if Length(moduli)=0 then
      SetSize(A,1);
    elif Product(moduli)=0 then
      SetSize(A,infinity);
    else
      SetSize(A,Product(moduli));
    fi;
#X    Fam!.basisVectors:= gens;

    # Store the ring in the family of the elements,
    # for accessing the full ring, e.g., in `DefaultFieldOfMatrixGroup'.
    Fam!.fullSCRing:= A;

    SetRepresentative(A,Zero(A));

    # if there is only 1 generator, the `One' - if any - can be obtained easily
    if Length(moduli)=1 then
      n:=ExtRepOfObj(gens[1]^2)[1];
      if moduli[1]=0 and n=1 then
        n:=ObjByExtRep(Fam,[1]);
        SetOne(Fam,n);
        SetOne(A,n);
      elif moduli[1]=0 and n=-1 then
        n:=ObjByExtRep(Fam,[-1]);
        SetOne(Fam,n);
        SetOne(A,n);
      elif moduli[1]>1 and Gcd(n,moduli[1])=1 then
        n:=1/n mod moduli[1];
        n:=ObjByExtRep(Fam,[n]);
        SetOne(Fam,n);
        SetOne(A,n);
      fi;
    fi;

    # Return the ring.
    return A;
end );

InstallAccessToGenerators( IsSubringSCRing and IsWholeFamily,
                           "whole SC ring", GeneratorsOfRing );

BindGlobal("SCRingElmSift",function(moduli,l,pivots,e,test)
local i, j, q;
  #e:=SCRingReducedModuli(moduli,e);
  if Length(l)=0 then
    if test=true then
      return IsZero(e);
    else
      return e;
    fi;
  fi;

  i:=1;
  while i<=Length(e) do
    if e[i]<>0 then
      # find corresponding pivot
      if IsBound(pivots[i]) then
        j:=pivots[i];
        # reduce
        q:=e[i]/l[j][i];
        if IsInt(q) then
          # can reduce completely
          e:=e-q*l[j];
          e:=SCRingReducedModuli(moduli,e);
        else
          ## cannot eliminate
          #if test=true then return false;fi;
          e:=e-Int(q)*l[j];
          e:=SCRingReducedModuli(moduli,e);
          if test=0 and e[i]<>0 then
            # stop after first nonzero reduction
            return e;
          fi;
        fi;
#      else
#       # no pivot -- not in
#       if test=true then
#          Error("GNU");
#         return false;
#       elif test=0 then
#         # element will give new pivot
#         return e;
#       fi;
      fi;
    fi;
    i:=i+1;
  od;
  if test=true then return IsZero(e);fi;
  return e;
end);

BindGlobal("SCRingElmSiftImages",function(moduli,l,imgs,pivots,e,ei)
local i, j, q;
  if Length(l)=0 then
    return [e,ei];
  fi;

  i:=1;
  while i<=Length(e) do
    if e[i]<>0 then
      # find corresponding pivot
      if IsBound(pivots[i]) then
        j:=pivots[i];
        # reduce
        q:=e[i]/l[j][i];
        if IsInt(q) then
          # can reduce completely
          e:=e-q*l[j];
          e:=SCRingReducedModuli(moduli,e);
          ei:=ei-q*imgs[j];
        else
          # cannot eliminate
          e:=e-Int(q)*l[j];
          e:=SCRingReducedModuli(moduli,e);
          ei:=ei-Int(q)*imgs[j];
          # stop after first reduction
          if e[i]<>0 then
            return [e,ei];
          fi;
        fi;
#      else
#       # no pivot -- not in
#       # element will give new pivot
#       return [e,ei];
      fi;
    fi;
    i:=i+1;
  od;
  return [e,ei];
end);

BindGlobal("SCRHNFExtend",function(moduli,l,pivots,e,imgs,ei)
local p, j, f, fj, g, q, gj, m, k, i;
  if not IsMutable(l) then l:=ShallowCopy(l);fi;
  if not IsMutable(pivots) then pivots:=ShallowCopy(pivots);fi;
  repeat
    if imgs=false then
      e:=SCRingElmSift(moduli,l,pivots,e,0);
      ei:=0;
    else
      e:=SCRingElmSiftImages(moduli,l,imgs,pivots,e,ei);
      ei:=e[2];
      e:=e[1];
    fi;

    #p:=PositionNonZero(e);
    # find the position of largest order
    p:=-1;
    f:=1;
    for j in [1..Length(moduli)] do
      if e[j]<>0 then
        g:=moduli[j]/Gcd(moduli[j],e[j]); # local order
        if g>f then
          f:=g;
          p:=j;
        fi;
      fi;
    od;

    if p>0 and IsBound(pivots[p]) then
      # reduction occurred at pivot element -- need to reduce further
      j:=pivots[p];
      f:=l[j];
      if imgs<>false then
        fj:=imgs[j];
      else
        fj:=0;
      fi;
      repeat
        g:=f;
        f:=e;
        q:=QuoInt(g[p],f[p]);
        e:=g-q*f;
        if imgs<>false then
          gj:=fj;
          fj:=ei;
          ei:=gj-q*fj;
        fi;
        e:=SCRingReducedModuli(moduli,e);
      until e[p]=0;

      #modify l
      if f[p]<0 then f:=-f;fj:=-fj;fi;
      # clean out f
      for k in [p+1..Length(moduli)] do
        if IsBound(pivots[k]) then
          q:=QuoInt(f[k],l[pivots[k]][k]);
          f:=SCRingReducedModuli(moduli,f-q*l[pivots[k]]);
          if imgs<>false then
            fj:=fj-q*imgs[pivots[k]];
          fi;
        fi;
      od;

      #Print("Set l[",j,"]:=",f," at ",p,"\n");
      l[j]:=f;
      if imgs<>false then
        imgs[j]:=f;
      fi;
      # clean out above
      for i in [1..j-1] do
        for k in [p..Length(moduli)] do
          if IsBound(pivots[k]) then
            q:=QuoInt(l[i][k],l[pivots[k]][k]);
            l[i]:=SCRingReducedModuli(moduli,l[i]-q*l[pivots[k]]);
            if imgs<>false then
              imgs[i]:=imgs[i]-q*imgs[pivots[k]];
            fi;
          fi;
        od;
      od;
    fi;
  until IsZero(e) or not IsBound(pivots[p]);

  if not IsZero(e) then
    # reduce modulo:
    if moduli[p]>0 then
      m:=Gcdex(e[p],moduli[p]);
      e:=e*m.coeff1;
      e:=SCRingReducedModuli(moduli,e);
      if imgs<>false then
        ei:=ei*m.coeff1;
      fi;
    fi;

    if e[p]<0 then e:=-e;ei:=-ei;fi;
    # find last known pivot before p
    j:=p-1;
    while j>0 and not IsBound(pivots[j]) do
      j:=j-1;
    od;
    if j>0 then
      j:=pivots[j];
    fi;
    # adjust pivots for insertion
    for i in [1..Length(pivots)] do
      if IsBound(pivots[i]) and pivots[i]>=j+1 then
        pivots[i]:=pivots[i]+1;
      fi;
    od;
    pivots[p]:=j+1;
    # clean out l[1..j]
    m:=[];
    gj:=[];
    for i in [1..j] do
      q:=QuoInt(l[i][p],e[p]);
      Add(m,SCRingReducedModuli(moduli,l[i]-q*e));
      if imgs<>false then
        Add(gj,imgs[i]-q*ei);
      fi;
    od;
    l:=Concatenation(m,[e],l{[j+1..Length(l)]});
    if imgs<>false then
      imgs:=Concatenation(gj,[ei],imgs{[j+1..Length(imgs)]});
    fi;
  fi;
  return [l,pivots,imgs];
end);

InstallMethod(StandardGeneratorsSubringSCRing,
  "for sc rings and their subrings",
  [IsSubringSCRing],
function(R)
local fam, l, piv, m, new, i, j, p;
  fam:=ElementsFamily(FamilyObj(R));
  l:=[];piv:=[];
  for i in GeneratorsOfRing(R) do
    m:=SCRHNFExtend(fam!.moduli,l,piv,ExtRepOfObj(i),false,false);
    l:=m[1];piv:=m[2];
  od;

  repeat
    new:=false;
    i:=1;
    while new=false and i<=Length(l) do
      j:=1;
      while new=false and j<=Length(l) do
        p:=ExtRepOfObj(ObjByExtRep(fam,l[i])*ObjByExtRep(fam,l[j]));
        m:=SCRHNFExtend(fam!.moduli,l,piv,p,false,false);
        new:=Length(m[1])>Length(l) or m[1]<>l;
        l:=m[1];piv:=m[2];

        j:=j+1;
      od;
      i:=i+1;
    od;
  until new=false;

  #RREF
  if Length(l)>1 then
    for i in [1..Length(piv)] do
      if IsBound(piv[i]) then
        for j in Difference([1..Length(l)],[piv[i]]) do
          p:=QuoInt(l[j][i],l[piv[i]][i]);
          if p>0 then
            l[j]:=l[j]-p*l[piv[i]];
          fi;
        od;
      fi;
    od;
  fi;

  return [l,piv,List(l,i->ObjByExtRep(fam,i))];
end);

BindGlobal("StandardGeneratorsImagesSubringSCRing",
function(fam,gens,imgs)
local l, piv, li, m, new, i, j, p, q;
  l:=[];piv:=[];li:=[];
  for i in [1..Length(gens)] do
    m:=SCRHNFExtend(fam!.moduli,l,piv,ExtRepOfObj(gens[i]),li,imgs[i]);
    l:=m[1];piv:=m[2];li:=m[3];
  od;
  repeat
    new:=false;
    i:=1;
    while new=false and i<=Length(l) do
      j:=1;
      while new=false and j<=Length(l) do
        p:=ExtRepOfObj(ObjByExtRep(fam,l[i])*ObjByExtRep(fam,l[j]));
        q:=li[i]*li[j];
        m:=SCRHNFExtend(fam!.moduli,l,piv,p,li,q);
        new:=Length(m[1])>Length(l);
        l:=m[1];piv:=m[2];li:=m[3];
        j:=j+1;
      od;
      i:=i+1;
    od;
  until new=false;
  return [l,piv,List(l,i->ObjByExtRep(fam,i)),li];
end);

# s is ``standard generators'' entry, e an element, return coefficients
BindGlobal("SCRingDecompositionStandardGens",function(s,e)
  local moduli, c, p, x, i;
  moduli:=FamilyObj(e)!.moduli;
  e:=ExtRepOfObj(e);
  c:=ListWithIdenticalEntries(Length(s[1]),0);
  for i in [1..Length(moduli)] do
    if e[i]<>0 then
      if not IsBound(s[2][i]) then
        Error("element does not lie in ring");
      fi;
      p:=s[2][i];
      if moduli[i]<>0 then
        x:=e[i]/s[1][p][i] mod moduli[i];
      else
        x:=e[i]/s[1][p][i];
      fi;
      c[p]:=x;
      e:=e-x*s[1][p];
      e:=SCRingReducedModuli(moduli,e);
    fi;
  od;
  return c;
end);

InstallMethod(Characteristic,
  "for sc rings and their subrings",
  [IsSubringSCRing and HasGeneratorsOfRing],
function(R)
  local fam, s, moduli, ind, ords, o, i;
  fam:=ElementsFamily(FamilyObj(R));
  s:=StandardGeneratorsSubringSCRing(R);

  # are there generators of infinite order?
  moduli:=fam!.moduli;
  ind:=Filtered([1..Length(moduli)],i->moduli[i]=0);
  if ForAny(s,i->ForAny(ind,x->i[x]<>0)) then
    SetSize(R,infinity);
    return 0;
  fi;

  # get additive order for each generator
  ords:=[];
  for i in s[1] do
    ind:=Filtered([1..Length(moduli)],x->i[x]<>0);
    o:=Lcm(List(ind,x->moduli[x]/Gcd(moduli[x],i[x])));
    Add(ords,o);
  od;
  SetSize(R,Product(ords));
  return Lcm(ords);
end);

InstallMethod(Size,
  "for sc rings and their subrings",
  [IsSubringSCRing and HasGeneratorsOfRing],
function(R)
  local fam, s, moduli, ind, ords, o, i;
  fam:=ElementsFamily(FamilyObj(R));
  s:=StandardGeneratorsSubringSCRing(R);

  # are there generators of infinite order?
  moduli:=fam!.moduli;
  ind:=Filtered([1..Length(moduli)],i->moduli[i]=0);
  if ForAny(s,i->ForAny(ind,x->i[x]<>0)) then
    SetCharacteristic(R,0);
    return infinity;
  fi;

  # get additive order for each generator
  ords:=[];
  for i in s[1] do
    ind:=Filtered([1..Length(moduli)],x->i[x]<>0);
    o:=Lcm(List(ind,x->moduli[x]/Gcd(moduli[x],i[x])));
    Add(ords,o);
  od;
  if Length(ords)=0 then
    ords:=[1];
  else
    SetCharacteristic(R,Lcm(ords));
  fi;
  return Product(ords);
end);

InstallMethod(\in,"SC Rings",IsElmsColls,
  [IsSCRingObj,IsSubringSCRing and HasGeneratorsOfRing],
function(e,r)
local fam,s;
  fam:=FamilyObj(e);
  s:=StandardGeneratorsSubringSCRing(r);
  return SCRingElmSift(fam!.moduli,s[1],s[2],ExtRepOfObj(e),true);
end);

BindGlobal("SCRingGroupInFamily",function(fam)
  local m, a, pcgs, rcgs, x, c, p, e, i,o;
  m:=fam!.moduli;
  if 0 in m then
    return fail;
  elif not IsBound(fam!.group) then
    a:=AbelianGroup(m);
    # translate pcgs generators to ring elements
    pcgs:=FamilyPcgs(a);
    rcgs:=[];
    for i in [1..Length(GeneratorsOfGroup(a))] do
      x:=GeneratorsOfGroup(a)[i];
      c:=1;
      while not IsOne(x) do
        p:=Position(pcgs,x);
        e:=ListWithIdenticalEntries(Length(m),0);
        e[i]:=c;
        rcgs[p]:=ObjByExtRep(fam,e);
        o:=RelativeOrders(pcgs)[p];
        x:=x^o;
        c:=c*o;
      od;
    od;
    fam!.group:=a;
    fam!.rcgs:=rcgs;
  fi;
  return fam!.group;
end);

BindGlobal("SCRingGroupElement",function(fam,e)
  local a, w, i;
  a:=SCRingGroupInFamily(fam);
  e:=ExponentsOfPcElement(FamilyPcgs(a),e);
  w:=Zero(fam);
  for i in [1..Length(e)] do
    w:=w+e[i]*fam!.rcgs[i];
  od;
  return w;
end);

InstallOtherMethod(One,"for finite SC Rings",
  [IsRing],0,
  #{} -> -RankFilter(IsRing),
function(R)
  if not (IsSubringSCRing(R) and IsFinite(R)) then
    TryNextMethod();
  fi;
  #T should be better code for SC rings by solving an equation
  return First(Enumerator(R),i->i=i*i and i<>i+i and
      ForAll(Enumerator(R),j->i*j=j and j*i=j));
end);

InstallOtherMethod(One,"for SC Rings -- try generators",
  [IsRing],0,
function(R)
  local l,a;
  if not IsSubringSCRing(R) then
    TryNextMethod();
  fi;
  l:=GeneratorsOfRing(R);
  a:=First(l,x->ForAll(l,y->x*y=y and y*x=y));
  if a=fail then
    TryNextMethod();
  else
    return a;
  fi;
end);

InstallOtherMethod(OneOp,"for finite SC Rings family",
  [IsSCRingObjFamily],0,
  #{} -> -RankFilter(IsRing),
function(fam)
local R;
  R:=fam!.fullSCRing;
  return One(R);
end);

InstallOtherMethod(IsUnit,"for finite Rings",
  IsCollsElms,[IsRing,IsScalar],0,
function(R,e)
local o,pow,a;
  if not IsFinite(R) then
    TryNextMethod();
  fi;
  if IsAssociative(R) and One(R) <> fail then
    # compute powers of e until we reach one or repeat
    o:=One(R);
    pow:=[];
    a:=e;
    repeat
      Add(pow,a);
      a:=a*e;
      if a=o then
        # power is one. So previous power is inverse
        return true;
      fi;
    until a in pow;
    # repeats without hitting the one element, cannot be a unit
    return false;
  fi;
  return One(R)<>fail
         and ForAny(Enumerator(R),x->x*e=One(R) and e*x=One(R));
end);

InstallMethod(Subrings,"for SC Rings",[IsSubringSCRing],
function(R)
  local fam, a, u, sr, g, l, piv, m, test, x, y, e, t, s, i;
  fam:=ElementsFamily(FamilyObj(R));
  a:=SCRingGroupInFamily(fam);
  # construct all subgroups
  m:=StandardGeneratorsSubringSCRing(R);
  a:=Subgroup(a,List(m[1],i->LinearCombinationPcgs(GeneratorsOfGroup(a),i)));
  u:=List(ConjugacyClassesSubgroups(a),Representative);
  sr:=[];
  #test which ones are a subring
  for s in u do
    g:=List(GeneratorsOfGroup(s),x->SCRingGroupElement(fam,x));
    l:=[];piv:=[];
    for i in g do
      m:=SCRHNFExtend(fam!.moduli,l,piv,ExtRepOfObj(i),false,false);
      l:=m[1];piv:=m[2];
    od;
    test:=true;
    x:=1;
    while test and x<=Length(g) do
      y:=1;
      while test and y<=Length(g) do
        e:=ExtRepOfObj(g[x]*g[y]);
        test:=SCRingElmSift(fam!.moduli,l,piv,e,true);
        y:=y+1;
      od;
      x:=x+1;
    od;
    if test then
      #workaround
      if Length(g)=0 then g:=[Zero(fam)];fi;
      t:=Subring(R,g);
      SetSize(t,Size(s));
      Add(sr,t);
      #Print("Added size ",Size(s),": ",g,"\n");
    else
      #Print("Discarded size ",Size(s),": ",g,"\n");
    fi;
  od;
  return sr;
end);

#############################################################################
##
#M  IsLeftIdealOp( <A>, <S> )
##
InstallOtherMethod( IsLeftIdealOp, "for SCRings", IsIdenticalObj,
    [ IsSubringSCRing, IsSubringSCRing ], 0,
function( A, S )
local gens, a, i;
  if not IsSubset( A, S ) then
    return false;
  fi;

  gens:=StandardGeneratorsSubringSCRing(S)[3];
  for a in GeneratorsOfRing( A ) do
    for i in gens do
      if not a * i in S then
        return false;
      fi;
    od;
  od;
  return true;
end );

#############################################################################
##
#M  IsRightIdealOp( <A>, <S> )
##
InstallOtherMethod( IsRightIdealOp, "for SCRings", IsIdenticalObj,
    [ IsSubringSCRing, IsSubringSCRing ], 0,
function( A, S )
local gens, a, i;
  if not IsSubset( A, S ) then
    return false;
  fi;

  gens:=StandardGeneratorsSubringSCRing(S)[3];
  for a in GeneratorsOfRing( A ) do
    for i in gens do
      if not i*a in S then
        return false;
      fi;
    od;
  od;
  return true;
end );

InstallOtherMethod( IsTwoSidedIdealOp, "for rings and subrings",
    IsIdenticalObj, [ IsRing, IsRing ], 0,
function( A, S )
local is;
  #T Check containment only once!
  is:=IsLeftIdeal(A,S);
  is:=is and IsRightIdeal(A,S);
  return is;
end );

InstallMethod(Ideals,"for SC Rings",[IsSubringSCRing],
function(R)
  return Filtered(Subrings(R),i->IsIdeal(R,i));
end);


#############################################################################
##
#F  DirectSum( <arg> )
##
InstallGlobalFunction( DirectSum, function( arg )
local d,t,i;
  if Length( arg ) = 0 then
    Error( "<arg> must be nonempty" );
  elif Length( arg ) = 1 and IsList( arg[1] ) then
    if IsEmpty( arg[1] ) then
      Error( "<arg>[1] must be nonempty" );
    fi;
    arg:= arg[1];
  fi;

  # special treatment of ``Integers'' as part of a direct sum: Replace by
  # SC ring:
  if ForAny(arg,x->IsIdenticalObj(x,Integers)) then
    t:=EmptySCTable(1,0);
    SetEntrySCTable(t,1,1,[1,1]);
    t:=RingByStructureConstants([0],t,"n");
    arg:=ShallowCopy(arg);
    for i in [1..Length(arg)] do
      if IsIdenticalObj(arg[i],Integers) then
        arg[i]:=t;
      fi;
    od;
  fi;

  d:=DirectSumOp( arg, arg[1] );
  if ForAll(arg,HasSize) then
    if   ForAll(arg,IsFinite)
    then SetSize(d,Product(List(arg,Size)));
    else SetSize(d,infinity); fi;
  fi;
  return d;
end );


#############################################################################
##
#M  DirectSumOp( <list>, <R> )
##
InstallMethod( DirectSumOp, "for a list (of rings), and a ring", true,
    [ IsList, IsRing ], 0,
function( list, gp )
local ids, tup, first, i, G, gens, g, new, D;

  # Check the arguments.
  if IsEmpty( list ) then
    Error( "<list> must be nonempty" );
  elif ForAny( list, G -> not IsRing( G ) ) then
    TryNextMethod();
  fi;

  ids := List( list, Zero );
  tup := [];
  first := [1];
  for i in [1..Length( list )] do
    G    := list[i];
    gens := GeneratorsOfRing( G );
    if Length(gens)=0 then
      gens:=[Zero(G)];
    fi;
    for g in gens do
      new := ShallowCopy( ids );
      new[i] := g;
      new := DirectProductElement( new );
      Add( tup, new );
    od;
    Add( first, Length( tup )+1 );
  od;

  D := RingByGenerators( tup );

  SetDirectSumInfo( D, rec( rings := list,
                            first  := first,
                            embeddings := [],
                            projections := [] ) );

  return D;
end );

InstallMethod( DirectSumOp, "for SC Rings", true,
    [ IsList, IsSubringSCRing ], 0,
function( list, gp )
local ones,s, moduli, orders, offsets, o, p, newmod, t, nams, gens, e, f, D, i, j, k, ii;

  # Check the arguments.
  if IsEmpty( list ) then
    Error( "<list> must be nonempty" );
  elif ForAny( list, G -> not IsSubringSCRing( G ) ) then
    TryNextMethod();
  fi;

  # get respective standard generators
  s:=List(list,StandardGeneratorsSubringSCRing);
  moduli:=List(list,i->ElementsFamily(FamilyObj(i))!.moduli);
  orders:=[];
  offsets:=[0];
  ones:=[];
  for i in [1..Length(list)] do
    o:=[];
    for j in [1..Length(s[i][1])] do
      p:=PositionNonZero(s[i][1][j]);
      if moduli[i][p]=0 then
        Add(o,0);
      else
        Add(o,moduli[i][p]/s[i][1][j][p]);
      fi;
    od;
    Add(orders,o);
    offsets[i+1]:=Sum(List(orders,Length));
    if (HasOne(list[i]) or (HasIsFinite(list[i]) and Size(list[i])<10^5 ))
      and One(list[i])<>fail then
      o:=One(list[i]);
      o:=SCRingDecompositionStandardGens(s[i],o);
      Add(ones,o);
    else
      Add(ones,fail);
    fi;
  od;

  newmod:=Concatenation(orders);
  t:=EmptySCTable(Length(newmod),0);
  nams:=[];
  for i in [1..Length(list)] do
    gens:=s[i][3];
    Append(nams,List([1..Length(gens)],j->[CHARS_UALPHA[i],CHARS_LALPHA[j]]));
    for j in [1..Length(gens)] do
      for k in [1..Length(gens)] do
        e:=gens[j]*gens[k];
        if not IsZero(e) then
          e:=SCRingDecompositionStandardGens(s[i],e);
          f:=[];
          for ii in [1..Length(e)] do
            if e[ii]<>0 then
              Add(f,e[ii]);
              Add(f,ii+offsets[i]);
            fi;
          od;
          SetEntrySCTable(t,j+offsets[i],k+offsets[i],f);
        fi;
      od;
    od;
  od;

  D := RingByStructureConstants(newmod,t,nams);

  if ForAll(ones,i->i<>fail) then
    f:=FamilyObj(Zero(D));
    e:=ObjByExtRep(f,Concatenation(ones));
    SetOne(D,e);
    SetOne(f,e);
  fi;

  SetDirectSumInfo( D, rec( rings := list,
                            first  := offsets,
                            embeddings := [],
                            projections := [] ) );

  return D;
end );

#############################################################################
##
#M  \+( <R1>, <R2> )  . . . . . . . . . . . . . . . . sum of rings
##
InstallOtherMethod( \+, "for two rings", [ IsRing, IsRing ],
function(R1,R2)
  return DirectSum(R1,R2);
end);

# data base of small rings. (Data taken from the nearring library in SONATA)

BindGlobal("NUMBER_SMALL_RINGS",
MakeImmutable([1,2,2,11,2,4,2,52,11,4,2,22,2,4,4]));

BindGlobal("SMALL_RINGS_DATA",
MakeImmutable(
[[1,1,[1],[]],
[2,1,[2],[]],[2,2,[2],[[1,1,[1,1]]]],
[3,1,[3],[]],[3,2,[3],[[1,1,[1,1]]]],
[4,1,[4],[]],[4,2,[4],[[1,1,[2,1]]]],[4,3,[4],[[1,1,[1,1]]]],
[4,4,[2,2],[]],[4,5,[2,2],[[1,1,[1,2]]]],[4,6,[2,2],[[1,1,[1,1]]]],
[4,7,[2,2],[[1,1,[1,1]],[1,2,[1,2]]]],[4,8,[2,2],[[1,1,[1,1]],[2,1,[1,2]]]],
[4,9,[2,2],[[1,1,[1,1]],[1,2,[1,2]],[2,1,[1,2]],[2,2,[1,1]]]],
[4,10,[2,2],[[1,1,[1,1]],[1,2,[1,2]],[2,1,[1,2]],[2,2,[1,2]]]],
[4,11,[2,2],[[1,1,[1,1]],[1,2,[1,2]],[2,1,[1,2]],[2,2,[1,1,1,2]]]],
[5,1,[5],[]],[5,2,[5],[[1,1,[1,1]]]],
[6,1,[6],[]],[6,2,[6],[[1,1,[4,1]]]],[6,3,[6],[[1,1,[3,1]]]],
[6,4,[6],[[1,1,[1,1]]]],
[7,1,[7],[]],[7,2,[7],[[1,1,[1,1]]]],
[8,1,[8],[]],[8,2,[8],[[1,1,[2,1]]]],[8,3,[8],[[1,1,[1,1]]]],
[8,4,[8],[[1,1,[4,1]]]],[8,5,[4,2],[]],[8,6,[4,2],[[2,2,[2,1]]]],
[8,7,[4,2],[[2,2,[1,2]]]],[8,8,[4,2],[[2,1,[2,1]]]],
[8,9,[4,2],[[2,1,[2,1]],[2,2,[2,1]]]],[8,10,[4,2],[[1,2,[2,1]]]],
[8,11,[4,2],[[1,2,[2,1]],[2,1,[2,1]]]],
[8,12,[4,2],[[1,2,[2,1]],[2,1,[2,1]],[2,2,[2,1]]]],[8,13,[4,2],[[1,1,[1,1]]]],
[8,14,[4,2],[[1,1,[1,1]],[1,2,[1,2]],[2,1,[1,2]],[2,2,[1,2]]]],
[8,15,[4,2],[[1,1,[1,1]],[2,1,[1,2]]]],[8,16,[4,2],[[1,1,[2,1]]]],
[8,17,[4,2],[[1,1,[2,1]],[2,2,[1,2]]]],
[8,18,[4,2],[[1,1,[2,1]],[2,1,[2,1]],[2,2,[2,1]]]],
[8,19,[4,2],[[1,1,[2,1]],[1,2,[2,1]],[2,1,[2,1]]]],
[8,20,[4,2],[[1,1,[3,1]],[1,2,[1,2]]]],
[8,21,[4,2],[[1,1,[1,1]],[1,2,[1,2]],[2,1,[1,2]]]],
[8,22,[4,2],[[1,1,[1,1]],[1,2,[1,2]],[2,1,[1,2]],[2,2,[2,1]]]],
[8,23,[4,2],[[1,1,[1,2]]]],[8,24,[4,2],[[1,1,[1,2]],[1,2,[2,1]],[2,1,[2,1]]]],
[8,25,[2,2,2],[]],[8,26,[2,2,2],[[1,1,[1,3]]]],[8,27,[2,2,2],[[1,1,[1,1]]]],
[8,28,[2,2,2],[[1,2,[1,3]]]],[8,29,[2,2,2],[[1,1,[1,1]],[1,2,[1,2]]]],
[8,30,[2,2,2],[[1,1,[1,1]],[1,2,[1,2]],[1,3,[1,3]]]],
[8,31,[2,2,2],[[1,2,[1,3]],[2,1,[1,3]]]],
[8,32,[2,2,2],[[1,1,[1,3]],[1,2,[1,3]],[2,1,[1,3]]]],
[8,33,[2,2,2],[[1,1,[1,2]],[1,2,[1,3]],[2,1,[1,3]]]],
[8,34,[2,2,2],[[1,1,[1,1]],[2,1,[1,2]]]],
[8,35,[2,2,2],[[1,1,[1,1]],[1,2,[1,2]],[2,1,[1,2]]]],
[8,36,[2,2,2],[[1,1,[1,1]],[1,3,[1,3]],[2,1,[1,2]]]],
[8,37,[2,2,2],[[1,1,[1,1,1,2]],[1,2,[1,2]],[1,3,[1,3]],[2,1,[1,2]]]],
[8,38,[2,2,2],[[1,1,[1,1]],[2,2,[1,3]]]],
[8,39,[2,2,2],[[1,1,[1,3]],[1,2,[1,3]],[2,2,[1,3]]]],
[8,40,[2,2,2],[[1,1,[1,1]],[2,2,[1,2]]]],
[8,41,[2,2,2],[[1,1,[1,1]],[1,3,[1,3]],[2,2,[1,2]]]],
[8,42,[2,2,2],[[1,1,[1,1,1,2]],[1,2,[1,1]],[2,1,[1,1]],[2,2,[1,2]]]],
[8,43,[2,2,2],[[1,1,[1,1]],[2,1,[1,2]],[3,1,[1,3]]]],
[8,44,[2,2,2],[[1,1,[1,1]],[1,2,[1,2]],[2,1,[1,2]],[3,1,[1,3]]]],
[8,45,[2,2,2],[[1,1,[1,1]],[1,2,[1,2]],[1,3,[1,3]],[2,1,[1,2]],[2,2,[1,1]],
  [2,3,[1,3]],[3,1,[1,3]],[3,2,[1,3]]]],
[8,46,[2,2,2],[[1,1,[1,1]],[1,2,[1,2]],[1,3,[1,3]],[2,1,[1,2]],[2,2,[1,1]],
  [2,3,[1,3]],[3,1,[1,3]],[3,2,[1,3]],[3,3,[1,1,1,2]]]],
[8,47,[2,2,2],[[1,1,[1,1]],[2,2,[1,2]],[3,1,[1,3]]]],
[8,48,[2,2,2],[[1,1,[1,1]],[1,2,[1,2]],[1,3,[1,3]],[2,1,[1,2]],[2,2,[1,2]],
  [2,3,[1,3]],[3,1,[1,3]],[3,2,[1,3]]]],
[8,49,[2,2,2],[[1,1,[1,1]],[1,2,[1,2]],[1,3,[1,3]],[2,1,[1,2]],[2,2,[1,2]],
  [3,1,[1,3]],[3,2,[1,3]]]],
[8,50,[2,2,2],[[1,1,[1,1]],[1,2,[1,2]],[1,3,[1,3]],[2,1,[1,2]],[2,2,[1,2]],
  [3,1,[1,3]],[3,3,[1,3]]]],
[8,51,[2,2,2],[[1,1,[1,1]],[1,2,[1,2]],[1,3,[1,3]],[2,1,[1,2]],[2,2,[1,2,1,3]],
  [2,3,[1,2]],[3,1,[1,3]],[3,2,[1,2]],[3,3,[1,3]]]],
[8,52,[2,2,2],[[1,1,[1,1]],[1,2,[1,2]],[1,3,[1,3]],[2,1,[1,2]],[2,2,[1,1,1,3]],
  [2,3,[1,2,1,3]],[3,1,[1,3]],[3,2,[1,2,1,3]],[3,3,[1,1,1,2,1,3]]]],
[9,1,[9],[]],[9,2,[9],[[1,1,[1,1]]]],[9,3,[9],[[1,1,[3,1]]]],[9,4,[3,3],[]],
[9,5,[3,3],[[1,1,[1,2]]]],[9,6,[3,3],[[1,1,[1,1]]]],
[9,7,[3,3],[[1,1,[2,1]],[1,2,[2,2]]]],[9,8,[3,3],[[1,1,[1,1]],[2,1,[1,2]]]],
[9,9,[3,3],[[1,1,[1,1]],[1,2,[1,2]],[2,1,[1,2]],[2,2,[2,1,2,2]]]],
[9,10,[3,3],[[1,1,[1,1]],[1,2,[1,2]],[2,1,[1,2]],[2,2,[1,2]]]],
[9,11,[3,3],[[1,1,[1,1]],[1,2,[1,2]],[2,1,[1,2]],[2,2,[2,1]]]],
[10,1,[10],[]],[10,2,[10],[[1,1,[4,1]]]],[10,3,[10],[[1,1,[1,1]]]],
[10,4,[10],[[1,1,[5,1]]]],
[11,1,[11],[]],[11,2,[11],[[1,1,[1,1]]]],
[12,1,[12],[]],[12,2,[12],[[1,1,[2,1]]]],[12,3,[12],[[1,1,[9,1]]]],
[12,4,[12],[[1,1,[4,1]]]],[12,5,[12],[[1,1,[1,1]]]],
[12,6,[12],[[1,1,[6,1]]]],[12,7,[6,2],[]],[12,8,[6,2],[[1,1,[1,2]]]],
[12,9,[6,2],[[1,1,[3,1]]]],[12,10,[6,2],[[1,1,[3,1]],[1,2,[1,2]]]],
[12,11,[6,2],[[1,1,[3,1]],[2,1,[1,2]]]],
[12,12,[6,2],[[1,1,[3,1]],[1,2,[1,2]],[2,1,[1,2]]]],
[12,13,[6,2],[[1,1,[2,1]],[2,2,[1,2]]]],
[12,14,[6,2],[[1,1,[1,1]],[1,2,[1,2]],[2,1,[1,2]],[2,2,[1,2]]]],
[12,15,[6,2],[[1,1,[2,1]],[1,2,[3,1]],[2,2,[1,2]]]],[12,16,[6,2],[[1,1,[4,1]]]],
[12,17,[6,2],[[1,1,[4,1,1,2]]]],[12,18,[6,2],[[1,1,[1,1]],[1,2,[1,2]]]],
[12,19,[6,2],[[1,1,[1,1]],[1,2,[1,2]],[2,1,[1,2]]]],
[12,20,[6,2],[[1,1,[3,1]],[2,2,[1,2]]]],
[12,21,[6,2],[[1,1,[3,1,1,2]],[1,2,[3,1]],[2,1,[3,1]],[2,2,[1,2]]]],
[12,22,[6,2],[[1,1,[1,1]],[1,2,[1,2]],[2,1,[1,2]],[2,2,[3,1,1,2]]]],
[13,1,[13],[]],[13,2,[13],[[1,1,[1,1]]]],
[14,1,[14],[]],[14,2,[14],[[1,1,[4,1]]]],
[14,3,[14],[[1,1,[1,1]]]],[14,4,[14],[[1,1,[7,1]]]],
[15,1,[15],[]],[15,2,[15],[[1,1,[1,1]]]],[15,3,[15],[[1,1,[9,1]]]],
[15,4,[15],[[1,1,[10,1]]]]]
));

InstallGlobalFunction(NumberSmallRings,function(x)
  if IsPosInt(x) then
    if IsBound(NUMBER_SMALL_RINGS[x]) then
      return NUMBER_SMALL_RINGS[x];
    else
      Error("the library of rings of size ", x, " is not available");
    fi;
  else
    Error("NumberSmallRings: the argument should be a positive integer");
  fi;
end);

InstallGlobalFunction(SmallRing,function(x,n)
  local r, s, t, i;
  if not (IsPosInt(x) and IsBound(NUMBER_SMALL_RINGS[x])
    and IsPosInt(n) and n<=NUMBER_SMALL_RINGS[x]) then
    r:=Filtered([1..Length(NUMBER_SMALL_RINGS)],i->NUMBER_SMALL_RINGS[i]>0);
    IsRange(r);
    Error("Size must be in ",r," and number in [1..",
          NUMBER_SMALL_RINGS[x],"]\n");
  else
    s:=First(SMALL_RINGS_DATA,i->i[1]=x and i[2]=n);
    r:=s[3];
    t:=EmptySCTable(Length(r),0);
    for i in s[4] do
      SetEntrySCTable(t,i[1],i[2],i[3]);
    od;
    if Length(r)>26 then
      s:="R";
    else
      s:=List([1..Length(r)],i->[CHARS_LALPHA[i]]);
    fi;
    r:=RingByStructureConstants(r,t,s);
    return r;
  fi;
end);

# matrices
InstallOtherMethod( InverseOp, "for sc ring matrices",
    [ IsListDefault and IsSCRingObjCollColl ],
    function( mat )
    if NestingDepthM( mat ) mod 2 = 0 and IsSmallList( mat ) then
        if IsRectangularTable( mat ) then
            return INV_MATRIX_MUTABLE( mat );
        else
            return fail;
        fi;
    else
      TryNextMethod();
    fi;
    end );

[ Dauer der Verarbeitung: 0.33 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


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