GCC Code Coverage Report


Directory: include/polyfloat/
File: include/polyfloat/types/traits.hpp
Date: 2026-11-09 15:28:50
Exec Total Coverage
Lines: 1 1 100.0%
Functions: 12 12 100.0%
Branches: 0 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 <eve/eve.hpp>
11 #include <polyfloat/types/helpers.hpp>
12 #include <polyfloat/types/concepts.hpp>
13 #include <polyfloat/details/decorators.hpp>
14 #include <eve/as.hpp>
15
16 namespace plf
17 {
18 template<eve::floating_scalar_value Type, unsigned int N>
19 requires(N > 1 && N <= _::MAX_N)
20 struct polyfloat;
21 }
22
23 namespace plf::_
24 {
25 // Force a type to be looked at as a wide so we can apply wide-like type preserving semantic in type computations
26 template<typename T> struct sema
27 {
28 using type = T;
29 };
30 template<typename T> struct sema<eve::logical<T>> : sema<T>
31 {
32 };
33 template<typename T, eve::width_type N> struct sema<eve::wide<T, N>>
34 {
35 using type = eve::wide<eve::underlying_type_t<T>>;
36 };
37 template<concepts::polyfloat T> struct sema<T>
38 {
39 using type = eve::wide<eve::underlying_type_t<T>>;
40 };
41
42 template<typename T> using sema_t = typename sema<T>::type;
43
44 // Convert a Base type to a potential wide if any appear in T...
45 template<typename Base, typename... T>
46 using widen = std::conditional_t<std::max({eve::width_v<T>...}) != 1ULL,
47 eve::as_wide_t<Base, std::max({eve::width_v<T>...})>,
48 eve::element_type_t<Base>>;
49 }
50
51 namespace plf
52 {
53 //====================================================================================================================
54 //! @addtogroup traits
55 //! @{
56 //====================================================================================================================
57
58 //====================================================================================================================
59 //! @brief Obtains the rank containing a given type
60 //!
61 //! If `T` satisfies plf::concepts::polyfloat, evaluates to the number of parts of a
62 //! poly-float. If `T` is another product type, evaluates to the largest dimension of its elements.
63 //!
64 //! @tparam T Type to analyze.
65 //====================================================================================================================
66
67 #if !defined(POLYFLOAT_DOXYGEN_INVOKED)
68 template<typename T> inline constexpr unsigned int dimension_v = 1;
69 #else
70 template<typename T> inline constexpr unsigned int dimension_v = *implementation - defined*;
71 #endif
72
73 template<concepts::polyfloat T>
74 inline constexpr auto dimension_v<T> = eve::element_type_t<std::remove_cvref_t<T>>::static_dimension;
75
76 #if !defined(POLYFLOAT_DOXYGEN_INVOKED)
77 template<typename T>
78 requires(kumi::concepts::product_type<T> && !concepts::polyfloat<T>)
79 inline constexpr unsigned int dimension_v<T> = []<std::size_t... I>(std::index_sequence<I...>) {
80 return std::max({1u, dimension_v<kumi::element_t<I, T>>...});
81 }(std::make_index_sequence<kumi::size_v<T>>{});
82 #endif
83
84 template<typename T> struct as_component_type
85 {
86 using type = T;
87 };
88 template<typename T, unsigned int Dim> struct as_component_type<polyfloat<T, Dim>>
89 {
90 using type = T;
91 };
92 template<typename T, eve::width_type N> struct as_component_type<eve::wide<T, N>>
93 {
94 using type = eve::wide<typename as_component_type<T>::type, N>;
95 };
96
97 //====================================================================================================================
98 //! @brief Compute the real type associated to a Poly-Float-like type
99 //!
100 //! @tparam T Type to convert to a real type.
101 //====================================================================================================================
102 template<typename T> using as_component_type_t = typename as_component_type<T>::type;
103
104 template<unsigned int Dim, typename... Ts> struct as_polyfloat_n;
105
106 template<unsigned int Dim, typename... Ts>
107 requires(Dim > 1 && requires(Ts... ts) { eve::add(std::declval<_::sema_t<Ts>>()...); })
108 struct as_polyfloat_n<Dim, Ts...>
109 #if !defined(POLYFLOAT_DOXYGEN_INVOKED)
110 : as_polyfloat_n<Dim, _::widen<decltype(eve::add(std::declval<_::sema_t<Ts>>()...)), Ts...>>
111 #endif
112 {
113 };
114
115 #if !defined(POLYFLOAT_DOXYGEN_INVOKED)
116 template<unsigned int Dim, typename... Ts>
117 requires(Dim > 1 && !requires(Ts... ts) { eve::add(std::declval<_::sema_t<Ts>>()...); })
118 struct as_polyfloat_n<Dim, Ts...>
119 {
120 };
121
122 template<unsigned int Dim, typename T>
123 requires(Dim > 1)
124 struct as_polyfloat_n<Dim, T>
125 {
126 static constexpr auto card = eve::width_v<T>;
127 using cd_t = polyfloat<eve::as_floating_point_t<eve::underlying_type_t<T>>, Dim>;
128 using type = std::conditional_t<card != 1ULL, eve::wide<cd_t, card>, cd_t>;
129 };
130
131 template<typename... Ts> struct as_polyfloat_n<1, Ts...> : eve::common_value<_::sema_t<Ts>...>
132 {
133 };
134 #endif
135
136 //====================================================================================================================
137 //! @brief Computes a Poly-Float type of a given dimension
138 //!
139 //! @tparam Dim Dimension of the Poly-Float to use.
140 //! @tparam Ts Types used to compute the Poly-Float underlying type.
141 //====================================================================================================================
142 template<unsigned int Dim, typename... Ts> using as_polyfloat_n_t = typename as_polyfloat_n<Dim, Ts...>::type;
143
144 template<typename... Ts>
145 requires(requires(Ts... ts) { typename as_polyfloat_n<std::max({dimension_v<Ts>...}), Ts...>::type; })
146 struct as_polyfloat : as_polyfloat_n<std::max({dimension_v<Ts>...}), Ts...>
147 {
148 };
149 }
150
151 namespace plf
152 {
153 namespace _
154 {
155 template<typename T> using common_real = eve::as_floating_point_t<as_component_type_t<T>>;
156 }
157
158 //====================================================================================================================
159 //! @brief Computes the best fitting Poly-Float type from a series of types.
160 //!
161 //! @tparam Ts Types used to compute the Poly-Float underlying type.
162 //====================================================================================================================
163 template<typename... Ts> using as_polyfloat_t = typename as_polyfloat<Ts...>::type;
164
165 template<auto Callable, typename... Ts>
166 using expected_result_t =
167 as_polyfloat_n_t<std::max({dimension_v<Ts>...}), decltype(Callable(std::declval<as_component_type_t<Ts>>()...))>;
168
169 using eve::as;
170
171 //====================================================================================================================
172 //! @struct as_component
173 //! @brief Lightweight type-wrapper of real value type
174 //!
175 //! Wraps the real type associated to `T` into a constexpr, trivially constructible empty class to optimize passing
176 //! type parameters via object instead of via template parameters.
177 //!
178 //! @tparam T Type to wrap
179 //====================================================================================================================
180 template<typename T> struct as_component : as<as_component_type_t<T>>
181 {
182 154573 constexpr as_component() noexcept {}
183 explicit constexpr as_component(T const&) noexcept {}
184 };
185 //====================================================================================================================
186 //! @}
187 //====================================================================================================================
188
189 //====================================================================================================================
190 //! @struct complexify
191 //! @brief compute the cayley dickson type associated to a floating type or any other type.
192 //!
193 //! if the type is an eve::floating_value return the complex type associated else let the type as is.
194 //!
195 //! @tparam T Type to wrap
196 //====================================================================================================================
197 template<typename T> struct double_it
198 {
199 using type = T;
200 };
201
202 template<eve::floating_value T> struct double_it<T>
203 {
204 using type = plf::as_polyfloat_n_t<2, T>;
205 };
206
207 template<typename T> using double_it_t = typename double_it<T>::type;
208
209 //====================================================================================================================
210 //! @brief Compute the cayley_dickson_like type associated to a Poly-Float-like family of types
211 //!
212 //! @tparam Ts Types used to compute the Poly-Float_like common type.
213 //====================================================================================================================
214
215 template<typename... Ts> struct as_polyfloat_like : as_polyfloat<Ts...>
216 {
217 };
218
219 template<typename Tup>
220 requires(kumi::concepts::product_type<Tup> && !concepts::polyfloat<Tup>)
221 struct as_polyfloat_like<Tup>
222 {
223 using type = Tup;
224 };
225
226 template<typename T, typename Tup>
227 requires(kumi::concepts::product_type<Tup> && !concepts::polyfloat<Tup>)
228 struct as_polyfloat_like<T, Tup> : as_polyfloat_like<T, kumi::apply_traits_t<as_polyfloat_like, Tup>>
229 {
230 };
231
232 template<concepts::real... Ts> struct as_polyfloat_like<Ts...> : eve::common_value<Ts...>
233 {
234 };
235 template<typename... Ts> using as_polyfloat_like_t = typename as_polyfloat_like<Ts...>::type;
236
237 }
238