|  | Home | Libraries | People | FAQ | More | 
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:
float and the type is constructable
                  from a float then
                  our code returns a float
                  literal. If the user-defined type is a literal type then the function
                  call that returns the constant will be a constexp.
                double and the type is constructable
                  from a double then
                  our code returns a double
                  literal. If the user-defined type is a literal type then the function
                  call that returns the constant will be a constexp.
                long double
                  and the type is constructable from a long
                  double then our code returns
                  a long double
                  literal. If the user-defined type is a literal type then the function
                  call that returns the constant will be a constexp.
                __float128 (and the compiler
                  supports such a type) and the type is constructable from a __float128 then our code returns
                  a __float128 literal.
                  If the user-defined type is a literal type then the function call
                  that returns the constant will be a constexp.
                boost::math::tools::digits<T>())
                  is less than 100 decimal digits, then the constant is constructed
                  "on the fly" from the string representation of the constant.
                
        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]](../../../../../../doc/src/images/note.png) | Note | 
|---|---|
| 
          Boost.Math doesn't know how to control the internal precision of  | 
        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 mpl::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. | 
        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 mpl::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
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.