summaryrefslogtreecommitdiff
path: root/scaddins
diff options
context:
space:
mode:
authorAlbert Thuswaldner <albert.thuswaldner@gmail.com>2012-08-01 01:26:25 +0200
committerEike Rathke <erack@redhat.com>2012-08-10 16:08:55 +0200
commit1f62afae0fd04236005be70736cf7ab059a10778 (patch)
tree67ddd7ca1931ad9edd71e113ee0dc1ef5c7a7139 /scaddins
parent6dcb3d4ef46312729bb6f16c473b433474863f68 (diff)
fdo#43135 - fix for MULTINOMIAL only supporting parameters up to 170
Change-Id: I9366de24414fa10e292e42df08a9658d90e5c1c1
Diffstat (limited to 'scaddins')
-rw-r--r--scaddins/source/analysis/analysis.cxx19
-rw-r--r--scaddins/source/analysis/analysishelper.cxx35
-rw-r--r--scaddins/source/analysis/analysishelper.hxx2
3 files changed, 27 insertions, 29 deletions
diff --git a/scaddins/source/analysis/analysis.cxx b/scaddins/source/analysis/analysis.cxx
index 00d5e3d78b8b..ca83361714e8 100644
--- a/scaddins/source/analysis/analysis.cxx
+++ b/scaddins/source/analysis/analysis.cxx
@@ -689,26 +689,21 @@ AnalysisAddIn::getMultinomial( constREFXPS& xOpt, const SEQSEQ( sal_Int32 )& aVL
if( aValList.Count() == 0 )
return 0.0;
- sal_Int32 nZ = 0;
- double fN = 1.0;
+ double nZ = 0;
+ double fRet = 1.0;
for( const double *p = aValList.First(); p; p = aValList.Next() )
{
- double fInt = (*p >= 0.0) ? rtl::math::approxFloor( *p ) : rtl::math::approxCeil( *p );
- if ( fInt < 0.0 || fInt > 170.0 )
+ double n = (*p >= 0.0) ? rtl::math::approxFloor( *p ) : rtl::math::approxCeil( *p );
+ if ( n < 0.0 )
THROW_IAE;
- sal_Int32 n = static_cast< sal_Int32 >( fInt );
- if( n > 0 )
+
+ if( n > 0.0 )
{
nZ += n;
- fN *= Fak( n );
+ fRet *= BinomialCoefficient(nZ, n);
}
}
-
- if( nZ > 170 )
- THROW_IAE;
-
- double fRet = Fak( nZ ) / fN;
RETURN_FINITE( fRet );
}
diff --git a/scaddins/source/analysis/analysishelper.cxx b/scaddins/source/analysis/analysishelper.cxx
index 6b4309a6f3c7..56064b56f884 100644
--- a/scaddins/source/analysis/analysishelper.cxx
+++ b/scaddins/source/analysis/analysishelper.cxx
@@ -521,29 +521,32 @@ double GetYearFrac( sal_Int32 nNullDate, sal_Int32 nStartDate, sal_Int32 nEndDat
return double( nYears ) + double( nDayDiff ) / double( nDaysInYear );
}
-
-double Fak( sal_Int32 n )
+double BinomialCoefficient( double n, double k )
{
- if( n > 0 )
- {
- double fRet = n;
- double f = n - 1;
+ // This method is a copy of BinomKoeff()
+ // found in sc/source/core/tool/interpr3.cxx
- while( f >= 2.0 )
+ double nVal = 0.0;
+ k = ::rtl::math::approxFloor(k);
+ if (n < k)
+ nVal = 0.0;
+ else if (k == 0.0)
+ nVal = 1.0;
+ else
+ {
+ nVal = n/k;
+ n--;
+ k--;
+ while (k > 0.0)
{
- fRet *= f;
- f--;
+ nVal *= n/k;
+ k--;
+ n--;
}
-
- return fRet;
}
- else if( !n )
- return 1.0;
- else
- return 0.0;
+ return nVal;
}
-
double GetGcd( double f1, double f2 )
{
double f = fmod( f1, f2 );
diff --git a/scaddins/source/analysis/analysishelper.hxx b/scaddins/source/analysis/analysishelper.hxx
index bad6e2124dfe..bbbbfc57f245 100644
--- a/scaddins/source/analysis/analysishelper.hxx
+++ b/scaddins/source/analysis/analysishelper.hxx
@@ -94,7 +94,7 @@ inline double GetYearFrac( constREFXPS& xOpt, sal_Int32 nStartDate, sal_In
THROWDEF_RTE_IAE;
inline void AlignDate( sal_uInt16& rDay, sal_uInt16 nMonth, sal_uInt16 nYear );
-double Fak( sal_Int32 n );
+double BinomialCoefficient( double n, double k );
double GetGcd( double f1, double f2 );
double ConvertToDec( const STRING& rFromNum, sal_uInt16 nBaseFrom, sal_uInt16 nCharLim ) THROWDEF_RTE_IAE;
STRING ConvertFromDec(