Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Use With User-Defined Types

The most common example of a high-precision user-defined type will probably be Boost.Multiprecision.

The syntax for using the function-call constants with user-defined types is the same as it is in the template class, which is to say we use:

#include <boost/math/constants/constants.hpp>

boost::math::constants::pi<UserDefinedType>();

For example:

boost::math::constants::pi<boost::multiprecision::cpp_dec_float_50>();

giving π with a precision of 50 decimal digits.

However, since the precision of the user-defined type may be much greater than that of the built-in floating point types, how the value returned is created is as follows:

In addition, it is possible to pass a Policy type as a second template argument, and use this to control the precision:

#include <boost/math/constants/constants.hpp>

typedef boost::math::policies::policy<boost::math::policies::digits2<80> > my_policy_type;
boost::math::constants::pi<MyType, my_policy_type>();
[Note] Note

Boost.Math doesn't know how to control the internal precision of MyType, the policy just controls how the selection process above is carried out, and the calculation precision if the result is computed.

It is also possible to control which method is used to construct the constant by specialising the traits class construction_traits:

namespace boost{ namespace math{ namespace constant{

template <class T, class Policy>
struct construction_traits
{
   typedef boost::integral_constant<int, N> type;
};

}}} // namespaces

Where N takes one of the following values:

N

Meaning

0

The precision is unavailable at compile time; either construct from a decimal digit string or calculate on the fly depending upon the runtime precision.

1

Return a float precision constant.

2

Return a double precision constant.

3

Return a long double precision constant.

4

Construct the result from the string representation, and cache the result.

Any other value N

Sets the compile time precision to N bits.

Custom Specializing a constant

In addition, for user-defined types that need special handling, it's possible to partially-specialize the internal structure used by each constant. For example, suppose we're using the C++ wrapper around MPFR mpfr_class: this has its own representation of Pi which we may well wish to use in place of the above mechanism. We can achieve this by specialising the class template boost::math::constants::detail::constant_pi:

namespace boost{ namespace math{ namespace constants{ namespace detail{

template<>
struct constant_pi<mpfr_class>
{
   template<int N>
   static mpfr_class get(const boost::integral_constant<int, N>&)
   {
      // The template param N is one of the values in the table above,
      // we can either handle all cases in one as is the case here,
      // or overload "get" for the different options.
      mpfr_class result;
      mpfr_const_pi(result.get_mpfr_t(), GMP_RNDN);
      return result;
   }
};

}}}} // namespaces
Diagnosing what meta-programmed code is doing

Finally, since it can be tricky to diagnose what meta-programmed code is doing, there is a diagnostic routine that prints information about how this library will handle a specific type, it can be used like this:

#include <boost/math/constants/info.hpp>

int main()
{
   boost::math::constants::print_info_on_type<MyType>();
}

If you wish, you can also pass an optional std::ostream argument to the print_info_on_type function. Typical output for a user-defined type looks like this:

Information on the Implementation and Handling of
Mathematical Constants for Type class boost::math::concepts::real_concept

Checking for std::numeric_limits<class boost::math::concepts::real_concept> specialisation: no
boost::math::policies::precision<class boost::math::concepts::real_concept, Policy>
reports that there is no compile type precision available.
boost::math::tools::digits<class boost::math::concepts::real_concept>()
reports that the current runtime precision is
53 binary digits.
No compile time precision is available, the construction method
will be decided at runtime and results will not be cached
- this may lead to poor runtime performance.
Current runtime precision indicates that
the constant will be constructed from a string on each call.

PrevUpHomeNext