update emoji autocorrect entries from po-files
[LibreOffice.git] / sc / source / core / tool / interpr6.cxx
blobe02abbc96ba292d472cb75d74ca08daeaf3d7a97
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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"
29 #include <formula/token.hxx>
31 using namespace formula;
33 double const fHalfMachEps = 0.5 * ::std::numeric_limits<double>::epsilon();
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]
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 double ScInterpreter::GetGammaContFraction( double fA, double fX )
45 double const fBigInv = ::std::numeric_limits<double>::epsilon();
46 double const fBig = 1.0/fBigInv;
47 double fCount = 0.0;
48 double fY = 1.0 - fA;
49 double fDenom = fX + 2.0-fA;
50 double fPkm1 = fX + 1.0;
51 double fPkm2 = 1.0;
52 double fQkm1 = fDenom * fX;
53 double fQkm2 = fX;
54 double fApprox = fPkm1/fQkm1;
55 bool bFinished = false;
58 fCount = fCount +1.0;
59 fY = fY+ 1.0;
60 const double fNum = fY * fCount;
61 fDenom = fDenom +2.0;
62 double fPk = fPkm1 * fDenom - fPkm2 * fNum;
63 const double fQk = fQkm1 * fDenom - fQkm2 * fNum;
64 if (fQk != 0.0)
66 const double fR = fPk/fQk;
67 bFinished = (fabs( (fApprox - fR)/fR ) <= fHalfMachEps);
68 fApprox = fR;
70 fPkm2 = fPkm1;
71 fPkm1 = fPk;
72 fQkm2 = fQkm1;
73 fQkm1 = fQk;
74 if (fabs(fPk) > fBig)
76 // reduce a fraction does not change the value
77 fPkm2 = fPkm2 * fBigInv;
78 fPkm1 = fPkm1 * fBigInv;
79 fQkm2 = fQkm2 * fBigInv;
80 fQkm1 = fQkm1 * fBigInv;
82 } while (!bFinished && fCount<10000);
83 // most iterations, if fX==fAlpha+1.0; approx sqrt(fAlpha) iterations then
84 if (!bFinished)
86 SetError(errNoConvergence);
88 return fApprox;
91 /** You must ensure fA>0.0 && fX>0.0
92 valid results only if fX <= fA+1.0
93 uses power series */
94 double ScInterpreter::GetGammaSeries( double fA, double fX )
96 double fDenomfactor = fA;
97 double fSummand = 1.0/fA;
98 double fSum = fSummand;
99 int nCount=1;
102 fDenomfactor = fDenomfactor + 1.0;
103 fSummand = fSummand * fX/fDenomfactor;
104 fSum = fSum + fSummand;
105 nCount = nCount+1;
106 } 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 if (nCount>10000)
111 SetError(errNoConvergence);
113 return fSum;
116 /** You must ensure fA>0.0 && fX>0.0) */
117 double ScInterpreter::GetLowRegIGamma( double fA, double fX )
119 double fLnFactor = fA * log(fX) - fX - GetLogGamma(fA);
120 double fFactor = exp(fLnFactor); // Do we need more accuracy than exp(ln()) has?
121 if (fX>fA+1.0) // includes fX>1.0; 1-GetUpRegIGamma, continued fraction
122 return 1.0 - fFactor * GetGammaContFraction(fA,fX);
123 else // fX<=1.0 || fX<=fA+1.0, series
124 return fFactor * GetGammaSeries(fA,fX);
127 /** You must ensure fA>0.0 && fX>0.0) */
128 double ScInterpreter::GetUpRegIGamma( double fA, double fX )
131 double fLnFactor= fA*log(fX)-fX-GetLogGamma(fA);
132 double fFactor = exp(fLnFactor); //Do I need more accuracy than exp(ln()) has?;
133 if (fX>fA+1.0) // includes fX>1.0
134 return fFactor * GetGammaContFraction(fA,fX);
135 else //fX<=1 || fX<=fA+1, 1-GetLowRegIGamma, series
136 return 1.0 -fFactor * GetGammaSeries(fA,fX);
139 /** Gamma distribution, probability density function.
140 fLambda is "scale" parameter
141 You must ensure fAlpha>0.0 and fLambda>0.0 */
142 double ScInterpreter::GetGammaDistPDF( double fX, double fAlpha, double fLambda )
144 if (fX < 0.0)
145 return 0.0; // see ODFF
146 else if (fX == 0)
147 // in this case 0^0 isn't zero
149 if (fAlpha < 1.0)
151 SetError(errDivisionByZero); // should be #DIV/0
152 return HUGE_VAL;
154 else if (fAlpha == 1)
156 return (1.0 / fLambda);
158 else
160 return 0.0;
163 else
165 double fXr = fX / fLambda;
166 // use exp(ln()) only for large arguments because of less accuracy
167 if (fXr > 1.0)
169 const double fLogDblMax = log( ::std::numeric_limits<double>::max());
170 if (log(fXr) * (fAlpha-1.0) < fLogDblMax && fAlpha < fMaxGammaArgument)
172 return pow( fXr, fAlpha-1.0) * exp(-fXr) / fLambda / GetGamma(fAlpha);
174 else
176 return exp( (fAlpha-1.0) * log(fXr) - fXr - log(fLambda) - GetLogGamma(fAlpha));
179 else // fXr near to zero
181 if (fAlpha<fMaxGammaArgument)
183 return pow( fXr, fAlpha-1.0) * exp(-fXr) / fLambda / GetGamma(fAlpha);
185 else
187 return pow( fXr, fAlpha-1.0) * exp(-fXr) / fLambda / exp( GetLogGamma(fAlpha));
193 /** Gamma distribution, cumulative distribution function.
194 fLambda is "scale" parameter
195 You must ensure fAlpha>0.0 and fLambda>0.0 */
196 double ScInterpreter::GetGammaDist( double fX, double fAlpha, double fLambda )
198 if (fX <= 0.0)
199 return 0.0;
200 else
201 return GetLowRegIGamma( fAlpha, fX / fLambda);
204 namespace {
206 class NumericCellAccumulator
208 double mfSum;
209 sal_uInt16 mnError;
211 public:
212 NumericCellAccumulator() : mfSum(0.0), mnError(0) {}
214 void operator() (size_t, double fVal)
216 mfSum += fVal;
219 void operator() (size_t, const ScFormulaCell* pCell)
221 if (mnError)
222 // Skip all the rest if we have an error.
223 return;
225 double fVal = 0.0;
226 sal_uInt16 nErr = 0;
227 ScFormulaCell& rCell = const_cast<ScFormulaCell&>(*pCell);
228 if (!rCell.GetErrorOrValue(nErr, fVal))
229 // The cell has neither error nor value. Perhaps string result.
230 return;
232 if (nErr)
234 // Cell has error.
235 mnError = nErr;
236 return;
239 mfSum += fVal;
242 sal_uInt16 getError() const { return mnError; }
243 double getSum() const { return mfSum; }
246 class NumericCellCounter
248 size_t mnCount;
249 public:
250 NumericCellCounter() : mnCount(0) {}
252 void operator() (const sc::CellStoreType::value_type& rNode, size_t nOffset, size_t nDataSize)
254 switch (rNode.type)
256 case sc::element_type_numeric:
257 mnCount += nDataSize;
258 break;
259 case sc::element_type_formula:
261 sc::formula_block::const_iterator it = sc::formula_block::begin(*rNode.data);
262 std::advance(it, nOffset);
263 sc::formula_block::const_iterator itEnd = it;
264 std::advance(itEnd, nDataSize);
265 for (; it != itEnd; ++it)
267 ScFormulaCell& rCell = const_cast<ScFormulaCell&>(**it);
268 if (rCell.IsValueNoError())
269 ++mnCount;
272 break;
273 default:
278 size_t getCount() const { return mnCount; }
281 class FuncCount : public sc::ColumnSpanSet::ColumnAction
283 sc::ColumnBlockConstPosition maPos;
284 ScColumn* mpCol;
285 size_t mnCount;
286 sal_uInt32 mnNumFmt;
288 public:
289 FuncCount() : mpCol(0), mnCount(0), mnNumFmt(0) {}
291 virtual void startColumn(ScColumn* pCol) SAL_OVERRIDE
293 mpCol = pCol;
294 mpCol->InitBlockPosition(maPos);
297 virtual void execute(SCROW nRow1, SCROW nRow2, bool bVal) SAL_OVERRIDE
299 if (!bVal)
300 return;
302 NumericCellCounter aFunc;
303 maPos.miCellPos = sc::ParseBlock(maPos.miCellPos, mpCol->GetCellStore(), aFunc, nRow1, nRow2);
304 mnCount += aFunc.getCount();
305 mnNumFmt = mpCol->GetNumberFormat(nRow2);
308 size_t getCount() const { return mnCount; }
309 sal_uInt32 getNumberFormat() const { return mnNumFmt; }
312 class FuncSum : public sc::ColumnSpanSet::ColumnAction
314 sc::ColumnBlockConstPosition maPos;
315 ScColumn* mpCol;
316 double mfSum;
317 sal_uInt16 mnError;
318 sal_uInt32 mnNumFmt;
320 public:
321 FuncSum() : mpCol(0), mfSum(0.0), mnError(0), mnNumFmt(0) {}
323 virtual void startColumn(ScColumn* pCol) SAL_OVERRIDE
325 mpCol = pCol;
326 mpCol->InitBlockPosition(maPos);
329 virtual void execute(SCROW nRow1, SCROW nRow2, bool bVal) SAL_OVERRIDE
331 if (!bVal)
332 return;
334 if (mnError)
335 return;
337 NumericCellAccumulator aFunc;
338 maPos.miCellPos = sc::ParseFormulaNumeric(maPos.miCellPos, mpCol->GetCellStore(), nRow1, nRow2, aFunc);
339 mnError = aFunc.getError();
340 if (mnError)
341 return;
343 mfSum += aFunc.getSum();
344 mnNumFmt = mpCol->GetNumberFormat(nRow2);
347 sal_uInt16 getError() const { return mnError; }
348 double getSum() const { return mfSum; }
349 sal_uInt32 getNumberFormat() const { return mnNumFmt; }
352 void IterateMatrix(
353 const ScMatrixRef& pMat, ScIterFunc eFunc, bool bTextAsZero,
354 sal_uLong& rCount, short& rFuncFmtType, double& fRes, double& fMem, bool& bNull)
356 if (!pMat)
357 return;
359 // TODO fdo73148 take mnSubTotalFlags into account
360 rFuncFmtType = css::util::NumberFormat::NUMBER;
361 switch (eFunc)
363 case ifAVERAGE:
364 case ifSUM:
366 ScMatrix::IterateResult aRes = pMat->Sum(bTextAsZero);
367 if (bNull)
369 bNull = false;
370 fMem = aRes.mfFirst;
371 fRes += aRes.mfRest;
373 else
374 fRes += aRes.mfFirst + aRes.mfRest;
375 rCount += aRes.mnCount;
377 break;
378 case ifCOUNT:
379 rCount += pMat->Count(bTextAsZero);
380 break;
381 case ifCOUNT2:
382 rCount += pMat->Count(true);
383 break;
384 case ifPRODUCT:
386 ScMatrix::IterateResult aRes = pMat->Product(bTextAsZero);
387 fRes *= aRes.mfFirst;
388 fRes *= aRes.mfRest;
389 rCount += aRes.mnCount;
391 break;
392 case ifSUMSQ:
394 ScMatrix::IterateResult aRes = pMat->SumSquare(bTextAsZero);
395 fRes += aRes.mfFirst;
396 fRes += aRes.mfRest;
397 rCount += aRes.mnCount;
399 break;
400 default:
407 double ScInterpreter::IterateParameters( ScIterFunc eFunc, bool bTextAsZero )
409 short nParamCount = GetByte();
410 double fRes = ( eFunc == ifPRODUCT ) ? 1.0 : 0.0;
411 double fVal = 0.0;
412 double fMem = 0.0; // first numeric value.
413 bool bNull = true;
414 sal_uLong nCount = 0;
415 ScAddress aAdr;
416 ScRange aRange;
417 size_t nRefInList = 0;
418 if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ||
419 ( mnSubTotalFlags & SUBTOTAL_IGN_ERR_VAL ) ) )
420 nGlobalError = 0;
421 while (nParamCount-- > 0)
423 switch (GetStackType())
425 case svString:
427 if( eFunc == ifCOUNT )
429 OUString aStr = PopString().getString();
430 if ( bTextAsZero )
431 nCount++;
432 else
434 // Only check if string can be converted to number, no
435 // error propagation.
436 sal_uInt16 nErr = nGlobalError;
437 nGlobalError = 0;
438 ConvertStringToValue( aStr );
439 if (!nGlobalError)
440 ++nCount;
441 nGlobalError = nErr;
444 else
446 switch ( eFunc )
448 case ifAVERAGE:
449 case ifSUM:
450 case ifSUMSQ:
451 case ifPRODUCT:
453 if ( bTextAsZero )
455 Pop();
456 nCount++;
457 if ( eFunc == ifPRODUCT )
458 fRes = 0.0;
460 else
462 while (nParamCount-- > 0)
463 Pop();
464 SetError( errNoValue );
467 break;
468 default:
469 Pop();
470 nCount++;
474 break;
475 case svDouble :
476 fVal = GetDouble();
477 nCount++;
478 switch( eFunc )
480 case ifAVERAGE:
481 case ifSUM:
482 if ( bNull && fVal != 0.0 )
484 bNull = false;
485 fMem = fVal;
487 else
488 fRes += fVal;
489 break;
490 case ifSUMSQ: fRes += fVal * fVal; break;
491 case ifPRODUCT: fRes *= fVal; break;
492 default: ; // nothing
494 nFuncFmtType = css::util::NumberFormat::NUMBER;
495 break;
496 case svExternalSingleRef:
498 ScExternalRefCache::TokenRef pToken;
499 ScExternalRefCache::CellFormat aFmt;
500 PopExternalSingleRef(pToken, &aFmt);
501 if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ||
502 ( mnSubTotalFlags & SUBTOTAL_IGN_ERR_VAL ) ) )
504 nGlobalError = 0;
505 if ( eFunc == ifCOUNT2 && !( mnSubTotalFlags & SUBTOTAL_IGN_ERR_VAL ) )
506 ++nCount;
507 break;
510 if (!pToken)
511 break;
513 StackVar eType = pToken->GetType();
514 if (eFunc == ifCOUNT2)
516 if ( eType != formula::svEmptyCell &&
517 ( ( pToken->GetOpCode() != ocSubTotal &&
518 pToken->GetOpCode() != ocAggregate ) ||
519 ( mnSubTotalFlags & SUBTOTAL_IGN_NESTED_ST_AG ) ) )
520 nCount++;
521 if (nGlobalError)
522 nGlobalError = 0;
524 else if (eType == formula::svDouble)
526 nCount++;
527 fVal = pToken->GetDouble();
528 if (aFmt.mbIsSet)
530 nFuncFmtType = aFmt.mnType;
531 nFuncFmtIndex = aFmt.mnIndex;
533 switch( eFunc )
535 case ifAVERAGE:
536 case ifSUM:
537 if ( bNull && fVal != 0.0 )
539 bNull = false;
540 fMem = fVal;
542 else
543 fRes += fVal;
544 break;
545 case ifSUMSQ: fRes += fVal * fVal; break;
546 case ifPRODUCT: fRes *= fVal; break;
547 case ifCOUNT:
548 if ( nGlobalError )
550 nGlobalError = 0;
551 nCount--;
553 break;
554 default: ; // nothing
557 else if (bTextAsZero && eType == formula::svString)
559 nCount++;
560 if ( eFunc == ifPRODUCT )
561 fRes = 0.0;
564 break;
565 case svSingleRef :
567 PopSingleRef( aAdr );
568 if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ||
569 ( mnSubTotalFlags & SUBTOTAL_IGN_ERR_VAL ) ) )
571 nGlobalError = 0;
572 if ( eFunc == ifCOUNT2 && !( mnSubTotalFlags & SUBTOTAL_IGN_ERR_VAL ) )
573 ++nCount;
574 break;
576 if ( ( mnSubTotalFlags & SUBTOTAL_IGN_FILTERED ) &&
577 pDok->RowFiltered( aAdr.Row(), aAdr.Tab() ) )
579 break;
581 ScRefCellValue aCell;
582 aCell.assign(*pDok, aAdr);
583 if (!aCell.isEmpty())
585 if( eFunc == ifCOUNT2 )
587 CellType eCellType = aCell.meType;
588 if ( eCellType != CELLTYPE_NONE )
589 nCount++;
590 if ( nGlobalError )
591 nGlobalError = 0;
593 else if (aCell.hasNumeric())
595 nCount++;
596 fVal = GetCellValue(aAdr, aCell);
597 CurFmtToFuncFmt();
598 switch( eFunc )
600 case ifAVERAGE:
601 case ifSUM:
602 if ( bNull && fVal != 0.0 )
604 bNull = false;
605 fMem = fVal;
607 else
608 fRes += fVal;
609 break;
610 case ifSUMSQ: fRes += fVal * fVal; break;
611 case ifPRODUCT: fRes *= fVal; break;
612 case ifCOUNT:
613 if ( nGlobalError )
615 nGlobalError = 0;
616 nCount--;
618 break;
619 default: ; // nothing
622 else if (bTextAsZero && aCell.hasString())
624 nCount++;
625 if ( eFunc == ifPRODUCT )
626 fRes = 0.0;
630 break;
631 case svDoubleRef :
632 case svRefList :
634 PopDoubleRef( aRange, nParamCount, nRefInList);
635 if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ||
636 ( mnSubTotalFlags & SUBTOTAL_IGN_ERR_VAL ) ) )
638 nGlobalError = 0;
639 if ( eFunc == ifCOUNT2 && !( mnSubTotalFlags & SUBTOTAL_IGN_ERR_VAL ) )
640 ++nCount;
641 if ( eFunc == ifCOUNT2 || eFunc == ifCOUNT )
642 break;
644 if( eFunc == ifCOUNT2 )
646 ScCellIterator aIter( pDok, aRange, mnSubTotalFlags );
647 for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
649 if ( !aIter.hasEmptyData() )
651 ++nCount;
655 if ( nGlobalError )
656 nGlobalError = 0;
658 else
660 ScValueIterator aValIter( pDok, aRange, mnSubTotalFlags, bTextAsZero );
661 sal_uInt16 nErr = 0;
662 if (aValIter.GetFirst(fVal, nErr))
664 // placed the loop on the inside for performance reasons:
665 aValIter.GetCurNumFmtInfo( nFuncFmtType, nFuncFmtIndex );
666 switch( eFunc )
668 case ifAVERAGE:
669 case ifSUM:
670 if ( mnSubTotalFlags & SUBTOTAL_IGN_ERR_VAL )
674 if ( !nErr )
676 SetError(nErr);
677 if ( bNull && fVal != 0.0 )
679 bNull = false;
680 fMem = fVal;
682 else
683 fRes += fVal;
684 nCount++;
687 while (aValIter.GetNext(fVal, nErr));
689 else
693 SetError(nErr);
694 if ( bNull && fVal != 0.0 )
696 bNull = false;
697 fMem = fVal;
699 else
700 fRes += fVal;
701 nCount++;
703 while (aValIter.GetNext(fVal, nErr));
705 break;
706 case ifSUMSQ:
707 if ( mnSubTotalFlags & SUBTOTAL_IGN_ERR_VAL )
711 if ( !nErr )
713 SetError(nErr);
714 fRes += fVal * fVal;
715 nCount++;
718 while (aValIter.GetNext(fVal, nErr));
720 else
724 SetError(nErr);
725 fRes += fVal * fVal;
726 nCount++;
728 while (aValIter.GetNext(fVal, nErr));
730 break;
731 case ifPRODUCT:
734 if ( !( nErr && ( mnSubTotalFlags & SUBTOTAL_IGN_ERR_VAL ) ) )
736 SetError(nErr);
737 fRes *= fVal;
738 nCount++;
741 while (aValIter.GetNext(fVal, nErr));
742 break;
743 case ifCOUNT:
746 if ( !nErr )
747 nCount++;
749 while (aValIter.GetNext(fVal, nErr));
750 break;
751 default: ; // nothing
753 SetError( nErr );
757 break;
758 case svExternalDoubleRef:
760 ScMatrixRef pMat;
761 PopExternalDoubleRef(pMat);
762 if ( nGlobalError && !( mnSubTotalFlags & SUBTOTAL_IGN_ERR_VAL ) )
763 break;
765 IterateMatrix(pMat, eFunc, bTextAsZero, nCount, nFuncFmtType, fRes, fMem, bNull);
767 break;
768 case svMatrix :
770 ScMatrixRef pMat = PopMatrix();
771 IterateMatrix(pMat, eFunc, bTextAsZero, nCount, nFuncFmtType, fRes, fMem, bNull);
773 break;
774 case svError:
776 PopError();
777 if ( eFunc == ifCOUNT || ( mnSubTotalFlags & SUBTOTAL_IGN_ERR_VAL ) )
779 nGlobalError = 0;
781 else if ( eFunc == ifCOUNT2 && !( mnSubTotalFlags & SUBTOTAL_IGN_ERR_VAL ) )
783 nCount++;
784 nGlobalError = 0;
787 break;
788 default :
789 while (nParamCount-- > 0)
790 PopError();
791 SetError(errIllegalParameter);
794 switch( eFunc )
796 case ifSUM: fRes = ::rtl::math::approxAdd( fRes, fMem ); break;
797 case ifAVERAGE: fRes = div(::rtl::math::approxAdd( fRes, fMem ), nCount); break;
798 case ifCOUNT2:
799 case ifCOUNT: fRes = nCount; break;
800 case ifPRODUCT: if ( !nCount ) fRes = 0.0; break;
801 default: ; // nothing
803 // Bei Summen etc. macht ein bool-Ergebnis keinen Sinn
804 // und Anzahl ist immer Number (#38345#)
805 if( eFunc == ifCOUNT || nFuncFmtType == css::util::NumberFormat::LOGICAL )
806 nFuncFmtType = css::util::NumberFormat::NUMBER;
807 return fRes;
810 void ScInterpreter::ScSumSQ()
812 PushDouble( IterateParameters( ifSUMSQ ) );
815 void ScInterpreter::ScSum()
817 if ( mnSubTotalFlags )
818 PushDouble( IterateParameters( ifSUM ) );
819 else
821 short nParamCount = GetByte();
822 double fRes = 0.0;
823 double fVal = 0.0;
824 ScAddress aAdr;
825 ScRange aRange;
826 size_t nRefInList = 0;
827 while (nParamCount-- > 0)
829 switch (GetStackType())
831 case svString:
833 while (nParamCount-- > 0)
834 Pop();
835 SetError( errNoValue );
837 break;
838 case svDouble :
839 fVal = GetDouble();
840 fRes += fVal;
841 nFuncFmtType = css::util::NumberFormat::NUMBER;
842 break;
843 case svExternalSingleRef:
845 ScExternalRefCache::TokenRef pToken;
846 ScExternalRefCache::CellFormat aFmt;
847 PopExternalSingleRef(pToken, &aFmt);
849 if (!pToken)
850 break;
852 StackVar eType = pToken->GetType();
853 if (eType == formula::svDouble)
855 fVal = pToken->GetDouble();
856 if (aFmt.mbIsSet)
858 nFuncFmtType = aFmt.mnType;
859 nFuncFmtIndex = aFmt.mnIndex;
862 fRes += fVal;
865 break;
866 case svSingleRef :
868 PopSingleRef( aAdr );
870 ScRefCellValue aCell;
871 aCell.assign(*pDok, aAdr);
872 if (!aCell.isEmpty())
874 if (aCell.hasNumeric())
876 fVal = GetCellValue(aAdr, aCell);
877 CurFmtToFuncFmt();
878 fRes += fVal;
882 break;
883 case svDoubleRef :
884 case svRefList :
886 PopDoubleRef( aRange, nParamCount, nRefInList);
888 sc::ColumnSpanSet aSet(false);
889 aSet.set(aRange, true);
891 FuncSum aAction;
892 aSet.executeColumnAction(*pDok, aAction);
893 sal_uInt16 nErr = aAction.getError();
894 if (nErr)
896 SetError(nErr);
897 return;
899 fRes += aAction.getSum();
901 // Get the number format of the last iterated cell.
902 nFuncFmtIndex = aAction.getNumberFormat();
903 nFuncFmtType = pDok->GetFormatTable()->GetType(nFuncFmtIndex);
905 break;
906 case svExternalDoubleRef:
908 ScMatrixRef pMat;
909 PopExternalDoubleRef(pMat);
910 if (nGlobalError)
911 break;
913 sal_uLong nCount = 0;
914 double fMem = 0.0;
915 bool bNull = true;
916 IterateMatrix(pMat, ifSUM, false, nCount, nFuncFmtType, fRes, fMem, bNull);
917 fRes += fMem;
919 break;
920 case svMatrix :
922 ScMatrixRef pMat = PopMatrix();
923 sal_uLong nCount = 0;
924 double fMem = 0.0;
925 bool bNull = true;
926 IterateMatrix(pMat, ifSUM, false, nCount, nFuncFmtType, fRes, fMem, bNull);
927 fRes += fMem;
929 break;
930 case svError:
932 PopError();
934 break;
935 default :
936 while (nParamCount-- > 0)
937 PopError();
938 SetError(errIllegalParameter);
942 if (nFuncFmtType == css::util::NumberFormat::LOGICAL)
943 nFuncFmtType = css::util::NumberFormat::NUMBER;
945 PushDouble(fRes);
949 void ScInterpreter::ScProduct()
951 PushDouble( IterateParameters( ifPRODUCT ) );
954 void ScInterpreter::ScAverage( bool bTextAsZero )
956 PushDouble( IterateParameters( ifAVERAGE, bTextAsZero ) );
959 void ScInterpreter::ScCount()
961 if ( mnSubTotalFlags )
962 PushDouble( IterateParameters( ifCOUNT ) );
963 else
965 short nParamCount = GetByte();
966 sal_uLong nCount = 0;
967 ScAddress aAdr;
968 ScRange aRange;
969 size_t nRefInList = 0;
970 if (nGlobalError)
971 nGlobalError = 0;
973 while (nParamCount-- > 0)
975 switch (GetRawStackType())
977 case svString:
979 OUString aStr = PopString().getString();
980 // Only check if string can be converted to number, no
981 // error propagation.
982 sal_uInt16 nErr = nGlobalError;
983 nGlobalError = 0;
984 ConvertStringToValue( aStr );
985 if (!nGlobalError)
986 ++nCount;
987 nGlobalError = nErr;
989 break;
990 case svDouble :
991 GetDouble();
992 nCount++;
993 nFuncFmtType = css::util::NumberFormat::NUMBER;
994 break;
995 case svExternalSingleRef:
997 ScExternalRefCache::TokenRef pToken;
998 ScExternalRefCache::CellFormat aFmt;
999 PopExternalSingleRef(pToken, &aFmt);
1000 if (nGlobalError)
1002 nGlobalError = 0;
1003 break;
1006 if (!pToken)
1007 break;
1009 StackVar eType = pToken->GetType();
1010 if (eType == formula::svDouble)
1012 nCount++;
1013 if (aFmt.mbIsSet)
1015 nFuncFmtType = aFmt.mnType;
1016 nFuncFmtIndex = aFmt.mnIndex;
1019 if (nGlobalError)
1021 nGlobalError = 0;
1022 nCount--;
1026 break;
1027 case svSingleRef :
1029 PopSingleRef( aAdr );
1030 if (nGlobalError)
1032 nGlobalError = 0;
1033 break;
1035 ScRefCellValue aCell;
1036 aCell.assign(*pDok, aAdr);
1037 if (!aCell.isEmpty())
1039 if (aCell.hasNumeric())
1041 nCount++;
1042 CurFmtToFuncFmt();
1043 if (nGlobalError)
1045 nGlobalError = 0;
1046 nCount--;
1051 break;
1052 case svDoubleRef :
1053 case svRefList :
1055 PopDoubleRef( aRange, nParamCount, nRefInList);
1056 if (nGlobalError)
1058 nGlobalError = 0;
1059 break;
1062 sc::ColumnSpanSet aSet(false);
1063 aSet.set(aRange, true);
1065 FuncCount aAction;
1066 aSet.executeColumnAction(*pDok, aAction);
1067 nCount += aAction.getCount();
1069 // Get the number format of the last iterated cell.
1070 nFuncFmtIndex = aAction.getNumberFormat();
1071 nFuncFmtType = pDok->GetFormatTable()->GetType(nFuncFmtIndex);
1073 break;
1074 case svExternalDoubleRef:
1076 ScMatrixRef pMat;
1077 PopExternalDoubleRef(pMat);
1078 if (nGlobalError)
1079 break;
1081 double fMem = 0.0, fRes = 0.0;
1082 bool bNull = true;
1083 IterateMatrix(pMat, ifCOUNT, false, nCount, nFuncFmtType, fRes, fMem, bNull);
1085 break;
1086 case svMatrix :
1088 ScMatrixRef pMat = PopMatrix();
1089 double fMem = 0.0, fRes = 0.0;
1090 bool bNull = true;
1091 IterateMatrix(pMat, ifCOUNT, false, nCount, nFuncFmtType, fRes, fMem, bNull);
1093 break;
1094 case svError:
1096 PopError();
1097 nGlobalError = 0;
1099 break;
1100 default :
1101 while (nParamCount-- > 0)
1102 PopError();
1103 SetError(errIllegalParameter);
1107 nFuncFmtType = css::util::NumberFormat::NUMBER;
1109 PushDouble(nCount);
1113 void ScInterpreter::ScCount2()
1115 PushDouble( IterateParameters( ifCOUNT2 ) );
1118 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */