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