consteig
Compile-time eigenvalue and eigenvector computation for C++17
Loading...
Searching...
No Matches
trig.hpp
1#ifndef CONSTMATH_TRIG_HPP
2#define CONSTMATH_TRIG_HPP
3// Reference:
4// https://en.wikipedia.org/wiki/Taylor_series#Trigonometric_functions
5
6#include "../../consteig_options.hpp"
7#include "utilities.hpp"
8
9namespace consteig
10{
11
14
15// Reduce x to (-pi, pi] by removing integer multiples of 2*pi.
16// NOTE: the cast of (x / two_pi) to long long is undefined behavior for
17// |x| > ~5.8e19 (where x / two_pi exceeds LLONG_MAX), and also for non-finite
18// inputs (NaN or Inf). A stdlib-free constexpr alternative does not exist in
19// C++17, so these limitations are accepted for the expected input range of this
20// library.
21template <typename T> constexpr T trig_reduce(const T x) noexcept
22{
23 constexpr T two_pi = static_cast<T>(2.0 * PI_CONST);
24 T k = static_cast<T>(static_cast<long long>(x / two_pi));
25 T r = x - k * two_pi;
26 if (r > static_cast<T>(PI_CONST))
27 {
28 r -= two_pi;
29 }
30 else if (r <= -static_cast<T>(PI_CONST))
31 {
32 r += two_pi;
33 }
34 return r;
35}
36
37template <typename T> constexpr T sin_series(const T x) noexcept
38{
39 // sin(x) = x - x^3/3! + x^5/5! - ...
40 T result = x;
41 T term = x;
42 int n = 1;
43 while (n <= CONSTEIG_TRIG_MAX_ITER)
44 {
45 term *= -x * x / static_cast<T>((2 * n) * (2 * n + 1));
46 result += term;
47 ++n;
48 }
49 return result;
50}
51
52template <typename T> constexpr T cos_series(const T x) noexcept
53{
54 // cos(x) = 1 - x^2/2! + x^4/4! - ...
55 T result = static_cast<T>(1);
56 T term = static_cast<T>(1);
57 int n = 1;
58 while (n <= CONSTEIG_TRIG_MAX_ITER)
59 {
60 term *= -x * x / static_cast<T>((2 * n - 1) * (2 * n));
61 result += term;
62 ++n;
63 }
64 return result;
65}
66
70template <typename T> constexpr auto sin(const T x) noexcept
71{
72 if constexpr (!is_float<T>())
73 {
74 return sin_series(trig_reduce(static_cast<double>(x)));
75 }
76 else
77 {
78 return sin_series(trig_reduce(x));
79 }
80}
81
85template <typename T> constexpr auto cos(const T x) noexcept
86{
87 if constexpr (!is_float<T>())
88 {
89 return cos_series(trig_reduce(static_cast<double>(x)));
90 }
91 else
92 {
93 return cos_series(trig_reduce(x));
94 }
95}
96
105template <typename T> constexpr auto tan(const T x) noexcept
106{
107 if constexpr (!is_float<T>())
108 {
109 const double r = trig_reduce(static_cast<double>(x));
110 return sin_series(r) / cos_series(r);
111 }
112 else
113 {
114 const T r = trig_reduce(x);
115 return sin_series(r) / cos_series(r);
116 }
117}
118
120
121} // namespace consteig
122
123#endif
#define PI_CONST
The constant π to 50 significant digits.
Definition consteig_options.hpp:56
#define CONSTEIG_TRIG_MAX_ITER
Maximum Taylor series iterations for trigonometric functions.
Definition consteig_options.hpp:69
constexpr auto sin(const T x) noexcept
Computes the sine of x (in radians).
Definition trig.hpp:70
constexpr T epsilon()
Machine epsilon for type T.
Definition utilities.hpp:82
constexpr auto tan(const T x) noexcept
Computes the tangent of x (in radians) as sin_series(r) / cos_series(r), where r = trig_reduce(x).
Definition trig.hpp:105
constexpr auto cos(const T x) noexcept
Computes the cosine of x (in radians).
Definition trig.hpp:85