Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / core / tool / interpr3.cxx
blob8fa0a0e5791d21e07beecfce9617074d02d3bdda
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
21 #include <stdlib.h>
22 #include <string.h>
24 #include "interpre.hxx"
25 #include "global.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"
33 #include <math.h>
34 #include <vector>
35 #include <algorithm>
37 using ::std::vector;
38 using namespace formula;
40 // STATIC DATA
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();
46 class ScDistFunc
48 public:
49 virtual double GetValue(double x) const = 0;
51 protected:
52 ~ScDistFunc() {}
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 )
67 rConvError = false;
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);
77 double fTemp;
78 unsigned short nCount;
79 for (nCount = 0; nCount < 1000 && !lcl_HasChangeOfSign(fAy,fBy); nCount++)
81 if (fabs(fAy) <= fabs(fBy))
83 fTemp = fAx;
84 fAx += 2.0 * (fAx - fBx);
85 if (fAx < 0.0)
86 fAx = 0.0;
87 fBx = fTemp;
88 fBy = fAy;
89 fAy = rFunction.GetValue(fAx);
91 else
93 fTemp = fBx;
94 fBx += 2.0 * (fBx - fAx);
95 fAx = fTemp;
96 fAy = fBy;
97 fBy = rFunction.GetValue(fBx);
101 if (fAy == 0.0)
102 return fAx;
103 if (fBy == 0.0)
104 return fBx;
105 if (!lcl_HasChangeOfSign( fAy, fBy))
107 rConvError = true;
108 return 0.0;
110 // inverse quadric interpolation with additional brackets
111 // set three points
112 double fPx = fAx;
113 double fPy = fAy;
114 double fQx = fBx;
115 double fQy = fBy;
116 double fRx = fAx;
117 double fRy = fAy;
118 double fSx = 0.5 * (fAx + fBx); // potential next point
119 bool bHasToInterpolate = true;
120 nCount = 0;
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?
133 else
134 bHasToInterpolate = false;
136 if(!bHasToInterpolate)
138 fSx = 0.5 * (fAx + fBx);
139 // reset points
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);
147 // update brackets
148 if (lcl_HasChangeOfSign( fAy, fRy))
150 fBx = fRx; fBy = fRy;
152 else
154 fAx = fRx; fAy = fRy;
156 // if last interration brought to small advance, then do bisection next
157 // time, for safety
158 bHasToInterpolate = bHasToInterpolate && (fabs(fRy) * 2.0 <= fabs(fQy));
159 ++nCount;
161 return fRx;
164 // Allgemeine Funktionen
166 void ScInterpreter::ScNoName()
168 PushError(errNoName);
171 void ScInterpreter::ScBadName()
173 short nParamCount = GetByte();
174 while (nParamCount-- > 0)
176 PopError();
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);
198 return nVal;
201 double ScInterpreter::gauss(double x)
204 double xAbs = fabs(x);
205 sal_uInt16 xShort = (sal_uInt16)::rtl::math::approxFloor(xAbs);
206 double nVal = 0.0;
207 if (xShort == 0)
209 double t0[] =
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))
218 double t2[] =
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))
231 double t4[] =
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));
241 else
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;
246 if (x < 0.0)
247 return -nVal;
248 else
249 return nVal;
253 // #i26836# new gaussinv implementation by Martin Eitzenberger <m.eitzenberger@unix.net>
256 double ScInterpreter::gaussinv(double x)
258 double q,t,z;
260 q=x-0.5;
262 if(fabs(q)<=.425)
264 t=0.180625-q*q;
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
309 *t+1.0
313 else
315 if(q>0) t=1-x;
316 else t=x;
318 t=sqrt(-log(t));
320 if(t<=5.0)
322 t+=-1.6;
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
366 *t+1.0
370 else
372 t+=-5.0;
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
416 *t+1.0
421 if(q<0.0) z=-z;
424 return z;
427 double ScInterpreter::Fakultaet(double x)
429 x = ::rtl::math::approxFloor(x);
430 if (x < 0.0)
431 return 0.0;
432 else if (x == 0.0)
433 return 1.0;
434 else if (x <= 170.0)
436 double fTemp = x;
437 while (fTemp > 2.0)
439 fTemp--;
440 x *= fTemp;
443 else
444 SetError(errNoValue);
445 return x;
448 double ScInterpreter::BinomKoeff(double n, double k)
450 // this method has been duplicated as BinomialCoefficient()
451 // in scaddins/source/analysis/analysishelper.cxx
453 double nVal = 0.0;
454 k = ::rtl::math::approxFloor(k);
455 if (n < k)
456 nVal = 0.0;
457 else if (k == 0.0)
458 nVal = 1.0;
459 else
461 nVal = n/k;
462 n--;
463 k--;
464 while (k > 0.0)
466 nVal *= n/k;
467 k--;
468 n--;
472 return nVal;
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] = {
498 39916800,
499 120543840,
500 150917976,
501 105258076,
502 45995730,
503 13339535,
504 2637558,
505 357423,
506 32670,
507 1925,
511 // Horner scheme
512 double fSumNum;
513 double fSumDenom;
514 int nI;
515 if (fZ<=1.0)
517 fSumNum = fNum[12];
518 fSumDenom = fDenom[12];
519 for (nI = 11; nI >= 0; --nI)
521 fSumNum *= fZ;
522 fSumNum += fNum[nI];
523 fSumDenom *= fZ;
524 fSumDenom += fDenom[nI];
527 else
528 // Cancel down with fZ^12; Horner scheme with reverse coefficients
530 double fZInv = 1/fZ;
531 fSumNum = fNum[0];
532 fSumDenom = fDenom[0];
533 for (nI = 1; nI <=12; ++nI)
535 fSumNum *= fZInv;
536 fSumNum += fNum[nI];
537 fSumDenom *= fZInv;
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);
559 return 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);
581 return HUGE_VAL;
584 if (fZ >= 1.0)
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);
596 return HUGE_VAL;
598 return lcl_GetGammaHelper(fZ+2) / (fZ+1) / fZ;
600 // fZ<-0.5
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
604 return 0.0;
606 if (fLogDivisor<0.0)
607 if (fLogPi - fLogDivisor > fLogDblMax) // overflow
609 SetError(errIllegalFPOperation);
610 return HUGE_VAL;
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);
621 if (fZ >= 1.0)
622 return log(lcl_GetGammaHelper(fZ));
623 if (fZ >= 0.5)
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)
645 if (fX <= 0.0)
646 return 1.0; // see ODFF
647 else
648 return GetUpRegIGamma( fDF/2.0, fX/2.0);
651 // ready for ODF 1.2
652 // for ODF CHISQDIST; cumulative distribution function, fDF=degrees of freedom
653 // returns left tail
654 /** You must ensure fDF>0.0 */
655 double ScInterpreter::GetChiSqDistCDF(double fX, double fDF)
657 if (fX <= 0.0)
658 return 0.0; // see ODFF
659 else
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
666 double fValue;
667 if (fX <= 0.0)
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
676 double fCount;
677 if (fmod(fDF,2.0)<0.5)
679 // even
680 fValue = 0.5;
681 fCount = 2.0;
683 else
685 fValue = 1/sqrt(fX*2*F_PI);
686 fCount = 1.0;
688 while ( fCount < fDF)
690 fValue *= (fX / fCount);
691 fCount += 2.0;
693 if (fX>=1425.0) // underflow in e^(-x/2)
694 fValue = exp(log(fValue)-fX/2);
695 else
696 fValue *= exp(-fX/2);
698 return fValue;
701 void ScInterpreter::ScChiSqDist()
703 sal_uInt8 nParamCount = GetByte();
704 if ( !MustHaveParamCount( nParamCount, 2, 3 ) )
705 return;
706 bool bCumulative;
707 if (nParamCount == 3)
708 bCumulative = GetBool();
709 else
710 bCumulative = true;
711 double fDF = ::rtl::math::approxFloor(GetDouble());
712 if (fDF < 1.0)
713 PushIllegalArgument();
714 else
716 double fX = GetDouble();
717 if (bCumulative)
718 PushDouble(GetChiSqDistCDF(fX,fDF));
719 else
720 PushDouble(GetChiSqDistPDF(fX,fDF));
724 void ScInterpreter::ScChiSqDist_MS()
726 sal_uInt8 nParamCount = GetByte();
727 if ( !MustHaveParamCount( nParamCount, 3, 3 ) )
728 return;
729 bool bCumulative = GetBool();
730 double fDF = ::rtl::math::approxFloor( GetDouble() );
731 if ( fDF < 1.0 || fDF > 1E10 )
732 PushIllegalArgument();
733 else
735 double fX = GetDouble();
736 if ( fX < 0 )
737 PushIllegalArgument();
738 else
740 if ( bCumulative )
741 PushDouble( GetChiSqDistCDF( fX, fDF ) );
742 else
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();
753 else
755 double fResult = GetGamma(x);
756 if (nGlobalError)
758 PushError( nGlobalError);
759 return;
761 PushDouble(fResult);
765 void ScInterpreter::ScLogGamma()
767 double x = GetDouble();
768 if (x > 0.0) // constraint from ODFF
769 PushDouble( GetLogGamma(x));
770 else
771 PushIllegalArgument();
774 double ScInterpreter::GetBeta(double fAlpha, double fBeta)
776 double fA;
777 double fB;
778 if (fAlpha > fBeta)
780 fA = fAlpha; fB = fBeta;
782 else
784 fA = fBeta; fB = fAlpha;
786 if (fA+fB < fMaxGammaArgument) // simple case
787 return GetGamma(fA)/GetGamma(fA+fB)*GetGamma(fB);
788 // need logarithm
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);
802 fResult *= fLanczos;
803 return fResult;
806 // Same as GetBeta but with logarithm
807 double ScInterpreter::GetLogBeta(double fAlpha, double fBeta)
809 double fA;
810 double fB;
811 if (fAlpha > fBeta)
813 fA = fAlpha; fB = fBeta;
815 else
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;
832 return fResult;
835 // beta distribution probability density function
836 double ScInterpreter::GetBetaDistPDF(double fX, double fA, double fB)
838 // special cases
839 if (fA == 1.0) // result b*(1-x)^(b-1)
841 if (fB == 1.0)
842 return 1.0;
843 if (fB == 2.0)
844 return -2.0*fX + 2.0;
845 if (fX == 1.0 && fB < 1.0)
847 SetError(errIllegalArgument);
848 return HUGE_VAL;
850 if (fX <= 0.01)
851 return fB + fB * ::rtl::math::expm1((fB-1.0) * ::rtl::math::log1p(-fX));
852 else
853 return fB * pow(0.5-fX+0.5,fB-1.0);
855 if (fB == 1.0) // result a*x^(a-1)
857 if (fA == 2.0)
858 return fA * fX;
859 if (fX == 0.0 && fA < 1.0)
861 SetError(errIllegalArgument);
862 return HUGE_VAL;
864 return fA * pow(fX,fA-1);
866 if (fX <= 0.0)
868 if (fA < 1.0 && fX == 0.0)
870 SetError(errIllegalArgument);
871 return HUGE_VAL;
873 else
874 return 0.0;
876 if (fX >= 1.0)
878 if (fB < 1.0 && fX == 1.0)
880 SetError(errIllegalArgument);
881 return HUGE_VAL;
883 else
884 return 0.0;
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);
907 x^a * (1-x)^b
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;
913 a1 = 1.0; b1 = 1.0;
914 b2 = 1.0 - (fA+fB)/(fA+1.0)*fX;
915 if (b2 == 0.0)
917 a2 = 0.0;
918 fnorm = 1.0;
919 cf = 1.0;
921 else
923 a2 = 1.0;
924 fnorm = 1.0/b2;
925 cf = a2*fnorm;
927 cfnew = 1.0;
928 double rm = 1.0;
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;
937 apl2m = fA + 2.0*rm;
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;
944 if (b2 != 0.0)
946 fnorm = 1.0/b2;
947 cfnew = a2*fnorm;
948 bfinished = (fabs(cf-cfnew) < fabs(cf)*fMachEps);
950 cf = cfnew;
951 rm += 1.0;
953 while (rm < fMaxIter && !bfinished);
954 return cf;
957 // cumulative distribution function, normalized
958 double ScInterpreter::GetBetaDist(double fXin, double fAlpha, double fBeta)
960 // special cases
961 if (fXin <= 0.0) // values are valid, see spec
962 return 0.0;
963 if (fXin >= 1.0) // values are valid, see spec
964 return 1.0;
965 if (fBeta == 1.0)
966 return pow(fXin, fAlpha);
967 if (fAlpha == 1.0)
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
971 double fResult;
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);
976 double fX = fXin;
977 double flnX = log(fXin);
978 double fA = fAlpha;
979 double fB = fBeta;
980 bool bReflect = fXin > fAlpha/(fAlpha+fBeta);
981 if (bReflect)
983 fA = fBeta;
984 fB = fAlpha;
985 fX = fY;
986 fY = fXin;
987 flnX = flnY;
988 flnY = log(fXin);
990 fResult = lcl_GetBetaHelperContFrac(fX,fA,fB);
991 fResult = fResult/fA;
992 double fP = fA/(fA+fB);
993 double fQ = fB/(fA+fB);
994 double fTemp;
995 if (fA > 1.0 && fB > 1.0 && fP < 0.97 && fQ < 0.97) //found experimental
996 fTemp = GetBetaDistPDF(fX,fA,fB)*fX*fY;
997 else
998 fTemp = exp(fA*flnX + fB*flnY - GetLogBeta(fA,fB));
999 fResult *= fTemp;
1000 if (bReflect)
1001 fResult = 0.5 - fResult + 0.5;
1002 if (fResult > 1.0) // ensure valid range
1003 fResult = 1.0;
1004 if (fResult < 0.0)
1005 fResult = 0.0;
1006 return fResult;
1009 void ScInterpreter::ScBetaDist()
1011 sal_uInt8 nParamCount = GetByte();
1012 if ( !MustHaveParamCount( nParamCount, 3, 6 ) ) // expanded, see #i91547#
1013 return;
1014 double fLowerBound, fUpperBound;
1015 double alpha, beta, x;
1016 bool bIsCumulative;
1017 if (nParamCount == 6)
1018 bIsCumulative = GetBool();
1019 else
1020 bIsCumulative = true;
1021 if (nParamCount >= 5)
1022 fUpperBound = GetDouble();
1023 else
1024 fUpperBound = 1.0;
1025 if (nParamCount >= 4)
1026 fLowerBound = GetDouble();
1027 else
1028 fLowerBound = 0.0;
1029 beta = GetDouble();
1030 alpha = GetDouble();
1031 x = GetDouble();
1032 double fScale = fUpperBound - fLowerBound;
1033 if (fScale <= 0.0 || alpha <= 0.0 || beta <= 0.0)
1035 PushIllegalArgument();
1036 return;
1038 if (bIsCumulative) // cumulative distribution function
1040 // special cases
1041 if (x < fLowerBound)
1043 PushDouble(0.0); return; //see spec
1045 if (x > fUpperBound)
1047 PushDouble(1.0); return; //see spec
1049 // normal cases
1050 x = (x-fLowerBound)/fScale; // convert to standard form
1051 PushDouble(GetBetaDist(x, alpha, beta));
1052 return;
1054 else // probability density function
1056 if (x < fLowerBound || x > fUpperBound)
1058 PushDouble(0.0);
1059 return;
1061 x = (x-fLowerBound)/fScale;
1062 PushDouble(GetBetaDistPDF(x, alpha, beta)/fScale);
1063 return;
1068 fdo#71008
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 ) )
1077 return;
1078 double fLowerBound, fUpperBound;
1079 double alpha, beta, x;
1080 bool bIsCumulative;
1081 if (nParamCount == 6)
1082 fUpperBound = GetDouble();
1083 else
1084 fUpperBound = 1.0;
1085 if (nParamCount >= 4)
1086 fLowerBound = GetDouble();
1087 else
1088 fLowerBound = 0.0;
1089 bIsCumulative = GetBool();
1090 beta = GetDouble();
1091 alpha = GetDouble();
1092 x = GetDouble();
1093 double fScale = fUpperBound - fLowerBound;
1094 if (fScale <= 0.0 || alpha <= 0.0 || beta <= 0.0)
1096 PushIllegalArgument();
1097 return;
1099 if (bIsCumulative) // cumulative distribution function
1101 // special cases
1102 if (x < fLowerBound)
1104 PushDouble(0.0); return; //see spec
1106 if (x > fUpperBound)
1108 PushDouble(1.0); return; //see spec
1110 // normal cases
1111 x = (x-fLowerBound)/fScale; // convert to standard form
1112 PushDouble(GetBetaDist(x, alpha, beta));
1113 return;
1115 else // probability density function
1117 if (x < fLowerBound || x > fUpperBound)
1119 PushDouble(0.0);
1120 return;
1122 x = (x-fLowerBound)/fScale;
1123 PushDouble(GetBetaDistPDF(x, alpha, beta)/fScale);
1124 return;
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();
1143 else
1144 PushDouble( ::rtl::math::atanh( fVal));
1147 void ScInterpreter::ScFisherInv()
1149 PushDouble( tanh( GetDouble()));
1152 void ScInterpreter::ScFact()
1154 double nVal = GetDouble();
1155 if (nVal < 0.0)
1156 PushIllegalArgument();
1157 else
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();
1169 else
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();
1182 else
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();
1195 else if (k == 0.0)
1196 PushInt(1); // (n! / (n - 0)!) == 1
1197 else
1199 double nVal = n;
1200 for (sal_uLong i = (sal_uLong)k-1; i >= 1; i--)
1201 nVal *= n-(double)i;
1202 PushDouble(nVal);
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();
1215 else
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);
1231 else
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;
1236 return fFactor;
1239 else
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;
1244 return fFactor;
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
1252 sal_uInt32 i;
1253 double fSum;
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;
1263 fSum += fFactor;
1265 return (fSum>1.0) ? 1.0 : fSum;
1268 void ScInterpreter::ScB()
1270 sal_uInt8 nParamCount = GetByte();
1271 if ( !MustHaveParamCount( nParamCount, 3, 4 ) )
1272 return ;
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();
1280 else if (p == 0.0)
1281 PushDouble( (x == 0.0) ? 1.0 : 0.0 );
1282 else if ( p == 1.0)
1283 PushDouble( (x == n) ? 1.0 : 0.0);
1284 else
1285 PushDouble(GetBinomDistPMF(x,n,p));
1287 else
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));
1299 else
1301 double fFactor = pow(q, n);
1302 if (fFactor > ::std::numeric_limits<double>::min())
1303 PushDouble(lcl_GetBinomDistRange(n,xs,xe,fFactor,p,q));
1304 else
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));
1313 else
1314 PushDouble(GetBetaDist(q,n-xe,xe+1.0)-GetBetaDist(q,n-xs+1,xs) );
1318 else
1320 if ( bIsValidX ) // not(0<p<1)
1322 if ( p == 0.0 )
1323 PushDouble( (xs == 0.0) ? 1.0 : 0.0 );
1324 else if ( p == 1.0 )
1325 PushDouble( (xe == n) ? 1.0 : 0.0 );
1326 else
1327 PushIllegalArgument();
1329 else
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();
1347 return;
1349 if ( p == 0.0)
1351 PushDouble( (x==0.0 || bIsCum) ? 1.0 : 0.0 );
1352 return;
1354 if ( p == 1.0)
1356 PushDouble( (x==n) ? 1.0 : 0.0);
1357 return;
1359 if (!bIsCum)
1360 PushDouble( GetBinomDistPMF(x,n,p));
1361 else
1363 if (x == n)
1364 PushDouble(1.0);
1365 else
1367 double fFactor = pow(q, n);
1368 if (x == 0.0)
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));
1375 else
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;
1384 fSum -= fFactor;
1386 PushDouble( (fSum < 0.0) ? 0.0 : fSum );
1388 else
1389 PushDouble(lcl_GetBinomDistRange(n,n-x,n,fFactor,q,p));
1392 else
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();
1408 else
1410 double fFactor;
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
1415 fFactor = pow(q,n);
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;
1423 fSum += fFactor;
1425 PushDouble(i);
1427 else
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 )
1437 fSum += x;
1439 else
1441 PushNoValue();
1442 return;
1445 PushDouble( i - 1 );
1448 else
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;
1459 fSum -= fFactor;
1461 PushDouble(n-i);
1463 else
1465 // accumulate BinomDist until accumulated BinomDist reaches alpha
1466 double fSum = 0.0, x;
1467 sal_uInt32 max = static_cast<sal_uInt32> (n), i;
1468 alpha = 1 - alpha;
1469 for (i = 0; i < max && fSum < alpha; i++)
1471 x = GetBetaDistPDF( q, ( i + 1 ), ( n - i + 1 ) )/( n + 1 );
1472 if ( !nGlobalError )
1474 fSum += x;
1476 else
1478 PushNoValue();
1479 return;
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();
1498 else
1500 double q = 1.0 - p;
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))
1513 return;
1514 bool bCumulative = nParamCount == 4 ? GetBool() : true;
1515 double sigma = GetDouble(); // standard deviation
1516 double mue = GetDouble(); // mean
1517 double x = GetDouble(); // x
1518 if (sigma <= 0.0)
1520 PushIllegalArgument();
1521 return;
1523 if (bCumulative)
1524 PushDouble(integralPhi((x-mue)/sigma));
1525 else
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))
1533 return;
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
1538 if (sigma <= 0.0)
1540 PushIllegalArgument();
1541 return;
1543 if (bCumulative)
1544 { // cumulative
1545 if (x <= 0.0)
1546 PushDouble(0.0);
1547 else
1548 PushDouble(integralPhi((log(x)-mue)/sigma));
1550 else
1551 { // density
1552 if (x <= 0.0)
1553 PushIllegalArgument();
1554 else
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
1571 if (lambda <= 0.0)
1572 PushIllegalArgument();
1573 else if (kum == 0.0) // Dichte
1575 if (x >= 0.0)
1576 PushDouble(lambda * exp(-lambda*x));
1577 else
1578 PushInt(0);
1580 else // Verteilung
1582 if (x > 0.0)
1583 PushDouble(1.0 - exp(-lambda*x));
1584 else
1585 PushInt(0);
1590 void ScInterpreter::ScTDist()
1592 if ( !MustHaveParamCount( GetByte(), 3 ) )
1593 return;
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();
1600 return;
1602 double R = GetTDist(T, fDF);
1603 if (fFlag == 1.0)
1604 PushDouble(R);
1605 else
1606 PushDouble(2.0*R);
1609 void ScInterpreter::ScFDist()
1611 if ( !MustHaveParamCount( GetByte(), 3 ) )
1612 return;
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();
1619 return;
1621 PushDouble(GetFDist(fF, fF1, fF2));
1624 void ScInterpreter::ScFDist_LT()
1626 if ( !MustHaveParamCount( GetByte(), 4 ) )
1627 return;
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();
1635 return;
1637 if ( bCum )
1639 // left tail cumulative distribution
1640 PushDouble( 1.0 - GetFDist( fF, fF1, fF2 ) );
1642 else
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()
1653 double fResult;
1654 if ( !MustHaveParamCount( GetByte(), 2 ) )
1655 return;
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();
1661 return;
1663 fResult = GetChiDist( fChi, fDF);
1664 if (nGlobalError)
1666 PushError( nGlobalError);
1667 return;
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)));
1685 else // Verteilung
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
1702 if (lambda == 0.0)
1703 PushInt(0);
1704 else
1706 if (lambda >712) // underflow in exp(-lambda)
1707 { // accuracy 11 Digits
1708 PushDouble( exp(x*log(lambda)-lambda-GetLogGamma(x+1.0)));
1710 else
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
1721 if (lambda == 0.0)
1722 PushInt(1);
1723 else
1725 if (lambda > 712 ) // underflow in exp(-lambda)
1726 { // accuracy 12 Digits
1727 PushDouble(GetUpRegIGamma(x+1.0,lambda));
1729 else
1731 if (x >= 936.0) // result is always undistinghable from 1
1732 PushDouble (1.0);
1733 else
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;
1741 fSum += fSummand;
1743 PushDouble(fSum);
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;
1758 if ( fVal > 1.0 )
1759 cn.push_back( fVal );
1763 /** Calculates a value of the hypergeometric distribution.
1765 @author Kohei Yoshida <kohei@openoffice.org>
1767 @see #i47296#
1770 void ScInterpreter::ScHypGeomDist()
1772 if ( !MustHaveParamCount( GetByte(), 4 ) )
1773 return;
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();
1783 return;
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.
1794 @see fdo#71722
1796 void ScInterpreter::ScHypGeomDist_MS()
1798 if ( !MustHaveParamCount( GetByte(), 5 ) )
1799 return;
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();
1810 return;
1813 if ( bCumulative )
1815 double fVal = 0.0;
1817 for ( int i = 0; i <= x && !nGlobalError; i++ )
1818 fVal += GetHypGeomDist( i, n, M, N );
1820 PushDouble( fVal );
1822 else
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>
1836 @see #i47296#
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 )
1850 PushNoValue();
1851 return 0;
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;
1867 #endif
1868 double fCDenomUpper = N - n - M + x + 1.0 - fCDenomVarLower;
1870 double fDNumVarLower = n - M;
1872 if ( n >= M + 1.0 )
1874 if ( N - M < n + 1.0 )
1876 // Case 1
1878 if ( N - n < n + 1.0 )
1880 // no overlap
1881 lcl_PutFactorialElements( cnNumer, 0.0, fCNumVarUpper, N - n );
1882 lcl_PutFactorialElements( cnDenom, 0.0, N - n - 1.0, N );
1884 else
1886 // overlap
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 )
1895 // no overlap
1896 lcl_PutFactorialElements( cnNumer, 1.0, N - M - n + x, N - M + 1.0 );
1897 else
1899 // overlap
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;
1906 else
1908 // Case 2
1910 if ( n > M - 1.0 )
1912 // no overlap
1913 lcl_PutFactorialElements( cnNumer, 0.0, fCNumVarUpper, N - n );
1914 lcl_PutFactorialElements( cnDenom, 0.0, M - 1.0, N );
1916 else
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 )
1925 // no overlap
1926 lcl_PutFactorialElements( cnNumer, N - M - n + 1.0, N - M - n + x, N - M + 1.0 );
1927 else
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" );
1937 else
1939 if ( N - M < M + 1.0 )
1941 // Case 3
1943 if ( N - n < M + 1.0 )
1945 // No overlap
1946 lcl_PutFactorialElements( cnNumer, 0.0, fCNumVarUpper, N - n );
1947 lcl_PutFactorialElements( cnDenom, 0.0, N - M - 1.0, N );
1949 else
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 )
1956 // No overlap
1957 lcl_PutFactorialElements( cnNumer, 1.0, N - M - n + x, N - M + 1.0 );
1958 else
1960 // Overlap
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;
1967 else
1969 // Case 4
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 )
1976 // No overlap
1977 lcl_PutFactorialElements( cnNumer, 0.0, fCNumVarUpper, N - n );
1978 lcl_PutFactorialElements( cnDenom, 0.0, M - 1.0, N );
1980 else
1982 // Overlap
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 )
1989 // No overlap
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;
1998 else
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 )
2029 fEnum = *it1++;
2030 if ( it2 != it2End )
2031 fDenom = *it2++;
2032 fFactor *= fEnum / fDenom;
2035 return fFactor;
2038 void ScInterpreter::ScGammaDist()
2040 sal_uInt8 nParamCount = GetByte();
2041 if ( !MustHaveParamCount( nParamCount, 3, 4 ) )
2042 return;
2043 double bCumulative;
2044 if (nParamCount == 4)
2045 bCumulative = GetBool();
2046 else
2047 bCumulative = true;
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();
2053 else
2055 if (bCumulative) // distribution
2056 PushDouble( GetGammaDist( fX, fAlpha, fBeta));
2057 else // density
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)
2072 PushNoValue();
2073 else
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)
2084 PushNoValue();
2085 else
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();
2098 else
2099 PushDouble(exp(mue+sigma*gaussinv(y)));
2103 class ScGammaDistFunction : public ScDistFunc
2105 ScInterpreter& rInt;
2106 double fp, fAlpha, fBeta;
2108 public:
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 ) )
2120 return;
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();
2127 return;
2129 if (fP == 0.0)
2130 PushInt(0);
2131 else
2133 bool bConvError;
2134 ScGammaDistFunction aFunc( *this, fP, fAlpha, fBeta );
2135 double fStart = fAlpha * fBeta;
2136 double fVal = lcl_IterateInverse( aFunc, fStart*0.5, fStart, bConvError );
2137 if (bConvError)
2138 SetError(errNoConvergence);
2139 PushDouble(fVal);
2143 class ScBetaDistFunction : public ScDistFunc
2145 ScInterpreter& rInt;
2146 double fp, fAlpha, fBeta;
2148 public:
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 ) )
2161 return;
2162 double fP, fA, fB, fAlpha, fBeta;
2163 if (nParamCount == 5)
2164 fB = GetDouble();
2165 else
2166 fB = 1.0;
2167 if (nParamCount >= 4)
2168 fA = GetDouble();
2169 else
2170 fA = 0.0;
2171 fBeta = GetDouble();
2172 fAlpha = GetDouble();
2173 fP = GetDouble();
2174 if (fP < 0.0 || fP >= 1.0 || fA == fB || fAlpha <= 0.0 || fBeta <= 0.0)
2176 PushIllegalArgument();
2177 return;
2179 if (fP == 0.0)
2180 PushInt(0);
2181 else
2183 bool bConvError;
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 );
2187 if (bConvError)
2188 PushError( errNoConvergence);
2189 else
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;
2201 double fp, fDF;
2203 public:
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 ) )
2215 return;
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();
2221 return;
2223 PushDouble( GetTInv( fP, fDF ) );
2226 double ScInterpreter::GetTInv( double fAlpha, double fSize )
2228 bool bConvError;
2229 ScTDistFunction aFunc( *this, fAlpha, fSize );
2230 double fVal = lcl_IterateInverse( aFunc, fSize * 0.5, fSize, bConvError );
2231 if (bConvError)
2232 SetError(errNoConvergence);
2233 return( fVal );
2236 class ScFDistFunction : public ScDistFunc
2238 ScInterpreter& rInt;
2239 double fp, fF1, fF2;
2241 public:
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 ) )
2253 return;
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();
2260 return;
2263 bool bConvError;
2264 ScFDistFunction aFunc( *this, fP, fF1, fF2 );
2265 double fVal = lcl_IterateInverse( aFunc, fF1*0.5, fF1, bConvError );
2266 if (bConvError)
2267 SetError(errNoConvergence);
2268 PushDouble(fVal);
2271 void ScInterpreter::ScFInv_LT()
2273 if ( !MustHaveParamCount( GetByte(), 3 ) )
2274 return;
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();
2281 return;
2284 bool bConvError;
2285 ScFDistFunction aFunc( *this, ( 1.0 - fP ), fF1, fF2 );
2286 double fVal = lcl_IterateInverse( aFunc, fF1*0.5, fF1, bConvError );
2287 if (bConvError)
2288 SetError(errNoConvergence);
2289 PushDouble(fVal);
2292 class ScChiDistFunction : public ScDistFunc
2294 ScInterpreter& rInt;
2295 double fp, fDF;
2297 public:
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 ) )
2309 return;
2310 double fDF = ::rtl::math::approxFloor(GetDouble());
2311 double fP = GetDouble();
2312 if (fDF < 1.0 || fP <= 0.0 || fP > 1.0 )
2314 PushIllegalArgument();
2315 return;
2318 bool bConvError;
2319 ScChiDistFunction aFunc( *this, fP, fDF );
2320 double fVal = lcl_IterateInverse( aFunc, fDF*0.5, fDF, bConvError );
2321 if (bConvError)
2322 SetError(errNoConvergence);
2323 PushDouble(fVal);
2326 /***********************************************/
2327 class ScChiSqDistFunction : public ScDistFunc
2329 ScInterpreter& rInt;
2330 double fp, fDF;
2332 public:
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 ) )
2344 return;
2345 double fDF = ::rtl::math::approxFloor(GetDouble());
2346 double fP = GetDouble();
2347 if (fDF < 1.0 || fP < 0.0 || fP >= 1.0 )
2349 PushIllegalArgument();
2350 return;
2353 bool bConvError;
2354 ScChiSqDistFunction aFunc( *this, fP, fDF );
2355 double fVal = lcl_IterateInverse( aFunc, fDF*0.5, fDF, bConvError );
2356 if (bConvError)
2357 SetError(errNoConvergence);
2358 PushDouble(fVal);
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();
2370 else
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();
2384 else
2385 PushDouble( sigma * GetTInv( alpha, n - 1 ) / sqrt( n ) );
2389 void ScInterpreter::ScZTest()
2391 sal_uInt8 nParamCount = GetByte();
2392 if ( !MustHaveParamCount( nParamCount, 2, 3 ) )
2393 return;
2394 double sigma = 0.0, mue, x;
2395 if (nParamCount == 3)
2397 sigma = GetDouble();
2398 if (sigma <= 0.0)
2400 PushIllegalArgument();
2401 return;
2404 x = GetDouble();
2406 double fSum = 0.0;
2407 double fSumSqr = 0.0;
2408 double fVal;
2409 double rValCount = 0.0;
2410 switch (GetStackType())
2412 case formula::svDouble :
2414 fVal = GetDouble();
2415 fSum += fVal;
2416 fSumSqr += fVal*fVal;
2417 rValCount++;
2419 break;
2420 case svSingleRef :
2422 ScAddress aAdr;
2423 PopSingleRef( aAdr );
2424 ScRefCellValue aCell;
2425 aCell.assign(*pDok, aAdr);
2426 if (aCell.hasNumeric())
2428 fVal = GetCellValue(aAdr, aCell);
2429 fSum += fVal;
2430 fSumSqr += fVal*fVal;
2431 rValCount++;
2434 break;
2435 case svRefList :
2436 case formula::svDoubleRef :
2438 short nParam = 1;
2439 size_t nRefInList = 0;
2440 while (nParam-- > 0)
2442 ScRange aRange;
2443 sal_uInt16 nErr = 0;
2444 PopDoubleRef( aRange, nParam, nRefInList);
2445 ScValueIterator aValIter(pDok, aRange, glSubTotal);
2446 if (aValIter.GetFirst(fVal, nErr))
2448 fSum += fVal;
2449 fSumSqr += fVal*fVal;
2450 rValCount++;
2451 while ((nErr == 0) && aValIter.GetNext(fVal, nErr))
2453 fSum += fVal;
2454 fSumSqr += fVal*fVal;
2455 rValCount++;
2457 SetError(nErr);
2461 break;
2462 case svMatrix :
2463 case svExternalSingleRef:
2464 case svExternalDoubleRef:
2466 ScMatrixRef pMat = GetMatrix();
2467 if (pMat)
2469 SCSIZE nCount = pMat->GetElementCount();
2470 if (pMat->IsNumeric())
2472 for ( SCSIZE i = 0; i < nCount; i++ )
2474 fVal= pMat->GetDouble(i);
2475 fSum += fVal;
2476 fSumSqr += fVal * fVal;
2477 rValCount++;
2480 else
2482 for (SCSIZE i = 0; i < nCount; i++)
2483 if (!pMat->IsString(i))
2485 fVal= pMat->GetDouble(i);
2486 fSum += fVal;
2487 fSumSqr += fVal * fVal;
2488 rValCount++;
2493 break;
2494 default : SetError(errIllegalParameter); break;
2496 if (rValCount <= 1.0)
2497 PushError( errDivisionByZero);
2498 else
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)));
2506 else
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;
2517 double fSum1 = 0.0;
2518 double fSumSqr1 = 0.0;
2519 double fSum2 = 0.0;
2520 double fSumSqr2 = 0.0;
2521 double fVal;
2522 SCSIZE i,j;
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);
2529 fSum1 += fVal;
2530 fSumSqr1 += fVal * fVal;
2531 fCount1++;
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);
2540 fSum2 += fVal;
2541 fSumSqr2 += fVal * fVal;
2542 fCount2++;
2545 if (fCount1 < 2.0 || fCount2 < 2.0)
2547 PushNoValue();
2548 return false;
2549 } // if (fCount1 < 2.0 || fCount2 < 2.0)
2550 if ( _bTemplin )
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)
2556 PushNoValue();
2557 return false;
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));
2565 else
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;
2575 return true;
2577 void ScInterpreter::ScTTest()
2579 if ( !MustHaveParamCount( GetByte(), 4 ) )
2580 return;
2581 double fTyp = ::rtl::math::approxFloor(GetDouble());
2582 double fAnz = ::rtl::math::approxFloor(GetDouble());
2583 if (fAnz != 1.0 && fAnz != 2.0)
2585 PushIllegalArgument();
2586 return;
2589 ScMatrixRef pMat2 = GetMatrix();
2590 ScMatrixRef pMat1 = GetMatrix();
2591 if (!pMat1 || !pMat2)
2593 PushIllegalParameter();
2594 return;
2596 double fT, fF;
2597 SCSIZE nC1, nC2;
2598 SCSIZE nR1, nR2;
2599 SCSIZE i, j;
2600 pMat1->GetDimensions(nC1, nR1);
2601 pMat2->GetDimensions(nC2, nR2);
2602 if (fTyp == 1.0)
2604 if (nC1 != nC2 || nR1 != nR2)
2606 PushIllegalArgument();
2607 return;
2609 double fCount = 0.0;
2610 double fSum1 = 0.0;
2611 double fSum2 = 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);
2621 fSum1 += fVal1;
2622 fSum2 += fVal2;
2623 fSumSqrD += (fVal1 - fVal2)*(fVal1 - fVal2);
2624 fCount++;
2627 if (fCount < 1.0)
2629 PushNoValue();
2630 return;
2632 fT = sqrt(fCount-1.0) * fabs(fSum1 - fSum2) /
2633 sqrt(fCount * fSumSqrD - (fSum1-fSum2)*(fSum1-fSum2));
2634 fF = fCount - 1.0;
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);
2645 else
2647 PushIllegalArgument();
2648 return;
2650 if (fAnz == 1.0)
2651 PushDouble(GetTDist(fT, fF));
2652 else
2653 PushDouble(2.0*GetTDist(fT, fF));
2656 void ScInterpreter::ScFTest()
2658 if ( !MustHaveParamCount( GetByte(), 2 ) )
2659 return;
2660 ScMatrixRef pMat2 = GetMatrix();
2661 ScMatrixRef pMat1 = GetMatrix();
2662 if (!pMat1 || !pMat2)
2664 PushIllegalParameter();
2665 return;
2667 SCSIZE nC1, nC2;
2668 SCSIZE nR1, nR2;
2669 SCSIZE i, j;
2670 pMat1->GetDimensions(nC1, nR1);
2671 pMat2->GetDimensions(nC2, nR2);
2672 double fCount1 = 0.0;
2673 double fCount2 = 0.0;
2674 double fSum1 = 0.0;
2675 double fSumSqr1 = 0.0;
2676 double fSum2 = 0.0;
2677 double fSumSqr2 = 0.0;
2678 double fVal;
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);
2685 fSum1 += fVal;
2686 fSumSqr1 += fVal * fVal;
2687 fCount1++;
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);
2696 fSum2 += fVal;
2697 fSumSqr2 += fVal * fVal;
2698 fCount2++;
2701 if (fCount1 < 2.0 || fCount2 < 2.0)
2703 PushNoValue();
2704 return;
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)
2710 PushNoValue();
2711 return;
2713 double fF, fF1, fF2;
2714 if (fS1 > fS2)
2716 fF = fS1/fS2;
2717 fF1 = fCount1-1.0;
2718 fF2 = fCount2-1.0;
2720 else
2722 fF = fS2/fS1;
2723 fF1 = fCount2-1.0;
2724 fF2 = fCount1-1.0;
2726 PushDouble(2.0*GetFDist(fF, fF1, fF2));
2729 void ScInterpreter::ScChiTest()
2731 if ( !MustHaveParamCount( GetByte(), 2 ) )
2732 return;
2733 ScMatrixRef pMat2 = GetMatrix();
2734 ScMatrixRef pMat1 = GetMatrix();
2735 if (!pMat1 || !pMat2)
2737 PushIllegalParameter();
2738 return;
2740 SCSIZE nC1, nC2;
2741 SCSIZE nR1, nR2;
2742 pMat1->GetDimensions(nC1, nR1);
2743 pMat2->GetDimensions(nC2, nR2);
2744 if (nR1 != nR2 || nC1 != nC2)
2746 PushIllegalArgument();
2747 return;
2749 double fChi = 0.0;
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;
2760 else
2762 PushIllegalArgument();
2763 return;
2767 double fDF;
2768 if (nC1 == 1 || nR1 == 1)
2770 fDF = (double)(nC1*nR1 - 1);
2771 if (fDF == 0.0)
2773 PushNoValue();
2774 return;
2777 else
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) )
2787 return;
2789 if (fCount == 0.0)
2791 PushError( errDivisionByZero);
2792 return;
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));
2801 double dx = 0.0;
2802 double xpower4 = 0.0;
2804 if (fStdDev == 0.0)
2806 PushError( errDivisionByZero);
2807 return;
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();
2826 double nVal = 0.0;
2827 double nValCount = 0.0;
2828 ScAddress aAdr;
2829 ScRange aRange;
2830 size_t nRefInList = 0;
2831 while ((nGlobalError == 0) && (nParamCount-- > 0))
2833 switch (GetStackType())
2835 case formula::svDouble :
2837 double x = GetDouble();
2838 if (x > 0.0)
2840 nVal += 1.0/x;
2841 nValCount++;
2843 else
2844 SetError( errIllegalArgument);
2845 break;
2847 case svSingleRef :
2849 PopSingleRef( aAdr );
2850 ScRefCellValue aCell;
2851 aCell.assign(*pDok, aAdr);
2852 if (aCell.hasNumeric())
2854 double x = GetCellValue(aAdr, aCell);
2855 if (x > 0.0)
2857 nVal += 1.0/x;
2858 nValCount++;
2860 else
2861 SetError( errIllegalArgument);
2863 break;
2865 case formula::svDoubleRef :
2866 case svRefList :
2868 sal_uInt16 nErr = 0;
2869 PopDoubleRef( aRange, nParamCount, nRefInList);
2870 double nCellVal;
2871 ScValueIterator aValIter(pDok, aRange, glSubTotal);
2872 if (aValIter.GetFirst(nCellVal, nErr))
2874 if (nCellVal > 0.0)
2876 nVal += 1.0/nCellVal;
2877 nValCount++;
2879 else
2880 SetError( errIllegalArgument);
2881 SetError(nErr);
2882 while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
2884 if (nCellVal > 0.0)
2886 nVal += 1.0/nCellVal;
2887 nValCount++;
2889 else
2890 SetError( errIllegalArgument);
2892 SetError(nErr);
2895 break;
2896 case svMatrix :
2897 case svExternalSingleRef:
2898 case svExternalDoubleRef:
2900 ScMatrixRef pMat = GetMatrix();
2901 if (pMat)
2903 SCSIZE nCount = pMat->GetElementCount();
2904 if (pMat->IsNumeric())
2906 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
2908 double x = pMat->GetDouble(nElem);
2909 if (x > 0.0)
2911 nVal += 1.0/x;
2912 nValCount++;
2914 else
2915 SetError( errIllegalArgument);
2918 else
2920 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
2921 if (!pMat->IsString(nElem))
2923 double x = pMat->GetDouble(nElem);
2924 if (x > 0.0)
2926 nVal += 1.0/x;
2927 nValCount++;
2929 else
2930 SetError( errIllegalArgument);
2935 break;
2936 default : SetError(errIllegalParameter); break;
2939 if (nGlobalError == 0)
2940 PushDouble((double)nValCount/nVal);
2941 else
2942 PushError( nGlobalError);
2945 void ScInterpreter::ScGeoMean()
2947 short nParamCount = GetByte();
2948 double nVal = 0.0;
2949 double nValCount = 0.0;
2950 ScAddress aAdr;
2951 ScRange aRange;
2953 size_t nRefInList = 0;
2954 while ((nGlobalError == 0) && (nParamCount-- > 0))
2956 switch (GetStackType())
2958 case formula::svDouble :
2960 double x = GetDouble();
2961 if (x > 0.0)
2963 nVal += log(x);
2964 nValCount++;
2966 else
2967 SetError( errIllegalArgument);
2968 break;
2970 case svSingleRef :
2972 PopSingleRef( aAdr );
2973 ScRefCellValue aCell;
2974 aCell.assign(*pDok, aAdr);
2975 if (aCell.hasNumeric())
2977 double x = GetCellValue(aAdr, aCell);
2978 if (x > 0.0)
2980 nVal += log(x);
2981 nValCount++;
2983 else
2984 SetError( errIllegalArgument);
2986 break;
2988 case formula::svDoubleRef :
2989 case svRefList :
2991 sal_uInt16 nErr = 0;
2992 PopDoubleRef( aRange, nParamCount, nRefInList);
2993 double nCellVal;
2994 ScValueIterator aValIter(pDok, aRange, glSubTotal);
2995 if (aValIter.GetFirst(nCellVal, nErr))
2997 if (nCellVal > 0.0)
2999 nVal += log(nCellVal);
3000 nValCount++;
3002 else
3003 SetError( errIllegalArgument);
3004 SetError(nErr);
3005 while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
3007 if (nCellVal > 0.0)
3009 nVal += log(nCellVal);
3010 nValCount++;
3012 else
3013 SetError( errIllegalArgument);
3015 SetError(nErr);
3018 break;
3019 case svMatrix :
3020 case svExternalSingleRef:
3021 case svExternalDoubleRef:
3023 ScMatrixRef pMat = GetMatrix();
3024 if (pMat)
3026 SCSIZE nCount = pMat->GetElementCount();
3027 if (pMat->IsNumeric())
3029 for (SCSIZE ui = 0; ui < nCount; ui++)
3031 double x = pMat->GetDouble(ui);
3032 if (x > 0.0)
3034 nVal += log(x);
3035 nValCount++;
3037 else
3038 SetError( errIllegalArgument);
3041 else
3043 for (SCSIZE ui = 0; ui < nCount; ui++)
3044 if (!pMat->IsString(ui))
3046 double x = pMat->GetDouble(ui);
3047 if (x > 0.0)
3049 nVal += log(x);
3050 nValCount++;
3052 else
3053 SetError( errIllegalArgument);
3058 break;
3059 default : SetError(errIllegalParameter); break;
3062 if (nGlobalError == 0)
3063 PushDouble(exp(nVal / nValCount));
3064 else
3065 PushError( nGlobalError);
3068 void ScInterpreter::ScStandard()
3070 if ( MustHaveParamCount( GetByte(), 3 ) )
3072 double sigma = GetDouble();
3073 double mue = GetDouble();
3074 double x = GetDouble();
3075 if (sigma < 0.0)
3076 PushError( errIllegalArgument);
3077 else if (sigma == 0.0)
3078 PushError( errDivisionByZero);
3079 else
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 ) )
3087 return false;
3089 fSum = 0.0;
3090 fCount = 0.0;
3091 vSum = 0.0;
3092 double fVal = 0.0;
3093 ScAddress aAdr;
3094 ScRange aRange;
3095 size_t nRefInList = 0;
3096 while (nParamCount-- > 0)
3098 switch (GetStackType())
3100 case formula::svDouble :
3102 fVal = GetDouble();
3103 fSum += fVal;
3104 values.push_back(fVal);
3105 fCount++;
3107 break;
3108 case svSingleRef :
3110 PopSingleRef( aAdr );
3111 ScRefCellValue aCell;
3112 aCell.assign(*pDok, aAdr);
3113 if (aCell.hasNumeric())
3115 fVal = GetCellValue(aAdr, aCell);
3116 fSum += fVal;
3117 values.push_back(fVal);
3118 fCount++;
3121 break;
3122 case formula::svDoubleRef :
3123 case svRefList :
3125 PopDoubleRef( aRange, nParamCount, nRefInList);
3126 sal_uInt16 nErr = 0;
3127 ScValueIterator aValIter(pDok, aRange);
3128 if (aValIter.GetFirst(fVal, nErr))
3130 fSum += fVal;
3131 values.push_back(fVal);
3132 fCount++;
3133 SetError(nErr);
3134 while ((nErr == 0) && aValIter.GetNext(fVal, nErr))
3136 fSum += fVal;
3137 values.push_back(fVal);
3138 fCount++;
3140 SetError(nErr);
3143 break;
3144 case svMatrix :
3145 case svExternalSingleRef:
3146 case svExternalDoubleRef:
3148 ScMatrixRef pMat = GetMatrix();
3149 if (pMat)
3151 SCSIZE nCount = pMat->GetElementCount();
3152 if (pMat->IsNumeric())
3154 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3156 fVal = pMat->GetDouble(nElem);
3157 fSum += fVal;
3158 values.push_back(fVal);
3159 fCount++;
3162 else
3164 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3165 if (!pMat->IsString(nElem))
3167 fVal = pMat->GetDouble(nElem);
3168 fSum += fVal;
3169 values.push_back(fVal);
3170 fCount++;
3175 break;
3176 default :
3177 SetError(errIllegalParameter);
3178 break;
3182 if (nGlobalError)
3184 PushError( nGlobalError);
3185 return false;
3186 } // if (nGlobalError)
3187 return true;
3190 void ScInterpreter::CalculateSkewOrSkewp( bool bSkewp )
3192 double fSum, fCount, vSum;
3193 std::vector<double> values;
3194 if (!CalculateSkew( fSum, fCount, vSum, values))
3195 return;
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)));
3203 double dx = 0.0;
3204 double xcube = 0.0;
3206 if (fStdDev == 0)
3208 PushIllegalArgument();
3209 return;
3212 for (size_t i = 0; i < values.size(); ++i)
3214 dx = (values[i] - fMean) / fStdDev;
3215 xcube = xcube + (dx * dx * dx);
3218 if (bSkewp)
3219 PushDouble( xcube / fCount );
3220 else
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);
3240 return 0.0;
3243 // Upper median.
3244 size_t nMid = nSize / 2;
3245 vector<double>::iterator iMid = rArray.begin() + nMid;
3246 ::std::nth_element( rArray.begin(), iMid, rArray.end());
3247 if (nSize & 1)
3248 return *iMid; // Lower and upper median are equal.
3249 else
3251 double fUp = *iMid;
3252 // Lower median.
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 ) )
3263 return;
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);
3275 return 0.0;
3278 if (nSize == 1)
3279 return rArray[0];
3280 else
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());
3287 if (fDiff == 0.0)
3288 return *iter;
3289 else
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 ) )
3303 return;
3304 double alpha = GetDouble();
3305 if (alpha < 0.0 || alpha > 1.0)
3307 PushIllegalArgument();
3308 return;
3310 vector<double> aArray;
3311 GetNumberSequenceArray( 1, aArray);
3312 PushDouble( GetPercentile( aArray, alpha));
3315 void ScInterpreter::ScQuartile()
3317 if ( !MustHaveParamCount( GetByte(), 2 ) )
3318 return;
3319 double fFlag = ::rtl::math::approxFloor(GetDouble());
3320 if (fFlag < 0.0 || fFlag > 4.0)
3322 PushIllegalArgument();
3323 return;
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 ) )
3334 return;
3335 vector<double> aSortArray;
3336 GetSortArray(nParamCount, aSortArray);
3337 SCSIZE nSize = aSortArray.size();
3338 if (aSortArray.empty() || nSize == 0 || nGlobalError)
3339 PushNoValue();
3340 else
3342 SCSIZE nMaxIndex = 0, nMax = 1, nCount = 1;
3343 double nOldVal = aSortArray[0];
3344 SCSIZE i;
3346 for ( i = 1; i < nSize; i++)
3348 if (aSortArray[i] == nOldVal)
3349 nCount++;
3350 else
3352 nOldVal = aSortArray[i];
3353 if (nCount > nMax)
3355 nMax = nCount;
3356 nMaxIndex = i-1;
3358 nCount = 1;
3361 if (nCount > nMax)
3363 nMax = nCount;
3364 nMaxIndex = i-1;
3366 if (nMax == 1 && nCount == 1)
3367 PushNoValue();
3368 else if (nMax == 1)
3369 PushDouble(nOldVal);
3370 else
3371 PushDouble(aSortArray[nMaxIndex]);
3375 void ScInterpreter::CalculateSmallLarge(bool bSmall)
3377 if ( !MustHaveParamCount( GetByte(), 2 ) )
3378 return;
3379 double f = ::rtl::math::approxFloor(GetDouble());
3380 if (f < 1.0)
3382 PushIllegalArgument();
3383 return;
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)
3394 PushNoValue();
3395 else
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());
3400 PushDouble( *iPos);
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 ) )
3418 return;
3420 double fNum = GetDouble();
3421 vector<double> aSortArray;
3422 GetSortArray(1, aSortArray);
3423 SCSIZE nSize = aSortArray.size();
3424 if (aSortArray.empty() || nSize == 0 || nGlobalError)
3425 PushNoValue();
3426 else
3428 if (fNum < aSortArray[0] || fNum > aSortArray[nSize-1])
3429 PushNoValue();
3430 else if ( nSize == 1 )
3431 PushDouble(1.0); // fNum == pSortArray[0], see test above
3432 else
3434 double fRes;
3435 SCSIZE nOldCount = 0;
3436 double fOldVal = aSortArray[0];
3437 SCSIZE i;
3438 for (i = 1; i < nSize && aSortArray[i] < fNum; i++)
3440 if (aSortArray[i] != fOldVal)
3442 nOldCount = i;
3443 fOldVal = aSortArray[i];
3446 if (aSortArray[i] != fOldVal)
3447 nOldCount = i;
3448 if (fNum == aSortArray[i])
3449 fRes = (double)nOldCount/(double)(nSize-1);
3450 else
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");
3459 fRes = 0.0;
3461 else
3463 double fFract = ( fNum - aSortArray[nOldCount-1] ) /
3464 ( aSortArray[nOldCount] - aSortArray[nOldCount-1] );
3465 fRes = ( (double)(nOldCount-1)+fFract )/(double)(nSize-1);
3468 PushDouble(fRes);
3473 void ScInterpreter::ScTrimMean()
3475 if ( !MustHaveParamCount( GetByte(), 2 ) )
3476 return;
3477 double alpha = GetDouble();
3478 if (alpha < 0.0 || alpha >= 1.0)
3480 PushIllegalArgument();
3481 return;
3483 vector<double> aSortArray;
3484 GetSortArray(1, aSortArray);
3485 SCSIZE nSize = aSortArray.size();
3486 if (aSortArray.empty() || nSize == 0 || nGlobalError)
3487 PushNoValue();
3488 else
3490 sal_uLong nIndex = (sal_uLong) ::rtl::math::approxFloor(alpha*(double)nSize);
3491 if (nIndex % 2 != 0)
3492 nIndex--;
3493 nIndex /= 2;
3494 OSL_ENSURE(nIndex < nSize, "ScTrimMean: falscher Index");
3495 double fSum = 0.0;
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 )
3504 ScAddress aAdr;
3505 ScRange aRange;
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());
3514 break;
3515 case svSingleRef :
3517 PopSingleRef( aAdr );
3518 ScRefCellValue aCell;
3519 aCell.assign(*pDok, aAdr);
3520 if (aCell.hasNumeric())
3521 rArray.push_back(GetCellValue(aAdr, aCell));
3523 break;
3524 case formula::svDoubleRef :
3525 case svRefList :
3527 PopDoubleRef( aRange, nParam, nRefInList);
3528 if (nGlobalError)
3529 break;
3531 aRange.Justify();
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;
3537 double fCellVal;
3538 ScValueIterator aValIter(pDok, aRange);
3539 if (aValIter.GetFirst( fCellVal, nErr))
3541 rArray.push_back( fCellVal);
3542 SetError(nErr);
3543 while ((nErr == 0) && aValIter.GetNext( fCellVal, nErr))
3544 rArray.push_back( fCellVal);
3545 SetError(nErr);
3548 break;
3549 case svMatrix :
3550 case svExternalSingleRef:
3551 case svExternalDoubleRef:
3553 ScMatrixRef pMat = GetMatrix();
3554 if (!pMat)
3555 break;
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));
3564 else
3566 for (SCSIZE i = 0; i < nCount; ++i)
3567 if (!pMat->IsString(i))
3568 rArray.push_back( pMat->GetDouble(i));
3571 break;
3572 default :
3573 PopError();
3574 SetError( errIllegalParameter);
3575 break;
3577 if (nGlobalError)
3578 break; // while
3580 // nParam > 0 in case of error, clean stack environment and obtain earlier
3581 // error if there was one.
3582 while (nParam-- > 0)
3583 PopError();
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().
3603 using ::std::swap;
3605 if (nHi - nLo == 1)
3607 if (rSortArray[nLo] > rSortArray[nHi])
3609 swap(rSortArray[nLo], rSortArray[nHi]);
3610 if (pIndexOrder)
3611 swap(pIndexOrder->at(nLo), pIndexOrder->at(nHi));
3613 return;
3616 long ni = nLo;
3617 long nj = nHi;
3620 double fLo = rSortArray[nLo];
3621 while (ni <= nHi && rSortArray[ni] < fLo) ni++;
3622 while (nj >= nLo && fLo < rSortArray[nj]) nj--;
3623 if (ni <= nj)
3625 if (ni != nj)
3627 swap(rSortArray[ni], rSortArray[nj]);
3628 if (pIndexOrder)
3629 swap(pIndexOrder->at(ni), pIndexOrder->at(nj));
3632 ++ni;
3633 --nj;
3636 while (ni < 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);
3643 else
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());
3654 if (pIndexOrder)
3656 pIndexOrder->clear();
3657 pIndexOrder->reserve(n);
3658 for (long i = 0; i < n; ++i)
3659 pIndexOrder->push_back(i);
3662 if (n < 2)
3663 return;
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]);
3670 if (pIndexOrder)
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 ) )
3681 return;
3682 bool bDescending;
3683 if (nParamCount == 3)
3684 bDescending = GetBool();
3685 else
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();
3695 if (x == fVal)
3696 bValid = true;
3697 break;
3699 case svSingleRef :
3701 ScAddress aAdr;
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);
3709 if (x == fVal)
3710 bValid = true;
3712 break;
3714 case formula::svDoubleRef :
3715 case svRefList :
3717 ScRange aRange;
3718 short nParam = 1;
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);
3726 if (nParam)
3727 --sp; // simulate pop
3728 double fVal = GetDouble();
3729 if (nParam)
3730 sp = nSaveSP;
3731 double nCellVal;
3732 ScValueIterator aValIter(pDok, aRange, glSubTotal);
3733 if (aValIter.GetFirst(nCellVal, nErr))
3735 if (nCellVal == fVal)
3736 bValid = true;
3737 else if ((!bDescending && nCellVal > fVal) ||
3738 (bDescending && nCellVal < fVal) )
3739 fCount++;
3740 SetError(nErr);
3741 while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
3743 if (nCellVal == fVal)
3744 bValid = true;
3745 else if ((!bDescending && nCellVal > fVal) ||
3746 (bDescending && nCellVal < fVal) )
3747 fCount++;
3750 SetError(nErr);
3753 break;
3754 case svMatrix :
3755 case svExternalSingleRef:
3756 case svExternalDoubleRef:
3758 ScMatrixRef pMat = GetMatrix();
3759 double fVal = GetDouble();
3760 if (pMat)
3762 SCSIZE nCount = pMat->GetElementCount();
3763 if (pMat->IsNumeric())
3765 for (SCSIZE i = 0; i < nCount; i++)
3767 double x = pMat->GetDouble(i);
3768 if (x == fVal)
3769 bValid = true;
3770 else if ((!bDescending && x > fVal) ||
3771 (bDescending && x < fVal) )
3772 fCount++;
3775 else
3777 for (SCSIZE i = 0; i < nCount; i++)
3778 if (!pMat->IsString(i))
3780 double x = pMat->GetDouble(i);
3781 if (x == fVal)
3782 bValid = true;
3783 else if ((!bDescending && x > fVal) ||
3784 (bDescending && x < fVal) )
3785 fCount++;
3790 break;
3791 default : SetError(errIllegalParameter); break;
3793 if (bValid)
3794 PushDouble(fCount);
3795 else
3796 PushNoValue();
3799 void ScInterpreter::ScAveDev()
3801 sal_uInt8 nParamCount = GetByte();
3802 if ( !MustHaveParamCountMin( nParamCount, 1 ) )
3803 return;
3804 sal_uInt16 SaveSP = sp;
3805 double nMiddle = 0.0;
3806 double rVal = 0.0;
3807 double rValCount = 0.0;
3808 ScAddress aAdr;
3809 ScRange aRange;
3810 short nParam = nParamCount;
3811 size_t nRefInList = 0;
3812 while (nParam-- > 0)
3814 switch (GetStackType())
3816 case formula::svDouble :
3817 rVal += GetDouble();
3818 rValCount++;
3819 break;
3820 case svSingleRef :
3822 PopSingleRef( aAdr );
3823 ScRefCellValue aCell;
3824 aCell.assign(*pDok, aAdr);
3825 if (aCell.hasNumeric())
3827 rVal += GetCellValue(aAdr, aCell);
3828 rValCount++;
3831 break;
3832 case formula::svDoubleRef :
3833 case svRefList :
3835 sal_uInt16 nErr = 0;
3836 double nCellVal;
3837 PopDoubleRef( aRange, nParam, nRefInList);
3838 ScValueIterator aValIter(pDok, aRange);
3839 if (aValIter.GetFirst(nCellVal, nErr))
3841 rVal += nCellVal;
3842 rValCount++;
3843 SetError(nErr);
3844 while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
3846 rVal += nCellVal;
3847 rValCount++;
3849 SetError(nErr);
3852 break;
3853 case svMatrix :
3854 case svExternalSingleRef:
3855 case svExternalDoubleRef:
3857 ScMatrixRef pMat = GetMatrix();
3858 if (pMat)
3860 SCSIZE nCount = pMat->GetElementCount();
3861 if (pMat->IsNumeric())
3863 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3865 rVal += pMat->GetDouble(nElem);
3866 rValCount++;
3869 else
3871 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3872 if (!pMat->IsString(nElem))
3874 rVal += pMat->GetDouble(nElem);
3875 rValCount++;
3880 break;
3881 default :
3882 SetError(errIllegalParameter);
3883 break;
3886 if (nGlobalError)
3888 PushError( nGlobalError);
3889 return;
3891 nMiddle = rVal / rValCount;
3892 sp = SaveSP;
3893 rVal = 0.0;
3894 nParam = nParamCount;
3895 nRefInList = 0;
3896 while (nParam-- > 0)
3898 switch (GetStackType())
3900 case formula::svDouble :
3901 rVal += fabs(GetDouble() - nMiddle);
3902 break;
3903 case svSingleRef :
3905 PopSingleRef( aAdr );
3906 ScRefCellValue aCell;
3907 aCell.assign(*pDok, aAdr);
3908 if (aCell.hasNumeric())
3909 rVal += fabs(GetCellValue(aAdr, aCell) - nMiddle);
3911 break;
3912 case formula::svDoubleRef :
3913 case svRefList :
3915 sal_uInt16 nErr = 0;
3916 double nCellVal;
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);
3926 break;
3927 case svMatrix :
3928 case svExternalSingleRef:
3929 case svExternalDoubleRef:
3931 ScMatrixRef pMat = GetMatrix();
3932 if (pMat)
3934 SCSIZE nCount = pMat->GetElementCount();
3935 if (pMat->IsNumeric())
3937 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3939 rVal += fabs(pMat->GetDouble(nElem) - nMiddle);
3942 else
3944 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3946 if (!pMat->IsString(nElem))
3947 rVal += fabs(pMat->GetDouble(nElem) - nMiddle);
3952 break;
3953 default : SetError(errIllegalParameter); break;
3956 PushDouble(rVal / rValCount);
3959 void ScInterpreter::ScDevSq()
3961 double nVal;
3962 double nValCount;
3963 GetStVarParams(nVal, nValCount);
3964 PushDouble(nVal);
3967 void ScInterpreter::ScProbability()
3969 sal_uInt8 nParamCount = GetByte();
3970 if ( !MustHaveParamCount( nParamCount, 3, 4 ) )
3971 return;
3972 double fUp, fLo;
3973 fUp = GetDouble();
3974 if (nParamCount == 4)
3975 fLo = GetDouble();
3976 else
3977 fLo = fUp;
3978 if (fLo > fUp)
3980 double fTemp = fLo;
3981 fLo = fUp;
3982 fUp = fTemp;
3984 ScMatrixRef pMatP = GetMatrix();
3985 ScMatrixRef pMatW = GetMatrix();
3986 if (!pMatP || !pMatW)
3987 PushIllegalParameter();
3988 else
3990 SCSIZE nC1, nC2;
3991 SCSIZE nR1, nR2;
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)
3996 PushNA();
3997 else
3999 double fSum = 0.0;
4000 double fRes = 0.0;
4001 bool bStop = false;
4002 double fP, fW;
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)
4012 bStop = true;
4013 else
4015 fSum += fP;
4016 if (fW >= fLo && fW <= fUp)
4017 fRes += fP;
4020 else
4021 SetError( errIllegalArgument);
4024 if (bStop || fabs(fSum -1.0) > 1.0E-7)
4025 PushNoValue();
4026 else
4027 PushDouble(fRes);
4032 void ScInterpreter::ScCorrel()
4034 // This is identical to ScPearson()
4035 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 ) )
4056 return;
4057 ScMatrixRef pMat1 = GetMatrix();
4058 ScMatrixRef pMat2 = GetMatrix();
4059 if (!pMat1 || !pMat2)
4061 PushIllegalParameter();
4062 return;
4064 SCSIZE nC1, nC2;
4065 SCSIZE nR1, nR2;
4066 pMat1->GetDimensions(nC1, nR1);
4067 pMat2->GetDimensions(nC2, nR2);
4068 if (nR1 != nR2 || nC1 != nC2)
4070 PushIllegalArgument();
4071 return;
4073 /* #i78250#
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;
4079 double fSumX = 0.0;
4080 double fSumY = 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);
4092 fSumX += fValX;
4093 fSumY += fValY;
4094 fCount++;
4098 if (fCount < (_bStexy ? 3.0 : (_bSample ? 2.0 : 1.0)))
4099 PushNoValue();
4100 else
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);
4113 if ( _bPearson )
4115 fSumSqrDeltaX += (fValX - fMeanX) * (fValX - fMeanX);
4116 fSumSqrDeltaY += (fValY - fMeanY) * (fValY - fMeanY);
4121 if ( _bPearson )
4123 if (fSumSqrDeltaX == 0.0 || ( !_bStexy && fSumSqrDeltaY == 0.0) )
4124 PushError( errDivisionByZero);
4125 else if ( _bStexy )
4126 PushDouble( sqrt( (fSumSqrDeltaY - fSumDeltaXDeltaY *
4127 fSumDeltaXDeltaY / fSumSqrDeltaX) / (fCount-2)));
4128 else
4129 PushDouble( fSumDeltaXDeltaY / sqrt( fSumSqrDeltaX * fSumSqrDeltaY));
4131 else
4133 if ( _bSample )
4134 PushDouble( fSumDeltaXDeltaY / ( fCount - 1 ) );
4135 else
4136 PushDouble( fSumDeltaXDeltaY / fCount);
4141 void ScInterpreter::ScRSQ()
4143 // Same as ScPearson()*ScPearson()
4144 ScPearson();
4145 if (!nGlobalError)
4147 switch (GetStackType())
4149 case formula::svDouble:
4151 double fVal = PopDouble();
4152 PushDouble( fVal * fVal);
4154 break;
4155 default:
4156 PopError();
4157 PushNoValue();
4162 void ScInterpreter::ScSTEXY()
4164 CalculatePearsonCovar( true, true, false );
4166 void ScInterpreter::CalculateSlopeIntercept(bool bSlope)
4168 if ( !MustHaveParamCount( GetByte(), 2 ) )
4169 return;
4170 ScMatrixRef pMat1 = GetMatrix();
4171 ScMatrixRef pMat2 = GetMatrix();
4172 if (!pMat1 || !pMat2)
4174 PushIllegalParameter();
4175 return;
4177 SCSIZE nC1, nC2;
4178 SCSIZE nR1, nR2;
4179 pMat1->GetDimensions(nC1, nR1);
4180 pMat2->GetDimensions(nC2, nR2);
4181 if (nR1 != nR2 || nC1 != nC2)
4183 PushIllegalArgument();
4184 return;
4186 // #i78250# numerical stability improved
4187 double fCount = 0.0;
4188 double fSumX = 0.0;
4189 double fSumY = 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);
4200 fSumX += fValX;
4201 fSumY += fValY;
4202 fCount++;
4206 if (fCount < 1.0)
4207 PushNoValue();
4208 else
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);
4227 else
4229 if ( bSlope )
4230 PushDouble( fSumDeltaXDeltaY / fSumSqrDeltaX);
4231 else
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 ) )
4250 return;
4251 ScMatrixRef pMat1 = GetMatrix();
4252 ScMatrixRef pMat2 = GetMatrix();
4253 if (!pMat1 || !pMat2)
4255 PushIllegalParameter();
4256 return;
4258 SCSIZE nC1, nC2;
4259 SCSIZE nR1, nR2;
4260 pMat1->GetDimensions(nC1, nR1);
4261 pMat2->GetDimensions(nC2, nR2);
4262 if (nR1 != nR2 || nC1 != nC2)
4264 PushIllegalArgument();
4265 return;
4267 double fVal = GetDouble();
4268 // #i78250# numerical stability improved
4269 double fCount = 0.0;
4270 double fSumX = 0.0;
4271 double fSumY = 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);
4282 fSumX += fValX;
4283 fSumY += fValY;
4284 fCount++;
4288 if (fCount < 1.0)
4289 PushNoValue();
4290 else
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);
4309 else
4310 PushDouble( fMeanY + fSumDeltaXDeltaY / fSumSqrDeltaX * (fVal - fMeanX));
4314 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */