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