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"
36 #include <boost/math/special_functions/log1p.hpp>
37 #include <comphelper/random.hxx>
40 using namespace formula
;
43 #define MAX_ANZ_DOUBLE_FOR_SORT 100000
45 const double ScInterpreter::fMaxGammaArgument
= 171.624376956302; // found experimental
46 const double fMachEps
= ::std::numeric_limits
<double>::epsilon();
51 virtual double GetValue(double x
) const = 0;
57 // iteration for inverse distributions
59 //template< class T > double lcl_IterateInverse( const T& rFunction, double x0, double x1, bool& rConvError )
61 /** u*w<0.0 fails for values near zero */
62 static inline bool lcl_HasChangeOfSign( double u
, double w
)
64 return (u
< 0.0 && w
> 0.0) || (u
> 0.0 && w
< 0.0);
67 static double lcl_IterateInverse( const ScDistFunc
& rFunction
, double fAx
, double fBx
, bool& rConvError
)
70 const double fYEps
= 1.0E-307;
71 const double fXEps
= ::std::numeric_limits
<double>::epsilon();
73 OSL_ENSURE(fAx
<fBx
, "IterateInverse: wrong interval");
75 // find enclosing interval
77 double fAy
= rFunction
.GetValue(fAx
);
78 double fBy
= rFunction
.GetValue(fBx
);
80 unsigned short nCount
;
81 for (nCount
= 0; nCount
< 1000 && !lcl_HasChangeOfSign(fAy
,fBy
); nCount
++)
83 if (fabs(fAy
) <= fabs(fBy
))
86 fAx
+= 2.0 * (fAx
- fBx
);
91 fAy
= rFunction
.GetValue(fAx
);
96 fBx
+= 2.0 * (fBx
- fAx
);
99 fBy
= rFunction
.GetValue(fBx
);
107 if (!lcl_HasChangeOfSign( fAy
, fBy
))
112 // inverse quadric interpolation with additional brackets
120 double fSx
= 0.5 * (fAx
+ fBx
); // potential next point
121 bool bHasToInterpolate
= true;
123 while ( nCount
< 500 && fabs(fRy
) > fYEps
&&
124 (fBx
-fAx
) > ::std::max( fabs(fAx
), fabs(fBx
)) * fXEps
)
126 if (bHasToInterpolate
)
128 if (fPy
!=fQy
&& fQy
!=fRy
&& fRy
!=fPy
)
130 fSx
= fPx
* fRy
* fQy
/ (fRy
-fPy
) / (fQy
-fPy
)
131 + fRx
* fQy
* fPy
/ (fQy
-fRy
) / (fPy
-fRy
)
132 + fQx
* fPy
* fRy
/ (fPy
-fQy
) / (fRy
-fQy
);
133 bHasToInterpolate
= (fAx
< fSx
) && (fSx
< fBx
); // inside the brackets?
136 bHasToInterpolate
= false;
138 if(!bHasToInterpolate
)
140 fSx
= 0.5 * (fAx
+ fBx
);
142 fQx
= fBx
; fQy
= fBy
;
143 bHasToInterpolate
= true;
145 // shift points for next interpolation
146 fPx
= fQx
; fQx
= fRx
; fRx
= fSx
;
147 fPy
= fQy
; fQy
= fRy
; fRy
= rFunction
.GetValue(fSx
);
149 if (lcl_HasChangeOfSign( fAy
, fRy
))
151 fBx
= fRx
; fBy
= fRy
;
155 fAx
= fRx
; fAy
= fRy
;
157 // if last interration brought to small advance, then do bisection next
159 bHasToInterpolate
= bHasToInterpolate
&& (fabs(fRy
) * 2.0 <= fabs(fQy
));
165 // Allgemeine Funktionen
167 void ScInterpreter::ScNoName()
169 PushError(errNoName
);
172 void ScInterpreter::ScBadName()
174 short nParamCount
= GetByte();
175 while (nParamCount
-- > 0)
179 PushError( errNoName
);
182 double ScInterpreter::phi(double x
)
184 return 0.39894228040143268 * exp(-(x
* x
) / 2.0);
187 double ScInterpreter::integralPhi(double x
)
188 { // Using gauss(x)+0.5 has severe cancellation errors for x<-4
189 return 0.5 * ::rtl::math::erfc(-x
* 0.7071067811865475); // * 1/sqrt(2)
192 double ScInterpreter::taylor(const double* pPolynom
, sal_uInt16 nMax
, double x
)
194 double nVal
= pPolynom
[nMax
];
195 for (short i
= nMax
-1; i
>= 0; i
--)
197 nVal
= pPolynom
[i
] + (nVal
* x
);
202 double ScInterpreter::gauss(double x
)
205 double xAbs
= fabs(x
);
206 sal_uInt16 xShort
= (sal_uInt16
)::rtl::math::approxFloor(xAbs
);
210 static const double t0
[] =
211 { 0.39894228040143268, -0.06649038006690545, 0.00997355701003582,
212 -0.00118732821548045, 0.00011543468761616, -0.00000944465625950,
213 0.00000066596935163, -0.00000004122667415, 0.00000000227352982,
214 0.00000000011301172, 0.00000000000511243, -0.00000000000021218 };
215 nVal
= taylor(t0
, 11, (xAbs
* xAbs
)) * xAbs
;
217 else if ((xShort
>= 1) && (xShort
<= 2))
219 static const double t2
[] =
220 { 0.47724986805182079, 0.05399096651318805, -0.05399096651318805,
221 0.02699548325659403, -0.00449924720943234, -0.00224962360471617,
222 0.00134977416282970, -0.00011783742691370, -0.00011515930357476,
223 0.00003704737285544, 0.00000282690796889, -0.00000354513195524,
224 0.00000037669563126, 0.00000019202407921, -0.00000005226908590,
225 -0.00000000491799345, 0.00000000366377919, -0.00000000015981997,
226 -0.00000000017381238, 0.00000000002624031, 0.00000000000560919,
227 -0.00000000000172127, -0.00000000000008634, 0.00000000000007894 };
228 nVal
= taylor(t2
, 23, (xAbs
- 2.0));
230 else if ((xShort
>= 3) && (xShort
<= 4))
232 static const double t4
[] =
233 { 0.49996832875816688, 0.00013383022576489, -0.00026766045152977,
234 0.00033457556441221, -0.00028996548915725, 0.00018178605666397,
235 -0.00008252863922168, 0.00002551802519049, -0.00000391665839292,
236 -0.00000074018205222, 0.00000064422023359, -0.00000017370155340,
237 0.00000000909595465, 0.00000000944943118, -0.00000000329957075,
238 0.00000000029492075, 0.00000000011874477, -0.00000000004420396,
239 0.00000000000361422, 0.00000000000143638, -0.00000000000045848 };
240 nVal
= taylor(t4
, 20, (xAbs
- 4.0));
244 static const double asympt
[] = { -1.0, 1.0, -3.0, 15.0, -105.0 };
245 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>
255 double ScInterpreter::gaussinv(double x
)
274 t
*2509.0809287301226727+33430.575583588128105
276 *t
+67265.770927008700853
278 *t
+45921.953931549871457
280 *t
+13731.693765509461125
282 *t
+1971.5909503065514427
284 *t
+133.14166789178437745
286 *t
+3.387132872796366608
296 t
*5226.495278852854561+28729.085735721942674
298 *t
+39307.89580009271061
300 *t
+21213.794301586595867
302 *t
+5394.1960214247511077
304 *t
+687.1870074920579083
306 *t
+42.313330701600911252
331 t
*7.7454501427834140764e-4+0.0227238449892691845833
333 *t
+0.24178072517745061177
335 *t
+1.27045825245236838258
337 *t
+3.64784832476320460504
339 *t
+5.7694972214606914055
341 *t
+4.6303378461565452959
343 *t
+1.42343711074968357734
353 t
*1.05075007164441684324e-9+5.475938084995344946e-4
355 *t
+0.0151986665636164571966
357 *t
+0.14810397642748007459
359 *t
+0.68976733498510000455
361 *t
+1.6763848301838038494
363 *t
+2.05319162663775882187
381 t
*2.01033439929228813265e-7+2.71155556874348757815e-5
383 *t
+0.0012426609473880784386
385 *t
+0.026532189526576123093
387 *t
+0.29656057182850489123
389 *t
+1.7848265399172913358
391 *t
+5.4637849111641143699
393 *t
+6.6579046435011037772
403 t
*2.04426310338993978564e-15+1.4215117583164458887e-7
405 *t
+1.8463183175100546818e-5
407 *t
+7.868691311456132591e-4
409 *t
+0.0148753612908506148525
411 *t
+0.13692988092273580531
413 *t
+0.59983220655588793769
426 double ScInterpreter::Fakultaet(double x
)
428 x
= ::rtl::math::approxFloor(x
);
443 SetError(errNoValue
);
447 double ScInterpreter::BinomKoeff(double n
, double k
)
449 // this method has been duplicated as BinomialCoefficient()
450 // in scaddins/source/analysis/analysishelper.cxx
453 k
= ::rtl::math::approxFloor(k
);
474 // The algorithm is based on lanczos13m53 in lanczos.hpp
475 // in math library from http://www.boost.org
476 /** you must ensure fZ>0
477 Uses a variant of the Lanczos sum with a rational function. */
478 static double lcl_getLanczosSum(double fZ
)
480 static const double fNum
[13] ={
481 23531376880.41075968857200767445163675473,
482 42919803642.64909876895789904700198885093,
483 35711959237.35566804944018545154716670596,
484 17921034426.03720969991975575445893111267,
485 6039542586.35202800506429164430729792107,
486 1439720407.311721673663223072794912393972,
487 248874557.8620541565114603864132294232163,
488 31426415.58540019438061423162831820536287,
489 2876370.628935372441225409051620849613599,
490 186056.2653952234950402949897160456992822,
491 8071.672002365816210638002902272250613822,
492 210.8242777515793458725097339207133627117,
493 2.506628274631000270164908177133837338626
495 static const double fDenom
[13] = {
517 fSumDenom
= fDenom
[12];
518 for (nI
= 11; nI
>= 0; --nI
)
523 fSumDenom
+= fDenom
[nI
];
527 // Cancel down with fZ^12; Horner scheme with reverse coefficients
531 fSumDenom
= fDenom
[0];
532 for (nI
= 1; nI
<=12; ++nI
)
537 fSumDenom
+= fDenom
[nI
];
540 return fSumNum
/fSumDenom
;
543 // The algorithm is based on tgamma in gamma.hpp
544 // in math library from http://www.boost.org
545 /** You must ensure fZ>0; fZ>171.624376956302 will overflow. */
546 static double lcl_GetGammaHelper(double fZ
)
548 double fGamma
= lcl_getLanczosSum(fZ
);
549 const double fg
= 6.024680040776729583740234375;
550 double fZgHelp
= fZ
+ fg
- 0.5;
551 // avoid intermediate overflow
552 double fHalfpower
= pow( fZgHelp
, fZ
/ 2 - 0.25);
553 fGamma
*= fHalfpower
;
554 fGamma
/= exp(fZgHelp
);
555 fGamma
*= fHalfpower
;
556 if (fZ
<= 20.0 && fZ
== ::rtl::math::approxFloor(fZ
))
557 fGamma
= ::rtl::math::round(fGamma
);
561 // The algorithm is based on tgamma in gamma.hpp
562 // in math library from http://www.boost.org
563 /** You must ensure fZ>0 */
564 static double lcl_GetLogGammaHelper(double fZ
)
566 const double fg
= 6.024680040776729583740234375;
567 double fZgHelp
= fZ
+ fg
- 0.5;
568 return log( lcl_getLanczosSum(fZ
)) + (fZ
-0.5) * log(fZgHelp
) - fZgHelp
;
571 /** You must ensure non integer arguments for fZ<1 */
572 double ScInterpreter::GetGamma(double fZ
)
574 const double fLogPi
= log(F_PI
);
575 const double fLogDblMax
= log( ::std::numeric_limits
<double>::max());
577 if (fZ
> fMaxGammaArgument
)
579 SetError(errIllegalFPOperation
);
584 return lcl_GetGammaHelper(fZ
);
586 if (fZ
>= 0.5) // shift to x>=1 using Gamma(x)=Gamma(x+1)/x
587 return lcl_GetGammaHelper(fZ
+1) / fZ
;
589 if (fZ
>= -0.5) // shift to x>=1, might overflow
591 double fLogTest
= lcl_GetLogGammaHelper(fZ
+2) - boost::math::log1p(fZ
) - log( fabs(fZ
));
592 if (fLogTest
>= fLogDblMax
)
594 SetError( errIllegalFPOperation
);
597 return lcl_GetGammaHelper(fZ
+2) / (fZ
+1) / fZ
;
600 // Use Euler's reflection formula: gamma(x)= pi/ ( gamma(1-x)*sin(pi*x) )
601 double fLogDivisor
= lcl_GetLogGammaHelper(1-fZ
) + log( fabs( ::rtl::math::sin( F_PI
*fZ
)));
602 if (fLogDivisor
- fLogPi
>= fLogDblMax
) // underflow
606 if (fLogPi
- fLogDivisor
> fLogDblMax
) // overflow
608 SetError(errIllegalFPOperation
);
612 return exp( fLogPi
- fLogDivisor
) * ((::rtl::math::sin( F_PI
*fZ
) < 0.0) ? -1.0 : 1.0);
615 /** You must ensure fZ>0 */
616 double ScInterpreter::GetLogGamma(double fZ
)
618 if (fZ
>= fMaxGammaArgument
)
619 return lcl_GetLogGammaHelper(fZ
);
621 return log(lcl_GetGammaHelper(fZ
));
623 return log( lcl_GetGammaHelper(fZ
+1) / fZ
);
624 return lcl_GetLogGammaHelper(fZ
+2) - boost::math::log1p(fZ
) - log(fZ
);
627 double ScInterpreter::GetFDist(double x
, double fF1
, double fF2
)
629 double arg
= fF2
/(fF2
+fF1
*x
);
630 double alpha
= fF2
/2.0;
631 double beta
= fF1
/2.0;
632 return GetBetaDist(arg
, alpha
, beta
);
635 double ScInterpreter::GetTDist( double T
, double fDF
, int nType
)
639 case 1 : // 1-tailed T-distribution
640 return 0.5 * GetBetaDist( fDF
/ ( fDF
+ T
* T
), fDF
/ 2.0, 0.5 );
641 case 2 : // 2-tailed T-distribution
642 return GetBetaDist( fDF
/ ( fDF
+ T
* T
), fDF
/ 2.0, 0.5);
643 case 3 : // left-tailed T-distribution (probability density function)
644 return pow( 1 + ( T
* T
/ fDF
), -( fDF
+ 1 ) / 2 ) / ( sqrt( fDF
) * GetBeta( 0.5, fDF
/ 2.0 ) );
645 case 4 : // left-tailed T-distribution (cumulative distribution function)
646 double X
= fDF
/ ( T
* T
+ fDF
);
647 double R
= 0.5 * GetBetaDist( X
, 0.5 * fDF
, 0.5 );
648 return ( T
< 0 ? R
: 1 - R
);
650 SetError( errIllegalArgument
);
654 // for LEGACY.CHIDIST, returns right tail, fDF=degrees of freedom
655 /** You must ensure fDF>0.0 */
656 double ScInterpreter::GetChiDist(double fX
, double fDF
)
659 return 1.0; // see ODFF
661 return GetUpRegIGamma( fDF
/2.0, fX
/2.0);
665 // for ODF CHISQDIST; cumulative distribution function, fDF=degrees of freedom
667 /** You must ensure fDF>0.0 */
668 double ScInterpreter::GetChiSqDistCDF(double fX
, double fDF
)
671 return 0.0; // see ODFF
673 return GetLowRegIGamma( fDF
/2.0, fX
/2.0);
676 double ScInterpreter::GetChiSqDistPDF(double fX
, double fDF
)
678 // you must ensure fDF is positive integer
681 return 0.0; // see ODFF
682 if (fDF
*fX
> 1391000.0)
684 // intermediate invalid values, use log
685 fValue
= exp((0.5*fDF
- 1) * log(fX
*0.5) - 0.5 * fX
- log(2.0) - GetLogGamma(0.5*fDF
));
687 else // fDF is small in most cases, we can iterate
690 if (fmod(fDF
,2.0)<0.5)
698 fValue
= 1/sqrt(fX
*2*F_PI
);
701 while ( fCount
< fDF
)
703 fValue
*= (fX
/ fCount
);
706 if (fX
>=1425.0) // underflow in e^(-x/2)
707 fValue
= exp(log(fValue
)-fX
/2);
709 fValue
*= exp(-fX
/2);
714 void ScInterpreter::ScChiSqDist()
716 sal_uInt8 nParamCount
= GetByte();
717 if ( !MustHaveParamCount( nParamCount
, 2, 3 ) )
720 if (nParamCount
== 3)
721 bCumulative
= GetBool();
724 double fDF
= ::rtl::math::approxFloor(GetDouble());
726 PushIllegalArgument();
729 double fX
= GetDouble();
731 PushDouble(GetChiSqDistCDF(fX
,fDF
));
733 PushDouble(GetChiSqDistPDF(fX
,fDF
));
737 void ScInterpreter::ScChiSqDist_MS()
739 sal_uInt8 nParamCount
= GetByte();
740 if ( !MustHaveParamCount( nParamCount
, 3, 3 ) )
742 bool bCumulative
= GetBool();
743 double fDF
= ::rtl::math::approxFloor( GetDouble() );
744 if ( fDF
< 1.0 || fDF
> 1E10
)
745 PushIllegalArgument();
748 double fX
= GetDouble();
750 PushIllegalArgument();
754 PushDouble( GetChiSqDistCDF( fX
, fDF
) );
756 PushDouble( GetChiSqDistPDF( fX
, fDF
) );
761 void ScInterpreter::ScGamma()
763 double x
= GetDouble();
764 if (x
<= 0.0 && x
== ::rtl::math::approxFloor(x
))
765 PushIllegalArgument();
768 double fResult
= GetGamma(x
);
771 PushError( nGlobalError
);
778 void ScInterpreter::ScLogGamma()
780 double x
= GetDouble();
781 if (x
> 0.0) // constraint from ODFF
782 PushDouble( GetLogGamma(x
));
784 PushIllegalArgument();
787 double ScInterpreter::GetBeta(double fAlpha
, double fBeta
)
793 fA
= fAlpha
; fB
= fBeta
;
797 fA
= fBeta
; fB
= fAlpha
;
799 if (fA
+fB
< fMaxGammaArgument
) // simple case
800 return GetGamma(fA
)/GetGamma(fA
+fB
)*GetGamma(fB
);
802 // GetLogGamma is not accurate enough, back to Lanczos for all three
803 // GetGamma and arrange factors newly.
804 const double fg
= 6.024680040776729583740234375; //see GetGamma
805 double fgm
= fg
- 0.5;
806 double fLanczos
= lcl_getLanczosSum(fA
);
807 fLanczos
/= lcl_getLanczosSum(fA
+fB
);
808 fLanczos
*= lcl_getLanczosSum(fB
);
809 double fABgm
= fA
+fB
+fgm
;
810 fLanczos
*= sqrt((fABgm
/(fA
+fgm
))/(fB
+fgm
));
811 double fTempA
= fB
/(fA
+fgm
); // (fA+fgm)/fABgm = 1 / ( 1 + fB/(fA+fgm))
812 double fTempB
= fA
/(fB
+fgm
);
813 double fResult
= exp(-fA
* ::rtl::math::log1p(fTempA
)
814 -fB
* ::rtl::math::log1p(fTempB
)-fgm
);
819 // Same as GetBeta but with logarithm
820 double ScInterpreter::GetLogBeta(double fAlpha
, double fBeta
)
826 fA
= fAlpha
; fB
= fBeta
;
830 fA
= fBeta
; fB
= fAlpha
;
832 const double fg
= 6.024680040776729583740234375; //see GetGamma
833 double fgm
= fg
- 0.5;
834 double fLanczos
= lcl_getLanczosSum(fA
);
835 fLanczos
/= lcl_getLanczosSum(fA
+fB
);
836 fLanczos
*= lcl_getLanczosSum(fB
);
837 double fLogLanczos
= log(fLanczos
);
838 double fABgm
= fA
+fB
+fgm
;
839 fLogLanczos
+= 0.5*(log(fABgm
)-log(fA
+fgm
)-log(fB
+fgm
));
840 double fTempA
= fB
/(fA
+fgm
); // (fA+fgm)/fABgm = 1 / ( 1 + fB/(fA+fgm))
841 double fTempB
= fA
/(fB
+fgm
);
842 double fResult
= -fA
* ::rtl::math::log1p(fTempA
)
843 -fB
* ::rtl::math::log1p(fTempB
)-fgm
;
844 fResult
+= fLogLanczos
;
848 // beta distribution probability density function
849 double ScInterpreter::GetBetaDistPDF(double fX
, double fA
, double fB
)
852 if (fA
== 1.0) // result b*(1-x)^(b-1)
857 return -2.0*fX
+ 2.0;
858 if (fX
== 1.0 && fB
< 1.0)
860 SetError(errIllegalArgument
);
864 return fB
+ fB
* ::rtl::math::expm1((fB
-1.0) * ::rtl::math::log1p(-fX
));
866 return fB
* pow(0.5-fX
+0.5,fB
-1.0);
868 if (fB
== 1.0) // result a*x^(a-1)
872 if (fX
== 0.0 && fA
< 1.0)
874 SetError(errIllegalArgument
);
877 return fA
* pow(fX
,fA
-1);
881 if (fA
< 1.0 && fX
== 0.0)
883 SetError(errIllegalArgument
);
891 if (fB
< 1.0 && fX
== 1.0)
893 SetError(errIllegalArgument
);
900 // normal cases; result x^(a-1)*(1-x)^(b-1)/Beta(a,b)
901 const double fLogDblMax
= log( ::std::numeric_limits
<double>::max());
902 const double fLogDblMin
= log( ::std::numeric_limits
<double>::min());
903 double fLogY
= (fX
< 0.1) ? ::rtl::math::log1p(-fX
) : log(0.5-fX
+0.5);
904 double fLogX
= log(fX
);
905 double fAm1LogX
= (fA
-1.0) * fLogX
;
906 double fBm1LogY
= (fB
-1.0) * fLogY
;
907 double fLogBeta
= GetLogBeta(fA
,fB
);
908 // check whether parts over- or underflow
909 if ( fAm1LogX
< fLogDblMax
&& fAm1LogX
> fLogDblMin
910 && fBm1LogY
< fLogDblMax
&& fBm1LogY
> fLogDblMin
911 && fLogBeta
< fLogDblMax
&& fLogBeta
> fLogDblMin
912 && fAm1LogX
+ fBm1LogY
< fLogDblMax
&& fAm1LogX
+ fBm1LogY
> fLogDblMin
)
913 return pow(fX
,fA
-1.0) * pow(0.5-fX
+0.5,fB
-1.0) / GetBeta(fA
,fB
);
914 else // need logarithm;
915 // might overflow as a whole, but seldom, not worth to pre-detect it
916 return exp( fAm1LogX
+ fBm1LogY
- fLogBeta
);
921 I_x(a,b) = ---------------- * result of ContFrac
924 static double lcl_GetBetaHelperContFrac(double fX
, double fA
, double fB
)
925 { // like old version
926 double a1
, b1
, a2
, b2
, fnorm
, cfnew
, cf
;
928 b2
= 1.0 - (fA
+fB
)/(fA
+1.0)*fX
;
944 const double fMaxIter
= 50000.0;
945 // loop security, normal cases converge in less than 100 iterations.
946 // FIXME: You will get so much iteratons for fX near mean,
947 // I do not know a better algorithm.
948 bool bfinished
= false;
951 const double apl2m
= fA
+ 2.0*rm
;
952 const double d2m
= rm
*(fB
-rm
)*fX
/((apl2m
-1.0)*apl2m
);
953 const double d2m1
= -(fA
+rm
)*(fA
+fB
+rm
)*fX
/(apl2m
*(apl2m
+1.0));
954 a1
= (a2
+d2m
*a1
)*fnorm
;
955 b1
= (b2
+d2m
*b1
)*fnorm
;
956 a2
= a1
+ d2m1
*a2
*fnorm
;
957 b2
= b1
+ d2m1
*b2
*fnorm
;
962 bfinished
= (fabs(cf
-cfnew
) < fabs(cf
)*fMachEps
);
967 while (rm
< fMaxIter
&& !bfinished
);
971 // cumulative distribution function, normalized
972 double ScInterpreter::GetBetaDist(double fXin
, double fAlpha
, double fBeta
)
975 if (fXin
<= 0.0) // values are valid, see spec
977 if (fXin
>= 1.0) // values are valid, see spec
980 return pow(fXin
, fAlpha
);
982 // 1.0 - pow(1.0-fX,fBeta) is not accurate enough
983 return -::rtl::math::expm1(fBeta
* ::rtl::math::log1p(-fXin
));
984 //FIXME: need special algorithm for fX near fP for large fA,fB
986 // I use always continued fraction, power series are neither
987 // faster nor more accurate.
988 double fY
= (0.5-fXin
)+0.5;
989 double flnY
= ::rtl::math::log1p(-fXin
);
991 double flnX
= log(fXin
);
994 bool bReflect
= fXin
> fAlpha
/(fAlpha
+fBeta
);
1004 fResult
= lcl_GetBetaHelperContFrac(fX
,fA
,fB
);
1005 fResult
= fResult
/fA
;
1006 double fP
= fA
/(fA
+fB
);
1007 double fQ
= fB
/(fA
+fB
);
1009 if (fA
> 1.0 && fB
> 1.0 && fP
< 0.97 && fQ
< 0.97) //found experimental
1010 fTemp
= GetBetaDistPDF(fX
,fA
,fB
)*fX
*fY
;
1012 fTemp
= exp(fA
*flnX
+ fB
*flnY
- GetLogBeta(fA
,fB
));
1015 fResult
= 0.5 - fResult
+ 0.5;
1016 if (fResult
> 1.0) // ensure valid range
1023 void ScInterpreter::ScBetaDist()
1025 sal_uInt8 nParamCount
= GetByte();
1026 if ( !MustHaveParamCount( nParamCount
, 3, 6 ) ) // expanded, see #i91547#
1028 double fLowerBound
, fUpperBound
;
1029 double alpha
, beta
, x
;
1031 if (nParamCount
== 6)
1032 bIsCumulative
= GetBool();
1034 bIsCumulative
= true;
1035 if (nParamCount
>= 5)
1036 fUpperBound
= GetDouble();
1039 if (nParamCount
>= 4)
1040 fLowerBound
= GetDouble();
1044 alpha
= GetDouble();
1046 double fScale
= fUpperBound
- fLowerBound
;
1047 if (fScale
<= 0.0 || alpha
<= 0.0 || beta
<= 0.0)
1049 PushIllegalArgument();
1052 if (bIsCumulative
) // cumulative distribution function
1055 if (x
< fLowerBound
)
1057 PushDouble(0.0); return; //see spec
1059 if (x
> fUpperBound
)
1061 PushDouble(1.0); return; //see spec
1064 x
= (x
-fLowerBound
)/fScale
; // convert to standard form
1065 PushDouble(GetBetaDist(x
, alpha
, beta
));
1068 else // probability density function
1070 if (x
< fLowerBound
|| x
> fUpperBound
)
1075 x
= (x
-fLowerBound
)/fScale
;
1076 PushDouble(GetBetaDistPDF(x
, alpha
, beta
)/fScale
);
1083 Microsoft version has parameters in different order
1084 Also, upper and lowerbound are optional and have default values
1085 otherwise, function is identical with ScInterpreter::ScBetaDist()
1087 void ScInterpreter::ScBetaDist_MS()
1089 sal_uInt8 nParamCount
= GetByte();
1090 if ( !MustHaveParamCount( nParamCount
, 4, 6 ) )
1092 double fLowerBound
, fUpperBound
;
1093 double alpha
, beta
, x
;
1095 if (nParamCount
== 6)
1096 fUpperBound
= GetDouble();
1099 if (nParamCount
>= 4)
1100 fLowerBound
= GetDouble();
1103 bIsCumulative
= GetBool();
1105 alpha
= GetDouble();
1107 double fScale
= fUpperBound
- fLowerBound
;
1108 if (fScale
<= 0.0 || alpha
<= 0.0 || beta
<= 0.0)
1110 PushIllegalArgument();
1113 if (bIsCumulative
) // cumulative distribution function
1116 if (x
< fLowerBound
)
1118 PushDouble(0.0); return; //see spec
1120 if (x
> fUpperBound
)
1122 PushDouble(1.0); return; //see spec
1125 x
= (x
-fLowerBound
)/fScale
; // convert to standard form
1126 PushDouble(GetBetaDist(x
, alpha
, beta
));
1129 else // probability density function
1131 if (x
< fLowerBound
|| x
> fUpperBound
)
1136 x
= (x
-fLowerBound
)/fScale
;
1137 PushDouble(GetBetaDistPDF(x
, alpha
, beta
)/fScale
);
1142 void ScInterpreter::ScPhi()
1144 PushDouble(phi(GetDouble()));
1147 void ScInterpreter::ScGauss()
1149 PushDouble(gauss(GetDouble()));
1152 void ScInterpreter::ScFisher()
1154 double fVal
= GetDouble();
1155 if (fabs(fVal
) >= 1.0)
1156 PushIllegalArgument();
1158 PushDouble( ::rtl::math::atanh( fVal
));
1161 void ScInterpreter::ScFisherInv()
1163 PushDouble( tanh( GetDouble()));
1166 void ScInterpreter::ScFact()
1168 double nVal
= GetDouble();
1170 PushIllegalArgument();
1172 PushDouble(Fakultaet(nVal
));
1175 void ScInterpreter::ScCombin()
1177 if ( MustHaveParamCount( GetByte(), 2 ) )
1179 double k
= ::rtl::math::approxFloor(GetDouble());
1180 double n
= ::rtl::math::approxFloor(GetDouble());
1181 if (k
< 0.0 || n
< 0.0 || k
> n
)
1182 PushIllegalArgument();
1184 PushDouble(BinomKoeff(n
, k
));
1188 void ScInterpreter::ScCombinA()
1190 if ( MustHaveParamCount( GetByte(), 2 ) )
1192 double k
= ::rtl::math::approxFloor(GetDouble());
1193 double n
= ::rtl::math::approxFloor(GetDouble());
1194 if (k
< 0.0 || n
< 0.0 || k
> n
)
1195 PushIllegalArgument();
1197 PushDouble(BinomKoeff(n
+ k
- 1, k
));
1201 void ScInterpreter::ScPermut()
1203 if ( MustHaveParamCount( GetByte(), 2 ) )
1205 double k
= ::rtl::math::approxFloor(GetDouble());
1206 double n
= ::rtl::math::approxFloor(GetDouble());
1207 if (n
< 0.0 || k
< 0.0 || k
> n
)
1208 PushIllegalArgument();
1210 PushInt(1); // (n! / (n - 0)!) == 1
1214 for (sal_uLong i
= (sal_uLong
)k
-1; i
>= 1; i
--)
1215 nVal
*= n
-(double)i
;
1221 void ScInterpreter::ScPermutationA()
1223 if ( MustHaveParamCount( GetByte(), 2 ) )
1225 double k
= ::rtl::math::approxFloor(GetDouble());
1226 double n
= ::rtl::math::approxFloor(GetDouble());
1227 if (n
< 0.0 || k
< 0.0 || k
> n
)
1228 PushIllegalArgument();
1230 PushDouble(pow(n
,k
));
1234 double ScInterpreter::GetBinomDistPMF(double x
, double n
, double p
)
1235 // used in ScB and ScBinomDist
1236 // preconditions: 0.0 <= x <= n, 0.0 < p < 1.0; x,n integral although double
1238 double q
= (0.5 - p
) + 0.5;
1239 double fFactor
= pow(q
, n
);
1240 if (fFactor
<=::std::numeric_limits
<double>::min())
1242 fFactor
= pow(p
, n
);
1243 if (fFactor
<= ::std::numeric_limits
<double>::min())
1244 return GetBetaDistPDF(p
, x
+1.0, n
-x
+1.0)/(n
+1.0);
1247 sal_uInt32 max
= static_cast<sal_uInt32
>(n
- x
);
1248 for (sal_uInt32 i
= 0; i
< max
&& fFactor
> 0.0; i
++)
1249 fFactor
*= (n
-i
)/(i
+1)*q
/p
;
1255 sal_uInt32 max
= static_cast<sal_uInt32
>(x
);
1256 for (sal_uInt32 i
= 0; i
< max
&& fFactor
> 0.0; i
++)
1257 fFactor
*= (n
-i
)/(i
+1)*p
/q
;
1262 double lcl_GetBinomDistRange(double n
, double xs
,double xe
,
1263 double fFactor
/* q^n */, double p
, double q
)
1264 //preconditions: 0.0 <= xs < xe <= n; xs,xe,n integral although double
1268 // skip summands index 0 to xs-1, start sum with index xs
1269 sal_uInt32 nXs
= static_cast<sal_uInt32
>( xs
);
1270 for (i
= 1; i
<= nXs
&& fFactor
> 0.0; i
++)
1271 fFactor
*= (n
-i
+1)/i
* p
/q
;
1272 fSum
= fFactor
; // Summand xs
1273 sal_uInt32 nXe
= static_cast<sal_uInt32
>(xe
);
1274 for (i
= nXs
+1; i
<= nXe
&& fFactor
> 0.0; i
++)
1276 fFactor
*= (n
-i
+1)/i
* p
/q
;
1279 return (fSum
>1.0) ? 1.0 : fSum
;
1282 void ScInterpreter::ScB()
1284 sal_uInt8 nParamCount
= GetByte();
1285 if ( !MustHaveParamCount( nParamCount
, 3, 4 ) )
1287 if (nParamCount
== 3) // mass function
1289 double x
= ::rtl::math::approxFloor(GetDouble());
1290 double p
= GetDouble();
1291 double n
= ::rtl::math::approxFloor(GetDouble());
1292 if (n
< 0.0 || x
< 0.0 || x
> n
|| p
< 0.0 || p
> 1.0)
1293 PushIllegalArgument();
1295 PushDouble( (x
== 0.0) ? 1.0 : 0.0 );
1297 PushDouble( (x
== n
) ? 1.0 : 0.0);
1299 PushDouble(GetBinomDistPMF(x
,n
,p
));
1302 { // nParamCount == 4
1303 double xe
= ::rtl::math::approxFloor(GetDouble());
1304 double xs
= ::rtl::math::approxFloor(GetDouble());
1305 double p
= GetDouble();
1306 double n
= ::rtl::math::approxFloor(GetDouble());
1307 double q
= (0.5 - p
) + 0.5;
1308 bool bIsValidX
= ( 0.0 <= xs
&& xs
<= xe
&& xe
<= n
);
1309 if ( bIsValidX
&& 0.0 < p
&& p
< 1.0)
1311 if (xs
== xe
) // mass function
1312 PushDouble(GetBinomDistPMF(xs
,n
,p
));
1315 double fFactor
= pow(q
, n
);
1316 if (fFactor
> ::std::numeric_limits
<double>::min())
1317 PushDouble(lcl_GetBinomDistRange(n
,xs
,xe
,fFactor
,p
,q
));
1320 fFactor
= pow(p
, n
);
1321 if (fFactor
> ::std::numeric_limits
<double>::min())
1323 // sum from j=xs to xe {(n choose j) * p^j * q^(n-j)}
1324 // = sum from i = n-xe to n-xs { (n choose i) * q^i * p^(n-i)}
1325 PushDouble(lcl_GetBinomDistRange(n
,n
-xe
,n
-xs
,fFactor
,q
,p
));
1328 PushDouble(GetBetaDist(q
,n
-xe
,xe
+1.0)-GetBetaDist(q
,n
-xs
+1,xs
) );
1334 if ( bIsValidX
) // not(0<p<1)
1337 PushDouble( (xs
== 0.0) ? 1.0 : 0.0 );
1338 else if ( p
== 1.0 )
1339 PushDouble( (xe
== n
) ? 1.0 : 0.0 );
1341 PushIllegalArgument();
1344 PushIllegalArgument();
1349 void ScInterpreter::ScBinomDist()
1351 if ( MustHaveParamCount( GetByte(), 4 ) )
1353 bool bIsCum
= GetBool(); // false=mass function; true=cumulative
1354 double p
= GetDouble();
1355 double n
= ::rtl::math::approxFloor(GetDouble());
1356 double x
= ::rtl::math::approxFloor(GetDouble());
1357 double q
= (0.5 - p
) + 0.5; // get one bit more for p near 1.0
1358 if (n
< 0.0 || x
< 0.0 || x
> n
|| p
< 0.0 || p
> 1.0)
1360 PushIllegalArgument();
1365 PushDouble( (x
==0.0 || bIsCum
) ? 1.0 : 0.0 );
1370 PushDouble( (x
==n
) ? 1.0 : 0.0);
1374 PushDouble( GetBinomDistPMF(x
,n
,p
));
1381 double fFactor
= pow(q
, n
);
1383 PushDouble(fFactor
);
1384 else if (fFactor
<= ::std::numeric_limits
<double>::min())
1386 fFactor
= pow(p
, n
);
1387 if (fFactor
<= ::std::numeric_limits
<double>::min())
1388 PushDouble(GetBetaDist(q
,n
-x
,x
+1.0));
1391 if (fFactor
> fMachEps
)
1393 double fSum
= 1.0 - fFactor
;
1394 sal_uInt32 max
= static_cast<sal_uInt32
> (n
- x
) - 1;
1395 for (sal_uInt32 i
= 0; i
< max
&& fFactor
> 0.0; i
++)
1397 fFactor
*= (n
-i
)/(i
+1)*q
/p
;
1400 PushDouble( (fSum
< 0.0) ? 0.0 : fSum
);
1403 PushDouble(lcl_GetBinomDistRange(n
,n
-x
,n
,fFactor
,q
,p
));
1407 PushDouble( lcl_GetBinomDistRange(n
,0.0,x
,fFactor
,p
,q
)) ;
1413 void ScInterpreter::ScCritBinom()
1415 if ( MustHaveParamCount( GetByte(), 3 ) )
1417 double alpha
= GetDouble();
1418 double p
= GetDouble();
1419 double n
= ::rtl::math::approxFloor(GetDouble());
1420 if (n
< 0.0 || alpha
<= 0.0 || alpha
>= 1.0 || p
< 0.0 || p
> 1.0)
1421 PushIllegalArgument();
1425 double q
= (0.5 - p
) + 0.5; // get one bit more for p near 1.0
1426 if ( q
> p
) // work from the side where the cumulative curve is
1428 // work from 0 upwards
1430 if (fFactor
> ::std::numeric_limits
<double>::min())
1432 double fSum
= fFactor
;
1433 sal_uInt32 max
= static_cast<sal_uInt32
> (n
), i
;
1434 for (i
= 0; i
< max
&& fSum
< alpha
; i
++)
1436 fFactor
*= (n
-i
)/(i
+1)*p
/q
;
1443 // accumulate BinomDist until accumulated BinomDist reaches alpha
1445 sal_uInt32 max
= static_cast<sal_uInt32
> (n
), i
;
1446 for (i
= 0; i
< max
&& fSum
< alpha
; i
++)
1448 const double x
= GetBetaDistPDF( p
, ( i
+ 1 ), ( n
- i
+ 1 ) )/( n
+ 1 );
1449 if ( !nGlobalError
)
1459 PushDouble( i
- 1 );
1464 // work from n backwards
1465 fFactor
= pow(p
, n
);
1466 if (fFactor
> ::std::numeric_limits
<double>::min())
1468 double fSum
= 1.0 - fFactor
;
1469 sal_uInt32 max
= static_cast<sal_uInt32
> (n
), i
;
1470 for (i
= 0; i
< max
&& fSum
>= alpha
; i
++)
1472 fFactor
*= (n
-i
)/(i
+1)*q
/p
;
1479 // accumulate BinomDist until accumulated BinomDist reaches alpha
1481 sal_uInt32 max
= static_cast<sal_uInt32
> (n
), i
;
1483 for (i
= 0; i
< max
&& fSum
< alpha
; i
++)
1485 const double x
= GetBetaDistPDF( q
, ( i
+ 1 ), ( n
- i
+ 1 ) )/( n
+ 1 );
1486 if ( !nGlobalError
)
1496 PushDouble( n
- i
+ 1 );
1503 void ScInterpreter::ScNegBinomDist()
1505 if ( MustHaveParamCount( GetByte(), 3 ) )
1507 double p
= GetDouble(); // p
1508 double r
= GetDouble(); // r
1509 double x
= GetDouble(); // x
1510 if (r
< 0.0 || x
< 0.0 || p
< 0.0 || p
> 1.0)
1511 PushIllegalArgument();
1515 double fFactor
= pow(p
,r
);
1516 for (double i
= 0.0; i
< x
; i
++)
1517 fFactor
*= (i
+r
)/(i
+1.0)*q
;
1518 PushDouble(fFactor
);
1523 void ScInterpreter::ScNegBinomDist_MS()
1525 if ( MustHaveParamCount( GetByte(), 4 ) )
1527 bool bCumulative
= GetBool();
1528 double p
= GetDouble(); // p
1529 double r
= GetDouble(); // r
1530 double x
= GetDouble(); // x
1531 if ( r
< 0.0 || x
< 0.0 || p
< 0.0 || p
> 1.0 )
1532 PushIllegalArgument();
1537 PushDouble( 1.0 - GetBetaDist( q
, x
+ 1, r
) );
1540 double fFactor
= pow( p
, r
);
1541 for ( double i
= 0.0; i
< x
; i
++ )
1542 fFactor
*= ( i
+ r
) / ( i
+ 1.0 ) * q
;
1543 PushDouble( fFactor
);
1549 void ScInterpreter::ScNormDist( int nMinParamCount
)
1551 sal_uInt8 nParamCount
= GetByte();
1552 if ( !MustHaveParamCount( nParamCount
, nMinParamCount
, 4 ) )
1554 bool bCumulative
= nParamCount
!= 4 || GetBool();
1555 double sigma
= GetDouble(); // standard deviation
1556 double mue
= GetDouble(); // mean
1557 double x
= GetDouble(); // x
1560 PushIllegalArgument();
1564 PushDouble(integralPhi((x
-mue
)/sigma
));
1566 PushDouble(phi((x
-mue
)/sigma
)/sigma
);
1569 void ScInterpreter::ScLogNormDist( int nMinParamCount
) //expanded, see #i100119# and fdo72158
1571 sal_uInt8 nParamCount
= GetByte();
1572 if ( !MustHaveParamCount( nParamCount
, nMinParamCount
, 4 ) )
1574 bool bCumulative
= nParamCount
!= 4 || GetBool(); // cumulative
1575 double sigma
= nParamCount
>= 3 ? GetDouble() : 1.0; // standard deviation
1576 double mue
= nParamCount
>= 2 ? GetDouble() : 0.0; // mean
1577 double x
= GetDouble(); // x
1580 PushIllegalArgument();
1588 PushDouble(integralPhi((log(x
)-mue
)/sigma
));
1593 PushIllegalArgument();
1595 PushDouble(phi((log(x
)-mue
)/sigma
)/sigma
/x
);
1599 void ScInterpreter::ScStdNormDist()
1601 double fVal
= GetDouble();
1602 if (!rtl::math::isNan(fVal
))
1603 fVal
= integralPhi(fVal
);
1607 void ScInterpreter::ScStdNormDist_MS()
1609 sal_uInt8 nParamCount
= GetByte();
1610 if ( !MustHaveParamCount( nParamCount
, 2 ) )
1612 bool bCumulative
= GetBool(); // cumulative
1613 double x
= GetDouble(); // x
1616 PushDouble( integralPhi( x
) );
1618 PushDouble( exp( - pow( x
, 2 ) / 2 ) / sqrt( 2 * F_PI
) );
1621 void ScInterpreter::ScExpDist()
1623 if ( MustHaveParamCount( GetByte(), 3 ) )
1625 double kum
= GetDouble(); // 0 oder 1
1626 double lambda
= GetDouble(); // lambda
1627 double x
= GetDouble(); // x
1629 PushIllegalArgument();
1630 else if (kum
== 0.0) // Dichte
1633 PushDouble(lambda
* exp(-lambda
*x
));
1640 PushDouble(1.0 - exp(-lambda
*x
));
1647 void ScInterpreter::ScTDist()
1649 if ( !MustHaveParamCount( GetByte(), 3 ) )
1651 double fFlag
= ::rtl::math::approxFloor(GetDouble());
1652 double fDF
= ::rtl::math::approxFloor(GetDouble());
1653 double T
= GetDouble();
1654 if (fDF
< 1.0 || T
< 0.0 || (fFlag
!= 1.0 && fFlag
!= 2.0) )
1656 PushIllegalArgument();
1659 PushDouble( GetTDist( T
, fDF
, ( int )fFlag
) );
1662 void ScInterpreter::ScTDist_T( int nTails
)
1664 if ( !MustHaveParamCount( GetByte(), 2 ) )
1666 double fDF
= ::rtl::math::approxFloor( GetDouble() );
1667 double T
= GetDouble();
1668 if ( fDF
< 1.0 || T
< 0.0 )
1670 PushIllegalArgument();
1673 PushDouble( GetTDist( T
, fDF
, nTails
) );
1676 void ScInterpreter::ScTDist_MS()
1678 if ( !MustHaveParamCount( GetByte(), 3 ) )
1680 bool bCumulative
= GetBool();
1681 double fDF
= ::rtl::math::approxFloor( GetDouble() );
1682 double T
= GetDouble();
1685 PushIllegalArgument();
1688 PushDouble( GetTDist( T
, fDF
, ( bCumulative
? 4 : 3 ) ) );
1691 void ScInterpreter::ScFDist()
1693 if ( !MustHaveParamCount( GetByte(), 3 ) )
1695 double fF2
= ::rtl::math::approxFloor(GetDouble());
1696 double fF1
= ::rtl::math::approxFloor(GetDouble());
1697 double fF
= GetDouble();
1698 if (fF
< 0.0 || fF1
< 1.0 || fF2
< 1.0 || fF1
>= 1.0E10
|| fF2
>= 1.0E10
)
1700 PushIllegalArgument();
1703 PushDouble(GetFDist(fF
, fF1
, fF2
));
1706 void ScInterpreter::ScFDist_LT()
1708 int nParamCount
= GetByte();
1709 if ( !MustHaveParamCount( nParamCount
, 3, 4 ) )
1712 if ( nParamCount
== 3 )
1714 else if ( IsMissing() )
1721 double fF2
= ::rtl::math::approxFloor( GetDouble() );
1722 double fF1
= ::rtl::math::approxFloor( GetDouble() );
1723 double fF
= GetDouble();
1724 if ( fF
< 0.0 || fF1
< 1.0 || fF2
< 1.0 || fF1
>= 1.0E10
|| fF2
>= 1.0E10
)
1726 PushIllegalArgument();
1731 // left tail cumulative distribution
1732 PushDouble( 1.0 - GetFDist( fF
, fF1
, fF2
) );
1736 // probability density function
1737 PushDouble( pow( fF1
/ fF2
, fF1
/ 2 ) * pow( fF
, ( fF1
/ 2 ) - 1 ) /
1738 ( pow( ( 1 + ( fF
* fF1
/ fF2
) ), ( fF1
+ fF2
) / 2 ) *
1739 GetBeta( fF1
/ 2, fF2
/ 2 ) ) );
1743 void ScInterpreter::ScChiDist()
1746 if ( !MustHaveParamCount( GetByte(), 2 ) )
1748 double fDF
= ::rtl::math::approxFloor(GetDouble());
1749 double fChi
= GetDouble();
1750 if (fDF
< 1.0) // x<=0 returns 1, see ODFF 6.17.10
1752 PushIllegalArgument();
1755 fResult
= GetChiDist( fChi
, fDF
);
1758 PushError( nGlobalError
);
1761 PushDouble(fResult
);
1764 void ScInterpreter::ScWeibull()
1766 if ( MustHaveParamCount( GetByte(), 4 ) )
1768 double kum
= GetDouble(); // 0 oder 1
1769 double beta
= GetDouble(); // beta
1770 double alpha
= GetDouble(); // alpha
1771 double x
= GetDouble(); // x
1772 if (alpha
<= 0.0 || beta
<= 0.0 || x
< 0.0)
1773 PushIllegalArgument();
1774 else if (kum
== 0.0) // Dichte
1775 PushDouble(alpha
/pow(beta
,alpha
)*pow(x
,alpha
-1.0)*
1776 exp(-pow(x
/beta
,alpha
)));
1778 PushDouble(1.0 - exp(-pow(x
/beta
,alpha
)));
1782 void ScInterpreter::ScPoissonDist()
1784 sal_uInt8 nParamCount
= GetByte();
1785 if ( MustHaveParamCount( nParamCount
, 2, 3 ) )
1787 bool bCumulative
= nParamCount
!= 3 || GetBool(); // default cumulative
1788 double lambda
= GetDouble(); // Mean
1789 double x
= ::rtl::math::approxFloor(GetDouble()); // discrete distribution
1790 if (lambda
< 0.0 || x
< 0.0)
1791 PushIllegalArgument();
1792 else if (!bCumulative
) // Probability mass function
1798 if (lambda
>712) // underflow in exp(-lambda)
1799 { // accuracy 11 Digits
1800 PushDouble( exp(x
*log(lambda
)-lambda
-GetLogGamma(x
+1.0)));
1804 double fPoissonVar
= 1.0;
1805 for ( double f
= 0.0; f
< x
; ++f
)
1806 fPoissonVar
*= lambda
/ ( f
+ 1.0 );
1807 PushDouble( fPoissonVar
* exp( -lambda
) );
1811 else // Cumulative distribution function
1817 if (lambda
> 712 ) // underflow in exp(-lambda)
1818 { // accuracy 12 Digits
1819 PushDouble(GetUpRegIGamma(x
+1.0,lambda
));
1823 if (x
>= 936.0) // result is always undistinghable from 1
1827 double fSummand
= exp(-lambda
);
1828 double fSum
= fSummand
;
1829 int nEnd
= sal::static_int_cast
<int>( x
);
1830 for (int i
= 1; i
<= nEnd
; i
++)
1832 fSummand
= (fSummand
* lambda
)/(double)i
;
1843 /** Local function used in the calculation of the hypergeometric distribution.
1845 static void lcl_PutFactorialElements( ::std::vector
< double >& cn
, double fLower
, double fUpper
, double fBase
)
1847 for ( double i
= fLower
; i
<= fUpper
; ++i
)
1849 double fVal
= fBase
- i
;
1851 cn
.push_back( fVal
);
1855 /** Calculates a value of the hypergeometric distribution.
1857 @author Kohei Yoshida <kohei@openoffice.org>
1862 void ScInterpreter::ScHypGeomDist()
1864 if ( !MustHaveParamCount( GetByte(), 4 ) )
1867 double N
= ::rtl::math::approxFloor(GetDouble());
1868 double M
= ::rtl::math::approxFloor(GetDouble());
1869 double n
= ::rtl::math::approxFloor(GetDouble());
1870 double x
= ::rtl::math::approxFloor(GetDouble());
1872 if( (x
< 0.0) || (n
< x
) || (M
< x
) || (N
< n
) || (N
< M
) || (x
< n
- N
+ M
) )
1874 PushIllegalArgument();
1878 PushDouble( GetHypGeomDist( x
, n
, M
, N
) );
1881 /** Calculates a value of the hypergeometric distribution (Excel 2010 function).
1883 This function has an extra argument bCumulative as compared to ScHypGeomDist(),
1884 which only calculates the non-cumulative distribution.
1888 void ScInterpreter::ScHypGeomDist_MS()
1890 if ( !MustHaveParamCount( GetByte(), 5 ) )
1893 bool bCumulative
= GetBool();
1894 double N
= ::rtl::math::approxFloor(GetDouble());
1895 double M
= ::rtl::math::approxFloor(GetDouble());
1896 double n
= ::rtl::math::approxFloor(GetDouble());
1897 double x
= ::rtl::math::approxFloor(GetDouble());
1899 if( (x
< 0.0) || (n
< x
) || (M
< x
) || (N
< n
) || (N
< M
) || (x
< n
- N
+ M
) )
1901 PushIllegalArgument();
1909 for ( int i
= 0; i
<= x
&& !nGlobalError
; i
++ )
1910 fVal
+= GetHypGeomDist( i
, n
, M
, N
);
1915 PushDouble( GetHypGeomDist( x
, n
, M
, N
) );
1918 /** Calculates a value of the hypergeometric distribution.
1920 The algorithm is designed to avoid unnecessary multiplications and division
1921 by expanding all factorial elements (9 of them). It is done by excluding
1922 those ranges that overlap in the numerator and the denominator. This allows
1923 for a fast calculation for large values which would otherwise cause an overflow
1924 in the intermediate values.
1926 @author Kohei Yoshida <kohei@openoffice.org>
1931 double ScInterpreter::GetHypGeomDist( double x
, double n
, double M
, double N
)
1933 const size_t nMaxArraySize
= 500000; // arbitrary max array size
1935 typedef ::std::vector
< double > HypContainer
;
1936 HypContainer cnNumer
, cnDenom
;
1938 size_t nEstContainerSize
= static_cast<size_t>( x
+ ::std::min( n
, M
) );
1939 size_t nMaxSize
= ::std::min( cnNumer
.max_size(), nMaxArraySize
);
1940 if ( nEstContainerSize
> nMaxSize
)
1945 cnNumer
.reserve( nEstContainerSize
+ 10 );
1946 cnDenom
.reserve( nEstContainerSize
+ 10 );
1948 // Trim coefficient C first
1949 double fCNumVarUpper
= N
- n
- M
+ x
- 1.0;
1950 double fCDenomVarLower
= 1.0;
1951 if ( N
- n
- M
+ x
>= M
- x
+ 1.0 )
1953 fCNumVarUpper
= M
- x
- 1.0;
1954 fCDenomVarLower
= N
- n
- 2.0*(M
- x
) + 1.0;
1957 #if OSL_DEBUG_LEVEL > 0
1958 double fCNumLower
= N
- n
- fCNumVarUpper
;
1960 double fCDenomUpper
= N
- n
- M
+ x
+ 1.0 - fCDenomVarLower
;
1962 double fDNumVarLower
= n
- M
;
1966 if ( N
- M
< n
+ 1.0 )
1970 if ( N
- n
< n
+ 1.0 )
1973 lcl_PutFactorialElements( cnNumer
, 0.0, fCNumVarUpper
, N
- n
);
1974 lcl_PutFactorialElements( cnDenom
, 0.0, N
- n
- 1.0, N
);
1979 OSL_ENSURE( fCNumLower
< n
+ 1.0, "ScHypGeomDist: wrong assertion" );
1980 lcl_PutFactorialElements( cnNumer
, N
- 2.0*n
, fCNumVarUpper
, N
- n
);
1981 lcl_PutFactorialElements( cnDenom
, 0.0, n
- 1.0, N
);
1984 OSL_ENSURE( fCDenomUpper
<= N
- M
, "ScHypGeomDist: wrong assertion" );
1986 if ( fCDenomUpper
< n
- x
+ 1.0 )
1988 lcl_PutFactorialElements( cnNumer
, 1.0, N
- M
- n
+ x
, N
- M
+ 1.0 );
1992 lcl_PutFactorialElements( cnNumer
, 1.0, N
- M
- fCDenomUpper
, N
- M
+ 1.0 );
1994 fCDenomUpper
= n
- x
;
1995 fCDenomVarLower
= N
- M
- 2.0*(n
- x
) + 1.0;
2005 lcl_PutFactorialElements( cnNumer
, 0.0, fCNumVarUpper
, N
- n
);
2006 lcl_PutFactorialElements( cnDenom
, 0.0, M
- 1.0, N
);
2010 lcl_PutFactorialElements( cnNumer
, M
- n
, fCNumVarUpper
, N
- n
);
2011 lcl_PutFactorialElements( cnDenom
, 0.0, n
- 1.0, N
);
2014 OSL_ENSURE( fCDenomUpper
<= n
, "ScHypGeomDist: wrong assertion" );
2016 if ( fCDenomUpper
< n
- x
+ 1.0 )
2018 lcl_PutFactorialElements( cnNumer
, N
- M
- n
+ 1.0, N
- M
- n
+ x
, N
- M
+ 1.0 );
2021 lcl_PutFactorialElements( cnNumer
, N
- M
- n
+ 1.0, N
- M
- fCDenomUpper
, N
- M
+ 1.0 );
2022 fCDenomUpper
= n
- x
;
2023 fCDenomVarLower
= N
- M
- 2.0*(n
- x
) + 1.0;
2027 OSL_ENSURE( fCDenomUpper
<= M
, "ScHypGeomDist: wrong assertion" );
2031 if ( N
- M
< M
+ 1.0 )
2035 if ( N
- n
< M
+ 1.0 )
2038 lcl_PutFactorialElements( cnNumer
, 0.0, fCNumVarUpper
, N
- n
);
2039 lcl_PutFactorialElements( cnDenom
, 0.0, N
- M
- 1.0, N
);
2043 lcl_PutFactorialElements( cnNumer
, N
- n
- M
, fCNumVarUpper
, N
- n
);
2044 lcl_PutFactorialElements( cnDenom
, 0.0, n
- 1.0, N
);
2047 if ( n
- x
+ 1.0 > fCDenomUpper
)
2049 lcl_PutFactorialElements( cnNumer
, 1.0, N
- M
- n
+ x
, N
- M
+ 1.0 );
2053 lcl_PutFactorialElements( cnNumer
, 1.0, N
- M
- fCDenomUpper
, N
- M
+ 1.0 );
2055 fCDenomVarLower
= N
- M
- 2.0*(n
- x
) + 1.0;
2056 fCDenomUpper
= n
- x
;
2063 OSL_ENSURE( M
>= n
- x
, "ScHypGeomDist: wrong assertion" );
2064 OSL_ENSURE( M
- x
<= N
- M
+ 1.0, "ScHypGeomDist: wrong assertion" );
2066 if ( N
- n
< N
- M
+ 1.0 )
2069 lcl_PutFactorialElements( cnNumer
, 0.0, fCNumVarUpper
, N
- n
);
2070 lcl_PutFactorialElements( cnDenom
, 0.0, M
- 1.0, N
);
2075 OSL_ENSURE( fCNumLower
<= N
- M
+ 1.0, "ScHypGeomDist: wrong assertion" );
2076 lcl_PutFactorialElements( cnNumer
, M
- n
, fCNumVarUpper
, N
- n
);
2077 lcl_PutFactorialElements( cnDenom
, 0.0, n
- 1.0, N
);
2080 if ( n
- x
+ 1.0 > fCDenomUpper
)
2082 lcl_PutFactorialElements( cnNumer
, N
- 2.0*M
+ 1.0, N
- M
- n
+ x
, N
- M
+ 1.0 );
2083 else if ( M
>= fCDenomUpper
)
2085 lcl_PutFactorialElements( cnNumer
, N
- 2.0*M
+ 1.0, N
- M
- fCDenomUpper
, N
- M
+ 1.0 );
2087 fCDenomUpper
= n
- x
;
2088 fCDenomVarLower
= N
- M
- 2.0*(n
- x
) + 1.0;
2092 OSL_ENSURE( M
<= fCDenomUpper
, "ScHypGeomDist: wrong assertion" );
2093 lcl_PutFactorialElements( cnDenom
, fCDenomVarLower
, N
- n
- 2.0*M
+ x
,
2094 N
- n
- M
+ x
+ 1.0 );
2096 fCDenomUpper
= n
- x
;
2097 fCDenomVarLower
= N
- M
- 2.0*(n
- x
) + 1.0;
2101 OSL_ENSURE( fCDenomUpper
<= n
, "ScHypGeomDist: wrong assertion" );
2103 fDNumVarLower
= 0.0;
2106 double nDNumVarUpper
= fCDenomUpper
< x
+ 1.0 ? n
- x
- 1.0 : n
- fCDenomUpper
- 1.0;
2107 double nDDenomVarLower
= fCDenomUpper
< x
+ 1.0 ? fCDenomVarLower
: N
- n
- M
+ 1.0;
2108 lcl_PutFactorialElements( cnNumer
, fDNumVarLower
, nDNumVarUpper
, n
);
2109 lcl_PutFactorialElements( cnDenom
, nDDenomVarLower
, N
- n
- M
+ x
, N
- n
- M
+ x
+ 1.0 );
2111 ::std::sort( cnNumer
.begin(), cnNumer
.end() );
2112 ::std::sort( cnDenom
.begin(), cnDenom
.end() );
2113 HypContainer::reverse_iterator it1
= cnNumer
.rbegin(), it1End
= cnNumer
.rend();
2114 HypContainer::reverse_iterator it2
= cnDenom
.rbegin(), it2End
= cnDenom
.rend();
2116 double fFactor
= 1.0;
2117 for ( ; it1
!= it1End
|| it2
!= it2End
; )
2119 double fEnum
= 1.0, fDenom
= 1.0;
2120 if ( it1
!= it1End
)
2122 if ( it2
!= it2End
)
2124 fFactor
*= fEnum
/ fDenom
;
2130 void ScInterpreter::ScGammaDist( int nMinParamCount
)
2132 sal_uInt8 nParamCount
= GetByte();
2133 if ( !MustHaveParamCount( nParamCount
, nMinParamCount
, 4 ) )
2136 if (nParamCount
== 4)
2137 bCumulative
= GetBool();
2140 double fBeta
= GetDouble(); // scale
2141 double fAlpha
= GetDouble(); // shape
2142 double fX
= GetDouble(); // x
2143 if (fAlpha
<= 0.0 || fBeta
<= 0.0)
2144 PushIllegalArgument();
2147 if (bCumulative
) // distribution
2148 PushDouble( GetGammaDist( fX
, fAlpha
, fBeta
));
2150 PushDouble( GetGammaDistPDF( fX
, fAlpha
, fBeta
));
2154 void ScInterpreter::ScNormInv()
2156 if ( MustHaveParamCount( GetByte(), 3 ) )
2158 double sigma
= GetDouble();
2159 double mue
= GetDouble();
2160 double x
= GetDouble();
2161 if (sigma
<= 0.0 || x
< 0.0 || x
> 1.0)
2162 PushIllegalArgument();
2163 else if (x
== 0.0 || x
== 1.0)
2166 PushDouble(gaussinv(x
)*sigma
+ mue
);
2170 void ScInterpreter::ScSNormInv()
2172 double x
= GetDouble();
2173 if (x
< 0.0 || x
> 1.0)
2174 PushIllegalArgument();
2175 else if (x
== 0.0 || x
== 1.0)
2178 PushDouble(gaussinv(x
));
2181 void ScInterpreter::ScLogNormInv()
2183 if ( MustHaveParamCount( GetByte(), 3 ) )
2185 double sigma
= GetDouble(); // Stdabw
2186 double mue
= GetDouble(); // Mittelwert
2187 double y
= GetDouble(); // y
2188 if (sigma
<= 0.0 || y
<= 0.0 || y
>= 1.0)
2189 PushIllegalArgument();
2191 PushDouble(exp(mue
+sigma
*gaussinv(y
)));
2195 class ScGammaDistFunction
: public ScDistFunc
2197 ScInterpreter
& rInt
;
2198 double fp
, fAlpha
, fBeta
;
2201 ScGammaDistFunction( ScInterpreter
& rI
, double fpVal
, double fAlphaVal
, double fBetaVal
) :
2202 rInt(rI
), fp(fpVal
), fAlpha(fAlphaVal
), fBeta(fBetaVal
) {}
2204 virtual ~ScGammaDistFunction() {}
2206 double GetValue( double x
) const SAL_OVERRIDE
{ return fp
- rInt
.GetGammaDist(x
, fAlpha
, fBeta
); }
2209 void ScInterpreter::ScGammaInv()
2211 if ( !MustHaveParamCount( GetByte(), 3 ) )
2213 double fBeta
= GetDouble();
2214 double fAlpha
= GetDouble();
2215 double fP
= GetDouble();
2216 if (fAlpha
<= 0.0 || fBeta
<= 0.0 || fP
< 0.0 || fP
>= 1.0 )
2218 PushIllegalArgument();
2226 ScGammaDistFunction
aFunc( *this, fP
, fAlpha
, fBeta
);
2227 double fStart
= fAlpha
* fBeta
;
2228 double fVal
= lcl_IterateInverse( aFunc
, fStart
*0.5, fStart
, bConvError
);
2230 SetError(errNoConvergence
);
2235 class ScBetaDistFunction
: public ScDistFunc
2237 ScInterpreter
& rInt
;
2238 double fp
, fAlpha
, fBeta
;
2241 ScBetaDistFunction( ScInterpreter
& rI
, double fpVal
, double fAlphaVal
, double fBetaVal
) :
2242 rInt(rI
), fp(fpVal
), fAlpha(fAlphaVal
), fBeta(fBetaVal
) {}
2244 virtual ~ScBetaDistFunction() {}
2246 double GetValue( double x
) const SAL_OVERRIDE
{ return fp
- rInt
.GetBetaDist(x
, fAlpha
, fBeta
); }
2249 void ScInterpreter::ScBetaInv()
2251 sal_uInt8 nParamCount
= GetByte();
2252 if ( !MustHaveParamCount( nParamCount
, 3, 5 ) )
2254 double fP
, fA
, fB
, fAlpha
, fBeta
;
2255 if (nParamCount
== 5)
2259 if (nParamCount
>= 4)
2263 fBeta
= GetDouble();
2264 fAlpha
= GetDouble();
2266 if (fP
< 0.0 || fP
>= 1.0 || fA
== fB
|| fAlpha
<= 0.0 || fBeta
<= 0.0)
2268 PushIllegalArgument();
2276 ScBetaDistFunction
aFunc( *this, fP
, fAlpha
, fBeta
);
2277 // 0..1 as range for iteration so it isn't extended beyond the valid range
2278 double fVal
= lcl_IterateInverse( aFunc
, 0.0, 1.0, bConvError
);
2280 PushError( errNoConvergence
);
2282 PushDouble(fA
+ fVal
*(fB
-fA
)); // scale to (A,B)
2286 // Achtung: T, F und Chi
2287 // sind monoton fallend,
2288 // deshalb 1-Dist als Funktion
2290 class ScTDistFunction
: public ScDistFunc
2292 ScInterpreter
& rInt
;
2297 ScTDistFunction( ScInterpreter
& rI
, double fpVal
, double fDFVal
, int nType
) :
2298 rInt( rI
), fp( fpVal
), fDF( fDFVal
), nT( nType
) {}
2300 virtual ~ScTDistFunction() {}
2302 double GetValue( double x
) const SAL_OVERRIDE
{ return fp
- rInt
.GetTDist( x
, fDF
, nT
); }
2305 void ScInterpreter::ScTInv( int nType
)
2307 if ( !MustHaveParamCount( GetByte(), 2 ) )
2309 double fDF
= ::rtl::math::approxFloor(GetDouble());
2310 double fP
= GetDouble();
2311 if (fDF
< 1.0 || fP
<= 0.0 || fP
> 1.0 )
2313 PushIllegalArgument();
2316 if ( nType
== 4 ) // left-tailed cumulative t-distribution
2319 PushDouble( -GetTInv( 1 - fP
, fDF
, nType
) );
2321 PushDouble( GetTInv( fP
, fDF
, nType
) );
2324 PushDouble( GetTInv( fP
, fDF
, nType
) );
2327 double ScInterpreter::GetTInv( double fAlpha
, double fSize
, int nType
)
2330 ScTDistFunction
aFunc( *this, fAlpha
, fSize
, nType
);
2331 double fVal
= lcl_IterateInverse( aFunc
, fSize
* 0.5, fSize
, bConvError
);
2333 SetError(errNoConvergence
);
2337 class ScFDistFunction
: public ScDistFunc
2339 ScInterpreter
& rInt
;
2340 double fp
, fF1
, fF2
;
2343 ScFDistFunction( ScInterpreter
& rI
, double fpVal
, double fF1Val
, double fF2Val
) :
2344 rInt(rI
), fp(fpVal
), fF1(fF1Val
), fF2(fF2Val
) {}
2346 virtual ~ScFDistFunction() {}
2348 double GetValue( double x
) const SAL_OVERRIDE
{ return fp
- rInt
.GetFDist(x
, fF1
, fF2
); }
2351 void ScInterpreter::ScFInv()
2353 if ( !MustHaveParamCount( GetByte(), 3 ) )
2355 double fF2
= ::rtl::math::approxFloor(GetDouble());
2356 double fF1
= ::rtl::math::approxFloor(GetDouble());
2357 double fP
= GetDouble();
2358 if (fP
<= 0.0 || fF1
< 1.0 || fF2
< 1.0 || fF1
>= 1.0E10
|| fF2
>= 1.0E10
|| fP
> 1.0)
2360 PushIllegalArgument();
2365 ScFDistFunction
aFunc( *this, fP
, fF1
, fF2
);
2366 double fVal
= lcl_IterateInverse( aFunc
, fF1
*0.5, fF1
, bConvError
);
2368 SetError(errNoConvergence
);
2372 void ScInterpreter::ScFInv_LT()
2374 if ( !MustHaveParamCount( GetByte(), 3 ) )
2376 double fF2
= ::rtl::math::approxFloor(GetDouble());
2377 double fF1
= ::rtl::math::approxFloor(GetDouble());
2378 double fP
= GetDouble();
2379 if (fP
<= 0.0 || fF1
< 1.0 || fF2
< 1.0 || fF1
>= 1.0E10
|| fF2
>= 1.0E10
|| fP
> 1.0)
2381 PushIllegalArgument();
2386 ScFDistFunction
aFunc( *this, ( 1.0 - fP
), fF1
, fF2
);
2387 double fVal
= lcl_IterateInverse( aFunc
, fF1
*0.5, fF1
, bConvError
);
2389 SetError(errNoConvergence
);
2393 class ScChiDistFunction
: public ScDistFunc
2395 ScInterpreter
& rInt
;
2399 ScChiDistFunction( ScInterpreter
& rI
, double fpVal
, double fDFVal
) :
2400 rInt(rI
), fp(fpVal
), fDF(fDFVal
) {}
2402 virtual ~ScChiDistFunction() {}
2404 double GetValue( double x
) const SAL_OVERRIDE
{ return fp
- rInt
.GetChiDist(x
, fDF
); }
2407 void ScInterpreter::ScChiInv()
2409 if ( !MustHaveParamCount( GetByte(), 2 ) )
2411 double fDF
= ::rtl::math::approxFloor(GetDouble());
2412 double fP
= GetDouble();
2413 if (fDF
< 1.0 || fP
<= 0.0 || fP
> 1.0 )
2415 PushIllegalArgument();
2420 ScChiDistFunction
aFunc( *this, fP
, fDF
);
2421 double fVal
= lcl_IterateInverse( aFunc
, fDF
*0.5, fDF
, bConvError
);
2423 SetError(errNoConvergence
);
2427 /***********************************************/
2428 class ScChiSqDistFunction
: public ScDistFunc
2430 ScInterpreter
& rInt
;
2434 ScChiSqDistFunction( ScInterpreter
& rI
, double fpVal
, double fDFVal
) :
2435 rInt(rI
), fp(fpVal
), fDF(fDFVal
) {}
2437 virtual ~ScChiSqDistFunction() {}
2439 double GetValue( double x
) const SAL_OVERRIDE
{ return fp
- rInt
.GetChiSqDistCDF(x
, fDF
); }
2442 void ScInterpreter::ScChiSqInv()
2444 if ( !MustHaveParamCount( GetByte(), 2 ) )
2446 double fDF
= ::rtl::math::approxFloor(GetDouble());
2447 double fP
= GetDouble();
2448 if (fDF
< 1.0 || fP
< 0.0 || fP
>= 1.0 )
2450 PushIllegalArgument();
2455 ScChiSqDistFunction
aFunc( *this, fP
, fDF
);
2456 double fVal
= lcl_IterateInverse( aFunc
, fDF
*0.5, fDF
, bConvError
);
2458 SetError(errNoConvergence
);
2462 void ScInterpreter::ScConfidence()
2464 if ( MustHaveParamCount( GetByte(), 3 ) )
2466 double n
= ::rtl::math::approxFloor(GetDouble());
2467 double sigma
= GetDouble();
2468 double alpha
= GetDouble();
2469 if (sigma
<= 0.0 || alpha
<= 0.0 || alpha
>= 1.0 || n
< 1.0)
2470 PushIllegalArgument();
2472 PushDouble( gaussinv(1.0-alpha
/2.0) * sigma
/sqrt(n
) );
2476 void ScInterpreter::ScConfidenceT()
2478 if ( MustHaveParamCount( GetByte(), 3 ) )
2480 double n
= ::rtl::math::approxFloor(GetDouble());
2481 double sigma
= GetDouble();
2482 double alpha
= GetDouble();
2483 if (sigma
<= 0.0 || alpha
<= 0.0 || alpha
>= 1.0 || n
< 1.0)
2484 PushIllegalArgument();
2486 PushDouble( sigma
* GetTInv( alpha
, n
- 1, 2 ) / sqrt( n
) );
2490 void ScInterpreter::ScZTest()
2492 sal_uInt8 nParamCount
= GetByte();
2493 if ( !MustHaveParamCount( nParamCount
, 2, 3 ) )
2495 double sigma
= 0.0, x
;
2496 if (nParamCount
== 3)
2498 sigma
= GetDouble();
2501 PushIllegalArgument();
2508 double fSumSqr
= 0.0;
2510 double rValCount
= 0.0;
2511 switch (GetStackType())
2513 case formula::svDouble
:
2517 fSumSqr
+= fVal
*fVal
;
2524 PopSingleRef( aAdr
);
2525 ScRefCellValue aCell
;
2526 aCell
.assign(*pDok
, aAdr
);
2527 if (aCell
.hasNumeric())
2529 fVal
= GetCellValue(aAdr
, aCell
);
2531 fSumSqr
+= fVal
*fVal
;
2537 case formula::svDoubleRef
:
2540 size_t nRefInList
= 0;
2541 while (nParam
-- > 0)
2544 sal_uInt16 nErr
= 0;
2545 PopDoubleRef( aRange
, nParam
, nRefInList
);
2546 ScValueIterator
aValIter( pDok
, aRange
, mnSubTotalFlags
);
2547 if (aValIter
.GetFirst(fVal
, nErr
))
2550 fSumSqr
+= fVal
*fVal
;
2552 while ((nErr
== 0) && aValIter
.GetNext(fVal
, nErr
))
2555 fSumSqr
+= fVal
*fVal
;
2564 case svExternalSingleRef
:
2565 case svExternalDoubleRef
:
2567 ScMatrixRef pMat
= GetMatrix();
2570 SCSIZE nCount
= pMat
->GetElementCount();
2571 if (pMat
->IsNumeric())
2573 for ( SCSIZE i
= 0; i
< nCount
; i
++ )
2575 fVal
= pMat
->GetDouble(i
);
2577 fSumSqr
+= fVal
* fVal
;
2583 for (SCSIZE i
= 0; i
< nCount
; i
++)
2584 if (!pMat
->IsString(i
))
2586 fVal
= pMat
->GetDouble(i
);
2588 fSumSqr
+= fVal
* fVal
;
2595 default : SetError(errIllegalParameter
); break;
2597 if (rValCount
<= 1.0)
2598 PushError( errDivisionByZero
);
2601 double mue
= fSum
/rValCount
;
2603 if (nParamCount
!= 3)
2605 sigma
= (fSumSqr
- fSum
*fSum
/rValCount
)/(rValCount
-1.0);
2606 PushDouble(0.5 - gauss((mue
-x
)/sqrt(sigma
/rValCount
)));
2609 PushDouble(0.5 - gauss((mue
-x
)*sqrt(rValCount
)/sigma
));
2613 bool ScInterpreter::CalculateTest(bool _bTemplin
2614 ,const SCSIZE nC1
, const SCSIZE nC2
,const SCSIZE nR1
,const SCSIZE nR2
2615 ,const ScMatrixRef
& pMat1
,const ScMatrixRef
& pMat2
2616 ,double& fT
,double& fF
)
2618 double fCount1
= 0.0;
2619 double fCount2
= 0.0;
2621 double fSumSqr1
= 0.0;
2623 double fSumSqr2
= 0.0;
2626 for (i
= 0; i
< nC1
; i
++)
2627 for (j
= 0; j
< nR1
; j
++)
2629 if (!pMat1
->IsString(i
,j
))
2631 fVal
= pMat1
->GetDouble(i
,j
);
2633 fSumSqr1
+= fVal
* fVal
;
2637 for (i
= 0; i
< nC2
; i
++)
2638 for (j
= 0; j
< nR2
; j
++)
2640 if (!pMat2
->IsString(i
,j
))
2642 fVal
= pMat2
->GetDouble(i
,j
);
2644 fSumSqr2
+= fVal
* fVal
;
2648 if (fCount1
< 2.0 || fCount2
< 2.0)
2652 } // if (fCount1 < 2.0 || fCount2 < 2.0)
2655 double fS1
= (fSumSqr1
-fSum1
*fSum1
/fCount1
)/(fCount1
-1.0)/fCount1
;
2656 double fS2
= (fSumSqr2
-fSum2
*fSum2
/fCount2
)/(fCount2
-1.0)/fCount2
;
2657 if (fS1
+ fS2
== 0.0)
2662 fT
= fabs(fSum1
/fCount1
- fSum2
/fCount2
)/sqrt(fS1
+fS2
);
2663 double c
= fS1
/(fS1
+fS2
);
2664 // GetTDist wird mit GetBetaDist berechnet und kommt auch mit nicht ganzzahligen
2665 // Freiheitsgraden klar. Dann stimmt das Ergebnis auch mit Excel ueberein (#52406#):
2666 fF
= 1.0/(c
*c
/(fCount1
-1.0)+(1.0-c
)*(1.0-c
)/(fCount2
-1.0));
2670 // laut Bronstein-Semendjajew
2671 double fS1
= (fSumSqr1
- fSum1
*fSum1
/fCount1
) / (fCount1
- 1.0); // Varianz
2672 double fS2
= (fSumSqr2
- fSum2
*fSum2
/fCount2
) / (fCount2
- 1.0);
2673 fT
= fabs( fSum1
/fCount1
- fSum2
/fCount2
) /
2674 sqrt( (fCount1
-1.0)*fS1
+ (fCount2
-1.0)*fS2
) *
2675 sqrt( fCount1
*fCount2
*(fCount1
+fCount2
-2)/(fCount1
+fCount2
) );
2676 fF
= fCount1
+ fCount2
- 2;
2680 void ScInterpreter::ScTTest()
2682 if ( !MustHaveParamCount( GetByte(), 4 ) )
2684 double fTyp
= ::rtl::math::approxFloor(GetDouble());
2685 double fTails
= ::rtl::math::approxFloor(GetDouble());
2686 if (fTails
!= 1.0 && fTails
!= 2.0)
2688 PushIllegalArgument();
2692 ScMatrixRef pMat2
= GetMatrix();
2693 ScMatrixRef pMat1
= GetMatrix();
2694 if (!pMat1
|| !pMat2
)
2696 PushIllegalParameter();
2703 pMat1
->GetDimensions(nC1
, nR1
);
2704 pMat2
->GetDimensions(nC2
, nR2
);
2707 if (nC1
!= nC2
|| nR1
!= nR2
)
2709 PushIllegalArgument();
2712 double fCount
= 0.0;
2715 double fSumSqrD
= 0.0;
2716 double fVal1
, fVal2
;
2717 for (i
= 0; i
< nC1
; i
++)
2718 for (j
= 0; j
< nR1
; j
++)
2720 if (!pMat1
->IsString(i
,j
) && !pMat2
->IsString(i
,j
))
2722 fVal1
= pMat1
->GetDouble(i
,j
);
2723 fVal2
= pMat2
->GetDouble(i
,j
);
2726 fSumSqrD
+= (fVal1
- fVal2
)*(fVal1
- fVal2
);
2735 fT
= sqrt(fCount
-1.0) * fabs(fSum1
- fSum2
) /
2736 sqrt(fCount
* fSumSqrD
- (fSum1
-fSum2
)*(fSum1
-fSum2
));
2739 else if (fTyp
== 2.0)
2741 CalculateTest(false,nC1
, nC2
,nR1
, nR2
,pMat1
,pMat2
,fT
,fF
);
2743 else if (fTyp
== 3.0)
2745 CalculateTest(true,nC1
, nC2
,nR1
, nR2
,pMat1
,pMat2
,fT
,fF
);
2750 PushIllegalArgument();
2753 PushDouble( GetTDist( fT
, fF
, ( int )fTails
) );
2756 void ScInterpreter::ScFTest()
2758 if ( !MustHaveParamCount( GetByte(), 2 ) )
2760 ScMatrixRef pMat2
= GetMatrix();
2761 ScMatrixRef pMat1
= GetMatrix();
2762 if (!pMat1
|| !pMat2
)
2764 PushIllegalParameter();
2770 pMat1
->GetDimensions(nC1
, nR1
);
2771 pMat2
->GetDimensions(nC2
, nR2
);
2772 double fCount1
= 0.0;
2773 double fCount2
= 0.0;
2775 double fSumSqr1
= 0.0;
2777 double fSumSqr2
= 0.0;
2779 for (i
= 0; i
< nC1
; i
++)
2780 for (j
= 0; j
< nR1
; j
++)
2782 if (!pMat1
->IsString(i
,j
))
2784 fVal
= pMat1
->GetDouble(i
,j
);
2786 fSumSqr1
+= fVal
* fVal
;
2790 for (i
= 0; i
< nC2
; i
++)
2791 for (j
= 0; j
< nR2
; j
++)
2793 if (!pMat2
->IsString(i
,j
))
2795 fVal
= pMat2
->GetDouble(i
,j
);
2797 fSumSqr2
+= fVal
* fVal
;
2801 if (fCount1
< 2.0 || fCount2
< 2.0)
2806 double fS1
= (fSumSqr1
-fSum1
*fSum1
/fCount1
)/(fCount1
-1.0);
2807 double fS2
= (fSumSqr2
-fSum2
*fSum2
/fCount2
)/(fCount2
-1.0);
2808 if (fS1
== 0.0 || fS2
== 0.0)
2813 double fF
, fF1
, fF2
;
2826 PushDouble(2.0*GetFDist(fF
, fF1
, fF2
));
2829 void ScInterpreter::ScChiTest()
2831 if ( !MustHaveParamCount( GetByte(), 2 ) )
2833 ScMatrixRef pMat2
= GetMatrix();
2834 ScMatrixRef pMat1
= GetMatrix();
2835 if (!pMat1
|| !pMat2
)
2837 PushIllegalParameter();
2842 pMat1
->GetDimensions(nC1
, nR1
);
2843 pMat2
->GetDimensions(nC2
, nR2
);
2844 if (nR1
!= nR2
|| nC1
!= nC2
)
2846 PushIllegalArgument();
2850 for (SCSIZE i
= 0; i
< nC1
; i
++)
2852 for (SCSIZE j
= 0; j
< nR1
; j
++)
2854 if (!pMat1
->IsString(i
,j
) && !pMat2
->IsString(i
,j
))
2856 double fValX
= pMat1
->GetDouble(i
,j
);
2857 double fValE
= pMat2
->GetDouble(i
,j
);
2858 fChi
+= (fValX
- fValE
) * (fValX
- fValE
) / fValE
;
2862 PushIllegalArgument();
2868 if (nC1
== 1 || nR1
== 1)
2870 fDF
= (double)(nC1
*nR1
- 1);
2878 fDF
= (double)(nC1
-1)*(double)(nR1
-1);
2879 PushDouble(GetChiDist(fChi
, fDF
));
2882 void ScInterpreter::ScKurt()
2884 double fSum
,fCount
,vSum
;
2885 std::vector
<double> values
;
2886 if ( !CalculateSkew(fSum
,fCount
,vSum
,values
) )
2891 PushError( errDivisionByZero
);
2895 double fMean
= fSum
/ fCount
;
2897 for (size_t i
= 0; i
< values
.size(); i
++)
2898 vSum
+= (values
[i
] - fMean
) * (values
[i
] - fMean
);
2900 double fStdDev
= sqrt(vSum
/ (fCount
- 1.0));
2901 double xpower4
= 0.0;
2905 PushError( errDivisionByZero
);
2909 for (size_t i
= 0; i
< values
.size(); i
++)
2911 double dx
= (values
[i
] - fMean
) / fStdDev
;
2912 xpower4
= xpower4
+ (dx
* dx
* dx
* dx
);
2915 double k_d
= (fCount
- 2.0) * (fCount
- 3.0);
2916 double k_l
= fCount
* (fCount
+ 1.0) / ((fCount
- 1.0) * k_d
);
2917 double k_t
= 3.0 * (fCount
- 1.0) * (fCount
- 1.0) / k_d
;
2919 PushDouble(xpower4
* k_l
- k_t
);
2922 void ScInterpreter::ScHarMean()
2924 short nParamCount
= GetByte();
2926 double nValCount
= 0.0;
2929 size_t nRefInList
= 0;
2930 while ((nGlobalError
== 0) && (nParamCount
-- > 0))
2932 switch (GetStackType())
2934 case formula::svDouble
:
2936 double x
= GetDouble();
2943 SetError( errIllegalArgument
);
2948 PopSingleRef( aAdr
);
2949 ScRefCellValue aCell
;
2950 aCell
.assign(*pDok
, aAdr
);
2951 if (aCell
.hasNumeric())
2953 double x
= GetCellValue(aAdr
, aCell
);
2960 SetError( errIllegalArgument
);
2964 case formula::svDoubleRef
:
2967 sal_uInt16 nErr
= 0;
2968 PopDoubleRef( aRange
, nParamCount
, nRefInList
);
2970 ScValueIterator
aValIter( pDok
, aRange
, mnSubTotalFlags
);
2971 if (aValIter
.GetFirst(nCellVal
, nErr
))
2975 nVal
+= 1.0/nCellVal
;
2979 SetError( errIllegalArgument
);
2981 while ((nErr
== 0) && aValIter
.GetNext(nCellVal
, nErr
))
2985 nVal
+= 1.0/nCellVal
;
2989 SetError( errIllegalArgument
);
2996 case svExternalSingleRef
:
2997 case svExternalDoubleRef
:
2999 ScMatrixRef pMat
= GetMatrix();
3002 SCSIZE nCount
= pMat
->GetElementCount();
3003 if (pMat
->IsNumeric())
3005 for (SCSIZE nElem
= 0; nElem
< nCount
; nElem
++)
3007 double x
= pMat
->GetDouble(nElem
);
3014 SetError( errIllegalArgument
);
3019 for (SCSIZE nElem
= 0; nElem
< nCount
; nElem
++)
3020 if (!pMat
->IsString(nElem
))
3022 double x
= pMat
->GetDouble(nElem
);
3029 SetError( errIllegalArgument
);
3035 default : SetError(errIllegalParameter
); break;
3038 if (nGlobalError
== 0)
3039 PushDouble((double)nValCount
/nVal
);
3041 PushError( nGlobalError
);
3044 void ScInterpreter::ScGeoMean()
3046 short nParamCount
= GetByte();
3048 double nValCount
= 0.0;
3052 size_t nRefInList
= 0;
3053 while ((nGlobalError
== 0) && (nParamCount
-- > 0))
3055 switch (GetStackType())
3057 case formula::svDouble
:
3059 double x
= GetDouble();
3066 SetError( errIllegalArgument
);
3071 PopSingleRef( aAdr
);
3072 ScRefCellValue aCell
;
3073 aCell
.assign(*pDok
, aAdr
);
3074 if (aCell
.hasNumeric())
3076 double x
= GetCellValue(aAdr
, aCell
);
3083 SetError( errIllegalArgument
);
3087 case formula::svDoubleRef
:
3090 sal_uInt16 nErr
= 0;
3091 PopDoubleRef( aRange
, nParamCount
, nRefInList
);
3093 ScValueIterator
aValIter( pDok
, aRange
, mnSubTotalFlags
);
3094 if (aValIter
.GetFirst(nCellVal
, nErr
))
3098 nVal
+= log(nCellVal
);
3102 SetError( errIllegalArgument
);
3104 while ((nErr
== 0) && aValIter
.GetNext(nCellVal
, nErr
))
3108 nVal
+= log(nCellVal
);
3112 SetError( errIllegalArgument
);
3119 case svExternalSingleRef
:
3120 case svExternalDoubleRef
:
3122 ScMatrixRef pMat
= GetMatrix();
3125 SCSIZE nCount
= pMat
->GetElementCount();
3126 if (pMat
->IsNumeric())
3128 for (SCSIZE ui
= 0; ui
< nCount
; ui
++)
3130 double x
= pMat
->GetDouble(ui
);
3137 SetError( errIllegalArgument
);
3142 for (SCSIZE ui
= 0; ui
< nCount
; ui
++)
3143 if (!pMat
->IsString(ui
))
3145 double x
= pMat
->GetDouble(ui
);
3152 SetError( errIllegalArgument
);
3158 default : SetError(errIllegalParameter
); break;
3161 if (nGlobalError
== 0)
3162 PushDouble(exp(nVal
/ nValCount
));
3164 PushError( nGlobalError
);
3167 void ScInterpreter::ScStandard()
3169 if ( MustHaveParamCount( GetByte(), 3 ) )
3171 double sigma
= GetDouble();
3172 double mue
= GetDouble();
3173 double x
= GetDouble();
3175 PushError( errIllegalArgument
);
3176 else if (sigma
== 0.0)
3177 PushError( errDivisionByZero
);
3179 PushDouble((x
-mue
)/sigma
);
3182 bool ScInterpreter::CalculateSkew(double& fSum
,double& fCount
,double& vSum
,std::vector
<double>& values
)
3184 short nParamCount
= GetByte();
3185 if ( !MustHaveParamCountMin( nParamCount
, 1 ) )
3194 size_t nRefInList
= 0;
3195 while (nParamCount
-- > 0)
3197 switch (GetStackType())
3199 case formula::svDouble
:
3203 values
.push_back(fVal
);
3209 PopSingleRef( aAdr
);
3210 ScRefCellValue aCell
;
3211 aCell
.assign(*pDok
, aAdr
);
3212 if (aCell
.hasNumeric())
3214 fVal
= GetCellValue(aAdr
, aCell
);
3216 values
.push_back(fVal
);
3221 case formula::svDoubleRef
:
3224 PopDoubleRef( aRange
, nParamCount
, nRefInList
);
3225 sal_uInt16 nErr
= 0;
3226 ScValueIterator
aValIter( pDok
, aRange
, mnSubTotalFlags
);
3227 if (aValIter
.GetFirst(fVal
, nErr
))
3230 values
.push_back(fVal
);
3233 while ((nErr
== 0) && aValIter
.GetNext(fVal
, nErr
))
3236 values
.push_back(fVal
);
3244 case svExternalSingleRef
:
3245 case svExternalDoubleRef
:
3247 ScMatrixRef pMat
= GetMatrix();
3250 SCSIZE nCount
= pMat
->GetElementCount();
3251 if (pMat
->IsNumeric())
3253 for (SCSIZE nElem
= 0; nElem
< nCount
; nElem
++)
3255 fVal
= pMat
->GetDouble(nElem
);
3257 values
.push_back(fVal
);
3263 for (SCSIZE nElem
= 0; nElem
< nCount
; nElem
++)
3264 if (!pMat
->IsString(nElem
))
3266 fVal
= pMat
->GetDouble(nElem
);
3268 values
.push_back(fVal
);
3276 SetError(errIllegalParameter
);
3283 PushError( nGlobalError
);
3285 } // if (nGlobalError)
3289 void ScInterpreter::CalculateSkewOrSkewp( bool bSkewp
)
3291 double fSum
, fCount
, vSum
;
3292 std::vector
<double> values
;
3293 if (!CalculateSkew( fSum
, fCount
, vSum
, values
))
3296 double fMean
= fSum
/ fCount
;
3298 for (size_t i
= 0; i
< values
.size(); ++i
)
3299 vSum
+= (values
[i
] - fMean
) * (values
[i
] - fMean
);
3301 double fStdDev
= sqrt( vSum
/ (bSkewp
? fCount
: (fCount
- 1.0)));
3306 PushIllegalArgument();
3310 for (size_t i
= 0; i
< values
.size(); ++i
)
3312 double dx
= (values
[i
] - fMean
) / fStdDev
;
3313 xcube
= xcube
+ (dx
* dx
* dx
);
3317 PushDouble( xcube
/ fCount
);
3319 PushDouble( ((xcube
* fCount
) / (fCount
- 1.0)) / (fCount
- 2.0) );
3322 void ScInterpreter::ScSkew()
3324 CalculateSkewOrSkewp( false );
3327 void ScInterpreter::ScSkewp()
3329 CalculateSkewOrSkewp( true );
3332 double ScInterpreter::GetMedian( vector
<double> & rArray
)
3334 size_t nSize
= rArray
.size();
3335 if (rArray
.empty() || nSize
== 0 || nGlobalError
)
3337 SetError( errNoValue
);
3342 size_t nMid
= nSize
/ 2;
3343 vector
<double>::iterator iMid
= rArray
.begin() + nMid
;
3344 ::std::nth_element( rArray
.begin(), iMid
, rArray
.end());
3346 return *iMid
; // Lower and upper median are equal.
3351 iMid
= rArray
.begin() + nMid
- 1;
3352 ::std::nth_element( rArray
.begin(), iMid
, rArray
.end());
3353 return (fUp
+ *iMid
) / 2;
3357 void ScInterpreter::ScMedian()
3359 sal_uInt8 nParamCount
= GetByte();
3360 if ( !MustHaveParamCountMin( nParamCount
, 1 ) )
3362 vector
<double> aArray
;
3363 GetNumberSequenceArray( nParamCount
, aArray
, false );
3364 PushDouble( GetMedian( aArray
));
3367 double ScInterpreter::GetPercentile( vector
<double> & rArray
, double fPercentile
)
3369 size_t nSize
= rArray
.size();
3370 if (rArray
.empty() || nSize
== 0 || nGlobalError
)
3372 SetError( errNoValue
);
3380 size_t nIndex
= (size_t)::rtl::math::approxFloor( fPercentile
* (nSize
-1));
3381 double fDiff
= fPercentile
* (nSize
-1) - ::rtl::math::approxFloor( fPercentile
* (nSize
-1));
3382 OSL_ENSURE(nIndex
< nSize
, "GetPercentile: wrong index(1)");
3383 vector
<double>::iterator iter
= rArray
.begin() + nIndex
;
3384 ::std::nth_element( rArray
.begin(), iter
, rArray
.end());
3389 OSL_ENSURE(nIndex
< nSize
-1, "GetPercentile: wrong index(2)");
3390 double fVal
= *iter
;
3391 iter
= rArray
.begin() + nIndex
+1;
3392 ::std::nth_element( rArray
.begin(), iter
, rArray
.end());
3393 return fVal
+ fDiff
* (*iter
- fVal
);
3398 double ScInterpreter::GetPercentileExclusive( vector
<double> & rArray
, double fPercentile
)
3400 size_t nSize1
= rArray
.size() + 1;
3401 if ( rArray
.empty() || nSize1
== 1 || nGlobalError
)
3403 SetError( errNoValue
);
3406 if ( fPercentile
* nSize1
< 1.0 || fPercentile
* nSize1
> (double) ( nSize1
- 1 ) )
3408 SetError( errIllegalParameter
);
3412 size_t nIndex
= (size_t)::rtl::math::approxFloor( fPercentile
* nSize1
- 1 );
3413 double fDiff
= fPercentile
* nSize1
- 1 - ::rtl::math::approxFloor( fPercentile
* nSize1
- 1 );
3414 OSL_ENSURE(nIndex
< ( nSize1
- 1 ), "GetPercentile: wrong index(1)");
3415 vector
<double>::iterator iter
= rArray
.begin() + nIndex
;
3416 ::std::nth_element( rArray
.begin(), iter
, rArray
.end());
3421 OSL_ENSURE(nIndex
< nSize1
, "GetPercentile: wrong index(2)");
3422 double fVal
= *iter
;
3423 iter
= rArray
.begin() + nIndex
+ 1;
3424 ::std::nth_element( rArray
.begin(), iter
, rArray
.end());
3425 return fVal
+ fDiff
* (*iter
- fVal
);
3429 void ScInterpreter::ScPercentile( bool bInclusive
)
3431 if ( !MustHaveParamCount( GetByte(), 2 ) )
3433 double alpha
= GetDouble();
3434 if ( bInclusive
? ( alpha
< 0.0 || alpha
> 1.0 ) : ( alpha
<= 0.0 || alpha
>= 1.0 ) )
3436 PushIllegalArgument();
3439 vector
<double> aArray
;
3440 GetNumberSequenceArray( 1, aArray
, false );
3442 PushDouble( GetPercentile( aArray
, alpha
));
3444 PushDouble( GetPercentileExclusive( aArray
, alpha
));
3447 void ScInterpreter::ScQuartile( bool bInclusive
)
3449 if ( !MustHaveParamCount( GetByte(), 2 ) )
3451 double fFlag
= ::rtl::math::approxFloor(GetDouble());
3452 if ( bInclusive
? ( fFlag
< 0.0 || fFlag
> 4.0 ) : ( fFlag
<= 0.0 || fFlag
>= 4.0 ) )
3454 PushIllegalArgument();
3457 vector
<double> aArray
;
3458 GetNumberSequenceArray( 1, aArray
, false );
3460 PushDouble( fFlag
== 2.0 ? GetMedian( aArray
) : GetPercentile( aArray
, 0.25 * fFlag
) );
3462 PushDouble( fFlag
== 2.0 ? GetMedian( aArray
) : GetPercentileExclusive( aArray
, 0.25 * fFlag
) );
3465 void ScInterpreter::ScModalValue()
3467 sal_uInt8 nParamCount
= GetByte();
3468 if ( !MustHaveParamCountMin( nParamCount
, 1 ) )
3470 vector
<double> aSortArray
;
3471 GetSortArray( nParamCount
, aSortArray
, NULL
, false, false );
3472 SCSIZE nSize
= aSortArray
.size();
3473 if (aSortArray
.empty() || nSize
== 0 || nGlobalError
)
3477 SCSIZE nMaxIndex
= 0, nMax
= 1, nCount
= 1;
3478 double nOldVal
= aSortArray
[0];
3481 for ( i
= 1; i
< nSize
; i
++)
3483 if (aSortArray
[i
] == nOldVal
)
3487 nOldVal
= aSortArray
[i
];
3501 if (nMax
== 1 && nCount
== 1)
3504 PushDouble(nOldVal
);
3506 PushDouble(aSortArray
[nMaxIndex
]);
3510 void ScInterpreter::CalculateSmallLarge(bool bSmall
)
3512 if ( !MustHaveParamCount( GetByte(), 2 ) )
3514 double f
= ::rtl::math::approxFloor(GetDouble());
3517 PushIllegalArgument();
3520 SCSIZE k
= static_cast<SCSIZE
>(f
);
3521 vector
<double> aSortArray
;
3522 /* TODO: using nth_element() is best for one single value, but LARGE/SMALL
3523 * actually are defined to return an array of values if an array of
3524 * positions was passed, in which case, depending on the number of values,
3525 * we may or will need a real sorted array again, see #i32345. */
3526 GetNumberSequenceArray(1, aSortArray
, false );
3527 SCSIZE nSize
= aSortArray
.size();
3528 if (aSortArray
.empty() || nSize
== 0 || nGlobalError
|| nSize
< k
)
3532 // TODO: the sorted case for array: PushDouble( aSortArray[ bSmall ? k-1 : nSize-k ] );
3533 vector
<double>::iterator iPos
= aSortArray
.begin() + (bSmall
? k
-1 : nSize
-k
);
3534 ::std::nth_element( aSortArray
.begin(), iPos
, aSortArray
.end());
3539 void ScInterpreter::ScLarge()
3541 CalculateSmallLarge(false);
3544 void ScInterpreter::ScSmall()
3546 CalculateSmallLarge(true);
3549 void ScInterpreter::ScPercentrank( bool bInclusive
)
3551 sal_uInt8 nParamCount
= GetByte();
3552 if ( !MustHaveParamCount( nParamCount
, 2, 3 ) )
3554 double fSignificance
= ( nParamCount
== 3 ? ::rtl::math::approxFloor( GetDouble() ) : 3.0 );
3555 double fNum
= GetDouble();
3556 vector
<double> aSortArray
;
3557 GetSortArray( 1, aSortArray
, NULL
, false, false );
3558 SCSIZE nSize
= aSortArray
.size();
3559 if ( aSortArray
.empty() || nSize
== 0 || nGlobalError
)
3563 if ( fNum
< aSortArray
[ 0 ] || fNum
> aSortArray
[ nSize
- 1 ] )
3569 fRes
= 1.0; // fNum == aSortArray[ 0 ], see test above
3571 fRes
= GetPercentrank( aSortArray
, fNum
, bInclusive
);
3574 double fExp
= ::rtl::math::approxFloor( log( fRes
) );
3575 fRes
= ::rtl::math::round( fRes
* pow( 10, -fExp
+ fSignificance
- 1 ) ) / pow( 10, -fExp
+ fSignificance
- 1 );
3582 double ScInterpreter::GetPercentrank( ::std::vector
<double> & rArray
, double fVal
, bool bInclusive
)
3584 SCSIZE nSize
= rArray
.size();
3586 if ( fVal
== rArray
[ 0 ] )
3591 fRes
= 1.0 / ( double )( nSize
+ 1 );
3595 SCSIZE nOldCount
= 0;
3596 double fOldVal
= rArray
[ 0 ];
3598 for ( i
= 1; i
< nSize
&& rArray
[ i
] < fVal
; i
++ )
3600 if ( rArray
[ i
] != fOldVal
)
3603 fOldVal
= rArray
[ i
];
3606 if ( rArray
[ i
] != fOldVal
)
3608 if ( fVal
== rArray
[ i
] )
3611 fRes
= div( nOldCount
, nSize
- 1 );
3613 fRes
= ( double )( i
+ 1 ) / ( double )( nSize
+ 1 );
3617 // nOldCount is the count of smaller entries
3618 // fVal is between rArray[ nOldCount - 1 ] and rArray[ nOldCount ]
3619 // use linear interpolation to find a position between the entries
3620 if ( nOldCount
== 0 )
3622 OSL_FAIL( "should not happen" );
3627 double fFract
= ( fVal
- rArray
[ nOldCount
- 1 ] ) /
3628 ( rArray
[ nOldCount
] - rArray
[ nOldCount
- 1 ] );
3630 fRes
= div( ( double )( nOldCount
- 1 ) + fFract
, nSize
- 1 );
3632 fRes
= ( ( double )nOldCount
+ fFract
) / ( double )( nSize
+ 1 );
3639 void ScInterpreter::ScTrimMean()
3641 if ( !MustHaveParamCount( GetByte(), 2 ) )
3643 double alpha
= GetDouble();
3644 if (alpha
< 0.0 || alpha
>= 1.0)
3646 PushIllegalArgument();
3649 vector
<double> aSortArray
;
3650 GetSortArray( 1, aSortArray
, NULL
, false, false );
3651 SCSIZE nSize
= aSortArray
.size();
3652 if (aSortArray
.empty() || nSize
== 0 || nGlobalError
)
3656 sal_uLong nIndex
= (sal_uLong
) ::rtl::math::approxFloor(alpha
*(double)nSize
);
3657 if (nIndex
% 2 != 0)
3660 OSL_ENSURE(nIndex
< nSize
, "ScTrimMean: falscher Index");
3662 for (SCSIZE i
= nIndex
; i
< nSize
-nIndex
; i
++)
3663 fSum
+= aSortArray
[i
];
3664 PushDouble(fSum
/(double)(nSize
-2*nIndex
));
3668 void ScInterpreter::GetNumberSequenceArray( sal_uInt8 nParamCount
, vector
<double>& rArray
, bool bConvertTextInArray
)
3672 short nParam
= nParamCount
;
3673 size_t nRefInList
= 0;
3674 while (nParam
-- > 0)
3676 const StackVar eStackType
= GetStackType();
3679 case formula::svDouble
:
3680 rArray
.push_back( PopDouble());
3684 PopSingleRef( aAdr
);
3685 ScRefCellValue aCell
;
3686 aCell
.assign(*pDok
, aAdr
);
3687 if (aCell
.hasNumeric())
3688 rArray
.push_back(GetCellValue(aAdr
, aCell
));
3691 case formula::svDoubleRef
:
3694 PopDoubleRef( aRange
, nParam
, nRefInList
);
3699 SCSIZE nCellCount
= aRange
.aEnd
.Col() - aRange
.aStart
.Col() + 1;
3700 nCellCount
*= aRange
.aEnd
.Row() - aRange
.aStart
.Row() + 1;
3701 rArray
.reserve( rArray
.size() + nCellCount
);
3703 sal_uInt16 nErr
= 0;
3705 ScValueIterator
aValIter( pDok
, aRange
, mnSubTotalFlags
);
3706 if (aValIter
.GetFirst( fCellVal
, nErr
))
3708 rArray
.push_back( fCellVal
);
3710 while ((nErr
== 0) && aValIter
.GetNext( fCellVal
, nErr
))
3711 rArray
.push_back( fCellVal
);
3717 case svExternalSingleRef
:
3718 case svExternalDoubleRef
:
3720 ScMatrixRef pMat
= GetMatrix();
3724 SCSIZE nCount
= pMat
->GetElementCount();
3725 rArray
.reserve( rArray
.size() + nCount
);
3726 if (pMat
->IsNumeric())
3728 for (SCSIZE i
= 0; i
< nCount
; ++i
)
3729 rArray
.push_back( pMat
->GetDouble(i
));
3731 else if (bConvertTextInArray
&& eStackType
== svMatrix
)
3733 for (SCSIZE i
= 0; i
< nCount
; ++i
)
3735 if ( pMat
->IsValue( i
) )
3736 rArray
.push_back( pMat
->GetDouble(i
));
3739 // tdf#88547 try to convert string to (date)value
3740 OUString aStr
= pMat
->GetString( i
).getString();
3741 if ( aStr
.getLength() > 0 )
3743 sal_uInt16 nErr
= nGlobalError
;
3745 double fVal
= ConvertStringToValue( aStr
);
3746 if ( !nGlobalError
)
3748 rArray
.push_back( fVal
);
3749 nGlobalError
= nErr
;
3753 rArray
.push_back( CreateDoubleError( errNoValue
));
3754 // Propagate previous error if any, else
3755 // the current #VALUE! error.
3757 nGlobalError
= nErr
;
3759 nGlobalError
= errNoValue
;
3767 for (SCSIZE i
= 0; i
< nCount
; ++i
)
3769 if ( pMat
->IsValue( i
) )
3770 rArray
.push_back( pMat
->GetDouble(i
));
3777 SetError( errIllegalParameter
);
3783 // nParam > 0 in case of error, clean stack environment and obtain earlier
3784 // error if there was one.
3785 while (nParam
-- > 0)
3789 void ScInterpreter::GetSortArray( sal_uInt8 nParamCount
, vector
<double>& rSortArray
, vector
<long>* pIndexOrder
, bool bConvertTextInArray
, bool bAllowEmptyArray
)
3791 GetNumberSequenceArray( nParamCount
, rSortArray
, bConvertTextInArray
);
3792 if (rSortArray
.size() > MAX_ANZ_DOUBLE_FOR_SORT
)
3793 SetError( errStackOverflow
);
3794 else if ( rSortArray
.empty() )
3796 if ( bAllowEmptyArray
)
3798 SetError( errNoValue
);
3801 if (nGlobalError
== 0)
3802 QuickSort( rSortArray
, pIndexOrder
);
3805 static void lcl_QuickSort( long nLo
, long nHi
, vector
<double>& rSortArray
, vector
<long>* pIndexOrder
)
3807 // If pIndexOrder is not NULL, we assume rSortArray.size() == pIndexOrder->size().
3813 if (rSortArray
[nLo
] > rSortArray
[nHi
])
3815 swap(rSortArray
[nLo
], rSortArray
[nHi
]);
3817 swap(pIndexOrder
->at(nLo
), pIndexOrder
->at(nHi
));
3826 double fLo
= rSortArray
[nLo
];
3827 while (ni
<= nHi
&& rSortArray
[ni
] < fLo
) ni
++;
3828 while (nj
>= nLo
&& fLo
< rSortArray
[nj
]) nj
--;
3833 swap(rSortArray
[ni
], rSortArray
[nj
]);
3835 swap(pIndexOrder
->at(ni
), pIndexOrder
->at(nj
));
3844 if ((nj
- nLo
) < (nHi
- ni
))
3846 if (nLo
< nj
) lcl_QuickSort(nLo
, nj
, rSortArray
, pIndexOrder
);
3847 if (ni
< nHi
) lcl_QuickSort(ni
, nHi
, rSortArray
, pIndexOrder
);
3851 if (ni
< nHi
) lcl_QuickSort(ni
, nHi
, rSortArray
, pIndexOrder
);
3852 if (nLo
< nj
) lcl_QuickSort(nLo
, nj
, rSortArray
, pIndexOrder
);
3856 void ScInterpreter::QuickSort( vector
<double>& rSortArray
, vector
<long>* pIndexOrder
)
3858 long n
= static_cast<long>(rSortArray
.size());
3862 pIndexOrder
->clear();
3863 pIndexOrder
->reserve(n
);
3864 for (long i
= 0; i
< n
; ++i
)
3865 pIndexOrder
->push_back(i
);
3871 size_t nValCount
= rSortArray
.size();
3872 for (size_t i
= 0; (i
+ 4) <= nValCount
-1; i
+= 4)
3874 size_t nInd
= comphelper::rng::uniform_size_distribution(0, nValCount
-2);
3875 ::std::swap( rSortArray
[i
], rSortArray
[nInd
]);
3877 ::std::swap( pIndexOrder
->at(i
), pIndexOrder
->at(nInd
));
3880 lcl_QuickSort(0, n
-1, rSortArray
, pIndexOrder
);
3883 void ScInterpreter::ScRank( bool bAverage
)
3885 sal_uInt8 nParamCount
= GetByte();
3886 if ( !MustHaveParamCount( nParamCount
, 2, 3 ) )
3889 if ( nParamCount
== 3 )
3890 bAscending
= GetBool();
3894 vector
<double> aSortArray
;
3895 GetSortArray( 1, aSortArray
, NULL
, false, false );
3896 double fVal
= GetDouble();
3897 SCSIZE nSize
= aSortArray
.size();
3898 if ( aSortArray
.empty() || nSize
== 0 || nGlobalError
)
3902 if ( fVal
< aSortArray
[ 0 ] || fVal
> aSortArray
[ nSize
- 1 ] )
3906 double fLastPos
= 0;
3907 double fFirstPos
= -1.0;
3908 bool bFinished
= false;
3910 for ( i
= 0; i
< nSize
&& !bFinished
&& !nGlobalError
; i
++ )
3912 if ( aSortArray
[ i
] == fVal
)
3914 if ( fFirstPos
< 0 )
3915 fFirstPos
= i
+ 1.0;
3919 if ( aSortArray
[ i
] > fVal
)
3931 PushDouble( fFirstPos
);
3933 PushDouble( nSize
+ 1.0 - fLastPos
);
3938 PushDouble( ( fFirstPos
+ fLastPos
) / 2.0 );
3940 PushDouble( nSize
+ 1.0 - ( fFirstPos
+ fLastPos
) / 2.0 );
3946 void ScInterpreter::ScAveDev()
3948 sal_uInt8 nParamCount
= GetByte();
3949 if ( !MustHaveParamCountMin( nParamCount
, 1 ) )
3951 sal_uInt16 SaveSP
= sp
;
3952 double nMiddle
= 0.0;
3954 double rValCount
= 0.0;
3957 short nParam
= nParamCount
;
3958 size_t nRefInList
= 0;
3959 while (nParam
-- > 0)
3961 switch (GetStackType())
3963 case formula::svDouble
:
3964 rVal
+= GetDouble();
3969 PopSingleRef( aAdr
);
3970 ScRefCellValue aCell
;
3971 aCell
.assign(*pDok
, aAdr
);
3972 if (aCell
.hasNumeric())
3974 rVal
+= GetCellValue(aAdr
, aCell
);
3979 case formula::svDoubleRef
:
3982 sal_uInt16 nErr
= 0;
3984 PopDoubleRef( aRange
, nParam
, nRefInList
);
3985 ScValueIterator
aValIter( pDok
, aRange
, mnSubTotalFlags
);
3986 if (aValIter
.GetFirst(nCellVal
, nErr
))
3991 while ((nErr
== 0) && aValIter
.GetNext(nCellVal
, nErr
))
4001 case svExternalSingleRef
:
4002 case svExternalDoubleRef
:
4004 ScMatrixRef pMat
= GetMatrix();
4007 SCSIZE nCount
= pMat
->GetElementCount();
4008 if (pMat
->IsNumeric())
4010 for (SCSIZE nElem
= 0; nElem
< nCount
; nElem
++)
4012 rVal
+= pMat
->GetDouble(nElem
);
4018 for (SCSIZE nElem
= 0; nElem
< nCount
; nElem
++)
4019 if (!pMat
->IsString(nElem
))
4021 rVal
+= pMat
->GetDouble(nElem
);
4029 SetError(errIllegalParameter
);
4035 PushError( nGlobalError
);
4038 nMiddle
= rVal
/ rValCount
;
4041 nParam
= nParamCount
;
4043 while (nParam
-- > 0)
4045 switch (GetStackType())
4047 case formula::svDouble
:
4048 rVal
+= fabs(GetDouble() - nMiddle
);
4052 PopSingleRef( aAdr
);
4053 ScRefCellValue aCell
;
4054 aCell
.assign(*pDok
, aAdr
);
4055 if (aCell
.hasNumeric())
4056 rVal
+= fabs(GetCellValue(aAdr
, aCell
) - nMiddle
);
4059 case formula::svDoubleRef
:
4062 sal_uInt16 nErr
= 0;
4064 PopDoubleRef( aRange
, nParam
, nRefInList
);
4065 ScValueIterator
aValIter( pDok
, aRange
, mnSubTotalFlags
);
4066 if (aValIter
.GetFirst(nCellVal
, nErr
))
4068 rVal
+= (fabs(nCellVal
- nMiddle
));
4069 while (aValIter
.GetNext(nCellVal
, nErr
))
4070 rVal
+= fabs(nCellVal
- nMiddle
);
4075 case svExternalSingleRef
:
4076 case svExternalDoubleRef
:
4078 ScMatrixRef pMat
= GetMatrix();
4081 SCSIZE nCount
= pMat
->GetElementCount();
4082 if (pMat
->IsNumeric())
4084 for (SCSIZE nElem
= 0; nElem
< nCount
; nElem
++)
4086 rVal
+= fabs(pMat
->GetDouble(nElem
) - nMiddle
);
4091 for (SCSIZE nElem
= 0; nElem
< nCount
; nElem
++)
4093 if (!pMat
->IsString(nElem
))
4094 rVal
+= fabs(pMat
->GetDouble(nElem
) - nMiddle
);
4100 default : SetError(errIllegalParameter
); break;
4103 PushDouble(rVal
/ rValCount
);
4106 void ScInterpreter::ScDevSq()
4110 GetStVarParams(nVal
, nValCount
);
4114 void ScInterpreter::ScProbability()
4116 sal_uInt8 nParamCount
= GetByte();
4117 if ( !MustHaveParamCount( nParamCount
, 3, 4 ) )
4121 if (nParamCount
== 4)
4131 ScMatrixRef pMatP
= GetMatrix();
4132 ScMatrixRef pMatW
= GetMatrix();
4133 if (!pMatP
|| !pMatW
)
4134 PushIllegalParameter();
4139 pMatP
->GetDimensions(nC1
, nR1
);
4140 pMatW
->GetDimensions(nC2
, nR2
);
4141 if (nC1
!= nC2
|| nR1
!= nR2
|| nC1
== 0 || nR1
== 0 ||
4142 nC2
== 0 || nR2
== 0)
4150 for ( SCSIZE i
= 0; i
< nC1
&& !bStop
; i
++ )
4152 for (SCSIZE j
= 0; j
< nR1
&& !bStop
; ++j
)
4154 if (pMatP
->IsValue(i
,j
) && pMatW
->IsValue(i
,j
))
4156 fP
= pMatP
->GetDouble(i
,j
);
4157 fW
= pMatW
->GetDouble(i
,j
);
4158 if (fP
< 0.0 || fP
> 1.0)
4163 if (fW
>= fLo
&& fW
<= fUp
)
4168 SetError( errIllegalArgument
);
4171 if (bStop
|| fabs(fSum
-1.0) > 1.0E-7)
4179 void ScInterpreter::ScCorrel()
4181 // This is identical to ScPearson()
4185 void ScInterpreter::ScCovarianceP()
4187 CalculatePearsonCovar( false, false, false );
4190 void ScInterpreter::ScCovarianceS()
4192 CalculatePearsonCovar( false, false, true );
4195 void ScInterpreter::ScPearson()
4197 CalculatePearsonCovar( true, false, false );
4200 void ScInterpreter::CalculatePearsonCovar( bool _bPearson
, bool _bStexy
, bool _bSample
)
4202 if ( !MustHaveParamCount( GetByte(), 2 ) )
4204 ScMatrixRef pMat1
= GetMatrix();
4205 ScMatrixRef pMat2
= GetMatrix();
4206 if (!pMat1
|| !pMat2
)
4208 PushIllegalParameter();
4213 pMat1
->GetDimensions(nC1
, nR1
);
4214 pMat2
->GetDimensions(nC2
, nR2
);
4215 if (nR1
!= nR2
|| nC1
!= nC2
)
4217 PushIllegalArgument();
4221 * (sum((X-MeanX)(Y-MeanY)))/N equals (SumXY)/N-MeanX*MeanY mathematically,
4222 * but the latter produces wrong results if the absolute values are high,
4223 * for example above 10^8
4225 double fCount
= 0.0;
4229 for (SCSIZE i
= 0; i
< nC1
; i
++)
4231 for (SCSIZE j
= 0; j
< nR1
; j
++)
4233 if (!pMat1
->IsString(i
,j
) && !pMat2
->IsString(i
,j
))
4235 double fValX
= pMat1
->GetDouble(i
,j
);
4236 double fValY
= pMat2
->GetDouble(i
,j
);
4243 if (fCount
< (_bStexy
? 3.0 : (_bSample
? 2.0 : 1.0)))
4247 double fSumDeltaXDeltaY
= 0.0; // sum of (ValX-MeanX)*(ValY-MeanY)
4248 double fSumSqrDeltaX
= 0.0; // sum of (ValX-MeanX)^2
4249 double fSumSqrDeltaY
= 0.0; // sum of (ValY-MeanY)^2
4250 const double fMeanX
= fSumX
/ fCount
;
4251 const double fMeanY
= fSumY
/ fCount
;
4252 for (SCSIZE i
= 0; i
< nC1
; i
++)
4254 for (SCSIZE j
= 0; j
< nR1
; j
++)
4256 if (!pMat1
->IsString(i
,j
) && !pMat2
->IsString(i
,j
))
4258 const double fValX
= pMat1
->GetDouble(i
,j
);
4259 const double fValY
= pMat2
->GetDouble(i
,j
);
4260 fSumDeltaXDeltaY
+= (fValX
- fMeanX
) * (fValY
- fMeanY
);
4263 fSumSqrDeltaX
+= (fValX
- fMeanX
) * (fValX
- fMeanX
);
4264 fSumSqrDeltaY
+= (fValY
- fMeanY
) * (fValY
- fMeanY
);
4271 if (fSumSqrDeltaX
== 0.0 || ( !_bStexy
&& fSumSqrDeltaY
== 0.0) )
4272 PushError( errDivisionByZero
);
4274 PushDouble( sqrt( (fSumSqrDeltaY
- fSumDeltaXDeltaY
*
4275 fSumDeltaXDeltaY
/ fSumSqrDeltaX
) / (fCount
-2)));
4277 PushDouble( fSumDeltaXDeltaY
/ sqrt( fSumSqrDeltaX
* fSumSqrDeltaY
));
4282 PushDouble( fSumDeltaXDeltaY
/ ( fCount
- 1 ) );
4284 PushDouble( fSumDeltaXDeltaY
/ fCount
);
4289 void ScInterpreter::ScRSQ()
4291 // Same as ScPearson()*ScPearson()
4295 switch (GetStackType())
4297 case formula::svDouble
:
4299 double fVal
= PopDouble();
4300 PushDouble( fVal
* fVal
);
4310 void ScInterpreter::ScSTEYX()
4312 CalculatePearsonCovar( true, true, false );
4314 void ScInterpreter::CalculateSlopeIntercept(bool bSlope
)
4316 if ( !MustHaveParamCount( GetByte(), 2 ) )
4318 ScMatrixRef pMat1
= GetMatrix();
4319 ScMatrixRef pMat2
= GetMatrix();
4320 if (!pMat1
|| !pMat2
)
4322 PushIllegalParameter();
4327 pMat1
->GetDimensions(nC1
, nR1
);
4328 pMat2
->GetDimensions(nC2
, nR2
);
4329 if (nR1
!= nR2
|| nC1
!= nC2
)
4331 PushIllegalArgument();
4334 // #i78250# numerical stability improved
4335 double fCount
= 0.0;
4339 for (SCSIZE i
= 0; i
< nC1
; i
++)
4341 for (SCSIZE j
= 0; j
< nR1
; j
++)
4343 if (!pMat1
->IsString(i
,j
) && !pMat2
->IsString(i
,j
))
4345 double fValX
= pMat1
->GetDouble(i
,j
);
4346 double fValY
= pMat2
->GetDouble(i
,j
);
4357 double fSumDeltaXDeltaY
= 0.0; // sum of (ValX-MeanX)*(ValY-MeanY)
4358 double fSumSqrDeltaX
= 0.0; // sum of (ValX-MeanX)^2
4359 double fMeanX
= fSumX
/ fCount
;
4360 double fMeanY
= fSumY
/ fCount
;
4361 for (SCSIZE i
= 0; i
< nC1
; i
++)
4363 for (SCSIZE j
= 0; j
< nR1
; j
++)
4365 if (!pMat1
->IsString(i
,j
) && !pMat2
->IsString(i
,j
))
4367 double fValX
= pMat1
->GetDouble(i
,j
);
4368 double fValY
= pMat2
->GetDouble(i
,j
);
4369 fSumDeltaXDeltaY
+= (fValX
- fMeanX
) * (fValY
- fMeanY
);
4370 fSumSqrDeltaX
+= (fValX
- fMeanX
) * (fValX
- fMeanX
);
4374 if (fSumSqrDeltaX
== 0.0)
4375 PushError( errDivisionByZero
);
4379 PushDouble( fSumDeltaXDeltaY
/ fSumSqrDeltaX
);
4381 PushDouble( fMeanY
- fSumDeltaXDeltaY
/ fSumSqrDeltaX
* fMeanX
);
4386 void ScInterpreter::ScSlope()
4388 CalculateSlopeIntercept(true);
4391 void ScInterpreter::ScIntercept()
4393 CalculateSlopeIntercept(false);
4396 void ScInterpreter::ScForecast()
4398 if ( !MustHaveParamCount( GetByte(), 3 ) )
4400 ScMatrixRef pMat1
= GetMatrix();
4401 ScMatrixRef pMat2
= GetMatrix();
4402 if (!pMat1
|| !pMat2
)
4404 PushIllegalParameter();
4409 pMat1
->GetDimensions(nC1
, nR1
);
4410 pMat2
->GetDimensions(nC2
, nR2
);
4411 if (nR1
!= nR2
|| nC1
!= nC2
)
4413 PushIllegalArgument();
4416 double fVal
= GetDouble();
4417 // #i78250# numerical stability improved
4418 double fCount
= 0.0;
4422 for (SCSIZE i
= 0; i
< nC1
; i
++)
4424 for (SCSIZE j
= 0; j
< nR1
; j
++)
4426 if (!pMat1
->IsString(i
,j
) && !pMat2
->IsString(i
,j
))
4428 double fValX
= pMat1
->GetDouble(i
,j
);
4429 double fValY
= pMat2
->GetDouble(i
,j
);
4440 double fSumDeltaXDeltaY
= 0.0; // sum of (ValX-MeanX)*(ValY-MeanY)
4441 double fSumSqrDeltaX
= 0.0; // sum of (ValX-MeanX)^2
4442 double fMeanX
= fSumX
/ fCount
;
4443 double fMeanY
= fSumY
/ fCount
;
4444 for (SCSIZE i
= 0; i
< nC1
; i
++)
4446 for (SCSIZE j
= 0; j
< nR1
; j
++)
4448 if (!pMat1
->IsString(i
,j
) && !pMat2
->IsString(i
,j
))
4450 double fValX
= pMat1
->GetDouble(i
,j
);
4451 double fValY
= pMat2
->GetDouble(i
,j
);
4452 fSumDeltaXDeltaY
+= (fValX
- fMeanX
) * (fValY
- fMeanY
);
4453 fSumSqrDeltaX
+= (fValX
- fMeanX
) * (fValX
- fMeanX
);
4457 if (fSumSqrDeltaX
== 0.0)
4458 PushError( errDivisionByZero
);
4460 PushDouble( fMeanY
+ fSumDeltaXDeltaY
/ fSumSqrDeltaX
* (fVal
- fMeanX
));
4464 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */