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()


Reply via email to