summaryrefslogtreecommitdiff
path: root/boost/math/tools/precision.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/math/tools/precision.hpp')
-rw-r--r--boost/math/tools/precision.hpp53
1 files changed, 49 insertions, 4 deletions
diff --git a/boost/math/tools/precision.hpp b/boost/math/tools/precision.hpp
index 8cdcd4eb87..49e653d6a3 100644
--- a/boost/math/tools/precision.hpp
+++ b/boost/math/tools/precision.hpp
@@ -18,8 +18,6 @@
#include <boost/mpl/if.hpp>
#include <boost/math/policies/policy.hpp>
-#include <iostream>
-#include <iomanip>
// These two are for LDBL_MAN_DIG:
#include <limits.h>
#include <math.h>
@@ -159,11 +157,19 @@ inline T epsilon(const mpl::true_& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T))
return std::numeric_limits<T>::epsilon();
}
-#if (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) && ((LDBL_MANT_DIG == 106) || (__LDBL_MANT_DIG__ == 106))
+#if defined(__GNUC__) && ((LDBL_MANT_DIG == 106) || (__LDBL_MANT_DIG__ == 106))
template <>
inline long double epsilon<long double>(const mpl::true_& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(long double))
{
- // numeric_limits on Darwin tells lies here.
+ // numeric_limits on Darwin (and elsewhere) tells lies here:
+ // the issue is that long double on a few platforms is
+ // really a "double double" which has a non-contiguous
+ // mantissa: 53 bits followed by an unspecified number of
+ // zero bits, followed by 53 more bits. Thus the apparent
+ // precision of the type varies depending where it's been.
+ // Set epsilon to the value that a 106 bit fixed mantissa
+ // type would have, as that will give us sensible behaviour everywhere.
+ //
// This static assert fails for some unknown reason, so
// disabled for now...
// BOOST_STATIC_ASSERT(std::numeric_limits<long double>::digits == 106);
@@ -282,6 +288,38 @@ inline T root_epsilon_imp(const T*, const Tag&)
}
template <class T>
+inline T cbrt_epsilon_imp(const mpl::int_<24>&)
+{
+ return static_cast<T>(0.0049215666011518482998719164346805794944150447839903L);
+}
+
+template <class T>
+inline T cbrt_epsilon_imp(const T*, const mpl::int_<53>&)
+{
+ return static_cast<T>(6.05545445239333906078989272793696693569753008995e-6L);
+}
+
+template <class T>
+inline T cbrt_epsilon_imp(const T*, const mpl::int_<64>&)
+{
+ return static_cast<T>(4.76837158203125e-7L);
+}
+
+template <class T>
+inline T cbrt_epsilon_imp(const T*, const mpl::int_<113>&)
+{
+ return static_cast<T>(5.7749313854154005630396773604745549542403508090496e-12L);
+}
+
+template <class T, class Tag>
+inline T cbrt_epsilon_imp(const T*, const Tag&)
+{
+ BOOST_MATH_STD_USING;
+ static const T cbrt_eps = pow(tools::epsilon<T>(), T(1) / 3);
+ return cbrt_eps;
+}
+
+template <class T>
inline T forth_root_epsilon_imp(const T*, const mpl::int_<24>&)
{
return static_cast<T>(0.018581361171917516667460937040007436176452688944747L);
@@ -323,6 +361,13 @@ inline T root_epsilon()
}
template <class T>
+inline T cbrt_epsilon()
+{
+ typedef mpl::int_< (::std::numeric_limits<T>::radix == 2) ? std::numeric_limits<T>::digits : 0> tag_type;
+ return detail::cbrt_epsilon_imp(static_cast<T const*>(0), tag_type());
+}
+
+template <class T>
inline T forth_root_epsilon()
{
typedef mpl::int_< (::std::numeric_limits<T>::radix == 2) ? std::numeric_limits<T>::digits : 0> tag_type;