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

Generated by: LCOV version 1.10