Kaydet (Commit) 482db19e authored tarafından Winfried Donkers's avatar Winfried Donkers Kaydeden (comit) Eike Rathke

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/32538Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarEike Rathke <erack@redhat.com>
üst 7e7fcb7e
...@@ -861,7 +861,7 @@ void ScGammaDist( bool bODFF ); ...@@ -861,7 +861,7 @@ void ScGammaDist( bool bODFF );
void ScGammaInv(); void ScGammaInv();
void ScExpDist(); void ScExpDist();
void ScBinomDist(); void ScBinomDist();
void ScPoissonDist(); void ScPoissonDist( bool bODFF );
void ScCombin(); void ScCombin();
void ScCombinA(); void ScCombinA();
void ScPermut(); void ScPermut();
......
...@@ -1765,61 +1765,51 @@ void ScInterpreter::ScWeibull() ...@@ -1765,61 +1765,51 @@ void ScInterpreter::ScWeibull()
} }
} }
void ScInterpreter::ScPoissonDist() void ScInterpreter::ScPoissonDist( bool bODFF )
{ {
sal_uInt8 nParamCount = GetByte(); 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 lambda = GetDouble(); // Mean
double x = ::rtl::math::approxFloor(GetDouble()); // discrete distribution double x = ::rtl::math::approxFloor(GetDouble()); // discrete distribution
if (lambda < 0.0 || x < 0.0) if (lambda <= 0.0 || x < 0.0)
PushIllegalArgument(); PushIllegalArgument();
else if (!bCumulative) // Probability mass function else if (!bCumulative) // Probability mass function
{ {
if (lambda == 0.0) if (lambda >712.0) // underflow in exp(-lambda)
PushInt(0); { // accuracy 11 Digits
PushDouble( exp(x*log(lambda)-lambda-GetLogGamma(x+1.0)));
}
else else
{ {
if (lambda >712) // underflow in exp(-lambda) double fPoissonVar = 1.0;
{ // accuracy 11 Digits for ( double f = 0.0; f < x; ++f )
PushDouble( exp(x*log(lambda)-lambda-GetLogGamma(x+1.0))); fPoissonVar *= lambda / ( f + 1.0 );
} PushDouble( fPoissonVar * exp( -lambda ) );
else
{
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 else // Cumulative distribution function
{ {
if (lambda == 0.0) if (lambda > 712.0) // underflow in exp(-lambda)
PushInt(1); { // accuracy 12 Digits
PushDouble(GetUpRegIGamma(x+1.0,lambda));
}
else else
{ {
if (lambda > 712 ) // underflow in exp(-lambda) if (x >= 936.0) // result is always undistinghable from 1
{ // accuracy 12 Digits PushDouble (1.0);
PushDouble(GetUpRegIGamma(x+1.0,lambda));
}
else else
{ {
if (x >= 936.0) // result is always undistinghable from 1 double fSummand = exp(-lambda);
PushDouble (1.0); double fSum = fSummand;
else int nEnd = sal::static_int_cast<int>( x );
for (int i = 1; i <= nEnd; i++)
{ {
double fSummand = exp(-lambda); fSummand = (fSummand * lambda)/(double)i;
double fSum = fSummand; 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);
} }
PushDouble(fSum);
} }
} }
} }
......
...@@ -4203,8 +4203,8 @@ StackVar ScInterpreter::Interpret() ...@@ -4203,8 +4203,8 @@ StackVar ScInterpreter::Interpret()
case ocExpDist_MS : ScExpDist(); break; case ocExpDist_MS : ScExpDist(); break;
case ocBinomDist : case ocBinomDist :
case ocBinomDist_MS : ScBinomDist(); break; case ocBinomDist_MS : ScBinomDist(); break;
case ocPoissonDist : case ocPoissonDist : ScPoissonDist( true ); break;
case ocPoissonDist_MS : ScPoissonDist(); break; case ocPoissonDist_MS : ScPoissonDist( false ); break;
case ocCombin : ScCombin(); break; case ocCombin : ScCombin(); break;
case ocCombinA : ScCombinA(); break; case ocCombinA : ScCombinA(); break;
case ocPermut : ScPermut(); break; case ocPermut : ScPermut(); break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment