epoc32/include/stdapis/boost/math/special_functions/log1p.hpp
author William Roberts <williamr@symbian.org>
Wed, 31 Mar 2010 12:33:34 +0100
branchSymbian3
changeset 4 837f303aceeb
permissions -rw-r--r--
Current Symbian^3 public API header files (from PDK 3.0.h)
This is the epoc32/include tree with the "platform" subtrees removed, and
all but a selected few mbg and rsg files removed.
     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_LOG1P_INCLUDED
     7 #define BOOST_MATH_LOG1P_INCLUDED
     8 
     9 #include <cmath>
    10 #include <math.h> // platform's ::log1p
    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 ::fabs; using ::log; }
    22 #endif
    23 
    24 
    25 namespace boost{ namespace math{
    26 
    27 namespace detail{
    28 
    29 //
    30 // Functor log1p_series returns the next term in the Taylor series
    31 // pow(-1, k-1)*pow(x, k) / k
    32 // each time that operator() is invoked.
    33 //
    34 template <class T>
    35 struct log1p_series
    36 {
    37    typedef T result_type;
    38 
    39    log1p_series(T x)
    40       : k(0), m_mult(-x), m_prod(-1){}
    41 
    42    T operator()()
    43    {
    44       m_prod *= m_mult;
    45       return m_prod / ++k; 
    46    }
    47 
    48    int count()const
    49    {
    50       return k;
    51    }
    52 
    53 private:
    54    int k;
    55    const T m_mult;
    56    T m_prod;
    57    log1p_series(const log1p_series&);
    58    log1p_series& operator=(const log1p_series&);
    59 };
    60 
    61 } // namespace
    62 
    63 //
    64 // Algorithm log1p is part of C99, but is not yet provided by many compilers.
    65 //
    66 // This version uses a Taylor series expansion for 0.5 > x > epsilon, which may
    67 // require up to std::numeric_limits<T>::digits+1 terms to be calculated.  It would
    68 // be much more efficient to use the equivalence:
    69 // log(1+x) == (log(1+x) * x) / ((1-x) - 1)
    70 // Unfortunately optimizing compilers make such a mess of this, that it performs
    71 // no better than log(1+x): which is to say not very well at all.
    72 //
    73 template <class T>
    74 T log1p(T x)
    75 {
    76 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
    77    BOOST_STATIC_ASSERT(::std::numeric_limits<T>::is_specialized);
    78 #else
    79    BOOST_ASSERT(std::numeric_limits<T>::is_specialized);
    80 #endif
    81    T a = std::fabs(x);
    82    if(a > T(0.5L))
    83       return std::log(T(1.0) + x);
    84    if(a < std::numeric_limits<T>::epsilon())
    85       return x;
    86    detail::log1p_series<T> s(x);
    87    return detail::kahan_sum_series(s, std::numeric_limits<T>::digits + 2);
    88 }
    89 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
    90 // these overloads work around a type deduction bug:
    91 inline float log1p(float z)
    92 {
    93    return log1p<float>(z);
    94 }
    95 inline double log1p(double z)
    96 {
    97    return log1p<double>(z);
    98 }
    99 inline long double log1p(long double z)
   100 {
   101    return log1p<long double>(z);
   102 }
   103 #endif
   104 
   105 #ifdef log1p
   106 #  ifndef BOOST_HAS_LOG1P
   107 #     define BOOST_HAS_LOG1P
   108 #  endif
   109 #  undef log1p
   110 #endif
   111 
   112 #ifdef BOOST_HAS_LOG1P
   113 #  if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)
   114 inline float log1p(float x){ return ::log1pf(x); }
   115 inline long double log1p(long double x){ return ::log1pl(x); }
   116 #else
   117 inline float log1p(float x){ return ::log1p(x); }
   118 #endif
   119 inline double log1p(double x){ return ::log1p(x); }
   120 #endif
   121 
   122 } } // namespaces
   123 
   124 #endif // BOOST_MATH_HYPOT_INCLUDED