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