xref: /aoo42x/main/sc/source/core/tool/interpr3.cxx (revision b3f79822)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 
27 // INCLUDE ---------------------------------------------------------------
28 
29 #include <tools/solar.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <rtl/logfile.hxx>
33 
34 #include "interpre.hxx"
35 #include "global.hxx"
36 #include "compiler.hxx"
37 #include "cell.hxx"
38 #include "document.hxx"
39 #include "dociter.hxx"
40 #include "scmatrix.hxx"
41 #include "globstr.hrc"
42 
43 #include <math.h>
44 #include <vector>
45 #include <algorithm>
46 
47 using ::std::vector;
48 using namespace formula;
49 
50 // STATIC DATA -----------------------------------------------------------
51 
52 #define SCdEpsilon                1.0E-7
53 #define SC_MAX_ITERATION_COUNT    20
54 #define MAX_ANZ_DOUBLE_FOR_SORT 100000
55 // PI jetzt als F_PI aus solar.h
56 //#define   PI            3.1415926535897932
57 
58 const double ScInterpreter::fMaxGammaArgument = 171.624376956302;  // found experimental
59 const double fMachEps = ::std::numeric_limits<double>::epsilon();
60 
61 //-----------------------------------------------------------------------------
62 
63 class ScDistFunc
64 {
65 public:
66     virtual double GetValue(double x) const = 0;
67 };
68 
69 //  iteration for inverse distributions
70 
71 //template< class T > double lcl_IterateInverse( const T& rFunction, double x0, double x1, bool& rConvError )
72 
73 /** u*w<0.0 fails for values near zero */
74 inline bool lcl_HasChangeOfSign( double u, double w )
75 {
76     return (u < 0.0 && w > 0.0) || (u > 0.0 && w < 0.0);
77 }
78 
79 double lcl_IterateInverse( const ScDistFunc& rFunction, double fAx, double fBx, bool& rConvError )
80 {
81     rConvError = false;
82     const double fYEps = 1.0E-307;
83     const double fXEps = ::std::numeric_limits<double>::epsilon();
84 
85     DBG_ASSERT(fAx<fBx, "IterateInverse: wrong interval");
86 
87     //  find enclosing interval
88 
89     double fAy = rFunction.GetValue(fAx);
90     double fBy = rFunction.GetValue(fBx);
91     double fTemp;
92     unsigned short nCount;
93     for (nCount = 0; nCount < 1000 && !lcl_HasChangeOfSign(fAy,fBy); nCount++)
94     {
95         if (fabs(fAy) <= fabs(fBy))
96         {
97             fTemp = fAx;
98             fAx += 2.0 * (fAx - fBx);
99             if (fAx < 0.0)
100                 fAx = 0.0;
101             fBx = fTemp;
102             fBy = fAy;
103             fAy = rFunction.GetValue(fAx);
104         }
105         else
106         {
107             fTemp = fBx;
108             fBx += 2.0 * (fBx - fAx);
109             fAx = fTemp;
110             fAy = fBy;
111             fBy = rFunction.GetValue(fBx);
112         }
113     }
114 
115     if (fAy == 0.0)
116         return fAx;
117     if (fBy == 0.0)
118         return fBx;
119     if (!lcl_HasChangeOfSign( fAy, fBy))
120     {
121         rConvError = true;
122         return 0.0;
123     }
124     // inverse quadric interpolation with additional brackets
125     // set three points
126     double fPx = fAx;
127     double fPy = fAy;
128     double fQx = fBx;
129     double fQy = fBy;
130     double fRx = fAx;
131     double fRy = fAy;
132     double fSx = 0.5 * (fAx + fBx); // potential next point
133     bool bHasToInterpolate = true;
134     nCount = 0;
135     while ( nCount < 500 && fabs(fRy) > fYEps &&
136             (fBx-fAx) > ::std::max( fabs(fAx), fabs(fBx)) * fXEps )
137     {
138         if (bHasToInterpolate)
139         {
140             if (fPy!=fQy && fQy!=fRy && fRy!=fPy)
141             {
142                 fSx = fPx * fRy * fQy / (fRy-fPy) / (fQy-fPy)
143                     + fRx * fQy * fPy / (fQy-fRy) / (fPy-fRy)
144                     + fQx * fPy * fRy / (fPy-fQy) / (fRy-fQy);
145                 bHasToInterpolate = (fAx < fSx) && (fSx < fBx); // inside the brackets?
146             }
147             else
148                 bHasToInterpolate = false;
149         }
150         if(!bHasToInterpolate)
151         {
152             fSx = 0.5 * (fAx + fBx);
153             // reset points
154             fPx = fAx; fPy = fAy;
155             fQx = fBx; fQy = fBy;
156             bHasToInterpolate = true;
157         }
158         // shift points for next interpolation
159         fPx = fQx; fQx = fRx; fRx = fSx;
160         fPy = fQy; fQy = fRy; fRy = rFunction.GetValue(fSx);
161         // update brackets
162         if (lcl_HasChangeOfSign( fAy, fRy))
163         {
164             fBx = fRx; fBy = fRy;
165         }
166         else
167         {
168             fAx = fRx; fAy = fRy;
169         }
170         // if last interration brought to small advance, then do bisection next
171         // time, for safety
172         bHasToInterpolate = bHasToInterpolate && (fabs(fRy) * 2.0 <= fabs(fQy));
173         ++nCount;
174     }
175     return fRx;
176 }
177 
178 //-----------------------------------------------------------------------------
179 // Allgemeine Funktionen
180 //-----------------------------------------------------------------------------
181 
182 void ScInterpreter::ScNoName()
183 {
184     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScNoName" );
185     PushError(errNoName);
186 }
187 
188 void ScInterpreter::ScBadName()
189 {
190     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScBadName" );
191     short nParamCount = GetByte();
192     while (nParamCount-- > 0)
193     {
194         PopError();
195     }
196     PushError( errNoName);
197 }
198 
199 double ScInterpreter::phi(double x)
200 {
201     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::phi" );
202     return  0.39894228040143268 * exp(-(x * x) / 2.0);
203 }
204 
205 double ScInterpreter::integralPhi(double x)
206 { // Using gauss(x)+0.5 has severe cancellation errors for x<-4
207     return 0.5 * ::rtl::math::erfc(-x * 0.7071067811865475); // * 1/sqrt(2)
208 }
209 
210 double ScInterpreter::taylor(double* pPolynom, sal_uInt16 nMax, double x)
211 {
212     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::taylor" );
213     double nVal = pPolynom[nMax];
214     for (short i = nMax-1; i >= 0; i--)
215     {
216         nVal = pPolynom[i] + (nVal * x);
217     }
218     return nVal;
219 }
220 
221 double ScInterpreter::gauss(double x)
222 {
223     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::gauss" );
224     double t0[] =
225     { 0.39894228040143268, -0.06649038006690545,  0.00997355701003582,
226      -0.00118732821548045,  0.00011543468761616, -0.00000944465625950,
227       0.00000066596935163, -0.00000004122667415,  0.00000000227352982,
228       0.00000000011301172,  0.00000000000511243, -0.00000000000021218 };
229     double t2[] =
230     { 0.47724986805182079,  0.05399096651318805, -0.05399096651318805,
231       0.02699548325659403, -0.00449924720943234, -0.00224962360471617,
232       0.00134977416282970, -0.00011783742691370, -0.00011515930357476,
233       0.00003704737285544,  0.00000282690796889, -0.00000354513195524,
234       0.00000037669563126,  0.00000019202407921, -0.00000005226908590,
235      -0.00000000491799345,  0.00000000366377919, -0.00000000015981997,
236      -0.00000000017381238,  0.00000000002624031,  0.00000000000560919,
237      -0.00000000000172127, -0.00000000000008634,  0.00000000000007894 };
238     double t4[] =
239     { 0.49996832875816688,  0.00013383022576489, -0.00026766045152977,
240       0.00033457556441221, -0.00028996548915725,  0.00018178605666397,
241      -0.00008252863922168,  0.00002551802519049, -0.00000391665839292,
242      -0.00000074018205222,  0.00000064422023359, -0.00000017370155340,
243       0.00000000909595465,  0.00000000944943118, -0.00000000329957075,
244       0.00000000029492075,  0.00000000011874477, -0.00000000004420396,
245       0.00000000000361422,  0.00000000000143638, -0.00000000000045848 };
246     double asympt[] = { -1.0, 1.0, -3.0, 15.0, -105.0 };
247 
248     double xAbs = fabs(x);
249     sal_uInt16 xShort = (sal_uInt16)::rtl::math::approxFloor(xAbs);
250     double nVal = 0.0;
251     if (xShort == 0)
252         nVal = taylor(t0, 11, (xAbs * xAbs)) * xAbs;
253     else if ((xShort >= 1) && (xShort <= 2))
254         nVal = taylor(t2, 23, (xAbs - 2.0));
255     else if ((xShort >= 3) && (xShort <= 4))
256         nVal = taylor(t4, 20, (xAbs - 4.0));
257     else
258         nVal = 0.5 + phi(xAbs) * taylor(asympt, 4, 1.0 / (xAbs * xAbs)) / xAbs;
259     if (x < 0.0)
260         return -nVal;
261     else
262         return nVal;
263 }
264 
265 //
266 //  #i26836# new gaussinv implementation by Martin Eitzenberger <m.eitzenberger@unix.net>
267 //
268 
269 double ScInterpreter::gaussinv(double x)
270 {
271     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::gaussinv" );
272     double q,t,z;
273 
274     q=x-0.5;
275 
276     if(fabs(q)<=.425)
277     {
278         t=0.180625-q*q;
279 
280         z=
281         q*
282         (
283             (
284                 (
285                     (
286                         (
287                             (
288                                 (
289                                     t*2509.0809287301226727+33430.575583588128105
290                                 )
291                                 *t+67265.770927008700853
292                             )
293                             *t+45921.953931549871457
294                         )
295                         *t+13731.693765509461125
296                     )
297                     *t+1971.5909503065514427
298                 )
299                 *t+133.14166789178437745
300             )
301             *t+3.387132872796366608
302         )
303         /
304         (
305             (
306                 (
307                     (
308                         (
309                             (
310                                 (
311                                     t*5226.495278852854561+28729.085735721942674
312                                 )
313                                 *t+39307.89580009271061
314                             )
315                             *t+21213.794301586595867
316                         )
317                         *t+5394.1960214247511077
318                     )
319                     *t+687.1870074920579083
320                 )
321                 *t+42.313330701600911252
322             )
323             *t+1.0
324         );
325 
326     }
327     else
328     {
329         if(q>0) t=1-x;
330         else        t=x;
331 
332         t=sqrt(-log(t));
333 
334         if(t<=5.0)
335         {
336             t+=-1.6;
337 
338             z=
339             (
340                 (
341                     (
342                         (
343                             (
344                                 (
345                                     (
346                                         t*7.7454501427834140764e-4+0.0227238449892691845833
347                                     )
348                                     *t+0.24178072517745061177
349                                 )
350                                 *t+1.27045825245236838258
351                             )
352                             *t+3.64784832476320460504
353                         )
354                         *t+5.7694972214606914055
355                     )
356                     *t+4.6303378461565452959
357                 )
358                 *t+1.42343711074968357734
359             )
360             /
361             (
362                 (
363                     (
364                         (
365                             (
366                                 (
367                                     (
368                                         t*1.05075007164441684324e-9+5.475938084995344946e-4
369                                     )
370                                     *t+0.0151986665636164571966
371                                 )
372                                 *t+0.14810397642748007459
373                             )
374                             *t+0.68976733498510000455
375                         )
376                         *t+1.6763848301838038494
377                     )
378                     *t+2.05319162663775882187
379                 )
380                 *t+1.0
381             );
382 
383         }
384         else
385         {
386             t+=-5.0;
387 
388             z=
389             (
390                 (
391                     (
392                         (
393                             (
394                                 (
395                                     (
396                                         t*2.01033439929228813265e-7+2.71155556874348757815e-5
397                                     )
398                                     *t+0.0012426609473880784386
399                                 )
400                                 *t+0.026532189526576123093
401                             )
402                             *t+0.29656057182850489123
403                         )
404                         *t+1.7848265399172913358
405                     )
406                     *t+5.4637849111641143699
407                 )
408                 *t+6.6579046435011037772
409             )
410             /
411             (
412                 (
413                     (
414                         (
415                             (
416                                 (
417                                     (
418                                         t*2.04426310338993978564e-15+1.4215117583164458887e-7
419                                     )
420                                     *t+1.8463183175100546818e-5
421                                 )
422                                 *t+7.868691311456132591e-4
423                             )
424                             *t+0.0148753612908506148525
425                         )
426                         *t+0.13692988092273580531
427                     )
428                     *t+0.59983220655588793769
429                 )
430                 *t+1.0
431             );
432 
433         }
434 
435         if(q<0.0) z=-z;
436     }
437 
438     return z;
439 }
440 
441 double ScInterpreter::Fakultaet(double x)
442 {
443     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::Fakultaet" );
444     x = ::rtl::math::approxFloor(x);
445     if (x < 0.0)
446         return 0.0;
447     else if (x == 0.0)
448         return 1.0;
449     else if (x <= 170.0)
450     {
451         double fTemp = x;
452         while (fTemp > 2.0)
453         {
454             fTemp--;
455             x *= fTemp;
456         }
457     }
458     else
459         SetError(errNoValue);
460 /*                                           // Stirlingsche Naeherung zu ungenau
461     else
462         x = pow(x/exp(1), x) * sqrt(x) * SQRT_2_PI * (1.0 + 1.0 / (12.0 * x));
463 */
464     return x;
465 }
466 
467 double ScInterpreter::BinomKoeff(double n, double k)
468 {
469     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::BinomKoeff" );
470     double nVal = 0.0;
471     k = ::rtl::math::approxFloor(k);
472     if (n < k)
473         nVal = 0.0;
474     else if (k == 0.0)
475         nVal = 1.0;
476     else
477     {
478         nVal = n/k;
479         n--;
480         k--;
481         while (k > 0.0)
482         {
483             nVal *= n/k;
484             k--;
485             n--;
486         }
487 /*
488         double f1 = n;                      // Zaehler
489         double f2 = k;                      // Nenner
490         n--;
491         k--;
492         while (k > 0.0)
493         {
494             f2 *= k;
495             f1 *= n;
496             k--;
497             n--;
498         }
499         nVal = f1 / f2;
500 */
501     }
502     return nVal;
503 }
504 
505 
506 // The algorithm is based on lanczos13m53 in lanczos.hpp
507 // in math library from http://www.boost.org
508 /** you must ensure fZ>0
509     Uses a variant of the Lanczos sum with a rational function. */
510 double lcl_getLanczosSum(double fZ)
511 {
512     const double fNum[13] ={
513         23531376880.41075968857200767445163675473,
514         42919803642.64909876895789904700198885093,
515         35711959237.35566804944018545154716670596,
516         17921034426.03720969991975575445893111267,
517         6039542586.35202800506429164430729792107,
518         1439720407.311721673663223072794912393972,
519         248874557.8620541565114603864132294232163,
520         31426415.58540019438061423162831820536287,
521         2876370.628935372441225409051620849613599,
522         186056.2653952234950402949897160456992822,
523         8071.672002365816210638002902272250613822,
524         210.8242777515793458725097339207133627117,
525         2.506628274631000270164908177133837338626
526         };
527     const double fDenom[13] = {
528         0,
529         39916800,
530         120543840,
531         150917976,
532         105258076,
533         45995730,
534         13339535,
535         2637558,
536         357423,
537         32670,
538         1925,
539         66,
540         1
541         };
542     // Horner scheme
543     double fSumNum;
544     double fSumDenom;
545     int nI;
546     double fZInv;
547     if (fZ<=1.0)
548     {
549         fSumNum = fNum[12];
550         fSumDenom = fDenom[12];
551         for (nI = 11; nI >= 0; --nI)
552         {
553             fSumNum *= fZ;
554             fSumNum += fNum[nI];
555             fSumDenom *= fZ;
556             fSumDenom += fDenom[nI];
557         }
558     }
559     else
560     // Cancel down with fZ^12; Horner scheme with reverse coefficients
561     {
562         fZInv = 1/fZ;
563         fSumNum = fNum[0];
564         fSumDenom = fDenom[0];
565         for (nI = 1; nI <=12; ++nI)
566         {
567             fSumNum *= fZInv;
568             fSumNum += fNum[nI];
569             fSumDenom *= fZInv;
570             fSumDenom += fDenom[nI];
571         }
572     }
573     return fSumNum/fSumDenom;
574 }
575 
576 // The algorithm is based on tgamma in gamma.hpp
577 // in math library from http://www.boost.org
578 /** You must ensure fZ>0; fZ>171.624376956302 will overflow. */
579 double lcl_GetGammaHelper(double fZ)
580 {
581     double fGamma = lcl_getLanczosSum(fZ);
582     const double fg = 6.024680040776729583740234375;
583     double fZgHelp = fZ + fg - 0.5;
584     // avoid intermediate overflow
585     double fHalfpower = pow( fZgHelp, fZ / 2 - 0.25);
586     fGamma *= fHalfpower;
587     fGamma /= exp(fZgHelp);
588     fGamma *= fHalfpower;
589     if (fZ <= 20.0 && fZ == ::rtl::math::approxFloor(fZ))
590         fGamma = ::rtl::math::round(fGamma);
591     return fGamma;
592 }
593 
594 // The algorithm is based on tgamma in gamma.hpp
595 // in math library from http://www.boost.org
596 /** You must ensure fZ>0 */
597 double lcl_GetLogGammaHelper(double fZ)
598 {
599     const double fg = 6.024680040776729583740234375;
600     double fZgHelp = fZ + fg - 0.5;
601     return log( lcl_getLanczosSum(fZ)) + (fZ-0.5) * log(fZgHelp) - fZgHelp;
602 }
603 
604 /** You must ensure non integer arguments for fZ<1 */
605 double ScInterpreter::GetGamma(double fZ)
606 {
607     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetGamma" );
608     const double fLogPi = log(F_PI);
609     const double fLogDblMax = log( ::std::numeric_limits<double>::max());
610 
611     if (fZ > fMaxGammaArgument)
612     {
613         SetError(errIllegalFPOperation);
614         return HUGE_VAL;
615     }
616 
617     if (fZ >= 1.0)
618         return lcl_GetGammaHelper(fZ);
619 
620     if (fZ >= 0.5)  // shift to x>=1 using Gamma(x)=Gamma(x+1)/x
621         return lcl_GetGammaHelper(fZ+1) / fZ;
622 
623     if (fZ >= -0.5) // shift to x>=1, might overflow
624     {
625         double fLogTest = lcl_GetLogGammaHelper(fZ+2) - log(fZ+1) - log( fabs(fZ));
626         if (fLogTest >= fLogDblMax)
627         {
628             SetError( errIllegalFPOperation);
629             return HUGE_VAL;
630         }
631         return lcl_GetGammaHelper(fZ+2) / (fZ+1) / fZ;
632     }
633     // fZ<-0.5
634     // Use Euler's reflection formula: gamma(x)= pi/ ( gamma(1-x)*sin(pi*x) )
635     double fLogDivisor = lcl_GetLogGammaHelper(1-fZ) + log( fabs( ::rtl::math::sin( F_PI*fZ)));
636     if (fLogDivisor - fLogPi >= fLogDblMax)     // underflow
637         return 0.0;
638 
639     if (fLogDivisor<0.0)
640         if (fLogPi - fLogDivisor > fLogDblMax)  // overflow
641         {
642             SetError(errIllegalFPOperation);
643             return HUGE_VAL;
644         }
645 
646     return exp( fLogPi - fLogDivisor) * ((::rtl::math::sin( F_PI*fZ) < 0.0) ? -1.0 : 1.0);
647 }
648 
649 
650 /** You must ensure fZ>0 */
651 double ScInterpreter::GetLogGamma(double fZ)
652 {
653     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetLogGamma" );
654     if (fZ >= fMaxGammaArgument)
655         return lcl_GetLogGammaHelper(fZ);
656     if (fZ >= 1.0)
657         return log(lcl_GetGammaHelper(fZ));
658     if (fZ >= 0.5)
659         return log( lcl_GetGammaHelper(fZ+1) / fZ);
660     return lcl_GetLogGammaHelper(fZ+2) - log(fZ+1) - log(fZ);
661 }
662 
663 double ScInterpreter::GetFDist(double x, double fF1, double fF2)
664 {
665     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetFDist" );
666     double arg = fF2/(fF2+fF1*x);
667     double alpha = fF2/2.0;
668     double beta = fF1/2.0;
669     return (GetBetaDist(arg, alpha, beta));
670 /*
671     double Z = (pow(fF,1.0/3.0)*(1.0-2.0/(9.0*fF2)) - (1.0-2.0/(9.0*fF1))) /
672                sqrt(2.0/(9.0*fF1) + pow(fF,2.0/3.0)*2.0/(9.0*fF2));
673     return (0.5-gauss(Z));
674 */
675 }
676 
677 double ScInterpreter::GetTDist(double T, double fDF)
678 {
679     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetTDist" );
680     return 0.5 * GetBetaDist(fDF/(fDF+T*T), fDF/2.0, 0.5);
681 /*
682     sal_uInt16 DF = (sal_uInt16) fDF;
683     double A = T / sqrt(DF);
684     double B = 1.0 + A*A;
685     double R;
686     if (DF == 1)
687         R = 0.5 + atan(A)/F_PI;
688     else if (DF % 2 == 0)
689     {
690         double S0 = A/(2.0 * sqrt(B));
691         double C0 = S0;
692         for (sal_uInt16 i = 2; i <= DF-2; i+=2)
693         {
694             C0 *= (1.0 - 1.0/(double)i)/B;
695             S0 += C0;
696         }
697         R = 0.5 + S0;
698     }
699     else
700     {
701         double S1 = A / (B * F_PI);
702         double C1 = S1;
703         for (sal_uInt16 i = 3; i <= DF-2; i+=2)
704         {
705             C1 *= (1.0 - 1.0/(double)i)/B;
706             S1 += C1;
707         }
708         R = 0.5 + atan(A)/F_PI + S1;
709     }
710     return 1.0 - R;
711 */
712 }
713 
714 // for LEGACY.CHIDIST, returns right tail, fDF=degrees of freedom
715 /** You must ensure fDF>0.0 */
716 double ScInterpreter::GetChiDist(double fX, double fDF)
717 {
718     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetChiDist" );
719     if (fX <= 0.0)
720         return 1.0; // see ODFF
721     else
722         return GetUpRegIGamma( fDF/2.0, fX/2.0);
723 }
724 
725 // ready for ODF 1.2
726 // for ODF CHISQDIST; cumulative distribution function, fDF=degrees of freedom
727 // returns left tail
728 /** You must ensure fDF>0.0 */
729 double ScInterpreter::GetChiSqDistCDF(double fX, double fDF)
730 {
731     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetChiSqDistCDF" );
732     if (fX <= 0.0)
733         return 0.0; // see ODFF
734     else
735         return GetLowRegIGamma( fDF/2.0, fX/2.0);
736 }
737 
738 double ScInterpreter::GetChiSqDistPDF(double fX, double fDF)
739 {
740     // you must ensure fDF is positive integer
741     double fValue;
742     double fCount;
743     if (fX <= 0.0)
744         return 0.0; // see ODFF
745     if (fDF*fX > 1391000.0)
746     {
747         // intermediate invalid values, use log
748         fValue = exp((0.5*fDF - 1) * log(fX*0.5) - 0.5 * fX - log(2.0) - GetLogGamma(0.5*fDF));
749     }
750     else // fDF is small in most cases, we can iterate
751     {
752         if (fmod(fDF,2.0)<0.5)
753         {
754             // even
755             fValue = 0.5;
756             fCount = 2.0;
757         }
758         else
759         {
760             fValue = 1/sqrt(fX*2*F_PI);
761             fCount = 1.0;
762         }
763         while ( fCount < fDF)
764         {
765             fValue *= (fX / fCount);
766             fCount += 2.0;
767         }
768         if (fX>=1425.0) // underflow in e^(-x/2)
769             fValue = exp(log(fValue)-fX/2);
770         else
771             fValue *= exp(-fX/2);
772     }
773     return fValue;
774 }
775 
776 void ScInterpreter::ScChiSqDist()
777 {
778     sal_uInt8 nParamCount = GetByte();
779     if ( !MustHaveParamCount( nParamCount, 2, 3 ) )
780         return;
781     double fX;
782     bool bCumulative;
783     if (nParamCount == 3)
784         bCumulative = GetBool();
785     else
786         bCumulative = true;
787     double fDF = ::rtl::math::approxFloor(GetDouble());
788     if (fDF < 1.0)
789         PushIllegalArgument();
790     else
791     {
792         fX = GetDouble();
793         if (bCumulative)
794             PushDouble(GetChiSqDistCDF(fX,fDF));
795         else
796             PushDouble(GetChiSqDistPDF(fX,fDF));
797     }
798 }
799 
800 void ScInterpreter::ScGamma()
801 {
802     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGamma" );
803     double x = GetDouble();
804     double fResult;
805     if (x <= 0.0 && x == ::rtl::math::approxFloor(x))
806         PushIllegalArgument();
807     else
808     {
809         fResult = GetGamma(x);
810         if (nGlobalError)
811         {
812             PushError( nGlobalError);
813             return;
814         }
815         PushDouble(fResult);
816     }
817 }
818 
819 
820 void ScInterpreter::ScLogGamma()
821 {
822     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLogGamma" );
823     double x = GetDouble();
824     if (x > 0.0)    // constraint from ODFF
825         PushDouble( GetLogGamma(x));
826     else
827         PushIllegalArgument();
828 }
829 
830 double ScInterpreter::GetBeta(double fAlpha, double fBeta)
831 {
832     double fA;
833     double fB;
834     if (fAlpha > fBeta)
835     {
836         fA = fAlpha; fB = fBeta;
837     }
838     else
839     {
840         fA = fBeta; fB = fAlpha;
841     }
842     if (fA+fB < fMaxGammaArgument) // simple case
843         return GetGamma(fA)/GetGamma(fA+fB)*GetGamma(fB);
844     // need logarithm
845     // GetLogGamma is not accurate enough, back to Lanczos for all three
846     // GetGamma and arrange factors newly.
847     const double fg = 6.024680040776729583740234375; //see GetGamma
848     double fgm = fg - 0.5;
849     double fLanczos = lcl_getLanczosSum(fA);
850     fLanczos /= lcl_getLanczosSum(fA+fB);
851     fLanczos *= lcl_getLanczosSum(fB);
852     double fABgm = fA+fB+fgm;
853     fLanczos *= sqrt((fABgm/(fA+fgm))/(fB+fgm));
854     double fTempA = fB/(fA+fgm); // (fA+fgm)/fABgm = 1 / ( 1 + fB/(fA+fgm))
855     double fTempB = fA/(fB+fgm);
856     double fResult = exp(-fA * ::rtl::math::log1p(fTempA)
857                             -fB * ::rtl::math::log1p(fTempB)-fgm);
858     fResult *= fLanczos;
859     return fResult;
860 }
861 
862 // Same as GetBeta but with logarithm
863 double ScInterpreter::GetLogBeta(double fAlpha, double fBeta)
864 {
865     double fA;
866     double fB;
867     if (fAlpha > fBeta)
868     {
869         fA = fAlpha; fB = fBeta;
870     }
871     else
872     {
873         fA = fBeta; fB = fAlpha;
874     }
875     const double fg = 6.024680040776729583740234375; //see GetGamma
876     double fgm = fg - 0.5;
877     double fLanczos = lcl_getLanczosSum(fA);
878     fLanczos /= lcl_getLanczosSum(fA+fB);
879     fLanczos *= lcl_getLanczosSum(fB);
880     double fLogLanczos = log(fLanczos);
881     double fABgm = fA+fB+fgm;
882     fLogLanczos += 0.5*(log(fABgm)-log(fA+fgm)-log(fB+fgm));
883     double fTempA = fB/(fA+fgm); // (fA+fgm)/fABgm = 1 / ( 1 + fB/(fA+fgm))
884     double fTempB = fA/(fB+fgm);
885     double fResult = -fA * ::rtl::math::log1p(fTempA)
886                         -fB * ::rtl::math::log1p(fTempB)-fgm;
887     fResult += fLogLanczos;
888     return fResult;
889 }
890 
891 // beta distribution probability density function
892 double ScInterpreter::GetBetaDistPDF(double fX, double fA, double fB)
893 {
894     // special cases
895     if (fA == 1.0) // result b*(1-x)^(b-1)
896     {
897         if (fB == 1.0)
898             return 1.0;
899         if (fB == 2.0)
900             return -2.0*fX + 2.0;
901         if (fX == 1.0 && fB < 1.0)
902         {
903             SetError(errIllegalArgument);
904             return HUGE_VAL;
905         }
906         if (fX <= 0.01)
907             return fB + fB * ::rtl::math::expm1((fB-1.0) * ::rtl::math::log1p(-fX));
908         else
909             return fB * pow(0.5-fX+0.5,fB-1.0);
910     }
911     if (fB == 1.0) // result a*x^(a-1)
912     {
913         if (fA == 2.0)
914             return fA * fX;
915         if (fX == 0.0 && fA < 1.0)
916         {
917             SetError(errIllegalArgument);
918             return HUGE_VAL;
919         }
920         return fA * pow(fX,fA-1);
921     }
922     if (fX <= 0.0)
923     {
924         if (fA < 1.0 && fX == 0.0)
925         {
926             SetError(errIllegalArgument);
927             return HUGE_VAL;
928         }
929         else
930             return 0.0;
931     }
932     if (fX >= 1.0)
933     {
934         if (fB < 1.0 && fX == 1.0)
935         {
936             SetError(errIllegalArgument);
937             return HUGE_VAL;
938         }
939         else
940             return 0.0;
941     }
942 
943     // normal cases; result x^(a-1)*(1-x)^(b-1)/Beta(a,b)
944     const double fLogDblMax = log( ::std::numeric_limits<double>::max());
945     const double fLogDblMin = log( ::std::numeric_limits<double>::min());
946     double fLogY = (fX < 0.1) ? ::rtl::math::log1p(-fX) : log(0.5-fX+0.5);
947     double fLogX = log(fX);
948     double fAm1LogX = (fA-1.0) * fLogX;
949     double fBm1LogY = (fB-1.0) * fLogY;
950     double fLogBeta = GetLogBeta(fA,fB);
951     // check whether parts over- or underflow
952     if (   fAm1LogX < fLogDblMax  && fAm1LogX > fLogDblMin
953         && fBm1LogY < fLogDblMax  && fBm1LogY > fLogDblMin
954         && fLogBeta < fLogDblMax  && fLogBeta > fLogDblMin
955         && fAm1LogX + fBm1LogY < fLogDblMax && fAm1LogX + fBm1LogY > fLogDblMin)
956         return pow(fX,fA-1.0) * pow(0.5-fX+0.5,fB-1.0) / GetBeta(fA,fB);
957     else // need logarithm;
958         // might overflow as a whole, but seldom, not worth to pre-detect it
959         return exp( fAm1LogX + fBm1LogY - fLogBeta);
960 }
961 
962 
963 /*
964                 x^a * (1-x)^b
965     I_x(a,b) = ----------------  * result of ContFrac
966                 a * Beta(a,b)
967 */
968 double lcl_GetBetaHelperContFrac(double fX, double fA, double fB)
969 {   // like old version
970     double a1, b1, a2, b2, fnorm, apl2m, d2m, d2m1, cfnew, cf;
971     a1 = 1.0; b1 = 1.0;
972     b2 = 1.0 - (fA+fB)/(fA+1.0)*fX;
973     if (b2 == 0.0)
974     {
975         a2 = 0.0;
976         fnorm = 1.0;
977         cf = 1.0;
978     }
979     else
980     {
981         a2 = 1.0;
982         fnorm = 1.0/b2;
983         cf = a2*fnorm;
984     }
985     cfnew = 1.0;
986     double rm = 1.0;
987 
988     const double fMaxIter = 50000.0;
989     // loop security, normal cases converge in less than 100 iterations.
990     // FIXME: You will get so much iteratons for fX near mean,
991     // I do not know a better algorithm.
992     bool bfinished = false;
993     do
994     {
995         apl2m = fA + 2.0*rm;
996         d2m = rm*(fB-rm)*fX/((apl2m-1.0)*apl2m);
997         d2m1 = -(fA+rm)*(fA+fB+rm)*fX/(apl2m*(apl2m+1.0));
998         a1 = (a2+d2m*a1)*fnorm;
999         b1 = (b2+d2m*b1)*fnorm;
1000         a2 = a1 + d2m1*a2*fnorm;
1001         b2 = b1 + d2m1*b2*fnorm;
1002         if (b2 != 0.0)
1003         {
1004             fnorm = 1.0/b2;
1005             cfnew = a2*fnorm;
1006             bfinished = (fabs(cf-cfnew) < fabs(cf)*fMachEps);
1007         }
1008         cf = cfnew;
1009         rm += 1.0;
1010     }
1011     while (rm < fMaxIter && !bfinished);
1012     return cf;
1013 }
1014 
1015 // cumulative distribution function, normalized
1016 double ScInterpreter::GetBetaDist(double fXin, double fAlpha, double fBeta)
1017 {
1018 // special cases
1019     if (fXin <= 0.0)  // values are valid, see spec
1020         return 0.0;
1021     if (fXin >= 1.0)  // values are valid, see spec
1022         return 1.0;
1023     if (fBeta == 1.0)
1024         return pow(fXin, fAlpha);
1025     if (fAlpha == 1.0)
1026     //            1.0 - pow(1.0-fX,fBeta) is not accurate enough
1027         return -::rtl::math::expm1(fBeta * ::rtl::math::log1p(-fXin));
1028     //FIXME: need special algorithm for fX near fP for large fA,fB
1029     double fResult;
1030     // I use always continued fraction, power series are neither
1031     // faster nor more accurate.
1032     double fY = (0.5-fXin)+0.5;
1033     double flnY = ::rtl::math::log1p(-fXin);
1034     double fX = fXin;
1035     double flnX = log(fXin);
1036     double fA = fAlpha;
1037     double fB = fBeta;
1038     bool bReflect = fXin > fAlpha/(fAlpha+fBeta);
1039     if (bReflect)
1040     {
1041         fA = fBeta;
1042         fB = fAlpha;
1043         fX = fY;
1044         fY = fXin;
1045         flnX = flnY;
1046         flnY = log(fXin);
1047     }
1048     fResult = lcl_GetBetaHelperContFrac(fX,fA,fB);
1049     fResult = fResult/fA;
1050     double fP = fA/(fA+fB);
1051     double fQ = fB/(fA+fB);
1052     double fTemp;
1053     if (fA > 1.0 && fB > 1.0 && fP < 0.97 && fQ < 0.97) //found experimental
1054         fTemp = GetBetaDistPDF(fX,fA,fB)*fX*fY;
1055     else
1056         fTemp = exp(fA*flnX + fB*flnY - GetLogBeta(fA,fB));
1057     fResult *= fTemp;
1058     if (bReflect)
1059         fResult = 0.5 - fResult + 0.5;
1060     if (fResult > 1.0) // ensure valid range
1061         fResult = 1.0;
1062     if (fResult < 0.0)
1063         fResult = 0.0;
1064     return fResult;
1065 }
1066 
1067   void ScInterpreter::ScBetaDist()
1068   {
1069       sal_uInt8 nParamCount = GetByte();
1070     if ( !MustHaveParamCount( nParamCount, 3, 6 ) ) // expanded, see #i91547#
1071           return;
1072     double fLowerBound, fUpperBound;
1073     double alpha, beta, x;
1074     bool bIsCumulative;
1075     if (nParamCount == 6)
1076         bIsCumulative = GetBool();
1077       else
1078         bIsCumulative = true;
1079     if (nParamCount >= 5)
1080         fUpperBound = GetDouble();
1081     else
1082         fUpperBound = 1.0;
1083       if (nParamCount >= 4)
1084         fLowerBound = GetDouble();
1085       else
1086         fLowerBound = 0.0;
1087       beta = GetDouble();
1088       alpha = GetDouble();
1089       x = GetDouble();
1090     double fScale = fUpperBound - fLowerBound;
1091     if (fScale <= 0.0 || alpha <= 0.0 || beta <= 0.0)
1092       {
1093           PushIllegalArgument();
1094           return;
1095       }
1096     if (bIsCumulative) // cumulative distribution function
1097     {
1098         // special cases
1099         if (x < fLowerBound)
1100         {
1101             PushDouble(0.0); return; //see spec
1102         }
1103         if (x > fUpperBound)
1104         {
1105             PushDouble(1.0); return; //see spec
1106         }
1107         // normal cases
1108         x = (x-fLowerBound)/fScale;  // convert to standard form
1109         PushDouble(GetBetaDist(x, alpha, beta));
1110         return;
1111     }
1112     else // probability density function
1113     {
1114         if (x < fLowerBound || x > fUpperBound)
1115         {
1116             PushDouble(0.0);
1117             return;
1118         }
1119         x = (x-fLowerBound)/fScale;
1120         PushDouble(GetBetaDistPDF(x, alpha, beta)/fScale);
1121         return;
1122     }
1123 }
1124 
1125 void ScInterpreter::ScPhi()
1126 {
1127     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScPhi" );
1128     PushDouble(phi(GetDouble()));
1129 }
1130 
1131 void ScInterpreter::ScGauss()
1132 {
1133     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGauss" );
1134     PushDouble(gauss(GetDouble()));
1135 }
1136 
1137 void ScInterpreter::ScFisher()
1138 {
1139     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScFisher" );
1140     double fVal = GetDouble();
1141     if (fabs(fVal) >= 1.0)
1142         PushIllegalArgument();
1143     else
1144         PushDouble( ::rtl::math::atanh( fVal));
1145 }
1146 
1147 void ScInterpreter::ScFisherInv()
1148 {
1149     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScFisherInv" );
1150     PushDouble( tanh( GetDouble()));
1151 }
1152 
1153 void ScInterpreter::ScFact()
1154 {
1155     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScFact" );
1156     double nVal = GetDouble();
1157     if (nVal < 0.0)
1158         PushIllegalArgument();
1159     else
1160         PushDouble(Fakultaet(nVal));
1161 }
1162 
1163 void ScInterpreter::ScKombin()
1164 {
1165     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScKombin" );
1166     if ( MustHaveParamCount( GetByte(), 2 ) )
1167     {
1168         double k = ::rtl::math::approxFloor(GetDouble());
1169         double n = ::rtl::math::approxFloor(GetDouble());
1170         if (k < 0.0 || n < 0.0 || k > n)
1171             PushIllegalArgument();
1172         else
1173             PushDouble(BinomKoeff(n, k));
1174     }
1175 }
1176 
1177 void ScInterpreter::ScKombin2()
1178 {
1179     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScKombin2" );
1180     if ( MustHaveParamCount( GetByte(), 2 ) )
1181     {
1182         double k = ::rtl::math::approxFloor(GetDouble());
1183         double n = ::rtl::math::approxFloor(GetDouble());
1184         if (k < 0.0 || n < 0.0 || k > n)
1185             PushIllegalArgument();
1186         else
1187             PushDouble(BinomKoeff(n + k - 1, k));
1188     }
1189 }
1190 
1191 void ScInterpreter::ScVariationen()
1192 {
1193     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScVariationen" );
1194     if ( MustHaveParamCount( GetByte(), 2 ) )
1195     {
1196         double k = ::rtl::math::approxFloor(GetDouble());
1197         double n = ::rtl::math::approxFloor(GetDouble());
1198         if (n < 0.0 || k < 0.0 || k > n)
1199             PushIllegalArgument();
1200         else if (k == 0.0)
1201             PushInt(1);     // (n! / (n - 0)!) == 1
1202         else
1203         {
1204             double nVal = n;
1205             for (sal_uLong i = (sal_uLong)k-1; i >= 1; i--)
1206                 nVal *= n-(double)i;
1207             PushDouble(nVal);
1208         }
1209     }
1210 }
1211 
1212 void ScInterpreter::ScVariationen2()
1213 {
1214     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScVariationen2" );
1215     if ( MustHaveParamCount( GetByte(), 2 ) )
1216     {
1217         double k = ::rtl::math::approxFloor(GetDouble());
1218         double n = ::rtl::math::approxFloor(GetDouble());
1219         if (n < 0.0 || k < 0.0 || k > n)
1220             PushIllegalArgument();
1221         else
1222             PushDouble(pow(n,k));
1223     }
1224 }
1225 
1226 
1227 double ScInterpreter::GetBinomDistPMF(double x, double n, double p)
1228 // used in ScB and ScBinomDist
1229 // preconditions: 0.0 <= x <= n, 0.0 < p < 1.0;  x,n integral although double
1230         {
1231     double q = (0.5 - p) + 0.5;
1232             double fFactor = pow(q, n);
1233     if (fFactor <=::std::numeric_limits<double>::min())
1234             {
1235                 fFactor = pow(p, n);
1236         if (fFactor <= ::std::numeric_limits<double>::min())
1237             return GetBetaDistPDF(p, x+1.0, n-x+1.0)/(n+1.0);
1238                 else
1239                 {
1240             sal_uInt32 max = static_cast<sal_uInt32>(n - x);
1241             for (sal_uInt32 i = 0; i < max && fFactor > 0.0; i++)
1242                         fFactor *= (n-i)/(i+1)*q/p;
1243             return fFactor;
1244                 }
1245             }
1246             else
1247             {
1248         sal_uInt32 max = static_cast<sal_uInt32>(x);
1249         for (sal_uInt32 i = 0; i < max && fFactor > 0.0; i++)
1250                     fFactor *= (n-i)/(i+1)*p/q;
1251         return fFactor;
1252         }
1253     }
1254 
1255 double lcl_GetBinomDistRange(double n, double xs,double xe,
1256             double fFactor /* q^n */, double p, double q)
1257 //preconditions: 0.0 <= xs < xe <= n; xs,xe,n integral although double
1258                 {
1259     sal_uInt32 i;
1260     double fSum;
1261     // skip summands index 0 to xs-1, start sum with index xs
1262     sal_uInt32 nXs = static_cast<sal_uInt32>( xs );
1263     for (i = 1; i <= nXs && fFactor > 0.0; i++)
1264         fFactor *= (n-i+1)/i * p/q;
1265     fSum = fFactor; // Summand xs
1266     sal_uInt32 nXe = static_cast<sal_uInt32>(xe);
1267     for (i = nXs+1; i <= nXe && fFactor > 0.0; i++)
1268                     {
1269         fFactor *= (n-i+1)/i * p/q;
1270                         fSum += fFactor;
1271                     }
1272     return (fSum>1.0) ? 1.0 : fSum;
1273                 }
1274 
1275 void ScInterpreter::ScB()
1276 {
1277     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScB" );
1278     sal_uInt8 nParamCount = GetByte();
1279     if ( !MustHaveParamCount( nParamCount, 3, 4 ) )
1280         return ;
1281     if (nParamCount == 3)   // mass function
1282     {
1283         double x = ::rtl::math::approxFloor(GetDouble());
1284         double p = GetDouble();
1285         double n = ::rtl::math::approxFloor(GetDouble());
1286         if (n < 0.0 || x < 0.0 || x > n || p < 0.0 || p > 1.0)
1287             PushIllegalArgument();
1288         else
1289             if (p == 0.0)
1290                 PushDouble( (x == 0.0) ? 1.0 : 0.0 );
1291             else
1292                 if ( p == 1.0)
1293                     PushDouble( (x == n) ? 1.0 : 0.0);
1294                 else
1295                     PushDouble(GetBinomDistPMF(x,n,p));
1296             }
1297             else
1298     {   // nParamCount == 4
1299         double xe = ::rtl::math::approxFloor(GetDouble());
1300         double xs = ::rtl::math::approxFloor(GetDouble());
1301         double p = GetDouble();
1302         double n = ::rtl::math::approxFloor(GetDouble());
1303         double q = (0.5 - p) + 0.5;
1304         bool bIsValidX = ( 0.0 <= xs && xs <= xe && xe <= n);
1305         if ( bIsValidX && 0.0 < p && p < 1.0)
1306             {
1307             if (xs == xe)       // mass function
1308                 PushDouble(GetBinomDistPMF(xs,n,p));
1309             else
1310                 {
1311                 double fFactor = pow(q, n);
1312                 if (fFactor > ::std::numeric_limits<double>::min())
1313                     PushDouble(lcl_GetBinomDistRange(n,xs,xe,fFactor,p,q));
1314                 else
1315                 {
1316                     fFactor = pow(p, n);
1317                     if (fFactor > ::std::numeric_limits<double>::min())
1318                     {
1319                     // sum from j=xs to xe {(n choose j) * p^j * q^(n-j)}
1320                     // = sum from i = n-xe to n-xs { (n choose i) * q^i * p^(n-i)}
1321                         PushDouble(lcl_GetBinomDistRange(n,n-xe,n-xs,fFactor,q,p));
1322                 }
1323                 else
1324                         PushDouble(GetBetaDist(q,n-xe,xe+1.0)-GetBetaDist(q,n-xs+1,xs) );
1325                 }
1326             }
1327         }
1328         else
1329         {
1330             if ( bIsValidX ) // not(0<p<1)
1331             {
1332                 if ( p == 0.0 )
1333                     PushDouble( (xs == 0.0) ? 1.0 : 0.0 );
1334                 else if ( p == 1.0 )
1335                     PushDouble( (xe == n) ? 1.0 : 0.0 );
1336                 else
1337                     PushIllegalArgument();
1338             }
1339             else
1340                 PushIllegalArgument();
1341         }
1342     }
1343 }
1344 
1345 void ScInterpreter::ScBinomDist()
1346 {
1347     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScBinomDist" );
1348     if ( MustHaveParamCount( GetByte(), 4 ) )
1349     {
1350         bool bIsCum   = GetBool();     // false=mass function; true=cumulative
1351         double p      = GetDouble();
1352         double n      = ::rtl::math::approxFloor(GetDouble());
1353         double x      = ::rtl::math::approxFloor(GetDouble());
1354         double q = (0.5 - p) + 0.5;           // get one bit more for p near 1.0
1355         double fFactor, fSum;
1356         if (n < 0.0 || x < 0.0 || x > n || p < 0.0 || p > 1.0)
1357         {
1358             PushIllegalArgument();
1359             return;
1360             }
1361         if ( p == 0.0)
1362             {
1363             PushDouble( (x==0.0 || bIsCum) ? 1.0 : 0.0 );
1364             return;
1365             }
1366         if ( p == 1.0)
1367         {
1368             PushDouble( (x==n) ? 1.0 : 0.0);
1369             return;
1370         }
1371         if (!bIsCum)
1372             PushDouble( GetBinomDistPMF(x,n,p));
1373         else
1374         {
1375             if (x == n)
1376                 PushDouble(1.0);
1377             else
1378             {
1379                 fFactor = pow(q, n);
1380                 if (x == 0.0)
1381                     PushDouble(fFactor);
1382                 else
1383                     if (fFactor <= ::std::numeric_limits<double>::min())
1384                 {
1385                     fFactor = pow(p, n);
1386                         if (fFactor <= ::std::numeric_limits<double>::min())
1387                             PushDouble(GetBetaDist(q,n-x,x+1.0));
1388                     else
1389                     {
1390                             if (fFactor > fMachEps)
1391                             {
1392                         fSum = 1.0 - fFactor;
1393                                 sal_uInt32 max = static_cast<sal_uInt32> (n - x) - 1;
1394                                 for (sal_uInt32 i = 0; i < max && fFactor > 0.0; i++)
1395                         {
1396                             fFactor *= (n-i)/(i+1)*q/p;
1397                             fSum -= fFactor;
1398                         }
1399                                 PushDouble( (fSum < 0.0) ? 0.0 : fSum );
1400                 }
1401                 else
1402                                 PushDouble(lcl_GetBinomDistRange(n,n-x,n,fFactor,q,p));
1403                     }
1404                 }
1405                     else
1406                         PushDouble( lcl_GetBinomDistRange(n,0.0,x,fFactor,p,q)) ;
1407             }
1408         }
1409     }
1410 }
1411 
1412 void ScInterpreter::ScCritBinom()
1413 {
1414     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCritBinom" );
1415     if ( MustHaveParamCount( GetByte(), 3 ) )
1416     {
1417         double alpha  = GetDouble();                    // alpha
1418         double p      = GetDouble();                    // p
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
1423         {
1424             double q = 1.0 - p;
1425             double fFactor = pow(q,n);
1426             if (fFactor == 0.0)
1427             {
1428                 fFactor = pow(p, n);
1429                 if (fFactor == 0.0)
1430                     PushNoValue();
1431                 else
1432                 {
1433                     double fSum = 1.0 - fFactor; sal_uLong max = (sal_uLong) n;
1434                     sal_uLong i;
1435 
1436                     for ( i = 0; i < max && fSum >= alpha; i++)
1437                     {
1438                         fFactor *= (n-i)/(i+1)*q/p;
1439                         fSum -= fFactor;
1440                     }
1441                     PushDouble(n-i);
1442                 }
1443             }
1444             else
1445             {
1446                 double fSum = fFactor; sal_uLong max = (sal_uLong) n;
1447                 sal_uLong i;
1448 
1449                 for ( i = 0; i < max && fSum < alpha; i++)
1450                 {
1451                     fFactor *= (n-i)/(i+1)*p/q;
1452                     fSum += fFactor;
1453                 }
1454                 PushDouble(i);
1455             }
1456         }
1457     }
1458 }
1459 
1460 void ScInterpreter::ScNegBinomDist()
1461 {
1462     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScNegBinomDist" );
1463     if ( MustHaveParamCount( GetByte(), 3 ) )
1464     {
1465         double p      = GetDouble();                    // p
1466         double r      = GetDouble();                    // r
1467         double x      = GetDouble();                    // x
1468         if (r < 0.0 || x < 0.0 || p < 0.0 || p > 1.0)
1469             PushIllegalArgument();
1470         else
1471         {
1472             double q = 1.0 - p;
1473             double fFactor = pow(p,r);
1474             for (double i = 0.0; i < x; i++)
1475                 fFactor *= (i+r)/(i+1.0)*q;
1476             PushDouble(fFactor);
1477         }
1478     }
1479 }
1480 
1481 void ScInterpreter::ScNormDist()
1482 {
1483     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScNormDist" );
1484     sal_uInt8 nParamCount = GetByte();
1485     if ( !MustHaveParamCount( nParamCount, 3, 4))
1486         return;
1487     bool bCumulative = nParamCount == 4 ? GetBool() : true;
1488     double sigma = GetDouble();                 // standard deviation
1489     double mue = GetDouble();                   // mean
1490     double x = GetDouble();                     // x
1491     if (sigma <= 0.0)
1492     {
1493         PushIllegalArgument();
1494         return;
1495     }
1496     if (bCumulative)
1497         PushDouble(integralPhi((x-mue)/sigma));
1498     else
1499         PushDouble(phi((x-mue)/sigma)/sigma);
1500 }
1501 
1502 void ScInterpreter::ScLogNormDist() //expanded, see #i100119#
1503 {
1504     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLogNormDist" );
1505     sal_uInt8 nParamCount = GetByte();
1506     if ( !MustHaveParamCount( nParamCount, 1, 4))
1507         return;
1508     bool bCumulative = nParamCount == 4 ? GetBool() : true; // cumulative
1509     double sigma = nParamCount >= 3 ? GetDouble() : 1.0; // standard deviation
1510     double mue = nParamCount >= 2 ? GetDouble() : 0.0;   // mean
1511     double x = GetDouble();                              // x
1512     if (sigma <= 0.0)
1513     {
1514         PushIllegalArgument();
1515         return;
1516     }
1517     if (bCumulative)
1518     { // cumulative
1519         if (x <= 0.0)
1520             PushDouble(0.0);
1521         else
1522             PushDouble(integralPhi((log(x)-mue)/sigma));
1523     }
1524     else
1525     { // density
1526         if (x <= 0.0)
1527             PushIllegalArgument();
1528         else
1529             PushDouble(phi((log(x)-mue)/sigma)/sigma/x);
1530     }
1531 }
1532 
1533 void ScInterpreter::ScStdNormDist()
1534 {
1535     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScStdNormDist" );
1536     PushDouble(integralPhi(GetDouble()));
1537 }
1538 
1539 void ScInterpreter::ScExpDist()
1540 {
1541     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScExpDist" );
1542     if ( MustHaveParamCount( GetByte(), 3 ) )
1543     {
1544         double kum    = GetDouble();                    // 0 oder 1
1545         double lambda = GetDouble();                    // lambda
1546         double x      = GetDouble();                    // x
1547         if (lambda <= 0.0)
1548             PushIllegalArgument();
1549         else if (kum == 0.0)                        // Dichte
1550         {
1551             if (x >= 0.0)
1552                 PushDouble(lambda * exp(-lambda*x));
1553             else
1554                 PushInt(0);
1555         }
1556         else                                        // Verteilung
1557         {
1558             if (x > 0.0)
1559                 PushDouble(1.0 - exp(-lambda*x));
1560             else
1561                 PushInt(0);
1562         }
1563     }
1564 }
1565 
1566 void ScInterpreter::ScTDist()
1567 {
1568     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTDist" );
1569     if ( !MustHaveParamCount( GetByte(), 3 ) )
1570         return;
1571     double fFlag = ::rtl::math::approxFloor(GetDouble());
1572     double fDF   = ::rtl::math::approxFloor(GetDouble());
1573     double T     = GetDouble();
1574     if (fDF < 1.0 || T < 0.0 || (fFlag != 1.0 && fFlag != 2.0) )
1575     {
1576         PushIllegalArgument();
1577         return;
1578     }
1579     double R = GetTDist(T, fDF);
1580     if (fFlag == 1.0)
1581         PushDouble(R);
1582     else
1583         PushDouble(2.0*R);
1584 }
1585 
1586 void ScInterpreter::ScFDist()
1587 {
1588     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScFDist" );
1589     if ( !MustHaveParamCount( GetByte(), 3 ) )
1590         return;
1591     double fF2 = ::rtl::math::approxFloor(GetDouble());
1592     double fF1 = ::rtl::math::approxFloor(GetDouble());
1593     double fF  = GetDouble();
1594     if (fF < 0.0 || fF1 < 1.0 || fF2 < 1.0 || fF1 >= 1.0E10 || fF2 >= 1.0E10)
1595     {
1596         PushIllegalArgument();
1597         return;
1598     }
1599     PushDouble(GetFDist(fF, fF1, fF2));
1600 }
1601 
1602 void ScInterpreter::ScChiDist()
1603 {
1604     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScChiDist" );
1605     double fResult;
1606     if ( !MustHaveParamCount( GetByte(), 2 ) )
1607         return;
1608     double fDF  = ::rtl::math::approxFloor(GetDouble());
1609     double fChi = GetDouble();
1610     if (fDF < 1.0) // x<=0 returns 1, see ODFF 6.17.10
1611     {
1612         PushIllegalArgument();
1613         return;
1614     }
1615     fResult = GetChiDist( fChi, fDF);
1616     if (nGlobalError)
1617     {
1618         PushError( nGlobalError);
1619         return;
1620     }
1621     PushDouble(fResult);
1622 }
1623 
1624 void ScInterpreter::ScWeibull()
1625 {
1626     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScWeibull" );
1627     if ( MustHaveParamCount( GetByte(), 4 ) )
1628     {
1629         double kum   = GetDouble();                 // 0 oder 1
1630         double beta  = GetDouble();                 // beta
1631         double alpha = GetDouble();                 // alpha
1632         double x     = GetDouble();                 // x
1633         if (alpha <= 0.0 || beta <= 0.0 || x < 0.0)
1634             PushIllegalArgument();
1635         else if (kum == 0.0)                        // Dichte
1636             PushDouble(alpha/pow(beta,alpha)*pow(x,alpha-1.0)*
1637                        exp(-pow(x/beta,alpha)));
1638         else                                        // Verteilung
1639             PushDouble(1.0 - exp(-pow(x/beta,alpha)));
1640     }
1641 }
1642 
1643 void ScInterpreter::ScPoissonDist()
1644 {
1645     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScPoissonDist" );
1646     sal_uInt8 nParamCount = GetByte();
1647     if ( MustHaveParamCount( nParamCount, 2, 3 ) )
1648     {
1649         bool bCumulative = (nParamCount == 3 ? GetBool() : true); // default cumulative
1650         double lambda    = GetDouble();                           // Mean
1651         double x         = ::rtl::math::approxFloor(GetDouble()); // discrete distribution
1652         if (lambda < 0.0 || x < 0.0)
1653             PushIllegalArgument();
1654         else if (!bCumulative)                            // Probability mass function
1655         {
1656             if (lambda == 0.0)
1657                 PushInt(0);
1658             else
1659             {
1660                 if (lambda >712)    // underflow in exp(-lambda)
1661                 {   // accuracy 11 Digits
1662                     PushDouble( exp(x*log(lambda)-lambda-GetLogGamma(x+1.0)));
1663                 }
1664                 else
1665                 {
1666                     double fPoissonVar = 1.0;
1667                     for ( double f = 0.0; f < x; ++f )
1668                         fPoissonVar *= lambda / ( f + 1.0 );
1669                     PushDouble( fPoissonVar * exp( -lambda ) );
1670                 }
1671             }
1672         }
1673         else                                // Cumulative distribution function
1674         {
1675             if (lambda == 0.0)
1676                 PushInt(1);
1677             else
1678             {
1679                 if (lambda > 712 )  // underflow in exp(-lambda)
1680                 {   // accuracy 12 Digits
1681                     PushDouble(GetUpRegIGamma(x+1.0,lambda));
1682                 }
1683                 else
1684                 {
1685                     if (x >= 936.0) // result is always undistinghable from 1
1686                         PushDouble (1.0);
1687                     else
1688                     {
1689                         double fSummand = exp(-lambda);
1690                         double fSum = fSummand;
1691                         int nEnd = sal::static_int_cast<int>( x );
1692                         for (int i = 1; i <= nEnd; i++)
1693                         {
1694                             fSummand = (fSummand * lambda)/(double)i;
1695                             fSum += fSummand;
1696                         }
1697                         PushDouble(fSum);
1698                     }
1699                 }
1700             }
1701         }
1702     }
1703 }
1704 
1705 /** Local function used in the calculation of the hypergeometric distribution.
1706  */
1707 void lcl_PutFactorialElements( ::std::vector< double >& cn, double fLower, double fUpper, double fBase )
1708 {
1709     for ( double i = fLower; i <= fUpper; ++i )
1710     {
1711         double fVal = fBase - i;
1712         if ( fVal > 1.0 )
1713             cn.push_back( fVal );
1714     }
1715 }
1716 
1717 /** Calculates a value of the hypergeometric distribution.
1718 
1719     The algorithm is designed to avoid unnecessary multiplications and division
1720     by expanding all factorial elements (9 of them).  It is done by excluding
1721     those ranges that overlap in the numerator and the denominator.  This allows
1722     for a fast calculation for large values which would otherwise cause an overflow
1723     in the intermediate values.
1724 
1725     @author Kohei Yoshida <kohei@openoffice.org>
1726 
1727     @see #i47296#
1728 
1729  */
1730 void ScInterpreter::ScHypGeomDist()
1731 {
1732     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScHypGeomDist" );
1733     const size_t nMaxArraySize = 500000; // arbitrary max array size
1734 
1735     if ( !MustHaveParamCount( GetByte(), 4 ) )
1736         return;
1737 
1738     double N = ::rtl::math::approxFloor(GetDouble());
1739     double M = ::rtl::math::approxFloor(GetDouble());
1740     double n = ::rtl::math::approxFloor(GetDouble());
1741     double x = ::rtl::math::approxFloor(GetDouble());
1742 
1743     if( (x < 0.0) || (n < x) || (M < x) || (N < n) || (N < M) || (x < n - N + M) )
1744     {
1745         PushIllegalArgument();
1746         return;
1747     }
1748 
1749     typedef ::std::vector< double > HypContainer;
1750     HypContainer cnNumer, cnDenom;
1751 
1752     size_t nEstContainerSize = static_cast<size_t>( x + ::std::min( n, M ) );
1753     size_t nMaxSize = ::std::min( cnNumer.max_size(), nMaxArraySize );
1754     if ( nEstContainerSize > nMaxSize )
1755     {
1756         PushNoValue();
1757         return;
1758     }
1759     cnNumer.reserve( nEstContainerSize + 10 );
1760     cnDenom.reserve( nEstContainerSize + 10 );
1761 
1762     // Trim coefficient C first
1763     double fCNumVarUpper = N - n - M + x - 1.0;
1764     double fCDenomVarLower = 1.0;
1765     if ( N - n - M + x >= M - x + 1.0 )
1766     {
1767         fCNumVarUpper = M - x - 1.0;
1768         fCDenomVarLower = N - n - 2.0*(M - x) + 1.0;
1769     }
1770 
1771 #ifdef DBG_UTIL
1772     double fCNumLower = N - n - fCNumVarUpper;
1773 #endif
1774     double fCDenomUpper = N - n - M + x + 1.0 - fCDenomVarLower;
1775 
1776     double fDNumVarLower = n - M;
1777 
1778     if ( n >= M + 1.0 )
1779     {
1780         if ( N - M < n + 1.0 )
1781         {
1782             // Case 1
1783 
1784             if ( N - n < n + 1.0 )
1785             {
1786                 // no overlap
1787                 lcl_PutFactorialElements( cnNumer, 0.0, fCNumVarUpper, N - n );
1788                 lcl_PutFactorialElements( cnDenom, 0.0, N - n - 1.0, N );
1789             }
1790             else
1791             {
1792                 // overlap
1793                 DBG_ASSERT( fCNumLower < n + 1.0, "ScHypGeomDist: wrong assertion" );
1794                 lcl_PutFactorialElements( cnNumer, N - 2.0*n, fCNumVarUpper, N - n );
1795                 lcl_PutFactorialElements( cnDenom, 0.0, n - 1.0, N );
1796             }
1797 
1798             DBG_ASSERT( fCDenomUpper <= N - M, "ScHypGeomDist: wrong assertion" );
1799 
1800             if ( fCDenomUpper < n - x + 1.0 )
1801                 // no overlap
1802                 lcl_PutFactorialElements( cnNumer, 1.0, N - M - n + x, N - M + 1.0 );
1803             else
1804             {
1805                 // overlap
1806                 lcl_PutFactorialElements( cnNumer, 1.0, N - M - fCDenomUpper, N - M + 1.0 );
1807 
1808                 fCDenomUpper = n - x;
1809                 fCDenomVarLower = N - M - 2.0*(n - x) + 1.0;
1810             }
1811         }
1812         else
1813         {
1814             // Case 2
1815 
1816             if ( n > M - 1.0 )
1817             {
1818                 // no overlap
1819                 lcl_PutFactorialElements( cnNumer, 0.0, fCNumVarUpper, N - n );
1820                 lcl_PutFactorialElements( cnDenom, 0.0, M - 1.0, N );
1821             }
1822             else
1823             {
1824                 lcl_PutFactorialElements( cnNumer, M - n, fCNumVarUpper, N - n );
1825                 lcl_PutFactorialElements( cnDenom, 0.0, n - 1.0, N );
1826             }
1827 
1828             DBG_ASSERT( fCDenomUpper <= n, "ScHypGeomDist: wrong assertion" );
1829 
1830             if ( fCDenomUpper < n - x + 1.0 )
1831                 // no overlap
1832                 lcl_PutFactorialElements( cnNumer, N - M - n + 1.0, N - M - n + x, N - M + 1.0 );
1833             else
1834             {
1835                 lcl_PutFactorialElements( cnNumer, N - M - n + 1.0, N - M - fCDenomUpper, N - M + 1.0 );
1836                 fCDenomUpper = n - x;
1837                 fCDenomVarLower = N - M - 2.0*(n - x) + 1.0;
1838             }
1839         }
1840 
1841         DBG_ASSERT( fCDenomUpper <= M, "ScHypGeomDist: wrong assertion" );
1842     }
1843     else
1844     {
1845         if ( N - M < M + 1.0 )
1846         {
1847             // Case 3
1848 
1849             if ( N - n < M + 1.0 )
1850             {
1851                 // No overlap
1852                 lcl_PutFactorialElements( cnNumer, 0.0, fCNumVarUpper, N - n );
1853                 lcl_PutFactorialElements( cnDenom, 0.0, N - M - 1.0, N );
1854             }
1855             else
1856             {
1857                 lcl_PutFactorialElements( cnNumer, N - n - M, fCNumVarUpper, N - n );
1858                 lcl_PutFactorialElements( cnDenom, 0.0, n - 1.0, N );
1859             }
1860 
1861             if ( n - x + 1.0 > fCDenomUpper )
1862                 // No overlap
1863                 lcl_PutFactorialElements( cnNumer, 1.0, N - M - n + x, N - M + 1.0 );
1864             else
1865             {
1866                 // Overlap
1867                 lcl_PutFactorialElements( cnNumer, 1.0, N - M - fCDenomUpper, N - M + 1.0 );
1868 
1869                 fCDenomVarLower = N - M - 2.0*(n - x) + 1.0;
1870                 fCDenomUpper = n - x;
1871             }
1872         }
1873         else
1874         {
1875             // Case 4
1876 
1877             DBG_ASSERT( M >= n - x, "ScHypGeomDist: wrong assertion" );
1878             DBG_ASSERT( M - x <= N - M + 1.0, "ScHypGeomDist: wrong assertion" );
1879 
1880             if ( N - n < N - M + 1.0 )
1881             {
1882                 // No overlap
1883                 lcl_PutFactorialElements( cnNumer, 0.0, fCNumVarUpper, N - n );
1884                 lcl_PutFactorialElements( cnDenom, 0.0, M - 1.0, N );
1885             }
1886             else
1887             {
1888                 // Overlap
1889                 DBG_ASSERT( fCNumLower <= N - M + 1.0, "ScHypGeomDist: wrong assertion" );
1890 
1891                 lcl_PutFactorialElements( cnNumer, M - n, fCNumVarUpper, N - n );
1892                 lcl_PutFactorialElements( cnDenom, 0.0, n - 1.0, N );
1893             }
1894 
1895             if ( n - x + 1.0 > fCDenomUpper )
1896                 // No overlap
1897                 lcl_PutFactorialElements( cnNumer, N - 2.0*M + 1.0, N - M - n + x, N - M + 1.0 );
1898             else if ( M >= fCDenomUpper )
1899             {
1900                 lcl_PutFactorialElements( cnNumer, N - 2.0*M + 1.0, N - M - fCDenomUpper, N - M + 1.0 );
1901 
1902                 fCDenomUpper = n - x;
1903                 fCDenomVarLower = N - M - 2.0*(n - x) + 1.0;
1904             }
1905             else
1906             {
1907                 DBG_ASSERT( M <= fCDenomUpper, "ScHypGeomDist: wrong assertion" );
1908                 lcl_PutFactorialElements( cnDenom, fCDenomVarLower, N - n - 2.0*M + x,
1909                         N - n - M + x + 1.0 );
1910 
1911                 fCDenomUpper = n - x;
1912                 fCDenomVarLower = N - M - 2.0*(n - x) + 1.0;
1913             }
1914         }
1915 
1916         DBG_ASSERT( fCDenomUpper <= n, "ScHypGeomDist: wrong assertion" );
1917 
1918         fDNumVarLower = 0.0;
1919     }
1920 
1921     double nDNumVarUpper   = fCDenomUpper < x + 1.0 ? n - x - 1.0     : n - fCDenomUpper - 1.0;
1922     double nDDenomVarLower = fCDenomUpper < x + 1.0 ? fCDenomVarLower : N - n - M + 1.0;
1923     lcl_PutFactorialElements( cnNumer, fDNumVarLower, nDNumVarUpper, n );
1924     lcl_PutFactorialElements( cnDenom, nDDenomVarLower, N - n - M + x, N - n - M + x + 1.0 );
1925 
1926     ::std::sort( cnNumer.begin(), cnNumer.end() );
1927     ::std::sort( cnDenom.begin(), cnDenom.end() );
1928     HypContainer::reverse_iterator it1 = cnNumer.rbegin(), it1End = cnNumer.rend();
1929     HypContainer::reverse_iterator it2 = cnDenom.rbegin(), it2End = cnDenom.rend();
1930 
1931     double fFactor = 1.0;
1932     for ( ; it1 != it1End || it2 != it2End; )
1933     {
1934         double fEnum = 1.0, fDenom = 1.0;
1935         if ( it1 != it1End )
1936             fEnum  = *it1++;
1937         if ( it2 != it2End )
1938             fDenom = *it2++;
1939         fFactor *= fEnum / fDenom;
1940     }
1941 
1942     PushDouble(fFactor);
1943 }
1944 
1945 void ScInterpreter::ScGammaDist()
1946 {
1947     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGammaDist" );
1948     sal_uInt8 nParamCount = GetByte();
1949     if ( !MustHaveParamCount( nParamCount, 3, 4 ) )
1950         return;
1951     double bCumulative;
1952     if (nParamCount == 4)
1953         bCumulative = GetBool();
1954     else
1955         bCumulative = true;
1956     double fBeta = GetDouble();                 // scale
1957     double fAlpha = GetDouble();                // shape
1958     double fX = GetDouble();                    // x
1959     if (fAlpha <= 0.0 || fBeta <= 0.0)
1960         PushIllegalArgument();
1961     else
1962     {
1963         if (bCumulative)                        // distribution
1964             PushDouble( GetGammaDist( fX, fAlpha, fBeta));
1965         else                                    // density
1966             PushDouble( GetGammaDistPDF( fX, fAlpha, fBeta));
1967     }
1968 }
1969 
1970 void ScInterpreter::ScNormInv()
1971 {
1972     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScNormInv" );
1973     if ( MustHaveParamCount( GetByte(), 3 ) )
1974     {
1975         double sigma = GetDouble();
1976         double mue   = GetDouble();
1977         double x     = GetDouble();
1978         if (sigma <= 0.0 || x < 0.0 || x > 1.0)
1979             PushIllegalArgument();
1980         else if (x == 0.0 || x == 1.0)
1981             PushNoValue();
1982         else
1983             PushDouble(gaussinv(x)*sigma + mue);
1984     }
1985 }
1986 
1987 void ScInterpreter::ScSNormInv()
1988 {
1989     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSNormInv" );
1990     double x = GetDouble();
1991     if (x < 0.0 || x > 1.0)
1992         PushIllegalArgument();
1993     else if (x == 0.0 || x == 1.0)
1994         PushNoValue();
1995     else
1996         PushDouble(gaussinv(x));
1997 }
1998 
1999 void ScInterpreter::ScLogNormInv()
2000 {
2001     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLogNormInv" );
2002     if ( MustHaveParamCount( GetByte(), 3 ) )
2003     {
2004         double sigma = GetDouble();                 // Stdabw
2005         double mue = GetDouble();                   // Mittelwert
2006         double y = GetDouble();                     // y
2007         if (sigma <= 0.0 || y <= 0.0 || y >= 1.0)
2008             PushIllegalArgument();
2009         else
2010             PushDouble(exp(mue+sigma*gaussinv(y)));
2011     }
2012 }
2013 
2014 class ScGammaDistFunction : public ScDistFunc
2015 {
2016     ScInterpreter&  rInt;
2017     double          fp, fAlpha, fBeta;
2018 
2019 public:
2020             ScGammaDistFunction( ScInterpreter& rI, double fpVal, double fAlphaVal, double fBetaVal ) :
2021                 rInt(rI), fp(fpVal), fAlpha(fAlphaVal), fBeta(fBetaVal) {}
2022 
2023     double  GetValue( double x ) const  { return fp - rInt.GetGammaDist(x, fAlpha, fBeta); }
2024 };
2025 
2026 void ScInterpreter::ScGammaInv()
2027 {
2028     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGammaInv" );
2029     if ( !MustHaveParamCount( GetByte(), 3 ) )
2030         return;
2031     double fBeta  = GetDouble();
2032     double fAlpha = GetDouble();
2033     double fP = GetDouble();
2034     if (fAlpha <= 0.0 || fBeta <= 0.0 || fP < 0.0 || fP >= 1.0 )
2035     {
2036         PushIllegalArgument();
2037         return;
2038     }
2039     if (fP == 0.0)
2040         PushInt(0);
2041     else
2042     {
2043         bool bConvError;
2044         ScGammaDistFunction aFunc( *this, fP, fAlpha, fBeta );
2045         double fStart = fAlpha * fBeta;
2046         double fVal = lcl_IterateInverse( aFunc, fStart*0.5, fStart, bConvError );
2047         if (bConvError)
2048             SetError(errNoConvergence);
2049         PushDouble(fVal);
2050     }
2051 }
2052 
2053 class ScBetaDistFunction : public ScDistFunc
2054 {
2055     ScInterpreter&  rInt;
2056     double          fp, fAlpha, fBeta;
2057 
2058 public:
2059             ScBetaDistFunction( ScInterpreter& rI, double fpVal, double fAlphaVal, double fBetaVal ) :
2060                 rInt(rI), fp(fpVal), fAlpha(fAlphaVal), fBeta(fBetaVal) {}
2061 
2062     double  GetValue( double x ) const  { return fp - rInt.GetBetaDist(x, fAlpha, fBeta); }
2063 };
2064 
2065 void ScInterpreter::ScBetaInv()
2066 {
2067     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScBetaInv" );
2068     sal_uInt8 nParamCount = GetByte();
2069     if ( !MustHaveParamCount( nParamCount, 3, 5 ) )
2070         return;
2071     double fP, fA, fB, fAlpha, fBeta;
2072     if (nParamCount == 5)
2073         fB = GetDouble();
2074     else
2075         fB = 1.0;
2076     if (nParamCount >= 4)
2077         fA = GetDouble();
2078     else
2079         fA = 0.0;
2080     fBeta  = GetDouble();
2081     fAlpha = GetDouble();
2082     fP     = GetDouble();
2083     if (fP < 0.0 || fP >= 1.0 || fA == fB || fAlpha <= 0.0 || fBeta <= 0.0)
2084     {
2085         PushIllegalArgument();
2086         return;
2087     }
2088     if (fP == 0.0)
2089         PushInt(0);
2090     else
2091     {
2092         bool bConvError;
2093         ScBetaDistFunction aFunc( *this, fP, fAlpha, fBeta );
2094         // 0..1 as range for iteration so it isn't extended beyond the valid range
2095         double fVal = lcl_IterateInverse( aFunc, 0.0, 1.0, bConvError );
2096         if (bConvError)
2097             PushError( errNoConvergence);
2098         else
2099             PushDouble(fA + fVal*(fB-fA));                  // scale to (A,B)
2100     }
2101 }
2102 
2103                                                             // Achtung: T, F und Chi
2104                                                             // sind monoton fallend,
2105                                                             // deshalb 1-Dist als Funktion
2106 
2107 class ScTDistFunction : public ScDistFunc
2108 {
2109     ScInterpreter&  rInt;
2110     double          fp, fDF;
2111 
2112 public:
2113             ScTDistFunction( ScInterpreter& rI, double fpVal, double fDFVal ) :
2114                 rInt(rI), fp(fpVal), fDF(fDFVal) {}
2115 
2116     double  GetValue( double x ) const  { return fp - 2 * rInt.GetTDist(x, fDF); }
2117 };
2118 
2119 void ScInterpreter::ScTInv()
2120 {
2121     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTInv" );
2122     if ( !MustHaveParamCount( GetByte(), 2 ) )
2123         return;
2124     double fDF  = ::rtl::math::approxFloor(GetDouble());
2125     double fP = GetDouble();
2126     if (fDF < 1.0 || fDF >= 1.0E5 || fP <= 0.0 || fP > 1.0 )
2127     {
2128         PushIllegalArgument();
2129         return;
2130     }
2131 
2132     bool bConvError;
2133     ScTDistFunction aFunc( *this, fP, fDF );
2134     double fVal = lcl_IterateInverse( aFunc, fDF*0.5, fDF, bConvError );
2135     if (bConvError)
2136         SetError(errNoConvergence);
2137     PushDouble(fVal);
2138 }
2139 
2140 class ScFDistFunction : public ScDistFunc
2141 {
2142     ScInterpreter&  rInt;
2143     double          fp, fF1, fF2;
2144 
2145 public:
2146             ScFDistFunction( ScInterpreter& rI, double fpVal, double fF1Val, double fF2Val ) :
2147                 rInt(rI), fp(fpVal), fF1(fF1Val), fF2(fF2Val) {}
2148 
2149     double  GetValue( double x ) const  { return fp - rInt.GetFDist(x, fF1, fF2); }
2150 };
2151 
2152 void ScInterpreter::ScFInv()
2153 {
2154     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScFInv" );
2155     if ( !MustHaveParamCount( GetByte(), 3 ) )
2156         return;
2157     double fF2 = ::rtl::math::approxFloor(GetDouble());
2158     double fF1 = ::rtl::math::approxFloor(GetDouble());
2159     double fP  = GetDouble();
2160     if (fP <= 0.0 || fF1 < 1.0 || fF2 < 1.0 || fF1 >= 1.0E10 || fF2 >= 1.0E10 || fP > 1.0)
2161     {
2162         PushIllegalArgument();
2163         return;
2164     }
2165 
2166     bool bConvError;
2167     ScFDistFunction aFunc( *this, fP, fF1, fF2 );
2168     double fVal = lcl_IterateInverse( aFunc, fF1*0.5, fF1, bConvError );
2169     if (bConvError)
2170         SetError(errNoConvergence);
2171     PushDouble(fVal);
2172 }
2173 
2174 class ScChiDistFunction : public ScDistFunc
2175 {
2176     ScInterpreter&  rInt;
2177     double          fp, fDF;
2178 
2179 public:
2180             ScChiDistFunction( ScInterpreter& rI, double fpVal, double fDFVal ) :
2181                 rInt(rI), fp(fpVal), fDF(fDFVal) {}
2182 
2183     double  GetValue( double x ) const  { return fp - rInt.GetChiDist(x, fDF); }
2184 };
2185 
2186 void ScInterpreter::ScChiInv()
2187 {
2188     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScChiInv" );
2189     if ( !MustHaveParamCount( GetByte(), 2 ) )
2190         return;
2191     double fDF  = ::rtl::math::approxFloor(GetDouble());
2192     double fP = GetDouble();
2193     if (fDF < 1.0 || fP <= 0.0 || fP > 1.0 )
2194     {
2195         PushIllegalArgument();
2196         return;
2197     }
2198 
2199     bool bConvError;
2200     ScChiDistFunction aFunc( *this, fP, fDF );
2201     double fVal = lcl_IterateInverse( aFunc, fDF*0.5, fDF, bConvError );
2202     if (bConvError)
2203         SetError(errNoConvergence);
2204     PushDouble(fVal);
2205 }
2206 
2207 /***********************************************/
2208 class ScChiSqDistFunction : public ScDistFunc
2209 {
2210     ScInterpreter&  rInt;
2211     double          fp, fDF;
2212 
2213 public:
2214             ScChiSqDistFunction( ScInterpreter& rI, double fpVal, double fDFVal ) :
2215                 rInt(rI), fp(fpVal), fDF(fDFVal) {}
2216 
2217     double  GetValue( double x ) const  { return fp - rInt.GetChiSqDistCDF(x, fDF); }
2218 };
2219 
2220 
2221 void ScInterpreter::ScChiSqInv()
2222 {
2223     if ( !MustHaveParamCount( GetByte(), 2 ) )
2224         return;
2225     double fDF  = ::rtl::math::approxFloor(GetDouble());
2226     double fP = GetDouble();
2227     if (fDF < 1.0 || fP < 0.0 || fP >= 1.0 )
2228     {
2229         PushIllegalArgument();
2230         return;
2231     }
2232 
2233     bool bConvError;
2234     ScChiSqDistFunction aFunc( *this, fP, fDF );
2235     double fVal = lcl_IterateInverse( aFunc, fDF*0.5, fDF, bConvError );
2236     if (bConvError)
2237         SetError(errNoConvergence);
2238     PushDouble(fVal);
2239 }
2240 
2241 
2242 void ScInterpreter::ScConfidence()
2243 {
2244     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScConfidence" );
2245     if ( MustHaveParamCount( GetByte(), 3 ) )
2246     {
2247         double n     = ::rtl::math::approxFloor(GetDouble());
2248         double sigma = GetDouble();
2249         double alpha = GetDouble();
2250         if (sigma <= 0.0 || alpha <= 0.0 || alpha >= 1.0 || n < 1.0)
2251             PushIllegalArgument();
2252         else
2253             PushDouble( gaussinv(1.0-alpha/2.0) * sigma/sqrt(n) );
2254     }
2255 }
2256 
2257 void ScInterpreter::ScZTest()
2258 {
2259     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScZTest" );
2260     sal_uInt8 nParamCount = GetByte();
2261     if ( !MustHaveParamCount( nParamCount, 2, 3 ) )
2262         return;
2263     double sigma = 0.0, mue, x;
2264     if (nParamCount == 3)
2265     {
2266         sigma = GetDouble();
2267         if (sigma <= 0.0)
2268         {
2269             PushIllegalArgument();
2270             return;
2271         }
2272     }
2273     x = GetDouble();
2274 
2275     double fSum    = 0.0;
2276     double fSumSqr = 0.0;
2277     double fVal;
2278     double rValCount = 0.0;
2279     switch (GetStackType())
2280     {
2281         case formula::svDouble :
2282         {
2283             fVal = GetDouble();
2284             fSum    += fVal;
2285             fSumSqr += fVal*fVal;
2286             rValCount++;
2287         }
2288         break;
2289         case svSingleRef :
2290         {
2291             ScAddress aAdr;
2292             PopSingleRef( aAdr );
2293             ScBaseCell* pCell = GetCell( aAdr );
2294             if (HasCellValueData(pCell))
2295             {
2296                 fVal = GetCellValue( aAdr, pCell );
2297                 fSum += fVal;
2298                 fSumSqr += fVal*fVal;
2299                 rValCount++;
2300             }
2301         }
2302         break;
2303         case svRefList :
2304         case formula::svDoubleRef :
2305         {
2306             short nParam = 1;
2307             size_t nRefInList = 0;
2308             while (nParam-- > 0)
2309             {
2310                 ScRange aRange;
2311                 sal_uInt16 nErr = 0;
2312                 PopDoubleRef( aRange, nParam, nRefInList);
2313                 ScValueIterator aValIter(pDok, aRange, glSubTotal);
2314                 if (aValIter.GetFirst(fVal, nErr))
2315                 {
2316                     fSum += fVal;
2317                     fSumSqr += fVal*fVal;
2318                     rValCount++;
2319                     while ((nErr == 0) && aValIter.GetNext(fVal, nErr))
2320                     {
2321                         fSum += fVal;
2322                         fSumSqr += fVal*fVal;
2323                         rValCount++;
2324                     }
2325                     SetError(nErr);
2326                 }
2327             }
2328         }
2329         break;
2330         case svMatrix :
2331         {
2332             ScMatrixRef pMat = PopMatrix();
2333             if (pMat)
2334             {
2335                 SCSIZE nCount = pMat->GetElementCount();
2336                 if (pMat->IsNumeric())
2337                 {
2338                     for ( SCSIZE i = 0; i < nCount; i++ )
2339                     {
2340                         fVal= pMat->GetDouble(i);
2341                         fSum += fVal;
2342                         fSumSqr += fVal * fVal;
2343                         rValCount++;
2344                     }
2345                 }
2346                 else
2347                 {
2348                     for (SCSIZE i = 0; i < nCount; i++)
2349                         if (!pMat->IsString(i))
2350                         {
2351                             fVal= pMat->GetDouble(i);
2352                             fSum += fVal;
2353                             fSumSqr += fVal * fVal;
2354                             rValCount++;
2355                         }
2356                 }
2357             }
2358         }
2359         break;
2360         default : SetError(errIllegalParameter); break;
2361     }
2362     if (rValCount <= 1.0)
2363         PushError( errDivisionByZero);
2364     else
2365     {
2366         mue = fSum/rValCount;
2367         if (nParamCount != 3)
2368         {
2369             sigma = (fSumSqr - fSum*fSum/rValCount)/(rValCount-1.0);
2370             PushDouble(0.5 - gauss((mue-x)/sqrt(sigma/rValCount)));
2371         }
2372         else
2373             PushDouble(0.5 - gauss((mue-x)*sqrt(rValCount)/sigma));
2374     }
2375 }
2376 bool ScInterpreter::CalculateTest(sal_Bool _bTemplin
2377                                   ,const SCSIZE nC1, const SCSIZE nC2,const SCSIZE nR1,const SCSIZE nR2
2378                                   ,const ScMatrixRef& pMat1,const ScMatrixRef& pMat2
2379                                   ,double& fT,double& fF)
2380 {
2381     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CalculateTest" );
2382     double fCount1  = 0.0;
2383     double fCount2  = 0.0;
2384     double fSum1    = 0.0;
2385     double fSumSqr1 = 0.0;
2386     double fSum2    = 0.0;
2387     double fSumSqr2 = 0.0;
2388     double fVal;
2389     SCSIZE i,j;
2390     for (i = 0; i < nC1; i++)
2391         for (j = 0; j < nR1; j++)
2392         {
2393             if (!pMat1->IsString(i,j))
2394             {
2395                 fVal = pMat1->GetDouble(i,j);
2396                 fSum1    += fVal;
2397                 fSumSqr1 += fVal * fVal;
2398                 fCount1++;
2399             }
2400         }
2401     for (i = 0; i < nC2; i++)
2402         for (j = 0; j < nR2; j++)
2403         {
2404             if (!pMat2->IsString(i,j))
2405             {
2406                 fVal = pMat2->GetDouble(i,j);
2407                 fSum2    += fVal;
2408                 fSumSqr2 += fVal * fVal;
2409                 fCount2++;
2410             }
2411         }
2412     if (fCount1 < 2.0 || fCount2 < 2.0)
2413     {
2414         PushNoValue();
2415         return false;
2416     } // if (fCount1 < 2.0 || fCount2 < 2.0)
2417     if ( _bTemplin )
2418     {
2419         double fS1 = (fSumSqr1-fSum1*fSum1/fCount1)/(fCount1-1.0)/fCount1;
2420         double fS2 = (fSumSqr2-fSum2*fSum2/fCount2)/(fCount2-1.0)/fCount2;
2421         if (fS1 + fS2 == 0.0)
2422         {
2423             PushNoValue();
2424             return false;
2425         }
2426         fT = fabs(fSum1/fCount1 - fSum2/fCount2)/sqrt(fS1+fS2);
2427         double c = fS1/(fS1+fS2);
2428 // s.u. fF = ::rtl::math::approxFloor(1.0/(c*c/(fCount1-1.0)+(1.0-c)*(1.0-c)/(fCount2-1.0)));
2429 //      fF = ::rtl::math::approxFloor((fS1+fS2)*(fS1+fS2)/(fS1*fS1/(fCount1-1.0) + fS2*fS2/(fCount2-1.0)));
2430 
2431     //  GetTDist wird mit GetBetaDist berechnet und kommt auch mit nicht ganzzahligen
2432     //  Freiheitsgraden klar. Dann stimmt das Ergebnis auch mit Excel ueberein (#52406#):
2433         fF = 1.0/(c*c/(fCount1-1.0)+(1.0-c)*(1.0-c)/(fCount2-1.0));
2434     }
2435     else
2436     {
2437         //  laut Bronstein-Semendjajew
2438         double fS1 = (fSumSqr1 - fSum1*fSum1/fCount1) / (fCount1 - 1.0);    // Varianz
2439         double fS2 = (fSumSqr2 - fSum2*fSum2/fCount2) / (fCount2 - 1.0);
2440         fT = fabs( fSum1/fCount1 - fSum2/fCount2 ) /
2441              sqrt( (fCount1-1.0)*fS1 + (fCount2-1.0)*fS2 ) *
2442              sqrt( fCount1*fCount2*(fCount1+fCount2-2)/(fCount1+fCount2) );
2443         fF = fCount1 + fCount2 - 2;
2444     }
2445     return true;
2446 }
2447 void ScInterpreter::ScTTest()
2448 {
2449     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTTest" );
2450     if ( !MustHaveParamCount( GetByte(), 4 ) )
2451         return;
2452     double fTyp = ::rtl::math::approxFloor(GetDouble());
2453     double fAnz = ::rtl::math::approxFloor(GetDouble());
2454     if (fAnz != 1.0 && fAnz != 2.0)
2455     {
2456         PushIllegalArgument();
2457         return;
2458     }
2459 
2460     ScMatrixRef pMat2 = GetMatrix();
2461     ScMatrixRef pMat1 = GetMatrix();
2462     if (!pMat1 || !pMat2)
2463     {
2464         PushIllegalParameter();
2465         return;
2466     }
2467     double fT, fF;
2468     SCSIZE nC1, nC2;
2469     SCSIZE nR1, nR2;
2470     SCSIZE i, j;
2471     pMat1->GetDimensions(nC1, nR1);
2472     pMat2->GetDimensions(nC2, nR2);
2473     if (fTyp == 1.0)
2474     {
2475         if (nC1 != nC2 || nR1 != nR2)
2476         {
2477             PushIllegalArgument();
2478             return;
2479         }
2480         double fCount   = 0.0;
2481         double fSum1    = 0.0;
2482         double fSum2    = 0.0;
2483         double fSumSqrD = 0.0;
2484         double fVal1, fVal2;
2485         for (i = 0; i < nC1; i++)
2486             for (j = 0; j < nR1; j++)
2487             {
2488                 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
2489                 {
2490                     fVal1 = pMat1->GetDouble(i,j);
2491                     fVal2 = pMat2->GetDouble(i,j);
2492                     fSum1    += fVal1;
2493                     fSum2    += fVal2;
2494                     fSumSqrD += (fVal1 - fVal2)*(fVal1 - fVal2);
2495                     fCount++;
2496                 }
2497             }
2498         if (fCount < 1.0)
2499         {
2500             PushNoValue();
2501             return;
2502         }
2503         fT = sqrt(fCount-1.0) * fabs(fSum1 - fSum2) /
2504              sqrt(fCount * fSumSqrD - (fSum1-fSum2)*(fSum1-fSum2));
2505         fF = fCount - 1.0;
2506     }
2507     else if (fTyp == 2.0)
2508     {
2509         CalculateTest(sal_False,nC1, nC2,nR1, nR2,pMat1,pMat2,fT,fF);
2510     }
2511     else if (fTyp == 3.0)
2512     {
2513         CalculateTest(sal_True,nC1, nC2,nR1, nR2,pMat1,pMat2,fT,fF);
2514     }
2515 
2516     else
2517     {
2518         PushIllegalArgument();
2519         return;
2520     }
2521     if (fAnz == 1.0)
2522         PushDouble(GetTDist(fT, fF));
2523     else
2524         PushDouble(2.0*GetTDist(fT, fF));
2525 }
2526 
2527 void ScInterpreter::ScFTest()
2528 {
2529     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScFTest" );
2530     if ( !MustHaveParamCount( GetByte(), 2 ) )
2531         return;
2532     ScMatrixRef pMat2 = GetMatrix();
2533     ScMatrixRef pMat1 = GetMatrix();
2534     if (!pMat1 || !pMat2)
2535     {
2536         PushIllegalParameter();
2537         return;
2538     }
2539     SCSIZE nC1, nC2;
2540     SCSIZE nR1, nR2;
2541     SCSIZE i, j;
2542     pMat1->GetDimensions(nC1, nR1);
2543     pMat2->GetDimensions(nC2, nR2);
2544     double fCount1  = 0.0;
2545     double fCount2  = 0.0;
2546     double fSum1    = 0.0;
2547     double fSumSqr1 = 0.0;
2548     double fSum2    = 0.0;
2549     double fSumSqr2 = 0.0;
2550     double fVal;
2551     for (i = 0; i < nC1; i++)
2552         for (j = 0; j < nR1; j++)
2553         {
2554             if (!pMat1->IsString(i,j))
2555             {
2556                 fVal = pMat1->GetDouble(i,j);
2557                 fSum1    += fVal;
2558                 fSumSqr1 += fVal * fVal;
2559                 fCount1++;
2560             }
2561         }
2562     for (i = 0; i < nC2; i++)
2563         for (j = 0; j < nR2; j++)
2564         {
2565             if (!pMat2->IsString(i,j))
2566             {
2567                 fVal = pMat2->GetDouble(i,j);
2568                 fSum2    += fVal;
2569                 fSumSqr2 += fVal * fVal;
2570                 fCount2++;
2571             }
2572         }
2573     if (fCount1 < 2.0 || fCount2 < 2.0)
2574     {
2575         PushNoValue();
2576         return;
2577     }
2578     double fS1 = (fSumSqr1-fSum1*fSum1/fCount1)/(fCount1-1.0);
2579     double fS2 = (fSumSqr2-fSum2*fSum2/fCount2)/(fCount2-1.0);
2580     if (fS1 == 0.0 || fS2 == 0.0)
2581     {
2582         PushNoValue();
2583         return;
2584     }
2585     double fF, fF1, fF2;
2586     if (fS1 > fS2)
2587     {
2588         fF = fS1/fS2;
2589         fF1 = fCount1-1.0;
2590         fF2 = fCount2-1.0;
2591     }
2592     else
2593     {
2594         fF = fS2/fS1;
2595         fF1 = fCount2-1.0;
2596         fF2 = fCount1-1.0;
2597     }
2598     PushDouble(2.0*GetFDist(fF, fF1, fF2));
2599 /*
2600     double Z = (pow(fF,1.0/3.0)*(1.0-2.0/(9.0*fF2)) - (1.0-2.0/(9.0*fF1))) /
2601                sqrt(2.0/(9.0*fF1) + pow(fF,2.0/3.0)*2.0/(9.0*fF2));
2602     PushDouble(1.0-2.0*gauss(Z));
2603 */
2604 }
2605 
2606 void ScInterpreter::ScChiTest()
2607 {
2608     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScChiTest" );
2609     if ( !MustHaveParamCount( GetByte(), 2 ) )
2610         return;
2611     ScMatrixRef pMat2 = GetMatrix();
2612     ScMatrixRef pMat1 = GetMatrix();
2613     if (!pMat1 || !pMat2)
2614     {
2615         PushIllegalParameter();
2616         return;
2617     }
2618     SCSIZE nC1, nC2;
2619     SCSIZE nR1, nR2;
2620     pMat1->GetDimensions(nC1, nR1);
2621     pMat2->GetDimensions(nC2, nR2);
2622     if (nR1 != nR2 || nC1 != nC2)
2623     {
2624         PushIllegalArgument();
2625         return;
2626     }
2627     double fChi = 0.0;
2628     for (SCSIZE i = 0; i < nC1; i++)
2629     {
2630         for (SCSIZE j = 0; j < nR1; j++)
2631         {
2632             if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
2633             {
2634                 double fValX = pMat1->GetDouble(i,j);
2635                 double fValE = pMat2->GetDouble(i,j);
2636                 fChi += (fValX - fValE) * (fValX - fValE) / fValE;
2637             }
2638             else
2639             {
2640                 PushIllegalArgument();
2641                 return;
2642             }
2643         }
2644     }
2645     double fDF;
2646     if (nC1 == 1 || nR1 == 1)
2647     {
2648         fDF = (double)(nC1*nR1 - 1);
2649         if (fDF == 0.0)
2650         {
2651             PushNoValue();
2652             return;
2653         }
2654     }
2655     else
2656         fDF = (double)(nC1-1)*(double)(nR1-1);
2657     PushDouble(GetChiDist(fChi, fDF));
2658 /*
2659     double fX, fS, fT, fG;
2660     fX = 1.0;
2661     for (double fi = fDF; fi >= 2.0; fi -= 2.0)
2662         fX *= fChi/fi;
2663     fX *= exp(-fChi/2.0);
2664     if (fmod(fDF, 2.0) != 0.0)
2665         fX *= sqrt(2.0*fChi/F_PI);
2666     fS = 1.0;
2667     fT = 1.0;
2668     fG = fDF;
2669     while (fT >= 1.0E-7)
2670     {
2671         fG += 2.0;
2672         fT *= fChi/fG;
2673         fS += fT;
2674     }
2675     PushDouble(1.0 - fX*fS);
2676 */
2677 }
2678 
2679 void ScInterpreter::ScKurt()
2680 {
2681     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScKurt" );
2682     double fSum,fCount,vSum;
2683     std::vector<double> values;
2684     if ( !CalculateSkew(fSum,fCount,vSum,values) )
2685         return;
2686 
2687     if (fCount == 0.0)
2688     {
2689         PushError( errDivisionByZero);
2690         return;
2691     }
2692 
2693     double fMean = fSum / fCount;
2694 
2695     for (size_t i = 0; i < values.size(); i++)
2696         vSum += (values[i] - fMean) * (values[i] - fMean);
2697 
2698     double fStdDev = sqrt(vSum / (fCount - 1.0));
2699     double dx = 0.0;
2700     double xpower4 = 0.0;
2701 
2702     if (fStdDev == 0.0)
2703     {
2704         PushError( errDivisionByZero);
2705         return;
2706     }
2707 
2708     for (size_t i = 0; i < values.size(); i++)
2709     {
2710         dx = (values[i] - fMean) / fStdDev;
2711         xpower4 = xpower4 + (dx * dx * dx * dx);
2712     }
2713 
2714     double k_d = (fCount - 2.0) * (fCount - 3.0);
2715     double k_l = fCount * (fCount + 1.0) / ((fCount - 1.0) * k_d);
2716     double k_t = 3.0 * (fCount - 1.0) * (fCount - 1.0) / k_d;
2717 
2718     PushDouble(xpower4 * k_l - k_t);
2719 }
2720 
2721 void ScInterpreter::ScHarMean()
2722 {
2723     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScHarMean" );
2724     short nParamCount = GetByte();
2725     double nVal = 0.0;
2726     double nValCount = 0.0;
2727     ScAddress aAdr;
2728     ScRange aRange;
2729     size_t nRefInList = 0;
2730     while ((nGlobalError == 0) && (nParamCount-- > 0))
2731     {
2732         switch (GetStackType())
2733         {
2734             case formula::svDouble    :
2735             {
2736                 double x = GetDouble();
2737                 if (x > 0.0)
2738                 {
2739                     nVal += 1.0/x;
2740                     nValCount++;
2741                 }
2742                 else
2743                     SetError( errIllegalArgument);
2744                 break;
2745             }
2746             case svSingleRef :
2747             {
2748                 PopSingleRef( aAdr );
2749                 ScBaseCell* pCell = GetCell( aAdr );
2750                 if (HasCellValueData(pCell))
2751                 {
2752                     double x = GetCellValue( aAdr, pCell );
2753                     if (x > 0.0)
2754                     {
2755                         nVal += 1.0/x;
2756                         nValCount++;
2757                     }
2758                     else
2759                         SetError( errIllegalArgument);
2760                 }
2761                 break;
2762             }
2763             case formula::svDoubleRef :
2764             case svRefList :
2765             {
2766                 sal_uInt16 nErr = 0;
2767                 PopDoubleRef( aRange, nParamCount, nRefInList);
2768                 double nCellVal;
2769                 ScValueIterator aValIter(pDok, aRange, glSubTotal);
2770                 if (aValIter.GetFirst(nCellVal, nErr))
2771                 {
2772                     if (nCellVal > 0.0)
2773                     {
2774                         nVal += 1.0/nCellVal;
2775                         nValCount++;
2776                     }
2777                     else
2778                         SetError( errIllegalArgument);
2779                     SetError(nErr);
2780                     while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
2781                     {
2782                         if (nCellVal > 0.0)
2783                         {
2784                             nVal += 1.0/nCellVal;
2785                             nValCount++;
2786                         }
2787                         else
2788                             SetError( errIllegalArgument);
2789                     }
2790                     SetError(nErr);
2791                 }
2792             }
2793             break;
2794             case svMatrix :
2795             {
2796                 ScMatrixRef pMat = PopMatrix();
2797                 if (pMat)
2798                 {
2799                     SCSIZE nCount = pMat->GetElementCount();
2800                     if (pMat->IsNumeric())
2801                     {
2802                         for (SCSIZE nElem = 0; nElem < nCount; nElem++)
2803                         {
2804                             double x = pMat->GetDouble(nElem);
2805                             if (x > 0.0)
2806                             {
2807                                 nVal += 1.0/x;
2808                                 nValCount++;
2809                             }
2810                             else
2811                                 SetError( errIllegalArgument);
2812                         }
2813                     }
2814                     else
2815                     {
2816                         for (SCSIZE nElem = 0; nElem < nCount; nElem++)
2817                             if (!pMat->IsString(nElem))
2818                             {
2819                                 double x = pMat->GetDouble(nElem);
2820                                 if (x > 0.0)
2821                                 {
2822                                     nVal += 1.0/x;
2823                                     nValCount++;
2824                                 }
2825                                 else
2826                                     SetError( errIllegalArgument);
2827                             }
2828                     }
2829                 }
2830             }
2831             break;
2832             default : SetError(errIllegalParameter); break;
2833         }
2834     }
2835     if (nGlobalError == 0)
2836         PushDouble((double)nValCount/nVal);
2837     else
2838         PushError( nGlobalError);
2839 }
2840 
2841 void ScInterpreter::ScGeoMean()
2842 {
2843     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGeoMean" );
2844     short nParamCount = GetByte();
2845     double nVal = 0.0;
2846     double nValCount = 0.0;
2847     ScAddress aAdr;
2848     ScRange aRange;
2849 
2850     size_t nRefInList = 0;
2851     while ((nGlobalError == 0) && (nParamCount-- > 0))
2852     {
2853         switch (GetStackType())
2854         {
2855             case formula::svDouble    :
2856             {
2857                 double x = GetDouble();
2858                 if (x > 0.0)
2859                 {
2860                     nVal += log(x);
2861                     nValCount++;
2862                 }
2863                 else
2864                     SetError( errIllegalArgument);
2865                 break;
2866             }
2867             case svSingleRef :
2868             {
2869                 PopSingleRef( aAdr );
2870                 ScBaseCell* pCell = GetCell( aAdr );
2871                 if (HasCellValueData(pCell))
2872                 {
2873                     double x = GetCellValue( aAdr, pCell );
2874                     if (x > 0.0)
2875                     {
2876                         nVal += log(x);
2877                         nValCount++;
2878                     }
2879                     else
2880                         SetError( errIllegalArgument);
2881                 }
2882                 break;
2883             }
2884             case formula::svDoubleRef :
2885             case svRefList :
2886             {
2887                 sal_uInt16 nErr = 0;
2888                 PopDoubleRef( aRange, nParamCount, nRefInList);
2889                 double nCellVal;
2890                 ScValueIterator aValIter(pDok, aRange, glSubTotal);
2891                 if (aValIter.GetFirst(nCellVal, nErr))
2892                 {
2893                     if (nCellVal > 0.0)
2894                     {
2895                         nVal += log(nCellVal);
2896                         nValCount++;
2897                     }
2898                     else
2899                         SetError( errIllegalArgument);
2900                     SetError(nErr);
2901                     while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
2902                     {
2903                         if (nCellVal > 0.0)
2904                         {
2905                             nVal += log(nCellVal);
2906                             nValCount++;
2907                         }
2908                         else
2909                             SetError( errIllegalArgument);
2910                     }
2911                     SetError(nErr);
2912                 }
2913             }
2914             break;
2915             case svMatrix :
2916             {
2917                 ScMatrixRef pMat = PopMatrix();
2918                 if (pMat)
2919                 {
2920                     SCSIZE nCount = pMat->GetElementCount();
2921                     if (pMat->IsNumeric())
2922                     {
2923                         for (SCSIZE ui = 0; ui < nCount; ui++)
2924                         {
2925                             double x = pMat->GetDouble(ui);
2926                             if (x > 0.0)
2927                             {
2928                                 nVal += log(x);
2929                                 nValCount++;
2930                             }
2931                             else
2932                                 SetError( errIllegalArgument);
2933                         }
2934                     }
2935                     else
2936                     {
2937                         for (SCSIZE ui = 0; ui < nCount; ui++)
2938                             if (!pMat->IsString(ui))
2939                             {
2940                                 double x = pMat->GetDouble(ui);
2941                                 if (x > 0.0)
2942                                 {
2943                                     nVal += log(x);
2944                                     nValCount++;
2945                                 }
2946                                 else
2947                                     SetError( errIllegalArgument);
2948                             }
2949                     }
2950                 }
2951             }
2952             break;
2953             default : SetError(errIllegalParameter); break;
2954         }
2955     }
2956     if (nGlobalError == 0)
2957         PushDouble(exp(nVal / nValCount));
2958     else
2959         PushError( nGlobalError);
2960 }
2961 
2962 void ScInterpreter::ScStandard()
2963 {
2964     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScStandard" );
2965     if ( MustHaveParamCount( GetByte(), 3 ) )
2966     {
2967         double sigma = GetDouble();
2968         double mue   = GetDouble();
2969         double x     = GetDouble();
2970         if (sigma < 0.0)
2971             PushError( errIllegalArgument);
2972         else if (sigma == 0.0)
2973             PushError( errDivisionByZero);
2974         else
2975             PushDouble((x-mue)/sigma);
2976     }
2977 }
2978 bool ScInterpreter::CalculateSkew(double& fSum,double& fCount,double& vSum,std::vector<double>& values)
2979 {
2980     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CalculateSkew" );
2981     short nParamCount = GetByte();
2982     if ( !MustHaveParamCountMin( nParamCount, 1 )  )
2983         return false;
2984 
2985     fSum   = 0.0;
2986     fCount = 0.0;
2987     vSum   = 0.0;
2988     double fVal = 0.0;
2989     ScAddress aAdr;
2990     ScRange aRange;
2991     size_t nRefInList = 0;
2992     while (nParamCount-- > 0)
2993     {
2994         switch (GetStackType())
2995         {
2996             case formula::svDouble :
2997             {
2998                 fVal = GetDouble();
2999                 fSum += fVal;
3000                 values.push_back(fVal);
3001                 fCount++;
3002             }
3003                 break;
3004             case svSingleRef :
3005             {
3006                 PopSingleRef( aAdr );
3007                 ScBaseCell* pCell = GetCell( aAdr );
3008                 if (HasCellValueData(pCell))
3009                 {
3010                     fVal = GetCellValue( aAdr, pCell );
3011                     fSum += fVal;
3012                     values.push_back(fVal);
3013                     fCount++;
3014                 }
3015             }
3016             break;
3017             case formula::svDoubleRef :
3018             case svRefList :
3019             {
3020                 PopDoubleRef( aRange, nParamCount, nRefInList);
3021                 sal_uInt16 nErr = 0;
3022                 ScValueIterator aValIter(pDok, aRange);
3023                 if (aValIter.GetFirst(fVal, nErr))
3024                 {
3025                     fSum += fVal;
3026                     values.push_back(fVal);
3027                     fCount++;
3028                     SetError(nErr);
3029                     while ((nErr == 0) && aValIter.GetNext(fVal, nErr))
3030                     {
3031                         fSum += fVal;
3032                         values.push_back(fVal);
3033                         fCount++;
3034                     }
3035                     SetError(nErr);
3036                 }
3037             }
3038             break;
3039             case svMatrix :
3040             {
3041                 ScMatrixRef pMat = PopMatrix();
3042                 if (pMat)
3043                 {
3044                     SCSIZE nCount = pMat->GetElementCount();
3045                     if (pMat->IsNumeric())
3046                     {
3047                         for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3048                         {
3049                             fVal = pMat->GetDouble(nElem);
3050                             fSum += fVal;
3051                             values.push_back(fVal);
3052                             fCount++;
3053                         }
3054                     }
3055                     else
3056                     {
3057                         for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3058                             if (!pMat->IsString(nElem))
3059                             {
3060                                 fVal = pMat->GetDouble(nElem);
3061                                 fSum += fVal;
3062                                 values.push_back(fVal);
3063                                 fCount++;
3064                             }
3065                     }
3066                 }
3067             }
3068             break;
3069             default :
3070                 SetError(errIllegalParameter);
3071             break;
3072         }
3073     }
3074 
3075     if (nGlobalError)
3076     {
3077         PushError( nGlobalError);
3078         return false;
3079     } // if (nGlobalError)
3080     return true;
3081 }
3082 
3083 void ScInterpreter::ScSkew()
3084 {
3085     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSkew" );
3086     double fSum,fCount,vSum;
3087     std::vector<double> values;
3088     if ( !CalculateSkew(fSum,fCount,vSum,values) )
3089         return;
3090 
3091     double fMean = fSum / fCount;
3092 
3093     for (size_t i = 0; i < values.size(); i++)
3094         vSum += (values[i] - fMean) * (values[i] - fMean);
3095 
3096     double fStdDev = sqrt(vSum / (fCount - 1.0));
3097     double dx = 0.0;
3098     double xcube = 0.0;
3099 
3100     if (fStdDev == 0)
3101     {
3102         PushIllegalArgument();
3103         return;
3104     }
3105 
3106     for (size_t i = 0; i < values.size(); i++)
3107     {
3108         dx = (values[i] - fMean) / fStdDev;
3109         xcube = xcube + (dx * dx * dx);
3110     }
3111 
3112     PushDouble(((xcube * fCount) / (fCount - 1.0)) / (fCount - 2.0));
3113 }
3114 
3115 double ScInterpreter::GetMedian( vector<double> & rArray )
3116 {
3117     size_t nSize = rArray.size();
3118     if (rArray.empty() || nSize == 0 || nGlobalError)
3119     {
3120         SetError( errNoValue);
3121         return 0.0;
3122     }
3123 
3124     // Upper median.
3125     size_t nMid = nSize / 2;
3126     vector<double>::iterator iMid = rArray.begin() + nMid;
3127     ::std::nth_element( rArray.begin(), iMid, rArray.end());
3128     if (nSize & 1)
3129         return *iMid;   // Lower and upper median are equal.
3130     else
3131     {
3132         double fUp = *iMid;
3133         // Lower median.
3134         iMid = rArray.begin() + nMid - 1;
3135         ::std::nth_element( rArray.begin(), iMid, rArray.end());
3136         return (fUp + *iMid) / 2;
3137     }
3138 }
3139 
3140 void ScInterpreter::ScMedian()
3141 {
3142     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMedian" );
3143     sal_uInt8 nParamCount = GetByte();
3144     if ( !MustHaveParamCountMin( nParamCount, 1 )  )
3145         return;
3146     vector<double> aArray;
3147     GetNumberSequenceArray( nParamCount, aArray);
3148     PushDouble( GetMedian( aArray));
3149 }
3150 
3151 double ScInterpreter::GetPercentile( vector<double> & rArray, double fPercentile )
3152 {
3153     size_t nSize = rArray.size();
3154     if (rArray.empty() || nSize == 0 || nGlobalError)
3155     {
3156         SetError( errNoValue);
3157         return 0.0;
3158     }
3159 
3160     if (nSize == 1)
3161         return rArray[0];
3162     else
3163     {
3164         size_t nIndex = (size_t)::rtl::math::approxFloor( fPercentile * (nSize-1));
3165         double fDiff = fPercentile * (nSize-1) - ::rtl::math::approxFloor( fPercentile * (nSize-1));
3166         DBG_ASSERT(nIndex < nSize, "GetPercentile: wrong index(1)");
3167         vector<double>::iterator iter = rArray.begin() + nIndex;
3168         ::std::nth_element( rArray.begin(), iter, rArray.end());
3169         if (fDiff == 0.0)
3170             return *iter;
3171         else
3172         {
3173             DBG_ASSERT(nIndex < nSize-1, "GetPercentile: wrong index(2)");
3174             double fVal = *iter;
3175             iter = rArray.begin() + nIndex+1;
3176             ::std::nth_element( rArray.begin(), iter, rArray.end());
3177             return fVal + fDiff * (*iter - fVal);
3178         }
3179     }
3180 }
3181 
3182 void ScInterpreter::ScPercentile()
3183 {
3184     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScPercentile" );
3185     if ( !MustHaveParamCount( GetByte(), 2 ) )
3186         return;
3187     double alpha = GetDouble();
3188     if (alpha < 0.0 || alpha > 1.0)
3189     {
3190         PushIllegalArgument();
3191         return;
3192     }
3193     vector<double> aArray;
3194     GetNumberSequenceArray( 1, aArray);
3195     PushDouble( GetPercentile( aArray, alpha));
3196 }
3197 
3198 void ScInterpreter::ScQuartile()
3199 {
3200     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScQuartile" );
3201     if ( !MustHaveParamCount( GetByte(), 2 ) )
3202         return;
3203     double fFlag = ::rtl::math::approxFloor(GetDouble());
3204     if (fFlag < 0.0 || fFlag > 4.0)
3205     {
3206         PushIllegalArgument();
3207         return;
3208     }
3209     vector<double> aArray;
3210     GetNumberSequenceArray( 1, aArray);
3211     PushDouble( fFlag == 2.0 ? GetMedian( aArray) : GetPercentile( aArray, 0.25 * fFlag));
3212 }
3213 
3214 void ScInterpreter::ScModalValue()
3215 {
3216     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScModalValue" );
3217     sal_uInt8 nParamCount = GetByte();
3218     if ( !MustHaveParamCountMin( nParamCount, 1 ) )
3219         return;
3220     vector<double> aSortArray;
3221     GetSortArray(nParamCount, aSortArray);
3222     SCSIZE nSize = aSortArray.size();
3223     if (aSortArray.empty() || nSize == 0 || nGlobalError)
3224         PushNoValue();
3225     else
3226     {
3227         SCSIZE nMaxIndex = 0, nMax = 1, nCount = 1;
3228         double nOldVal = aSortArray[0];
3229         SCSIZE i;
3230 
3231         for ( i = 1; i < nSize; i++)
3232         {
3233             if (aSortArray[i] == nOldVal)
3234                 nCount++;
3235             else
3236             {
3237                 nOldVal = aSortArray[i];
3238                 if (nCount > nMax)
3239                 {
3240                     nMax = nCount;
3241                     nMaxIndex = i-1;
3242                 }
3243                 nCount = 1;
3244             }
3245         }
3246         if (nCount > nMax)
3247         {
3248             nMax = nCount;
3249             nMaxIndex = i-1;
3250         }
3251         if (nMax == 1 && nCount == 1)
3252             PushNoValue();
3253         else if (nMax == 1)
3254             PushDouble(nOldVal);
3255         else
3256             PushDouble(aSortArray[nMaxIndex]);
3257     }
3258 }
3259 
3260 void ScInterpreter::CalculateSmallLarge(sal_Bool bSmall)
3261 {
3262     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CalculateSmallLarge" );
3263     if ( !MustHaveParamCount( GetByte(), 2 )  )
3264         return;
3265     double f = ::rtl::math::approxFloor(GetDouble());
3266     if (f < 1.0)
3267     {
3268         PushIllegalArgument();
3269         return;
3270     }
3271     SCSIZE k = static_cast<SCSIZE>(f);
3272     vector<double> aSortArray;
3273     /* TODO: using nth_element() is best for one single value, but LARGE/SMALL
3274      * actually are defined to return an array of values if an array of
3275      * positions was passed, in which case, depending on the number of values,
3276      * we may or will need a real sorted array again, see #i32345. */
3277     //GetSortArray(1, aSortArray);
3278     GetNumberSequenceArray(1, aSortArray);
3279     SCSIZE nSize = aSortArray.size();
3280     if (aSortArray.empty() || nSize == 0 || nGlobalError || nSize < k)
3281         PushNoValue();
3282     else
3283     {
3284         // TODO: the sorted case for array: PushDouble( aSortArray[ bSmall ? k-1 : nSize-k ] );
3285         vector<double>::iterator iPos = aSortArray.begin() + (bSmall ? k-1 : nSize-k);
3286         ::std::nth_element( aSortArray.begin(), iPos, aSortArray.end());
3287         PushDouble( *iPos);
3288     }
3289 }
3290 
3291 void ScInterpreter::ScLarge()
3292 {
3293     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLarge" );
3294     CalculateSmallLarge(sal_False);
3295 }
3296 
3297 void ScInterpreter::ScSmall()
3298 {
3299     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSmall" );
3300     CalculateSmallLarge(sal_True);
3301 }
3302 
3303 void ScInterpreter::ScPercentrank()
3304 {
3305     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScPercentrank" );
3306     sal_uInt8 nParamCount = GetByte();
3307     if ( !MustHaveParamCount( nParamCount, 2 ) )
3308         return;
3309 #if 0
3310 /*                          wird nicht unterstuetzt
3311     double fPrec;
3312     if (nParamCount == 3)
3313     {
3314         fPrec = ::rtl::math::approxFloor(GetDouble());
3315         if (fPrec < 1.0)
3316         {
3317             PushIllegalArgument();
3318             return;
3319         }
3320     }
3321     else
3322         fPrec = 3.0;
3323 */
3324 #endif
3325     double fNum = GetDouble();
3326     vector<double> aSortArray;
3327     GetSortArray(1, aSortArray);
3328     SCSIZE nSize = aSortArray.size();
3329     if (aSortArray.empty() || nSize == 0 || nGlobalError)
3330         PushNoValue();
3331     else
3332     {
3333         if (fNum < aSortArray[0] || fNum > aSortArray[nSize-1])
3334             PushNoValue();
3335         else if ( nSize == 1 )
3336             PushDouble(1.0);            // fNum == pSortArray[0], see test above
3337         else
3338         {
3339             double fRes;
3340             SCSIZE nOldCount = 0;
3341             double fOldVal = aSortArray[0];
3342             SCSIZE i;
3343             for (i = 1; i < nSize && aSortArray[i] < fNum; i++)
3344             {
3345                 if (aSortArray[i] != fOldVal)
3346                 {
3347                     nOldCount = i;
3348                     fOldVal = aSortArray[i];
3349                 }
3350             }
3351             if (aSortArray[i] != fOldVal)
3352                 nOldCount = i;
3353             if (fNum == aSortArray[i])
3354                 fRes = (double)nOldCount/(double)(nSize-1);
3355             else
3356             {
3357                 //  #75312# nOldCount is the count of smaller entries
3358                 //  fNum is between pSortArray[nOldCount-1] and pSortArray[nOldCount]
3359                 //  use linear interpolation to find a position between the entries
3360 
3361                 if ( nOldCount == 0 )
3362                 {
3363                     DBG_ERROR("should not happen");
3364                     fRes = 0.0;
3365                 }
3366                 else
3367                 {
3368                     double fFract = ( fNum - aSortArray[nOldCount-1] ) /
3369                         ( aSortArray[nOldCount] - aSortArray[nOldCount-1] );
3370                     fRes = ( (double)(nOldCount-1)+fFract )/(double)(nSize-1);
3371                 }
3372             }
3373             PushDouble(fRes);
3374         }
3375     }
3376 }
3377 
3378 void ScInterpreter::ScTrimMean()
3379 {
3380     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTrimMean" );
3381     if ( !MustHaveParamCount( GetByte(), 2 ) )
3382         return;
3383     double alpha = GetDouble();
3384     if (alpha < 0.0 || alpha >= 1.0)
3385     {
3386         PushIllegalArgument();
3387         return;
3388     }
3389     vector<double> aSortArray;
3390     GetSortArray(1, aSortArray);
3391     SCSIZE nSize = aSortArray.size();
3392     if (aSortArray.empty() || nSize == 0 || nGlobalError)
3393         PushNoValue();
3394     else
3395     {
3396         sal_uLong nIndex = (sal_uLong) ::rtl::math::approxFloor(alpha*(double)nSize);
3397         if (nIndex % 2 != 0)
3398             nIndex--;
3399         nIndex /= 2;
3400         DBG_ASSERT(nIndex < nSize, "ScTrimMean: falscher Index");
3401         double fSum = 0.0;
3402         for (SCSIZE i = nIndex; i < nSize-nIndex; i++)
3403             fSum += aSortArray[i];
3404         PushDouble(fSum/(double)(nSize-2*nIndex));
3405     }
3406 }
3407 
3408 void ScInterpreter::GetNumberSequenceArray( sal_uInt8 nParamCount, vector<double>& rArray )
3409 {
3410     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetSortArray" );
3411     ScAddress aAdr;
3412     ScRange aRange;
3413     short nParam = nParamCount;
3414     size_t nRefInList = 0;
3415     while (nParam-- > 0)
3416     {
3417         switch (GetStackType())
3418         {
3419             case formula::svDouble :
3420                 rArray.push_back( PopDouble());
3421             break;
3422             case svSingleRef :
3423             {
3424                 PopSingleRef( aAdr );
3425                 ScBaseCell* pCell = GetCell( aAdr );
3426                 if (HasCellValueData(pCell))
3427                     rArray.push_back( GetCellValue( aAdr, pCell));
3428             }
3429             break;
3430             case formula::svDoubleRef :
3431             case svRefList :
3432             {
3433                 PopDoubleRef( aRange, nParam, nRefInList);
3434                 if (nGlobalError)
3435                     break;
3436 
3437                 aRange.Justify();
3438                 SCSIZE nCellCount = aRange.aEnd.Col() - aRange.aStart.Col() + 1;
3439                 nCellCount *= aRange.aEnd.Row() - aRange.aStart.Row() + 1;
3440                 rArray.reserve( rArray.size() + nCellCount);
3441 
3442                 sal_uInt16 nErr = 0;
3443                 double fCellVal;
3444                 ScValueIterator aValIter(pDok, aRange);
3445                 if (aValIter.GetFirst( fCellVal, nErr))
3446                 {
3447                     rArray.push_back( fCellVal);
3448                     SetError(nErr);
3449                     while ((nErr == 0) && aValIter.GetNext( fCellVal, nErr))
3450                         rArray.push_back( fCellVal);
3451                     SetError(nErr);
3452                 }
3453             }
3454             break;
3455             case svMatrix :
3456             {
3457                 ScMatrixRef pMat = PopMatrix();
3458                 if (!pMat)
3459                     break;
3460 
3461                 SCSIZE nCount = pMat->GetElementCount();
3462                 rArray.reserve( rArray.size() + nCount);
3463                 if (pMat->IsNumeric())
3464                 {
3465                     for (SCSIZE i = 0; i < nCount; ++i)
3466                         rArray.push_back( pMat->GetDouble(i));
3467                 }
3468                 else
3469                 {
3470                     for (SCSIZE i = 0; i < nCount; ++i)
3471                         if (!pMat->IsString(i))
3472                             rArray.push_back( pMat->GetDouble(i));
3473                 }
3474             }
3475             break;
3476             default :
3477                 PopError();
3478                 SetError( errIllegalParameter);
3479             break;
3480         }
3481         if (nGlobalError)
3482             break;  // while
3483     }
3484     // nParam > 0 in case of error, clean stack environment and obtain earlier
3485     // error if there was one.
3486     while (nParam-- > 0)
3487         PopError();
3488 }
3489 
3490 void ScInterpreter::GetSortArray( sal_uInt8 nParamCount, vector<double>& rSortArray, vector<long>* pIndexOrder )
3491 {
3492     GetNumberSequenceArray( nParamCount, rSortArray);
3493 
3494     if (rSortArray.size() > MAX_ANZ_DOUBLE_FOR_SORT)
3495         SetError( errStackOverflow);
3496     else if (rSortArray.empty())
3497         SetError( errNoValue);
3498 
3499     if (nGlobalError == 0)
3500         QuickSort( rSortArray, pIndexOrder);
3501 }
3502 
3503 static void lcl_QuickSort( long nLo, long nHi, vector<double>& rSortArray, vector<long>* pIndexOrder )
3504 {
3505     // If pIndexOrder is not NULL, we assume rSortArray.size() == pIndexOrder->size().
3506 
3507     using ::std::swap;
3508 
3509     if (nHi - nLo == 1)
3510     {
3511         if (rSortArray[nLo] > rSortArray[nHi])
3512         {
3513             swap(rSortArray[nLo],  rSortArray[nHi]);
3514             if (pIndexOrder)
3515                 swap(pIndexOrder->at(nLo), pIndexOrder->at(nHi));
3516         }
3517         return;
3518     }
3519 
3520     long ni = nLo;
3521     long nj = nHi;
3522     do
3523     {
3524         double fLo = rSortArray[nLo];
3525         while (ni <= nHi && rSortArray[ni] < fLo) ni++;
3526         while (nj >= nLo && fLo < rSortArray[nj]) nj--;
3527         if (ni <= nj)
3528         {
3529             if (ni != nj)
3530             {
3531                 swap(rSortArray[ni],  rSortArray[nj]);
3532                 if (pIndexOrder)
3533                     swap(pIndexOrder->at(ni), pIndexOrder->at(nj));
3534             }
3535 
3536             ++ni;
3537             --nj;
3538         }
3539     }
3540     while (ni < nj);
3541 
3542     if ((nj - nLo) < (nHi - ni))
3543     {
3544         if (nLo < nj) lcl_QuickSort(nLo, nj, rSortArray, pIndexOrder);
3545         if (ni < nHi) lcl_QuickSort(ni, nHi, rSortArray, pIndexOrder);
3546     }
3547     else
3548     {
3549         if (ni < nHi) lcl_QuickSort(ni, nHi, rSortArray, pIndexOrder);
3550         if (nLo < nj) lcl_QuickSort(nLo, nj, rSortArray, pIndexOrder);
3551     }
3552 }
3553 
3554 void ScInterpreter::QuickSort( vector<double>& rSortArray, vector<long>* pIndexOrder )
3555 {
3556     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::QuickSort" );
3557     long n = static_cast<long>(rSortArray.size());
3558 
3559     if (pIndexOrder)
3560     {
3561         pIndexOrder->clear();
3562         pIndexOrder->reserve(n);
3563         for (long i = 0; i < n; ++i)
3564             pIndexOrder->push_back(i);
3565     }
3566 
3567     if (n < 2)
3568         return;
3569 
3570     size_t nValCount = rSortArray.size();
3571     for (size_t i = 0; (i + 4) <= nValCount-1; i += 4)
3572     {
3573         size_t nInd = rand() % (int) (nValCount-1);
3574         ::std::swap( rSortArray[i], rSortArray[nInd]);
3575         if (pIndexOrder)
3576             ::std::swap( pIndexOrder->at(i), pIndexOrder->at(nInd));
3577     }
3578 
3579     lcl_QuickSort(0, n-1, rSortArray, pIndexOrder);
3580 }
3581 
3582 void ScInterpreter::ScRank()
3583 {
3584     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRank" );
3585     sal_uInt8 nParamCount = GetByte();
3586     if ( !MustHaveParamCount( nParamCount, 2, 3 ) )
3587         return;
3588     sal_Bool bDescending;
3589     if (nParamCount == 3)
3590         bDescending = GetBool();
3591     else
3592         bDescending = sal_False;
3593     double fCount = 1.0;
3594     sal_Bool bValid = sal_False;
3595     switch (GetStackType())
3596     {
3597         case formula::svDouble    :
3598         {
3599             double x = GetDouble();
3600             double fVal = GetDouble();
3601             if (x == fVal)
3602                 bValid = sal_True;
3603             break;
3604         }
3605         case svSingleRef :
3606         {
3607             ScAddress aAdr;
3608             PopSingleRef( aAdr );
3609             double fVal = GetDouble();
3610             ScBaseCell* pCell = GetCell( aAdr );
3611             if (HasCellValueData(pCell))
3612             {
3613                 double x = GetCellValue( aAdr, pCell );
3614                 if (x == fVal)
3615                     bValid = sal_True;
3616             }
3617             break;
3618         }
3619         case formula::svDoubleRef :
3620         case svRefList :
3621         {
3622             ScRange aRange;
3623             short nParam = 1;
3624             size_t nRefInList = 0;
3625             while (nParam-- > 0)
3626             {
3627                 sal_uInt16 nErr = 0;
3628                 // Preserve stack until all RefList elements are done!
3629                 sal_uInt16 nSaveSP = sp;
3630                 PopDoubleRef( aRange, nParam, nRefInList);
3631                 if (nParam)
3632                     --sp;   // simulate pop
3633                 double fVal = GetDouble();
3634                 if (nParam)
3635                     sp = nSaveSP;
3636                 double nCellVal;
3637                 ScValueIterator aValIter(pDok, aRange, glSubTotal);
3638                 if (aValIter.GetFirst(nCellVal, nErr))
3639                 {
3640                     if (nCellVal == fVal)
3641                         bValid = sal_True;
3642                     else if ((!bDescending && nCellVal > fVal) ||
3643                             (bDescending && nCellVal < fVal) )
3644                         fCount++;
3645                     SetError(nErr);
3646                     while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
3647                     {
3648                         if (nCellVal == fVal)
3649                             bValid = sal_True;
3650                         else if ((!bDescending && nCellVal > fVal) ||
3651                                 (bDescending && nCellVal < fVal) )
3652                             fCount++;
3653                     }
3654                 }
3655                 SetError(nErr);
3656             }
3657         }
3658         break;
3659         case svMatrix :
3660         {
3661             ScMatrixRef pMat = PopMatrix();
3662             double fVal = GetDouble();
3663             if (pMat)
3664             {
3665                 SCSIZE nCount = pMat->GetElementCount();
3666                 if (pMat->IsNumeric())
3667                 {
3668                     for (SCSIZE i = 0; i < nCount; i++)
3669                     {
3670                         double x = pMat->GetDouble(i);
3671                         if (x == fVal)
3672                             bValid = sal_True;
3673                         else if ((!bDescending && x > fVal) ||
3674                                     (bDescending && x < fVal) )
3675                             fCount++;
3676                     }
3677                 }
3678                 else
3679                 {
3680                     for (SCSIZE i = 0; i < nCount; i++)
3681                         if (!pMat->IsString(i))
3682                         {
3683                             double x = pMat->GetDouble(i);
3684                             if (x == fVal)
3685                                 bValid = sal_True;
3686                             else if ((!bDescending && x > fVal) ||
3687                                         (bDescending && x < fVal) )
3688                                 fCount++;
3689                         }
3690                 }
3691             }
3692         }
3693         break;
3694         default : SetError(errIllegalParameter); break;
3695     }
3696     if (bValid)
3697         PushDouble(fCount);
3698     else
3699         PushNoValue();
3700 }
3701 
3702 void ScInterpreter::ScAveDev()
3703 {
3704     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScAveDev" );
3705     sal_uInt8 nParamCount = GetByte();
3706     if ( !MustHaveParamCountMin( nParamCount, 1 ) )
3707         return;
3708     sal_uInt16 SaveSP = sp;
3709     double nMiddle = 0.0;
3710     double rVal = 0.0;
3711     double rValCount = 0.0;
3712     ScAddress aAdr;
3713     ScRange aRange;
3714     short nParam = nParamCount;
3715     size_t nRefInList = 0;
3716     while (nParam-- > 0)
3717     {
3718         switch (GetStackType())
3719         {
3720             case formula::svDouble :
3721                 rVal += GetDouble();
3722                 rValCount++;
3723                 break;
3724             case svSingleRef :
3725             {
3726                 PopSingleRef( aAdr );
3727                 ScBaseCell* pCell = GetCell( aAdr );
3728                 if (HasCellValueData(pCell))
3729                 {
3730                     rVal += GetCellValue( aAdr, pCell );
3731                     rValCount++;
3732                 }
3733             }
3734             break;
3735             case formula::svDoubleRef :
3736             case svRefList :
3737             {
3738                 sal_uInt16 nErr = 0;
3739                 double nCellVal;
3740                 PopDoubleRef( aRange, nParam, nRefInList);
3741                 ScValueIterator aValIter(pDok, aRange);
3742                 if (aValIter.GetFirst(nCellVal, nErr))
3743                 {
3744                     rVal += nCellVal;
3745                     rValCount++;
3746                     SetError(nErr);
3747                     while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
3748                     {
3749                         rVal += nCellVal;
3750                         rValCount++;
3751                     }
3752                     SetError(nErr);
3753                 }
3754             }
3755             break;
3756             case svMatrix :
3757             {
3758                 ScMatrixRef pMat = PopMatrix();
3759                 if (pMat)
3760                 {
3761                     SCSIZE nCount = pMat->GetElementCount();
3762                     if (pMat->IsNumeric())
3763                     {
3764                         for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3765                         {
3766                             rVal += pMat->GetDouble(nElem);
3767                             rValCount++;
3768                         }
3769                     }
3770                     else
3771                     {
3772                         for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3773                             if (!pMat->IsString(nElem))
3774                             {
3775                                 rVal += pMat->GetDouble(nElem);
3776                                 rValCount++;
3777                             }
3778                     }
3779                 }
3780             }
3781             break;
3782             default :
3783                 SetError(errIllegalParameter);
3784             break;
3785         }
3786     }
3787     if (nGlobalError)
3788     {
3789         PushError( nGlobalError);
3790         return;
3791     }
3792     nMiddle = rVal / rValCount;
3793     sp = SaveSP;
3794     rVal = 0.0;
3795     nParam = nParamCount;
3796     nRefInList = 0;
3797     while (nParam-- > 0)
3798     {
3799         switch (GetStackType())
3800         {
3801             case formula::svDouble :
3802                 rVal += fabs(GetDouble() - nMiddle);
3803                 break;
3804             case svSingleRef :
3805             {
3806                 PopSingleRef( aAdr );
3807                 ScBaseCell* pCell = GetCell( aAdr );
3808                 if (HasCellValueData(pCell))
3809                     rVal += fabs(GetCellValue( aAdr, pCell ) - nMiddle);
3810             }
3811             break;
3812             case formula::svDoubleRef :
3813             case svRefList :
3814             {
3815                 sal_uInt16 nErr = 0;
3816                 double nCellVal;
3817                 PopDoubleRef( aRange, nParam, nRefInList);
3818                 ScValueIterator aValIter(pDok, aRange);
3819                 if (aValIter.GetFirst(nCellVal, nErr))
3820                 {
3821                     rVal += (fabs(nCellVal - nMiddle));
3822                     while (aValIter.GetNext(nCellVal, nErr))
3823                          rVal += fabs(nCellVal - nMiddle);
3824                 }
3825             }
3826             break;
3827             case svMatrix :
3828             {
3829                 ScMatrixRef pMat = PopMatrix();
3830                 if (pMat)
3831                 {
3832                     SCSIZE nCount = pMat->GetElementCount();
3833                     if (pMat->IsNumeric())
3834                     {
3835                         for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3836                         {
3837                             rVal += fabs(pMat->GetDouble(nElem) - nMiddle);
3838                         }
3839                     }
3840                     else
3841                     {
3842                         for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3843                         {
3844                             if (!pMat->IsString(nElem))
3845                                 rVal += fabs(pMat->GetDouble(nElem) - nMiddle);
3846                         }
3847                     }
3848                 }
3849             }
3850             break;
3851             default : SetError(errIllegalParameter); break;
3852         }
3853     }
3854     PushDouble(rVal / rValCount);
3855 }
3856 
3857 void ScInterpreter::ScDevSq()
3858 {
3859     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDevSq" );
3860     double nVal;
3861     double nValCount;
3862     GetStVarParams(nVal, nValCount);
3863     PushDouble(nVal);
3864 }
3865 
3866 void ScInterpreter::ScProbability()
3867 {
3868     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScProbability" );
3869     sal_uInt8 nParamCount = GetByte();
3870     if ( !MustHaveParamCount( nParamCount, 3, 4 ) )
3871         return;
3872     double fUp, fLo;
3873     fUp = GetDouble();
3874     if (nParamCount == 4)
3875         fLo = GetDouble();
3876     else
3877         fLo = fUp;
3878     if (fLo > fUp)
3879     {
3880         double fTemp = fLo;
3881         fLo = fUp;
3882         fUp = fTemp;
3883     }
3884     ScMatrixRef pMatP = GetMatrix();
3885     ScMatrixRef pMatW = GetMatrix();
3886     if (!pMatP || !pMatW)
3887         PushIllegalParameter();
3888     else
3889     {
3890         SCSIZE nC1, nC2;
3891         SCSIZE nR1, nR2;
3892         pMatP->GetDimensions(nC1, nR1);
3893         pMatW->GetDimensions(nC2, nR2);
3894         if (nC1 != nC2 || nR1 != nR2 || nC1 == 0 || nR1 == 0 ||
3895             nC2 == 0 || nR2 == 0)
3896             PushNA();
3897         else
3898         {
3899             double fSum = 0.0;
3900             double fRes = 0.0;
3901             sal_Bool bStop = sal_False;
3902             double fP, fW;
3903             SCSIZE nCount1 = nC1 * nR1;
3904             for ( SCSIZE i = 0; i < nCount1 && !bStop; i++ )
3905             {
3906                 if (pMatP->IsValue(i) && pMatW->IsValue(i))
3907                 {
3908                     fP = pMatP->GetDouble(i);
3909                     fW = pMatW->GetDouble(i);
3910                     if (fP < 0.0 || fP > 1.0)
3911                         bStop = sal_True;
3912                     else
3913                     {
3914                         fSum += fP;
3915                         if (fW >= fLo && fW <= fUp)
3916                             fRes += fP;
3917                     }
3918                 }
3919                 else
3920                     SetError( errIllegalArgument);
3921             }
3922             if (bStop || fabs(fSum -1.0) > 1.0E-7)
3923                 PushNoValue();
3924             else
3925                 PushDouble(fRes);
3926         }
3927     }
3928 }
3929 
3930 void ScInterpreter::ScCorrel()
3931 {
3932     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCorrel" );
3933     // This is identical to ScPearson()
3934     ScPearson();
3935 }
3936 
3937 void ScInterpreter::ScCovar()
3938 {
3939     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCovar" );
3940     CalculatePearsonCovar(sal_False,sal_False);
3941 }
3942 
3943 void ScInterpreter::ScPearson()
3944 {
3945     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScPearson" );
3946     CalculatePearsonCovar(sal_True,sal_False);
3947 }
3948 void ScInterpreter::CalculatePearsonCovar(sal_Bool _bPearson,sal_Bool _bStexy)
3949 {
3950     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CalculatePearsonCovar" );
3951     if ( !MustHaveParamCount( GetByte(), 2 ) )
3952         return;
3953     ScMatrixRef pMat1 = GetMatrix();
3954     ScMatrixRef pMat2 = GetMatrix();
3955     if (!pMat1 || !pMat2)
3956     {
3957         PushIllegalParameter();
3958         return;
3959     }
3960     SCSIZE nC1, nC2;
3961     SCSIZE nR1, nR2;
3962     pMat1->GetDimensions(nC1, nR1);
3963     pMat2->GetDimensions(nC2, nR2);
3964     if (nR1 != nR2 || nC1 != nC2)
3965     {
3966         PushIllegalArgument();
3967         return;
3968     }
3969     /* #i78250#
3970      * (sum((X-MeanX)(Y-MeanY)))/N equals (SumXY)/N-MeanX*MeanY mathematically,
3971      * but the latter produces wrong results if the absolute values are high,
3972      * for example above 10^8
3973      */
3974     double fCount           = 0.0;
3975     double fSumX            = 0.0;
3976     double fSumY            = 0.0;
3977     double fSumDeltaXDeltaY = 0.0; // sum of (ValX-MeanX)*(ValY-MeanY)
3978     double fSumSqrDeltaX    = 0.0; // sum of (ValX-MeanX)^2
3979     double fSumSqrDeltaY    = 0.0; // sum of (ValY-MeanY)^2
3980     for (SCSIZE i = 0; i < nC1; i++)
3981     {
3982         for (SCSIZE j = 0; j < nR1; j++)
3983         {
3984             if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
3985             {
3986                 double fValX = pMat1->GetDouble(i,j);
3987                 double fValY = pMat2->GetDouble(i,j);
3988                 fSumX += fValX;
3989                 fSumY += fValY;
3990                 fCount++;
3991             }
3992         }
3993     }
3994     if (fCount < (_bStexy ? 3.0 : 1.0)) // fCount==1 is handled by checking denominator later on
3995         PushNoValue();
3996     else
3997     {
3998         const double fMeanX = fSumX / fCount;
3999         const double fMeanY = fSumY / fCount;
4000         for (SCSIZE i = 0; i < nC1; i++)
4001         {
4002             for (SCSIZE j = 0; j < nR1; j++)
4003             {
4004                 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
4005                 {
4006                     const double fValX = pMat1->GetDouble(i,j);
4007                     const double fValY = pMat2->GetDouble(i,j);
4008                     fSumDeltaXDeltaY += (fValX - fMeanX) * (fValY - fMeanY);
4009                     if ( _bPearson )
4010                     {
4011                         fSumSqrDeltaX    += (fValX - fMeanX) * (fValX - fMeanX);
4012                         fSumSqrDeltaY    += (fValY - fMeanY) * (fValY - fMeanY);
4013                     }
4014                 }
4015             }
4016         } // for (SCSIZE i = 0; i < nC1; i++)
4017         if ( _bPearson )
4018         {
4019             if (fSumSqrDeltaX == 0.0 || ( !_bStexy && fSumSqrDeltaY == 0.0) )
4020                 PushError( errDivisionByZero);
4021             else if ( _bStexy )
4022                 PushDouble( sqrt( (fSumSqrDeltaY - fSumDeltaXDeltaY *
4023                             fSumDeltaXDeltaY / fSumSqrDeltaX) / (fCount-2)));
4024             else
4025                 PushDouble( fSumDeltaXDeltaY / sqrt( fSumSqrDeltaX * fSumSqrDeltaY));
4026         } // if ( _bPearson )
4027         else
4028         {
4029             PushDouble( fSumDeltaXDeltaY / fCount);
4030         }
4031     }
4032 }
4033 
4034 void ScInterpreter::ScRSQ()
4035 {
4036     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRSQ" );
4037     // Same as ScPearson()*ScPearson()
4038     ScPearson();
4039     if (!nGlobalError)
4040     {
4041         switch (GetStackType())
4042         {
4043             case formula::svDouble:
4044                 {
4045                     double fVal = PopDouble();
4046                     PushDouble( fVal * fVal);
4047                 }
4048                 break;
4049             default:
4050                 PopError();
4051                 PushNoValue();
4052         }
4053     }
4054 }
4055 
4056 void ScInterpreter::ScSTEXY()
4057 {
4058     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSTEXY" );
4059     CalculatePearsonCovar(sal_True,sal_True);
4060 }
4061 void ScInterpreter::CalculateSlopeIntercept(sal_Bool bSlope)
4062 {
4063     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CalculateSlopeIntercept" );
4064     if ( !MustHaveParamCount( GetByte(), 2 ) )
4065         return;
4066     ScMatrixRef pMat1 = GetMatrix();
4067     ScMatrixRef pMat2 = GetMatrix();
4068     if (!pMat1 || !pMat2)
4069     {
4070         PushIllegalParameter();
4071         return;
4072     }
4073     SCSIZE nC1, nC2;
4074     SCSIZE nR1, nR2;
4075     pMat1->GetDimensions(nC1, nR1);
4076     pMat2->GetDimensions(nC2, nR2);
4077     if (nR1 != nR2 || nC1 != nC2)
4078     {
4079         PushIllegalArgument();
4080         return;
4081     }
4082     // #i78250# numerical stability improved
4083     double fCount           = 0.0;
4084     double fSumX            = 0.0;
4085     double fSumY            = 0.0;
4086     double fSumDeltaXDeltaY = 0.0; // sum of (ValX-MeanX)*(ValY-MeanY)
4087     double fSumSqrDeltaX    = 0.0; // sum of (ValX-MeanX)^2
4088     for (SCSIZE i = 0; i < nC1; i++)
4089     {
4090         for (SCSIZE j = 0; j < nR1; j++)
4091         {
4092             if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
4093             {
4094                 double fValX = pMat1->GetDouble(i,j);
4095                 double fValY = pMat2->GetDouble(i,j);
4096                 fSumX += fValX;
4097                 fSumY += fValY;
4098                 fCount++;
4099             }
4100         }
4101     }
4102     if (fCount < 1.0)
4103         PushNoValue();
4104     else
4105     {
4106         double fMeanX = fSumX / fCount;
4107         double fMeanY = fSumY / fCount;
4108         for (SCSIZE i = 0; i < nC1; i++)
4109         {
4110             for (SCSIZE j = 0; j < nR1; j++)
4111             {
4112                 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
4113                 {
4114                     double fValX = pMat1->GetDouble(i,j);
4115                     double fValY = pMat2->GetDouble(i,j);
4116                     fSumDeltaXDeltaY += (fValX - fMeanX) * (fValY - fMeanY);
4117                     fSumSqrDeltaX    += (fValX - fMeanX) * (fValX - fMeanX);
4118                 }
4119             }
4120         }
4121         if (fSumSqrDeltaX == 0.0)
4122             PushError( errDivisionByZero);
4123         else
4124         {
4125             if ( bSlope )
4126                 PushDouble( fSumDeltaXDeltaY / fSumSqrDeltaX);
4127             else
4128                 PushDouble( fMeanY - fSumDeltaXDeltaY / fSumSqrDeltaX * fMeanX);
4129         }
4130     }
4131 }
4132 
4133 void ScInterpreter::ScSlope()
4134 {
4135     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSlope" );
4136     CalculateSlopeIntercept(sal_True);
4137 }
4138 
4139 void ScInterpreter::ScIntercept()
4140 {
4141     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIntercept" );
4142     CalculateSlopeIntercept(sal_False);
4143 }
4144 
4145 void ScInterpreter::ScForecast()
4146 {
4147     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScForecast" );
4148     if ( !MustHaveParamCount( GetByte(), 3 ) )
4149         return;
4150     ScMatrixRef pMat1 = GetMatrix();
4151     ScMatrixRef pMat2 = GetMatrix();
4152     if (!pMat1 || !pMat2)
4153     {
4154         PushIllegalParameter();
4155         return;
4156     }
4157     SCSIZE nC1, nC2;
4158     SCSIZE nR1, nR2;
4159     pMat1->GetDimensions(nC1, nR1);
4160     pMat2->GetDimensions(nC2, nR2);
4161     if (nR1 != nR2 || nC1 != nC2)
4162     {
4163         PushIllegalArgument();
4164         return;
4165     }
4166     double fVal = GetDouble();
4167     // #i78250# numerical stability improved
4168     double fCount           = 0.0;
4169     double fSumX            = 0.0;
4170     double fSumY            = 0.0;
4171     double fSumDeltaXDeltaY = 0.0; // sum of (ValX-MeanX)*(ValY-MeanY)
4172     double fSumSqrDeltaX    = 0.0; // sum of (ValX-MeanX)^2
4173     for (SCSIZE i = 0; i < nC1; i++)
4174     {
4175         for (SCSIZE j = 0; j < nR1; j++)
4176         {
4177             if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
4178             {
4179                 double fValX = pMat1->GetDouble(i,j);
4180                 double fValY = pMat2->GetDouble(i,j);
4181                 fSumX += fValX;
4182                 fSumY += fValY;
4183                 fCount++;
4184             }
4185         }
4186     }
4187     if (fCount < 1.0)
4188         PushNoValue();
4189     else
4190     {
4191         double fMeanX = fSumX / fCount;
4192         double fMeanY = fSumY / fCount;
4193         for (SCSIZE i = 0; i < nC1; i++)
4194         {
4195             for (SCSIZE j = 0; j < nR1; j++)
4196             {
4197                 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
4198                 {
4199                     double fValX = pMat1->GetDouble(i,j);
4200                     double fValY = pMat2->GetDouble(i,j);
4201                     fSumDeltaXDeltaY += (fValX - fMeanX) * (fValY - fMeanY);
4202                     fSumSqrDeltaX    += (fValX - fMeanX) * (fValX - fMeanX);
4203                 }
4204             }
4205         }
4206         if (fSumSqrDeltaX == 0.0)
4207             PushError( errDivisionByZero);
4208         else
4209             PushDouble( fMeanY + fSumDeltaXDeltaY / fSumSqrDeltaX * (fVal - fMeanX));
4210     }
4211 }
4212 
4213