diff options
author | Winfried Donkers <winfrieddonkers@libreoffice.org> | 2016-12-31 16:24:27 +0100 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2017-01-03 20:30:48 +0000 |
commit | 482db19e3c792892c536898408dd7da98265073a (patch) | |
tree | b690e82db0a758d2c8b46e23c77eacf23dd2ac64 /sc | |
parent | 7e7fcb7ee614be44589d0ca90e7785a4efcf1457 (diff) |
tdf#105019 fix POISSON/POISSON.DIST deficiencies.
Apply constraint lambda > 0.
For POISSON.DIST all 3 arguments are mandatory.
Change-Id: Ica056a2b315c10f0a22dd105c121d8ce97ea1717
Reviewed-on: https://gerrit.libreoffice.org/32538
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Eike Rathke <erack@redhat.com>
Diffstat (limited to 'sc')
-rw-r--r-- | sc/source/core/inc/interpre.hxx | 2 | ||||
-rw-r--r-- | sc/source/core/tool/interpr3.cxx | 60 | ||||
-rw-r--r-- | sc/source/core/tool/interpr4.cxx | 4 |
3 files changed, 28 insertions, 38 deletions
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx index b093fec2e839..2a810abd301f 100644 --- a/sc/source/core/inc/interpre.hxx +++ b/sc/source/core/inc/interpre.hxx @@ -861,7 +861,7 @@ void ScGammaDist( bool bODFF ); void ScGammaInv(); void ScExpDist(); void ScBinomDist(); -void ScPoissonDist(); +void ScPoissonDist( bool bODFF ); void ScCombin(); void ScCombinA(); void ScPermut(); diff --git a/sc/source/core/tool/interpr3.cxx b/sc/source/core/tool/interpr3.cxx index 1b6a367d42b5..205e1aae708a 100644 --- a/sc/source/core/tool/interpr3.cxx +++ b/sc/source/core/tool/interpr3.cxx @@ -1765,61 +1765,51 @@ void ScInterpreter::ScWeibull() } } -void ScInterpreter::ScPoissonDist() +void ScInterpreter::ScPoissonDist( bool bODFF ) { sal_uInt8 nParamCount = GetByte(); - if ( MustHaveParamCount( nParamCount, 2, 3 ) ) + if ( MustHaveParamCount( nParamCount, ( bODFF ? 2 : 3 ), 3 ) ) { - bool bCumulative = nParamCount != 3 || GetBool(); // default cumulative + bool bCumulative = nParamCount != 3 || GetBool(); // default cumulative double lambda = GetDouble(); // Mean double x = ::rtl::math::approxFloor(GetDouble()); // discrete distribution - if (lambda < 0.0 || x < 0.0) + if (lambda <= 0.0 || x < 0.0) PushIllegalArgument(); else if (!bCumulative) // Probability mass function { - if (lambda == 0.0) - PushInt(0); + if (lambda >712.0) // underflow in exp(-lambda) + { // accuracy 11 Digits + PushDouble( exp(x*log(lambda)-lambda-GetLogGamma(x+1.0))); + } else { - if (lambda >712) // underflow in exp(-lambda) - { // accuracy 11 Digits - PushDouble( exp(x*log(lambda)-lambda-GetLogGamma(x+1.0))); - } - else - { - double fPoissonVar = 1.0; - for ( double f = 0.0; f < x; ++f ) - fPoissonVar *= lambda / ( f + 1.0 ); - PushDouble( fPoissonVar * exp( -lambda ) ); - } + double fPoissonVar = 1.0; + for ( double f = 0.0; f < x; ++f ) + fPoissonVar *= lambda / ( f + 1.0 ); + PushDouble( fPoissonVar * exp( -lambda ) ); } } else // Cumulative distribution function { - if (lambda == 0.0) - PushInt(1); + if (lambda > 712.0) // underflow in exp(-lambda) + { // accuracy 12 Digits + PushDouble(GetUpRegIGamma(x+1.0,lambda)); + } else { - if (lambda > 712 ) // underflow in exp(-lambda) - { // accuracy 12 Digits - PushDouble(GetUpRegIGamma(x+1.0,lambda)); - } + if (x >= 936.0) // result is always undistinghable from 1 + PushDouble (1.0); else { - if (x >= 936.0) // result is always undistinghable from 1 - PushDouble (1.0); - else + double fSummand = exp(-lambda); + double fSum = fSummand; + int nEnd = sal::static_int_cast<int>( x ); + for (int i = 1; i <= nEnd; i++) { - double fSummand = exp(-lambda); - double fSum = fSummand; - int nEnd = sal::static_int_cast<int>( x ); - for (int i = 1; i <= nEnd; i++) - { - fSummand = (fSummand * lambda)/(double)i; - fSum += fSummand; - } - PushDouble(fSum); + fSummand = (fSummand * lambda)/(double)i; + fSum += fSummand; } + PushDouble(fSum); } } } diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx index 11a8870a8f7b..94d04acfaf2c 100644 --- a/sc/source/core/tool/interpr4.cxx +++ b/sc/source/core/tool/interpr4.cxx @@ -4203,8 +4203,8 @@ StackVar ScInterpreter::Interpret() case ocExpDist_MS : ScExpDist(); break; case ocBinomDist : case ocBinomDist_MS : ScBinomDist(); break; - case ocPoissonDist : - case ocPoissonDist_MS : ScPoissonDist(); break; + case ocPoissonDist : ScPoissonDist( true ); break; + case ocPoissonDist_MS : ScPoissonDist( false ); break; case ocCombin : ScCombin(); break; case ocCombinA : ScCombinA(); break; case ocPermut : ScPermut(); break; |