Index: sc/source/core/inc/interpre.hxx =================================================================== RCS file: /cvs/sc/sc/source/core/inc/interpre.hxx,v --- sc/source/core/inc/interpre.hxx 13 May 2005 07:33:07 -0000 1.21 +++ sc/source/core/inc/interpre.hxx 5 Sep 2005 21:10:41 -0000 @@ -91,6 +91,7 @@ #endif #include +#include class ScDocument; class SbxVariable; @@ -623,6 +624,7 @@ double GetTDist(double T, double fDF); double Fakultaet(double x); double BinomKoeff(double n, double k); +void SetBinomElements( sal_uInt32 n, sal_uInt32 k, std::multiset& rEnum, std::multiset& rDenom ); double GammaHelp(double& x, BOOL& bReflect); double GetGamma(double x); double GetLogGamma(double x); Index: sc/source/core/tool/interpr3.cxx =================================================================== RCS file: /cvs/sc/sc/source/core/tool/interpr3.cxx,v --- sc/source/core/tool/interpr3.cxx 15 Nov 2004 16:35:44 -0000 1.12 +++ sc/source/core/tool/interpr3.cxx 5 Sep 2005 21:10:42 -0000 @@ -345,6 +345,51 @@ return nVal; } +void lcl_InsertElementIntoDenom( sal_uInt32 k, + std::multiset& rEnum, std::multiset& rDenom ) +{ + std::multiset::iterator itr = rEnum.find( k ); + if ( itr != rEnum.end() ) + rEnum.erase( itr ); + else + rDenom.insert( k ); +} + +/** Inserts individual binomial elements of (n, k) = n! / k!(n-k)! into enumerator + and denominator arrays, respectively. + + @param n + @param k + @param rEnum multiset array to store enumerator elements + @param rDenom multiset array to store denominator elements + + @author Kohei Yoshida + */ +void ScInterpreter::SetBinomElements( sal_uInt32 n, sal_uInt32 k, + std::multiset& rEnum, std::multiset& rDenom ) +{ + if ( n >= k ) + { + if ( n == 0 || k == 0 ) + return; + if ( n > 1 ) + rEnum.insert( n ); + if ( k > 1 ) + lcl_InsertElementIntoDenom( k, rEnum, rDenom ); + --n; + --k; + while ( k > 0 ) + { + if ( n > 1 ) + rEnum.insert( n ); + if ( k > 1 ) + lcl_InsertElementIntoDenom( k, rEnum, rDenom ); + --n; + --k; + } + } +} + double ScInterpreter::GammaHelp(double& x, BOOL& bReflect) { double c[6] = {76.18009173, -86.50532033, 24.01409822, @@ -1121,30 +1166,29 @@ SetIllegalArgument(); return; } - double fFactor = - BinomKoeff( n, x ) / BinomKoeff( N, M ) * BinomKoeff( N - n, M - x ); -/* - double fFactor; - if (x == n - N + M) - fFactor = BinomKoeff(M,x)/BinomKoeff(N,n); - else - { - double fIndex = N - M - n; - if (fIndex >= 0.0) - { - fFactor = BinomKoeff(N-M,n)/BinomKoeff(N,n); - for (double i = 0; i < x; i++) - fFactor *= (M-i)*(n-i)/((i+1.0)*(N-M-n+i+1.0)); - } - else - { - fFactor = BinomKoeff(M,-fIndex)/BinomKoeff(N,n); - for (double i = -fIndex + 1.0; i < x; i++) - fFactor *= (M-i)*(n-i)/((i+1)*(N-M-n+i+1.0)); - } + typedef std::multiset ULongMultiSet; + ULongMultiSet rEnum, rDenom; + SetBinomElements( static_cast(n), static_cast(x), + rEnum, rDenom ); + SetBinomElements( static_cast(N), static_cast(M), + rDenom, rEnum ); + SetBinomElements( static_cast(N-n), static_cast(M-x), + rEnum, rDenom ); + + double fFactor = 1.0; + ULongMultiSet::reverse_iterator it1 = rEnum.rbegin(), it1End = rEnum.rend(); + ULongMultiSet::reverse_iterator it2 = rDenom.rbegin(), it2End = rDenom.rend(); + for ( ; it1 != it1End || it2 != it2End; ) + { + double fEnum = 1.0, fDenom = 1.0; + if ( it1 != it1End ) + fEnum = static_cast( *it1++ ); + if ( it2 != it2End ) + fDenom = static_cast( *it2++ ); + fFactor *= fEnum / fDenom; } -*/ + PushDouble(fFactor); } }