xref: /trunk/main/sc/source/core/tool/interpr3.cxx (revision 2b70322d0a1dcef079c5cf96a5496abfc581f5e1)
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     double fF, fF1, fF2;
2588     if (fS1 > fS2)
2589     {
2590         fF = fS1/fS2;
2591         fF1 = fCount1-1.0;
2592         fF2 = fCount2-1.0;
2593     }
2594     else
2595     {
2596         fF = fS2/fS1;
2597         fF1 = fCount2-1.0;
2598         fF2 = fCount1-1.0;
2599     }
2600     PushDouble(2.0*GetFDist(fF, fF1, fF2));
2601 /*
2602     double Z = (pow(fF,1.0/3.0)*(1.0-2.0/(9.0*fF2)) - (1.0-2.0/(9.0*fF1))) /
2603                sqrt(2.0/(9.0*fF1) + pow(fF,2.0/3.0)*2.0/(9.0*fF2));
2604     PushDouble(1.0-2.0*gauss(Z));
2605 */
2606 }
2607 
ScChiTest()2608 void ScInterpreter::ScChiTest()
2609 {
2610     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScChiTest" );
2611     if ( !MustHaveParamCount( GetByte(), 2 ) )
2612         return;
2613     ScMatrixRef pMat2 = GetMatrix();
2614     ScMatrixRef pMat1 = GetMatrix();
2615     if (!pMat1 || !pMat2)
2616     {
2617         PushIllegalParameter();
2618         return;
2619     }
2620     SCSIZE nC1, nC2;
2621     SCSIZE nR1, nR2;
2622     pMat1->GetDimensions(nC1, nR1);
2623     pMat2->GetDimensions(nC2, nR2);
2624     if (nR1 != nR2 || nC1 != nC2)
2625     {
2626         PushIllegalArgument();
2627         return;
2628     }
2629     double fChi = 0.0;
2630     for (SCSIZE i = 0; i < nC1; i++)
2631     {
2632         for (SCSIZE j = 0; j < nR1; j++)
2633         {
2634             if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
2635             {
2636                 double fValX = pMat1->GetDouble(i,j);
2637                 double fValE = pMat2->GetDouble(i,j);
2638                 fChi += (fValX - fValE) * (fValX - fValE) / fValE;
2639             }
2640             else
2641             {
2642                 PushIllegalArgument();
2643                 return;
2644             }
2645         }
2646     }
2647     double fDF;
2648     if (nC1 == 1 || nR1 == 1)
2649     {
2650         fDF = (double)(nC1*nR1 - 1);
2651         if (fDF == 0.0)
2652         {
2653             PushNoValue();
2654             return;
2655         }
2656     }
2657     else
2658         fDF = (double)(nC1-1)*(double)(nR1-1);
2659     PushDouble(GetChiDist(fChi, fDF));
2660 /*
2661     double fX, fS, fT, fG;
2662     fX = 1.0;
2663     for (double fi = fDF; fi >= 2.0; fi -= 2.0)
2664         fX *= fChi/fi;
2665     fX *= exp(-fChi/2.0);
2666     if (fmod(fDF, 2.0) != 0.0)
2667         fX *= sqrt(2.0*fChi/F_PI);
2668     fS = 1.0;
2669     fT = 1.0;
2670     fG = fDF;
2671     while (fT >= 1.0E-7)
2672     {
2673         fG += 2.0;
2674         fT *= fChi/fG;
2675         fS += fT;
2676     }
2677     PushDouble(1.0 - fX*fS);
2678 */
2679 }
2680 
ScKurt()2681 void ScInterpreter::ScKurt()
2682 {
2683     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScKurt" );
2684     double fSum,fCount,vSum;
2685     std::vector<double> values;
2686     if ( !CalculateSkew(fSum,fCount,vSum,values) )
2687         return;
2688 
2689     if (fCount == 0.0)
2690     {
2691         PushError( errDivisionByZero);
2692         return;
2693     }
2694 
2695     double fMean = fSum / fCount;
2696 
2697     for (size_t i = 0; i < values.size(); i++)
2698         vSum += (values[i] - fMean) * (values[i] - fMean);
2699 
2700     double fStdDev = sqrt(vSum / (fCount - 1.0));
2701     double dx = 0.0;
2702     double xpower4 = 0.0;
2703 
2704     if (fStdDev == 0.0)
2705     {
2706         PushError( errDivisionByZero);
2707         return;
2708     }
2709 
2710     for (size_t i = 0; i < values.size(); i++)
2711     {
2712         dx = (values[i] - fMean) / fStdDev;
2713         xpower4 = xpower4 + (dx * dx * dx * dx);
2714     }
2715 
2716     double k_d = (fCount - 2.0) * (fCount - 3.0);
2717     double k_l = fCount * (fCount + 1.0) / ((fCount - 1.0) * k_d);
2718     double k_t = 3.0 * (fCount - 1.0) * (fCount - 1.0) / k_d;
2719 
2720     PushDouble(xpower4 * k_l - k_t);
2721 }
2722 
ScHarMean()2723 void ScInterpreter::ScHarMean()
2724 {
2725     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScHarMean" );
2726     short nParamCount = GetByte();
2727     double nVal = 0.0;
2728     double nValCount = 0.0;
2729     ScAddress aAdr;
2730     ScRange aRange;
2731     size_t nRefInList = 0;
2732     while ((nGlobalError == 0) && (nParamCount-- > 0))
2733     {
2734         switch (GetStackType())
2735         {
2736             case formula::svDouble    :
2737             {
2738                 double x = GetDouble();
2739                 if (x > 0.0)
2740                 {
2741                     nVal += 1.0/x;
2742                     nValCount++;
2743                 }
2744                 else
2745                     SetError( errIllegalArgument);
2746                 break;
2747             }
2748             case svSingleRef :
2749             {
2750                 PopSingleRef( aAdr );
2751                 ScBaseCell* pCell = GetCell( aAdr );
2752                 if (HasCellValueData(pCell))
2753                 {
2754                     double x = GetCellValue( aAdr, pCell );
2755                     if (x > 0.0)
2756                     {
2757                         nVal += 1.0/x;
2758                         nValCount++;
2759                     }
2760                     else
2761                         SetError( errIllegalArgument);
2762                 }
2763                 break;
2764             }
2765             case formula::svDoubleRef :
2766             case svRefList :
2767             {
2768                 sal_uInt16 nErr = 0;
2769                 PopDoubleRef( aRange, nParamCount, nRefInList);
2770                 double nCellVal;
2771                 ScValueIterator aValIter(pDok, aRange, glSubTotal);
2772                 if (aValIter.GetFirst(nCellVal, nErr))
2773                 {
2774                     if (nCellVal > 0.0)
2775                     {
2776                         nVal += 1.0/nCellVal;
2777                         nValCount++;
2778                     }
2779                     else
2780                         SetError( errIllegalArgument);
2781                     SetError(nErr);
2782                     while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
2783                     {
2784                         if (nCellVal > 0.0)
2785                         {
2786                             nVal += 1.0/nCellVal;
2787                             nValCount++;
2788                         }
2789                         else
2790                             SetError( errIllegalArgument);
2791                     }
2792                     SetError(nErr);
2793                 }
2794             }
2795             break;
2796             case svMatrix :
2797             {
2798                 ScMatrixRef pMat = PopMatrix();
2799                 if (pMat)
2800                 {
2801                     SCSIZE nCount = pMat->GetElementCount();
2802                     if (pMat->IsNumeric())
2803                     {
2804                         for (SCSIZE nElem = 0; nElem < nCount; nElem++)
2805                         {
2806                             double x = pMat->GetDouble(nElem);
2807                             if (x > 0.0)
2808                             {
2809                                 nVal += 1.0/x;
2810                                 nValCount++;
2811                             }
2812                             else
2813                                 SetError( errIllegalArgument);
2814                         }
2815                     }
2816                     else
2817                     {
2818                         for (SCSIZE nElem = 0; nElem < nCount; nElem++)
2819                             if (!pMat->IsString(nElem))
2820                             {
2821                                 double x = pMat->GetDouble(nElem);
2822                                 if (x > 0.0)
2823                                 {
2824                                     nVal += 1.0/x;
2825                                     nValCount++;
2826                                 }
2827                                 else
2828                                     SetError( errIllegalArgument);
2829                             }
2830                     }
2831                 }
2832             }
2833             break;
2834             default : SetError(errIllegalParameter); break;
2835         }
2836     }
2837     if (nGlobalError == 0)
2838         PushDouble((double)nValCount/nVal);
2839     else
2840         PushError( nGlobalError);
2841 }
2842 
ScGeoMean()2843 void ScInterpreter::ScGeoMean()
2844 {
2845     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGeoMean" );
2846     short nParamCount = GetByte();
2847     double nVal = 0.0;
2848     double nValCount = 0.0;
2849     ScAddress aAdr;
2850     ScRange aRange;
2851 
2852     size_t nRefInList = 0;
2853     while ((nGlobalError == 0) && (nParamCount-- > 0))
2854     {
2855         switch (GetStackType())
2856         {
2857             case formula::svDouble    :
2858             {
2859                 double x = GetDouble();
2860                 if (x > 0.0)
2861                 {
2862                     nVal += log(x);
2863                     nValCount++;
2864                 }
2865                 else
2866                     SetError( errIllegalArgument);
2867                 break;
2868             }
2869             case svSingleRef :
2870             {
2871                 PopSingleRef( aAdr );
2872                 ScBaseCell* pCell = GetCell( aAdr );
2873                 if (HasCellValueData(pCell))
2874                 {
2875                     double x = GetCellValue( aAdr, pCell );
2876                     if (x > 0.0)
2877                     {
2878                         nVal += log(x);
2879                         nValCount++;
2880                     }
2881                     else
2882                         SetError( errIllegalArgument);
2883                 }
2884                 break;
2885             }
2886             case formula::svDoubleRef :
2887             case svRefList :
2888             {
2889                 sal_uInt16 nErr = 0;
2890                 PopDoubleRef( aRange, nParamCount, nRefInList);
2891                 double nCellVal;
2892                 ScValueIterator aValIter(pDok, aRange, glSubTotal);
2893                 if (aValIter.GetFirst(nCellVal, nErr))
2894                 {
2895                     if (nCellVal > 0.0)
2896                     {
2897                         nVal += log(nCellVal);
2898                         nValCount++;
2899                     }
2900                     else
2901                         SetError( errIllegalArgument);
2902                     SetError(nErr);
2903                     while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
2904                     {
2905                         if (nCellVal > 0.0)
2906                         {
2907                             nVal += log(nCellVal);
2908                             nValCount++;
2909                         }
2910                         else
2911                             SetError( errIllegalArgument);
2912                     }
2913                     SetError(nErr);
2914                 }
2915             }
2916             break;
2917             case svMatrix :
2918             {
2919                 ScMatrixRef pMat = PopMatrix();
2920                 if (pMat)
2921                 {
2922                     SCSIZE nCount = pMat->GetElementCount();
2923                     if (pMat->IsNumeric())
2924                     {
2925                         for (SCSIZE ui = 0; ui < nCount; ui++)
2926                         {
2927                             double x = pMat->GetDouble(ui);
2928                             if (x > 0.0)
2929                             {
2930                                 nVal += log(x);
2931                                 nValCount++;
2932                             }
2933                             else
2934                                 SetError( errIllegalArgument);
2935                         }
2936                     }
2937                     else
2938                     {
2939                         for (SCSIZE ui = 0; ui < nCount; ui++)
2940                             if (!pMat->IsString(ui))
2941                             {
2942                                 double x = pMat->GetDouble(ui);
2943                                 if (x > 0.0)
2944                                 {
2945                                     nVal += log(x);
2946                                     nValCount++;
2947                                 }
2948                                 else
2949                                     SetError( errIllegalArgument);
2950                             }
2951                     }
2952                 }
2953             }
2954             break;
2955             default : SetError(errIllegalParameter); break;
2956         }
2957     }
2958     if (nGlobalError == 0)
2959         PushDouble(exp(nVal / nValCount));
2960     else
2961         PushError( nGlobalError);
2962 }
2963 
ScStandard()2964 void ScInterpreter::ScStandard()
2965 {
2966     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScStandard" );
2967     if ( MustHaveParamCount( GetByte(), 3 ) )
2968     {
2969         double sigma = GetDouble();
2970         double mue   = GetDouble();
2971         double x     = GetDouble();
2972         if (sigma < 0.0)
2973             PushError( errIllegalArgument);
2974         else if (sigma == 0.0)
2975             PushError( errDivisionByZero);
2976         else
2977             PushDouble((x-mue)/sigma);
2978     }
2979 }
CalculateSkew(double & fSum,double & fCount,double & vSum,std::vector<double> & values)2980 bool ScInterpreter::CalculateSkew(double& fSum,double& fCount,double& vSum,std::vector<double>& values)
2981 {
2982     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CalculateSkew" );
2983     short nParamCount = GetByte();
2984     if ( !MustHaveParamCountMin( nParamCount, 1 )  )
2985         return false;
2986 
2987     fSum   = 0.0;
2988     fCount = 0.0;
2989     vSum   = 0.0;
2990     double fVal = 0.0;
2991     ScAddress aAdr;
2992     ScRange aRange;
2993     size_t nRefInList = 0;
2994     while (nParamCount-- > 0)
2995     {
2996         switch (GetStackType())
2997         {
2998             case formula::svDouble :
2999             {
3000                 fVal = GetDouble();
3001                 fSum += fVal;
3002                 values.push_back(fVal);
3003                 fCount++;
3004             }
3005                 break;
3006             case svSingleRef :
3007             {
3008                 PopSingleRef( aAdr );
3009                 ScBaseCell* pCell = GetCell( aAdr );
3010                 if (HasCellValueData(pCell))
3011                 {
3012                     fVal = GetCellValue( aAdr, pCell );
3013                     fSum += fVal;
3014                     values.push_back(fVal);
3015                     fCount++;
3016                 }
3017             }
3018             break;
3019             case formula::svDoubleRef :
3020             case svRefList :
3021             {
3022                 PopDoubleRef( aRange, nParamCount, nRefInList);
3023                 sal_uInt16 nErr = 0;
3024                 ScValueIterator aValIter(pDok, aRange);
3025                 if (aValIter.GetFirst(fVal, nErr))
3026                 {
3027                     fSum += fVal;
3028                     values.push_back(fVal);
3029                     fCount++;
3030                     SetError(nErr);
3031                     while ((nErr == 0) && aValIter.GetNext(fVal, nErr))
3032                     {
3033                         fSum += fVal;
3034                         values.push_back(fVal);
3035                         fCount++;
3036                     }
3037                     SetError(nErr);
3038                 }
3039             }
3040             break;
3041             case svMatrix :
3042             {
3043                 ScMatrixRef pMat = PopMatrix();
3044                 if (pMat)
3045                 {
3046                     SCSIZE nCount = pMat->GetElementCount();
3047                     if (pMat->IsNumeric())
3048                     {
3049                         for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3050                         {
3051                             fVal = pMat->GetDouble(nElem);
3052                             fSum += fVal;
3053                             values.push_back(fVal);
3054                             fCount++;
3055                         }
3056                     }
3057                     else
3058                     {
3059                         for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3060                             if (!pMat->IsString(nElem))
3061                             {
3062                                 fVal = pMat->GetDouble(nElem);
3063                                 fSum += fVal;
3064                                 values.push_back(fVal);
3065                                 fCount++;
3066                             }
3067                     }
3068                 }
3069             }
3070             break;
3071             default :
3072                 SetError(errIllegalParameter);
3073             break;
3074         }
3075     }
3076 
3077     if (nGlobalError)
3078     {
3079         PushError( nGlobalError);
3080         return false;
3081     } // if (nGlobalError)
3082     return true;
3083 }
3084 
ScSkew()3085 void ScInterpreter::ScSkew()
3086 {
3087     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSkew" );
3088     double fSum,fCount,vSum;
3089     std::vector<double> values;
3090     if ( !CalculateSkew(fSum,fCount,vSum,values) )
3091         return;
3092 
3093     double fMean = fSum / fCount;
3094 
3095     for (size_t i = 0; i < values.size(); i++)
3096         vSum += (values[i] - fMean) * (values[i] - fMean);
3097 
3098     double fStdDev = sqrt(vSum / (fCount - 1.0));
3099     double dx = 0.0;
3100     double xcube = 0.0;
3101 
3102     if (fStdDev == 0)
3103     {
3104         PushIllegalArgument();
3105         return;
3106     }
3107 
3108     for (size_t i = 0; i < values.size(); i++)
3109     {
3110         dx = (values[i] - fMean) / fStdDev;
3111         xcube = xcube + (dx * dx * dx);
3112     }
3113 
3114     PushDouble(((xcube * fCount) / (fCount - 1.0)) / (fCount - 2.0));
3115 }
3116 
GetMedian(vector<double> & rArray)3117 double ScInterpreter::GetMedian( vector<double> & rArray )
3118 {
3119     size_t nSize = rArray.size();
3120     if (rArray.empty() || nSize == 0 || nGlobalError)
3121     {
3122         SetError( errNoValue);
3123         return 0.0;
3124     }
3125 
3126     // Upper median.
3127     size_t nMid = nSize / 2;
3128     vector<double>::iterator iMid = rArray.begin() + nMid;
3129     ::std::nth_element( rArray.begin(), iMid, rArray.end());
3130     if (nSize & 1)
3131         return *iMid;   // Lower and upper median are equal.
3132     else
3133     {
3134         double fUp = *iMid;
3135         // Lower median.
3136         iMid = rArray.begin() + nMid - 1;
3137         ::std::nth_element( rArray.begin(), iMid, rArray.end());
3138         return (fUp + *iMid) / 2;
3139     }
3140 }
3141 
ScMedian()3142 void ScInterpreter::ScMedian()
3143 {
3144     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMedian" );
3145     sal_uInt8 nParamCount = GetByte();
3146     if ( !MustHaveParamCountMin( nParamCount, 1 )  )
3147         return;
3148     vector<double> aArray;
3149     GetNumberSequenceArray( nParamCount, aArray);
3150     PushDouble( GetMedian( aArray));
3151 }
3152 
GetPercentile(vector<double> & rArray,double fPercentile)3153 double ScInterpreter::GetPercentile( vector<double> & rArray, double fPercentile )
3154 {
3155     size_t nSize = rArray.size();
3156     if (rArray.empty() || nSize == 0 || nGlobalError)
3157     {
3158         SetError( errNoValue);
3159         return 0.0;
3160     }
3161 
3162     if (nSize == 1)
3163         return rArray[0];
3164     else
3165     {
3166         size_t nIndex = (size_t)::rtl::math::approxFloor( fPercentile * (nSize-1));
3167         double fDiff = fPercentile * (nSize-1) - ::rtl::math::approxFloor( fPercentile * (nSize-1));
3168         DBG_ASSERT(nIndex < nSize, "GetPercentile: wrong index(1)");
3169         vector<double>::iterator iter = rArray.begin() + nIndex;
3170         ::std::nth_element( rArray.begin(), iter, rArray.end());
3171         if (fDiff == 0.0)
3172             return *iter;
3173         else
3174         {
3175             DBG_ASSERT(nIndex < nSize-1, "GetPercentile: wrong index(2)");
3176             double fVal = *iter;
3177             iter = rArray.begin() + nIndex+1;
3178             ::std::nth_element( rArray.begin(), iter, rArray.end());
3179             return fVal + fDiff * (*iter - fVal);
3180         }
3181     }
3182 }
3183 
ScPercentile()3184 void ScInterpreter::ScPercentile()
3185 {
3186     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScPercentile" );
3187     if ( !MustHaveParamCount( GetByte(), 2 ) )
3188         return;
3189     double alpha = GetDouble();
3190     if (alpha < 0.0 || alpha > 1.0)
3191     {
3192         PushIllegalArgument();
3193         return;
3194     }
3195     vector<double> aArray;
3196     GetNumberSequenceArray( 1, aArray);
3197     PushDouble( GetPercentile( aArray, alpha));
3198 }
3199 
ScQuartile()3200 void ScInterpreter::ScQuartile()
3201 {
3202     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScQuartile" );
3203     if ( !MustHaveParamCount( GetByte(), 2 ) )
3204         return;
3205     double fFlag = ::rtl::math::approxFloor(GetDouble());
3206     if (fFlag < 0.0 || fFlag > 4.0)
3207     {
3208         PushIllegalArgument();
3209         return;
3210     }
3211     vector<double> aArray;
3212     GetNumberSequenceArray( 1, aArray);
3213     PushDouble( fFlag == 2.0 ? GetMedian( aArray) : GetPercentile( aArray, 0.25 * fFlag));
3214 }
3215 
ScModalValue()3216 void ScInterpreter::ScModalValue()
3217 {
3218     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScModalValue" );
3219     sal_uInt8 nParamCount = GetByte();
3220     if ( !MustHaveParamCountMin( nParamCount, 1 ) )
3221         return;
3222     vector<double> aSortArray;
3223     GetSortArray(nParamCount, aSortArray);
3224     SCSIZE nSize = aSortArray.size();
3225     if (aSortArray.empty() || nSize == 0 || nGlobalError)
3226         PushNoValue();
3227     else
3228     {
3229         SCSIZE nMaxIndex = 0, nMax = 1, nCount = 1;
3230         double nOldVal = aSortArray[0];
3231         SCSIZE i;
3232 
3233         for ( i = 1; i < nSize; i++)
3234         {
3235             if (aSortArray[i] == nOldVal)
3236                 nCount++;
3237             else
3238             {
3239                 nOldVal = aSortArray[i];
3240                 if (nCount > nMax)
3241                 {
3242                     nMax = nCount;
3243                     nMaxIndex = i-1;
3244                 }
3245                 nCount = 1;
3246             }
3247         }
3248         if (nCount > nMax)
3249         {
3250             nMax = nCount;
3251             nMaxIndex = i-1;
3252         }
3253         if (nMax == 1 && nCount == 1)
3254             PushNoValue();
3255         else if (nMax == 1)
3256             PushDouble(nOldVal);
3257         else
3258             PushDouble(aSortArray[nMaxIndex]);
3259     }
3260 }
3261 
CalculateSmallLarge(sal_Bool bSmall)3262 void ScInterpreter::CalculateSmallLarge(sal_Bool bSmall)
3263 {
3264     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CalculateSmallLarge" );
3265     if ( !MustHaveParamCount( GetByte(), 2 )  )
3266         return;
3267     double f = ::rtl::math::approxFloor(GetDouble());
3268     if (f < 1.0)
3269     {
3270         PushIllegalArgument();
3271         return;
3272     }
3273     SCSIZE k = static_cast<SCSIZE>(f);
3274     vector<double> aSortArray;
3275     /* TODO: using nth_element() is best for one single value, but LARGE/SMALL
3276      * actually are defined to return an array of values if an array of
3277      * positions was passed, in which case, depending on the number of values,
3278      * we may or will need a real sorted array again, see #i32345. */
3279     //GetSortArray(1, aSortArray);
3280     GetNumberSequenceArray(1, aSortArray);
3281     SCSIZE nSize = aSortArray.size();
3282     if (aSortArray.empty() || nSize == 0 || nGlobalError || nSize < k)
3283         PushNoValue();
3284     else
3285     {
3286         // TODO: the sorted case for array: PushDouble( aSortArray[ bSmall ? k-1 : nSize-k ] );
3287         vector<double>::iterator iPos = aSortArray.begin() + (bSmall ? k-1 : nSize-k);
3288         ::std::nth_element( aSortArray.begin(), iPos, aSortArray.end());
3289         PushDouble( *iPos);
3290     }
3291 }
3292 
ScLarge()3293 void ScInterpreter::ScLarge()
3294 {
3295     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLarge" );
3296     CalculateSmallLarge(sal_False);
3297 }
3298 
ScSmall()3299 void ScInterpreter::ScSmall()
3300 {
3301     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSmall" );
3302     CalculateSmallLarge(sal_True);
3303 }
3304 
ScPercentrank()3305 void ScInterpreter::ScPercentrank()
3306 {
3307     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScPercentrank" );
3308     sal_uInt8 nParamCount = GetByte();
3309     if ( !MustHaveParamCount( nParamCount, 2 ) )
3310         return;
3311 #if 0
3312 /*                          wird nicht unterstuetzt
3313     double fPrec;
3314     if (nParamCount == 3)
3315     {
3316         fPrec = ::rtl::math::approxFloor(GetDouble());
3317         if (fPrec < 1.0)
3318         {
3319             PushIllegalArgument();
3320             return;
3321         }
3322     }
3323     else
3324         fPrec = 3.0;
3325 */
3326 #endif
3327     double fNum = GetDouble();
3328     vector<double> aSortArray;
3329     GetSortArray(1, aSortArray);
3330     SCSIZE nSize = aSortArray.size();
3331     if (aSortArray.empty() || nSize == 0 || nGlobalError)
3332         PushNoValue();
3333     else
3334     {
3335         if (fNum < aSortArray[0] || fNum > aSortArray[nSize-1])
3336             PushNoValue();
3337         else if ( nSize == 1 )
3338             PushDouble(1.0);            // fNum == pSortArray[0], see test above
3339         else
3340         {
3341             double fRes;
3342             SCSIZE nOldCount = 0;
3343             double fOldVal = aSortArray[0];
3344             SCSIZE i;
3345             for (i = 1; i < nSize && aSortArray[i] < fNum; i++)
3346             {
3347                 if (aSortArray[i] != fOldVal)
3348                 {
3349                     nOldCount = i;
3350                     fOldVal = aSortArray[i];
3351                 }
3352             }
3353             if (aSortArray[i] != fOldVal)
3354                 nOldCount = i;
3355             if (fNum == aSortArray[i])
3356                 fRes = (double)nOldCount/(double)(nSize-1);
3357             else
3358             {
3359                 //  #75312# nOldCount is the count of smaller entries
3360                 //  fNum is between pSortArray[nOldCount-1] and pSortArray[nOldCount]
3361                 //  use linear interpolation to find a position between the entries
3362 
3363                 if ( nOldCount == 0 )
3364                 {
3365                     DBG_ERROR("should not happen");
3366                     fRes = 0.0;
3367                 }
3368                 else
3369                 {
3370                     double fFract = ( fNum - aSortArray[nOldCount-1] ) /
3371                         ( aSortArray[nOldCount] - aSortArray[nOldCount-1] );
3372                     fRes = ( (double)(nOldCount-1)+fFract )/(double)(nSize-1);
3373                 }
3374             }
3375             PushDouble(fRes);
3376         }
3377     }
3378 }
3379 
ScTrimMean()3380 void ScInterpreter::ScTrimMean()
3381 {
3382     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTrimMean" );
3383     if ( !MustHaveParamCount( GetByte(), 2 ) )
3384         return;
3385     double alpha = GetDouble();
3386     if (alpha < 0.0 || alpha >= 1.0)
3387     {
3388         PushIllegalArgument();
3389         return;
3390     }
3391     vector<double> aSortArray;
3392     GetSortArray(1, aSortArray);
3393     SCSIZE nSize = aSortArray.size();
3394     if (aSortArray.empty() || nSize == 0 || nGlobalError)
3395         PushNoValue();
3396     else
3397     {
3398         sal_uLong nIndex = (sal_uLong) ::rtl::math::approxFloor(alpha*(double)nSize);
3399         if (nIndex % 2 != 0)
3400             nIndex--;
3401         nIndex /= 2;
3402         DBG_ASSERT(nIndex < nSize, "ScTrimMean: falscher Index");
3403         double fSum = 0.0;
3404         for (SCSIZE i = nIndex; i < nSize-nIndex; i++)
3405             fSum += aSortArray[i];
3406         PushDouble(fSum/(double)(nSize-2*nIndex));
3407     }
3408 }
3409 
GetNumberSequenceArray(sal_uInt8 nParamCount,vector<double> & rArray)3410 void ScInterpreter::GetNumberSequenceArray( sal_uInt8 nParamCount, vector<double>& rArray )
3411 {
3412     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetSortArray" );
3413     ScAddress aAdr;
3414     ScRange aRange;
3415     short nParam = nParamCount;
3416     size_t nRefInList = 0;
3417     while (nParam-- > 0)
3418     {
3419         switch (GetStackType())
3420         {
3421             case formula::svDouble :
3422                 rArray.push_back( PopDouble());
3423             break;
3424             case svSingleRef :
3425             {
3426                 PopSingleRef( aAdr );
3427                 ScBaseCell* pCell = GetCell( aAdr );
3428                 if (HasCellValueData(pCell))
3429                     rArray.push_back( GetCellValue( aAdr, pCell));
3430             }
3431             break;
3432             case formula::svDoubleRef :
3433             case svRefList :
3434             {
3435                 PopDoubleRef( aRange, nParam, nRefInList);
3436                 if (nGlobalError)
3437                     break;
3438 
3439                 aRange.Justify();
3440                 SCSIZE nCellCount = aRange.aEnd.Col() - aRange.aStart.Col() + 1;
3441                 nCellCount *= aRange.aEnd.Row() - aRange.aStart.Row() + 1;
3442                 rArray.reserve( rArray.size() + nCellCount);
3443 
3444                 sal_uInt16 nErr = 0;
3445                 double fCellVal;
3446                 ScValueIterator aValIter(pDok, aRange);
3447                 if (aValIter.GetFirst( fCellVal, nErr))
3448                 {
3449                     rArray.push_back( fCellVal);
3450                     SetError(nErr);
3451                     while ((nErr == 0) && aValIter.GetNext( fCellVal, nErr))
3452                         rArray.push_back( fCellVal);
3453                     SetError(nErr);
3454                 }
3455             }
3456             break;
3457             case svMatrix :
3458             {
3459                 ScMatrixRef pMat = PopMatrix();
3460                 if (!pMat)
3461                     break;
3462 
3463                 SCSIZE nCount = pMat->GetElementCount();
3464                 rArray.reserve( rArray.size() + nCount);
3465                 if (pMat->IsNumeric())
3466                 {
3467                     for (SCSIZE i = 0; i < nCount; ++i)
3468                         rArray.push_back( pMat->GetDouble(i));
3469                 }
3470                 else
3471                 {
3472                     for (SCSIZE i = 0; i < nCount; ++i)
3473                         if (!pMat->IsString(i))
3474                             rArray.push_back( pMat->GetDouble(i));
3475                 }
3476             }
3477             break;
3478             default :
3479                 PopError();
3480                 SetError( errIllegalParameter);
3481             break;
3482         }
3483         if (nGlobalError)
3484             break;  // while
3485     }
3486     // nParam > 0 in case of error, clean stack environment and obtain earlier
3487     // error if there was one.
3488     while (nParam-- > 0)
3489         PopError();
3490 }
3491 
GetSortArray(sal_uInt8 nParamCount,vector<double> & rSortArray,vector<long> * pIndexOrder)3492 void ScInterpreter::GetSortArray( sal_uInt8 nParamCount, vector<double>& rSortArray, vector<long>* pIndexOrder )
3493 {
3494     GetNumberSequenceArray( nParamCount, rSortArray);
3495 
3496     if (rSortArray.size() > MAX_ANZ_DOUBLE_FOR_SORT)
3497         SetError( errStackOverflow);
3498     else if (rSortArray.empty())
3499         SetError( errNoValue);
3500 
3501     if (nGlobalError == 0)
3502         QuickSort( rSortArray, pIndexOrder);
3503 }
3504 
lcl_QuickSort(long nLo,long nHi,vector<double> & rSortArray,vector<long> * pIndexOrder)3505 static void lcl_QuickSort( long nLo, long nHi, vector<double>& rSortArray, vector<long>* pIndexOrder )
3506 {
3507     // If pIndexOrder is not NULL, we assume rSortArray.size() == pIndexOrder->size().
3508 
3509     using ::std::swap;
3510 
3511     if (nHi - nLo == 1)
3512     {
3513         if (rSortArray[nLo] > rSortArray[nHi])
3514         {
3515             swap(rSortArray[nLo],  rSortArray[nHi]);
3516             if (pIndexOrder)
3517                 swap(pIndexOrder->at(nLo), pIndexOrder->at(nHi));
3518         }
3519         return;
3520     }
3521 
3522     long ni = nLo;
3523     long nj = nHi;
3524     do
3525     {
3526         double fLo = rSortArray[nLo];
3527         while (ni <= nHi && rSortArray[ni] < fLo) ni++;
3528         while (nj >= nLo && fLo < rSortArray[nj]) nj--;
3529         if (ni <= nj)
3530         {
3531             if (ni != nj)
3532             {
3533                 swap(rSortArray[ni],  rSortArray[nj]);
3534                 if (pIndexOrder)
3535                     swap(pIndexOrder->at(ni), pIndexOrder->at(nj));
3536             }
3537 
3538             ++ni;
3539             --nj;
3540         }
3541     }
3542     while (ni < nj);
3543 
3544     if ((nj - nLo) < (nHi - ni))
3545     {
3546         if (nLo < nj) lcl_QuickSort(nLo, nj, rSortArray, pIndexOrder);
3547         if (ni < nHi) lcl_QuickSort(ni, nHi, rSortArray, pIndexOrder);
3548     }
3549     else
3550     {
3551         if (ni < nHi) lcl_QuickSort(ni, nHi, rSortArray, pIndexOrder);
3552         if (nLo < nj) lcl_QuickSort(nLo, nj, rSortArray, pIndexOrder);
3553     }
3554 }
3555 
QuickSort(vector<double> & rSortArray,vector<long> * pIndexOrder)3556 void ScInterpreter::QuickSort( vector<double>& rSortArray, vector<long>* pIndexOrder )
3557 {
3558     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::QuickSort" );
3559     long n = static_cast<long>(rSortArray.size());
3560 
3561     if (pIndexOrder)
3562     {
3563         pIndexOrder->clear();
3564         pIndexOrder->reserve(n);
3565         for (long i = 0; i < n; ++i)
3566             pIndexOrder->push_back(i);
3567     }
3568 
3569     if (n < 2)
3570         return;
3571 
3572     size_t nValCount = rSortArray.size();
3573     for (size_t i = 0; (i + 4) <= nValCount-1; i += 4)
3574     {
3575         size_t nInd = rand() % (int) (nValCount-1);
3576         ::std::swap( rSortArray[i], rSortArray[nInd]);
3577         if (pIndexOrder)
3578             ::std::swap( pIndexOrder->at(i), pIndexOrder->at(nInd));
3579     }
3580 
3581     lcl_QuickSort(0, n-1, rSortArray, pIndexOrder);
3582 }
3583 
ScRank()3584 void ScInterpreter::ScRank()
3585 {
3586     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRank" );
3587     sal_uInt8 nParamCount = GetByte();
3588     if ( !MustHaveParamCount( nParamCount, 2, 3 ) )
3589         return;
3590     sal_Bool bDescending;
3591     if (nParamCount == 3)
3592         bDescending = GetBool();
3593     else
3594         bDescending = sal_False;
3595     double fCount = 1.0;
3596     sal_Bool bValid = sal_False;
3597     switch (GetStackType())
3598     {
3599         case formula::svDouble    :
3600         {
3601             double x = GetDouble();
3602             double fVal = GetDouble();
3603             if (x == fVal)
3604                 bValid = sal_True;
3605             break;
3606         }
3607         case svSingleRef :
3608         {
3609             ScAddress aAdr;
3610             PopSingleRef( aAdr );
3611             double fVal = GetDouble();
3612             ScBaseCell* pCell = GetCell( aAdr );
3613             if (HasCellValueData(pCell))
3614             {
3615                 double x = GetCellValue( aAdr, pCell );
3616                 if (x == fVal)
3617                     bValid = sal_True;
3618             }
3619             break;
3620         }
3621         case formula::svDoubleRef :
3622         case svRefList :
3623         {
3624             ScRange aRange;
3625             short nParam = 1;
3626             size_t nRefInList = 0;
3627             while (nParam-- > 0)
3628             {
3629                 sal_uInt16 nErr = 0;
3630                 // Preserve stack until all RefList elements are done!
3631                 sal_uInt16 nSaveSP = sp;
3632                 PopDoubleRef( aRange, nParam, nRefInList);
3633                 if (nParam)
3634                     --sp;   // simulate pop
3635                 double fVal = GetDouble();
3636                 if (nParam)
3637                     sp = nSaveSP;
3638                 double nCellVal;
3639                 ScValueIterator aValIter(pDok, aRange, glSubTotal);
3640                 if (aValIter.GetFirst(nCellVal, nErr))
3641                 {
3642                     if (nCellVal == fVal)
3643                         bValid = sal_True;
3644                     else if ((!bDescending && nCellVal > fVal) ||
3645                             (bDescending && nCellVal < fVal) )
3646                         fCount++;
3647                     SetError(nErr);
3648                     while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
3649                     {
3650                         if (nCellVal == fVal)
3651                             bValid = sal_True;
3652                         else if ((!bDescending && nCellVal > fVal) ||
3653                                 (bDescending && nCellVal < fVal) )
3654                             fCount++;
3655                     }
3656                 }
3657                 SetError(nErr);
3658             }
3659         }
3660         break;
3661         case svMatrix :
3662         {
3663             ScMatrixRef pMat = PopMatrix();
3664             double fVal = GetDouble();
3665             if (pMat)
3666             {
3667                 SCSIZE nCount = pMat->GetElementCount();
3668                 if (pMat->IsNumeric())
3669                 {
3670                     for (SCSIZE i = 0; i < nCount; i++)
3671                     {
3672                         double x = pMat->GetDouble(i);
3673                         if (x == fVal)
3674                             bValid = sal_True;
3675                         else if ((!bDescending && x > fVal) ||
3676                                     (bDescending && x < fVal) )
3677                             fCount++;
3678                     }
3679                 }
3680                 else
3681                 {
3682                     for (SCSIZE i = 0; i < nCount; i++)
3683                         if (!pMat->IsString(i))
3684                         {
3685                             double x = pMat->GetDouble(i);
3686                             if (x == fVal)
3687                                 bValid = sal_True;
3688                             else if ((!bDescending && x > fVal) ||
3689                                         (bDescending && x < fVal) )
3690                                 fCount++;
3691                         }
3692                 }
3693             }
3694         }
3695         break;
3696         default : SetError(errIllegalParameter); break;
3697     }
3698     if (bValid)
3699         PushDouble(fCount);
3700     else
3701         PushNoValue();
3702 }
3703 
ScAveDev()3704 void ScInterpreter::ScAveDev()
3705 {
3706     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScAveDev" );
3707     sal_uInt8 nParamCount = GetByte();
3708     if ( !MustHaveParamCountMin( nParamCount, 1 ) )
3709         return;
3710     sal_uInt16 SaveSP = sp;
3711     double nMiddle = 0.0;
3712     double rVal = 0.0;
3713     double rValCount = 0.0;
3714     ScAddress aAdr;
3715     ScRange aRange;
3716     short nParam = nParamCount;
3717     size_t nRefInList = 0;
3718     while (nParam-- > 0)
3719     {
3720         switch (GetStackType())
3721         {
3722             case formula::svDouble :
3723                 rVal += GetDouble();
3724                 rValCount++;
3725                 break;
3726             case svSingleRef :
3727             {
3728                 PopSingleRef( aAdr );
3729                 ScBaseCell* pCell = GetCell( aAdr );
3730                 if (HasCellValueData(pCell))
3731                 {
3732                     rVal += GetCellValue( aAdr, pCell );
3733                     rValCount++;
3734                 }
3735             }
3736             break;
3737             case formula::svDoubleRef :
3738             case svRefList :
3739             {
3740                 sal_uInt16 nErr = 0;
3741                 double nCellVal;
3742                 PopDoubleRef( aRange, nParam, nRefInList);
3743                 ScValueIterator aValIter(pDok, aRange);
3744                 if (aValIter.GetFirst(nCellVal, nErr))
3745                 {
3746                     rVal += nCellVal;
3747                     rValCount++;
3748                     SetError(nErr);
3749                     while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
3750                     {
3751                         rVal += nCellVal;
3752                         rValCount++;
3753                     }
3754                     SetError(nErr);
3755                 }
3756             }
3757             break;
3758             case svMatrix :
3759             {
3760                 ScMatrixRef pMat = PopMatrix();
3761                 if (pMat)
3762                 {
3763                     SCSIZE nCount = pMat->GetElementCount();
3764                     if (pMat->IsNumeric())
3765                     {
3766                         for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3767                         {
3768                             rVal += pMat->GetDouble(nElem);
3769                             rValCount++;
3770                         }
3771                     }
3772                     else
3773                     {
3774                         for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3775                             if (!pMat->IsString(nElem))
3776                             {
3777                                 rVal += pMat->GetDouble(nElem);
3778                                 rValCount++;
3779                             }
3780                     }
3781                 }
3782             }
3783             break;
3784             default :
3785                 SetError(errIllegalParameter);
3786             break;
3787         }
3788     }
3789     if (nGlobalError)
3790     {
3791         PushError( nGlobalError);
3792         return;
3793     }
3794     nMiddle = rVal / rValCount;
3795     sp = SaveSP;
3796     rVal = 0.0;
3797     nParam = nParamCount;
3798     nRefInList = 0;
3799     while (nParam-- > 0)
3800     {
3801         switch (GetStackType())
3802         {
3803             case formula::svDouble :
3804                 rVal += fabs(GetDouble() - nMiddle);
3805                 break;
3806             case svSingleRef :
3807             {
3808                 PopSingleRef( aAdr );
3809                 ScBaseCell* pCell = GetCell( aAdr );
3810                 if (HasCellValueData(pCell))
3811                     rVal += fabs(GetCellValue( aAdr, pCell ) - nMiddle);
3812             }
3813             break;
3814             case formula::svDoubleRef :
3815             case svRefList :
3816             {
3817                 sal_uInt16 nErr = 0;
3818                 double nCellVal;
3819                 PopDoubleRef( aRange, nParam, nRefInList);
3820                 ScValueIterator aValIter(pDok, aRange);
3821                 if (aValIter.GetFirst(nCellVal, nErr))
3822                 {
3823                     rVal += (fabs(nCellVal - nMiddle));
3824                     while (aValIter.GetNext(nCellVal, nErr))
3825                          rVal += fabs(nCellVal - nMiddle);
3826                 }
3827             }
3828             break;
3829             case svMatrix :
3830             {
3831                 ScMatrixRef pMat = PopMatrix();
3832                 if (pMat)
3833                 {
3834                     SCSIZE nCount = pMat->GetElementCount();
3835                     if (pMat->IsNumeric())
3836                     {
3837                         for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3838                         {
3839                             rVal += fabs(pMat->GetDouble(nElem) - nMiddle);
3840                         }
3841                     }
3842                     else
3843                     {
3844                         for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3845                         {
3846                             if (!pMat->IsString(nElem))
3847                                 rVal += fabs(pMat->GetDouble(nElem) - nMiddle);
3848                         }
3849                     }
3850                 }
3851             }
3852             break;
3853             default : SetError(errIllegalParameter); break;
3854         }
3855     }
3856     PushDouble(rVal / rValCount);
3857 }
3858 
ScDevSq()3859 void ScInterpreter::ScDevSq()
3860 {
3861     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDevSq" );
3862     double nVal;
3863     double nValCount;
3864     GetStVarParams(nVal, nValCount);
3865     PushDouble(nVal);
3866 }
3867 
ScProbability()3868 void ScInterpreter::ScProbability()
3869 {
3870     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScProbability" );
3871     sal_uInt8 nParamCount = GetByte();
3872     if ( !MustHaveParamCount( nParamCount, 3, 4 ) )
3873         return;
3874     double fUp, fLo;
3875     fUp = GetDouble();
3876     if (nParamCount == 4)
3877         fLo = GetDouble();
3878     else
3879         fLo = fUp;
3880     if (fLo > fUp)
3881     {
3882         double fTemp = fLo;
3883         fLo = fUp;
3884         fUp = fTemp;
3885     }
3886     ScMatrixRef pMatP = GetMatrix();
3887     ScMatrixRef pMatW = GetMatrix();
3888     if (!pMatP || !pMatW)
3889         PushIllegalParameter();
3890     else
3891     {
3892         SCSIZE nC1, nC2;
3893         SCSIZE nR1, nR2;
3894         pMatP->GetDimensions(nC1, nR1);
3895         pMatW->GetDimensions(nC2, nR2);
3896         if (nC1 != nC2 || nR1 != nR2 || nC1 == 0 || nR1 == 0 ||
3897             nC2 == 0 || nR2 == 0)
3898             PushNA();
3899         else
3900         {
3901             double fSum = 0.0;
3902             double fRes = 0.0;
3903             sal_Bool bStop = sal_False;
3904             double fP, fW;
3905             SCSIZE nCount1 = nC1 * nR1;
3906             for ( SCSIZE i = 0; i < nCount1 && !bStop; i++ )
3907             {
3908                 if (pMatP->IsValue(i) && pMatW->IsValue(i))
3909                 {
3910                     fP = pMatP->GetDouble(i);
3911                     fW = pMatW->GetDouble(i);
3912                     if (fP < 0.0 || fP > 1.0)
3913                         bStop = sal_True;
3914                     else
3915                     {
3916                         fSum += fP;
3917                         if (fW >= fLo && fW <= fUp)
3918                             fRes += fP;
3919                     }
3920                 }
3921                 else
3922                     SetError( errIllegalArgument);
3923             }
3924             if (bStop || fabs(fSum -1.0) > 1.0E-7)
3925                 PushNoValue();
3926             else
3927                 PushDouble(fRes);
3928         }
3929     }
3930 }
3931 
ScCorrel()3932 void ScInterpreter::ScCorrel()
3933 {
3934     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCorrel" );
3935     // This is identical to ScPearson()
3936     ScPearson();
3937 }
3938 
ScCovar()3939 void ScInterpreter::ScCovar()
3940 {
3941     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCovar" );
3942     CalculatePearsonCovar(sal_False,sal_False);
3943 }
3944 
ScPearson()3945 void ScInterpreter::ScPearson()
3946 {
3947     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScPearson" );
3948     CalculatePearsonCovar(sal_True,sal_False);
3949 }
CalculatePearsonCovar(sal_Bool _bPearson,sal_Bool _bStexy)3950 void ScInterpreter::CalculatePearsonCovar(sal_Bool _bPearson,sal_Bool _bStexy)
3951 {
3952     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CalculatePearsonCovar" );
3953     if ( !MustHaveParamCount( GetByte(), 2 ) )
3954         return;
3955     ScMatrixRef pMat1 = GetMatrix();
3956     ScMatrixRef pMat2 = GetMatrix();
3957     if (!pMat1 || !pMat2)
3958     {
3959         PushIllegalParameter();
3960         return;
3961     }
3962     SCSIZE nC1, nC2;
3963     SCSIZE nR1, nR2;
3964     pMat1->GetDimensions(nC1, nR1);
3965     pMat2->GetDimensions(nC2, nR2);
3966     if (nR1 != nR2 || nC1 != nC2)
3967     {
3968         PushIllegalArgument();
3969         return;
3970     }
3971     /* #i78250#
3972      * (sum((X-MeanX)(Y-MeanY)))/N equals (SumXY)/N-MeanX*MeanY mathematically,
3973      * but the latter produces wrong results if the absolute values are high,
3974      * for example above 10^8
3975      */
3976     double fCount           = 0.0;
3977     double fSumX            = 0.0;
3978     double fSumY            = 0.0;
3979     double fSumDeltaXDeltaY = 0.0; // sum of (ValX-MeanX)*(ValY-MeanY)
3980     double fSumSqrDeltaX    = 0.0; // sum of (ValX-MeanX)^2
3981     double fSumSqrDeltaY    = 0.0; // sum of (ValY-MeanY)^2
3982     for (SCSIZE i = 0; i < nC1; i++)
3983     {
3984         for (SCSIZE j = 0; j < nR1; j++)
3985         {
3986             if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
3987             {
3988                 double fValX = pMat1->GetDouble(i,j);
3989                 double fValY = pMat2->GetDouble(i,j);
3990                 fSumX += fValX;
3991                 fSumY += fValY;
3992                 fCount++;
3993             }
3994         }
3995     }
3996     if (fCount < (_bStexy ? 3.0 : 1.0)) // fCount==1 is handled by checking denominator later on
3997         PushNoValue();
3998     else
3999     {
4000         const double fMeanX = fSumX / fCount;
4001         const double fMeanY = fSumY / fCount;
4002         for (SCSIZE i = 0; i < nC1; i++)
4003         {
4004             for (SCSIZE j = 0; j < nR1; j++)
4005             {
4006                 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
4007                 {
4008                     const double fValX = pMat1->GetDouble(i,j);
4009                     const double fValY = pMat2->GetDouble(i,j);
4010                     fSumDeltaXDeltaY += (fValX - fMeanX) * (fValY - fMeanY);
4011                     if ( _bPearson )
4012                     {
4013                         fSumSqrDeltaX    += (fValX - fMeanX) * (fValX - fMeanX);
4014                         fSumSqrDeltaY    += (fValY - fMeanY) * (fValY - fMeanY);
4015                     }
4016                 }
4017             }
4018         } // for (SCSIZE i = 0; i < nC1; i++)
4019         if ( _bPearson )
4020         {
4021             if (fSumSqrDeltaX == 0.0 || ( !_bStexy && fSumSqrDeltaY == 0.0) )
4022                 PushError( errDivisionByZero);
4023             else if ( _bStexy )
4024                 PushDouble( sqrt( (fSumSqrDeltaY - fSumDeltaXDeltaY *
4025                             fSumDeltaXDeltaY / fSumSqrDeltaX) / (fCount-2)));
4026             else
4027                 PushDouble( fSumDeltaXDeltaY / sqrt( fSumSqrDeltaX * fSumSqrDeltaY));
4028         } // if ( _bPearson )
4029         else
4030         {
4031             PushDouble( fSumDeltaXDeltaY / fCount);
4032         }
4033     }
4034 }
4035 
ScRSQ()4036 void ScInterpreter::ScRSQ()
4037 {
4038     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRSQ" );
4039     // Same as ScPearson()*ScPearson()
4040     ScPearson();
4041     if (!nGlobalError)
4042     {
4043         switch (GetStackType())
4044         {
4045             case formula::svDouble:
4046                 {
4047                     double fVal = PopDouble();
4048                     PushDouble( fVal * fVal);
4049                 }
4050                 break;
4051             default:
4052                 PopError();
4053                 PushNoValue();
4054         }
4055     }
4056 }
4057 
ScSTEXY()4058 void ScInterpreter::ScSTEXY()
4059 {
4060     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSTEXY" );
4061     CalculatePearsonCovar(sal_True,sal_True);
4062 }
CalculateSlopeIntercept(sal_Bool bSlope)4063 void ScInterpreter::CalculateSlopeIntercept(sal_Bool bSlope)
4064 {
4065     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CalculateSlopeIntercept" );
4066     if ( !MustHaveParamCount( GetByte(), 2 ) )
4067         return;
4068     ScMatrixRef pMat1 = GetMatrix();
4069     ScMatrixRef pMat2 = GetMatrix();
4070     if (!pMat1 || !pMat2)
4071     {
4072         PushIllegalParameter();
4073         return;
4074     }
4075     SCSIZE nC1, nC2;
4076     SCSIZE nR1, nR2;
4077     pMat1->GetDimensions(nC1, nR1);
4078     pMat2->GetDimensions(nC2, nR2);
4079     if (nR1 != nR2 || nC1 != nC2)
4080     {
4081         PushIllegalArgument();
4082         return;
4083     }
4084     // #i78250# numerical stability improved
4085     double fCount           = 0.0;
4086     double fSumX            = 0.0;
4087     double fSumY            = 0.0;
4088     double fSumDeltaXDeltaY = 0.0; // sum of (ValX-MeanX)*(ValY-MeanY)
4089     double fSumSqrDeltaX    = 0.0; // sum of (ValX-MeanX)^2
4090     for (SCSIZE i = 0; i < nC1; i++)
4091     {
4092         for (SCSIZE j = 0; j < nR1; j++)
4093         {
4094             if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
4095             {
4096                 double fValX = pMat1->GetDouble(i,j);
4097                 double fValY = pMat2->GetDouble(i,j);
4098                 fSumX += fValX;
4099                 fSumY += fValY;
4100                 fCount++;
4101             }
4102         }
4103     }
4104     if (fCount < 1.0)
4105         PushNoValue();
4106     else
4107     {
4108         double fMeanX = fSumX / fCount;
4109         double fMeanY = fSumY / fCount;
4110         for (SCSIZE i = 0; i < nC1; i++)
4111         {
4112             for (SCSIZE j = 0; j < nR1; j++)
4113             {
4114                 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
4115                 {
4116                     double fValX = pMat1->GetDouble(i,j);
4117                     double fValY = pMat2->GetDouble(i,j);
4118                     fSumDeltaXDeltaY += (fValX - fMeanX) * (fValY - fMeanY);
4119                     fSumSqrDeltaX    += (fValX - fMeanX) * (fValX - fMeanX);
4120                 }
4121             }
4122         }
4123         if (fSumSqrDeltaX == 0.0)
4124             PushError( errDivisionByZero);
4125         else
4126         {
4127             if ( bSlope )
4128                 PushDouble( fSumDeltaXDeltaY / fSumSqrDeltaX);
4129             else
4130                 PushDouble( fMeanY - fSumDeltaXDeltaY / fSumSqrDeltaX * fMeanX);
4131         }
4132     }
4133 }
4134 
ScSlope()4135 void ScInterpreter::ScSlope()
4136 {
4137     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSlope" );
4138     CalculateSlopeIntercept(sal_True);
4139 }
4140 
ScIntercept()4141 void ScInterpreter::ScIntercept()
4142 {
4143     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIntercept" );
4144     CalculateSlopeIntercept(sal_False);
4145 }
4146 
ScForecast()4147 void ScInterpreter::ScForecast()
4148 {
4149     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScForecast" );
4150     if ( !MustHaveParamCount( GetByte(), 3 ) )
4151         return;
4152     ScMatrixRef pMat1 = GetMatrix();
4153     ScMatrixRef pMat2 = GetMatrix();
4154     if (!pMat1 || !pMat2)
4155     {
4156         PushIllegalParameter();
4157         return;
4158     }
4159     SCSIZE nC1, nC2;
4160     SCSIZE nR1, nR2;
4161     pMat1->GetDimensions(nC1, nR1);
4162     pMat2->GetDimensions(nC2, nR2);
4163     if (nR1 != nR2 || nC1 != nC2)
4164     {
4165         PushIllegalArgument();
4166         return;
4167     }
4168     double fVal = GetDouble();
4169     // #i78250# numerical stability improved
4170     double fCount           = 0.0;
4171     double fSumX            = 0.0;
4172     double fSumY            = 0.0;
4173     double fSumDeltaXDeltaY = 0.0; // sum of (ValX-MeanX)*(ValY-MeanY)
4174     double fSumSqrDeltaX    = 0.0; // sum of (ValX-MeanX)^2
4175     for (SCSIZE i = 0; i < nC1; i++)
4176     {
4177         for (SCSIZE j = 0; j < nR1; j++)
4178         {
4179             if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
4180             {
4181                 double fValX = pMat1->GetDouble(i,j);
4182                 double fValY = pMat2->GetDouble(i,j);
4183                 fSumX += fValX;
4184                 fSumY += fValY;
4185                 fCount++;
4186             }
4187         }
4188     }
4189     if (fCount < 1.0)
4190         PushNoValue();
4191     else
4192     {
4193         double fMeanX = fSumX / fCount;
4194         double fMeanY = fSumY / fCount;
4195         for (SCSIZE i = 0; i < nC1; i++)
4196         {
4197             for (SCSIZE j = 0; j < nR1; j++)
4198             {
4199                 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
4200                 {
4201                     double fValX = pMat1->GetDouble(i,j);
4202                     double fValY = pMat2->GetDouble(i,j);
4203                     fSumDeltaXDeltaY += (fValX - fMeanX) * (fValY - fMeanY);
4204                     fSumSqrDeltaX    += (fValX - fMeanX) * (fValX - fMeanX);
4205                 }
4206             }
4207         }
4208         if (fSumSqrDeltaX == 0.0)
4209             PushError( errDivisionByZero);
4210         else
4211             PushDouble( fMeanY + fSumDeltaXDeltaY / fSumSqrDeltaX * (fVal - fMeanX));
4212     }
4213 }
4214