WPILibC++ 2023.4.3
log.hpp
Go to the documentation of this file.
1/*################################################################################
2 ##
3 ## Copyright (C) 2016-2022 Keith O'Hara
4 ##
5 ## This file is part of the GCE-Math C++ library.
6 ##
7 ## Licensed under the Apache License, Version 2.0 (the "License");
8 ## you may not use this file except in compliance with the License.
9 ## You may obtain a copy of the License at
10 ##
11 ## http://www.apache.org/licenses/LICENSE-2.0
12 ##
13 ## Unless required by applicable law or agreed to in writing, software
14 ## distributed under the License is distributed on an "AS IS" BASIS,
15 ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 ## See the License for the specific language governing permissions and
17 ## limitations under the License.
18 ##
19 ################################################################################*/
20
21/*
22 * compile-time natural logarithm function
23 */
24
25#ifndef _gcem_log_HPP
26#define _gcem_log_HPP
27
28namespace internal
29{
30
31// continued fraction seems to be a better approximation for small x
32// see http://functions.wolfram.com/ElementaryFunctions/Log/10/0005/
33
34template<typename T>
35constexpr
36T
37log_cf_main(const T xx, const int depth)
38noexcept
39{
40 return( depth < GCEM_LOG_MAX_ITER_SMALL ? \
41 // if
42 T(2*depth - 1) - T(depth*depth)*xx/log_cf_main(xx,depth+1) :
43 // else
44 T(2*depth - 1) );
45}
46
47template<typename T>
48constexpr
49T
50log_cf_begin(const T x)
51noexcept
52{
53 return( T(2)*x/log_cf_main(x*x,1) );
54}
55
56template<typename T>
57constexpr
58T
59log_main(const T x)
60noexcept
61{
62 return( log_cf_begin((x - T(1))/(x + T(1))) );
63}
64
65constexpr
66long double
68noexcept
69{
70 return( x == 2 ? 0.6931471805599453094172321214581765680755L :
71 x == 3 ? 1.0986122886681096913952452369225257046475L :
72 x == 4 ? 1.3862943611198906188344642429163531361510L :
73 x == 5 ? 1.6094379124341003746007593332261876395256L :
74 x == 6 ? 1.7917594692280550008124773583807022727230L :
75 x == 7 ? 1.9459101490553133051053527434431797296371L :
76 x == 8 ? 2.0794415416798359282516963643745297042265L :
77 x == 9 ? 2.1972245773362193827904904738450514092950L :
78 x == 10 ? 2.3025850929940456840179914546843642076011L :
79 0.0L );
80}
81
82template<typename T>
83constexpr
84T
85log_mantissa(const T x)
86noexcept
87{ // divide by the integer part of x, which will be in [1,10], then adjust using tables
88 return( log_main(x/T(static_cast<int>(x))) + T(log_mantissa_integer(static_cast<int>(x))) );
89}
90
91template<typename T>
92constexpr
93T
94log_breakup(const T x)
95noexcept
96{ // x = a*b, where b = 10^c
97 return( log_mantissa(mantissa(x)) + T(GCEM_LOG_10)*T(find_exponent(x,0)) );
98}
99
100template<typename T>
101constexpr
102T
103log_check(const T x)
104noexcept
105{
106 return( is_nan(x) ? \
107 GCLIM<T>::quiet_NaN() :
108 // x < 0
109 x < T(0) ? \
110 GCLIM<T>::quiet_NaN() :
111 // x ~= 0
112 GCLIM<T>::min() > x ? \
113 - GCLIM<T>::infinity() :
114 // indistinguishable from 1
115 GCLIM<T>::min() > abs(x - T(1)) ? \
116 T(0) :
117 //
118 x == GCLIM<T>::infinity() ? \
119 GCLIM<T>::infinity() :
120 // else
121 (x < T(0.5) || x > T(1.5)) ?
122 // if
123 log_breakup(x) :
124 // else
125 log_main(x) );
126}
127
128template<typename T>
129constexpr
130return_t<T>
132noexcept
133{
134 return( std::is_integral<T>::value ? \
135 x == T(0) ? \
136 - GCLIM<return_t<T>>::infinity() :
137 x > T(1) ? \
138 log_check( static_cast<return_t<T>>(x) ) :
139 static_cast<return_t<T>>(0) :
140 log_check( static_cast<return_t<T>>(x) ) );
141}
142
143}
144
145/**
146 * Compile-time natural logarithm function
147 *
148 * @param x a real-valued input.
149 * @return \f$ \log_e(x) \f$ using \f[ \log\left(\frac{1+x}{1-x}\right) = \dfrac{2x}{1-\dfrac{x^2}{3-\dfrac{4x^2}{5 - \dfrac{9x^3}{7 - \ddots}}}}, \ \ x \in [-1,1] \f]
150 * The continued fraction argument is split into two parts: \f$ x = a \times 10^c \f$, where \f$ c \f$ is an integer.
151 */
152
153template<typename T>
154constexpr
155return_t<T>
156log(const T x)
157noexcept
158{
160}
161
162#endif
#define GCEM_LOG_MAX_ITER_SMALL
Definition: gcem_options.hpp:153
#define GCEM_LOG_10
Definition: gcem_options.hpp:94
UnitType abs(const UnitType x) noexcept
Compute absolute value.
Definition: math.h:721
constexpr return_t< T > log(const T x) noexcept
Compile-time natural logarithm function.
Definition: log.hpp:156
constexpr common_t< T1, T2 > min(const T1 x, const T2 y) noexcept
Compile-time pairwise minimum function.
Definition: min.hpp:35
std::numeric_limits< T > GCLIM
Definition: gcem_options.hpp:74
Definition: Eigen_Colamd.h:50
constexpr T log_cf_begin(const T x) noexcept
Definition: log.hpp:50
constexpr bool is_nan(const T x) noexcept
Definition: is_nan.hpp:36
constexpr llint_t find_exponent(const T x, const llint_t exponent) noexcept
Definition: find_exponent.hpp:34
constexpr T log_main(const T x) noexcept
Definition: log.hpp:59
constexpr long double log_mantissa_integer(const int x) noexcept
Definition: log.hpp:67
constexpr T log_check(const T x) noexcept
Definition: log.hpp:103
constexpr T mantissa(const T x) noexcept
Definition: mantissa.hpp:34
constexpr T log_breakup(const T x) noexcept
Definition: log.hpp:94
constexpr return_t< T > log_integral_check(const T x) noexcept
Definition: log.hpp:131
constexpr T log_mantissa(const T x) noexcept
Definition: log.hpp:85
constexpr T log_cf_main(const T xx, const int depth) noexcept
Definition: log.hpp:37