diff options
author | Winfried Donkers <winfrieddonkers@libreoffice.org> | 2013-11-21 11:16:43 +0100 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2013-11-22 17:22:45 +0100 |
commit | dec38b9b514e256354297073b2bf556f4a2c3c38 (patch) | |
tree | 64859db81fe33c34c88adcfa4f20a6885d5a7464 /sc/source/core/tool | |
parent | 73ee1d61ddbda7271623f5dccd0c647d614d8d1e (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.cxx | 69 | ||||
-rw-r--r-- | sc/source/core/tool/interpr4.cxx | 10 |
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; |