2007-10-12 05:15:25 +00:00
|
|
|
// This file is part of Eigen, a lightweight C++ template library
|
2009-05-22 20:25:33 +02:00
|
|
|
// for linear algebra.
|
2007-09-05 10:42:15 +00:00
|
|
|
//
|
2015-10-31 18:06:28 +01:00
|
|
|
// Copyright (C) 2008-2015 Gael Guennebaud <gael.guennebaud@inria.fr>
|
2008-11-24 13:40:43 +00:00
|
|
|
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
2007-09-05 10:42:15 +00:00
|
|
|
//
|
2012-07-13 14:42:47 -04:00
|
|
|
// This Source Code Form is subject to the terms of the Mozilla
|
|
|
|
|
// Public License v. 2.0. If a copy of the MPL was not distributed
|
|
|
|
|
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
2007-09-05 10:42:15 +00:00
|
|
|
|
2008-04-10 09:41:13 +00:00
|
|
|
#ifndef EIGEN_META_H
|
|
|
|
|
#define EIGEN_META_H
|
2008-03-21 20:26:14 +00:00
|
|
|
|
2023-08-21 16:25:22 +00:00
|
|
|
// IWYU pragma: private
|
2021-09-10 19:12:26 +00:00
|
|
|
#include "../InternalHeaderCheck.h"
|
|
|
|
|
|
2018-06-14 10:21:54 -04:00
|
|
|
#if defined(EIGEN_GPU_COMPILE_PHASE)
|
2015-10-28 16:49:15 +01:00
|
|
|
|
2018-06-14 10:21:54 -04:00
|
|
|
#include <cfloat>
|
|
|
|
|
|
|
|
|
|
#if defined(EIGEN_CUDA_ARCH)
|
|
|
|
|
#include <math_constants.h>
|
|
|
|
|
#endif
|
2018-06-06 10:12:58 -04:00
|
|
|
|
2018-06-14 10:21:54 -04:00
|
|
|
#if defined(EIGEN_HIP_DEVICE_COMPILE)
|
|
|
|
|
#include "Eigen/src/Core/arch/HIP/hcc/math_constants.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
2015-10-28 16:49:15 +01:00
|
|
|
#endif
|
|
|
|
|
|
2021-01-26 13:39:34 -08:00
|
|
|
// Define portable (u)int{32,64} types
|
2016-07-06 14:07:14 +02:00
|
|
|
#include <cstdint>
|
2021-09-10 19:12:26 +00:00
|
|
|
|
2021-01-26 13:39:34 -08:00
|
|
|
namespace Eigen {
|
|
|
|
|
namespace numext {
|
|
|
|
|
typedef std::uint8_t uint8_t;
|
|
|
|
|
typedef std::int8_t int8_t;
|
|
|
|
|
typedef std::uint16_t uint16_t;
|
|
|
|
|
typedef std::int16_t int16_t;
|
|
|
|
|
typedef std::uint32_t uint32_t;
|
|
|
|
|
typedef std::int32_t int32_t;
|
|
|
|
|
typedef std::uint64_t uint64_t;
|
|
|
|
|
typedef std::int64_t int64_t;
|
2022-11-04 00:31:20 +00:00
|
|
|
|
|
|
|
|
template <size_t Size>
|
|
|
|
|
struct get_integer_by_size {
|
|
|
|
|
typedef void signed_type;
|
|
|
|
|
typedef void unsigned_type;
|
|
|
|
|
};
|
|
|
|
|
template <>
|
|
|
|
|
struct get_integer_by_size<1> {
|
|
|
|
|
typedef int8_t signed_type;
|
|
|
|
|
typedef uint8_t unsigned_type;
|
|
|
|
|
};
|
|
|
|
|
template <>
|
|
|
|
|
struct get_integer_by_size<2> {
|
|
|
|
|
typedef int16_t signed_type;
|
|
|
|
|
typedef uint16_t unsigned_type;
|
|
|
|
|
};
|
|
|
|
|
template <>
|
|
|
|
|
struct get_integer_by_size<4> {
|
|
|
|
|
typedef int32_t signed_type;
|
|
|
|
|
typedef uint32_t unsigned_type;
|
|
|
|
|
};
|
|
|
|
|
template <>
|
|
|
|
|
struct get_integer_by_size<8> {
|
|
|
|
|
typedef int64_t signed_type;
|
|
|
|
|
typedef uint64_t unsigned_type;
|
|
|
|
|
};
|
2021-01-26 13:39:34 -08:00
|
|
|
} // namespace numext
|
|
|
|
|
} // namespace Eigen
|
2016-07-06 14:07:14 +02:00
|
|
|
|
2012-04-15 11:06:28 +01:00
|
|
|
namespace Eigen {
|
|
|
|
|
|
2016-08-31 15:45:25 +02:00
|
|
|
typedef EIGEN_DEFAULT_DENSE_INDEX_TYPE DenseIndex;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief The Index type as used for the API.
|
|
|
|
|
* \details To change this, \c \#define the preprocessor symbol \c EIGEN_DEFAULT_DENSE_INDEX_TYPE.
|
|
|
|
|
* \sa \blank \ref TopicPreprocessorDirectives, StorageIndex.
|
|
|
|
|
*/
|
|
|
|
|
typedef EIGEN_DEFAULT_DENSE_INDEX_TYPE Index;
|
|
|
|
|
|
2010-10-25 10:15:22 -04:00
|
|
|
namespace internal {
|
|
|
|
|
|
2008-08-24 15:15:32 +00:00
|
|
|
/** \internal
|
|
|
|
|
* \file Meta.h
|
|
|
|
|
* This file contains generic metaprogramming classes which are not specifically related to Eigen.
|
|
|
|
|
* \note In case you wonder, yes we're aware that Boost already provides all these features,
|
|
|
|
|
* we however don't want to add a dependency to Boost.
|
|
|
|
|
*/
|
2008-01-13 19:55:23 +00:00
|
|
|
|
2025-04-12 00:31:10 +00:00
|
|
|
using std::false_type;
|
|
|
|
|
using std::true_type;
|
2008-03-21 20:26:14 +00:00
|
|
|
|
2019-09-11 15:40:07 +02:00
|
|
|
template <bool Condition>
|
|
|
|
|
struct bool_constant;
|
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
struct bool_constant<true> : true_type {};
|
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
struct bool_constant<false> : false_type {};
|
|
|
|
|
|
2022-03-31 15:08:01 -07:00
|
|
|
// Third-party libraries rely on these.
|
|
|
|
|
using std::conditional;
|
|
|
|
|
using std::remove_const;
|
|
|
|
|
using std::remove_pointer;
|
|
|
|
|
using std::remove_reference;
|
|
|
|
|
|
2010-10-26 16:47:01 +02:00
|
|
|
template <typename T>
|
|
|
|
|
struct remove_all {
|
|
|
|
|
typedef T type;
|
|
|
|
|
};
|
|
|
|
|
template <typename T>
|
|
|
|
|
struct remove_all<const T> {
|
|
|
|
|
typedef typename remove_all<T>::type type;
|
|
|
|
|
};
|
2010-11-26 18:06:08 +01:00
|
|
|
template <typename T>
|
|
|
|
|
struct remove_all<T const&> {
|
|
|
|
|
typedef typename remove_all<T>::type type;
|
|
|
|
|
};
|
2010-10-26 16:47:01 +02:00
|
|
|
template <typename T>
|
|
|
|
|
struct remove_all<T&> {
|
|
|
|
|
typedef typename remove_all<T>::type type;
|
|
|
|
|
};
|
2010-11-26 18:06:08 +01:00
|
|
|
template <typename T>
|
|
|
|
|
struct remove_all<T const*> {
|
|
|
|
|
typedef typename remove_all<T>::type type;
|
|
|
|
|
};
|
2010-10-26 16:47:01 +02:00
|
|
|
template <typename T>
|
|
|
|
|
struct remove_all<T*> {
|
|
|
|
|
typedef typename remove_all<T>::type type;
|
|
|
|
|
};
|
2010-10-25 10:15:22 -04:00
|
|
|
|
2022-03-16 16:43:40 +00:00
|
|
|
template <typename T>
|
|
|
|
|
using remove_all_t = typename remove_all<T>::type;
|
|
|
|
|
|
2010-10-25 22:13:49 +02:00
|
|
|
template <typename T>
|
|
|
|
|
struct is_arithmetic {
|
|
|
|
|
enum { value = false };
|
|
|
|
|
};
|
|
|
|
|
template <>
|
|
|
|
|
struct is_arithmetic<float> {
|
|
|
|
|
enum { value = true };
|
|
|
|
|
};
|
|
|
|
|
template <>
|
|
|
|
|
struct is_arithmetic<double> {
|
2018-04-23 16:26:29 +02:00
|
|
|
enum { value = true };
|
2023-11-29 11:12:48 +00:00
|
|
|
};
|
2023-02-24 21:49:59 +00:00
|
|
|
// GPU devices treat `long double` as `double`.
|
|
|
|
|
#ifndef EIGEN_GPU_COMPILE_PHASE
|
2010-10-25 22:13:49 +02:00
|
|
|
template <>
|
|
|
|
|
struct is_arithmetic<long double> {
|
|
|
|
|
enum { value = true };
|
|
|
|
|
};
|
2023-02-24 21:49:59 +00:00
|
|
|
#endif
|
2010-10-25 22:13:49 +02:00
|
|
|
template <>
|
|
|
|
|
struct is_arithmetic<bool> {
|
|
|
|
|
enum { value = true };
|
|
|
|
|
};
|
|
|
|
|
template <>
|
|
|
|
|
struct is_arithmetic<char> {
|
|
|
|
|
enum { value = true };
|
|
|
|
|
};
|
|
|
|
|
template <>
|
|
|
|
|
struct is_arithmetic<signed char> {
|
|
|
|
|
enum { value = true };
|
|
|
|
|
};
|
|
|
|
|
template <>
|
|
|
|
|
struct is_arithmetic<unsigned char> {
|
|
|
|
|
enum { value = true };
|
|
|
|
|
};
|
|
|
|
|
template <>
|
|
|
|
|
struct is_arithmetic<signed short> {
|
|
|
|
|
enum { value = true };
|
|
|
|
|
};
|
|
|
|
|
template <>
|
|
|
|
|
struct is_arithmetic<unsigned short> {
|
|
|
|
|
enum { value = true };
|
|
|
|
|
};
|
|
|
|
|
template <>
|
|
|
|
|
struct is_arithmetic<signed int> {
|
|
|
|
|
enum { value = true };
|
|
|
|
|
};
|
|
|
|
|
template <>
|
|
|
|
|
struct is_arithmetic<unsigned int> {
|
|
|
|
|
enum { value = true };
|
|
|
|
|
};
|
|
|
|
|
template <>
|
|
|
|
|
struct is_arithmetic<signed long> {
|
|
|
|
|
enum { value = true };
|
|
|
|
|
};
|
|
|
|
|
template <>
|
|
|
|
|
struct is_arithmetic<unsigned long> {
|
2019-09-24 12:52:45 -07:00
|
|
|
enum { value = true };
|
|
|
|
|
};
|
2023-11-29 11:12:48 +00:00
|
|
|
|
2019-09-24 12:52:45 -07:00
|
|
|
template <typename T, typename U>
|
|
|
|
|
struct is_same {
|
|
|
|
|
enum { value = 0 };
|
2023-11-29 11:12:48 +00:00
|
|
|
};
|
2019-09-24 12:52:45 -07:00
|
|
|
template <typename T>
|
|
|
|
|
struct is_same<T, T> {
|
|
|
|
|
enum { value = 1 };
|
2023-11-29 11:12:48 +00:00
|
|
|
};
|
|
|
|
|
|
2019-09-24 12:52:45 -07:00
|
|
|
template <class T>
|
2022-03-16 16:43:40 +00:00
|
|
|
struct is_void : is_same<void, std::remove_const_t<T>> {};
|
2019-09-24 12:52:45 -07:00
|
|
|
|
2023-01-20 17:38:13 +00:00
|
|
|
/** \internal
|
|
|
|
|
* Implementation of std::void_t for SFINAE.
|
|
|
|
|
*
|
|
|
|
|
* Pre C++17:
|
|
|
|
|
* Custom implementation.
|
|
|
|
|
*
|
|
|
|
|
* Post C++17: Uses std::void_t
|
|
|
|
|
*/
|
2025-02-28 19:52:37 +00:00
|
|
|
#if EIGEN_COMP_CXXVER >= 17 && defined(__cpp_lib_void_t) && __cpp_lib_void_t >= 201411L
|
2023-01-20 17:38:13 +00:00
|
|
|
using std::void_t;
|
|
|
|
|
#else
|
|
|
|
|
template <typename...>
|
|
|
|
|
using void_t = void;
|
|
|
|
|
#endif
|
|
|
|
|
|
2018-04-23 16:26:29 +02:00
|
|
|
template <>
|
|
|
|
|
struct is_arithmetic<signed long long> {
|
|
|
|
|
enum { value = true };
|
|
|
|
|
};
|
|
|
|
|
template <>
|
|
|
|
|
struct is_arithmetic<unsigned long long> {
|
2010-12-01 09:22:54 -05:00
|
|
|
enum { value = true };
|
2023-11-29 11:12:48 +00:00
|
|
|
};
|
2017-02-13 17:14:26 +01:00
|
|
|
using std::is_integral;
|
|
|
|
|
|
2018-08-08 20:19:32 -07:00
|
|
|
using std::make_unsigned;
|
2015-11-20 13:54:28 +01:00
|
|
|
|
2010-12-01 09:22:54 -05:00
|
|
|
template <typename T>
|
|
|
|
|
struct is_const {
|
|
|
|
|
enum { value = 0 };
|
|
|
|
|
};
|
|
|
|
|
template <typename T>
|
|
|
|
|
struct is_const<T const> {
|
|
|
|
|
enum { value = 1 };
|
|
|
|
|
};
|
2010-11-26 16:56:03 +01:00
|
|
|
|
2010-11-26 16:30:45 +01:00
|
|
|
template <typename T>
|
|
|
|
|
struct add_const_on_value_type {
|
|
|
|
|
typedef const T type;
|
|
|
|
|
};
|
2010-11-26 16:56:03 +01:00
|
|
|
template <typename T>
|
|
|
|
|
struct add_const_on_value_type<T&> {
|
|
|
|
|
typedef T const& type;
|
|
|
|
|
};
|
|
|
|
|
template <typename T>
|
|
|
|
|
struct add_const_on_value_type<T*> {
|
|
|
|
|
typedef T const* type;
|
|
|
|
|
};
|
2010-11-26 18:06:08 +01:00
|
|
|
template <typename T>
|
|
|
|
|
struct add_const_on_value_type<T* const> {
|
|
|
|
|
typedef T const* const type;
|
|
|
|
|
};
|
|
|
|
|
template <typename T>
|
|
|
|
|
struct add_const_on_value_type<T const* const> {
|
|
|
|
|
typedef T const* const type;
|
|
|
|
|
};
|
2010-10-25 10:15:22 -04:00
|
|
|
|
2022-03-16 16:43:40 +00:00
|
|
|
template <typename T>
|
|
|
|
|
using add_const_on_value_type_t = typename add_const_on_value_type<T>::type;
|
2019-10-10 17:41:47 +02:00
|
|
|
|
2022-03-16 16:43:40 +00:00
|
|
|
using std::is_convertible;
|
2009-03-26 12:50:24 +00:00
|
|
|
|
2012-06-04 13:21:15 +02:00
|
|
|
/** \internal
|
2018-03-11 10:01:44 -04:00
|
|
|
* A base class do disable default copy ctor and copy assignment operator.
|
2012-06-04 13:21:15 +02:00
|
|
|
*/
|
|
|
|
|
class noncopyable {
|
2015-09-03 14:14:54 +02:00
|
|
|
EIGEN_DEVICE_FUNC noncopyable(const noncopyable&);
|
|
|
|
|
EIGEN_DEVICE_FUNC const noncopyable& operator=(const noncopyable&);
|
2023-11-29 11:12:48 +00:00
|
|
|
|
2012-06-04 13:21:15 +02:00
|
|
|
protected:
|
2015-09-03 14:14:54 +02:00
|
|
|
EIGEN_DEVICE_FUNC noncopyable() {}
|
|
|
|
|
EIGEN_DEVICE_FUNC ~noncopyable() {}
|
2012-06-04 13:21:15 +02:00
|
|
|
};
|
|
|
|
|
|
2017-01-11 17:24:02 +01:00
|
|
|
/** \internal
|
|
|
|
|
* Provides access to the number of elements in the object of as a compile-time constant expression.
|
|
|
|
|
* It "returns" Eigen::Dynamic if the size cannot be resolved at compile-time (default).
|
|
|
|
|
*
|
|
|
|
|
* Similar to std::tuple_size, but more general.
|
|
|
|
|
*
|
|
|
|
|
* It currently supports:
|
|
|
|
|
* - any types T defining T::SizeAtCompileTime
|
|
|
|
|
* - plain C arrays as T[N]
|
|
|
|
|
* - std::array (c++11)
|
|
|
|
|
* - some internal types such as SingleRange and AllRange
|
|
|
|
|
*
|
2017-01-25 22:53:58 +01:00
|
|
|
* The second template parameter eases SFINAE-based specializations.
|
2017-01-11 17:24:02 +01:00
|
|
|
*/
|
|
|
|
|
template <typename T, typename EnableIf = void>
|
|
|
|
|
struct array_size {
|
2024-02-22 22:52:25 +00:00
|
|
|
static constexpr Index value = Dynamic;
|
2017-01-11 17:24:02 +01:00
|
|
|
};
|
|
|
|
|
|
2022-03-16 16:43:40 +00:00
|
|
|
template <typename T>
|
|
|
|
|
struct array_size<T, std::enable_if_t<((T::SizeAtCompileTime & 0) == 0)>> {
|
2024-02-22 22:52:25 +00:00
|
|
|
static constexpr Index value = T::SizeAtCompileTime;
|
2017-01-11 17:24:02 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <typename T, int N>
|
|
|
|
|
struct array_size<const T (&)[N]> {
|
2024-02-22 22:52:25 +00:00
|
|
|
static constexpr Index value = N;
|
2017-01-11 17:24:02 +01:00
|
|
|
};
|
2017-01-25 22:53:58 +01:00
|
|
|
template <typename T, int N>
|
|
|
|
|
struct array_size<T (&)[N]> {
|
2024-02-22 22:52:25 +00:00
|
|
|
static constexpr Index value = N;
|
2017-01-25 22:53:58 +01:00
|
|
|
};
|
2017-01-11 17:24:02 +01:00
|
|
|
|
2017-01-25 22:53:58 +01:00
|
|
|
template <typename T, std::size_t N>
|
|
|
|
|
struct array_size<const std::array<T, N>> {
|
2024-02-22 22:52:25 +00:00
|
|
|
static constexpr Index value = N;
|
2017-01-25 22:53:58 +01:00
|
|
|
};
|
2017-01-11 17:24:02 +01:00
|
|
|
template <typename T, std::size_t N>
|
|
|
|
|
struct array_size<std::array<T, N>> {
|
2024-02-22 22:52:25 +00:00
|
|
|
static constexpr Index value = N;
|
2017-01-11 17:24:02 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/** \internal
|
2022-01-05 00:46:09 +00:00
|
|
|
* Analogue of the std::ssize free function.
|
|
|
|
|
* It returns the signed size of the container or view \a x of type \c T
|
2017-01-11 17:24:02 +01:00
|
|
|
*
|
|
|
|
|
* It currently supports:
|
|
|
|
|
* - any types T defining a member T::size() const
|
|
|
|
|
* - plain C arrays as T[N]
|
|
|
|
|
*
|
2022-01-05 00:46:09 +00:00
|
|
|
* For C++20, this function just forwards to `std::ssize`, or any ADL discoverable `ssize` function.
|
2017-01-11 17:24:02 +01:00
|
|
|
*/
|
2025-02-28 19:52:37 +00:00
|
|
|
#if EIGEN_COMP_CXXVER >= 20 && defined(__cpp_lib_ssize) && __cpp_lib_ssize >= 201902L
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
2024-11-15 21:11:01 -08:00
|
|
|
constexpr auto index_list_size(T&& x) {
|
2025-02-28 19:52:37 +00:00
|
|
|
using std::ssize;
|
|
|
|
|
return ssize(std::forward<T>(x));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
2022-01-05 00:46:09 +00:00
|
|
|
template <typename T>
|
2024-11-15 21:11:01 -08:00
|
|
|
constexpr auto index_list_size(const T& x) {
|
2022-01-05 00:46:09 +00:00
|
|
|
using R = std::common_type_t<std::ptrdiff_t, std::make_signed_t<decltype(x.size())>>;
|
|
|
|
|
return static_cast<R>(x.size());
|
|
|
|
|
}
|
2017-01-11 17:24:02 +01:00
|
|
|
|
2022-01-05 00:46:09 +00:00
|
|
|
template <typename T, std::ptrdiff_t N>
|
2024-11-15 21:11:01 -08:00
|
|
|
constexpr std::ptrdiff_t index_list_size(const T (&)[N]) {
|
2022-01-05 00:46:09 +00:00
|
|
|
return N;
|
|
|
|
|
}
|
2025-02-28 19:52:37 +00:00
|
|
|
#endif
|
2017-01-11 17:24:02 +01:00
|
|
|
|
2008-03-08 19:02:24 +00:00
|
|
|
/** \internal
|
2021-02-17 11:59:33 -08:00
|
|
|
* Convenient struct to get the result type of a nullary, unary, binary, or
|
|
|
|
|
* ternary functor.
|
2022-01-21 01:48:59 +00:00
|
|
|
*
|
|
|
|
|
* Pre C++17:
|
2021-02-17 11:59:33 -08:00
|
|
|
* This uses std::result_of. However, note the `type` member removes
|
|
|
|
|
* const and converts references/pointers to their corresponding value type.
|
2022-01-21 01:48:59 +00:00
|
|
|
*
|
|
|
|
|
* Post C++17: Uses std::invoke_result
|
2008-03-06 11:36:27 +00:00
|
|
|
*/
|
2021-02-17 11:59:33 -08:00
|
|
|
#if EIGEN_HAS_STD_INVOKE_RESULT
|
|
|
|
|
template <typename T>
|
|
|
|
|
struct result_of;
|
|
|
|
|
|
|
|
|
|
template <typename F, typename... ArgTypes>
|
|
|
|
|
struct result_of<F(ArgTypes...)> {
|
|
|
|
|
typedef typename std::invoke_result<F, ArgTypes...>::type type1;
|
2022-03-16 16:43:40 +00:00
|
|
|
typedef remove_all_t<type1> type;
|
2021-02-17 11:59:33 -08:00
|
|
|
};
|
2016-06-06 12:06:42 -07:00
|
|
|
|
2021-02-17 11:59:33 -08:00
|
|
|
template <typename F, typename... ArgTypes>
|
|
|
|
|
struct invoke_result {
|
|
|
|
|
typedef typename std::invoke_result<F, ArgTypes...>::type type1;
|
2022-03-16 16:43:40 +00:00
|
|
|
typedef remove_all_t<type1> type;
|
2021-02-17 11:59:33 -08:00
|
|
|
};
|
2021-11-24 20:08:49 +00:00
|
|
|
#else
|
2022-01-21 01:48:59 +00:00
|
|
|
template <typename T>
|
|
|
|
|
struct result_of {
|
|
|
|
|
typedef typename std::result_of<T>::type type1;
|
2022-03-16 16:43:40 +00:00
|
|
|
typedef remove_all_t<type1> type;
|
2021-02-17 11:59:33 -08:00
|
|
|
};
|
2021-08-26 13:05:23 -07:00
|
|
|
|
2022-01-21 01:48:59 +00:00
|
|
|
template <typename F, typename... ArgTypes>
|
|
|
|
|
struct invoke_result {
|
|
|
|
|
typedef typename result_of<F(ArgTypes...)>::type type1;
|
2022-03-16 16:43:40 +00:00
|
|
|
typedef remove_all_t<type1> type;
|
2021-08-26 13:05:23 -07:00
|
|
|
};
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// Reduces a sequence of bools to true if all are true, false otherwise.
|
|
|
|
|
template <bool... values>
|
2022-01-21 01:48:59 +00:00
|
|
|
using reduce_all =
|
|
|
|
|
std::is_same<std::integer_sequence<bool, values..., true>, std::integer_sequence<bool, true, values...>>;
|
2021-08-26 13:05:23 -07:00
|
|
|
|
|
|
|
|
// Reduces a sequence of bools to true if any are true, false if all false.
|
|
|
|
|
template <bool... values>
|
2022-01-21 01:48:59 +00:00
|
|
|
using reduce_any = std::integral_constant<bool, !std::is_same<std::integer_sequence<bool, values..., false>,
|
|
|
|
|
std::integer_sequence<bool, false, values...>>::value>;
|
2021-08-26 13:05:23 -07:00
|
|
|
|
2016-08-31 23:04:14 +02:00
|
|
|
struct meta_yes {
|
|
|
|
|
char a[1];
|
|
|
|
|
};
|
|
|
|
|
struct meta_no {
|
|
|
|
|
char a[2];
|
|
|
|
|
};
|
|
|
|
|
|
2016-07-20 09:56:39 +02:00
|
|
|
// Check whether T::ReturnType does exist
|
|
|
|
|
template <typename T>
|
|
|
|
|
struct has_ReturnType {
|
2017-03-17 17:33:15 +01:00
|
|
|
template <typename C>
|
|
|
|
|
static meta_yes testFunctor(C const*, typename C::ReturnType const* = 0);
|
|
|
|
|
template <typename C>
|
|
|
|
|
static meta_no testFunctor(...);
|
2016-07-20 09:56:39 +02:00
|
|
|
|
2017-03-17 17:33:15 +01:00
|
|
|
enum { value = sizeof(testFunctor<T>(static_cast<T*>(0))) == sizeof(meta_yes) };
|
2016-07-20 09:56:39 +02:00
|
|
|
};
|
|
|
|
|
|
2016-11-17 17:54:27 -05:00
|
|
|
template <typename T>
|
|
|
|
|
const T* return_ptr();
|
2016-08-31 15:45:25 +02:00
|
|
|
|
2016-09-05 15:50:41 +02:00
|
|
|
template <typename T, typename IndexType = Index>
|
2016-08-31 15:45:25 +02:00
|
|
|
struct has_nullary_operator {
|
2022-03-16 16:43:40 +00:00
|
|
|
template <typename C>
|
|
|
|
|
static meta_yes testFunctor(C const*, std::enable_if_t<(sizeof(return_ptr<C>()->operator()()) > 0)>* = 0);
|
2016-08-31 15:45:25 +02:00
|
|
|
static meta_no testFunctor(...);
|
|
|
|
|
|
|
|
|
|
enum { value = sizeof(testFunctor(static_cast<T*>(0))) == sizeof(meta_yes) };
|
|
|
|
|
};
|
|
|
|
|
|
2016-09-05 15:50:41 +02:00
|
|
|
template <typename T, typename IndexType = Index>
|
2016-08-31 15:45:25 +02:00
|
|
|
struct has_unary_operator {
|
2022-03-16 16:43:40 +00:00
|
|
|
template <typename C>
|
|
|
|
|
static meta_yes testFunctor(C const*, std::enable_if_t<(sizeof(return_ptr<C>()->operator()(IndexType(0))) > 0)>* = 0);
|
2016-08-31 15:45:25 +02:00
|
|
|
static meta_no testFunctor(...);
|
|
|
|
|
|
|
|
|
|
enum { value = sizeof(testFunctor(static_cast<T*>(0))) == sizeof(meta_yes) };
|
|
|
|
|
};
|
|
|
|
|
|
2016-09-05 15:50:41 +02:00
|
|
|
template <typename T, typename IndexType = Index>
|
2016-08-31 15:45:25 +02:00
|
|
|
struct has_binary_operator {
|
2022-03-16 16:43:40 +00:00
|
|
|
template <typename C>
|
|
|
|
|
static meta_yes testFunctor(
|
|
|
|
|
C const*, std::enable_if_t<(sizeof(return_ptr<C>()->operator()(IndexType(0), IndexType(0))) > 0)>* = 0);
|
2016-08-31 15:45:25 +02:00
|
|
|
static meta_no testFunctor(...);
|
|
|
|
|
|
|
|
|
|
enum { value = sizeof(testFunctor(static_cast<T*>(0))) == sizeof(meta_yes) };
|
|
|
|
|
};
|
|
|
|
|
|
2008-08-24 15:15:32 +00:00
|
|
|
/** \internal In short, it computes int(sqrt(\a Y)) with \a Y an integer.
|
2010-10-25 10:15:22 -04:00
|
|
|
* Usage example: \code meta_sqrt<1023>::ret \endcode
|
2008-08-24 15:15:32 +00:00
|
|
|
*/
|
2008-08-24 19:14:20 +00:00
|
|
|
template <int Y, int InfX = 0, int SupX = ((Y == 1) ? 1 : Y / 2),
|
2022-03-16 00:08:16 +00:00
|
|
|
bool Done = ((SupX - InfX) <= 1 || ((SupX * SupX <= Y) && ((SupX + 1) * (SupX + 1) > Y)))>
|
2010-10-25 10:15:22 -04:00
|
|
|
class meta_sqrt {
|
2008-08-23 17:11:44 +00:00
|
|
|
enum {
|
2008-08-24 15:15:32 +00:00
|
|
|
MidX = (InfX + SupX) / 2,
|
2008-08-24 19:14:20 +00:00
|
|
|
TakeInf = MidX * MidX > Y ? 1 : 0,
|
|
|
|
|
NewInf = int(TakeInf) ? InfX : int(MidX),
|
|
|
|
|
NewSup = int(TakeInf) ? int(MidX) : SupX
|
2010-10-25 10:15:22 -04:00
|
|
|
};
|
2008-07-29 16:33:07 +00:00
|
|
|
|
2023-11-29 11:12:48 +00:00
|
|
|
public:
|
2010-10-25 10:15:22 -04:00
|
|
|
enum { ret = meta_sqrt<Y, NewInf, NewSup>::ret };
|
2023-11-29 11:12:48 +00:00
|
|
|
};
|
|
|
|
|
|
2008-08-24 15:15:32 +00:00
|
|
|
template <int Y, int InfX, int SupX>
|
2010-10-25 10:15:22 -04:00
|
|
|
class meta_sqrt<Y, InfX, SupX, true> {
|
2023-11-29 11:12:48 +00:00
|
|
|
public:
|
2010-10-25 10:15:22 -04:00
|
|
|
enum { ret = (SupX * SupX <= Y) ? SupX : InfX };
|
2023-11-29 11:12:48 +00:00
|
|
|
};
|
2016-01-27 17:11:39 +01:00
|
|
|
|
|
|
|
|
/** \internal Computes the least common multiple of two positive integer A and B
|
2021-08-11 18:10:01 +00:00
|
|
|
* at compile-time.
|
2016-01-27 17:11:39 +01:00
|
|
|
*/
|
2021-08-11 18:10:01 +00:00
|
|
|
template <int A, int B, int K = 1, bool Done = ((A * K) % B) == 0, bool Big = (A >= B)>
|
2016-01-27 17:11:39 +01:00
|
|
|
struct meta_least_common_multiple {
|
|
|
|
|
enum { ret = meta_least_common_multiple<A, B, K + 1>::ret };
|
|
|
|
|
};
|
2021-08-11 18:10:01 +00:00
|
|
|
template <int A, int B, int K, bool Done>
|
|
|
|
|
struct meta_least_common_multiple<A, B, K, Done, false> {
|
|
|
|
|
enum { ret = meta_least_common_multiple<B, A, K>::ret };
|
|
|
|
|
};
|
2016-01-27 17:11:39 +01:00
|
|
|
template <int A, int B, int K>
|
2021-08-11 18:10:01 +00:00
|
|
|
struct meta_least_common_multiple<A, B, K, true, true> {
|
2016-01-27 17:11:39 +01:00
|
|
|
enum { ret = A * K };
|
|
|
|
|
};
|
|
|
|
|
|
2008-12-21 20:55:46 +00:00
|
|
|
/** \internal determines whether the product of two numeric types is allowed and what the return type is */
|
2013-03-20 21:19:16 +01:00
|
|
|
template <typename T, typename U>
|
|
|
|
|
struct scalar_product_traits {
|
|
|
|
|
enum { Defined = 0 };
|
|
|
|
|
};
|
2008-12-21 20:55:46 +00:00
|
|
|
|
2010-10-25 10:15:22 -04:00
|
|
|
// FIXME quick workaround around current limitation of result_of
|
2010-07-19 16:49:09 +02:00
|
|
|
// template<typename Scalar, typename ArgType0, typename ArgType1>
|
2010-10-25 10:15:22 -04:00
|
|
|
// struct result_of<scalar_product_op<Scalar>(ArgType0,ArgType1)> {
|
2022-03-16 16:43:40 +00:00
|
|
|
// typedef typename scalar_product_traits<remove_all_t<ArgType0>, remove_all_t<ArgType1>>::ReturnType type;
|
2010-07-19 16:49:09 +02:00
|
|
|
// };
|
2008-12-21 20:55:46 +00:00
|
|
|
|
2019-11-07 14:34:06 +00:00
|
|
|
/** \internal Obtains a POD type suitable to use as storage for an object of a size
|
|
|
|
|
* of at most Len bytes, aligned as specified by \c Align.
|
|
|
|
|
*/
|
|
|
|
|
template <unsigned Len, unsigned Align>
|
|
|
|
|
struct aligned_storage {
|
|
|
|
|
struct type {
|
|
|
|
|
EIGEN_ALIGN_TO_BOUNDARY(Align) unsigned char data[Len];
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
2010-10-25 10:15:22 -04:00
|
|
|
} // end namespace internal
|
|
|
|
|
|
2022-01-26 18:16:19 +00:00
|
|
|
template <typename T>
|
|
|
|
|
struct NumTraits;
|
|
|
|
|
|
2013-11-07 09:01:26 +01:00
|
|
|
namespace numext {
|
2018-08-01 12:36:24 -07:00
|
|
|
|
2018-06-14 10:21:54 -04:00
|
|
|
#if defined(EIGEN_GPU_COMPILE_PHASE)
|
2013-11-07 09:01:26 +01:00
|
|
|
template <typename T>
|
|
|
|
|
EIGEN_DEVICE_FUNC void swap(T& a, T& b) {
|
|
|
|
|
T tmp = b;
|
|
|
|
|
b = a;
|
|
|
|
|
a = tmp;
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
template <typename T>
|
|
|
|
|
EIGEN_STRONG_INLINE void swap(T& a, T& b) {
|
|
|
|
|
std::swap(a, b);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2016-01-22 15:02:21 +01:00
|
|
|
using std::numeric_limits;
|
|
|
|
|
|
2023-07-07 20:19:58 +00:00
|
|
|
// Handle integer comparisons of different signedness.
|
|
|
|
|
template <typename X, typename Y, bool XIsInteger = NumTraits<X>::IsInteger, bool XIsSigned = NumTraits<X>::IsSigned,
|
|
|
|
|
bool YIsInteger = NumTraits<Y>::IsInteger, bool YIsSigned = NumTraits<Y>::IsSigned>
|
|
|
|
|
struct equal_strict_impl {
|
|
|
|
|
static EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool run(const X& x, const Y& y) { return x == y; }
|
|
|
|
|
};
|
|
|
|
|
template <typename X, typename Y>
|
|
|
|
|
struct equal_strict_impl<X, Y, true, false, true, true> {
|
|
|
|
|
// X is an unsigned integer
|
|
|
|
|
// Y is a signed integer
|
|
|
|
|
// if Y is non-negative, it may be represented exactly as its unsigned counterpart.
|
|
|
|
|
using UnsignedY = typename internal::make_unsigned<Y>::type;
|
|
|
|
|
static EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool run(const X& x, const Y& y) {
|
|
|
|
|
return y < Y(0) ? false : (x == static_cast<UnsignedY>(y));
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
template <typename X, typename Y>
|
|
|
|
|
struct equal_strict_impl<X, Y, true, true, true, false> {
|
|
|
|
|
// X is a signed integer
|
|
|
|
|
// Y is an unsigned integer
|
|
|
|
|
static EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool run(const X& x, const Y& y) {
|
|
|
|
|
return equal_strict_impl<Y, X>::run(y, x);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2018-04-11 15:24:13 +02:00
|
|
|
// The aim of the following functions is to bypass -Wfloat-equal warnings
|
|
|
|
|
// when we really want a strict equality comparison on floating points.
|
2023-07-07 20:19:58 +00:00
|
|
|
template <typename X, typename Y>
|
|
|
|
|
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool equal_strict(const X& x, const Y& y) {
|
|
|
|
|
return equal_strict_impl<X, Y>::run(x, y);
|
|
|
|
|
}
|
2018-04-11 15:24:13 +02:00
|
|
|
|
2018-10-22 16:18:24 -07:00
|
|
|
#if !defined(EIGEN_GPU_COMPILE_PHASE) || (!defined(EIGEN_CUDA_ARCH) && defined(EIGEN_CONSTEXPR_ARE_DEVICE_FUNC))
|
2018-06-07 13:02:07 -07:00
|
|
|
template <>
|
2018-04-11 15:24:13 +02:00
|
|
|
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool equal_strict(const float& x, const float& y) {
|
|
|
|
|
return std::equal_to<float>()(x, y);
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-07 13:02:07 -07:00
|
|
|
template <>
|
2018-04-11 15:24:13 +02:00
|
|
|
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool equal_strict(const double& x, const double& y) {
|
|
|
|
|
return std::equal_to<double>()(x, y);
|
|
|
|
|
}
|
2018-06-07 13:02:07 -07:00
|
|
|
#endif
|
2018-04-11 15:24:13 +02:00
|
|
|
|
2022-01-26 18:16:19 +00:00
|
|
|
/**
|
|
|
|
|
* \internal Performs an exact comparison of x to zero, e.g. to decide whether a term can be ignored.
|
|
|
|
|
* Use this to to bypass -Wfloat-equal warnings when exact zero is what needs to be tested.
|
|
|
|
|
*/
|
|
|
|
|
template <typename X>
|
|
|
|
|
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool is_exactly_zero(const X& x) {
|
|
|
|
|
return equal_strict(x, typename NumTraits<X>::Literal{0});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \internal Performs an exact comparison of x to one, e.g. to decide whether a factor needs to be multiplied.
|
|
|
|
|
* Use this to to bypass -Wfloat-equal warnings when exact one is what needs to be tested.
|
|
|
|
|
*/
|
|
|
|
|
template <typename X>
|
|
|
|
|
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool is_exactly_one(const X& x) {
|
|
|
|
|
return equal_strict(x, typename NumTraits<X>::Literal{1});
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-07 13:02:07 -07:00
|
|
|
template <typename X, typename Y>
|
2023-07-07 20:19:58 +00:00
|
|
|
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool not_equal_strict(const X& x, const Y& y) {
|
|
|
|
|
return !equal_strict_impl<X, Y>::run(x, y);
|
|
|
|
|
}
|
2018-04-11 15:24:13 +02:00
|
|
|
|
2018-10-22 16:18:24 -07:00
|
|
|
#if !defined(EIGEN_GPU_COMPILE_PHASE) || (!defined(EIGEN_CUDA_ARCH) && defined(EIGEN_CONSTEXPR_ARE_DEVICE_FUNC))
|
2018-06-07 13:02:07 -07:00
|
|
|
template <>
|
2018-04-11 15:24:13 +02:00
|
|
|
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool not_equal_strict(const float& x, const float& y) {
|
|
|
|
|
return std::not_equal_to<float>()(x, y);
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-07 13:02:07 -07:00
|
|
|
template <>
|
2018-04-11 15:24:13 +02:00
|
|
|
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool not_equal_strict(const double& x, const double& y) {
|
|
|
|
|
return std::not_equal_to<double>()(x, y);
|
|
|
|
|
}
|
2018-06-07 13:02:07 -07:00
|
|
|
#endif
|
2018-04-11 15:24:13 +02:00
|
|
|
|
2013-11-07 09:01:26 +01:00
|
|
|
} // end namespace numext
|
|
|
|
|
|
2021-12-10 19:27:01 +00:00
|
|
|
namespace internal {
|
2022-05-25 15:26:10 +00:00
|
|
|
|
|
|
|
|
template <typename Scalar>
|
|
|
|
|
struct is_identically_zero_impl {
|
|
|
|
|
static inline bool run(const Scalar& s) { return numext::is_exactly_zero(s); }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <typename Scalar>
|
|
|
|
|
EIGEN_STRONG_INLINE bool is_identically_zero(const Scalar& s) {
|
|
|
|
|
return is_identically_zero_impl<Scalar>::run(s);
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-10 19:27:01 +00:00
|
|
|
/// \internal Returns true if its argument is of integer or enum type.
|
|
|
|
|
/// FIXME this has the same purpose as `is_valid_index_type` in XprHelper.h
|
|
|
|
|
template <typename A>
|
|
|
|
|
constexpr bool is_int_or_enum_v = std::is_enum<A>::value || std::is_integral<A>::value;
|
|
|
|
|
|
|
|
|
|
template <typename A, typename B>
|
2024-11-15 21:11:01 -08:00
|
|
|
constexpr void plain_enum_asserts(A, B) {
|
2021-12-10 19:27:01 +00:00
|
|
|
static_assert(is_int_or_enum_v<A>, "Argument a must be an integer or enum");
|
|
|
|
|
static_assert(is_int_or_enum_v<B>, "Argument b must be an integer or enum");
|
2024-05-31 14:33:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// \internal Gets the minimum of two values which may be integers or enums
|
|
|
|
|
template <typename A, typename B>
|
2024-11-15 21:11:01 -08:00
|
|
|
constexpr int plain_enum_min(A a, B b) {
|
2024-05-31 14:33:37 +00:00
|
|
|
plain_enum_asserts(a, b);
|
2021-12-10 19:27:01 +00:00
|
|
|
return ((int)a <= (int)b) ? (int)a : (int)b;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// \internal Gets the maximum of two values which may be integers or enums
|
|
|
|
|
template <typename A, typename B>
|
2024-11-15 21:11:01 -08:00
|
|
|
constexpr int plain_enum_max(A a, B b) {
|
2024-05-31 14:33:37 +00:00
|
|
|
plain_enum_asserts(a, b);
|
2021-12-10 19:27:01 +00:00
|
|
|
return ((int)a >= (int)b) ? (int)a : (int)b;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \internal
|
|
|
|
|
* `min_size_prefer_dynamic` gives the min between compile-time sizes. 0 has absolute priority, followed by 1,
|
|
|
|
|
* followed by Dynamic, followed by other finite values. The reason for giving Dynamic the priority over
|
|
|
|
|
* finite values is that min(3, Dynamic) should be Dynamic, since that could be anything between 0 and 3.
|
|
|
|
|
*/
|
|
|
|
|
template <typename A, typename B>
|
2024-11-15 21:11:01 -08:00
|
|
|
constexpr int min_size_prefer_dynamic(A a, B b) {
|
2024-05-31 14:33:37 +00:00
|
|
|
plain_enum_asserts(a, b);
|
2021-12-10 19:27:01 +00:00
|
|
|
if ((int)a == 0 || (int)b == 0) return 0;
|
|
|
|
|
if ((int)a == 1 || (int)b == 1) return 1;
|
|
|
|
|
if ((int)a == Dynamic || (int)b == Dynamic) return Dynamic;
|
|
|
|
|
return plain_enum_min(a, b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \internal
|
|
|
|
|
* min_size_prefer_fixed is a variant of `min_size_prefer_dynamic` comparing MaxSizes. The difference is that finite
|
|
|
|
|
* values now have priority over Dynamic, so that min(3, Dynamic) gives 3. Indeed, whatever the actual value is (between
|
|
|
|
|
* 0 and 3), it is not more than 3.
|
|
|
|
|
*/
|
|
|
|
|
template <typename A, typename B>
|
2024-11-15 21:11:01 -08:00
|
|
|
constexpr int min_size_prefer_fixed(A a, B b) {
|
2024-05-31 14:33:37 +00:00
|
|
|
plain_enum_asserts(a, b);
|
2021-12-10 19:27:01 +00:00
|
|
|
if ((int)a == 0 || (int)b == 0) return 0;
|
|
|
|
|
if ((int)a == 1 || (int)b == 1) return 1;
|
|
|
|
|
if ((int)a == Dynamic && (int)b == Dynamic) return Dynamic;
|
|
|
|
|
if ((int)a == Dynamic) return (int)b;
|
|
|
|
|
if ((int)b == Dynamic) return (int)a;
|
|
|
|
|
return plain_enum_min(a, b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// \internal see `min_size_prefer_fixed`. No need for a separate variant for MaxSizes here.
|
|
|
|
|
template <typename A, typename B>
|
2024-11-15 21:11:01 -08:00
|
|
|
constexpr int max_size_prefer_dynamic(A a, B b) {
|
2024-05-31 14:33:37 +00:00
|
|
|
plain_enum_asserts(a, b);
|
2021-12-10 19:27:01 +00:00
|
|
|
if ((int)a == Dynamic || (int)b == Dynamic) return Dynamic;
|
|
|
|
|
return plain_enum_max(a, b);
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-18 19:23:14 +00:00
|
|
|
template <typename A, typename B>
|
|
|
|
|
inline constexpr int size_prefer_fixed(A a, B b) {
|
|
|
|
|
plain_enum_asserts(a, b);
|
|
|
|
|
return int(a) == Dynamic ? int(b) : int(a);
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-31 14:33:37 +00:00
|
|
|
template <typename A, typename B>
|
|
|
|
|
inline constexpr bool enum_eq_not_dynamic(A a, B b) {
|
|
|
|
|
plain_enum_asserts(a, b);
|
|
|
|
|
if ((int)a == Dynamic || (int)b == Dynamic) return false;
|
|
|
|
|
return (int)a == (int)b;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename A, typename B>
|
2024-11-15 21:11:01 -08:00
|
|
|
constexpr bool enum_lt_not_dynamic(A a, B b) {
|
2024-05-31 14:33:37 +00:00
|
|
|
plain_enum_asserts(a, b);
|
|
|
|
|
if ((int)a == Dynamic || (int)b == Dynamic) return false;
|
|
|
|
|
return (int)a < (int)b;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename A, typename B>
|
2024-11-15 21:11:01 -08:00
|
|
|
constexpr bool enum_le_not_dynamic(A a, B b) {
|
2024-05-31 14:33:37 +00:00
|
|
|
plain_enum_asserts(a, b);
|
|
|
|
|
if ((int)a == Dynamic || (int)b == Dynamic) return false;
|
|
|
|
|
return (int)a <= (int)b;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename A, typename B>
|
2024-11-15 21:11:01 -08:00
|
|
|
constexpr bool enum_gt_not_dynamic(A a, B b) {
|
2024-05-31 14:33:37 +00:00
|
|
|
plain_enum_asserts(a, b);
|
|
|
|
|
if ((int)a == Dynamic || (int)b == Dynamic) return false;
|
|
|
|
|
return (int)a > (int)b;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename A, typename B>
|
2024-11-15 21:11:01 -08:00
|
|
|
constexpr bool enum_ge_not_dynamic(A a, B b) {
|
2024-05-31 14:33:37 +00:00
|
|
|
plain_enum_asserts(a, b);
|
|
|
|
|
if ((int)a == Dynamic || (int)b == Dynamic) return false;
|
|
|
|
|
return (int)a >= (int)b;
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-10 19:27:01 +00:00
|
|
|
/// \internal Calculate logical XOR at compile time
|
2024-11-15 21:11:01 -08:00
|
|
|
constexpr bool logical_xor(bool a, bool b) { return a != b; }
|
2021-12-10 19:27:01 +00:00
|
|
|
|
|
|
|
|
/// \internal Calculate logical IMPLIES at compile time
|
2024-11-15 21:11:01 -08:00
|
|
|
constexpr bool check_implication(bool a, bool b) { return !a || b; }
|
2022-03-25 04:00:58 +00:00
|
|
|
|
|
|
|
|
/// \internal Provide fallback for std::is_constant_evaluated for pre-C++20.
|
2025-02-28 19:52:37 +00:00
|
|
|
#if EIGEN_COMP_CXXVER >= 20 && defined(__cpp_lib_is_constant_evaluated) && __cpp_lib_is_constant_evaluated >= 201811L
|
2022-03-25 04:00:58 +00:00
|
|
|
using std::is_constant_evaluated;
|
|
|
|
|
#else
|
|
|
|
|
constexpr bool is_constant_evaluated() { return false; }
|
|
|
|
|
#endif
|
|
|
|
|
|
2025-02-12 11:21:44 -08:00
|
|
|
template <typename Scalar>
|
|
|
|
|
using make_complex_t = std::conditional_t<NumTraits<Scalar>::IsComplex, Scalar, std::complex<Scalar>>;
|
|
|
|
|
|
2021-12-10 19:27:01 +00:00
|
|
|
} // end namespace internal
|
|
|
|
|
|
2012-04-15 11:06:28 +01:00
|
|
|
} // end namespace Eigen
|
|
|
|
|
|
2008-04-10 09:41:13 +00:00
|
|
|
#endif // EIGEN_META_H
|