LCOV - code coverage report
Current view: top level - sc/source/core/tool - interpr6.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 347 584 59.4 %
Date: 2014-11-03 Functions: 35 39 89.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "interpre.hxx"
      21             : #include "columnspanset.hxx"
      22             : #include "column.hxx"
      23             : #include "document.hxx"
      24             : #include "cellvalue.hxx"
      25             : #include "dociter.hxx"
      26             : #include "mtvcellfunc.hxx"
      27             : 
      28             : #include <formula/token.hxx>
      29             : 
      30             : using namespace formula;
      31             : 
      32             : double const fHalfMachEps = 0.5 * ::std::numeric_limits<double>::epsilon();
      33             : 
      34             : // The idea how this group of gamma functions is calculated, is
      35             : // based on the Cephes library
      36             : // online http://www.moshier.net/#Cephes [called 2008-02]
      37             : 
      38             : /** You must ensure fA>0.0 && fX>0.0
      39             :     valid results only if fX > fA+1.0
      40             :     uses continued fraction with odd items */
      41          78 : double ScInterpreter::GetGammaContFraction( double fA, double fX )
      42             : {
      43             : 
      44          78 :     double const fBigInv = ::std::numeric_limits<double>::epsilon();
      45          78 :     double const fBig = 1.0/fBigInv;
      46          78 :     double fCount = 0.0;
      47          78 :     double fNum = 0.0;  // dummy value
      48          78 :     double fY = 1.0 - fA;
      49          78 :     double fDenom = fX + 2.0-fA;
      50          78 :     double fPk = 0.0;   // dummy value
      51          78 :     double fPkm1 = fX + 1.0;
      52          78 :     double fPkm2 = 1.0;
      53          78 :     double fQk = 1.0;   // dummy value
      54          78 :     double fQkm1 = fDenom * fX;
      55          78 :     double fQkm2 = fX;
      56          78 :     double fApprox = fPkm1/fQkm1;
      57          78 :     bool bFinished = false;
      58          78 :     double fR = 0.0;    // dummy value
      59        1932 :     do
      60             :     {
      61        1932 :         fCount = fCount +1.0;
      62        1932 :         fY = fY+ 1.0;
      63        1932 :         fNum = fY * fCount;
      64        1932 :         fDenom = fDenom +2.0;
      65        1932 :         fPk = fPkm1 * fDenom  -  fPkm2 * fNum;
      66        1932 :         fQk = fQkm1 * fDenom  -  fQkm2 * fNum;
      67        1932 :         if (fQk != 0.0)
      68             :         {
      69        1932 :             fR = fPk/fQk;
      70        1932 :             bFinished = (fabs( (fApprox - fR)/fR ) <= fHalfMachEps);
      71        1932 :             fApprox = fR;
      72             :         }
      73        1932 :         fPkm2 = fPkm1;
      74        1932 :         fPkm1 = fPk;
      75        1932 :         fQkm2 = fQkm1;
      76        1932 :         fQkm1 = fQk;
      77        1932 :         if (fabs(fPk) > fBig)
      78             :         {
      79             :             // reduce a fraction does not change the value
      80         120 :             fPkm2 = fPkm2 * fBigInv;
      81         120 :             fPkm1 = fPkm1 * fBigInv;
      82         120 :             fQkm2 = fQkm2 * fBigInv;
      83         120 :             fQkm1 = fQkm1 * fBigInv;
      84             :         }
      85        3786 :     } while (!bFinished && fCount<10000);
      86             :     // most iterations, if fX==fAlpha+1.0; approx sqrt(fAlpha) iterations then
      87          78 :     if (!bFinished)
      88             :     {
      89           0 :         SetError(errNoConvergence);
      90             :     }
      91          78 :     return fApprox;
      92             : }
      93             : 
      94             : /** You must ensure fA>0.0 && fX>0.0
      95             :     valid results only if fX <= fA+1.0
      96             :     uses power series */
      97         414 : double ScInterpreter::GetGammaSeries( double fA, double fX )
      98             : {
      99         414 :     double fDenomfactor = fA;
     100         414 :     double fSummand = 1.0/fA;
     101         414 :     double fSum = fSummand;
     102         414 :     int nCount=1;
     103        4800 :     do
     104             :     {
     105        4800 :         fDenomfactor = fDenomfactor + 1.0;
     106        4800 :         fSummand = fSummand * fX/fDenomfactor;
     107        4800 :         fSum = fSum + fSummand;
     108        4800 :         nCount = nCount+1;
     109        9186 :     } while ( fSummand/fSum > fHalfMachEps && nCount<=10000);
     110             :     // large amount of iterations will be carried out for huge fAlpha, even
     111             :     // if fX <= fAlpha+1.0
     112         414 :     if (nCount>10000)
     113             :     {
     114           0 :         SetError(errNoConvergence);
     115             :     }
     116         414 :     return fSum;
     117             : }
     118             : 
     119             : /** You must ensure fA>0.0 && fX>0.0) */
     120         402 : double ScInterpreter::GetLowRegIGamma( double fA, double fX )
     121             : {
     122         402 :     double fLnFactor = fA * log(fX) - fX - GetLogGamma(fA);
     123         402 :     double fFactor = exp(fLnFactor);    // Do we need more accuracy than exp(ln()) has?
     124         402 :     if (fX>fA+1.0)  // includes fX>1.0; 1-GetUpRegIGamma, continued fraction
     125           6 :         return 1.0 - fFactor * GetGammaContFraction(fA,fX);
     126             :     else            // fX<=1.0 || fX<=fA+1.0, series
     127         396 :         return fFactor * GetGammaSeries(fA,fX);
     128             : }
     129             : 
     130             : /** You must ensure fA>0.0 && fX>0.0) */
     131          90 : double ScInterpreter::GetUpRegIGamma( double fA, double fX )
     132             : {
     133             : 
     134          90 :     double fLnFactor= fA*log(fX)-fX-GetLogGamma(fA);
     135          90 :     double fFactor = exp(fLnFactor); //Do I need more accuracy than exp(ln()) has?;
     136          90 :     if (fX>fA+1.0) // includes fX>1.0
     137          72 :             return fFactor * GetGammaContFraction(fA,fX);
     138             :     else //fX<=1 || fX<=fA+1, 1-GetLowRegIGamma, series
     139          18 :             return 1.0 -fFactor * GetGammaSeries(fA,fX);
     140             : }
     141             : 
     142             : /** Gamma distribution, probability density function.
     143             :     fLambda is "scale" parameter
     144             :     You must ensure fAlpha>0.0 and fLambda>0.0 */
     145           0 : double ScInterpreter::GetGammaDistPDF( double fX, double fAlpha, double fLambda )
     146             : {
     147           0 :     if (fX < 0.0)
     148           0 :         return 0.0;     // see ODFF
     149           0 :     else if (fX == 0)
     150             :         // in this case 0^0 isn't zero
     151             :     {
     152           0 :         if (fAlpha < 1.0)
     153             :         {
     154           0 :             SetError(errDivisionByZero);  // should be #DIV/0
     155           0 :             return HUGE_VAL;
     156             :         }
     157           0 :         else if (fAlpha == 1)
     158             :         {
     159           0 :             return (1.0 / fLambda);
     160             :         }
     161             :         else
     162             :         {
     163           0 :             return 0.0;
     164             :         }
     165             :     }
     166             :     else
     167             :     {
     168           0 :         double fXr = fX / fLambda;
     169             :         // use exp(ln()) only for large arguments because of less accuracy
     170           0 :         if (fXr > 1.0)
     171             :         {
     172           0 :             const double fLogDblMax = log( ::std::numeric_limits<double>::max());
     173           0 :             if (log(fXr) * (fAlpha-1.0) < fLogDblMax && fAlpha < fMaxGammaArgument)
     174             :             {
     175           0 :                 return pow( fXr, fAlpha-1.0) * exp(-fXr) / fLambda / GetGamma(fAlpha);
     176             :             }
     177             :             else
     178             :             {
     179           0 :                 return exp( (fAlpha-1.0) * log(fXr) - fXr - log(fLambda) - GetLogGamma(fAlpha));
     180             :             }
     181             :         }
     182             :         else    // fXr near to zero
     183             :         {
     184           0 :             if (fAlpha<fMaxGammaArgument)
     185             :             {
     186           0 :                 return pow( fXr, fAlpha-1.0) * exp(-fXr) / fLambda / GetGamma(fAlpha);
     187             :             }
     188             :             else
     189             :             {
     190           0 :                 return pow( fXr, fAlpha-1.0) * exp(-fXr) / fLambda / exp( GetLogGamma(fAlpha));
     191             :             }
     192             :         }
     193             :     }
     194             : }
     195             : 
     196             : /** Gamma distribution, cumulative distribution function.
     197             :     fLambda is "scale" parameter
     198             :     You must ensure fAlpha>0.0 and fLambda>0.0 */
     199         348 : double ScInterpreter::GetGammaDist( double fX, double fAlpha, double fLambda )
     200             : {
     201         348 :     if (fX <= 0.0)
     202           6 :         return 0.0;
     203             :     else
     204         342 :         return GetLowRegIGamma( fAlpha, fX / fLambda);
     205             : }
     206             : 
     207             : namespace {
     208             : 
     209             : class NumericCellAccumulator
     210             : {
     211             :     double mfSum;
     212             :     sal_uInt16 mnError;
     213             : 
     214             : public:
     215        2394 :     NumericCellAccumulator() : mfSum(0.0), mnError(0) {}
     216             : 
     217        9658 :     void operator() (size_t, double fVal)
     218             :     {
     219        9658 :         mfSum += fVal;
     220        9658 :     }
     221             : 
     222        1428 :     void operator() (size_t, const ScFormulaCell* pCell)
     223             :     {
     224        1428 :         if (mnError)
     225             :             // Skip all the rest if we have an error.
     226           8 :             return;
     227             : 
     228        1426 :         double fVal = 0.0;
     229        1426 :         sal_uInt16 nErr = 0;
     230        1426 :         ScFormulaCell& rCell = const_cast<ScFormulaCell&>(*pCell);
     231        1426 :         if (!rCell.GetErrorOrValue(nErr, fVal))
     232             :             // The cell has neither error nor value.  Perhaps string result.
     233           0 :             return;
     234             : 
     235        1426 :         if (nErr)
     236             :         {
     237             :             // Cell has error.
     238           4 :             mnError = nErr;
     239           4 :             return;
     240             :         }
     241             : 
     242        1422 :         mfSum += fVal;
     243             :     }
     244             : 
     245        2394 :     sal_uInt16 getError() const { return mnError; }
     246        2390 :     double getSum() const { return mfSum; }
     247             : };
     248             : 
     249             : class NumericCellCounter
     250             : {
     251             :     size_t mnCount;
     252             : public:
     253          40 :     NumericCellCounter() : mnCount(0) {}
     254             : 
     255          96 :     void operator() (const sc::CellStoreType::value_type& rNode, size_t nOffset, size_t nDataSize)
     256             :     {
     257          96 :         switch (rNode.type)
     258             :         {
     259             :             case sc::element_type_numeric:
     260          36 :                 mnCount += nDataSize;
     261          36 :             break;
     262             :             case sc::element_type_formula:
     263             :             {
     264          44 :                 sc::formula_block::const_iterator it = sc::formula_block::begin(*rNode.data);
     265          44 :                 std::advance(it, nOffset);
     266          44 :                 sc::formula_block::const_iterator itEnd = it;
     267          44 :                 std::advance(itEnd, nDataSize);
     268         112 :                 for (; it != itEnd; ++it)
     269             :                 {
     270          68 :                     ScFormulaCell& rCell = const_cast<ScFormulaCell&>(**it);
     271          68 :                     if (rCell.IsValueNoError())
     272          64 :                         ++mnCount;
     273             :                 }
     274             :             }
     275          44 :             break;
     276             :             default:
     277             :                 ;
     278             :         }
     279          96 :     }
     280             : 
     281          40 :     size_t getCount() const { return mnCount; }
     282             : };
     283             : 
     284          32 : class FuncCount : public sc::ColumnSpanSet::ColumnAction
     285             : {
     286             :     sc::ColumnBlockConstPosition maPos;
     287             :     ScColumn* mpCol;
     288             :     size_t mnCount;
     289             :     sal_uInt32 mnNumFmt;
     290             : 
     291             : public:
     292          32 :     FuncCount() : mpCol(0), mnCount(0), mnNumFmt(0) {}
     293             : 
     294          40 :     virtual void startColumn(ScColumn* pCol) SAL_OVERRIDE
     295             :     {
     296          40 :         mpCol = pCol;
     297          40 :         mpCol->InitBlockPosition(maPos);
     298          40 :     }
     299             : 
     300          80 :     virtual void execute(SCROW nRow1, SCROW nRow2, bool bVal) SAL_OVERRIDE
     301             :     {
     302          80 :         if (!bVal)
     303         120 :             return;
     304             : 
     305          40 :         NumericCellCounter aFunc;
     306          40 :         maPos.miCellPos = sc::ParseBlock(maPos.miCellPos, mpCol->GetCellStore(), aFunc, nRow1, nRow2);
     307          40 :         mnCount += aFunc.getCount();
     308          40 :         mnNumFmt = mpCol->GetNumberFormat(nRow2);
     309             :     };
     310             : 
     311          32 :     size_t getCount() const { return mnCount; }
     312          32 :     sal_uInt32 getNumberFormat() const { return mnNumFmt; }
     313             : };
     314             : 
     315        1757 : class FuncSum : public sc::ColumnSpanSet::ColumnAction
     316             : {
     317             :     sc::ColumnBlockConstPosition maPos;
     318             :     ScColumn* mpCol;
     319             :     double mfSum;
     320             :     sal_uInt16 mnError;
     321             :     sal_uInt32 mnNumFmt;
     322             : 
     323             : public:
     324        1757 :     FuncSum() : mpCol(0), mfSum(0.0), mnError(0), mnNumFmt(0) {}
     325             : 
     326        2394 :     virtual void startColumn(ScColumn* pCol) SAL_OVERRIDE
     327             :     {
     328        2394 :         mpCol = pCol;
     329        2394 :         mpCol->InitBlockPosition(maPos);
     330        2394 :     }
     331             : 
     332        6718 :     virtual void execute(SCROW nRow1, SCROW nRow2, bool bVal) SAL_OVERRIDE
     333             :     {
     334        6718 :         if (!bVal)
     335        8652 :             return;
     336             : 
     337        2394 :         if (mnError)
     338           0 :             return;
     339             : 
     340        2394 :         NumericCellAccumulator aFunc;
     341        2394 :         maPos.miCellPos = sc::ParseFormulaNumeric(maPos.miCellPos, mpCol->GetCellStore(), nRow1, nRow2, aFunc);
     342        2394 :         mnError = aFunc.getError();
     343        2394 :         if (mnError)
     344           4 :             return;
     345             : 
     346        2390 :         mfSum += aFunc.getSum();
     347        2390 :         mnNumFmt = mpCol->GetNumberFormat(nRow2);
     348             :     };
     349             : 
     350        1757 :     sal_uInt16 getError() const { return mnError; }
     351        1753 :     double getSum() const { return mfSum; }
     352        1753 :     sal_uInt32 getNumberFormat() const { return mnNumFmt; }
     353             : };
     354             : 
     355          18 : void IterateMatrix(
     356             :     const ScMatrixRef& pMat, ScIterFunc eFunc, bool bTextAsZero,
     357             :     sal_uLong& rCount, short& rFuncFmtType, double& fRes, double& fMem, bool& bNull)
     358             : {
     359          18 :     if (!pMat)
     360          18 :         return;
     361             : 
     362             :     // TODO fdo73148 take mnSubTotalFlags into account
     363          18 :     rFuncFmtType = NUMBERFORMAT_NUMBER;
     364          18 :     switch (eFunc)
     365             :     {
     366             :         case ifAVERAGE:
     367             :         case ifSUM:
     368             :         {
     369           8 :             ScMatrix::IterateResult aRes = pMat->Sum(bTextAsZero);
     370           8 :             if (bNull)
     371             :             {
     372           8 :                 bNull = false;
     373           8 :                 fMem = aRes.mfFirst;
     374           8 :                 fRes += aRes.mfRest;
     375             :             }
     376             :             else
     377           0 :                 fRes += aRes.mfFirst + aRes.mfRest;
     378           8 :             rCount += aRes.mnCount;
     379             :         }
     380           8 :         break;
     381             :         case ifCOUNT:
     382           4 :             rCount += pMat->Count(bTextAsZero);
     383           4 :         break;
     384             :         case ifCOUNT2:
     385           4 :             rCount += pMat->Count(true);
     386           4 :         break;
     387             :         case ifPRODUCT:
     388             :         {
     389           2 :             ScMatrix::IterateResult aRes = pMat->Product(bTextAsZero);
     390           2 :             fRes = aRes.mfFirst;
     391           2 :             fRes *= aRes.mfRest;
     392           2 :             rCount += aRes.mnCount;
     393             :         }
     394           2 :         break;
     395             :         case ifSUMSQ:
     396             :         {
     397           0 :             ScMatrix::IterateResult aRes = pMat->SumSquare(bTextAsZero);
     398           0 :             fRes += aRes.mfRest;
     399           0 :             rCount += aRes.mnCount;
     400             :         }
     401           0 :         break;
     402             :         default:
     403             :             ;
     404             :     }
     405             : }
     406             : 
     407             : }
     408             : 
     409         594 : double ScInterpreter::IterateParameters( ScIterFunc eFunc, bool bTextAsZero )
     410             : {
     411         594 :     short nParamCount = GetByte();
     412         594 :     double fRes = ( eFunc == ifPRODUCT ) ? 1.0 : 0.0;
     413         594 :     double fVal = 0.0;
     414         594 :     double fMem = 0.0; // first numeric value.
     415         594 :     bool bNull = true;
     416         594 :     sal_uLong nCount = 0;
     417         594 :     ScAddress aAdr;
     418         594 :     ScRange aRange;
     419         594 :     size_t nRefInList = 0;
     420         594 :     if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ||
     421           0 :          ( mnSubTotalFlags & SUBTOTAL_IGN_ERR_VAL ) ) )
     422           0 :         nGlobalError = 0;
     423        1792 :     while (nParamCount-- > 0)
     424             :     {
     425         604 :         switch (GetStackType())
     426             :         {
     427             :             case svString:
     428             :             {
     429           0 :                 if( eFunc == ifCOUNT )
     430             :                 {
     431           0 :                     OUString aStr = PopString().getString();
     432           0 :                     sal_uInt32 nFIndex = 0;                 // damit default Land/Spr.
     433           0 :                     if ( bTextAsZero || pFormatter->IsNumberFormat(aStr, nFIndex, fVal))
     434           0 :                         nCount++;
     435             :                 }
     436             :                 else
     437             :                 {
     438           0 :                     switch ( eFunc )
     439             :                     {
     440             :                         case ifAVERAGE:
     441             :                         case ifSUM:
     442             :                         case ifSUMSQ:
     443             :                         case ifPRODUCT:
     444             :                         {
     445           0 :                             if ( bTextAsZero )
     446             :                             {
     447           0 :                                 Pop();
     448           0 :                                 nCount++;
     449           0 :                                 if ( eFunc == ifPRODUCT )
     450           0 :                                     fRes = 0.0;
     451             :                             }
     452             :                             else
     453             :                             {
     454           0 :                                 while (nParamCount-- > 0)
     455           0 :                                     Pop();
     456           0 :                                 SetError( errNoValue );
     457             :                             }
     458             :                         }
     459           0 :                         break;
     460             :                         default:
     461           0 :                             Pop();
     462           0 :                             nCount++;
     463             :                     }
     464             :                 }
     465             :             }
     466           0 :             break;
     467             :             case svDouble    :
     468          14 :                 fVal = GetDouble();
     469          14 :                 nCount++;
     470          14 :                 switch( eFunc )
     471             :                 {
     472             :                     case ifAVERAGE:
     473             :                     case ifSUM:
     474          14 :                         if ( bNull && fVal != 0.0 )
     475             :                         {
     476           4 :                             bNull = false;
     477           4 :                             fMem = fVal;
     478             :                         }
     479             :                         else
     480          10 :                             fRes += fVal;
     481          14 :                         break;
     482           0 :                     case ifSUMSQ:   fRes += fVal * fVal; break;
     483           0 :                     case ifPRODUCT: fRes *= fVal; break;
     484             :                     default: ; // nothing
     485             :                 }
     486          14 :                 nFuncFmtType = NUMBERFORMAT_NUMBER;
     487          14 :                 break;
     488             :             case svExternalSingleRef:
     489             :             {
     490           0 :                 ScExternalRefCache::TokenRef pToken;
     491           0 :                 ScExternalRefCache::CellFormat aFmt;
     492           0 :                 PopExternalSingleRef(pToken, &aFmt);
     493           0 :                 if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ||
     494           0 :                      ( mnSubTotalFlags & SUBTOTAL_IGN_ERR_VAL ) ) )
     495             :                 {
     496           0 :                     nGlobalError = 0;
     497           0 :                     if ( eFunc == ifCOUNT2 && !( mnSubTotalFlags & SUBTOTAL_IGN_ERR_VAL ) )
     498           0 :                         ++nCount;
     499           0 :                     break;
     500             :                 }
     501             : 
     502           0 :                 if (!pToken)
     503           0 :                     break;
     504             : 
     505           0 :                 StackVar eType = pToken->GetType();
     506           0 :                 if (eFunc == ifCOUNT2)
     507             :                 {
     508           0 :                     if ( eType != formula::svEmptyCell &&
     509           0 :                          ( ( pToken->GetOpCode() != ocSubTotal &&
     510           0 :                              pToken->GetOpCode() != ocAggregate ) ||
     511           0 :                            ( mnSubTotalFlags & SUBTOTAL_IGN_NESTED_ST_AG ) ) )
     512           0 :                         nCount++;
     513           0 :                     if (nGlobalError)
     514           0 :                         nGlobalError = 0;
     515             :                 }
     516           0 :                 else if (eType == formula::svDouble)
     517             :                 {
     518           0 :                     nCount++;
     519           0 :                     fVal = pToken->GetDouble();
     520           0 :                     if (aFmt.mbIsSet)
     521             :                     {
     522           0 :                         nFuncFmtType = aFmt.mnType;
     523           0 :                         nFuncFmtIndex = aFmt.mnIndex;
     524             :                     }
     525           0 :                     switch( eFunc )
     526             :                     {
     527             :                         case ifAVERAGE:
     528             :                         case ifSUM:
     529           0 :                             if ( bNull && fVal != 0.0 )
     530             :                             {
     531           0 :                                 bNull = false;
     532           0 :                                 fMem = fVal;
     533             :                             }
     534             :                             else
     535           0 :                                 fRes += fVal;
     536           0 :                             break;
     537           0 :                         case ifSUMSQ:   fRes += fVal * fVal; break;
     538           0 :                         case ifPRODUCT: fRes *= fVal; break;
     539             :                         case ifCOUNT:
     540           0 :                             if ( nGlobalError )
     541             :                             {
     542           0 :                                 nGlobalError = 0;
     543           0 :                                 nCount--;
     544             :                             }
     545           0 :                             break;
     546             :                         default: ; // nothing
     547             :                     }
     548             :                 }
     549           0 :                 else if (bTextAsZero && eType == formula::svString)
     550             :                 {
     551           0 :                     nCount++;
     552           0 :                     if ( eFunc == ifPRODUCT )
     553           0 :                         fRes = 0.0;
     554           0 :                 }
     555             :             }
     556           0 :             break;
     557             :             case svSingleRef :
     558             :             {
     559           0 :                 PopSingleRef( aAdr );
     560           0 :                 if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ||
     561           0 :                      ( mnSubTotalFlags & SUBTOTAL_IGN_ERR_VAL ) ) )
     562             :                 {
     563           0 :                     nGlobalError = 0;
     564           0 :                     if ( eFunc == ifCOUNT2 && !( mnSubTotalFlags & SUBTOTAL_IGN_ERR_VAL ) )
     565           0 :                         ++nCount;
     566           0 :                     break;
     567             :                 }
     568           0 :                 if ( ( mnSubTotalFlags & SUBTOTAL_IGN_FILTERED ) &&
     569           0 :                      pDok->RowFiltered( aAdr.Row(), aAdr.Tab() ) )
     570             :                 {
     571           0 :                     break;
     572             :                 }
     573           0 :                 ScRefCellValue aCell;
     574           0 :                 aCell.assign(*pDok, aAdr);
     575           0 :                 if (!aCell.isEmpty())
     576             :                 {
     577           0 :                     if( eFunc == ifCOUNT2 )
     578             :                     {
     579           0 :                         CellType eCellType = aCell.meType;
     580           0 :                         if ( eCellType != CELLTYPE_NONE )
     581           0 :                             nCount++;
     582           0 :                         if ( nGlobalError )
     583           0 :                             nGlobalError = 0;
     584             :                     }
     585           0 :                     else if (aCell.hasNumeric())
     586             :                     {
     587           0 :                         nCount++;
     588           0 :                         fVal = GetCellValue(aAdr, aCell);
     589           0 :                         CurFmtToFuncFmt();
     590           0 :                         switch( eFunc )
     591             :                         {
     592             :                             case ifAVERAGE:
     593             :                             case ifSUM:
     594           0 :                                 if ( bNull && fVal != 0.0 )
     595             :                                 {
     596           0 :                                     bNull = false;
     597           0 :                                     fMem = fVal;
     598             :                                 }
     599             :                                 else
     600           0 :                                     fRes += fVal;
     601           0 :                                 break;
     602           0 :                             case ifSUMSQ:   fRes += fVal * fVal; break;
     603           0 :                             case ifPRODUCT: fRes *= fVal; break;
     604             :                             case ifCOUNT:
     605           0 :                                 if ( nGlobalError )
     606             :                                 {
     607           0 :                                     nGlobalError = 0;
     608           0 :                                     nCount--;
     609             :                                 }
     610           0 :                                 break;
     611             :                             default: ; // nothing
     612             :                         }
     613             :                     }
     614           0 :                     else if (bTextAsZero && aCell.hasString())
     615             :                     {
     616           0 :                         nCount++;
     617           0 :                         if ( eFunc == ifPRODUCT )
     618           0 :                             fRes = 0.0;
     619             :                     }
     620           0 :                 }
     621             :             }
     622           0 :             break;
     623             :             case svDoubleRef :
     624             :             case svRefList :
     625             :             {
     626         580 :                 PopDoubleRef( aRange, nParamCount, nRefInList);
     627         580 :                 if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ||
     628           0 :                      ( mnSubTotalFlags & SUBTOTAL_IGN_ERR_VAL ) ) )
     629             :                 {
     630           0 :                     nGlobalError = 0;
     631           0 :                     if ( eFunc == ifCOUNT2 && !( mnSubTotalFlags & SUBTOTAL_IGN_ERR_VAL ) )
     632           0 :                         ++nCount;
     633           0 :                     if ( eFunc == ifCOUNT2 || eFunc == ifCOUNT )
     634             :                         break;
     635             :                 }
     636         580 :                 if( eFunc == ifCOUNT2 )
     637             :                 {
     638         106 :                     ScCellIterator aIter( pDok, aRange, mnSubTotalFlags );
     639        1090 :                     for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
     640             :                     {
     641         984 :                         if ( !aIter.hasEmptyData() )
     642             :                         {
     643         984 :                             ++nCount;
     644             :                         }
     645             :                     }
     646             : 
     647         106 :                     if ( nGlobalError )
     648           0 :                         nGlobalError = 0;
     649             :                 }
     650             :                 else
     651             :                 {
     652         474 :                     ScValueIterator aValIter( pDok, aRange, mnSubTotalFlags, bTextAsZero );
     653         474 :                     sal_uInt16 nErr = 0;
     654         474 :                     if (aValIter.GetFirst(fVal, nErr))
     655             :                     {
     656             :                         // placed the loop on the inside for performance reasons:
     657         474 :                         aValIter.GetCurNumFmtInfo( nFuncFmtType, nFuncFmtIndex );
     658         474 :                         switch( eFunc )
     659             :                         {
     660             :                             case ifAVERAGE:
     661             :                             case ifSUM:
     662         274 :                                     if ( mnSubTotalFlags & SUBTOTAL_IGN_ERR_VAL )
     663             :                                     {
     664         804 :                                         do
     665             :                                         {
     666         804 :                                             if ( !nErr )
     667             :                                             {
     668         804 :                                                 SetError(nErr);
     669         804 :                                                 if ( bNull && fVal != 0.0 )
     670             :                                                 {
     671          90 :                                                     bNull = false;
     672          90 :                                                     fMem = fVal;
     673             :                                                 }
     674             :                                                 else
     675         714 :                                                     fRes += fVal;
     676         804 :                                                 nCount++;
     677             :                                             }
     678             :                                         }
     679             :                                         while (aValIter.GetNext(fVal, nErr));
     680             :                                     }
     681             :                                     else
     682             :                                     {
     683        1282 :                                         do
     684             :                                         {
     685        1282 :                                             SetError(nErr);
     686        1282 :                                             if ( bNull && fVal != 0.0 )
     687             :                                             {
     688         184 :                                                 bNull = false;
     689         184 :                                                 fMem = fVal;
     690             :                                             }
     691             :                                             else
     692        1098 :                                                 fRes += fVal;
     693        1282 :                                             nCount++;
     694             :                                         }
     695             :                                         while (aValIter.GetNext(fVal, nErr));
     696             :                                     }
     697         274 :                                     break;
     698             :                             case ifSUMSQ:
     699           0 :                                     if ( mnSubTotalFlags & SUBTOTAL_IGN_ERR_VAL )
     700             :                                     {
     701           0 :                                         do
     702             :                                         {
     703           0 :                                             if ( !nErr )
     704             :                                             {
     705           0 :                                                 SetError(nErr);
     706           0 :                                                 fRes += fVal * fVal;
     707           0 :                                                 nCount++;
     708             :                                             }
     709             :                                         }
     710             :                                         while (aValIter.GetNext(fVal, nErr));
     711             :                                     }
     712             :                                     else
     713             :                                     {
     714           0 :                                         do
     715             :                                         {
     716           0 :                                             SetError(nErr);
     717           0 :                                             fRes += fVal * fVal;
     718           0 :                                             nCount++;
     719             :                                         }
     720             :                                         while (aValIter.GetNext(fVal, nErr));
     721             :                                     }
     722           0 :                                     break;
     723             :                             case ifPRODUCT:
     724        1002 :                                     do
     725             :                                     {
     726        1002 :                                         if ( !( nErr && ( mnSubTotalFlags & SUBTOTAL_IGN_ERR_VAL ) ) )
     727             :                                         {
     728        1002 :                                             SetError(nErr);
     729        1002 :                                             fRes *= fVal;
     730        1002 :                                             nCount++;
     731             :                                         }
     732             :                                     }
     733             :                                     while (aValIter.GetNext(fVal, nErr));
     734         110 :                                     break;
     735             :                             case ifCOUNT:
     736         804 :                                     do
     737             :                                     {
     738         804 :                                         if ( !nErr )
     739         804 :                                             nCount++;
     740             :                                     }
     741             :                                     while (aValIter.GetNext(fVal, nErr));
     742          90 :                                     break;
     743             :                             default: ;  // nothing
     744             :                         }
     745         474 :                         SetError( nErr );
     746             :                     }
     747             :                 }
     748             :             }
     749         580 :             break;
     750             :             case svExternalDoubleRef:
     751             :             {
     752           8 :                 ScMatrixRef pMat;
     753           8 :                 PopExternalDoubleRef(pMat);
     754           8 :                 if ( nGlobalError && !( mnSubTotalFlags & SUBTOTAL_IGN_ERR_VAL ) )
     755           0 :                     break;
     756             : 
     757           8 :                 IterateMatrix(pMat, eFunc, bTextAsZero, nCount, nFuncFmtType, fRes, fMem, bNull);
     758             :             }
     759           8 :             break;
     760             :             case svMatrix :
     761             :             {
     762           2 :                 ScMatrixRef pMat = PopMatrix();
     763           2 :                 IterateMatrix(pMat, eFunc, bTextAsZero, nCount, nFuncFmtType, fRes, fMem, bNull);
     764             :             }
     765           2 :             break;
     766             :             case svError:
     767             :             {
     768           0 :                 PopError();
     769           0 :                 if ( eFunc == ifCOUNT || ( mnSubTotalFlags & SUBTOTAL_IGN_ERR_VAL ) )
     770             :                 {
     771           0 :                     nGlobalError = 0;
     772             :                 }
     773           0 :                 else if ( eFunc == ifCOUNT2 && !( mnSubTotalFlags & SUBTOTAL_IGN_ERR_VAL ) )
     774             :                 {
     775           0 :                     nCount++;
     776           0 :                     nGlobalError = 0;
     777             :                 }
     778             :             }
     779           0 :             break;
     780             :             default :
     781           0 :                 while (nParamCount-- > 0)
     782           0 :                     PopError();
     783           0 :                 SetError(errIllegalParameter);
     784             :         }
     785             :     }
     786         594 :     switch( eFunc )
     787             :     {
     788         106 :         case ifSUM:     fRes = ::rtl::math::approxAdd( fRes, fMem ); break;
     789         176 :         case ifAVERAGE: fRes = div(::rtl::math::approxAdd( fRes, fMem ), nCount); break;
     790             :         case ifCOUNT2:
     791         200 :         case ifCOUNT:   fRes  = nCount; break;
     792         112 :         case ifPRODUCT: if ( !nCount ) fRes = 0.0; break;
     793             :         default: ; // nothing
     794             :     }
     795             :     // Bei Summen etc. macht ein bool-Ergebnis keinen Sinn
     796             :     // und Anzahl ist immer Number (#38345#)
     797         594 :     if( eFunc == ifCOUNT || nFuncFmtType == NUMBERFORMAT_LOGICAL )
     798          90 :         nFuncFmtType = NUMBERFORMAT_NUMBER;
     799         594 :     return fRes;
     800             : }
     801             : 
     802           0 : void ScInterpreter::ScSumSQ()
     803             : {
     804           0 :     PushDouble( IterateParameters( ifSUMSQ ) );
     805           0 : }
     806             : 
     807        1881 : void ScInterpreter::ScSum()
     808             : {
     809        1881 :     if ( mnSubTotalFlags )
     810         106 :         PushDouble( IterateParameters( ifSUM ) );
     811             :     else
     812             :     {
     813        1775 :         short nParamCount = GetByte();
     814        1775 :         double fRes = 0.0;
     815        1775 :         double fVal = 0.0;
     816        1775 :         ScAddress aAdr;
     817        1775 :         ScRange aRange;
     818        1775 :         size_t nRefInList = 0;
     819        5483 :         while (nParamCount-- > 0)
     820             :         {
     821        1937 :             switch (GetStackType())
     822             :             {
     823             :                 case svString:
     824             :                 {
     825           0 :                     while (nParamCount-- > 0)
     826           0 :                         Pop();
     827           0 :                     SetError( errNoValue );
     828             :                 }
     829           0 :                 break;
     830             :                 case svDouble    :
     831           4 :                     fVal = GetDouble();
     832           4 :                     fRes += fVal;
     833           4 :                     nFuncFmtType = NUMBERFORMAT_NUMBER;
     834           4 :                     break;
     835             :                 case svExternalSingleRef:
     836             :                 {
     837           0 :                     ScExternalRefCache::TokenRef pToken;
     838           0 :                     ScExternalRefCache::CellFormat aFmt;
     839           0 :                     PopExternalSingleRef(pToken, &aFmt);
     840             : 
     841           0 :                     if (!pToken)
     842           0 :                         break;
     843             : 
     844           0 :                     StackVar eType = pToken->GetType();
     845           0 :                     if (eType == formula::svDouble)
     846             :                     {
     847           0 :                         fVal = pToken->GetDouble();
     848           0 :                         if (aFmt.mbIsSet)
     849             :                         {
     850           0 :                             nFuncFmtType = aFmt.mnType;
     851           0 :                             nFuncFmtIndex = aFmt.mnIndex;
     852             :                         }
     853             : 
     854           0 :                         fRes += fVal;
     855           0 :                     }
     856             :                 }
     857           0 :                 break;
     858             :                 case svSingleRef :
     859             :                 {
     860         172 :                     PopSingleRef( aAdr );
     861             : 
     862         172 :                     ScRefCellValue aCell;
     863         172 :                     aCell.assign(*pDok, aAdr);
     864         172 :                     if (!aCell.isEmpty())
     865             :                     {
     866         170 :                         if (aCell.hasNumeric())
     867             :                         {
     868         170 :                             fVal = GetCellValue(aAdr, aCell);
     869         170 :                             CurFmtToFuncFmt();
     870         170 :                             fRes += fVal;
     871             :                         }
     872         172 :                     }
     873             :                 }
     874         172 :                 break;
     875             :                 case svDoubleRef :
     876             :                 case svRefList :
     877             :                 {
     878        1757 :                     PopDoubleRef( aRange, nParamCount, nRefInList);
     879             : 
     880        1757 :                     sc::ColumnSpanSet aSet(false);
     881        1757 :                     aSet.set(aRange, true);
     882             : 
     883        3510 :                     FuncSum aAction;
     884        1757 :                     aSet.executeColumnAction(*pDok, aAction);
     885        1757 :                     sal_uInt16 nErr = aAction.getError();
     886        1757 :                     if (nErr)
     887             :                     {
     888           4 :                         SetError(nErr);
     889        1885 :                         return;
     890             :                     }
     891        1753 :                     fRes += aAction.getSum();
     892             : 
     893             :                     // Get the number format of the last iterated cell.
     894        1753 :                     nFuncFmtIndex = aAction.getNumberFormat();
     895        3506 :                     nFuncFmtType = pDok->GetFormatTable()->GetType(nFuncFmtIndex);
     896             :                 }
     897        1753 :                 break;
     898             :                 case svExternalDoubleRef:
     899             :                 {
     900           4 :                     ScMatrixRef pMat;
     901           4 :                     PopExternalDoubleRef(pMat);
     902           4 :                     if (nGlobalError)
     903           0 :                         break;
     904             : 
     905           4 :                     sal_uLong nCount = 0;
     906           4 :                     double fMem = 0.0;
     907           4 :                     bool bNull = true;
     908           4 :                     IterateMatrix(pMat, ifSUM, false, nCount, nFuncFmtType, fRes, fMem, bNull);
     909           4 :                     fRes += fMem;
     910             :                 }
     911           4 :                 break;
     912             :                 case svMatrix :
     913             :                 {
     914           0 :                     ScMatrixRef pMat = PopMatrix();
     915           0 :                     sal_uLong nCount = 0;
     916           0 :                     double fMem = 0.0;
     917           0 :                     bool bNull = true;
     918           0 :                     IterateMatrix(pMat, ifSUM, false, nCount, nFuncFmtType, fRes, fMem, bNull);
     919           0 :                     fRes += fMem;
     920             :                 }
     921           0 :                 break;
     922             :                 case svError:
     923             :                 {
     924           0 :                     PopError();
     925             :                 }
     926           0 :                 break;
     927             :                 default :
     928           0 :                     while (nParamCount-- > 0)
     929           0 :                         PopError();
     930           0 :                     SetError(errIllegalParameter);
     931             :             }
     932             :         }
     933             : 
     934        1771 :         if (nFuncFmtType == NUMBERFORMAT_LOGICAL)
     935           0 :             nFuncFmtType = NUMBERFORMAT_NUMBER;
     936             : 
     937        1771 :         PushDouble(fRes);
     938             :     }
     939             : }
     940             : 
     941         112 : void ScInterpreter::ScProduct()
     942             : {
     943         112 :     PushDouble( IterateParameters( ifPRODUCT ) );
     944         112 : }
     945             : 
     946         176 : void ScInterpreter::ScAverage( bool bTextAsZero )
     947             : {
     948         176 :     PushDouble( IterateParameters( ifAVERAGE, bTextAsZero ) );
     949         176 : }
     950             : 
     951         132 : void ScInterpreter::ScCount()
     952             : {
     953         132 :     if ( mnSubTotalFlags )
     954          90 :         PushDouble( IterateParameters( ifCOUNT ) );
     955             :     else
     956             :     {
     957          42 :         short nParamCount = GetByte();
     958          42 :         double fVal = 0.0;
     959          42 :         sal_uLong nCount = 0;
     960          42 :         ScAddress aAdr;
     961          42 :         ScRange aRange;
     962          42 :         size_t nRefInList = 0;
     963          42 :         if (nGlobalError)
     964           0 :             nGlobalError = 0;
     965             : 
     966         148 :         while (nParamCount-- > 0)
     967             :         {
     968          64 :             switch (GetRawStackType())
     969             :             {
     970             :                 case svString:
     971             :                 {
     972           4 :                     OUString aStr = PopString().getString();
     973           4 :                     sal_uInt32 nFIndex = 0;                 // damit default Land/Spr.
     974           4 :                     if (pFormatter->IsNumberFormat(aStr, nFIndex, fVal))
     975           0 :                         nCount++;
     976             :                 }
     977           4 :                 break;
     978             :                 case svDouble    :
     979          20 :                     GetDouble();
     980          20 :                     nCount++;
     981          20 :                     nFuncFmtType = NUMBERFORMAT_NUMBER;
     982          20 :                     break;
     983             :                 case svExternalSingleRef:
     984             :                 {
     985           0 :                     ScExternalRefCache::TokenRef pToken;
     986           0 :                     ScExternalRefCache::CellFormat aFmt;
     987           0 :                     PopExternalSingleRef(pToken, &aFmt);
     988           0 :                     if (nGlobalError)
     989             :                     {
     990           0 :                         nGlobalError = 0;
     991           0 :                         break;
     992             :                     }
     993             : 
     994           0 :                     if (!pToken)
     995           0 :                         break;
     996             : 
     997           0 :                     StackVar eType = pToken->GetType();
     998           0 :                     if (eType == formula::svDouble)
     999             :                     {
    1000           0 :                         nCount++;
    1001           0 :                         if (aFmt.mbIsSet)
    1002             :                         {
    1003           0 :                             nFuncFmtType = aFmt.mnType;
    1004           0 :                             nFuncFmtIndex = aFmt.mnIndex;
    1005             :                         }
    1006             : 
    1007           0 :                         if (nGlobalError)
    1008             :                         {
    1009           0 :                             nGlobalError = 0;
    1010           0 :                             nCount--;
    1011             :                         }
    1012           0 :                     }
    1013             :                 }
    1014           0 :                 break;
    1015             :                 case svSingleRef :
    1016             :                 {
    1017           4 :                     PopSingleRef( aAdr );
    1018           4 :                     if (nGlobalError)
    1019             :                     {
    1020           0 :                         nGlobalError = 0;
    1021           0 :                         break;
    1022             :                     }
    1023           4 :                     ScRefCellValue aCell;
    1024           4 :                     aCell.assign(*pDok, aAdr);
    1025           4 :                     if (!aCell.isEmpty())
    1026             :                     {
    1027           4 :                         if (aCell.hasNumeric())
    1028             :                         {
    1029           4 :                             nCount++;
    1030           4 :                             CurFmtToFuncFmt();
    1031           4 :                             if (nGlobalError)
    1032             :                             {
    1033           0 :                                 nGlobalError = 0;
    1034           0 :                                 nCount--;
    1035             :                             }
    1036             :                         }
    1037           4 :                     }
    1038             :                 }
    1039           4 :                 break;
    1040             :                 case svDoubleRef :
    1041             :                 case svRefList :
    1042             :                 {
    1043          32 :                     PopDoubleRef( aRange, nParamCount, nRefInList);
    1044          32 :                     if (nGlobalError)
    1045             :                     {
    1046           0 :                         nGlobalError = 0;
    1047           0 :                         break;
    1048             :                     }
    1049             : 
    1050          32 :                     sc::ColumnSpanSet aSet(false);
    1051          32 :                     aSet.set(aRange, true);
    1052             : 
    1053          64 :                     FuncCount aAction;
    1054          32 :                     aSet.executeColumnAction(*pDok, aAction);
    1055          32 :                     nCount += aAction.getCount();
    1056             : 
    1057             :                     // Get the number format of the last iterated cell.
    1058          32 :                     nFuncFmtIndex = aAction.getNumberFormat();
    1059          64 :                     nFuncFmtType = pDok->GetFormatTable()->GetType(nFuncFmtIndex);
    1060             :                 }
    1061          32 :                 break;
    1062             :                 case svExternalDoubleRef:
    1063             :                 {
    1064           4 :                     ScMatrixRef pMat;
    1065           4 :                     PopExternalDoubleRef(pMat);
    1066           4 :                     if (nGlobalError)
    1067           0 :                         break;
    1068             : 
    1069           4 :                     double fMem = 0.0, fRes = 0.0;
    1070           4 :                     bool bNull = true;
    1071           4 :                     IterateMatrix(pMat, ifCOUNT, false, nCount, nFuncFmtType, fRes, fMem, bNull);
    1072             :                 }
    1073           4 :                 break;
    1074             :                 case svMatrix :
    1075             :                 {
    1076           0 :                     ScMatrixRef pMat = PopMatrix();
    1077           0 :                     double fMem = 0.0, fRes = 0.0;
    1078           0 :                     bool bNull = true;
    1079           0 :                     IterateMatrix(pMat, ifCOUNT, false, nCount, nFuncFmtType, fRes, fMem, bNull);
    1080             :                 }
    1081           0 :                 break;
    1082             :                 case svError:
    1083             :                 {
    1084           0 :                     PopError();
    1085           0 :                     nGlobalError = 0;
    1086             :                 }
    1087           0 :                 break;
    1088             :                 default :
    1089           0 :                     while (nParamCount-- > 0)
    1090           0 :                         PopError();
    1091           0 :                     SetError(errIllegalParameter);
    1092             :             }
    1093             :         }
    1094             : 
    1095          42 :         nFuncFmtType = NUMBERFORMAT_NUMBER;
    1096             : 
    1097          42 :         PushDouble(nCount);
    1098             :     }
    1099         132 : }
    1100             : 
    1101         110 : void ScInterpreter::ScCount2()
    1102             : {
    1103         110 :     PushDouble( IterateParameters( ifCOUNT2 ) );
    1104         338 : }
    1105             : 
    1106             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10