Eigen  5.0.1
 
Loading...
Searching...
No Matches
Meta.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2008-2015 Gael Guennebaud <gael.guennebaud@inria.fr>
5// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
6//
7// This Source Code Form is subject to the terms of the Mozilla
8// Public License v. 2.0. If a copy of the MPL was not distributed
9// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10// SPDX-License-Identifier: MPL-2.0
11
12#ifndef EIGEN_META_H
13#define EIGEN_META_H
14
15// IWYU pragma: private
16#include "../InternalHeaderCheck.h"
17
18// Define portable (u)int{32,64} types
19#include <cstdint>
20
21namespace Eigen {
22namespace numext {
23using uint8_t = std::uint8_t;
24using int8_t = std::int8_t;
25using uint16_t = std::uint16_t;
26using int16_t = std::int16_t;
27using uint32_t = std::uint32_t;
28using int32_t = std::int32_t;
29using uint64_t = std::uint64_t;
30using int64_t = std::int64_t;
31
32template <size_t Size>
33struct get_integer_by_size {
34 using signed_type = void;
35 using unsigned_type = void;
36};
37template <>
38struct get_integer_by_size<1> {
39 using signed_type = int8_t;
40 using unsigned_type = uint8_t;
41};
42template <>
43struct get_integer_by_size<2> {
44 using signed_type = int16_t;
45 using unsigned_type = uint16_t;
46};
47template <>
48struct get_integer_by_size<4> {
49 using signed_type = int32_t;
50 using unsigned_type = uint32_t;
51};
52template <>
53struct get_integer_by_size<8> {
54 using signed_type = int64_t;
55 using unsigned_type = uint64_t;
56};
57} // namespace numext
58} // namespace Eigen
59
60namespace Eigen {
61
62using DenseIndex = EIGEN_DEFAULT_DENSE_INDEX_TYPE;
63
69using Index = EIGEN_DEFAULT_DENSE_INDEX_TYPE;
70
71namespace internal {
72
79
80template <bool Condition>
81using bool_constant = std::integral_constant<bool, Condition>;
82
83// Deprecated compatibility aliases. Third-party libraries rely on these, but new code should use std:: directly.
84using std::conditional;
85using std::false_type;
86using std::is_const;
87using std::is_convertible;
88using std::is_integral;
89using std::is_same;
90using std::is_void;
91using std::make_unsigned;
92using std::remove_const;
93using std::remove_pointer;
94using std::remove_reference;
95using std::true_type;
96
97template <typename T>
98struct remove_all {
99 using type = T;
100};
101template <typename T>
102struct remove_all<const T> {
103 using type = typename remove_all<T>::type;
104};
105template <typename T>
106struct remove_all<T const&> {
107 using type = typename remove_all<T>::type;
108};
109template <typename T>
110struct remove_all<T&> {
111 using type = typename remove_all<T>::type;
112};
113template <typename T>
114struct remove_all<T const*> {
115 using type = typename remove_all<T>::type;
116};
117template <typename T>
118struct remove_all<T*> {
119 using type = typename remove_all<T>::type;
120};
121
122template <typename T>
123using remove_all_t = typename remove_all<T>::type;
124
125// Eigen's is_arithmetic is similar to std::is_arithmetic but can be specialized
126// for SIMD packet types and other Eigen-specific types. The primary template
127// delegates to std::is_arithmetic for fundamental types.
128template <typename T>
129struct is_arithmetic : std::is_arithmetic<T> {};
130// GPU devices treat `long double` as `double`.
131#ifdef EIGEN_GPU_COMPILE_PHASE
132template <>
133struct is_arithmetic<long double> : std::false_type {};
134#endif
135
144#if EIGEN_COMP_CXXVER >= 17 && defined(__cpp_lib_void_t) && __cpp_lib_void_t >= 201411L
145using std::void_t;
146#else
147template <typename...>
148using void_t = void;
149#endif
150
151template <typename T>
152struct add_const_on_value_type {
153 using type = const T;
154};
155template <typename T>
156struct add_const_on_value_type<T&> {
157 using type = const T&;
158};
159template <typename T>
160struct add_const_on_value_type<T*> {
161 using type = const T*;
162};
163template <typename T>
164struct add_const_on_value_type<T* const> {
165 using type = const T* const;
166};
167template <typename T>
168struct add_const_on_value_type<T const* const> {
169 using type = const T* const;
170};
171
172template <typename T>
173using add_const_on_value_type_t = typename add_const_on_value_type<T>::type;
174
189template <typename T, typename EnableIf = void>
190struct array_size {
191 static constexpr Index value = Dynamic;
192};
193
194template <typename T>
195struct array_size<T, std::enable_if_t<((T::SizeAtCompileTime & 0) == 0)>> {
196 static constexpr Index value = T::SizeAtCompileTime;
197};
198
199template <typename T, int N>
200struct array_size<const T (&)[N]> {
201 static constexpr Index value = N;
202};
203template <typename T, int N>
204struct array_size<T (&)[N]> {
205 static constexpr Index value = N;
206};
207
208template <typename T, std::size_t N>
209struct array_size<const std::array<T, N>> {
210 static constexpr Index value = N;
211};
212template <typename T, std::size_t N>
213struct array_size<std::array<T, N>> {
214 static constexpr Index value = N;
215};
216
227#if EIGEN_COMP_CXXVER >= 20 && defined(__cpp_lib_ssize) && __cpp_lib_ssize >= 201902L
228
229template <typename T>
230constexpr auto index_list_size(T&& x) {
231 using std::ssize;
232 return ssize(std::forward<T>(x));
233}
234
235#else
236
237template <typename T>
238constexpr auto index_list_size(const T& x) {
239 using R = std::common_type_t<std::ptrdiff_t, std::make_signed_t<decltype(x.size())>>;
240 return static_cast<R>(x.size());
241}
242
243template <typename T, std::ptrdiff_t N>
244constexpr std::ptrdiff_t index_list_size(const T (&)[N]) {
245 return N;
246}
247#endif
248
249// std::remove_cvref_t is C++20; use it when the standard library exposes the feature-test macro.
250#if defined(__cpp_lib_remove_cvref)
251using std::remove_cvref_t;
252#else
253template <typename T>
254using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
255#endif
256
267#if EIGEN_HAS_STD_INVOKE_RESULT
268template <typename T>
269struct result_of;
270
271template <typename F, typename... ArgTypes>
272struct result_of<F(ArgTypes...)> {
273 using type1 = std::invoke_result_t<F, ArgTypes...>;
274 using type = remove_cvref_t<type1>;
275};
276#else
277template <typename T>
278struct result_of {
279 using type1 = std::result_of_t<T>;
280 using type = remove_cvref_t<type1>;
281};
282#endif
283
284// Reduces a sequence of bools to true if all are true, false otherwise.
285template <bool... values>
286using reduce_all =
287 std::is_same<std::integer_sequence<bool, values..., true>, std::integer_sequence<bool, true, values...>>;
288
289// Check whether T::ReturnType does exist
290template <typename T, typename EnableIf = void>
291struct has_ReturnType : std::false_type {};
292
293template <typename T>
294struct has_ReturnType<T, void_t<typename T::ReturnType>> : std::true_type {};
295
296template <typename T, typename IndexType = Index, typename EnableIf = void>
297struct has_nullary_operator : std::false_type {};
298
299template <typename T, typename IndexType>
300struct has_nullary_operator<T, IndexType, void_t<decltype(std::declval<const T&>()())>> : std::true_type {};
301
302template <typename T, typename IndexType = Index, typename EnableIf = void>
303struct has_unary_operator : std::false_type {};
304
305template <typename T, typename IndexType>
306struct has_unary_operator<T, IndexType, void_t<decltype(std::declval<const T&>()(IndexType(0)))>> : std::true_type {};
307
308template <typename T, typename IndexType = Index, typename EnableIf = void>
309struct has_binary_operator : std::false_type {};
310
311template <typename T, typename IndexType>
312struct has_binary_operator<T, IndexType, void_t<decltype(std::declval<const T&>()(IndexType(0), IndexType(0)))>>
313 : std::true_type {};
314
318template <int A, int B, int K = 1, bool Done = ((A * K) % B) == 0, bool Big = (A >= B)>
319struct meta_least_common_multiple : std::integral_constant<int, meta_least_common_multiple<A, B, K + 1>::value> {};
320template <int A, int B, int K, bool Done>
321struct meta_least_common_multiple<A, B, K, Done, false>
322 : std::integral_constant<int, meta_least_common_multiple<B, A, K>::value> {};
323template <int A, int B, int K>
324struct meta_least_common_multiple<A, B, K, true, true> : std::integral_constant<int, A * K> {};
325
327template <typename T, typename U>
328struct scalar_product_traits {
329 enum { Defined = 0 };
330};
331
337template <unsigned Len, unsigned Align>
338struct aligned_storage {
339 struct type {
340 EIGEN_ALIGN_TO_BOUNDARY(Align) unsigned char data[Len];
341 };
342};
343
344} // end namespace internal
345
346template <typename T>
347struct NumTraits;
348
349namespace numext {
350
351#if defined(EIGEN_GPU_COMPILE_PHASE)
352template <typename T>
353EIGEN_DEVICE_FUNC constexpr void swap(T& a, T& b) {
354 T tmp = b;
355 b = a;
356 a = tmp;
357}
358#else
359template <typename T>
360constexpr EIGEN_STRONG_INLINE void swap(T& a, T& b) {
361 std::swap(a, b);
362}
363#endif
364
365using std::numeric_limits;
366
367// Handle integer comparisons of different signedness.
368template <typename X, typename Y, bool XIsInteger = NumTraits<X>::IsInteger, bool XIsSigned = NumTraits<X>::IsSigned,
369 bool YIsInteger = NumTraits<Y>::IsInteger, bool YIsSigned = NumTraits<Y>::IsSigned>
370struct equal_strict_impl {
371 static constexpr EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool run(const X& x, const Y& y) { return x == y; }
372};
373template <typename X, typename Y>
374struct equal_strict_impl<X, Y, true, false, true, true> {
375 // X is an unsigned integer
376 // Y is a signed integer
377 // if Y is non-negative, it may be represented exactly as its unsigned counterpart.
378 using UnsignedY = std::make_unsigned_t<Y>;
379 static constexpr EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool run(const X& x, const Y& y) {
380 return y < Y(0) ? false : (x == static_cast<UnsignedY>(y));
381 }
382};
383template <typename X, typename Y>
384struct equal_strict_impl<X, Y, true, true, true, false> {
385 // X is a signed integer
386 // Y is an unsigned integer
387 static constexpr EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool run(const X& x, const Y& y) {
388 return equal_strict_impl<Y, X>::run(y, x);
389 }
390};
391
392// The aim of the following functions is to bypass -Wfloat-equal warnings
393// when we really want a strict equality comparison on floating points.
394template <typename X, typename Y>
395constexpr EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool equal_strict(const X& x, const Y& y) {
396 return equal_strict_impl<X, Y>::run(x, y);
397}
398
399#if !defined(EIGEN_GPU_COMPILE_PHASE) || (!defined(EIGEN_CUDA_ARCH) && defined(EIGEN_CONSTEXPR_ARE_DEVICE_FUNC))
400template <>
401constexpr EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool equal_strict(const float& x, const float& y) {
402 return std::equal_to<float>()(x, y);
403}
404
405template <>
406constexpr EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool equal_strict(const double& x, const double& y) {
407 return std::equal_to<double>()(x, y);
408}
409
410#ifndef EIGEN_GPU_COMPILE_PHASE
411template <>
412constexpr EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool equal_strict(const long double& x, const long double& y) {
413 return std::equal_to<long double>()(x, y);
414}
415#endif
416#endif
417
422template <typename X>
423constexpr EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool is_exactly_zero(const X& x) {
424 return equal_strict(x, typename NumTraits<X>::Literal{0});
425}
426
427// Unlike is_exactly_zero, inspect supported binary float/double encodings so DAZ cannot hide a subnormal.
428// Both signed zeros compare as zero. Other scalar types retain their usual equality semantics.
429// Defined in MathFunctions.h, after binary_floating_point_traits.
430template <typename X>
431EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool is_exactly_zero_no_flush(const X& x);
432
437template <typename X>
438constexpr EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool is_exactly_one(const X& x) {
439 return equal_strict(x, typename NumTraits<X>::Literal{1});
440}
441
442template <typename X, typename Y>
443constexpr EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool not_equal_strict(const X& x, const Y& y) {
444 return !equal_strict_impl<X, Y>::run(x, y);
445}
446
447#if !defined(EIGEN_GPU_COMPILE_PHASE) || (!defined(EIGEN_CUDA_ARCH) && defined(EIGEN_CONSTEXPR_ARE_DEVICE_FUNC))
448template <>
449constexpr EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool not_equal_strict(const float& x, const float& y) {
450 return std::not_equal_to<float>()(x, y);
451}
452
453template <>
454constexpr EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool not_equal_strict(const double& x, const double& y) {
455 return std::not_equal_to<double>()(x, y);
456}
457
458#ifndef EIGEN_GPU_COMPILE_PHASE
459template <>
460constexpr EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool not_equal_strict(const long double& x, const long double& y) {
461 return std::not_equal_to<long double>()(x, y);
462}
463#endif
464#endif
465
466} // end namespace numext
467
468namespace internal {
469
470template <typename Scalar>
471struct is_identically_zero_impl {
472 static constexpr bool run(const Scalar& s) { return numext::is_exactly_zero(s); }
473};
474
475template <typename Scalar>
476constexpr EIGEN_STRONG_INLINE bool is_identically_zero(const Scalar& s) {
477 return is_identically_zero_impl<Scalar>::run(s);
478}
479
480// true if T can be considered as an integral index (i.e., an integral type or enum)
481template <typename T>
482using is_valid_index_type = bool_constant<std::is_integral<T>::value || std::is_enum<T>::value>;
483
484template <typename A, typename B>
485constexpr void plain_enum_asserts(A, B) {
486 static_assert(is_valid_index_type<A>::value, "Argument a must be an integer or enum");
487 static_assert(is_valid_index_type<B>::value, "Argument b must be an integer or enum");
488}
489
491template <typename A, typename B>
492constexpr int plain_enum_min(A a, B b) {
493 plain_enum_asserts(a, b);
494 return ((int)a <= (int)b) ? (int)a : (int)b;
495}
496
498template <typename A, typename B>
499constexpr int plain_enum_max(A a, B b) {
500 plain_enum_asserts(a, b);
501 return ((int)a >= (int)b) ? (int)a : (int)b;
502}
503
510template <typename A, typename B>
511constexpr int min_size_prefer_dynamic(A a, B b) {
512 plain_enum_asserts(a, b);
513 if ((int)a == 0 || (int)b == 0) return 0;
514 if ((int)a == 1 || (int)b == 1) return 1;
515 if ((int)a == Dynamic || (int)b == Dynamic) return Dynamic;
516 return plain_enum_min(a, b);
517}
518
525template <typename A, typename B>
526constexpr int min_size_prefer_fixed(A a, B b) {
527 plain_enum_asserts(a, b);
528 if ((int)a == 0 || (int)b == 0) return 0;
529 if ((int)a == 1 || (int)b == 1) return 1;
530 if ((int)a == Dynamic && (int)b == Dynamic) return Dynamic;
531 if ((int)a == Dynamic) return (int)b;
532 if ((int)b == Dynamic) return (int)a;
533 return plain_enum_min(a, b);
534}
535
537template <typename A, typename B>
538constexpr int max_size_prefer_dynamic(A a, B b) {
539 plain_enum_asserts(a, b);
540 if ((int)a == Dynamic || (int)b == Dynamic) return Dynamic;
541 return plain_enum_max(a, b);
542}
543
544template <typename A, typename B>
545inline constexpr int size_prefer_fixed(A a, B b) {
546 plain_enum_asserts(a, b);
547 return int(a) == Dynamic ? int(b) : int(a);
548}
549
550template <typename A, typename B>
551inline constexpr bool enum_eq_not_dynamic(A a, B b) {
552 plain_enum_asserts(a, b);
553 if ((int)a == Dynamic || (int)b == Dynamic) return false;
554 return (int)a == (int)b;
555}
556
557template <typename A, typename B>
558constexpr bool enum_lt_not_dynamic(A a, B b) {
559 plain_enum_asserts(a, b);
560 if ((int)a == Dynamic || (int)b == Dynamic) return false;
561 return (int)a < (int)b;
562}
563
564template <typename A, typename B>
565constexpr bool enum_ge_not_dynamic(A a, B b) {
566 plain_enum_asserts(a, b);
567 if ((int)a == Dynamic || (int)b == Dynamic) return false;
568 return (int)a >= (int)b;
569}
570
572constexpr bool logical_xor(bool a, bool b) { return a != b; }
573
575constexpr bool check_implication(bool a, bool b) { return !a || b; }
576
578#if EIGEN_COMP_CXXVER >= 20 && defined(__cpp_lib_is_constant_evaluated) && __cpp_lib_is_constant_evaluated >= 201811L
579using std::is_constant_evaluated;
580#else
581constexpr bool is_constant_evaluated() { return false; }
582#endif
583
584template <typename Scalar>
585using make_complex_t = std::conditional_t<NumTraits<Scalar>::IsComplex, Scalar, std::complex<Scalar>>;
586
587} // end namespace internal
588
589} // end namespace Eigen
590
591#endif // EIGEN_META_H
Holds information about the various numeric (i.e. scalar) types allowed by Eigen.
Definition NumTraits.h:233