[Libreoffice-commits] core.git: sc/source
Winfried Donkers
winfrieddonkers at libreoffice.org
Fri Nov 8 15:54:33 CET 2013
sc/source/core/tool/interpr3.cxx | 73 +++++++++++++++++++++++++++++++--------
1 file changed, 59 insertions(+), 14 deletions(-)
New commits:
commit fa7085bd182e1968237b742c544de3ff0a5b9742
Author: Winfried Donkers <winfrieddonkers at libreoffice.org>
Date: Mon Nov 4 10:32:40 2013 +0100
improve calc function CRITBINOM
CRITBINOM could not handle large sample quantities, e.g.
CRITBINOM(1080,0.5,0.1).
This patch fixes that and also improves the efficiency of
the function by always iterating from the end nearest to
the cumulative binomial distribution.
Change-Id: I35f965acc83e26141fb2cf5a7e3303ec0791f04a
Reviewed-on: https://gerrit.libreoffice.org/6559
Reviewed-by: Eike Rathke <erack at redhat.com>
Tested-by: Eike Rathke <erack at redhat.com>
diff --git a/sc/source/core/tool/interpr3.cxx b/sc/source/core/tool/interpr3.cxx
index e7b071f..3f665f3 100644
--- a/sc/source/core/tool/interpr3.cxx
+++ b/sc/source/core/tool/interpr3.cxx
@@ -1383,15 +1383,50 @@ void ScInterpreter::ScCritBinom()
PushIllegalArgument();
else
{
+ double fFactor;
double q = (0.5 - p) + 0.5; // get one bit more for p near 1.0
- double fFactor = pow(q,n);
- if (fFactor <= ::std::numeric_limits<double>::min())
+ if ( q > p ) // work from the side where the cumulative curve is
{
- fFactor = pow(p, n);
- if (fFactor <= ::std::numeric_limits<double>::min())
- PushNoValue();
+ // work from 0 upwards
+ fFactor = pow(q,n);
+ if (fFactor > ::std::numeric_limits<double>::min())
+ {
+ double fSum = fFactor;
+ sal_uInt32 max = static_cast<sal_uInt32> (n), i;
+ for (i = 0; i < max && fSum < alpha; i++)
+ {
+ fFactor *= (n-i)/(i+1)*p/q;
+ fSum += fFactor;
+ }
+ PushDouble(i);
+ }
else
{
+ // accumulate BinomDist until accumulated BinomDist reaches alpha
+ double fSum = 0.0, x;
+ sal_uInt32 max = static_cast<sal_uInt32> (n), i;
+ for (i = 0; i < max && fSum < alpha; i++)
+ {
+ x = GetBetaDistPDF( p, ( i + 1 ), ( n - i + 1 ) )/( n + 1 );
+ if ( !nGlobalError )
+ {
+ fSum += x;
+ }
+ else
+ {
+ PushNoValue();
+ return;
+ }
+ }
+ PushDouble( i - 1 );
+ }
+ }
+ else
+ {
+ // work from n backwards
+ fFactor = pow(p, n);
+ if (fFactor > ::std::numeric_limits<double>::min())
+ {
double fSum = 1.0 - fFactor;
sal_uInt32 max = static_cast<sal_uInt32> (n), i;
for (i = 0; i < max && fSum >= alpha; i++)
@@ -1401,17 +1436,27 @@ void ScInterpreter::ScCritBinom()
}
PushDouble(n-i);
}
- }
- else
- {
- double fSum = fFactor;
- sal_uInt32 max = static_cast<sal_uInt32> (n), i;
- for (i = 0; i < max && fSum < alpha; i++)
+ else
{
- fFactor *= (n-i)/(i+1)*p/q;
- fSum += fFactor;
+ // accumulate BinomDist until accumulated BinomDist reaches alpha
+ double fSum = 0.0, x;
+ sal_uInt32 max = static_cast<sal_uInt32> (n), i;
+ alpha = 1 - alpha;
+ for (i = 0; i < max && fSum < alpha; i++)
+ {
+ x = GetBetaDistPDF( q, ( i + 1 ), ( n - i + 1 ) )/( n + 1 );
+ if ( !nGlobalError )
+ {
+ fSum += x;
+ }
+ else
+ {
+ PushNoValue();
+ return;
+ }
+ }
+ PushDouble( n - i + 1 );
}
- PushDouble(i);
}
}
}
More information about the Libreoffice-commits
mailing list