LCOV - code coverage report
Current view: top level - sc/source/core/tool - interpr3.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 1701 2404 70.8 %
Date: 2015-06-13 12:38:46 Functions: 143 152 94.1 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11