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 double fF, fF1, fF2;
2588 if (fS1 > fS2)
2589 {
2590 fF = fS1/fS2;
2591 fF1 = fCount1-1.0;
2592 fF2 = fCount2-1.0;
2593 }
2594 else
2595 {
2596 fF = fS2/fS1;
2597 fF1 = fCount2-1.0;
2598 fF2 = fCount1-1.0;
2599 }
2600 PushDouble(2.0*GetFDist(fF, fF1, fF2));
2601 /*
2602 double Z = (pow(fF,1.0/3.0)*(1.0-2.0/(9.0*fF2)) - (1.0-2.0/(9.0*fF1))) /
2603 sqrt(2.0/(9.0*fF1) + pow(fF,2.0/3.0)*2.0/(9.0*fF2));
2604 PushDouble(1.0-2.0*gauss(Z));
2605 */
2606 }
2607
ScChiTest()2608 void ScInterpreter::ScChiTest()
2609 {
2610 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScChiTest" );
2611 if ( !MustHaveParamCount( GetByte(), 2 ) )
2612 return;
2613 ScMatrixRef pMat2 = GetMatrix();
2614 ScMatrixRef pMat1 = GetMatrix();
2615 if (!pMat1 || !pMat2)
2616 {
2617 PushIllegalParameter();
2618 return;
2619 }
2620 SCSIZE nC1, nC2;
2621 SCSIZE nR1, nR2;
2622 pMat1->GetDimensions(nC1, nR1);
2623 pMat2->GetDimensions(nC2, nR2);
2624 if (nR1 != nR2 || nC1 != nC2)
2625 {
2626 PushIllegalArgument();
2627 return;
2628 }
2629 double fChi = 0.0;
2630 for (SCSIZE i = 0; i < nC1; i++)
2631 {
2632 for (SCSIZE j = 0; j < nR1; j++)
2633 {
2634 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
2635 {
2636 double fValX = pMat1->GetDouble(i,j);
2637 double fValE = pMat2->GetDouble(i,j);
2638 fChi += (fValX - fValE) * (fValX - fValE) / fValE;
2639 }
2640 else
2641 {
2642 PushIllegalArgument();
2643 return;
2644 }
2645 }
2646 }
2647 double fDF;
2648 if (nC1 == 1 || nR1 == 1)
2649 {
2650 fDF = (double)(nC1*nR1 - 1);
2651 if (fDF == 0.0)
2652 {
2653 PushNoValue();
2654 return;
2655 }
2656 }
2657 else
2658 fDF = (double)(nC1-1)*(double)(nR1-1);
2659 PushDouble(GetChiDist(fChi, fDF));
2660 /*
2661 double fX, fS, fT, fG;
2662 fX = 1.0;
2663 for (double fi = fDF; fi >= 2.0; fi -= 2.0)
2664 fX *= fChi/fi;
2665 fX *= exp(-fChi/2.0);
2666 if (fmod(fDF, 2.0) != 0.0)
2667 fX *= sqrt(2.0*fChi/F_PI);
2668 fS = 1.0;
2669 fT = 1.0;
2670 fG = fDF;
2671 while (fT >= 1.0E-7)
2672 {
2673 fG += 2.0;
2674 fT *= fChi/fG;
2675 fS += fT;
2676 }
2677 PushDouble(1.0 - fX*fS);
2678 */
2679 }
2680
ScKurt()2681 void ScInterpreter::ScKurt()
2682 {
2683 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScKurt" );
2684 double fSum,fCount,vSum;
2685 std::vector<double> values;
2686 if ( !CalculateSkew(fSum,fCount,vSum,values) )
2687 return;
2688
2689 if (fCount == 0.0)
2690 {
2691 PushError( errDivisionByZero);
2692 return;
2693 }
2694
2695 double fMean = fSum / fCount;
2696
2697 for (size_t i = 0; i < values.size(); i++)
2698 vSum += (values[i] - fMean) * (values[i] - fMean);
2699
2700 double fStdDev = sqrt(vSum / (fCount - 1.0));
2701 double dx = 0.0;
2702 double xpower4 = 0.0;
2703
2704 if (fStdDev == 0.0)
2705 {
2706 PushError( errDivisionByZero);
2707 return;
2708 }
2709
2710 for (size_t i = 0; i < values.size(); i++)
2711 {
2712 dx = (values[i] - fMean) / fStdDev;
2713 xpower4 = xpower4 + (dx * dx * dx * dx);
2714 }
2715
2716 double k_d = (fCount - 2.0) * (fCount - 3.0);
2717 double k_l = fCount * (fCount + 1.0) / ((fCount - 1.0) * k_d);
2718 double k_t = 3.0 * (fCount - 1.0) * (fCount - 1.0) / k_d;
2719
2720 PushDouble(xpower4 * k_l - k_t);
2721 }
2722
ScHarMean()2723 void ScInterpreter::ScHarMean()
2724 {
2725 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScHarMean" );
2726 short nParamCount = GetByte();
2727 double nVal = 0.0;
2728 double nValCount = 0.0;
2729 ScAddress aAdr;
2730 ScRange aRange;
2731 size_t nRefInList = 0;
2732 while ((nGlobalError == 0) && (nParamCount-- > 0))
2733 {
2734 switch (GetStackType())
2735 {
2736 case formula::svDouble :
2737 {
2738 double x = GetDouble();
2739 if (x > 0.0)
2740 {
2741 nVal += 1.0/x;
2742 nValCount++;
2743 }
2744 else
2745 SetError( errIllegalArgument);
2746 break;
2747 }
2748 case svSingleRef :
2749 {
2750 PopSingleRef( aAdr );
2751 ScBaseCell* pCell = GetCell( aAdr );
2752 if (HasCellValueData(pCell))
2753 {
2754 double x = GetCellValue( aAdr, pCell );
2755 if (x > 0.0)
2756 {
2757 nVal += 1.0/x;
2758 nValCount++;
2759 }
2760 else
2761 SetError( errIllegalArgument);
2762 }
2763 break;
2764 }
2765 case formula::svDoubleRef :
2766 case svRefList :
2767 {
2768 sal_uInt16 nErr = 0;
2769 PopDoubleRef( aRange, nParamCount, nRefInList);
2770 double nCellVal;
2771 ScValueIterator aValIter(pDok, aRange, glSubTotal);
2772 if (aValIter.GetFirst(nCellVal, nErr))
2773 {
2774 if (nCellVal > 0.0)
2775 {
2776 nVal += 1.0/nCellVal;
2777 nValCount++;
2778 }
2779 else
2780 SetError( errIllegalArgument);
2781 SetError(nErr);
2782 while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
2783 {
2784 if (nCellVal > 0.0)
2785 {
2786 nVal += 1.0/nCellVal;
2787 nValCount++;
2788 }
2789 else
2790 SetError( errIllegalArgument);
2791 }
2792 SetError(nErr);
2793 }
2794 }
2795 break;
2796 case svMatrix :
2797 {
2798 ScMatrixRef pMat = PopMatrix();
2799 if (pMat)
2800 {
2801 SCSIZE nCount = pMat->GetElementCount();
2802 if (pMat->IsNumeric())
2803 {
2804 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
2805 {
2806 double x = pMat->GetDouble(nElem);
2807 if (x > 0.0)
2808 {
2809 nVal += 1.0/x;
2810 nValCount++;
2811 }
2812 else
2813 SetError( errIllegalArgument);
2814 }
2815 }
2816 else
2817 {
2818 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
2819 if (!pMat->IsString(nElem))
2820 {
2821 double x = pMat->GetDouble(nElem);
2822 if (x > 0.0)
2823 {
2824 nVal += 1.0/x;
2825 nValCount++;
2826 }
2827 else
2828 SetError( errIllegalArgument);
2829 }
2830 }
2831 }
2832 }
2833 break;
2834 default : SetError(errIllegalParameter); break;
2835 }
2836 }
2837 if (nGlobalError == 0)
2838 PushDouble((double)nValCount/nVal);
2839 else
2840 PushError( nGlobalError);
2841 }
2842
ScGeoMean()2843 void ScInterpreter::ScGeoMean()
2844 {
2845 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGeoMean" );
2846 short nParamCount = GetByte();
2847 double nVal = 0.0;
2848 double nValCount = 0.0;
2849 ScAddress aAdr;
2850 ScRange aRange;
2851
2852 size_t nRefInList = 0;
2853 while ((nGlobalError == 0) && (nParamCount-- > 0))
2854 {
2855 switch (GetStackType())
2856 {
2857 case formula::svDouble :
2858 {
2859 double x = GetDouble();
2860 if (x > 0.0)
2861 {
2862 nVal += log(x);
2863 nValCount++;
2864 }
2865 else
2866 SetError( errIllegalArgument);
2867 break;
2868 }
2869 case svSingleRef :
2870 {
2871 PopSingleRef( aAdr );
2872 ScBaseCell* pCell = GetCell( aAdr );
2873 if (HasCellValueData(pCell))
2874 {
2875 double x = GetCellValue( aAdr, pCell );
2876 if (x > 0.0)
2877 {
2878 nVal += log(x);
2879 nValCount++;
2880 }
2881 else
2882 SetError( errIllegalArgument);
2883 }
2884 break;
2885 }
2886 case formula::svDoubleRef :
2887 case svRefList :
2888 {
2889 sal_uInt16 nErr = 0;
2890 PopDoubleRef( aRange, nParamCount, nRefInList);
2891 double nCellVal;
2892 ScValueIterator aValIter(pDok, aRange, glSubTotal);
2893 if (aValIter.GetFirst(nCellVal, nErr))
2894 {
2895 if (nCellVal > 0.0)
2896 {
2897 nVal += log(nCellVal);
2898 nValCount++;
2899 }
2900 else
2901 SetError( errIllegalArgument);
2902 SetError(nErr);
2903 while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
2904 {
2905 if (nCellVal > 0.0)
2906 {
2907 nVal += log(nCellVal);
2908 nValCount++;
2909 }
2910 else
2911 SetError( errIllegalArgument);
2912 }
2913 SetError(nErr);
2914 }
2915 }
2916 break;
2917 case svMatrix :
2918 {
2919 ScMatrixRef pMat = PopMatrix();
2920 if (pMat)
2921 {
2922 SCSIZE nCount = pMat->GetElementCount();
2923 if (pMat->IsNumeric())
2924 {
2925 for (SCSIZE ui = 0; ui < nCount; ui++)
2926 {
2927 double x = pMat->GetDouble(ui);
2928 if (x > 0.0)
2929 {
2930 nVal += log(x);
2931 nValCount++;
2932 }
2933 else
2934 SetError( errIllegalArgument);
2935 }
2936 }
2937 else
2938 {
2939 for (SCSIZE ui = 0; ui < nCount; ui++)
2940 if (!pMat->IsString(ui))
2941 {
2942 double x = pMat->GetDouble(ui);
2943 if (x > 0.0)
2944 {
2945 nVal += log(x);
2946 nValCount++;
2947 }
2948 else
2949 SetError( errIllegalArgument);
2950 }
2951 }
2952 }
2953 }
2954 break;
2955 default : SetError(errIllegalParameter); break;
2956 }
2957 }
2958 if (nGlobalError == 0)
2959 PushDouble(exp(nVal / nValCount));
2960 else
2961 PushError( nGlobalError);
2962 }
2963
ScStandard()2964 void ScInterpreter::ScStandard()
2965 {
2966 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScStandard" );
2967 if ( MustHaveParamCount( GetByte(), 3 ) )
2968 {
2969 double sigma = GetDouble();
2970 double mue = GetDouble();
2971 double x = GetDouble();
2972 if (sigma < 0.0)
2973 PushError( errIllegalArgument);
2974 else if (sigma == 0.0)
2975 PushError( errDivisionByZero);
2976 else
2977 PushDouble((x-mue)/sigma);
2978 }
2979 }
CalculateSkew(double & fSum,double & fCount,double & vSum,std::vector<double> & values)2980 bool ScInterpreter::CalculateSkew(double& fSum,double& fCount,double& vSum,std::vector<double>& values)
2981 {
2982 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CalculateSkew" );
2983 short nParamCount = GetByte();
2984 if ( !MustHaveParamCountMin( nParamCount, 1 ) )
2985 return false;
2986
2987 fSum = 0.0;
2988 fCount = 0.0;
2989 vSum = 0.0;
2990 double fVal = 0.0;
2991 ScAddress aAdr;
2992 ScRange aRange;
2993 size_t nRefInList = 0;
2994 while (nParamCount-- > 0)
2995 {
2996 switch (GetStackType())
2997 {
2998 case formula::svDouble :
2999 {
3000 fVal = GetDouble();
3001 fSum += fVal;
3002 values.push_back(fVal);
3003 fCount++;
3004 }
3005 break;
3006 case svSingleRef :
3007 {
3008 PopSingleRef( aAdr );
3009 ScBaseCell* pCell = GetCell( aAdr );
3010 if (HasCellValueData(pCell))
3011 {
3012 fVal = GetCellValue( aAdr, pCell );
3013 fSum += fVal;
3014 values.push_back(fVal);
3015 fCount++;
3016 }
3017 }
3018 break;
3019 case formula::svDoubleRef :
3020 case svRefList :
3021 {
3022 PopDoubleRef( aRange, nParamCount, nRefInList);
3023 sal_uInt16 nErr = 0;
3024 ScValueIterator aValIter(pDok, aRange);
3025 if (aValIter.GetFirst(fVal, nErr))
3026 {
3027 fSum += fVal;
3028 values.push_back(fVal);
3029 fCount++;
3030 SetError(nErr);
3031 while ((nErr == 0) && aValIter.GetNext(fVal, nErr))
3032 {
3033 fSum += fVal;
3034 values.push_back(fVal);
3035 fCount++;
3036 }
3037 SetError(nErr);
3038 }
3039 }
3040 break;
3041 case svMatrix :
3042 {
3043 ScMatrixRef pMat = PopMatrix();
3044 if (pMat)
3045 {
3046 SCSIZE nCount = pMat->GetElementCount();
3047 if (pMat->IsNumeric())
3048 {
3049 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3050 {
3051 fVal = pMat->GetDouble(nElem);
3052 fSum += fVal;
3053 values.push_back(fVal);
3054 fCount++;
3055 }
3056 }
3057 else
3058 {
3059 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3060 if (!pMat->IsString(nElem))
3061 {
3062 fVal = pMat->GetDouble(nElem);
3063 fSum += fVal;
3064 values.push_back(fVal);
3065 fCount++;
3066 }
3067 }
3068 }
3069 }
3070 break;
3071 default :
3072 SetError(errIllegalParameter);
3073 break;
3074 }
3075 }
3076
3077 if (nGlobalError)
3078 {
3079 PushError( nGlobalError);
3080 return false;
3081 } // if (nGlobalError)
3082 return true;
3083 }
3084
ScSkew()3085 void ScInterpreter::ScSkew()
3086 {
3087 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSkew" );
3088 double fSum,fCount,vSum;
3089 std::vector<double> values;
3090 if ( !CalculateSkew(fSum,fCount,vSum,values) )
3091 return;
3092
3093 double fMean = fSum / fCount;
3094
3095 for (size_t i = 0; i < values.size(); i++)
3096 vSum += (values[i] - fMean) * (values[i] - fMean);
3097
3098 double fStdDev = sqrt(vSum / (fCount - 1.0));
3099 double dx = 0.0;
3100 double xcube = 0.0;
3101
3102 if (fStdDev == 0)
3103 {
3104 PushIllegalArgument();
3105 return;
3106 }
3107
3108 for (size_t i = 0; i < values.size(); i++)
3109 {
3110 dx = (values[i] - fMean) / fStdDev;
3111 xcube = xcube + (dx * dx * dx);
3112 }
3113
3114 PushDouble(((xcube * fCount) / (fCount - 1.0)) / (fCount - 2.0));
3115 }
3116
GetMedian(vector<double> & rArray)3117 double ScInterpreter::GetMedian( vector<double> & rArray )
3118 {
3119 size_t nSize = rArray.size();
3120 if (rArray.empty() || nSize == 0 || nGlobalError)
3121 {
3122 SetError( errNoValue);
3123 return 0.0;
3124 }
3125
3126 // Upper median.
3127 size_t nMid = nSize / 2;
3128 vector<double>::iterator iMid = rArray.begin() + nMid;
3129 ::std::nth_element( rArray.begin(), iMid, rArray.end());
3130 if (nSize & 1)
3131 return *iMid; // Lower and upper median are equal.
3132 else
3133 {
3134 double fUp = *iMid;
3135 // Lower median.
3136 iMid = rArray.begin() + nMid - 1;
3137 ::std::nth_element( rArray.begin(), iMid, rArray.end());
3138 return (fUp + *iMid) / 2;
3139 }
3140 }
3141
ScMedian()3142 void ScInterpreter::ScMedian()
3143 {
3144 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMedian" );
3145 sal_uInt8 nParamCount = GetByte();
3146 if ( !MustHaveParamCountMin( nParamCount, 1 ) )
3147 return;
3148 vector<double> aArray;
3149 GetNumberSequenceArray( nParamCount, aArray);
3150 PushDouble( GetMedian( aArray));
3151 }
3152
GetPercentile(vector<double> & rArray,double fPercentile)3153 double ScInterpreter::GetPercentile( vector<double> & rArray, double fPercentile )
3154 {
3155 size_t nSize = rArray.size();
3156 if (rArray.empty() || nSize == 0 || nGlobalError)
3157 {
3158 SetError( errNoValue);
3159 return 0.0;
3160 }
3161
3162 if (nSize == 1)
3163 return rArray[0];
3164 else
3165 {
3166 size_t nIndex = (size_t)::rtl::math::approxFloor( fPercentile * (nSize-1));
3167 double fDiff = fPercentile * (nSize-1) - ::rtl::math::approxFloor( fPercentile * (nSize-1));
3168 DBG_ASSERT(nIndex < nSize, "GetPercentile: wrong index(1)");
3169 vector<double>::iterator iter = rArray.begin() + nIndex;
3170 ::std::nth_element( rArray.begin(), iter, rArray.end());
3171 if (fDiff == 0.0)
3172 return *iter;
3173 else
3174 {
3175 DBG_ASSERT(nIndex < nSize-1, "GetPercentile: wrong index(2)");
3176 double fVal = *iter;
3177 iter = rArray.begin() + nIndex+1;
3178 ::std::nth_element( rArray.begin(), iter, rArray.end());
3179 return fVal + fDiff * (*iter - fVal);
3180 }
3181 }
3182 }
3183
ScPercentile()3184 void ScInterpreter::ScPercentile()
3185 {
3186 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScPercentile" );
3187 if ( !MustHaveParamCount( GetByte(), 2 ) )
3188 return;
3189 double alpha = GetDouble();
3190 if (alpha < 0.0 || alpha > 1.0)
3191 {
3192 PushIllegalArgument();
3193 return;
3194 }
3195 vector<double> aArray;
3196 GetNumberSequenceArray( 1, aArray);
3197 PushDouble( GetPercentile( aArray, alpha));
3198 }
3199
ScQuartile()3200 void ScInterpreter::ScQuartile()
3201 {
3202 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScQuartile" );
3203 if ( !MustHaveParamCount( GetByte(), 2 ) )
3204 return;
3205 double fFlag = ::rtl::math::approxFloor(GetDouble());
3206 if (fFlag < 0.0 || fFlag > 4.0)
3207 {
3208 PushIllegalArgument();
3209 return;
3210 }
3211 vector<double> aArray;
3212 GetNumberSequenceArray( 1, aArray);
3213 PushDouble( fFlag == 2.0 ? GetMedian( aArray) : GetPercentile( aArray, 0.25 * fFlag));
3214 }
3215
ScModalValue()3216 void ScInterpreter::ScModalValue()
3217 {
3218 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScModalValue" );
3219 sal_uInt8 nParamCount = GetByte();
3220 if ( !MustHaveParamCountMin( nParamCount, 1 ) )
3221 return;
3222 vector<double> aSortArray;
3223 GetSortArray(nParamCount, aSortArray);
3224 SCSIZE nSize = aSortArray.size();
3225 if (aSortArray.empty() || nSize == 0 || nGlobalError)
3226 PushNoValue();
3227 else
3228 {
3229 SCSIZE nMaxIndex = 0, nMax = 1, nCount = 1;
3230 double nOldVal = aSortArray[0];
3231 SCSIZE i;
3232
3233 for ( i = 1; i < nSize; i++)
3234 {
3235 if (aSortArray[i] == nOldVal)
3236 nCount++;
3237 else
3238 {
3239 nOldVal = aSortArray[i];
3240 if (nCount > nMax)
3241 {
3242 nMax = nCount;
3243 nMaxIndex = i-1;
3244 }
3245 nCount = 1;
3246 }
3247 }
3248 if (nCount > nMax)
3249 {
3250 nMax = nCount;
3251 nMaxIndex = i-1;
3252 }
3253 if (nMax == 1 && nCount == 1)
3254 PushNoValue();
3255 else if (nMax == 1)
3256 PushDouble(nOldVal);
3257 else
3258 PushDouble(aSortArray[nMaxIndex]);
3259 }
3260 }
3261
CalculateSmallLarge(sal_Bool bSmall)3262 void ScInterpreter::CalculateSmallLarge(sal_Bool bSmall)
3263 {
3264 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CalculateSmallLarge" );
3265 if ( !MustHaveParamCount( GetByte(), 2 ) )
3266 return;
3267 double f = ::rtl::math::approxFloor(GetDouble());
3268 if (f < 1.0)
3269 {
3270 PushIllegalArgument();
3271 return;
3272 }
3273 SCSIZE k = static_cast<SCSIZE>(f);
3274 vector<double> aSortArray;
3275 /* TODO: using nth_element() is best for one single value, but LARGE/SMALL
3276 * actually are defined to return an array of values if an array of
3277 * positions was passed, in which case, depending on the number of values,
3278 * we may or will need a real sorted array again, see #i32345. */
3279 //GetSortArray(1, aSortArray);
3280 GetNumberSequenceArray(1, aSortArray);
3281 SCSIZE nSize = aSortArray.size();
3282 if (aSortArray.empty() || nSize == 0 || nGlobalError || nSize < k)
3283 PushNoValue();
3284 else
3285 {
3286 // TODO: the sorted case for array: PushDouble( aSortArray[ bSmall ? k-1 : nSize-k ] );
3287 vector<double>::iterator iPos = aSortArray.begin() + (bSmall ? k-1 : nSize-k);
3288 ::std::nth_element( aSortArray.begin(), iPos, aSortArray.end());
3289 PushDouble( *iPos);
3290 }
3291 }
3292
ScLarge()3293 void ScInterpreter::ScLarge()
3294 {
3295 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLarge" );
3296 CalculateSmallLarge(sal_False);
3297 }
3298
ScSmall()3299 void ScInterpreter::ScSmall()
3300 {
3301 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSmall" );
3302 CalculateSmallLarge(sal_True);
3303 }
3304
ScPercentrank()3305 void ScInterpreter::ScPercentrank()
3306 {
3307 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScPercentrank" );
3308 sal_uInt8 nParamCount = GetByte();
3309 if ( !MustHaveParamCount( nParamCount, 2 ) )
3310 return;
3311 #if 0
3312 /* wird nicht unterstuetzt
3313 double fPrec;
3314 if (nParamCount == 3)
3315 {
3316 fPrec = ::rtl::math::approxFloor(GetDouble());
3317 if (fPrec < 1.0)
3318 {
3319 PushIllegalArgument();
3320 return;
3321 }
3322 }
3323 else
3324 fPrec = 3.0;
3325 */
3326 #endif
3327 double fNum = GetDouble();
3328 vector<double> aSortArray;
3329 GetSortArray(1, aSortArray);
3330 SCSIZE nSize = aSortArray.size();
3331 if (aSortArray.empty() || nSize == 0 || nGlobalError)
3332 PushNoValue();
3333 else
3334 {
3335 if (fNum < aSortArray[0] || fNum > aSortArray[nSize-1])
3336 PushNoValue();
3337 else if ( nSize == 1 )
3338 PushDouble(1.0); // fNum == pSortArray[0], see test above
3339 else
3340 {
3341 double fRes;
3342 SCSIZE nOldCount = 0;
3343 double fOldVal = aSortArray[0];
3344 SCSIZE i;
3345 for (i = 1; i < nSize && aSortArray[i] < fNum; i++)
3346 {
3347 if (aSortArray[i] != fOldVal)
3348 {
3349 nOldCount = i;
3350 fOldVal = aSortArray[i];
3351 }
3352 }
3353 if (aSortArray[i] != fOldVal)
3354 nOldCount = i;
3355 if (fNum == aSortArray[i])
3356 fRes = (double)nOldCount/(double)(nSize-1);
3357 else
3358 {
3359 // #75312# nOldCount is the count of smaller entries
3360 // fNum is between pSortArray[nOldCount-1] and pSortArray[nOldCount]
3361 // use linear interpolation to find a position between the entries
3362
3363 if ( nOldCount == 0 )
3364 {
3365 DBG_ERROR("should not happen");
3366 fRes = 0.0;
3367 }
3368 else
3369 {
3370 double fFract = ( fNum - aSortArray[nOldCount-1] ) /
3371 ( aSortArray[nOldCount] - aSortArray[nOldCount-1] );
3372 fRes = ( (double)(nOldCount-1)+fFract )/(double)(nSize-1);
3373 }
3374 }
3375 PushDouble(fRes);
3376 }
3377 }
3378 }
3379
ScTrimMean()3380 void ScInterpreter::ScTrimMean()
3381 {
3382 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTrimMean" );
3383 if ( !MustHaveParamCount( GetByte(), 2 ) )
3384 return;
3385 double alpha = GetDouble();
3386 if (alpha < 0.0 || alpha >= 1.0)
3387 {
3388 PushIllegalArgument();
3389 return;
3390 }
3391 vector<double> aSortArray;
3392 GetSortArray(1, aSortArray);
3393 SCSIZE nSize = aSortArray.size();
3394 if (aSortArray.empty() || nSize == 0 || nGlobalError)
3395 PushNoValue();
3396 else
3397 {
3398 sal_uLong nIndex = (sal_uLong) ::rtl::math::approxFloor(alpha*(double)nSize);
3399 if (nIndex % 2 != 0)
3400 nIndex--;
3401 nIndex /= 2;
3402 DBG_ASSERT(nIndex < nSize, "ScTrimMean: falscher Index");
3403 double fSum = 0.0;
3404 for (SCSIZE i = nIndex; i < nSize-nIndex; i++)
3405 fSum += aSortArray[i];
3406 PushDouble(fSum/(double)(nSize-2*nIndex));
3407 }
3408 }
3409
GetNumberSequenceArray(sal_uInt8 nParamCount,vector<double> & rArray)3410 void ScInterpreter::GetNumberSequenceArray( sal_uInt8 nParamCount, vector<double>& rArray )
3411 {
3412 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetSortArray" );
3413 ScAddress aAdr;
3414 ScRange aRange;
3415 short nParam = nParamCount;
3416 size_t nRefInList = 0;
3417 while (nParam-- > 0)
3418 {
3419 switch (GetStackType())
3420 {
3421 case formula::svDouble :
3422 rArray.push_back( PopDouble());
3423 break;
3424 case svSingleRef :
3425 {
3426 PopSingleRef( aAdr );
3427 ScBaseCell* pCell = GetCell( aAdr );
3428 if (HasCellValueData(pCell))
3429 rArray.push_back( GetCellValue( aAdr, pCell));
3430 }
3431 break;
3432 case formula::svDoubleRef :
3433 case svRefList :
3434 {
3435 PopDoubleRef( aRange, nParam, nRefInList);
3436 if (nGlobalError)
3437 break;
3438
3439 aRange.Justify();
3440 SCSIZE nCellCount = aRange.aEnd.Col() - aRange.aStart.Col() + 1;
3441 nCellCount *= aRange.aEnd.Row() - aRange.aStart.Row() + 1;
3442 rArray.reserve( rArray.size() + nCellCount);
3443
3444 sal_uInt16 nErr = 0;
3445 double fCellVal;
3446 ScValueIterator aValIter(pDok, aRange);
3447 if (aValIter.GetFirst( fCellVal, nErr))
3448 {
3449 rArray.push_back( fCellVal);
3450 SetError(nErr);
3451 while ((nErr == 0) && aValIter.GetNext( fCellVal, nErr))
3452 rArray.push_back( fCellVal);
3453 SetError(nErr);
3454 }
3455 }
3456 break;
3457 case svMatrix :
3458 {
3459 ScMatrixRef pMat = PopMatrix();
3460 if (!pMat)
3461 break;
3462
3463 SCSIZE nCount = pMat->GetElementCount();
3464 rArray.reserve( rArray.size() + nCount);
3465 if (pMat->IsNumeric())
3466 {
3467 for (SCSIZE i = 0; i < nCount; ++i)
3468 rArray.push_back( pMat->GetDouble(i));
3469 }
3470 else
3471 {
3472 for (SCSIZE i = 0; i < nCount; ++i)
3473 if (!pMat->IsString(i))
3474 rArray.push_back( pMat->GetDouble(i));
3475 }
3476 }
3477 break;
3478 default :
3479 PopError();
3480 SetError( errIllegalParameter);
3481 break;
3482 }
3483 if (nGlobalError)
3484 break; // while
3485 }
3486 // nParam > 0 in case of error, clean stack environment and obtain earlier
3487 // error if there was one.
3488 while (nParam-- > 0)
3489 PopError();
3490 }
3491
GetSortArray(sal_uInt8 nParamCount,vector<double> & rSortArray,vector<long> * pIndexOrder)3492 void ScInterpreter::GetSortArray( sal_uInt8 nParamCount, vector<double>& rSortArray, vector<long>* pIndexOrder )
3493 {
3494 GetNumberSequenceArray( nParamCount, rSortArray);
3495
3496 if (rSortArray.size() > MAX_ANZ_DOUBLE_FOR_SORT)
3497 SetError( errStackOverflow);
3498 else if (rSortArray.empty())
3499 SetError( errNoValue);
3500
3501 if (nGlobalError == 0)
3502 QuickSort( rSortArray, pIndexOrder);
3503 }
3504
lcl_QuickSort(long nLo,long nHi,vector<double> & rSortArray,vector<long> * pIndexOrder)3505 static void lcl_QuickSort( long nLo, long nHi, vector<double>& rSortArray, vector<long>* pIndexOrder )
3506 {
3507 // If pIndexOrder is not NULL, we assume rSortArray.size() == pIndexOrder->size().
3508
3509 using ::std::swap;
3510
3511 if (nHi - nLo == 1)
3512 {
3513 if (rSortArray[nLo] > rSortArray[nHi])
3514 {
3515 swap(rSortArray[nLo], rSortArray[nHi]);
3516 if (pIndexOrder)
3517 swap(pIndexOrder->at(nLo), pIndexOrder->at(nHi));
3518 }
3519 return;
3520 }
3521
3522 long ni = nLo;
3523 long nj = nHi;
3524 do
3525 {
3526 double fLo = rSortArray[nLo];
3527 while (ni <= nHi && rSortArray[ni] < fLo) ni++;
3528 while (nj >= nLo && fLo < rSortArray[nj]) nj--;
3529 if (ni <= nj)
3530 {
3531 if (ni != nj)
3532 {
3533 swap(rSortArray[ni], rSortArray[nj]);
3534 if (pIndexOrder)
3535 swap(pIndexOrder->at(ni), pIndexOrder->at(nj));
3536 }
3537
3538 ++ni;
3539 --nj;
3540 }
3541 }
3542 while (ni < nj);
3543
3544 if ((nj - nLo) < (nHi - ni))
3545 {
3546 if (nLo < nj) lcl_QuickSort(nLo, nj, rSortArray, pIndexOrder);
3547 if (ni < nHi) lcl_QuickSort(ni, nHi, rSortArray, pIndexOrder);
3548 }
3549 else
3550 {
3551 if (ni < nHi) lcl_QuickSort(ni, nHi, rSortArray, pIndexOrder);
3552 if (nLo < nj) lcl_QuickSort(nLo, nj, rSortArray, pIndexOrder);
3553 }
3554 }
3555
QuickSort(vector<double> & rSortArray,vector<long> * pIndexOrder)3556 void ScInterpreter::QuickSort( vector<double>& rSortArray, vector<long>* pIndexOrder )
3557 {
3558 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::QuickSort" );
3559 long n = static_cast<long>(rSortArray.size());
3560
3561 if (pIndexOrder)
3562 {
3563 pIndexOrder->clear();
3564 pIndexOrder->reserve(n);
3565 for (long i = 0; i < n; ++i)
3566 pIndexOrder->push_back(i);
3567 }
3568
3569 if (n < 2)
3570 return;
3571
3572 size_t nValCount = rSortArray.size();
3573 for (size_t i = 0; (i + 4) <= nValCount-1; i += 4)
3574 {
3575 size_t nInd = rand() % (int) (nValCount-1);
3576 ::std::swap( rSortArray[i], rSortArray[nInd]);
3577 if (pIndexOrder)
3578 ::std::swap( pIndexOrder->at(i), pIndexOrder->at(nInd));
3579 }
3580
3581 lcl_QuickSort(0, n-1, rSortArray, pIndexOrder);
3582 }
3583
ScRank()3584 void ScInterpreter::ScRank()
3585 {
3586 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRank" );
3587 sal_uInt8 nParamCount = GetByte();
3588 if ( !MustHaveParamCount( nParamCount, 2, 3 ) )
3589 return;
3590 sal_Bool bDescending;
3591 if (nParamCount == 3)
3592 bDescending = GetBool();
3593 else
3594 bDescending = sal_False;
3595 double fCount = 1.0;
3596 sal_Bool bValid = sal_False;
3597 switch (GetStackType())
3598 {
3599 case formula::svDouble :
3600 {
3601 double x = GetDouble();
3602 double fVal = GetDouble();
3603 if (x == fVal)
3604 bValid = sal_True;
3605 break;
3606 }
3607 case svSingleRef :
3608 {
3609 ScAddress aAdr;
3610 PopSingleRef( aAdr );
3611 double fVal = GetDouble();
3612 ScBaseCell* pCell = GetCell( aAdr );
3613 if (HasCellValueData(pCell))
3614 {
3615 double x = GetCellValue( aAdr, pCell );
3616 if (x == fVal)
3617 bValid = sal_True;
3618 }
3619 break;
3620 }
3621 case formula::svDoubleRef :
3622 case svRefList :
3623 {
3624 ScRange aRange;
3625 short nParam = 1;
3626 size_t nRefInList = 0;
3627 while (nParam-- > 0)
3628 {
3629 sal_uInt16 nErr = 0;
3630 // Preserve stack until all RefList elements are done!
3631 sal_uInt16 nSaveSP = sp;
3632 PopDoubleRef( aRange, nParam, nRefInList);
3633 if (nParam)
3634 --sp; // simulate pop
3635 double fVal = GetDouble();
3636 if (nParam)
3637 sp = nSaveSP;
3638 double nCellVal;
3639 ScValueIterator aValIter(pDok, aRange, glSubTotal);
3640 if (aValIter.GetFirst(nCellVal, nErr))
3641 {
3642 if (nCellVal == fVal)
3643 bValid = sal_True;
3644 else if ((!bDescending && nCellVal > fVal) ||
3645 (bDescending && nCellVal < fVal) )
3646 fCount++;
3647 SetError(nErr);
3648 while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
3649 {
3650 if (nCellVal == fVal)
3651 bValid = sal_True;
3652 else if ((!bDescending && nCellVal > fVal) ||
3653 (bDescending && nCellVal < fVal) )
3654 fCount++;
3655 }
3656 }
3657 SetError(nErr);
3658 }
3659 }
3660 break;
3661 case svMatrix :
3662 {
3663 ScMatrixRef pMat = PopMatrix();
3664 double fVal = GetDouble();
3665 if (pMat)
3666 {
3667 SCSIZE nCount = pMat->GetElementCount();
3668 if (pMat->IsNumeric())
3669 {
3670 for (SCSIZE i = 0; i < nCount; i++)
3671 {
3672 double x = pMat->GetDouble(i);
3673 if (x == fVal)
3674 bValid = sal_True;
3675 else if ((!bDescending && x > fVal) ||
3676 (bDescending && x < fVal) )
3677 fCount++;
3678 }
3679 }
3680 else
3681 {
3682 for (SCSIZE i = 0; i < nCount; i++)
3683 if (!pMat->IsString(i))
3684 {
3685 double x = pMat->GetDouble(i);
3686 if (x == fVal)
3687 bValid = sal_True;
3688 else if ((!bDescending && x > fVal) ||
3689 (bDescending && x < fVal) )
3690 fCount++;
3691 }
3692 }
3693 }
3694 }
3695 break;
3696 default : SetError(errIllegalParameter); break;
3697 }
3698 if (bValid)
3699 PushDouble(fCount);
3700 else
3701 PushNoValue();
3702 }
3703
ScAveDev()3704 void ScInterpreter::ScAveDev()
3705 {
3706 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScAveDev" );
3707 sal_uInt8 nParamCount = GetByte();
3708 if ( !MustHaveParamCountMin( nParamCount, 1 ) )
3709 return;
3710 sal_uInt16 SaveSP = sp;
3711 double nMiddle = 0.0;
3712 double rVal = 0.0;
3713 double rValCount = 0.0;
3714 ScAddress aAdr;
3715 ScRange aRange;
3716 short nParam = nParamCount;
3717 size_t nRefInList = 0;
3718 while (nParam-- > 0)
3719 {
3720 switch (GetStackType())
3721 {
3722 case formula::svDouble :
3723 rVal += GetDouble();
3724 rValCount++;
3725 break;
3726 case svSingleRef :
3727 {
3728 PopSingleRef( aAdr );
3729 ScBaseCell* pCell = GetCell( aAdr );
3730 if (HasCellValueData(pCell))
3731 {
3732 rVal += GetCellValue( aAdr, pCell );
3733 rValCount++;
3734 }
3735 }
3736 break;
3737 case formula::svDoubleRef :
3738 case svRefList :
3739 {
3740 sal_uInt16 nErr = 0;
3741 double nCellVal;
3742 PopDoubleRef( aRange, nParam, nRefInList);
3743 ScValueIterator aValIter(pDok, aRange);
3744 if (aValIter.GetFirst(nCellVal, nErr))
3745 {
3746 rVal += nCellVal;
3747 rValCount++;
3748 SetError(nErr);
3749 while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
3750 {
3751 rVal += nCellVal;
3752 rValCount++;
3753 }
3754 SetError(nErr);
3755 }
3756 }
3757 break;
3758 case svMatrix :
3759 {
3760 ScMatrixRef pMat = PopMatrix();
3761 if (pMat)
3762 {
3763 SCSIZE nCount = pMat->GetElementCount();
3764 if (pMat->IsNumeric())
3765 {
3766 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3767 {
3768 rVal += pMat->GetDouble(nElem);
3769 rValCount++;
3770 }
3771 }
3772 else
3773 {
3774 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3775 if (!pMat->IsString(nElem))
3776 {
3777 rVal += pMat->GetDouble(nElem);
3778 rValCount++;
3779 }
3780 }
3781 }
3782 }
3783 break;
3784 default :
3785 SetError(errIllegalParameter);
3786 break;
3787 }
3788 }
3789 if (nGlobalError)
3790 {
3791 PushError( nGlobalError);
3792 return;
3793 }
3794 nMiddle = rVal / rValCount;
3795 sp = SaveSP;
3796 rVal = 0.0;
3797 nParam = nParamCount;
3798 nRefInList = 0;
3799 while (nParam-- > 0)
3800 {
3801 switch (GetStackType())
3802 {
3803 case formula::svDouble :
3804 rVal += fabs(GetDouble() - nMiddle);
3805 break;
3806 case svSingleRef :
3807 {
3808 PopSingleRef( aAdr );
3809 ScBaseCell* pCell = GetCell( aAdr );
3810 if (HasCellValueData(pCell))
3811 rVal += fabs(GetCellValue( aAdr, pCell ) - nMiddle);
3812 }
3813 break;
3814 case formula::svDoubleRef :
3815 case svRefList :
3816 {
3817 sal_uInt16 nErr = 0;
3818 double nCellVal;
3819 PopDoubleRef( aRange, nParam, nRefInList);
3820 ScValueIterator aValIter(pDok, aRange);
3821 if (aValIter.GetFirst(nCellVal, nErr))
3822 {
3823 rVal += (fabs(nCellVal - nMiddle));
3824 while (aValIter.GetNext(nCellVal, nErr))
3825 rVal += fabs(nCellVal - nMiddle);
3826 }
3827 }
3828 break;
3829 case svMatrix :
3830 {
3831 ScMatrixRef pMat = PopMatrix();
3832 if (pMat)
3833 {
3834 SCSIZE nCount = pMat->GetElementCount();
3835 if (pMat->IsNumeric())
3836 {
3837 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3838 {
3839 rVal += fabs(pMat->GetDouble(nElem) - nMiddle);
3840 }
3841 }
3842 else
3843 {
3844 for (SCSIZE nElem = 0; nElem < nCount; nElem++)
3845 {
3846 if (!pMat->IsString(nElem))
3847 rVal += fabs(pMat->GetDouble(nElem) - nMiddle);
3848 }
3849 }
3850 }
3851 }
3852 break;
3853 default : SetError(errIllegalParameter); break;
3854 }
3855 }
3856 PushDouble(rVal / rValCount);
3857 }
3858
ScDevSq()3859 void ScInterpreter::ScDevSq()
3860 {
3861 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDevSq" );
3862 double nVal;
3863 double nValCount;
3864 GetStVarParams(nVal, nValCount);
3865 PushDouble(nVal);
3866 }
3867
ScProbability()3868 void ScInterpreter::ScProbability()
3869 {
3870 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScProbability" );
3871 sal_uInt8 nParamCount = GetByte();
3872 if ( !MustHaveParamCount( nParamCount, 3, 4 ) )
3873 return;
3874 double fUp, fLo;
3875 fUp = GetDouble();
3876 if (nParamCount == 4)
3877 fLo = GetDouble();
3878 else
3879 fLo = fUp;
3880 if (fLo > fUp)
3881 {
3882 double fTemp = fLo;
3883 fLo = fUp;
3884 fUp = fTemp;
3885 }
3886 ScMatrixRef pMatP = GetMatrix();
3887 ScMatrixRef pMatW = GetMatrix();
3888 if (!pMatP || !pMatW)
3889 PushIllegalParameter();
3890 else
3891 {
3892 SCSIZE nC1, nC2;
3893 SCSIZE nR1, nR2;
3894 pMatP->GetDimensions(nC1, nR1);
3895 pMatW->GetDimensions(nC2, nR2);
3896 if (nC1 != nC2 || nR1 != nR2 || nC1 == 0 || nR1 == 0 ||
3897 nC2 == 0 || nR2 == 0)
3898 PushNA();
3899 else
3900 {
3901 double fSum = 0.0;
3902 double fRes = 0.0;
3903 sal_Bool bStop = sal_False;
3904 double fP, fW;
3905 SCSIZE nCount1 = nC1 * nR1;
3906 for ( SCSIZE i = 0; i < nCount1 && !bStop; i++ )
3907 {
3908 if (pMatP->IsValue(i) && pMatW->IsValue(i))
3909 {
3910 fP = pMatP->GetDouble(i);
3911 fW = pMatW->GetDouble(i);
3912 if (fP < 0.0 || fP > 1.0)
3913 bStop = sal_True;
3914 else
3915 {
3916 fSum += fP;
3917 if (fW >= fLo && fW <= fUp)
3918 fRes += fP;
3919 }
3920 }
3921 else
3922 SetError( errIllegalArgument);
3923 }
3924 if (bStop || fabs(fSum -1.0) > 1.0E-7)
3925 PushNoValue();
3926 else
3927 PushDouble(fRes);
3928 }
3929 }
3930 }
3931
ScCorrel()3932 void ScInterpreter::ScCorrel()
3933 {
3934 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCorrel" );
3935 // This is identical to ScPearson()
3936 ScPearson();
3937 }
3938
ScCovar()3939 void ScInterpreter::ScCovar()
3940 {
3941 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCovar" );
3942 CalculatePearsonCovar(sal_False,sal_False);
3943 }
3944
ScPearson()3945 void ScInterpreter::ScPearson()
3946 {
3947 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScPearson" );
3948 CalculatePearsonCovar(sal_True,sal_False);
3949 }
CalculatePearsonCovar(sal_Bool _bPearson,sal_Bool _bStexy)3950 void ScInterpreter::CalculatePearsonCovar(sal_Bool _bPearson,sal_Bool _bStexy)
3951 {
3952 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CalculatePearsonCovar" );
3953 if ( !MustHaveParamCount( GetByte(), 2 ) )
3954 return;
3955 ScMatrixRef pMat1 = GetMatrix();
3956 ScMatrixRef pMat2 = GetMatrix();
3957 if (!pMat1 || !pMat2)
3958 {
3959 PushIllegalParameter();
3960 return;
3961 }
3962 SCSIZE nC1, nC2;
3963 SCSIZE nR1, nR2;
3964 pMat1->GetDimensions(nC1, nR1);
3965 pMat2->GetDimensions(nC2, nR2);
3966 if (nR1 != nR2 || nC1 != nC2)
3967 {
3968 PushIllegalArgument();
3969 return;
3970 }
3971 /* #i78250#
3972 * (sum((X-MeanX)(Y-MeanY)))/N equals (SumXY)/N-MeanX*MeanY mathematically,
3973 * but the latter produces wrong results if the absolute values are high,
3974 * for example above 10^8
3975 */
3976 double fCount = 0.0;
3977 double fSumX = 0.0;
3978 double fSumY = 0.0;
3979 double fSumDeltaXDeltaY = 0.0; // sum of (ValX-MeanX)*(ValY-MeanY)
3980 double fSumSqrDeltaX = 0.0; // sum of (ValX-MeanX)^2
3981 double fSumSqrDeltaY = 0.0; // sum of (ValY-MeanY)^2
3982 for (SCSIZE i = 0; i < nC1; i++)
3983 {
3984 for (SCSIZE j = 0; j < nR1; j++)
3985 {
3986 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
3987 {
3988 double fValX = pMat1->GetDouble(i,j);
3989 double fValY = pMat2->GetDouble(i,j);
3990 fSumX += fValX;
3991 fSumY += fValY;
3992 fCount++;
3993 }
3994 }
3995 }
3996 if (fCount < (_bStexy ? 3.0 : 1.0)) // fCount==1 is handled by checking denominator later on
3997 PushNoValue();
3998 else
3999 {
4000 const double fMeanX = fSumX / fCount;
4001 const double fMeanY = fSumY / fCount;
4002 for (SCSIZE i = 0; i < nC1; i++)
4003 {
4004 for (SCSIZE j = 0; j < nR1; j++)
4005 {
4006 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
4007 {
4008 const double fValX = pMat1->GetDouble(i,j);
4009 const double fValY = pMat2->GetDouble(i,j);
4010 fSumDeltaXDeltaY += (fValX - fMeanX) * (fValY - fMeanY);
4011 if ( _bPearson )
4012 {
4013 fSumSqrDeltaX += (fValX - fMeanX) * (fValX - fMeanX);
4014 fSumSqrDeltaY += (fValY - fMeanY) * (fValY - fMeanY);
4015 }
4016 }
4017 }
4018 } // for (SCSIZE i = 0; i < nC1; i++)
4019 if ( _bPearson )
4020 {
4021 if (fSumSqrDeltaX == 0.0 || ( !_bStexy && fSumSqrDeltaY == 0.0) )
4022 PushError( errDivisionByZero);
4023 else if ( _bStexy )
4024 PushDouble( sqrt( (fSumSqrDeltaY - fSumDeltaXDeltaY *
4025 fSumDeltaXDeltaY / fSumSqrDeltaX) / (fCount-2)));
4026 else
4027 PushDouble( fSumDeltaXDeltaY / sqrt( fSumSqrDeltaX * fSumSqrDeltaY));
4028 } // if ( _bPearson )
4029 else
4030 {
4031 PushDouble( fSumDeltaXDeltaY / fCount);
4032 }
4033 }
4034 }
4035
ScRSQ()4036 void ScInterpreter::ScRSQ()
4037 {
4038 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRSQ" );
4039 // Same as ScPearson()*ScPearson()
4040 ScPearson();
4041 if (!nGlobalError)
4042 {
4043 switch (GetStackType())
4044 {
4045 case formula::svDouble:
4046 {
4047 double fVal = PopDouble();
4048 PushDouble( fVal * fVal);
4049 }
4050 break;
4051 default:
4052 PopError();
4053 PushNoValue();
4054 }
4055 }
4056 }
4057
ScSTEXY()4058 void ScInterpreter::ScSTEXY()
4059 {
4060 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSTEXY" );
4061 CalculatePearsonCovar(sal_True,sal_True);
4062 }
CalculateSlopeIntercept(sal_Bool bSlope)4063 void ScInterpreter::CalculateSlopeIntercept(sal_Bool bSlope)
4064 {
4065 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CalculateSlopeIntercept" );
4066 if ( !MustHaveParamCount( GetByte(), 2 ) )
4067 return;
4068 ScMatrixRef pMat1 = GetMatrix();
4069 ScMatrixRef pMat2 = GetMatrix();
4070 if (!pMat1 || !pMat2)
4071 {
4072 PushIllegalParameter();
4073 return;
4074 }
4075 SCSIZE nC1, nC2;
4076 SCSIZE nR1, nR2;
4077 pMat1->GetDimensions(nC1, nR1);
4078 pMat2->GetDimensions(nC2, nR2);
4079 if (nR1 != nR2 || nC1 != nC2)
4080 {
4081 PushIllegalArgument();
4082 return;
4083 }
4084 // #i78250# numerical stability improved
4085 double fCount = 0.0;
4086 double fSumX = 0.0;
4087 double fSumY = 0.0;
4088 double fSumDeltaXDeltaY = 0.0; // sum of (ValX-MeanX)*(ValY-MeanY)
4089 double fSumSqrDeltaX = 0.0; // sum of (ValX-MeanX)^2
4090 for (SCSIZE i = 0; i < nC1; i++)
4091 {
4092 for (SCSIZE j = 0; j < nR1; j++)
4093 {
4094 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
4095 {
4096 double fValX = pMat1->GetDouble(i,j);
4097 double fValY = pMat2->GetDouble(i,j);
4098 fSumX += fValX;
4099 fSumY += fValY;
4100 fCount++;
4101 }
4102 }
4103 }
4104 if (fCount < 1.0)
4105 PushNoValue();
4106 else
4107 {
4108 double fMeanX = fSumX / fCount;
4109 double fMeanY = fSumY / fCount;
4110 for (SCSIZE i = 0; i < nC1; i++)
4111 {
4112 for (SCSIZE j = 0; j < nR1; j++)
4113 {
4114 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
4115 {
4116 double fValX = pMat1->GetDouble(i,j);
4117 double fValY = pMat2->GetDouble(i,j);
4118 fSumDeltaXDeltaY += (fValX - fMeanX) * (fValY - fMeanY);
4119 fSumSqrDeltaX += (fValX - fMeanX) * (fValX - fMeanX);
4120 }
4121 }
4122 }
4123 if (fSumSqrDeltaX == 0.0)
4124 PushError( errDivisionByZero);
4125 else
4126 {
4127 if ( bSlope )
4128 PushDouble( fSumDeltaXDeltaY / fSumSqrDeltaX);
4129 else
4130 PushDouble( fMeanY - fSumDeltaXDeltaY / fSumSqrDeltaX * fMeanX);
4131 }
4132 }
4133 }
4134
ScSlope()4135 void ScInterpreter::ScSlope()
4136 {
4137 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSlope" );
4138 CalculateSlopeIntercept(sal_True);
4139 }
4140
ScIntercept()4141 void ScInterpreter::ScIntercept()
4142 {
4143 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIntercept" );
4144 CalculateSlopeIntercept(sal_False);
4145 }
4146
ScForecast()4147 void ScInterpreter::ScForecast()
4148 {
4149 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScForecast" );
4150 if ( !MustHaveParamCount( GetByte(), 3 ) )
4151 return;
4152 ScMatrixRef pMat1 = GetMatrix();
4153 ScMatrixRef pMat2 = GetMatrix();
4154 if (!pMat1 || !pMat2)
4155 {
4156 PushIllegalParameter();
4157 return;
4158 }
4159 SCSIZE nC1, nC2;
4160 SCSIZE nR1, nR2;
4161 pMat1->GetDimensions(nC1, nR1);
4162 pMat2->GetDimensions(nC2, nR2);
4163 if (nR1 != nR2 || nC1 != nC2)
4164 {
4165 PushIllegalArgument();
4166 return;
4167 }
4168 double fVal = GetDouble();
4169 // #i78250# numerical stability improved
4170 double fCount = 0.0;
4171 double fSumX = 0.0;
4172 double fSumY = 0.0;
4173 double fSumDeltaXDeltaY = 0.0; // sum of (ValX-MeanX)*(ValY-MeanY)
4174 double fSumSqrDeltaX = 0.0; // sum of (ValX-MeanX)^2
4175 for (SCSIZE i = 0; i < nC1; i++)
4176 {
4177 for (SCSIZE j = 0; j < nR1; j++)
4178 {
4179 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
4180 {
4181 double fValX = pMat1->GetDouble(i,j);
4182 double fValY = pMat2->GetDouble(i,j);
4183 fSumX += fValX;
4184 fSumY += fValY;
4185 fCount++;
4186 }
4187 }
4188 }
4189 if (fCount < 1.0)
4190 PushNoValue();
4191 else
4192 {
4193 double fMeanX = fSumX / fCount;
4194 double fMeanY = fSumY / fCount;
4195 for (SCSIZE i = 0; i < nC1; i++)
4196 {
4197 for (SCSIZE j = 0; j < nR1; j++)
4198 {
4199 if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
4200 {
4201 double fValX = pMat1->GetDouble(i,j);
4202 double fValY = pMat2->GetDouble(i,j);
4203 fSumDeltaXDeltaY += (fValX - fMeanX) * (fValY - fMeanY);
4204 fSumSqrDeltaX += (fValX - fMeanX) * (fValX - fMeanX);
4205 }
4206 }
4207 }
4208 if (fSumSqrDeltaX == 0.0)
4209 PushError( errDivisionByZero);
4210 else
4211 PushDouble( fMeanY + fSumDeltaXDeltaY / fSumSqrDeltaX * (fVal - fMeanX));
4212 }
4213 }
4214