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