Update ooo320-m1
[ooovba.git] / sc / source / core / tool / interpr3.cxx
blob0481c0603a0ce184564503456acbefc86ef72d2e
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: interpr3.cxx,v $
10 * $Revision: 1.25 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 // INCLUDE ---------------------------------------------------------------
36 #include <tools/solar.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <rtl/logfile.hxx>
41 #include "interpre.hxx"
42 #include "global.hxx"
43 #include "compiler.hxx"
44 #include "cell.hxx"
45 #include "document.hxx"
46 #include "dociter.hxx"
47 #include "scmatrix.hxx"
48 #include "globstr.hrc"
50 #include <math.h>
51 #include <vector>
52 #include <algorithm>
54 using ::std::vector;
55 using namespace formula;
57 // STATIC DATA -----------------------------------------------------------
59 #define SCdEpsilon 1.0E-7
60 #define SC_MAX_ITERATION_COUNT 20
61 #define MAX_ANZ_DOUBLE_FOR_SORT 100000
62 // PI jetzt als F_PI aus solar.h
63 //#define PI 3.1415926535897932
65 const double ScInterpreter::fMaxGammaArgument = 171.624376956302; // found experimental
66 const double fMachEps = ::std::numeric_limits<double>::epsilon();
68 //-----------------------------------------------------------------------------
70 class ScDistFunc
72 public:
73 virtual double GetValue(double x) const = 0;
76 // iteration for inverse distributions
78 //template< class T > double lcl_IterateInverse( const T& rFunction, double x0, double x1, bool& rConvError )
80 /** u*w<0.0 fails for values near zero */
81 inline bool lcl_HasChangeOfSign( double u, double w )
83 return (u < 0.0 && w > 0.0) || (u > 0.0 && w < 0.0);
86 double lcl_IterateInverse( const ScDistFunc& rFunction, double fAx, double fBx, bool& rConvError )
88 rConvError = false;
89 const double fYEps = 1.0E-307;
90 const double fXEps = ::std::numeric_limits<double>::epsilon();
92 DBG_ASSERT(fAx<fBx, "IterateInverse: wrong interval");
94 // find enclosing interval
96 double fAy = rFunction.GetValue(fAx);
97 double fBy = rFunction.GetValue(fBx);
98 double fTemp;
99 unsigned short nCount;
100 for (nCount = 0; nCount < 1000 && !lcl_HasChangeOfSign(fAy,fBy); nCount++)
102 if (fabs(fAy) <= fabs(fBy))
104 fTemp = fAx;
105 fAx += 2.0 * (fAx - fBx);
106 if (fAx < 0.0)
107 fAx = 0.0;
108 fBx = fTemp;
109 fBy = fAy;
110 fAy = rFunction.GetValue(fAx);
112 else
114 fTemp = fBx;
115 fBx += 2.0 * (fBx - fAx);
116 fAx = fTemp;
117 fAy = fBy;
118 fBy = rFunction.GetValue(fBx);
122 if (fAy == 0.0)
123 return fAx;
124 if (fBy == 0.0)
125 return fBx;
126 if (!lcl_HasChangeOfSign( fAy, fBy))
128 rConvError = true;
129 return 0.0;
131 // inverse quadric interpolation with additional brackets
132 // set three points
133 double fPx = fAx;
134 double fPy = fAy;
135 double fQx = fBx;
136 double fQy = fBy;
137 double fRx = fAx;
138 double fRy = fAy;
139 double fSx = 0.5 * (fAx + fBx); // potential next point
140 bool bHasToInterpolate = true;
141 nCount = 0;
142 while ( nCount < 500 && fabs(fRy) > fYEps &&
143 (fBx-fAx) > ::std::max( fabs(fAx), fabs(fBx)) * fXEps )
145 if (bHasToInterpolate)
147 if (fPy!=fQy && fQy!=fRy && fRy!=fPy)
149 fSx = fPx * fRy * fQy / (fRy-fPy) / (fQy-fPy)
150 + fRx * fQy * fPy / (fQy-fRy) / (fPy-fRy)
151 + fQx * fPy * fRy / (fPy-fQy) / (fRy-fQy);
152 bHasToInterpolate = (fAx < fSx) && (fSx < fBx); // inside the brackets?
154 else
155 bHasToInterpolate = false;
157 if(!bHasToInterpolate)
159 fSx = 0.5 * (fAx + fBx);
160 // reset points
161 fPx = fAx; fPy = fAy;
162 fQx = fBx; fQy = fBy;
163 bHasToInterpolate = true;
165 // shift points for next interpolation
166 fPx = fQx; fQx = fRx; fRx = fSx;
167 fPy = fQy; fQy = fRy; fRy = rFunction.GetValue(fSx);
168 // update brackets
169 if (lcl_HasChangeOfSign( fAy, fRy))
171 fBx = fRx; fBy = fRy;
173 else
175 fAx = fRx; fAy = fRy;
177 // if last interration brought to small advance, then do bisection next
178 // time, for safety
179 bHasToInterpolate = bHasToInterpolate && (fabs(fRy) * 2.0 <= fabs(fQy));
180 ++nCount;
182 return fRx;
185 //-----------------------------------------------------------------------------
186 // Allgemeine Funktionen
187 //-----------------------------------------------------------------------------
189 void ScInterpreter::ScNoName()
191 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScNoName" );
192 PushError(errNoName);
195 void ScInterpreter::ScBadName()
197 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScBadName" );
198 short nParamCount = GetByte();
199 while (nParamCount-- > 0)
201 PopError();
203 PushError( errNoName);
206 double ScInterpreter::phi(double x)
208 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::phi" );
209 return 0.39894228040143268 * exp(-(x * x) / 2.0);
212 double ScInterpreter::integralPhi(double x)
213 { // Using gauss(x)+0.5 has severe cancellation errors for x<-4
214 return 0.5 * ::rtl::math::erfc(-x * 0.7071067811865475); // * 1/sqrt(2)
217 double ScInterpreter::taylor(double* pPolynom, USHORT nMax, double x)
219 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::taylor" );
220 double nVal = pPolynom[nMax];
221 for (short i = nMax-1; i >= 0; i--)
223 nVal = pPolynom[i] + (nVal * x);
225 return nVal;
228 double ScInterpreter::gauss(double x)
230 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::gauss" );
231 double t0[] =
232 { 0.39894228040143268, -0.06649038006690545, 0.00997355701003582,
233 -0.00118732821548045, 0.00011543468761616, -0.00000944465625950,
234 0.00000066596935163, -0.00000004122667415, 0.00000000227352982,
235 0.00000000011301172, 0.00000000000511243, -0.00000000000021218 };
236 double t2[] =
237 { 0.47724986805182079, 0.05399096651318805, -0.05399096651318805,
238 0.02699548325659403, -0.00449924720943234, -0.00224962360471617,
239 0.00134977416282970, -0.00011783742691370, -0.00011515930357476,
240 0.00003704737285544, 0.00000282690796889, -0.00000354513195524,
241 0.00000037669563126, 0.00000019202407921, -0.00000005226908590,
242 -0.00000000491799345, 0.00000000366377919, -0.00000000015981997,
243 -0.00000000017381238, 0.00000000002624031, 0.00000000000560919,
244 -0.00000000000172127, -0.00000000000008634, 0.00000000000007894 };
245 double t4[] =
246 { 0.49996832875816688, 0.00013383022576489, -0.00026766045152977,
247 0.00033457556441221, -0.00028996548915725, 0.00018178605666397,
248 -0.00008252863922168, 0.00002551802519049, -0.00000391665839292,
249 -0.00000074018205222, 0.00000064422023359, -0.00000017370155340,
250 0.00000000909595465, 0.00000000944943118, -0.00000000329957075,
251 0.00000000029492075, 0.00000000011874477, -0.00000000004420396,
252 0.00000000000361422, 0.00000000000143638, -0.00000000000045848 };
253 double asympt[] = { -1.0, 1.0, -3.0, 15.0, -105.0 };
255 double xAbs = fabs(x);
256 USHORT xShort = (USHORT)::rtl::math::approxFloor(xAbs);
257 double nVal = 0.0;
258 if (xShort == 0)
259 nVal = taylor(t0, 11, (xAbs * xAbs)) * xAbs;
260 else if ((xShort >= 1) && (xShort <= 2))
261 nVal = taylor(t2, 23, (xAbs - 2.0));
262 else if ((xShort >= 3) && (xShort <= 4))
263 nVal = taylor(t4, 20, (xAbs - 4.0));
264 else
265 nVal = 0.5 + phi(xAbs) * taylor(asympt, 4, 1.0 / (xAbs * xAbs)) / xAbs;
266 if (x < 0.0)
267 return -nVal;
268 else
269 return nVal;
273 // #i26836# new gaussinv implementation by Martin Eitzenberger <m.eitzenberger@unix.net>
276 double ScInterpreter::gaussinv(double x)
278 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::gaussinv" );
279 double q,t,z;
281 q=x-0.5;
283 if(fabs(q)<=.425)
285 t=0.180625-q*q;
296 t*2509.0809287301226727+33430.575583588128105
298 *t+67265.770927008700853
300 *t+45921.953931549871457
302 *t+13731.693765509461125
304 *t+1971.5909503065514427
306 *t+133.14166789178437745
308 *t+3.387132872796366608
318 t*5226.495278852854561+28729.085735721942674
320 *t+39307.89580009271061
322 *t+21213.794301586595867
324 *t+5394.1960214247511077
326 *t+687.1870074920579083
328 *t+42.313330701600911252
330 *t+1.0
334 else
336 if(q>0) t=1-x;
337 else t=x;
339 t=sqrt(-log(t));
341 if(t<=5.0)
343 t+=-1.6;
353 t*7.7454501427834140764e-4+0.0227238449892691845833
355 *t+0.24178072517745061177
357 *t+1.27045825245236838258
359 *t+3.64784832476320460504
361 *t+5.7694972214606914055
363 *t+4.6303378461565452959
365 *t+1.42343711074968357734
375 t*1.05075007164441684324e-9+5.475938084995344946e-4
377 *t+0.0151986665636164571966
379 *t+0.14810397642748007459
381 *t+0.68976733498510000455
383 *t+1.6763848301838038494
385 *t+2.05319162663775882187
387 *t+1.0
391 else
393 t+=-5.0;
403 t*2.01033439929228813265e-7+2.71155556874348757815e-5
405 *t+0.0012426609473880784386
407 *t+0.026532189526576123093
409 *t+0.29656057182850489123
411 *t+1.7848265399172913358
413 *t+5.4637849111641143699
415 *t+6.6579046435011037772
425 t*2.04426310338993978564e-15+1.4215117583164458887e-7
427 *t+1.8463183175100546818e-5
429 *t+7.868691311456132591e-4
431 *t+0.0148753612908506148525
433 *t+0.13692988092273580531
435 *t+0.59983220655588793769
437 *t+1.0
442 if(q<0.0) z=-z;
445 return z;
448 double ScInterpreter::Fakultaet(double x)
450 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::Fakultaet" );
451 x = ::rtl::math::approxFloor(x);
452 if (x < 0.0)
453 return 0.0;
454 else if (x == 0.0)
455 return 1.0;
456 else if (x <= 170.0)
458 double fTemp = x;
459 while (fTemp > 2.0)
461 fTemp--;
462 x *= fTemp;
465 else
466 SetError(errNoValue);
467 /* // Stirlingsche Naeherung zu ungenau
468 else
469 x = pow(x/exp(1), x) * sqrt(x) * SQRT_2_PI * (1.0 + 1.0 / (12.0 * x));
471 return x;
474 double ScInterpreter::BinomKoeff(double n, double k)
476 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::BinomKoeff" );
477 double nVal = 0.0;
478 k = ::rtl::math::approxFloor(k);
479 if (n < k)
480 nVal = 0.0;
481 else if (k == 0.0)
482 nVal = 1.0;
483 else
485 nVal = n/k;
486 n--;
487 k--;
488 while (k > 0.0)
490 nVal *= n/k;
491 k--;
492 n--;
495 double f1 = n; // Zaehler
496 double f2 = k; // Nenner
497 n--;
498 k--;
499 while (k > 0.0)
501 f2 *= k;
502 f1 *= n;
503 k--;
504 n--;
506 nVal = f1 / f2;
509 return nVal;
513 // The algorithm is based on lanczos13m53 in lanczos.hpp
514 // in math library from http://www.boost.org
515 /** you must ensure fZ>0
516 Uses a variant of the Lanczos sum with a rational function. */
517 double lcl_getLanczosSum(double fZ)
519 const double fNum[13] ={
520 23531376880.41075968857200767445163675473,
521 42919803642.64909876895789904700198885093,
522 35711959237.35566804944018545154716670596,
523 17921034426.03720969991975575445893111267,
524 6039542586.35202800506429164430729792107,
525 1439720407.311721673663223072794912393972,
526 248874557.8620541565114603864132294232163,
527 31426415.58540019438061423162831820536287,
528 2876370.628935372441225409051620849613599,
529 186056.2653952234950402949897160456992822,
530 8071.672002365816210638002902272250613822,
531 210.8242777515793458725097339207133627117,
532 2.506628274631000270164908177133837338626
534 const double fDenom[13] = {
536 39916800,
537 120543840,
538 150917976,
539 105258076,
540 45995730,
541 13339535,
542 2637558,
543 357423,
544 32670,
545 1925,
549 // Horner scheme
550 double fSumNum;
551 double fSumDenom;
552 int nI;
553 double fZInv;
554 if (fZ<=1.0)
556 fSumNum = fNum[12];
557 fSumDenom = fDenom[12];
558 for (nI = 11; nI >= 0; --nI)
560 fSumNum *= fZ;
561 fSumNum += fNum[nI];
562 fSumDenom *= fZ;
563 fSumDenom += fDenom[nI];
566 else
567 // Cancel down with fZ^12; Horner scheme with reverse coefficients
569 fZInv = 1/fZ;
570 fSumNum = fNum[0];
571 fSumDenom = fDenom[0];
572 for (nI = 1; nI <=12; ++nI)
574 fSumNum *= fZInv;
575 fSumNum += fNum[nI];
576 fSumDenom *= fZInv;
577 fSumDenom += fDenom[nI];
580 return fSumNum/fSumDenom;
583 // The algorithm is based on tgamma in gamma.hpp
584 // in math library from http://www.boost.org
585 /** You must ensure fZ>0; fZ>171.624376956302 will overflow. */
586 double lcl_GetGammaHelper(double fZ)
588 double fGamma = lcl_getLanczosSum(fZ);
589 const double fg = 6.024680040776729583740234375;
590 double fZgHelp = fZ + fg - 0.5;
591 // avoid intermediate overflow
592 double fHalfpower = pow( fZgHelp, fZ / 2 - 0.25);
593 fGamma *= fHalfpower;
594 fGamma /= exp(fZgHelp);
595 fGamma *= fHalfpower;
596 if (fZ <= 20.0 && fZ == ::rtl::math::approxFloor(fZ))
597 fGamma = ::rtl::math::round(fGamma);
598 return fGamma;
601 // The algorithm is based on tgamma in gamma.hpp
602 // in math library from http://www.boost.org
603 /** You must ensure fZ>0 */
604 double lcl_GetLogGammaHelper(double fZ)
606 const double fg = 6.024680040776729583740234375;
607 double fZgHelp = fZ + fg - 0.5;
608 return log( lcl_getLanczosSum(fZ)) + (fZ-0.5) * log(fZgHelp) - fZgHelp;
611 /** You must ensure non integer arguments for fZ<1 */
612 double ScInterpreter::GetGamma(double fZ)
614 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetGamma" );
615 const double fLogPi = log(F_PI);
616 const double fLogDblMax = log( ::std::numeric_limits<double>::max());
618 if (fZ > fMaxGammaArgument)
620 SetError(errIllegalFPOperation);
621 return HUGE_VAL;
624 if (fZ >= 1.0)
625 return lcl_GetGammaHelper(fZ);
627 if (fZ >= 0.5) // shift to x>=1 using Gamma(x)=Gamma(x+1)/x
628 return lcl_GetGammaHelper(fZ+1) / fZ;
630 if (fZ >= -0.5) // shift to x>=1, might overflow
632 double fLogTest = lcl_GetLogGammaHelper(fZ+2) - log(fZ+1) - log( fabs(fZ));
633 if (fLogTest >= fLogDblMax)
635 SetError( errIllegalFPOperation);
636 return HUGE_VAL;
638 return lcl_GetGammaHelper(fZ+2) / (fZ+1) / fZ;
640 // fZ<-0.5
641 // Use Euler's reflection formula: gamma(x)= pi/ ( gamma(1-x)*sin(pi*x) )
642 double fLogDivisor = lcl_GetLogGammaHelper(1-fZ) + log( fabs( ::rtl::math::sin( F_PI*fZ)));
643 if (fLogDivisor - fLogPi >= fLogDblMax) // underflow
644 return 0.0;
646 if (fLogDivisor<0.0)
647 if (fLogPi - fLogDivisor > fLogDblMax) // overflow
649 SetError(errIllegalFPOperation);
650 return HUGE_VAL;
653 return exp( fLogPi - fLogDivisor) * ((::rtl::math::sin( F_PI*fZ) < 0.0) ? -1.0 : 1.0);
657 /** You must ensure fZ>0 */
658 double ScInterpreter::GetLogGamma(double fZ)
660 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetLogGamma" );
661 if (fZ >= fMaxGammaArgument)
662 return lcl_GetLogGammaHelper(fZ);
663 if (fZ >= 1.0)
664 return log(lcl_GetGammaHelper(fZ));
665 if (fZ >= 0.5)
666 return log( lcl_GetGammaHelper(fZ+1) / fZ);
667 return lcl_GetLogGammaHelper(fZ+2) - log(fZ+1) - log(fZ);
670 double ScInterpreter::GetFDist(double x, double fF1, double fF2)
672 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetFDist" );
673 double arg = fF2/(fF2+fF1*x);
674 double alpha = fF2/2.0;
675 double beta = fF1/2.0;
676 return (GetBetaDist(arg, alpha, beta));
678 double Z = (pow(fF,1.0/3.0)*(1.0-2.0/(9.0*fF2)) - (1.0-2.0/(9.0*fF1))) /
679 sqrt(2.0/(9.0*fF1) + pow(fF,2.0/3.0)*2.0/(9.0*fF2));
680 return (0.5-gauss(Z));
684 double ScInterpreter::GetTDist(double T, double fDF)
686 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetTDist" );
687 return 0.5 * GetBetaDist(fDF/(fDF+T*T), fDF/2.0, 0.5);
689 USHORT DF = (USHORT) fDF;
690 double A = T / sqrt(DF);
691 double B = 1.0 + A*A;
692 double R;
693 if (DF == 1)
694 R = 0.5 + atan(A)/F_PI;
695 else if (DF % 2 == 0)
697 double S0 = A/(2.0 * sqrt(B));
698 double C0 = S0;
699 for (USHORT i = 2; i <= DF-2; i+=2)
701 C0 *= (1.0 - 1.0/(double)i)/B;
702 S0 += C0;
704 R = 0.5 + S0;
706 else
708 double S1 = A / (B * F_PI);
709 double C1 = S1;
710 for (USHORT i = 3; i <= DF-2; i+=2)
712 C1 *= (1.0 - 1.0/(double)i)/B;
713 S1 += C1;
715 R = 0.5 + atan(A)/F_PI + S1;
717 return 1.0 - R;
721 // for LEGACY.CHIDIST, returns right tail, fDF=degrees of freedom
722 /** You must ensure fDF>0.0 */
723 double ScInterpreter::GetChiDist(double fX, double fDF)
725 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetChiDist" );
726 if (fX <= 0.0)
727 return 1.0; // see ODFF
728 else
729 return GetUpRegIGamma( fDF/2.0, fX/2.0);
732 // ready for ODF 1.2
733 // for ODF CHISQDIST; cumulative distribution function, fDF=degrees of freedom
734 // returns left tail
735 /** You must ensure fDF>0.0 */
736 double ScInterpreter::GetChiSqDistCDF(double fX, double fDF)
738 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetChiSqDistCDF" );
739 if (fX <= 0.0)
740 return 0.0; // see ODFF
741 else
742 return GetLowRegIGamma( fDF/2.0, fX/2.0);
745 double ScInterpreter::GetChiSqDistPDF(double fX, double fDF)
747 // you must ensure fDF is positive integer
748 double fValue;
749 double fCount;
750 if (fX <= 0.0)
751 return 0.0; // see ODFF
752 if (fDF*fX > 1391000.0)
754 // intermediate invalid values, use log
755 fValue = exp((0.5*fDF - 1) * log(fX*0.5) - 0.5 * fX - log(2.0) - GetLogGamma(0.5*fDF));
757 else // fDF is small in most cases, we can iterate
759 if (fmod(fDF,2.0)<0.5)
761 // even
762 fValue = 0.5;
763 fCount = 2.0;
765 else
767 fValue = 1/sqrt(fX*2*F_PI);
768 fCount = 1.0;
770 while ( fCount < fDF)
772 fValue *= (fX / fCount);
773 fCount += 2.0;
775 if (fX>=1425.0) // underflow in e^(-x/2)
776 fValue = exp(log(fValue)-fX/2);
777 else
778 fValue *= exp(-fX/2);
780 return fValue;
783 void ScInterpreter::ScChiSqDist()
785 BYTE nParamCount = GetByte();
786 if ( !MustHaveParamCount( nParamCount, 2, 3 ) )
787 return;
788 double fX;
789 bool bCumulative;
790 if (nParamCount == 3)
791 bCumulative = GetBool();
792 else
793 bCumulative = true;
794 double fDF = ::rtl::math::approxFloor(GetDouble());
795 if (fDF < 1.0)
796 PushIllegalArgument();
797 else
799 fX = GetDouble();
800 if (bCumulative)
801 PushDouble(GetChiSqDistCDF(fX,fDF));
802 else
803 PushDouble(GetChiSqDistPDF(fX,fDF));
807 void ScInterpreter::ScGamma()
809 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGamma" );
810 double x = GetDouble();
811 double fResult;
812 if (x <= 0.0 && x == ::rtl::math::approxFloor(x))
813 PushIllegalArgument();
814 else
816 fResult = GetGamma(x);
817 if (nGlobalError)
819 PushError( nGlobalError);
820 return;
822 PushDouble(fResult);
827 void ScInterpreter::ScLogGamma()
829 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLogGamma" );
830 double x = GetDouble();
831 if (x > 0.0) // constraint from ODFF
832 PushDouble( GetLogGamma(x));
833 else
834 PushIllegalArgument();
837 double ScInterpreter::GetBeta(double fAlpha, double fBeta)
839 double fA;
840 double fB;
841 if (fAlpha > fBeta)
843 fA = fAlpha; fB = fBeta;
845 else
847 fA = fBeta; fB = fAlpha;
849 if (fA+fB < fMaxGammaArgument) // simple case
850 return GetGamma(fA)/GetGamma(fA+fB)*GetGamma(fB);
851 // need logarithm
852 // GetLogGamma is not accurate enough, back to Lanczos for all three
853 // GetGamma and arrange factors newly.
854 const double fg = 6.024680040776729583740234375; //see GetGamma
855 double fgm = fg - 0.5;
856 double fLanczos = lcl_getLanczosSum(fA);
857 fLanczos /= lcl_getLanczosSum(fA+fB);
858 fLanczos *= lcl_getLanczosSum(fB);
859 double fABgm = fA+fB+fgm;
860 fLanczos *= sqrt((fABgm/(fA+fgm))/(fB+fgm));
861 double fTempA = fB/(fA+fgm); // (fA+fgm)/fABgm = 1 / ( 1 + fB/(fA+fgm))
862 double fTempB = fA/(fB+fgm);
863 double fResult = exp(-fA * ::rtl::math::log1p(fTempA)
864 -fB * ::rtl::math::log1p(fTempB)-fgm);
865 fResult *= fLanczos;
866 return fResult;
869 // Same as GetBeta but with logarithm
870 double ScInterpreter::GetLogBeta(double fAlpha, double fBeta)
872 double fA;
873 double fB;
874 if (fAlpha > fBeta)
876 fA = fAlpha; fB = fBeta;
878 else
880 fA = fBeta; fB = fAlpha;
882 const double fg = 6.024680040776729583740234375; //see GetGamma
883 double fgm = fg - 0.5;
884 double fLanczos = lcl_getLanczosSum(fA);
885 fLanczos /= lcl_getLanczosSum(fA+fB);
886 fLanczos *= lcl_getLanczosSum(fB);
887 double fLogLanczos = log(fLanczos);
888 double fABgm = fA+fB+fgm;
889 fLogLanczos += 0.5*(log(fABgm)-log(fA+fgm)-log(fB+fgm));
890 double fTempA = fB/(fA+fgm); // (fA+fgm)/fABgm = 1 / ( 1 + fB/(fA+fgm))
891 double fTempB = fA/(fB+fgm);
892 double fResult = -fA * ::rtl::math::log1p(fTempA)
893 -fB * ::rtl::math::log1p(fTempB)-fgm;
894 fResult += fLogLanczos;
895 return fResult;
898 // beta distribution probability density function
899 double ScInterpreter::GetBetaDistPDF(double fX, double fA, double fB)
901 // special cases
902 if (fA == 1.0) // result b*(1-x)^(b-1)
904 if (fB == 1.0)
905 return 1.0;
906 if (fB == 2.0)
907 return -2.0*fX + 2.0;
908 if (fX == 1.0 && fB < 1.0)
910 SetError(errIllegalArgument);
911 return HUGE_VAL;
913 if (fX <= 0.01)
914 return fB + fB * ::rtl::math::expm1((fB-1.0) * ::rtl::math::log1p(-fX));
915 else
916 return fB * pow(0.5-fX+0.5,fB-1.0);
918 if (fB == 1.0) // result a*x^(a-1)
920 if (fA == 2.0)
921 return fA * fX;
922 if (fX == 0.0 && fA < 1.0)
924 SetError(errIllegalArgument);
925 return HUGE_VAL;
927 return fA * pow(fX,fA-1);
929 if (fX <= 0.0)
931 if (fA < 1.0 && fX == 0.0)
933 SetError(errIllegalArgument);
934 return HUGE_VAL;
936 else
937 return 0.0;
939 if (fX >= 1.0)
941 if (fB < 1.0 && fX == 1.0)
943 SetError(errIllegalArgument);
944 return HUGE_VAL;
946 else
947 return 0.0;
950 // normal cases; result x^(a-1)*(1-x)^(b-1)/Beta(a,b)
951 const double fLogDblMax = log( ::std::numeric_limits<double>::max());
952 const double fLogDblMin = log( ::std::numeric_limits<double>::min());
953 double fLogY = (fX < 0.1) ? ::rtl::math::log1p(-fX) : log(0.5-fX+0.5);
954 double fLogX = log(fX);
955 double fAm1 = fA-1.0;
956 double fBm1 = fB-1.0;
957 double fLogBeta = GetLogBeta(fA,fB);
958 // check whether parts over- or underflow
959 if ( fAm1 * fLogX < fLogDblMax && fAm1 * fLogX > fLogDblMin
960 && fBm1 * fLogY < fLogDblMax && fBm1* fLogY > fLogDblMin
961 && fLogBeta < fLogDblMax && fLogBeta > fLogDblMin )
962 return pow(fX,fA-1.0) * pow(0.5-fX+0.5,fB-1.0) / GetBeta(fA,fB);
963 else // need logarithm;
964 // might overflow as a whole, but seldom, not worth to pre-detect it
965 return exp((fA-1.0)*fLogX + (fB-1.0)* fLogY - fLogBeta);
970 x^a * (1-x)^b
971 I_x(a,b) = ---------------- * result of ContFrac
972 a * Beta(a,b)
974 double lcl_GetBetaHelperContFrac(double fX, double fA, double fB)
975 { // like old version
976 double a1, b1, a2, b2, fnorm, apl2m, d2m, d2m1, cfnew, cf;
977 a1 = 1.0; b1 = 1.0;
978 b2 = 1.0 - (fA+fB)/(fA+1.0)*fX;
979 if (b2 == 0.0)
981 a2 = 0.0;
982 fnorm = 1.0;
983 cf = 1.0;
985 else
987 a2 = 1.0;
988 fnorm = 1.0/b2;
989 cf = a2*fnorm;
991 cfnew = 1.0;
992 double rm = 1.0;
994 const double fMaxIter = 50000.0;
995 // loop security, normal cases converge in less than 100 iterations.
996 // FIXME: You will get so much iteratons for fX near mean,
997 // I do not know a better algorithm.
998 bool bfinished = false;
1001 apl2m = fA + 2.0*rm;
1002 d2m = rm*(fB-rm)*fX/((apl2m-1.0)*apl2m);
1003 d2m1 = -(fA+rm)*(fA+fB+rm)*fX/(apl2m*(apl2m+1.0));
1004 a1 = (a2+d2m*a1)*fnorm;
1005 b1 = (b2+d2m*b1)*fnorm;
1006 a2 = a1 + d2m1*a2*fnorm;
1007 b2 = b1 + d2m1*b2*fnorm;
1008 if (b2 != 0.0)
1010 fnorm = 1.0/b2;
1011 cfnew = a2*fnorm;
1012 bfinished = (fabs(cf-cfnew) < fabs(cf)*fMachEps);
1014 cf = cfnew;
1015 rm += 1.0;
1017 while (rm < fMaxIter && !bfinished);
1018 return cf;
1021 // cumulative distribution function, normalized
1022 double ScInterpreter::GetBetaDist(double fXin, double fAlpha, double fBeta)
1024 // special cases
1025 if (fXin <= 0.0) // values are valid, see spec
1026 return 0.0;
1027 if (fXin >= 1.0) // values are valid, see spec
1028 return 1.0;
1029 if (fBeta == 1.0)
1030 return pow(fXin, fAlpha);
1031 if (fAlpha == 1.0)
1032 // 1.0 - pow(1.0-fX,fBeta) is not accurate enough
1033 return -::rtl::math::expm1(fBeta * ::rtl::math::log1p(-fXin));
1034 //FIXME: need special algorithm for fX near fP for large fA,fB
1035 double fResult;
1036 // I use always continued fraction, power series are neither
1037 // faster nor more accurate.
1038 double fY = (0.5-fXin)+0.5;
1039 double flnY = ::rtl::math::log1p(-fXin);
1040 double fX = fXin;
1041 double flnX = log(fXin);
1042 double fA = fAlpha;
1043 double fB = fBeta;
1044 bool bReflect = fXin > fAlpha/(fAlpha+fBeta);
1045 if (bReflect)
1047 fA = fBeta;
1048 fB = fAlpha;
1049 fX = fY;
1050 fY = fXin;
1051 flnX = flnY;
1052 flnY = log(fXin);
1054 fResult = lcl_GetBetaHelperContFrac(fX,fA,fB);
1055 fResult = fResult/fA;
1056 double fP = fA/(fA+fB);
1057 double fQ = fB/(fA+fB);
1058 double fTemp;
1059 if (fA > 1.0 && fB > 1.0 && fP < 0.97 && fQ < 0.97) //found experimental
1060 fTemp = GetBetaDistPDF(fX,fA,fB)*fX*fY;
1061 else
1062 fTemp = exp(fA*flnX + fB*flnY - GetLogBeta(fA,fB));
1063 fResult *= fTemp;
1064 if (bReflect)
1065 fResult = 0.5 - fResult + 0.5;
1066 if (fResult > 1.0) // ensure valid range
1067 fResult = 1.0;
1068 if (fResult < 0.0)
1069 fResult = 0.0;
1070 return fResult;
1073 void ScInterpreter::ScBetaDist()
1075 BYTE nParamCount = GetByte();
1076 if ( !MustHaveParamCount( nParamCount, 3, 6 ) ) // expanded, see #i91547#
1077 return;
1078 double fLowerBound, fUpperBound;
1079 double alpha, beta, x;
1080 bool bIsCumulative;
1081 if (nParamCount == 6)
1082 bIsCumulative = GetBool();
1083 else
1084 bIsCumulative = true;
1085 if (nParamCount >= 5)
1086 fUpperBound = GetDouble();
1087 else
1088 fUpperBound = 1.0;
1089 if (nParamCount >= 4)
1090 fLowerBound = GetDouble();
1091 else
1092 fLowerBound = 0.0;
1093 beta = GetDouble();
1094 alpha = GetDouble();
1095 x = GetDouble();
1096 double fScale = fUpperBound - fLowerBound;
1097 if (fScale <= 0.0 || alpha <= 0.0 || beta <= 0.0)
1099 PushIllegalArgument();
1100 return;
1102 if (bIsCumulative) // cumulative distribution function
1104 // special cases
1105 if (x < fLowerBound)
1107 PushDouble(0.0); return; //see spec
1109 if (x > fUpperBound)
1111 PushDouble(1.0); return; //see spec
1113 // normal cases
1114 x = (x-fLowerBound)/fScale; // convert to standard form
1115 PushDouble(GetBetaDist(x, alpha, beta));
1116 return;
1118 else // probability density function
1120 if (x < fLowerBound || x > fUpperBound)
1122 PushDouble(0.0);
1123 return;
1125 x = (x-fLowerBound)/fScale;
1126 PushDouble(GetBetaDistPDF(x, alpha, beta)/fScale);
1127 return;
1131 void ScInterpreter::ScPhi()
1133 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScPhi" );
1134 PushDouble(phi(GetDouble()));
1137 void ScInterpreter::ScGauss()
1139 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGauss" );
1140 PushDouble(gauss(GetDouble()));
1143 void ScInterpreter::ScFisher()
1145 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScFisher" );
1146 double fVal = GetDouble();
1147 if (fabs(fVal) >= 1.0)
1148 PushIllegalArgument();
1149 else
1150 PushDouble( ::rtl::math::atanh( fVal));
1153 void ScInterpreter::ScFisherInv()
1155 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScFisherInv" );
1156 PushDouble( tanh( GetDouble()));
1159 void ScInterpreter::ScFact()
1161 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScFact" );
1162 double nVal = GetDouble();
1163 if (nVal < 0.0)
1164 PushIllegalArgument();
1165 else
1166 PushDouble(Fakultaet(nVal));
1169 void ScInterpreter::ScKombin()
1171 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScKombin" );
1172 if ( MustHaveParamCount( GetByte(), 2 ) )
1174 double k = ::rtl::math::approxFloor(GetDouble());
1175 double n = ::rtl::math::approxFloor(GetDouble());
1176 if (k < 0.0 || n < 0.0 || k > n)
1177 PushIllegalArgument();
1178 else
1179 PushDouble(BinomKoeff(n, k));
1183 void ScInterpreter::ScKombin2()
1185 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScKombin2" );
1186 if ( MustHaveParamCount( GetByte(), 2 ) )
1188 double k = ::rtl::math::approxFloor(GetDouble());
1189 double n = ::rtl::math::approxFloor(GetDouble());
1190 if (k < 0.0 || n < 0.0 || k > n)
1191 PushIllegalArgument();
1192 else
1193 PushDouble(BinomKoeff(n + k - 1, k));
1197 void ScInterpreter::ScVariationen()
1199 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScVariationen" );
1200 if ( MustHaveParamCount( GetByte(), 2 ) )
1202 double k = ::rtl::math::approxFloor(GetDouble());
1203 double n = ::rtl::math::approxFloor(GetDouble());
1204 if (n < 0.0 || k < 0.0 || k > n)
1205 PushIllegalArgument();
1206 else if (k == 0.0)
1207 PushInt(1); // (n! / (n - 0)!) == 1
1208 else
1210 double nVal = n;
1211 for (ULONG i = (ULONG)k-1; i >= 1; i--)
1212 nVal *= n-(double)i;
1213 PushDouble(nVal);
1218 void ScInterpreter::ScVariationen2()
1220 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScVariationen2" );
1221 if ( MustHaveParamCount( GetByte(), 2 ) )
1223 double k = ::rtl::math::approxFloor(GetDouble());
1224 double n = ::rtl::math::approxFloor(GetDouble());
1225 if (n < 0.0 || k < 0.0 || k > n)
1226 PushIllegalArgument();
1227 else
1228 PushDouble(pow(n,k));
1232 void ScInterpreter::ScB()
1234 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScB" );
1235 BYTE nParamCount = GetByte();
1236 if ( !MustHaveParamCount( nParamCount, 3, 4 ) )
1237 return ;
1238 if (nParamCount == 3)
1240 double x = ::rtl::math::approxFloor(GetDouble());
1241 double p = GetDouble();
1242 double n = ::rtl::math::approxFloor(GetDouble());
1243 if (n < 0.0 || x < 0.0 || x > n || p < 0.0 || p > 1.0)
1244 PushIllegalArgument();
1245 else
1247 double q = 1.0 - p;
1248 double fFactor = pow(q, n);
1249 if (fFactor == 0.0)
1251 fFactor = pow(p, n);
1252 if (fFactor == 0.0)
1253 PushNoValue();
1254 else
1256 ULONG max = (ULONG) (n - x);
1257 for (ULONG i = 0; i < max && fFactor > 0.0; i++)
1258 fFactor *= (n-i)/(i+1)*q/p;
1259 PushDouble(fFactor);
1262 else
1264 ULONG max = (ULONG) x;
1265 for (ULONG i = 0; i < max && fFactor > 0.0; i++)
1266 fFactor *= (n-i)/(i+1)*p/q;
1267 PushDouble(fFactor);
1271 else if (nParamCount == 4)
1273 double xe = GetDouble();
1274 double xs = GetDouble();
1275 double p = GetDouble();
1276 double n = GetDouble();
1277 // alter Stand 300-SC
1278 // if ((xs < n) && (xe < n) && (p < 1.0))
1279 // {
1280 // double Varianz = sqrt(n * p * (1.0 - p));
1281 // xs = fabs(xs - (n * p /* / 2.0 STE */ ));
1282 // xe = fabs(xe - (n * p /* / 2.0 STE */ ));
1283 //// STE double nVal = gauss((xs + 0.5) / Varianz) + gauss((xe + 0.5) / Varianz);
1284 // double nVal = fabs(gauss(xs / Varianz) - gauss(xe / Varianz));
1285 // PushDouble(nVal);
1286 // }
1287 bool bIsValidX = ( 0.0 <= xs && xs <= xe && xe <= n);
1288 if ( bIsValidX && 0.0 < p && p < 1.0 )
1290 double q = 1.0 - p;
1291 double fFactor = pow(q, n);
1292 if (fFactor == 0.0)
1294 fFactor = pow(p, n);
1295 if (fFactor == 0.0)
1296 PushNoValue();
1297 else
1299 double fSum = 0.0;
1300 ULONG max;
1301 if (xe < (ULONG) n)
1302 max = (ULONG) (n-xe)-1;
1303 else
1304 max = 0;
1305 ULONG i;
1306 for (i = 0; i < max && fFactor > 0.0; i++)
1307 fFactor *= (n-i)/(i+1)*q/p;
1308 if (xs < (ULONG) n)
1309 max = (ULONG) (n-xs);
1310 else
1311 fSum = fFactor;
1312 for (; i < max && fFactor > 0.0; i++)
1314 fFactor *= (n-i)/(i+1)*q/p;
1315 fSum += fFactor;
1317 PushDouble(fSum);
1320 else
1322 ULONG max;
1323 double fSum;
1324 if ( (ULONG) xs == 0)
1326 fSum = fFactor;
1327 max = 0;
1329 else
1331 max = (ULONG) xs-1;
1332 fSum = 0.0;
1334 ULONG i;
1335 for (i = 0; i < max && fFactor > 0.0; i++)
1336 fFactor *= (n-i)/(i+1)*p/q;
1337 if ((ULONG)xe == 0) // beide 0
1338 fSum = fFactor;
1339 else
1340 max = (ULONG) xe;
1341 for (; i < max && fFactor > 0.0; i++)
1343 fFactor *= (n-i)/(i+1)*p/q;
1344 fSum += fFactor;
1346 PushDouble(fSum);
1349 else
1351 if ( bIsValidX ) // not(0<p<1)
1353 if ( p == 0.0 )
1354 PushDouble( (xs == 0.0) ? 1.0 : 0.0 );
1355 else if ( p == 1.0 )
1356 PushDouble( (xe == n) ? 1.0 : 0.0 );
1357 else
1358 PushIllegalArgument();
1360 else
1361 PushIllegalArgument();
1366 void ScInterpreter::ScBinomDist()
1368 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScBinomDist" );
1369 if ( MustHaveParamCount( GetByte(), 4 ) )
1371 double kum = GetDouble(); // 0 oder 1
1372 double p = GetDouble(); // p
1373 double n = ::rtl::math::approxFloor(GetDouble()); // n
1374 double x = ::rtl::math::approxFloor(GetDouble()); // x
1375 double fFactor, q, fSum;
1376 if (n < 0.0 || x < 0.0 || x > n || p < 0.0 || p > 1.0)
1377 PushIllegalArgument();
1378 else if (kum == 0.0) // Dichte
1380 q = 1.0 - p;
1381 fFactor = pow(q, n);
1382 if (fFactor == 0.0)
1384 fFactor = pow(p, n);
1385 if (fFactor == 0.0)
1386 PushNoValue();
1387 else
1389 ULONG max = (ULONG) (n - x);
1390 for (ULONG i = 0; i < max && fFactor > 0.0; i++)
1391 fFactor *= (n-i)/(i+1)*q/p;
1392 PushDouble(fFactor);
1395 else
1397 ULONG max = (ULONG) x;
1398 for (ULONG i = 0; i < max && fFactor > 0.0; i++)
1399 fFactor *= (n-i)/(i+1)*p/q;
1400 PushDouble(fFactor);
1403 else // Verteilung
1405 if (n == x)
1406 PushDouble(1.0);
1407 else
1409 q = 1.0 - p;
1410 fFactor = pow(q, n);
1411 if (fFactor == 0.0)
1413 fFactor = pow(p, n);
1414 if (fFactor == 0.0)
1415 PushNoValue();
1416 else
1418 fSum = 1.0 - fFactor;
1419 ULONG max = (ULONG) (n - x) - 1;
1420 for (ULONG i = 0; i < max && fFactor > 0.0; i++)
1422 fFactor *= (n-i)/(i+1)*q/p;
1423 fSum -= fFactor;
1425 if (fSum < 0.0)
1426 PushDouble(0.0);
1427 else
1428 PushDouble(fSum);
1431 else
1433 fSum = fFactor;
1434 ULONG max = (ULONG) x;
1435 for (ULONG i = 0; i < max && fFactor > 0.0; i++)
1437 fFactor *= (n-i)/(i+1)*p/q;
1438 fSum += fFactor;
1440 PushDouble(fSum);
1447 void ScInterpreter::ScCritBinom()
1449 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCritBinom" );
1450 if ( MustHaveParamCount( GetByte(), 3 ) )
1452 double alpha = GetDouble(); // alpha
1453 double p = GetDouble(); // p
1454 double n = ::rtl::math::approxFloor(GetDouble());
1455 if (n < 0.0 || alpha <= 0.0 || alpha >= 1.0 || p < 0.0 || p > 1.0)
1456 PushIllegalArgument();
1457 else
1459 double q = 1.0 - p;
1460 double fFactor = pow(q,n);
1461 if (fFactor == 0.0)
1463 fFactor = pow(p, n);
1464 if (fFactor == 0.0)
1465 PushNoValue();
1466 else
1468 double fSum = 1.0 - fFactor; ULONG max = (ULONG) n;
1469 ULONG i;
1471 for ( i = 0; i < max && fSum >= alpha; i++)
1473 fFactor *= (n-i)/(i+1)*q/p;
1474 fSum -= fFactor;
1476 PushDouble(n-i);
1479 else
1481 double fSum = fFactor; ULONG max = (ULONG) n;
1482 ULONG i;
1484 for ( i = 0; i < max && fSum < alpha; i++)
1486 fFactor *= (n-i)/(i+1)*p/q;
1487 fSum += fFactor;
1489 PushDouble(i);
1495 void ScInterpreter::ScNegBinomDist()
1497 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScNegBinomDist" );
1498 if ( MustHaveParamCount( GetByte(), 3 ) )
1500 double p = GetDouble(); // p
1501 double r = GetDouble(); // r
1502 double x = GetDouble(); // x
1503 if (r < 0.0 || x < 0.0 || p < 0.0 || p > 1.0)
1504 PushIllegalArgument();
1505 else
1507 double q = 1.0 - p;
1508 double fFactor = pow(p,r);
1509 for (double i = 0.0; i < x; i++)
1510 fFactor *= (i+r)/(i+1.0)*q;
1511 PushDouble(fFactor);
1516 void ScInterpreter::ScNormDist()
1518 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScNormDist" );
1519 BYTE nParamCount = GetByte();
1520 if ( !MustHaveParamCount( nParamCount, 3, 4))
1521 return;
1522 bool bCumulative = nParamCount == 4 ? GetBool() : true;
1523 double sigma = GetDouble(); // standard deviation
1524 double mue = GetDouble(); // mean
1525 double x = GetDouble(); // x
1526 if (sigma <= 0.0)
1528 PushIllegalArgument();
1529 return;
1531 if (bCumulative)
1532 PushDouble(integralPhi((x-mue)/sigma));
1533 else
1534 PushDouble(phi((x-mue)/sigma)/sigma);
1537 void ScInterpreter::ScLogNormDist() //expanded, see #i100119#
1539 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLogNormDist" );
1540 BYTE nParamCount = GetByte();
1541 if ( !MustHaveParamCount( nParamCount, 1, 4))
1542 return;
1543 bool bCumulative = nParamCount == 4 ? GetBool() : true; // cumulative
1544 double sigma = nParamCount >= 3 ? GetDouble() : 1.0; // standard deviation
1545 double mue = nParamCount >= 2 ? GetDouble() : 0.0; // mean
1546 double x = GetDouble(); // x
1547 if (sigma <= 0.0)
1549 PushIllegalArgument();
1550 return;
1552 if (bCumulative)
1553 { // cumulative
1554 if (x <= 0.0)
1555 PushDouble(0.0);
1556 else
1557 PushDouble(integralPhi((log(x)-mue)/sigma));
1559 else
1560 { // density
1561 if (x <= 0.0)
1562 PushIllegalArgument();
1563 else
1564 PushDouble(phi((log(x)-mue)/sigma)/sigma/x);
1568 void ScInterpreter::ScStdNormDist()
1570 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScStdNormDist" );
1571 PushDouble(integralPhi(GetDouble()));
1574 void ScInterpreter::ScExpDist()
1576 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScExpDist" );
1577 if ( MustHaveParamCount( GetByte(), 3 ) )
1579 double kum = GetDouble(); // 0 oder 1
1580 double lambda = GetDouble(); // lambda
1581 double x = GetDouble(); // x
1582 if (lambda <= 0.0)
1583 PushIllegalArgument();
1584 else if (kum == 0.0) // Dichte
1586 if (x >= 0.0)
1587 PushDouble(lambda * exp(-lambda*x));
1588 else
1589 PushInt(0);
1591 else // Verteilung
1593 if (x > 0.0)
1594 PushDouble(1.0 - exp(-lambda*x));
1595 else
1596 PushInt(0);
1601 void ScInterpreter::ScTDist()
1603 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTDist" );
1604 if ( !MustHaveParamCount( GetByte(), 3 ) )
1605 return;
1606 double fFlag = ::rtl::math::approxFloor(GetDouble());
1607 double fDF = ::rtl::math::approxFloor(GetDouble());
1608 double T = GetDouble();
1609 if (fDF < 1.0 || T < 0.0 || (fFlag != 1.0 && fFlag != 2.0) )
1611 PushIllegalArgument();
1612 return;
1614 double R = GetTDist(T, fDF);
1615 if (fFlag == 1.0)
1616 PushDouble(R);
1617 else
1618 PushDouble(2.0*R);
1621 void ScInterpreter::ScFDist()
1623 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScFDist" );
1624 if ( !MustHaveParamCount( GetByte(), 3 ) )
1625 return;
1626 double fF2 = ::rtl::math::approxFloor(GetDouble());
1627 double fF1 = ::rtl::math::approxFloor(GetDouble());
1628 double fF = GetDouble();
1629 if (fF < 0.0 || fF1 < 1.0 || fF2 < 1.0 || fF1 >= 1.0E10 || fF2 >= 1.0E10)
1631 PushIllegalArgument();
1632 return;
1634 PushDouble(GetFDist(fF, fF1, fF2));
1637 void ScInterpreter::ScChiDist()
1639 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScChiDist" );
1640 double fResult;
1641 if ( !MustHaveParamCount( GetByte(), 2 ) )
1642 return;
1643 double fDF = ::rtl::math::approxFloor(GetDouble());
1644 double fChi = GetDouble();
1645 if (fDF < 1.0) // x<=0 returns 1, see ODFF 6.17.10
1647 PushIllegalArgument();
1648 return;
1650 fResult = GetChiDist( fChi, fDF);
1651 if (nGlobalError)
1653 PushError( nGlobalError);
1654 return;
1656 PushDouble(fResult);
1659 void ScInterpreter::ScWeibull()
1661 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScWeibull" );
1662 if ( MustHaveParamCount( GetByte(), 4 ) )
1664 double kum = GetDouble(); // 0 oder 1
1665 double beta = GetDouble(); // beta
1666 double alpha = GetDouble(); // alpha
1667 double x = GetDouble(); // x
1668 if (alpha <= 0.0 || beta <= 0.0 || x < 0.0)
1669 PushIllegalArgument();
1670 else if (kum == 0.0) // Dichte
1671 PushDouble(alpha/pow(beta,alpha)*pow(x,alpha-1.0)*
1672 exp(-pow(x/beta,alpha)));
1673 else // Verteilung
1674 PushDouble(1.0 - exp(-pow(x/beta,alpha)));
1678 void ScInterpreter::ScPoissonDist()
1680 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScPoissonDist" );
1681 BYTE nParamCount = GetByte();
1682 if ( MustHaveParamCount( nParamCount, 2, 3 ) )
1684 bool bCumulative = (nParamCount == 3 ? GetBool() : true); // default cumulative
1685 double lambda = GetDouble(); // Mean
1686 double x = ::rtl::math::approxFloor(GetDouble()); // discrete distribution
1687 if (lambda < 0.0 || x < 0.0)
1688 PushIllegalArgument();
1689 else if (!bCumulative) // Probability mass function
1691 if (lambda == 0.0)
1692 PushInt(0);
1693 else
1695 if (lambda >712) // underflow in exp(-lambda)
1696 { // accuracy 11 Digits
1697 PushDouble( exp(x*log(lambda)-lambda-GetLogGamma(x+1.0)));
1699 else
1701 double fPoissonVar = 1.0;
1702 for ( double f = 0.0; f < x; ++f )
1703 fPoissonVar *= lambda / ( f + 1.0 );
1704 PushDouble( fPoissonVar * exp( -lambda ) );
1708 else // Cumulative distribution function
1710 if (lambda == 0.0)
1711 PushInt(1);
1712 else
1714 if (lambda > 712 ) // underflow in exp(-lambda)
1715 { // accuracy 12 Digits
1716 PushDouble(GetUpRegIGamma(x+1.0,lambda));
1718 else
1720 if (x >= 936.0) // result is always undistinghable from 1
1721 PushDouble (1.0);
1722 else
1724 double fSummand = exp(-lambda);
1725 double fSum = fSummand;
1726 int nEnd = sal::static_int_cast<int>( x );
1727 for (int i = 1; i <= nEnd; i++)
1729 fSummand = (fSummand * lambda)/(double)i;
1730 fSum += fSummand;
1732 PushDouble(fSum);
1740 /** Local function used in the calculation of the hypergeometric distribution.
1742 void lcl_PutFactorialElements( ::std::vector< double >& cn, double fLower, double fUpper, double fBase )
1744 for ( double i = fLower; i <= fUpper; ++i )
1746 double fVal = fBase - i;
1747 if ( fVal > 1.0 )
1748 cn.push_back( fVal );
1752 /** Calculates a value of the hypergeometric distribution.
1754 The algorithm is designed to avoid unnecessary multiplications and division
1755 by expanding all factorial elements (9 of them). It is done by excluding
1756 those ranges that overlap in the numerator and the denominator. This allows
1757 for a fast calculation for large values which would otherwise cause an overflow
1758 in the intermediate values.
1760 @author Kohei Yoshida <kohei@openoffice.org>
1762 @see #i47296#
1765 void ScInterpreter::ScHypGeomDist()
1767 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScHypGeomDist" );
1768 const size_t nMaxArraySize = 500000; // arbitrary max array size
1770 if ( !MustHaveParamCount( GetByte(), 4 ) )
1771 return;
1773 double N = ::rtl::math::approxFloor(GetDouble());
1774 double M = ::rtl::math::approxFloor(GetDouble());
1775 double n = ::rtl::math::approxFloor(GetDouble());
1776 double x = ::rtl::math::approxFloor(GetDouble());
1778 if( (x < 0.0) || (n < x) || (M < x) || (N < n) || (N < M) || (x < n - N + M) )
1780 PushIllegalArgument();
1781 return;
1784 typedef ::std::vector< double > HypContainer;
1785 HypContainer cnNumer, cnDenom;
1787 size_t nEstContainerSize = static_cast<size_t>( x + ::std::min( n, M ) );
1788 size_t nMaxSize = ::std::min( cnNumer.max_size(), nMaxArraySize );
1789 if ( nEstContainerSize > nMaxSize )
1791 PushNoValue();
1792 return;
1794 cnNumer.reserve( nEstContainerSize + 10 );
1795 cnDenom.reserve( nEstContainerSize + 10 );
1797 // Trim coefficient C first
1798 double fCNumVarUpper = N - n - M + x - 1.0;
1799 double fCDenomVarLower = 1.0;
1800 if ( N - n - M + x >= M - x + 1.0 )
1802 fCNumVarUpper = M - x - 1.0;
1803 fCDenomVarLower = N - n - 2.0*(M - x) + 1.0;
1806 #ifdef DBG_UTIL
1807 double fCNumLower = N - n - fCNumVarUpper;
1808 #endif
1809 double fCDenomUpper = N - n - M + x + 1.0 - fCDenomVarLower;
1811 double fDNumVarLower = n - M;
1813 if ( n >= M + 1.0 )
1815 if ( N - M < n + 1.0 )
1817 // Case 1
1819 if ( N - n < n + 1.0 )
1821 // no overlap
1822 lcl_PutFactorialElements( cnNumer, 0.0, fCNumVarUpper, N - n );
1823 lcl_PutFactorialElements( cnDenom, 0.0, N - n - 1.0, N );
1825 else
1827 // overlap
1828 DBG_ASSERT( fCNumLower < n + 1.0, "ScHypGeomDist: wrong assertion" );
1829 lcl_PutFactorialElements( cnNumer, N - 2.0*n, fCNumVarUpper, N - n );
1830 lcl_PutFactorialElements( cnDenom, 0.0, n - 1.0, N );
1833 DBG_ASSERT( fCDenomUpper <= N - M, "ScHypGeomDist: wrong assertion" );
1835 if ( fCDenomUpper < n - x + 1.0 )
1836 // no overlap
1837 lcl_PutFactorialElements( cnNumer, 1.0, N - M - n + x, N - M + 1.0 );
1838 else
1840 // overlap
1841 lcl_PutFactorialElements( cnNumer, 1.0, N - M - fCDenomUpper, N - M + 1.0 );
1843 fCDenomUpper = n - x;
1844 fCDenomVarLower = N - M - 2.0*(n - x) + 1.0;
1847 else
1849 // Case 2
1851 if ( n > M - 1.0 )
1853 // no overlap
1854 lcl_PutFactorialElements( cnNumer, 0.0, fCNumVarUpper, N - n );
1855 lcl_PutFactorialElements( cnDenom, 0.0, M - 1.0, N );
1857 else
1859 lcl_PutFactorialElements( cnNumer, M - n, fCNumVarUpper, N - n );
1860 lcl_PutFactorialElements( cnDenom, 0.0, n - 1.0, N );
1863 DBG_ASSERT( fCDenomUpper <= n, "ScHypGeomDist: wrong assertion" );
1865 if ( fCDenomUpper < n - x + 1.0 )
1866 // no overlap
1867 lcl_PutFactorialElements( cnNumer, N - M - n + 1.0, N - M - n + x, N - M + 1.0 );
1868 else
1870 lcl_PutFactorialElements( cnNumer, N - M - n + 1.0, N - M - fCDenomUpper, N - M + 1.0 );
1871 fCDenomUpper = n - x;
1872 fCDenomVarLower = N - M - 2.0*(n - x) + 1.0;
1876 DBG_ASSERT( fCDenomUpper <= M, "ScHypGeomDist: wrong assertion" );
1878 else
1880 if ( N - M < M + 1.0 )
1882 // Case 3
1884 if ( N - n < M + 1.0 )
1886 // No overlap
1887 lcl_PutFactorialElements( cnNumer, 0.0, fCNumVarUpper, N - n );
1888 lcl_PutFactorialElements( cnDenom, 0.0, N - M - 1.0, N );
1890 else
1892 lcl_PutFactorialElements( cnNumer, N - n - M, fCNumVarUpper, N - n );
1893 lcl_PutFactorialElements( cnDenom, 0.0, n - 1.0, N );
1896 if ( n - x + 1.0 > fCDenomUpper )
1897 // No overlap
1898 lcl_PutFactorialElements( cnNumer, 1.0, N - M - n + x, N - M + 1.0 );
1899 else
1901 // Overlap
1902 lcl_PutFactorialElements( cnNumer, 1.0, N - M - fCDenomUpper, N - M + 1.0 );
1904 fCDenomVarLower = N - M - 2.0*(n - x) + 1.0;
1905 fCDenomUpper = n - x;
1908 else
1910 // Case 4
1912 DBG_ASSERT( M >= n - x, "ScHypGeomDist: wrong assertion" );
1913 DBG_ASSERT( M - x <= N - M + 1.0, "ScHypGeomDist: wrong assertion" );
1915 if ( N - n < N - M + 1.0 )
1917 // No overlap
1918 lcl_PutFactorialElements( cnNumer, 0.0, fCNumVarUpper, N - n );
1919 lcl_PutFactorialElements( cnDenom, 0.0, M - 1.0, N );
1921 else
1923 // Overlap
1924 DBG_ASSERT( fCNumLower <= N - M + 1.0, "ScHypGeomDist: wrong assertion" );
1926 lcl_PutFactorialElements( cnNumer, M - n, fCNumVarUpper, N - n );
1927 lcl_PutFactorialElements( cnDenom, 0.0, n - 1.0, N );
1930 if ( n - x + 1.0 > fCDenomUpper )
1931 // No overlap
1932 lcl_PutFactorialElements( cnNumer, N - 2.0*M + 1.0, N - M - n + x, N - M + 1.0 );
1933 else if ( M >= fCDenomUpper )
1935 lcl_PutFactorialElements( cnNumer, N - 2.0*M + 1.0, N - M - fCDenomUpper, N - M + 1.0 );
1937 fCDenomUpper = n - x;
1938 fCDenomVarLower = N - M - 2.0*(n - x) + 1.0;
1940 else
1942 DBG_ASSERT( M <= fCDenomUpper, "ScHypGeomDist: wrong assertion" );
1943 lcl_PutFactorialElements( cnDenom, fCDenomVarLower, N - n - 2.0*M + x,
1944 N - n - M + x + 1.0 );
1946 fCDenomUpper = n - x;
1947 fCDenomVarLower = N - M - 2.0*(n - x) + 1.0;
1951 DBG_ASSERT( fCDenomUpper <= n, "ScHypGeomDist: wrong assertion" );
1953 fDNumVarLower = 0.0;
1956 double nDNumVarUpper = fCDenomUpper < x + 1.0 ? n - x - 1.0 : n - fCDenomUpper - 1.0;
1957 double nDDenomVarLower = fCDenomUpper < x + 1.0 ? fCDenomVarLower : N - n - M + 1.0;
1958 lcl_PutFactorialElements( cnNumer, fDNumVarLower, nDNumVarUpper, n );
1959 lcl_PutFactorialElements( cnDenom, nDDenomVarLower, N - n - M + x, N - n - M + x + 1.0 );
1961 ::std::sort( cnNumer.begin(), cnNumer.end() );
1962 ::std::sort( cnDenom.begin(), cnDenom.end() );
1963 HypContainer::reverse_iterator it1 = cnNumer.rbegin(), it1End = cnNumer.rend();
1964 HypContainer::reverse_iterator it2 = cnDenom.rbegin(), it2End = cnDenom.rend();
1966 double fFactor = 1.0;
1967 for ( ; it1 != it1End || it2 != it2End; )
1969 double fEnum = 1.0, fDenom = 1.0;
1970 if ( it1 != it1End )
1971 fEnum = *it1++;
1972 if ( it2 != it2End )
1973 fDenom = *it2++;
1974 fFactor *= fEnum / fDenom;
1977 PushDouble(fFactor);
1980 void ScInterpreter::ScGammaDist()
1982 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGammaDist" );
1983 BYTE nParamCount = GetByte();
1984 if ( !MustHaveParamCount( nParamCount, 3, 4 ) )
1985 return;
1986 double bCumulative;
1987 if (nParamCount == 4)
1988 bCumulative = GetBool();
1989 else
1990 bCumulative = true;
1991 double fBeta = GetDouble(); // scale
1992 double fAlpha = GetDouble(); // shape
1993 double fX = GetDouble(); // x
1994 if (fAlpha <= 0.0 || fBeta <= 0.0)
1995 PushIllegalArgument();
1996 else
1998 if (bCumulative) // distribution
1999 PushDouble( GetGammaDist( fX, fAlpha, fBeta));
2000 else // density
2001 PushDouble( GetGammaDistPDF( fX, fAlpha, fBeta));
2005 void ScInterpreter::ScNormInv()
2007 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScNormInv" );
2008 if ( MustHaveParamCount( GetByte(), 3 ) )
2010 double sigma = GetDouble();
2011 double mue = GetDouble();
2012 double x = GetDouble();
2013 if (sigma <= 0.0 || x < 0.0 || x > 1.0)
2014 PushIllegalArgument();
2015 else if (x == 0.0 || x == 1.0)
2016 PushNoValue();
2017 else
2018 PushDouble(gaussinv(x)*sigma + mue);
2022 void ScInterpreter::ScSNormInv()
2024 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSNormInv" );
2025 double x = GetDouble();
2026 if (x < 0.0 || x > 1.0)
2027 PushIllegalArgument();
2028 else if (x == 0.0 || x == 1.0)
2029 PushNoValue();
2030 else
2031 PushDouble(gaussinv(x));
2034 void ScInterpreter::ScLogNormInv()
2036 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLogNormInv" );
2037 if ( MustHaveParamCount( GetByte(), 3 ) )
2039 double sigma = GetDouble(); // Stdabw
2040 double mue = GetDouble(); // Mittelwert
2041 double y = GetDouble(); // y
2042 if (sigma <= 0.0 || y <= 0.0 || y >= 1.0)
2043 PushIllegalArgument();
2044 else
2045 PushDouble(exp(mue+sigma*gaussinv(y)));
2049 class ScGammaDistFunction : public ScDistFunc
2051 ScInterpreter& rInt;
2052 double fp, fAlpha, fBeta;
2054 public:
2055 ScGammaDistFunction( ScInterpreter& rI, double fpVal, double fAlphaVal, double fBetaVal ) :
2056 rInt(rI), fp(fpVal), fAlpha(fAlphaVal), fBeta(fBetaVal) {}
2058 double GetValue( double x ) const { return fp - rInt.GetGammaDist(x, fAlpha, fBeta); }
2061 void ScInterpreter::ScGammaInv()
2063 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGammaInv" );
2064 if ( !MustHaveParamCount( GetByte(), 3 ) )
2065 return;
2066 double fBeta = GetDouble();
2067 double fAlpha = GetDouble();
2068 double fP = GetDouble();
2069 if (fAlpha <= 0.0 || fBeta <= 0.0 || fP < 0.0 || fP >= 1.0 )
2071 PushIllegalArgument();
2072 return;
2074 if (fP == 0.0)
2075 PushInt(0);
2076 else
2078 bool bConvError;
2079 ScGammaDistFunction aFunc( *this, fP, fAlpha, fBeta );
2080 double fStart = fAlpha * fBeta;
2081 double fVal = lcl_IterateInverse( aFunc, fStart*0.5, fStart, bConvError );
2082 if (bConvError)
2083 SetError(errNoConvergence);
2084 PushDouble(fVal);
2088 class ScBetaDistFunction : public ScDistFunc
2090 ScInterpreter& rInt;
2091 double fp, fAlpha, fBeta;
2093 public:
2094 ScBetaDistFunction( ScInterpreter& rI, double fpVal, double fAlphaVal, double fBetaVal ) :
2095 rInt(rI), fp(fpVal), fAlpha(fAlphaVal), fBeta(fBetaVal) {}
2097 double GetValue( double x ) const { return fp - rInt.GetBetaDist(x, fAlpha, fBeta); }
2100 void ScInterpreter::ScBetaInv()
2102 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScBetaInv" );
2103 BYTE nParamCount = GetByte();
2104 if ( !MustHaveParamCount( nParamCount, 3, 5 ) )
2105 return;
2106 double fP, fA, fB, fAlpha, fBeta;
2107 if (nParamCount == 5)
2108 fB = GetDouble();
2109 else
2110 fB = 1.0;
2111 if (nParamCount >= 4)
2112 fA = GetDouble();
2113 else
2114 fA = 0.0;
2115 fBeta = GetDouble();
2116 fAlpha = GetDouble();
2117 fP = GetDouble();
2118 if (fP < 0.0 || fP >= 1.0 || fA == fB || fAlpha <= 0.0 || fBeta <= 0.0)
2120 PushIllegalArgument();
2121 return;
2123 if (fP == 0.0)
2124 PushInt(0);
2125 else
2127 bool bConvError;
2128 ScBetaDistFunction aFunc( *this, fP, fAlpha, fBeta );
2129 // 0..1 as range for iteration so it isn't extended beyond the valid range
2130 double fVal = lcl_IterateInverse( aFunc, 0.0, 1.0, bConvError );
2131 if (bConvError)
2132 PushError( errNoConvergence);
2133 else
2134 PushDouble(fA + fVal*(fB-fA)); // scale to (A,B)
2138 // Achtung: T, F und Chi
2139 // sind monoton fallend,
2140 // deshalb 1-Dist als Funktion
2142 class ScTDistFunction : public ScDistFunc
2144 ScInterpreter& rInt;
2145 double fp, fDF;
2147 public:
2148 ScTDistFunction( ScInterpreter& rI, double fpVal, double fDFVal ) :
2149 rInt(rI), fp(fpVal), fDF(fDFVal) {}
2151 double GetValue( double x ) const { return fp - 2 * rInt.GetTDist(x, fDF); }
2154 void ScInterpreter::ScTInv()
2156 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTInv" );
2157 if ( !MustHaveParamCount( GetByte(), 2 ) )
2158 return;
2159 double fDF = ::rtl::math::approxFloor(GetDouble());
2160 double fP = GetDouble();
2161 if (fDF < 1.0 || fDF >= 1.0E5 || fP <= 0.0 || fP > 1.0 )
2163 PushIllegalArgument();
2164 return;
2167 bool bConvError;
2168 ScTDistFunction aFunc( *this, fP, fDF );
2169 double fVal = lcl_IterateInverse( aFunc, fDF*0.5, fDF, bConvError );
2170 if (bConvError)
2171 SetError(errNoConvergence);
2172 PushDouble(fVal);
2175 class ScFDistFunction : public ScDistFunc
2177 ScInterpreter& rInt;
2178 double fp, fF1, fF2;
2180 public:
2181 ScFDistFunction( ScInterpreter& rI, double fpVal, double fF1Val, double fF2Val ) :
2182 rInt(rI), fp(fpVal), fF1(fF1Val), fF2(fF2Val) {}
2184 double GetValue( double x ) const { return fp - rInt.GetFDist(x, fF1, fF2); }
2187 void ScInterpreter::ScFInv()
2189 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScFInv" );
2190 if ( !MustHaveParamCount( GetByte(), 3 ) )
2191 return;
2192 double fF2 = ::rtl::math::approxFloor(GetDouble());
2193 double fF1 = ::rtl::math::approxFloor(GetDouble());
2194 double fP = GetDouble();
2195 if (fP <= 0.0 || fF1 < 1.0 || fF2 < 1.0 || fF1 >= 1.0E10 || fF2 >= 1.0E10 || fP > 1.0)
2197 PushIllegalArgument();
2198 return;
2201 bool bConvError;
2202 ScFDistFunction aFunc( *this, fP, fF1, fF2 );
2203 double fVal = lcl_IterateInverse( aFunc, fF1*0.5, fF1, bConvError );
2204 if (bConvError)
2205 SetError(errNoConvergence);
2206 PushDouble(fVal);
2209 class ScChiDistFunction : public ScDistFunc
2211 ScInterpreter& rInt;
2212 double fp, fDF;
2214 public:
2215 ScChiDistFunction( ScInterpreter& rI, double fpVal, double fDFVal ) :
2216 rInt(rI), fp(fpVal), fDF(fDFVal) {}
2218 double GetValue( double x ) const { return fp - rInt.GetChiDist(x, fDF); }
2221 void ScInterpreter::ScChiInv()
2223 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScChiInv" );
2224 if ( !MustHaveParamCount( GetByte(), 2 ) )
2225 return;
2226 double fDF = ::rtl::math::approxFloor(GetDouble());
2227 double fP = GetDouble();
2228 if (fDF < 1.0 || fP <= 0.0 || fP > 1.0 )
2230 PushIllegalArgument();
2231 return;
2234 bool bConvError;
2235 ScChiDistFunction aFunc( *this, fP, fDF );
2236 double fVal = lcl_IterateInverse( aFunc, fDF*0.5, fDF, bConvError );
2237 if (bConvError)
2238 SetError(errNoConvergence);
2239 PushDouble(fVal);
2242 /***********************************************/
2243 class ScChiSqDistFunction : public ScDistFunc
2245 ScInterpreter& rInt;
2246 double fp, fDF;
2248 public:
2249 ScChiSqDistFunction( ScInterpreter& rI, double fpVal, double fDFVal ) :
2250 rInt(rI), fp(fpVal), fDF(fDFVal) {}
2252 double GetValue( double x ) const { return fp - rInt.GetChiSqDistCDF(x, fDF); }
2256 void ScInterpreter::ScChiSqInv()
2258 if ( !MustHaveParamCount( GetByte(), 2 ) )
2259 return;
2260 double fDF = ::rtl::math::approxFloor(GetDouble());
2261 double fP = GetDouble();
2262 if (fDF < 1.0 || fP < 0.0 || fP >= 1.0 )
2264 PushIllegalArgument();
2265 return;
2268 bool bConvError;
2269 ScChiSqDistFunction aFunc( *this, fP, fDF );
2270 double fVal = lcl_IterateInverse( aFunc, fDF*0.5, fDF, bConvError );
2271 if (bConvError)
2272 SetError(errNoConvergence);
2273 PushDouble(fVal);
2277 void ScInterpreter::ScConfidence()
2279 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScConfidence" );
2280 if ( MustHaveParamCount( GetByte(), 3 ) )
2282 double n = ::rtl::math::approxFloor(GetDouble());
2283 double sigma = GetDouble();
2284 double alpha = GetDouble();
2285 if (sigma <= 0.0 || alpha <= 0.0 || alpha >= 1.0 || n < 1.0)
2286 PushIllegalArgument();
2287 else
2288 PushDouble( gaussinv(1.0-alpha/2.0) * sigma/sqrt(n) );
2292 void ScInterpreter::ScZTest()
2294 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScZTest" );
2295 BYTE nParamCount = GetByte();
2296 if ( !MustHaveParamCount( nParamCount, 2, 3 ) )
2297 return;
2298 double sigma = 0.0, mue, x;
2299 if (nParamCount == 3)
2301 sigma = GetDouble();
2302 if (sigma <= 0.0)
2304 PushIllegalArgument();
2305 return;
2308 x = GetDouble();
2310 double fSum = 0.0;
2311 double fSumSqr = 0.0;
2312 double fVal;
2313 double rValCount = 0.0;
2314 switch (GetStackType())
2316 case formula::svDouble :
2318 fVal = GetDouble();
2319 fSum += fVal;
2320 fSumSqr += fVal*fVal;
2321 rValCount++;
2323 break;
2324 case svSingleRef :
2326 ScAddress aAdr;
2327 PopSingleRef( aAdr );
2328 ScBaseCell* pCell = GetCell( aAdr );
2329 if (HasCellValueData(pCell))
2331 fVal = GetCellValue( aAdr, pCell );
2332 fSum += fVal;
2333 fSumSqr += fVal*fVal;
2334 rValCount++;
2337 break;
2338 case svRefList :
2339 case formula::svDoubleRef :
2341 short nParam = 1;
2342 size_t nRefInList = 0;
2343 while (nParam-- > 0)
2345 ScRange aRange;
2346 USHORT nErr = 0;
2347 PopDoubleRef( aRange, nParam, nRefInList);
2348 ScValueIterator aValIter(pDok, aRange, glSubTotal);
2349 if (aValIter.GetFirst(fVal, nErr))
2351 fSum += fVal;
2352 fSumSqr += fVal*fVal;
2353 rValCount++;
2354 while ((nErr == 0) && aValIter.GetNext(fVal, nErr))
2356 fSum += fVal;
2357 fSumSqr += fVal*fVal;
2358 rValCount++;
2360 SetError(nErr);
2364 break;
2365 case svMatrix :
2367 ScMatrixRef pMat = PopMatrix();
2368 if (pMat)
2370 SCSIZE nCount = pMat->GetElementCount();
2371 if (pMat->IsNumeric())
2373 for ( SCSIZE i = 0; i < nCount; i++ )
2375 fVal= pMat->GetDouble(i);
2376 fSum += fVal;
2377 fSumSqr += fVal * fVal;
2378 rValCount++;
2381 else
2383 for (SCSIZE i = 0; i < nCount; i++)
2384 if (!pMat->IsString(i))
2386 fVal= pMat->GetDouble(i);
2387 fSum += fVal;
2388 fSumSqr += fVal * fVal;
2389 rValCount++;
2394 break;
2395 default : SetError(errIllegalParameter); break;
2397 if (rValCount <= 1.0)
2398 PushError( errDivisionByZero);
2399 else
2401 mue = fSum/rValCount;
2402 if (nParamCount != 3)
2404 sigma = (fSumSqr - fSum*fSum/rValCount)/(rValCount-1.0);
2405 PushDouble(0.5 - gauss((mue-x)/sqrt(sigma/rValCount)));
2407 else
2408 PushDouble(0.5 - gauss((mue-x)*sqrt(rValCount)/sigma));
2411 bool ScInterpreter::CalculateTest(BOOL _bTemplin
2412 ,const SCSIZE nC1, const SCSIZE nC2,const SCSIZE nR1,const SCSIZE nR2
2413 ,const ScMatrixRef& pMat1,const ScMatrixRef& pMat2
2414 ,double& fT,double& fF)
2416 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CalculateTest" );
2417 double fCount1 = 0.0;
2418 double fCount2 = 0.0;
2419 double fSum1 = 0.0;
2420 double fSumSqr1 = 0.0;
2421 double fSum2 = 0.0;
2422 double fSumSqr2 = 0.0;
2423 double fVal;
2424 SCSIZE i,j;
2425 for (i = 0; i < nC1; i++)
2426 for (j = 0; j < nR1; j++)
2428 if (!pMat1->IsString(i,j))
2430 fVal = pMat1->GetDouble(i,j);
2431 fSum1 += fVal;
2432 fSumSqr1 += fVal * fVal;
2433 fCount1++;
2436 for (i = 0; i < nC2; i++)
2437 for (j = 0; j < nR2; j++)
2439 if (!pMat2->IsString(i,j))
2441 fVal = pMat2->GetDouble(i,j);
2442 fSum2 += fVal;
2443 fSumSqr2 += fVal * fVal;
2444 fCount2++;
2447 if (fCount1 < 2.0 || fCount2 < 2.0)
2449 PushNoValue();
2450 return false;
2451 } // if (fCount1 < 2.0 || fCount2 < 2.0)
2452 if ( _bTemplin )
2454 double fS1 = (fSumSqr1-fSum1*fSum1/fCount1)/(fCount1-1.0)/fCount1;
2455 double fS2 = (fSumSqr2-fSum2*fSum2/fCount2)/(fCount2-1.0)/fCount2;
2456 if (fS1 + fS2 == 0.0)
2458 PushNoValue();
2459 return false;
2461 fT = fabs(fSum1/fCount1 - fSum2/fCount2)/sqrt(fS1+fS2);
2462 double c = fS1/(fS1+fS2);
2463 // s.u. fF = ::rtl::math::approxFloor(1.0/(c*c/(fCount1-1.0)+(1.0-c)*(1.0-c)/(fCount2-1.0)));
2464 // fF = ::rtl::math::approxFloor((fS1+fS2)*(fS1+fS2)/(fS1*fS1/(fCount1-1.0) + fS2*fS2/(fCount2-1.0)));
2466 // GetTDist wird mit GetBetaDist berechnet und kommt auch mit nicht ganzzahligen
2467 // Freiheitsgraden klar. Dann stimmt das Ergebnis auch mit Excel ueberein (#52406#):
2468 fF = 1.0/(c*c/(fCount1-1.0)+(1.0-c)*(1.0-c)/(fCount2-1.0));
2470 else
2472 // laut Bronstein-Semendjajew
2473 double fS1 = (fSumSqr1 - fSum1*fSum1/fCount1) / (fCount1 - 1.0); // Varianz
2474 double fS2 = (fSumSqr2 - fSum2*fSum2/fCount2) / (fCount2 - 1.0);
2475 fT = fabs( fSum1/fCount1 - fSum2/fCount2 ) /
2476 sqrt( (fCount1-1.0)*fS1 + (fCount2-1.0)*fS2 ) *
2477 sqrt( fCount1*fCount2*(fCount1+fCount2-2)/(fCount1+fCount2) );
2478 fF = fCount1 + fCount2 - 2;
2480 return true;
2482 void ScInterpreter::ScTTest()
2484 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTTest" );
2485 if ( !MustHaveParamCount( GetByte(), 4 ) )
2486 return;
2487 double fTyp = ::rtl::math::approxFloor(GetDouble());
2488 double fAnz = ::rtl::math::approxFloor(GetDouble());
2489 if (fAnz != 1.0 && fAnz != 2.0)
2491 PushIllegalArgument();
2492 return;
2495 ScMatrixRef pMat2 = GetMatrix();
2496 ScMatrixRef pMat1 = GetMatrix();
2497 if (!pMat1 || !pMat2)
2499 PushIllegalParameter();
2500 return;
2502 double fT, fF;
2503 SCSIZE nC1, nC2;
2504 SCSIZE nR1, nR2;
2505 SCSIZE i, j;
2506 pMat1->GetDimensions(nC1, nR1);
2507 pMat2->GetDimensions(nC2, nR2);
2508 if (fTyp == 1.0)
2510 if (nC1 != nC2 || nR1 != nR2)
2512 PushIllegalArgument();
2513 return;
2515 double fCount = 0.0;
2516 double fSum1 = 0.0;
2517 double fSum2 = 0.0;
2518 double fSumSqrD = 0.0;
2519 double fVal1, fVal2;
2520 for (i = 0; i < nC1; i++)
2521 for (j = 0; j < nR1; j++)
2523 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
2525 fVal1 = pMat1->GetDouble(i,j);
2526 fVal2 = pMat2->GetDouble(i,j);
2527 fSum1 += fVal1;
2528 fSum2 += fVal2;
2529 fSumSqrD += (fVal1 - fVal2)*(fVal1 - fVal2);
2530 fCount++;
2533 if (fCount < 1.0)
2535 PushNoValue();
2536 return;
2538 fT = sqrt(fCount-1.0) * fabs(fSum1 - fSum2) /
2539 sqrt(fCount * fSumSqrD - (fSum1-fSum2)*(fSum1-fSum2));
2540 fF = fCount - 1.0;
2542 else if (fTyp == 2.0)
2544 CalculateTest(FALSE,nC1, nC2,nR1, nR2,pMat1,pMat2,fT,fF);
2546 else if (fTyp == 3.0)
2548 CalculateTest(TRUE,nC1, nC2,nR1, nR2,pMat1,pMat2,fT,fF);
2551 else
2553 PushIllegalArgument();
2554 return;
2556 if (fAnz == 1.0)
2557 PushDouble(GetTDist(fT, fF));
2558 else
2559 PushDouble(2.0*GetTDist(fT, fF));
2562 void ScInterpreter::ScFTest()
2564 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScFTest" );
2565 if ( !MustHaveParamCount( GetByte(), 2 ) )
2566 return;
2567 ScMatrixRef pMat2 = GetMatrix();
2568 ScMatrixRef pMat1 = GetMatrix();
2569 if (!pMat1 || !pMat2)
2571 PushIllegalParameter();
2572 return;
2574 SCSIZE nC1, nC2;
2575 SCSIZE nR1, nR2;
2576 SCSIZE i, j;
2577 pMat1->GetDimensions(nC1, nR1);
2578 pMat2->GetDimensions(nC2, nR2);
2579 double fCount1 = 0.0;
2580 double fCount2 = 0.0;
2581 double fSum1 = 0.0;
2582 double fSumSqr1 = 0.0;
2583 double fSum2 = 0.0;
2584 double fSumSqr2 = 0.0;
2585 double fVal;
2586 for (i = 0; i < nC1; i++)
2587 for (j = 0; j < nR1; j++)
2589 if (!pMat1->IsString(i,j))
2591 fVal = pMat1->GetDouble(i,j);
2592 fSum1 += fVal;
2593 fSumSqr1 += fVal * fVal;
2594 fCount1++;
2597 for (i = 0; i < nC2; i++)
2598 for (j = 0; j < nR2; j++)
2600 if (!pMat2->IsString(i,j))
2602 fVal = pMat2->GetDouble(i,j);
2603 fSum2 += fVal;
2604 fSumSqr2 += fVal * fVal;
2605 fCount2++;
2608 if (fCount1 < 2.0 || fCount2 < 2.0)
2610 PushNoValue();
2611 return;
2613 double fS1 = (fSumSqr1-fSum1*fSum1/fCount1)/(fCount1-1.0);
2614 double fS2 = (fSumSqr2-fSum2*fSum2/fCount2)/(fCount2-1.0);
2615 if (fS1 == 0.0 || fS2 == 0.0)
2617 PushNoValue();
2618 return;
2620 double fF, fF1, fF2;
2621 if (fS1 > fS2)
2623 fF = fS1/fS2;
2624 fF1 = fCount1-1.0;
2625 fF2 = fCount2-1.0;
2627 else
2629 fF = fS2/fS1;
2630 fF1 = fCount2-1.0;
2631 fF2 = fCount1-1.0;
2633 PushDouble(2.0*GetFDist(fF, fF1, fF2));
2635 double Z = (pow(fF,1.0/3.0)*(1.0-2.0/(9.0*fF2)) - (1.0-2.0/(9.0*fF1))) /
2636 sqrt(2.0/(9.0*fF1) + pow(fF,2.0/3.0)*2.0/(9.0*fF2));
2637 PushDouble(1.0-2.0*gauss(Z));
2641 void ScInterpreter::ScChiTest()
2643 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScChiTest" );
2644 if ( !MustHaveParamCount( GetByte(), 2 ) )
2645 return;
2646 ScMatrixRef pMat2 = GetMatrix();
2647 ScMatrixRef pMat1 = GetMatrix();
2648 if (!pMat1 || !pMat2)
2650 PushIllegalParameter();
2651 return;
2653 SCSIZE nC1, nC2;
2654 SCSIZE nR1, nR2;
2655 pMat1->GetDimensions(nC1, nR1);
2656 pMat2->GetDimensions(nC2, nR2);
2657 if (nR1 != nR2 || nC1 != nC2)
2659 PushIllegalArgument();
2660 return;
2662 double fChi = 0.0;
2663 for (SCSIZE i = 0; i < nC1; i++)
2665 for (SCSIZE j = 0; j < nR1; j++)
2667 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
2669 double fValX = pMat1->GetDouble(i,j);
2670 double fValE = pMat2->GetDouble(i,j);
2671 fChi += (fValX - fValE) * (fValX - fValE) / fValE;
2673 else
2675 PushIllegalArgument();
2676 return;
2680 double fDF;
2681 if (nC1 == 1 || nR1 == 1)
2683 fDF = (double)(nC1*nR1 - 1);
2684 if (fDF == 0.0)
2686 PushNoValue();
2687 return;
2690 else
2691 fDF = (double)(nC1-1)*(double)(nR1-1);
2692 PushDouble(GetChiDist(fChi, fDF));
2694 double fX, fS, fT, fG;
2695 fX = 1.0;
2696 for (double fi = fDF; fi >= 2.0; fi -= 2.0)
2697 fX *= fChi/fi;
2698 fX *= exp(-fChi/2.0);
2699 if (fmod(fDF, 2.0) != 0.0)
2700 fX *= sqrt(2.0*fChi/F_PI);
2701 fS = 1.0;
2702 fT = 1.0;
2703 fG = fDF;
2704 while (fT >= 1.0E-7)
2706 fG += 2.0;
2707 fT *= fChi/fG;
2708 fS += fT;
2710 PushDouble(1.0 - fX*fS);
2714 void ScInterpreter::ScKurt()
2716 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScKurt" );
2717 double fSum,fCount,vSum;
2718 std::vector<double> values;
2719 if ( !CalculateSkew(fSum,fCount,vSum,values) )
2720 return;
2722 if (fCount == 0.0)
2724 PushError( errDivisionByZero);
2725 return;
2728 double fMean = fSum / fCount;
2730 for (size_t i = 0; i < values.size(); i++)
2731 vSum += (values[i] - fMean) * (values[i] - fMean);
2733 double fStdDev = sqrt(vSum / (fCount - 1.0));
2734 double dx = 0.0;
2735 double xpower4 = 0.0;
2737 if (fStdDev == 0.0)
2739 PushError( errDivisionByZero);
2740 return;
2743 for (size_t i = 0; i < values.size(); i++)
2745 dx = (values[i] - fMean) / fStdDev;
2746 xpower4 = xpower4 + (dx * dx * dx * dx);
2749 double k_d = (fCount - 2.0) * (fCount - 3.0);
2750 double k_l = fCount * (fCount + 1.0) / ((fCount - 1.0) * k_d);
2751 double k_t = 3.0 * (fCount - 1.0) * (fCount - 1.0) / k_d;
2753 PushDouble(xpower4 * k_l - k_t);
2756 void ScInterpreter::ScHarMean()
2758 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScHarMean" );
2759 short nParamCount = GetByte();
2760 double nVal = 0.0;
2761 double nValCount = 0.0;
2762 ScAddress aAdr;
2763 ScRange aRange;
2764 size_t nRefInList = 0;
2765 while ((nGlobalError == 0) && (nParamCount-- > 0))
2767 switch (GetStackType())
2769 case formula::svDouble :
2771 double x = GetDouble();
2772 if (x > 0.0)
2774 nVal += 1.0/x;
2775 nValCount++;
2777 else
2778 SetError( errIllegalArgument);
2779 break;
2781 case svSingleRef :
2783 PopSingleRef( aAdr );
2784 ScBaseCell* pCell = GetCell( aAdr );
2785 if (HasCellValueData(pCell))
2787 double x = GetCellValue( aAdr, pCell );
2788 if (x > 0.0)
2790 nVal += 1.0/x;
2791 nValCount++;
2793 else
2794 SetError( errIllegalArgument);
2796 break;
2798 case formula::svDoubleRef :
2799 case svRefList :
2801 USHORT nErr = 0;
2802 PopDoubleRef( aRange, nParamCount, nRefInList);
2803 double nCellVal;
2804 ScValueIterator aValIter(pDok, aRange, glSubTotal);
2805 if (aValIter.GetFirst(nCellVal, nErr))
2807 if (nCellVal > 0.0)
2809 nVal += 1.0/nCellVal;
2810 nValCount++;
2812 else
2813 SetError( errIllegalArgument);
2814 SetError(nErr);
2815 while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
2817 if (nCellVal > 0.0)
2819 nVal += 1.0/nCellVal;
2820 nValCount++;
2822 else
2823 SetError( errIllegalArgument);
2825 SetError(nErr);
2828 break;
2829 case svMatrix :
2831 ScMatrixRef pMat = PopMatrix();
2832 if (pMat)
2834 SCSIZE nCount = pMat->GetElementCount();
2835 if (pMat->IsNumeric())
2837 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
2839 double x = pMat->GetDouble(nElem);
2840 if (x > 0.0)
2842 nVal += 1.0/x;
2843 nValCount++;
2845 else
2846 SetError( errIllegalArgument);
2849 else
2851 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
2852 if (!pMat->IsString(nElem))
2854 double x = pMat->GetDouble(nElem);
2855 if (x > 0.0)
2857 nVal += 1.0/x;
2858 nValCount++;
2860 else
2861 SetError( errIllegalArgument);
2866 break;
2867 default : SetError(errIllegalParameter); break;
2870 if (nGlobalError == 0)
2871 PushDouble((double)nValCount/nVal);
2872 else
2873 PushError( nGlobalError);
2876 void ScInterpreter::ScGeoMean()
2878 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGeoMean" );
2879 short nParamCount = GetByte();
2880 double nVal = 0.0;
2881 double nValCount = 0.0;
2882 ScAddress aAdr;
2883 ScRange aRange;
2885 size_t nRefInList = 0;
2886 while ((nGlobalError == 0) && (nParamCount-- > 0))
2888 switch (GetStackType())
2890 case formula::svDouble :
2892 double x = GetDouble();
2893 if (x > 0.0)
2895 nVal += log(x);
2896 nValCount++;
2898 else
2899 SetError( errIllegalArgument);
2900 break;
2902 case svSingleRef :
2904 PopSingleRef( aAdr );
2905 ScBaseCell* pCell = GetCell( aAdr );
2906 if (HasCellValueData(pCell))
2908 double x = GetCellValue( aAdr, pCell );
2909 if (x > 0.0)
2911 nVal += log(x);
2912 nValCount++;
2914 else
2915 SetError( errIllegalArgument);
2917 break;
2919 case formula::svDoubleRef :
2920 case svRefList :
2922 USHORT nErr = 0;
2923 PopDoubleRef( aRange, nParamCount, nRefInList);
2924 double nCellVal;
2925 ScValueIterator aValIter(pDok, aRange, glSubTotal);
2926 if (aValIter.GetFirst(nCellVal, nErr))
2928 if (nCellVal > 0.0)
2930 nVal += log(nCellVal);
2931 nValCount++;
2933 else
2934 SetError( errIllegalArgument);
2935 SetError(nErr);
2936 while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
2938 if (nCellVal > 0.0)
2940 nVal += log(nCellVal);
2941 nValCount++;
2943 else
2944 SetError( errIllegalArgument);
2946 SetError(nErr);
2949 break;
2950 case svMatrix :
2952 ScMatrixRef pMat = PopMatrix();
2953 if (pMat)
2955 SCSIZE nCount = pMat->GetElementCount();
2956 if (pMat->IsNumeric())
2958 for (SCSIZE ui = 0; ui < nCount; ui++)
2960 double x = pMat->GetDouble(ui);
2961 if (x > 0.0)
2963 nVal += log(x);
2964 nValCount++;
2966 else
2967 SetError( errIllegalArgument);
2970 else
2972 for (SCSIZE ui = 0; ui < nCount; ui++)
2973 if (!pMat->IsString(ui))
2975 double x = pMat->GetDouble(ui);
2976 if (x > 0.0)
2978 nVal += log(x);
2979 nValCount++;
2981 else
2982 SetError( errIllegalArgument);
2987 break;
2988 default : SetError(errIllegalParameter); break;
2991 if (nGlobalError == 0)
2992 PushDouble(exp(nVal / nValCount));
2993 else
2994 PushError( nGlobalError);
2997 void ScInterpreter::ScStandard()
2999 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScStandard" );
3000 if ( MustHaveParamCount( GetByte(), 3 ) )
3002 double sigma = GetDouble();
3003 double mue = GetDouble();
3004 double x = GetDouble();
3005 if (sigma < 0.0)
3006 PushError( errIllegalArgument);
3007 else if (sigma == 0.0)
3008 PushError( errDivisionByZero);
3009 else
3010 PushDouble((x-mue)/sigma);
3013 bool ScInterpreter::CalculateSkew(double& fSum,double& fCount,double& vSum,std::vector<double>& values)
3015 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CalculateSkew" );
3016 short nParamCount = GetByte();
3017 if ( !MustHaveParamCountMin( nParamCount, 1 ) )
3018 return false;
3020 fSum = 0.0;
3021 fCount = 0.0;
3022 vSum = 0.0;
3023 double fVal = 0.0;
3024 ScAddress aAdr;
3025 ScRange aRange;
3026 size_t nRefInList = 0;
3027 while (nParamCount-- > 0)
3029 switch (GetStackType())
3031 case formula::svDouble :
3033 fVal = GetDouble();
3034 fSum += fVal;
3035 values.push_back(fVal);
3036 fCount++;
3038 break;
3039 case svSingleRef :
3041 PopSingleRef( aAdr );
3042 ScBaseCell* pCell = GetCell( aAdr );
3043 if (HasCellValueData(pCell))
3045 fVal = GetCellValue( aAdr, pCell );
3046 fSum += fVal;
3047 values.push_back(fVal);
3048 fCount++;
3051 break;
3052 case formula::svDoubleRef :
3053 case svRefList :
3055 PopDoubleRef( aRange, nParamCount, nRefInList);
3056 USHORT nErr = 0;
3057 ScValueIterator aValIter(pDok, aRange);
3058 if (aValIter.GetFirst(fVal, nErr))
3060 fSum += fVal;
3061 values.push_back(fVal);
3062 fCount++;
3063 SetError(nErr);
3064 while ((nErr == 0) && aValIter.GetNext(fVal, nErr))
3066 fSum += fVal;
3067 values.push_back(fVal);
3068 fCount++;
3070 SetError(nErr);
3073 break;
3074 case svMatrix :
3076 ScMatrixRef pMat = PopMatrix();
3077 if (pMat)
3079 SCSIZE nCount = pMat->GetElementCount();
3080 if (pMat->IsNumeric())
3082 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3084 fVal = pMat->GetDouble(nElem);
3085 fSum += fVal;
3086 values.push_back(fVal);
3087 fCount++;
3090 else
3092 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3093 if (!pMat->IsString(nElem))
3095 fVal = pMat->GetDouble(nElem);
3096 fSum += fVal;
3097 values.push_back(fVal);
3098 fCount++;
3103 break;
3104 default :
3105 SetError(errIllegalParameter);
3106 break;
3110 if (nGlobalError)
3112 PushError( nGlobalError);
3113 return false;
3114 } // if (nGlobalError)
3115 return true;
3118 void ScInterpreter::ScSkew()
3120 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSkew" );
3121 double fSum,fCount,vSum;
3122 std::vector<double> values;
3123 if ( !CalculateSkew(fSum,fCount,vSum,values) )
3124 return;
3126 double fMean = fSum / fCount;
3128 for (size_t i = 0; i < values.size(); i++)
3129 vSum += (values[i] - fMean) * (values[i] - fMean);
3131 double fStdDev = sqrt(vSum / (fCount - 1.0));
3132 double dx = 0.0;
3133 double xcube = 0.0;
3135 if (fStdDev == 0)
3137 PushIllegalArgument();
3138 return;
3141 for (size_t i = 0; i < values.size(); i++)
3143 dx = (values[i] - fMean) / fStdDev;
3144 xcube = xcube + (dx * dx * dx);
3147 PushDouble(((xcube * fCount) / (fCount - 1.0)) / (fCount - 2.0));
3150 double ScInterpreter::GetMedian( vector<double> & rArray )
3152 size_t nSize = rArray.size();
3153 if (rArray.empty() || nSize == 0 || nGlobalError)
3155 SetError( errNoValue);
3156 return 0.0;
3159 // Upper median.
3160 size_t nMid = nSize / 2;
3161 vector<double>::iterator iMid = rArray.begin() + nMid;
3162 ::std::nth_element( rArray.begin(), iMid, rArray.end());
3163 if (nSize & 1)
3164 return *iMid; // Lower and upper median are equal.
3165 else
3167 double fUp = *iMid;
3168 // Lower median.
3169 iMid = rArray.begin() + nMid - 1;
3170 ::std::nth_element( rArray.begin(), iMid, rArray.end());
3171 return (fUp + *iMid) / 2;
3175 void ScInterpreter::ScMedian()
3177 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMedian" );
3178 BYTE nParamCount = GetByte();
3179 if ( !MustHaveParamCountMin( nParamCount, 1 ) )
3180 return;
3181 vector<double> aArray;
3182 GetNumberSequenceArray( nParamCount, aArray);
3183 PushDouble( GetMedian( aArray));
3186 double ScInterpreter::GetPercentile( vector<double> & rArray, double fPercentile )
3188 size_t nSize = rArray.size();
3189 if (rArray.empty() || nSize == 0 || nGlobalError)
3191 SetError( errNoValue);
3192 return 0.0;
3195 if (nSize == 1)
3196 return rArray[0];
3197 else
3199 size_t nIndex = (size_t)::rtl::math::approxFloor( fPercentile * (nSize-1));
3200 double fDiff = fPercentile * (nSize-1) - ::rtl::math::approxFloor( fPercentile * (nSize-1));
3201 DBG_ASSERT(nIndex < nSize, "GetPercentile: wrong index(1)");
3202 vector<double>::iterator iter = rArray.begin() + nIndex;
3203 ::std::nth_element( rArray.begin(), iter, rArray.end());
3204 if (fDiff == 0.0)
3205 return *iter;
3206 else
3208 DBG_ASSERT(nIndex < nSize-1, "GetPercentile: wrong index(2)");
3209 double fVal = *iter;
3210 iter = rArray.begin() + nIndex+1;
3211 ::std::nth_element( rArray.begin(), iter, rArray.end());
3212 return fVal + fDiff * (*iter - fVal);
3217 void ScInterpreter::ScPercentile()
3219 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScPercentile" );
3220 if ( !MustHaveParamCount( GetByte(), 2 ) )
3221 return;
3222 double alpha = GetDouble();
3223 if (alpha < 0.0 || alpha > 1.0)
3225 PushIllegalArgument();
3226 return;
3228 vector<double> aArray;
3229 GetNumberSequenceArray( 1, aArray);
3230 PushDouble( GetPercentile( aArray, alpha));
3233 void ScInterpreter::ScQuartile()
3235 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScQuartile" );
3236 if ( !MustHaveParamCount( GetByte(), 2 ) )
3237 return;
3238 double fFlag = ::rtl::math::approxFloor(GetDouble());
3239 if (fFlag < 0.0 || fFlag > 4.0)
3241 PushIllegalArgument();
3242 return;
3244 vector<double> aArray;
3245 GetNumberSequenceArray( 1, aArray);
3246 PushDouble( fFlag == 2.0 ? GetMedian( aArray) : GetPercentile( aArray, 0.25 * fFlag));
3249 void ScInterpreter::ScModalValue()
3251 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScModalValue" );
3252 BYTE nParamCount = GetByte();
3253 if ( !MustHaveParamCountMin( nParamCount, 1 ) )
3254 return;
3255 vector<double> aSortArray;
3256 GetSortArray(nParamCount, aSortArray);
3257 SCSIZE nSize = aSortArray.size();
3258 if (aSortArray.empty() || nSize == 0 || nGlobalError)
3259 PushNoValue();
3260 else
3262 SCSIZE nMaxIndex = 0, nMax = 1, nCount = 1;
3263 double nOldVal = aSortArray[0];
3264 SCSIZE i;
3266 for ( i = 1; i < nSize; i++)
3268 if (aSortArray[i] == nOldVal)
3269 nCount++;
3270 else
3272 nOldVal = aSortArray[i];
3273 if (nCount > nMax)
3275 nMax = nCount;
3276 nMaxIndex = i-1;
3278 nCount = 1;
3281 if (nCount > nMax)
3283 nMax = nCount;
3284 nMaxIndex = i-1;
3286 if (nMax == 1 && nCount == 1)
3287 PushNoValue();
3288 else if (nMax == 1)
3289 PushDouble(nOldVal);
3290 else
3291 PushDouble(aSortArray[nMaxIndex]);
3295 void ScInterpreter::CalculateSmallLarge(BOOL bSmall)
3297 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CalculateSmallLarge" );
3298 if ( !MustHaveParamCount( GetByte(), 2 ) )
3299 return;
3300 double f = ::rtl::math::approxFloor(GetDouble());
3301 if (f < 1.0)
3303 PushIllegalArgument();
3304 return;
3306 SCSIZE k = static_cast<SCSIZE>(f);
3307 vector<double> aSortArray;
3308 /* TODO: using nth_element() is best for one single value, but LARGE/SMALL
3309 * actually are defined to return an array of values if an array of
3310 * positions was passed, in which case, depending on the number of values,
3311 * we may or will need a real sorted array again, see #i32345. */
3312 //GetSortArray(1, aSortArray);
3313 GetNumberSequenceArray(1, aSortArray);
3314 SCSIZE nSize = aSortArray.size();
3315 if (aSortArray.empty() || nSize == 0 || nGlobalError || nSize < k)
3316 PushNoValue();
3317 else
3319 // TODO: the sorted case for array: PushDouble( aSortArray[ bSmall ? k-1 : nSize-k ] );
3320 vector<double>::iterator iPos = aSortArray.begin() + (bSmall ? k-1 : nSize-k);
3321 ::std::nth_element( aSortArray.begin(), iPos, aSortArray.end());
3322 PushDouble( *iPos);
3326 void ScInterpreter::ScLarge()
3328 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLarge" );
3329 CalculateSmallLarge(FALSE);
3332 void ScInterpreter::ScSmall()
3334 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSmall" );
3335 CalculateSmallLarge(TRUE);
3338 void ScInterpreter::ScPercentrank()
3340 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScPercentrank" );
3341 BYTE nParamCount = GetByte();
3342 if ( !MustHaveParamCount( nParamCount, 2 ) )
3343 return;
3344 #if 0
3345 /* wird nicht unterstuetzt
3346 double fPrec;
3347 if (nParamCount == 3)
3349 fPrec = ::rtl::math::approxFloor(GetDouble());
3350 if (fPrec < 1.0)
3352 PushIllegalArgument();
3353 return;
3356 else
3357 fPrec = 3.0;
3359 #endif
3360 double fNum = GetDouble();
3361 vector<double> aSortArray;
3362 GetSortArray(1, aSortArray);
3363 SCSIZE nSize = aSortArray.size();
3364 if (aSortArray.empty() || nSize == 0 || nGlobalError)
3365 PushNoValue();
3366 else
3368 if (fNum < aSortArray[0] || fNum > aSortArray[nSize-1])
3369 PushNoValue();
3370 else if ( nSize == 1 )
3371 PushDouble(1.0); // fNum == pSortArray[0], see test above
3372 else
3374 double fRes;
3375 SCSIZE nOldCount = 0;
3376 double fOldVal = aSortArray[0];
3377 SCSIZE i;
3378 for (i = 1; i < nSize && aSortArray[i] < fNum; i++)
3380 if (aSortArray[i] != fOldVal)
3382 nOldCount = i;
3383 fOldVal = aSortArray[i];
3386 if (aSortArray[i] != fOldVal)
3387 nOldCount = i;
3388 if (fNum == aSortArray[i])
3389 fRes = (double)nOldCount/(double)(nSize-1);
3390 else
3392 // #75312# nOldCount is the count of smaller entries
3393 // fNum is between pSortArray[nOldCount-1] and pSortArray[nOldCount]
3394 // use linear interpolation to find a position between the entries
3396 if ( nOldCount == 0 )
3398 DBG_ERROR("should not happen");
3399 fRes = 0.0;
3401 else
3403 double fFract = ( fNum - aSortArray[nOldCount-1] ) /
3404 ( aSortArray[nOldCount] - aSortArray[nOldCount-1] );
3405 fRes = ( (double)(nOldCount-1)+fFract )/(double)(nSize-1);
3408 PushDouble(fRes);
3413 void ScInterpreter::ScTrimMean()
3415 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTrimMean" );
3416 if ( !MustHaveParamCount( GetByte(), 2 ) )
3417 return;
3418 double alpha = GetDouble();
3419 if (alpha < 0.0 || alpha >= 1.0)
3421 PushIllegalArgument();
3422 return;
3424 vector<double> aSortArray;
3425 GetSortArray(1, aSortArray);
3426 SCSIZE nSize = aSortArray.size();
3427 if (aSortArray.empty() || nSize == 0 || nGlobalError)
3428 PushNoValue();
3429 else
3431 ULONG nIndex = (ULONG) ::rtl::math::approxFloor(alpha*(double)nSize);
3432 if (nIndex % 2 != 0)
3433 nIndex--;
3434 nIndex /= 2;
3435 DBG_ASSERT(nIndex < nSize, "ScTrimMean: falscher Index");
3436 double fSum = 0.0;
3437 for (SCSIZE i = nIndex; i < nSize-nIndex; i++)
3438 fSum += aSortArray[i];
3439 PushDouble(fSum/(double)(nSize-2*nIndex));
3443 void ScInterpreter::GetNumberSequenceArray( BYTE nParamCount, vector<double>& rArray )
3445 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetSortArray" );
3446 ScAddress aAdr;
3447 ScRange aRange;
3448 short nParam = nParamCount;
3449 size_t nRefInList = 0;
3450 while (nParam-- > 0)
3452 switch (GetStackType())
3454 case formula::svDouble :
3455 rArray.push_back( PopDouble());
3456 break;
3457 case svSingleRef :
3459 PopSingleRef( aAdr );
3460 ScBaseCell* pCell = GetCell( aAdr );
3461 if (HasCellValueData(pCell))
3462 rArray.push_back( GetCellValue( aAdr, pCell));
3464 break;
3465 case formula::svDoubleRef :
3466 case svRefList :
3468 PopDoubleRef( aRange, nParam, nRefInList);
3469 if (nGlobalError)
3470 break;
3472 aRange.Justify();
3473 SCSIZE nCellCount = aRange.aEnd.Col() - aRange.aStart.Col() + 1;
3474 nCellCount *= aRange.aEnd.Row() - aRange.aStart.Row() + 1;
3475 rArray.reserve( rArray.size() + nCellCount);
3477 USHORT nErr = 0;
3478 double fCellVal;
3479 ScValueIterator aValIter(pDok, aRange);
3480 if (aValIter.GetFirst( fCellVal, nErr))
3482 rArray.push_back( fCellVal);
3483 SetError(nErr);
3484 while ((nErr == 0) && aValIter.GetNext( fCellVal, nErr))
3485 rArray.push_back( fCellVal);
3486 SetError(nErr);
3489 break;
3490 case svMatrix :
3492 ScMatrixRef pMat = PopMatrix();
3493 if (!pMat)
3494 break;
3496 SCSIZE nCount = pMat->GetElementCount();
3497 rArray.reserve( rArray.size() + nCount);
3498 if (pMat->IsNumeric())
3500 for (SCSIZE i = 0; i < nCount; ++i)
3501 rArray.push_back( pMat->GetDouble(i));
3503 else
3505 for (SCSIZE i = 0; i < nCount; ++i)
3506 if (!pMat->IsString(i))
3507 rArray.push_back( pMat->GetDouble(i));
3510 break;
3511 default :
3512 PopError();
3513 SetError( errIllegalParameter);
3514 break;
3516 if (nGlobalError)
3517 break; // while
3519 // nParam > 0 in case of error, clean stack environment and obtain earlier
3520 // error if there was one.
3521 while (nParam-- > 0)
3522 PopError();
3525 void ScInterpreter::GetSortArray( BYTE nParamCount, vector<double>& rSortArray, vector<long>* pIndexOrder )
3527 GetNumberSequenceArray( nParamCount, rSortArray);
3529 if (rSortArray.size() > MAX_ANZ_DOUBLE_FOR_SORT)
3530 SetError( errStackOverflow);
3531 else if (rSortArray.empty())
3532 SetError( errNoValue);
3534 if (nGlobalError == 0)
3535 QuickSort( rSortArray, pIndexOrder);
3538 static void lcl_QuickSort( long nLo, long nHi, vector<double>& rSortArray, vector<long>* pIndexOrder )
3540 // If pIndexOrder is not NULL, we assume rSortArray.size() == pIndexOrder->size().
3542 using ::std::swap;
3544 if (nHi - nLo == 1)
3546 if (rSortArray[nLo] > rSortArray[nHi])
3548 swap(rSortArray[nLo], rSortArray[nHi]);
3549 if (pIndexOrder)
3550 swap(pIndexOrder->at(nLo), pIndexOrder->at(nHi));
3552 return;
3555 long ni = nLo;
3556 long nj = nHi;
3559 double fLo = rSortArray[nLo];
3560 while (ni <= nHi && rSortArray[ni] < fLo) ni++;
3561 while (nj >= nLo && fLo < rSortArray[nj]) nj--;
3562 if (ni <= nj)
3564 if (ni != nj)
3566 swap(rSortArray[ni], rSortArray[nj]);
3567 if (pIndexOrder)
3568 swap(pIndexOrder->at(ni), pIndexOrder->at(nj));
3571 ++ni;
3572 --nj;
3575 while (ni < nj);
3577 if ((nj - nLo) < (nHi - ni))
3579 if (nLo < nj) lcl_QuickSort(nLo, nj, rSortArray, pIndexOrder);
3580 if (ni < nHi) lcl_QuickSort(ni, nHi, rSortArray, pIndexOrder);
3582 else
3584 if (ni < nHi) lcl_QuickSort(ni, nHi, rSortArray, pIndexOrder);
3585 if (nLo < nj) lcl_QuickSort(nLo, nj, rSortArray, pIndexOrder);
3589 void ScInterpreter::QuickSort( vector<double>& rSortArray, vector<long>* pIndexOrder )
3591 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::QuickSort" );
3592 long n = static_cast<long>(rSortArray.size());
3594 if (pIndexOrder)
3596 pIndexOrder->clear();
3597 pIndexOrder->reserve(n);
3598 for (long i = 0; i < n; ++i)
3599 pIndexOrder->push_back(i);
3602 if (n < 2)
3603 return;
3605 size_t nValCount = rSortArray.size();
3606 for (size_t i = 0; (i + 4) <= nValCount-1; i += 4)
3608 size_t nInd = rand() % (int) (nValCount-1);
3609 ::std::swap( rSortArray[i], rSortArray[nInd]);
3610 if (pIndexOrder)
3611 ::std::swap( pIndexOrder->at(i), pIndexOrder->at(nInd));
3614 lcl_QuickSort(0, n-1, rSortArray, pIndexOrder);
3617 void ScInterpreter::ScRank()
3619 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRank" );
3620 BYTE nParamCount = GetByte();
3621 if ( !MustHaveParamCount( nParamCount, 2, 3 ) )
3622 return;
3623 BOOL bDescending;
3624 if (nParamCount == 3)
3625 bDescending = GetBool();
3626 else
3627 bDescending = FALSE;
3628 double fCount = 1.0;
3629 BOOL bValid = FALSE;
3630 switch (GetStackType())
3632 case formula::svDouble :
3634 double x = GetDouble();
3635 double fVal = GetDouble();
3636 if (x == fVal)
3637 bValid = TRUE;
3638 break;
3640 case svSingleRef :
3642 ScAddress aAdr;
3643 PopSingleRef( aAdr );
3644 double fVal = GetDouble();
3645 ScBaseCell* pCell = GetCell( aAdr );
3646 if (HasCellValueData(pCell))
3648 double x = GetCellValue( aAdr, pCell );
3649 if (x == fVal)
3650 bValid = TRUE;
3652 break;
3654 case formula::svDoubleRef :
3655 case svRefList :
3657 ScRange aRange;
3658 short nParam = 1;
3659 size_t nRefInList = 0;
3660 while (nParam-- > 0)
3662 USHORT nErr = 0;
3663 // Preserve stack until all RefList elements are done!
3664 USHORT nSaveSP = sp;
3665 PopDoubleRef( aRange, nParam, nRefInList);
3666 if (nParam)
3667 --sp; // simulate pop
3668 double fVal = GetDouble();
3669 if (nParam)
3670 sp = nSaveSP;
3671 double nCellVal;
3672 ScValueIterator aValIter(pDok, aRange, glSubTotal);
3673 if (aValIter.GetFirst(nCellVal, nErr))
3675 if (nCellVal == fVal)
3676 bValid = TRUE;
3677 else if ((!bDescending && nCellVal > fVal) ||
3678 (bDescending && nCellVal < fVal) )
3679 fCount++;
3680 SetError(nErr);
3681 while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
3683 if (nCellVal == fVal)
3684 bValid = TRUE;
3685 else if ((!bDescending && nCellVal > fVal) ||
3686 (bDescending && nCellVal < fVal) )
3687 fCount++;
3690 SetError(nErr);
3693 break;
3694 case svMatrix :
3696 ScMatrixRef pMat = PopMatrix();
3697 double fVal = GetDouble();
3698 if (pMat)
3700 SCSIZE nCount = pMat->GetElementCount();
3701 if (pMat->IsNumeric())
3703 for (SCSIZE i = 0; i < nCount; i++)
3705 double x = pMat->GetDouble(i);
3706 if (x == fVal)
3707 bValid = TRUE;
3708 else if ((!bDescending && x > fVal) ||
3709 (bDescending && x < fVal) )
3710 fCount++;
3713 else
3715 for (SCSIZE i = 0; i < nCount; i++)
3716 if (!pMat->IsString(i))
3718 double x = pMat->GetDouble(i);
3719 if (x == fVal)
3720 bValid = TRUE;
3721 else if ((!bDescending && x > fVal) ||
3722 (bDescending && x < fVal) )
3723 fCount++;
3728 break;
3729 default : SetError(errIllegalParameter); break;
3731 if (bValid)
3732 PushDouble(fCount);
3733 else
3734 PushNoValue();
3737 void ScInterpreter::ScAveDev()
3739 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScAveDev" );
3740 BYTE nParamCount = GetByte();
3741 if ( !MustHaveParamCountMin( nParamCount, 1 ) )
3742 return;
3743 USHORT SaveSP = sp;
3744 double nMiddle = 0.0;
3745 double rVal = 0.0;
3746 double rValCount = 0.0;
3747 ScAddress aAdr;
3748 ScRange aRange;
3749 short nParam = nParamCount;
3750 size_t nRefInList = 0;
3751 while (nParam-- > 0)
3753 switch (GetStackType())
3755 case formula::svDouble :
3756 rVal += GetDouble();
3757 rValCount++;
3758 break;
3759 case svSingleRef :
3761 PopSingleRef( aAdr );
3762 ScBaseCell* pCell = GetCell( aAdr );
3763 if (HasCellValueData(pCell))
3765 rVal += GetCellValue( aAdr, pCell );
3766 rValCount++;
3769 break;
3770 case formula::svDoubleRef :
3771 case svRefList :
3773 USHORT nErr = 0;
3774 double nCellVal;
3775 PopDoubleRef( aRange, nParam, nRefInList);
3776 ScValueIterator aValIter(pDok, aRange);
3777 if (aValIter.GetFirst(nCellVal, nErr))
3779 rVal += nCellVal;
3780 rValCount++;
3781 SetError(nErr);
3782 while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
3784 rVal += nCellVal;
3785 rValCount++;
3787 SetError(nErr);
3790 break;
3791 case svMatrix :
3793 ScMatrixRef pMat = PopMatrix();
3794 if (pMat)
3796 SCSIZE nCount = pMat->GetElementCount();
3797 if (pMat->IsNumeric())
3799 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3801 rVal += pMat->GetDouble(nElem);
3802 rValCount++;
3805 else
3807 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3808 if (!pMat->IsString(nElem))
3810 rVal += pMat->GetDouble(nElem);
3811 rValCount++;
3816 break;
3817 default :
3818 SetError(errIllegalParameter);
3819 break;
3822 if (nGlobalError)
3824 PushError( nGlobalError);
3825 return;
3827 nMiddle = rVal / rValCount;
3828 sp = SaveSP;
3829 rVal = 0.0;
3830 nParam = nParamCount;
3831 nRefInList = 0;
3832 while (nParam-- > 0)
3834 switch (GetStackType())
3836 case formula::svDouble :
3837 rVal += fabs(GetDouble() - nMiddle);
3838 break;
3839 case svSingleRef :
3841 PopSingleRef( aAdr );
3842 ScBaseCell* pCell = GetCell( aAdr );
3843 if (HasCellValueData(pCell))
3844 rVal += fabs(GetCellValue( aAdr, pCell ) - nMiddle);
3846 break;
3847 case formula::svDoubleRef :
3848 case svRefList :
3850 USHORT nErr = 0;
3851 double nCellVal;
3852 PopDoubleRef( aRange, nParam, nRefInList);
3853 ScValueIterator aValIter(pDok, aRange);
3854 if (aValIter.GetFirst(nCellVal, nErr))
3856 rVal += (fabs(nCellVal - nMiddle));
3857 while (aValIter.GetNext(nCellVal, nErr))
3858 rVal += fabs(nCellVal - nMiddle);
3861 break;
3862 case svMatrix :
3864 ScMatrixRef pMat = PopMatrix();
3865 if (pMat)
3867 SCSIZE nCount = pMat->GetElementCount();
3868 if (pMat->IsNumeric())
3870 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3872 rVal += fabs(pMat->GetDouble(nElem) - nMiddle);
3875 else
3877 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3879 if (!pMat->IsString(nElem))
3880 rVal += fabs(pMat->GetDouble(nElem) - nMiddle);
3885 break;
3886 default : SetError(errIllegalParameter); break;
3889 PushDouble(rVal / rValCount);
3892 void ScInterpreter::ScDevSq()
3894 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDevSq" );
3895 double nVal;
3896 double nValCount;
3897 GetStVarParams(nVal, nValCount);
3898 PushDouble(nVal);
3901 void ScInterpreter::ScProbability()
3903 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScProbability" );
3904 BYTE nParamCount = GetByte();
3905 if ( !MustHaveParamCount( nParamCount, 3, 4 ) )
3906 return;
3907 double fUp, fLo;
3908 fUp = GetDouble();
3909 if (nParamCount == 4)
3910 fLo = GetDouble();
3911 else
3912 fLo = fUp;
3913 if (fLo > fUp)
3915 double fTemp = fLo;
3916 fLo = fUp;
3917 fUp = fTemp;
3919 ScMatrixRef pMatP = GetMatrix();
3920 ScMatrixRef pMatW = GetMatrix();
3921 if (!pMatP || !pMatW)
3922 PushIllegalParameter();
3923 else
3925 SCSIZE nC1, nC2;
3926 SCSIZE nR1, nR2;
3927 pMatP->GetDimensions(nC1, nR1);
3928 pMatW->GetDimensions(nC2, nR2);
3929 if (nC1 != nC2 || nR1 != nR2 || nC1 == 0 || nR1 == 0 ||
3930 nC2 == 0 || nR2 == 0)
3931 PushNA();
3932 else
3934 double fSum = 0.0;
3935 double fRes = 0.0;
3936 BOOL bStop = FALSE;
3937 double fP, fW;
3938 SCSIZE nCount1 = nC1 * nR1;
3939 for ( SCSIZE i = 0; i < nCount1 && !bStop; i++ )
3941 if (pMatP->IsValue(i) && pMatW->IsValue(i))
3943 fP = pMatP->GetDouble(i);
3944 fW = pMatW->GetDouble(i);
3945 if (fP < 0.0 || fP > 1.0)
3946 bStop = TRUE;
3947 else
3949 fSum += fP;
3950 if (fW >= fLo && fW <= fUp)
3951 fRes += fP;
3954 else
3955 SetError( errIllegalArgument);
3957 if (bStop || fabs(fSum -1.0) > 1.0E-7)
3958 PushNoValue();
3959 else
3960 PushDouble(fRes);
3965 void ScInterpreter::ScCorrel()
3967 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCorrel" );
3968 // This is identical to ScPearson()
3969 ScPearson();
3972 void ScInterpreter::ScCovar()
3974 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCovar" );
3975 CalculatePearsonCovar(FALSE,FALSE);
3978 void ScInterpreter::ScPearson()
3980 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScPearson" );
3981 CalculatePearsonCovar(TRUE,FALSE);
3983 void ScInterpreter::CalculatePearsonCovar(BOOL _bPearson,BOOL _bStexy)
3985 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CalculatePearsonCovar" );
3986 if ( !MustHaveParamCount( GetByte(), 2 ) )
3987 return;
3988 ScMatrixRef pMat1 = GetMatrix();
3989 ScMatrixRef pMat2 = GetMatrix();
3990 if (!pMat1 || !pMat2)
3992 PushIllegalParameter();
3993 return;
3995 SCSIZE nC1, nC2;
3996 SCSIZE nR1, nR2;
3997 pMat1->GetDimensions(nC1, nR1);
3998 pMat2->GetDimensions(nC2, nR2);
3999 if (nR1 != nR2 || nC1 != nC2)
4001 PushIllegalArgument();
4002 return;
4004 /* #i78250#
4005 * (sum((X-MeanX)(Y-MeanY)))/N equals (SumXY)/N-MeanX*MeanY mathematically,
4006 * but the latter produces wrong results if the absolute values are high,
4007 * for example above 10^8
4009 double fCount = 0.0;
4010 double fSumX = 0.0;
4011 double fSumY = 0.0;
4012 double fSumDeltaXDeltaY = 0.0; // sum of (ValX-MeanX)*(ValY-MeanY)
4013 double fSumSqrDeltaX = 0.0; // sum of (ValX-MeanX)^2
4014 double fSumSqrDeltaY = 0.0; // sum of (ValY-MeanY)^2
4015 for (SCSIZE i = 0; i < nC1; i++)
4017 for (SCSIZE j = 0; j < nR1; j++)
4019 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
4021 double fValX = pMat1->GetDouble(i,j);
4022 double fValY = pMat2->GetDouble(i,j);
4023 fSumX += fValX;
4024 fSumY += fValY;
4025 fCount++;
4029 if (fCount < (_bStexy ? 3.0 : 1.0)) // fCount==1 is handled by checking denominator later on
4030 PushNoValue();
4031 else
4033 const double fMeanX = fSumX / fCount;
4034 const double fMeanY = fSumY / fCount;
4035 for (SCSIZE i = 0; i < nC1; i++)
4037 for (SCSIZE j = 0; j < nR1; j++)
4039 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
4041 const double fValX = pMat1->GetDouble(i,j);
4042 const double fValY = pMat2->GetDouble(i,j);
4043 fSumDeltaXDeltaY += (fValX - fMeanX) * (fValY - fMeanY);
4044 if ( _bPearson )
4046 fSumSqrDeltaX += (fValX - fMeanX) * (fValX - fMeanX);
4047 fSumSqrDeltaY += (fValY - fMeanY) * (fValY - fMeanY);
4051 } // for (SCSIZE i = 0; i < nC1; i++)
4052 if ( _bPearson )
4054 if (fSumSqrDeltaX == 0.0 || ( !_bStexy && fSumSqrDeltaY == 0.0) )
4055 PushError( errDivisionByZero);
4056 else if ( _bStexy )
4057 PushDouble( sqrt( (fSumSqrDeltaY - fSumDeltaXDeltaY *
4058 fSumDeltaXDeltaY / fSumSqrDeltaX) / (fCount-2)));
4059 else
4060 PushDouble( fSumDeltaXDeltaY / sqrt( fSumSqrDeltaX * fSumSqrDeltaY));
4061 } // if ( _bPearson )
4062 else
4064 PushDouble( fSumDeltaXDeltaY / fCount);
4069 void ScInterpreter::ScRSQ()
4071 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRSQ" );
4072 // Same as ScPearson()*ScPearson()
4073 ScPearson();
4074 if (!nGlobalError)
4076 switch (GetStackType())
4078 case formula::svDouble:
4080 double fVal = PopDouble();
4081 PushDouble( fVal * fVal);
4083 break;
4084 default:
4085 PopError();
4086 PushNoValue();
4091 void ScInterpreter::ScSTEXY()
4093 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSTEXY" );
4094 CalculatePearsonCovar(TRUE,TRUE);
4096 void ScInterpreter::CalculateSlopeIntercept(BOOL bSlope)
4098 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CalculateSlopeIntercept" );
4099 if ( !MustHaveParamCount( GetByte(), 2 ) )
4100 return;
4101 ScMatrixRef pMat1 = GetMatrix();
4102 ScMatrixRef pMat2 = GetMatrix();
4103 if (!pMat1 || !pMat2)
4105 PushIllegalParameter();
4106 return;
4108 SCSIZE nC1, nC2;
4109 SCSIZE nR1, nR2;
4110 pMat1->GetDimensions(nC1, nR1);
4111 pMat2->GetDimensions(nC2, nR2);
4112 if (nR1 != nR2 || nC1 != nC2)
4114 PushIllegalArgument();
4115 return;
4117 // #i78250# numerical stability improved
4118 double fCount = 0.0;
4119 double fSumX = 0.0;
4120 double fSumY = 0.0;
4121 double fSumDeltaXDeltaY = 0.0; // sum of (ValX-MeanX)*(ValY-MeanY)
4122 double fSumSqrDeltaX = 0.0; // sum of (ValX-MeanX)^2
4123 for (SCSIZE i = 0; i < nC1; i++)
4125 for (SCSIZE j = 0; j < nR1; j++)
4127 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
4129 double fValX = pMat1->GetDouble(i,j);
4130 double fValY = pMat2->GetDouble(i,j);
4131 fSumX += fValX;
4132 fSumY += fValY;
4133 fCount++;
4137 if (fCount < 1.0)
4138 PushNoValue();
4139 else
4141 double fMeanX = fSumX / fCount;
4142 double fMeanY = fSumY / fCount;
4143 for (SCSIZE i = 0; i < nC1; i++)
4145 for (SCSIZE j = 0; j < nR1; j++)
4147 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
4149 double fValX = pMat1->GetDouble(i,j);
4150 double fValY = pMat2->GetDouble(i,j);
4151 fSumDeltaXDeltaY += (fValX - fMeanX) * (fValY - fMeanY);
4152 fSumSqrDeltaX += (fValX - fMeanX) * (fValX - fMeanX);
4156 if (fSumSqrDeltaX == 0.0)
4157 PushError( errDivisionByZero);
4158 else
4160 if ( bSlope )
4161 PushDouble( fSumDeltaXDeltaY / fSumSqrDeltaX);
4162 else
4163 PushDouble( fMeanY - fSumDeltaXDeltaY / fSumSqrDeltaX * fMeanX);
4168 void ScInterpreter::ScSlope()
4170 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSlope" );
4171 CalculateSlopeIntercept(TRUE);
4174 void ScInterpreter::ScIntercept()
4176 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIntercept" );
4177 CalculateSlopeIntercept(FALSE);
4180 void ScInterpreter::ScForecast()
4182 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScForecast" );
4183 if ( !MustHaveParamCount( GetByte(), 3 ) )
4184 return;
4185 ScMatrixRef pMat1 = GetMatrix();
4186 ScMatrixRef pMat2 = GetMatrix();
4187 if (!pMat1 || !pMat2)
4189 PushIllegalParameter();
4190 return;
4192 SCSIZE nC1, nC2;
4193 SCSIZE nR1, nR2;
4194 pMat1->GetDimensions(nC1, nR1);
4195 pMat2->GetDimensions(nC2, nR2);
4196 if (nR1 != nR2 || nC1 != nC2)
4198 PushIllegalArgument();
4199 return;
4201 double fVal = GetDouble();
4202 // #i78250# numerical stability improved
4203 double fCount = 0.0;
4204 double fSumX = 0.0;
4205 double fSumY = 0.0;
4206 double fSumDeltaXDeltaY = 0.0; // sum of (ValX-MeanX)*(ValY-MeanY)
4207 double fSumSqrDeltaX = 0.0; // sum of (ValX-MeanX)^2
4208 for (SCSIZE i = 0; i < nC1; i++)
4210 for (SCSIZE j = 0; j < nR1; j++)
4212 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
4214 double fValX = pMat1->GetDouble(i,j);
4215 double fValY = pMat2->GetDouble(i,j);
4216 fSumX += fValX;
4217 fSumY += fValY;
4218 fCount++;
4222 if (fCount < 1.0)
4223 PushNoValue();
4224 else
4226 double fMeanX = fSumX / fCount;
4227 double fMeanY = fSumY / fCount;
4228 for (SCSIZE i = 0; i < nC1; i++)
4230 for (SCSIZE j = 0; j < nR1; j++)
4232 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
4234 double fValX = pMat1->GetDouble(i,j);
4235 double fValY = pMat2->GetDouble(i,j);
4236 fSumDeltaXDeltaY += (fValX - fMeanX) * (fValY - fMeanY);
4237 fSumSqrDeltaX += (fValX - fMeanX) * (fValX - fMeanX);
4241 if (fSumSqrDeltaX == 0.0)
4242 PushError( errDivisionByZero);
4243 else
4244 PushDouble( fMeanY + fSumDeltaXDeltaY / fSumSqrDeltaX * (fVal - fMeanX));