Imported Upstream version 1.57.0
[platform/upstream/boost.git] / boost / math / constants / constants.hpp
index bb2260e..e9381ad 100644 (file)
@@ -14,7 +14,9 @@
 #pragma warning(push)
 #pragma warning(disable: 4127 4701)
 #endif
+#ifndef BOOST_MATH_NO_LEXICAL_CAST
 #include <boost/lexical_cast.hpp>
+#endif
 #ifdef BOOST_MSVC
 #pragma warning(pop)
 #endif
 #include <boost/mpl/and.hpp>
 #include <boost/mpl/int.hpp>
 #include <boost/type_traits/is_convertible.hpp>
+#include <boost/utility/declval.hpp>
+
 
 namespace boost{ namespace math
 {
   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.
@@ -46,7 +50,33 @@ namespace boost{ namespace math
       construct_from_float = 1,
       construct_from_double = 2,
       construct_from_long_double = 3,
-      construct_from_string = 4
+      construct_from_string = 4,
+      construct_from_float128 = 5,
+      // Must be the largest value above:
+      construct_max = construct_from_float128
+   };
+
+   //
+   // Traits class determines how to convert from string based on whether T has a constructor
+   // from const char* or not:
+   //
+   template <int N>
+   struct dummy_size{};
+
+   template <class T>
+   struct is_explicitly_convertible_from_string
+   {
+#ifndef BOOST_NO_SFINAE_EXPR
+      template<typename S1, typename T1>
+      static type_traits::yes_type selector(dummy_size<sizeof(static_cast<T1>(declval<S1>()))>*);
+
+      template<typename S1, typename T1>
+      static type_traits::no_type selector(...);
+
+      static const bool value = sizeof(selector<const char*, T>(0)) == sizeof(type_traits::yes_type);
+#else
+      static const bool value = false;
+#endif
    };
 
    //
@@ -63,6 +93,9 @@ namespace boost{ namespace math
       typedef typename policies::precision<float, Policy>::type t2;
       typedef typename policies::precision<double, Policy>::type t3;
       typedef typename policies::precision<long double, Policy>::type t4;
+#ifdef BOOST_MATH_USE_FLOAT128
+      typedef mpl::int_<113> t5;
+#endif
    public:
       typedef typename mpl::if_<
          mpl::and_<boost::is_convertible<float, Real>, mpl::bool_< t1::value <= t2::value>, mpl::bool_<0 != t1::value> >,
@@ -73,11 +106,23 @@ namespace boost{ namespace math
             typename mpl::if_<
                mpl::and_<boost::is_convertible<long double, Real>, mpl::bool_< t1::value <= t4::value>, mpl::bool_<0 != t1::value> >,
                mpl::int_<construct_from_long_double>,
+#ifdef BOOST_MATH_USE_FLOAT128
+               typename mpl::if_<
+               mpl::and_<boost::is_convertible<BOOST_MATH_FLOAT128_TYPE, Real>, mpl::bool_< t1::value <= t5::value>, mpl::bool_<0 != t1::value> >,
+                  mpl::int_<construct_from_float128>,
+                  typename mpl::if_<
+                     mpl::and_<mpl::bool_< t1::value <= max_string_digits>, mpl::bool_<0 != t1::value> >,
+                     mpl::int_<construct_from_string>,
+                     mpl::int_<t1::value>
+                  >::type
+               >::type
+#else
                typename mpl::if_<
                   mpl::and_<mpl::bool_< t1::value <= max_string_digits>, mpl::bool_<0 != t1::value> >,
                   mpl::int_<construct_from_string>,
                   mpl::int_<t1::value>
                >::type
+#endif
             >::type
          >::type
       >::type type;
@@ -93,10 +138,24 @@ namespace boost{ namespace math
 
    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) || (construct_type::value > construct_max),
+            const Real&, Real>::type type;
+      };
+
       template <class Real>
       Real convert_from_string(const char* p, const mpl::false_&)
       {
+#ifdef BOOST_MATH_NO_LEXICAL_CAST
+         // This function should not compile, we don't have the necesary functionality to support it:
+         BOOST_STATIC_ASSERT(sizeof(Real) == 0);
+#else
          return boost::lexical_cast<Real>(p);
+#endif
       }
       template <class Real>
       const char* convert_from_string(const char* p, const mpl::true_&)
@@ -104,7 +163,7 @@ namespace boost{ namespace math
          return p;
       }
 
-      template <class T, T (*F)(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(T))>
+      template <class T, const T& (*F)()>
       struct constant_initializer
       {
          static void force_instantiate()
@@ -116,21 +175,17 @@ namespace boost{ namespace math
          {
             initializer()
             {
-               F(
-      #ifdef BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS
-                  0
-      #endif
-                  );
+               F();
             }
             void force_instantiate()const{}
          };
          static const initializer init;
       };
 
-      template <class T, T (*F)(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(T))>
+      template <class T, const T& (*F)()>
       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()
@@ -142,37 +197,47 @@ namespace boost{ namespace math
          {
             initializer()
             {
-               F(
-      #ifdef BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS
-                  mpl::int_<N>() , 0
-      #endif
-                  );
+               F();
             }
             void force_instantiate()const{}
          };
          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;
 
    }
 
-   #define BOOST_DEFINE_MATH_CONSTANT(name, x, y)\
+#ifdef BOOST_MATH_USE_FLOAT128
+#  define BOOST_MATH_FLOAT128_CONSTANT_OVERLOAD(x) \
+   static inline BOOST_CONSTEXPR T get(const mpl::int_<construct_from_float128>&)\
+   { return BOOST_JOIN(x, Q); }
+#else
+#  define BOOST_MATH_FLOAT128_CONSTANT_OVERLOAD(x)
+#endif
+
+#define BOOST_DEFINE_MATH_CONSTANT(name, x, y)\
    namespace detail{\
    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>());\
+      typedef mpl::bool_<boost::is_convertible<const char*, T>::value || boost::math::constants::is_explicitly_convertible_from_string<T>::value> tag_type;\
+      static const T result(convert_from_string<T>(y, tag_type()));\
       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 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();\
@@ -183,10 +248,11 @@ namespace boost{ namespace math
    { 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>& n)\
+   BOOST_MATH_FLOAT128_CONSTANT_OVERLOAD(x) \
+   template <int N> static inline const T& get(const mpl::int_<N>&)\
    {\
-      constant_initializer2<T, N, & BOOST_JOIN(constant_, name)<T>::template compute<N> >::force_instantiate();\
-      return compute<N>(); \
+      constant_initializer2<T, N, & BOOST_JOIN(constant_, name)<T>::template get_from_compute<N> >::force_instantiate();\
+      return get_from_compute<N>(); \
    }\
    /* This one is for true arbitary precision, which may well vary at runtime: */ \
    static inline T get(const mpl::int_<0>&)\
@@ -196,9 +262,9 @@ namespace boost{ namespace math
    \
    \
    /* 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<> >(); }\
    \
    \
@@ -233,11 +299,12 @@ namespace boost{ namespace math
   BOOST_DEFINE_MATH_CONSTANT(root_pi, 1.772453850905516027298167483341145182e+00, "1.77245385090551602729816748334114518279754945612238712821380778985291128459103218137495065673854466541622682362e+00")
   BOOST_DEFINE_MATH_CONSTANT(root_half_pi, 1.253314137315500251207882642405522626e+00, "1.25331413731550025120788264240552262650349337030496915831496178817114682730392098747329791918902863305800498633e+00")
   BOOST_DEFINE_MATH_CONSTANT(root_two_pi, 2.506628274631000502415765284811045253e+00, "2.50662827463100050241576528481104525300698674060993831662992357634229365460784197494659583837805726611600997267e+00")
+  BOOST_DEFINE_MATH_CONSTANT(log_root_two_pi, 9.189385332046727417803297364056176398e-01, "9.18938533204672741780329736405617639861397473637783412817151540482765695927260397694743298635954197622005646625e-01")
   BOOST_DEFINE_MATH_CONSTANT(one_div_root_pi, 5.641895835477562869480794515607725858e-01, "5.64189583547756286948079451560772585844050629328998856844085721710642468441493414486743660202107363443028347906e-01")
   BOOST_DEFINE_MATH_CONSTANT(root_one_div_pi, 5.641895835477562869480794515607725858e-01, "5.64189583547756286948079451560772585844050629328998856844085721710642468441493414486743660202107363443028347906e-01")
   BOOST_DEFINE_MATH_CONSTANT(pi_minus_three, 1.415926535897932384626433832795028841e-01, "1.41592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513e-01")
   BOOST_DEFINE_MATH_CONSTANT(four_minus_pi, 8.584073464102067615373566167204971158e-01, "8.58407346410206761537356616720497115802830600624894179025055407692183593713791001371965174657882932017851913487e-01")
-  BOOST_DEFINE_MATH_CONSTANT(pow23_four_minus_pi, 7.953167673715975443483953350568065807e-01, "7.95316767371597544348395335056806580727639173327713205445302234388856268267518187590758006888600828436839800178e-01")
+  //BOOST_DEFINE_MATH_CONSTANT(pow23_four_minus_pi, 7.953167673715975443483953350568065807e-01, "7.95316767371597544348395335056806580727639173327713205445302234388856268267518187590758006888600828436839800178e-01")
   BOOST_DEFINE_MATH_CONSTANT(pi_pow_e, 2.245915771836104547342715220454373502e+01, "2.24591577183610454734271522045437350275893151339966922492030025540669260403991179123185197527271430315314500731e+01")
   BOOST_DEFINE_MATH_CONSTANT(pi_sqr, 9.869604401089358618834490999876151135e+00, "9.86960440108935861883449099987615113531369940724079062641334937622004482241920524300177340371855223182402591377e+00")
   BOOST_DEFINE_MATH_CONSTANT(pi_sqr_div_six, 1.644934066848226436472415166646025189e+00, "1.64493406684822643647241516664602518921894990120679843773555822937000747040320087383362890061975870530400431896e+00")
@@ -272,7 +339,7 @@ namespace boost{ namespace math
   BOOST_DEFINE_MATH_CONSTANT(rayleigh_skewness, 6.311106578189371381918993515442277798e-01, "6.31110657818937138191899351544227779844042203134719497658094585692926819617473725459905027032537306794400047264e-01")
   BOOST_DEFINE_MATH_CONSTANT(rayleigh_kurtosis, 3.245089300687638062848660410619754415e+00, "3.24508930068763806284866041061975441541706673178920936177133764493367904540874159051490619368679348977426462633e+00")
   BOOST_DEFINE_MATH_CONSTANT(rayleigh_kurtosis_excess, 2.450893006876380628486604106197544154e-01, "2.45089300687638062848660410619754415417066731789209361771337644933679045408741590514906193686793489774264626328e-01")
-  
+
   BOOST_DEFINE_MATH_CONSTANT(two_div_pi, 6.366197723675813430755350534900574481e-01, "6.36619772367581343075535053490057448137838582961825794990669376235587190536906140360455211065012343824291370907e-01")
   BOOST_DEFINE_MATH_CONSTANT(root_two_div_pi, 7.978845608028653558798921198687637369e-01, "7.97884560802865355879892119868763736951717262329869315331851659341315851798603677002504667814613872860605117725e-01")