Boost logo

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