diff options
author | Kurt Zenker <kz@openoffice.org> | 2009-09-11 18:55:06 +0000 |
---|---|---|
committer | Kurt Zenker <kz@openoffice.org> | 2009-09-11 18:55:06 +0000 |
commit | 8a0e80a04216b93aee215d091d57fde3d9674c99 (patch) | |
tree | 6b158b7f6482fd4ce10ceb359e13c2c9ad706e39 | |
parent | 1821099ab0a9957276d87305cc5b8ff916f2de18 (diff) |
CWS-TOOLING: integrate CWS odff06
2009-09-10 18:58:49 +0200 dr r276042 : #i104954# excel export: fixed broken handling of unary operators
2009-09-06 19:30:43 +0200 er r275861 : warnings
2009-09-05 19:48:41 +0200 er r275849 : warnings; wntmsci12 tries to be too smart
2009-09-05 19:37:47 +0200 er r275848 : warnings
2009-09-03 22:45:42 +0200 er r275776 : #i5658# GetCellValueOrZero: missed the formula cell case
2009-09-03 14:28:41 +0200 er r275752 : #i90759# better description of ZTEST
2009-09-03 03:34:03 +0200 er r275739 : warnings
2009-09-03 03:31:19 +0200 er r275738 : warnings
2009-09-03 03:16:46 +0200 er r275737 : warnings
2009-09-03 03:11:42 +0200 er r275736 : CELLTYPE_DESTROYED only if DBG_UTIL
2009-09-03 03:06:31 +0200 er r275735 : warnings
2009-09-03 03:00:30 +0200 er r275734 : warnings
2009-09-03 02:32:35 +0200 er r275733 : fix broken rebase merge
2009-09-02 22:27:53 +0200 er r275730 : CWS-TOOLING: rebase CWS odff06 to trunk@275331 (milestone: DEV300:m56)
2009-09-02 14:45:05 +0200 er r275712 : #i5658# calculate with string operands as long as they unambiguously represent an integer or ISO 8601 date and/or time value
2009-08-29 22:05:31 +0200 er r275559 : #i99140# CONVERT_ADD new conversions as per ODFF; patch from <lvyue>, slightly changed
2009-08-25 13:23:59 +0200 er r275349 : #i90759# rewording of ZTEST description
2009-08-21 00:10:22 +0200 er r275204 : #i82007# correct description of POWER and parameters; patch from <regina>
2009-08-20 23:58:20 +0200 er r275203 : #i74704# B correct calculation for SP arguments 0 and 1; patch from <regina>
2009-08-20 22:58:57 +0200 er r275201 : #i90759# ZTEST correct calculation using the 3rd parameter sigma
2009-08-14 17:55:45 +0200 er r275000 : #i81214# LOOKUP with single values, data arrays and result arrays; based on a patch from <lvyue>
2009-08-11 00:47:48 +0200 er r274845 : unxlngi6 compiler warnings
2009-08-11 00:43:06 +0200 er r274844 : unxlngi6 compiler warnings
2009-08-10 23:59:05 +0200 er r274843 : #91351# make HYPERLINK accept and return numeric values, propagate errors
2009-07-08 18:46:00 +0200 dr r273846 : #i102022# export 3D refs to cond. formats and data validation
2009-07-02 17:59:40 +0200 dr r273667 : #i102702# adapt changes from sc/source/filter/excel
2009-07-02 15:20:37 +0200 dr r273656 : #i102702# reimplementation of formula token class export
2009-07-02 14:41:02 +0200 er r273653 : a surrogate with value 0x10000 is also valid (ran into when testing #i99900# Calc's UNICHAR function), and Unicode ends at 0x10ffff
2009-07-01 00:10:16 +0200 er r273536 : #i99900# iterateCodePoints: check index against string length to avoid assertion; caught this when testing Calc's new UNICHAR function, with the result of a surrogate pair forming one character.
2009-07-01 00:03:57 +0200 er r273535 : #i99900# new UNICODE and UNICHAR functions; patch from <tanchengbiao>
2009-06-15 16:42:06 +0200 er r272999 : merge patch from #i102701
2009-06-15 11:15:16 +0200 dr r272970 : #i102702# in BIFF, the SKIP flag may be missing for the tAttrSkip token
2009-06-11 13:27:46 +0200 er r272867 : CWS-TOOLING: rebase CWS odff06 to trunk@272827 (milestone: DEV300:m50)
2009-04-30 18:28:02 +0200 er r271423 : #i94618# on status bar, ignore error of cell for COUNT and COUNTA if selection; patch from <kohei>
2009-04-30 13:58:44 +0200 er r271413 : get rid of that ugly mail address thingie in RTL_LOGFILE_CONTEXT_AUTHOR introduced by CWS frmdlg ...
2009-04-30 12:32:44 +0200 er r271411 : #i94618# do not display error of cell for COUNT and COUNTA status bar functions
2009-04-30 01:32:38 +0200 er r271399 : #i101316# improve accuracy of STDEV on equal values; patch from <regina>
2009-04-30 01:18:54 +0200 er r271398 : #i97605# improve accuracy of ASINH and ACOSH; patch from <regina>
2009-04-30 00:46:00 +0200 er r271397 : #i59153# improve accuracy of MOD; patch from <regina>
2009-04-30 00:29:43 +0200 er r271396 : #i69069# improve accuracy of NORMSDIST and POISSON; patch from <regina>
2009-04-29 23:53:28 +0200 er r271395 : #i100119# NORMDIST and LOGNORMDIST optional parameters, plus improvement in accuracy also of NORMSDIST (part of i69069); patch from <regina>
2009-04-28 18:22:07 +0200 er r271337 : #i97052# REPLACE with no length of text to be removed simply inserts new text; patch from <lvyue>, slightly modified
2009-03-24 17:29:36 +0100 er r269982 : #i97091# moved implementation of erf() and erfc() from scaddins to sal to provide C99 functions for compilers lacking it
-rw-r--r-- | sal/inc/rtl/math.h | 36 | ||||
-rw-r--r-- | sal/inc/rtl/math.hxx | 29 | ||||
-rw-r--r-- | sal/rtl/source/math.cxx | 250 | ||||
-rwxr-xr-x | sal/util/sal.map | 4 |
4 files changed, 319 insertions, 0 deletions
diff --git a/sal/inc/rtl/math.h b/sal/inc/rtl/math.h index 704992109..6f24b5735 100644 --- a/sal/inc/rtl/math.h +++ b/sal/inc/rtl/math.h @@ -434,6 +434,42 @@ double SAL_CALL rtl_math_log1p(double fValue) SAL_THROW_EXTERN_C(); */ double SAL_CALL rtl_math_atanh(double fValue) SAL_THROW_EXTERN_C(); +/** Returns values of the Errorfunction erf. + + erf is part of the C99 standard, but not provided by some compilers. + + @param fValue + The value x in the term erf(x). + */ +double SAL_CALL rtl_math_erf(double fValue) SAL_THROW_EXTERN_C(); + +/** Returns values of the complement Errorfunction erfc. + + erfc is part of the C99 standard, but not provided by some compilers. + + @param fValue + The value x in the term erfc(x). + */ +double SAL_CALL rtl_math_erfc(double fValue) SAL_THROW_EXTERN_C(); + +/** Returns values of the inverse hyperbolic sine. + + asinh is part of the C99 standard, but not provided by some compilers. + + @param fValue + The value x in the term asinh(x). + */ +double SAL_CALL rtl_math_asinh(double fValue) SAL_THROW_EXTERN_C(); + +/** Returns values of the inverse hyperbolic cosine. + + acosh is part of the C99 standard, but not provided by some compilers. + + @param fValue + The value x in the term acosh(x). + */ +double SAL_CALL rtl_math_acosh(double fValue) SAL_THROW_EXTERN_C(); + #if defined __cplusplus } #endif /* __cplusplus */ diff --git a/sal/inc/rtl/math.hxx b/sal/inc/rtl/math.hxx index 4223415cd..2c180170d 100644 --- a/sal/inc/rtl/math.hxx +++ b/sal/inc/rtl/math.hxx @@ -221,6 +221,35 @@ inline double atanh(double fValue) return rtl_math_atanh(fValue); } +/** A wrapper around rtl_math_erf. + */ +inline double erf(double fValue) +{ + return rtl_math_erf(fValue); +} + +/** A wrapper around rtl_math_erfc. + */ +inline double erfc(double fValue) +{ + return rtl_math_erfc(fValue); +} + +/** A wrapper around rtl_math_asinh. + */ +inline double asinh(double fValue) +{ + return rtl_math_asinh(fValue); +} + +/** A wrapper around rtl_math_acosh. + */ +inline double acosh(double fValue) +{ + return rtl_math_acosh(fValue); +} + + /** Test equality of two values with an accuracy of the magnitude of the given values scaled by 2^-48 (4 bits roundoff stripped). diff --git a/sal/rtl/source/math.cxx b/sal/rtl/source/math.cxx index 4d8be2b01..731ab18c6 100644 --- a/sal/rtl/source/math.cxx +++ b/sal/rtl/source/math.cxx @@ -79,6 +79,130 @@ static double getN10Exp( int nExp ) return 1.0; } +/** Approximation algorithm for erf for 0 < x < 0.65. */ +void lcl_Erf0065( double x, double& fVal ) +{ + static const double pn[] = { + 1.12837916709551256, + 1.35894887627277916E-1, + 4.03259488531795274E-2, + 1.20339380863079457E-3, + 6.49254556481904354E-5 + }; + static const double qn[] = { + 1.00000000000000000, + 4.53767041780002545E-1, + 8.69936222615385890E-2, + 8.49717371168693357E-3, + 3.64915280629351082E-4 + }; + double fPSum = 0.0; + double fQSum = 0.0; + double fXPow = 1.0; + for ( unsigned int i = 0; i <= 4; ++i ) + { + fPSum += pn[i]*fXPow; + fQSum += qn[i]*fXPow; + fXPow *= x*x; + } + fVal = x * fPSum / fQSum; +} + +/** Approximation algorithm for erfc for 0.65 < x < 6.0. */ +void lcl_Erfc0600( double x, double& fVal ) +{ + double fPSum = 0.0; + double fQSum = 0.0; + double fXPow = 1.0; + const double *pn; + const double *qn; + + if ( x < 2.2 ) + { + static const double pn22[] = { + 9.99999992049799098E-1, + 1.33154163936765307, + 8.78115804155881782E-1, + 3.31899559578213215E-1, + 7.14193832506776067E-2, + 7.06940843763253131E-3 + }; + static const double qn22[] = { + 1.00000000000000000, + 2.45992070144245533, + 2.65383972869775752, + 1.61876655543871376, + 5.94651311286481502E-1, + 1.26579413030177940E-1, + 1.25304936549413393E-2 + }; + pn = pn22; + qn = qn22; + } + else /* if ( x < 6.0 ) this is true, but the compiler does not know */ + { + static const double pn60[] = { + 9.99921140009714409E-1, + 1.62356584489366647, + 1.26739901455873222, + 5.81528574177741135E-1, + 1.57289620742838702E-1, + 2.25716982919217555E-2 + }; + static const double qn60[] = { + 1.00000000000000000, + 2.75143870676376208, + 3.37367334657284535, + 2.38574194785344389, + 1.05074004614827206, + 2.78788439273628983E-1, + 4.00072964526861362E-2 + }; + pn = pn60; + qn = qn60; + } + + for ( unsigned int i = 0; i < 6; ++i ) + { + fPSum += pn[i]*fXPow; + fQSum += qn[i]*fXPow; + fXPow *= x; + } + fQSum += qn[6]*fXPow; + fVal = exp( -1.0*x*x )* fPSum / fQSum; +} + +/** Approximation algorithm for erfc for 6.0 < x < 26.54 (but used for all + x > 6.0). */ +void lcl_Erfc2654( double x, double& fVal ) +{ + static const double pn[] = { + 5.64189583547756078E-1, + 8.80253746105525775, + 3.84683103716117320E1, + 4.77209965874436377E1, + 8.08040729052301677 + }; + static const double qn[] = { + 1.00000000000000000, + 1.61020914205869003E1, + 7.54843505665954743E1, + 1.12123870801026015E2, + 3.73997570145040850E1 + }; + + double fPSum = 0.0; + double fQSum = 0.0; + double fXPow = 1.0; + + for ( unsigned int i = 0; i <= 4; ++i ) + { + fPSum += pn[i]*fXPow; + fQSum += qn[i]*fXPow; + fXPow /= x*x; + } + fVal = exp(-1.0*x*x)*fPSum / (x*fQSum); +} namespace { @@ -991,3 +1115,129 @@ double SAL_CALL rtl_math_atanh( double fValue ) SAL_THROW_EXTERN_C() { return 0.5 * rtl_math_log1p( 2.0 * fValue / (1.0-fValue) ); } + + +/** Parent error function (erf) that calls different algorithms based on the + value of x. It takes care of cases where x is negative as erf is an odd + function i.e. erf(-x) = -erf(x). + + Kramer, W., and Blomquist, F., 2000, Algorithms with Guaranteed Error Bounds + for the Error Function and the Complementary Error Function + + http://www.math.uni-wuppertal.de/wrswt/literatur_en.html + + @author Kohei Yoshida <kohei@openoffice.org> + + @see #i55735# + */ +double SAL_CALL rtl_math_erf( double x ) SAL_THROW_EXTERN_C() +{ + if( x == 0.0 ) + return 0.0; + + bool bNegative = false; + if ( x < 0.0 ) + { + x = fabs( x ); + bNegative = true; + } + + double fErf = 1.0; + if ( x < 1.0e-10 ) + fErf = (double) (x*1.1283791670955125738961589031215452L); + else if ( x < 0.65 ) + lcl_Erf0065( x, fErf ); + else + fErf = 1.0 - rtl_math_erfc( x ); + + if ( bNegative ) + fErf *= -1.0; + + return fErf; +} + + +/** Parent complementary error function (erfc) that calls different algorithms + based on the value of x. It takes care of cases where x is negative as erfc + satisfies relationship erfc(-x) = 2 - erfc(x). See the comment for Erf(x) + for the source publication. + + @author Kohei Yoshida <kohei@openoffice.org> + + @see #i55735#, moved from module scaddins (#i97091#) + + */ +double SAL_CALL rtl_math_erfc( double x ) SAL_THROW_EXTERN_C() +{ + if ( x == 0.0 ) + return 1.0; + + bool bNegative = false; + if ( x < 0.0 ) + { + x = fabs( x ); + bNegative = true; + } + + double fErfc = 0.0; + if ( x >= 0.65 ) + { + if ( x < 6.0 ) + lcl_Erfc0600( x, fErfc ); + else + lcl_Erfc2654( x, fErfc ); + } + else + fErfc = 1.0 - rtl_math_erf( x ); + + if ( bNegative ) + fErfc = 2.0 - fErfc; + + return fErfc; +} + +/** improved accuracy of asinh for |x| large and for x near zero + @see #i97605# + */ +double SAL_CALL rtl_math_asinh( double fX ) SAL_THROW_EXTERN_C() +{ + double fSign = 1.0; + if ( fX == 0.0 ) + return 0.0; + else + { + if ( fX < 0.0 ) + { + fX = - fX; + fSign = -1.0; + } + if ( fX < 0.125 ) + return fSign * rtl_math_log1p( fX + fX*fX / (1.0 + sqrt( 1.0 + fX*fX))); + else if ( fX < 1.25e7 ) + return fSign * log( fX + sqrt( 1.0 + fX*fX)); + else + return fSign * log( 2.0*fX); + } +} + +/** improved accuracy of acosh for x large and for x near 1 + @see #i97605# + */ +double SAL_CALL rtl_math_acosh( double fX ) SAL_THROW_EXTERN_C() +{ + volatile double fZ = fX - 1.0; + if ( fX < 1.0 ) + { + double fResult; + ::rtl::math::setNan( &fResult ); + return fResult; + } + else if ( fX == 1.0 ) + return 0.0; + else if ( fX < 1.1 ) + return rtl_math_log1p( fZ + sqrt( fZ*fZ + 2.0*fZ)); + else if ( fX < 1.25e7 ) + return log( fX + sqrt( fX*fX - 1.0)); + else + return log( 2.0*fX); +} diff --git a/sal/util/sal.map b/sal/util/sal.map index ad063f379..d5faa563a 100755 --- a/sal/util/sal.map +++ b/sal/util/sal.map @@ -591,6 +591,10 @@ UDK_3.9 { # OOo 3.1 UDK_3.10 { # OOo 3.2 global: rtl_logfile_hasLogFile; + rtl_math_erf; + rtl_math_erfc; + rtl_math_asinh; + rtl_math_acosh; } UDK_3.9; PRIVATE_1.0 { |