summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorWinfried Donkers <winfrieddonkers@libreoffice.org>2016-12-31 16:24:27 +0100
committerEike Rathke <erack@redhat.com>2017-01-03 20:30:48 +0000
commit482db19e3c792892c536898408dd7da98265073a (patch)
treeb690e82db0a758d2c8b46e23c77eacf23dd2ac64 /sc
parent7e7fcb7ee614be44589d0ca90e7785a4efcf1457 (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.hxx2
-rw-r--r--sc/source/core/tool/interpr3.cxx60
-rw-r--r--sc/source/core/tool/interpr4.cxx4
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;