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


Quelle  HomalgRing.gi   Sprache: unbekannt

 
# SPDX-License-Identifier: GPL-2.0-or-later
# MatricesForHomalg: Matrices for the homalg project
#
# Implementations
#

####################################
#
# representations:
#
####################################

##  <#GAPDoc Label="IsHomalgInternalRingRep">
##  <ManSection>
##    <Filt Type="Representation" Arg="R" Name="IsHomalgInternalRingRep"/>
##    <Returns><C>true</C> or <C>false</C></Returns>
##    <Description>
##      The internal representation of &homalg; rings. <P/>
##      (It is a representation of the &GAP; category <C>IsHomalgRing</C>.)
##    </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareRepresentation( "IsHomalgInternalRingRep",
        IsHomalgRing and IsHomalgRingOrFinitelyPresentedModuleRep,
        [ "ring", "homalgTable" ] );

##
DeclareRepresentation( "IsContainerForWeakPointersOnIdentityMatricesRep",
        IsContainerForWeakPointersRep,
        [ "weak_pointers" ] );

####################################
#
# families and types:
#
####################################

# a new family:
BindGlobal( "TheFamilyOfHomalgRingElements",
        NewFamily( "TheFamilyOfHomalgRingElements" ) );

# a new family:
BindGlobal( "TheFamilyOfHomalgRings",
        CollectionsFamily( TheFamilyOfHomalgRingElements ) );

# a new type:
BindGlobal( "TheTypeHomalgInternalRing",
        NewType( TheFamilyOfHomalgRings,
                IsHomalgInternalRingRep ) );

# a new family:
BindGlobal( "TheFamilyOfContainersForWeakPointersOfIdentityMatrices",
        NewFamily( "TheFamilyOfContainersForWeakPointersOfIdentityMatrices" ) );

# a new type:
BindGlobal( "TheTypeContainerForWeakPointersOnIdentityMatrices",
        NewType( TheFamilyOfContainersForWeakPointersOfIdentityMatrices,
                IsContainerForWeakPointersOnIdentityMatricesRep ) );

####################################
#
# global variables:
#
####################################

##
InstallValue( CommonHomalgTableForRings,
        rec(
            RingName :=
              function( R )
                local minimal_polynomial, var, brackets, r;
                
                if IsBound( R!.MinimalPolynomialOfPrimitiveElement ) then
                    minimal_polynomial := R!.MinimalPolynomialOfPrimitiveElement;
                fi;
                
                ## the Weyl algebra (relative version):
                if HasRelativeIndeterminateDerivationsOfRingOfDerivations( R ) then
                    
                    var := RelativeIndeterminateDerivationsOfRingOfDerivations( R );
                    
                    brackets := [ "<", ">" ];
                    
                ## the Weyl algebra:
                elif HasIndeterminateDerivationsOfRingOfDerivations( R ) then
                    
                    var := IndeterminateDerivationsOfRingOfDerivations( R );
                    
                    brackets := [ "<", ">" ];
                    
                ## the exterior algebra (relative version):
                elif HasRelativeIndeterminateAntiCommutingVariablesOfExteriorRing( R ) then
                    
                    var := RelativeIndeterminateAntiCommutingVariablesOfExteriorRing( R );
                    
                    brackets := [ "{", "}" ];
                    
                ## the exterior algebra:
                elif HasIndeterminateAntiCommutingVariablesOfExteriorRing( R ) then
                    
                    var := IndeterminateAntiCommutingVariablesOfExteriorRing( R );
                    
                    brackets := [ "{", "}" ];
                    
                ## the pseudo shift algebra:
                elif HasIndeterminateShiftsOfShiftAlgebra( R ) then
                    
                    var := IndeterminateShiftsOfShiftAlgebra( R );
                    
                    brackets := [ "<", ">" ];
                    
                ## the pseudo shift algebra:
                elif HasIndeterminateShiftsOfRationalShiftAlgebra( R ) then
                    
                    var := IndeterminateShiftsOfRationalShiftAlgebra( R );
                    
                    brackets := [ "<", ">" ];
                    
                ## the pseudo double-shift algebra:
                elif HasIndeterminateShiftsOfPseudoDoubleShiftAlgebra( R ) then
                    
                    var := IndeterminateShiftsOfPseudoDoubleShiftAlgebra( R );
                    
                    brackets := [ "<", ">" ];
                    
                ## the pseudo double-shift algebra:
                elif HasIndeterminateShiftsOfRationalPseudoDoubleShiftAlgebra( R ) then
                    
                    var := IndeterminateShiftsOfRationalPseudoDoubleShiftAlgebra( R );
                    
                    brackets := [ "<", ">" ];
                    
                ## the biased double-shift algebra:
                elif HasIndeterminateShiftsOfBiasedDoubleShiftAlgebra( R ) then
                    
                    var := IndeterminateShiftsOfBiasedDoubleShiftAlgebra( R );
                    
                    brackets := [ "<", ">" ];
                    
                ## the (free) polynomial ring (relative version):
                elif HasBaseRing( R ) and HasRelativeIndeterminatesOfPolynomialRing( R ) and
                  not IsIdenticalObj( R, BaseRing( R ) ) then
                    
                    var := RelativeIndeterminatesOfPolynomialRing( R );
                    
                    brackets := [ "[", "]" ];
                    
                ## the (free) polynomial ring:
                elif HasIndeterminatesOfPolynomialRing( R ) then
                    
                    var := IndeterminatesOfPolynomialRing( R );
                    
                    brackets := [ "[", "]" ];
                    
                elif HasRationalParameters( R ) then
                    
                    var := RationalParameters( R );
                    
                    if IsBound( minimal_polynomial ) then
                        brackets := [ "[", "]" ];
                    else
                        brackets := [ "(", ")" ];
                    fi;
                    
                fi;
                
                if not IsBound( var ) then
                    return fail;
                fi;
                
                var := JoinStringsWithSeparator( List( var, String ) );
                
                var := Concatenation( brackets[1], var, brackets[2] );
                
                if HasBaseRing( R ) and HasCoefficientsRing( R ) and
                   not IsIdenticalObj( BaseRing( R ), CoefficientsRing( R ) ) then
                    r := RingName( BaseRing( R ) );
                elif HasCoefficientsRing( R ) then
                    r := CoefficientsRing( R );
                    if IsBound( r!.MinimalPolynomialOfPrimitiveElement ) and IsSubset( RingName( r ), "/" ) then
                        r := Concatenation( "(", RingName( r ), ")" );
                    else
                        r := RingName( r );
                    fi;
                else
                    r := "(some ring)";
                fi;
                
                r := Concatenation( r, var );
                
                if IsBound( minimal_polynomial ) then
                    r := Concatenation( r, "/(", minimal_polynomial, ")" );
                fi;
                
                return String( r );
                
            end,
         
         )
);

####################################
#
# methods for attributes:
#
####################################

##
InstallMethod( Zero,
        "for homalg rings",
        [ IsHomalgInternalRingRep ], 10001,
        
  function( R )
    
    return Zero( R!.ring );
    
end );

##
InstallMethod( Zero,
        "for homalg rings",
        [ IsHomalgInternalRingRep ], 10001,
        
  function( R )
    local RP;
    
    RP := homalgTable( R );
    
    if IsBound( RP!.Zero ) then
        return RP!.Zero;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( One,
        "for homalg rings",
        [ IsHomalgInternalRingRep ], 1001,
        
  function( R )
    
    return One( R!.ring );
    
end );

##
InstallMethod( One,
        "for homalg rings",
        [ IsHomalgInternalRingRep ], 1001,
        
  function( R )
    local RP;
    
    RP := homalgTable( R );
    
    if IsBound( RP!.One ) then
        return RP!.One;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( MinusOne,
        "for homalg rings",
        [ IsHomalgInternalRingRep ],
        
  function( R )
    
    return -One( R );
    
end );

##
InstallMethod( MinusOne,
        "for homalg rings",
        [ IsHomalgInternalRingRep ],
        
  function( R )
    local RP;
    
    RP := homalgTable( R );
    
    if IsBound( RP!.MinusOne ) then
        return RP!.MinusOne;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( ZeroMutable,
        "for homalg ring elements",
        [ IsHomalgRingElement ],
        
  function( r )
    
    return Zero( HomalgRing( r ) );
    
end );

##
InstallMethod( OneMutable,
        "for homalg ring elements",
        [ IsHomalgRingElement ],
        
  function( r )
    
    return One( HomalgRing( r ) );
    
end );

##
InstallMethod( Inverse,
        "for homalg ring elements",
        [ IsHomalgRingElement ],
        
  function( r )
    
    return One( r ) / r;
    
end );

##
InstallMethod( MinusOneMutable,
        "for homalg ring elements",
        [ IsHomalgRingElement ],
        
  function( r )
    
    return MinusOne( HomalgRing( r ) );
    
end );

##
InstallMethod( Characteristic,
        "for homalg ring elements",
        [ IsHomalgRingElement ],
        
  function( r )
    
    return Characteristic( HomalgRing( r ) );
    
end );

## for the computeralgebra course
InstallOtherMethod( IndeterminateOfLaurentPolynomial,
        "for homalg ring elements",
        [ IsHomalgRingElement ],
        
  function( r )
    local R, indets;
    
    R := HomalgRing( r );
    
    indets := IndeterminatesOfPolynomialRing( R );
    
    return indets[Length( indets )];
    
end );

## for the computeralgebra course
InstallOtherMethod( CoefficientsRing,
        "for ring elements",
        [ IsRingElement ],
        
  function( r )
    local R;
    
    if IsHomalgRingElement( r ) then
        R := HomalgRing( r );
    else
        R := DefaultRing( r );
    fi;
    
    return CoefficientsRing( R );
    
end );

##
InstallMethod( AssociatedPolynomialRing,
        "for homalg fields",
        [ IsHomalgRing and IsFieldForHomalg ],
        
  function( R )
    local a, r;
    
    if not HasRationalParameters( R ) then
        Error( "the field has no rational parameters" );
    elif not HasCoefficientsRing( R ) then
        Error( "the field has no subfield of coefficients" );
    fi;
    
    r := CoefficientsRing( R );
    
    a := RationalParameters( R );
    
    return r * List( a, String );
    
end );

##
InstallMethod( PolynomialRingWithProductOrdering,
        "for homalg rings",
        [ IsHomalgRing ],
        
  function( R )
    local B, C;
    
    if not IsIdenticalObj( BaseRing( R ), CoefficientsRing( R ) ) then
        TryNextMethod( );
    fi;
    
    return R;
    
end );

##
InstallMethod( BaseRing,
        "for homalg rings",
        [ IsHomalgRing and HasCoefficientsRing ],
        
  CoefficientsRing );

##
InstallMethod( PrimitiveElement,
        "for homalg fields",
        [ IsFieldForHomalg ],
        
  function( R )
    
    if not IsBound( R!.NameOfPrimitiveElement ) then
        TryNextMethod( );
    fi;
    
    return R!.NameOfPrimitiveElement / R;
    
end );

####################################
#
# methods for operations:
#
####################################

##
InstallMethod( HomalgRing,
        "for homalg rings",
        [ IsHomalgRing ],
        
  function( R )
    
    return R;
    
end );

##
InstallMethod( \=,
        "for two homalg rings",
        [ IsHomalgRing, IsHomalgRing ], 10001,
        
  IsIdenticalObj );

##
InstallMethod( HomalgRing,
        "for homalg ring elements",
        [ IsHomalgRingElement ],
        
  function( r )
    
    return r!.ring;
    
end );

##
InstallMethod( LT,
        "for homalg ring elements",
        [ IsHomalgRingElement, IsHomalgRingElement ],
        
  function( a, b )
    
    return LT( String( a ), String( b ) );
    
end );

##
InstallMethod( InverseMutable,
        "for homalg ring elements",
        [ IsHomalgRingElement ],
        
  function( r )
    
    return Inverse( r );
    
end );

##
InstallMethod( \*,
        "for homalg ring elements",
        [ IS_RAT, IsHomalgRingElement ],
        
  function( a, b )
    
    if IS_INT( a ) then
        TryNextMethod( );
    fi;
    
    return ( NUMERATOR_RAT( a ) * b ) / ( DENOMINATOR_RAT( a ) * One( b ) );
    
end );

##
InstallMethod( \*,
        "for homalg ring elements",
        [ IsHomalgRingElement, IS_RAT ],
        
  function( a, b )
    
    if IS_INT( b ) then
        TryNextMethod( );
    fi;
    
    return ( NUMERATOR_RAT( b ) * a ) / ( DENOMINATOR_RAT( b ) * One( a ) );
    
end );

##
InstallMethod( \+,
        "for homalg ring elements",
        [ IS_RAT, IsHomalgRingElement ],
        
  function( a, b )
    
    return a * One( b ) + b;
    
end );

##
InstallMethod( \+,
        "for homalg ring elements",
        [ IsHomalgRingElement, IS_RAT ],
        
  function( a, b )
    
    return a + b * One( a );
    
end );

##
InstallMethod( Indeterminates,
        "for homalg rings",
        [ IsHomalgRing and HasIndeterminatesOfPolynomialRing ],
        
  function( R )
    
    return IndeterminatesOfPolynomialRing( R );
    
end );

##
InstallMethod( Indeterminates,
        "for homalg rings",
        [ IsHomalgRing and HasIndeterminatesOfExteriorRing ],
        
  function( R )
    
    return IndeterminatesOfExteriorRing( R );
    
end );

##
InstallMethod( Indeterminates,
        "for homalg rings",
        [ IsHomalgRing and HasIndeterminateCoordinatesOfRingOfDerivations ],
        
  function( R )
    
    return
      Concatenation(
              IndeterminateCoordinatesOfRingOfDerivations( R ),
              IndeterminateDerivationsOfRingOfDerivations( R )
              );
    
end );

##
InstallMethod( Indeterminates,
        "for homalg rings",
        [ IsHomalgRing and HasIndeterminateCoordinatesOfShiftAlgebra ],
        
  function( R )
    
    return
      Concatenation(
              IndeterminateCoordinatesOfShiftAlgebra( R ),
              IndeterminateShiftsOfShiftAlgebra( R )
              );
    
end );

##
InstallMethod( Indeterminates,
        "for homalg rings",
        [ IsHomalgRing and HasIndeterminateCoordinatesOfPseudoDoubleShiftAlgebra ],
        
  function( R )
    
    return
      Concatenation(
              IndeterminateCoordinatesOfPseudoDoubleShiftAlgebra( R ),
              IndeterminateShiftsOfPseudoDoubleShiftAlgebra( R )
              );
    
end );

##
InstallMethod( Indeterminates,
        "for homalg rings",
        [ IsHomalgRing and HasIndeterminateCoordinatesOfDoubleShiftAlgebra ],
        
  function( R )
    
    return
      Concatenation(
              IndeterminateCoordinatesOfDoubleShiftAlgebra( R ),
              IndeterminateShiftsOfDoubleShiftAlgebra( R )
              );
    
end );

##
InstallMethod( Indeterminates,
        "for homalg rings",
        [ IsHomalgRing and HasIndeterminateCoordinatesOfBiasedDoubleShiftAlgebra ],
        
  function( R )
    
    return
      Concatenation(
              IndeterminateCoordinatesOfBiasedDoubleShiftAlgebra( R ),
              IndeterminateShiftsOfBiasedDoubleShiftAlgebra( R )
              );
    
end );

##
InstallMethod( Indeterminates,
        "for homalg fields",
        [ IsHomalgRing and IsFieldForHomalg ],
        
  function( R )
    
    return [ ];
    
end );

##
InstallMethod( Indeterminates,
        "for homalg ring of integers",
        [ IsHomalgRing and IsIntegersForHomalg ],
        
  function( R )
    
    return [ ];
    
end );

## Fallback method
InstallMethod( RelativeIndeterminatesOfPolynomialRing,
        "for homalg rings",
        [ IsHomalgRing and HasCoefficientsRing ],
        
  IndeterminatesOfPolynomialRing );

##
InstallMethod( AssignGeneratorVariables,
        "for homalg rings",
        [ IsHomalgRing ],
        
  function( R )
    local indets;
    
    indets := Indeterminates( R );
    
    DoAssignGenVars( indets );
    
    return;
    
end );

##
InstallMethod( ExportIndeterminates,
        "for homalg rings",
        [ IsHomalgRing ],
        
  function( R )
    local indets, x_name, x;
    
    indets := Indeterminates( R );
    
    for x in indets do
        x_name := String( x );
        if IsBoundGlobal( x_name ) then
            if not IsHomalgRingElement( ValueGlobal( x_name ) ) then
                Error( "the name ", x_name, " is not bound to a homalg ring element\n" );
            elif IsReadOnlyGlobal( x_name ) then
                MakeReadWriteGlobal( x_name );
            fi;
            UnbindGlobal( x_name );
        fi;
        BindGlobal( x_name, x );
    od;
    
    return indets;
    
end );

##
InstallMethod( ExportRationalParameters,
        "for homalg rings",
        [ IsHomalgRing and HasRationalParameters ],
        
  function( R )
    local params, x_name, x;
    
    params := RationalParameters( R );
    
    for x in params do
        x_name := ShallowCopy( String( x ) );
        RemoveCharacters( x_name, "()" );
        if IsBoundGlobal( x_name ) then
            if not IsHomalgRingElement( ValueGlobal( x_name ) ) then
                Error( "the name ", x_name, " is not bound to a homalg ring element\n" );
            elif IsReadOnlyGlobal( x_name ) then
                MakeReadWriteGlobal( x_name );
            fi;
            UnbindGlobal( x_name );
        fi;
        BindGlobal( x_name, x );
    od;
    
    return params;
    
end );

##
InstallMethod( ExportVariables,
        "for homalg rings",
        [ IsHomalgRing ],
        
  function( R )
    
    return ExportIndeterminates( R );
    
end );

##
InstallMethod( ExportVariables,
        "for homalg rings",
        [ IsHomalgRing and HasRationalParameters ],
        
  function( R )
    
    return Concatenation(
                   ExportRationalParameters( R ),
                   ExportIndeterminates( R ) );
    
end );

##
InstallMethod( Indeterminate,
        "for homalg rings",
        [ IsHomalgRing, IsPosInt ],
        
  function( R, i )
    
    return Indeterminates( R )[i];
    
end );

##
InstallMethod( ProductOfIndeterminates,
        "for homalg rings",
        [ IsHomalgRing ],
        
  function( R )
    
    return Product( Indeterminates( R ) );
    
end );

##
InstallMethod( ProductOfIndeterminatesOverBaseRing,
        "for homalg rings",
        [ IsHomalgRing and HasIndeterminatesOfPolynomialRing ],
        
  function( R )
    
    return Product( IndeterminatesOfPolynomialRing( R ) );
    
end );

##
InstallMethod( ProductOfIndeterminatesOverBaseRing,
        "for homalg rings",
        [ IsHomalgRing and HasRelativeIndeterminatesOfPolynomialRing ], 100, ## otherwise the above method is triggered :(
        
  function( R )
    
    return Product( RelativeIndeterminatesOfPolynomialRing( R ) );
    
end );

## provided to avoid branching in the code and always returns fail
InstallMethod( PositionOfTheDefaultPresentation,
        "for ring elements",
        [ IsRingElement ],
        
  function( r )
    
    return fail;
    
end );

##
InstallMethod( \=,
        "for two homalg ring elements",
        [ IsHomalgRingElement, IsHomalgRingElement ],
        
  function( r1, r2 )
    
    if IsIdenticalObj( HomalgRing( r1 ), HomalgRing( r2 ) ) then
        return IsZero( r1 - r2 );
    fi;
    
    return false;
    
end );

##
InstallMethod( \=,
        "for a rational and a homalg ring element",
        [ IS_RAT, IsHomalgRingElement ],
        
  function( r1, r2 )
    
    return r1 / HomalgRing( r2 ) = r2;
    
end );

##
InstallMethod( \=,
        "for a homalg ring element and a rational",
        [ IsHomalgRingElement, IS_RAT ],
        
  function( r1, r2 )
    
    return r1 = r2 / HomalgRing( r1 );
    
end );

##
InstallMethod( StandardBasisRowVectors,
        "for homalg rings",
        [ IsInt, IsHomalgRing ],
        
  function( n, R )
    local id;
    
    id := HomalgIdentityMatrix( n, R );
    
    return List( [ 1 .. n ], r -> CertainRows( id, [ r ] ) );
    
end );

##
InstallMethod( StandardBasisColumnVectors,
        "for homalg rings",
        [ IsInt, IsHomalgRing ],
        
  function( n, R )
    local id;
    
    id := HomalgIdentityMatrix( n, R );
    
    return List( [ 1 .. n ], c -> CertainColumns( id, [ c ] ) );
    
end );

##
InstallMethod( RingName,
        "for homalg rings",
        [ IsHomalgRing ],
        
  function( R )
    local RP, var, r, c;
    
    if HasName( R ) then
        return Name( R );
    fi;
    
    ## ask the ring table
    RP := homalgTable( R );
    
    if IsBound(RP!.RingName) then
        
        if IsFunction( RP!.RingName ) then
            r := RP!.RingName( R );
        else
            r := RP!.RingName;
        fi;
        
        if r <> fail then
            return r;
        fi;
        
    fi;
    
    ## residue class rings/fields of the integers
    if HasIsResidueClassRingOfTheIntegers( R ) and
       IsResidueClassRingOfTheIntegers( R ) and
       HasCharacteristic( R ) then
        
        c := Characteristic( R );
        
        if c = 0 then
            return "Z";
        elif IsPrime( c ) then
            if HasDegreeOverPrimeField( R ) and DegreeOverPrimeField( R ) > 1 then
                r := [ "GF(", String( c ), "^", String( DegreeOverPrimeField( R ) ), ")" ];
            else
                r := [ "GF(", String( c ), ")" ];
            fi;
        else
            r := [ "Z/", String( c ), "Z" ];
        fi;
        
        return String( Concatenation( r ) );
        
    fi;
    
    ## the rationals
    if HasIsRationalsForHomalg( R ) and IsRationalsForHomalg( R ) then
        return "Q";
    fi;
    
    return "(homalg ring)";
    
end );

##
InstallMethod( homalgRingStatistics,
        "for homalg rings",
        [ IsHomalgRing ],
        
  function( R )
    
    return R!.statistics;
    
end );

##
InstallMethod( IncreaseRingStatistics,
        "for homalg rings",
        [ IsHomalgRing, IsString ],
        
  function( R, s )
    
    R!.statistics.(s) := R!.statistics.(s) + 1;
    
end );

##
InstallMethod( DecreaseRingStatistics,
        "for homalg rings",
        [ IsHomalgRing, IsString ],
        
  function( R, s )
    
    R!.statistics.(s) := R!.statistics.(s) - 1;
    
end );

##
InstallOtherMethod( AsList,
        "for homalg internal rings",
        [ IsHomalgInternalRingRep ],
        
  function( r )
    
    return AsList( r!.ring );
    
end );

##
InstallMethod( homalgSetName,
        "for homalg ring elements",
        [ IsHomalgRingElement, IsString ],
        
  SetName );

##
InstallMethod( IrreducibleFactors,
        "for ring elements",
        [ IsRingElement ],
        
  PrimeDivisors );

##
InstallMethod( IrreducibleFactors,
        "for homalg ring elements",
        [ IsHomalgRingElement ],
        
  function( r )
    local R, factors;
    
    R := HomalgRing( r );
    
    if IsHomalgInternalRingRep( R ) then
        if not IsBound( r!.IrreducibleFactors ) then
            r!.IrreducibleFactors := PrimeDivisors( EvalString( String( r ) ) );
        fi;
    fi;
    
    factors := RadicalDecompositionOp( HomalgMatrix( [ r ], 1, 1, R ) );
    
    r!.Factors := List( factors, a -> a[ 1, 1 ] );
    
    return r!.Factors;
    
end );

##
InstallMethod( Factors,
        "for homalg ring elements",
        [ IsHomalgRingElement ],
        
  function( r )
    local R, factors, primary, prime, one, divide;
    
    R := HomalgRing( r );
    
    if IsHomalgInternalRingRep( R ) then
        if not IsBound( r!.Factors ) then
            r!.Factors := Factors( EvalString( String( r ) ) );
        fi;
    fi;
    
    factors := PrimaryDecompositionOp( HomalgMatrix( [ r ], 1, 1, R ) );
    
    primary := List( factors, a -> a[1][ 1, 1 ] );
    prime := List( factors, a -> a[2][ 1, 1 ] );
    
    one := One( R );
    
    divide :=
      function( q, p )
        local list;
        
        list := [ ];
        
        repeat
            q := q / p;
            Add( list, p );
        until IsZero( DecideZero( one, q ) );
        
        return list;
        
    end;
    
    factors := List( [ 1 .. Length( factors ) ], i -> divide( primary[i], prime[i] ) );
    
    factors := Concatenation( factors );
    
    factors[1] := ( r / Product( factors ) ) * factors[1];
      
    r!.Factors := factors;
    
    return r!.Factors;
    
end );

##
InstallMethod( Roots,
        "for homalg ring elements",
        [ IsHomalgRingElement ],
        
  function( r )
    local R, roots;
    
    R := HomalgRing( r );
    
    if not IsHomalgInternalRingRep( R ) then
        TryNextMethod( );
    fi;
    
    if not IsBound( r!.Roots ) then
        roots := RootsOfUPol( EvalString( String( r ) ) );
        Sort( roots );
        r!.Roots := roots;
    fi;
    
    return r!.Roots;
    
end );

##
InstallMethod( DecideZero,
        "for homalg ring elements",
        [ IsHomalgRingElement ],
        
  function( r )
    
    IsZero( r );
    
    return r;
    
end );

##
InstallMethod( SetRingProperties,
        "for homalg rings",
        [ IsHomalgRing and IsFreePolynomialRing, IsHomalgRing, IsList ],
        
  function( S, R, var )
    local param, paramS, d;
    
    d := Length( var );
    
    if d > 0 then
        SetIsFinite( S, false );
    fi;
    
    SetCoefficientsRing( S, R );
    
    if HasRationalParameters( R ) then
        param := RationalParameters( R );
        paramS := List( param, a -> a / S );
        Perform( [ 1 .. Length( param ) ], function( i ) SetName( paramS[i], Name( param[i] ) ); end );
        SetRationalParameters( S, paramS );
    fi;
    
    if HasCharacteristic( R ) then
        SetCharacteristic( S, Characteristic( R ) );
    fi;
    
    SetIsCommutative( S, true );
    
    SetIndeterminatesOfPolynomialRing( S, var );
    
    if HasContainsAField( R ) and ContainsAField( R ) then
        SetContainsAField( S, true );
    fi;
    
    if d > 0 then
        SetIsLeftArtinian( S, false );
        SetIsRightArtinian( S, false );
    fi;
    
    if HasGlobalDimension( R ) then
        SetGlobalDimension( S, d + GlobalDimension( R ) );
    fi;
    
    if HasKrullDimension( R ) then
        SetKrullDimension( S, d + KrullDimension( R ) );
    fi;
    
    SetGeneralLinearRank( S, 1 );       ## Quillen-Suslin Theorem (see [McCRob, 11.5.5]
    
    if d = 1 then                       ## [McCRob, 11.5.7]
        SetElementaryRank( S, 1 );
    elif d > 2 then
        SetElementaryRank( S, 2 );
    fi;
    
    SetIsIntegralDomain( S, true );
    
    SetBasisAlgorithmRespectsPrincipalIdeals( S, true );
    
end );

##
InstallMethod( SetRingProperties,
        "for homalg rings",
        [ IsHomalgRing and IsWeylRing, IsHomalgRing and IsFreePolynomialRing, IsList ],
        
  function( S, R, der )
    local r, b, param, paramS, var, d;
    
    r := CoefficientsRing( R );
    
    if HasBaseRing( R ) then
        b := BaseRing( R );
    else
        b := r;
    fi;
    
    var := IndeterminatesOfPolynomialRing( R );
    var := List( var, a -> a / S );
    
    d := Length( var );
    
    if d > 0 then
        SetIsFinite( S, false );
    fi;
    
    SetCoefficientsRing( S, r );
    
    if HasRationalParameters( r ) then
        param := RationalParameters( r );
        paramS := List( param, a -> a / S );
        Perform( [ 1 .. Length( param ) ], function( i ) SetName( paramS[i], Name( param[i] ) ); end );
        SetRationalParameters( S, paramS );
    fi;
    
    SetCharacteristic( S, Characteristic( R ) );
    
    SetIsCommutative( S, der = [ ] );
    
    SetCenter( S, Center( b ) );
    
    SetIndeterminateCoordinatesOfRingOfDerivations( S, var );
    
    if HasRelativeIndeterminatesOfPolynomialRing( R ) then
        SetRelativeIndeterminateCoordinatesOfRingOfDerivations(
                S, RelativeIndeterminatesOfPolynomialRing( R ) );
    fi;
    
    SetIndeterminateDerivationsOfRingOfDerivations( S, der );
    
    if d > 0 then
        SetIsLeftArtinian( S, false );
        SetIsRightArtinian( S, false );
    fi;
    
    SetIsLeftNoetherian( S, true );
    SetIsRightNoetherian( S, true );
    
    if HasGlobalDimension( r ) then
        SetGlobalDimension( S, d + GlobalDimension( r ) );
    fi;
    
    if HasIsFieldForHomalg( b ) and IsFieldForHomalg( b ) and Characteristic( S ) = 0 then
        SetGeneralLinearRank( S, 2 );   ## [Stafford78], [McCRob, 11.2.15(i)]
        SetIsSimpleRing( S, true );     ## [Coutinho, Thm 2.2.1]
    fi;
    
    if HasIsIntegralDomain( r ) and IsIntegralDomain( r ) then
        SetIsIntegralDomain( S, true );
    fi;
    
    if d > 0 then
        SetIsLeftPrincipalIdealRing( S, false );
        SetIsRightPrincipalIdealRing( S, false );
        SetIsPrincipalIdealRing( S, false );
    fi;
    
    SetBasisAlgorithmRespectsPrincipalIdeals( S, true );
    
    SetAreUnitsCentral( S, true );
    
end );

##
InstallMethod( SetRingProperties,
        "for homalg rings",
        [ IsHomalgRing and IsLocalizedWeylRing, IsString ],
        
  function( S, _var )
    local var, d;
    
    var := SplitString( _var, ",", "[]" );
    var := List( var, a -> a / S );
    
    SetIndeterminateCoordinatesOfRingOfDerivations( S, var );
    
    d := Length( var );
    
    ## SetCoefficientsRing( S, r );
    
    SetCharacteristic( S, 0 );
    
    SetIsCommutative( S, false );
    
    ## SetCenter( S, r );
    
    SetIndeterminateCoordinatesOfRingOfDerivations( S, var );
    
    ## SetIndeterminateDerivationsOfRingOfDerivations( S, der );
    
    if d > 0 then
        SetIsLeftArtinian( S, false );
        SetIsRightArtinian( S, false );
    fi;
    
    SetIsLeftNoetherian( S, true );
    SetIsRightNoetherian( S, true );
    
    SetGlobalDimension( S, d + 0 );     ## Janet only knows Q as the coefficient ring
    
    ## SetGeneralLinearRank( S, 2 );    ## [Stafford78], [McCRob, 11.2.15(i)]
    SetIsSimpleRing( S, true );         ## [Coutinho, Thm 2.2.1]
    
    if d > 0 then
        SetIsPrincipalIdealRing( S, false );
    fi;
    
    if d = 1 then
        SetIsLeftPrincipalIdealRing( S, true );
        SetIsRightPrincipalIdealRing( S, true );
    elif d > 0 then
        SetIsLeftPrincipalIdealRing( S, false );
        SetIsRightPrincipalIdealRing( S, false );
    fi;
    
    SetIsIntegralDomain( S, true );
    
    SetBasisAlgorithmRespectsPrincipalIdeals( S, true );
    
    SetAreUnitsCentral( S, false );
    
end );

##
InstallMethod( SetRingProperties,
        "for homalg rings",
        [ IsHomalgRing and IsExteriorRing, IsHomalgRing and IsFreePolynomialRing, IsList ],
        
  function( A, S, anti )
    local r, d, param, paramA, comm, T;
    
    r := CoefficientsRing( S );
    
    d := Length( anti );
    
    SetCoefficientsRing( A, r );
    
    if HasRationalParameters( r ) then
        param := RationalParameters( r );
        paramA := List( param, a -> a / A );
        Perform( [ 1 .. Length( param ) ], function( i ) SetName( paramA[i], Name( param[i] ) ); end );
        SetRationalParameters( A, paramA );
    fi;
    
    SetCharacteristic( A, Characteristic( S ) );
    
    if d <= 1 or Characteristic( A ) = 2 then
        
        ## the Center is then automatically set to S
        SetIsCommutative( A, true );
        
    else
        
        ## the center is the even part, which is
        ## bigger than the coefficients ring r
        SetIsCommutative( A, false );
        
    fi;
    
    SetIsSuperCommutative( A, true );
    
    SetIsIntegralDomain( A, d = 0 );
    
    comm := [ ];
    
    if HasBaseRing( S ) then
        T := BaseRing( S );
        if HasIndeterminatesOfPolynomialRing( T ) then
            comm := IndeterminatesOfPolynomialRing( T );
        fi;
    fi;
    
    if not HasIndeterminateAntiCommutingVariablesOfExteriorRing( A ) then
        
        SetIndeterminateAntiCommutingVariablesOfExteriorRing( A, anti );
        
    fi;
    
    if not HasIndeterminatesOfExteriorRing( A ) then
        
        SetIndeterminatesOfExteriorRing( A, Concatenation( comm, anti ) );
        
    fi;
    
    SetBasisAlgorithmRespectsPrincipalIdeals( A, true );
    
    SetAreUnitsCentral( S, true );
    
end );

##
InstallMethod( SetRingProperties,
        "for homalg rings",
        [ IsHomalgRing and IsShiftAlgebra, IsHomalgRing and IsFreePolynomialRing, IsList ],
        
  function( S, R, shift )
    local r, b, param, paramS, var, d;
    
    r := CoefficientsRing( R );
    
    if HasBaseRing( R ) then
        b := BaseRing( R );
    else
        b := r;
    fi;
    
    var := IndeterminatesOfPolynomialRing( R );
    var := List( var, a -> a / S );
    
    d := Length( var );
    
    if d > 0 then
        SetIsFinite( S, false );
    fi;
    
    SetCoefficientsRing( S, r );
    
    if HasRationalParameters( r ) then
        param := RationalParameters( r );
        paramS := List( param, a -> a / S );
        Perform( [ 1 .. Length( param ) ], function( i ) SetName( paramS[i], Name( param[i] ) ); end );
        SetRationalParameters( S, paramS );
    fi;
    
    SetCharacteristic( S, Characteristic( R ) );
    
    SetIsCommutative( S, shift = [ ] );
    
    SetIndeterminateCoordinatesOfShiftAlgebra( S, var );
    
    if HasRelativeIndeterminatesOfPolynomialRing( R ) then
        SetRelativeIndeterminateCoordinatesOfShiftAlgebra(
                S, RelativeIndeterminatesOfPolynomialRing( R ) );
    fi;
    
    SetIndeterminateShiftsOfShiftAlgebra( S, shift );
    
    if d > 0 then
        SetIsLeftArtinian( S, false );
        SetIsRightArtinian( S, false );
    fi;
    
    SetIsLeftNoetherian( S, true );
    SetIsRightNoetherian( S, true );
    
    if HasIsIntegralDomain( r ) and IsIntegralDomain( r ) then
        SetIsIntegralDomain( S, true );
    fi;
    
    if d > 0 then
        SetIsLeftPrincipalIdealRing( S, false );
        SetIsRightPrincipalIdealRing( S, false );
        SetIsPrincipalIdealRing( S, false );
    fi;
    
    SetBasisAlgorithmRespectsPrincipalIdeals( S, true );
    
end );

##
InstallMethod( SetRingProperties,
        "for homalg rings",
        [ IsHomalgRing and IsRationalShiftAlgebra, IsHomalgRing and IsFreePolynomialRing, IsList ],
        
  function( S, R, shift )
    local r, b, param, paramS, var, d;
    
    r := CoefficientsRing( R );
    
    if HasBaseRing( R ) then
        b := BaseRing( R );
    else
        b := r;
    fi;
    
    var := IndeterminatesOfPolynomialRing( R );
    var := List( var, a -> a / S );
    
    d := Length( var );
    
    if d > 0 then
        SetIsFinite( S, false );
    fi;
    
    SetCoefficientsRing( S, r );
    
    if HasRationalParameters( r ) then
        param := RationalParameters( r );
        paramS := List( param, a -> a / S );
        Perform( [ 1 .. Length( param ) ], function( i ) SetName( paramS[i], Name( param[i] ) ); end );
        SetRationalParameters( S, paramS );
    fi;
    
    SetCharacteristic( S, Characteristic( R ) );
    
    SetIsCommutative( S, shift = [ ] );
    
    SetParametersOfRationalShiftAlgebra( S, var );
    
    if HasRelativeIndeterminatesOfPolynomialRing( R ) then
        SetRelativeParametersOfRationalShiftAlgebra(
                S, RelativeIndeterminatesOfPolynomialRing( R ) );
    fi;
    
    SetIndeterminateShiftsOfRationalShiftAlgebra( S, shift );
    
    if d > 0 then
        SetIsLeftArtinian( S, false );
        SetIsRightArtinian( S, false );
    fi;
    
    SetIsLeftNoetherian( S, true );
    SetIsRightNoetherian( S, true );
    
    if HasIsIntegralDomain( r ) and IsIntegralDomain( r ) then
        SetIsIntegralDomain( S, true );
    fi;
    
    if d > 0 then
        SetIsLeftPrincipalIdealRing( S, false );
        SetIsRightPrincipalIdealRing( S, false );
        SetIsPrincipalIdealRing( S, false );
    fi;
    
    SetBasisAlgorithmRespectsPrincipalIdeals( S, true );
    
end );

##
InstallMethod( SetRingProperties,
        "for homalg rings",
        [ IsHomalgRing and IsPseudoDoubleShiftAlgebra, IsHomalgRing and IsFreePolynomialRing, IsList ],
        
  function( S, R, shift )
    local r, b, param, paramS, var, d;
    
    r := CoefficientsRing( R );
    
    if HasBaseRing( R ) then
        b := BaseRing( R );
    else
        b := r;
    fi;
    
    var := IndeterminatesOfPolynomialRing( R );
    var := List( var, a -> a / S );
    
    d := Length( var );
    
    if d > 0 then
        SetIsFinite( S, false );
    fi;
    
    SetCoefficientsRing( S, r );
    
    if HasRationalParameters( r ) then
        param := RationalParameters( r );
        paramS := List( param, a -> a / S );
        Perform( [ 1 .. Length( param ) ], function( i ) SetName( paramS[i], Name( param[i] ) ); end );
        SetRationalParameters( S, paramS );
    fi;
    
    SetCharacteristic( S, Characteristic( R ) );
    
    SetIsCommutative( S, shift = [ ] );
    
    SetIndeterminateCoordinatesOfPseudoDoubleShiftAlgebra( S, var );
    
    if HasRelativeIndeterminatesOfPolynomialRing( R ) then
        SetRelativeIndeterminateCoordinatesOfPseudoDoubleShiftAlgebra(
                S, RelativeIndeterminatesOfPolynomialRing( R ) );
    fi;
    
    SetIndeterminateShiftsOfPseudoDoubleShiftAlgebra( S, shift );
    
    if d > 0 then
        SetIsLeftArtinian( S, false );
        SetIsRightArtinian( S, false );
    fi;
    
    SetIsLeftNoetherian( S, true );
    SetIsRightNoetherian( S, true );
    
    if HasIsIntegralDomain( r ) and IsIntegralDomain( r ) then
        SetIsIntegralDomain( S, true );
    fi;
    
    if d > 0 then
        SetIsLeftPrincipalIdealRing( S, false );
        SetIsRightPrincipalIdealRing( S, false );
        SetIsPrincipalIdealRing( S, false );
    fi;
    
    SetBasisAlgorithmRespectsPrincipalIdeals( S, true );
    
end );

##
InstallMethod( SetRingProperties,
        "for homalg rings",
        [ IsHomalgRing and IsRationalPseudoDoubleShiftAlgebra, IsHomalgRing and IsFreePolynomialRing, IsList ],
        
  function( S, R, shift )
    local r, b, param, paramS, var, d;
    
    r := CoefficientsRing( R );
    
    if HasBaseRing( R ) then
        b := BaseRing( R );
    else
        b := r;
    fi;
    
    var := IndeterminatesOfPolynomialRing( R );
    var := List( var, a -> a / S );
    
    d := Length( var );
    
    if d > 0 then
        SetIsFinite( S, false );
    fi;
    
    SetCoefficientsRing( S, r );
    
    if HasRationalParameters( r ) then
        param := RationalParameters( r );
        paramS := List( param, a -> a / S );
        Perform( [ 1 .. Length( param ) ], function( i ) SetName( paramS[i], Name( param[i] ) ); end );
        SetRationalParameters( S, paramS );
    fi;
    
    SetCharacteristic( S, Characteristic( R ) );
    
    SetIsCommutative( S, shift = [ ] );
    
    SetParametersOfRationalPseudoDoubleShiftAlgebra( S, var );
    
    if HasRelativeIndeterminatesOfPolynomialRing( R ) then
        SetRelativeParametersOfRationalPseudoDoubleShiftAlgebra(
                S, RelativeIndeterminatesOfPolynomialRing( R ) );
    fi;
    
    SetIndeterminateShiftsOfRationalPseudoDoubleShiftAlgebra( S, shift );
    
    if d > 0 then
        SetIsLeftArtinian( S, false );
        SetIsRightArtinian( S, false );
    fi;
    
    SetIsLeftNoetherian( S, true );
    SetIsRightNoetherian( S, true );
    
    if HasIsIntegralDomain( r ) and IsIntegralDomain( r ) then
        SetIsIntegralDomain( S, true );
    fi;
    
    if d > 0 then
        SetIsLeftPrincipalIdealRing( S, false );
        SetIsRightPrincipalIdealRing( S, false );
        SetIsPrincipalIdealRing( S, false );
    fi;
    
    SetBasisAlgorithmRespectsPrincipalIdeals( S, true );
    
end );

##
InstallMethod( SetRingProperties,
        "for homalg rings",
        [ IsHomalgRing and IsBiasedDoubleShiftAlgebra, IsHomalgRing and IsFreePolynomialRing, IsList ],
        
  function( S, R, shift )
    local r, b, param, paramS, var, d;
    
    r := CoefficientsRing( R );
    
    if HasBaseRing( R ) then
        b := BaseRing( R );
    else
        b := r;
    fi;
    
    var := IndeterminatesOfPolynomialRing( R );
    var := List( var, a -> a / S );
    
    d := Length( var );
    
    if d > 0 then
        SetIsFinite( S, false );
    fi;
    
    SetCoefficientsRing( S, r );
    
    if HasRationalParameters( r ) then
        param := RationalParameters( r );
        paramS := List( param, a -> a / S );
        Perform( [ 1 .. Length( param ) ], function( i ) SetName( paramS[i], Name( param[i] ) ); end );
        SetRationalParameters( S, paramS );
    fi;
    
    SetCharacteristic( S, Characteristic( R ) );
    
    SetIsCommutative( S, shift = [ ] );
    
    SetIndeterminateCoordinatesOfBiasedDoubleShiftAlgebra( S, var );
    
    if HasRelativeIndeterminatesOfPolynomialRing( R ) then
        SetRelativeIndeterminateCoordinatesOfBiasedDoubleShiftAlgebra(
                S, RelativeIndeterminatesOfPolynomialRing( R ) );
    fi;
    
    SetIndeterminateShiftsOfBiasedDoubleShiftAlgebra( S, shift );
    
    if d > 0 then
        SetIsLeftArtinian( S, false );
        SetIsRightArtinian( S, false );
    fi;
    
    SetIsLeftNoetherian( S, true );
    SetIsRightNoetherian( S, true );
    
    if HasIsIntegralDomain( r ) and IsIntegralDomain( r ) then
        SetIsIntegralDomain( S, true );
    fi;
    
    if d > 0 then
        SetIsLeftPrincipalIdealRing( S, false );
        SetIsRightPrincipalIdealRing( S, false );
        SetIsPrincipalIdealRing( S, false );
    fi;
    
    SetBasisAlgorithmRespectsPrincipalIdeals( S, true );
    
end );

##
InstallMethod( SetRingProperties,
        "for homalg rings",
        [ IsHomalgRing and IsPrincipalIdealRing and IsCommutative, IsInt ],
        
  function( R, c )
    local RP, powers;
    
    SetCharacteristic( R, c );
    
    if HasIsFieldForHomalg( R ) and IsFieldForHomalg( R ) then
        TryNextMethod( );
    elif HasIsResidueClassRingOfTheIntegers( R ) and
      IsResidueClassRingOfTheIntegers( R ) then
        TryNextMethod( );
    fi;
    
    if c = 0 then
        SetContainsAField( R, false );
        SetIsIntegralDomain( R, true );
        SetIsArtinian( R, false );
        SetKrullDimension( R, 1 ); ## FIXME: it is not set automatically although an immediate method is installed
    elif not IsPrime( c ) then
        SetIsSemiLocalRing( R, true );
        SetIsIntegralDomain( R, false );
        powers := List( Collected( FactorsInt( c ) ), a -> a[2] );
        if Set( powers ) = [ 1 ] then
            SetIsSemiSimpleRing( R, true );
        else
            SetIsRegular( R, false );
            if Length( powers ) = 1 then
                SetIsLocal( R, true );
            fi;
        fi;
        SetKrullDimension( R, 0 );
    fi;
    
    RP := homalgTable( R );
    
    if HasIsIntegralDomain( R ) and IsIntegralDomain( R ) then
        if IsBound( RP!.RowRankOfMatrixOverDomain ) then
            RP!.RowRankOfMatrix := RP!.RowRankOfMatrixOverDomain;
        fi;
        
        if IsBound( RP!.ColumnRankOfMatrixOverDomain ) then
            RP!.ColumnRankOfMatrix := RP!.ColumnRankOfMatrixOverDomain;
        fi;
    fi;
    
    SetBasisAlgorithmRespectsPrincipalIdeals( R, true );
    
end );

##
InstallMethod( SetRingProperties,
        "for homalg rings",
        [ IsHomalgRing and IsResidueClassRingOfTheIntegers, IsInt ],
        
  function( R, c )
    local RP, powers;
    
    SetCharacteristic( R, c );
    
    SetIsRationalsForHomalg( R, false );
    
    if c = 0 then
        SetIsIntegersForHomalg( R, true );
        SetContainsAField( R, false );
        SetIsArtinian( R, false );
        SetKrullDimension( R, 1 ); ## FIXME: it is not set automatically although an immediate method is installed
    elif IsPrime( c ) then
        SetIsFieldForHomalg( R, true );
        SetRingProperties( R, c );
    else
        SetIsSemiLocalRing( R, true );
        SetIsIntegralDomain( R, false );
        powers := List( Collected( FactorsInt( c ) ), a -> a[2] );
        if Set( powers ) = [ 1 ] then
            SetIsSemiSimpleRing( R, true );
        else
            SetIsRegular( R, false );
            if Length( powers ) = 1 then
                SetIsLocal( R, true );
            fi;
        fi;
        SetKrullDimension( R, 0 );
    fi;
    
    RP := homalgTable( R );
    
    if HasIsIntegralDomain( R ) and IsIntegralDomain( R ) then
        if IsBound( RP!.RowRankOfMatrixOverDomain ) then
            RP!.RowRankOfMatrix := RP!.RowRankOfMatrixOverDomain;
        fi;
        
        if IsBound( RP!.ColumnRankOfMatrixOverDomain ) then
            RP!.ColumnRankOfMatrix := RP!.ColumnRankOfMatrixOverDomain;
        fi;
    fi;
    
    SetBasisAlgorithmRespectsPrincipalIdeals( R, true );
    
end );

##
InstallMethod( SetRingProperties,
        "for homalg rings",
        [ IsHomalgRing and IsFieldForHomalg, IsInt ],
        
  function( R, c )
    local RP;
    
    SetCharacteristic( R, c );
    
    if HasRationalParameters( R ) and Length( RationalParameters( R ) ) > 0 then
        SetIsRationalsForHomalg( R, false );
        SetIsResidueClassRingOfTheIntegers( R, false );
    else
        SetDegreeOverPrimeField( R, 1 );
    fi;
    
    RP := homalgTable( R );
    
    if IsBound( RP!.RowRankOfMatrixOverDomain ) then
        RP!.RowRankOfMatrix := RP!.RowRankOfMatrixOverDomain;
    fi;
    
    if IsBound( RP!.ColumnRankOfMatrixOverDomain ) then
        RP!.ColumnRankOfMatrix := RP!.ColumnRankOfMatrixOverDomain;
    fi;
    
    SetFilterObj( R, IsField );
    SetLeftActingDomain( R, R );
    
    SetBasisAlgorithmRespectsPrincipalIdeals( R, true );
    
end );

##
InstallMethod( SetRingProperties,
        "for homalg rings",
        [ IsHomalgRing and IsFieldForHomalg, IsInt, IsInt ],
        
  function( R, c, d )
    local RP;
    
    SetCharacteristic( R, c );
    SetDegreeOverPrimeField( R, d );
    
    if HasRationalParameters( R ) and Length( RationalParameters( R ) ) > 0 then
        SetIsRationalsForHomalg( R, false );
        SetIsResidueClassRingOfTheIntegers( R, false );
    fi;
    
    RP := homalgTable( R );
    
    if IsBound( RP!.RowRankOfMatrixOverDomain ) then
        RP!.RowRankOfMatrix := RP!.RowRankOfMatrixOverDomain;
    fi;
    
    if IsBound( RP!.ColumnRankOfMatrixOverDomain ) then
        RP!.ColumnRankOfMatrix := RP!.ColumnRankOfMatrixOverDomain;
    fi;
    
    SetFilterObj( R, IsField );
    SetLeftActingDomain( R, R );
    
    SetBasisAlgorithmRespectsPrincipalIdeals( R, true );
    
end );

##
InstallMethod( UnusedVariableName,
        "for a homalg ring and a string",
        [ IsHomalgRing, IsString ],
        
  function( R, t )
    local var;
    
    var := [ ];
    
    if HasRationalParameters( R ) then
        Append( var, List( RationalParameters( R ), Name ) );
    fi;
    
    if HasIndeterminatesOfPolynomialRing( R ) then
        Append( var, List( IndeterminatesOfPolynomialRing( R ), Name ) );
    fi;
    
    while true do
        
        if not t in var then
            return t;
        fi;
        
        t := Concatenation( t, "_" );
    od;
    
end );

##
InstallMethod( EuclideanQuotient,
        "for a homalg ring and two homalg ring elements",
        [ IsHomalgInternalRingRep and IsPrincipalIdealRing and IsCommutative, IsRingElement, IsRingElement ],
        
  function( R, a, b )
    
    return EuclideanQuotient( R!.ring, a, b );
    
end );

##
InstallMethod( EuclideanRemainder,
        "for a homalg ring and two homalg ring elements",
        [ IsHomalgInternalRingRep and IsPrincipalIdealRing and IsCommutative, IsRingElement, IsRingElement ],
        
  function( R, a, b )
    
    return EuclideanRemainder( R!.ring, a, b );
    
end );

##
InstallMethod( QuotientRemainder,
        "for a homalg ring and two homalg ring elements",
        [ IsHomalgInternalRingRep and IsPrincipalIdealRing and IsCommutative, IsRingElement, IsRingElement ],
        
  function( R, a, b )
    
    return QuotientRemainder( R!.ring, a, b );
    
end );

####################################
#
# constructor functions and methods:
#
####################################

##
InstallGlobalFunction( CreateHomalgRing,
  function( arg )
    local nargs, r, IdentityMatrices, statistics, asserts,
          homalg_ring, table, properties, ar, type, matrix_type,
          ring_element_constructor, finalizers, c, el;
    
    nargs := Length( arg );
    
    if nargs = 0 then
        Error( "expecting a ring as the first argument\n" );
    fi;
    
    r := arg[1];
    
    IdentityMatrices := ContainerForWeakPointers( TheTypeContainerForWeakPointersOnIdentityMatrices );
    Unbind( IdentityMatrices!.active );
    Unbind( IdentityMatrices!.deleted );
    Unbind( IdentityMatrices!.accessed );
    Unbind( IdentityMatrices!.cache_misses );
    
    statistics := rec(
                      BasisOfRowModule := 0,
                      BasisOfColumnModule := 0,
                      BasisOfRowsCoeff := 0,
                      BasisOfColumnsCoeff := 0,
                      DecideZeroRows := 0,
                      DecideZeroColumns := 0,
                      DecideZeroRowsEffectively := 0,
                      DecideZeroColumnsEffectively := 0,
                      SyzygiesGeneratorsOfRows := 0,
                      SyzygiesGeneratorsOfColumns := 0,
                      RelativeSyzygiesGeneratorsOfRows := 0,
                      RelativeSyzygiesGeneratorsOfColumns := 0,
                      PartiallyReducedBasisOfRowModule := 0,
                      PartiallyReducedBasisOfColumnModule := 0,
                      ReducedBasisOfRowModule := 0,
                      ReducedBasisOfColumnModule := 0,
                      ReducedSyzygiesGeneratorsOfRows := 0,
                      ReducedSyzygiesGeneratorsOfColumns := 0
                      );
    
    
    ##  <#GAPDoc Label="asserts">
    ##   Below you can find the record of the available level-4 assertions,
    ##   which is a &GAP;-component of every &homalg; ring. Each assertion can
    ##   thus be overwritten by package developers or even ordinary users.
    ##      <Listing Type="Code"><![CDATA[
    asserts :=
      rec(
          BasisOfRowModule :=
            function( B ) return ( NumberRows( B ) = 0 ) = IsZero( B ); end,
          
          BasisOfColumnModule :=
            function( B ) return ( NumberColumns( B ) = 0 ) = IsZero( B ); end,
          
          BasisOfRowsCoeff :=
            function( B, T, M ) return B = T * M; end,
          
          BasisOfColumnsCoeff :=
            function( B, M, T ) return B = M * T; end,
          
          DecideZeroRows_Effectively :=
            function( M, A, B ) return M = DecideZeroRows( A, B ); end,
          
          DecideZeroColumns_Effectively :=
            function( M, A, B ) return M = DecideZeroColumns( A, B ); end,
          
          DecideZeroRowsEffectively :=
            function( M, A, T, B ) return M = A + T * B; end,
          
          DecideZeroColumnsEffectively :=
            function( M, A, B, T ) return M = A + B * T; end,
          
          DecideZeroRowsWRTNonBasis :=
            function( B )
              local R;
              R := HomalgRing( B );
              if not ( HasIsBasisOfRowsMatrix( B ) and
                       IsBasisOfRowsMatrix( B ) ) and
                 IsBound( R!.DecideZeroWRTNonBasis ) then
                  if R!.DecideZeroWRTNonBasis = "warn" then
                      Info( InfoWarning, 1,
                            "about to reduce with respect to a matrix",
                            "with IsBasisOfRowsMatrix not set to true" );
                  elif R!.DecideZeroWRTNonBasis = "error" then
                      Error( "about to reduce with respect to a matrix",
                             "with IsBasisOfRowsMatrix not set to true\n" );
                  fi;
              fi;
            end,
          
          DecideZeroColumnsWRTNonBasis :=
            function( B )
              local R;
              R := HomalgRing( B );
              if not ( HasIsBasisOfColumnsMatrix( B ) and
                       IsBasisOfColumnsMatrix( B ) ) and
                 IsBound( R!.DecideZeroWRTNonBasis ) then
                  if R!.DecideZeroWRTNonBasis = "warn" then
                      Info( InfoWarning, 1,
                            "about to reduce with respect to a matrix",
                            "with IsBasisOfColumnsMatrix not set to true" );
                  elif R!.DecideZeroWRTNonBasis = "error" then
                      Error( "about to reduce with respect to a matrix",
                             "with IsBasisOfColumnsMatrix not set to true\n" );
                  fi;
              fi;
            end,
          
          ReducedBasisOfRowModule :=
            function( M, B )
              return GenerateSameRowModule( B, BasisOfRowModule( M ) );
            end,
          
          ReducedBasisOfColumnModule :=
            function( M, B )
              return GenerateSameColumnModule( B, BasisOfColumnModule( M ) );
            end,
          
          ReducedSyzygiesGeneratorsOfRows :=
            function( M, S )
              return GenerateSameRowModule( S, SyzygiesGeneratorsOfRows( M ) );
            end,
          
          ReducedSyzygiesGeneratorsOfColumns :=
            function( M, S )
              return GenerateSameColumnModule( S, SyzygiesGeneratorsOfColumns( M ) );
            end,
          
         );
    ##  ]]></Listing>
    ##  <#/GAPDoc>
    
    homalg_ring := rec(
                       ring := r,
                       IdentityMatrices := IdentityMatrices,
                       statistics := statistics,
                       asserts := asserts,
                       DecideZeroWRTNonBasis := "warn/error"
                       );
    
    if nargs > 1 and IshomalgTable( arg[nargs] ) then
        table := arg[nargs];
    else
        table := CreateHomalgTable( r );
    fi;
    
    if not IsBound( table!.InitialMatrix ) and IsBound( table!.ZeroMatrix ) then
        table!.InitialMatrix := table!.ZeroMatrix;
    fi;
    
    if not IsBound( table!.InitialIdentityMatrix ) and IsBound( table!.IdentityMatrix ) then
        table!.InitialIdentityMatrix := table!.IdentityMatrix;
    fi;
    
    properties := [ ];
    
    for ar in arg{[ 2 .. nargs ]} do
        if IsFilter( ar ) then
            Add( properties, ar );
        elif not IsBound( type ) and IsList( ar ) and Length( ar ) = 2 and ForAll( ar, IsType ) then
            type := ar;
        elif not IsBound( ring_element_constructor ) and IsFunction( ar ) then
            ring_element_constructor := ar;
        elif not IsBound( finalizers ) and IsList( ar ) and ForAll( ar, IsFunction ) then
            finalizers := ar;
        fi;
    od;
    
    if IsBound( type ) then
        matrix_type := type[2];
        type := type[1];
    elif IsSemiringWithOneAndZero( r ) then
        matrix_type := ValueGlobal( "TheTypeHomalgInternalMatrix" ); ## will be defined later in HomalgMatrix.gi
        type := TheTypeHomalgInternalRing;
    else
        Error( "the types of the ring and matrices were not specified\n" );
    fi;
    
    ## Objectify:
    ObjectifyWithAttributes(
            homalg_ring, type,
            homalgTable, table );
    
    if IsBound( matrix_type ) then
        SetTypeOfHomalgMatrix( homalg_ring, matrix_type );
    fi;
    
    if properties <> [ ] then
        for ar in properties do
            Setter( ar )( homalg_ring, true );
        od;
    fi;
    
    if IsBound( HOMALG_MATRICES.RingCounter ) then
        HOMALG_MATRICES.RingCounter := HOMALG_MATRICES.RingCounter + 1;
    else
        HOMALG_MATRICES.RingCounter := 1;
    fi;
    
    ## this has to be done before we call
    ## ring_element_constructor below
    homalg_ring!.creation_number := HOMALG_MATRICES.RingCounter;
    
    ## do not invoke SetRingProperties here, since I might be
    ## the first step of creating a residue class ring!
    
    ## this has to be invoked before we set the distinguished ring elements below;
    ## these functions are used to finalize the construction of the ring
    if IsBound( finalizers ) then
        Perform( finalizers, function( f ) f( homalg_ring ); end );
    fi;
    
    ## add distinguished ring elements like 0 and 1
    ## (sometimes also -1) to the homalg table:
    if IsBound( ring_element_constructor ) then
        
        for c in NamesOfComponents( table ) do
            if IsRingElement( table!.(c) ) then
                table!.(c) := ring_element_constructor( table!.(c), homalg_ring );
            fi;
        od;
        
        ## set the attribute
        SetRingElementConstructor( homalg_ring, ring_element_constructor );
        
    fi;
    
    if IsBound( HOMALG_MATRICES.ByASmallerPresentation ) and HOMALG_MATRICES.ByASmallerPresentation = true then
        homalg_ring!.ByASmallerPresentation := true;
    fi;
    
    ## e.g. needed to construct residue class rings
    homalg_ring!.ConstructorArguments := arg;
    
    homalg_ring!.interpret_rationals_func :=
      function( r )
        local d;
        d := DenominatorRat( r ) / homalg_ring;
        if IsZero( d ) or not IsUnit( homalg_ring, d ) then
            return fail;
        fi;
        return r / homalg_ring;
    end;
    
    return homalg_ring;
    
end );

##  <#GAPDoc Label="HomalgRingOfIntegers">
##  <ManSection>
##    <Func Arg="" Name="HomalgRingOfIntegers" Label="constructor for the integers"/>
##    <Returns>a &homalg; ring</Returns>
##    <Func Arg="c" Name="HomalgRingOfIntegers" Label="constructor for the residue class rings of the integers"/>
##    <Returns>a &homalg; ring</Returns>
##    <Description>
##      The no-argument form returns the ring of integers <M>&ZZ;</M> for &homalg;. <P/>
##      The one-argument form accepts an integer <A>c</A> and returns
##      the ring <M>&ZZ; / c </M> for &homalg;:
##      <List>
##        <Item><A>c</A><M> = 0</M> defaults to <M>&ZZ;</M></Item>
##        <Item>if <A>c</A> is a prime power then the package &GaussForHomalg; is loaded (if it fails to load an error is issued)</Item>
##        <Item>otherwise, the residue class ring constructor <C>/</C>
##          (&see; <Ref Oper="\/" Label="constructor for residue class rings" Style="Number"/>) is invoked</Item>
##      </List>
##      The operation <C>SetRingProperties</C> is automatically invoked to set the ring properties. <P/>
##      If for some reason you don't want to use the &GaussForHomalg; package (maybe because you didn't install it), then use<P/>
##      <C>HomalgRingOfIntegers</C>( ) <C>/</C> <A>c</A>; <P/>
##      but note that the computations will then be considerably slower.
##    </Description>
##  </ManSection>
##  <#/GAPDoc>
##
InstallGlobalFunction( HomalgRingOfIntegers,
  function( arg )
    local nargs, R, c, d, rel;
    
    nargs := Length( arg );
    
    if nargs = 0 or arg[1] = 0 then
        c := 0;
        R := CreateHomalgRing( Integers );
        SetRingFilter( R, IsHomalgRing );
        SetRingElementFilter( R, IsInt );
    elif IsInt( arg[1] ) then
        c := arg[1];
        if Length( Collected( FactorsInt( c ) ) ) = 1 and IsPackageMarkedForLoading( "GaussForHomalg", ">= 2018.09.20") then
            R := HOMALG_RING_OF_INTEGERS_PRIME_POWER_HELPER( arg, c );
        else
            R := HomalgRingOfIntegers( );
            rel := HomalgRingRelationsAsGeneratorsOfLeftIdeal( [ c ], R );
            return R / rel;
        fi;
    else
        Error( "the first argument must be an integer\n" );
    fi;
    
    SetIsResidueClassRingOfTheIntegers( R, true );
    
    SetRingProperties( R, c );
    
    return R;
    
end );

##
InstallMethod( HomalgRingOfIntegersInUnderlyingCAS,
        "for an integer and homalg internal ring",
        [ IsInt, IsHomalgInternalRingRep ],
        
  HomalgRingOfIntegers );

##
InstallOtherMethod( \in,
        "for an object and a homalg internal ring",
        [ IsObject, IsHomalgInternalRingRep ], 100001,
        
  function( r, R )
    
    return r in R!.ring;
    
end );

##
InstallMethod( ParseListOfIndeterminates,
        "for lists",
        [ IsList ],
        
  function( _indets )
    local err, l, indets, i, v, l1, l2, p1, p2, c;
    
    if _indets = [ ] then
        return [ ];
    fi;
    
    err := function( ) Error( "a list of variable strings or range strings is expected\n" ); end;
    
    if ForAll( _indets, IsRingElement and HasName ) then
        return ParseListOfIndeterminates( List( _indets, Name ) );
    fi;
    
    if not ForAll( _indets, e -> IsStringRep( e ) or ( IsList( e ) and ForAll( e, IsInt ) ) ) then
        TryNextMethod( );
    fi;
    
    l := Length( _indets );
    
    indets := [ ];
    
    for i in [ 1 .. l ] do
        v := _indets[i];
        if Position( v, ',' ) <> fail then
            err( );
        elif ForAll( v, IsInt ) then
            ## do nothing
        elif Position( v, '.' ) = fail then
            if i < l and ForAll( _indets[ i + 1 ], IsInt ) then
                Append( indets, List( _indets[ i + 1 ], i -> Concatenation( v, String( i ) ) ) );
            else
                Add( indets, v );
            fi;
        elif PositionSublist( v, ".." ) = fail then
            err( );
        else
            v := SplitString( v, "." );
            v := Filtered( v, s -> not IsEmpty( s ) );
            if Length( v ) <> 2 then
                err( );
            fi;
#             p1 := PositionProperty( v[1], c -> Position( "0123456789", c ) <> fail );
#             p2 := PositionProperty( v[2], c -> Position( "0123456789", c ) <> fail );
            l1 := Flat( List( "0123456789", c -> Positions( v[1], c ) ) );
            Sort( l1 );
            l2 := Flat( List( "0123456789", c -> Positions( v[2], c ) ) );
            Sort( l2 );
            if l1 = [] or l2 = [] then
                err( );
            fi;
            p1 := l1[1];
            p2 := l2[1];
            for i in [ 2 .. Length( l1 ) ] do
                if l1[i-1] + 1 <> l1[i] then
                    p1 := l1[i];
                fi;
            od;
            for i in [ 2 .. Length( l2 ) ] do
                if l2[i-1] + 1 <> l2[i] then
                    p2 := l2[i];
                fi;
            od;
            if p1 = 1 then
                err( );
            fi;
            c := v[1]{[ 1 .. p1 - 1 ]};
            if p1 = p2 and c <> v[2]{[ 1 .. p2 - 1 ]} then
                err( );
            fi;
            p1 := EvalString( v[1]{[ p1 .. Length( v[1] ) ]} );
            p2 := EvalString( v[2]{[ p2 .. Length( v[2] ) ]} );
            Append( indets, List( [ p1 .. p2 ], i -> Concatenation( c, String( i ) ) ) );
        fi;
    od;
    
    return indets;
    
end );

##
InstallGlobalFunction( _PrepareInputForPolynomialRing,
  function( R, indets )
    local var, nr_var, properties, r, var_of_base_ring, param;
    
    if HasRingRelations( R ) then
        Error( "polynomial rings over homalg residue class rings are not supported yet\nUse the generic residue class ring constructor '/' provided by homalg after defining the ambient ring\nfor help type: ?homalg: constructor for residue class rings\n" );
    fi;
    
    ## get the new indeterminates for the ring and save them in var
    if IsString( indets ) and indets <> "" then
        var := SplitString( indets, "," );
    elif indets <> [ ] and ForAll( indets, i -> IsString( i ) and i <> "" ) then
        var := indets;
    else
        Error( "either a non-empty list of indeterminates or a comma separated string of them must be provided as the second argument\n" );
    fi;
    
    if not IsDuplicateFree( var ) then
        Error( "your list of indeterminates is not duplicate free: ", var, "\n" );
    fi;
    
    nr_var := Length( var );
    
    properties := [ IsCommutative ];
    
    ## K[x] is a principal ideal ring for a field K
    if Length( var ) = 1 and HasIsFieldForHomalg( R ) and IsFieldForHomalg( R ) then
        Add( properties, IsPrincipalIdealRing );
    fi;
    
    ## r is set to the ring of coefficients
    ## further a check is done, whether the old indeterminates (if exist) and the new
    ## ones are disjoint
    if HasIndeterminatesOfPolynomialRing( R ) then
        r := CoefficientsRing( R );
        var_of_base_ring := IndeterminatesOfPolynomialRing( R );
        var_of_base_ring := List( var_of_base_ring, Name );
        if Intersection2( var_of_base_ring, var ) <> [ ] then
            Error( "the following indeterminates are already elements of the base ring: ", Intersection2( var_of_base_ring, var ), "\n" );
        fi;
    else
        r := R;
        var_of_base_ring := [ ];
    fi;
    
    var := Concatenation( var_of_base_ring, var );
    
    if HasRationalParameters( r ) then
--> --------------------

--> maximum size reached

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

[ Dauer der Verarbeitung: 0.39 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