1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <tools/solar.h>
24 #include "interpre.hxx"
26 #include "compiler.hxx"
27 #include "formulacell.hxx"
28 #include "document.hxx"
29 #include "dociter.hxx"
30 #include "scmatrix.hxx"
31 #include "globstr.hrc"
38 using namespace formula
;
41 #define MAX_ANZ_DOUBLE_FOR_SORT 100000
43 const double ScInterpreter::fMaxGammaArgument
= 171.624376956302; // found experimental
44 const double fMachEps
= ::std::numeric_limits
<double>::epsilon();
49 virtual double GetValue(double x
) const = 0;
55 // iteration for inverse distributions
57 //template< class T > double lcl_IterateInverse( const T& rFunction, double x0, double x1, bool& rConvError )
59 /** u*w<0.0 fails for values near zero */
60 static inline bool lcl_HasChangeOfSign( double u
, double w
)
62 return (u
< 0.0 && w
> 0.0) || (u
> 0.0 && w
< 0.0);
65 static double lcl_IterateInverse( const ScDistFunc
& rFunction
, double fAx
, double fBx
, bool& rConvError
)
68 const double fYEps
= 1.0E-307;
69 const double fXEps
= ::std::numeric_limits
<double>::epsilon();
71 OSL_ENSURE(fAx
<fBx
, "IterateInverse: wrong interval");
73 // find enclosing interval
75 double fAy
= rFunction
.GetValue(fAx
);
76 double fBy
= rFunction
.GetValue(fBx
);
78 unsigned short nCount
;
79 for (nCount
= 0; nCount
< 1000 && !lcl_HasChangeOfSign(fAy
,fBy
); nCount
++)
81 if (fabs(fAy
) <= fabs(fBy
))
84 fAx
+= 2.0 * (fAx
- fBx
);
89 fAy
= rFunction
.GetValue(fAx
);
94 fBx
+= 2.0 * (fBx
- fAx
);
97 fBy
= rFunction
.GetValue(fBx
);
105 if (!lcl_HasChangeOfSign( fAy
, fBy
))
110 // inverse quadric interpolation with additional brackets
118 double fSx
= 0.5 * (fAx
+ fBx
); // potential next point
119 bool bHasToInterpolate
= true;
121 while ( nCount
< 500 && fabs(fRy
) > fYEps
&&
122 (fBx
-fAx
) > ::std::max( fabs(fAx
), fabs(fBx
)) * fXEps
)
124 if (bHasToInterpolate
)
126 if (fPy
!=fQy
&& fQy
!=fRy
&& fRy
!=fPy
)
128 fSx
= fPx
* fRy
* fQy
/ (fRy
-fPy
) / (fQy
-fPy
)
129 + fRx
* fQy
* fPy
/ (fQy
-fRy
) / (fPy
-fRy
)
130 + fQx
* fPy
* fRy
/ (fPy
-fQy
) / (fRy
-fQy
);
131 bHasToInterpolate
= (fAx
< fSx
) && (fSx
< fBx
); // inside the brackets?
134 bHasToInterpolate
= false;
136 if(!bHasToInterpolate
)
138 fSx
= 0.5 * (fAx
+ fBx
);
140 fPx
= fAx
; fPy
= fAy
;
141 fQx
= fBx
; fQy
= fBy
;
142 bHasToInterpolate
= true;
144 // shift points for next interpolation
145 fPx
= fQx
; fQx
= fRx
; fRx
= fSx
;
146 fPy
= fQy
; fQy
= fRy
; fRy
= rFunction
.GetValue(fSx
);
148 if (lcl_HasChangeOfSign( fAy
, fRy
))
150 fBx
= fRx
; fBy
= fRy
;
154 fAx
= fRx
; fAy
= fRy
;
156 // if last interration brought to small advance, then do bisection next
158 bHasToInterpolate
= bHasToInterpolate
&& (fabs(fRy
) * 2.0 <= fabs(fQy
));
164 // Allgemeine Funktionen
166 void ScInterpreter::ScNoName()
168 PushError(errNoName
);
171 void ScInterpreter::ScBadName()
173 short nParamCount
= GetByte();
174 while (nParamCount
-- > 0)
178 PushError( errNoName
);
181 double ScInterpreter::phi(double x
)
183 return 0.39894228040143268 * exp(-(x
* x
) / 2.0);
186 double ScInterpreter::integralPhi(double x
)
187 { // Using gauss(x)+0.5 has severe cancellation errors for x<-4
188 return 0.5 * ::rtl::math::erfc(-x
* 0.7071067811865475); // * 1/sqrt(2)
191 double ScInterpreter::taylor(double* pPolynom
, sal_uInt16 nMax
, double x
)
193 double nVal
= pPolynom
[nMax
];
194 for (short i
= nMax
-1; i
>= 0; i
--)
196 nVal
= pPolynom
[i
] + (nVal
* x
);
201 double ScInterpreter::gauss(double x
)
204 double xAbs
= fabs(x
);
205 sal_uInt16 xShort
= (sal_uInt16
)::rtl::math::approxFloor(xAbs
);
210 { 0.39894228040143268, -0.06649038006690545, 0.00997355701003582,
211 -0.00118732821548045, 0.00011543468761616, -0.00000944465625950,
212 0.00000066596935163, -0.00000004122667415, 0.00000000227352982,
213 0.00000000011301172, 0.00000000000511243, -0.00000000000021218 };
214 nVal
= taylor(t0
, 11, (xAbs
* xAbs
)) * xAbs
;
216 else if ((xShort
>= 1) && (xShort
<= 2))
219 { 0.47724986805182079, 0.05399096651318805, -0.05399096651318805,
220 0.02699548325659403, -0.00449924720943234, -0.00224962360471617,
221 0.00134977416282970, -0.00011783742691370, -0.00011515930357476,
222 0.00003704737285544, 0.00000282690796889, -0.00000354513195524,
223 0.00000037669563126, 0.00000019202407921, -0.00000005226908590,
224 -0.00000000491799345, 0.00000000366377919, -0.00000000015981997,
225 -0.00000000017381238, 0.00000000002624031, 0.00000000000560919,
226 -0.00000000000172127, -0.00000000000008634, 0.00000000000007894 };
227 nVal
= taylor(t2
, 23, (xAbs
- 2.0));
229 else if ((xShort
>= 3) && (xShort
<= 4))
232 { 0.49996832875816688, 0.00013383022576489, -0.00026766045152977,
233 0.00033457556441221, -0.00028996548915725, 0.00018178605666397,
234 -0.00008252863922168, 0.00002551802519049, -0.00000391665839292,
235 -0.00000074018205222, 0.00000064422023359, -0.00000017370155340,
236 0.00000000909595465, 0.00000000944943118, -0.00000000329957075,
237 0.00000000029492075, 0.00000000011874477, -0.00000000004420396,
238 0.00000000000361422, 0.00000000000143638, -0.00000000000045848 };
239 nVal
= taylor(t4
, 20, (xAbs
- 4.0));
243 double asympt
[] = { -1.0, 1.0, -3.0, 15.0, -105.0 };
244 nVal
= 0.5 + phi(xAbs
) * taylor(asympt
, 4, 1.0 / (xAbs
* xAbs
)) / xAbs
;
253 // #i26836# new gaussinv implementation by Martin Eitzenberger <m.eitzenberger@unix.net>
256 double ScInterpreter::gaussinv(double x
)
275 t
*2509.0809287301226727+33430.575583588128105
277 *t
+67265.770927008700853
279 *t
+45921.953931549871457
281 *t
+13731.693765509461125
283 *t
+1971.5909503065514427
285 *t
+133.14166789178437745
287 *t
+3.387132872796366608
297 t
*5226.495278852854561+28729.085735721942674
299 *t
+39307.89580009271061
301 *t
+21213.794301586595867
303 *t
+5394.1960214247511077
305 *t
+687.1870074920579083
307 *t
+42.313330701600911252
332 t
*7.7454501427834140764e-4+0.0227238449892691845833
334 *t
+0.24178072517745061177
336 *t
+1.27045825245236838258
338 *t
+3.64784832476320460504
340 *t
+5.7694972214606914055
342 *t
+4.6303378461565452959
344 *t
+1.42343711074968357734
354 t
*1.05075007164441684324e-9+5.475938084995344946e-4
356 *t
+0.0151986665636164571966
358 *t
+0.14810397642748007459
360 *t
+0.68976733498510000455
362 *t
+1.6763848301838038494
364 *t
+2.05319162663775882187
382 t
*2.01033439929228813265e-7+2.71155556874348757815e-5
384 *t
+0.0012426609473880784386
386 *t
+0.026532189526576123093
388 *t
+0.29656057182850489123
390 *t
+1.7848265399172913358
392 *t
+5.4637849111641143699
394 *t
+6.6579046435011037772
404 t
*2.04426310338993978564e-15+1.4215117583164458887e-7
406 *t
+1.8463183175100546818e-5
408 *t
+7.868691311456132591e-4
410 *t
+0.0148753612908506148525
412 *t
+0.13692988092273580531
414 *t
+0.59983220655588793769
427 double ScInterpreter::Fakultaet(double x
)
429 x
= ::rtl::math::approxFloor(x
);
444 SetError(errNoValue
);
448 double ScInterpreter::BinomKoeff(double n
, double k
)
450 // this method has been duplicated as BinomialCoefficient()
451 // in scaddins/source/analysis/analysishelper.cxx
454 k
= ::rtl::math::approxFloor(k
);
475 // The algorithm is based on lanczos13m53 in lanczos.hpp
476 // in math library from http://www.boost.org
477 /** you must ensure fZ>0
478 Uses a variant of the Lanczos sum with a rational function. */
479 static double lcl_getLanczosSum(double fZ
)
481 const double fNum
[13] ={
482 23531376880.41075968857200767445163675473,
483 42919803642.64909876895789904700198885093,
484 35711959237.35566804944018545154716670596,
485 17921034426.03720969991975575445893111267,
486 6039542586.35202800506429164430729792107,
487 1439720407.311721673663223072794912393972,
488 248874557.8620541565114603864132294232163,
489 31426415.58540019438061423162831820536287,
490 2876370.628935372441225409051620849613599,
491 186056.2653952234950402949897160456992822,
492 8071.672002365816210638002902272250613822,
493 210.8242777515793458725097339207133627117,
494 2.506628274631000270164908177133837338626
496 const double fDenom
[13] = {
518 fSumDenom
= fDenom
[12];
519 for (nI
= 11; nI
>= 0; --nI
)
524 fSumDenom
+= fDenom
[nI
];
528 // Cancel down with fZ^12; Horner scheme with reverse coefficients
532 fSumDenom
= fDenom
[0];
533 for (nI
= 1; nI
<=12; ++nI
)
538 fSumDenom
+= fDenom
[nI
];
541 return fSumNum
/fSumDenom
;
544 // The algorithm is based on tgamma in gamma.hpp
545 // in math library from http://www.boost.org
546 /** You must ensure fZ>0; fZ>171.624376956302 will overflow. */
547 static double lcl_GetGammaHelper(double fZ
)
549 double fGamma
= lcl_getLanczosSum(fZ
);
550 const double fg
= 6.024680040776729583740234375;
551 double fZgHelp
= fZ
+ fg
- 0.5;
552 // avoid intermediate overflow
553 double fHalfpower
= pow( fZgHelp
, fZ
/ 2 - 0.25);
554 fGamma
*= fHalfpower
;
555 fGamma
/= exp(fZgHelp
);
556 fGamma
*= fHalfpower
;
557 if (fZ
<= 20.0 && fZ
== ::rtl::math::approxFloor(fZ
))
558 fGamma
= ::rtl::math::round(fGamma
);
562 // The algorithm is based on tgamma in gamma.hpp
563 // in math library from http://www.boost.org
564 /** You must ensure fZ>0 */
565 static double lcl_GetLogGammaHelper(double fZ
)
567 const double fg
= 6.024680040776729583740234375;
568 double fZgHelp
= fZ
+ fg
- 0.5;
569 return log( lcl_getLanczosSum(fZ
)) + (fZ
-0.5) * log(fZgHelp
) - fZgHelp
;
572 /** You must ensure non integer arguments for fZ<1 */
573 double ScInterpreter::GetGamma(double fZ
)
575 const double fLogPi
= log(F_PI
);
576 const double fLogDblMax
= log( ::std::numeric_limits
<double>::max());
578 if (fZ
> fMaxGammaArgument
)
580 SetError(errIllegalFPOperation
);
585 return lcl_GetGammaHelper(fZ
);
587 if (fZ
>= 0.5) // shift to x>=1 using Gamma(x)=Gamma(x+1)/x
588 return lcl_GetGammaHelper(fZ
+1) / fZ
;
590 if (fZ
>= -0.5) // shift to x>=1, might overflow
592 double fLogTest
= lcl_GetLogGammaHelper(fZ
+2) - log(fZ
+1) - log( fabs(fZ
));
593 if (fLogTest
>= fLogDblMax
)
595 SetError( errIllegalFPOperation
);
598 return lcl_GetGammaHelper(fZ
+2) / (fZ
+1) / fZ
;
601 // Use Euler's reflection formula: gamma(x)= pi/ ( gamma(1-x)*sin(pi*x) )
602 double fLogDivisor
= lcl_GetLogGammaHelper(1-fZ
) + log( fabs( ::rtl::math::sin( F_PI
*fZ
)));
603 if (fLogDivisor
- fLogPi
>= fLogDblMax
) // underflow
607 if (fLogPi
- fLogDivisor
> fLogDblMax
) // overflow
609 SetError(errIllegalFPOperation
);
613 return exp( fLogPi
- fLogDivisor
) * ((::rtl::math::sin( F_PI
*fZ
) < 0.0) ? -1.0 : 1.0);
616 /** You must ensure fZ>0 */
617 double ScInterpreter::GetLogGamma(double fZ
)
619 if (fZ
>= fMaxGammaArgument
)
620 return lcl_GetLogGammaHelper(fZ
);
622 return log(lcl_GetGammaHelper(fZ
));
624 return log( lcl_GetGammaHelper(fZ
+1) / fZ
);
625 return lcl_GetLogGammaHelper(fZ
+2) - log(fZ
+1) - log(fZ
);
628 double ScInterpreter::GetFDist(double x
, double fF1
, double fF2
)
630 double arg
= fF2
/(fF2
+fF1
*x
);
631 double alpha
= fF2
/2.0;
632 double beta
= fF1
/2.0;
633 return (GetBetaDist(arg
, alpha
, beta
));
636 double ScInterpreter::GetTDist(double T
, double fDF
)
638 return 0.5 * GetBetaDist(fDF
/(fDF
+T
*T
), fDF
/2.0, 0.5);
641 // for LEGACY.CHIDIST, returns right tail, fDF=degrees of freedom
642 /** You must ensure fDF>0.0 */
643 double ScInterpreter::GetChiDist(double fX
, double fDF
)
646 return 1.0; // see ODFF
648 return GetUpRegIGamma( fDF
/2.0, fX
/2.0);
652 // for ODF CHISQDIST; cumulative distribution function, fDF=degrees of freedom
654 /** You must ensure fDF>0.0 */
655 double ScInterpreter::GetChiSqDistCDF(double fX
, double fDF
)
658 return 0.0; // see ODFF
660 return GetLowRegIGamma( fDF
/2.0, fX
/2.0);
663 double ScInterpreter::GetChiSqDistPDF(double fX
, double fDF
)
665 // you must ensure fDF is positive integer
668 return 0.0; // see ODFF
669 if (fDF
*fX
> 1391000.0)
671 // intermediate invalid values, use log
672 fValue
= exp((0.5*fDF
- 1) * log(fX
*0.5) - 0.5 * fX
- log(2.0) - GetLogGamma(0.5*fDF
));
674 else // fDF is small in most cases, we can iterate
677 if (fmod(fDF
,2.0)<0.5)
685 fValue
= 1/sqrt(fX
*2*F_PI
);
688 while ( fCount
< fDF
)
690 fValue
*= (fX
/ fCount
);
693 if (fX
>=1425.0) // underflow in e^(-x/2)
694 fValue
= exp(log(fValue
)-fX
/2);
696 fValue
*= exp(-fX
/2);
701 void ScInterpreter::ScChiSqDist()
703 sal_uInt8 nParamCount
= GetByte();
704 if ( !MustHaveParamCount( nParamCount
, 2, 3 ) )
707 if (nParamCount
== 3)
708 bCumulative
= GetBool();
711 double fDF
= ::rtl::math::approxFloor(GetDouble());
713 PushIllegalArgument();
716 double fX
= GetDouble();
718 PushDouble(GetChiSqDistCDF(fX
,fDF
));
720 PushDouble(GetChiSqDistPDF(fX
,fDF
));
724 void ScInterpreter::ScChiSqDist_MS()
726 sal_uInt8 nParamCount
= GetByte();
727 if ( !MustHaveParamCount( nParamCount
, 3, 3 ) )
729 bool bCumulative
= GetBool();
730 double fDF
= ::rtl::math::approxFloor( GetDouble() );
731 if ( fDF
< 1.0 || fDF
> 1E10
)
732 PushIllegalArgument();
735 double fX
= GetDouble();
737 PushIllegalArgument();
741 PushDouble( GetChiSqDistCDF( fX
, fDF
) );
743 PushDouble( GetChiSqDistPDF( fX
, fDF
) );
748 void ScInterpreter::ScGamma()
750 double x
= GetDouble();
751 if (x
<= 0.0 && x
== ::rtl::math::approxFloor(x
))
752 PushIllegalArgument();
755 double fResult
= GetGamma(x
);
758 PushError( nGlobalError
);
765 void ScInterpreter::ScLogGamma()
767 double x
= GetDouble();
768 if (x
> 0.0) // constraint from ODFF
769 PushDouble( GetLogGamma(x
));
771 PushIllegalArgument();
774 double ScInterpreter::GetBeta(double fAlpha
, double fBeta
)
780 fA
= fAlpha
; fB
= fBeta
;
784 fA
= fBeta
; fB
= fAlpha
;
786 if (fA
+fB
< fMaxGammaArgument
) // simple case
787 return GetGamma(fA
)/GetGamma(fA
+fB
)*GetGamma(fB
);
789 // GetLogGamma is not accurate enough, back to Lanczos for all three
790 // GetGamma and arrange factors newly.
791 const double fg
= 6.024680040776729583740234375; //see GetGamma
792 double fgm
= fg
- 0.5;
793 double fLanczos
= lcl_getLanczosSum(fA
);
794 fLanczos
/= lcl_getLanczosSum(fA
+fB
);
795 fLanczos
*= lcl_getLanczosSum(fB
);
796 double fABgm
= fA
+fB
+fgm
;
797 fLanczos
*= sqrt((fABgm
/(fA
+fgm
))/(fB
+fgm
));
798 double fTempA
= fB
/(fA
+fgm
); // (fA+fgm)/fABgm = 1 / ( 1 + fB/(fA+fgm))
799 double fTempB
= fA
/(fB
+fgm
);
800 double fResult
= exp(-fA
* ::rtl::math::log1p(fTempA
)
801 -fB
* ::rtl::math::log1p(fTempB
)-fgm
);
806 // Same as GetBeta but with logarithm
807 double ScInterpreter::GetLogBeta(double fAlpha
, double fBeta
)
813 fA
= fAlpha
; fB
= fBeta
;
817 fA
= fBeta
; fB
= fAlpha
;
819 const double fg
= 6.024680040776729583740234375; //see GetGamma
820 double fgm
= fg
- 0.5;
821 double fLanczos
= lcl_getLanczosSum(fA
);
822 fLanczos
/= lcl_getLanczosSum(fA
+fB
);
823 fLanczos
*= lcl_getLanczosSum(fB
);
824 double fLogLanczos
= log(fLanczos
);
825 double fABgm
= fA
+fB
+fgm
;
826 fLogLanczos
+= 0.5*(log(fABgm
)-log(fA
+fgm
)-log(fB
+fgm
));
827 double fTempA
= fB
/(fA
+fgm
); // (fA+fgm)/fABgm = 1 / ( 1 + fB/(fA+fgm))
828 double fTempB
= fA
/(fB
+fgm
);
829 double fResult
= -fA
* ::rtl::math::log1p(fTempA
)
830 -fB
* ::rtl::math::log1p(fTempB
)-fgm
;
831 fResult
+= fLogLanczos
;
835 // beta distribution probability density function
836 double ScInterpreter::GetBetaDistPDF(double fX
, double fA
, double fB
)
839 if (fA
== 1.0) // result b*(1-x)^(b-1)
844 return -2.0*fX
+ 2.0;
845 if (fX
== 1.0 && fB
< 1.0)
847 SetError(errIllegalArgument
);
851 return fB
+ fB
* ::rtl::math::expm1((fB
-1.0) * ::rtl::math::log1p(-fX
));
853 return fB
* pow(0.5-fX
+0.5,fB
-1.0);
855 if (fB
== 1.0) // result a*x^(a-1)
859 if (fX
== 0.0 && fA
< 1.0)
861 SetError(errIllegalArgument
);
864 return fA
* pow(fX
,fA
-1);
868 if (fA
< 1.0 && fX
== 0.0)
870 SetError(errIllegalArgument
);
878 if (fB
< 1.0 && fX
== 1.0)
880 SetError(errIllegalArgument
);
887 // normal cases; result x^(a-1)*(1-x)^(b-1)/Beta(a,b)
888 const double fLogDblMax
= log( ::std::numeric_limits
<double>::max());
889 const double fLogDblMin
= log( ::std::numeric_limits
<double>::min());
890 double fLogY
= (fX
< 0.1) ? ::rtl::math::log1p(-fX
) : log(0.5-fX
+0.5);
891 double fLogX
= log(fX
);
892 double fAm1LogX
= (fA
-1.0) * fLogX
;
893 double fBm1LogY
= (fB
-1.0) * fLogY
;
894 double fLogBeta
= GetLogBeta(fA
,fB
);
895 // check whether parts over- or underflow
896 if ( fAm1LogX
< fLogDblMax
&& fAm1LogX
> fLogDblMin
897 && fBm1LogY
< fLogDblMax
&& fBm1LogY
> fLogDblMin
898 && fLogBeta
< fLogDblMax
&& fLogBeta
> fLogDblMin
899 && fAm1LogX
+ fBm1LogY
< fLogDblMax
&& fAm1LogX
+ fBm1LogY
> fLogDblMin
)
900 return pow(fX
,fA
-1.0) * pow(0.5-fX
+0.5,fB
-1.0) / GetBeta(fA
,fB
);
901 else // need logarithm;
902 // might overflow as a whole, but seldom, not worth to pre-detect it
903 return exp( fAm1LogX
+ fBm1LogY
- fLogBeta
);
908 Ix(a,b) * result of ContFrac a * Beta(a,b)
910 static double lcl_GetBetaHelperContFrac(double fX
, double fA
, double fB
)
911 { // like old version
912 double a1
, b1
, a2
, b2
, fnorm
, apl2m
, d2m
, d2m1
, cfnew
, cf
;
914 b2
= 1.0 - (fA
+fB
)/(fA
+1.0)*fX
;
930 const double fMaxIter
= 50000.0;
931 // loop security, normal cases converge in less than 100 iterations.
932 // FIXME: You will get so much iteratons for fX near mean,
933 // I do not know a better algorithm.
934 bool bfinished
= false;
938 d2m
= rm
*(fB
-rm
)*fX
/((apl2m
-1.0)*apl2m
);
939 d2m1
= -(fA
+rm
)*(fA
+fB
+rm
)*fX
/(apl2m
*(apl2m
+1.0));
940 a1
= (a2
+d2m
*a1
)*fnorm
;
941 b1
= (b2
+d2m
*b1
)*fnorm
;
942 a2
= a1
+ d2m1
*a2
*fnorm
;
943 b2
= b1
+ d2m1
*b2
*fnorm
;
948 bfinished
= (fabs(cf
-cfnew
) < fabs(cf
)*fMachEps
);
953 while (rm
< fMaxIter
&& !bfinished
);
957 // cumulative distribution function, normalized
958 double ScInterpreter::GetBetaDist(double fXin
, double fAlpha
, double fBeta
)
961 if (fXin
<= 0.0) // values are valid, see spec
963 if (fXin
>= 1.0) // values are valid, see spec
966 return pow(fXin
, fAlpha
);
968 // 1.0 - pow(1.0-fX,fBeta) is not accurate enough
969 return -::rtl::math::expm1(fBeta
* ::rtl::math::log1p(-fXin
));
970 //FIXME: need special algorithm for fX near fP for large fA,fB
972 // I use always continued fraction, power series are neither
973 // faster nor more accurate.
974 double fY
= (0.5-fXin
)+0.5;
975 double flnY
= ::rtl::math::log1p(-fXin
);
977 double flnX
= log(fXin
);
980 bool bReflect
= fXin
> fAlpha
/(fAlpha
+fBeta
);
990 fResult
= lcl_GetBetaHelperContFrac(fX
,fA
,fB
);
991 fResult
= fResult
/fA
;
992 double fP
= fA
/(fA
+fB
);
993 double fQ
= fB
/(fA
+fB
);
995 if (fA
> 1.0 && fB
> 1.0 && fP
< 0.97 && fQ
< 0.97) //found experimental
996 fTemp
= GetBetaDistPDF(fX
,fA
,fB
)*fX
*fY
;
998 fTemp
= exp(fA
*flnX
+ fB
*flnY
- GetLogBeta(fA
,fB
));
1001 fResult
= 0.5 - fResult
+ 0.5;
1002 if (fResult
> 1.0) // ensure valid range
1009 void ScInterpreter::ScBetaDist()
1011 sal_uInt8 nParamCount
= GetByte();
1012 if ( !MustHaveParamCount( nParamCount
, 3, 6 ) ) // expanded, see #i91547#
1014 double fLowerBound
, fUpperBound
;
1015 double alpha
, beta
, x
;
1017 if (nParamCount
== 6)
1018 bIsCumulative
= GetBool();
1020 bIsCumulative
= true;
1021 if (nParamCount
>= 5)
1022 fUpperBound
= GetDouble();
1025 if (nParamCount
>= 4)
1026 fLowerBound
= GetDouble();
1030 alpha
= GetDouble();
1032 double fScale
= fUpperBound
- fLowerBound
;
1033 if (fScale
<= 0.0 || alpha
<= 0.0 || beta
<= 0.0)
1035 PushIllegalArgument();
1038 if (bIsCumulative
) // cumulative distribution function
1041 if (x
< fLowerBound
)
1043 PushDouble(0.0); return; //see spec
1045 if (x
> fUpperBound
)
1047 PushDouble(1.0); return; //see spec
1050 x
= (x
-fLowerBound
)/fScale
; // convert to standard form
1051 PushDouble(GetBetaDist(x
, alpha
, beta
));
1054 else // probability density function
1056 if (x
< fLowerBound
|| x
> fUpperBound
)
1061 x
= (x
-fLowerBound
)/fScale
;
1062 PushDouble(GetBetaDistPDF(x
, alpha
, beta
)/fScale
);
1069 Microsoft version has parameters in different order
1070 Also, upper and lowerbound are optional and have default values
1071 otherwise, function is identical with ScInterpreter::ScBetaDist()
1073 void ScInterpreter::ScBetaDist_MS()
1075 sal_uInt8 nParamCount
= GetByte();
1076 if ( !MustHaveParamCount( nParamCount
, 4, 6 ) )
1078 double fLowerBound
, fUpperBound
;
1079 double alpha
, beta
, x
;
1081 if (nParamCount
== 6)
1082 fUpperBound
= GetDouble();
1085 if (nParamCount
>= 4)
1086 fLowerBound
= GetDouble();
1089 bIsCumulative
= GetBool();
1091 alpha
= GetDouble();
1093 double fScale
= fUpperBound
- fLowerBound
;
1094 if (fScale
<= 0.0 || alpha
<= 0.0 || beta
<= 0.0)
1096 PushIllegalArgument();
1099 if (bIsCumulative
) // cumulative distribution function
1102 if (x
< fLowerBound
)
1104 PushDouble(0.0); return; //see spec
1106 if (x
> fUpperBound
)
1108 PushDouble(1.0); return; //see spec
1111 x
= (x
-fLowerBound
)/fScale
; // convert to standard form
1112 PushDouble(GetBetaDist(x
, alpha
, beta
));
1115 else // probability density function
1117 if (x
< fLowerBound
|| x
> fUpperBound
)
1122 x
= (x
-fLowerBound
)/fScale
;
1123 PushDouble(GetBetaDistPDF(x
, alpha
, beta
)/fScale
);
1128 void ScInterpreter::ScPhi()
1130 PushDouble(phi(GetDouble()));
1133 void ScInterpreter::ScGauss()
1135 PushDouble(gauss(GetDouble()));
1138 void ScInterpreter::ScFisher()
1140 double fVal
= GetDouble();
1141 if (fabs(fVal
) >= 1.0)
1142 PushIllegalArgument();
1144 PushDouble( ::rtl::math::atanh( fVal
));
1147 void ScInterpreter::ScFisherInv()
1149 PushDouble( tanh( GetDouble()));
1152 void ScInterpreter::ScFact()
1154 double nVal
= GetDouble();
1156 PushIllegalArgument();
1158 PushDouble(Fakultaet(nVal
));
1161 void ScInterpreter::ScKombin()
1163 if ( MustHaveParamCount( GetByte(), 2 ) )
1165 double k
= ::rtl::math::approxFloor(GetDouble());
1166 double n
= ::rtl::math::approxFloor(GetDouble());
1167 if (k
< 0.0 || n
< 0.0 || k
> n
)
1168 PushIllegalArgument();
1170 PushDouble(BinomKoeff(n
, k
));
1174 void ScInterpreter::ScKombin2()
1176 if ( MustHaveParamCount( GetByte(), 2 ) )
1178 double k
= ::rtl::math::approxFloor(GetDouble());
1179 double n
= ::rtl::math::approxFloor(GetDouble());
1180 if (k
< 0.0 || n
< 0.0 || k
> n
)
1181 PushIllegalArgument();
1183 PushDouble(BinomKoeff(n
+ k
- 1, k
));
1187 void ScInterpreter::ScVariationen()
1189 if ( MustHaveParamCount( GetByte(), 2 ) )
1191 double k
= ::rtl::math::approxFloor(GetDouble());
1192 double n
= ::rtl::math::approxFloor(GetDouble());
1193 if (n
< 0.0 || k
< 0.0 || k
> n
)
1194 PushIllegalArgument();
1196 PushInt(1); // (n! / (n - 0)!) == 1
1200 for (sal_uLong i
= (sal_uLong
)k
-1; i
>= 1; i
--)
1201 nVal
*= n
-(double)i
;
1207 void ScInterpreter::ScVariationen2()
1209 if ( MustHaveParamCount( GetByte(), 2 ) )
1211 double k
= ::rtl::math::approxFloor(GetDouble());
1212 double n
= ::rtl::math::approxFloor(GetDouble());
1213 if (n
< 0.0 || k
< 0.0 || k
> n
)
1214 PushIllegalArgument();
1216 PushDouble(pow(n
,k
));
1220 double ScInterpreter::GetBinomDistPMF(double x
, double n
, double p
)
1221 // used in ScB and ScBinomDist
1222 // preconditions: 0.0 <= x <= n, 0.0 < p < 1.0; x,n integral although double
1224 double q
= (0.5 - p
) + 0.5;
1225 double fFactor
= pow(q
, n
);
1226 if (fFactor
<=::std::numeric_limits
<double>::min())
1228 fFactor
= pow(p
, n
);
1229 if (fFactor
<= ::std::numeric_limits
<double>::min())
1230 return GetBetaDistPDF(p
, x
+1.0, n
-x
+1.0)/(n
+1.0);
1233 sal_uInt32 max
= static_cast<sal_uInt32
>(n
- x
);
1234 for (sal_uInt32 i
= 0; i
< max
&& fFactor
> 0.0; i
++)
1235 fFactor
*= (n
-i
)/(i
+1)*q
/p
;
1241 sal_uInt32 max
= static_cast<sal_uInt32
>(x
);
1242 for (sal_uInt32 i
= 0; i
< max
&& fFactor
> 0.0; i
++)
1243 fFactor
*= (n
-i
)/(i
+1)*p
/q
;
1248 double lcl_GetBinomDistRange(double n
, double xs
,double xe
,
1249 double fFactor
/* q^n */, double p
, double q
)
1250 //preconditions: 0.0 <= xs < xe <= n; xs,xe,n integral although double
1254 // skip summands index 0 to xs-1, start sum with index xs
1255 sal_uInt32 nXs
= static_cast<sal_uInt32
>( xs
);
1256 for (i
= 1; i
<= nXs
&& fFactor
> 0.0; i
++)
1257 fFactor
*= (n
-i
+1)/i
* p
/q
;
1258 fSum
= fFactor
; // Summand xs
1259 sal_uInt32 nXe
= static_cast<sal_uInt32
>(xe
);
1260 for (i
= nXs
+1; i
<= nXe
&& fFactor
> 0.0; i
++)
1262 fFactor
*= (n
-i
+1)/i
* p
/q
;
1265 return (fSum
>1.0) ? 1.0 : fSum
;
1268 void ScInterpreter::ScB()
1270 sal_uInt8 nParamCount
= GetByte();
1271 if ( !MustHaveParamCount( nParamCount
, 3, 4 ) )
1273 if (nParamCount
== 3) // mass function
1275 double x
= ::rtl::math::approxFloor(GetDouble());
1276 double p
= GetDouble();
1277 double n
= ::rtl::math::approxFloor(GetDouble());
1278 if (n
< 0.0 || x
< 0.0 || x
> n
|| p
< 0.0 || p
> 1.0)
1279 PushIllegalArgument();
1281 PushDouble( (x
== 0.0) ? 1.0 : 0.0 );
1283 PushDouble( (x
== n
) ? 1.0 : 0.0);
1285 PushDouble(GetBinomDistPMF(x
,n
,p
));
1288 { // nParamCount == 4
1289 double xe
= ::rtl::math::approxFloor(GetDouble());
1290 double xs
= ::rtl::math::approxFloor(GetDouble());
1291 double p
= GetDouble();
1292 double n
= ::rtl::math::approxFloor(GetDouble());
1293 double q
= (0.5 - p
) + 0.5;
1294 bool bIsValidX
= ( 0.0 <= xs
&& xs
<= xe
&& xe
<= n
);
1295 if ( bIsValidX
&& 0.0 < p
&& p
< 1.0)
1297 if (xs
== xe
) // mass function
1298 PushDouble(GetBinomDistPMF(xs
,n
,p
));
1301 double fFactor
= pow(q
, n
);
1302 if (fFactor
> ::std::numeric_limits
<double>::min())
1303 PushDouble(lcl_GetBinomDistRange(n
,xs
,xe
,fFactor
,p
,q
));
1306 fFactor
= pow(p
, n
);
1307 if (fFactor
> ::std::numeric_limits
<double>::min())
1309 // sum from j=xs to xe {(n choose j) * p^j * q^(n-j)}
1310 // = sum from i = n-xe to n-xs { (n choose i) * q^i * p^(n-i)}
1311 PushDouble(lcl_GetBinomDistRange(n
,n
-xe
,n
-xs
,fFactor
,q
,p
));
1314 PushDouble(GetBetaDist(q
,n
-xe
,xe
+1.0)-GetBetaDist(q
,n
-xs
+1,xs
) );
1320 if ( bIsValidX
) // not(0<p<1)
1323 PushDouble( (xs
== 0.0) ? 1.0 : 0.0 );
1324 else if ( p
== 1.0 )
1325 PushDouble( (xe
== n
) ? 1.0 : 0.0 );
1327 PushIllegalArgument();
1330 PushIllegalArgument();
1335 void ScInterpreter::ScBinomDist()
1337 if ( MustHaveParamCount( GetByte(), 4 ) )
1339 bool bIsCum
= GetBool(); // false=mass function; true=cumulative
1340 double p
= GetDouble();
1341 double n
= ::rtl::math::approxFloor(GetDouble());
1342 double x
= ::rtl::math::approxFloor(GetDouble());
1343 double q
= (0.5 - p
) + 0.5; // get one bit more for p near 1.0
1344 if (n
< 0.0 || x
< 0.0 || x
> n
|| p
< 0.0 || p
> 1.0)
1346 PushIllegalArgument();
1351 PushDouble( (x
==0.0 || bIsCum
) ? 1.0 : 0.0 );
1356 PushDouble( (x
==n
) ? 1.0 : 0.0);
1360 PushDouble( GetBinomDistPMF(x
,n
,p
));
1367 double fFactor
= pow(q
, n
);
1369 PushDouble(fFactor
);
1370 else if (fFactor
<= ::std::numeric_limits
<double>::min())
1372 fFactor
= pow(p
, n
);
1373 if (fFactor
<= ::std::numeric_limits
<double>::min())
1374 PushDouble(GetBetaDist(q
,n
-x
,x
+1.0));
1377 if (fFactor
> fMachEps
)
1379 double fSum
= 1.0 - fFactor
;
1380 sal_uInt32 max
= static_cast<sal_uInt32
> (n
- x
) - 1;
1381 for (sal_uInt32 i
= 0; i
< max
&& fFactor
> 0.0; i
++)
1383 fFactor
*= (n
-i
)/(i
+1)*q
/p
;
1386 PushDouble( (fSum
< 0.0) ? 0.0 : fSum
);
1389 PushDouble(lcl_GetBinomDistRange(n
,n
-x
,n
,fFactor
,q
,p
));
1393 PushDouble( lcl_GetBinomDistRange(n
,0.0,x
,fFactor
,p
,q
)) ;
1399 void ScInterpreter::ScCritBinom()
1401 if ( MustHaveParamCount( GetByte(), 3 ) )
1403 double alpha
= GetDouble();
1404 double p
= GetDouble();
1405 double n
= ::rtl::math::approxFloor(GetDouble());
1406 if (n
< 0.0 || alpha
<= 0.0 || alpha
>= 1.0 || p
< 0.0 || p
> 1.0)
1407 PushIllegalArgument();
1411 double q
= (0.5 - p
) + 0.5; // get one bit more for p near 1.0
1412 if ( q
> p
) // work from the side where the cumulative curve is
1414 // work from 0 upwards
1416 if (fFactor
> ::std::numeric_limits
<double>::min())
1418 double fSum
= fFactor
;
1419 sal_uInt32 max
= static_cast<sal_uInt32
> (n
), i
;
1420 for (i
= 0; i
< max
&& fSum
< alpha
; i
++)
1422 fFactor
*= (n
-i
)/(i
+1)*p
/q
;
1429 // accumulate BinomDist until accumulated BinomDist reaches alpha
1430 double fSum
= 0.0, x
;
1431 sal_uInt32 max
= static_cast<sal_uInt32
> (n
), i
;
1432 for (i
= 0; i
< max
&& fSum
< alpha
; i
++)
1434 x
= GetBetaDistPDF( p
, ( i
+ 1 ), ( n
- i
+ 1 ) )/( n
+ 1 );
1435 if ( !nGlobalError
)
1445 PushDouble( i
- 1 );
1450 // work from n backwards
1451 fFactor
= pow(p
, n
);
1452 if (fFactor
> ::std::numeric_limits
<double>::min())
1454 double fSum
= 1.0 - fFactor
;
1455 sal_uInt32 max
= static_cast<sal_uInt32
> (n
), i
;
1456 for (i
= 0; i
< max
&& fSum
>= alpha
; i
++)
1458 fFactor
*= (n
-i
)/(i
+1)*q
/p
;
1465 // accumulate BinomDist until accumulated BinomDist reaches alpha
1466 double fSum
= 0.0, x
;
1467 sal_uInt32 max
= static_cast<sal_uInt32
> (n
), i
;
1469 for (i
= 0; i
< max
&& fSum
< alpha
; i
++)
1471 x
= GetBetaDistPDF( q
, ( i
+ 1 ), ( n
- i
+ 1 ) )/( n
+ 1 );
1472 if ( !nGlobalError
)
1482 PushDouble( n
- i
+ 1 );
1489 void ScInterpreter::ScNegBinomDist()
1491 if ( MustHaveParamCount( GetByte(), 3 ) )
1493 double p
= GetDouble(); // p
1494 double r
= GetDouble(); // r
1495 double x
= GetDouble(); // x
1496 if (r
< 0.0 || x
< 0.0 || p
< 0.0 || p
> 1.0)
1497 PushIllegalArgument();
1501 double fFactor
= pow(p
,r
);
1502 for (double i
= 0.0; i
< x
; i
++)
1503 fFactor
*= (i
+r
)/(i
+1.0)*q
;
1504 PushDouble(fFactor
);
1509 void ScInterpreter::ScNormDist()
1511 sal_uInt8 nParamCount
= GetByte();
1512 if ( !MustHaveParamCount( nParamCount
, 3, 4))
1514 bool bCumulative
= nParamCount
== 4 ? GetBool() : true;
1515 double sigma
= GetDouble(); // standard deviation
1516 double mue
= GetDouble(); // mean
1517 double x
= GetDouble(); // x
1520 PushIllegalArgument();
1524 PushDouble(integralPhi((x
-mue
)/sigma
));
1526 PushDouble(phi((x
-mue
)/sigma
)/sigma
);
1529 void ScInterpreter::ScLogNormDist() //expanded, see #i100119#
1531 sal_uInt8 nParamCount
= GetByte();
1532 if ( !MustHaveParamCount( nParamCount
, 1, 4))
1534 bool bCumulative
= nParamCount
== 4 ? GetBool() : true; // cumulative
1535 double sigma
= nParamCount
>= 3 ? GetDouble() : 1.0; // standard deviation
1536 double mue
= nParamCount
>= 2 ? GetDouble() : 0.0; // mean
1537 double x
= GetDouble(); // x
1540 PushIllegalArgument();
1548 PushDouble(integralPhi((log(x
)-mue
)/sigma
));
1553 PushIllegalArgument();
1555 PushDouble(phi((log(x
)-mue
)/sigma
)/sigma
/x
);
1559 void ScInterpreter::ScStdNormDist()
1561 PushDouble(integralPhi(GetDouble()));
1564 void ScInterpreter::ScExpDist()
1566 if ( MustHaveParamCount( GetByte(), 3 ) )
1568 double kum
= GetDouble(); // 0 oder 1
1569 double lambda
= GetDouble(); // lambda
1570 double x
= GetDouble(); // x
1572 PushIllegalArgument();
1573 else if (kum
== 0.0) // Dichte
1576 PushDouble(lambda
* exp(-lambda
*x
));
1583 PushDouble(1.0 - exp(-lambda
*x
));
1590 void ScInterpreter::ScTDist()
1592 if ( !MustHaveParamCount( GetByte(), 3 ) )
1594 double fFlag
= ::rtl::math::approxFloor(GetDouble());
1595 double fDF
= ::rtl::math::approxFloor(GetDouble());
1596 double T
= GetDouble();
1597 if (fDF
< 1.0 || T
< 0.0 || (fFlag
!= 1.0 && fFlag
!= 2.0) )
1599 PushIllegalArgument();
1602 double R
= GetTDist(T
, fDF
);
1609 void ScInterpreter::ScFDist()
1611 if ( !MustHaveParamCount( GetByte(), 3 ) )
1613 double fF2
= ::rtl::math::approxFloor(GetDouble());
1614 double fF1
= ::rtl::math::approxFloor(GetDouble());
1615 double fF
= GetDouble();
1616 if (fF
< 0.0 || fF1
< 1.0 || fF2
< 1.0 || fF1
>= 1.0E10
|| fF2
>= 1.0E10
)
1618 PushIllegalArgument();
1621 PushDouble(GetFDist(fF
, fF1
, fF2
));
1624 void ScInterpreter::ScFDist_LT()
1626 if ( !MustHaveParamCount( GetByte(), 4 ) )
1628 bool bCum
= GetBool();
1629 double fF2
= ::rtl::math::approxFloor( GetDouble() );
1630 double fF1
= ::rtl::math::approxFloor( GetDouble() );
1631 double fF
= GetDouble();
1632 if ( fF
< 0.0 || fF1
< 1.0 || fF2
< 1.0 || fF1
>= 1.0E10
|| fF2
>= 1.0E10
)
1634 PushIllegalArgument();
1639 // left tail cumulative distribution
1640 PushDouble( 1.0 - GetFDist( fF
, fF1
, fF2
) );
1644 // probability density function
1645 PushDouble( pow( fF1
/ fF2
, fF1
/ 2 ) * pow( fF
, ( fF1
/ 2 ) - 1 ) /
1646 ( pow( ( 1 + ( fF
* fF1
/ fF2
) ), ( fF1
+ fF2
) / 2 ) *
1647 GetBeta( fF1
/ 2, fF2
/ 2 ) ) );
1651 void ScInterpreter::ScChiDist()
1654 if ( !MustHaveParamCount( GetByte(), 2 ) )
1656 double fDF
= ::rtl::math::approxFloor(GetDouble());
1657 double fChi
= GetDouble();
1658 if (fDF
< 1.0) // x<=0 returns 1, see ODFF 6.17.10
1660 PushIllegalArgument();
1663 fResult
= GetChiDist( fChi
, fDF
);
1666 PushError( nGlobalError
);
1669 PushDouble(fResult
);
1672 void ScInterpreter::ScWeibull()
1674 if ( MustHaveParamCount( GetByte(), 4 ) )
1676 double kum
= GetDouble(); // 0 oder 1
1677 double beta
= GetDouble(); // beta
1678 double alpha
= GetDouble(); // alpha
1679 double x
= GetDouble(); // x
1680 if (alpha
<= 0.0 || beta
<= 0.0 || x
< 0.0)
1681 PushIllegalArgument();
1682 else if (kum
== 0.0) // Dichte
1683 PushDouble(alpha
/pow(beta
,alpha
)*pow(x
,alpha
-1.0)*
1684 exp(-pow(x
/beta
,alpha
)));
1686 PushDouble(1.0 - exp(-pow(x
/beta
,alpha
)));
1690 void ScInterpreter::ScPoissonDist()
1692 sal_uInt8 nParamCount
= GetByte();
1693 if ( MustHaveParamCount( nParamCount
, 2, 3 ) )
1695 bool bCumulative
= (nParamCount
== 3 ? GetBool() : true); // default cumulative
1696 double lambda
= GetDouble(); // Mean
1697 double x
= ::rtl::math::approxFloor(GetDouble()); // discrete distribution
1698 if (lambda
< 0.0 || x
< 0.0)
1699 PushIllegalArgument();
1700 else if (!bCumulative
) // Probability mass function
1706 if (lambda
>712) // underflow in exp(-lambda)
1707 { // accuracy 11 Digits
1708 PushDouble( exp(x
*log(lambda
)-lambda
-GetLogGamma(x
+1.0)));
1712 double fPoissonVar
= 1.0;
1713 for ( double f
= 0.0; f
< x
; ++f
)
1714 fPoissonVar
*= lambda
/ ( f
+ 1.0 );
1715 PushDouble( fPoissonVar
* exp( -lambda
) );
1719 else // Cumulative distribution function
1725 if (lambda
> 712 ) // underflow in exp(-lambda)
1726 { // accuracy 12 Digits
1727 PushDouble(GetUpRegIGamma(x
+1.0,lambda
));
1731 if (x
>= 936.0) // result is always undistinghable from 1
1735 double fSummand
= exp(-lambda
);
1736 double fSum
= fSummand
;
1737 int nEnd
= sal::static_int_cast
<int>( x
);
1738 for (int i
= 1; i
<= nEnd
; i
++)
1740 fSummand
= (fSummand
* lambda
)/(double)i
;
1751 /** Local function used in the calculation of the hypergeometric distribution.
1753 static void lcl_PutFactorialElements( ::std::vector
< double >& cn
, double fLower
, double fUpper
, double fBase
)
1755 for ( double i
= fLower
; i
<= fUpper
; ++i
)
1757 double fVal
= fBase
- i
;
1759 cn
.push_back( fVal
);
1763 /** Calculates a value of the hypergeometric distribution.
1765 @author Kohei Yoshida <kohei@openoffice.org>
1770 void ScInterpreter::ScHypGeomDist()
1772 if ( !MustHaveParamCount( GetByte(), 4 ) )
1775 double N
= ::rtl::math::approxFloor(GetDouble());
1776 double M
= ::rtl::math::approxFloor(GetDouble());
1777 double n
= ::rtl::math::approxFloor(GetDouble());
1778 double x
= ::rtl::math::approxFloor(GetDouble());
1780 if( (x
< 0.0) || (n
< x
) || (M
< x
) || (N
< n
) || (N
< M
) || (x
< n
- N
+ M
) )
1782 PushIllegalArgument();
1786 PushDouble( GetHypGeomDist( x
, n
, M
, N
) );
1789 /** Calculates a value of the hypergeometric distribution (Excel 2010 function).
1791 This function has an extra argument bCumulative as compared to ScHypGeomDist(),
1792 which only calculates the non-cumulative distribution.
1796 void ScInterpreter::ScHypGeomDist_MS()
1798 if ( !MustHaveParamCount( GetByte(), 5 ) )
1801 bool bCumulative
= GetBool();
1802 double N
= ::rtl::math::approxFloor(GetDouble());
1803 double M
= ::rtl::math::approxFloor(GetDouble());
1804 double n
= ::rtl::math::approxFloor(GetDouble());
1805 double x
= ::rtl::math::approxFloor(GetDouble());
1807 if( (x
< 0.0) || (n
< x
) || (M
< x
) || (N
< n
) || (N
< M
) || (x
< n
- N
+ M
) )
1809 PushIllegalArgument();
1817 for ( int i
= 0; i
<= x
&& !nGlobalError
; i
++ )
1818 fVal
+= GetHypGeomDist( i
, n
, M
, N
);
1823 PushDouble( GetHypGeomDist( x
, n
, M
, N
) );
1826 /** Calculates a value of the hypergeometric distribution.
1828 The algorithm is designed to avoid unnecessary multiplications and division
1829 by expanding all factorial elements (9 of them). It is done by excluding
1830 those ranges that overlap in the numerator and the denominator. This allows
1831 for a fast calculation for large values which would otherwise cause an overflow
1832 in the intermediate values.
1834 @author Kohei Yoshida <kohei@openoffice.org>
1839 double ScInterpreter::GetHypGeomDist( double x
, double n
, double M
, double N
)
1841 const size_t nMaxArraySize
= 500000; // arbitrary max array size
1843 typedef ::std::vector
< double > HypContainer
;
1844 HypContainer cnNumer
, cnDenom
;
1846 size_t nEstContainerSize
= static_cast<size_t>( x
+ ::std::min( n
, M
) );
1847 size_t nMaxSize
= ::std::min( cnNumer
.max_size(), nMaxArraySize
);
1848 if ( nEstContainerSize
> nMaxSize
)
1853 cnNumer
.reserve( nEstContainerSize
+ 10 );
1854 cnDenom
.reserve( nEstContainerSize
+ 10 );
1856 // Trim coefficient C first
1857 double fCNumVarUpper
= N
- n
- M
+ x
- 1.0;
1858 double fCDenomVarLower
= 1.0;
1859 if ( N
- n
- M
+ x
>= M
- x
+ 1.0 )
1861 fCNumVarUpper
= M
- x
- 1.0;
1862 fCDenomVarLower
= N
- n
- 2.0*(M
- x
) + 1.0;
1865 #if OSL_DEBUG_LEVEL > 0
1866 double fCNumLower
= N
- n
- fCNumVarUpper
;
1868 double fCDenomUpper
= N
- n
- M
+ x
+ 1.0 - fCDenomVarLower
;
1870 double fDNumVarLower
= n
- M
;
1874 if ( N
- M
< n
+ 1.0 )
1878 if ( N
- n
< n
+ 1.0 )
1881 lcl_PutFactorialElements( cnNumer
, 0.0, fCNumVarUpper
, N
- n
);
1882 lcl_PutFactorialElements( cnDenom
, 0.0, N
- n
- 1.0, N
);
1887 OSL_ENSURE( fCNumLower
< n
+ 1.0, "ScHypGeomDist: wrong assertion" );
1888 lcl_PutFactorialElements( cnNumer
, N
- 2.0*n
, fCNumVarUpper
, N
- n
);
1889 lcl_PutFactorialElements( cnDenom
, 0.0, n
- 1.0, N
);
1892 OSL_ENSURE( fCDenomUpper
<= N
- M
, "ScHypGeomDist: wrong assertion" );
1894 if ( fCDenomUpper
< n
- x
+ 1.0 )
1896 lcl_PutFactorialElements( cnNumer
, 1.0, N
- M
- n
+ x
, N
- M
+ 1.0 );
1900 lcl_PutFactorialElements( cnNumer
, 1.0, N
- M
- fCDenomUpper
, N
- M
+ 1.0 );
1902 fCDenomUpper
= n
- x
;
1903 fCDenomVarLower
= N
- M
- 2.0*(n
- x
) + 1.0;
1913 lcl_PutFactorialElements( cnNumer
, 0.0, fCNumVarUpper
, N
- n
);
1914 lcl_PutFactorialElements( cnDenom
, 0.0, M
- 1.0, N
);
1918 lcl_PutFactorialElements( cnNumer
, M
- n
, fCNumVarUpper
, N
- n
);
1919 lcl_PutFactorialElements( cnDenom
, 0.0, n
- 1.0, N
);
1922 OSL_ENSURE( fCDenomUpper
<= n
, "ScHypGeomDist: wrong assertion" );
1924 if ( fCDenomUpper
< n
- x
+ 1.0 )
1926 lcl_PutFactorialElements( cnNumer
, N
- M
- n
+ 1.0, N
- M
- n
+ x
, N
- M
+ 1.0 );
1929 lcl_PutFactorialElements( cnNumer
, N
- M
- n
+ 1.0, N
- M
- fCDenomUpper
, N
- M
+ 1.0 );
1930 fCDenomUpper
= n
- x
;
1931 fCDenomVarLower
= N
- M
- 2.0*(n
- x
) + 1.0;
1935 OSL_ENSURE( fCDenomUpper
<= M
, "ScHypGeomDist: wrong assertion" );
1939 if ( N
- M
< M
+ 1.0 )
1943 if ( N
- n
< M
+ 1.0 )
1946 lcl_PutFactorialElements( cnNumer
, 0.0, fCNumVarUpper
, N
- n
);
1947 lcl_PutFactorialElements( cnDenom
, 0.0, N
- M
- 1.0, N
);
1951 lcl_PutFactorialElements( cnNumer
, N
- n
- M
, fCNumVarUpper
, N
- n
);
1952 lcl_PutFactorialElements( cnDenom
, 0.0, n
- 1.0, N
);
1955 if ( n
- x
+ 1.0 > fCDenomUpper
)
1957 lcl_PutFactorialElements( cnNumer
, 1.0, N
- M
- n
+ x
, N
- M
+ 1.0 );
1961 lcl_PutFactorialElements( cnNumer
, 1.0, N
- M
- fCDenomUpper
, N
- M
+ 1.0 );
1963 fCDenomVarLower
= N
- M
- 2.0*(n
- x
) + 1.0;
1964 fCDenomUpper
= n
- x
;
1971 OSL_ENSURE( M
>= n
- x
, "ScHypGeomDist: wrong assertion" );
1972 OSL_ENSURE( M
- x
<= N
- M
+ 1.0, "ScHypGeomDist: wrong assertion" );
1974 if ( N
- n
< N
- M
+ 1.0 )
1977 lcl_PutFactorialElements( cnNumer
, 0.0, fCNumVarUpper
, N
- n
);
1978 lcl_PutFactorialElements( cnDenom
, 0.0, M
- 1.0, N
);
1983 OSL_ENSURE( fCNumLower
<= N
- M
+ 1.0, "ScHypGeomDist: wrong assertion" );
1984 lcl_PutFactorialElements( cnNumer
, M
- n
, fCNumVarUpper
, N
- n
);
1985 lcl_PutFactorialElements( cnDenom
, 0.0, n
- 1.0, N
);
1988 if ( n
- x
+ 1.0 > fCDenomUpper
)
1990 lcl_PutFactorialElements( cnNumer
, N
- 2.0*M
+ 1.0, N
- M
- n
+ x
, N
- M
+ 1.0 );
1991 else if ( M
>= fCDenomUpper
)
1993 lcl_PutFactorialElements( cnNumer
, N
- 2.0*M
+ 1.0, N
- M
- fCDenomUpper
, N
- M
+ 1.0 );
1995 fCDenomUpper
= n
- x
;
1996 fCDenomVarLower
= N
- M
- 2.0*(n
- x
) + 1.0;
2000 OSL_ENSURE( M
<= fCDenomUpper
, "ScHypGeomDist: wrong assertion" );
2001 lcl_PutFactorialElements( cnDenom
, fCDenomVarLower
, N
- n
- 2.0*M
+ x
,
2002 N
- n
- M
+ x
+ 1.0 );
2004 fCDenomUpper
= n
- x
;
2005 fCDenomVarLower
= N
- M
- 2.0*(n
- x
) + 1.0;
2009 OSL_ENSURE( fCDenomUpper
<= n
, "ScHypGeomDist: wrong assertion" );
2011 fDNumVarLower
= 0.0;
2014 double nDNumVarUpper
= fCDenomUpper
< x
+ 1.0 ? n
- x
- 1.0 : n
- fCDenomUpper
- 1.0;
2015 double nDDenomVarLower
= fCDenomUpper
< x
+ 1.0 ? fCDenomVarLower
: N
- n
- M
+ 1.0;
2016 lcl_PutFactorialElements( cnNumer
, fDNumVarLower
, nDNumVarUpper
, n
);
2017 lcl_PutFactorialElements( cnDenom
, nDDenomVarLower
, N
- n
- M
+ x
, N
- n
- M
+ x
+ 1.0 );
2019 ::std::sort( cnNumer
.begin(), cnNumer
.end() );
2020 ::std::sort( cnDenom
.begin(), cnDenom
.end() );
2021 HypContainer::reverse_iterator it1
= cnNumer
.rbegin(), it1End
= cnNumer
.rend();
2022 HypContainer::reverse_iterator it2
= cnDenom
.rbegin(), it2End
= cnDenom
.rend();
2024 double fFactor
= 1.0;
2025 for ( ; it1
!= it1End
|| it2
!= it2End
; )
2027 double fEnum
= 1.0, fDenom
= 1.0;
2028 if ( it1
!= it1End
)
2030 if ( it2
!= it2End
)
2032 fFactor
*= fEnum
/ fDenom
;
2038 void ScInterpreter::ScGammaDist()
2040 sal_uInt8 nParamCount
= GetByte();
2041 if ( !MustHaveParamCount( nParamCount
, 3, 4 ) )
2044 if (nParamCount
== 4)
2045 bCumulative
= GetBool();
2048 double fBeta
= GetDouble(); // scale
2049 double fAlpha
= GetDouble(); // shape
2050 double fX
= GetDouble(); // x
2051 if (fAlpha
<= 0.0 || fBeta
<= 0.0)
2052 PushIllegalArgument();
2055 if (bCumulative
) // distribution
2056 PushDouble( GetGammaDist( fX
, fAlpha
, fBeta
));
2058 PushDouble( GetGammaDistPDF( fX
, fAlpha
, fBeta
));
2062 void ScInterpreter::ScNormInv()
2064 if ( MustHaveParamCount( GetByte(), 3 ) )
2066 double sigma
= GetDouble();
2067 double mue
= GetDouble();
2068 double x
= GetDouble();
2069 if (sigma
<= 0.0 || x
< 0.0 || x
> 1.0)
2070 PushIllegalArgument();
2071 else if (x
== 0.0 || x
== 1.0)
2074 PushDouble(gaussinv(x
)*sigma
+ mue
);
2078 void ScInterpreter::ScSNormInv()
2080 double x
= GetDouble();
2081 if (x
< 0.0 || x
> 1.0)
2082 PushIllegalArgument();
2083 else if (x
== 0.0 || x
== 1.0)
2086 PushDouble(gaussinv(x
));
2089 void ScInterpreter::ScLogNormInv()
2091 if ( MustHaveParamCount( GetByte(), 3 ) )
2093 double sigma
= GetDouble(); // Stdabw
2094 double mue
= GetDouble(); // Mittelwert
2095 double y
= GetDouble(); // y
2096 if (sigma
<= 0.0 || y
<= 0.0 || y
>= 1.0)
2097 PushIllegalArgument();
2099 PushDouble(exp(mue
+sigma
*gaussinv(y
)));
2103 class ScGammaDistFunction
: public ScDistFunc
2105 ScInterpreter
& rInt
;
2106 double fp
, fAlpha
, fBeta
;
2109 ScGammaDistFunction( ScInterpreter
& rI
, double fpVal
, double fAlphaVal
, double fBetaVal
) :
2110 rInt(rI
), fp(fpVal
), fAlpha(fAlphaVal
), fBeta(fBetaVal
) {}
2112 virtual ~ScGammaDistFunction() {}
2114 double GetValue( double x
) const { return fp
- rInt
.GetGammaDist(x
, fAlpha
, fBeta
); }
2117 void ScInterpreter::ScGammaInv()
2119 if ( !MustHaveParamCount( GetByte(), 3 ) )
2121 double fBeta
= GetDouble();
2122 double fAlpha
= GetDouble();
2123 double fP
= GetDouble();
2124 if (fAlpha
<= 0.0 || fBeta
<= 0.0 || fP
< 0.0 || fP
>= 1.0 )
2126 PushIllegalArgument();
2134 ScGammaDistFunction
aFunc( *this, fP
, fAlpha
, fBeta
);
2135 double fStart
= fAlpha
* fBeta
;
2136 double fVal
= lcl_IterateInverse( aFunc
, fStart
*0.5, fStart
, bConvError
);
2138 SetError(errNoConvergence
);
2143 class ScBetaDistFunction
: public ScDistFunc
2145 ScInterpreter
& rInt
;
2146 double fp
, fAlpha
, fBeta
;
2149 ScBetaDistFunction( ScInterpreter
& rI
, double fpVal
, double fAlphaVal
, double fBetaVal
) :
2150 rInt(rI
), fp(fpVal
), fAlpha(fAlphaVal
), fBeta(fBetaVal
) {}
2152 virtual ~ScBetaDistFunction() {}
2154 double GetValue( double x
) const { return fp
- rInt
.GetBetaDist(x
, fAlpha
, fBeta
); }
2157 void ScInterpreter::ScBetaInv()
2159 sal_uInt8 nParamCount
= GetByte();
2160 if ( !MustHaveParamCount( nParamCount
, 3, 5 ) )
2162 double fP
, fA
, fB
, fAlpha
, fBeta
;
2163 if (nParamCount
== 5)
2167 if (nParamCount
>= 4)
2171 fBeta
= GetDouble();
2172 fAlpha
= GetDouble();
2174 if (fP
< 0.0 || fP
>= 1.0 || fA
== fB
|| fAlpha
<= 0.0 || fBeta
<= 0.0)
2176 PushIllegalArgument();
2184 ScBetaDistFunction
aFunc( *this, fP
, fAlpha
, fBeta
);
2185 // 0..1 as range for iteration so it isn't extended beyond the valid range
2186 double fVal
= lcl_IterateInverse( aFunc
, 0.0, 1.0, bConvError
);
2188 PushError( errNoConvergence
);
2190 PushDouble(fA
+ fVal
*(fB
-fA
)); // scale to (A,B)
2194 // Achtung: T, F und Chi
2195 // sind monoton fallend,
2196 // deshalb 1-Dist als Funktion
2198 class ScTDistFunction
: public ScDistFunc
2200 ScInterpreter
& rInt
;
2204 ScTDistFunction( ScInterpreter
& rI
, double fpVal
, double fDFVal
) :
2205 rInt(rI
), fp(fpVal
), fDF(fDFVal
) {}
2207 virtual ~ScTDistFunction() {}
2209 double GetValue( double x
) const { return fp
- 2 * rInt
.GetTDist(x
, fDF
); }
2212 void ScInterpreter::ScTInv()
2214 if ( !MustHaveParamCount( GetByte(), 2 ) )
2216 double fDF
= ::rtl::math::approxFloor(GetDouble());
2217 double fP
= GetDouble();
2218 if (fDF
< 1.0 || fDF
> 1.0E10
|| fP
<= 0.0 || fP
> 1.0 )
2220 PushIllegalArgument();
2223 PushDouble( GetTInv( fP
, fDF
) );
2226 double ScInterpreter::GetTInv( double fAlpha
, double fSize
)
2229 ScTDistFunction
aFunc( *this, fAlpha
, fSize
);
2230 double fVal
= lcl_IterateInverse( aFunc
, fSize
* 0.5, fSize
, bConvError
);
2232 SetError(errNoConvergence
);
2236 class ScFDistFunction
: public ScDistFunc
2238 ScInterpreter
& rInt
;
2239 double fp
, fF1
, fF2
;
2242 ScFDistFunction( ScInterpreter
& rI
, double fpVal
, double fF1Val
, double fF2Val
) :
2243 rInt(rI
), fp(fpVal
), fF1(fF1Val
), fF2(fF2Val
) {}
2245 virtual ~ScFDistFunction() {}
2247 double GetValue( double x
) const { return fp
- rInt
.GetFDist(x
, fF1
, fF2
); }
2250 void ScInterpreter::ScFInv()
2252 if ( !MustHaveParamCount( GetByte(), 3 ) )
2254 double fF2
= ::rtl::math::approxFloor(GetDouble());
2255 double fF1
= ::rtl::math::approxFloor(GetDouble());
2256 double fP
= GetDouble();
2257 if (fP
<= 0.0 || fF1
< 1.0 || fF2
< 1.0 || fF1
>= 1.0E10
|| fF2
>= 1.0E10
|| fP
> 1.0)
2259 PushIllegalArgument();
2264 ScFDistFunction
aFunc( *this, fP
, fF1
, fF2
);
2265 double fVal
= lcl_IterateInverse( aFunc
, fF1
*0.5, fF1
, bConvError
);
2267 SetError(errNoConvergence
);
2271 void ScInterpreter::ScFInv_LT()
2273 if ( !MustHaveParamCount( GetByte(), 3 ) )
2275 double fF2
= ::rtl::math::approxFloor(GetDouble());
2276 double fF1
= ::rtl::math::approxFloor(GetDouble());
2277 double fP
= GetDouble();
2278 if (fP
<= 0.0 || fF1
< 1.0 || fF2
< 1.0 || fF1
>= 1.0E10
|| fF2
>= 1.0E10
|| fP
> 1.0)
2280 PushIllegalArgument();
2285 ScFDistFunction
aFunc( *this, ( 1.0 - fP
), fF1
, fF2
);
2286 double fVal
= lcl_IterateInverse( aFunc
, fF1
*0.5, fF1
, bConvError
);
2288 SetError(errNoConvergence
);
2292 class ScChiDistFunction
: public ScDistFunc
2294 ScInterpreter
& rInt
;
2298 ScChiDistFunction( ScInterpreter
& rI
, double fpVal
, double fDFVal
) :
2299 rInt(rI
), fp(fpVal
), fDF(fDFVal
) {}
2301 virtual ~ScChiDistFunction() {}
2303 double GetValue( double x
) const { return fp
- rInt
.GetChiDist(x
, fDF
); }
2306 void ScInterpreter::ScChiInv()
2308 if ( !MustHaveParamCount( GetByte(), 2 ) )
2310 double fDF
= ::rtl::math::approxFloor(GetDouble());
2311 double fP
= GetDouble();
2312 if (fDF
< 1.0 || fP
<= 0.0 || fP
> 1.0 )
2314 PushIllegalArgument();
2319 ScChiDistFunction
aFunc( *this, fP
, fDF
);
2320 double fVal
= lcl_IterateInverse( aFunc
, fDF
*0.5, fDF
, bConvError
);
2322 SetError(errNoConvergence
);
2326 /***********************************************/
2327 class ScChiSqDistFunction
: public ScDistFunc
2329 ScInterpreter
& rInt
;
2333 ScChiSqDistFunction( ScInterpreter
& rI
, double fpVal
, double fDFVal
) :
2334 rInt(rI
), fp(fpVal
), fDF(fDFVal
) {}
2336 virtual ~ScChiSqDistFunction() {}
2338 double GetValue( double x
) const { return fp
- rInt
.GetChiSqDistCDF(x
, fDF
); }
2341 void ScInterpreter::ScChiSqInv()
2343 if ( !MustHaveParamCount( GetByte(), 2 ) )
2345 double fDF
= ::rtl::math::approxFloor(GetDouble());
2346 double fP
= GetDouble();
2347 if (fDF
< 1.0 || fP
< 0.0 || fP
>= 1.0 )
2349 PushIllegalArgument();
2354 ScChiSqDistFunction
aFunc( *this, fP
, fDF
);
2355 double fVal
= lcl_IterateInverse( aFunc
, fDF
*0.5, fDF
, bConvError
);
2357 SetError(errNoConvergence
);
2361 void ScInterpreter::ScConfidence()
2363 if ( MustHaveParamCount( GetByte(), 3 ) )
2365 double n
= ::rtl::math::approxFloor(GetDouble());
2366 double sigma
= GetDouble();
2367 double alpha
= GetDouble();
2368 if (sigma
<= 0.0 || alpha
<= 0.0 || alpha
>= 1.0 || n
< 1.0)
2369 PushIllegalArgument();
2371 PushDouble( gaussinv(1.0-alpha
/2.0) * sigma
/sqrt(n
) );
2375 void ScInterpreter::ScConfidenceT()
2377 if ( MustHaveParamCount( GetByte(), 3 ) )
2379 double n
= ::rtl::math::approxFloor(GetDouble());
2380 double sigma
= GetDouble();
2381 double alpha
= GetDouble();
2382 if (sigma
<= 0.0 || alpha
<= 0.0 || alpha
>= 1.0 || n
< 1.0)
2383 PushIllegalArgument();
2385 PushDouble( sigma
* GetTInv( alpha
, n
- 1 ) / sqrt( n
) );
2389 void ScInterpreter::ScZTest()
2391 sal_uInt8 nParamCount
= GetByte();
2392 if ( !MustHaveParamCount( nParamCount
, 2, 3 ) )
2394 double sigma
= 0.0, mue
, x
;
2395 if (nParamCount
== 3)
2397 sigma
= GetDouble();
2400 PushIllegalArgument();
2407 double fSumSqr
= 0.0;
2409 double rValCount
= 0.0;
2410 switch (GetStackType())
2412 case formula::svDouble
:
2416 fSumSqr
+= fVal
*fVal
;
2423 PopSingleRef( aAdr
);
2424 ScRefCellValue aCell
;
2425 aCell
.assign(*pDok
, aAdr
);
2426 if (aCell
.hasNumeric())
2428 fVal
= GetCellValue(aAdr
, aCell
);
2430 fSumSqr
+= fVal
*fVal
;
2436 case formula::svDoubleRef
:
2439 size_t nRefInList
= 0;
2440 while (nParam
-- > 0)
2443 sal_uInt16 nErr
= 0;
2444 PopDoubleRef( aRange
, nParam
, nRefInList
);
2445 ScValueIterator
aValIter(pDok
, aRange
, glSubTotal
);
2446 if (aValIter
.GetFirst(fVal
, nErr
))
2449 fSumSqr
+= fVal
*fVal
;
2451 while ((nErr
== 0) && aValIter
.GetNext(fVal
, nErr
))
2454 fSumSqr
+= fVal
*fVal
;
2463 case svExternalSingleRef
:
2464 case svExternalDoubleRef
:
2466 ScMatrixRef pMat
= GetMatrix();
2469 SCSIZE nCount
= pMat
->GetElementCount();
2470 if (pMat
->IsNumeric())
2472 for ( SCSIZE i
= 0; i
< nCount
; i
++ )
2474 fVal
= pMat
->GetDouble(i
);
2476 fSumSqr
+= fVal
* fVal
;
2482 for (SCSIZE i
= 0; i
< nCount
; i
++)
2483 if (!pMat
->IsString(i
))
2485 fVal
= pMat
->GetDouble(i
);
2487 fSumSqr
+= fVal
* fVal
;
2494 default : SetError(errIllegalParameter
); break;
2496 if (rValCount
<= 1.0)
2497 PushError( errDivisionByZero
);
2500 mue
= fSum
/rValCount
;
2501 if (nParamCount
!= 3)
2503 sigma
= (fSumSqr
- fSum
*fSum
/rValCount
)/(rValCount
-1.0);
2504 PushDouble(0.5 - gauss((mue
-x
)/sqrt(sigma
/rValCount
)));
2507 PushDouble(0.5 - gauss((mue
-x
)*sqrt(rValCount
)/sigma
));
2510 bool ScInterpreter::CalculateTest(bool _bTemplin
2511 ,const SCSIZE nC1
, const SCSIZE nC2
,const SCSIZE nR1
,const SCSIZE nR2
2512 ,const ScMatrixRef
& pMat1
,const ScMatrixRef
& pMat2
2513 ,double& fT
,double& fF
)
2515 double fCount1
= 0.0;
2516 double fCount2
= 0.0;
2518 double fSumSqr1
= 0.0;
2520 double fSumSqr2
= 0.0;
2523 for (i
= 0; i
< nC1
; i
++)
2524 for (j
= 0; j
< nR1
; j
++)
2526 if (!pMat1
->IsString(i
,j
))
2528 fVal
= pMat1
->GetDouble(i
,j
);
2530 fSumSqr1
+= fVal
* fVal
;
2534 for (i
= 0; i
< nC2
; i
++)
2535 for (j
= 0; j
< nR2
; j
++)
2537 if (!pMat2
->IsString(i
,j
))
2539 fVal
= pMat2
->GetDouble(i
,j
);
2541 fSumSqr2
+= fVal
* fVal
;
2545 if (fCount1
< 2.0 || fCount2
< 2.0)
2549 } // if (fCount1 < 2.0 || fCount2 < 2.0)
2552 double fS1
= (fSumSqr1
-fSum1
*fSum1
/fCount1
)/(fCount1
-1.0)/fCount1
;
2553 double fS2
= (fSumSqr2
-fSum2
*fSum2
/fCount2
)/(fCount2
-1.0)/fCount2
;
2554 if (fS1
+ fS2
== 0.0)
2559 fT
= fabs(fSum1
/fCount1
- fSum2
/fCount2
)/sqrt(fS1
+fS2
);
2560 double c
= fS1
/(fS1
+fS2
);
2561 // GetTDist wird mit GetBetaDist berechnet und kommt auch mit nicht ganzzahligen
2562 // Freiheitsgraden klar. Dann stimmt das Ergebnis auch mit Excel ueberein (#52406#):
2563 fF
= 1.0/(c
*c
/(fCount1
-1.0)+(1.0-c
)*(1.0-c
)/(fCount2
-1.0));
2567 // laut Bronstein-Semendjajew
2568 double fS1
= (fSumSqr1
- fSum1
*fSum1
/fCount1
) / (fCount1
- 1.0); // Varianz
2569 double fS2
= (fSumSqr2
- fSum2
*fSum2
/fCount2
) / (fCount2
- 1.0);
2570 fT
= fabs( fSum1
/fCount1
- fSum2
/fCount2
) /
2571 sqrt( (fCount1
-1.0)*fS1
+ (fCount2
-1.0)*fS2
) *
2572 sqrt( fCount1
*fCount2
*(fCount1
+fCount2
-2)/(fCount1
+fCount2
) );
2573 fF
= fCount1
+ fCount2
- 2;
2577 void ScInterpreter::ScTTest()
2579 if ( !MustHaveParamCount( GetByte(), 4 ) )
2581 double fTyp
= ::rtl::math::approxFloor(GetDouble());
2582 double fAnz
= ::rtl::math::approxFloor(GetDouble());
2583 if (fAnz
!= 1.0 && fAnz
!= 2.0)
2585 PushIllegalArgument();
2589 ScMatrixRef pMat2
= GetMatrix();
2590 ScMatrixRef pMat1
= GetMatrix();
2591 if (!pMat1
|| !pMat2
)
2593 PushIllegalParameter();
2600 pMat1
->GetDimensions(nC1
, nR1
);
2601 pMat2
->GetDimensions(nC2
, nR2
);
2604 if (nC1
!= nC2
|| nR1
!= nR2
)
2606 PushIllegalArgument();
2609 double fCount
= 0.0;
2612 double fSumSqrD
= 0.0;
2613 double fVal1
, fVal2
;
2614 for (i
= 0; i
< nC1
; i
++)
2615 for (j
= 0; j
< nR1
; j
++)
2617 if (!pMat1
->IsString(i
,j
) && !pMat2
->IsString(i
,j
))
2619 fVal1
= pMat1
->GetDouble(i
,j
);
2620 fVal2
= pMat2
->GetDouble(i
,j
);
2623 fSumSqrD
+= (fVal1
- fVal2
)*(fVal1
- fVal2
);
2632 fT
= sqrt(fCount
-1.0) * fabs(fSum1
- fSum2
) /
2633 sqrt(fCount
* fSumSqrD
- (fSum1
-fSum2
)*(fSum1
-fSum2
));
2636 else if (fTyp
== 2.0)
2638 CalculateTest(false,nC1
, nC2
,nR1
, nR2
,pMat1
,pMat2
,fT
,fF
);
2640 else if (fTyp
== 3.0)
2642 CalculateTest(true,nC1
, nC2
,nR1
, nR2
,pMat1
,pMat2
,fT
,fF
);
2647 PushIllegalArgument();
2651 PushDouble(GetTDist(fT
, fF
));
2653 PushDouble(2.0*GetTDist(fT
, fF
));
2656 void ScInterpreter::ScFTest()
2658 if ( !MustHaveParamCount( GetByte(), 2 ) )
2660 ScMatrixRef pMat2
= GetMatrix();
2661 ScMatrixRef pMat1
= GetMatrix();
2662 if (!pMat1
|| !pMat2
)
2664 PushIllegalParameter();
2670 pMat1
->GetDimensions(nC1
, nR1
);
2671 pMat2
->GetDimensions(nC2
, nR2
);
2672 double fCount1
= 0.0;
2673 double fCount2
= 0.0;
2675 double fSumSqr1
= 0.0;
2677 double fSumSqr2
= 0.0;
2679 for (i
= 0; i
< nC1
; i
++)
2680 for (j
= 0; j
< nR1
; j
++)
2682 if (!pMat1
->IsString(i
,j
))
2684 fVal
= pMat1
->GetDouble(i
,j
);
2686 fSumSqr1
+= fVal
* fVal
;
2690 for (i
= 0; i
< nC2
; i
++)
2691 for (j
= 0; j
< nR2
; j
++)
2693 if (!pMat2
->IsString(i
,j
))
2695 fVal
= pMat2
->GetDouble(i
,j
);
2697 fSumSqr2
+= fVal
* fVal
;
2701 if (fCount1
< 2.0 || fCount2
< 2.0)
2706 double fS1
= (fSumSqr1
-fSum1
*fSum1
/fCount1
)/(fCount1
-1.0);
2707 double fS2
= (fSumSqr2
-fSum2
*fSum2
/fCount2
)/(fCount2
-1.0);
2708 if (fS1
== 0.0 || fS2
== 0.0)
2713 double fF
, fF1
, fF2
;
2726 PushDouble(2.0*GetFDist(fF
, fF1
, fF2
));
2729 void ScInterpreter::ScChiTest()
2731 if ( !MustHaveParamCount( GetByte(), 2 ) )
2733 ScMatrixRef pMat2
= GetMatrix();
2734 ScMatrixRef pMat1
= GetMatrix();
2735 if (!pMat1
|| !pMat2
)
2737 PushIllegalParameter();
2742 pMat1
->GetDimensions(nC1
, nR1
);
2743 pMat2
->GetDimensions(nC2
, nR2
);
2744 if (nR1
!= nR2
|| nC1
!= nC2
)
2746 PushIllegalArgument();
2750 for (SCSIZE i
= 0; i
< nC1
; i
++)
2752 for (SCSIZE j
= 0; j
< nR1
; j
++)
2754 if (!pMat1
->IsString(i
,j
) && !pMat2
->IsString(i
,j
))
2756 double fValX
= pMat1
->GetDouble(i
,j
);
2757 double fValE
= pMat2
->GetDouble(i
,j
);
2758 fChi
+= (fValX
- fValE
) * (fValX
- fValE
) / fValE
;
2762 PushIllegalArgument();
2768 if (nC1
== 1 || nR1
== 1)
2770 fDF
= (double)(nC1
*nR1
- 1);
2778 fDF
= (double)(nC1
-1)*(double)(nR1
-1);
2779 PushDouble(GetChiDist(fChi
, fDF
));
2782 void ScInterpreter::ScKurt()
2784 double fSum
,fCount
,vSum
;
2785 std::vector
<double> values
;
2786 if ( !CalculateSkew(fSum
,fCount
,vSum
,values
) )
2791 PushError( errDivisionByZero
);
2795 double fMean
= fSum
/ fCount
;
2797 for (size_t i
= 0; i
< values
.size(); i
++)
2798 vSum
+= (values
[i
] - fMean
) * (values
[i
] - fMean
);
2800 double fStdDev
= sqrt(vSum
/ (fCount
- 1.0));
2802 double xpower4
= 0.0;
2806 PushError( errDivisionByZero
);
2810 for (size_t i
= 0; i
< values
.size(); i
++)
2812 dx
= (values
[i
] - fMean
) / fStdDev
;
2813 xpower4
= xpower4
+ (dx
* dx
* dx
* dx
);
2816 double k_d
= (fCount
- 2.0) * (fCount
- 3.0);
2817 double k_l
= fCount
* (fCount
+ 1.0) / ((fCount
- 1.0) * k_d
);
2818 double k_t
= 3.0 * (fCount
- 1.0) * (fCount
- 1.0) / k_d
;
2820 PushDouble(xpower4
* k_l
- k_t
);
2823 void ScInterpreter::ScHarMean()
2825 short nParamCount
= GetByte();
2827 double nValCount
= 0.0;
2830 size_t nRefInList
= 0;
2831 while ((nGlobalError
== 0) && (nParamCount
-- > 0))
2833 switch (GetStackType())
2835 case formula::svDouble
:
2837 double x
= GetDouble();
2844 SetError( errIllegalArgument
);
2849 PopSingleRef( aAdr
);
2850 ScRefCellValue aCell
;
2851 aCell
.assign(*pDok
, aAdr
);
2852 if (aCell
.hasNumeric())
2854 double x
= GetCellValue(aAdr
, aCell
);
2861 SetError( errIllegalArgument
);
2865 case formula::svDoubleRef
:
2868 sal_uInt16 nErr
= 0;
2869 PopDoubleRef( aRange
, nParamCount
, nRefInList
);
2871 ScValueIterator
aValIter(pDok
, aRange
, glSubTotal
);
2872 if (aValIter
.GetFirst(nCellVal
, nErr
))
2876 nVal
+= 1.0/nCellVal
;
2880 SetError( errIllegalArgument
);
2882 while ((nErr
== 0) && aValIter
.GetNext(nCellVal
, nErr
))
2886 nVal
+= 1.0/nCellVal
;
2890 SetError( errIllegalArgument
);
2897 case svExternalSingleRef
:
2898 case svExternalDoubleRef
:
2900 ScMatrixRef pMat
= GetMatrix();
2903 SCSIZE nCount
= pMat
->GetElementCount();
2904 if (pMat
->IsNumeric())
2906 for (SCSIZE nElem
= 0; nElem
< nCount
; nElem
++)
2908 double x
= pMat
->GetDouble(nElem
);
2915 SetError( errIllegalArgument
);
2920 for (SCSIZE nElem
= 0; nElem
< nCount
; nElem
++)
2921 if (!pMat
->IsString(nElem
))
2923 double x
= pMat
->GetDouble(nElem
);
2930 SetError( errIllegalArgument
);
2936 default : SetError(errIllegalParameter
); break;
2939 if (nGlobalError
== 0)
2940 PushDouble((double)nValCount
/nVal
);
2942 PushError( nGlobalError
);
2945 void ScInterpreter::ScGeoMean()
2947 short nParamCount
= GetByte();
2949 double nValCount
= 0.0;
2953 size_t nRefInList
= 0;
2954 while ((nGlobalError
== 0) && (nParamCount
-- > 0))
2956 switch (GetStackType())
2958 case formula::svDouble
:
2960 double x
= GetDouble();
2967 SetError( errIllegalArgument
);
2972 PopSingleRef( aAdr
);
2973 ScRefCellValue aCell
;
2974 aCell
.assign(*pDok
, aAdr
);
2975 if (aCell
.hasNumeric())
2977 double x
= GetCellValue(aAdr
, aCell
);
2984 SetError( errIllegalArgument
);
2988 case formula::svDoubleRef
:
2991 sal_uInt16 nErr
= 0;
2992 PopDoubleRef( aRange
, nParamCount
, nRefInList
);
2994 ScValueIterator
aValIter(pDok
, aRange
, glSubTotal
);
2995 if (aValIter
.GetFirst(nCellVal
, nErr
))
2999 nVal
+= log(nCellVal
);
3003 SetError( errIllegalArgument
);
3005 while ((nErr
== 0) && aValIter
.GetNext(nCellVal
, nErr
))
3009 nVal
+= log(nCellVal
);
3013 SetError( errIllegalArgument
);
3020 case svExternalSingleRef
:
3021 case svExternalDoubleRef
:
3023 ScMatrixRef pMat
= GetMatrix();
3026 SCSIZE nCount
= pMat
->GetElementCount();
3027 if (pMat
->IsNumeric())
3029 for (SCSIZE ui
= 0; ui
< nCount
; ui
++)
3031 double x
= pMat
->GetDouble(ui
);
3038 SetError( errIllegalArgument
);
3043 for (SCSIZE ui
= 0; ui
< nCount
; ui
++)
3044 if (!pMat
->IsString(ui
))
3046 double x
= pMat
->GetDouble(ui
);
3053 SetError( errIllegalArgument
);
3059 default : SetError(errIllegalParameter
); break;
3062 if (nGlobalError
== 0)
3063 PushDouble(exp(nVal
/ nValCount
));
3065 PushError( nGlobalError
);
3068 void ScInterpreter::ScStandard()
3070 if ( MustHaveParamCount( GetByte(), 3 ) )
3072 double sigma
= GetDouble();
3073 double mue
= GetDouble();
3074 double x
= GetDouble();
3076 PushError( errIllegalArgument
);
3077 else if (sigma
== 0.0)
3078 PushError( errDivisionByZero
);
3080 PushDouble((x
-mue
)/sigma
);
3083 bool ScInterpreter::CalculateSkew(double& fSum
,double& fCount
,double& vSum
,std::vector
<double>& values
)
3085 short nParamCount
= GetByte();
3086 if ( !MustHaveParamCountMin( nParamCount
, 1 ) )
3095 size_t nRefInList
= 0;
3096 while (nParamCount
-- > 0)
3098 switch (GetStackType())
3100 case formula::svDouble
:
3104 values
.push_back(fVal
);
3110 PopSingleRef( aAdr
);
3111 ScRefCellValue aCell
;
3112 aCell
.assign(*pDok
, aAdr
);
3113 if (aCell
.hasNumeric())
3115 fVal
= GetCellValue(aAdr
, aCell
);
3117 values
.push_back(fVal
);
3122 case formula::svDoubleRef
:
3125 PopDoubleRef( aRange
, nParamCount
, nRefInList
);
3126 sal_uInt16 nErr
= 0;
3127 ScValueIterator
aValIter(pDok
, aRange
);
3128 if (aValIter
.GetFirst(fVal
, nErr
))
3131 values
.push_back(fVal
);
3134 while ((nErr
== 0) && aValIter
.GetNext(fVal
, nErr
))
3137 values
.push_back(fVal
);
3145 case svExternalSingleRef
:
3146 case svExternalDoubleRef
:
3148 ScMatrixRef pMat
= GetMatrix();
3151 SCSIZE nCount
= pMat
->GetElementCount();
3152 if (pMat
->IsNumeric())
3154 for (SCSIZE nElem
= 0; nElem
< nCount
; nElem
++)
3156 fVal
= pMat
->GetDouble(nElem
);
3158 values
.push_back(fVal
);
3164 for (SCSIZE nElem
= 0; nElem
< nCount
; nElem
++)
3165 if (!pMat
->IsString(nElem
))
3167 fVal
= pMat
->GetDouble(nElem
);
3169 values
.push_back(fVal
);
3177 SetError(errIllegalParameter
);
3184 PushError( nGlobalError
);
3186 } // if (nGlobalError)
3190 void ScInterpreter::CalculateSkewOrSkewp( bool bSkewp
)
3192 double fSum
, fCount
, vSum
;
3193 std::vector
<double> values
;
3194 if (!CalculateSkew( fSum
, fCount
, vSum
, values
))
3197 double fMean
= fSum
/ fCount
;
3199 for (size_t i
= 0; i
< values
.size(); ++i
)
3200 vSum
+= (values
[i
] - fMean
) * (values
[i
] - fMean
);
3202 double fStdDev
= sqrt( vSum
/ (bSkewp
? fCount
: (fCount
- 1.0)));
3208 PushIllegalArgument();
3212 for (size_t i
= 0; i
< values
.size(); ++i
)
3214 dx
= (values
[i
] - fMean
) / fStdDev
;
3215 xcube
= xcube
+ (dx
* dx
* dx
);
3219 PushDouble( xcube
/ fCount
);
3221 PushDouble( ((xcube
* fCount
) / (fCount
- 1.0)) / (fCount
- 2.0) );
3224 void ScInterpreter::ScSkew()
3226 CalculateSkewOrSkewp( false );
3229 void ScInterpreter::ScSkewp()
3231 CalculateSkewOrSkewp( true );
3234 double ScInterpreter::GetMedian( vector
<double> & rArray
)
3236 size_t nSize
= rArray
.size();
3237 if (rArray
.empty() || nSize
== 0 || nGlobalError
)
3239 SetError( errNoValue
);
3244 size_t nMid
= nSize
/ 2;
3245 vector
<double>::iterator iMid
= rArray
.begin() + nMid
;
3246 ::std::nth_element( rArray
.begin(), iMid
, rArray
.end());
3248 return *iMid
; // Lower and upper median are equal.
3253 iMid
= rArray
.begin() + nMid
- 1;
3254 ::std::nth_element( rArray
.begin(), iMid
, rArray
.end());
3255 return (fUp
+ *iMid
) / 2;
3259 void ScInterpreter::ScMedian()
3261 sal_uInt8 nParamCount
= GetByte();
3262 if ( !MustHaveParamCountMin( nParamCount
, 1 ) )
3264 vector
<double> aArray
;
3265 GetNumberSequenceArray( nParamCount
, aArray
);
3266 PushDouble( GetMedian( aArray
));
3269 double ScInterpreter::GetPercentile( vector
<double> & rArray
, double fPercentile
)
3271 size_t nSize
= rArray
.size();
3272 if (rArray
.empty() || nSize
== 0 || nGlobalError
)
3274 SetError( errNoValue
);
3282 size_t nIndex
= (size_t)::rtl::math::approxFloor( fPercentile
* (nSize
-1));
3283 double fDiff
= fPercentile
* (nSize
-1) - ::rtl::math::approxFloor( fPercentile
* (nSize
-1));
3284 OSL_ENSURE(nIndex
< nSize
, "GetPercentile: wrong index(1)");
3285 vector
<double>::iterator iter
= rArray
.begin() + nIndex
;
3286 ::std::nth_element( rArray
.begin(), iter
, rArray
.end());
3291 OSL_ENSURE(nIndex
< nSize
-1, "GetPercentile: wrong index(2)");
3292 double fVal
= *iter
;
3293 iter
= rArray
.begin() + nIndex
+1;
3294 ::std::nth_element( rArray
.begin(), iter
, rArray
.end());
3295 return fVal
+ fDiff
* (*iter
- fVal
);
3300 void ScInterpreter::ScPercentile()
3302 if ( !MustHaveParamCount( GetByte(), 2 ) )
3304 double alpha
= GetDouble();
3305 if (alpha
< 0.0 || alpha
> 1.0)
3307 PushIllegalArgument();
3310 vector
<double> aArray
;
3311 GetNumberSequenceArray( 1, aArray
);
3312 PushDouble( GetPercentile( aArray
, alpha
));
3315 void ScInterpreter::ScQuartile()
3317 if ( !MustHaveParamCount( GetByte(), 2 ) )
3319 double fFlag
= ::rtl::math::approxFloor(GetDouble());
3320 if (fFlag
< 0.0 || fFlag
> 4.0)
3322 PushIllegalArgument();
3325 vector
<double> aArray
;
3326 GetNumberSequenceArray( 1, aArray
);
3327 PushDouble( fFlag
== 2.0 ? GetMedian( aArray
) : GetPercentile( aArray
, 0.25 * fFlag
));
3330 void ScInterpreter::ScModalValue()
3332 sal_uInt8 nParamCount
= GetByte();
3333 if ( !MustHaveParamCountMin( nParamCount
, 1 ) )
3335 vector
<double> aSortArray
;
3336 GetSortArray(nParamCount
, aSortArray
);
3337 SCSIZE nSize
= aSortArray
.size();
3338 if (aSortArray
.empty() || nSize
== 0 || nGlobalError
)
3342 SCSIZE nMaxIndex
= 0, nMax
= 1, nCount
= 1;
3343 double nOldVal
= aSortArray
[0];
3346 for ( i
= 1; i
< nSize
; i
++)
3348 if (aSortArray
[i
] == nOldVal
)
3352 nOldVal
= aSortArray
[i
];
3366 if (nMax
== 1 && nCount
== 1)
3369 PushDouble(nOldVal
);
3371 PushDouble(aSortArray
[nMaxIndex
]);
3375 void ScInterpreter::CalculateSmallLarge(bool bSmall
)
3377 if ( !MustHaveParamCount( GetByte(), 2 ) )
3379 double f
= ::rtl::math::approxFloor(GetDouble());
3382 PushIllegalArgument();
3385 SCSIZE k
= static_cast<SCSIZE
>(f
);
3386 vector
<double> aSortArray
;
3387 /* TODO: using nth_element() is best for one single value, but LARGE/SMALL
3388 * actually are defined to return an array of values if an array of
3389 * positions was passed, in which case, depending on the number of values,
3390 * we may or will need a real sorted array again, see #i32345. */
3391 GetNumberSequenceArray(1, aSortArray
);
3392 SCSIZE nSize
= aSortArray
.size();
3393 if (aSortArray
.empty() || nSize
== 0 || nGlobalError
|| nSize
< k
)
3397 // TODO: the sorted case for array: PushDouble( aSortArray[ bSmall ? k-1 : nSize-k ] );
3398 vector
<double>::iterator iPos
= aSortArray
.begin() + (bSmall
? k
-1 : nSize
-k
);
3399 ::std::nth_element( aSortArray
.begin(), iPos
, aSortArray
.end());
3404 void ScInterpreter::ScLarge()
3406 CalculateSmallLarge(false);
3409 void ScInterpreter::ScSmall()
3411 CalculateSmallLarge(true);
3414 void ScInterpreter::ScPercentrank()
3416 sal_uInt8 nParamCount
= GetByte();
3417 if ( !MustHaveParamCount( nParamCount
, 2 ) )
3420 double fNum
= GetDouble();
3421 vector
<double> aSortArray
;
3422 GetSortArray(1, aSortArray
);
3423 SCSIZE nSize
= aSortArray
.size();
3424 if (aSortArray
.empty() || nSize
== 0 || nGlobalError
)
3428 if (fNum
< aSortArray
[0] || fNum
> aSortArray
[nSize
-1])
3430 else if ( nSize
== 1 )
3431 PushDouble(1.0); // fNum == pSortArray[0], see test above
3435 SCSIZE nOldCount
= 0;
3436 double fOldVal
= aSortArray
[0];
3438 for (i
= 1; i
< nSize
&& aSortArray
[i
] < fNum
; i
++)
3440 if (aSortArray
[i
] != fOldVal
)
3443 fOldVal
= aSortArray
[i
];
3446 if (aSortArray
[i
] != fOldVal
)
3448 if (fNum
== aSortArray
[i
])
3449 fRes
= (double)nOldCount
/(double)(nSize
-1);
3452 // nOldCount is the count of smaller entries
3453 // fNum is between pSortArray[nOldCount-1] and pSortArray[nOldCount]
3454 // use linear interpolation to find a position between the entries
3456 if ( nOldCount
== 0 )
3458 OSL_FAIL("should not happen");
3463 double fFract
= ( fNum
- aSortArray
[nOldCount
-1] ) /
3464 ( aSortArray
[nOldCount
] - aSortArray
[nOldCount
-1] );
3465 fRes
= ( (double)(nOldCount
-1)+fFract
)/(double)(nSize
-1);
3473 void ScInterpreter::ScTrimMean()
3475 if ( !MustHaveParamCount( GetByte(), 2 ) )
3477 double alpha
= GetDouble();
3478 if (alpha
< 0.0 || alpha
>= 1.0)
3480 PushIllegalArgument();
3483 vector
<double> aSortArray
;
3484 GetSortArray(1, aSortArray
);
3485 SCSIZE nSize
= aSortArray
.size();
3486 if (aSortArray
.empty() || nSize
== 0 || nGlobalError
)
3490 sal_uLong nIndex
= (sal_uLong
) ::rtl::math::approxFloor(alpha
*(double)nSize
);
3491 if (nIndex
% 2 != 0)
3494 OSL_ENSURE(nIndex
< nSize
, "ScTrimMean: falscher Index");
3496 for (SCSIZE i
= nIndex
; i
< nSize
-nIndex
; i
++)
3497 fSum
+= aSortArray
[i
];
3498 PushDouble(fSum
/(double)(nSize
-2*nIndex
));
3502 void ScInterpreter::GetNumberSequenceArray( sal_uInt8 nParamCount
, vector
<double>& rArray
)
3506 short nParam
= nParamCount
;
3507 size_t nRefInList
= 0;
3508 while (nParam
-- > 0)
3510 switch (GetStackType())
3512 case formula::svDouble
:
3513 rArray
.push_back( PopDouble());
3517 PopSingleRef( aAdr
);
3518 ScRefCellValue aCell
;
3519 aCell
.assign(*pDok
, aAdr
);
3520 if (aCell
.hasNumeric())
3521 rArray
.push_back(GetCellValue(aAdr
, aCell
));
3524 case formula::svDoubleRef
:
3527 PopDoubleRef( aRange
, nParam
, nRefInList
);
3532 SCSIZE nCellCount
= aRange
.aEnd
.Col() - aRange
.aStart
.Col() + 1;
3533 nCellCount
*= aRange
.aEnd
.Row() - aRange
.aStart
.Row() + 1;
3534 rArray
.reserve( rArray
.size() + nCellCount
);
3536 sal_uInt16 nErr
= 0;
3538 ScValueIterator
aValIter(pDok
, aRange
);
3539 if (aValIter
.GetFirst( fCellVal
, nErr
))
3541 rArray
.push_back( fCellVal
);
3543 while ((nErr
== 0) && aValIter
.GetNext( fCellVal
, nErr
))
3544 rArray
.push_back( fCellVal
);
3550 case svExternalSingleRef
:
3551 case svExternalDoubleRef
:
3553 ScMatrixRef pMat
= GetMatrix();
3557 SCSIZE nCount
= pMat
->GetElementCount();
3558 rArray
.reserve( rArray
.size() + nCount
);
3559 if (pMat
->IsNumeric())
3561 for (SCSIZE i
= 0; i
< nCount
; ++i
)
3562 rArray
.push_back( pMat
->GetDouble(i
));
3566 for (SCSIZE i
= 0; i
< nCount
; ++i
)
3567 if (!pMat
->IsString(i
))
3568 rArray
.push_back( pMat
->GetDouble(i
));
3574 SetError( errIllegalParameter
);
3580 // nParam > 0 in case of error, clean stack environment and obtain earlier
3581 // error if there was one.
3582 while (nParam
-- > 0)
3586 void ScInterpreter::GetSortArray( sal_uInt8 nParamCount
, vector
<double>& rSortArray
, vector
<long>* pIndexOrder
)
3588 GetNumberSequenceArray( nParamCount
, rSortArray
);
3590 if (rSortArray
.size() > MAX_ANZ_DOUBLE_FOR_SORT
)
3591 SetError( errStackOverflow
);
3592 else if (rSortArray
.empty())
3593 SetError( errNoValue
);
3595 if (nGlobalError
== 0)
3596 QuickSort( rSortArray
, pIndexOrder
);
3599 static void lcl_QuickSort( long nLo
, long nHi
, vector
<double>& rSortArray
, vector
<long>* pIndexOrder
)
3601 // If pIndexOrder is not NULL, we assume rSortArray.size() == pIndexOrder->size().
3607 if (rSortArray
[nLo
] > rSortArray
[nHi
])
3609 swap(rSortArray
[nLo
], rSortArray
[nHi
]);
3611 swap(pIndexOrder
->at(nLo
), pIndexOrder
->at(nHi
));
3620 double fLo
= rSortArray
[nLo
];
3621 while (ni
<= nHi
&& rSortArray
[ni
] < fLo
) ni
++;
3622 while (nj
>= nLo
&& fLo
< rSortArray
[nj
]) nj
--;
3627 swap(rSortArray
[ni
], rSortArray
[nj
]);
3629 swap(pIndexOrder
->at(ni
), pIndexOrder
->at(nj
));
3638 if ((nj
- nLo
) < (nHi
- ni
))
3640 if (nLo
< nj
) lcl_QuickSort(nLo
, nj
, rSortArray
, pIndexOrder
);
3641 if (ni
< nHi
) lcl_QuickSort(ni
, nHi
, rSortArray
, pIndexOrder
);
3645 if (ni
< nHi
) lcl_QuickSort(ni
, nHi
, rSortArray
, pIndexOrder
);
3646 if (nLo
< nj
) lcl_QuickSort(nLo
, nj
, rSortArray
, pIndexOrder
);
3650 void ScInterpreter::QuickSort( vector
<double>& rSortArray
, vector
<long>* pIndexOrder
)
3652 long n
= static_cast<long>(rSortArray
.size());
3656 pIndexOrder
->clear();
3657 pIndexOrder
->reserve(n
);
3658 for (long i
= 0; i
< n
; ++i
)
3659 pIndexOrder
->push_back(i
);
3665 size_t nValCount
= rSortArray
.size();
3666 for (size_t i
= 0; (i
+ 4) <= nValCount
-1; i
+= 4)
3668 size_t nInd
= rand() % (int) (nValCount
-1);
3669 ::std::swap( rSortArray
[i
], rSortArray
[nInd
]);
3671 ::std::swap( pIndexOrder
->at(i
), pIndexOrder
->at(nInd
));
3674 lcl_QuickSort(0, n
-1, rSortArray
, pIndexOrder
);
3677 void ScInterpreter::ScRank()
3679 sal_uInt8 nParamCount
= GetByte();
3680 if ( !MustHaveParamCount( nParamCount
, 2, 3 ) )
3683 if (nParamCount
== 3)
3684 bDescending
= GetBool();
3686 bDescending
= false;
3687 double fCount
= 1.0;
3688 bool bValid
= false;
3689 switch (GetStackType())
3691 case formula::svDouble
:
3693 double x
= GetDouble();
3694 double fVal
= GetDouble();
3702 PopSingleRef( aAdr
);
3703 double fVal
= GetDouble();
3704 ScRefCellValue aCell
;
3705 aCell
.assign(*pDok
, aAdr
);
3706 if (aCell
.hasNumeric())
3708 double x
= GetCellValue(aAdr
, aCell
);
3714 case formula::svDoubleRef
:
3719 size_t nRefInList
= 0;
3720 while (nParam
-- > 0)
3722 sal_uInt16 nErr
= 0;
3723 // Preserve stack until all RefList elements are done!
3724 sal_uInt16 nSaveSP
= sp
;
3725 PopDoubleRef( aRange
, nParam
, nRefInList
);
3727 --sp
; // simulate pop
3728 double fVal
= GetDouble();
3732 ScValueIterator
aValIter(pDok
, aRange
, glSubTotal
);
3733 if (aValIter
.GetFirst(nCellVal
, nErr
))
3735 if (nCellVal
== fVal
)
3737 else if ((!bDescending
&& nCellVal
> fVal
) ||
3738 (bDescending
&& nCellVal
< fVal
) )
3741 while ((nErr
== 0) && aValIter
.GetNext(nCellVal
, nErr
))
3743 if (nCellVal
== fVal
)
3745 else if ((!bDescending
&& nCellVal
> fVal
) ||
3746 (bDescending
&& nCellVal
< fVal
) )
3755 case svExternalSingleRef
:
3756 case svExternalDoubleRef
:
3758 ScMatrixRef pMat
= GetMatrix();
3759 double fVal
= GetDouble();
3762 SCSIZE nCount
= pMat
->GetElementCount();
3763 if (pMat
->IsNumeric())
3765 for (SCSIZE i
= 0; i
< nCount
; i
++)
3767 double x
= pMat
->GetDouble(i
);
3770 else if ((!bDescending
&& x
> fVal
) ||
3771 (bDescending
&& x
< fVal
) )
3777 for (SCSIZE i
= 0; i
< nCount
; i
++)
3778 if (!pMat
->IsString(i
))
3780 double x
= pMat
->GetDouble(i
);
3783 else if ((!bDescending
&& x
> fVal
) ||
3784 (bDescending
&& x
< fVal
) )
3791 default : SetError(errIllegalParameter
); break;
3799 void ScInterpreter::ScAveDev()
3801 sal_uInt8 nParamCount
= GetByte();
3802 if ( !MustHaveParamCountMin( nParamCount
, 1 ) )
3804 sal_uInt16 SaveSP
= sp
;
3805 double nMiddle
= 0.0;
3807 double rValCount
= 0.0;
3810 short nParam
= nParamCount
;
3811 size_t nRefInList
= 0;
3812 while (nParam
-- > 0)
3814 switch (GetStackType())
3816 case formula::svDouble
:
3817 rVal
+= GetDouble();
3822 PopSingleRef( aAdr
);
3823 ScRefCellValue aCell
;
3824 aCell
.assign(*pDok
, aAdr
);
3825 if (aCell
.hasNumeric())
3827 rVal
+= GetCellValue(aAdr
, aCell
);
3832 case formula::svDoubleRef
:
3835 sal_uInt16 nErr
= 0;
3837 PopDoubleRef( aRange
, nParam
, nRefInList
);
3838 ScValueIterator
aValIter(pDok
, aRange
);
3839 if (aValIter
.GetFirst(nCellVal
, nErr
))
3844 while ((nErr
== 0) && aValIter
.GetNext(nCellVal
, nErr
))
3854 case svExternalSingleRef
:
3855 case svExternalDoubleRef
:
3857 ScMatrixRef pMat
= GetMatrix();
3860 SCSIZE nCount
= pMat
->GetElementCount();
3861 if (pMat
->IsNumeric())
3863 for (SCSIZE nElem
= 0; nElem
< nCount
; nElem
++)
3865 rVal
+= pMat
->GetDouble(nElem
);
3871 for (SCSIZE nElem
= 0; nElem
< nCount
; nElem
++)
3872 if (!pMat
->IsString(nElem
))
3874 rVal
+= pMat
->GetDouble(nElem
);
3882 SetError(errIllegalParameter
);
3888 PushError( nGlobalError
);
3891 nMiddle
= rVal
/ rValCount
;
3894 nParam
= nParamCount
;
3896 while (nParam
-- > 0)
3898 switch (GetStackType())
3900 case formula::svDouble
:
3901 rVal
+= fabs(GetDouble() - nMiddle
);
3905 PopSingleRef( aAdr
);
3906 ScRefCellValue aCell
;
3907 aCell
.assign(*pDok
, aAdr
);
3908 if (aCell
.hasNumeric())
3909 rVal
+= fabs(GetCellValue(aAdr
, aCell
) - nMiddle
);
3912 case formula::svDoubleRef
:
3915 sal_uInt16 nErr
= 0;
3917 PopDoubleRef( aRange
, nParam
, nRefInList
);
3918 ScValueIterator
aValIter(pDok
, aRange
);
3919 if (aValIter
.GetFirst(nCellVal
, nErr
))
3921 rVal
+= (fabs(nCellVal
- nMiddle
));
3922 while (aValIter
.GetNext(nCellVal
, nErr
))
3923 rVal
+= fabs(nCellVal
- nMiddle
);
3928 case svExternalSingleRef
:
3929 case svExternalDoubleRef
:
3931 ScMatrixRef pMat
= GetMatrix();
3934 SCSIZE nCount
= pMat
->GetElementCount();
3935 if (pMat
->IsNumeric())
3937 for (SCSIZE nElem
= 0; nElem
< nCount
; nElem
++)
3939 rVal
+= fabs(pMat
->GetDouble(nElem
) - nMiddle
);
3944 for (SCSIZE nElem
= 0; nElem
< nCount
; nElem
++)
3946 if (!pMat
->IsString(nElem
))
3947 rVal
+= fabs(pMat
->GetDouble(nElem
) - nMiddle
);
3953 default : SetError(errIllegalParameter
); break;
3956 PushDouble(rVal
/ rValCount
);
3959 void ScInterpreter::ScDevSq()
3963 GetStVarParams(nVal
, nValCount
);
3967 void ScInterpreter::ScProbability()
3969 sal_uInt8 nParamCount
= GetByte();
3970 if ( !MustHaveParamCount( nParamCount
, 3, 4 ) )
3974 if (nParamCount
== 4)
3984 ScMatrixRef pMatP
= GetMatrix();
3985 ScMatrixRef pMatW
= GetMatrix();
3986 if (!pMatP
|| !pMatW
)
3987 PushIllegalParameter();
3992 pMatP
->GetDimensions(nC1
, nR1
);
3993 pMatW
->GetDimensions(nC2
, nR2
);
3994 if (nC1
!= nC2
|| nR1
!= nR2
|| nC1
== 0 || nR1
== 0 ||
3995 nC2
== 0 || nR2
== 0)
4003 for ( SCSIZE i
= 0; i
< nC1
&& !bStop
; i
++ )
4005 for (SCSIZE j
= 0; j
< nR1
&& !bStop
; ++j
)
4007 if (pMatP
->IsValue(i
,j
) && pMatW
->IsValue(i
,j
))
4009 fP
= pMatP
->GetDouble(i
,j
);
4010 fW
= pMatW
->GetDouble(i
,j
);
4011 if (fP
< 0.0 || fP
> 1.0)
4016 if (fW
>= fLo
&& fW
<= fUp
)
4021 SetError( errIllegalArgument
);
4024 if (bStop
|| fabs(fSum
-1.0) > 1.0E-7)
4032 void ScInterpreter::ScCorrel()
4034 // This is identical to ScPearson()
4038 void ScInterpreter::ScCovarianceP()
4040 CalculatePearsonCovar( false, false, false );
4043 void ScInterpreter::ScCovarianceS()
4045 CalculatePearsonCovar( false, false, true );
4048 void ScInterpreter::ScPearson()
4050 CalculatePearsonCovar( true, false, false );
4053 void ScInterpreter::CalculatePearsonCovar( bool _bPearson
, bool _bStexy
, bool _bSample
)
4055 if ( !MustHaveParamCount( GetByte(), 2 ) )
4057 ScMatrixRef pMat1
= GetMatrix();
4058 ScMatrixRef pMat2
= GetMatrix();
4059 if (!pMat1
|| !pMat2
)
4061 PushIllegalParameter();
4066 pMat1
->GetDimensions(nC1
, nR1
);
4067 pMat2
->GetDimensions(nC2
, nR2
);
4068 if (nR1
!= nR2
|| nC1
!= nC2
)
4070 PushIllegalArgument();
4074 * (sum((X-MeanX)(Y-MeanY)))/N equals (SumXY)/N-MeanX*MeanY mathematically,
4075 * but the latter produces wrong results if the absolute values are high,
4076 * for example above 10^8
4078 double fCount
= 0.0;
4081 double fSumDeltaXDeltaY
= 0.0; // sum of (ValX-MeanX)*(ValY-MeanY)
4082 double fSumSqrDeltaX
= 0.0; // sum of (ValX-MeanX)^2
4083 double fSumSqrDeltaY
= 0.0; // sum of (ValY-MeanY)^2
4084 for (SCSIZE i
= 0; i
< nC1
; i
++)
4086 for (SCSIZE j
= 0; j
< nR1
; j
++)
4088 if (!pMat1
->IsString(i
,j
) && !pMat2
->IsString(i
,j
))
4090 double fValX
= pMat1
->GetDouble(i
,j
);
4091 double fValY
= pMat2
->GetDouble(i
,j
);
4098 if (fCount
< (_bStexy
? 3.0 : (_bSample
? 2.0 : 1.0)))
4102 const double fMeanX
= fSumX
/ fCount
;
4103 const double fMeanY
= fSumY
/ fCount
;
4104 for (SCSIZE i
= 0; i
< nC1
; i
++)
4106 for (SCSIZE j
= 0; j
< nR1
; j
++)
4108 if (!pMat1
->IsString(i
,j
) && !pMat2
->IsString(i
,j
))
4110 const double fValX
= pMat1
->GetDouble(i
,j
);
4111 const double fValY
= pMat2
->GetDouble(i
,j
);
4112 fSumDeltaXDeltaY
+= (fValX
- fMeanX
) * (fValY
- fMeanY
);
4115 fSumSqrDeltaX
+= (fValX
- fMeanX
) * (fValX
- fMeanX
);
4116 fSumSqrDeltaY
+= (fValY
- fMeanY
) * (fValY
- fMeanY
);
4123 if (fSumSqrDeltaX
== 0.0 || ( !_bStexy
&& fSumSqrDeltaY
== 0.0) )
4124 PushError( errDivisionByZero
);
4126 PushDouble( sqrt( (fSumSqrDeltaY
- fSumDeltaXDeltaY
*
4127 fSumDeltaXDeltaY
/ fSumSqrDeltaX
) / (fCount
-2)));
4129 PushDouble( fSumDeltaXDeltaY
/ sqrt( fSumSqrDeltaX
* fSumSqrDeltaY
));
4134 PushDouble( fSumDeltaXDeltaY
/ ( fCount
- 1 ) );
4136 PushDouble( fSumDeltaXDeltaY
/ fCount
);
4141 void ScInterpreter::ScRSQ()
4143 // Same as ScPearson()*ScPearson()
4147 switch (GetStackType())
4149 case formula::svDouble
:
4151 double fVal
= PopDouble();
4152 PushDouble( fVal
* fVal
);
4162 void ScInterpreter::ScSTEXY()
4164 CalculatePearsonCovar( true, true, false );
4166 void ScInterpreter::CalculateSlopeIntercept(bool bSlope
)
4168 if ( !MustHaveParamCount( GetByte(), 2 ) )
4170 ScMatrixRef pMat1
= GetMatrix();
4171 ScMatrixRef pMat2
= GetMatrix();
4172 if (!pMat1
|| !pMat2
)
4174 PushIllegalParameter();
4179 pMat1
->GetDimensions(nC1
, nR1
);
4180 pMat2
->GetDimensions(nC2
, nR2
);
4181 if (nR1
!= nR2
|| nC1
!= nC2
)
4183 PushIllegalArgument();
4186 // #i78250# numerical stability improved
4187 double fCount
= 0.0;
4190 double fSumDeltaXDeltaY
= 0.0; // sum of (ValX-MeanX)*(ValY-MeanY)
4191 double fSumSqrDeltaX
= 0.0; // sum of (ValX-MeanX)^2
4192 for (SCSIZE i
= 0; i
< nC1
; i
++)
4194 for (SCSIZE j
= 0; j
< nR1
; j
++)
4196 if (!pMat1
->IsString(i
,j
) && !pMat2
->IsString(i
,j
))
4198 double fValX
= pMat1
->GetDouble(i
,j
);
4199 double fValY
= pMat2
->GetDouble(i
,j
);
4210 double fMeanX
= fSumX
/ fCount
;
4211 double fMeanY
= fSumY
/ fCount
;
4212 for (SCSIZE i
= 0; i
< nC1
; i
++)
4214 for (SCSIZE j
= 0; j
< nR1
; j
++)
4216 if (!pMat1
->IsString(i
,j
) && !pMat2
->IsString(i
,j
))
4218 double fValX
= pMat1
->GetDouble(i
,j
);
4219 double fValY
= pMat2
->GetDouble(i
,j
);
4220 fSumDeltaXDeltaY
+= (fValX
- fMeanX
) * (fValY
- fMeanY
);
4221 fSumSqrDeltaX
+= (fValX
- fMeanX
) * (fValX
- fMeanX
);
4225 if (fSumSqrDeltaX
== 0.0)
4226 PushError( errDivisionByZero
);
4230 PushDouble( fSumDeltaXDeltaY
/ fSumSqrDeltaX
);
4232 PushDouble( fMeanY
- fSumDeltaXDeltaY
/ fSumSqrDeltaX
* fMeanX
);
4237 void ScInterpreter::ScSlope()
4239 CalculateSlopeIntercept(true);
4242 void ScInterpreter::ScIntercept()
4244 CalculateSlopeIntercept(false);
4247 void ScInterpreter::ScForecast()
4249 if ( !MustHaveParamCount( GetByte(), 3 ) )
4251 ScMatrixRef pMat1
= GetMatrix();
4252 ScMatrixRef pMat2
= GetMatrix();
4253 if (!pMat1
|| !pMat2
)
4255 PushIllegalParameter();
4260 pMat1
->GetDimensions(nC1
, nR1
);
4261 pMat2
->GetDimensions(nC2
, nR2
);
4262 if (nR1
!= nR2
|| nC1
!= nC2
)
4264 PushIllegalArgument();
4267 double fVal
= GetDouble();
4268 // #i78250# numerical stability improved
4269 double fCount
= 0.0;
4272 double fSumDeltaXDeltaY
= 0.0; // sum of (ValX-MeanX)*(ValY-MeanY)
4273 double fSumSqrDeltaX
= 0.0; // sum of (ValX-MeanX)^2
4274 for (SCSIZE i
= 0; i
< nC1
; i
++)
4276 for (SCSIZE j
= 0; j
< nR1
; j
++)
4278 if (!pMat1
->IsString(i
,j
) && !pMat2
->IsString(i
,j
))
4280 double fValX
= pMat1
->GetDouble(i
,j
);
4281 double fValY
= pMat2
->GetDouble(i
,j
);
4292 double fMeanX
= fSumX
/ fCount
;
4293 double fMeanY
= fSumY
/ fCount
;
4294 for (SCSIZE i
= 0; i
< nC1
; i
++)
4296 for (SCSIZE j
= 0; j
< nR1
; j
++)
4298 if (!pMat1
->IsString(i
,j
) && !pMat2
->IsString(i
,j
))
4300 double fValX
= pMat1
->GetDouble(i
,j
);
4301 double fValY
= pMat2
->GetDouble(i
,j
);
4302 fSumDeltaXDeltaY
+= (fValX
- fMeanX
) * (fValY
- fMeanY
);
4303 fSumSqrDeltaX
+= (fValX
- fMeanX
) * (fValX
- fMeanX
);
4307 if (fSumSqrDeltaX
== 0.0)
4308 PushError( errDivisionByZero
);
4310 PushDouble( fMeanY
+ fSumDeltaXDeltaY
/ fSumSqrDeltaX
* (fVal
- fMeanX
));
4314 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */