Author: pfg
Date: Wed Jan 2 20:05:18 2013
New Revision: 1427988
URL: http://svn.apache.org/viewvc?rev=1427988&view=rev
Log:
i121561 - Use of boost instead of RTL hyperbolic/power functions.
Boost provides some well implemented and tested versions of the
inverse hyperbolic and small power functions. According to the
documentation the error for these boost versions should be about
1 or 2 Epsilon.
Testing shows that for recent Apache OpenOffice this won't cause
much difference but Symphony users will see important precision
improvements.
Special Thanks to Regina Henschel for providing excellent test cases.
Modified:
openoffice/trunk/main/sc/source/core/inc/interpre.hxx
openoffice/trunk/main/sc/source/core/tool/interpr1.cxx
openoffice/trunk/main/sc/source/core/tool/interpr2.cxx
openoffice/trunk/main/sc/source/core/tool/interpr3.cxx
Modified: openoffice/trunk/main/sc/source/core/inc/interpre.hxx
URL:
http://svn.apache.org/viewvc/openoffice/trunk/main/sc/source/core/inc/interpre.hxx?rev=1427988&r1=1427987&r2=1427988&view=diff
==============================================================================
--- openoffice/trunk/main/sc/source/core/inc/interpre.hxx (original)
+++ openoffice/trunk/main/sc/source/core/inc/interpre.hxx Wed Jan 2 20:05:18
2013
@@ -33,6 +33,12 @@
#include <math.h>
#include <map>
+// Policy Definitions for Boost math.
+// This header must be included before including any Boost
+// math function.
+//
+#define BOOST_MATH_OVERFLOW_ERROR_POLICY errno_on_error
+
class ScDocument;
class SbxVariable;
class ScBaseCell;
Modified: openoffice/trunk/main/sc/source/core/tool/interpr1.cxx
URL:
http://svn.apache.org/viewvc/openoffice/trunk/main/sc/source/core/tool/interpr1.cxx?rev=1427988&r1=1427987&r2=1427988&view=diff
==============================================================================
--- openoffice/trunk/main/sc/source/core/tool/interpr1.cxx (original)
+++ openoffice/trunk/main/sc/source/core/tool/interpr1.cxx Wed Jan 2 20:05:18
2013
@@ -72,6 +72,10 @@
#include "doubleref.hxx"
#include "queryparam.hxx"
+#include <boost/math/special_functions/acosh.hpp>
+#include <boost/math/special_functions/asinh.hpp>
+#include <boost/math/special_functions/atanh.hpp>
+
#define SC_DOUBLE_MAXVALUE 1.7e307
IMPL_FIXEDMEMPOOL_NEWDEL( ScTokenStack, 8, 4 )
@@ -1702,7 +1706,7 @@ void ScInterpreter::ScCotHyp()
void ScInterpreter::ScArcSinHyp()
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er",
"ScInterpreter::ScArcSinHyp" );
- PushDouble( ::rtl::math::asinh( GetDouble()));
+ PushDouble( ::boost::math::asinh( GetDouble()));
}
void ScInterpreter::ScArcCosHyp()
@@ -1712,7 +1716,7 @@ void ScInterpreter::ScArcCosHyp()
if (fVal < 1.0)
PushIllegalArgument();
else
- PushDouble( ::rtl::math::acosh( fVal));
+ PushDouble( ::boost::math::acosh( fVal));
}
void ScInterpreter::ScArcTanHyp()
@@ -1722,7 +1726,7 @@ void ScInterpreter::ScArcTanHyp()
if (fabs(fVal) >= 1.0)
PushIllegalArgument();
else
- PushDouble( ::rtl::math::atanh( fVal));
+ PushDouble( ::boost::math::atanh( fVal));
}
Modified: openoffice/trunk/main/sc/source/core/tool/interpr2.cxx
URL:
http://svn.apache.org/viewvc/openoffice/trunk/main/sc/source/core/tool/interpr2.cxx?rev=1427988&r1=1427987&r2=1427988&view=diff
==============================================================================
--- openoffice/trunk/main/sc/source/core/tool/interpr2.cxx (original)
+++ openoffice/trunk/main/sc/source/core/tool/interpr2.cxx Wed Jan 2 20:05:18
2013
@@ -52,6 +52,9 @@
#include <string.h>
#include <math.h>
+#include <boost/math/special_functions/expm1.hpp>
+#include <boost/math/special_functions/log1p.hpp>
+
using namespace formula;
// STATIC DATA -----------------------------------------------------------
@@ -1135,11 +1138,11 @@ double ScInterpreter::ScGetRmz(double fR
else
{
if (fPaytype > 0.0) // payment in advance
- fPayment = (fFv + fPv * exp( fNper * ::rtl::math::log1p(fRate) ) )
* fRate /
- (::rtl::math::expm1( (fNper + 1) * ::rtl::math::log1p(fRate) )
- fRate);
+ fPayment = (fFv + fPv * exp( fNper * ::boost::math::log1p(fRate) )
) * fRate /
+ (::boost::math::expm1( (fNper + 1) *
::boost::math::log1p(fRate) ) - fRate);
else // payment in arrear
- fPayment = (fFv + fPv * exp(fNper * ::rtl::math::log1p(fRate) ) )
* fRate /
- ::rtl::math::expm1( fNper * ::rtl::math::log1p(fRate) );
+ fPayment = (fFv + fPv * exp(fNper * ::boost::math::log1p(fRate) )
) * fRate /
+ ::boost::math::expm1( fNper * ::boost::math::log1p(fRate) );
}
return -fPayment;
}
Modified: openoffice/trunk/main/sc/source/core/tool/interpr3.cxx
URL:
http://svn.apache.org/viewvc/openoffice/trunk/main/sc/source/core/tool/interpr3.cxx?rev=1427988&r1=1427987&r2=1427988&view=diff
==============================================================================
--- openoffice/trunk/main/sc/source/core/tool/interpr3.cxx (original)
+++ openoffice/trunk/main/sc/source/core/tool/interpr3.cxx Wed Jan 2 20:05:18
2013
@@ -44,6 +44,10 @@
#include <vector>
#include <algorithm>
+#include <boost/math/special_functions/atanh.hpp>
+#include <boost/math/special_functions/expm1.hpp>
+#include <boost/math/special_functions/log1p.hpp>
+
using ::std::vector;
using namespace formula;
@@ -853,8 +857,8 @@ double ScInterpreter::GetBeta(double fAl
fLanczos *= sqrt((fABgm/(fA+fgm))/(fB+fgm));
double fTempA = fB/(fA+fgm); // (fA+fgm)/fABgm = 1 / ( 1 + fB/(fA+fgm))
double fTempB = fA/(fB+fgm);
- double fResult = exp(-fA * ::rtl::math::log1p(fTempA)
- -fB * ::rtl::math::log1p(fTempB)-fgm);
+ double fResult = exp(-fA * ::boost::math::log1p(fTempA)
+ -fB * ::boost::math::log1p(fTempB)-fgm);
fResult *= fLanczos;
return fResult;
}
@@ -882,8 +886,8 @@ double ScInterpreter::GetLogBeta(double
fLogLanczos += 0.5*(log(fABgm)-log(fA+fgm)-log(fB+fgm));
double fTempA = fB/(fA+fgm); // (fA+fgm)/fABgm = 1 / ( 1 + fB/(fA+fgm))
double fTempB = fA/(fB+fgm);
- double fResult = -fA * ::rtl::math::log1p(fTempA)
- -fB * ::rtl::math::log1p(fTempB)-fgm;
+ double fResult = -fA * ::boost::math::log1p(fTempA)
+ -fB * ::boost::math::log1p(fTempB)-fgm;
fResult += fLogLanczos;
return fResult;
}
@@ -904,7 +908,7 @@ double ScInterpreter::GetBetaDistPDF(dou
return HUGE_VAL;
}
if (fX <= 0.01)
- return fB + fB * ::rtl::math::expm1((fB-1.0) *
::rtl::math::log1p(-fX));
+ return fB + fB * ::boost::math::expm1((fB-1.0) *
::boost::math::log1p(-fX));
else
return fB * pow(0.5-fX+0.5,fB-1.0);
}
@@ -943,7 +947,7 @@ double ScInterpreter::GetBetaDistPDF(dou
// normal cases; result x^(a-1)*(1-x)^(b-1)/Beta(a,b)
const double fLogDblMax = log( ::std::numeric_limits<double>::max());
const double fLogDblMin = log( ::std::numeric_limits<double>::min());
- double fLogY = (fX < 0.1) ? ::rtl::math::log1p(-fX) : log(0.5-fX+0.5);
+ double fLogY = (fX < 0.1) ? ::boost::math::log1p(-fX) : log(0.5-fX+0.5);
double fLogX = log(fX);
double fAm1LogX = (fA-1.0) * fLogX;
double fBm1LogY = (fB-1.0) * fLogY;
@@ -1024,13 +1028,13 @@ double ScInterpreter::GetBetaDist(double
return pow(fXin, fAlpha);
if (fAlpha == 1.0)
// 1.0 - pow(1.0-fX,fBeta) is not accurate enough
- return -::rtl::math::expm1(fBeta * ::rtl::math::log1p(-fXin));
+ return -::boost::math::expm1(fBeta * ::boost::math::log1p(-fXin));
//FIXME: need special algorithm for fX near fP for large fA,fB
double fResult;
// I use always continued fraction, power series are neither
// faster nor more accurate.
double fY = (0.5-fXin)+0.5;
- double flnY = ::rtl::math::log1p(-fXin);
+ double flnY = ::boost::math::log1p(-fXin);
double fX = fXin;
double flnX = log(fXin);
double fA = fAlpha;
@@ -1141,7 +1145,7 @@ void ScInterpreter::ScFisher()
if (fabs(fVal) >= 1.0)
PushIllegalArgument();
else
- PushDouble( ::rtl::math::atanh( fVal));
+ PushDouble( ::boost::math::atanh( fVal));
}
void ScInterpreter::ScFisherInv()