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