
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Barend Gehrels Sent: Thursday, December 08, 2011 7:22 PM To: boost@lists.boost.org Subject: Re: [boost] Boost.Math and Math Constants
On 8-12-2011 11:19, John Maddock wrote:
Nice. But actually I need something else too. I don't think I mailed this earlier so I use this announcement to describe this additional wish/suggestion shortly.
pi<Real>() is a macro/function, but there should be a structure behind. If I want to use a templated user defined type, such as ttmath (I'm a fan of that library), I'm stuck (unless I oversee something). Because it boost::math::constants::pi<T> cannot be partially specialized because it is a function.
Ah yes, the functions can only be fully specialized, and yes we could relatively easily add a struct layer in behind the function.
That would be perfect!
John has worked more macro magic, so that the effect a that Boost constant macro like BOOST_DEFINE_MATH_CONSTANT(pi, 3.141592653589793238462643383279502884, 1971693993751058209749445923078164062862089986280348253421170679821480865, 0); for pi now generates a struct so partial specialization is now possible as Barend requested. The C++ that this produces is show below (and will be in the Boost.Math docs), but we'd just like to check that this meets your needs/suggestion. (An example of using this with ttmath would be nice for the docs? Could provide one?) Paul // Preprocessed pi constant, annotated. namespace boost { namespace math { namespace constants { namespace detail { template <class T> struct constant_pi { private: // Default implementations from string of decimal digits: static inline T get_from_string() { static const T result = detail::convert_from_string<T>("3.141592653589793238462643383279502884197169399375105820974944592307 81640628620899862803482534211706798214808651e+00", boost::is_convertible<const char*, T>()); return result; } template <int N> static T compute(); public: // Default implementations from string of decimal digits: static inline T get(const mpl::int_<construct_from_string>&) { constant_initializer<T, & constant_pi<T>::get_from_string >::do_nothing(); return get_from_string(); } // Float, double and long double versions: static inline T get(const mpl::int_<construct_from_float>) { return 3.141592653589793238462643383279502884e+00F; } static inline T get(const mpl::int_<construct_from_double>&) { return 3.141592653589793238462643383279502884e+00; } static inline T get(const mpl::int_<construct_from_long_double>&) { return 3.141592653589793238462643383279502884e+00L; } // For very high precision that is nonetheless can be calculated at compile time: template <int N> static inline T get(const mpl::int_<N>& n) { constant_initializer2<T, N, & constant_pi<T>::template compute<N> >::do_nothing(); return compute<N>(); } //For true arbitrary precision, which may well vary at runtime. static inline T get(const mpl::int_<0>&) { return tools::digits<T>() > max_string_digits ? compute<0>() : get(mpl::int_<construct_from_string>()); } }; // template <class T> struct constant_pi } // namespace detail // The actual forwarding function (including policy to control precision). template <class T, class Policy> inline T pi( ) { return detail:: constant_pi<T>::get(typename construction_traits<T, Policy>::type()); } // The actual forwarding function (using default policy to control precision). template <class T> inline T pi() { return pi<T, boost::math::policies::policy<> >() } } // namespace constants // Namespace specific versions, for the three built-in floats: namespace float_constants { static const float pi = 3.141592653589793238462643383279502884e+00F; } namespace double_constants { static const double pi = 3.141592653589793238462643383279502884e+00; } namespace long_double_constants { static const long double pi = 3.141592653589793238462643383279502884e+00L; } namespace constants{; } // namespace constants } // namespace math } // namespace boost