Boost logo

Boost :

Subject: Re: [boost] Boost.Math and Math Constants
From: Paul A. Bristow (pbristow_at_[hidden])
Date: 2011-12-16 08:07:13


> -----Original Message-----
> From: boost-bounces_at_[hidden] [mailto:boost-bounces_at_[hidden]] On Behalf Of Barend
> Gehrels
> Sent: Thursday, December 08, 2011 7:22 PM
> To: boost_at_[hidden]
> 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


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk