|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r82585 - in trunk: boost/math/constants libs/math/test
From: john_at_[hidden]
Date: 2013-01-22 07:16:52
Author: johnmaddock
Date: 2013-01-22 07:16:51 EST (Tue, 22 Jan 2013)
New Revision: 82585
URL: http://svn.boost.org/trac/boost/changeset/82585
Log:
Modify constants code to return a constant reference when returning a cached value, while still maintaining value semantics and constexpr support for built in types.
Text files modified:
trunk/boost/math/constants/calculate_constants.hpp | 2 +-
trunk/boost/math/constants/constants.hpp | 31 ++++++++++++++++++++-----------
trunk/libs/math/test/test_constants.cpp | 14 ++++++++++++++
3 files changed, 35 insertions(+), 12 deletions(-)
Modified: trunk/boost/math/constants/calculate_constants.hpp
==============================================================================
--- trunk/boost/math/constants/calculate_constants.hpp (original)
+++ trunk/boost/math/constants/calculate_constants.hpp 2013-01-22 07:16:51 EST (Tue, 22 Jan 2013)
@@ -161,7 +161,7 @@
// See equation 17 with p = 2.
//
T n = 3 + (M ? (std::min)(M, tools::digits<T>()) : tools::digits<T>()) / 4;
- T lim = M ? ldexp(T(1), (std::min)(M, tools::digits<T>())) : tools::epsilon<T>();
+ T lim = M ? ldexp(T(1), 1 - (std::min)(M, tools::digits<T>())) : tools::epsilon<T>();
T lnn = log(n);
T term = 1;
T N = -lnn;
Modified: trunk/boost/math/constants/constants.hpp
==============================================================================
--- trunk/boost/math/constants/constants.hpp (original)
+++ trunk/boost/math/constants/constants.hpp 2013-01-22 07:16:51 EST (Tue, 22 Jan 2013)
@@ -27,7 +27,7 @@
{
namespace constants
{
- // To permit other calculations at about 100 decimal digits with NTL::RR type,
+ // To permit other calculations at about 100 decimal digits with some UDT,
// it is obviously necessary to define constants to this accuracy.
// However, some compilers do not accept decimal digits strings as long as this.
@@ -93,6 +93,15 @@
namespace detail{
+ template <class Real, class Policy = boost::math::policies::policy<> >
+ struct constant_return
+ {
+ typedef typename construction_traits<Real, Policy>::type construct_type;
+ typedef typename mpl::if_c<
+ (construct_type::value >= construct_from_string),
+ const Real&, Real>::type type;
+ };
+
template <class Real>
Real convert_from_string(const char* p, const mpl::false_&)
{
@@ -104,7 +113,7 @@
return p;
}
- template <class T, T (*F)(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(T))>
+ template <class T, const T& (*F)(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(T))>
struct constant_initializer
{
static void force_instantiate()
@@ -127,10 +136,10 @@
static const initializer init;
};
- template <class T, T (*F)(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(T))>
+ template <class T, const T& (*F)(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(T))>
typename constant_initializer<T, F>::initializer const constant_initializer<T, F>::init;
- template <class T, int N, T (*F)(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>) BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T))>
+ template <class T, int N, const T& (*F)(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>) BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T))>
struct constant_initializer2
{
static void force_instantiate()
@@ -153,7 +162,7 @@
static const initializer init;
};
- template <class T, int N, T (*F)(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>) BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T))>
+ template <class T, int N, const T& (*F)(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>) BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T))>
typename constant_initializer2<T, N, F>::initializer const constant_initializer2<T, N, F>::init;
}
@@ -163,21 +172,21 @@
template <class T> struct BOOST_JOIN(constant_, name){\
private:\
/* The default implementations come next: */ \
- static inline T get_from_string()\
+ static inline const T& get_from_string()\
{\
static const T result = convert_from_string<T>(y, boost::is_convertible<const char*, T>());\
return result;\
}\
/* This one is for very high precision that is none the less known at compile time: */ \
template <int N> static T compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>));\
- template <int N> static inline T get_from_compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))\
+ template <int N> static inline const T& get_from_compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))\
{\
static const T result = compute<N>();\
return result;\
}\
/* public getters come next */\
public:\
- static inline T get(const mpl::int_<construct_from_string>&)\
+ static inline const T& get(const mpl::int_<construct_from_string>&)\
{\
constant_initializer<T, & BOOST_JOIN(constant_, name)<T>::get_from_string >::force_instantiate();\
return get_from_string();\
@@ -188,7 +197,7 @@
{ return x; }\
static inline BOOST_CONSTEXPR T get(const mpl::int_<construct_from_long_double>&)\
{ return BOOST_JOIN(x, L); }\
- template <int N> static inline T get(const mpl::int_<N>&)\
+ template <int N> static inline const T& get(const mpl::int_<N>&)\
{\
constant_initializer2<T, N, & BOOST_JOIN(constant_, name)<T>::template get_from_compute<N> >::force_instantiate();\
return get_from_compute<N>(); \
@@ -201,9 +210,9 @@
\
\
/* The actual forwarding function: */ \
- template <class T, class Policy> inline BOOST_CONSTEXPR T name(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T) BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(Policy))\
+ template <class T, class Policy> inline BOOST_CONSTEXPR typename detail::constant_return<T, Policy>::type name(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T) BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(Policy))\
{ return detail:: BOOST_JOIN(constant_, name)<T>::get(typename construction_traits<T, Policy>::type()); }\
- template <class T> inline BOOST_CONSTEXPR T name(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T))\
+ template <class T> inline BOOST_CONSTEXPR typename detail::constant_return<T>::type name(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T))\
{ return name<T, boost::math::policies::policy<> >(); }\
\
\
Modified: trunk/libs/math/test/test_constants.cpp
==============================================================================
--- trunk/libs/math/test/test_constants.cpp (original)
+++ trunk/libs/math/test/test_constants.cpp 2013-01-22 07:16:51 EST (Tue, 22 Jan 2013)
@@ -40,9 +40,20 @@
// forces the precision of the policy to be greater than
// that of a long double, and therefore triggers different code (construct from string).
typedef boost::math::policies::policy<boost::math::policies::digits2<std::numeric_limits<long double>::digits + 2> > real_concept_policy_2;
+// Policy with precision greater than the string representations, forces computation of values (i.e. different code path):
+typedef boost::math::policies::policy<boost::math::policies::digits2<400> > real_concept_policy_3;
BOOST_STATIC_ASSERT((boost::is_same<boost::math::constants::construction_traits<boost::math::concepts::real_concept, real_concept_policy_1 >::type, boost::mpl::int_<(sizeof(double) == sizeof(long double) ? boost::math::constants::construct_from_double : boost::math::constants::construct_from_long_double) > >::value));
BOOST_STATIC_ASSERT((boost::is_same<boost::math::constants::construction_traits<boost::math::concepts::real_concept, real_concept_policy_2 >::type, boost::mpl::int_<boost::math::constants::construct_from_string> >::value));
+BOOST_STATIC_ASSERT((boost::math::constants::construction_traits<boost::math::concepts::real_concept, real_concept_policy_3>::type::value >= 5));
+
+#ifndef BOOST_NO_CXX11_CONSTEXPR
+
+constexpr float fval = boost::math::constants::pi<float>();
+constexpr double dval = boost::math::constants::pi<double>();
+constexpr long double ldval = boost::math::constants::pi<long double>();
+
+#endif
// We need to declare a conceptual type whose precision is unknown at
// compile time, and is so enormous when checked at runtime,
@@ -605,6 +616,8 @@
using boost::math::concepts::real_concept;
boost::math::concepts::real_concept tolerance = boost::math::tools::epsilon<real_concept>() * 2; // double
+ if(Policy::precision_type::value > 200)
+ tolerance *= 50;
std::cout << "Tolerance for type " << typeid(real_concept).name() << " is " << tolerance << "." << std::endl;
//typedef typename boost::math::policies::precision<boost::math::concepts::real_concept, boost::math::policies::policy<> >::type t1;
@@ -748,6 +761,7 @@
test_real_concept_policy(real_concept_policy_1());
test_real_concept_policy(real_concept_policy_2()); // Increased precision forcing construction from string.
+ test_real_concept_policy(real_concept_policy_3()); // Increased precision forcing caching of computed values.
test_real_concept_policy(boost::math::policies::policy<>()); // Default.
// (Parameter value, arbitrarily zero, only communicates the floating-point type).
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk