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