epoc32/include/stdapis/boost/math/special_functions/expm1.hpp
author William Roberts <williamr@symbian.org>
Tue, 16 Mar 2010 16:12:26 +0000
branchSymbian2
changeset 2 2fe1408b6811
permissions -rw-r--r--
Final list of Symbian^2 public API header files
     1 //  (C) Copyright John Maddock 2005.
     2 //  Use, modification and distribution are subject to the
     3 //  Boost Software License, Version 1.0. (See accompanying file
     4 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
     5 
     6 #ifndef BOOST_MATH_EXPM1_INCLUDED
     7 #define BOOST_MATH_EXPM1_INCLUDED
     8 
     9 #include <cmath>
    10 #include <math.h> // platform's ::expm1
    11 #include <boost/limits.hpp>
    12 #include <boost/math/special_functions/detail/series.hpp>
    13 
    14 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
    15 #  include <boost/static_assert.hpp>
    16 #else
    17 #  include <boost/assert.hpp>
    18 #endif
    19 
    20 #ifdef BOOST_NO_STDC_NAMESPACE
    21 namespace std{ using ::exp; using ::fabs; }
    22 #endif
    23 
    24 
    25 namespace boost{ namespace math{
    26 
    27 namespace detail{
    28 //
    29 // Functor expm1_series returns the next term in the Taylor series
    30 // x^k / k!
    31 // each time that operator() is invoked.
    32 //
    33 template <class T>
    34 struct expm1_series
    35 {
    36    typedef T result_type;
    37 
    38    expm1_series(T x)
    39       : k(0), m_x(x), m_term(1) {}
    40 
    41    T operator()()
    42    {
    43       ++k;
    44       m_term *= m_x;
    45       m_term /= k;
    46       return m_term; 
    47    }
    48 
    49    int count()const
    50    {
    51       return k;
    52    }
    53 
    54 private:
    55    int k;
    56    const T m_x;
    57    T m_term;
    58    expm1_series(const expm1_series&);
    59    expm1_series& operator=(const expm1_series&);
    60 };
    61 
    62 } // namespace
    63 
    64 //
    65 // Algorithm expm1 is part of C99, but is not yet provided by many compilers.
    66 //
    67 // This version uses a Taylor series expansion for 0.5 > |x| > epsilon.
    68 //
    69 template <class T>
    70 T expm1(T x)
    71 {
    72 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
    73    BOOST_STATIC_ASSERT(::std::numeric_limits<T>::is_specialized);
    74 #else
    75    BOOST_ASSERT(std::numeric_limits<T>::is_specialized);
    76 #endif
    77 
    78    T a = std::fabs(x);
    79    if(a > T(0.5L))
    80       return std::exp(x) - T(1);
    81    if(a < std::numeric_limits<T>::epsilon())
    82       return x;
    83    detail::expm1_series<T> s(x);
    84    T result = detail::kahan_sum_series(s, std::numeric_limits<T>::digits + 2);
    85    return result;
    86 }
    87 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
    88 inline float expm1(float z)
    89 {
    90    return expm1<float>(z);
    91 }
    92 inline double expm1(double z)
    93 {
    94    return expm1<double>(z);
    95 }
    96 inline long double expm1(long double z)
    97 {
    98    return expm1<long double>(z);
    99 }
   100 #endif
   101 
   102 #ifdef expm1
   103 #  ifndef BOOST_HAS_expm1
   104 #     define BOOST_HAS_expm1
   105 #  endif
   106 #  undef expm1
   107 #endif
   108 
   109 #ifdef BOOST_HAS_EXPM1
   110 #  if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)
   111 inline float expm1(float x){ return ::expm1f(x); }
   112 inline long double expm1(long double x){ return ::expm1l(x); }
   113 #else
   114 inline float expm1(float x){ return ::expm1(x); }
   115 #endif
   116 inline double expm1(double x){ return ::expm1(x); }
   117 #endif
   118 
   119 } } // namespaces
   120 
   121 #endif // BOOST_MATH_HYPOT_INCLUDED