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