fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / core / tool / interpr3.cxx
blobec2fbdc210caa3f40b619fa77e2d6d2a25b12dad
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <tools/solar.h>
21 #include <stdlib.h>
22 #include <string.h>
24 #include "interpre.hxx"
25 #include "global.hxx"
26 #include "compiler.hxx"
27 #include "formulacell.hxx"
28 #include "document.hxx"
29 #include "dociter.hxx"
30 #include "scmatrix.hxx"
31 #include "globstr.hrc"
33 #include <math.h>
34 #include <vector>
35 #include <algorithm>
36 #include <boost/math/special_functions/log1p.hpp>
37 #include <comphelper/random.hxx>
39 using ::std::vector;
40 using namespace formula;
42 // STATIC DATA
43 #define MAX_ANZ_DOUBLE_FOR_SORT 100000
45 const double ScInterpreter::fMaxGammaArgument = 171.624376956302; // found experimental
46 const double fMachEps = ::std::numeric_limits<double>::epsilon();
48 class ScDistFunc
50 public:
51 virtual double GetValue(double x) const = 0;
53 protected:
54 ~ScDistFunc() {}
57 // iteration for inverse distributions
59 //template< class T > double lcl_IterateInverse( const T& rFunction, double x0, double x1, bool& rConvError )
61 /** u*w<0.0 fails for values near zero */
62 static inline bool lcl_HasChangeOfSign( double u, double w )
64 return (u < 0.0 && w > 0.0) || (u > 0.0 && w < 0.0);
67 static double lcl_IterateInverse( const ScDistFunc& rFunction, double fAx, double fBx, bool& rConvError )
69 rConvError = false;
70 const double fYEps = 1.0E-307;
71 const double fXEps = ::std::numeric_limits<double>::epsilon();
73 OSL_ENSURE(fAx<fBx, "IterateInverse: wrong interval");
75 // find enclosing interval
77 double fAy = rFunction.GetValue(fAx);
78 double fBy = rFunction.GetValue(fBx);
79 double fTemp;
80 unsigned short nCount;
81 for (nCount = 0; nCount < 1000 && !lcl_HasChangeOfSign(fAy,fBy); nCount++)
83 if (fabs(fAy) <= fabs(fBy))
85 fTemp = fAx;
86 fAx += 2.0 * (fAx - fBx);
87 if (fAx < 0.0)
88 fAx = 0.0;
89 fBx = fTemp;
90 fBy = fAy;
91 fAy = rFunction.GetValue(fAx);
93 else
95 fTemp = fBx;
96 fBx += 2.0 * (fBx - fAx);
97 fAx = fTemp;
98 fAy = fBy;
99 fBy = rFunction.GetValue(fBx);
103 if (fAy == 0.0)
104 return fAx;
105 if (fBy == 0.0)
106 return fBx;
107 if (!lcl_HasChangeOfSign( fAy, fBy))
109 rConvError = true;
110 return 0.0;
112 // inverse quadric interpolation with additional brackets
113 // set three points
114 double fPx = fAx;
115 double fPy = fAy;
116 double fQx = fBx;
117 double fQy = fBy;
118 double fRx = fAx;
119 double fRy = fAy;
120 double fSx = 0.5 * (fAx + fBx); // potential next point
121 bool bHasToInterpolate = true;
122 nCount = 0;
123 while ( nCount < 500 && fabs(fRy) > fYEps &&
124 (fBx-fAx) > ::std::max( fabs(fAx), fabs(fBx)) * fXEps )
126 if (bHasToInterpolate)
128 if (fPy!=fQy && fQy!=fRy && fRy!=fPy)
130 fSx = fPx * fRy * fQy / (fRy-fPy) / (fQy-fPy)
131 + fRx * fQy * fPy / (fQy-fRy) / (fPy-fRy)
132 + fQx * fPy * fRy / (fPy-fQy) / (fRy-fQy);
133 bHasToInterpolate = (fAx < fSx) && (fSx < fBx); // inside the brackets?
135 else
136 bHasToInterpolate = false;
138 if(!bHasToInterpolate)
140 fSx = 0.5 * (fAx + fBx);
141 // reset points
142 fQx = fBx; fQy = fBy;
143 bHasToInterpolate = true;
145 // shift points for next interpolation
146 fPx = fQx; fQx = fRx; fRx = fSx;
147 fPy = fQy; fQy = fRy; fRy = rFunction.GetValue(fSx);
148 // update brackets
149 if (lcl_HasChangeOfSign( fAy, fRy))
151 fBx = fRx; fBy = fRy;
153 else
155 fAx = fRx; fAy = fRy;
157 // if last interration brought to small advance, then do bisection next
158 // time, for safety
159 bHasToInterpolate = bHasToInterpolate && (fabs(fRy) * 2.0 <= fabs(fQy));
160 ++nCount;
162 return fRx;
165 // Allgemeine Funktionen
167 void ScInterpreter::ScNoName()
169 PushError(errNoName);
172 void ScInterpreter::ScBadName()
174 short nParamCount = GetByte();
175 while (nParamCount-- > 0)
177 PopError();
179 PushError( errNoName);
182 double ScInterpreter::phi(double x)
184 return 0.39894228040143268 * exp(-(x * x) / 2.0);
187 double ScInterpreter::integralPhi(double x)
188 { // Using gauss(x)+0.5 has severe cancellation errors for x<-4
189 return 0.5 * ::rtl::math::erfc(-x * 0.7071067811865475); // * 1/sqrt(2)
192 double ScInterpreter::taylor(const double* pPolynom, sal_uInt16 nMax, double x)
194 double nVal = pPolynom[nMax];
195 for (short i = nMax-1; i >= 0; i--)
197 nVal = pPolynom[i] + (nVal * x);
199 return nVal;
202 double ScInterpreter::gauss(double x)
205 double xAbs = fabs(x);
206 sal_uInt16 xShort = (sal_uInt16)::rtl::math::approxFloor(xAbs);
207 double nVal = 0.0;
208 if (xShort == 0)
210 static const double t0[] =
211 { 0.39894228040143268, -0.06649038006690545, 0.00997355701003582,
212 -0.00118732821548045, 0.00011543468761616, -0.00000944465625950,
213 0.00000066596935163, -0.00000004122667415, 0.00000000227352982,
214 0.00000000011301172, 0.00000000000511243, -0.00000000000021218 };
215 nVal = taylor(t0, 11, (xAbs * xAbs)) * xAbs;
217 else if ((xShort >= 1) && (xShort <= 2))
219 static const double t2[] =
220 { 0.47724986805182079, 0.05399096651318805, -0.05399096651318805,
221 0.02699548325659403, -0.00449924720943234, -0.00224962360471617,
222 0.00134977416282970, -0.00011783742691370, -0.00011515930357476,
223 0.00003704737285544, 0.00000282690796889, -0.00000354513195524,
224 0.00000037669563126, 0.00000019202407921, -0.00000005226908590,
225 -0.00000000491799345, 0.00000000366377919, -0.00000000015981997,
226 -0.00000000017381238, 0.00000000002624031, 0.00000000000560919,
227 -0.00000000000172127, -0.00000000000008634, 0.00000000000007894 };
228 nVal = taylor(t2, 23, (xAbs - 2.0));
230 else if ((xShort >= 3) && (xShort <= 4))
232 static const double t4[] =
233 { 0.49996832875816688, 0.00013383022576489, -0.00026766045152977,
234 0.00033457556441221, -0.00028996548915725, 0.00018178605666397,
235 -0.00008252863922168, 0.00002551802519049, -0.00000391665839292,
236 -0.00000074018205222, 0.00000064422023359, -0.00000017370155340,
237 0.00000000909595465, 0.00000000944943118, -0.00000000329957075,
238 0.00000000029492075, 0.00000000011874477, -0.00000000004420396,
239 0.00000000000361422, 0.00000000000143638, -0.00000000000045848 };
240 nVal = taylor(t4, 20, (xAbs - 4.0));
242 else
244 static const double asympt[] = { -1.0, 1.0, -3.0, 15.0, -105.0 };
245 nVal = 0.5 + phi(xAbs) * taylor(asympt, 4, 1.0 / (xAbs * xAbs)) / xAbs;
247 if (x < 0.0)
248 return -nVal;
249 else
250 return nVal;
253 // #i26836# new gaussinv implementation by Martin Eitzenberger <m.eitzenberger@unix.net>
255 double ScInterpreter::gaussinv(double x)
257 double q,t,z;
259 q=x-0.5;
261 if(fabs(q)<=.425)
263 t=0.180625-q*q;
274 t*2509.0809287301226727+33430.575583588128105
276 *t+67265.770927008700853
278 *t+45921.953931549871457
280 *t+13731.693765509461125
282 *t+1971.5909503065514427
284 *t+133.14166789178437745
286 *t+3.387132872796366608
296 t*5226.495278852854561+28729.085735721942674
298 *t+39307.89580009271061
300 *t+21213.794301586595867
302 *t+5394.1960214247511077
304 *t+687.1870074920579083
306 *t+42.313330701600911252
308 *t+1.0
312 else
314 if(q>0) t=1-x;
315 else t=x;
317 t=sqrt(-log(t));
319 if(t<=5.0)
321 t+=-1.6;
331 t*7.7454501427834140764e-4+0.0227238449892691845833
333 *t+0.24178072517745061177
335 *t+1.27045825245236838258
337 *t+3.64784832476320460504
339 *t+5.7694972214606914055
341 *t+4.6303378461565452959
343 *t+1.42343711074968357734
353 t*1.05075007164441684324e-9+5.475938084995344946e-4
355 *t+0.0151986665636164571966
357 *t+0.14810397642748007459
359 *t+0.68976733498510000455
361 *t+1.6763848301838038494
363 *t+2.05319162663775882187
365 *t+1.0
369 else
371 t+=-5.0;
381 t*2.01033439929228813265e-7+2.71155556874348757815e-5
383 *t+0.0012426609473880784386
385 *t+0.026532189526576123093
387 *t+0.29656057182850489123
389 *t+1.7848265399172913358
391 *t+5.4637849111641143699
393 *t+6.6579046435011037772
403 t*2.04426310338993978564e-15+1.4215117583164458887e-7
405 *t+1.8463183175100546818e-5
407 *t+7.868691311456132591e-4
409 *t+0.0148753612908506148525
411 *t+0.13692988092273580531
413 *t+0.59983220655588793769
415 *t+1.0
420 if(q<0.0) z=-z;
423 return z;
426 double ScInterpreter::Fakultaet(double x)
428 x = ::rtl::math::approxFloor(x);
429 if (x < 0.0)
430 return 0.0;
431 else if (x == 0.0)
432 return 1.0;
433 else if (x <= 170.0)
435 double fTemp = x;
436 while (fTemp > 2.0)
438 fTemp--;
439 x *= fTemp;
442 else
443 SetError(errNoValue);
444 return x;
447 double ScInterpreter::BinomKoeff(double n, double k)
449 // this method has been duplicated as BinomialCoefficient()
450 // in scaddins/source/analysis/analysishelper.cxx
452 double nVal = 0.0;
453 k = ::rtl::math::approxFloor(k);
454 if (n < k)
455 nVal = 0.0;
456 else if (k == 0.0)
457 nVal = 1.0;
458 else
460 nVal = n/k;
461 n--;
462 k--;
463 while (k > 0.0)
465 nVal *= n/k;
466 k--;
467 n--;
471 return nVal;
474 // The algorithm is based on lanczos13m53 in lanczos.hpp
475 // in math library from http://www.boost.org
476 /** you must ensure fZ>0
477 Uses a variant of the Lanczos sum with a rational function. */
478 static double lcl_getLanczosSum(double fZ)
480 static const double fNum[13] ={
481 23531376880.41075968857200767445163675473,
482 42919803642.64909876895789904700198885093,
483 35711959237.35566804944018545154716670596,
484 17921034426.03720969991975575445893111267,
485 6039542586.35202800506429164430729792107,
486 1439720407.311721673663223072794912393972,
487 248874557.8620541565114603864132294232163,
488 31426415.58540019438061423162831820536287,
489 2876370.628935372441225409051620849613599,
490 186056.2653952234950402949897160456992822,
491 8071.672002365816210638002902272250613822,
492 210.8242777515793458725097339207133627117,
493 2.506628274631000270164908177133837338626
495 static const double fDenom[13] = {
497 39916800,
498 120543840,
499 150917976,
500 105258076,
501 45995730,
502 13339535,
503 2637558,
504 357423,
505 32670,
506 1925,
510 // Horner scheme
511 double fSumNum;
512 double fSumDenom;
513 int nI;
514 if (fZ<=1.0)
516 fSumNum = fNum[12];
517 fSumDenom = fDenom[12];
518 for (nI = 11; nI >= 0; --nI)
520 fSumNum *= fZ;
521 fSumNum += fNum[nI];
522 fSumDenom *= fZ;
523 fSumDenom += fDenom[nI];
526 else
527 // Cancel down with fZ^12; Horner scheme with reverse coefficients
529 double fZInv = 1/fZ;
530 fSumNum = fNum[0];
531 fSumDenom = fDenom[0];
532 for (nI = 1; nI <=12; ++nI)
534 fSumNum *= fZInv;
535 fSumNum += fNum[nI];
536 fSumDenom *= fZInv;
537 fSumDenom += fDenom[nI];
540 return fSumNum/fSumDenom;
543 // The algorithm is based on tgamma in gamma.hpp
544 // in math library from http://www.boost.org
545 /** You must ensure fZ>0; fZ>171.624376956302 will overflow. */
546 static double lcl_GetGammaHelper(double fZ)
548 double fGamma = lcl_getLanczosSum(fZ);
549 const double fg = 6.024680040776729583740234375;
550 double fZgHelp = fZ + fg - 0.5;
551 // avoid intermediate overflow
552 double fHalfpower = pow( fZgHelp, fZ / 2 - 0.25);
553 fGamma *= fHalfpower;
554 fGamma /= exp(fZgHelp);
555 fGamma *= fHalfpower;
556 if (fZ <= 20.0 && fZ == ::rtl::math::approxFloor(fZ))
557 fGamma = ::rtl::math::round(fGamma);
558 return fGamma;
561 // The algorithm is based on tgamma in gamma.hpp
562 // in math library from http://www.boost.org
563 /** You must ensure fZ>0 */
564 static double lcl_GetLogGammaHelper(double fZ)
566 const double fg = 6.024680040776729583740234375;
567 double fZgHelp = fZ + fg - 0.5;
568 return log( lcl_getLanczosSum(fZ)) + (fZ-0.5) * log(fZgHelp) - fZgHelp;
571 /** You must ensure non integer arguments for fZ<1 */
572 double ScInterpreter::GetGamma(double fZ)
574 const double fLogPi = log(F_PI);
575 const double fLogDblMax = log( ::std::numeric_limits<double>::max());
577 if (fZ > fMaxGammaArgument)
579 SetError(errIllegalFPOperation);
580 return HUGE_VAL;
583 if (fZ >= 1.0)
584 return lcl_GetGammaHelper(fZ);
586 if (fZ >= 0.5) // shift to x>=1 using Gamma(x)=Gamma(x+1)/x
587 return lcl_GetGammaHelper(fZ+1) / fZ;
589 if (fZ >= -0.5) // shift to x>=1, might overflow
591 double fLogTest = lcl_GetLogGammaHelper(fZ+2) - boost::math::log1p(fZ) - log( fabs(fZ));
592 if (fLogTest >= fLogDblMax)
594 SetError( errIllegalFPOperation);
595 return HUGE_VAL;
597 return lcl_GetGammaHelper(fZ+2) / (fZ+1) / fZ;
599 // fZ<-0.5
600 // Use Euler's reflection formula: gamma(x)= pi/ ( gamma(1-x)*sin(pi*x) )
601 double fLogDivisor = lcl_GetLogGammaHelper(1-fZ) + log( fabs( ::rtl::math::sin( F_PI*fZ)));
602 if (fLogDivisor - fLogPi >= fLogDblMax) // underflow
603 return 0.0;
605 if (fLogDivisor<0.0)
606 if (fLogPi - fLogDivisor > fLogDblMax) // overflow
608 SetError(errIllegalFPOperation);
609 return HUGE_VAL;
612 return exp( fLogPi - fLogDivisor) * ((::rtl::math::sin( F_PI*fZ) < 0.0) ? -1.0 : 1.0);
615 /** You must ensure fZ>0 */
616 double ScInterpreter::GetLogGamma(double fZ)
618 if (fZ >= fMaxGammaArgument)
619 return lcl_GetLogGammaHelper(fZ);
620 if (fZ >= 1.0)
621 return log(lcl_GetGammaHelper(fZ));
622 if (fZ >= 0.5)
623 return log( lcl_GetGammaHelper(fZ+1) / fZ);
624 return lcl_GetLogGammaHelper(fZ+2) - boost::math::log1p(fZ) - log(fZ);
627 double ScInterpreter::GetFDist(double x, double fF1, double fF2)
629 double arg = fF2/(fF2+fF1*x);
630 double alpha = fF2/2.0;
631 double beta = fF1/2.0;
632 return GetBetaDist(arg, alpha, beta);
635 double ScInterpreter::GetTDist( double T, double fDF, int nType )
637 switch ( nType )
639 case 1 : // 1-tailed T-distribution
640 return 0.5 * GetBetaDist( fDF / ( fDF + T * T ), fDF / 2.0, 0.5 );
641 case 2 : // 2-tailed T-distribution
642 return GetBetaDist( fDF / ( fDF + T * T ), fDF / 2.0, 0.5);
643 case 3 : // left-tailed T-distribution (probability density function)
644 return pow( 1 + ( T * T / fDF ), -( fDF + 1 ) / 2 ) / ( sqrt( fDF ) * GetBeta( 0.5, fDF / 2.0 ) );
645 case 4 : // left-tailed T-distribution (cumulative distribution function)
646 double X = fDF / ( T * T + fDF );
647 double R = 0.5 * GetBetaDist( X, 0.5 * fDF, 0.5 );
648 return ( T < 0 ? R : 1 - R );
650 SetError( errIllegalArgument );
651 return HUGE_VAL;
654 // for LEGACY.CHIDIST, returns right tail, fDF=degrees of freedom
655 /** You must ensure fDF>0.0 */
656 double ScInterpreter::GetChiDist(double fX, double fDF)
658 if (fX <= 0.0)
659 return 1.0; // see ODFF
660 else
661 return GetUpRegIGamma( fDF/2.0, fX/2.0);
664 // ready for ODF 1.2
665 // for ODF CHISQDIST; cumulative distribution function, fDF=degrees of freedom
666 // returns left tail
667 /** You must ensure fDF>0.0 */
668 double ScInterpreter::GetChiSqDistCDF(double fX, double fDF)
670 if (fX <= 0.0)
671 return 0.0; // see ODFF
672 else
673 return GetLowRegIGamma( fDF/2.0, fX/2.0);
676 double ScInterpreter::GetChiSqDistPDF(double fX, double fDF)
678 // you must ensure fDF is positive integer
679 double fValue;
680 if (fX <= 0.0)
681 return 0.0; // see ODFF
682 if (fDF*fX > 1391000.0)
684 // intermediate invalid values, use log
685 fValue = exp((0.5*fDF - 1) * log(fX*0.5) - 0.5 * fX - log(2.0) - GetLogGamma(0.5*fDF));
687 else // fDF is small in most cases, we can iterate
689 double fCount;
690 if (fmod(fDF,2.0)<0.5)
692 // even
693 fValue = 0.5;
694 fCount = 2.0;
696 else
698 fValue = 1/sqrt(fX*2*F_PI);
699 fCount = 1.0;
701 while ( fCount < fDF)
703 fValue *= (fX / fCount);
704 fCount += 2.0;
706 if (fX>=1425.0) // underflow in e^(-x/2)
707 fValue = exp(log(fValue)-fX/2);
708 else
709 fValue *= exp(-fX/2);
711 return fValue;
714 void ScInterpreter::ScChiSqDist()
716 sal_uInt8 nParamCount = GetByte();
717 if ( !MustHaveParamCount( nParamCount, 2, 3 ) )
718 return;
719 bool bCumulative;
720 if (nParamCount == 3)
721 bCumulative = GetBool();
722 else
723 bCumulative = true;
724 double fDF = ::rtl::math::approxFloor(GetDouble());
725 if (fDF < 1.0)
726 PushIllegalArgument();
727 else
729 double fX = GetDouble();
730 if (bCumulative)
731 PushDouble(GetChiSqDistCDF(fX,fDF));
732 else
733 PushDouble(GetChiSqDistPDF(fX,fDF));
737 void ScInterpreter::ScChiSqDist_MS()
739 sal_uInt8 nParamCount = GetByte();
740 if ( !MustHaveParamCount( nParamCount, 3, 3 ) )
741 return;
742 bool bCumulative = GetBool();
743 double fDF = ::rtl::math::approxFloor( GetDouble() );
744 if ( fDF < 1.0 || fDF > 1E10 )
745 PushIllegalArgument();
746 else
748 double fX = GetDouble();
749 if ( fX < 0 )
750 PushIllegalArgument();
751 else
753 if ( bCumulative )
754 PushDouble( GetChiSqDistCDF( fX, fDF ) );
755 else
756 PushDouble( GetChiSqDistPDF( fX, fDF ) );
761 void ScInterpreter::ScGamma()
763 double x = GetDouble();
764 if (x <= 0.0 && x == ::rtl::math::approxFloor(x))
765 PushIllegalArgument();
766 else
768 double fResult = GetGamma(x);
769 if (nGlobalError)
771 PushError( nGlobalError);
772 return;
774 PushDouble(fResult);
778 void ScInterpreter::ScLogGamma()
780 double x = GetDouble();
781 if (x > 0.0) // constraint from ODFF
782 PushDouble( GetLogGamma(x));
783 else
784 PushIllegalArgument();
787 double ScInterpreter::GetBeta(double fAlpha, double fBeta)
789 double fA;
790 double fB;
791 if (fAlpha > fBeta)
793 fA = fAlpha; fB = fBeta;
795 else
797 fA = fBeta; fB = fAlpha;
799 if (fA+fB < fMaxGammaArgument) // simple case
800 return GetGamma(fA)/GetGamma(fA+fB)*GetGamma(fB);
801 // need logarithm
802 // GetLogGamma is not accurate enough, back to Lanczos for all three
803 // GetGamma and arrange factors newly.
804 const double fg = 6.024680040776729583740234375; //see GetGamma
805 double fgm = fg - 0.5;
806 double fLanczos = lcl_getLanczosSum(fA);
807 fLanczos /= lcl_getLanczosSum(fA+fB);
808 fLanczos *= lcl_getLanczosSum(fB);
809 double fABgm = fA+fB+fgm;
810 fLanczos *= sqrt((fABgm/(fA+fgm))/(fB+fgm));
811 double fTempA = fB/(fA+fgm); // (fA+fgm)/fABgm = 1 / ( 1 + fB/(fA+fgm))
812 double fTempB = fA/(fB+fgm);
813 double fResult = exp(-fA * ::rtl::math::log1p(fTempA)
814 -fB * ::rtl::math::log1p(fTempB)-fgm);
815 fResult *= fLanczos;
816 return fResult;
819 // Same as GetBeta but with logarithm
820 double ScInterpreter::GetLogBeta(double fAlpha, double fBeta)
822 double fA;
823 double fB;
824 if (fAlpha > fBeta)
826 fA = fAlpha; fB = fBeta;
828 else
830 fA = fBeta; fB = fAlpha;
832 const double fg = 6.024680040776729583740234375; //see GetGamma
833 double fgm = fg - 0.5;
834 double fLanczos = lcl_getLanczosSum(fA);
835 fLanczos /= lcl_getLanczosSum(fA+fB);
836 fLanczos *= lcl_getLanczosSum(fB);
837 double fLogLanczos = log(fLanczos);
838 double fABgm = fA+fB+fgm;
839 fLogLanczos += 0.5*(log(fABgm)-log(fA+fgm)-log(fB+fgm));
840 double fTempA = fB/(fA+fgm); // (fA+fgm)/fABgm = 1 / ( 1 + fB/(fA+fgm))
841 double fTempB = fA/(fB+fgm);
842 double fResult = -fA * ::rtl::math::log1p(fTempA)
843 -fB * ::rtl::math::log1p(fTempB)-fgm;
844 fResult += fLogLanczos;
845 return fResult;
848 // beta distribution probability density function
849 double ScInterpreter::GetBetaDistPDF(double fX, double fA, double fB)
851 // special cases
852 if (fA == 1.0) // result b*(1-x)^(b-1)
854 if (fB == 1.0)
855 return 1.0;
856 if (fB == 2.0)
857 return -2.0*fX + 2.0;
858 if (fX == 1.0 && fB < 1.0)
860 SetError(errIllegalArgument);
861 return HUGE_VAL;
863 if (fX <= 0.01)
864 return fB + fB * ::rtl::math::expm1((fB-1.0) * ::rtl::math::log1p(-fX));
865 else
866 return fB * pow(0.5-fX+0.5,fB-1.0);
868 if (fB == 1.0) // result a*x^(a-1)
870 if (fA == 2.0)
871 return fA * fX;
872 if (fX == 0.0 && fA < 1.0)
874 SetError(errIllegalArgument);
875 return HUGE_VAL;
877 return fA * pow(fX,fA-1);
879 if (fX <= 0.0)
881 if (fA < 1.0 && fX == 0.0)
883 SetError(errIllegalArgument);
884 return HUGE_VAL;
886 else
887 return 0.0;
889 if (fX >= 1.0)
891 if (fB < 1.0 && fX == 1.0)
893 SetError(errIllegalArgument);
894 return HUGE_VAL;
896 else
897 return 0.0;
900 // normal cases; result x^(a-1)*(1-x)^(b-1)/Beta(a,b)
901 const double fLogDblMax = log( ::std::numeric_limits<double>::max());
902 const double fLogDblMin = log( ::std::numeric_limits<double>::min());
903 double fLogY = (fX < 0.1) ? ::rtl::math::log1p(-fX) : log(0.5-fX+0.5);
904 double fLogX = log(fX);
905 double fAm1LogX = (fA-1.0) * fLogX;
906 double fBm1LogY = (fB-1.0) * fLogY;
907 double fLogBeta = GetLogBeta(fA,fB);
908 // check whether parts over- or underflow
909 if ( fAm1LogX < fLogDblMax && fAm1LogX > fLogDblMin
910 && fBm1LogY < fLogDblMax && fBm1LogY > fLogDblMin
911 && fLogBeta < fLogDblMax && fLogBeta > fLogDblMin
912 && fAm1LogX + fBm1LogY < fLogDblMax && fAm1LogX + fBm1LogY > fLogDblMin)
913 return pow(fX,fA-1.0) * pow(0.5-fX+0.5,fB-1.0) / GetBeta(fA,fB);
914 else // need logarithm;
915 // might overflow as a whole, but seldom, not worth to pre-detect it
916 return exp( fAm1LogX + fBm1LogY - fLogBeta);
920 x^a * (1-x)^b
921 I_x(a,b) = ---------------- * result of ContFrac
922 a * Beta(a,b)
924 static double lcl_GetBetaHelperContFrac(double fX, double fA, double fB)
925 { // like old version
926 double a1, b1, a2, b2, fnorm, cfnew, cf;
927 a1 = 1.0; b1 = 1.0;
928 b2 = 1.0 - (fA+fB)/(fA+1.0)*fX;
929 if (b2 == 0.0)
931 a2 = 0.0;
932 fnorm = 1.0;
933 cf = 1.0;
935 else
937 a2 = 1.0;
938 fnorm = 1.0/b2;
939 cf = a2*fnorm;
941 cfnew = 1.0;
942 double rm = 1.0;
944 const double fMaxIter = 50000.0;
945 // loop security, normal cases converge in less than 100 iterations.
946 // FIXME: You will get so much iteratons for fX near mean,
947 // I do not know a better algorithm.
948 bool bfinished = false;
951 const double apl2m = fA + 2.0*rm;
952 const double d2m = rm*(fB-rm)*fX/((apl2m-1.0)*apl2m);
953 const double d2m1 = -(fA+rm)*(fA+fB+rm)*fX/(apl2m*(apl2m+1.0));
954 a1 = (a2+d2m*a1)*fnorm;
955 b1 = (b2+d2m*b1)*fnorm;
956 a2 = a1 + d2m1*a2*fnorm;
957 b2 = b1 + d2m1*b2*fnorm;
958 if (b2 != 0.0)
960 fnorm = 1.0/b2;
961 cfnew = a2*fnorm;
962 bfinished = (fabs(cf-cfnew) < fabs(cf)*fMachEps);
964 cf = cfnew;
965 rm += 1.0;
967 while (rm < fMaxIter && !bfinished);
968 return cf;
971 // cumulative distribution function, normalized
972 double ScInterpreter::GetBetaDist(double fXin, double fAlpha, double fBeta)
974 // special cases
975 if (fXin <= 0.0) // values are valid, see spec
976 return 0.0;
977 if (fXin >= 1.0) // values are valid, see spec
978 return 1.0;
979 if (fBeta == 1.0)
980 return pow(fXin, fAlpha);
981 if (fAlpha == 1.0)
982 // 1.0 - pow(1.0-fX,fBeta) is not accurate enough
983 return -::rtl::math::expm1(fBeta * ::rtl::math::log1p(-fXin));
984 //FIXME: need special algorithm for fX near fP for large fA,fB
985 double fResult;
986 // I use always continued fraction, power series are neither
987 // faster nor more accurate.
988 double fY = (0.5-fXin)+0.5;
989 double flnY = ::rtl::math::log1p(-fXin);
990 double fX = fXin;
991 double flnX = log(fXin);
992 double fA = fAlpha;
993 double fB = fBeta;
994 bool bReflect = fXin > fAlpha/(fAlpha+fBeta);
995 if (bReflect)
997 fA = fBeta;
998 fB = fAlpha;
999 fX = fY;
1000 fY = fXin;
1001 flnX = flnY;
1002 flnY = log(fXin);
1004 fResult = lcl_GetBetaHelperContFrac(fX,fA,fB);
1005 fResult = fResult/fA;
1006 double fP = fA/(fA+fB);
1007 double fQ = fB/(fA+fB);
1008 double fTemp;
1009 if (fA > 1.0 && fB > 1.0 && fP < 0.97 && fQ < 0.97) //found experimental
1010 fTemp = GetBetaDistPDF(fX,fA,fB)*fX*fY;
1011 else
1012 fTemp = exp(fA*flnX + fB*flnY - GetLogBeta(fA,fB));
1013 fResult *= fTemp;
1014 if (bReflect)
1015 fResult = 0.5 - fResult + 0.5;
1016 if (fResult > 1.0) // ensure valid range
1017 fResult = 1.0;
1018 if (fResult < 0.0)
1019 fResult = 0.0;
1020 return fResult;
1023 void ScInterpreter::ScBetaDist()
1025 sal_uInt8 nParamCount = GetByte();
1026 if ( !MustHaveParamCount( nParamCount, 3, 6 ) ) // expanded, see #i91547#
1027 return;
1028 double fLowerBound, fUpperBound;
1029 double alpha, beta, x;
1030 bool bIsCumulative;
1031 if (nParamCount == 6)
1032 bIsCumulative = GetBool();
1033 else
1034 bIsCumulative = true;
1035 if (nParamCount >= 5)
1036 fUpperBound = GetDouble();
1037 else
1038 fUpperBound = 1.0;
1039 if (nParamCount >= 4)
1040 fLowerBound = GetDouble();
1041 else
1042 fLowerBound = 0.0;
1043 beta = GetDouble();
1044 alpha = GetDouble();
1045 x = GetDouble();
1046 double fScale = fUpperBound - fLowerBound;
1047 if (fScale <= 0.0 || alpha <= 0.0 || beta <= 0.0)
1049 PushIllegalArgument();
1050 return;
1052 if (bIsCumulative) // cumulative distribution function
1054 // special cases
1055 if (x < fLowerBound)
1057 PushDouble(0.0); return; //see spec
1059 if (x > fUpperBound)
1061 PushDouble(1.0); return; //see spec
1063 // normal cases
1064 x = (x-fLowerBound)/fScale; // convert to standard form
1065 PushDouble(GetBetaDist(x, alpha, beta));
1066 return;
1068 else // probability density function
1070 if (x < fLowerBound || x > fUpperBound)
1072 PushDouble(0.0);
1073 return;
1075 x = (x-fLowerBound)/fScale;
1076 PushDouble(GetBetaDistPDF(x, alpha, beta)/fScale);
1077 return;
1082 fdo#71008
1083 Microsoft version has parameters in different order
1084 Also, upper and lowerbound are optional and have default values
1085 otherwise, function is identical with ScInterpreter::ScBetaDist()
1087 void ScInterpreter::ScBetaDist_MS()
1089 sal_uInt8 nParamCount = GetByte();
1090 if ( !MustHaveParamCount( nParamCount, 4, 6 ) )
1091 return;
1092 double fLowerBound, fUpperBound;
1093 double alpha, beta, x;
1094 bool bIsCumulative;
1095 if (nParamCount == 6)
1096 fUpperBound = GetDouble();
1097 else
1098 fUpperBound = 1.0;
1099 if (nParamCount >= 4)
1100 fLowerBound = GetDouble();
1101 else
1102 fLowerBound = 0.0;
1103 bIsCumulative = GetBool();
1104 beta = GetDouble();
1105 alpha = GetDouble();
1106 x = GetDouble();
1107 double fScale = fUpperBound - fLowerBound;
1108 if (fScale <= 0.0 || alpha <= 0.0 || beta <= 0.0)
1110 PushIllegalArgument();
1111 return;
1113 if (bIsCumulative) // cumulative distribution function
1115 // special cases
1116 if (x < fLowerBound)
1118 PushDouble(0.0); return; //see spec
1120 if (x > fUpperBound)
1122 PushDouble(1.0); return; //see spec
1124 // normal cases
1125 x = (x-fLowerBound)/fScale; // convert to standard form
1126 PushDouble(GetBetaDist(x, alpha, beta));
1127 return;
1129 else // probability density function
1131 if (x < fLowerBound || x > fUpperBound)
1133 PushDouble(0.0);
1134 return;
1136 x = (x-fLowerBound)/fScale;
1137 PushDouble(GetBetaDistPDF(x, alpha, beta)/fScale);
1138 return;
1142 void ScInterpreter::ScPhi()
1144 PushDouble(phi(GetDouble()));
1147 void ScInterpreter::ScGauss()
1149 PushDouble(gauss(GetDouble()));
1152 void ScInterpreter::ScFisher()
1154 double fVal = GetDouble();
1155 if (fabs(fVal) >= 1.0)
1156 PushIllegalArgument();
1157 else
1158 PushDouble( ::rtl::math::atanh( fVal));
1161 void ScInterpreter::ScFisherInv()
1163 PushDouble( tanh( GetDouble()));
1166 void ScInterpreter::ScFact()
1168 double nVal = GetDouble();
1169 if (nVal < 0.0)
1170 PushIllegalArgument();
1171 else
1172 PushDouble(Fakultaet(nVal));
1175 void ScInterpreter::ScCombin()
1177 if ( MustHaveParamCount( GetByte(), 2 ) )
1179 double k = ::rtl::math::approxFloor(GetDouble());
1180 double n = ::rtl::math::approxFloor(GetDouble());
1181 if (k < 0.0 || n < 0.0 || k > n)
1182 PushIllegalArgument();
1183 else
1184 PushDouble(BinomKoeff(n, k));
1188 void ScInterpreter::ScCombinA()
1190 if ( MustHaveParamCount( GetByte(), 2 ) )
1192 double k = ::rtl::math::approxFloor(GetDouble());
1193 double n = ::rtl::math::approxFloor(GetDouble());
1194 if (k < 0.0 || n < 0.0 || k > n)
1195 PushIllegalArgument();
1196 else
1197 PushDouble(BinomKoeff(n + k - 1, k));
1201 void ScInterpreter::ScPermut()
1203 if ( MustHaveParamCount( GetByte(), 2 ) )
1205 double k = ::rtl::math::approxFloor(GetDouble());
1206 double n = ::rtl::math::approxFloor(GetDouble());
1207 if (n < 0.0 || k < 0.0 || k > n)
1208 PushIllegalArgument();
1209 else if (k == 0.0)
1210 PushInt(1); // (n! / (n - 0)!) == 1
1211 else
1213 double nVal = n;
1214 for (sal_uLong i = (sal_uLong)k-1; i >= 1; i--)
1215 nVal *= n-(double)i;
1216 PushDouble(nVal);
1221 void ScInterpreter::ScPermutationA()
1223 if ( MustHaveParamCount( GetByte(), 2 ) )
1225 double k = ::rtl::math::approxFloor(GetDouble());
1226 double n = ::rtl::math::approxFloor(GetDouble());
1227 if (n < 0.0 || k < 0.0 || k > n)
1228 PushIllegalArgument();
1229 else
1230 PushDouble(pow(n,k));
1234 double ScInterpreter::GetBinomDistPMF(double x, double n, double p)
1235 // used in ScB and ScBinomDist
1236 // preconditions: 0.0 <= x <= n, 0.0 < p < 1.0; x,n integral although double
1238 double q = (0.5 - p) + 0.5;
1239 double fFactor = pow(q, n);
1240 if (fFactor <=::std::numeric_limits<double>::min())
1242 fFactor = pow(p, n);
1243 if (fFactor <= ::std::numeric_limits<double>::min())
1244 return GetBetaDistPDF(p, x+1.0, n-x+1.0)/(n+1.0);
1245 else
1247 sal_uInt32 max = static_cast<sal_uInt32>(n - x);
1248 for (sal_uInt32 i = 0; i < max && fFactor > 0.0; i++)
1249 fFactor *= (n-i)/(i+1)*q/p;
1250 return fFactor;
1253 else
1255 sal_uInt32 max = static_cast<sal_uInt32>(x);
1256 for (sal_uInt32 i = 0; i < max && fFactor > 0.0; i++)
1257 fFactor *= (n-i)/(i+1)*p/q;
1258 return fFactor;
1262 double lcl_GetBinomDistRange(double n, double xs,double xe,
1263 double fFactor /* q^n */, double p, double q)
1264 //preconditions: 0.0 <= xs < xe <= n; xs,xe,n integral although double
1266 sal_uInt32 i;
1267 double fSum;
1268 // skip summands index 0 to xs-1, start sum with index xs
1269 sal_uInt32 nXs = static_cast<sal_uInt32>( xs );
1270 for (i = 1; i <= nXs && fFactor > 0.0; i++)
1271 fFactor *= (n-i+1)/i * p/q;
1272 fSum = fFactor; // Summand xs
1273 sal_uInt32 nXe = static_cast<sal_uInt32>(xe);
1274 for (i = nXs+1; i <= nXe && fFactor > 0.0; i++)
1276 fFactor *= (n-i+1)/i * p/q;
1277 fSum += fFactor;
1279 return (fSum>1.0) ? 1.0 : fSum;
1282 void ScInterpreter::ScB()
1284 sal_uInt8 nParamCount = GetByte();
1285 if ( !MustHaveParamCount( nParamCount, 3, 4 ) )
1286 return ;
1287 if (nParamCount == 3) // mass function
1289 double x = ::rtl::math::approxFloor(GetDouble());
1290 double p = GetDouble();
1291 double n = ::rtl::math::approxFloor(GetDouble());
1292 if (n < 0.0 || x < 0.0 || x > n || p < 0.0 || p > 1.0)
1293 PushIllegalArgument();
1294 else if (p == 0.0)
1295 PushDouble( (x == 0.0) ? 1.0 : 0.0 );
1296 else if ( p == 1.0)
1297 PushDouble( (x == n) ? 1.0 : 0.0);
1298 else
1299 PushDouble(GetBinomDistPMF(x,n,p));
1301 else
1302 { // nParamCount == 4
1303 double xe = ::rtl::math::approxFloor(GetDouble());
1304 double xs = ::rtl::math::approxFloor(GetDouble());
1305 double p = GetDouble();
1306 double n = ::rtl::math::approxFloor(GetDouble());
1307 double q = (0.5 - p) + 0.5;
1308 bool bIsValidX = ( 0.0 <= xs && xs <= xe && xe <= n);
1309 if ( bIsValidX && 0.0 < p && p < 1.0)
1311 if (xs == xe) // mass function
1312 PushDouble(GetBinomDistPMF(xs,n,p));
1313 else
1315 double fFactor = pow(q, n);
1316 if (fFactor > ::std::numeric_limits<double>::min())
1317 PushDouble(lcl_GetBinomDistRange(n,xs,xe,fFactor,p,q));
1318 else
1320 fFactor = pow(p, n);
1321 if (fFactor > ::std::numeric_limits<double>::min())
1323 // sum from j=xs to xe {(n choose j) * p^j * q^(n-j)}
1324 // = sum from i = n-xe to n-xs { (n choose i) * q^i * p^(n-i)}
1325 PushDouble(lcl_GetBinomDistRange(n,n-xe,n-xs,fFactor,q,p));
1327 else
1328 PushDouble(GetBetaDist(q,n-xe,xe+1.0)-GetBetaDist(q,n-xs+1,xs) );
1332 else
1334 if ( bIsValidX ) // not(0<p<1)
1336 if ( p == 0.0 )
1337 PushDouble( (xs == 0.0) ? 1.0 : 0.0 );
1338 else if ( p == 1.0 )
1339 PushDouble( (xe == n) ? 1.0 : 0.0 );
1340 else
1341 PushIllegalArgument();
1343 else
1344 PushIllegalArgument();
1349 void ScInterpreter::ScBinomDist()
1351 if ( MustHaveParamCount( GetByte(), 4 ) )
1353 bool bIsCum = GetBool(); // false=mass function; true=cumulative
1354 double p = GetDouble();
1355 double n = ::rtl::math::approxFloor(GetDouble());
1356 double x = ::rtl::math::approxFloor(GetDouble());
1357 double q = (0.5 - p) + 0.5; // get one bit more for p near 1.0
1358 if (n < 0.0 || x < 0.0 || x > n || p < 0.0 || p > 1.0)
1360 PushIllegalArgument();
1361 return;
1363 if ( p == 0.0)
1365 PushDouble( (x==0.0 || bIsCum) ? 1.0 : 0.0 );
1366 return;
1368 if ( p == 1.0)
1370 PushDouble( (x==n) ? 1.0 : 0.0);
1371 return;
1373 if (!bIsCum)
1374 PushDouble( GetBinomDistPMF(x,n,p));
1375 else
1377 if (x == n)
1378 PushDouble(1.0);
1379 else
1381 double fFactor = pow(q, n);
1382 if (x == 0.0)
1383 PushDouble(fFactor);
1384 else if (fFactor <= ::std::numeric_limits<double>::min())
1386 fFactor = pow(p, n);
1387 if (fFactor <= ::std::numeric_limits<double>::min())
1388 PushDouble(GetBetaDist(q,n-x,x+1.0));
1389 else
1391 if (fFactor > fMachEps)
1393 double fSum = 1.0 - fFactor;
1394 sal_uInt32 max = static_cast<sal_uInt32> (n - x) - 1;
1395 for (sal_uInt32 i = 0; i < max && fFactor > 0.0; i++)
1397 fFactor *= (n-i)/(i+1)*q/p;
1398 fSum -= fFactor;
1400 PushDouble( (fSum < 0.0) ? 0.0 : fSum );
1402 else
1403 PushDouble(lcl_GetBinomDistRange(n,n-x,n,fFactor,q,p));
1406 else
1407 PushDouble( lcl_GetBinomDistRange(n,0.0,x,fFactor,p,q)) ;
1413 void ScInterpreter::ScCritBinom()
1415 if ( MustHaveParamCount( GetByte(), 3 ) )
1417 double alpha = GetDouble();
1418 double p = GetDouble();
1419 double n = ::rtl::math::approxFloor(GetDouble());
1420 if (n < 0.0 || alpha <= 0.0 || alpha >= 1.0 || p < 0.0 || p > 1.0)
1421 PushIllegalArgument();
1422 else
1424 double fFactor;
1425 double q = (0.5 - p) + 0.5; // get one bit more for p near 1.0
1426 if ( q > p ) // work from the side where the cumulative curve is
1428 // work from 0 upwards
1429 fFactor = pow(q,n);
1430 if (fFactor > ::std::numeric_limits<double>::min())
1432 double fSum = fFactor;
1433 sal_uInt32 max = static_cast<sal_uInt32> (n), i;
1434 for (i = 0; i < max && fSum < alpha; i++)
1436 fFactor *= (n-i)/(i+1)*p/q;
1437 fSum += fFactor;
1439 PushDouble(i);
1441 else
1443 // accumulate BinomDist until accumulated BinomDist reaches alpha
1444 double fSum = 0.0;
1445 sal_uInt32 max = static_cast<sal_uInt32> (n), i;
1446 for (i = 0; i < max && fSum < alpha; i++)
1448 const double x = GetBetaDistPDF( p, ( i + 1 ), ( n - i + 1 ) )/( n + 1 );
1449 if ( !nGlobalError )
1451 fSum += x;
1453 else
1455 PushNoValue();
1456 return;
1459 PushDouble( i - 1 );
1462 else
1464 // work from n backwards
1465 fFactor = pow(p, n);
1466 if (fFactor > ::std::numeric_limits<double>::min())
1468 double fSum = 1.0 - fFactor;
1469 sal_uInt32 max = static_cast<sal_uInt32> (n), i;
1470 for (i = 0; i < max && fSum >= alpha; i++)
1472 fFactor *= (n-i)/(i+1)*q/p;
1473 fSum -= fFactor;
1475 PushDouble(n-i);
1477 else
1479 // accumulate BinomDist until accumulated BinomDist reaches alpha
1480 double fSum = 0.0;
1481 sal_uInt32 max = static_cast<sal_uInt32> (n), i;
1482 alpha = 1 - alpha;
1483 for (i = 0; i < max && fSum < alpha; i++)
1485 const double x = GetBetaDistPDF( q, ( i + 1 ), ( n - i + 1 ) )/( n + 1 );
1486 if ( !nGlobalError )
1488 fSum += x;
1490 else
1492 PushNoValue();
1493 return;
1496 PushDouble( n - i + 1 );
1503 void ScInterpreter::ScNegBinomDist()
1505 if ( MustHaveParamCount( GetByte(), 3 ) )
1507 double p = GetDouble(); // p
1508 double r = GetDouble(); // r
1509 double x = GetDouble(); // x
1510 if (r < 0.0 || x < 0.0 || p < 0.0 || p > 1.0)
1511 PushIllegalArgument();
1512 else
1514 double q = 1.0 - p;
1515 double fFactor = pow(p,r);
1516 for (double i = 0.0; i < x; i++)
1517 fFactor *= (i+r)/(i+1.0)*q;
1518 PushDouble(fFactor);
1523 void ScInterpreter::ScNegBinomDist_MS()
1525 if ( MustHaveParamCount( GetByte(), 4 ) )
1527 bool bCumulative = GetBool();
1528 double p = GetDouble(); // p
1529 double r = GetDouble(); // r
1530 double x = GetDouble(); // x
1531 if ( r < 0.0 || x < 0.0 || p < 0.0 || p > 1.0 )
1532 PushIllegalArgument();
1533 else
1535 double q = 1.0 - p;
1536 if ( bCumulative )
1537 PushDouble( 1.0 - GetBetaDist( q, x + 1, r ) );
1538 else
1540 double fFactor = pow( p, r );
1541 for ( double i = 0.0; i < x; i++ )
1542 fFactor *= ( i + r ) / ( i + 1.0 ) * q;
1543 PushDouble( fFactor );
1549 void ScInterpreter::ScNormDist( int nMinParamCount )
1551 sal_uInt8 nParamCount = GetByte();
1552 if ( !MustHaveParamCount( nParamCount, nMinParamCount, 4 ) )
1553 return;
1554 bool bCumulative = nParamCount != 4 || GetBool();
1555 double sigma = GetDouble(); // standard deviation
1556 double mue = GetDouble(); // mean
1557 double x = GetDouble(); // x
1558 if (sigma <= 0.0)
1560 PushIllegalArgument();
1561 return;
1563 if (bCumulative)
1564 PushDouble(integralPhi((x-mue)/sigma));
1565 else
1566 PushDouble(phi((x-mue)/sigma)/sigma);
1569 void ScInterpreter::ScLogNormDist( int nMinParamCount ) //expanded, see #i100119# and fdo72158
1571 sal_uInt8 nParamCount = GetByte();
1572 if ( !MustHaveParamCount( nParamCount, nMinParamCount, 4 ) )
1573 return;
1574 bool bCumulative = nParamCount != 4 || GetBool(); // cumulative
1575 double sigma = nParamCount >= 3 ? GetDouble() : 1.0; // standard deviation
1576 double mue = nParamCount >= 2 ? GetDouble() : 0.0; // mean
1577 double x = GetDouble(); // x
1578 if (sigma <= 0.0)
1580 PushIllegalArgument();
1581 return;
1583 if (bCumulative)
1584 { // cumulative
1585 if (x <= 0.0)
1586 PushDouble(0.0);
1587 else
1588 PushDouble(integralPhi((log(x)-mue)/sigma));
1590 else
1591 { // density
1592 if (x <= 0.0)
1593 PushIllegalArgument();
1594 else
1595 PushDouble(phi((log(x)-mue)/sigma)/sigma/x);
1599 void ScInterpreter::ScStdNormDist()
1601 double fVal = GetDouble();
1602 if (!rtl::math::isNan(fVal))
1603 fVal = integralPhi(fVal);
1604 PushDouble(fVal);
1607 void ScInterpreter::ScStdNormDist_MS()
1609 sal_uInt8 nParamCount = GetByte();
1610 if ( !MustHaveParamCount( nParamCount, 2 ) )
1611 return;
1612 bool bCumulative = GetBool(); // cumulative
1613 double x = GetDouble(); // x
1615 if ( bCumulative )
1616 PushDouble( integralPhi( x ) );
1617 else
1618 PushDouble( exp( - pow( x, 2 ) / 2 ) / sqrt( 2 * F_PI ) );
1621 void ScInterpreter::ScExpDist()
1623 if ( MustHaveParamCount( GetByte(), 3 ) )
1625 double kum = GetDouble(); // 0 oder 1
1626 double lambda = GetDouble(); // lambda
1627 double x = GetDouble(); // x
1628 if (lambda <= 0.0)
1629 PushIllegalArgument();
1630 else if (kum == 0.0) // Dichte
1632 if (x >= 0.0)
1633 PushDouble(lambda * exp(-lambda*x));
1634 else
1635 PushInt(0);
1637 else // Verteilung
1639 if (x > 0.0)
1640 PushDouble(1.0 - exp(-lambda*x));
1641 else
1642 PushInt(0);
1647 void ScInterpreter::ScTDist()
1649 if ( !MustHaveParamCount( GetByte(), 3 ) )
1650 return;
1651 double fFlag = ::rtl::math::approxFloor(GetDouble());
1652 double fDF = ::rtl::math::approxFloor(GetDouble());
1653 double T = GetDouble();
1654 if (fDF < 1.0 || T < 0.0 || (fFlag != 1.0 && fFlag != 2.0) )
1656 PushIllegalArgument();
1657 return;
1659 PushDouble( GetTDist( T, fDF, ( int )fFlag ) );
1662 void ScInterpreter::ScTDist_T( int nTails )
1664 if ( !MustHaveParamCount( GetByte(), 2 ) )
1665 return;
1666 double fDF = ::rtl::math::approxFloor( GetDouble() );
1667 double T = GetDouble();
1668 if ( fDF < 1.0 || T < 0.0 )
1670 PushIllegalArgument();
1671 return;
1673 PushDouble( GetTDist( T, fDF, nTails ) );
1676 void ScInterpreter::ScTDist_MS()
1678 if ( !MustHaveParamCount( GetByte(), 3 ) )
1679 return;
1680 bool bCumulative = GetBool();
1681 double fDF = ::rtl::math::approxFloor( GetDouble() );
1682 double T = GetDouble();
1683 if ( fDF < 1.0 )
1685 PushIllegalArgument();
1686 return;
1688 PushDouble( GetTDist( T, fDF, ( bCumulative ? 4 : 3 ) ) );
1691 void ScInterpreter::ScFDist()
1693 if ( !MustHaveParamCount( GetByte(), 3 ) )
1694 return;
1695 double fF2 = ::rtl::math::approxFloor(GetDouble());
1696 double fF1 = ::rtl::math::approxFloor(GetDouble());
1697 double fF = GetDouble();
1698 if (fF < 0.0 || fF1 < 1.0 || fF2 < 1.0 || fF1 >= 1.0E10 || fF2 >= 1.0E10)
1700 PushIllegalArgument();
1701 return;
1703 PushDouble(GetFDist(fF, fF1, fF2));
1706 void ScInterpreter::ScFDist_LT()
1708 int nParamCount = GetByte();
1709 if ( !MustHaveParamCount( nParamCount, 3, 4 ) )
1710 return;
1711 bool bCum;
1712 if ( nParamCount == 3 )
1713 bCum = true;
1714 else if ( IsMissing() )
1716 bCum = true;
1717 Pop();
1719 else
1720 bCum = GetBool();
1721 double fF2 = ::rtl::math::approxFloor( GetDouble() );
1722 double fF1 = ::rtl::math::approxFloor( GetDouble() );
1723 double fF = GetDouble();
1724 if ( fF < 0.0 || fF1 < 1.0 || fF2 < 1.0 || fF1 >= 1.0E10 || fF2 >= 1.0E10 )
1726 PushIllegalArgument();
1727 return;
1729 if ( bCum )
1731 // left tail cumulative distribution
1732 PushDouble( 1.0 - GetFDist( fF, fF1, fF2 ) );
1734 else
1736 // probability density function
1737 PushDouble( pow( fF1 / fF2, fF1 / 2 ) * pow( fF, ( fF1 / 2 ) - 1 ) /
1738 ( pow( ( 1 + ( fF * fF1 / fF2 ) ), ( fF1 + fF2 ) / 2 ) *
1739 GetBeta( fF1 / 2, fF2 / 2 ) ) );
1743 void ScInterpreter::ScChiDist()
1745 double fResult;
1746 if ( !MustHaveParamCount( GetByte(), 2 ) )
1747 return;
1748 double fDF = ::rtl::math::approxFloor(GetDouble());
1749 double fChi = GetDouble();
1750 if (fDF < 1.0) // x<=0 returns 1, see ODFF 6.17.10
1752 PushIllegalArgument();
1753 return;
1755 fResult = GetChiDist( fChi, fDF);
1756 if (nGlobalError)
1758 PushError( nGlobalError);
1759 return;
1761 PushDouble(fResult);
1764 void ScInterpreter::ScWeibull()
1766 if ( MustHaveParamCount( GetByte(), 4 ) )
1768 double kum = GetDouble(); // 0 oder 1
1769 double beta = GetDouble(); // beta
1770 double alpha = GetDouble(); // alpha
1771 double x = GetDouble(); // x
1772 if (alpha <= 0.0 || beta <= 0.0 || x < 0.0)
1773 PushIllegalArgument();
1774 else if (kum == 0.0) // Dichte
1775 PushDouble(alpha/pow(beta,alpha)*pow(x,alpha-1.0)*
1776 exp(-pow(x/beta,alpha)));
1777 else // Verteilung
1778 PushDouble(1.0 - exp(-pow(x/beta,alpha)));
1782 void ScInterpreter::ScPoissonDist()
1784 sal_uInt8 nParamCount = GetByte();
1785 if ( MustHaveParamCount( nParamCount, 2, 3 ) )
1787 bool bCumulative = nParamCount != 3 || GetBool(); // default cumulative
1788 double lambda = GetDouble(); // Mean
1789 double x = ::rtl::math::approxFloor(GetDouble()); // discrete distribution
1790 if (lambda < 0.0 || x < 0.0)
1791 PushIllegalArgument();
1792 else if (!bCumulative) // Probability mass function
1794 if (lambda == 0.0)
1795 PushInt(0);
1796 else
1798 if (lambda >712) // underflow in exp(-lambda)
1799 { // accuracy 11 Digits
1800 PushDouble( exp(x*log(lambda)-lambda-GetLogGamma(x+1.0)));
1802 else
1804 double fPoissonVar = 1.0;
1805 for ( double f = 0.0; f < x; ++f )
1806 fPoissonVar *= lambda / ( f + 1.0 );
1807 PushDouble( fPoissonVar * exp( -lambda ) );
1811 else // Cumulative distribution function
1813 if (lambda == 0.0)
1814 PushInt(1);
1815 else
1817 if (lambda > 712 ) // underflow in exp(-lambda)
1818 { // accuracy 12 Digits
1819 PushDouble(GetUpRegIGamma(x+1.0,lambda));
1821 else
1823 if (x >= 936.0) // result is always undistinghable from 1
1824 PushDouble (1.0);
1825 else
1827 double fSummand = exp(-lambda);
1828 double fSum = fSummand;
1829 int nEnd = sal::static_int_cast<int>( x );
1830 for (int i = 1; i <= nEnd; i++)
1832 fSummand = (fSummand * lambda)/(double)i;
1833 fSum += fSummand;
1835 PushDouble(fSum);
1843 /** Local function used in the calculation of the hypergeometric distribution.
1845 static void lcl_PutFactorialElements( ::std::vector< double >& cn, double fLower, double fUpper, double fBase )
1847 for ( double i = fLower; i <= fUpper; ++i )
1849 double fVal = fBase - i;
1850 if ( fVal > 1.0 )
1851 cn.push_back( fVal );
1855 /** Calculates a value of the hypergeometric distribution.
1857 @author Kohei Yoshida <kohei@openoffice.org>
1859 @see #i47296#
1862 void ScInterpreter::ScHypGeomDist()
1864 if ( !MustHaveParamCount( GetByte(), 4 ) )
1865 return;
1867 double N = ::rtl::math::approxFloor(GetDouble());
1868 double M = ::rtl::math::approxFloor(GetDouble());
1869 double n = ::rtl::math::approxFloor(GetDouble());
1870 double x = ::rtl::math::approxFloor(GetDouble());
1872 if( (x < 0.0) || (n < x) || (M < x) || (N < n) || (N < M) || (x < n - N + M) )
1874 PushIllegalArgument();
1875 return;
1878 PushDouble( GetHypGeomDist( x, n, M, N ) );
1881 /** Calculates a value of the hypergeometric distribution (Excel 2010 function).
1883 This function has an extra argument bCumulative as compared to ScHypGeomDist(),
1884 which only calculates the non-cumulative distribution.
1886 @see fdo#71722
1888 void ScInterpreter::ScHypGeomDist_MS()
1890 if ( !MustHaveParamCount( GetByte(), 5 ) )
1891 return;
1893 bool bCumulative = GetBool();
1894 double N = ::rtl::math::approxFloor(GetDouble());
1895 double M = ::rtl::math::approxFloor(GetDouble());
1896 double n = ::rtl::math::approxFloor(GetDouble());
1897 double x = ::rtl::math::approxFloor(GetDouble());
1899 if( (x < 0.0) || (n < x) || (M < x) || (N < n) || (N < M) || (x < n - N + M) )
1901 PushIllegalArgument();
1902 return;
1905 if ( bCumulative )
1907 double fVal = 0.0;
1909 for ( int i = 0; i <= x && !nGlobalError; i++ )
1910 fVal += GetHypGeomDist( i, n, M, N );
1912 PushDouble( fVal );
1914 else
1915 PushDouble( GetHypGeomDist( x, n, M, N ) );
1918 /** Calculates a value of the hypergeometric distribution.
1920 The algorithm is designed to avoid unnecessary multiplications and division
1921 by expanding all factorial elements (9 of them). It is done by excluding
1922 those ranges that overlap in the numerator and the denominator. This allows
1923 for a fast calculation for large values which would otherwise cause an overflow
1924 in the intermediate values.
1926 @author Kohei Yoshida <kohei@openoffice.org>
1928 @see #i47296#
1931 double ScInterpreter::GetHypGeomDist( double x, double n, double M, double N )
1933 const size_t nMaxArraySize = 500000; // arbitrary max array size
1935 typedef ::std::vector< double > HypContainer;
1936 HypContainer cnNumer, cnDenom;
1938 size_t nEstContainerSize = static_cast<size_t>( x + ::std::min( n, M ) );
1939 size_t nMaxSize = ::std::min( cnNumer.max_size(), nMaxArraySize );
1940 if ( nEstContainerSize > nMaxSize )
1942 PushNoValue();
1943 return 0;
1945 cnNumer.reserve( nEstContainerSize + 10 );
1946 cnDenom.reserve( nEstContainerSize + 10 );
1948 // Trim coefficient C first
1949 double fCNumVarUpper = N - n - M + x - 1.0;
1950 double fCDenomVarLower = 1.0;
1951 if ( N - n - M + x >= M - x + 1.0 )
1953 fCNumVarUpper = M - x - 1.0;
1954 fCDenomVarLower = N - n - 2.0*(M - x) + 1.0;
1957 #if OSL_DEBUG_LEVEL > 0
1958 double fCNumLower = N - n - fCNumVarUpper;
1959 #endif
1960 double fCDenomUpper = N - n - M + x + 1.0 - fCDenomVarLower;
1962 double fDNumVarLower = n - M;
1964 if ( n >= M + 1.0 )
1966 if ( N - M < n + 1.0 )
1968 // Case 1
1970 if ( N - n < n + 1.0 )
1972 // no overlap
1973 lcl_PutFactorialElements( cnNumer, 0.0, fCNumVarUpper, N - n );
1974 lcl_PutFactorialElements( cnDenom, 0.0, N - n - 1.0, N );
1976 else
1978 // overlap
1979 OSL_ENSURE( fCNumLower < n + 1.0, "ScHypGeomDist: wrong assertion" );
1980 lcl_PutFactorialElements( cnNumer, N - 2.0*n, fCNumVarUpper, N - n );
1981 lcl_PutFactorialElements( cnDenom, 0.0, n - 1.0, N );
1984 OSL_ENSURE( fCDenomUpper <= N - M, "ScHypGeomDist: wrong assertion" );
1986 if ( fCDenomUpper < n - x + 1.0 )
1987 // no overlap
1988 lcl_PutFactorialElements( cnNumer, 1.0, N - M - n + x, N - M + 1.0 );
1989 else
1991 // overlap
1992 lcl_PutFactorialElements( cnNumer, 1.0, N - M - fCDenomUpper, N - M + 1.0 );
1994 fCDenomUpper = n - x;
1995 fCDenomVarLower = N - M - 2.0*(n - x) + 1.0;
1998 else
2000 // Case 2
2002 if ( n > M - 1.0 )
2004 // no overlap
2005 lcl_PutFactorialElements( cnNumer, 0.0, fCNumVarUpper, N - n );
2006 lcl_PutFactorialElements( cnDenom, 0.0, M - 1.0, N );
2008 else
2010 lcl_PutFactorialElements( cnNumer, M - n, fCNumVarUpper, N - n );
2011 lcl_PutFactorialElements( cnDenom, 0.0, n - 1.0, N );
2014 OSL_ENSURE( fCDenomUpper <= n, "ScHypGeomDist: wrong assertion" );
2016 if ( fCDenomUpper < n - x + 1.0 )
2017 // no overlap
2018 lcl_PutFactorialElements( cnNumer, N - M - n + 1.0, N - M - n + x, N - M + 1.0 );
2019 else
2021 lcl_PutFactorialElements( cnNumer, N - M - n + 1.0, N - M - fCDenomUpper, N - M + 1.0 );
2022 fCDenomUpper = n - x;
2023 fCDenomVarLower = N - M - 2.0*(n - x) + 1.0;
2027 OSL_ENSURE( fCDenomUpper <= M, "ScHypGeomDist: wrong assertion" );
2029 else
2031 if ( N - M < M + 1.0 )
2033 // Case 3
2035 if ( N - n < M + 1.0 )
2037 // No overlap
2038 lcl_PutFactorialElements( cnNumer, 0.0, fCNumVarUpper, N - n );
2039 lcl_PutFactorialElements( cnDenom, 0.0, N - M - 1.0, N );
2041 else
2043 lcl_PutFactorialElements( cnNumer, N - n - M, fCNumVarUpper, N - n );
2044 lcl_PutFactorialElements( cnDenom, 0.0, n - 1.0, N );
2047 if ( n - x + 1.0 > fCDenomUpper )
2048 // No overlap
2049 lcl_PutFactorialElements( cnNumer, 1.0, N - M - n + x, N - M + 1.0 );
2050 else
2052 // Overlap
2053 lcl_PutFactorialElements( cnNumer, 1.0, N - M - fCDenomUpper, N - M + 1.0 );
2055 fCDenomVarLower = N - M - 2.0*(n - x) + 1.0;
2056 fCDenomUpper = n - x;
2059 else
2061 // Case 4
2063 OSL_ENSURE( M >= n - x, "ScHypGeomDist: wrong assertion" );
2064 OSL_ENSURE( M - x <= N - M + 1.0, "ScHypGeomDist: wrong assertion" );
2066 if ( N - n < N - M + 1.0 )
2068 // No overlap
2069 lcl_PutFactorialElements( cnNumer, 0.0, fCNumVarUpper, N - n );
2070 lcl_PutFactorialElements( cnDenom, 0.0, M - 1.0, N );
2072 else
2074 // Overlap
2075 OSL_ENSURE( fCNumLower <= N - M + 1.0, "ScHypGeomDist: wrong assertion" );
2076 lcl_PutFactorialElements( cnNumer, M - n, fCNumVarUpper, N - n );
2077 lcl_PutFactorialElements( cnDenom, 0.0, n - 1.0, N );
2080 if ( n - x + 1.0 > fCDenomUpper )
2081 // No overlap
2082 lcl_PutFactorialElements( cnNumer, N - 2.0*M + 1.0, N - M - n + x, N - M + 1.0 );
2083 else if ( M >= fCDenomUpper )
2085 lcl_PutFactorialElements( cnNumer, N - 2.0*M + 1.0, N - M - fCDenomUpper, N - M + 1.0 );
2087 fCDenomUpper = n - x;
2088 fCDenomVarLower = N - M - 2.0*(n - x) + 1.0;
2090 else
2092 OSL_ENSURE( M <= fCDenomUpper, "ScHypGeomDist: wrong assertion" );
2093 lcl_PutFactorialElements( cnDenom, fCDenomVarLower, N - n - 2.0*M + x,
2094 N - n - M + x + 1.0 );
2096 fCDenomUpper = n - x;
2097 fCDenomVarLower = N - M - 2.0*(n - x) + 1.0;
2101 OSL_ENSURE( fCDenomUpper <= n, "ScHypGeomDist: wrong assertion" );
2103 fDNumVarLower = 0.0;
2106 double nDNumVarUpper = fCDenomUpper < x + 1.0 ? n - x - 1.0 : n - fCDenomUpper - 1.0;
2107 double nDDenomVarLower = fCDenomUpper < x + 1.0 ? fCDenomVarLower : N - n - M + 1.0;
2108 lcl_PutFactorialElements( cnNumer, fDNumVarLower, nDNumVarUpper, n );
2109 lcl_PutFactorialElements( cnDenom, nDDenomVarLower, N - n - M + x, N - n - M + x + 1.0 );
2111 ::std::sort( cnNumer.begin(), cnNumer.end() );
2112 ::std::sort( cnDenom.begin(), cnDenom.end() );
2113 HypContainer::reverse_iterator it1 = cnNumer.rbegin(), it1End = cnNumer.rend();
2114 HypContainer::reverse_iterator it2 = cnDenom.rbegin(), it2End = cnDenom.rend();
2116 double fFactor = 1.0;
2117 for ( ; it1 != it1End || it2 != it2End; )
2119 double fEnum = 1.0, fDenom = 1.0;
2120 if ( it1 != it1End )
2121 fEnum = *it1++;
2122 if ( it2 != it2End )
2123 fDenom = *it2++;
2124 fFactor *= fEnum / fDenom;
2127 return fFactor;
2130 void ScInterpreter::ScGammaDist( int nMinParamCount )
2132 sal_uInt8 nParamCount = GetByte();
2133 if ( !MustHaveParamCount( nParamCount, nMinParamCount, 4 ) )
2134 return;
2135 bool bCumulative;
2136 if (nParamCount == 4)
2137 bCumulative = GetBool();
2138 else
2139 bCumulative = true;
2140 double fBeta = GetDouble(); // scale
2141 double fAlpha = GetDouble(); // shape
2142 double fX = GetDouble(); // x
2143 if (fAlpha <= 0.0 || fBeta <= 0.0)
2144 PushIllegalArgument();
2145 else
2147 if (bCumulative) // distribution
2148 PushDouble( GetGammaDist( fX, fAlpha, fBeta));
2149 else // density
2150 PushDouble( GetGammaDistPDF( fX, fAlpha, fBeta));
2154 void ScInterpreter::ScNormInv()
2156 if ( MustHaveParamCount( GetByte(), 3 ) )
2158 double sigma = GetDouble();
2159 double mue = GetDouble();
2160 double x = GetDouble();
2161 if (sigma <= 0.0 || x < 0.0 || x > 1.0)
2162 PushIllegalArgument();
2163 else if (x == 0.0 || x == 1.0)
2164 PushNoValue();
2165 else
2166 PushDouble(gaussinv(x)*sigma + mue);
2170 void ScInterpreter::ScSNormInv()
2172 double x = GetDouble();
2173 if (x < 0.0 || x > 1.0)
2174 PushIllegalArgument();
2175 else if (x == 0.0 || x == 1.0)
2176 PushNoValue();
2177 else
2178 PushDouble(gaussinv(x));
2181 void ScInterpreter::ScLogNormInv()
2183 if ( MustHaveParamCount( GetByte(), 3 ) )
2185 double sigma = GetDouble(); // Stdabw
2186 double mue = GetDouble(); // Mittelwert
2187 double y = GetDouble(); // y
2188 if (sigma <= 0.0 || y <= 0.0 || y >= 1.0)
2189 PushIllegalArgument();
2190 else
2191 PushDouble(exp(mue+sigma*gaussinv(y)));
2195 class ScGammaDistFunction : public ScDistFunc
2197 ScInterpreter& rInt;
2198 double fp, fAlpha, fBeta;
2200 public:
2201 ScGammaDistFunction( ScInterpreter& rI, double fpVal, double fAlphaVal, double fBetaVal ) :
2202 rInt(rI), fp(fpVal), fAlpha(fAlphaVal), fBeta(fBetaVal) {}
2204 virtual ~ScGammaDistFunction() {}
2206 double GetValue( double x ) const SAL_OVERRIDE { return fp - rInt.GetGammaDist(x, fAlpha, fBeta); }
2209 void ScInterpreter::ScGammaInv()
2211 if ( !MustHaveParamCount( GetByte(), 3 ) )
2212 return;
2213 double fBeta = GetDouble();
2214 double fAlpha = GetDouble();
2215 double fP = GetDouble();
2216 if (fAlpha <= 0.0 || fBeta <= 0.0 || fP < 0.0 || fP >= 1.0 )
2218 PushIllegalArgument();
2219 return;
2221 if (fP == 0.0)
2222 PushInt(0);
2223 else
2225 bool bConvError;
2226 ScGammaDistFunction aFunc( *this, fP, fAlpha, fBeta );
2227 double fStart = fAlpha * fBeta;
2228 double fVal = lcl_IterateInverse( aFunc, fStart*0.5, fStart, bConvError );
2229 if (bConvError)
2230 SetError(errNoConvergence);
2231 PushDouble(fVal);
2235 class ScBetaDistFunction : public ScDistFunc
2237 ScInterpreter& rInt;
2238 double fp, fAlpha, fBeta;
2240 public:
2241 ScBetaDistFunction( ScInterpreter& rI, double fpVal, double fAlphaVal, double fBetaVal ) :
2242 rInt(rI), fp(fpVal), fAlpha(fAlphaVal), fBeta(fBetaVal) {}
2244 virtual ~ScBetaDistFunction() {}
2246 double GetValue( double x ) const SAL_OVERRIDE { return fp - rInt.GetBetaDist(x, fAlpha, fBeta); }
2249 void ScInterpreter::ScBetaInv()
2251 sal_uInt8 nParamCount = GetByte();
2252 if ( !MustHaveParamCount( nParamCount, 3, 5 ) )
2253 return;
2254 double fP, fA, fB, fAlpha, fBeta;
2255 if (nParamCount == 5)
2256 fB = GetDouble();
2257 else
2258 fB = 1.0;
2259 if (nParamCount >= 4)
2260 fA = GetDouble();
2261 else
2262 fA = 0.0;
2263 fBeta = GetDouble();
2264 fAlpha = GetDouble();
2265 fP = GetDouble();
2266 if (fP < 0.0 || fP >= 1.0 || fA == fB || fAlpha <= 0.0 || fBeta <= 0.0)
2268 PushIllegalArgument();
2269 return;
2271 if (fP == 0.0)
2272 PushInt(0);
2273 else
2275 bool bConvError;
2276 ScBetaDistFunction aFunc( *this, fP, fAlpha, fBeta );
2277 // 0..1 as range for iteration so it isn't extended beyond the valid range
2278 double fVal = lcl_IterateInverse( aFunc, 0.0, 1.0, bConvError );
2279 if (bConvError)
2280 PushError( errNoConvergence);
2281 else
2282 PushDouble(fA + fVal*(fB-fA)); // scale to (A,B)
2286 // Achtung: T, F und Chi
2287 // sind monoton fallend,
2288 // deshalb 1-Dist als Funktion
2290 class ScTDistFunction : public ScDistFunc
2292 ScInterpreter& rInt;
2293 double fp, fDF;
2294 int nT;
2296 public:
2297 ScTDistFunction( ScInterpreter& rI, double fpVal, double fDFVal, int nType ) :
2298 rInt( rI ), fp( fpVal ), fDF( fDFVal ), nT( nType ) {}
2300 virtual ~ScTDistFunction() {}
2302 double GetValue( double x ) const SAL_OVERRIDE { return fp - rInt.GetTDist( x, fDF, nT ); }
2305 void ScInterpreter::ScTInv( int nType )
2307 if ( !MustHaveParamCount( GetByte(), 2 ) )
2308 return;
2309 double fDF = ::rtl::math::approxFloor(GetDouble());
2310 double fP = GetDouble();
2311 if (fDF < 1.0 || fP <= 0.0 || fP > 1.0 )
2313 PushIllegalArgument();
2314 return;
2316 if ( nType == 4 ) // left-tailed cumulative t-distribution
2318 if ( fP < 0.5 )
2319 PushDouble( -GetTInv( 1 - fP, fDF, nType ) );
2320 else
2321 PushDouble( GetTInv( fP, fDF, nType ) );
2323 else
2324 PushDouble( GetTInv( fP, fDF, nType ) );
2327 double ScInterpreter::GetTInv( double fAlpha, double fSize, int nType )
2329 bool bConvError;
2330 ScTDistFunction aFunc( *this, fAlpha, fSize, nType );
2331 double fVal = lcl_IterateInverse( aFunc, fSize * 0.5, fSize, bConvError );
2332 if (bConvError)
2333 SetError(errNoConvergence);
2334 return fVal;
2337 class ScFDistFunction : public ScDistFunc
2339 ScInterpreter& rInt;
2340 double fp, fF1, fF2;
2342 public:
2343 ScFDistFunction( ScInterpreter& rI, double fpVal, double fF1Val, double fF2Val ) :
2344 rInt(rI), fp(fpVal), fF1(fF1Val), fF2(fF2Val) {}
2346 virtual ~ScFDistFunction() {}
2348 double GetValue( double x ) const SAL_OVERRIDE { return fp - rInt.GetFDist(x, fF1, fF2); }
2351 void ScInterpreter::ScFInv()
2353 if ( !MustHaveParamCount( GetByte(), 3 ) )
2354 return;
2355 double fF2 = ::rtl::math::approxFloor(GetDouble());
2356 double fF1 = ::rtl::math::approxFloor(GetDouble());
2357 double fP = GetDouble();
2358 if (fP <= 0.0 || fF1 < 1.0 || fF2 < 1.0 || fF1 >= 1.0E10 || fF2 >= 1.0E10 || fP > 1.0)
2360 PushIllegalArgument();
2361 return;
2364 bool bConvError;
2365 ScFDistFunction aFunc( *this, fP, fF1, fF2 );
2366 double fVal = lcl_IterateInverse( aFunc, fF1*0.5, fF1, bConvError );
2367 if (bConvError)
2368 SetError(errNoConvergence);
2369 PushDouble(fVal);
2372 void ScInterpreter::ScFInv_LT()
2374 if ( !MustHaveParamCount( GetByte(), 3 ) )
2375 return;
2376 double fF2 = ::rtl::math::approxFloor(GetDouble());
2377 double fF1 = ::rtl::math::approxFloor(GetDouble());
2378 double fP = GetDouble();
2379 if (fP <= 0.0 || fF1 < 1.0 || fF2 < 1.0 || fF1 >= 1.0E10 || fF2 >= 1.0E10 || fP > 1.0)
2381 PushIllegalArgument();
2382 return;
2385 bool bConvError;
2386 ScFDistFunction aFunc( *this, ( 1.0 - fP ), fF1, fF2 );
2387 double fVal = lcl_IterateInverse( aFunc, fF1*0.5, fF1, bConvError );
2388 if (bConvError)
2389 SetError(errNoConvergence);
2390 PushDouble(fVal);
2393 class ScChiDistFunction : public ScDistFunc
2395 ScInterpreter& rInt;
2396 double fp, fDF;
2398 public:
2399 ScChiDistFunction( ScInterpreter& rI, double fpVal, double fDFVal ) :
2400 rInt(rI), fp(fpVal), fDF(fDFVal) {}
2402 virtual ~ScChiDistFunction() {}
2404 double GetValue( double x ) const SAL_OVERRIDE { return fp - rInt.GetChiDist(x, fDF); }
2407 void ScInterpreter::ScChiInv()
2409 if ( !MustHaveParamCount( GetByte(), 2 ) )
2410 return;
2411 double fDF = ::rtl::math::approxFloor(GetDouble());
2412 double fP = GetDouble();
2413 if (fDF < 1.0 || fP <= 0.0 || fP > 1.0 )
2415 PushIllegalArgument();
2416 return;
2419 bool bConvError;
2420 ScChiDistFunction aFunc( *this, fP, fDF );
2421 double fVal = lcl_IterateInverse( aFunc, fDF*0.5, fDF, bConvError );
2422 if (bConvError)
2423 SetError(errNoConvergence);
2424 PushDouble(fVal);
2427 /***********************************************/
2428 class ScChiSqDistFunction : public ScDistFunc
2430 ScInterpreter& rInt;
2431 double fp, fDF;
2433 public:
2434 ScChiSqDistFunction( ScInterpreter& rI, double fpVal, double fDFVal ) :
2435 rInt(rI), fp(fpVal), fDF(fDFVal) {}
2437 virtual ~ScChiSqDistFunction() {}
2439 double GetValue( double x ) const SAL_OVERRIDE { return fp - rInt.GetChiSqDistCDF(x, fDF); }
2442 void ScInterpreter::ScChiSqInv()
2444 if ( !MustHaveParamCount( GetByte(), 2 ) )
2445 return;
2446 double fDF = ::rtl::math::approxFloor(GetDouble());
2447 double fP = GetDouble();
2448 if (fDF < 1.0 || fP < 0.0 || fP >= 1.0 )
2450 PushIllegalArgument();
2451 return;
2454 bool bConvError;
2455 ScChiSqDistFunction aFunc( *this, fP, fDF );
2456 double fVal = lcl_IterateInverse( aFunc, fDF*0.5, fDF, bConvError );
2457 if (bConvError)
2458 SetError(errNoConvergence);
2459 PushDouble(fVal);
2462 void ScInterpreter::ScConfidence()
2464 if ( MustHaveParamCount( GetByte(), 3 ) )
2466 double n = ::rtl::math::approxFloor(GetDouble());
2467 double sigma = GetDouble();
2468 double alpha = GetDouble();
2469 if (sigma <= 0.0 || alpha <= 0.0 || alpha >= 1.0 || n < 1.0)
2470 PushIllegalArgument();
2471 else
2472 PushDouble( gaussinv(1.0-alpha/2.0) * sigma/sqrt(n) );
2476 void ScInterpreter::ScConfidenceT()
2478 if ( MustHaveParamCount( GetByte(), 3 ) )
2480 double n = ::rtl::math::approxFloor(GetDouble());
2481 double sigma = GetDouble();
2482 double alpha = GetDouble();
2483 if (sigma <= 0.0 || alpha <= 0.0 || alpha >= 1.0 || n < 1.0)
2484 PushIllegalArgument();
2485 else
2486 PushDouble( sigma * GetTInv( alpha, n - 1, 2 ) / sqrt( n ) );
2490 void ScInterpreter::ScZTest()
2492 sal_uInt8 nParamCount = GetByte();
2493 if ( !MustHaveParamCount( nParamCount, 2, 3 ) )
2494 return;
2495 double sigma = 0.0, x;
2496 if (nParamCount == 3)
2498 sigma = GetDouble();
2499 if (sigma <= 0.0)
2501 PushIllegalArgument();
2502 return;
2505 x = GetDouble();
2507 double fSum = 0.0;
2508 double fSumSqr = 0.0;
2509 double fVal;
2510 double rValCount = 0.0;
2511 switch (GetStackType())
2513 case formula::svDouble :
2515 fVal = GetDouble();
2516 fSum += fVal;
2517 fSumSqr += fVal*fVal;
2518 rValCount++;
2520 break;
2521 case svSingleRef :
2523 ScAddress aAdr;
2524 PopSingleRef( aAdr );
2525 ScRefCellValue aCell;
2526 aCell.assign(*pDok, aAdr);
2527 if (aCell.hasNumeric())
2529 fVal = GetCellValue(aAdr, aCell);
2530 fSum += fVal;
2531 fSumSqr += fVal*fVal;
2532 rValCount++;
2535 break;
2536 case svRefList :
2537 case formula::svDoubleRef :
2539 short nParam = 1;
2540 size_t nRefInList = 0;
2541 while (nParam-- > 0)
2543 ScRange aRange;
2544 sal_uInt16 nErr = 0;
2545 PopDoubleRef( aRange, nParam, nRefInList);
2546 ScValueIterator aValIter( pDok, aRange, mnSubTotalFlags );
2547 if (aValIter.GetFirst(fVal, nErr))
2549 fSum += fVal;
2550 fSumSqr += fVal*fVal;
2551 rValCount++;
2552 while ((nErr == 0) && aValIter.GetNext(fVal, nErr))
2554 fSum += fVal;
2555 fSumSqr += fVal*fVal;
2556 rValCount++;
2558 SetError(nErr);
2562 break;
2563 case svMatrix :
2564 case svExternalSingleRef:
2565 case svExternalDoubleRef:
2567 ScMatrixRef pMat = GetMatrix();
2568 if (pMat)
2570 SCSIZE nCount = pMat->GetElementCount();
2571 if (pMat->IsNumeric())
2573 for ( SCSIZE i = 0; i < nCount; i++ )
2575 fVal= pMat->GetDouble(i);
2576 fSum += fVal;
2577 fSumSqr += fVal * fVal;
2578 rValCount++;
2581 else
2583 for (SCSIZE i = 0; i < nCount; i++)
2584 if (!pMat->IsString(i))
2586 fVal= pMat->GetDouble(i);
2587 fSum += fVal;
2588 fSumSqr += fVal * fVal;
2589 rValCount++;
2594 break;
2595 default : SetError(errIllegalParameter); break;
2597 if (rValCount <= 1.0)
2598 PushError( errDivisionByZero);
2599 else
2601 double mue = fSum/rValCount;
2603 if (nParamCount != 3)
2605 sigma = (fSumSqr - fSum*fSum/rValCount)/(rValCount-1.0);
2606 PushDouble(0.5 - gauss((mue-x)/sqrt(sigma/rValCount)));
2608 else
2609 PushDouble(0.5 - gauss((mue-x)*sqrt(rValCount)/sigma));
2613 bool ScInterpreter::CalculateTest(bool _bTemplin
2614 ,const SCSIZE nC1, const SCSIZE nC2,const SCSIZE nR1,const SCSIZE nR2
2615 ,const ScMatrixRef& pMat1,const ScMatrixRef& pMat2
2616 ,double& fT,double& fF)
2618 double fCount1 = 0.0;
2619 double fCount2 = 0.0;
2620 double fSum1 = 0.0;
2621 double fSumSqr1 = 0.0;
2622 double fSum2 = 0.0;
2623 double fSumSqr2 = 0.0;
2624 double fVal;
2625 SCSIZE i,j;
2626 for (i = 0; i < nC1; i++)
2627 for (j = 0; j < nR1; j++)
2629 if (!pMat1->IsString(i,j))
2631 fVal = pMat1->GetDouble(i,j);
2632 fSum1 += fVal;
2633 fSumSqr1 += fVal * fVal;
2634 fCount1++;
2637 for (i = 0; i < nC2; i++)
2638 for (j = 0; j < nR2; j++)
2640 if (!pMat2->IsString(i,j))
2642 fVal = pMat2->GetDouble(i,j);
2643 fSum2 += fVal;
2644 fSumSqr2 += fVal * fVal;
2645 fCount2++;
2648 if (fCount1 < 2.0 || fCount2 < 2.0)
2650 PushNoValue();
2651 return false;
2652 } // if (fCount1 < 2.0 || fCount2 < 2.0)
2653 if ( _bTemplin )
2655 double fS1 = (fSumSqr1-fSum1*fSum1/fCount1)/(fCount1-1.0)/fCount1;
2656 double fS2 = (fSumSqr2-fSum2*fSum2/fCount2)/(fCount2-1.0)/fCount2;
2657 if (fS1 + fS2 == 0.0)
2659 PushNoValue();
2660 return false;
2662 fT = fabs(fSum1/fCount1 - fSum2/fCount2)/sqrt(fS1+fS2);
2663 double c = fS1/(fS1+fS2);
2664 // GetTDist wird mit GetBetaDist berechnet und kommt auch mit nicht ganzzahligen
2665 // Freiheitsgraden klar. Dann stimmt das Ergebnis auch mit Excel ueberein (#52406#):
2666 fF = 1.0/(c*c/(fCount1-1.0)+(1.0-c)*(1.0-c)/(fCount2-1.0));
2668 else
2670 // laut Bronstein-Semendjajew
2671 double fS1 = (fSumSqr1 - fSum1*fSum1/fCount1) / (fCount1 - 1.0); // Varianz
2672 double fS2 = (fSumSqr2 - fSum2*fSum2/fCount2) / (fCount2 - 1.0);
2673 fT = fabs( fSum1/fCount1 - fSum2/fCount2 ) /
2674 sqrt( (fCount1-1.0)*fS1 + (fCount2-1.0)*fS2 ) *
2675 sqrt( fCount1*fCount2*(fCount1+fCount2-2)/(fCount1+fCount2) );
2676 fF = fCount1 + fCount2 - 2;
2678 return true;
2680 void ScInterpreter::ScTTest()
2682 if ( !MustHaveParamCount( GetByte(), 4 ) )
2683 return;
2684 double fTyp = ::rtl::math::approxFloor(GetDouble());
2685 double fTails = ::rtl::math::approxFloor(GetDouble());
2686 if (fTails != 1.0 && fTails != 2.0)
2688 PushIllegalArgument();
2689 return;
2692 ScMatrixRef pMat2 = GetMatrix();
2693 ScMatrixRef pMat1 = GetMatrix();
2694 if (!pMat1 || !pMat2)
2696 PushIllegalParameter();
2697 return;
2699 double fT, fF;
2700 SCSIZE nC1, nC2;
2701 SCSIZE nR1, nR2;
2702 SCSIZE i, j;
2703 pMat1->GetDimensions(nC1, nR1);
2704 pMat2->GetDimensions(nC2, nR2);
2705 if (fTyp == 1.0)
2707 if (nC1 != nC2 || nR1 != nR2)
2709 PushIllegalArgument();
2710 return;
2712 double fCount = 0.0;
2713 double fSum1 = 0.0;
2714 double fSum2 = 0.0;
2715 double fSumSqrD = 0.0;
2716 double fVal1, fVal2;
2717 for (i = 0; i < nC1; i++)
2718 for (j = 0; j < nR1; j++)
2720 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
2722 fVal1 = pMat1->GetDouble(i,j);
2723 fVal2 = pMat2->GetDouble(i,j);
2724 fSum1 += fVal1;
2725 fSum2 += fVal2;
2726 fSumSqrD += (fVal1 - fVal2)*(fVal1 - fVal2);
2727 fCount++;
2730 if (fCount < 1.0)
2732 PushNoValue();
2733 return;
2735 fT = sqrt(fCount-1.0) * fabs(fSum1 - fSum2) /
2736 sqrt(fCount * fSumSqrD - (fSum1-fSum2)*(fSum1-fSum2));
2737 fF = fCount - 1.0;
2739 else if (fTyp == 2.0)
2741 CalculateTest(false,nC1, nC2,nR1, nR2,pMat1,pMat2,fT,fF);
2743 else if (fTyp == 3.0)
2745 CalculateTest(true,nC1, nC2,nR1, nR2,pMat1,pMat2,fT,fF);
2748 else
2750 PushIllegalArgument();
2751 return;
2753 PushDouble( GetTDist( fT, fF, ( int )fTails ) );
2756 void ScInterpreter::ScFTest()
2758 if ( !MustHaveParamCount( GetByte(), 2 ) )
2759 return;
2760 ScMatrixRef pMat2 = GetMatrix();
2761 ScMatrixRef pMat1 = GetMatrix();
2762 if (!pMat1 || !pMat2)
2764 PushIllegalParameter();
2765 return;
2767 SCSIZE nC1, nC2;
2768 SCSIZE nR1, nR2;
2769 SCSIZE i, j;
2770 pMat1->GetDimensions(nC1, nR1);
2771 pMat2->GetDimensions(nC2, nR2);
2772 double fCount1 = 0.0;
2773 double fCount2 = 0.0;
2774 double fSum1 = 0.0;
2775 double fSumSqr1 = 0.0;
2776 double fSum2 = 0.0;
2777 double fSumSqr2 = 0.0;
2778 double fVal;
2779 for (i = 0; i < nC1; i++)
2780 for (j = 0; j < nR1; j++)
2782 if (!pMat1->IsString(i,j))
2784 fVal = pMat1->GetDouble(i,j);
2785 fSum1 += fVal;
2786 fSumSqr1 += fVal * fVal;
2787 fCount1++;
2790 for (i = 0; i < nC2; i++)
2791 for (j = 0; j < nR2; j++)
2793 if (!pMat2->IsString(i,j))
2795 fVal = pMat2->GetDouble(i,j);
2796 fSum2 += fVal;
2797 fSumSqr2 += fVal * fVal;
2798 fCount2++;
2801 if (fCount1 < 2.0 || fCount2 < 2.0)
2803 PushNoValue();
2804 return;
2806 double fS1 = (fSumSqr1-fSum1*fSum1/fCount1)/(fCount1-1.0);
2807 double fS2 = (fSumSqr2-fSum2*fSum2/fCount2)/(fCount2-1.0);
2808 if (fS1 == 0.0 || fS2 == 0.0)
2810 PushNoValue();
2811 return;
2813 double fF, fF1, fF2;
2814 if (fS1 > fS2)
2816 fF = fS1/fS2;
2817 fF1 = fCount1-1.0;
2818 fF2 = fCount2-1.0;
2820 else
2822 fF = fS2/fS1;
2823 fF1 = fCount2-1.0;
2824 fF2 = fCount1-1.0;
2826 PushDouble(2.0*GetFDist(fF, fF1, fF2));
2829 void ScInterpreter::ScChiTest()
2831 if ( !MustHaveParamCount( GetByte(), 2 ) )
2832 return;
2833 ScMatrixRef pMat2 = GetMatrix();
2834 ScMatrixRef pMat1 = GetMatrix();
2835 if (!pMat1 || !pMat2)
2837 PushIllegalParameter();
2838 return;
2840 SCSIZE nC1, nC2;
2841 SCSIZE nR1, nR2;
2842 pMat1->GetDimensions(nC1, nR1);
2843 pMat2->GetDimensions(nC2, nR2);
2844 if (nR1 != nR2 || nC1 != nC2)
2846 PushIllegalArgument();
2847 return;
2849 double fChi = 0.0;
2850 for (SCSIZE i = 0; i < nC1; i++)
2852 for (SCSIZE j = 0; j < nR1; j++)
2854 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
2856 double fValX = pMat1->GetDouble(i,j);
2857 double fValE = pMat2->GetDouble(i,j);
2858 fChi += (fValX - fValE) * (fValX - fValE) / fValE;
2860 else
2862 PushIllegalArgument();
2863 return;
2867 double fDF;
2868 if (nC1 == 1 || nR1 == 1)
2870 fDF = (double)(nC1*nR1 - 1);
2871 if (fDF == 0.0)
2873 PushNoValue();
2874 return;
2877 else
2878 fDF = (double)(nC1-1)*(double)(nR1-1);
2879 PushDouble(GetChiDist(fChi, fDF));
2882 void ScInterpreter::ScKurt()
2884 double fSum,fCount,vSum;
2885 std::vector<double> values;
2886 if ( !CalculateSkew(fSum,fCount,vSum,values) )
2887 return;
2889 if (fCount == 0.0)
2891 PushError( errDivisionByZero);
2892 return;
2895 double fMean = fSum / fCount;
2897 for (size_t i = 0; i < values.size(); i++)
2898 vSum += (values[i] - fMean) * (values[i] - fMean);
2900 double fStdDev = sqrt(vSum / (fCount - 1.0));
2901 double xpower4 = 0.0;
2903 if (fStdDev == 0.0)
2905 PushError( errDivisionByZero);
2906 return;
2909 for (size_t i = 0; i < values.size(); i++)
2911 double dx = (values[i] - fMean) / fStdDev;
2912 xpower4 = xpower4 + (dx * dx * dx * dx);
2915 double k_d = (fCount - 2.0) * (fCount - 3.0);
2916 double k_l = fCount * (fCount + 1.0) / ((fCount - 1.0) * k_d);
2917 double k_t = 3.0 * (fCount - 1.0) * (fCount - 1.0) / k_d;
2919 PushDouble(xpower4 * k_l - k_t);
2922 void ScInterpreter::ScHarMean()
2924 short nParamCount = GetByte();
2925 double nVal = 0.0;
2926 double nValCount = 0.0;
2927 ScAddress aAdr;
2928 ScRange aRange;
2929 size_t nRefInList = 0;
2930 while ((nGlobalError == 0) && (nParamCount-- > 0))
2932 switch (GetStackType())
2934 case formula::svDouble :
2936 double x = GetDouble();
2937 if (x > 0.0)
2939 nVal += 1.0/x;
2940 nValCount++;
2942 else
2943 SetError( errIllegalArgument);
2944 break;
2946 case svSingleRef :
2948 PopSingleRef( aAdr );
2949 ScRefCellValue aCell;
2950 aCell.assign(*pDok, aAdr);
2951 if (aCell.hasNumeric())
2953 double x = GetCellValue(aAdr, aCell);
2954 if (x > 0.0)
2956 nVal += 1.0/x;
2957 nValCount++;
2959 else
2960 SetError( errIllegalArgument);
2962 break;
2964 case formula::svDoubleRef :
2965 case svRefList :
2967 sal_uInt16 nErr = 0;
2968 PopDoubleRef( aRange, nParamCount, nRefInList);
2969 double nCellVal;
2970 ScValueIterator aValIter( pDok, aRange, mnSubTotalFlags );
2971 if (aValIter.GetFirst(nCellVal, nErr))
2973 if (nCellVal > 0.0)
2975 nVal += 1.0/nCellVal;
2976 nValCount++;
2978 else
2979 SetError( errIllegalArgument);
2980 SetError(nErr);
2981 while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
2983 if (nCellVal > 0.0)
2985 nVal += 1.0/nCellVal;
2986 nValCount++;
2988 else
2989 SetError( errIllegalArgument);
2991 SetError(nErr);
2994 break;
2995 case svMatrix :
2996 case svExternalSingleRef:
2997 case svExternalDoubleRef:
2999 ScMatrixRef pMat = GetMatrix();
3000 if (pMat)
3002 SCSIZE nCount = pMat->GetElementCount();
3003 if (pMat->IsNumeric())
3005 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3007 double x = pMat->GetDouble(nElem);
3008 if (x > 0.0)
3010 nVal += 1.0/x;
3011 nValCount++;
3013 else
3014 SetError( errIllegalArgument);
3017 else
3019 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3020 if (!pMat->IsString(nElem))
3022 double x = pMat->GetDouble(nElem);
3023 if (x > 0.0)
3025 nVal += 1.0/x;
3026 nValCount++;
3028 else
3029 SetError( errIllegalArgument);
3034 break;
3035 default : SetError(errIllegalParameter); break;
3038 if (nGlobalError == 0)
3039 PushDouble((double)nValCount/nVal);
3040 else
3041 PushError( nGlobalError);
3044 void ScInterpreter::ScGeoMean()
3046 short nParamCount = GetByte();
3047 double nVal = 0.0;
3048 double nValCount = 0.0;
3049 ScAddress aAdr;
3050 ScRange aRange;
3052 size_t nRefInList = 0;
3053 while ((nGlobalError == 0) && (nParamCount-- > 0))
3055 switch (GetStackType())
3057 case formula::svDouble :
3059 double x = GetDouble();
3060 if (x > 0.0)
3062 nVal += log(x);
3063 nValCount++;
3065 else
3066 SetError( errIllegalArgument);
3067 break;
3069 case svSingleRef :
3071 PopSingleRef( aAdr );
3072 ScRefCellValue aCell;
3073 aCell.assign(*pDok, aAdr);
3074 if (aCell.hasNumeric())
3076 double x = GetCellValue(aAdr, aCell);
3077 if (x > 0.0)
3079 nVal += log(x);
3080 nValCount++;
3082 else
3083 SetError( errIllegalArgument);
3085 break;
3087 case formula::svDoubleRef :
3088 case svRefList :
3090 sal_uInt16 nErr = 0;
3091 PopDoubleRef( aRange, nParamCount, nRefInList);
3092 double nCellVal;
3093 ScValueIterator aValIter( pDok, aRange, mnSubTotalFlags );
3094 if (aValIter.GetFirst(nCellVal, nErr))
3096 if (nCellVal > 0.0)
3098 nVal += log(nCellVal);
3099 nValCount++;
3101 else
3102 SetError( errIllegalArgument);
3103 SetError(nErr);
3104 while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
3106 if (nCellVal > 0.0)
3108 nVal += log(nCellVal);
3109 nValCount++;
3111 else
3112 SetError( errIllegalArgument);
3114 SetError(nErr);
3117 break;
3118 case svMatrix :
3119 case svExternalSingleRef:
3120 case svExternalDoubleRef:
3122 ScMatrixRef pMat = GetMatrix();
3123 if (pMat)
3125 SCSIZE nCount = pMat->GetElementCount();
3126 if (pMat->IsNumeric())
3128 for (SCSIZE ui = 0; ui < nCount; ui++)
3130 double x = pMat->GetDouble(ui);
3131 if (x > 0.0)
3133 nVal += log(x);
3134 nValCount++;
3136 else
3137 SetError( errIllegalArgument);
3140 else
3142 for (SCSIZE ui = 0; ui < nCount; ui++)
3143 if (!pMat->IsString(ui))
3145 double x = pMat->GetDouble(ui);
3146 if (x > 0.0)
3148 nVal += log(x);
3149 nValCount++;
3151 else
3152 SetError( errIllegalArgument);
3157 break;
3158 default : SetError(errIllegalParameter); break;
3161 if (nGlobalError == 0)
3162 PushDouble(exp(nVal / nValCount));
3163 else
3164 PushError( nGlobalError);
3167 void ScInterpreter::ScStandard()
3169 if ( MustHaveParamCount( GetByte(), 3 ) )
3171 double sigma = GetDouble();
3172 double mue = GetDouble();
3173 double x = GetDouble();
3174 if (sigma < 0.0)
3175 PushError( errIllegalArgument);
3176 else if (sigma == 0.0)
3177 PushError( errDivisionByZero);
3178 else
3179 PushDouble((x-mue)/sigma);
3182 bool ScInterpreter::CalculateSkew(double& fSum,double& fCount,double& vSum,std::vector<double>& values)
3184 short nParamCount = GetByte();
3185 if ( !MustHaveParamCountMin( nParamCount, 1 ) )
3186 return false;
3188 fSum = 0.0;
3189 fCount = 0.0;
3190 vSum = 0.0;
3191 double fVal = 0.0;
3192 ScAddress aAdr;
3193 ScRange aRange;
3194 size_t nRefInList = 0;
3195 while (nParamCount-- > 0)
3197 switch (GetStackType())
3199 case formula::svDouble :
3201 fVal = GetDouble();
3202 fSum += fVal;
3203 values.push_back(fVal);
3204 fCount++;
3206 break;
3207 case svSingleRef :
3209 PopSingleRef( aAdr );
3210 ScRefCellValue aCell;
3211 aCell.assign(*pDok, aAdr);
3212 if (aCell.hasNumeric())
3214 fVal = GetCellValue(aAdr, aCell);
3215 fSum += fVal;
3216 values.push_back(fVal);
3217 fCount++;
3220 break;
3221 case formula::svDoubleRef :
3222 case svRefList :
3224 PopDoubleRef( aRange, nParamCount, nRefInList);
3225 sal_uInt16 nErr = 0;
3226 ScValueIterator aValIter( pDok, aRange, mnSubTotalFlags );
3227 if (aValIter.GetFirst(fVal, nErr))
3229 fSum += fVal;
3230 values.push_back(fVal);
3231 fCount++;
3232 SetError(nErr);
3233 while ((nErr == 0) && aValIter.GetNext(fVal, nErr))
3235 fSum += fVal;
3236 values.push_back(fVal);
3237 fCount++;
3239 SetError(nErr);
3242 break;
3243 case svMatrix :
3244 case svExternalSingleRef:
3245 case svExternalDoubleRef:
3247 ScMatrixRef pMat = GetMatrix();
3248 if (pMat)
3250 SCSIZE nCount = pMat->GetElementCount();
3251 if (pMat->IsNumeric())
3253 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3255 fVal = pMat->GetDouble(nElem);
3256 fSum += fVal;
3257 values.push_back(fVal);
3258 fCount++;
3261 else
3263 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3264 if (!pMat->IsString(nElem))
3266 fVal = pMat->GetDouble(nElem);
3267 fSum += fVal;
3268 values.push_back(fVal);
3269 fCount++;
3274 break;
3275 default :
3276 SetError(errIllegalParameter);
3277 break;
3281 if (nGlobalError)
3283 PushError( nGlobalError);
3284 return false;
3285 } // if (nGlobalError)
3286 return true;
3289 void ScInterpreter::CalculateSkewOrSkewp( bool bSkewp )
3291 double fSum, fCount, vSum;
3292 std::vector<double> values;
3293 if (!CalculateSkew( fSum, fCount, vSum, values))
3294 return;
3296 double fMean = fSum / fCount;
3298 for (size_t i = 0; i < values.size(); ++i)
3299 vSum += (values[i] - fMean) * (values[i] - fMean);
3301 double fStdDev = sqrt( vSum / (bSkewp ? fCount : (fCount - 1.0)));
3302 double xcube = 0.0;
3304 if (fStdDev == 0)
3306 PushIllegalArgument();
3307 return;
3310 for (size_t i = 0; i < values.size(); ++i)
3312 double dx = (values[i] - fMean) / fStdDev;
3313 xcube = xcube + (dx * dx * dx);
3316 if (bSkewp)
3317 PushDouble( xcube / fCount );
3318 else
3319 PushDouble( ((xcube * fCount) / (fCount - 1.0)) / (fCount - 2.0) );
3322 void ScInterpreter::ScSkew()
3324 CalculateSkewOrSkewp( false );
3327 void ScInterpreter::ScSkewp()
3329 CalculateSkewOrSkewp( true );
3332 double ScInterpreter::GetMedian( vector<double> & rArray )
3334 size_t nSize = rArray.size();
3335 if (rArray.empty() || nSize == 0 || nGlobalError)
3337 SetError( errNoValue);
3338 return 0.0;
3341 // Upper median.
3342 size_t nMid = nSize / 2;
3343 vector<double>::iterator iMid = rArray.begin() + nMid;
3344 ::std::nth_element( rArray.begin(), iMid, rArray.end());
3345 if (nSize & 1)
3346 return *iMid; // Lower and upper median are equal.
3347 else
3349 double fUp = *iMid;
3350 // Lower median.
3351 iMid = rArray.begin() + nMid - 1;
3352 ::std::nth_element( rArray.begin(), iMid, rArray.end());
3353 return (fUp + *iMid) / 2;
3357 void ScInterpreter::ScMedian()
3359 sal_uInt8 nParamCount = GetByte();
3360 if ( !MustHaveParamCountMin( nParamCount, 1 ) )
3361 return;
3362 vector<double> aArray;
3363 GetNumberSequenceArray( nParamCount, aArray, false );
3364 PushDouble( GetMedian( aArray));
3367 double ScInterpreter::GetPercentile( vector<double> & rArray, double fPercentile )
3369 size_t nSize = rArray.size();
3370 if (rArray.empty() || nSize == 0 || nGlobalError)
3372 SetError( errNoValue);
3373 return 0.0;
3376 if (nSize == 1)
3377 return rArray[0];
3378 else
3380 size_t nIndex = (size_t)::rtl::math::approxFloor( fPercentile * (nSize-1));
3381 double fDiff = fPercentile * (nSize-1) - ::rtl::math::approxFloor( fPercentile * (nSize-1));
3382 OSL_ENSURE(nIndex < nSize, "GetPercentile: wrong index(1)");
3383 vector<double>::iterator iter = rArray.begin() + nIndex;
3384 ::std::nth_element( rArray.begin(), iter, rArray.end());
3385 if (fDiff == 0.0)
3386 return *iter;
3387 else
3389 OSL_ENSURE(nIndex < nSize-1, "GetPercentile: wrong index(2)");
3390 double fVal = *iter;
3391 iter = rArray.begin() + nIndex+1;
3392 ::std::nth_element( rArray.begin(), iter, rArray.end());
3393 return fVal + fDiff * (*iter - fVal);
3398 double ScInterpreter::GetPercentileExclusive( vector<double> & rArray, double fPercentile )
3400 size_t nSize1 = rArray.size() + 1;
3401 if ( rArray.empty() || nSize1 == 1 || nGlobalError )
3403 SetError( errNoValue );
3404 return 0.0;
3406 if ( fPercentile * nSize1 < 1.0 || fPercentile * nSize1 > (double) ( nSize1 - 1 ) )
3408 SetError( errIllegalParameter );
3409 return 0.0;
3412 size_t nIndex = (size_t)::rtl::math::approxFloor( fPercentile * nSize1 - 1 );
3413 double fDiff = fPercentile * nSize1 - 1 - ::rtl::math::approxFloor( fPercentile * nSize1 - 1 );
3414 OSL_ENSURE(nIndex < ( nSize1 - 1 ), "GetPercentile: wrong index(1)");
3415 vector<double>::iterator iter = rArray.begin() + nIndex;
3416 ::std::nth_element( rArray.begin(), iter, rArray.end());
3417 if (fDiff == 0.0)
3418 return *iter;
3419 else
3421 OSL_ENSURE(nIndex < nSize1, "GetPercentile: wrong index(2)");
3422 double fVal = *iter;
3423 iter = rArray.begin() + nIndex + 1;
3424 ::std::nth_element( rArray.begin(), iter, rArray.end());
3425 return fVal + fDiff * (*iter - fVal);
3429 void ScInterpreter::ScPercentile( bool bInclusive )
3431 if ( !MustHaveParamCount( GetByte(), 2 ) )
3432 return;
3433 double alpha = GetDouble();
3434 if ( bInclusive ? ( alpha < 0.0 || alpha > 1.0 ) : ( alpha <= 0.0 || alpha >= 1.0 ) )
3436 PushIllegalArgument();
3437 return;
3439 vector<double> aArray;
3440 GetNumberSequenceArray( 1, aArray, false );
3441 if ( bInclusive )
3442 PushDouble( GetPercentile( aArray, alpha ));
3443 else
3444 PushDouble( GetPercentileExclusive( aArray, alpha ));
3447 void ScInterpreter::ScQuartile( bool bInclusive )
3449 if ( !MustHaveParamCount( GetByte(), 2 ) )
3450 return;
3451 double fFlag = ::rtl::math::approxFloor(GetDouble());
3452 if ( bInclusive ? ( fFlag < 0.0 || fFlag > 4.0 ) : ( fFlag <= 0.0 || fFlag >= 4.0 ) )
3454 PushIllegalArgument();
3455 return;
3457 vector<double> aArray;
3458 GetNumberSequenceArray( 1, aArray, false );
3459 if ( bInclusive )
3460 PushDouble( fFlag == 2.0 ? GetMedian( aArray ) : GetPercentile( aArray, 0.25 * fFlag ) );
3461 else
3462 PushDouble( fFlag == 2.0 ? GetMedian( aArray ) : GetPercentileExclusive( aArray, 0.25 * fFlag ) );
3465 void ScInterpreter::ScModalValue()
3467 sal_uInt8 nParamCount = GetByte();
3468 if ( !MustHaveParamCountMin( nParamCount, 1 ) )
3469 return;
3470 vector<double> aSortArray;
3471 GetSortArray( nParamCount, aSortArray, NULL, false, false );
3472 SCSIZE nSize = aSortArray.size();
3473 if (aSortArray.empty() || nSize == 0 || nGlobalError)
3474 PushNoValue();
3475 else
3477 SCSIZE nMaxIndex = 0, nMax = 1, nCount = 1;
3478 double nOldVal = aSortArray[0];
3479 SCSIZE i;
3481 for ( i = 1; i < nSize; i++)
3483 if (aSortArray[i] == nOldVal)
3484 nCount++;
3485 else
3487 nOldVal = aSortArray[i];
3488 if (nCount > nMax)
3490 nMax = nCount;
3491 nMaxIndex = i-1;
3493 nCount = 1;
3496 if (nCount > nMax)
3498 nMax = nCount;
3499 nMaxIndex = i-1;
3501 if (nMax == 1 && nCount == 1)
3502 PushNoValue();
3503 else if (nMax == 1)
3504 PushDouble(nOldVal);
3505 else
3506 PushDouble(aSortArray[nMaxIndex]);
3510 void ScInterpreter::CalculateSmallLarge(bool bSmall)
3512 if ( !MustHaveParamCount( GetByte(), 2 ) )
3513 return;
3514 double f = ::rtl::math::approxFloor(GetDouble());
3515 if (f < 1.0)
3517 PushIllegalArgument();
3518 return;
3520 SCSIZE k = static_cast<SCSIZE>(f);
3521 vector<double> aSortArray;
3522 /* TODO: using nth_element() is best for one single value, but LARGE/SMALL
3523 * actually are defined to return an array of values if an array of
3524 * positions was passed, in which case, depending on the number of values,
3525 * we may or will need a real sorted array again, see #i32345. */
3526 GetNumberSequenceArray(1, aSortArray, false );
3527 SCSIZE nSize = aSortArray.size();
3528 if (aSortArray.empty() || nSize == 0 || nGlobalError || nSize < k)
3529 PushNoValue();
3530 else
3532 // TODO: the sorted case for array: PushDouble( aSortArray[ bSmall ? k-1 : nSize-k ] );
3533 vector<double>::iterator iPos = aSortArray.begin() + (bSmall ? k-1 : nSize-k);
3534 ::std::nth_element( aSortArray.begin(), iPos, aSortArray.end());
3535 PushDouble( *iPos);
3539 void ScInterpreter::ScLarge()
3541 CalculateSmallLarge(false);
3544 void ScInterpreter::ScSmall()
3546 CalculateSmallLarge(true);
3549 void ScInterpreter::ScPercentrank( bool bInclusive )
3551 sal_uInt8 nParamCount = GetByte();
3552 if ( !MustHaveParamCount( nParamCount, 2, 3 ) )
3553 return;
3554 double fSignificance = ( nParamCount == 3 ? ::rtl::math::approxFloor( GetDouble() ) : 3.0 );
3555 double fNum = GetDouble();
3556 vector<double> aSortArray;
3557 GetSortArray( 1, aSortArray, NULL, false, false );
3558 SCSIZE nSize = aSortArray.size();
3559 if ( aSortArray.empty() || nSize == 0 || nGlobalError )
3560 PushNoValue();
3561 else
3563 if ( fNum < aSortArray[ 0 ] || fNum > aSortArray[ nSize - 1 ] )
3564 PushNoValue();
3565 else
3567 double fRes;
3568 if ( nSize == 1 )
3569 fRes = 1.0; // fNum == aSortArray[ 0 ], see test above
3570 else
3571 fRes = GetPercentrank( aSortArray, fNum, bInclusive );
3572 if ( fRes != 0.0 )
3574 double fExp = ::rtl::math::approxFloor( log( fRes ) );
3575 fRes = ::rtl::math::round( fRes * pow( 10, -fExp + fSignificance - 1 ) ) / pow( 10, -fExp + fSignificance - 1 );
3577 PushDouble( fRes );
3582 double ScInterpreter::GetPercentrank( ::std::vector<double> & rArray, double fVal, bool bInclusive )
3584 SCSIZE nSize = rArray.size();
3585 double fRes;
3586 if ( fVal == rArray[ 0 ] )
3588 if ( bInclusive )
3589 fRes = 0.0;
3590 else
3591 fRes = 1.0 / ( double )( nSize + 1 );
3593 else
3595 SCSIZE nOldCount = 0;
3596 double fOldVal = rArray[ 0 ];
3597 SCSIZE i;
3598 for ( i = 1; i < nSize && rArray[ i ] < fVal; i++ )
3600 if ( rArray[ i ] != fOldVal )
3602 nOldCount = i;
3603 fOldVal = rArray[ i ];
3606 if ( rArray[ i ] != fOldVal )
3607 nOldCount = i;
3608 if ( fVal == rArray[ i ] )
3610 if ( bInclusive )
3611 fRes = div( nOldCount, nSize - 1 );
3612 else
3613 fRes = ( double )( i + 1 ) / ( double )( nSize + 1 );
3615 else
3617 // nOldCount is the count of smaller entries
3618 // fVal is between rArray[ nOldCount - 1 ] and rArray[ nOldCount ]
3619 // use linear interpolation to find a position between the entries
3620 if ( nOldCount == 0 )
3622 OSL_FAIL( "should not happen" );
3623 fRes = 0.0;
3625 else
3627 double fFract = ( fVal - rArray[ nOldCount - 1 ] ) /
3628 ( rArray[ nOldCount ] - rArray[ nOldCount - 1 ] );
3629 if ( bInclusive )
3630 fRes = div( ( double )( nOldCount - 1 ) + fFract, nSize - 1 );
3631 else
3632 fRes = ( ( double )nOldCount + fFract ) / ( double )( nSize + 1 );
3636 return fRes;
3639 void ScInterpreter::ScTrimMean()
3641 if ( !MustHaveParamCount( GetByte(), 2 ) )
3642 return;
3643 double alpha = GetDouble();
3644 if (alpha < 0.0 || alpha >= 1.0)
3646 PushIllegalArgument();
3647 return;
3649 vector<double> aSortArray;
3650 GetSortArray( 1, aSortArray, NULL, false, false );
3651 SCSIZE nSize = aSortArray.size();
3652 if (aSortArray.empty() || nSize == 0 || nGlobalError)
3653 PushNoValue();
3654 else
3656 sal_uLong nIndex = (sal_uLong) ::rtl::math::approxFloor(alpha*(double)nSize);
3657 if (nIndex % 2 != 0)
3658 nIndex--;
3659 nIndex /= 2;
3660 OSL_ENSURE(nIndex < nSize, "ScTrimMean: falscher Index");
3661 double fSum = 0.0;
3662 for (SCSIZE i = nIndex; i < nSize-nIndex; i++)
3663 fSum += aSortArray[i];
3664 PushDouble(fSum/(double)(nSize-2*nIndex));
3668 void ScInterpreter::GetNumberSequenceArray( sal_uInt8 nParamCount, vector<double>& rArray, bool bConvertTextInArray )
3670 ScAddress aAdr;
3671 ScRange aRange;
3672 short nParam = nParamCount;
3673 size_t nRefInList = 0;
3674 while (nParam-- > 0)
3676 const StackVar eStackType = GetStackType();
3677 switch (eStackType)
3679 case formula::svDouble :
3680 rArray.push_back( PopDouble());
3681 break;
3682 case svSingleRef :
3684 PopSingleRef( aAdr );
3685 ScRefCellValue aCell;
3686 aCell.assign(*pDok, aAdr);
3687 if (aCell.hasNumeric())
3688 rArray.push_back(GetCellValue(aAdr, aCell));
3690 break;
3691 case formula::svDoubleRef :
3692 case svRefList :
3694 PopDoubleRef( aRange, nParam, nRefInList);
3695 if (nGlobalError)
3696 break;
3698 aRange.Justify();
3699 SCSIZE nCellCount = aRange.aEnd.Col() - aRange.aStart.Col() + 1;
3700 nCellCount *= aRange.aEnd.Row() - aRange.aStart.Row() + 1;
3701 rArray.reserve( rArray.size() + nCellCount);
3703 sal_uInt16 nErr = 0;
3704 double fCellVal;
3705 ScValueIterator aValIter( pDok, aRange, mnSubTotalFlags );
3706 if (aValIter.GetFirst( fCellVal, nErr))
3708 rArray.push_back( fCellVal);
3709 SetError(nErr);
3710 while ((nErr == 0) && aValIter.GetNext( fCellVal, nErr))
3711 rArray.push_back( fCellVal);
3712 SetError(nErr);
3715 break;
3716 case svMatrix :
3717 case svExternalSingleRef:
3718 case svExternalDoubleRef:
3720 ScMatrixRef pMat = GetMatrix();
3721 if (!pMat)
3722 break;
3724 SCSIZE nCount = pMat->GetElementCount();
3725 rArray.reserve( rArray.size() + nCount);
3726 if (pMat->IsNumeric())
3728 for (SCSIZE i = 0; i < nCount; ++i)
3729 rArray.push_back( pMat->GetDouble(i));
3731 else if (bConvertTextInArray && eStackType == svMatrix)
3733 for (SCSIZE i = 0; i < nCount; ++i)
3735 if ( pMat->IsValue( i ) )
3736 rArray.push_back( pMat->GetDouble(i));
3737 else
3739 // tdf#88547 try to convert string to (date)value
3740 OUString aStr = pMat->GetString( i ).getString();
3741 if ( aStr.getLength() > 0 )
3743 sal_uInt16 nErr = nGlobalError;
3744 nGlobalError = 0;
3745 double fVal = ConvertStringToValue( aStr );
3746 if ( !nGlobalError )
3748 rArray.push_back( fVal );
3749 nGlobalError = nErr;
3751 else
3753 rArray.push_back( CreateDoubleError( errNoValue));
3754 // Propagate previous error if any, else
3755 // the current #VALUE! error.
3756 if (nErr)
3757 nGlobalError = nErr;
3758 else
3759 nGlobalError = errNoValue;
3765 else
3767 for (SCSIZE i = 0; i < nCount; ++i)
3769 if ( pMat->IsValue( i ) )
3770 rArray.push_back( pMat->GetDouble(i));
3774 break;
3775 default :
3776 PopError();
3777 SetError( errIllegalParameter);
3778 break;
3780 if (nGlobalError)
3781 break; // while
3783 // nParam > 0 in case of error, clean stack environment and obtain earlier
3784 // error if there was one.
3785 while (nParam-- > 0)
3786 PopError();
3789 void ScInterpreter::GetSortArray( sal_uInt8 nParamCount, vector<double>& rSortArray, vector<long>* pIndexOrder, bool bConvertTextInArray, bool bAllowEmptyArray )
3791 GetNumberSequenceArray( nParamCount, rSortArray, bConvertTextInArray );
3792 if (rSortArray.size() > MAX_ANZ_DOUBLE_FOR_SORT)
3793 SetError( errStackOverflow);
3794 else if ( rSortArray.empty() )
3796 if ( bAllowEmptyArray )
3797 return;
3798 SetError( errNoValue);
3801 if (nGlobalError == 0)
3802 QuickSort( rSortArray, pIndexOrder);
3805 static void lcl_QuickSort( long nLo, long nHi, vector<double>& rSortArray, vector<long>* pIndexOrder )
3807 // If pIndexOrder is not NULL, we assume rSortArray.size() == pIndexOrder->size().
3809 using ::std::swap;
3811 if (nHi - nLo == 1)
3813 if (rSortArray[nLo] > rSortArray[nHi])
3815 swap(rSortArray[nLo], rSortArray[nHi]);
3816 if (pIndexOrder)
3817 swap(pIndexOrder->at(nLo), pIndexOrder->at(nHi));
3819 return;
3822 long ni = nLo;
3823 long nj = nHi;
3826 double fLo = rSortArray[nLo];
3827 while (ni <= nHi && rSortArray[ni] < fLo) ni++;
3828 while (nj >= nLo && fLo < rSortArray[nj]) nj--;
3829 if (ni <= nj)
3831 if (ni != nj)
3833 swap(rSortArray[ni], rSortArray[nj]);
3834 if (pIndexOrder)
3835 swap(pIndexOrder->at(ni), pIndexOrder->at(nj));
3838 ++ni;
3839 --nj;
3842 while (ni < nj);
3844 if ((nj - nLo) < (nHi - ni))
3846 if (nLo < nj) lcl_QuickSort(nLo, nj, rSortArray, pIndexOrder);
3847 if (ni < nHi) lcl_QuickSort(ni, nHi, rSortArray, pIndexOrder);
3849 else
3851 if (ni < nHi) lcl_QuickSort(ni, nHi, rSortArray, pIndexOrder);
3852 if (nLo < nj) lcl_QuickSort(nLo, nj, rSortArray, pIndexOrder);
3856 void ScInterpreter::QuickSort( vector<double>& rSortArray, vector<long>* pIndexOrder )
3858 long n = static_cast<long>(rSortArray.size());
3860 if (pIndexOrder)
3862 pIndexOrder->clear();
3863 pIndexOrder->reserve(n);
3864 for (long i = 0; i < n; ++i)
3865 pIndexOrder->push_back(i);
3868 if (n < 2)
3869 return;
3871 size_t nValCount = rSortArray.size();
3872 for (size_t i = 0; (i + 4) <= nValCount-1; i += 4)
3874 size_t nInd = comphelper::rng::uniform_size_distribution(0, nValCount-2);
3875 ::std::swap( rSortArray[i], rSortArray[nInd]);
3876 if (pIndexOrder)
3877 ::std::swap( pIndexOrder->at(i), pIndexOrder->at(nInd));
3880 lcl_QuickSort(0, n-1, rSortArray, pIndexOrder);
3883 void ScInterpreter::ScRank( bool bAverage )
3885 sal_uInt8 nParamCount = GetByte();
3886 if ( !MustHaveParamCount( nParamCount, 2, 3 ) )
3887 return;
3888 bool bAscending;
3889 if ( nParamCount == 3 )
3890 bAscending = GetBool();
3891 else
3892 bAscending = false;
3894 vector<double> aSortArray;
3895 GetSortArray( 1, aSortArray, NULL, false, false );
3896 double fVal = GetDouble();
3897 SCSIZE nSize = aSortArray.size();
3898 if ( aSortArray.empty() || nSize == 0 || nGlobalError )
3899 PushNoValue();
3900 else
3902 if ( fVal < aSortArray[ 0 ] || fVal > aSortArray[ nSize - 1 ] )
3903 PushNoValue();
3904 else
3906 double fLastPos = 0;
3907 double fFirstPos = -1.0;
3908 bool bFinished = false;
3909 SCSIZE i;
3910 for ( i = 0; i < nSize && !bFinished && !nGlobalError; i++ )
3912 if ( aSortArray[ i ] == fVal )
3914 if ( fFirstPos < 0 )
3915 fFirstPos = i + 1.0;
3917 else
3919 if ( aSortArray[ i ] > fVal )
3921 fLastPos = i;
3922 bFinished = true;
3926 if ( !bFinished )
3927 fLastPos = i;
3928 if ( !bAverage )
3930 if ( bAscending )
3931 PushDouble( fFirstPos );
3932 else
3933 PushDouble( nSize + 1.0 - fLastPos );
3935 else
3937 if ( bAscending )
3938 PushDouble( ( fFirstPos + fLastPos ) / 2.0 );
3939 else
3940 PushDouble( nSize + 1.0 - ( fFirstPos + fLastPos ) / 2.0 );
3946 void ScInterpreter::ScAveDev()
3948 sal_uInt8 nParamCount = GetByte();
3949 if ( !MustHaveParamCountMin( nParamCount, 1 ) )
3950 return;
3951 sal_uInt16 SaveSP = sp;
3952 double nMiddle = 0.0;
3953 double rVal = 0.0;
3954 double rValCount = 0.0;
3955 ScAddress aAdr;
3956 ScRange aRange;
3957 short nParam = nParamCount;
3958 size_t nRefInList = 0;
3959 while (nParam-- > 0)
3961 switch (GetStackType())
3963 case formula::svDouble :
3964 rVal += GetDouble();
3965 rValCount++;
3966 break;
3967 case svSingleRef :
3969 PopSingleRef( aAdr );
3970 ScRefCellValue aCell;
3971 aCell.assign(*pDok, aAdr);
3972 if (aCell.hasNumeric())
3974 rVal += GetCellValue(aAdr, aCell);
3975 rValCount++;
3978 break;
3979 case formula::svDoubleRef :
3980 case svRefList :
3982 sal_uInt16 nErr = 0;
3983 double nCellVal;
3984 PopDoubleRef( aRange, nParam, nRefInList);
3985 ScValueIterator aValIter( pDok, aRange, mnSubTotalFlags );
3986 if (aValIter.GetFirst(nCellVal, nErr))
3988 rVal += nCellVal;
3989 rValCount++;
3990 SetError(nErr);
3991 while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
3993 rVal += nCellVal;
3994 rValCount++;
3996 SetError(nErr);
3999 break;
4000 case svMatrix :
4001 case svExternalSingleRef:
4002 case svExternalDoubleRef:
4004 ScMatrixRef pMat = GetMatrix();
4005 if (pMat)
4007 SCSIZE nCount = pMat->GetElementCount();
4008 if (pMat->IsNumeric())
4010 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
4012 rVal += pMat->GetDouble(nElem);
4013 rValCount++;
4016 else
4018 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
4019 if (!pMat->IsString(nElem))
4021 rVal += pMat->GetDouble(nElem);
4022 rValCount++;
4027 break;
4028 default :
4029 SetError(errIllegalParameter);
4030 break;
4033 if (nGlobalError)
4035 PushError( nGlobalError);
4036 return;
4038 nMiddle = rVal / rValCount;
4039 sp = SaveSP;
4040 rVal = 0.0;
4041 nParam = nParamCount;
4042 nRefInList = 0;
4043 while (nParam-- > 0)
4045 switch (GetStackType())
4047 case formula::svDouble :
4048 rVal += fabs(GetDouble() - nMiddle);
4049 break;
4050 case svSingleRef :
4052 PopSingleRef( aAdr );
4053 ScRefCellValue aCell;
4054 aCell.assign(*pDok, aAdr);
4055 if (aCell.hasNumeric())
4056 rVal += fabs(GetCellValue(aAdr, aCell) - nMiddle);
4058 break;
4059 case formula::svDoubleRef :
4060 case svRefList :
4062 sal_uInt16 nErr = 0;
4063 double nCellVal;
4064 PopDoubleRef( aRange, nParam, nRefInList);
4065 ScValueIterator aValIter( pDok, aRange, mnSubTotalFlags );
4066 if (aValIter.GetFirst(nCellVal, nErr))
4068 rVal += (fabs(nCellVal - nMiddle));
4069 while (aValIter.GetNext(nCellVal, nErr))
4070 rVal += fabs(nCellVal - nMiddle);
4073 break;
4074 case svMatrix :
4075 case svExternalSingleRef:
4076 case svExternalDoubleRef:
4078 ScMatrixRef pMat = GetMatrix();
4079 if (pMat)
4081 SCSIZE nCount = pMat->GetElementCount();
4082 if (pMat->IsNumeric())
4084 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
4086 rVal += fabs(pMat->GetDouble(nElem) - nMiddle);
4089 else
4091 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
4093 if (!pMat->IsString(nElem))
4094 rVal += fabs(pMat->GetDouble(nElem) - nMiddle);
4099 break;
4100 default : SetError(errIllegalParameter); break;
4103 PushDouble(rVal / rValCount);
4106 void ScInterpreter::ScDevSq()
4108 double nVal;
4109 double nValCount;
4110 GetStVarParams(nVal, nValCount);
4111 PushDouble(nVal);
4114 void ScInterpreter::ScProbability()
4116 sal_uInt8 nParamCount = GetByte();
4117 if ( !MustHaveParamCount( nParamCount, 3, 4 ) )
4118 return;
4119 double fUp, fLo;
4120 fUp = GetDouble();
4121 if (nParamCount == 4)
4122 fLo = GetDouble();
4123 else
4124 fLo = fUp;
4125 if (fLo > fUp)
4127 double fTemp = fLo;
4128 fLo = fUp;
4129 fUp = fTemp;
4131 ScMatrixRef pMatP = GetMatrix();
4132 ScMatrixRef pMatW = GetMatrix();
4133 if (!pMatP || !pMatW)
4134 PushIllegalParameter();
4135 else
4137 SCSIZE nC1, nC2;
4138 SCSIZE nR1, nR2;
4139 pMatP->GetDimensions(nC1, nR1);
4140 pMatW->GetDimensions(nC2, nR2);
4141 if (nC1 != nC2 || nR1 != nR2 || nC1 == 0 || nR1 == 0 ||
4142 nC2 == 0 || nR2 == 0)
4143 PushNA();
4144 else
4146 double fSum = 0.0;
4147 double fRes = 0.0;
4148 bool bStop = false;
4149 double fP, fW;
4150 for ( SCSIZE i = 0; i < nC1 && !bStop; i++ )
4152 for (SCSIZE j = 0; j < nR1 && !bStop; ++j )
4154 if (pMatP->IsValue(i,j) && pMatW->IsValue(i,j))
4156 fP = pMatP->GetDouble(i,j);
4157 fW = pMatW->GetDouble(i,j);
4158 if (fP < 0.0 || fP > 1.0)
4159 bStop = true;
4160 else
4162 fSum += fP;
4163 if (fW >= fLo && fW <= fUp)
4164 fRes += fP;
4167 else
4168 SetError( errIllegalArgument);
4171 if (bStop || fabs(fSum -1.0) > 1.0E-7)
4172 PushNoValue();
4173 else
4174 PushDouble(fRes);
4179 void ScInterpreter::ScCorrel()
4181 // This is identical to ScPearson()
4182 ScPearson();
4185 void ScInterpreter::ScCovarianceP()
4187 CalculatePearsonCovar( false, false, false );
4190 void ScInterpreter::ScCovarianceS()
4192 CalculatePearsonCovar( false, false, true );
4195 void ScInterpreter::ScPearson()
4197 CalculatePearsonCovar( true, false, false );
4200 void ScInterpreter::CalculatePearsonCovar( bool _bPearson, bool _bStexy, bool _bSample )
4202 if ( !MustHaveParamCount( GetByte(), 2 ) )
4203 return;
4204 ScMatrixRef pMat1 = GetMatrix();
4205 ScMatrixRef pMat2 = GetMatrix();
4206 if (!pMat1 || !pMat2)
4208 PushIllegalParameter();
4209 return;
4211 SCSIZE nC1, nC2;
4212 SCSIZE nR1, nR2;
4213 pMat1->GetDimensions(nC1, nR1);
4214 pMat2->GetDimensions(nC2, nR2);
4215 if (nR1 != nR2 || nC1 != nC2)
4217 PushIllegalArgument();
4218 return;
4220 /* #i78250#
4221 * (sum((X-MeanX)(Y-MeanY)))/N equals (SumXY)/N-MeanX*MeanY mathematically,
4222 * but the latter produces wrong results if the absolute values are high,
4223 * for example above 10^8
4225 double fCount = 0.0;
4226 double fSumX = 0.0;
4227 double fSumY = 0.0;
4229 for (SCSIZE i = 0; i < nC1; i++)
4231 for (SCSIZE j = 0; j < nR1; j++)
4233 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
4235 double fValX = pMat1->GetDouble(i,j);
4236 double fValY = pMat2->GetDouble(i,j);
4237 fSumX += fValX;
4238 fSumY += fValY;
4239 fCount++;
4243 if (fCount < (_bStexy ? 3.0 : (_bSample ? 2.0 : 1.0)))
4244 PushNoValue();
4245 else
4247 double fSumDeltaXDeltaY = 0.0; // sum of (ValX-MeanX)*(ValY-MeanY)
4248 double fSumSqrDeltaX = 0.0; // sum of (ValX-MeanX)^2
4249 double fSumSqrDeltaY = 0.0; // sum of (ValY-MeanY)^2
4250 const double fMeanX = fSumX / fCount;
4251 const double fMeanY = fSumY / fCount;
4252 for (SCSIZE i = 0; i < nC1; i++)
4254 for (SCSIZE j = 0; j < nR1; j++)
4256 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
4258 const double fValX = pMat1->GetDouble(i,j);
4259 const double fValY = pMat2->GetDouble(i,j);
4260 fSumDeltaXDeltaY += (fValX - fMeanX) * (fValY - fMeanY);
4261 if ( _bPearson )
4263 fSumSqrDeltaX += (fValX - fMeanX) * (fValX - fMeanX);
4264 fSumSqrDeltaY += (fValY - fMeanY) * (fValY - fMeanY);
4269 if ( _bPearson )
4271 if (fSumSqrDeltaX == 0.0 || ( !_bStexy && fSumSqrDeltaY == 0.0) )
4272 PushError( errDivisionByZero);
4273 else if ( _bStexy )
4274 PushDouble( sqrt( (fSumSqrDeltaY - fSumDeltaXDeltaY *
4275 fSumDeltaXDeltaY / fSumSqrDeltaX) / (fCount-2)));
4276 else
4277 PushDouble( fSumDeltaXDeltaY / sqrt( fSumSqrDeltaX * fSumSqrDeltaY));
4279 else
4281 if ( _bSample )
4282 PushDouble( fSumDeltaXDeltaY / ( fCount - 1 ) );
4283 else
4284 PushDouble( fSumDeltaXDeltaY / fCount);
4289 void ScInterpreter::ScRSQ()
4291 // Same as ScPearson()*ScPearson()
4292 ScPearson();
4293 if (!nGlobalError)
4295 switch (GetStackType())
4297 case formula::svDouble:
4299 double fVal = PopDouble();
4300 PushDouble( fVal * fVal);
4302 break;
4303 default:
4304 PopError();
4305 PushNoValue();
4310 void ScInterpreter::ScSTEYX()
4312 CalculatePearsonCovar( true, true, false );
4314 void ScInterpreter::CalculateSlopeIntercept(bool bSlope)
4316 if ( !MustHaveParamCount( GetByte(), 2 ) )
4317 return;
4318 ScMatrixRef pMat1 = GetMatrix();
4319 ScMatrixRef pMat2 = GetMatrix();
4320 if (!pMat1 || !pMat2)
4322 PushIllegalParameter();
4323 return;
4325 SCSIZE nC1, nC2;
4326 SCSIZE nR1, nR2;
4327 pMat1->GetDimensions(nC1, nR1);
4328 pMat2->GetDimensions(nC2, nR2);
4329 if (nR1 != nR2 || nC1 != nC2)
4331 PushIllegalArgument();
4332 return;
4334 // #i78250# numerical stability improved
4335 double fCount = 0.0;
4336 double fSumX = 0.0;
4337 double fSumY = 0.0;
4339 for (SCSIZE i = 0; i < nC1; i++)
4341 for (SCSIZE j = 0; j < nR1; j++)
4343 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
4345 double fValX = pMat1->GetDouble(i,j);
4346 double fValY = pMat2->GetDouble(i,j);
4347 fSumX += fValX;
4348 fSumY += fValY;
4349 fCount++;
4353 if (fCount < 1.0)
4354 PushNoValue();
4355 else
4357 double fSumDeltaXDeltaY = 0.0; // sum of (ValX-MeanX)*(ValY-MeanY)
4358 double fSumSqrDeltaX = 0.0; // sum of (ValX-MeanX)^2
4359 double fMeanX = fSumX / fCount;
4360 double fMeanY = fSumY / fCount;
4361 for (SCSIZE i = 0; i < nC1; i++)
4363 for (SCSIZE j = 0; j < nR1; j++)
4365 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
4367 double fValX = pMat1->GetDouble(i,j);
4368 double fValY = pMat2->GetDouble(i,j);
4369 fSumDeltaXDeltaY += (fValX - fMeanX) * (fValY - fMeanY);
4370 fSumSqrDeltaX += (fValX - fMeanX) * (fValX - fMeanX);
4374 if (fSumSqrDeltaX == 0.0)
4375 PushError( errDivisionByZero);
4376 else
4378 if ( bSlope )
4379 PushDouble( fSumDeltaXDeltaY / fSumSqrDeltaX);
4380 else
4381 PushDouble( fMeanY - fSumDeltaXDeltaY / fSumSqrDeltaX * fMeanX);
4386 void ScInterpreter::ScSlope()
4388 CalculateSlopeIntercept(true);
4391 void ScInterpreter::ScIntercept()
4393 CalculateSlopeIntercept(false);
4396 void ScInterpreter::ScForecast()
4398 if ( !MustHaveParamCount( GetByte(), 3 ) )
4399 return;
4400 ScMatrixRef pMat1 = GetMatrix();
4401 ScMatrixRef pMat2 = GetMatrix();
4402 if (!pMat1 || !pMat2)
4404 PushIllegalParameter();
4405 return;
4407 SCSIZE nC1, nC2;
4408 SCSIZE nR1, nR2;
4409 pMat1->GetDimensions(nC1, nR1);
4410 pMat2->GetDimensions(nC2, nR2);
4411 if (nR1 != nR2 || nC1 != nC2)
4413 PushIllegalArgument();
4414 return;
4416 double fVal = GetDouble();
4417 // #i78250# numerical stability improved
4418 double fCount = 0.0;
4419 double fSumX = 0.0;
4420 double fSumY = 0.0;
4422 for (SCSIZE i = 0; i < nC1; i++)
4424 for (SCSIZE j = 0; j < nR1; j++)
4426 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
4428 double fValX = pMat1->GetDouble(i,j);
4429 double fValY = pMat2->GetDouble(i,j);
4430 fSumX += fValX;
4431 fSumY += fValY;
4432 fCount++;
4436 if (fCount < 1.0)
4437 PushNoValue();
4438 else
4440 double fSumDeltaXDeltaY = 0.0; // sum of (ValX-MeanX)*(ValY-MeanY)
4441 double fSumSqrDeltaX = 0.0; // sum of (ValX-MeanX)^2
4442 double fMeanX = fSumX / fCount;
4443 double fMeanY = fSumY / fCount;
4444 for (SCSIZE i = 0; i < nC1; i++)
4446 for (SCSIZE j = 0; j < nR1; j++)
4448 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
4450 double fValX = pMat1->GetDouble(i,j);
4451 double fValY = pMat2->GetDouble(i,j);
4452 fSumDeltaXDeltaY += (fValX - fMeanX) * (fValY - fMeanY);
4453 fSumSqrDeltaX += (fValX - fMeanX) * (fValX - fMeanX);
4457 if (fSumSqrDeltaX == 0.0)
4458 PushError( errDivisionByZero);
4459 else
4460 PushDouble( fMeanY + fSumDeltaXDeltaY / fSumSqrDeltaX * (fVal - fMeanX));
4464 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */