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


Quelle  resclass.gi   Sprache: unbekannt

 
#############################################################################
##
#W  resclass.gi             GAP4 Package `ResClasses'             Stefan Kohl
##
##  This file contains implementations of methods and functions for computing
##  with unions of residue classes +/- finite sets ('residue class unions').
##
#############################################################################

#############################################################################
##
#S  Implications between the categories of residue class unions /////////////
#S  and shorthands for commonly used filters. ///////////////////////////////
##
#############################################################################

InstallTrueMethod( IsResidueClassUnion,
                   IsResidueClassUnionOfZorZ_pi );
InstallTrueMethod( IsResidueClassUnionOfZorZ_pi,
                   IsResidueClassUnionOfZ );
InstallTrueMethod( IsResidueClassUnionOfZorZ_pi,
                   IsResidueClassUnionOfZ_pi );
InstallTrueMethod( IsResidueClassUnion,
                   IsResidueClassUnionOfZxZ );
InstallTrueMethod( IsResidueClassUnion,
                   IsResidueClassUnionOfGFqx );

BindGlobal( "IsResidueClassOfZ",
             IsResidueClassUnionOfZ and IsResidueClass );
BindGlobal( "IsResidueClassOfZxZ",
             IsResidueClassUnionOfZxZ and IsResidueClass );
BindGlobal( "IsResidueClassOfZ_pi",
             IsResidueClassUnionOfZ_pi and IsResidueClass );
BindGlobal( "IsResidueClassOfZorZ_pi",
             IsResidueClassUnionOfZorZ_pi and IsResidueClass );
BindGlobal( "IsResidueClassOfGFqx",
             IsResidueClassUnionOfGFqx and IsResidueClass );

BindGlobal( "IsResidueClassUnionInResidueListRep",
             IsResidueClassUnion and IsResidueClassUnionResidueListRep );
BindGlobal( "IsResidueClassUnionInClassListRep",
             IsResidueClassUnion and IsResidueClassUnionClassListRep );
BindGlobal( "IsResidueClassUnionOfZInClassListRep",
             IsResidueClassUnionOfZ and IsResidueClassUnionClassListRep );

#############################################################################
##
#S  The families of residue class unions. ///////////////////////////////////
##
#############################################################################

# Internal variables for caching the families of residue class unions
# used in the current GAP session.

BindGlobal( "Z_RESIDUE_CLASS_UNIONS_FAMILIES", [] );
BindGlobal( "Z_PI_RESIDUE_CLASS_UNIONS_FAMILIES", [] );
BindGlobal( "GF_Q_X_RESIDUE_CLASS_UNIONS_FAMILIES", [] );

#############################################################################
##
#F  ZResidueClassUnionsFamily( <fixedreps> )
##
InstallGlobalFunction( ZResidueClassUnionsFamily,

  function ( fixedreps )

    local  fam, pos;

    if not fixedreps then pos := 1; else pos := 2; fi;
    if   IsBound( Z_RESIDUE_CLASS_UNIONS_FAMILIES[ pos ] )
    then return   Z_RESIDUE_CLASS_UNIONS_FAMILIES[ pos ]; fi;
    if not fixedreps then
      fam := NewFamily( "ResidueClassUnionsFamily( Integers )",
                        IsResidueClassUnionOfZ,
                        CanEasilySortElements, CanEasilySortElements );
      SetUnderlyingRing( fam, Integers );
      SetElementsFamily( fam, FamilyObj( 1 ) );
    else
      fam := NewFamily( "ResidueClassUnionsFamily( Integers, true )",
                        IsUnionOfResidueClassesWithFixedRepresentatives,
                        CanEasilySortElements, CanEasilySortElements );
      SetUnderlyingRing( fam, Integers );
      SetElementsFamily( fam, fam );
    fi;
    MakeReadWriteGlobal( "Z_RESIDUE_CLASS_UNIONS_FAMILIES" );
    Z_RESIDUE_CLASS_UNIONS_FAMILIES[ pos ] := fam;
    MakeReadOnlyGlobal( "Z_RESIDUE_CLASS_UNIONS_FAMILIES" );
    return fam;
  end );

#############################################################################
##
#V  ZxZResidueClassUnionsFamily . . family of all residue class unions of Z^2
##
##  GAP does not view Z^2 as a ring, but rather as a row module.
##  Anyway it is viewed as the underlying ring of the family, since it
##  mathematically is a ring and since this avoids a case distinction
##  in many places in the code.
##
BindGlobal( "ZxZResidueClassUnionsFamily",
            NewFamily( "ResidueClassUnionsFamily( Integers^2 )",
                       IsResidueClassUnionOfZxZ,
                       CanEasilySortElements, CanEasilySortElements ) );
SetUnderlyingRing( ZxZResidueClassUnionsFamily, Integers^2 );
SetElementsFamily( ZxZResidueClassUnionsFamily, FamilyObj( [ 0, 0 ] ) );

#############################################################################
##
#F  Z_piResidueClassUnionsFamily( <R> , <fixedreps> )
##
InstallGlobalFunction( Z_piResidueClassUnionsFamily,

  function ( R, fixedreps )

    local  fam, cat, name;

    fam := First( Z_PI_RESIDUE_CLASS_UNIONS_FAMILIES,
                  fam ->     UnderlyingRing( fam ) = R
                         and PositionSublist( fam!.NAME,
                                              String(fixedreps) ) <> fail );
    if fam <> fail then return fam; fi;
    if   not fixedreps
    then cat := IsResidueClassUnionOfZ_pi;
    else cat := IsUnionOfResidueClassesOfZ_piWithFixedRepresentatives; fi;
    name := Concatenation( "ResidueClassUnionsFamily( ",
                           String( R ),", ",String(fixedreps)," )" );
    fam := NewFamily( name, cat,
                      CanEasilySortElements, CanEasilySortElements );
    SetUnderlyingRing( fam, R );
    if not fixedreps then SetElementsFamily( fam, FamilyObj( 1 ) );
                     else SetElementsFamily( fam, fam ); fi;
    MakeReadWriteGlobal( "Z_PI_RESIDUE_CLASS_UNIONS_FAMILIES" );
    Add( Z_PI_RESIDUE_CLASS_UNIONS_FAMILIES, fam );
    MakeReadOnlyGlobal( "Z_PI_RESIDUE_CLASS_UNIONS_FAMILIES" );

    return fam;
  end );

#############################################################################
##
#F  GFqxResidueClassUnionsFamily( <R>, <fixedreps> )
##
InstallGlobalFunction( GFqxResidueClassUnionsFamily,

  function ( R, fixedreps )

    local  fam, cat, name, x;

    x := IndeterminatesOfPolynomialRing( R )[ 1 ];
    fam := First( GF_Q_X_RESIDUE_CLASS_UNIONS_FAMILIES,
                  fam -> UnderlyingRing( fam ) = R
                         and PositionSublist( fam!.NAME,
                                              String(fixedreps) ) <> fail );
    if fam <> fail then return fam; fi;
    if   not fixedreps
    then cat := IsResidueClassUnionOfGFqx;
    else cat := IsUnionOfResidueClassesOfGFqxWithFixedRepresentatives; fi;
    name := Concatenation( "ResidueClassUnionsFamily( ",
                           ViewString( R ),", ",String(fixedreps)," )" );
    fam := NewFamily( name, cat,
                      CanEasilySortElements, CanEasilySortElements );
    SetUnderlyingIndeterminate( fam, x );
    SetUnderlyingRing( fam, R );
    if not fixedreps then SetElementsFamily( fam, FamilyObj( x ) );
                     else SetElementsFamily( fam, fam ); fi;
    MakeReadWriteGlobal( "GF_Q_X_RESIDUE_CLASS_UNIONS_FAMILIES" );
    Add( GF_Q_X_RESIDUE_CLASS_UNIONS_FAMILIES, fam );
    MakeReadOnlyGlobal( "GF_Q_X_RESIDUE_CLASS_UNIONS_FAMILIES" );

    return fam;
  end );

#############################################################################
##
#F  ResidueClassUnionsFamily( <R> [ , <fixedreps> ]  )
##
InstallGlobalFunction( ResidueClassUnionsFamily,

  function ( arg )

    local  R, fixedreps;

    if   not Length(arg) in [1,2]
    or   Length(arg) = 2 and not arg[2] in [true,false]
    then Error("Usage: ResidueClassUnionsFamily( <R> [ , <fixedreps> ] )\n");
    fi;
    R := arg[1];
    if Length(arg) = 2 then fixedreps := arg[2]; else fixedreps := false; fi;
    if   IsIntegers( R )
    then return ZResidueClassUnionsFamily( fixedreps );
    elif IsZxZ( R ) then return ZxZResidueClassUnionsFamily;
    elif IsZ_pi( R )
    then return Z_piResidueClassUnionsFamily( R, fixedreps );
    elif IsUnivariatePolynomialRing( R ) and IsFiniteFieldPolynomialRing( R )
    then return GFqxResidueClassUnionsFamily( R, fixedreps );
    else Error("Sorry, residue class unions of ",R,
               " are not yet implemented.\n");
    fi;
  end );

#############################################################################
##
#M  IsZxZ( <R> ) . . . . . . . . . . . . . . . . . . Z^2 = Z x Z = Integers^2
##
InstallMethod( IsZxZ, "general method (ResClasses)", true,
               [ IsObject ], 0, R -> R = Integers^2 );

#############################################################################
##
#S  Residues / residue classes (mod m). /////////////////////////////////////
##
#############################################################################

# Buffer for storing already computed polynomial residue systems.

BindGlobal( "POLYNOMIAL_RESIDUE_CACHE", [] );

BindGlobal( "AllGFqPolynomialsModDegree",

  function ( q, d, x )

    local  erg, mon, gflist;

    if   d = 0
    then return [ Zero( x ) ];
    elif     IsBound( POLYNOMIAL_RESIDUE_CACHE[ q ] )
         and IsBound( POLYNOMIAL_RESIDUE_CACHE[ q ][ d ] )
    then return ShallowCopy( POLYNOMIAL_RESIDUE_CACHE[ q ][ d ] );
    else gflist := AsList( GF( q ) );
         mon := List( gflist, el -> List( [ 0 .. d - 1 ], i -> el * x^i ) );
         erg := List( Tuples( GF( q ), d ),
                      t -> Sum( List( [ 1 .. d ],
                                      i -> mon[ Position( gflist, t[ i ] ) ]
                                              [ d - i + 1 ] ) ) );
         MakeReadWriteGlobal( "POLYNOMIAL_RESIDUE_CACHE" );
         if not IsBound( POLYNOMIAL_RESIDUE_CACHE[ q ] )
         then POLYNOMIAL_RESIDUE_CACHE[ q ] := [ ]; fi;
         POLYNOMIAL_RESIDUE_CACHE[ q ][ d ] := Immutable( erg );
         MakeReadOnlyGlobal( "POLYNOMIAL_RESIDUE_CACHE" );
         return erg;
    fi;
  end );

# Difference r1(m1) \ r2(m2) of two residue classes;
# the residue classes r1(m1) and r2(m2) are to be given as pairs
# [r1,m1] and [r2,m2] of integers, and the output is a list of
# residue classes represented in the same way.

BindGlobal( "DIFFERENCE_OF_RESIDUE_CLASSES",

  function ( cl1, cl2 )

    local  cls, r1, m1, r2, m2, r3, m3, divs, d, p, r, inc, i;

    r1 := cl1[1]; m1 := cl1[2];
    r2 := cl2[1]; m2 := cl2[2];

    if (r1-r2) mod Gcd(m1,m2) <> 0 then return [cl1]; fi; # disjoint
    m3 := Lcm(m1,m2);
    if m3 = m1 then return []; fi; # second cl. is a superset of first cl.
    r3 := ChineseRem([m1,m2],[r1,r2]);

    divs := []; d := 1;
    for p in Factors(m3/m1) do 
      d := d * p;
      Add(divs,d);
    od;
    cls := [];
    for i in [1..Length(divs)] do
      d := divs[i];
      if i > 1 then inc := divs[i-1]; else inc := 1; fi;
      for r in [inc,2*inc..d-inc] do
        Add(cls,[r,d]);
      od;
    od;
    for i in [1..Length(cls)] do # get moduli and residues right
      cls[i][2] := cls[i][2] * m1;
      cls[i][1] := (cls[i][1] * m1 + r3) mod cls[i][2];
    od;
    SortParallel( List( cls, Reversed ), cls );

    return cls;
  end );

#############################################################################
##
#M  AllResidues( <R>, <m> ) . . . . . . . . . . . .  for Z, Z_pi and GF(q)[x]
##
InstallMethod( AllResidues,
               "for Z, Z_pi and GF(q)[x] (ResClasses)", ReturnTrue,
               [ IsRing, IsRingElement ], 0,

  function ( R, m )

    local  q, d, x;

    if   IsIntegers(R) or IsZ_pi(R)
    then return [0..StandardAssociate(R,m)-1]; fi;
    if IsUnivariatePolynomialRing(R) and Characteristic(R) <> 0 then
      q := Size(CoefficientsRing(R));
      d := DegreeOfLaurentPolynomial(m);
      x := IndeterminatesOfPolynomialRing(R)[1];
      return AllGFqPolynomialsModDegree(q,d,x);
    fi;
    TryNextMethod();
  end );

#############################################################################
##
#M  AllResidues( Integers^2, <L> ) . . . . . . . . . . . . for lattice in Z^2
##
InstallOtherMethod( AllResidues,
                    "for lattice in Z^2 (ResClasses)", true,
                    [ IsRowModule, IsMatrix ], 0,

  function ( ZxZ, L )
    if not IsZxZ(ZxZ) or not IsSubset(ZxZ,L) then TryNextMethod(); fi;
    L := HermiteNormalFormIntegerMat(L);
    return Cartesian([0..L[1][1]-1],[0..L[2][2]-1]);
  end );

#############################################################################
##
#M  NumberOfResidues( <R>, <m> ) . . . . . . . . . . for Z, Z_pi and GF(q)[x]
##
InstallMethod( NumberOfResidues,
               "for Z, Z_pi and GF(q)[x] (ResClasses)", ReturnTrue,
               [ IsRing, IsRingElement ], 0,

  function ( R, m )

    local  q, d, x;

    if IsIntegers(R) or IsZ_pi(R) then return StandardAssociate(R,m); fi;
    if IsUnivariatePolynomialRing(R) and Characteristic(R) <> 0 then
      q := Size(CoefficientsRing(R));
      d := DegreeOfLaurentPolynomial(m);
      return q^d;
    fi;
    TryNextMethod();
  end );

#############################################################################
##
#M  NumberOfResidues( Integers^2, <L> ) . . . . . . . . .  for lattice in Z^2
##
InstallOtherMethod( NumberOfResidues,
                    "for lattice in Z^2 (ResClasses)", ReturnTrue,
                    [ IsRowModule, IsMatrix ], 0,

  function ( ZxZ, L )
    if not IsZxZ(ZxZ) or not IsSubset(ZxZ,L) then TryNextMethod(); fi;
    return AbsInt(DeterminantMat(L));
  end );

#############################################################################
##
#F  AllResidueClassesModulo( [ <R>, ] <m> ) . . the residue classes (mod <m>)
##
InstallGlobalFunction( AllResidueClassesModulo,

  function ( arg )

    local  R, m;

    if   Length(arg) = 2
    then R := arg[1]; m := arg[2];
    else m := arg[1]; R := DefaultRing(m); fi;
    if IsRing(R) and (IsZero(m) or not m in R) then return fail; fi;
    return List(AllResidues(R,m),r->ResidueClass(R,m,r));
  end );

#############################################################################
##
#F  All2x2IntegerMatricesInHNFWithDeterminantUpTo( <maxdet> )
##
InstallGlobalFunction( All2x2IntegerMatricesInHNFWithDeterminantUpTo,

  function ( maxdet )

    local  mods, det, diags, diag;

    mods := [];
    for det in [1..maxdet] do 
      diags := List(DivisorsInt(det),d->[d,det/d]);
      for diag in diags do
        Append(mods,List([0..diag[2]-1],k->[[diag[1],k],[0,diag[2]]]));
      od;
    od;
    return mods;
  end );

#############################################################################
##
#M  SizeOfSmallestResidueClassRing( <R> ) . . . . .  for Z, Z_pi and GF(q)[x]
##
InstallMethod( SizeOfSmallestResidueClassRing,
               "for Z, Z_pi and GF(q)[x] (ResClasses)", true, [ IsRing ], 0,

  function ( R )
    if   IsIntegers(R) then return 2;
    elif IsZ_pi(R) then return Minimum(NoninvertiblePrimes(R));
    elif IsFiniteFieldPolynomialRing(R) then return Characteristic(R);
    else TryNextMethod(); fi;
  end );

#############################################################################
##
#M  SizeOfSmallestResidueClassRing( Integers^2 ) . . . . . . . . . .  for Z^2
##
InstallOtherMethod( SizeOfSmallestResidueClassRing,
                    "for Z^2 (ResClasses)", true, [ IsRowModule ], 0,

  function ( ZxZ )
    if IsZxZ(ZxZ) then return 2; else TryNextMethod(); fi;
  end );

#############################################################################
##
#S  Basic functionality for lattices in Z^n. ////////////////////////////////
##
#############################################################################

#############################################################################
##
#M  StandardAssociate( <R>, <mat> ) . . . . . . . HNF of n x n integer matrix
##
InstallOtherMethod( StandardAssociate,
                    "HNF of n x n integer matrix (ResClasses)", IsCollsElms,
                    [ IsRing and IsFullMatrixModule, IsMatrix ], 0,

  function ( R, mat )
    if   not IsIntegers(LeftActingDomain(R))
      or Length(Set(DimensionOfVectors(R))) <> 1 or not mat in R
    then TryNextMethod(); fi;
    return HermiteNormalFormIntegerMat(mat);
  end );

#############################################################################
##
#M  \mod . . . . . . . . . . . . . . . . . . . . . for a vector and a lattice
##
if   not IsReadOnlyGlobal( "VectorModLattice" ) # not protected in polycyclic
then MakeReadOnlyGlobal( "VectorModLattice" ); fi;

InstallMethod( \mod, "for a vector and a lattice (ResClasses)", IsElmsColls,
               [ IsRowVector, IsMatrix ], 0,
               function ( v, L ) return VectorModLattice( v, L ); end );

#############################################################################
##
#M  LcmOp( <R>, <mat1>, <mat2> ) . . . . . . . .  lattice intersection in Z^n
##
InstallOtherMethod( LcmOp, "lattice intersection in Z^n (ResClasses)",
                    IsCollsElmsElms,
                    [ IsRing and IsFullMatrixModule, IsMatrix, IsMatrix ], 0,

  function ( R, mat1, mat2 )

    local  n;

    if   not IsIntegers(LeftActingDomain(R)) 
      or Length(Set(DimensionOfVectors(R))) <> 1
      or not mat1 in R or not mat2 in R 
    then TryNextMethod(); fi;

    n := DimensionOfVectors(R)[1];

    if n = 2 then # Check whether matrices are already in HNF.
      if   mat1[2][1] <> 0 or ForAny(Flat(mat1),n->n<0)
        or mat1[1][2] >= mat1[2][2]
      then mat1 := HermiteNormalFormIntegerMat(mat1); fi;
      if   mat2[2][1] <> 0 or ForAny(Flat(mat2),n->n<0)
        or mat2[1][2] >= mat2[2][2]
      then mat2 := HermiteNormalFormIntegerMat(mat2); fi;
    else
      mat1 := HermiteNormalFormIntegerMat(mat1);
      mat2 := HermiteNormalFormIntegerMat(mat2);
    fi;

    return LatticeIntersection( mat1, mat2 );

  end );

#############################################################################
##
#M  IsSublattice( <L1>, <L2> ) . . . . . . . . . . . . .  for lattices in Z^n
##
InstallMethod( IsSublattice,
               "for lattices in Z^n (ResClasses)", IsIdenticalObj,
               [ IsMatrix, IsMatrix ], 0,

  function ( L1, L2 )
    return ForAll( Flat( L2 / L1 ), IsInt );
  end );

#############################################################################
##
#M  Superlattices( <L> ) . . . . . . . . . . . . . . . . for a lattice in Z^2
##
SetupCache( "RESCLASSES_SUPERLATTICES_CACHE", 100 );

InstallMethod( Superlattices,
               "for a lattice in Z^2 (ResClasses)", true, [ IsMatrix ], 0,

  function ( L )

    local  lattices, sup, divx, divy, x, y, dx;

    if   Set(DimensionsMat(L)) <> [2] or not ForAll(Flat(L),IsInt)
      or DeterminantMat(L) = 0
    then TryNextMethod(); fi;

    if IsOne(L) then return [[[1,0],[0,1]]]; fi;

    lattices := FetchFromCache( "RESCLASSES_SUPERLATTICES_CACHE", L );
    if lattices <> fail then return lattices; fi;

    divx := DivisorsInt(L[2][2]); divy := DivisorsInt(L[1][1]);
    lattices := [];
    for x in divx do for y in divy do for dx in [0..x-1] do
      sup := [[y,dx],[0,x]];
      if ForAll(Flat(L/sup),IsInt) then Add(lattices,sup); fi;
    od; od; od;
    lattices := Set(lattices,HermiteNormalFormIntegerMat);
    SortParallel(List(lattices,Li->[DeterminantMat(Li),Li]),lattices);
    
    PutIntoCache( "RESCLASSES_SUPERLATTICES_CACHE", L, lattices );
    return lattices;
  end );

#############################################################################
##
#F  ModulusAsFormattedString( <m> ) . format lattice etc. for output purposes
##
BindGlobal( "ModulusAsFormattedString",
  function ( m )
    if not IsMatrix(m) then return ViewString(m); fi;
    return Filtered(Concatenation(List(["(",m[1][1],",",m[1][2],")Z+(",
                                            m[2][1],",",m[2][2],")Z"],
                                       String)),ch->ch<>' ');
  end );

#############################################################################
##
#S  Construction of residue class unions. ///////////////////////////////////
##
#############################################################################

#############################################################################
##
#M  ResidueClassUnionCons( <filter>, <R>, <m>, <r>, <included>, <excluded> )
##
InstallMethod( ResidueClassUnionCons,
               "residue list rep., for Z, Z_pi and GF(q)[x] (ResClasses)",
               ReturnTrue, [ IsResidueClassUnion, IsRing, IsRingElement,
                             IsList, IsList, IsList ], 0,

  function ( filter, R, m, r, included, excluded )

    local  ReduceResidueClassUnion, result, both, fam, type, rep, pos;

    ReduceResidueClassUnion := function ( U )

      local  R, m, r, mRed, mRedBuf, rRed, rRedBuf, valid, fact, p;

      R := UnderlyingRing(FamilyObj(U));
      m := StandardAssociate(R,U!.m);  mRed := m;
      r := Set( U!.r, n -> n mod m ); rRed := r;
      fact := Set(Factors(R,m));
      for p in fact do
        repeat
          mRedBuf := mRed; rRedBuf := ShallowCopy(rRed);
          mRed := mRed/p;
          rRed := Set(rRedBuf,n->n mod mRed);
          if   IsIntegers(R) or IsZ_pi(R)
          then valid := Length(rRed) = Length(rRedBuf)/p;
          else valid := Length(rRed) = Length(rRedBuf)/
                      Size(CoefficientsRing(R))^DegreeOfLaurentPolynomial(p);
          fi;
        until not valid or not IsZero(mRed mod p) or IsOne(mRed);
        if not valid then mRed := mRedBuf; rRed := rRedBuf; fi;
      od;
      U!.m := mRed; U!.r := Immutable(rRed);
      U!.included := Immutable(Set(Filtered(U!.included,
                                            n -> not (n mod mRed in rRed))));
      U!.excluded := Immutable(Set(Filtered(U!.excluded,
                                            n -> n mod mRed in rRed)));
      if rRed = [] then U := Difference(U!.included,U!.excluded); fi;
    end;

    if not ( IsIntegers( R ) or IsZ_pi( R )
             or (     IsFiniteFieldPolynomialRing( R )
                  and IsUnivariatePolynomialRing( R ) ) )
    then TryNextMethod( ); fi;
    m := StandardAssociate( R, m );
    r := Set( r, n -> n mod m );
    both := Intersection( included, excluded );
    included := Difference( included, both );
    excluded := Difference( excluded, both );
    if r = [] then return Difference(included,excluded); fi;
    fam := ResidueClassUnionsFamily( R );
    if   IsIntegers( R )       then type := IsResidueClassUnionOfZ;
    elif IsZ_pi( R )           then type := IsResidueClassUnionOfZ_pi;
    elif IsPolynomialRing( R ) then type := IsResidueClassUnionOfGFqx;
    fi;
    result := Objectify( NewType( fam, type and
                                  IsResidueClassUnionResidueListRep ),
                         rec( m := m, r := r,
                              included := included, excluded := excluded ) );
    SetSize( result, infinity ); SetIsFinite( result, false );
    SetIsEmpty( result, false );
    rep := r[1]; pos := 1;
    while rep in excluded do
      pos := pos + 1;
      rep := r[pos mod Length(r) + 1] + Int(pos/Length(r)) * m;
    od;
    if   included <> [ ] and rep > Minimum( included ) 
    then rep := Minimum( included ); fi;
    SetRepresentative( result, rep );
    ReduceResidueClassUnion( result );
    if Length( result!.r ) = 1 then SetIsResidueClass( result, true ); fi;
    if IsOne( result!.m ) and result!.r = [ Zero( R ) ]
      and [ result!.included, result!.excluded ] = [ [ ], [ ] ]
    then return R; else return result; fi;
  end );

#############################################################################
##
#M  ResidueClassUnionCons( <filter>, <R>, <cls>, <included>, <excluded> )
##
InstallMethod( ResidueClassUnionCons,
               "class list rep., for Z (ResClasses)",
               ReturnTrue, [ IsResidueClassUnionOfZInClassListRep,
                             IsIntegers, IsList, IsList, IsList ], 0,

  function ( filter, R, cls, included, excluded )

    local  ReduceResidueClassUnion, result, m, both, rep, pos;

    ReduceResidueClassUnion := function ( U )

      local  R, cls, clsRed, m, ndpair, d1, d2, density, divs, d, i,
             partdens, cl, int, res, r, both;

      cls := U!.cls;
      cls := Set( cls, c -> [ c[1] mod c[2], AbsInt( c[2] ) ] );
      SortParallel( List( cls, Reversed ), cls );
      repeat
        ndpair := First(Combinations(cls,2),
                        c->(c[1][1]-c[2][1]) mod Gcd(c[1][2],c[2][2]) = 0);
        if ndpair <> fail then
          cls := Difference(cls,ndpair);
          d1 := DIFFERENCE_OF_RESIDUE_CLASSES(ndpair[1],ndpair[2]);
          d2 := DIFFERENCE_OF_RESIDUE_CLASSES(ndpair[2],ndpair[1]);
          if Length(d1) <= Length(d2) then
            Append(cls,d1); Add(cls,ndpair[2]);
          else
            Append(cls,d2); Add(cls,ndpair[1]);
          fi;
          cls := Filtered(cls,cl->cl<>[]);
        fi;
      until ndpair = fail;
      SortParallel( List( cls, Reversed ), cls );

      clsRed := [];
      m := U!.m;
      divs := DivisorsInt(m);
      density := Sum(List(cls,cl->1/cl[2]));
      for d in divs do
        if 1/d > density then continue; fi;
        res := Set(cls,cl->cl[1] mod d);
        for r in res do
          partdens := 0;
          for cl in cls do
            if (r - cl[1]) mod Gcd(d,cl[2]) = 0
            then partdens := partdens + 1/Lcm(d,cl[2]); fi;
          od;
          if partdens = 1/d then
            Add(clsRed,[r,d]);
            cls := List(cls,cl->DIFFERENCE_OF_RESIDUE_CLASSES(cl,[r,d]));
            cls := Filtered(Concatenation(cls),cl->cl<>[]);
            if cls = [] then break; fi;
            SortParallel( List( cls, Reversed ), cls );
            density := Sum(List(cls,cl->1/cl[2]));
          elif partdens > 1/d then Error("internal error"); fi;
        od;
        if cls = [] then break; fi;
      od;

      m := Lcm(List(clsRed,c->c[2]));
      SortParallel( List( clsRed, Reversed ), clsRed );
      U!.cls := Immutable(clsRed); U!.m := m;
      both := Intersection( U!.included, U!.excluded );
      U!.included := Difference( U!.included, both );
      U!.excluded := Difference( U!.excluded, both );
      U!.included := Immutable(Set(Filtered(U!.included,
                       n -> not ForAny(clsRed,c -> n mod c[2] = c[1]))));
      U!.excluded := Immutable(Set(Filtered(U!.excluded,
                       n -> ForAny(clsRed,c -> n mod c[2] = c[1]))));
      if clsRed = [] then U := U!.included; fi;
    end;

    if not IsIntegers(R) then TryNextMethod(); fi;
    if cls = [] then return Difference(included,excluded); fi;

    result := Objectify( NewType( ResidueClassUnionsFamily( Integers ),
                                  IsResidueClassUnionOfZ and
                                  IsResidueClassUnionClassListRep ),
                         rec( cls := cls, m := Lcm(List(cls,c->c[2])),
                              included := included, excluded := excluded ) );
    SetSize( result, infinity ); SetIsFinite( result, false );
    SetIsEmpty( result, false );

    if ValueOption("RCU_AlreadyReduced") <> true then
      ReduceResidueClassUnion( result );
      cls := result!.cls; m := result!.m;
      included := result!.included; excluded := result!.excluded;
    fi;

    rep := cls[1][1]; pos := 1;
    while rep in excluded do
      pos := pos + 1;
      rep := cls[pos mod Length(cls) + 1][1]
           + Int(pos/Length(cls)) * cls[pos mod Length(cls) + 1][2];
    od;
    if   included <> [ ] and rep > Minimum( included ) 
    then rep := Minimum( included ); fi;
    SetRepresentative( result, rep );

    if Length(result!.cls) = 1 then SetIsResidueClass(result,true); fi;
    if result!.m = 1 and result!.cls = [[0,1]]
      and [result!.included,result!.excluded] = [[],[]]
    then return Integers; else return result; fi;
  end );

#############################################################################
##
#M  ResidueClassUnionCons( <filter>, Integers^2,
##                         <L>, <r>, <included>, <excluded> )
##
InstallMethod( ResidueClassUnionCons,
               "residue list representation, for Z^2 (ResClasses)",
               ReturnTrue, [ IsResidueClassUnion, IsRowModule,
                             IsMatrix, IsList, IsList, IsList ], 0,

  function ( filter, ZxZ, L, r, included, excluded )

    local  ReduceResidueClassUnion, result, both, rep, pos;

    ReduceResidueClassUnion := function ( U )

      local  L, r, LRed, rRed, divs, d;

      L := HermiteNormalFormIntegerMat(U!.m);  LRed := L;
      r := List(U!.r,v->v mod L); rRed := r;
      divs := Superlattices(L);
      for d in divs do
        if DeterminantMat(L)/DeterminantMat(d) > Length(r) then continue; fi;
        rRed := Set(r,v->v mod d);
        if   Length(rRed) = Length(r)*DeterminantMat(d)/DeterminantMat(L)
        then LRed := d; break; fi;
      od;
      U!.m := LRed; U!.r := Immutable(rRed);
      U!.included := Immutable(Set(Filtered(U!.included,
                                            v->not v mod LRed in rRed)));
      U!.excluded := Immutable(Set(Filtered(U!.excluded,
                                            v->v mod LRed in rRed)));
    end;

    if not IsZxZ( ZxZ ) then TryNextMethod( ); fi;
    L := HermiteNormalFormIntegerMat( L );
    r := Set( r, v -> v mod L );
    both := Intersection( included, excluded );
    included := Difference( included, both );
    excluded := Difference( excluded, both );
    if r = [] then L := [[1,0],[0,1]]; excluded := []; fi;
    result := Objectify( NewType( ResidueClassUnionsFamily( ZxZ ),
                                  IsResidueClassUnionOfZxZ and
                                  IsResidueClassUnionResidueListRep ),
                         rec( m := L, r := r,
                              included := included, excluded := excluded ) );
    if r <> [] then
      SetSize( result, infinity ); SetIsFinite( result, false );
      SetIsEmpty( result, false );
    else
      SetSize( result, Length( included ) );
      SetIsEmpty( result, IsEmpty( included ) );
    fi;
    if not IsEmpty( result ) then
      if included <> [ ] then rep := included[ 1 ]; else
        rep := r[1]; pos := 1;
        while rep in excluded do
          pos := pos + 1;
          rep := r[pos mod Length(r) + 1] + Int(pos/Length(r)) * L[1];
        od;
      fi;
      SetRepresentative( result, rep );
    fi;
    if r <> [] then ReduceResidueClassUnion( result ); else
      MakeImmutable( result!.included ); MakeImmutable( result!.excluded );
    fi;
    if Length( result!.r ) = 1 then SetIsResidueClass( result, true ); fi;
    if AbsInt( DeterminantMat( result!.m ) ) = 1
      and result!.r = [ [ 0, 0 ] ]
      and [ result!.included, result!.excluded ] = [ [ ], [ ] ]
    then return ZxZ; else return result; fi;
  end );

#############################################################################
##
#M  ResidueClassUnionCons( <filter>, Integers^2,      ("modulus L as vector")
##                         <L>, <r>, <included>, <excluded> )
##
InstallOtherMethod( ResidueClassUnionCons,
                    "residue list rep, mod. as vector, for Z^2 (ResClasses)",
                    ReturnTrue, [ IsResidueClassUnion, IsRowModule,
                                  IsRowVector, IsList, IsList, IsList ], 0,

  function ( filter, ZxZ, L, r, included, excluded )
    return ResidueClassUnionCons( filter, ZxZ,
                                  DiagonalMat(L), r, included, excluded );
  end );

#############################################################################
##
#F  ResidueClassUnion( <R>, <m>, <r> ) . . . . . . . union of residue classes
#F  ResidueClassUnion( <R>, <m>, <r>, <included>, <excluded> )
#F  ResidueClassUnion( <R>, <cls> )
#F  ResidueClassUnion( <R>, <cls>, <included>, <excluded> )
##
InstallGlobalFunction( ResidueClassUnion,

  function ( arg )

    if    not (     Length(arg) in [3,5]
                and (    IsRing(arg[1]) and arg[2] in arg[1]
                      or     IsRowModule(arg[1]) and IsMatrix(arg[2])
                         and IsSubset(arg[1],arg[2])
                         and not IsZero(DeterminantMat(arg[2])) )
                and IsList(arg[3]) and IsSubset(arg[1],arg[3])
                and (    Length(arg) = 3 or IsList(arg[4]) and IsList(arg[5])
                     and IsSubset(arg[1],arg[4])
                     and IsSubset(arg[1],arg[5])) )
      and not (     Length(arg) in [2,4]
                and (IsRing(arg[1]) and IsList(arg[2])
                     and ForAll(arg[2],l->IsList(l) and Length(l) = 2
                                and IsSubset(arg[1],l) and not IsZero(l[2])))
                and (    Length(arg) = 2 or IsList(arg[3]) and IsList(arg[4])
                     and IsSubset(arg[1],arg[3])
                     and IsSubset(arg[1],arg[4])) )
    then Error("usage: ResidueClassUnion( <R>, <m>, <r> [, <included>",
               ", <excluded> ] )\nor ResidueClassUnion( <R>, <cls> ",
               "[, <included>, <excluded> ] ), for details see manual.\n");
         return fail;
    fi;
    return CallFuncList( ResidueClassUnionNC, arg );
  end );

#############################################################################
##
#F  ResidueClassUnionNC( <R>, <m>, <r> ) . . . . . . union of residue classes
#F  ResidueClassUnionNC( <R>, <m>, <r>, <included>, <excluded> )
#F  ResidueClassUnionNC( <R>, <cls> )
#F  ResidueClassUnionNC( <R>, <cls>, <included>, <excluded> )
##
InstallGlobalFunction( ResidueClassUnionNC,

  function ( arg )

    local  R, m, r, cls, included, excluded;

    if Length(arg) in [2,4] then
      R := arg[1]; cls := arg[2];
      if   Length(arg) = 4
      then included := Set(arg[3]); excluded := Set(arg[4]);
      else included := [];          excluded := []; fi;
      return ResidueClassUnionCons( IsResidueClassUnionOfZInClassListRep,
                                    R, cls, included, excluded );
    elif Length(arg) in [3,5] then
      R := arg[1]; m := arg[2]; r := Set(arg[3]);
      if   Length(arg) = 5
      then included := Set(arg[4]); excluded := Set(arg[5]);
      else included := [];          excluded := []; fi;
      return ResidueClassUnionCons( IsResidueClassUnion, R, m, r,
                                    included, excluded );
    fi;
  end );

#############################################################################
##
#F  ResidueClass( <R>, <m>, <r> ) . . . . . . . . . . .  residue class of <R>
#F  ResidueClass( <m>, <r> )  . residue class of the default ring of <m>, <r>
#F  ResidueClass( <r>, <m> )  . . . . . . . . . . . . . . . . . . .  ( dito )
##
InstallGlobalFunction( ResidueClass,

  function ( arg )

    local  R, m, r, d, cl, usage;

    usage := "usage: see ?ResidueClass\n";
    if   Length( arg ) = 3 then
      R := arg[1]; m := arg[2]; r := arg[3];
      if   not (    IsRing(R) and m in R and r in R and not IsZero(m)
                 or IsRowModule(R) and IsMatrix(m) and IsSubset(R,m)
                    and not IsZero(DeterminantMat(m)) )
      then Error( usage ); return fail; fi;
    elif Length( arg ) = 2 then
      if ForAll( arg, IsRingElement ) then
        if   IsPolynomial(arg[1])
        then R := DefaultRing(arg[1]); arg[2] := arg[2] * One(R);
        elif IsPolynomial(arg[2])
        then R := DefaultRing(arg[2]); arg[1] := arg[1] * One(R);
        else R := DefaultRing(arg); fi;
        m := Maximum( arg ); r := Minimum( arg );
        if IsZero( m ) then Error( usage ); return fail; fi;
      else
        if IsMatrix( arg[1] ) then m := arg[1]; r := arg[2];
                              else m := arg[2]; r := arg[1]; fi;
        if   not ( IsMatrix(m) and IsVector(r) )
        then Error( usage ); return fail; fi;
        d := Length(r);
        R := DefaultRing(r)^d;
        if not (     DimensionsMat(m) = [d,d] and IsSubset(R,m)
                 and RankMat(m) = d and r in R )
        then Error( usage ); return fail; fi;
      fi;
    elif Length( arg ) = 1 then
      if   IsList( arg[1] )
      then return CallFuncList( ResidueClass, arg[1] );
      elif IsResidueClass( arg[1] )
      then return arg[1];
      else Error( usage ); return fail; fi;
    else
      Error( usage ); return fail;
    fi;
    cl := ResidueClassUnionNC( R, m, [ r ] );
    SetIsResidueClass( cl, true );
    return cl;
  end );

#############################################################################
##
#F  ResidueClassNC( <R>, <m>, <r> ) . . . . . . . . . .  residue class of <R>
#F  ResidueClassNC( <m>, <r> )  residue class of the default ring of <m>, <r>
#F  ResidueClassNC( <r>, <m> )  . . . . . . . . . . . . . . . . . .  ( dito )
##
InstallGlobalFunction( ResidueClassNC,

  function ( arg )

    local  R, m, r, d, cl;

    if   Length( arg ) = 3 then
      R := arg[1]; m := arg[2]; r := arg[3];
    elif Length( arg ) = 2 then
      if ForAll(arg,IsRingElement) then
        R := DefaultRing( arg ); 
        m := Maximum( arg ); r := Minimum( arg );
      else
        if IsMatrix(arg[1]) then m := arg[1]; r := arg[2];
                            else m := arg[2]; r := arg[1]; fi;
        d := Length(r);
        R := DefaultRing(r)^d;
      fi;
    elif Length( arg ) = 1 then return CallFuncList(ResidueClassNC,arg[1]);
    else return fail; fi;
    cl := ResidueClassUnionNC( R, m, [ r ] );
    SetIsResidueClass( cl, true );
    return cl;
  end );

#############################################################################
##
#M  IsResidueClass( <obj> ) . . . . . . . . . . . . . . . . .  general method
##
InstallMethod( IsResidueClass,
               "general method (ResClasses)", true, [ IsObject ], 0,

  function ( obj )
    if IsRing(obj) then return true; fi;
    if    IsResidueClassUnionInResidueListRep(obj)
      and Length(obj!.r) = 1 and obj!.included = [] and obj!.excluded = []
    then return true; fi;
    if    IsResidueClassUnionInClassListRep(obj)
      and Length(obj!.cls) = 1 and obj!.included = [] and obj!.excluded = []
    then return true; fi;
    return false;
  end );

#############################################################################
##
#S  ExtRepOfObj / ObjByExtRep for residue class unions. /////////////////////
##
#############################################################################

#############################################################################
##
#M  ExtRepOfObj( <U> ) . . . . . . . . . . . . . . . for residue class unions
##
InstallMethod( ExtRepOfObj,
               "for residue class unions (ResClasses)",
               true, [ IsResidueClassUnion ], 0,
               U -> [ Modulus( U ), ShallowCopy( Residues( U ) ),
                      ShallowCopy( IncludedElements( U ) ),
                      ShallowCopy( ExcludedElements( U ) ) ] );

#############################################################################
##
#M  ExtRepOfObj( <U> ) . . . . . . . . . . . . . . . for residue class unions
##
InstallMethod( ExtRepOfObj,
               "for residue class unions in standard rep. (ResClasses)",
               true, [ IsResidueClassUnionInResidueListRep ], 0,
               U -> [U!.m, ShallowCopy( U!.r ),
                     ShallowCopy(U!.included), ShallowCopy(U!.excluded)] );

#############################################################################
##
#M  ObjByExtRep( <fam>, <l> ) . . . . . . . reconstruct a residue class union
##
InstallMethod( ObjByExtRep,
               "reconstruct a residue class union (ResClasses)",
               ReturnTrue, [ IsFamily, IsList ], 0,

  function ( fam, l )

    local  R;

    if not HasUnderlyingRing(fam) or Length(l) <> 4 then TryNextMethod(); fi;
    R := UnderlyingRing(fam);
    if fam <> ResidueClassUnionsFamily(R) then TryNextMethod(); fi;
    return ResidueClassUnion(R,l[1],l[2],l[3],l[4]);
  end );

#############################################################################
##
#S  Accessing the components of a residue class union object. ///////////////
##
#############################################################################

#############################################################################
##
#M  Modulus( <U> ) . . . . . . . . . . . . . . . . . for residue class unions
#M  Modulus( <R> ) . . . . . . . . . . . . . . .  for the base ring / -module
#M  Modulus( <l> ) . . . . . . . . . . . . . . . . . . . . .  for finite sets
##
##  Since the empty list carries no information about the objects it does
##  not contain, the method for that case silently assumes that these are
##  supposed to be integers, and returns 0.
##
InstallMethod( Modulus,
               "for residue class unions, standard rep. (ResClasses)", true,
               [ IsResidueClassUnionInResidueListRep ], 0, U -> U!.m );
InstallMethod( Modulus,
               "for residue class unions, sparse rep. (ResClasses)", true,
               [ IsResidueClassUnionInClassListRep ], 0, U -> U!.m );
InstallOtherMethod( Modulus, "for the base ring (ResClasses)", true,
                    [ IsRing ], 0, One );
InstallOtherMethod( Modulus, "for the base module (ResClasses)", true,
                    [ IsRowModule ], 0, R -> AsList( Basis( R ) ) );
InstallOtherMethod( Modulus, "for finite sets (ResClasses)", true,
                    [ IsList ], 0, l -> Zero( l[ 1 ] ) );
InstallOtherMethod( Modulus, "for the empty set (ResClasses)", true,
                    [ IsList and IsEmpty ], 0, empty -> 0 );

#############################################################################
##
#M  Residue( <cl> ) . . . . . . . . . . . . . . . . . . . for residue classes
#M  Residue( <R> ) . . . . . . . . . . . . . . .  for the base ring / -module
##
InstallMethod( Residue, "for residue classes (ResClasses)", true,
               [ IsResidueClass ], 0, cl -> Residues(cl)[1] );
InstallOtherMethod( Residue, "for the base ring (ResClasses)", true,
                    [ IsRing ], 0, Zero );
InstallOtherMethod( Residue, "for the base module (ResClasses)", true,
                    [ IsRowModule ], 0, Zero );

#############################################################################
##
#M  Residues( <U> ) . . . . . . . . . . . . . . . .  for residue class unions
#M  Residues( <R> ) . . . . . . . . . . . . . . . for the base ring / -module
#M  Residues( <l> ) . . . . . . . . . . . . . . . . . . . . . for finite sets
##
InstallMethod( Residues,
               "for residue class unions of Z in sparse rep (ResClasses)",
               true, [ IsResidueClassUnionOfZInClassListRep ], 0,

  function ( U )

    local  res, cls, m, cl, i;

    cls := U!.cls; m := U!.m; res := [];
    for cl in cls do
      for i in [0..m/cl[2]-1] do
        Add(res,i*cl[2]+cl[1]);
      od;
    od;
    res := Set(res);
    return res;
  end );

InstallMethod( Residues, "for residue class unions (ResClasses)", true,
               [ IsResidueClassUnionInResidueListRep ], 0, U -> U!.r );
InstallOtherMethod( Residues, "for the base ring (ResClasses)", true,
                    [ IsRing ], 0, R -> [ Zero( R ) ] );
InstallOtherMethod( Residues, "for the base module (ResClasses)", true,
                    [ IsRowModule ], 0, R -> [ Zero( R ) ] );
InstallOtherMethod( Residues, "for finite sets (ResClasses)", true,
                    [ IsList ], 0, l -> [  ] );

#############################################################################
##
#M  Classes( <U> ) . . . . . . . . . . . . . . . . . for residue class unions
##
InstallMethod( Classes, "for residue class unions, sparse rep. (ResClasses)",
               true, [ IsResidueClassUnionInClassListRep ], 0, U -> U!.cls );
InstallMethod( Classes, "for residue class unions, std. rep. (ResClasses)",
               true, [ IsResidueClassUnionInResidueListRep ], 0,
               U -> List(AsUnionOfFewClasses(U),
                         cl->[Residue(cl),Modulus(cl)]) );
InstallOtherMethod( Classes, "for the base ring (ResClasses)",
                    true, [ IsRing ], 0, R -> [ [ Zero(R), One(R) ] ] );
InstallOtherMethod( Classes, "for finite sets (ResClasses)",
                    true, [ IsList ], 0, R -> [  ] );

#############################################################################
##
#M  IncludedElements( <U> ) . . . . . . . . . . . .  for residue class unions
#M  IncludedElements( <R> ) . . . . . . . . . . . for the base ring / -module
#M  IncludedElements( <l> ) . . . . . . . . . . . . . . . . . for finite sets
##
InstallMethod( IncludedElements, "for residue class unions (ResClasses)",
               true, [ IsResidueClassUnionInResidueListRep ], 0,
               U -> U!.included );
InstallMethod( IncludedElements, "for residue class unions (ResClasses)",
               true, [ IsResidueClassUnionInClassListRep ], 0,
               U -> U!.included );
InstallOtherMethod( IncludedElements, "for the base ring (ResClasses)",
                    true, [ IsRing ], 0, R -> [ ] );
InstallOtherMethod( IncludedElements, "for the base module (ResClasses)",
                    true, [ IsRowModule ], 0, R -> [ ] );
InstallOtherMethod( IncludedElements, "for finite sets (ResClasses)",
                    true, [ IsList ], 0, l -> l );

#############################################################################
##
#M  ExcludedElements( <U> ) . . . . . . . . . . . .  for residue class unions
#M  ExcludedElements( <R> ) . . . . . . . . . . . for the base ring / -module
#M  ExcludedElements( <l> ) . . . . . . . . . . . . . . . . . for finite sets
##
InstallMethod( ExcludedElements, "for residue class unions (ResClasses)",
               true, [ IsResidueClassUnionInResidueListRep ], 0,
               U -> U!.excluded );
InstallMethod( ExcludedElements, "for residue class unions (ResClasses)",
               true, [ IsResidueClassUnionInClassListRep ], 0,
               U -> U!.excluded );
InstallOtherMethod( ExcludedElements, "for the base ring (ResClasses)",
                    true, [ IsRing ], 0, R -> [ ] );
InstallOtherMethod( ExcludedElements, "for the base module (ResClasses)",
                    true, [ IsRowModule ], 0, R -> [ ] );
InstallOtherMethod( ExcludedElements, "for finite sets (ResClasses)",
                    true, [ IsList ], 0, l -> [ ] );

#############################################################################
##
#M  SparseRep( <U> ) . . . conversion to class list ("sparse") representation
##
InstallMethod( SparseRep,
               "for residue class unions in standard rep. (ResClasses)",
               true, [ IsResidueClassUnionInResidueListRep ], 0,
               U -> ResidueClassUnionNC(UnderlyingRing(FamilyObj(U)),
                                        List(AsUnionOfFewClasses(U),
                                             cl->[Residue(cl),Modulus(cl)]),
                                        U!.included,U!.excluded) );
InstallMethod( SparseRep,
               "for residue class unions in sparse rep (ResClasses)",
               true, [ IsResidueClassUnionInClassListRep ], 0, U -> U );
InstallMethod( SparseRep,
               "for finite sets (ResClasses)",
               true, [ IsList ], 0, l -> l );
InstallMethod( SparseRep,
               "for the base ring (ResClasses)",
               true, [ IsRing ], 0, R -> R );
InstallMethod( SparseRep,
               "for the base module (ResClasses)",
               true, [ IsRowModule ], 0, R -> R );

#############################################################################
##
#M  StandardRep( <U> ) . . . . . conversion to residue list ("standard") rep.
##
InstallMethod( StandardRep,
               "for residue class unions in sparse rep. (ResClasses)",
               true, [ IsResidueClassUnionInClassListRep ], 0,
               U -> ResidueClassUnionNC(UnderlyingRing(FamilyObj(U)),
                                        Modulus(U),Residues(U),
                                        U!.included,U!.excluded) );
InstallMethod( StandardRep,
               "for residue class unions in standard rep. (ResClasses)",
               true, [ IsResidueClassUnionInResidueListRep ], 0, U -> U );
InstallMethod( StandardRep,
               "for finite sets (ResClasses)",
               true, [ IsList ], 0, l -> l );
InstallMethod( StandardRep,
               "for the base ring (ResClasses)",
               true, [ IsRing ], 0, R -> R );
InstallMethod( StandardRep,
               "for the base module (ResClasses)",
               true, [ IsRowModule ], 0, R -> R );

#############################################################################
##
#S  Testing residue class unions for equality. //////////////////////////////
##
#############################################################################

#############################################################################
##
#M  \=( <U1>, <U2> ) . . . . . . . . . . . . . . . . for residue class unions
##
InstallMethod( \=,
               "for two residue class unions in standard rep. (ResClasses)",
               IsIdenticalObj,
               [ IsResidueClassUnionInResidueListRep,
                 IsResidueClassUnionInResidueListRep ], 0,

  function ( U1, U2 )
    return U1!.m = U2!.m and U1!.r = U2!.r
           and U1!.included = U2!.included and U1!.excluded = U2!.excluded;
  end );

InstallMethod( \=,
               "for two residue class unions in sparse rep. (ResClasses)",
               IsIdenticalObj,
               [ IsResidueClassUnionInClassListRep,
                 IsResidueClassUnionInClassListRep ], 0,

  function ( U1, U2 )
    return U1!.m = U2!.m and U1!.cls = U2!.cls
           and U1!.included = U2!.included and U1!.excluded = U2!.excluded;
  end );

InstallMethod( \=,
               "for two residue class unions in different rep. (ResClasses)",
               IsIdenticalObj,
               [ IsResidueClassUnionInResidueListRep,
                 IsResidueClassUnionInClassListRep ], 0,
               function ( U1, U2 ) return SparseRep(U1) = U2; end );

InstallMethod( \=,
               "for two residue class unions in different rep. (ResClasses)",
               IsIdenticalObj,
               [ IsResidueClassUnionInClassListRep,
                 IsResidueClassUnionInResidueListRep ], 0,
               function ( U1, U2 ) return U1 = SparseRep(U2); end );


#############################################################################
##
#M  \=( <U>, <l> ) . . . . . . . . . . . for a residue class union and a list
#M  \=( <l>, <U> ) . . . . . . . . . . . for a list and a residue class union
##
InstallMethod( \=, "for a residue class union and a list (ResClasses)",
               ReturnTrue, [ IsResidueClassUnionInResidueListRep, IsList ],
               SUM_FLAGS,
               function ( U, l )
                 return IsOne(U!.m) and U!.r = [] and U!.included = l;
               end );

InstallMethod( \=, "for a list and a residue class union (ResClasses)",
               ReturnTrue, [ IsList, IsResidueClassUnionInResidueListRep ],
               SUM_FLAGS, function ( l, U ) return U = l; end );

#############################################################################
##
#M  \=( <D>, <l> ) . . . . . .  for an infinite domain and a list of elements
#M  \=( <l>, <D> ) . . . . . .  for a list of elements and an infinite domain
##
InstallMethod( \=,
               "for an infinite domain and a list of elements (ResClasses)", 
               IsIdenticalObj, [ IsDomain, IsList and IsFinite ], 0,
               function ( D, l )
                 if   not IsFinite( D ) then return false;
                 else TryNextMethod(  ); fi;
               end );
InstallMethod( \=,
               "for a list of elements and an infinite domain (ResClasses)", 
               IsIdenticalObj, [ IsList and IsFinite, IsDomain ], 0,
               function ( l, D ) return D = l; end );

#############################################################################
##
#M  \<( <U1>, <U2> ) . . . . . . . . . . . . . . . . for residue class unions
##
##  A total ordering of residue class unions - we want to be able to form
##  sorted lists and sets of these objects.
##
InstallMethod( \<,
               "for two residue class unions in standard rep. (ResClasses)",
               IsIdenticalObj,
               [ IsResidueClassUnionInResidueListRep,
                 IsResidueClassUnionInResidueListRep ], 0,

  function ( U1, U2 )
    if   U1!.r = []  and U2!.r <> [] then return false;
    elif U1!.r <> [] and U2!.r = []  then return true;
    elif U1!.m <> U2!.m then return U1!.m < U2!.m;
    elif U1!.r <> U2!.r then return U1!.r < U2!.r;
    elif U1!.included <> U2!.included
    then return U1!.included < U2!.included;
    else return U1!.excluded < U2!.excluded; fi;
  end );

InstallMethod( \<,
               "for two residue class unions in sparse rep. (ResClasses)",
               IsIdenticalObj,
               [ IsResidueClassUnionInClassListRep,
                 IsResidueClassUnionInClassListRep ], 0,

  function ( U1, U2 )
    if   U1!.m <> U2!.m then return U1!.m < U2!.m;
    elif List(U1!.cls,cl->cl[2]) <> List(U2!.cls,cl->cl[2])
    then return List(U1!.cls,cl->cl[2]) < List(U2!.cls,cl->cl[2]);
    elif U1!.cls <> U2!.cls then return U1!.cls < U2!.cls;
    elif U1!.included <> U2!.included
    then return U1!.included < U2!.included;
    else return U1!.excluded < U2!.excluded; fi;
  end );

InstallMethod( \<,
               "for two residue class unions, mixed rep. (ResClasses)",
               IsIdenticalObj,
               [ IsResidueClassUnionInResidueListRep,
                 IsResidueClassUnionInClassListRep ], 0,

  function ( U1, U2 )
    Error("residue class unions in different representations ",
          "cannot be sorted\n-- convert to same representation first");
    return fail;
  end );

InstallMethod( \<,
               "for two residue class unions, mixed rep. (ResClasses)",
               IsIdenticalObj,
               [ IsResidueClassUnionInClassListRep,
                 IsResidueClassUnionInResidueListRep ], 0,

  function ( U1, U2 )
    Error("residue class unions in different representations ",
          "cannot be sorted\n-- convert to same representation first");
    return fail;
  end );

#############################################################################
##
#M  \<( <U>, <R> ) . . . . . .  for a residue class union and a ring / module
#M  \<( <R>, <U> ) . . . . . .  for a ring / module and a residue class union
#M  \<( <l>, <R> ) . . . .  for a finite list of elements and a ring / module
#M  \<( <R>, <l> ) . . . .  for a ring / module and a finite list of elements
#M  \<( <l>, <U> ) .  for a finite list of elements and a residue class union
#M  \<( <U>, <l> ) .  for a residue class union and a finite list of elements
##
InstallMethod( \<, "for a residue class union and a ring (ResClasses)",
               ReturnTrue, [ IsResidueClassUnion, IsRing ], 0, ReturnFalse );
InstallMethod( \<, "for a residue class union and a module (ResClasses)",
               ReturnTrue, [ IsResidueClassUnion, IsRowModule ], 0,
               ReturnFalse );
InstallMethod( \<, "for a ring and a residue class union (ResClasses)",
               ReturnTrue, [ IsRing, IsResidueClassUnion ], 0, ReturnTrue );
InstallMethod( \<, "for a module and a residue class union (ResClasses)",
               ReturnTrue, [ IsRowModule, IsResidueClassUnion ], 0,
               ReturnTrue );
InstallMethod( \<, "for a list of elements and a ring (ResClasses)",
               IsIdenticalObj, [ IsList, IsRing ], 0,
  function ( list, R )
    if not IsIntegers(R) and not IsZ_pi(R)
       and not (     IsUnivariatePolynomialRing(R)
                 and IsFiniteFieldPolynomialRing(R))
    then TryNextMethod(); fi;
    return false;
   end );

InstallMethod( \<, "for a list of elements and a module (ResClasses)",
               IsIdenticalObj, [ IsList, IsRowModule ], 0, ReturnFalse );
InstallMethod( \<, "for a ring and a list of elements (ResClasses)",
               IsIdenticalObj, [ IsRing, IsList ], 0,
  function ( R, list )
    if not IsIntegers(R) and not IsZ_pi(R)
       and not (     IsUnivariatePolynomialRing(R)
                 and IsFiniteFieldPolynomialRing(R))
    then TryNextMethod(); fi;
    return true;
   end );

InstallMethod( \<, "for a module and a list of elements (ResClasses)",
               IsIdenticalObj, [ IsRowModule, IsList ], 0, ReturnTrue );
InstallMethod( \<, "for a list and a residue class union (ResClasses)",
               ReturnTrue, [ IsList, IsResidueClassUnion ], 0, ReturnFalse );
InstallMethod( \<, "for a residue class union and a list (ResClasses)",
               ReturnTrue, [ IsResidueClassUnion, IsList ], 0,
               function ( U, l )
                 if   IsFinite(U) then return AsList(U) < l;
                 else return true; fi;
               end );

#############################################################################
##
#S  Testing for membership in a residue class union. ////////////////////////
##
#############################################################################

#############################################################################
##
#M  \in( <n>, <U> ) . . . . . .  for a ring element and a residue class union
##
InstallMethod( \in,
               Concatenation("for a ring element and a residue class union ",
                             "in standard rep. (ResClasses)"),
               ReturnTrue,
               [ IsObject, IsResidueClassUnionInResidueListRep ], 0,

  function ( n, U )
    if not n in UnderlyingRing(FamilyObj(U)) then return false; fi;
    if   n in U!.included then return true;
    elif n in U!.excluded then return false;
    else return n mod U!.m in U!.r; fi;
  end );

InstallMethod( \in,
               Concatenation("for a ring element and a residue class union ",
                             "in sparse rep. (ResClasses)"),
               ReturnTrue,
               [ IsObject, IsResidueClassUnionInClassListRep ], 0,

  function ( n, U )
    if not n in UnderlyingRing(FamilyObj(U)) then return false; fi;
    if   n in U!.included then return true;
    elif n in U!.excluded then return false;
    else return ForAny(U!.cls,cl->n mod cl[2] = cl[1]); fi;
  end );

#############################################################################
##
#S  Density and subset relations. ///////////////////////////////////////////
##
#############################################################################

#############################################################################
##
#M  Density( <U> ) . . . . . . . . . . . . . . . . . for residue class unions
#M  Density( <R> ) . . . . . . . . . . . .  for the whole base ring / -module
#M  Density( <l> ) . . . . . . . . . . . . . . . . . . . . .  for finite sets
##
InstallMethod( Density,
               "for residue class unions in standard rep. (ResClasses)",
               true, [ IsResidueClassUnionInResidueListRep ], 0,
               U -> Length(Residues(U))/
                    NumberOfResidues(UnderlyingRing(FamilyObj(U)),
                                     Modulus(U)) );
InstallMethod( Density,
               "for residue class unions in sparse rep. (ResClasses)",
               true, [ IsResidueClassUnionOfZInClassListRep ], 0,
               U -> Sum(List(U!.cls,cl->1/cl[2])) );

InstallOtherMethod( Density, "for the whole base ring (ResClasses)", true,
                    [ IsRing ], 0, R -> 1 );
InstallOtherMethod( Density, "for the whole base module (ResClasses)", true,
                    [ IsRowModule ], 0, R -> 1 );
InstallOtherMethod( Density, "for finite sets (ResClasses)", true,
                    [ IsList and IsCollection ], 0,
                    function ( l )
                      if   not IsFinite(DefaultRing(l[1]))
                      then return 0; else TryNextMethod(); fi;
                    end );
InstallOtherMethod( Density, "for the empty set (ResClasses)", true,
                    [ IsList and IsEmpty ], 0, l -> 0 );

#############################################################################
##
#M  IsSubset( <U>, <l> ) . . .  for a residue class union and an element list
##
InstallMethod( IsSubset,
               "for residue class union and element list (ResClasses)",
               ReturnTrue, [ IsResidueClassUnion, IsList ], 0,

  function ( U, l )
    return ForAll( Set( l ), n -> n in U );
  end );

#############################################################################
##
#M  IsSubset( <U1>, <U2> ) . .  for two residue class unions in standard rep.
##
InstallMethod( IsSubset,
               "for two residue class unions in standard rep. (ResClasses)",
               IsIdenticalObj,
               [ IsResidueClassUnionInResidueListRep,
                 IsResidueClassUnionInResidueListRep ], 0,

  function ( U1, U2 )

    local  R, m1, m2, m, r1, r2, r, allres1, allres2, allres;

    R := UnderlyingRing(FamilyObj(U1));
    m1 := U1!.m; m2 := U2!.m;
    r1 := U1!.r; r2 := U2!.r;
    if   not IsSubset(U1,U2!.included) or Intersection(U1!.excluded,U2) <> []
    then return false; fi;
    if   IsRing(R)      then m := Lcm(R,m1,m2);
    elif IsRowModule(R) then m := LatticeIntersection(m1,m2); fi;
    allres  := AllResidues(R,m);
    allres1 := Filtered(allres,n->n mod m1 in r1);
    allres2 := Filtered(allres,n->n mod m2 in r2);
    return IsSubset(allres1,allres2);
  end );

#############################################################################
##
#M  IsSubset( <U1>, <U2> ) . . .  for two residue class unions in sparse rep.
##
InstallMethod( IsSubset,
               "for two residue class unions in sparse rep. (ResClasses)",
               IsIdenticalObj,
               [ IsResidueClassUnionInClassListRep,
                 IsResidueClassUnionInClassListRep ], 0,

  function ( U1, U2 )

    if Density(U2) > Density(U1) then return false; fi; 
    if   not IsSubset(U1,U2!.included) or Intersection(U1!.excluded,U2) <> []
    then return false; fi;

    return Difference(U2,U1) = [];
  end );

#############################################################################
##
#M  IsSubset( <U1>, <U2> ) . . for two residue class unions in different rep.
##
InstallMethod( IsSubset,
               "for two residue class unions in different rep. (ResClasses)",
               IsIdenticalObj,
               [ IsResidueClassUnionInResidueListRep,
                 IsResidueClassUnionInClassListRep ], 0,
               function ( U1, U2 ) return IsSubset(SparseRep(U1),U2); end );
InstallMethod( IsSubset,
               "for two residue class unions in different rep. (ResClasses)",
               IsIdenticalObj,
               [ IsResidueClassUnionInClassListRep,
                 IsResidueClassUnionInResidueListRep ], 0,
               function ( U1, U2 ) return IsSubset(U1,SparseRep(U2)); end );

#############################################################################
##
#M  IsSubset( <R>, <U> ) . . . .  for the base ring and a residue class union
#M  IsSubset( <U>, <R> ) . . . .  for a residue class union and the base ring
##
InstallMethod( IsSubset,
               "for the base ring and a residue class union (ResClasses)",
               ReturnTrue, [ IsDomain, IsResidueClassUnion ], 0,
               function ( R, U )
                 if   R = UnderlyingRing(FamilyObj(U))
                 then return true; else TryNextMethod(); fi;
               end );

InstallMethod( IsSubset,
               "for a residue class union and the base ring (ResClasses)",
               ReturnTrue, [ IsResidueClassUnion, IsDomain ], 0,
               function ( U, R )
                 if   R = UnderlyingRing(FamilyObj(U))
                 then return U = R; else TryNextMethod(); fi;
               end );

#############################################################################
##
#M  IsSubset( Z_pi( <pi> ), Rationals ) . . . . . . . . . . .  for Z_pi and Q
##
InstallMethod( IsSubset, "for Z_pi and Rationals (ResClasses)",
               ReturnTrue, [ IsZ_pi, IsRationals ], 0, ReturnFalse );

#############################################################################
##
#S  Computing unions, intersections and differences. ////////////////////////
##
#############################################################################

#############################################################################
##
#M  Union2( <U1>, <U2> ) . . . . .  for residue class unions in standard rep.
##
InstallMethod( Union2,
               "for two residue class unions in standard rep. (ResClasses)",
               IsIdenticalObj,
               [ IsResidueClassUnionInResidueListRep,
                 IsResidueClassUnionInResidueListRep ], 0,

  function ( U1, U2 )

    local  R, m1, m2, m, r1, r2, r, included, excluded,
           r1exp, r2exp, allres;

    R := UnderlyingRing(FamilyObj(U1));
    m1 := U1!.m; m2 := U2!.m;
    r1 := U1!.r; r2 := U2!.r;
    if   IsRing(R)      then m := Lcm(R,m1,m2);
    elif IsRowModule(R) then m := LatticeIntersection(m1,m2); fi;
    included := Union(U1!.included,U2!.included);
    excluded := Difference(Union(Difference(U1!.excluded,U2),
                                 Difference(U2!.excluded,U1)),included);
    if IsIntegers(R) then
      r1exp := Concatenation(List([0..m/m1-1],i->i*m1+r1));
      r2exp := Concatenation(List([0..m/m2-1],i->i*m2+r2));
      r     := Union(r1exp,r2exp);
    else
      allres := AllResidues(R,m);
      r := Filtered(allres,n->n mod m1 in r1 or n mod m2 in r2);
    fi;
    return ResidueClassUnionNC(R,m,r,included,excluded);
  end );

#############################################################################
##
#M  Union2( <U1>, <U2> ) . . . . . .  for residue class unions in sparse rep.
##
InstallMethod( Union2,
               "for two residue class unions in sparse rep. (ResClasses)",
               IsIdenticalObj,
--> --------------------

--> maximum size reached

--> --------------------

[ Verzeichnis aufwärts0.12unsichere 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