Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/sc/source/core/tool/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 20 kB image not shown  

Quelle  refupdat.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include <refupdat.hxx>
#include <document.hxx>
#include <bigrange.hxx>
#include <refdata.hxx>

#include <osl/diagnose.h>

templatetypename R, typename S, typename U >
static bool lcl_MoveStart( R& rRef, U nStart, S nDelta, U nMask, bool bShrink = true )
{
    bool bCut = false;
    if ( rRef >= nStart )
        rRef = sal::static_int_cast<R>( rRef + nDelta );
    else if ( nDelta < 0 && bShrink && rRef >= nStart + nDelta )
        rRef = nStart + nDelta;             //TODO: limit ???
    if ( rRef < 0 )
    {
        rRef = 0;
        bCut = true;
    }
    else if ( rRef > nMask )
    {
        rRef = nMask;
        bCut = true;
    }
    return bCut;
}

templatetypename R, typename S, typename U >
static bool lcl_MoveEnd( R& rRef, U nStart, S nDelta, U nMask, bool bShrink = true )
{
    bool bCut = false;
    if ( rRef >= nStart )
        rRef = sal::static_int_cast<R>( rRef + nDelta );
    else if ( nDelta < 0 && bShrink && rRef >= nStart + nDelta )
        rRef = nStart + nDelta - 1;         //TODO: limit ???
    if (rRef < 0)
    {
        rRef = 0;
        bCut = true;
    }
    else if(rRef > nMask)
    {
        rRef = nMask;
        bCut = true;
    }
    return bCut;
}

templatetypename R, typename S, typename U >
static bool lcl_MoveReorder( R& rRef, U nStart, U nEnd, S nDelta )
{
    if ( rRef >= nStart && rRef <= nEnd )
    {
        rRef = sal::static_int_cast<R>( rRef + nDelta );
        return true;
    }

    if ( nDelta > 0 )                   // move backward
    {
        if ( rRef >= nStart && rRef <= nEnd + nDelta )
        {
            if ( rRef <= nEnd )
                rRef = sal::static_int_cast<R>( rRef + nDelta );    // in the moved range
            else
                rRef -= nEnd - nStart + 1;      // move up
            return true;
        }
    }
    else                                // move forward
    {
        if ( rRef >= nStart + nDelta && rRef <= nEnd )
        {
            if ( rRef >= nStart )
                rRef = sal::static_int_cast<R>( rRef + nDelta );    // in the moved range
            else
                rRef += nEnd - nStart + 1;      // move up
            return true;
        }
    }

    return false;
}

templatetypename R, typename S, typename U >
static bool lcl_MoveItCut( R& rRef, S nDelta, U nMask )
{
    bool bCut = false;
    rRef = sal::static_int_cast<R>( rRef + nDelta );
    if ( rRef < 0 )
    {
        rRef = 0;
        bCut = true;
    }
    else if ( rRef > nMask )
    {
        rRef = nMask;
        bCut = true;
    }
    return bCut;
}

templatetypename R, typename U >
static void lcl_MoveItWrap( R& rRef, U nMask )
{
    rRef = sal::static_int_cast<R>( rRef );
    if ( rRef < 0 )
        rRef += nMask+1;
    else if ( rRef > nMask )
        rRef -= nMask+1;
}

templatetypename R, typename S, typename U >
static bool IsExpand( R n1, R n2, U nStart, S nD )
{   // before normal Move...
    return
        nD > 0          // Insert
     && n1 < n2         // at least two Cols/Rows/Tabs in Ref
     && (
        (nStart <= n1 && n1 < nStart + nD)      // n1 within the Insert
        || (n2 + 1 == nStart)                   // n2 directly before Insert
        );      // n1 < nStart <= n2 is expanded anyway!
}

templatetypename R, typename S, typename U >
static void Expand( R& n1, R& n2, U nStart, S nD )
{   // after normal Move..., only if IsExpand was true before!
    // first the End
    if ( n2 + 1 == nStart )
    {   // at End
        n2 = sal::static_int_cast<R>( n2 + nD );
        return;
    }
    // at the beginning
    n1 = sal::static_int_cast<R>( n1 - nD );
}

static bool lcl_IsWrapBig( sal_Int64 nRef, sal_Int32 nDelta )
{
    if (nDelta > 0)
        return nRef > std::numeric_limits<sal_Int64>::max() - nDelta;
    else
        return nRef < std::numeric_limits<sal_Int64>::min() - nDelta;
}

static bool lcl_MoveBig( sal_Int64& rRef, sal_Int64 nStart, sal_Int32 nDelta )
{
    bool bCut = false;
    if ( rRef >= nStart )
    {
        if ( nDelta > 0 )
            bCut = lcl_IsWrapBig( rRef, nDelta );
        if ( bCut )
            rRef = ScBigRange::nRangeMax;
        else
            rRef += nDelta;
    }
    return bCut;
}

static bool lcl_MoveItCutBig( sal_Int64& rRef, sal_Int32 nDelta )
{
    bool bCut = lcl_IsWrapBig( rRef, nDelta );
    rRef += nDelta;
    return bCut;
}

ScRefUpdateRes ScRefUpdate::Update( const ScDocument& rDoc, UpdateRefMode eUpdateRefMode,
                                        SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
                                        SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
                                        SCCOL nDx, SCROW nDy, SCTAB nDz,
                                        SCCOL& theCol1, SCROW& theRow1, SCTAB& theTab1,
                                        SCCOL& theCol2, SCROW& theRow2, SCTAB& theTab2 )
{
    ScRefUpdateRes eRet = UR_NOTHING;

    SCCOL oldCol1 = theCol1;
    SCROW oldRow1 = theRow1;
    SCTAB oldTab1 = theTab1;
    SCCOL oldCol2 = theCol2;
    SCROW oldRow2 = theRow2;
    SCTAB oldTab2 = theTab2;

    bool bCut1, bCut2;

    if (eUpdateRefMode == URM_INSDEL)
    {
        bool bExpand = rDoc.IsExpandRefs();
        if ( nDx && (theRow1 >= nRow1) && (theRow2 <= nRow2) &&
                    (theTab1 >= nTab1) && (theTab2 <= nTab2))
        {
            bool bExp = (bExpand && IsExpand( theCol1, theCol2, nCol1, nDx ));
            bCut1 = lcl_MoveStart( theCol1, nCol1, nDx, rDoc.MaxCol() );
            bCut2 = lcl_MoveEnd( theCol2, nCol1, nDx, rDoc.MaxCol() );
            if ( theCol2 < theCol1 )
            {
                eRet = UR_INVALID;
                theCol2 = theCol1;
            }
            else if (bCut2 && theCol2 == 0)
                eRet = UR_INVALID;
            else if ( bCut1 || bCut2 )
                eRet = UR_UPDATED;
            if ( bExp )
            {
                Expand( theCol1, theCol2, nCol1, nDx );
                eRet = UR_UPDATED;
            }
            if (eRet != UR_NOTHING && oldCol1 == 0 && oldCol2 == rDoc.MaxCol())
            {
                eRet = UR_STICKY;
                theCol1 = oldCol1;
                theCol2 = oldCol2;
            }
            else if (oldCol2 == rDoc.MaxCol() && oldCol1 < rDoc.MaxCol())
            {
                // End was sticky, but start may have been moved. Only on range.
                theCol2 = oldCol2;
                if (eRet == UR_NOTHING)
                    eRet = UR_STICKY;
            }
            // Else, if (bCut2 && theCol2 == rDoc.MaxCol()) then end becomes sticky,
            // but currently there's nothing to do.
        }
        if ( nDy && (theCol1 >= nCol1) && (theCol2 <= nCol2) &&
                    (theTab1 >= nTab1) && (theTab2 <= nTab2))
        {
            bool bExp = (bExpand && IsExpand( theRow1, theRow2, nRow1, nDy ));
            bCut1 = lcl_MoveStart( theRow1, nRow1, nDy, rDoc.MaxRow() );
            bCut2 = lcl_MoveEnd( theRow2, nRow1, nDy, rDoc.MaxRow() );
            if ( theRow2 < theRow1 )
            {
                eRet = UR_INVALID;
                theRow2 = theRow1;
            }
            else if (bCut2 && theRow2 == 0)
                eRet = UR_INVALID;
            else if ( bCut1 || bCut2 )
                eRet = UR_UPDATED;
            if ( bExp )
            {
                Expand( theRow1, theRow2, nRow1, nDy );
                eRet = UR_UPDATED;
            }
            if (eRet != UR_NOTHING && oldRow1 == 0 && oldRow2 == rDoc.MaxRow())
            {
                eRet = UR_STICKY;
                theRow1 = oldRow1;
                theRow2 = oldRow2;
            }
            else if (oldRow2 == rDoc.MaxRow() && oldRow1 < rDoc.MaxRow())
            {
                // End was sticky, but start may have been moved. Only on range.
                theRow2 = oldRow2;
                if (eRet == UR_NOTHING)
                    eRet = UR_STICKY;
            }
            // Else, if (bCut2 && theRow2 == rDoc.MaxRow()) then end becomes sticky,
            // but currently there's nothing to do.
        }
        if ( nDz && (theCol1 >= nCol1) && (theCol2 <= nCol2) &&
                    (theRow1 >= nRow1) && (theRow2 <= nRow2) )
        {
            SCTAB nMaxTab = rDoc.GetTableCount() - 1;
            nMaxTab = sal::static_int_cast<SCTAB>(nMaxTab + nDz);      // adjust to new count
            bool bExp = (bExpand && IsExpand( theTab1, theTab2, nTab1, nDz ));
            bCut1 = lcl_MoveStart( theTab1, nTab1, nDz, nMaxTab, false /*bShrink*/);
            bCut2 = lcl_MoveEnd( theTab2, nTab1, nDz, nMaxTab, false /*bShrink*/);
            if ( theTab2 < theTab1 )
            {
                eRet = UR_INVALID;
                theTab2 = theTab1;
            }
            else if ( bCut1 || bCut2 )
                eRet = UR_UPDATED;
            if ( bExp )
            {
                Expand( theTab1, theTab2, nTab1, nDz );
                eRet = UR_UPDATED;
            }
        }
    }
    else if (eUpdateRefMode == URM_MOVE)
    {
        if ((theCol1 >= nCol1-nDx) && (theRow1 >= nRow1-nDy) && (theTab1 >= nTab1-nDz) &&
            (theCol2 <= nCol2-nDx) && (theRow2 <= nRow2-nDy) && (theTab2 <= nTab2-nDz))
        {
            if ( nDx )
            {
                bCut1 = lcl_MoveItCut( theCol1, nDx, rDoc.MaxCol() );
                bCut2 = lcl_MoveItCut( theCol2, nDx, rDoc.MaxCol() );
                if ( bCut1 || bCut2 )
                    eRet = UR_UPDATED;
                if (eRet != UR_NOTHING && oldCol1 == 0 && oldCol2 == rDoc.MaxCol())
                {
                    eRet = UR_STICKY;
                    theCol1 = oldCol1;
                    theCol2 = oldCol2;
                }
            }
            if ( nDy )
            {
                bCut1 = lcl_MoveItCut( theRow1, nDy, rDoc.MaxRow() );
                bCut2 = lcl_MoveItCut( theRow2, nDy, rDoc.MaxRow() );
                if ( bCut1 || bCut2 )
                    eRet = UR_UPDATED;
                if (eRet != UR_NOTHING && oldRow1 == 0 && oldRow2 == rDoc.MaxRow())
                {
                    eRet = UR_STICKY;
                    theRow1 = oldRow1;
                    theRow2 = oldRow2;
                }
            }
            if ( nDz )
            {
                SCTAB nMaxTab = rDoc.GetTableCount() - 1;
                bCut1 = lcl_MoveItCut( theTab1, nDz, nMaxTab );
                bCut2 = lcl_MoveItCut( theTab2, nDz, nMaxTab );
                if ( bCut1 || bCut2 )
                    eRet = UR_UPDATED;
            }
        }
    }
    else if (eUpdateRefMode == URM_REORDER)
    {
        //  so far only for nDz (MoveTab)
        OSL_ENSURE ( !nDx && !nDy, "URM_REORDER for x and y not yet implemented" );

        if ( nDz && (theCol1 >= nCol1) && (theCol2 <= nCol2) &&
                    (theRow1 >= nRow1) && (theRow2 <= nRow2) )
        {
            bCut1 = lcl_MoveReorder( theTab1, nTab1, nTab2, nDz );
            bCut2 = lcl_MoveReorder( theTab2, nTab1, nTab2, nDz );
            if ( bCut1 || bCut2 )
                eRet = UR_UPDATED;
        }
    }

    if ( eRet == UR_NOTHING )
    {
        if (oldCol1 != theCol1
         || oldRow1 != theRow1
         || oldTab1 != theTab1
         || oldCol2 != theCol2
         || oldRow2 != theRow2
         || oldTab2 != theTab2
            )
            eRet = UR_UPDATED;
    }
    return eRet;
}

// simple UpdateReference for ScBigRange (ScChangeAction/ScChangeTrack)
// References can also be located outside of the document!
// Whole columns/rows (ScBigRange::nRangeMin..ScBigRange::nRangeMax) stay as such!
ScRefUpdateRes ScRefUpdate::Update( UpdateRefMode eUpdateRefMode,
        const ScBigRange& rWhere, sal_Int32 nDx, sal_Int32 nDy, sal_Int32 nDz,
        ScBigRange& rWhat )
{
    ScRefUpdateRes eRet = UR_NOTHING;
    const ScBigRange aOldRange( rWhat );

    sal_Int64 nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
    sal_Int64 theCol1, theRow1, theTab1, theCol2, theRow2, theTab2;
    rWhere.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
    rWhat.GetVars( theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 );

    bool bCut1, bCut2;

    if (eUpdateRefMode == URM_INSDEL)
    {
        if ( nDx && (theRow1 >= nRow1) && (theRow2 <= nRow2) &&
                    (theTab1 >= nTab1) && (theTab2 <= nTab2) &&
                    (theCol1 != ScBigRange::nRangeMin || theCol2 != ScBigRange::nRangeMax) )
        {
            bCut1 = lcl_MoveBig( theCol1, nCol1, nDx );
            bCut2 = lcl_MoveBig( theCol2, nCol1, nDx );
            if ( bCut1 || bCut2 )
                eRet = UR_UPDATED;
            rWhat.aStart.SetCol( theCol1 );
            rWhat.aEnd.SetCol( theCol2 );
        }
        if ( nDy && (theCol1 >= nCol1) && (theCol2 <= nCol2) &&
                    (theTab1 >= nTab1) && (theTab2 <= nTab2) &&
                    (theRow1 != ScBigRange::nRangeMin || theRow2 != ScBigRange::nRangeMax) )
        {
            bCut1 = lcl_MoveBig( theRow1, nRow1, nDy );
            bCut2 = lcl_MoveBig( theRow2, nRow1, nDy );
            if ( bCut1 || bCut2 )
                eRet = UR_UPDATED;
            rWhat.aStart.SetRow( theRow1 );
            rWhat.aEnd.SetRow( theRow2 );
        }
        if ( nDz && (theCol1 >= nCol1) && (theCol2 <= nCol2) &&
                    (theRow1 >= nRow1) && (theRow2 <= nRow2) &&
                    (theTab1 != ScBigRange::nRangeMin || theTab2 != ScBigRange::nRangeMax) )
        {
            bCut1 = lcl_MoveBig( theTab1, nTab1, nDz );
            bCut2 = lcl_MoveBig( theTab2, nTab1, nDz );
            if ( bCut1 || bCut2 )
                eRet = UR_UPDATED;
            rWhat.aStart.SetTab( theTab1 );
            rWhat.aEnd.SetTab( theTab2 );
        }
    }
    else if (eUpdateRefMode == URM_MOVE)
    {
        if ( rWhere.Contains( rWhat ) )
        {
            if ( nDx && (theCol1 != ScBigRange::nRangeMin || theCol2 != ScBigRange::nRangeMax) )
            {
                bCut1 = lcl_MoveItCutBig( theCol1, nDx );
                bCut2 = lcl_MoveItCutBig( theCol2, nDx );
                if ( bCut1 || bCut2 )
                    eRet = UR_UPDATED;
                rWhat.aStart.SetCol( theCol1 );
                rWhat.aEnd.SetCol( theCol2 );
            }
            if ( nDy && (theRow1 != ScBigRange::nRangeMin || theRow2 != ScBigRange::nRangeMax) )
            {
                bCut1 = lcl_MoveItCutBig( theRow1, nDy );
                bCut2 = lcl_MoveItCutBig( theRow2, nDy );
                if ( bCut1 || bCut2 )
                    eRet = UR_UPDATED;
                rWhat.aStart.SetRow( theRow1 );
                rWhat.aEnd.SetRow( theRow2 );
            }
            if ( nDz && (theTab1 != ScBigRange::nRangeMin || theTab2 != ScBigRange::nRangeMax) )
            {
                bCut1 = lcl_MoveItCutBig( theTab1, nDz );
                bCut2 = lcl_MoveItCutBig( theTab2, nDz );
                if ( bCut1 || bCut2 )
                    eRet = UR_UPDATED;
                rWhat.aStart.SetTab( theTab1 );
                rWhat.aEnd.SetTab( theTab2 );
            }
        }
    }

    if ( eRet == UR_NOTHING && rWhat != aOldRange )
        eRet = UR_UPDATED;

    return eRet;
}

void ScRefUpdate::MoveRelWrap( const ScDocument& rDoc, const ScAddress& rPos,
                               SCCOL nMaxCol, SCROW nMaxRow, ScComplexRefData& rRef )
{
    ScRange aAbsRange = rRef.toAbs(rDoc, rPos);
    if( rRef.Ref1.IsColRel() )
    {
        SCCOL nCol = aAbsRange.aStart.Col();
        lcl_MoveItWrap(nCol, nMaxCol);
        aAbsRange.aStart.SetCol(nCol);
    }
    if( rRef.Ref2.IsColRel() )
    {
        SCCOL nCol = aAbsRange.aEnd.Col();
        lcl_MoveItWrap(nCol, nMaxCol);
        aAbsRange.aEnd.SetCol(nCol);
    }
    if( rRef.Ref1.IsRowRel() )
    {
        SCROW nRow = aAbsRange.aStart.Row();
        lcl_MoveItWrap(nRow, nMaxRow);
        aAbsRange.aStart.SetRow(nRow);
    }
    if( rRef.Ref2.IsRowRel() )
    {
        SCROW nRow = aAbsRange.aEnd.Row();
        lcl_MoveItWrap(nRow, nMaxRow);
        aAbsRange.aEnd.SetRow(nRow);
    }
    SCTAB nMaxTab = rDoc.GetTableCount() - 1;
    if( rRef.Ref1.IsTabRel() )
    {
        SCTAB nTab = aAbsRange.aStart.Tab();
        lcl_MoveItWrap(nTab, nMaxTab);
        aAbsRange.aStart.SetTab(nTab);
    }
    if( rRef.Ref2.IsTabRel() )
    {
        SCTAB nTab = aAbsRange.aEnd.Tab();
        lcl_MoveItWrap(nTab, nMaxTab);
        aAbsRange.aEnd.SetTab(nTab);
    }

    aAbsRange.PutInOrder();
    rRef.SetRange(rDoc.GetSheetLimits(), aAbsRange, rPos);
}

void ScRefUpdate::DoTranspose( SCCOL& rCol, SCROW& rRow, SCTAB& rTab,
                        const ScDocument& rDoc, const ScRange& rSource, const ScAddress& rDest )
{
    SCTAB nDz = rDest.Tab() - rSource.aStart.Tab();
    if (nDz)
    {
        SCTAB nNewTab = rTab+nDz;
        SCTAB nCount = rDoc.GetTableCount();
        while (nNewTab<0) nNewTab = sal::static_int_cast<SCTAB>( nNewTab + nCount );
        while (nNewTab>=nCount) nNewTab = sal::static_int_cast<SCTAB>( nNewTab - nCount );
        rTab = nNewTab;
    }
    OSL_ENSURE( rCol>=rSource.aStart.Col() && rRow>=rSource.aStart.Row(),
                "UpdateTranspose: pos. wrong" );

    SCCOL nRelX = rCol - rSource.aStart.Col();
    SCROW nRelY = rRow - rSource.aStart.Row();

    rCol = static_cast<SCCOL>(static_cast<SCCOLROW>(rDest.Col()) +
            static_cast<SCCOLROW>(nRelY));
    rRow = static_cast<SCROW>(static_cast<SCCOLROW>(rDest.Row()) +
            static_cast<SCCOLROW>(nRelX));
}

ScRefUpdateRes ScRefUpdate::UpdateTranspose(
    const ScDocument& rDoc, const ScRange& rSource, const ScAddress& rDest, ScRange& rRef )
{
    ScRefUpdateRes eRet = UR_NOTHING;
    // Only references in source range must be updated, i.e. no references in destination area.
    // Otherwise existing references pointing to destination area will be wrongly transposed.
    if (rSource.Contains(rRef))
    {
        // Source range contains the reference range.
        SCCOL nCol1 = rRef.aStart.Col(), nCol2 = rRef.aEnd.Col();
        SCROW nRow1 = rRef.aStart.Row(), nRow2 = rRef.aEnd.Row();
        SCTAB nTab1 = rRef.aStart.Tab(), nTab2 = rRef.aEnd.Tab();
        DoTranspose(nCol1, nRow1, nTab1, rDoc, rSource, rDest);
        DoTranspose(nCol2, nRow2, nTab2, rDoc, rSource, rDest);
        rRef.aStart = ScAddress(nCol1, nRow1, nTab1);
        rRef.aEnd = ScAddress(nCol2, nRow2, nTab2);
        eRet = UR_UPDATED;
    }
    return eRet;
}

//  UpdateGrow - expands references which point exactly to the area
//  gets by without document

ScRefUpdateRes ScRefUpdate::UpdateGrow(
    const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY, ScRange& rRef )
{
    ScRefUpdateRes eRet = UR_NOTHING;

    //  in y-direction the Ref may also start one row further below,
    //  if an area contains column heads

    bool bUpdateX = ( nGrowX &&
            rRef.aStart.Col() == rArea.aStart.Col() && rRef.aEnd.Col() == rArea.aEnd.Col() &&
            rRef.aStart.Row() >= rArea.aStart.Row() && rRef.aEnd.Row() <= rArea.aEnd.Row() &&
            rRef.aStart.Tab() >= rArea.aStart.Tab() && rRef.aEnd.Tab() <= rArea.aEnd.Tab() );
    bool bUpdateY = ( nGrowY &&
        rRef.aStart.Col() >= rArea.aStart.Col() && rRef.aEnd.Col() <= rArea.aEnd.Col() &&
        (rRef.aStart.Row() == rArea.aStart.Row() || rRef.aStart.Row() == rArea.aStart.Row()+1) &&
        rRef.aEnd.Row() == rArea.aEnd.Row() &&
        rRef.aStart.Tab() >= rArea.aStart.Tab() && rRef.aEnd.Tab() <= rArea.aEnd.Tab() );

    if ( bUpdateX )
    {
        rRef.aEnd.SetCol(sal::static_int_cast<SCCOL>(rRef.aEnd.Col() + nGrowX));
        eRet = UR_UPDATED;
    }
    if ( bUpdateY )
    {
        rRef.aEnd.SetRow(sal::static_int_cast<SCROW>(rRef.aEnd.Row() + nGrowY));
        eRet = UR_UPDATED;
    }

    return eRet;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=89 H=96 G=92

¤ Dauer der Verarbeitung: 0.7 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.