GCC Code Coverage Report


Directory: include/polyfloat/
File: include/polyfloat/module/math/details/trig_finalize.hpp
Date: 2026-11-09 15:28:50
Exec Total Coverage
Lines: 76 78 97.4%
Functions: 58 74 78.4%
Branches: 2 2 100.0%

Line Branch Exec Source
1 //======================================================================================================================
2 /*
3 POLYFLOAT - Extended precision floating points
4 Copyright : POLYFLOAT Contributors & Maintainers
5 SPDX-License-Identifier: BSL-1.0
6 */
7 //======================================================================================================================
8 #pragma once
9
10 #include <polyfloat/details/callable.hpp>
11 #include <polyfloat/types/concepts.hpp>
12 #include <polyfloat/types/traits.hpp>
13 #include <type_traits>
14 #include <polyfloat/module/core/fma.hpp>
15 #include <polyfloat/module/core/nearest.hpp>
16 #include <polyfloat/module/core/quadrant.hpp>
17 #include <eve/traits/helpers.hpp>
18 #include <polyfloat/module/math/details/sincos_coefs.hpp>
19 #include <polyfloat/module/math/details/tancot_coefs.hpp>
20 #include <eve/traits/helpers.hpp>
21
22 namespace plf::_
23 {
24 76524 template<typename T> constexpr auto gauss(T z2, T z, int order)
25 {
26 // Gauss continued fraction of Rank order
27 76524 T a(order);
28
2/2
✓ Branch 0 taken 590538 times.
✓ Branch 1 taken 38266 times.
1257520 for (int i = order - 2; i > 0; i -= 2)
29 {
30 1180996 auto div_step = z2 / a;
31 1180996 a = i - div_step;
32 }
33 76524 return z / a;
34 }
35
36 600 template<typename T> constexpr auto cos_eval(T const& z2) noexcept
37 {
38 using e_t = eve::element_type_t<T>;
39 600 return plf::reverse_horner(z2, eve::coefficients(cos_coefs<e_t>()));
40 }
41
42 600 template<typename T> constexpr auto sin_eval(T const& z2, T const& z) noexcept
43 {
44 using e_t = eve::element_type_t<T>;
45 600 return z * plf::reverse_horner(z2, eve::coefficients(sino_x_coefs<e_t>()));
46 }
47
48 ✗ template<typename T> constexpr auto sinc_eval(T const& z2) noexcept
49 {
50 using e_t = eve::element_type_t<T>;
51 ✗ return plf::reverse_horner(z2, eve::coefficients(sino_x_coefs<e_t>()));
52 }
53
54 78616 template<typename T> auto tancot_eval(T const& z) noexcept
55 {
56 using e_t = eve::element_type_t<T>;
57 // here z is positive
58 78616 T z2 = eve::sqr(z);
59 if constexpr (std::same_as<e_t, float>)
60 {
61 float num = plf::reverse_horner(z2, 1.0f, -0.11110803f, 0.00105762f);
62 float den = plf::reverse_horner(z2, 1.0f, -0.44444137f, 0.01587148f);
63 return z * (num / den);
64 }
65 else if constexpr (std::same_as<e_t, double>)
66 {
67 double num = plf::reverse_horner(z2, 2027025.0, -270270.0, 6930.0, -36.0);
68 double den = plf::reverse_horner(z2, 2027025.0, -945945.0, 51975.0, -630.0, 1.0);
69 return z * (num / den);
70 }
71 else if constexpr (std::same_as<e_t, plf::double_real_t<float>>)
72 {
73 2092 kumi::tuple num_coefs{plf::_::from_pair(0x1p+0f, 0x0p+0f), plf::_::from_pair(-0x1.06b888p-3f, 0x1.f8471p-28f),
74 2092 plf::_::from_pair(0x1.6fc02cp-9f, 0x1.8e0b8p-36f),
75 2092 plf::_::from_pair(-0x1.f6161cp-18f, -0x1.70d7f6p-43f)};
76 2092 kumi::tuple den_coefs{plf::_::from_pair(0x1p+0f, 0x0p+0f), plf::_::from_pair(-0x1.d8b198p-2f, -0x1.ae8718p-27f),
77 2092 plf::_::from_pair(0x1.7e7802p-6f, -0x1.0c8338p-31f),
78 2092 plf::_::from_pair(-0x1.b51608p-13f, -0x1.12306p-38f)};
79 2092 auto num = plf::reverse_horner(z2, eve::coefficients(num_coefs));
80 2092 auto den = plf::reverse_horner(z2, eve::coefficients(den_coefs));
81 2092 return z * (num / den);
82 }
83 else if constexpr (std::same_as<e_t, plf::double_real_t<double>>)
84 {
85 2068 return gauss(z2, z, 27);
86 }
87 else if constexpr (std::same_as<e_t, plf::triple_real_t<float>>)
88 {
89 37224 return gauss(z2, z, 21);
90 }
91 else if constexpr (std::same_as<e_t, plf::triple_real_t<double>>)
92 {
93 37232 return gauss(z2, z, 43);
94 }
95 }
96
97 //========================================================================
98
99 256 template<typename T> constexpr auto cos_finalize(T const& fn, T const& xr, T const& dxr = T(0)) noexcept
100 {
101 256 auto tmp = plf::one[fn >= T(2)](eve::as(xr));
102 256 auto swap_bit = plf::is_nez(plf::fma(T(-2), tmp, fn));
103 256 auto zz1 = plf::is_odd(fn + tmp);
104 256 auto sign = plf::if_else(zz1, plf::mone(eve::as(xr)), plf::one(eve::as(xr)));
105 256 T xr2 = plf::sqr(xr);
106 256 T se = sin_eval(xr2, xr);
107 256 T ce = cos_eval(xr2);
108 256 auto z = plf::if_else(swap_bit, plf::fma(dxr, ce, se), plf::fnma(se, dxr, ce));
109 256 return sign * z;
110 }
111
112 266 template<typename T> constexpr auto sin_finalize(T const& a0, T const& fn, T const& xr, T const& dxr = T(0)) noexcept
113 {
114 266 auto tmp = plf::one[fn >= T(2)](eve::as(xr));
115 266 auto swap_bit = plf::is_nez(plf::fma(T(-2), tmp, fn));
116 266 auto sign = plf::signnz[eve::pedantic](a0);
117 266 sign *= plf::if_else(plf::is_nez(tmp), plf::mone(eve::as(a0)), plf::one(eve::as(xr)));
118 266 auto xr2 = plf::sqr(xr);
119 266 auto se = sin_eval(xr2, xr);
120 266 auto ce = cos_eval(xr2);
121 266 auto z = plf::if_else(swap_bit, plf::fnma(se, dxr, ce), plf::fma(dxr, ce, se));
122 266 return plf::if_else(plf::is_ltz(sign), -z, z);
123 }
124
125 24 template<typename T> constexpr auto sincos_finalize(T const& a0, T const& fn, T const& xr, T const& dxr) noexcept
126 {
127 24 auto tmp = plf::one[fn >= T(2)](plf::as(xr));
128 24 auto swap = plf::is_nez(plf::fma(T(-2), tmp, fn));
129 24 auto cos_sign = plf::if_else(plf::is_odd(fn + tmp), plf::mone(plf::as(xr)), plf::one(plf::as(xr)));
130 24 auto sin_sign = plf::signnz(a0);
131 24 sin_sign *= plf::if_else(plf::is_nez(tmp), plf::mone(plf::as(a0)), plf::one(plf::as(a0)));
132 24 auto xr2 = plf::sqr(xr);
133 24 auto se0 = sin_eval(xr2, xr);
134 24 auto ce0 = cos_eval(xr2);
135 24 auto ce = plf::fnma(se0, dxr, ce0);
136 24 auto se = plf::fma(dxr, ce0, se0);
137 24 return eve::zip((plf::if_else(swap, ce, se) * sin_sign), plf::if_else(swap, se, ce) * cos_sign);
138 }
139
140 1516 template<typename T> constexpr auto tan_finalize(T const& a0, T const& fn, T const& xr, T const& dxr) noexcept
141 {
142 1516 auto aa0lteps = plf::abs(xr) < eps(as<T>());
143 1516 auto tmp = plf::one[fn >= T(2)](eve::as(xr));
144 1516 auto swap_bit = (plf::fma(T(-2), tmp, fn));
145 1516 auto test = plf::is_eqz(swap_bit);
146 1516 auto y = tancot_eval(xr);
147 1516 y = plf::if_else(test, y, -plf::rec[pedantic](y));
148 1516 y = plf::fma(dxr, plf::fma(y, y, plf::one(eve::as<T>())), y);
149 1516 y = plf::if_else(aa0lteps, xr, y);
150 1516 return plf::if_else(plf::is_negative(a0), -y, y);
151 }
152
153 42 template<typename T> constexpr auto cot_finalize(T a0, T fn, T xr, T dxr) noexcept
154 {
155 42 auto aa0lteps = plf::abs(xr) < plf::eps(as<T>());
156 42 auto tmp = plf::one[fn >= T(2)](eve::as(xr));
157 42 auto swap_bit = (plf::fma(T(-2), tmp, fn));
158 42 auto test = plf::is_eqz(swap_bit);
159 42 auto y = tancot_eval(xr);
160 42 y = plf::if_else(test, plf::rec[eve::pedantic](y), -y);
161 42 y = plf::fma(dxr, plf::fma(y, y, plf::one(eve::as<T>())), y);
162 42 y = plf::if_else(aa0lteps, xr, y);
163 42 return plf::if_else(plf::is_negative(a0), -y, y);
164 }
165 }
166