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