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

Generated by: LCOV version 1.11