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


Quelle  StaticObjects.gi   Sprache: unbekannt

 
# SPDX-License-Identifier: GPL-2.0-or-later
# homalg: A homological algebra meta-package for computable Abelian categories
#
# Implementations
#

##  Implementations of homalg procedures for homalg static objects.

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

## fallback method
InstallMethod( ResolutionWithRespectToMorphism,
          "for a homalg object",
        [ IsInt, IsHomalgStaticObject, IsStaticMorphismOfFinitelyGeneratedObjectsRep ],
        
  function( q, M, psi )
    
    return Resolution( q, M );
    
end );


##
InstallMethod( \/,
        "for homalg subobjects of static objects",
        [ IsStaticFinitelyPresentedSubobjectRep, IsStaticFinitelyPresentedSubobjectRep ],
        
  function( K, J )
    local M, mapK, mapJ, phi, im, iso, def, emb;
    
    M := SuperObject( J );
    
    if not IsIdenticalObj( M, SuperObject( K ) ) then
        Error( "the super objects must coincide\n" );
    fi;
    
    mapK := MorphismHavingSubobjectAsItsImage( K );
    mapJ := MorphismHavingSubobjectAsItsImage( J );
    
    phi := PreCompose( mapK, CokernelEpi( mapJ ) );
    
    im := ImageObject( phi );
    
    ## recall that im was created as a subobject of
    ## Cokernel( mapJ ) which in turn is a factor object of M,
    ## but since we need to view im as a subfactor of M
    ## we will construct an isomorphism iso onto im
    iso := AnIsomorphism( im );
    
    ## and call its source def (for defect)
    def := Source( iso );
    
    ## then: the following compositions give the
    ## desired generalized embedding of def into M
    emb := PreCompose( iso, NaturalGeneralizedEmbedding( im ) );
    
    emb := PreCompose( emb, CokernelNaturalGeneralizedIsomorphism( mapJ ) );
    
    ## check assertion
    Assert( 5, IsGeneralizedMonomorphism( emb ) );
    
    SetIsGeneralizedMonomorphism( emb, true );
    
    def!.NaturalGeneralizedEmbedding := emb;
    
    return def;
    
end );

##
InstallMethod( \/,
        "for homalg subobjects of static objects",
        [ IsStaticFinitelyPresentedObjectRep, IsStaticFinitelyPresentedSubobjectRep ],
        
  function( M, N ) ## M must be either the super object of N or 1 * R or R * 1
    local R;
    
    CheckIfTheyLieInTheSameCategory( M, N );
    
    R := StructureObject( M );
    
    if not ( IsIdenticalObj( M, SuperObject( N ) ) or IsIdenticalObj( M, 1 * R ) or IsIdenticalObj( M, R * 1 ) ) then
        TryNextMethod( );
    fi;
    
    return FactorObject( N );
    
end );

##
InstallMethod( \/,
        "for homalg static objects",
        [ IsStaticFinitelyPresentedObjectRep, IsStaticFinitelyPresentedObjectRep and HasUnderlyingSubobject ],
        
  function( M, N ) ## M must be either the super object of N or 1 * R or R * 1
    
    return M / UnderlyingSubobject( N );
    
end );

##
InstallMethod( HasCurrentResolution,
        "for a homalg static object",
        [ IsHomalgStaticObject ],
        
  function( M )
    local pos;
    
    pos := PositionOfTheDefaultPresentation( M );
    
    return IsBound( M!.Resolutions ) and IsBound( M!.Resolutions.(pos) );
    
end );

##
InstallMethod( CurrentResolution,
        "for a homalg static object",
        [ IsHomalgStaticObject ],
        
  function( M )
    local pos;
    
    pos := PositionOfTheDefaultPresentation( M );
    
    return M!.Resolutions.(pos);
    
end );

##
InstallMethod( Resolution,
        "for homalg subobjects of static objects",
        [ IsInt, IsStaticFinitelyPresentedSubobjectRep ],
        
  function( q, N )
    
    return Resolution( q, UnderlyingObject( N ) );
    
end );

##
InstallMethod( Resolution,
        "for homalg static objects",
        [ IsStaticFinitelyPresentedObjectOrSubobjectRep ],
        
  function( M )
    
    return Resolution( -1, M );
    
end );

##
InstallMethod( FiniteFreeResolution,
        "for homalg static objects",
        [ IsStaticFinitelyPresentedObjectRep ],
        
  function( M )
    
    if HasAFiniteFreeResolution( M ) then
        return AFiniteFreeResolution( M );
    elif not HasFiniteFreeResolutionExists( M ) or FiniteFreeResolutionExists( M ) then ## in words: either a finite free resolution exists or its existence is not known yet
        Resolution( M );
    fi;
    
    ## now check again:
    if HasAFiniteFreeResolution( M ) then
        return AFiniteFreeResolution( M );
    fi;
    
    return fail;
    
end );

##
InstallMethod( LengthOfResolution,
        "for homalg static objects",
        [ IsStaticFinitelyPresentedObjectOrSubobjectRep ],
        
  function( M )
    local d;
    
    d := Resolution( M );
    
    if IsBound(d!.LengthOfResolution) then
        return d!.LengthOfResolution;
    else
        return fail;
    fi;
    
end );

##
InstallMethod( FirstMorphismOfResolution,
        "for homalg static objects",
        [ IsStaticFinitelyPresentedObjectOrSubobjectRep ],
        
  function( M )
    local d;
    
    d := Resolution( 1, M );
    
    return CertainMorphism( d, 1 );
    
end );

##
InstallMethod( SyzygiesObjectEmb,
        "for homalg static objects",
        [ IsInt, IsStaticFinitelyPresentedObjectRep ],
        
  function( q, M )
    local d;
    
    if q < 0 then
        Error( "a negative integer does not make sense\n" );
    elif q = 0 then
        ## this is not really an embedding, but spares us case distinctions at several places (e.g. Left/RightSatelliteOfFunctor)
        return TheMorphismToZero( M );
    elif q = 1 then
        return KernelEmb( CoveringEpi( M ) );
    fi;
    
    d := Resolution( q - 1, M );
    
    return KernelEmb( CertainMorphism( d, q - 1 ) );
    
end );

##
InstallMethod( SyzygiesObjectEmb,
        "for homalg static objects",
        [ IsStaticFinitelyPresentedObjectRep ],
        
  function( M )
    
    return SyzygiesObjectEmb( 1, M );
    
end );

##
InstallMethod( SyzygiesObject,
        "for homalg static objects",
        [ IsInt, IsStaticFinitelyPresentedObjectRep ],
        
  function( q, M )
    local d;
    
    if q < 0 then
        return 0 * M;
    elif q = 0 then
        return M;
    fi;
    
    return Source( SyzygiesObjectEmb( q, M ) );
    
end );

##
InstallMethod( SyzygiesObject,
        "for homalg static objects",
        [ IsStaticFinitelyPresentedObjectRep ],
        
  function( M )
    
    return SyzygiesObject( 1, M );
    
end );

##
InstallMethod( CoveringEpi,
        "for homalg static objects",
        [ IsStaticFinitelyPresentedObjectRep ],
        
  function( M )
    
    return SyzygiesObjectEpi( 0, M );
    
end );

InstallMethod( CoveringEpi,
        "for homalg static objects",
        [ IsStaticFinitelyPresentedSubobjectRep ],
        
  function( M )
    
    return CoveringEpi( UnderlyingObject( M ) );
    
end );

##
InstallMethod( CoveringObject,
        "for homalg static objects",
        [ IsStaticFinitelyPresentedObjectRep ],
        
  function( M )
    
    return Source( CoveringEpi( M ) );
    
end );

##
InstallMethod( SubResolution,
        "for homalg static objects",
        [ IsInt, IsStaticFinitelyPresentedObjectRep and IsHomalgLeftObjectOrMorphismOfLeftObjects ],
        
  function( q, M )
    local d, dq1, res;
    
    if q < 0 then
        Error( "a negative integer does not make sense\n" );
    elif q = 0 then
        dq1 := FirstMorphismOfResolution( M );
        res := AsATwoSequence( dq1, TheMorphismToZero( CoveringObject( M ) ) );
        if HasIsMonomorphism( dq1 ) and IsMonomorphism( dq1 ) then
            SetIsRightAcyclic( res, true );
        else
            SetIsAcyclic( res, true );
        fi;
        return res;
    fi;
    
    d := Resolution( q + 1, M );
    
    dq1 := CertainMorphism( d, q + 1 );
    
    res := AsATwoSequence( dq1, CertainMorphism( d, q ) );
    
    res := Shift( res, -q );
    
    if HasIsMonomorphism( dq1 ) and IsMonomorphism( dq1 ) then
        SetIsRightAcyclic( res, true );
    else
        SetIsAcyclic( res, true );
    fi;
    
    SetIsATwoSequence( res, true );
    
    return res;
    
end );

##
InstallMethod( SubResolution,
        "for homalg static objects",
        [ IsInt, IsStaticFinitelyPresentedObjectRep and IsHomalgRightObjectOrMorphismOfRightObjects ],
        
  function( q, M )
    local d, dq1, res;
    
    if q < 0 then
        Error( "a negative integer does not make sense\n" );
    elif q = 0 then
        dq1 := FirstMorphismOfResolution( M );
        res := AsATwoSequence( TheMorphismToZero( CoveringObject( M ) ), dq1 );
        if HasIsMonomorphism( dq1 ) and IsMonomorphism( dq1 ) then
            SetIsRightAcyclic( res, true );
        else
            SetIsAcyclic( res, true );
        fi;
        return res;
    fi;
    
    d := Resolution( q + 1, M );
    
    dq1 := CertainMorphism( d, q + 1 );
    
    res := AsATwoSequence( CertainMorphism( d, q ), dq1 );
    
    res := Shift( res, -q );
    
    if HasIsMonomorphism( dq1 ) and IsMonomorphism( dq1 ) then
        SetIsRightAcyclic( res, true );
    else
        SetIsAcyclic( res, true );
    fi;
    
    SetIsATwoSequence( res, true );
    
    return res;
    
end );

#=======================================================================
# Shorten a given resolution q times if possible
#
# I learned it from Alban's thesis
#
# see also Alban and Daniel:
# Constructive Computation of Bases of Free Modules over the Weyl Algebras
#
# (see also [Rotman, Lemma 9.40])
#
#_______________________________________________________________________
InstallMethod( ShortenResolution,
        "an integer and a right acyclic complex",
        [ IsInt, IsComplexOfFinitelyPresentedObjectsRep and IsRightAcyclic ],
        
  function( q, d ) ## q is the number of shortening steps
    local max, min, m, n, mx, d_m, d_m_1, shortened, F_m, s_m_1, d_m_2,
          d_short, l, epi;
    
    max := HighestDegree( d );
    min := LowestDegree( d );
    
    m := max - min;
    
    ## q = 0 means do not shorten
    ## q < 0 means fully shorten
    
    if q = 0 or m < 2 then
        return d;
    fi;
    
    ## initialize
    n := q; ## number of shortening steps
    mx := max;
    
    d_m := CertainMorphism( d, mx );
    d_m_1 := CertainMorphism( d, mx - 1 );
    
    shortened := false;
    
    ## iterate: m is now at least 2, i.e. at least two morphisms
    while n <> 0 and m > 1 do
        
        F_m := Source( d_m );
        
        if IsZero( F_m ) then
            
            d_m := d_m_1;
            
            if m > 2 then
                d_m_1 := CertainMorphism( d, mx - 2 );
            fi;
            
        else
            
            s_m_1 := PostInverse( d_m );
            
            if IsBool( s_m_1 ) then
                if not shortened then
                    ## the resolution cannot be shortened
                    return d;
                fi;
                
                ## the resolution cannot be shortened further
                break;
            fi;
            
            shortened := true;
            
            d_m := ProductMorphism( d_m_1, s_m_1 );
            
            Assert( 4, IsMonomorphism( d_m ) );
            
            SetIsMonomorphism( d_m, true );
            
            if m > 2 then
                d_m_2 := CertainMorphism( d, mx - 2 ); ## only for the next line
                d_m_1 := CoproductMorphism( d_m_2, TheZeroMorphism( F_m, Range( d_m_2 ) ) );
                if m = 3 then
                    if not HasCokernelEpi( d_m_2 ) then
                        Error( "d_m_2 has no CokernelEpi set\n" );
                    fi;
                    epi := CokernelEpi( d_m_2 );
                    if HasCokernelEpi( d_m_1 ) and not CokernelEpi( d_m_1 ) = epi then
                        Error( "d_m_1 already has CokernelEpi set\n" );
                    fi;
                    SetCokernelEpi( d_m_1, epi );
                fi;
            fi;
            
        fi;
        
        mx := mx - 1;
        m := m - 1;
        n := n - 1;
    od;
    
    if m > 2 then
        d_short := HomalgComplex( CertainMorphism( d, min + 1 ), min + 1 );
        for l in [ 2 .. m - 2 ] do
            Add( d_short, CertainMorphism( d, min + l ) );
        od;
        Add( d_short, d_m_1 );
        Add( d_short, d_m );
    elif m = 2 then
        d_short := HomalgComplex( d_m_1, min + 1 );
        Add( d_short, d_m );
    else ## m = 1
        
        if not IsIdenticalObj( d_m, CertainMorphism( d, 1 ) ) then
            
            if not IsIdenticalObj( d_m_1, CertainMorphism( d, 1 ) ) then
                Error( "expected d_m_1 to be the first morphism of the given resolution\n" );
            elif HasCokernelEpi( d_m_1 ) then
                ## d_m_1 is the first morphism of the given resolution
                epi := PreCompose( EpiOnLeftFactor( Range( d_m ) ), CokernelEpi( d_m_1 ) );
                if HasCokernelEpi( d_m ) and not CokernelEpi( d_m ) = epi then
                    Error( "d_m already has CokernelEpi set\n" );
                fi;
                SetCokernelEpi( d_m, epi );
            fi;
        fi;
        
        d_short := HomalgComplex( d_m, min + 1 );
    fi;
    
    d_short!.LengthOfResolution := m;
    
    SetIsRightAcyclic( d_short, true );
    
    return d_short;
    
end );

##
InstallMethod( ShortenResolution,
        "for homalg complexes",
        [ IsComplexOfFinitelyPresentedObjectsRep and IsRightAcyclic ],
        
  function( d )
    
    return ShortenResolution( -1, d );
    
end );

##
InstallMethod( ShortenResolution,
        "for homalg static objects",
        [ IsInt, IsStaticFinitelyPresentedObjectRep ],
        
  function( q, M )
    local d, l;
    
    d := Resolution( M );
    
    d := ShortenResolution( q, d );
    
    l := HighestDegree( d );
    
    if IsZero( CertainMorphism( d, l ) ) then
        l := 0;
    fi;
    
    if ForAll( ObjectsOfComplex( d ), HasIsProjective and IsProjective ) then
        SetUpperBoundForProjectiveDimension( M, l );
    fi;
    
    if l <> 1 then
        SetProjectiveDimension( M, l );
    fi;
    
    SetCurrentResolution( M, d );
    
    SetAFiniteFreeResolution( M, d );
    
    return d;
    
end );

##
InstallMethod( ShortenResolution,
        "for homalg static objects",
        [ IsStaticFinitelyPresentedObjectRep ],
        
  function( M )
    
    return ShortenResolution( -1, M );
    
end );

##
InstallMethod( AsEpimorphicImage,
        "for morphisms of static homalg objects",
        [ IsStaticMorphismOfFinitelyGeneratedObjectsRep ],
        
  function( phi )
    local pos, iso;
    
    if not ( HasIsEpimorphism( phi ) and IsEpimorphism( phi ) ) and
       not IsZero( Cokernel( phi ) ) then ## I do not require phi to be a morphism, that's why I don't use IsEpimorphism
        Error( "the first argument must be an epimorphism\n" );
    fi;
    
    if HasIsIsomorphism( phi ) and IsIsomorphism( phi ) then
        
        iso := phi;
        
    else
        
        iso := ImageObjectEmb( phi );
        
        ## phi is not required to be a morphism, hence
        ## the properties of iso might not have been set
        IsIsomorphism( iso );
        
    fi;
    
    return PushPresentationByIsomorphism( iso );
    
end );

## the second argument is there for method selection
InstallMethod( Intersect2,
        "for homalg objects",
        [ IsList, IsObject ],
        
  function( L, M )
    
    return Iterated( L, Intersect2 );
    
end );

##
InstallGlobalFunction( Intersect,
  function( arg )
    local nargs;
    
    nargs := Length( arg );
    
    if nargs = 0  then
        Error( "<arg> must be nonempty" );
    elif Length( arg ) = 1 and IsList( arg[1] )  then
        if IsEmpty( arg[1] )  then
            Error( "<arg>[1] must be nonempty" );
        fi;
        arg := arg[1];
    fi;
    
    return Intersect2( arg, arg[1] );
    
end );

##
InstallMethod( Intersect2,
        "for homalg subobjects of static objects",
        [ IsStaticFinitelyPresentedSubobjectRep, IsStaticFinitelyPresentedSubobjectRep ],
        
  function( K, J )
    local M, KnJ;
    
    M := SuperObject( J );
    
    if not IsIdenticalObj( M, SuperObject( K ) ) then
        Error( "the super objects must coincide\n" );
    fi;
    
    K := MorphismHavingSubobjectAsItsImage( K );
    J := MorphismHavingSubobjectAsItsImage( J );
    
    K := CokernelEpi( K );
    J := CokernelEpi( J );
    
    KnJ := KernelEmb( ProductMorphism( K, J ) );
    
    return Subobject( KnJ );
    
end );

##  <#GAPDoc Label="IntersectWithMultiplicity">
##  <ManSection>
##    <Oper Arg="ideals, mults" Name="IntersectWithMultiplicity"/>
##    <Returns>a &homalg; left or right ideal</Returns>
##    <Description>
##      Intersect the ideals in the list <A>ideals</A> after raising them to the corresponding power specified in the list of
##      multiplicities <A>mults</A>.
##      <Example><![CDATA[
##  ]]></Example>
##    </Description>
##  </ManSection>
##  <#/GAPDoc>
##
InstallMethod( IntersectWithMultiplicity,
        "for homalg ideals",
        [ IsList, IsList ],
        
  function( ideals, mults )
    local s, left, intersection;
    
    if not ForAll( ideals, p -> IsStaticFinitelyPresentedSubobjectRep( p ) and HasConstructedAsAnIdeal( p ) and ConstructedAsAnIdeal( p ) ) then
        Error( "the first argument is not a list of ideals\n" );
    fi;
    
    ## the number of ideals
    s := Length( ideals );
    
    if s = 0 then
        Error( "the list of ideals is empty\n" );
    fi;
    
    if s <> Length( mults ) then
        Error( "the length of the list of ideals and the length of the list of their multiplicities must coincide\n" );
    fi;
    
    ## decide if we are dealing with left or right ideals
    left := IsHomalgLeftObjectOrMorphismOfLeftObjects( ideals[1] );
    
    if not ForAll( ideals, a -> IsHomalgLeftObjectOrMorphismOfLeftObjects( a ) = left ) then
        Error( "all ideals must be provided either by left or by right ideals\n" );
    fi;
    
    intersection := Iterated( List( [ 1 .. s ], i -> ideals[i]^mults[i] ), Intersect );
    
    SetGenesis( intersection, [ IntersectWithMultiplicity, ideals, mults ] );
    
    return intersection;
    
end );

##
InstallMethod( EmbeddingsInCoproductObject,
        "for homalg static objects",
        [ IsStaticFinitelyPresentedObjectRep, IsList ],
        
  function( coproduct, degrees )
    local l, embeddings, emb_summand, summand, i;
    
    if ( IsBound( coproduct!.EmbeddingsInCoproductObject ) and
         IsBound( coproduct!.EmbeddingsInCoproductObject.degrees ) and
         coproduct!.EmbeddingsInCoproductObject.degrees = degrees ) then
        
        return coproduct!.EmbeddingsInCoproductObject;
        
    fi;
    
    l := Length( degrees );
    
    if l < 2 then
        return fail;
    fi;
    
    embeddings := rec( );
    
    ## contruct the total embeddings of summands into their coproduct
    if l = 2 then
        embeddings.(String(degrees[1])) := MonoOfRightSummand( coproduct );
        embeddings.(String(degrees[2])) := MonoOfLeftSummand( coproduct );
    else
        emb_summand := TheIdentityMorphism( coproduct );
        summand := coproduct;
        embeddings.(String(degrees[1])) := MonoOfRightSummand( summand );
        
        for i in [ 2 .. l - 1 ] do
            emb_summand := PreCompose( MonoOfLeftSummand( summand ), emb_summand );
            summand := Range( EpiOnLeftFactor( summand ) );
            embeddings.(String(degrees[i])) := PreCompose( MonoOfRightSummand( summand ), emb_summand );
        od;
        
        embeddings.(String(degrees[l])) := PreCompose( MonoOfLeftSummand( summand ), emb_summand );
    fi;
    
    coproduct!.EmbeddingsInCoproductObject := embeddings;
    
    return embeddings;
    
end );

##
InstallMethod( ProjectionsFromProductObject,
        "for homalg static objects",
        [ IsStaticFinitelyPresentedObjectRep, IsList ],
        
  function( product, degrees )
    local l, projections, prj_factor, factor, i;
    
    if ( IsBound( product!.ProjectionsFromProductObject ) and
         IsBound( product!.ProjectionsFromProductObject.degrees ) and
         product!.ProjectionsFromProductObject.degrees = degrees ) then
        
        return product!.ProjectionsFromProductObject;
        
    fi;
    
    l := Length( degrees );
    
    if l < 2 then
        return fail;
    fi;
    
    projections := rec( );
    
    ## contruct the total projections from the product onto the factors
    if l = 2 then
        projections.(String(degrees[1])) := EpiOnRightFactor( product );
        projections.(String(degrees[2])) := EpiOnLeftFactor( product );
    else
        prj_factor := TheIdentityMorphism( product );
        factor := product;
        projections.(String(degrees[1])) := EpiOnRightFactor( factor );
        
        for i in [ 2 .. l - 1 ] do
            prj_factor := PreCompose( prj_factor, EpiOnLeftFactor( factor ) );
            factor := Source( MonoOfLeftSummand( factor ) );
            projections.(String(degrees[i])) := PreCompose( prj_factor, EpiOnRightFactor( factor ) );
        od;
        
        projections.(String(degrees[l])) := PreCompose( prj_factor, EpiOnLeftFactor( factor ) );
    fi;
    
    product!.ProjectionsFromProductObject := projections;
    
    return projections;
    
end );

##  <#GAPDoc Label="Saturate">
##  <ManSection>
##    <Oper Arg="K, J" Name="Saturate" Label="for ideals"/>
##    <Returns>a &homalg; ideal</Returns>
##    <Description>
##      Compute the saturation ideal <M><A>K</A>:<A>J</A>^\infty</M> of the ideals <A>K</A> and <A>J</A>.
##    <P/>
##    <#Include Label="Saturate:example">
##    <P/>
##    <Listing Type="Code"><![CDATA[
InstallMethod( Saturate,
        "for homalg subobjects of static objects",
        [ IsStaticFinitelyPresentedSubobjectRep, IsStaticFinitelyPresentedSubobjectRep ],
        
  function( K, J )
    local quotient_last, quotient;
    
    quotient_last := SubobjectQuotient( K, J );
    
    quotient := SubobjectQuotient( quotient_last, J );
    
    while not IsSubset( quotient_last, quotient ) do
        quotient_last := quotient;
        quotient := SubobjectQuotient( quotient_last, J );
    od;
    
    return quotient_last;
    
end );

##
InstallMethod( \-, ## a geometrically motivated definition
        "for homalg subobjects of static objects",
        [ IsStaticFinitelyPresentedSubobjectRep, IsStaticFinitelyPresentedSubobjectRep ],
        
  function( K, J )
    
    return Saturate( K, J );
    
end );
##  ]]></Listing>
##    </Description>
##  </ManSection>
##  <#/GAPDoc>

##
InstallMethod( SetPropertiesIfKernelIsTorsionObject,
        "for homalg morphisms of static object",
        [ IsHomalgStaticMorphism ],
        
  function( par )
    local M;
    
    M := Source( par );
    
    if HasIsTorsionFree( M ) then
        ## never skip this HasIsTorsionFree since
        ## the current procedure maybe have been invoked from
        ## a procedure used to set IsTorsionFree,
        ## which would then lead to infinite loops
        
        Assert( 4, IsMonomorphism( par ) = IsTorsionFree( M ) );
        
        SetIsMonomorphism( par, IsTorsionFree( M ) );
        
    else
        
        Assert( 4, IsMorphism( par ) );
        
        SetIsMorphism( par, true );
        
    fi;
    
end );

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