WPILibC++ 2023.4.3-108-ge5452e3
tan.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 tangent function
23 */
24
25#ifndef _gcem_tan_HPP
26#define _gcem_tan_HPP
27
28namespace internal
29{
30
31template<typename T>
32constexpr
33T
35noexcept
36{ // this is based on a fourth-order expansion of tan(z) using Bernoulli numbers
37 return( - 1/z + (z/3 + (pow_integral(z,3)/45 + (2*pow_integral(z,5)/945 + pow_integral(z,7)/4725))) );
38}
39
40template<typename T>
41constexpr
42T
44noexcept
45{
46 return( GCLIM<T>::min() > abs(x - T(GCEM_HALF_PI)) ? \
47 // the value tan(pi/2) is somewhat of a convention;
48 // technically the function is not defined at EXACTLY pi/2,
49 // but this is floating point pi/2
50 T(1.633124e+16) :
51 // otherwise we use an expansion around pi/2
53 );
54}
55
56template<typename T>
57constexpr
58T
59tan_cf_recur(const T xx, const int depth, const int max_depth)
60noexcept
61{
62 return( depth < max_depth ? \
63 // if
64 T(2*depth - 1) - xx/tan_cf_recur(xx,depth+1,max_depth) :
65 // else
66 T(2*depth - 1) );
67}
68
69template<typename T>
70constexpr
71T
72tan_cf_main(const T x)
73noexcept
74{
75 return( (x > T(1.55) && x < T(1.60)) ? \
76 tan_series_exp(x) : // deals with a singularity at tan(pi/2)
77 //
78 x > T(1.4) ? \
79 x/tan_cf_recur(x*x,1,45) :
80 x > T(1) ? \
81 x/tan_cf_recur(x*x,1,35) :
82 // else
83 x/tan_cf_recur(x*x,1,25) );
84}
85
86template<typename T>
87constexpr
88T
89tan_begin(const T x, const int count = 0)
90noexcept
91{ // tan(x) = tan(x + pi)
92 return( x > T(GCEM_PI) ? \
93 // if
94 count > 1 ? GCLIM<T>::quiet_NaN() : // protect against undefined behavior
96 // else
97 tan_cf_main(x) );
98}
99
100template<typename T>
101constexpr
102T
103tan_check(const T x)
104noexcept
105{
106 return( // NaN check
107 is_nan(x) ? \
108 GCLIM<T>::quiet_NaN() :
109 // indistinguishable from zero
110 GCLIM<T>::min() > abs(x) ? \
111 T(0) :
112 // else
113 x < T(0) ? \
114 - tan_begin(-x) :
115 tan_begin( x) );
116}
117
118}
119
120/**
121 * Compile-time tangent function
122 *
123 * @param x a real-valued input.
124 * @return the tangent function using
125 * \f[ \tan(x) = \dfrac{x}{1 - \dfrac{x^2}{3 - \dfrac{x^2}{5 - \ddots}}} \f]
126 * To deal with a singularity at \f$ \pi / 2 \f$, the following expansion is employed:
127 * \f[ \tan(x) = - \frac{1}{x-\pi/2} - \sum_{k=1}^\infty \frac{(-1)^k 2^{2k} B_{2k}}{(2k)!} (x - \pi/2)^{2k - 1} \f]
128 * where \f$ B_n \f$ is the n-th Bernoulli number.
129 */
130
131template<typename T>
132constexpr
133return_t<T>
134tan(const T x)
135noexcept
136{
137 return internal::tan_check( static_cast<return_t<T>>(x) );
138}
139
140#endif
constexpr auto count() -> size_t
Definition: core.h:1204
#define GCEM_PI
Definition: gcem_options.hpp:98
#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
Definition: Eigen_Colamd.h:50
constexpr T tan_series_exp(const T x) noexcept
Definition: tan.hpp:43
constexpr T1 pow_integral(const T1 base, const T2 exp_term) noexcept
Definition: pow_integral.hpp:120
constexpr T tan_begin(const T x, const int count=0) noexcept
Definition: tan.hpp:89
constexpr bool is_nan(const T x) noexcept
Definition: is_nan.hpp:36
constexpr T tan_series_exp_long(const T z) noexcept
Definition: tan.hpp:34
constexpr T tan_cf_recur(const T xx, const int depth, const int max_depth) noexcept
Definition: tan.hpp:59
constexpr T tan_cf_main(const T x) noexcept
Definition: tan.hpp:72
constexpr T tan_check(const T x) noexcept
Definition: tan.hpp:103
constexpr T floor_check(const T x) noexcept
Definition: floor.hpp:96
constexpr return_t< T > tan(const T x) noexcept
Compile-time tangent function.
Definition: tan.hpp:134