LibreOffice Module sc (master)  1
interpr8.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  */
10 
11 #include <interpre.hxx>
12 #include <global.hxx>
13 #include <dociter.hxx>
14 #include <scmatrix.hxx>
15 #include <comphelper/random.hxx>
16 #include <formula/token.hxx>
17 #include <sal/log.hxx>
18 
19 #include <stack>
20 #include <cmath>
21 #include <memory>
22 #include <vector>
23 
24 using namespace formula;
25 
26 namespace {
27 
28 struct DataPoint
29 {
30  double X, Y;
31 
32  DataPoint( double rX, double rY ) : X( rX ), Y( rY ) {};
33 };
34 
35 }
36 
37 static bool lcl_SortByX( const DataPoint &lhs, const DataPoint &rhs ) { return lhs.X < rhs.X; }
38 
39 /*
40  * ScETSForecastCalculation
41  *
42  * Class is set up to be used with Calc's FORECAST.ETS
43  * functions and with chart extrapolations (not yet implemented).
44  *
45  * Triple Exponential Smoothing (Holt-Winters method)
46  *
47  * Forecasting of a linear change in data over time (y=a+b*x) with
48  * superimposed absolute or relative seasonal deviations, using additive
49  * respectively multiplicative Holt-Winters method.
50  *
51  * Initialisation and forecasting calculations are based on
52  * Engineering Statistics Handbook, 6.4.3.5 Triple Exponential Smoothing
53  * see "http://www.itl.nist.gov/div898/handbook/pmc/section4/pmc435.htm"
54  * Further to the above is that initial calculation of Seasonal effect
55  * is corrected for trend.
56  *
57  * Prediction Interval calculations are based on
58  * Yar & Chatfield, Prediction Intervals for the Holt-Winters forecasting
59  * procedure, International Journal of Forecasting, 1990, Vol.6, pp127-137
60  * The calculation here is a simplified numerical approximation of the above,
61  * using random distributions.
62  *
63  * Double Exponential Smoothing (Holt-Winters method)
64  *
65  * Forecasting of a linear change in data over time (y=a+b*x), using
66  * the Holt-Winters method.
67  *
68  * Initialisation and forecasting calculations are based on
69  * Engineering Statistics Handbook, 6.4.3.3 Double Exponential Smoothing
70  * see "http://www.itl.nist.gov/div898/handbook/pmc/section4/pmc433.htm"
71  *
72  * Prediction Interval calculations are based on
73  * Statistical Methods for Forecasting, Bovas & Ledolter, 2009, 3.8 Prediction
74  * Intervals for Future Values
75  *
76  */
77 
78 namespace {
79 
80 class ScETSForecastCalculation
81 {
82 private:
83  SvNumberFormatter* mpFormatter;
84  std::vector< DataPoint > maRange; // data (X, Y)
85  std::unique_ptr<double[]> mpBase; // calculated base value array
86  std::unique_ptr<double[]> mpTrend; // calculated trend factor array
87  std::unique_ptr<double[]> mpPerIdx; // calculated periodical deviation array, not used with eds
88  std::unique_ptr<double[]> mpForecast; // forecasted value array
89  SCSIZE mnSmplInPrd; // samples per period
90  double mfStepSize; // increment of X in maRange
91  double mfAlpha, mfBeta, mfGamma; // constants to minimize the RMSE in the ES-equations
92  SCSIZE mnCount; // No of data points
93  bool mbInitialised;
94  int mnMonthDay; // n-month X-interval, value is day of month
95  // accuracy indicators
96  double mfMAE; // mean absolute error
97  double mfMASE; // mean absolute scaled error
98  double mfMSE; // mean squared error (variation)
99  double mfRMSE; // root mean squared error (standard deviation)
100  double mfSMAPE; // symmetric mean absolute error
101  FormulaError mnErrorValue;
102  bool bAdditive; // true: additive method, false: multiplicative method
103  bool bEDS; // true: EDS, false: ETS
104 
105  // constants used in determining best fit for alpha, beta, gamma
106  static constexpr double cfMinABCResolution = 0.001; // minimum change of alpha, beta, gamma
107  static const SCSIZE cnScenarios = 1000; // No. of scenarios to calculate for PI calculations
108 
109  bool initData();
110  void prefillBaseData();
111  bool prefillTrendData();
112  bool prefillPerIdx();
113  void initCalc();
114  void refill();
115  SCSIZE CalcPeriodLen();
116  void CalcAlphaBetaGamma();
117  void CalcBetaGamma();
118  void CalcGamma();
119  void calcAccuracyIndicators();
120  void GetForecast( double fTarget, double& rForecast );
121  double RandDev();
122  double convertXtoMonths( double x );
123 
124 public:
125  ScETSForecastCalculation( SCSIZE nSize, SvNumberFormatter* pFormatter );
126 
127  bool PreprocessDataRange( const ScMatrixRef& rMatX, const ScMatrixRef& rMatY, int nSmplInPrd,
128  bool bDataCompletion, int nAggregation, const ScMatrixRef& rTMat,
129  ScETSType eETSType );
130  FormulaError GetError() const { return mnErrorValue; };
131  void GetForecastRange( const ScMatrixRef& rTMat, const ScMatrixRef& rFcMat );
132  void GetStatisticValue( const ScMatrixRef& rTypeMat, const ScMatrixRef& rStatMat );
133  void GetSamplesInPeriod( double& rVal );
134  void GetEDSPredictionIntervals( const ScMatrixRef& rTMat, const ScMatrixRef& rPIMat, double fPILevel );
135  void GetETSPredictionIntervals( const ScMatrixRef& rTMat, const ScMatrixRef& rPIMat, double fPILevel );
136 };
137 
138 }
139 
140 ScETSForecastCalculation::ScETSForecastCalculation( SCSIZE nSize, SvNumberFormatter* pFormatter )
141  : mpFormatter(pFormatter)
142  , mnSmplInPrd(0)
143  , mfStepSize(0.0)
144  , mfAlpha(0.0)
145  , mfBeta(0.0)
146  , mfGamma(0.0)
147  , mnCount(nSize)
148  , mbInitialised(false)
149  , mnMonthDay(0)
150  , mfMAE(0.0)
151  , mfMASE(0.0)
152  , mfMSE(0.0)
153  , mfRMSE(0.0)
154  , mfSMAPE(0.0)
155  , mnErrorValue(FormulaError::NONE)
156  , bAdditive(false)
157  , bEDS(false)
158 {
159  maRange.reserve( mnCount );
160 }
161 
162 bool ScETSForecastCalculation::PreprocessDataRange( const ScMatrixRef& rMatX, const ScMatrixRef& rMatY, int nSmplInPrd,
163  bool bDataCompletion, int nAggregation, const ScMatrixRef& rTMat,
164  ScETSType eETSType )
165 {
166  bEDS = ( nSmplInPrd == 0 );
167  bAdditive = ( eETSType == etsAdd || eETSType == etsPIAdd || eETSType == etsStatAdd );
168 
169  // maRange needs to be sorted by X
170  for ( SCSIZE i = 0; i < mnCount; i++ )
171  maRange.emplace_back( rMatX->GetDouble( i ), rMatY->GetDouble( i ) );
172  sort( maRange.begin(), maRange.end(), lcl_SortByX );
173 
174  if ( rTMat )
175  {
176  if ( eETSType != etsPIAdd && eETSType != etsPIMult )
177  {
178  if ( rTMat->GetDouble( 0 ) < maRange[ 0 ].X )
179  {
180  // target cannot be less than start of X-range
181  mnErrorValue = FormulaError::IllegalFPOperation;
182  return false;
183  }
184  }
185  else
186  {
187  if ( rTMat->GetDouble( 0 ) < maRange[ mnCount - 1 ].X )
188  {
189  // target cannot be before end of X-range
190  mnErrorValue = FormulaError::IllegalFPOperation;
191  return false;
192  }
193  }
194  }
195 
196  // Month intervals don't have exact stepsize, so first
197  // detect if month interval is used.
198  // Method: assume there is an month interval and verify.
199  // If month interval is used, replace maRange.X with month values
200  // for ease of calculations.
201  Date aNullDate = mpFormatter->GetNullDate();
202  Date aDate = aNullDate + static_cast< sal_Int32 >( maRange[ 0 ].X );
203  mnMonthDay = aDate.GetDay();
204  for ( SCSIZE i = 1; i < mnCount && mnMonthDay; i++ )
205  {
206  Date aDate1 = aNullDate + static_cast< sal_Int32 >( maRange[ i ].X );
207  if ( aDate != aDate1 )
208  {
209  if ( aDate1.GetDay() != mnMonthDay )
210  mnMonthDay = 0;
211  }
212  }
213 
214  mfStepSize = ::std::numeric_limits<double>::max();
215  if ( mnMonthDay )
216  {
217  for ( SCSIZE i = 0; i < mnCount; i++ )
218  {
219  aDate = aNullDate + static_cast< sal_Int32 >( maRange[ i ].X );
220  maRange[ i ].X = aDate.GetYear() * 12 + aDate.GetMonth();
221  }
222  }
223  for ( SCSIZE i = 1; i < mnCount; i++ )
224  {
225  double fStep = maRange[ i ].X - maRange[ i - 1 ].X;
226  if ( fStep == 0.0 )
227  {
228  if ( nAggregation == 0 )
229  {
230  // identical X-values are not allowed
231  mnErrorValue = FormulaError::NoValue;
232  return false;
233  }
234  double fTmp = maRange[ i - 1 ].Y;
235  SCSIZE nCounter = 1;
236  switch ( nAggregation )
237  {
238  case 1 : // AVERAGE (default)
239  while ( i < mnCount && maRange[ i ].X == maRange[ i - 1 ].X )
240  {
241  maRange.erase( maRange.begin() + i );
242  --mnCount;
243  }
244  break;
245  case 7 : // SUM
246  while ( i < mnCount && maRange[ i ].X == maRange[ i - 1 ].X )
247  {
248  fTmp += maRange[ i ].Y;
249  maRange.erase( maRange.begin() + i );
250  --mnCount;
251  }
252  maRange[ i - 1 ].Y = fTmp;
253  break;
254 
255  case 2 : // COUNT
256  case 3 : // COUNTA (same as COUNT as there are no non-numeric Y-values)
257  while ( i < mnCount && maRange[ i ].X == maRange[ i - 1 ].X )
258  {
259  nCounter++;
260  maRange.erase( maRange.begin() + i );
261  --mnCount;
262  }
263  maRange[ i - 1 ].Y = nCounter;
264  break;
265 
266  case 4 : // MAX
267  while ( i < mnCount && maRange[ i ].X == maRange[ i - 1 ].X )
268  {
269  if ( maRange[ i ].Y > fTmp )
270  fTmp = maRange[ i ].Y;
271  maRange.erase( maRange.begin() + i );
272  --mnCount;
273  }
274  maRange[ i - 1 ].Y = fTmp;
275  break;
276 
277  case 5 : // MEDIAN
278  {
279  std::vector< double > aTmp;
280  aTmp.push_back( maRange[ i - 1 ].Y );
281  while ( i < mnCount && maRange[ i ].X == maRange[ i - 1 ].X )
282  {
283  aTmp.push_back( maRange[ i ].Y );
284  nCounter++;
285  maRange.erase( maRange.begin() + i );
286  --mnCount;
287  }
288  sort( aTmp.begin(), aTmp.end() );
289 
290  if ( nCounter % 2 )
291  maRange[ i - 1 ].Y = aTmp[ nCounter / 2 ];
292  else
293  maRange[ i - 1 ].Y = ( aTmp[ nCounter / 2 ] + aTmp[ nCounter / 2 - 1 ] ) / 2.0;
294  }
295  break;
296 
297  case 6 : // MIN
298  while ( i < mnCount && maRange[ i ].X == maRange[ i - 1 ].X )
299  {
300  if ( maRange[ i ].Y < fTmp )
301  fTmp = maRange[ i ].Y;
302  maRange.erase( maRange.begin() + i );
303  --mnCount;
304  }
305  maRange[ i - 1 ].Y = fTmp;
306  break;
307  }
308  if ( i < mnCount - 1 )
309  fStep = maRange[ i ].X - maRange[ i - 1 ].X;
310  else
311  fStep = mfStepSize;
312  }
313  if ( fStep > 0 && fStep < mfStepSize )
314  mfStepSize = fStep;
315  }
316 
317  // step must be constant (or gap multiple of step)
318  bool bHasGap = false;
319  for ( SCSIZE i = 1; i < mnCount && !bHasGap; i++ )
320  {
321  double fStep = maRange[ i ].X - maRange[ i - 1 ].X;
322 
323  if ( fStep != mfStepSize )
324  {
325  if ( fmod( fStep, mfStepSize ) != 0.0 )
326  {
327  // step not constant nor multiple of mfStepSize in case of gaps
328  mnErrorValue = FormulaError::NoValue;
329  return false;
330  }
331  bHasGap = true;
332  }
333  }
334 
335  // fill gaps with values depending on bDataCompletion
336  if ( bHasGap )
337  {
338  SCSIZE nMissingXCount = 0;
339  double fOriginalCount = static_cast< double >( mnCount );
340  if ( mnMonthDay )
341  aDate = aNullDate + static_cast< sal_Int32 >( maRange[ 0 ].X );
342  for ( SCSIZE i = 1; i < mnCount; i++ )
343  {
344  double fDist;
345  if ( mnMonthDay )
346  {
347  Date aDate1 = aNullDate + static_cast< sal_Int32 >( maRange[ i ].X );
348  fDist = 12 * ( aDate1.GetYear() - aDate.GetYear() ) +
349  ( aDate1.GetMonth() - aDate.GetMonth() );
350  aDate = aDate1;
351  }
352  else
353  fDist = maRange[ i ].X - maRange[ i - 1 ].X;
354  if ( fDist > mfStepSize )
355  {
356  // gap, insert missing data points
357  double fYGap = ( maRange[ i ].Y + maRange[ i - 1 ].Y ) / 2.0;
358  for ( double fXGap = maRange[ i - 1].X + mfStepSize; fXGap < maRange[ i ].X; fXGap += mfStepSize )
359  {
360  maRange.insert( maRange.begin() + i, DataPoint( fXGap, ( bDataCompletion ? fYGap : 0.0 ) ) );
361  i++;
362  mnCount++;
363  nMissingXCount++;
364  if ( static_cast< double >( nMissingXCount ) / fOriginalCount > 0.3 )
365  {
366  // maximum of 30% missing points exceeded
367  mnErrorValue = FormulaError::NoValue;
368  return false;
369  }
370  }
371  }
372  }
373  }
374 
375  if ( nSmplInPrd != 1 )
376  mnSmplInPrd = nSmplInPrd;
377  else
378  {
379  mnSmplInPrd = CalcPeriodLen();
380  if ( mnSmplInPrd == 1 )
381  bEDS = true; // period length 1 means no periodic data: EDS suffices
382  }
383 
384  if ( !initData() )
385  return false; // note: mnErrorValue is set in called function(s)
386 
387  return true;
388 }
389 
390 bool ScETSForecastCalculation::initData( )
391 {
392  // give various vectors size and initial value
393  mpBase.reset( new double[ mnCount ] );
394  mpTrend.reset( new double[ mnCount ] );
395  if ( !bEDS )
396  mpPerIdx.reset( new double[ mnCount ] );
397  mpForecast.reset( new double[ mnCount ] );
398  mpForecast[ 0 ] = maRange[ 0 ].Y;
399 
400  if ( prefillTrendData() )
401  {
402  if ( prefillPerIdx() )
403  {
404  prefillBaseData();
405  return true;
406  }
407  }
408  return false;
409 }
410 
411 bool ScETSForecastCalculation::prefillTrendData()
412 {
413  if ( bEDS )
414  mpTrend[ 0 ] = ( maRange[ mnCount - 1 ].Y - maRange[ 0 ].Y ) / static_cast< double >( mnCount - 1 );
415  else
416  {
417  // we need at least 2 periods in the data range
418  if ( mnCount < 2 * mnSmplInPrd )
419  {
420  mnErrorValue = FormulaError::NoValue;
421  return false;
422  }
423 
424  double fSum = 0.0;
425  for ( SCSIZE i = 0; i < mnSmplInPrd; i++ )
426  fSum += maRange[ i + mnSmplInPrd ].Y - maRange[ i ].Y;
427  double fTrend = fSum / static_cast< double >( mnSmplInPrd * mnSmplInPrd );
428 
429  mpTrend[ 0 ] = fTrend;
430  }
431 
432  return true;
433 }
434 
435 bool ScETSForecastCalculation::prefillPerIdx()
436 {
437  if ( !bEDS )
438  {
439  // use as many complete periods as available
440  if ( mnSmplInPrd == 0 )
441  {
442  // should never happen; if mnSmplInPrd equals 0, bEDS is true
443  mnErrorValue = FormulaError::UnknownState;
444  return false;
445  }
446  SCSIZE nPeriods = mnCount / mnSmplInPrd;
447  std::vector< double > aPeriodAverage( nPeriods, 0.0 );
448  for ( SCSIZE i = 0; i < nPeriods ; i++ )
449  {
450  for ( SCSIZE j = 0; j < mnSmplInPrd; j++ )
451  aPeriodAverage[ i ] += maRange[ i * mnSmplInPrd + j ].Y;
452  aPeriodAverage[ i ] /= static_cast< double >( mnSmplInPrd );
453  if ( aPeriodAverage[ i ] == 0.0 )
454  {
455  SAL_WARN( "sc.core", "prefillPerIdx(), average of 0 will cause divide by zero error, quitting calculation" );
456  mnErrorValue = FormulaError::DivisionByZero;
457  return false;
458  }
459  }
460 
461  for ( SCSIZE j = 0; j < mnSmplInPrd; j++ )
462  {
463  double fI = 0.0;
464  for ( SCSIZE i = 0; i < nPeriods ; i++ )
465  {
466  // adjust average value for position within period
467  if ( bAdditive )
468  fI += ( maRange[ i * mnSmplInPrd + j ].Y -
469  ( aPeriodAverage[ i ] + ( static_cast< double >( j ) - 0.5 * ( mnSmplInPrd - 1 ) ) *
470  mpTrend[ 0 ] ) );
471  else
472  fI += ( maRange[ i * mnSmplInPrd + j ].Y /
473  ( aPeriodAverage[ i ] + ( static_cast< double >( j ) - 0.5 * ( mnSmplInPrd - 1 ) ) *
474  mpTrend[ 0 ] ) );
475  }
476  mpPerIdx[ j ] = fI / nPeriods;
477  }
478  if (mnSmplInPrd < mnCount)
479  mpPerIdx[mnSmplInPrd] = 0.0;
480  }
481  return true;
482 }
483 
484 void ScETSForecastCalculation::prefillBaseData()
485 {
486  if ( bEDS )
487  mpBase[ 0 ] = maRange[ 0 ].Y;
488  else
489  mpBase[ 0 ] = maRange[ 0 ].Y / mpPerIdx[ 0 ];
490 }
491 
492 void ScETSForecastCalculation::initCalc()
493 {
494  if ( !mbInitialised )
495  {
496  CalcAlphaBetaGamma();
497 
498  mbInitialised = true;
499  calcAccuracyIndicators();
500  }
501 }
502 
503 void ScETSForecastCalculation::calcAccuracyIndicators()
504 {
505  double fSumAbsErr = 0.0;
506  double fSumDivisor = 0.0;
507  double fSumErrSq = 0.0;
508  double fSumAbsPercErr = 0.0;
509 
510  for ( SCSIZE i = 1; i < mnCount; i++ )
511  {
512  double fError = mpForecast[ i ] - maRange[ i ].Y;
513  fSumAbsErr += fabs( fError );
514  fSumErrSq += fError * fError;
515  fSumAbsPercErr += fabs( fError ) / ( fabs( mpForecast[ i ] ) + fabs( maRange[ i ].Y ) );
516  }
517 
518  for ( SCSIZE i = 2; i < mnCount; i++ )
519  fSumDivisor += fabs( maRange[ i ].Y - maRange[ i - 1 ].Y );
520 
521  int nCalcCount = mnCount - 1;
522  mfMAE = fSumAbsErr / nCalcCount;
523  mfMASE = fSumAbsErr / ( nCalcCount * fSumDivisor / ( nCalcCount - 1 ) );
524  mfMSE = fSumErrSq / nCalcCount;
525  mfRMSE = sqrt( mfMSE );
526  mfSMAPE = fSumAbsPercErr * 2.0 / nCalcCount;
527 }
528 
529 /*
530  * CalcPeriodLen() calculates the most likely length of a period.
531  *
532  * Method used: for all possible values (between mnCount/2 and 2) compare for
533  * each (sample-previous sample) with next period and calculate mean error.
534  * Use as much samples as possible for each period length and the most recent samples
535  * Return the period length with the lowest mean error.
536  */
537 SCSIZE ScETSForecastCalculation::CalcPeriodLen()
538 {
539  SCSIZE nBestVal = mnCount;
540  double fBestME = ::std::numeric_limits<double>::max();
541 
542  for ( SCSIZE nPeriodLen = mnCount / 2; nPeriodLen >= 1; nPeriodLen-- )
543  {
544  double fMeanError = 0.0;
545  SCSIZE nPeriods = mnCount / nPeriodLen;
546  SCSIZE nStart = mnCount - ( nPeriods * nPeriodLen ) + 1;
547  for ( SCSIZE i = nStart; i < ( mnCount - nPeriodLen ); i++ )
548  {
549  fMeanError += fabs( ( maRange[ i ].Y - maRange[ i - 1 ].Y ) -
550  ( maRange[ nPeriodLen + i ].Y - maRange[ nPeriodLen + i - 1 ].Y ) );
551  }
552  fMeanError /= static_cast< double >( ( nPeriods - 1 ) * nPeriodLen - 1 );
553 
554  if ( fMeanError <= fBestME || fMeanError == 0.0 )
555  {
556  nBestVal = nPeriodLen;
557  fBestME = fMeanError;
558  }
559  }
560  return nBestVal;
561 }
562 
563 void ScETSForecastCalculation::CalcAlphaBetaGamma()
564 {
565  double f0 = 0.0;
566  mfAlpha = f0;
567  if ( bEDS )
568  {
569  mfBeta = 0.0; // beta is not used with EDS
570  CalcGamma();
571  }
572  else
573  CalcBetaGamma();
574  refill();
575  double fE0 = mfMSE;
576 
577  double f2 = 1.0;
578  mfAlpha = f2;
579  if ( bEDS )
580  CalcGamma();
581  else
582  CalcBetaGamma();
583  refill();
584  double fE2 = mfMSE;
585 
586  double f1 = 0.5;
587  mfAlpha = f1;
588  if ( bEDS )
589  CalcGamma();
590  else
591  CalcBetaGamma();
592  refill();
593 
594  if ( fE0 == mfMSE && mfMSE == fE2 )
595  {
596  mfAlpha = 0;
597  if ( bEDS )
598  CalcGamma();
599  else
600  CalcBetaGamma();
601  refill();
602  return;
603  }
604  while ( ( f2 - f1 ) > cfMinABCResolution )
605  {
606  if ( fE2 > fE0 )
607  {
608  f2 = f1;
609  fE2 = mfMSE;
610  f1 = ( f0 + f1 ) / 2;
611  }
612  else
613  {
614  f0 = f1;
615  fE0 = mfMSE;
616  f1 = ( f1 + f2 ) / 2;
617  }
618  mfAlpha = f1;
619  if ( bEDS )
620  CalcGamma();
621  else
622  CalcBetaGamma();
623  refill();
624  }
625  if ( fE2 > fE0 )
626  {
627  if ( fE0 < mfMSE )
628  {
629  mfAlpha = f0;
630  if ( bEDS )
631  CalcGamma();
632  else
633  CalcBetaGamma();
634  refill();
635  }
636  }
637  else
638  {
639  if ( fE2 < mfMSE )
640  {
641  mfAlpha = f2;
642  if ( bEDS )
643  CalcGamma();
644  else
645  CalcBetaGamma();
646  refill();
647  }
648  }
649  calcAccuracyIndicators();
650 }
651 
652 void ScETSForecastCalculation::CalcBetaGamma()
653 {
654  double f0 = 0.0;
655  mfBeta = f0;
656  CalcGamma();
657  refill();
658  double fE0 = mfMSE;
659 
660  double f2 = 1.0;
661  mfBeta = f2;
662  CalcGamma();
663  refill();
664  double fE2 = mfMSE;
665 
666  double f1 = 0.5;
667  mfBeta = f1;
668  CalcGamma();
669  refill();
670 
671  if ( fE0 == mfMSE && mfMSE == fE2 )
672  {
673  mfBeta = 0;
674  CalcGamma();
675  refill();
676  return;
677  }
678  while ( ( f2 - f1 ) > cfMinABCResolution )
679  {
680  if ( fE2 > fE0 )
681  {
682  f2 = f1;
683  fE2 = mfMSE;
684  f1 = ( f0 + f1 ) / 2;
685  }
686  else
687  {
688  f0 = f1;
689  fE0 = mfMSE;
690  f1 = ( f1 + f2 ) / 2;
691  }
692  mfBeta = f1;
693  CalcGamma();
694  refill();
695  }
696  if ( fE2 > fE0 )
697  {
698  if ( fE0 < mfMSE )
699  {
700  mfBeta = f0;
701  CalcGamma();
702  refill();
703  }
704  }
705  else
706  {
707  if ( fE2 < mfMSE )
708  {
709  mfBeta = f2;
710  CalcGamma();
711  refill();
712  }
713  }
714 }
715 
716 void ScETSForecastCalculation::CalcGamma()
717 {
718  double f0 = 0.0;
719  mfGamma = f0;
720  refill();
721  double fE0 = mfMSE;
722 
723  double f2 = 1.0;
724  mfGamma = f2;
725  refill();
726  double fE2 = mfMSE;
727 
728  double f1 = 0.5;
729  mfGamma = f1;
730  refill();
731 
732  if ( fE0 == mfMSE && mfMSE == fE2 )
733  {
734  mfGamma = 0;
735  refill();
736  return;
737  }
738  while ( ( f2 - f1 ) > cfMinABCResolution )
739  {
740  if ( fE2 > fE0 )
741  {
742  f2 = f1;
743  fE2 = mfMSE;
744  f1 = ( f0 + f1 ) / 2;
745  }
746  else
747  {
748  f0 = f1;
749  fE0 = mfMSE;
750  f1 = ( f1 + f2 ) / 2;
751  }
752  mfGamma = f1;
753  refill();
754  }
755  if ( fE2 > fE0 )
756  {
757  if ( fE0 < mfMSE )
758  {
759  mfGamma = f0;
760  refill();
761  }
762  }
763  else
764  {
765  if ( fE2 < mfMSE )
766  {
767  mfGamma = f2;
768  refill();
769  }
770  }
771 }
772 
773 void ScETSForecastCalculation::refill()
774 {
775  // refill mpBase, mpTrend, mpPerIdx and mpForecast with values
776  // using the calculated mfAlpha, (mfBeta), mfGamma
777  // forecast 1 step ahead
778  for ( SCSIZE i = 1; i < mnCount; i++ )
779  {
780  if ( bEDS )
781  {
782  mpBase[ i ] = mfAlpha * maRange[ i ].Y +
783  ( 1 - mfAlpha ) * ( mpBase[ i - 1 ] + mpTrend[ i - 1 ] );
784  mpTrend[ i ] = mfGamma * ( mpBase[ i ] - mpBase[ i - 1 ] ) +
785  ( 1 - mfGamma ) * mpTrend[ i - 1 ];
786  mpForecast[ i ] = mpBase[ i - 1 ] + mpTrend[ i - 1 ];
787  }
788  else
789  {
790  SCSIZE nIdx;
791  if ( bAdditive )
792  {
793  nIdx = ( i > mnSmplInPrd ? i - mnSmplInPrd : i );
794  mpBase[ i ] = mfAlpha * ( maRange[ i ].Y - mpPerIdx[ nIdx ] ) +
795  ( 1 - mfAlpha ) * ( mpBase[ i - 1 ] + mpTrend[ i - 1 ] );
796  mpPerIdx[ i ] = mfBeta * ( maRange[ i ].Y - mpBase[ i ] ) +
797  ( 1 - mfBeta ) * mpPerIdx[ nIdx ];
798  }
799  else
800  {
801  nIdx = ( i >= mnSmplInPrd ? i - mnSmplInPrd : i );
802  mpBase[ i ] = mfAlpha * ( maRange[ i ].Y / mpPerIdx[ nIdx ] ) +
803  ( 1 - mfAlpha ) * ( mpBase[ i - 1 ] + mpTrend[ i - 1 ] );
804  mpPerIdx[ i ] = mfBeta * ( maRange[ i ].Y / mpBase[ i ] ) +
805  ( 1 - mfBeta ) * mpPerIdx[ nIdx ];
806  }
807  mpTrend[ i ] = mfGamma * ( mpBase[ i ] - mpBase[ i - 1 ] ) +
808  ( 1 - mfGamma ) * mpTrend[ i - 1 ];
809 
810  if ( bAdditive )
811  mpForecast[ i ] = mpBase[ i - 1 ] + mpTrend[ i - 1 ] + mpPerIdx[ nIdx ];
812  else
813  mpForecast[ i ] = ( mpBase[ i - 1 ] + mpTrend[ i - 1 ] ) * mpPerIdx[ nIdx ];
814  }
815  }
816  calcAccuracyIndicators();
817 }
818 
819 double ScETSForecastCalculation::convertXtoMonths( double x )
820 {
821  Date aDate = mpFormatter->GetNullDate() + static_cast< sal_Int32 >( x );
822  int nYear = aDate.GetYear();
823  int nMonth = aDate.GetMonth();
824  double fMonthLength;
825  switch ( nMonth )
826  {
827  case 1 :
828  case 3 :
829  case 5 :
830  case 7 :
831  case 8 :
832  case 10 :
833  case 12 :
834  fMonthLength = 31.0;
835  break;
836  case 2 :
837  fMonthLength = ( aDate.IsLeapYear() ? 29.0 : 28.0 );
838  break;
839  default :
840  fMonthLength = 30.0;
841  }
842  return ( 12.0 * nYear + nMonth + ( aDate.GetDay() - mnMonthDay ) / fMonthLength );
843 }
844 
845 void ScETSForecastCalculation::GetForecast( double fTarget, double& rForecast )
846 {
847  initCalc();
848 
849  if ( fTarget <= maRange[ mnCount - 1 ].X )
850  {
851  SCSIZE n = ( fTarget - maRange[ 0 ].X ) / mfStepSize;
852  double fInterpolate = fmod( fTarget - maRange[ 0 ].X, mfStepSize );
853  rForecast = maRange[ n ].Y;
854 
855  if ( fInterpolate >= cfMinABCResolution )
856  {
857  double fInterpolateFactor = fInterpolate / mfStepSize;
858  double fFc_1 = mpForecast[ n + 1 ];
859  rForecast = rForecast + fInterpolateFactor * ( fFc_1 - rForecast );
860  }
861  }
862  else
863  {
864  SCSIZE n = ( fTarget - maRange[ mnCount - 1 ].X ) / mfStepSize;
865  double fInterpolate = fmod( fTarget - maRange[ mnCount - 1 ].X, mfStepSize );
866 
867  if ( bEDS )
868  rForecast = mpBase[ mnCount - 1 ] + n * mpTrend[ mnCount - 1 ];
869  else if ( bAdditive )
870  rForecast = mpBase[ mnCount - 1 ] + n * mpTrend[ mnCount - 1 ] +
871  mpPerIdx[ mnCount - 1 - mnSmplInPrd + ( n % mnSmplInPrd ) ];
872  else
873  rForecast = ( mpBase[ mnCount - 1 ] + n * mpTrend[ mnCount - 1 ] ) *
874  mpPerIdx[ mnCount - 1 - mnSmplInPrd + ( n % mnSmplInPrd ) ];
875 
876  if ( fInterpolate >= cfMinABCResolution )
877  {
878  double fInterpolateFactor = fInterpolate / mfStepSize;
879  double fFc_1;
880  if ( bEDS )
881  fFc_1 = mpBase[ mnCount - 1 ] + ( n + 1 ) * mpTrend[ mnCount - 1 ];
882  else if ( bAdditive )
883  fFc_1 = mpBase[ mnCount - 1 ] + ( n + 1 ) * mpTrend[ mnCount - 1 ] +
884  mpPerIdx[ mnCount - 1 - mnSmplInPrd + ( ( n + 1 ) % mnSmplInPrd ) ];
885  else
886  fFc_1 = ( mpBase[ mnCount - 1 ] + ( n + 1 ) * mpTrend[ mnCount - 1 ] ) *
887  mpPerIdx[ mnCount - 1 - mnSmplInPrd + ( ( n + 1 ) % mnSmplInPrd ) ];
888  rForecast = rForecast + fInterpolateFactor * ( fFc_1 - rForecast );
889  }
890  }
891 }
892 
893 void ScETSForecastCalculation::GetForecastRange( const ScMatrixRef& rTMat, const ScMatrixRef& rFcMat )
894 {
895  SCSIZE nC, nR;
896  rTMat->GetDimensions( nC, nR );
897 
898  for ( SCSIZE i = 0; i < nR; i++ )
899  {
900  for ( SCSIZE j = 0; j < nC; j++ )
901  {
902  double fTarget;
903  if ( mnMonthDay )
904  fTarget = convertXtoMonths( rTMat->GetDouble( j, i ) );
905  else
906  fTarget = rTMat->GetDouble( j, i );
907  double fForecast;
908  GetForecast( fTarget, fForecast );
909  rFcMat->PutDouble( fForecast, j, i );
910  }
911  }
912 }
913 
914 void ScETSForecastCalculation::GetStatisticValue( const ScMatrixRef& rTypeMat, const ScMatrixRef& rStatMat )
915 {
916  initCalc();
917 
918  SCSIZE nC, nR;
919  rTypeMat->GetDimensions( nC, nR );
920  for ( SCSIZE i = 0; i < nR; i++ )
921  {
922  for ( SCSIZE j = 0; j < nC; j++ )
923  {
924  switch ( static_cast< int >( rTypeMat->GetDouble( j, i ) ) )
925  {
926  case 1 : // alpha
927  rStatMat->PutDouble( mfAlpha, j, i );
928  break;
929  case 2 : // gamma
930  rStatMat->PutDouble( mfGamma, j, i );
931  break;
932  case 3 : // beta
933  rStatMat->PutDouble( mfBeta, j, i );
934  break;
935  case 4 : // MASE
936  rStatMat->PutDouble( mfMASE, j, i );
937  break;
938  case 5 : // SMAPE
939  rStatMat->PutDouble( mfSMAPE, j, i );
940  break;
941  case 6 : // MAE
942  rStatMat->PutDouble( mfMAE, j, i );
943  break;
944  case 7 : // RMSE
945  rStatMat->PutDouble( mfRMSE, j, i );
946  break;
947  case 8 : // step size
948  rStatMat->PutDouble( mfStepSize, j, i );
949  break;
950  case 9 : // samples in period
951  rStatMat->PutDouble( mnSmplInPrd, j, i );
952  break;
953  }
954  }
955  }
956 }
957 
958 void ScETSForecastCalculation::GetSamplesInPeriod( double& rVal )
959 {
960  rVal = mnSmplInPrd;
961 }
962 
963 double ScETSForecastCalculation::RandDev()
964 {
965  // return a random deviation given the standard deviation
966  return ( mfRMSE * ScInterpreter::gaussinv(
968 }
969 
970 void ScETSForecastCalculation::GetETSPredictionIntervals( const ScMatrixRef& rTMat, const ScMatrixRef& rPIMat, double fPILevel )
971 {
972  initCalc();
973 
974  SCSIZE nC, nR;
975  rTMat->GetDimensions( nC, nR );
976 
977  // find maximum target value and calculate size of scenario-arrays
978  double fMaxTarget = rTMat->GetDouble( 0, 0 );
979  for ( SCSIZE i = 0; i < nR; i++ )
980  {
981  for ( SCSIZE j = 0; j < nC; j++ )
982  {
983  if ( fMaxTarget < rTMat->GetDouble( j, i ) )
984  fMaxTarget = rTMat->GetDouble( j, i );
985  }
986  }
987  if ( mnMonthDay )
988  fMaxTarget = convertXtoMonths( fMaxTarget ) - maRange[ mnCount - 1 ].X;
989  else
990  fMaxTarget -= maRange[ mnCount - 1 ].X;
991  SCSIZE nSize = fMaxTarget / mfStepSize;
992  if ( fmod( fMaxTarget, mfStepSize ) != 0.0 )
993  nSize++;
994 
995  if (nSize == 0)
996  {
997  mnErrorValue = FormulaError::IllegalArgument;
998  return;
999  }
1000 
1001  std::unique_ptr< double[] > xScenRange( new double[nSize]);
1002  std::unique_ptr< double[] > xScenBase( new double[nSize]);
1003  std::unique_ptr< double[] > xScenTrend( new double[nSize]);
1004  std::unique_ptr< double[] > xScenPerIdx( new double[nSize]);
1005  std::vector< std::vector< double > > aPredictions( nSize, std::vector< double >( cnScenarios ) );
1006 
1007  // fill scenarios
1008  for ( SCSIZE k = 0; k < cnScenarios; k++ )
1009  {
1010  // fill array with forecasts, with RandDev() added to xScenRange
1011  if ( bAdditive )
1012  {
1013  double nPIdx = !bEDS ? mpPerIdx[mnCount - mnSmplInPrd] : 0.0;
1014  // calculation based on additive model
1015  xScenRange[ 0 ] = mpBase[ mnCount - 1 ] + mpTrend[ mnCount - 1 ] +
1016  nPIdx +
1017  RandDev();
1018  aPredictions[ 0 ][ k ] = xScenRange[ 0 ];
1019  xScenBase[ 0 ] = mfAlpha * ( xScenRange[ 0 ] - nPIdx ) +
1020  ( 1 - mfAlpha ) * ( mpBase[ mnCount - 1 ] + mpTrend[ mnCount - 1 ] );
1021  xScenTrend[ 0 ] = mfGamma * ( xScenBase[ 0 ] - mpBase[ mnCount - 1 ] ) +
1022  ( 1 - mfGamma ) * mpTrend[ mnCount - 1 ];
1023  xScenPerIdx[ 0 ] = mfBeta * ( xScenRange[ 0 ] - xScenBase[ 0 ] ) +
1024  ( 1 - mfBeta ) * nPIdx;
1025  for ( SCSIZE i = 1; i < nSize; i++ )
1026  {
1027  double fPerIdx;
1028  if ( i < mnSmplInPrd )
1029  fPerIdx = mpPerIdx[ mnCount + i - mnSmplInPrd ];
1030  else
1031  fPerIdx = xScenPerIdx[ i - mnSmplInPrd ];
1032  xScenRange[ i ] = xScenBase[ i - 1 ] + xScenTrend[ i - 1 ] + fPerIdx + RandDev();
1033  aPredictions[ i ][ k ] = xScenRange[ i ];
1034  xScenBase[ i ] = mfAlpha * ( xScenRange[ i ] - fPerIdx ) +
1035  ( 1 - mfAlpha ) * ( xScenBase[ i - 1 ] + xScenTrend[ i - 1 ] );
1036  xScenTrend[ i ] = mfGamma * ( xScenBase[ i ] - xScenBase[ i - 1 ] ) +
1037  ( 1 - mfGamma ) * xScenTrend[ i - 1 ];
1038  xScenPerIdx[ i ] = mfBeta * ( xScenRange[ i ] - xScenBase[ i ] ) +
1039  ( 1 - mfBeta ) * fPerIdx;
1040  }
1041  }
1042  else
1043  {
1044  // calculation based on multiplicative model
1045  xScenRange[ 0 ] = ( mpBase[ mnCount - 1 ] + mpTrend[ mnCount - 1 ] ) *
1046  mpPerIdx[ mnCount - mnSmplInPrd ] +
1047  RandDev();
1048  aPredictions[ 0 ][ k ] = xScenRange[ 0 ];
1049  xScenBase[ 0 ] = mfAlpha * ( xScenRange[ 0 ] / mpPerIdx[ mnCount - mnSmplInPrd ] ) +
1050  ( 1 - mfAlpha ) * ( mpBase[ mnCount - 1 ] + mpTrend[ mnCount - 1 ] );
1051  xScenTrend[ 0 ] = mfGamma * ( xScenBase[ 0 ] - mpBase[ mnCount - 1 ] ) +
1052  ( 1 - mfGamma ) * mpTrend[ mnCount - 1 ];
1053  xScenPerIdx[ 0 ] = mfBeta * ( xScenRange[ 0 ] / xScenBase[ 0 ] ) +
1054  ( 1 - mfBeta ) * mpPerIdx[ mnCount - mnSmplInPrd ];
1055  for ( SCSIZE i = 1; i < nSize; i++ )
1056  {
1057  double fPerIdx;
1058  if ( i < mnSmplInPrd )
1059  fPerIdx = mpPerIdx[ mnCount + i - mnSmplInPrd ];
1060  else
1061  fPerIdx = xScenPerIdx[ i - mnSmplInPrd ];
1062  xScenRange[ i ] = ( xScenBase[ i - 1 ] + xScenTrend[ i - 1 ] ) * fPerIdx + RandDev();
1063  aPredictions[ i ][ k ] = xScenRange[ i ];
1064  xScenBase[ i ] = mfAlpha * ( xScenRange[ i ] / fPerIdx ) +
1065  ( 1 - mfAlpha ) * ( xScenBase[ i - 1 ] + xScenTrend[ i - 1 ] );
1066  xScenTrend[ i ] = mfGamma * ( xScenBase[ i ] - xScenBase[ i - 1 ] ) +
1067  ( 1 - mfGamma ) * xScenTrend[ i - 1 ];
1068  xScenPerIdx[ i ] = mfBeta * ( xScenRange[ i ] / xScenBase[ i ] ) +
1069  ( 1 - mfBeta ) * fPerIdx;
1070  }
1071  }
1072  }
1073 
1074  // create array of Percentile values;
1075  std::unique_ptr< double[] > xPercentile( new double[nSize]);
1076  for ( SCSIZE i = 0; i < nSize; i++ )
1077  {
1078  xPercentile[ i ] = ScInterpreter::GetPercentile( aPredictions[ i ], ( 1 + fPILevel ) / 2 ) -
1079  ScInterpreter::GetPercentile( aPredictions[ i ], 0.5 );
1080  }
1081 
1082  for ( SCSIZE i = 0; i < nR; i++ )
1083  {
1084  for ( SCSIZE j = 0; j < nC; j++ )
1085  {
1086  double fTarget;
1087  if ( mnMonthDay )
1088  fTarget = convertXtoMonths( rTMat->GetDouble( j, i ) ) - maRange[ mnCount - 1 ].X;
1089  else
1090  fTarget = rTMat->GetDouble( j, i ) - maRange[ mnCount - 1 ].X;
1091  SCSIZE nSteps = ( fTarget / mfStepSize ) - 1;
1092  double fFactor = fmod( fTarget, mfStepSize );
1093  double fPI = xPercentile[ nSteps ];
1094  if ( fFactor != 0.0 )
1095  {
1096  // interpolate
1097  double fPI1 = xPercentile[ nSteps + 1 ];
1098  fPI = fPI + fFactor * ( fPI1 - fPI );
1099  }
1100  rPIMat->PutDouble( fPI, j, i );
1101  }
1102  }
1103 }
1104 
1105 
1106 void ScETSForecastCalculation::GetEDSPredictionIntervals( const ScMatrixRef& rTMat, const ScMatrixRef& rPIMat, double fPILevel )
1107 {
1108  initCalc();
1109 
1110  SCSIZE nC, nR;
1111  rTMat->GetDimensions( nC, nR );
1112 
1113  // find maximum target value and calculate size of coefficient- array c
1114  double fMaxTarget = rTMat->GetDouble( 0, 0 );
1115  for ( SCSIZE i = 0; i < nR; i++ )
1116  {
1117  for ( SCSIZE j = 0; j < nC; j++ )
1118  {
1119  if ( fMaxTarget < rTMat->GetDouble( j, i ) )
1120  fMaxTarget = rTMat->GetDouble( j, i );
1121  }
1122  }
1123  if ( mnMonthDay )
1124  fMaxTarget = convertXtoMonths( fMaxTarget ) - maRange[ mnCount - 1 ].X;
1125  else
1126  fMaxTarget -= maRange[ mnCount - 1 ].X;
1127  SCSIZE nSize = fMaxTarget / mfStepSize;
1128  if ( fmod( fMaxTarget, mfStepSize ) != 0.0 )
1129  nSize++;
1130 
1131  if (nSize == 0)
1132  {
1133  mnErrorValue = FormulaError::IllegalArgument;
1134  return;
1135  }
1136 
1137  double z = ScInterpreter::gaussinv( ( 1.0 + fPILevel ) / 2.0 );
1138  double o = 1 - fPILevel;
1139  std::vector< double > c( nSize );
1140  for ( SCSIZE i = 0; i < nSize; i++ )
1141  {
1142  c[ i ] = sqrt( 1 + ( fPILevel / pow( 1 + o, 3.0 ) ) *
1143  ( ( 1 + 4 * o + 5 * o * o ) +
1144  2 * static_cast< double >( i ) * fPILevel * ( 1 + 3 * o ) +
1145  2 * static_cast< double >( i * i ) * fPILevel * fPILevel ) );
1146  }
1147 
1148 
1149  for ( SCSIZE i = 0; i < nR; i++ )
1150  {
1151  for ( SCSIZE j = 0; j < nC; j++ )
1152  {
1153  double fTarget;
1154  if ( mnMonthDay )
1155  fTarget = convertXtoMonths( rTMat->GetDouble( j, i ) ) - maRange[ mnCount - 1 ].X;
1156  else
1157  fTarget = rTMat->GetDouble( j, i ) - maRange[ mnCount - 1 ].X;
1158  SCSIZE nSteps = ( fTarget / mfStepSize ) - 1;
1159  double fFactor = fmod( fTarget, mfStepSize );
1160  double fPI = z * mfRMSE * c[ nSteps ] / c[ 0 ];
1161  if ( fFactor != 0.0 )
1162  {
1163  // interpolate
1164  double fPI1 = z * mfRMSE * c[ nSteps + 1 ] / c[ 0 ];
1165  fPI = fPI + fFactor * ( fPI1 - fPI );
1166  }
1167  rPIMat->PutDouble( fPI, j, i );
1168  }
1169  }
1170 }
1171 
1172 
1174 {
1176  switch ( eETSType )
1177  {
1178  case etsAdd :
1179  case etsMult :
1180  case etsStatAdd :
1181  case etsStatMult :
1182  if ( !MustHaveParamCount( nParamCount, 3, 6 ) )
1183  return;
1184  break;
1185  case etsPIAdd :
1186  case etsPIMult :
1187  if ( !MustHaveParamCount( nParamCount, 3, 7 ) )
1188  {
1189  return;
1190  }
1191  break;
1192  case etsSeason :
1193  if ( !MustHaveParamCount( nParamCount, 2, 4 ) )
1194  return;
1195  break;
1196  }
1197 
1198  int nAggregation;
1199  if ( ( nParamCount == 6 && eETSType != etsPIAdd && eETSType != etsPIMult ) ||
1200  ( nParamCount == 4 && eETSType == etsSeason ) ||
1201  nParamCount == 7 )
1202  nAggregation = static_cast< int >( GetDoubleWithDefault( 1.0 ) );
1203  else
1204  nAggregation = 1;
1205  if ( nAggregation < 1 || nAggregation > 7 )
1206  {
1208  return;
1209  }
1210 
1211  bool bDataCompletion;
1212  if ( ( nParamCount >= 5 && eETSType != etsPIAdd && eETSType != etsPIMult ) ||
1213  ( nParamCount >= 3 && eETSType == etsSeason ) ||
1214  ( nParamCount >= 6 && ( eETSType == etsPIAdd || eETSType == etsPIMult ) ) )
1215  {
1216  int nTemp = static_cast< int >( GetDoubleWithDefault( 1.0 ) );
1217  if ( nTemp == 0 || nTemp == 1 )
1218  bDataCompletion = nTemp;
1219  else
1220  {
1222  return;
1223  }
1224  }
1225  else
1226  bDataCompletion = true;
1227 
1228  int nSmplInPrd;
1229  if ( ( ( nParamCount >= 4 && eETSType != etsPIAdd && eETSType != etsPIMult ) ||
1230  ( nParamCount >= 5 && ( eETSType == etsPIAdd || eETSType == etsPIMult ) ) ) &&
1231  eETSType != etsSeason )
1232  {
1233  double fVal = GetDoubleWithDefault( 1.0 );
1234  if ( fmod( fVal, 1.0 ) != 0 || fVal < 0.0 )
1235  {
1236  PushError( FormulaError::IllegalFPOperation );
1237  return;
1238  }
1239  nSmplInPrd = static_cast< int >( fVal );
1240  }
1241  else
1242  nSmplInPrd = 1;
1243 
1244  // required arguments
1245  double fPILevel = 0.0;
1246  if ( nParamCount < 3 && ( nParamCount != 2 || eETSType != etsSeason ) )
1247  {
1249  return;
1250  }
1251 
1252  if ( eETSType == etsPIAdd || eETSType == etsPIMult )
1253  {
1254  fPILevel = (nParamCount < 4 ? 0.95 : GetDoubleWithDefault( 0.95 ));
1255  if ( fPILevel < 0 || fPILevel > 1 )
1256  {
1258  return;
1259  }
1260  }
1261 
1262  ScMatrixRef pTypeMat;
1263  if ( eETSType == etsStatAdd || eETSType == etsStatMult )
1264  {
1265  pTypeMat = GetMatrix();
1266  SCSIZE nC, nR;
1267  pTypeMat->GetDimensions( nC, nR );
1268  for ( SCSIZE i = 0; i < nR; i++ )
1269  {
1270  for ( SCSIZE j = 0; j < nC; j++ )
1271  {
1272  if ( static_cast< int >( pTypeMat->GetDouble( j, i ) ) < 1 ||
1273  static_cast< int >( pTypeMat->GetDouble( j, i ) ) > 9 )
1274  {
1276  return;
1277  }
1278  }
1279  }
1280  }
1281 
1282  ScMatrixRef pMatX = GetMatrix();
1283  ScMatrixRef pMatY = GetMatrix();
1284  if ( !pMatX || !pMatY )
1285  {
1287  return;
1288  }
1289  SCSIZE nCX, nCY;
1290  SCSIZE nRX, nRY;
1291  pMatX->GetDimensions( nCX, nRX );
1292  pMatY->GetDimensions( nCY, nRY );
1293  if ( nRX != nRY || nCX != nCY ||
1294  !pMatX->IsNumeric() || !pMatY->IsNumeric() )
1295  {
1297  return;
1298  }
1299 
1300  ScMatrixRef pTMat;
1301  if ( eETSType != etsStatAdd && eETSType != etsStatMult && eETSType != etsSeason )
1302  {
1303  pTMat = GetMatrix();
1304  if ( !pTMat )
1305  {
1307  return;
1308  }
1309  }
1310 
1311  ScETSForecastCalculation aETSCalc( pMatX->GetElementCount(), pFormatter );
1312  if ( !aETSCalc.PreprocessDataRange( pMatX, pMatY, nSmplInPrd, bDataCompletion,
1313  nAggregation,
1314  ( eETSType != etsStatAdd && eETSType != etsStatMult ? pTMat : nullptr ),
1315  eETSType ) )
1316  {
1317  PushError( aETSCalc.GetError() );
1318  return;
1319  }
1320 
1321  switch ( eETSType )
1322  {
1323  case etsAdd :
1324  case etsMult :
1325  {
1326  SCSIZE nC, nR;
1327  pTMat->GetDimensions( nC, nR );
1328  ScMatrixRef pFcMat = GetNewMat( nC, nR );
1329  aETSCalc.GetForecastRange( pTMat, pFcMat );
1330  if (aETSCalc.GetError() != FormulaError::NONE)
1331  PushError( aETSCalc.GetError()); // explicitly push error, PushMatrix() does not
1332  else
1333  PushMatrix( pFcMat );
1334  }
1335  break;
1336  case etsPIAdd :
1337  case etsPIMult :
1338  {
1339  SCSIZE nC, nR;
1340  pTMat->GetDimensions( nC, nR );
1341  ScMatrixRef pPIMat = GetNewMat( nC, nR );
1342  if ( nSmplInPrd == 0 )
1343  {
1344  aETSCalc.GetEDSPredictionIntervals( pTMat, pPIMat, fPILevel );
1345  }
1346  else
1347  {
1348  aETSCalc.GetETSPredictionIntervals( pTMat, pPIMat, fPILevel );
1349  }
1350  if (aETSCalc.GetError() != FormulaError::NONE)
1351  PushError( aETSCalc.GetError()); // explicitly push error, PushMatrix() does not
1352  else
1353  PushMatrix( pPIMat );
1354  }
1355  break;
1356  case etsStatAdd :
1357  case etsStatMult :
1358  {
1359  SCSIZE nC, nR;
1360  pTypeMat->GetDimensions( nC, nR );
1361  ScMatrixRef pStatMat = GetNewMat( nC, nR );
1362  aETSCalc.GetStatisticValue( pTypeMat, pStatMat );
1363  if (aETSCalc.GetError() != FormulaError::NONE)
1364  PushError( aETSCalc.GetError()); // explicitly push error, PushMatrix() does not
1365  else
1366  PushMatrix( pStatMat );
1367  }
1368  break;
1369  case etsSeason :
1370  {
1371  double rVal;
1372  aETSCalc.GetSamplesInPeriod( rVal );
1373  SetError( aETSCalc.GetError() );
1374  PushDouble( rVal );
1375  }
1376  break;
1377  }
1378 }
1379 
1381 {
1382  OUStringBuffer aResBuf;
1383  short nParamCount = GetByte();
1384 
1385  //reverse order of parameter stack to simplify concatenation:
1386  ReverseStack( nParamCount );
1387 
1388  size_t nRefInList = 0;
1389  while ( nParamCount-- > 0 && nGlobalError == FormulaError::NONE )
1390  {
1391  switch ( GetStackType() )
1392  {
1393  case svString:
1394  case svDouble:
1395  {
1396  const OUString& rStr = GetString().getString();
1397  if (CheckStringResultLen( aResBuf, rStr))
1398  aResBuf.append( rStr);
1399  }
1400  break;
1401  case svSingleRef :
1402  {
1403  ScAddress aAdr;
1404  PopSingleRef( aAdr );
1405  if ( nGlobalError != FormulaError::NONE )
1406  break;
1407  ScRefCellValue aCell( mrDoc, aAdr );
1408  if ( !aCell.isEmpty() )
1409  {
1410  if ( !aCell.hasEmptyValue() )
1411  {
1412  svl::SharedString aSS;
1413  GetCellString( aSS, aCell);
1414  const OUString& rStr = aSS.getString();
1415  if (CheckStringResultLen( aResBuf, rStr))
1416  aResBuf.append( rStr);
1417  }
1418  }
1419  }
1420  break;
1421  case svDoubleRef :
1422  case svRefList :
1423  {
1424  ScRange aRange;
1425  PopDoubleRef( aRange, nParamCount, nRefInList);
1426  if ( nGlobalError != FormulaError::NONE )
1427  break;
1428  // we need to read row for row, so we can't use ScCellIter
1429  SCCOL nCol1, nCol2;
1430  SCROW nRow1, nRow2;
1431  SCTAB nTab1, nTab2;
1432  aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
1433  if ( nTab1 != nTab2 )
1434  {
1435  SetError( FormulaError::IllegalParameter);
1436  break;
1437  }
1438  if ( nRow1 > nRow2 )
1439  std::swap( nRow1, nRow2 );
1440  if ( nCol1 > nCol2 )
1441  std::swap( nCol1, nCol2 );
1442  ScAddress aAdr;
1443  aAdr.SetTab( nTab1 );
1444  for ( SCROW nRow = nRow1; nRow <= nRow2; nRow++ )
1445  {
1446  for ( SCCOL nCol = nCol1; nCol <= nCol2; nCol++ )
1447  {
1448  aAdr.SetRow( nRow );
1449  aAdr.SetCol( nCol );
1450  ScRefCellValue aCell( mrDoc, aAdr );
1451  if ( !aCell.isEmpty() )
1452  {
1453  if ( !aCell.hasEmptyValue() )
1454  {
1455  svl::SharedString aSS;
1456  GetCellString( aSS, aCell);
1457  const OUString& rStr = aSS.getString();
1458  if (CheckStringResultLen( aResBuf, rStr))
1459  aResBuf.append( rStr);
1460  }
1461  }
1462  }
1463  }
1464  }
1465  break;
1466  case svMatrix :
1467  case svExternalSingleRef:
1468  case svExternalDoubleRef:
1469  {
1470  ScMatrixRef pMat = GetMatrix();
1471  if (pMat)
1472  {
1473  SCSIZE nC, nR;
1474  pMat->GetDimensions(nC, nR);
1475  if (nC == 0 || nR == 0)
1476  SetError(FormulaError::IllegalArgument);
1477  else
1478  {
1479  for (SCSIZE k = 0; k < nR; ++k)
1480  {
1481  for (SCSIZE j = 0; j < nC; ++j)
1482  {
1483  if ( pMat->IsStringOrEmpty( j, k ) )
1484  {
1485  const OUString& rStr = pMat->GetString( j, k ).getString();
1486  if (CheckStringResultLen( aResBuf, rStr))
1487  aResBuf.append( rStr);
1488  }
1489  else
1490  {
1491  if ( pMat->IsValue( j, k ) )
1492  {
1493  const OUString& rStr = pMat->GetString( *pFormatter, j, k ).getString();
1494  if (CheckStringResultLen( aResBuf, rStr))
1495  aResBuf.append( rStr);
1496  }
1497  }
1498  }
1499  }
1500  }
1501  }
1502  }
1503  break;
1504  default:
1505  PopError();
1506  SetError( FormulaError::IllegalArgument);
1507  break;
1508  }
1509  }
1510  PushString( aResBuf.makeStringAndClear() );
1511 }
1512 
1514 {
1515  short nParamCount = GetByte();
1516 
1517  if ( !MustHaveParamCountMin( nParamCount, 3 ) )
1518  return;
1519 
1520  //reverse order of parameter stack to simplify processing
1521  ReverseStack( nParamCount );
1522 
1523  // get aDelimiters and bSkipEmpty
1524  std::vector< OUString > aDelimiters;
1525  size_t nRefInList = 0;
1526  switch ( GetStackType() )
1527  {
1528  case svString:
1529  case svDouble:
1530  aDelimiters.push_back( GetString().getString() );
1531  break;
1532  case svSingleRef :
1533  {
1534  ScAddress aAdr;
1535  PopSingleRef( aAdr );
1536  if ( nGlobalError != FormulaError::NONE )
1537  break;
1538  ScRefCellValue aCell( mrDoc, aAdr );
1539  if ( !aCell.isEmpty() )
1540  {
1541  if ( !aCell.hasEmptyValue() )
1542  {
1543  svl::SharedString aSS;
1544  GetCellString( aSS, aCell);
1545  aDelimiters.push_back( aSS.getString());
1546  }
1547  }
1548  }
1549  break;
1550  case svDoubleRef :
1551  case svRefList :
1552  {
1553  ScRange aRange;
1554  PopDoubleRef( aRange, nParamCount, nRefInList);
1555  if ( nGlobalError != FormulaError::NONE )
1556  break;
1557  // we need to read row for row, so we can't use ScCellIterator
1558  SCCOL nCol1, nCol2;
1559  SCROW nRow1, nRow2;
1560  SCTAB nTab1, nTab2;
1561  aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
1562  if ( nTab1 != nTab2 )
1563  {
1564  SetError( FormulaError::IllegalParameter);
1565  break;
1566  }
1567  if ( nRow1 > nRow2 )
1568  std::swap( nRow1, nRow2 );
1569  if ( nCol1 > nCol2 )
1570  std::swap( nCol1, nCol2 );
1571  ScAddress aAdr;
1572  aAdr.SetTab( nTab1 );
1573  for ( SCROW nRow = nRow1; nRow <= nRow2; nRow++ )
1574  {
1575  for ( SCCOL nCol = nCol1; nCol <= nCol2; nCol++ )
1576  {
1577  aAdr.SetRow( nRow );
1578  aAdr.SetCol( nCol );
1579  ScRefCellValue aCell( mrDoc, aAdr );
1580  if ( !aCell.isEmpty() )
1581  {
1582  if ( !aCell.hasEmptyValue() )
1583  {
1584  svl::SharedString aSS;
1585  GetCellString( aSS, aCell);
1586  aDelimiters.push_back( aSS.getString());
1587  }
1588  }
1589  else
1590  aDelimiters.emplace_back("" );
1591  }
1592  }
1593  }
1594  break;
1595  case svMatrix :
1596  case svExternalSingleRef:
1597  case svExternalDoubleRef:
1598  {
1599  ScMatrixRef pMat = GetMatrix();
1600  if (pMat)
1601  {
1602  SCSIZE nC, nR;
1603  pMat->GetDimensions(nC, nR);
1604  if (nC == 0 || nR == 0)
1605  SetError(FormulaError::IllegalArgument);
1606  else
1607  {
1608  for (SCSIZE k = 0; k < nR; ++k)
1609  {
1610  for (SCSIZE j = 0; j < nC; ++j)
1611  {
1612  if ( !pMat->IsEmpty( j, k ) )
1613  {
1614  if ( pMat->IsStringOrEmpty( j, k ) )
1615  aDelimiters.push_back( pMat->GetString( j, k ).getString() );
1616  else
1617  {
1618  if ( pMat->IsValue( j, k ) )
1619  aDelimiters.push_back( pMat->GetString( *pFormatter, j, k ).getString() );
1620  }
1621  }
1622  else
1623  aDelimiters.emplace_back("" );
1624  }
1625  }
1626  }
1627  }
1628  }
1629  break;
1630  default:
1631  PopError();
1632  SetError( FormulaError::IllegalArgument);
1633  break;
1634  }
1635  if ( aDelimiters.empty() )
1636  {
1638  return;
1639  }
1640  SCSIZE nSize = aDelimiters.size();
1641  bool bSkipEmpty = static_cast< bool >( GetDouble() );
1642  nParamCount -= 2;
1643 
1644  OUStringBuffer aResBuf;
1645  bool bFirst = true;
1646  SCSIZE nIdx = 0;
1647  nRefInList = 0;
1648  // get the strings to be joined
1649  while ( nParamCount-- > 0 && nGlobalError == FormulaError::NONE )
1650  {
1651  switch ( GetStackType() )
1652  {
1653  case svString:
1654  case svDouble:
1655  {
1656  OUString aStr = GetString().getString();
1657  if ( !aStr.isEmpty() || !bSkipEmpty )
1658  {
1659  if ( !bFirst )
1660  {
1661  aResBuf.append( aDelimiters[ nIdx ] );
1662  if ( nSize > 1 )
1663  {
1664  if ( ++nIdx >= nSize )
1665  nIdx = 0;
1666  }
1667  }
1668  else
1669  bFirst = false;
1670  if (CheckStringResultLen( aResBuf, aStr))
1671  aResBuf.append( aStr );
1672  }
1673  }
1674  break;
1675  case svSingleRef :
1676  {
1677  ScAddress aAdr;
1678  PopSingleRef( aAdr );
1679  if ( nGlobalError != FormulaError::NONE )
1680  break;
1681  ScRefCellValue aCell( mrDoc, aAdr );
1682  OUString aStr;
1683  if ( !aCell.isEmpty() )
1684  {
1685  if ( !aCell.hasEmptyValue() )
1686  {
1687  svl::SharedString aSS;
1688  GetCellString( aSS, aCell);
1689  aStr = aSS.getString();
1690  }
1691  }
1692  else
1693  aStr.clear();
1694  if ( !aStr.isEmpty() || !bSkipEmpty )
1695  {
1696  if ( !bFirst )
1697  {
1698  aResBuf.append( aDelimiters[ nIdx ] );
1699  if ( nSize > 1 )
1700  {
1701  if ( ++nIdx >= nSize )
1702  nIdx = 0;
1703  }
1704  }
1705  else
1706  bFirst = false;
1707  if (CheckStringResultLen( aResBuf, aStr))
1708  aResBuf.append( aStr );
1709  }
1710  }
1711  break;
1712  case svDoubleRef :
1713  case svRefList :
1714  {
1715  ScRange aRange;
1716  PopDoubleRef( aRange, nParamCount, nRefInList);
1717  if ( nGlobalError != FormulaError::NONE )
1718  break;
1719  // we need to read row for row, so we can't use ScCellIterator
1720  SCCOL nCol1, nCol2;
1721  SCROW nRow1, nRow2;
1722  SCTAB nTab1, nTab2;
1723  aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
1724  if ( nTab1 != nTab2 )
1725  {
1726  SetError( FormulaError::IllegalParameter);
1727  break;
1728  }
1729  if ( nRow1 > nRow2 )
1730  std::swap( nRow1, nRow2 );
1731  if ( nCol1 > nCol2 )
1732  std::swap( nCol1, nCol2 );
1733  ScAddress aAdr;
1734  aAdr.SetTab( nTab1 );
1735  OUString aStr;
1736  for ( SCROW nRow = nRow1; nRow <= nRow2; nRow++ )
1737  {
1738  for ( SCCOL nCol = nCol1; nCol <= nCol2; nCol++ )
1739  {
1740  aAdr.SetRow( nRow );
1741  aAdr.SetCol( nCol );
1742  ScRefCellValue aCell( mrDoc, aAdr );
1743  if ( !aCell.isEmpty() )
1744  {
1745  if ( !aCell.hasEmptyValue() )
1746  {
1747  svl::SharedString aSS;
1748  GetCellString( aSS, aCell);
1749  aStr = aSS.getString();
1750  }
1751  }
1752  else
1753  aStr.clear();
1754  if ( !aStr.isEmpty() || !bSkipEmpty )
1755  {
1756  if ( !bFirst )
1757  {
1758  aResBuf.append( aDelimiters[ nIdx ] );
1759  if ( nSize > 1 )
1760  {
1761  if ( ++nIdx >= nSize )
1762  nIdx = 0;
1763  }
1764  }
1765  else
1766  bFirst = false;
1767  if (CheckStringResultLen( aResBuf, aStr))
1768  aResBuf.append( aStr );
1769  }
1770  }
1771  }
1772  }
1773  break;
1774  case svMatrix :
1775  case svExternalSingleRef:
1776  case svExternalDoubleRef:
1777  {
1778  ScMatrixRef pMat = GetMatrix();
1779  if (pMat)
1780  {
1781  SCSIZE nC, nR;
1782  pMat->GetDimensions(nC, nR);
1783  if (nC == 0 || nR == 0)
1784  SetError(FormulaError::IllegalArgument);
1785  else
1786  {
1787  OUString aStr;
1788  for (SCSIZE k = 0; k < nR; ++k)
1789  {
1790  for (SCSIZE j = 0; j < nC; ++j)
1791  {
1792  if ( !pMat->IsEmpty( j, k ) )
1793  {
1794  if ( pMat->IsStringOrEmpty( j, k ) )
1795  aStr = pMat->GetString( j, k ).getString();
1796  else
1797  {
1798  if ( pMat->IsValue( j, k ) )
1799  aStr = pMat->GetString( *pFormatter, j, k ).getString();
1800  }
1801  }
1802  else
1803  aStr.clear();
1804  if ( !aStr.isEmpty() || !bSkipEmpty )
1805  {
1806  if ( !bFirst )
1807  {
1808  aResBuf.append( aDelimiters[ nIdx ] );
1809  if ( nSize > 1 )
1810  {
1811  if ( ++nIdx >= nSize )
1812  nIdx = 0;
1813  }
1814  }
1815  else
1816  bFirst = false;
1817  if (CheckStringResultLen( aResBuf, aStr))
1818  aResBuf.append( aStr );
1819  }
1820  }
1821  }
1822  }
1823  }
1824  }
1825  break;
1826  case svMissing :
1827  {
1828  if ( !bSkipEmpty )
1829  {
1830  if ( !bFirst )
1831  {
1832  aResBuf.append( aDelimiters[ nIdx ] );
1833  if ( nSize > 1 )
1834  {
1835  if ( ++nIdx >= nSize )
1836  nIdx = 0;
1837  }
1838  }
1839  else
1840  bFirst = false;
1841  }
1842  }
1843  break;
1844  default:
1845  PopError();
1846  SetError( FormulaError::IllegalArgument);
1847  break;
1848  }
1849  }
1850  PushString( aResBuf.makeStringAndClear() );
1851 }
1852 
1853 
1855 {
1856  short nParamCount = GetByte();
1857 
1858  ReverseStack( nParamCount );
1859 
1860  nGlobalError = FormulaError::NONE; // propagate only for condition or active result path
1861  bool bFinished = false;
1862  while ( nParamCount > 0 && !bFinished && nGlobalError == FormulaError::NONE )
1863  {
1864  bool bVal = GetBool();
1865  nParamCount--;
1866  if ( bVal )
1867  {
1868  // TRUE
1869  if ( nParamCount < 1 )
1870  {
1871  // no parameter given for THEN
1873  return;
1874  }
1875  bFinished = true;
1876  }
1877  else
1878  {
1879  // FALSE
1880  if ( nParamCount >= 3 )
1881  {
1882  // ELSEIF path
1883  Pop();
1884  nParamCount--;
1885  }
1886  else
1887  {
1888  // no parameter given for ELSE
1889  PushNA();
1890  return;
1891  }
1892  }
1893  }
1894 
1895  if ( nGlobalError != FormulaError::NONE || !bFinished )
1896  {
1897  if ( !bFinished )
1898  PushNA(); // no true expression found
1899  if ( nGlobalError != FormulaError::NONE )
1900  PushNoValue(); // expression returned something other than true or false
1901  return;
1902  }
1903 
1904  //push result :
1905  FormulaConstTokenRef xToken( PopToken() );
1906  if ( xToken )
1907  {
1908  // Remove unused arguments of IFS from the stack before pushing the result.
1909  while ( nParamCount > 1 )
1910  {
1911  Pop();
1912  nParamCount--;
1913  }
1914  PushTokenRef( xToken );
1915  }
1916  else
1917  PushError( FormulaError::UnknownStackVariable );
1918 }
1919 
1920 
1922 {
1923  short nParamCount = GetByte();
1924 
1925  if (!MustHaveParamCountMin( nParamCount, 3))
1926  return;
1927 
1928  ReverseStack( nParamCount );
1929 
1930  nGlobalError = FormulaError::NONE; // propagate only for match or active result path
1931  bool isValue = false;
1932  double fRefVal = 0;
1933  svl::SharedString aRefStr;
1934  switch ( GetStackType() )
1935  {
1936  case svDouble:
1937  isValue = true;
1938  fRefVal = GetDouble();
1939  break;
1940  case svString:
1941  isValue = false;
1942  aRefStr = GetString();
1943  break;
1944  case svSingleRef :
1945  case svDoubleRef :
1946  {
1947  ScAddress aAdr;
1948  if (!PopDoubleRefOrSingleRef( aAdr ))
1949  break;
1950  ScRefCellValue aCell( mrDoc, aAdr );
1951  isValue = !( aCell.hasString() || aCell.hasEmptyValue() || aCell.isEmpty() );
1952  if ( isValue )
1953  fRefVal = GetCellValue( aAdr, aCell);
1954  else
1955  GetCellString( aRefStr, aCell);
1956  }
1957  break;
1958  case svExternalSingleRef:
1959  case svExternalDoubleRef:
1960  case svMatrix:
1961  isValue = ScMatrix::IsValueType( GetDoubleOrStringFromMatrix( fRefVal, aRefStr ) );
1962  break;
1963  default :
1964  PopError();
1966  return;
1967  }
1968  nParamCount--;
1969  bool bFinished = false;
1970  while ( nParamCount > 1 && !bFinished && nGlobalError == FormulaError::NONE )
1971  {
1972  double fVal = 0;
1974  if ( isValue )
1975  fVal = GetDouble();
1976  else
1977  aStr = GetString();
1978  nParamCount--;
1979  if ((nGlobalError != FormulaError::NONE && nParamCount < 2)
1980  || (isValue && rtl::math::approxEqual( fRefVal, fVal))
1981  || (!isValue && aRefStr.getDataIgnoreCase() == aStr.getDataIgnoreCase()))
1982  {
1983  // TRUE
1984  bFinished = true;
1985  }
1986  else
1987  {
1988  // FALSE
1989  if ( nParamCount >= 2 )
1990  {
1991  // ELSEIF path
1992  Pop();
1993  nParamCount--;
1994  // if nParamCount equals 1: default value to be returned
1995  bFinished = ( nParamCount == 1 );
1996  }
1997  else
1998  {
1999  // no parameter given for ELSE
2000  PushNA();
2001  return;
2002  }
2003  nGlobalError = FormulaError::NONE;
2004  }
2005  }
2006 
2007  if ( nGlobalError != FormulaError::NONE || !bFinished )
2008  {
2009  if ( !bFinished )
2010  PushNA(); // no true expression found
2011  else
2013  return;
2014  }
2015 
2016  // push result
2017  FormulaConstTokenRef xToken( PopToken() );
2018  if ( xToken )
2019  {
2020  // Remove unused arguments of SWITCH from the stack before pushing the result.
2021  while ( nParamCount > 1 )
2022  {
2023  Pop();
2024  nParamCount--;
2025  }
2026  PushTokenRef( xToken );
2027  }
2028  else
2029  PushError( FormulaError::UnknownStackVariable );
2030 }
2031 
2032 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
svString
::boost::intrusive_ptr< const FormulaToken > FormulaConstTokenRef
svRefList
OUString getString() const
void ScSwitch_MS()
Definition: interpr8.cxx:1921
static double GetPercentile(::std::vector< double > &rArray, double fPercentile)
Definition: interpr3.cxx:3416
void PushIllegalParameter()
Definition: interpr4.cxx:1914
rtl_uString * getDataIgnoreCase()
bool isEmpty() const
Definition: cellvalue.cxx:670
void ScTextJoin_MS()
Definition: interpr8.cxx:1513
void ReverseStack(sal_uInt8 nParamCount)
Definition: interpr4.cxx:1985
ScMatrixRef GetMatrix()
Definition: interpr5.cxx:462
sal_Int64 n
void PopSingleRef(ScAddress &)
Definition: interpr4.cxx:909
bool IsLeapYear() const
void ScConcat_MS()
Definition: interpr8.cxx:1380
void ScIfs_MS()
Definition: interpr8.cxx:1854
This is very similar to ScCellValue, except that it references the original value instead of copying ...
Definition: cellvalue.hxx:104
double GetCellValue(const ScAddress &, ScRefCellValue &rCell)
Definition: interpr4.cxx:183
double GetDoubleWithDefault(double nDefault)
Definition: interpr4.cxx:2154
bool PopDoubleRefOrSingleRef(ScAddress &rAdr)
Definition: interpr4.cxx:1324
NONE
SvNumberFormatter * pFormatter
Definition: interpre.hxx:207
void PushParameterExpected()
Definition: interpr4.cxx:1909
char sal_uInt16 & nParamCount
Definition: callform.cxx:54
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
ScMatrixRef GetNewMat(SCSIZE nC, SCSIZE nR, bool bEmpty=false)
Definition: interpr5.cxx:299
sal_uInt16 GetMonth() const
#define X
bool hasString() const
Definition: cellvalue.cxx:617
static double gaussinv(double x)
Definition: interpr3.cxx:268
ScETSType
Definition: interpre.hxx:122
svDouble
::boost::intrusive_ptr< ScMatrix > ScMatrixRef
Definition: types.hxx:26
void PushString(const OUString &rStr)
Definition: interpr4.cxx:1801
void SetRow(SCROW nRowP)
Definition: address.hxx:275
bool hasEmptyValue()
Definition: cellvalue.cxx:675
void PushError(FormulaError nError)
Definition: interpr4.cxx:1903
void SetCol(SCCOL nColP)
Definition: address.hxx:279
double GetDouble()
Definition: interpr4.cxx:2073
sal_Int16 GetYear() const
bool MustHaveParamCount(short nAct, short nMust)
Definition: interpre.hxx:1062
void SetTab(SCTAB nTabP)
Definition: address.hxx:283
formula::FormulaConstTokenRef PopToken()
Definition: interpr4.cxx:768
ScMatValType GetDoubleOrStringFromMatrix(double &rDouble, svl::SharedString &rString)
Definition: interpr4.cxx:2411
int i
void PushDouble(double nVal)
Definition: interpr4.cxx:1777
sal_Int16 SCCOL
Definition: types.hxx:22
static bool IsValueType(ScMatValType nType)
Value or boolean.
Definition: scmatrix.hxx:161
void PopDoubleRef(ScRange &rRange, short &rParam, size_t &rRefInList)
If formula::StackVar formula::svDoubleRef pop ScDoubleRefToken and return values of ScComplexRefData...
Definition: interpr4.cxx:1049
bool MustHaveParamCountMin(short nAct, short nMin)
Definition: interpre.hxx:1084
void PushMatrix(const sc::RangeMatrix &rMat)
Definition: interpr4.cxx:1878
svExternalDoubleRef
sal_uInt16 GetDay() const
void GetCellString(svl::SharedString &rStr, ScRefCellValue &rCell)
Definition: interpr4.cxx:250
svExternalSingleRef
FormulaError nGlobalError
Definition: interpre.hxx:212
void GetVars(SCCOL &nCol1, SCROW &nRow1, SCTAB &nTab1, SCCOL &nCol2, SCROW &nRow2, SCTAB &nTab2) const
Definition: address.hxx:693
std::size_t mnCount
formula::StackVar GetStackType()
Stack type with replacement of defaults, e.g. svMissing and formula::svEmptyCell will result in formu...
Definition: interpr4.cxx:1954
double uniform_real_distribution(double a=0.0, double b=1.0)
svSingleRef
#define Y
FormulaError
sal_uInt8 GetByte() const
Definition: interpre.hxx:427
svDoubleRef
void PushIllegalArgument()
Definition: interpr4.cxx:1919
sal_Int32 SCROW
Definition: types.hxx:18
unsigned char sal_uInt8
void ScForecast_Ets(ScETSType eETSType)
Definition: interpr8.cxx:1173
float z
ScDocument & mrDoc
Definition: interpre.hxx:200
svMatrix
int GetError()
svl::SharedString GetString()
Definition: interpr4.cxx:2310
void PushNoValue()
Definition: interpr4.cxx:1929
void PopError()
Definition: interpr4.cxx:756
#define SAL_WARN(area, stream)
bool CheckStringResultLen(OUString &rResult, const OUString &rAdd)
Definition: interpre.hxx:1123
void PushTokenRef(const formula::FormulaConstTokenRef &)
Pushes the token or substitutes with formula::FormulaErrorToken in case nGlobalError is set and the t...
Definition: interpr4.cxx:669
OUString getString(const Any &_rAny)
svMissing
void SetError(FormulaError nError)
Definition: interpre.hxx:1020
aStr
bool GetBool()
Definition: interpre.hxx:445
static bool lcl_SortByX(const DataPoint &lhs, const DataPoint &rhs)
Definition: interpr8.cxx:37
B2DRange maRange
sal_Int16 SCTAB
Definition: types.hxx:23