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