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