summaryrefslogtreecommitdiff
path: root/sc/source/core/tool
diff options
context:
space:
mode:
authorWinfried Donkers <winfrieddonkers@libreoffice.org>2013-11-21 11:16:43 +0100
committerEike Rathke <erack@redhat.com>2013-11-22 17:22:45 +0100
commitdec38b9b514e256354297073b2bf556f4a2c3c38 (patch)
tree64859db81fe33c34c88adcfa4f20a6885d5a7464 /sc/source/core/tool
parent73ee1d61ddbda7271623f5dccd0c647d614d8d1e (diff)
fdo#71722 add Excel 2010 functions
EXPON.DIST, HYPGEOM.DIST, POISSON.DIST, WEIBULL.DIST Change-Id: Ib9f648739ec0af90cdf2f576c7f548a6acb7b4a6 Reviewed-on: https://gerrit.libreoffice.org/6748 Reviewed-by: Eike Rathke <erack@redhat.com> Tested-by: Eike Rathke <erack@redhat.com> (cherry picked from commit e434c1ce0557454ef4cdd98435c5c0b1d5181bcf)
Diffstat (limited to 'sc/source/core/tool')
-rw-r--r--sc/source/core/tool/interpr3.cxx69
-rw-r--r--sc/source/core/tool/interpr4.cxx10
2 files changed, 66 insertions, 13 deletions
diff --git a/sc/source/core/tool/interpr3.cxx b/sc/source/core/tool/interpr3.cxx
index 515530bf4b9e..0cb0cc8b902a 100644
--- a/sc/source/core/tool/interpr3.cxx
+++ b/sc/source/core/tool/interpr3.cxx
@@ -1738,12 +1738,6 @@ static void lcl_PutFactorialElements( ::std::vector< double >& cn, double fLower
/** Calculates a value of the hypergeometric distribution.
- The algorithm is designed to avoid unnecessary multiplications and division
- by expanding all factorial elements (9 of them). It is done by excluding
- those ranges that overlap in the numerator and the denominator. This allows
- for a fast calculation for large values which would otherwise cause an overflow
- in the intermediate values.
-
@author Kohei Yoshida <kohei@openoffice.org>
@see #i47296#
@@ -1751,8 +1745,6 @@ static void lcl_PutFactorialElements( ::std::vector< double >& cn, double fLower
*/
void ScInterpreter::ScHypGeomDist()
{
- const size_t nMaxArraySize = 500000; // arbitrary max array size
-
if ( !MustHaveParamCount( GetByte(), 4 ) )
return;
@@ -1767,6 +1759,63 @@ void ScInterpreter::ScHypGeomDist()
return;
}
+ PushDouble( GetHypGeomDist( x, n, M, N ) );
+}
+
+/** Calculates a value of the hypergeometric distribution (Excel 2010 function).
+
+ This function has an extra argument bCumulative as compared to ScHypGeomDist(),
+ which only calculates the non-cumulative distribution.
+
+ @see fdo#71722
+*/
+void ScInterpreter::ScHypGeomDist_MS()
+{
+ if ( !MustHaveParamCount( GetByte(), 5 ) )
+ return;
+
+ bool bCumulative = GetBool();
+ double N = ::rtl::math::approxFloor(GetDouble());
+ double M = ::rtl::math::approxFloor(GetDouble());
+ double n = ::rtl::math::approxFloor(GetDouble());
+ double x = ::rtl::math::approxFloor(GetDouble());
+
+ if( (x < 0.0) || (n < x) || (M < x) || (N < n) || (N < M) || (x < n - N + M) )
+ {
+ PushIllegalArgument();
+ return;
+ }
+
+ if ( bCumulative )
+ {
+ double fVal = 0.0;
+
+ for ( int i = 0; i <= x && !nGlobalError; i++ )
+ fVal += GetHypGeomDist( i, n, M, N );
+
+ PushDouble( fVal );
+ }
+ else
+ PushDouble( GetHypGeomDist( x, n, M, N ) );
+}
+
+/** Calculates a value of the hypergeometric distribution.
+
+ The algorithm is designed to avoid unnecessary multiplications and division
+ by expanding all factorial elements (9 of them). It is done by excluding
+ those ranges that overlap in the numerator and the denominator. This allows
+ for a fast calculation for large values which would otherwise cause an overflow
+ in the intermediate values.
+
+ @author Kohei Yoshida <kohei@openoffice.org>
+
+ @see #i47296#
+
+ */
+double ScInterpreter::GetHypGeomDist( double x, double n, double M, double N )
+{
+ const size_t nMaxArraySize = 500000; // arbitrary max array size
+
typedef ::std::vector< double > HypContainer;
HypContainer cnNumer, cnDenom;
@@ -1775,7 +1824,7 @@ void ScInterpreter::ScHypGeomDist()
if ( nEstContainerSize > nMaxSize )
{
PushNoValue();
- return;
+ return 0;
}
cnNumer.reserve( nEstContainerSize + 10 );
cnDenom.reserve( nEstContainerSize + 10 );
@@ -1959,7 +2008,7 @@ void ScInterpreter::ScHypGeomDist()
fFactor *= fEnum / fDenom;
}
- PushDouble(fFactor);
+ return fFactor;
}
void ScInterpreter::ScGammaDist()
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index 38d73b096c29..d230ac896872 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -4099,15 +4099,18 @@ StackVar ScInterpreter::Interpret()
case ocMatRef : ScMatRef(); break;
case ocB : ScB(); break;
case ocNormDist : ScNormDist(); break;
- case ocExpDist : ScExpDist(); break;
+ case ocExpDist :
+ case ocExpDist_MS : ScExpDist(); break;
case ocBinomDist :
case ocBinomDist_MS : ScBinomDist(); break;
- case ocPoissonDist : ScPoissonDist(); break;
+ case ocPoissonDist :
+ case ocPoissonDist_MS : ScPoissonDist(); break;
case ocKombin : ScKombin(); break;
case ocKombin2 : ScKombin2(); break;
case ocVariationen : ScVariationen(); break;
case ocVariationen2 : ScVariationen2(); break;
case ocHypGeomDist : ScHypGeomDist(); break;
+ case ocHypGeomDist_MS : ScHypGeomDist_MS(); break;
case ocLogNormDist : ScLogNormDist(); break;
case ocTDist : ScTDist(); break;
case ocFDist :
@@ -4127,7 +4130,8 @@ StackVar ScInterpreter::Interpret()
case ocMedian : ScMedian(); break;
case ocGeoMean : ScGeoMean(); break;
case ocHarMean : ScHarMean(); break;
- case ocWeibull : ScWeibull(); break;
+ case ocWeibull :
+ case ocWeibull_MS : ScWeibull(); break;
case ocBinomInv :
case ocKritBinom : ScCritBinom(); break;
case ocNegBinomVert : ScNegBinomDist(); break;