WPILibC++ 2024.3.2
atan.hpp
Go to the documentation of this file.
1/*################################################################################
2 ##
3 ## Copyright (C) 2016-2023 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
32#include <cmath>
33#include <type_traits>
34
35namespace gcem
36{
37
38namespace internal
39{
40
41// Series
42
43template<typename T>
44constexpr
45T
46atan_series_order_calc(const T x, const T x_pow, const uint_t order)
47noexcept
48{
49 return( T(1)/( T((order-1)*4 - 1) * x_pow ) \
50 - T(1)/( T((order-1)*4 + 1) * x_pow*x) );
51}
52
53template<typename T>
54constexpr
55T
56atan_series_order(const T x, const T x_pow, const uint_t order, const uint_t max_order)
57noexcept
58{
59 return( order == 1 ? \
60 GCEM_HALF_PI - T(1)/x + atan_series_order(x*x,pow(x,3),order+1,max_order) :
61 // NOTE: x changes to x*x for order > 1
62 order < max_order ? \
63 atan_series_order_calc(x,x_pow,order) \
64 + atan_series_order(x,x_pow*x*x,order+1,max_order) :
65 // order == max_order
66 atan_series_order_calc(x,x_pow,order) );
67}
68
69template<typename T>
70constexpr
71T
73noexcept
74{
75 return( x < T(3) ? atan_series_order(x,x,1U,10U) : // O(1/x^39)
76 x < T(4) ? atan_series_order(x,x,1U,9U) : // O(1/x^35)
77 x < T(5) ? atan_series_order(x,x,1U,8U) : // O(1/x^31)
78 x < T(7) ? atan_series_order(x,x,1U,7U) : // O(1/x^27)
79 x < T(11) ? atan_series_order(x,x,1U,6U) : // O(1/x^23)
80 x < T(25) ? atan_series_order(x,x,1U,5U) : // O(1/x^19)
81 x < T(100) ? atan_series_order(x,x,1U,4U) : // O(1/x^15)
82 x < T(1000) ? atan_series_order(x,x,1U,3U) : // O(1/x^11)
83 atan_series_order(x,x,1U,2U) ); // O(1/x^7)
84}
85
86// CF
87
88template<typename T>
89constexpr
90T
91atan_cf_recur(const T xx, const uint_t depth, const uint_t max_depth)
92noexcept
93{
94 return( depth < max_depth ? \
95 // if
96 T(2*depth - 1) + depth*depth*xx/atan_cf_recur(xx,depth+1,max_depth) :
97 // else
98 T(2*depth - 1) );
99}
100
101template<typename T>
102constexpr
103T
104atan_cf_main(const T x)
105noexcept
106{
107 return( x < T(0.5) ? x/atan_cf_recur(x*x,1U, 15U ) :
108 x < T(1) ? x/atan_cf_recur(x*x,1U, 25U ) :
109 x < T(1.5) ? x/atan_cf_recur(x*x,1U, 35U ) :
110 x < T(2) ? x/atan_cf_recur(x*x,1U, 45U ) :
111 x/atan_cf_recur(x*x,1U, 52U ) );
112}
113
114//
115
116template<typename T>
117constexpr
118T
119atan_begin(const T x)
120noexcept
121{
122 return( x > T(2.5) ? atan_series_main(x) : atan_cf_main(x) );
123}
124
125template<typename T>
126constexpr
127T
128atan_check(const T x)
129noexcept
130{
131 return( // NaN check
132 is_nan(x) ? \
134 // indistinguishable from zero
135 GCLIM<T>::min() > abs(x) ? \
136 T(0) :
137 // negative or positive
138 x < T(0) ? \
139 - atan_begin(-x) :
140 atan_begin( x) );
141}
142
143}
144
145/**
146 * Compile-time arctangent function
147 *
148 * @param x a real-valued input.
149 * @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]
150 */
151
152template<typename T>
153constexpr
154return_t<T>
155atan(const T x)
156noexcept
157{
159 return internal::atan_check( static_cast<return_t<T>>(x) );
160 } else {
161 return std::atan(x);
162 }
163}
164
165}
166
167#endif
#define GCEM_HALF_PI
Definition: gcem_options.hpp:118
constexpr FMT_INLINE auto is_constant_evaluated(bool default_value=false) noexcept -> bool
Definition: core.h:304
constexpr T atan_check(const T x) noexcept
Definition: atan.hpp:128
constexpr T atan_cf_main(const T x) noexcept
Definition: atan.hpp:104
constexpr T atan_cf_recur(const T xx, const uint_t depth, const uint_t max_depth) noexcept
Definition: atan.hpp:91
constexpr bool is_nan(const T x) noexcept
Definition: is_nan.hpp:39
constexpr T atan_series_main(const T x) noexcept
Definition: atan.hpp:72
constexpr T atan_begin(const T x) noexcept
Definition: atan.hpp:119
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:56
constexpr T atan_series_order_calc(const T x, const T x_pow, const uint_t order) noexcept
Definition: atan.hpp:46
Definition: is_even.hpp:29
constexpr T abs(const T x) noexcept
Compile-time absolute value function.
Definition: abs.hpp:40
constexpr return_t< T > atan(const T x) noexcept
Compile-time arctangent function.
Definition: atan.hpp:155
constexpr common_t< T1, T2 > pow(const T1 base, const T2 exp_term) noexcept
Compile-time power function.
Definition: pow.hpp:82
std::numeric_limits< T > GCLIM
Definition: gcem_options.hpp:74
unsigned int uint_t
Definition: gcem_options.hpp:68
typename std::conditional< std::is_integral< T >::value, double, T >::type return_t
Definition: gcem_options.hpp:77