LCOV - code coverage report
Current view: top level - sc/source/core/tool - interpr3.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 78 2101 3.7 %
Date: 2012-08-25 Functions: 5 131 3.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 67 2640 2.5 %

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

Generated by: LCOV version 1.10