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.
williamr@2
     1
//  (C) Copyright John Maddock 2005.
williamr@2
     2
//  Use, modification and distribution are subject to the
williamr@2
     3
//  Boost Software License, Version 1.0. (See accompanying file
williamr@2
     4
//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
williamr@2
     5
williamr@2
     6
#ifndef BOOST_MATH_LOG1P_INCLUDED
williamr@2
     7
#define BOOST_MATH_LOG1P_INCLUDED
williamr@2
     8
williamr@2
     9
#include <cmath>
williamr@2
    10
#include <math.h> // platform's ::log1p
williamr@2
    11
#include <boost/limits.hpp>
williamr@2
    12
#include <boost/math/special_functions/detail/series.hpp>
williamr@2
    13
williamr@2
    14
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
williamr@2
    15
#  include <boost/static_assert.hpp>
williamr@2
    16
#else
williamr@2
    17
#  include <boost/assert.hpp>
williamr@2
    18
#endif
williamr@2
    19
williamr@2
    20
#ifdef BOOST_NO_STDC_NAMESPACE
williamr@2
    21
namespace std{ using ::fabs; using ::log; }
williamr@2
    22
#endif
williamr@2
    23
williamr@2
    24
williamr@2
    25
namespace boost{ namespace math{
williamr@2
    26
williamr@2
    27
namespace detail{
williamr@2
    28
williamr@2
    29
//
williamr@2
    30
// Functor log1p_series returns the next term in the Taylor series
williamr@2
    31
// pow(-1, k-1)*pow(x, k) / k
williamr@2
    32
// each time that operator() is invoked.
williamr@2
    33
//
williamr@2
    34
template <class T>
williamr@2
    35
struct log1p_series
williamr@2
    36
{
williamr@2
    37
   typedef T result_type;
williamr@2
    38
williamr@2
    39
   log1p_series(T x)
williamr@2
    40
      : k(0), m_mult(-x), m_prod(-1){}
williamr@2
    41
williamr@2
    42
   T operator()()
williamr@2
    43
   {
williamr@2
    44
      m_prod *= m_mult;
williamr@2
    45
      return m_prod / ++k; 
williamr@2
    46
   }
williamr@2
    47
williamr@2
    48
   int count()const
williamr@2
    49
   {
williamr@2
    50
      return k;
williamr@2
    51
   }
williamr@2
    52
williamr@2
    53
private:
williamr@2
    54
   int k;
williamr@2
    55
   const T m_mult;
williamr@2
    56
   T m_prod;
williamr@2
    57
   log1p_series(const log1p_series&);
williamr@2
    58
   log1p_series& operator=(const log1p_series&);
williamr@2
    59
};
williamr@2
    60
williamr@2
    61
} // namespace
williamr@2
    62
williamr@2
    63
//
williamr@2
    64
// Algorithm log1p is part of C99, but is not yet provided by many compilers.
williamr@2
    65
//
williamr@2
    66
// This version uses a Taylor series expansion for 0.5 > x > epsilon, which may
williamr@2
    67
// require up to std::numeric_limits<T>::digits+1 terms to be calculated.  It would
williamr@2
    68
// be much more efficient to use the equivalence:
williamr@2
    69
// log(1+x) == (log(1+x) * x) / ((1-x) - 1)
williamr@2
    70
// Unfortunately optimizing compilers make such a mess of this, that it performs
williamr@2
    71
// no better than log(1+x): which is to say not very well at all.
williamr@2
    72
//
williamr@2
    73
template <class T>
williamr@2
    74
T log1p(T x)
williamr@2
    75
{
williamr@2
    76
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
williamr@2
    77
   BOOST_STATIC_ASSERT(::std::numeric_limits<T>::is_specialized);
williamr@2
    78
#else
williamr@2
    79
   BOOST_ASSERT(std::numeric_limits<T>::is_specialized);
williamr@2
    80
#endif
williamr@2
    81
   T a = std::fabs(x);
williamr@2
    82
   if(a > T(0.5L))
williamr@2
    83
      return std::log(T(1.0) + x);
williamr@2
    84
   if(a < std::numeric_limits<T>::epsilon())
williamr@2
    85
      return x;
williamr@2
    86
   detail::log1p_series<T> s(x);
williamr@2
    87
   return detail::kahan_sum_series(s, std::numeric_limits<T>::digits + 2);
williamr@2
    88
}
williamr@2
    89
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
williamr@2
    90
// these overloads work around a type deduction bug:
williamr@2
    91
inline float log1p(float z)
williamr@2
    92
{
williamr@2
    93
   return log1p<float>(z);
williamr@2
    94
}
williamr@2
    95
inline double log1p(double z)
williamr@2
    96
{
williamr@2
    97
   return log1p<double>(z);
williamr@2
    98
}
williamr@2
    99
inline long double log1p(long double z)
williamr@2
   100
{
williamr@2
   101
   return log1p<long double>(z);
williamr@2
   102
}
williamr@2
   103
#endif
williamr@2
   104
williamr@2
   105
#ifdef log1p
williamr@2
   106
#  ifndef BOOST_HAS_LOG1P
williamr@2
   107
#     define BOOST_HAS_LOG1P
williamr@2
   108
#  endif
williamr@2
   109
#  undef log1p
williamr@2
   110
#endif
williamr@2
   111
williamr@2
   112
#ifdef BOOST_HAS_LOG1P
williamr@2
   113
#  if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)
williamr@2
   114
inline float log1p(float x){ return ::log1pf(x); }
williamr@2
   115
inline long double log1p(long double x){ return ::log1pl(x); }
williamr@2
   116
#else
williamr@2
   117
inline float log1p(float x){ return ::log1p(x); }
williamr@2
   118
#endif
williamr@2
   119
inline double log1p(double x){ return ::log1p(x); }
williamr@2
   120
#endif
williamr@2
   121
williamr@2
   122
} } // namespaces
williamr@2
   123
williamr@2
   124
#endif // BOOST_MATH_HYPOT_INCLUDED