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