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