WPILibC++ 2023.4.3-108-ge5452e3
atan.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 arctangent function
23 */
24
25// see
26// http://functions.wolfram.com/ElementaryFunctions/ArcTan/10/0001/
27// http://functions.wolfram.com/ElementaryFunctions/ArcTan/06/01/06/01/0002/
28
29#ifndef _gcem_atan_HPP
30#define _gcem_atan_HPP
31
32namespace internal
33{
34
35// Series
36
37template<typename T>
38constexpr
39T
40atan_series_order_calc(const T x, const T x_pow, const uint_t order)
41noexcept
42{
43 return( T(1)/( T((order-1)*4 - 1) * x_pow ) \
44 - T(1)/( T((order-1)*4 + 1) * x_pow*x) );
45}
46
47template<typename T>
48constexpr
49T
50atan_series_order(const T x, const T x_pow, const uint_t order, const uint_t max_order)
51noexcept
52{
53 return( order == 1 ? \
54 GCEM_HALF_PI - T(1)/x + atan_series_order(x*x,pow(x,3),order+1,max_order) :
55 // NOTE: x changes to x*x for order > 1
56 order < max_order ? \
57 atan_series_order_calc(x,x_pow,order) \
58 + atan_series_order(x,x_pow*x*x,order+1,max_order) :
59 // order == max_order
60 atan_series_order_calc(x,x_pow,order) );
61}
62
63template<typename T>
64constexpr
65T
67noexcept
68{
69 return( x < T(3) ? atan_series_order(x,x,1U,10U) : // O(1/x^39)
70 x < T(4) ? atan_series_order(x,x,1U,9U) : // O(1/x^35)
71 x < T(5) ? atan_series_order(x,x,1U,8U) : // O(1/x^31)
72 x < T(7) ? atan_series_order(x,x,1U,7U) : // O(1/x^27)
73 x < T(11) ? atan_series_order(x,x,1U,6U) : // O(1/x^23)
74 x < T(25) ? atan_series_order(x,x,1U,5U) : // O(1/x^19)
75 x < T(100) ? atan_series_order(x,x,1U,4U) : // O(1/x^15)
76 x < T(1000) ? atan_series_order(x,x,1U,3U) : // O(1/x^11)
77 atan_series_order(x,x,1U,2U) ); // O(1/x^7)
78}
79
80// CF
81
82template<typename T>
83constexpr
84T
85atan_cf_recur(const T xx, const uint_t depth, const uint_t max_depth)
86noexcept
87{
88 return( depth < max_depth ? \
89 // if
90 T(2*depth - 1) + depth*depth*xx/atan_cf_recur(xx,depth+1,max_depth) :
91 // else
92 T(2*depth - 1) );
93}
94
95template<typename T>
96constexpr
97T
98atan_cf_main(const T x)
99noexcept
100{
101 return( x < T(0.5) ? x/atan_cf_recur(x*x,1U, 15U ) :
102 x < T(1) ? x/atan_cf_recur(x*x,1U, 25U ) :
103 x < T(1.5) ? x/atan_cf_recur(x*x,1U, 35U ) :
104 x < T(2) ? x/atan_cf_recur(x*x,1U, 45U ) :
105 x/atan_cf_recur(x*x,1U, 52U ) );
106}
107
108//
109
110template<typename T>
111constexpr
112T
113atan_begin(const T x)
114noexcept
115{
116 return( x > T(2.5) ? atan_series_main(x) : atan_cf_main(x) );
117}
118
119template<typename T>
120constexpr
121T
122atan_check(const T x)
123noexcept
124{
125 return( // NaN check
126 is_nan(x) ? \
127 GCLIM<T>::quiet_NaN() :
128 // indistinguishable from zero
129 GCLIM<T>::min() > abs(x) ? \
130 T(0) :
131 // negative or positive
132 x < T(0) ? \
133 - atan_begin(-x) :
134 atan_begin( x) );
135}
136
137}
138
139/**
140 * Compile-time arctangent function
141 *
142 * @param x a real-valued input.
143 * @return the inverse tangent function using \f[ \text{atan}(x) = \dfrac{x}{1 + \dfrac{x^2}{3 + \dfrac{4x^2}{5 + \dfrac{9x^2}{7 + \ddots}}}} \f]
144 */
145
146template<typename T>
147constexpr
148return_t<T>
149atan(const T x)
150noexcept
151{
152 return internal::atan_check( static_cast<return_t<T>>(x) );
153}
154
155#endif
constexpr return_t< T > atan(const T x) noexcept
Compile-time arctangent function.
Definition: atan.hpp:149
#define GCEM_HALF_PI
Definition: gcem_options.hpp:118
UnitType abs(const UnitType x) noexcept
Compute absolute value.
Definition: math.h:721
constexpr common_t< T1, T2 > min(const T1 x, const T2 y) noexcept
Compile-time pairwise minimum function.
Definition: min.hpp:35
unsigned int uint_t
Definition: gcem_options.hpp:68
Definition: Eigen_Colamd.h:50
constexpr T atan_check(const T x) noexcept
Definition: atan.hpp:122
constexpr T atan_series_main(const T x) noexcept
Definition: atan.hpp:66
constexpr T atan_begin(const T x) noexcept
Definition: atan.hpp:113
constexpr bool is_nan(const T x) noexcept
Definition: is_nan.hpp:36
constexpr T atan_series_order(const T x, const T x_pow, const uint_t order, const uint_t max_order) noexcept
Definition: atan.hpp:50
constexpr T atan_cf_recur(const T xx, const uint_t depth, const uint_t max_depth) noexcept
Definition: atan.hpp:85
constexpr T atan_cf_main(const T x) noexcept
Definition: atan.hpp:98
constexpr T atan_series_order_calc(const T x, const T x_pow, const uint_t order) noexcept
Definition: atan.hpp:40
constexpr common_t< T1, T2 > pow(const T1 base, const T2 exp_term) noexcept
Compile-time power function.
Definition: pow.hpp:76