31 DataPoint(
double rX,
double rY ) :
X( rX ),
Y( rY ) {};
36static bool lcl_SortByX(
const DataPoint &lhs,
const DataPoint &rhs ) {
return lhs.X < rhs.X; }
79class ScETSForecastCalculation
83 std::vector< DataPoint >
maRange;
84 std::unique_ptr<double[]> mpBase;
85 std::unique_ptr<double[]> mpTrend;
86 std::unique_ptr<double[]> mpPerIdx;
87 std::unique_ptr<double[]> mpForecast;
90 double mfAlpha, mfBeta, mfGamma;
105 static constexpr double cfMinABCResolution = 0.001;
106 static const SCSIZE cnScenarios = 1000;
109 void prefillBaseData();
110 bool prefillTrendData();
111 bool prefillPerIdx();
115 void CalcAlphaBetaGamma();
116 void CalcBetaGamma();
118 void calcAccuracyIndicators();
119 void GetForecast(
double fTarget,
double& rForecast );
121 double convertXtoMonths(
double x );
127 bool bDataCompletion,
int nAggregation,
const ScMatrixRef& rTMat,
132 void GetSamplesInPeriod(
double& rVal );
140 : mpFormatter(pFormatter)
147 , mbInitialised(false)
161bool ScETSForecastCalculation::PreprocessDataRange(
const ScMatrixRef& rMatX,
const ScMatrixRef& rMatY,
int nSmplInPrd,
162 bool bDataCompletion,
int nAggregation,
const ScMatrixRef& rTMat,
165 bEDS = ( nSmplInPrd == 0 );
170 maRange.emplace_back( rMatX->GetDouble( i ), rMatY->GetDouble( i ) );
177 if ( rTMat->GetDouble( 0 ) < maRange[ 0 ].X )
180 mnErrorValue = FormulaError::IllegalFPOperation;
186 if ( rTMat->GetDouble( 0 ) < maRange[ mnCount - 1 ].X )
189 mnErrorValue = FormulaError::IllegalFPOperation;
200 Date aNullDate = mpFormatter->GetNullDate();
201 Date aDate = aNullDate +
static_cast< sal_Int32
>(
maRange[ 0 ].X );
202 mnMonthDay = aDate.
GetDay();
205 Date aDate1 = aNullDate +
static_cast< sal_Int32
>(
maRange[
i ].X );
206 if ( aDate != aDate1 )
208 if ( aDate1.
GetDay() != mnMonthDay )
213 mfStepSize = ::std::numeric_limits<double>::max();
218 aDate = aNullDate +
static_cast< sal_Int32
>(
maRange[
i ].X );
227 if ( nAggregation == 0 )
230 mnErrorValue = FormulaError::NoValue;
235 switch ( nAggregation )
238 while ( i < mnCount && maRange[ i ].X == maRange[ i - 1 ].X )
245 while ( i < mnCount && maRange[ i ].X == maRange[ i - 1 ].X )
256 while ( i < mnCount && maRange[ i ].X == maRange[ i - 1 ].X )
266 while ( i < mnCount && maRange[ i ].X == maRange[ i - 1 ].X )
268 if ( maRange[ i ].Y > fTmp )
278 std::vector< double > aTmp {
maRange[
i - 1 ].Y };
279 while ( i < mnCount && maRange[ i ].X == maRange[ i - 1 ].X )
281 aTmp.push_back( maRange[ i ].Y );
286 sort( aTmp.begin(), aTmp.end() );
289 maRange[
i - 1 ].Y = aTmp[ nCounter / 2 ];
291 maRange[
i - 1 ].Y = ( aTmp[ nCounter / 2 ] + aTmp[ nCounter / 2 - 1 ] ) / 2.0;
296 while ( i < mnCount && maRange[ i ].X == maRange[ i - 1 ].X )
298 if ( maRange[ i ].Y < fTmp )
306 if ( i < mnCount - 1 )
311 if ( fStep > 0 && fStep < mfStepSize )
316 bool bHasGap =
false;
321 if ( fStep != mfStepSize )
323 if ( fmod( fStep, mfStepSize ) != 0.0 )
326 mnErrorValue = FormulaError::NoValue;
336 SCSIZE nMissingXCount = 0;
337 double fOriginalCount =
static_cast< double >(
mnCount );
339 aDate = aNullDate +
static_cast< sal_Int32
>(
maRange[ 0 ].X );
345 Date aDate1 = aNullDate +
static_cast< sal_Int32
>(
maRange[
i ].X );
352 if ( fDist > mfStepSize )
356 for (
KahanSum fXGap = maRange[ i - 1].X + mfStepSize; fXGap <
maRange[
i ].X; fXGap += mfStepSize )
358 maRange.insert(
maRange.begin() +
i, DataPoint( fXGap.get(), ( bDataCompletion ? fYGap : 0.0 ) ) );
362 if (
static_cast< double >( nMissingXCount ) / fOriginalCount > 0.3 )
365 mnErrorValue = FormulaError::NoValue;
373 if ( nSmplInPrd != 1 )
374 mnSmplInPrd = nSmplInPrd;
377 mnSmplInPrd = CalcPeriodLen();
378 if ( mnSmplInPrd == 1 )
388bool ScETSForecastCalculation::initData( )
391 mpBase.reset(
new double[ mnCount ] );
392 mpTrend.reset(
new double[ mnCount ] );
394 mpPerIdx.reset(
new double[ mnCount ] );
395 mpForecast.reset(
new double[ mnCount ] );
396 mpForecast[ 0 ] =
maRange[ 0 ].Y;
398 if ( prefillTrendData() )
400 if ( prefillPerIdx() )
409bool ScETSForecastCalculation::prefillTrendData()
416 if ( mnCount < 2 * mnSmplInPrd )
418 mnErrorValue = FormulaError::NoValue;
423 for (
SCSIZE i = 0;
i < mnSmplInPrd;
i++ )
425 fSum +=
maRange[
i + mnSmplInPrd ].Y;
428 double fTrend = fSum.
get() /
static_cast< double >( mnSmplInPrd * mnSmplInPrd );
430 mpTrend[ 0 ] = fTrend;
436bool ScETSForecastCalculation::prefillPerIdx()
441 if ( mnSmplInPrd == 0 )
444 mnErrorValue = FormulaError::UnknownState;
448 std::vector< KahanSum > aPeriodAverage( nPeriods, 0.0 );
449 for (
SCSIZE i = 0;
i < nPeriods ;
i++ )
451 for (
SCSIZE j = 0; j < mnSmplInPrd; j++ )
452 aPeriodAverage[ i ] += maRange[ i * mnSmplInPrd + j ].Y;
453 aPeriodAverage[
i ] /=
static_cast< double >( mnSmplInPrd );
454 if ( aPeriodAverage[ i ] == 0.0 )
456 SAL_WARN(
"sc.core",
"prefillPerIdx(), average of 0 will cause divide by zero error, quitting calculation" );
457 mnErrorValue = FormulaError::DivisionByZero;
462 for (
SCSIZE j = 0; j < mnSmplInPrd; j++ )
465 for (
SCSIZE i = 0;
i < nPeriods ;
i++ )
469 fI +=
maRange[
i * mnSmplInPrd + j ].Y -
470 ( aPeriodAverage[
i ].get() + (
static_cast< double >( j ) - 0.5 * ( mnSmplInPrd - 1 ) ) *
473 fI +=
maRange[
i * mnSmplInPrd + j ].Y /
474 ( aPeriodAverage[
i ].get() + (
static_cast< double >( j ) - 0.5 * ( mnSmplInPrd - 1 ) ) *
477 mpPerIdx[ j ] = fI.
get() / nPeriods;
479 if (mnSmplInPrd < mnCount)
480 mpPerIdx[mnSmplInPrd] = 0.0;
485void ScETSForecastCalculation::prefillBaseData()
490 mpBase[ 0 ] =
maRange[ 0 ].Y / mpPerIdx[ 0 ];
493void ScETSForecastCalculation::initCalc()
495 if ( !mbInitialised )
497 CalcAlphaBetaGamma();
499 mbInitialised =
true;
500 calcAccuracyIndicators();
504void ScETSForecastCalculation::calcAccuracyIndicators()
513 double fError = mpForecast[
i ] -
maRange[
i ].Y;
514 fSumAbsErr += fabs( fError );
515 fSumErrSq += fError * fError;
516 fSumAbsPercErr += fabs( fError ) / ( fabs( mpForecast[ i ] ) + fabs( maRange[ i ].Y ) );
520 fSumDivisor += fabs( maRange[ i ].Y - maRange[ i - 1 ].Y );
523 mfMAE = fSumAbsErr.
get() / nCalcCount;
524 mfMASE = fSumAbsErr.
get() / ( nCalcCount * fSumDivisor.
get() / ( nCalcCount - 1 ) );
525 mfMSE = fSumErrSq.
get() / nCalcCount;
526 mfRMSE = sqrt( mfMSE );
527 mfSMAPE = fSumAbsPercErr.
get() * 2.0 / nCalcCount;
538SCSIZE ScETSForecastCalculation::CalcPeriodLen()
541 double fBestME = ::std::numeric_limits<double>::max();
543 for (
SCSIZE nPeriodLen = mnCount / 2; nPeriodLen >= 1; nPeriodLen-- )
550 fMeanError += fabs( ( maRange[ i ].Y - maRange[ i - 1 ].Y ) -
551 ( maRange[ nPeriodLen + i ].Y - maRange[ nPeriodLen + i - 1 ].Y ) );
553 double fMeanErrorGet = fMeanError.
get();
554 fMeanErrorGet /=
static_cast< double >( ( nPeriods - 1 ) * nPeriodLen - 1 );
556 if ( fMeanErrorGet <= fBestME || fMeanErrorGet == 0.0 )
558 nBestVal = nPeriodLen;
559 fBestME = fMeanErrorGet;
565void ScETSForecastCalculation::CalcAlphaBetaGamma()
596 if ( fE0 == mfMSE && mfMSE == fE2 )
606 while ( ( f2 - f1 ) > cfMinABCResolution )
612 f1 = ( f0 + f1 ) / 2;
618 f1 = ( f1 + f2 ) / 2;
651 calcAccuracyIndicators();
654void ScETSForecastCalculation::CalcBetaGamma()
673 if ( fE0 == mfMSE && mfMSE == fE2 )
680 while ( ( f2 - f1 ) > cfMinABCResolution )
686 f1 = ( f0 + f1 ) / 2;
692 f1 = ( f1 + f2 ) / 2;
718void ScETSForecastCalculation::CalcGamma()
734 if ( fE0 == mfMSE && mfMSE == fE2 )
740 while ( ( f2 - f1 ) > cfMinABCResolution )
746 f1 = ( f0 + f1 ) / 2;
752 f1 = ( f1 + f2 ) / 2;
775void ScETSForecastCalculation::refill()
785 ( 1 - mfAlpha ) * ( mpBase[ i - 1 ] + mpTrend[ i - 1 ] );
786 mpTrend[
i ] = mfGamma * ( mpBase[
i ] - mpBase[
i - 1 ] ) +
787 ( 1 - mfGamma ) * mpTrend[
i - 1 ];
788 mpForecast[
i ] = mpBase[
i - 1 ] + mpTrend[
i - 1 ];
795 nIdx = (
i > mnSmplInPrd ?
i - mnSmplInPrd :
i );
796 mpBase[
i ] = mfAlpha * (
maRange[
i ].Y - mpPerIdx[ nIdx ] ) +
797 ( 1 - mfAlpha ) * ( mpBase[
i - 1 ] + mpTrend[
i - 1 ] );
798 mpPerIdx[
i ] = mfBeta * (
maRange[
i ].Y - mpBase[
i ] ) +
799 ( 1 - mfBeta ) * mpPerIdx[ nIdx ];
803 nIdx = (
i >= mnSmplInPrd ?
i - mnSmplInPrd :
i );
804 mpBase[
i ] = mfAlpha * (
maRange[
i ].Y / mpPerIdx[ nIdx ] ) +
805 ( 1 - mfAlpha ) * ( mpBase[
i - 1 ] + mpTrend[
i - 1 ] );
806 mpPerIdx[
i ] = mfBeta * (
maRange[
i ].Y / mpBase[
i ] ) +
807 ( 1 - mfBeta ) * mpPerIdx[ nIdx ];
809 mpTrend[
i ] = mfGamma * ( mpBase[
i ] - mpBase[
i - 1 ] ) +
810 ( 1 - mfGamma ) * mpTrend[
i - 1 ];
813 mpForecast[
i ] = mpBase[
i - 1 ] + mpTrend[
i - 1 ] + mpPerIdx[ nIdx ];
815 mpForecast[
i ] = ( mpBase[
i - 1 ] + mpTrend[
i - 1 ] ) * mpPerIdx[ nIdx ];
818 calcAccuracyIndicators();
821double ScETSForecastCalculation::convertXtoMonths(
double x )
823 Date aDate = mpFormatter->GetNullDate() +
static_cast< sal_Int32
>(
x );
839 fMonthLength = ( aDate.
IsLeapYear() ? 29.0 : 28.0 );
844 return ( 12.0 * nYear + nMonth + ( aDate.
GetDay() - mnMonthDay ) / fMonthLength );
847void ScETSForecastCalculation::GetForecast(
double fTarget,
double& rForecast )
851 if ( fTarget <= maRange[ mnCount - 1 ].X )
854 double fInterpolate = fmod( fTarget - maRange[ 0 ].X, mfStepSize );
857 if ( fInterpolate >= cfMinABCResolution )
859 double fInterpolateFactor = fInterpolate / mfStepSize;
860 double fFc_1 = mpForecast[
n + 1 ];
861 rForecast = rForecast + fInterpolateFactor * ( fFc_1 - rForecast );
867 double fInterpolate = fmod( fTarget - maRange[ mnCount - 1 ].X, mfStepSize );
871 else if ( bAdditive )
873 mpPerIdx[
mnCount - 1 - mnSmplInPrd + (
n % mnSmplInPrd ) ];
876 mpPerIdx[ mnCount - 1 - mnSmplInPrd + ( n % mnSmplInPrd ) ];
878 if ( fInterpolate >= cfMinABCResolution )
880 double fInterpolateFactor = fInterpolate / mfStepSize;
883 fFc_1 = mpBase[
mnCount - 1 ] + (
n + 1 ) * mpTrend[ mnCount - 1 ];
884 else if ( bAdditive )
885 fFc_1 = mpBase[
mnCount - 1 ] + (
n + 1 ) * mpTrend[ mnCount - 1 ] +
886 mpPerIdx[ mnCount - 1 - mnSmplInPrd + ( ( n + 1 ) % mnSmplInPrd ) ];
888 fFc_1 = ( mpBase[
mnCount - 1 ] + (
n + 1 ) * mpTrend[ mnCount - 1 ] ) *
889 mpPerIdx[
mnCount - 1 - mnSmplInPrd + ( (
n + 1 ) % mnSmplInPrd ) ];
890 rForecast = rForecast + fInterpolateFactor * ( fFc_1 - rForecast );
898 rTMat->GetDimensions( nC, nR );
902 for (
SCSIZE j = 0; j < nC; j++ )
906 fTarget = convertXtoMonths( rTMat->GetDouble( j, i ) );
908 fTarget = rTMat->GetDouble( j, i );
910 GetForecast( fTarget, fForecast );
911 rFcMat->PutDouble( fForecast, j, i );
916void ScETSForecastCalculation::GetStatisticValue(
const ScMatrixRef& rTypeMat,
const ScMatrixRef& rStatMat )
921 rTypeMat->GetDimensions( nC, nR );
924 for (
SCSIZE j = 0; j < nC; j++ )
926 switch (
static_cast< int >( rTypeMat->GetDouble( j, i ) ) )
929 rStatMat->PutDouble( mfAlpha, j, i );
932 rStatMat->PutDouble( mfGamma, j, i );
935 rStatMat->PutDouble( mfBeta, j, i );
938 rStatMat->PutDouble( mfMASE, j, i );
941 rStatMat->PutDouble( mfSMAPE, j, i );
944 rStatMat->PutDouble( mfMAE, j, i );
947 rStatMat->PutDouble( mfRMSE, j, i );
950 rStatMat->PutDouble( mfStepSize, j, i );
953 rStatMat->PutDouble( mnSmplInPrd, j, i );
960void ScETSForecastCalculation::GetSamplesInPeriod(
double& rVal )
965double ScETSForecastCalculation::RandDev()
969 ::comphelper::rng::uniform_real_distribution( 0.5, 1.0 ) ) );
972void ScETSForecastCalculation::GetETSPredictionIntervals(
const ScMatrixRef& rTMat,
const ScMatrixRef& rPIMat,
double fPILevel )
977 rTMat->GetDimensions( nC, nR );
980 double fMaxTarget = rTMat->GetDouble( 0, 0 );
983 for (
SCSIZE j = 0; j < nC; j++ )
985 if ( fMaxTarget < rTMat->GetDouble( j, i ) )
986 fMaxTarget = rTMat->GetDouble( j, i );
990 fMaxTarget = convertXtoMonths( fMaxTarget ) -
maRange[
mnCount - 1 ].X;
993 SCSIZE nSize = fMaxTarget / mfStepSize;
994 if ( fmod( fMaxTarget, mfStepSize ) != 0.0 )
999 mnErrorValue = FormulaError::IllegalArgument;
1003 std::unique_ptr< double[] > xScenRange(
new double[nSize]);
1004 std::unique_ptr< double[] > xScenBase(
new double[nSize]);
1005 std::unique_ptr< double[] > xScenTrend(
new double[nSize]);
1006 std::unique_ptr< double[] > xScenPerIdx(
new double[nSize]);
1007 std::vector< std::vector< double > > aPredictions( nSize, std::vector< double >( cnScenarios ) );
1010 for (
SCSIZE k = 0; k < cnScenarios; k++ )
1015 double nPIdx = !bEDS ? mpPerIdx[
mnCount - mnSmplInPrd] : 0.0;
1017 xScenRange[ 0 ] = mpBase[
mnCount - 1 ] + mpTrend[
mnCount - 1 ] +
1020 aPredictions[ 0 ][ k ] = xScenRange[ 0 ];
1021 xScenBase[ 0 ] = mfAlpha * ( xScenRange[ 0 ] - nPIdx ) +
1022 ( 1 - mfAlpha ) * ( mpBase[
mnCount - 1 ] + mpTrend[
mnCount - 1 ] );
1023 xScenTrend[ 0 ] = mfGamma * ( xScenBase[ 0 ] - mpBase[
mnCount - 1 ] ) +
1024 ( 1 - mfGamma ) * mpTrend[
mnCount - 1 ];
1025 xScenPerIdx[ 0 ] = mfBeta * ( xScenRange[ 0 ] - xScenBase[ 0 ] ) +
1026 ( 1 - mfBeta ) * nPIdx;
1027 for (
SCSIZE i = 1;
i < nSize;
i++ )
1030 if ( i < mnSmplInPrd )
1031 fPerIdx = mpPerIdx[
mnCount +
i - mnSmplInPrd ];
1033 fPerIdx = xScenPerIdx[
i - mnSmplInPrd ];
1034 xScenRange[
i ] = xScenBase[
i - 1 ] + xScenTrend[
i - 1 ] + fPerIdx + RandDev();
1035 aPredictions[
i ][ k ] = xScenRange[
i ];
1036 xScenBase[
i ] = mfAlpha * ( xScenRange[
i ] - fPerIdx ) +
1037 ( 1 - mfAlpha ) * ( xScenBase[
i - 1 ] + xScenTrend[
i - 1 ] );
1038 xScenTrend[
i ] = mfGamma * ( xScenBase[
i ] - xScenBase[
i - 1 ] ) +
1039 ( 1 - mfGamma ) * xScenTrend[
i - 1 ];
1040 xScenPerIdx[
i ] = mfBeta * ( xScenRange[
i ] - xScenBase[
i ] ) +
1041 ( 1 - mfBeta ) * fPerIdx;
1047 xScenRange[ 0 ] = ( mpBase[
mnCount - 1 ] + mpTrend[
mnCount - 1 ] ) *
1048 mpPerIdx[ mnCount - mnSmplInPrd ] +
1050 aPredictions[ 0 ][ k ] = xScenRange[ 0 ];
1051 xScenBase[ 0 ] = mfAlpha * ( xScenRange[ 0 ] / mpPerIdx[
mnCount - mnSmplInPrd ] ) +
1052 ( 1 - mfAlpha ) * ( mpBase[
mnCount - 1 ] + mpTrend[
mnCount - 1 ] );
1053 xScenTrend[ 0 ] = mfGamma * ( xScenBase[ 0 ] - mpBase[
mnCount - 1 ] ) +
1054 ( 1 - mfGamma ) * mpTrend[
mnCount - 1 ];
1055 xScenPerIdx[ 0 ] = mfBeta * ( xScenRange[ 0 ] / xScenBase[ 0 ] ) +
1056 ( 1 - mfBeta ) * mpPerIdx[
mnCount - mnSmplInPrd ];
1057 for (
SCSIZE i = 1;
i < nSize;
i++ )
1060 if ( i < mnSmplInPrd )
1061 fPerIdx = mpPerIdx[
mnCount +
i - mnSmplInPrd ];
1063 fPerIdx = xScenPerIdx[
i - mnSmplInPrd ];
1064 xScenRange[
i ] = ( xScenBase[
i - 1 ] + xScenTrend[
i - 1 ] ) * fPerIdx + RandDev();
1065 aPredictions[
i ][ k ] = xScenRange[
i ];
1066 xScenBase[
i ] = mfAlpha * ( xScenRange[
i ] / fPerIdx ) +
1067 ( 1 - mfAlpha ) * ( xScenBase[
i - 1 ] + xScenTrend[
i - 1 ] );
1068 xScenTrend[
i ] = mfGamma * ( xScenBase[
i ] - xScenBase[
i - 1 ] ) +
1069 ( 1 - mfGamma ) * xScenTrend[
i - 1 ];
1070 xScenPerIdx[
i ] = mfBeta * ( xScenRange[
i ] / xScenBase[
i ] ) +
1071 ( 1 - mfBeta ) * fPerIdx;
1077 std::unique_ptr< double[] > xPercentile(
new double[nSize]);
1078 for (
SCSIZE i = 0;
i < nSize;
i++ )
1086 for (
SCSIZE j = 0; j < nC; j++ )
1090 fTarget = convertXtoMonths( rTMat->GetDouble( j, i ) ) -
maRange[
mnCount - 1 ].X;
1093 SCSIZE nSteps = ( fTarget / mfStepSize ) - 1;
1094 double fFactor = fmod( fTarget, mfStepSize );
1095 double fPI = xPercentile[ nSteps ];
1096 if ( fFactor != 0.0 )
1099 double fPI1 = xPercentile[ nSteps + 1 ];
1100 fPI = fPI + fFactor * ( fPI1 - fPI );
1102 rPIMat->PutDouble( fPI, j, i );
1108void ScETSForecastCalculation::GetEDSPredictionIntervals(
const ScMatrixRef& rTMat,
const ScMatrixRef& rPIMat,
double fPILevel )
1113 rTMat->GetDimensions( nC, nR );
1116 double fMaxTarget = rTMat->GetDouble( 0, 0 );
1119 for (
SCSIZE j = 0; j < nC; j++ )
1121 if ( fMaxTarget < rTMat->GetDouble( j, i ) )
1122 fMaxTarget = rTMat->GetDouble( j, i );
1126 fMaxTarget = convertXtoMonths( fMaxTarget ) -
maRange[
mnCount - 1 ].X;
1129 SCSIZE nSize = fMaxTarget / mfStepSize;
1130 if ( fmod( fMaxTarget, mfStepSize ) != 0.0 )
1135 mnErrorValue = FormulaError::IllegalArgument;
1140 double o = 1 - fPILevel;
1141 std::vector< double > c( nSize );
1142 for (
SCSIZE i = 0;
i < nSize;
i++ )
1144 c[
i ] = sqrt( 1 + ( fPILevel / pow( 1 + o, 3.0 ) ) *
1145 ( ( 1 + 4 * o + 5 * o * o ) +
1146 2 *
static_cast< double >( i ) * fPILevel * ( 1 + 3 * o ) +
1147 2 *
static_cast< double >( i * i ) * fPILevel * fPILevel ) );
1153 for (
SCSIZE j = 0; j < nC; j++ )
1157 fTarget = convertXtoMonths( rTMat->GetDouble( j, i ) ) -
maRange[
mnCount - 1 ].X;
1160 SCSIZE nSteps = ( fTarget / mfStepSize ) - 1;
1161 double fFactor = fmod( fTarget, mfStepSize );
1162 double fPI =
z * mfRMSE * c[ nSteps ] / c[ 0 ];
1163 if ( fFactor != 0.0 )
1166 double fPI1 =
z * mfRMSE * c[ nSteps + 1 ] / c[ 0 ];
1167 fPI = fPI + fFactor * ( fPI1 - fPI );
1169 rPIMat->PutDouble( fPI, j, i );
1202 ( nParamCount == 4 && eETSType ==
etsSeason ) ||
1207 if ( nAggregation < 1 || nAggregation > 7 )
1213 bool bDataCompletion;
1215 ( nParamCount >= 3 && eETSType ==
etsSeason ) ||
1219 if ( nTemp == 0 || nTemp == 1 )
1220 bDataCompletion = nTemp;
1228 bDataCompletion =
true;
1236 if ( fmod( fVal, 1.0 ) != 0 || fVal < 0.0 )
1238 PushError( FormulaError::IllegalFPOperation );
1241 nSmplInPrd =
static_cast< int >( fVal );
1247 double fPILevel = 0.0;
1248 if ( nParamCount < 3 && ( nParamCount != 2 || eETSType !=
etsSeason ) )
1257 if ( fPILevel < 0 || fPILevel > 1 )
1269 pTypeMat->GetDimensions( nC, nR );
1272 for (
SCSIZE j = 0; j < nC; j++ )
1274 if (
static_cast< int >( pTypeMat->GetDouble( j,
i ) ) < 1 ||
1275 static_cast< int >( pTypeMat->GetDouble( j,
i ) ) > 9 )
1286 if ( !pMatX || !pMatY )
1293 pMatX->GetDimensions( nCX, nRX );
1294 pMatY->GetDimensions( nCY, nRY );
1295 if ( nRX != nRY || nCX != nCY ||
1296 !pMatX->IsNumeric() || !pMatY->IsNumeric() )
1313 ScETSForecastCalculation aETSCalc( pMatX->GetElementCount(),
pFormatter );
1314 if ( !aETSCalc.PreprocessDataRange( pMatX, pMatY, nSmplInPrd, bDataCompletion,
1329 pTMat->GetDimensions( nC, nR );
1331 aETSCalc.GetForecastRange( pTMat, pFcMat );
1332 if (aETSCalc.GetError() != FormulaError::NONE)
1342 pTMat->GetDimensions( nC, nR );
1344 if ( nSmplInPrd == 0 )
1346 aETSCalc.GetEDSPredictionIntervals( pTMat, pPIMat, fPILevel );
1350 aETSCalc.GetETSPredictionIntervals( pTMat, pPIMat, fPILevel );
1352 if (aETSCalc.GetError() != FormulaError::NONE)
1362 pTypeMat->GetDimensions( nC, nR );
1364 aETSCalc.GetStatisticValue( pTypeMat, pStatMat );
1365 if (aETSCalc.GetError() != FormulaError::NONE)
1374 aETSCalc.GetSamplesInPeriod( rVal );
1384 OUStringBuffer aResBuf;
1385 short nParamCount =
GetByte();
1390 size_t nRefInList = 0;
1391 while ( nParamCount-- > 0 &&
nGlobalError == FormulaError::NONE )
1400 aResBuf.append(
aStr);
1416 aResBuf.append( rStr);
1431 aRange.
GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
1432 if ( nTab1 != nTab2 )
1434 SetError( FormulaError::IllegalParameter);
1441 for (
SCROW nRow = nRow1; nRow <= nRow2; nRow++ )
1443 for (
SCCOL nCol = nCol1; nCol <= nCol2; nCol++ )
1454 aResBuf.append( rStr);
1468 pMat->GetDimensions(nC, nR);
1469 if (nC == 0 || nR == 0)
1470 SetError(FormulaError::IllegalArgument);
1473 for (
SCSIZE k = 0; k < nR; ++k)
1475 for (
SCSIZE j = 0; j < nC; ++j)
1477 if ( pMat->IsStringOrEmpty( j, k ) )
1479 OUString
aStr = pMat->GetString( j, k ).getString();
1481 aResBuf.append(
aStr);
1485 if ( pMat->IsValue( j, k ) )
1487 OUString
aStr = pMat->GetString( *
pFormatter, j, k ).getString();
1489 aResBuf.append(
aStr);
1500 SetError( FormulaError::IllegalArgument);
1509 short nParamCount =
GetByte();
1518 std::vector< OUString > aDelimiters;
1519 size_t nRefInList = 0;
1534 aDelimiters.emplace_back(
"");
1539 aDelimiters.push_back( aSS.
getString());
1554 aRange.
GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
1555 if ( nTab1 != nTab2 )
1557 SetError( FormulaError::IllegalParameter);
1564 for (
SCROW nRow = nRow1; nRow <= nRow2; nRow++ )
1566 for (
SCCOL nCol = nCol1; nCol <= nCol2; nCol++ )
1572 aDelimiters.emplace_back(
"");
1577 aDelimiters.push_back( aSS.
getString());
1591 pMat->GetDimensions(nC, nR);
1592 if (nC == 0 || nR == 0)
1593 SetError(FormulaError::IllegalArgument);
1596 for (
SCSIZE k = 0; k < nR; ++k)
1598 for (
SCSIZE j = 0; j < nC; ++j)
1600 if (pMat->IsEmpty( j, k ))
1601 aDelimiters.emplace_back(
"");
1602 else if (pMat->IsStringOrEmpty( j, k ))
1603 aDelimiters.push_back( pMat->GetString( j, k ).getString() );
1604 else if (pMat->IsValue( j, k ))
1605 aDelimiters.push_back( pMat->GetString( *
pFormatter, j, k ).getString() );
1608 assert(!
"should this really happen?");
1609 aDelimiters.emplace_back(
"");
1619 SetError( FormulaError::IllegalArgument);
1622 if ( aDelimiters.empty() )
1627 SCSIZE nSize = aDelimiters.size();
1628 bool bSkipEmpty =
static_cast< bool >(
GetDouble() );
1631 OUStringBuffer aResBuf;
1636 while ( nParamCount-- > 0 &&
nGlobalError == FormulaError::NONE )
1644 if ( !
aStr.isEmpty() || !bSkipEmpty )
1648 aResBuf.append( aDelimiters[ nIdx ] );
1651 if ( ++nIdx >= nSize )
1658 aResBuf.append(
aStr );
1676 if ( !
aStr.isEmpty() || !bSkipEmpty )
1680 aResBuf.append( aDelimiters[ nIdx ] );
1683 if ( ++nIdx >= nSize )
1690 aResBuf.append(
aStr );
1705 aRange.
GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
1706 if ( nTab1 != nTab2 )
1708 SetError( FormulaError::IllegalParameter);
1716 for (
SCROW nRow = nRow1; nRow <= nRow2; nRow++ )
1718 for (
SCCOL nCol = nCol1; nCol <= nCol2; nCol++ )
1731 if ( !
aStr.isEmpty() || !bSkipEmpty )
1735 aResBuf.append( aDelimiters[ nIdx ] );
1738 if ( ++nIdx >= nSize )
1745 aResBuf.append(
aStr );
1759 pMat->GetDimensions(nC, nR);
1760 if (nC == 0 || nR == 0)
1761 SetError(FormulaError::IllegalArgument);
1765 for (
SCSIZE k = 0; k < nR; ++k)
1767 for (
SCSIZE j = 0; j < nC; ++j)
1769 if (pMat->IsEmpty( j, k ) )
1771 else if (pMat->IsStringOrEmpty( j, k ))
1772 aStr = pMat->GetString( j, k ).getString();
1773 else if (pMat->IsValue( j, k ))
1777 assert(!
"should this really happen?");
1780 if ( !
aStr.isEmpty() || !bSkipEmpty )
1784 aResBuf.append( aDelimiters[ nIdx ] );
1787 if ( ++nIdx >= nSize )
1794 aResBuf.append(
aStr );
1808 aResBuf.append( aDelimiters[ nIdx ] );
1811 if ( ++nIdx >= nSize )
1822 SetError( FormulaError::IllegalArgument);
1832 short nParamCount =
GetByte();
1837 bool bFinished =
false;
1838 while ( nParamCount > 0 && !bFinished &&
nGlobalError == FormulaError::NONE )
1845 if ( nParamCount < 1 )
1856 if ( nParamCount >= 3 )
1871 if (
nGlobalError != FormulaError::NONE || !bFinished )
1885 while ( nParamCount > 1 )
1893 PushError( FormulaError::UnknownStackVariable );
1899 short nParamCount =
GetByte();
1907 bool isValue =
false;
1945 bool bFinished =
false;
1946 while ( nParamCount > 1 && !bFinished &&
nGlobalError == FormulaError::NONE )
1955 if ((
nGlobalError != FormulaError::NONE && nParamCount < 2)
1956 || (isValue && rtl::math::approxEqual( fRefVal, fVal))
1965 if ( nParamCount >= 2 )
1971 bFinished = ( nParamCount == 1 );
1983 if (
nGlobalError != FormulaError::NONE || !bFinished )
1997 while ( nParamCount > 1 )
2005 PushError( FormulaError::UnknownStackVariable );
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 ...
void PutInOrder(T &nStart, T &nEnd)
sal_Int16 GetYear() const
sal_uInt16 GetDay() const
sal_uInt16 GetMonth() const
This class provides LO with Kahan summation algorithm About this algorithm: https://en....
double get() const
Returns the final sum.
formula::FormulaConstTokenRef PopToken()
void SetError(FormulaError nError)
svl::SharedString GetString()
bool MustHaveParamCount(short nAct, short nMust)
bool MustHaveParamCountMin(short nAct, short nMin)
void PushIllegalParameter()
FormulaError nGlobalError
void PushIllegalArgument()
void GetCellString(svl::SharedString &rStr, ScRefCellValue &rCell)
bool PopDoubleRefOrSingleRef(ScAddress &rAdr)
void PushError(FormulaError nError)
sal_uInt8 GetByte() const
void ScForecast_Ets(ScETSType eETSType)
bool CheckStringResultLen(OUString &rResult, sal_Int32 nIncrease)
ScMatrixRef GetNewMat(SCSIZE nC, SCSIZE nR, bool bEmpty=false)
ScMatValType GetDoubleOrStringFromMatrix(double &rDouble, svl::SharedString &rString)
void PushDouble(double nVal)
void PopSingleRef(ScAddress &)
void ReverseStack(sal_uInt8 nParamCount)
SvNumberFormatter * pFormatter
void PushParameterExpected()
void PopDoubleRef(ScRange &rRange, short &rParam, size_t &rRefInList)
If formula::StackVar formula::svDoubleRef pop ScDoubleRefToken and return values of ScComplexRefData.
void PushTokenRef(const formula::FormulaConstTokenRef &)
Pushes the token or substitutes with formula::FormulaErrorToken in case nGlobalError is set and the t...
void PushMatrix(const sc::RangeMatrix &rMat)
double GetCellValue(const ScAddress &, ScRefCellValue &rCell)
double GetDoubleWithDefault(double nDefault)
static double GetPercentile(::std::vector< double > &rArray, double fPercentile)
formula::StackVar GetStackType()
Stack type with replacement of defaults, e.g. svMissing and formula::svEmptyCell will result in formu...
static double gaussinv(double x)
void PushString(const OUString &rStr)
static bool IsValueType(ScMatValType nType)
Value or boolean.
void GetVars(SCCOL &nCol1, SCROW &nRow1, SCTAB &nTab1, SCCOL &nCol2, SCROW &nRow2, SCTAB &nTab2) const
const OUString & getString() const
rtl_uString * getDataIgnoreCase()
static bool lcl_SortByX(const DataPoint &lhs, const DataPoint &rhs)
#define SAL_WARN(area, stream)
OUString getString(const Any &_rAny)
This is very similar to ScCellValue, except that it references the original value instead of copying ...
::boost::intrusive_ptr< ScMatrix > ScMatrixRef