chromium/third_party/eigen3/src/Eigen/src/Core/util/Meta.h

// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2015 Gael Guennebaud <[email protected]>
// Copyright (C) 2006-2008 Benoit Jacob <[email protected]>
//
// 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/.

#ifndef EIGEN_META_H
#define EIGEN_META_H

// IWYU pragma: private
#include "../InternalHeaderCheck.h"

#if defined(EIGEN_GPU_COMPILE_PHASE)

#include <cfloat>

#if defined(EIGEN_CUDA_ARCH)
#include <math_constants.h>
#endif

#if defined(EIGEN_HIP_DEVICE_COMPILE)
#include "Eigen/src/Core/arch/HIP/hcc/math_constants.h"
#endif

#endif

// Define portable (u)int{32,64} types
#include <cstdint>

namespace Eigen {
namespace numext {
uint8_t;
int8_t;
uint16_t;
int16_t;
uint32_t;
int32_t;
uint64_t;
int64_t;

template <size_t Size>
struct get_integer_by_size {};
template <>
struct get_integer_by_size<1> {};
template <>
struct get_integer_by_size<2> {};
template <>
struct get_integer_by_size<4> {};
template <>
struct get_integer_by_size<8> {};
}  // namespace numext
}  // namespace Eigen

namespace Eigen {

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.
 */

Index;

namespace internal {

/** \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.
 */

struct true_type {};
struct false_type {};

template <bool Condition>
struct bool_constant;

template <>
struct bool_constant<true> : true_type {};

template <>
struct bool_constant<false> : false_type {};

// Third-party libraries rely on these.
conditional;
remove_const;
remove_pointer;
remove_reference;

template <typename T>
struct remove_all {};
remove_all<const T>;
remove_all<const T &>;
remove_all<T &>;
remove_all<const T *>;
remove_all<T *>;

remove_all_t;

template <typename T>
struct is_arithmetic {};
template <>
struct is_arithmetic<float> {};
template <>
struct is_arithmetic<double> {};
// GPU devices treat `long double` as `double`.
#ifndef EIGEN_GPU_COMPILE_PHASE
template <>
struct is_arithmetic<long double> {};
#endif
template <>
struct is_arithmetic<bool> {};
template <>
struct is_arithmetic<char> {};
template <>
struct is_arithmetic<signed char> {};
template <>
struct is_arithmetic<unsigned char> {};
template <>
struct is_arithmetic<signed short> {};
template <>
struct is_arithmetic<unsigned short> {};
template <>
struct is_arithmetic<signed int> {};
template <>
struct is_arithmetic<unsigned int> {};
template <>
struct is_arithmetic<signed long> {};
template <>
struct is_arithmetic<unsigned long> {};

template <typename T, typename U>
struct is_same {};
is_same<T, T>;

template <class T>
struct is_void : is_same<void, std::remove_const_t<T>> {};

/** \internal
 * Implementation of std::void_t for SFINAE.
 *
 * Pre C++17:
 * Custom implementation.
 *
 * Post C++17: Uses std::void_t
 */
#if EIGEN_COMP_CXXVER >= 17
void_t;
#else
template <typename...>
using void_t = void;
#endif

template <>
struct is_arithmetic<signed long long> {};
template <>
struct is_arithmetic<unsigned long long> {};
is_integral;

make_unsigned;

template <typename T>
struct is_const {};
is_const<const T>;

template <typename T>
struct add_const_on_value_type {};
add_const_on_value_type<T &>;
add_const_on_value_type<T *>;
add_const_on_value_type<T *const>;
add_const_on_value_type<const T *const>;

add_const_on_value_type_t;

is_convertible;

/** \internal
 * A base class do disable default copy ctor and copy assignment operator.
 */
class noncopyable {};

/** \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
 *
 * The second template parameter eases SFINAE-based specializations.
 */
template <typename T, typename EnableIf = void>
struct array_size {};

array_size<T, std::enable_if_t<((T::SizeAtCompileTime & 0) == 0)>>;

array_size<const T (&)[N]>;
array_size<T (&)[N]>;

array_size<const std::array<T, N>>;
array_size<std::array<T, N>>;

/** \internal
 * Analogue of the std::ssize free function.
 * It returns the signed size of the container or view \a x of type \c T
 *
 * It currently supports:
 *  - any types T defining a member T::size() const
 *  - plain C arrays as T[N]
 *
 * For C++20, this function just forwards to `std::ssize`, or any ADL discoverable `ssize` function.
 */
#if EIGEN_COMP_CXXVER < 20 || EIGEN_GNUC_STRICT_LESS_THAN(10, 0, 0)
template <typename T>
EIGEN_CONSTEXPR auto index_list_size(const T& x) {
  using R = std::common_type_t<std::ptrdiff_t, std::make_signed_t<decltype(x.size())>>;
  return static_cast<R>(x.size());
}

template <typename T, std::ptrdiff_t N>
EIGEN_CONSTEXPR std::ptrdiff_t index_list_size(const T (&)[N]) {
  return N;
}
#else
template <typename T>
EIGEN_CONSTEXPR auto index_list_size(T&& x) {}
#endif  // EIGEN_COMP_CXXVER

/** \internal
 * Convenient struct to get the result type of a nullary, unary, binary, or
 * ternary functor.
 *
 * Pre C++17:
 * This uses std::result_of. However, note the `type` member removes
 * const and converts references/pointers to their corresponding value type.
 *
 * Post C++17: Uses std::invoke_result
 */
#if EIGEN_HAS_STD_INVOKE_RESULT
template <typename T>
struct result_of;

result_of<F (ArgTypes...)>;

template <typename F, typename... ArgTypes>
struct invoke_result {};
#else
template <typename T>
struct result_of {
  typedef typename std::result_of<T>::type type1;
  typedef remove_all_t<type1> type;
};

template <typename F, typename... ArgTypes>
struct invoke_result {
  typedef typename result_of<F(ArgTypes...)>::type type1;
  typedef remove_all_t<type1> type;
};
#endif

// Reduces a sequence of bools to true if all are true, false otherwise.
reduce_all;

// Reduces a sequence of bools to true if any are true, false if all false.
reduce_any;

struct meta_yes {};
struct meta_no {};

// Check whether T::ReturnType does exist
template <typename T>
struct has_ReturnType {};

template <typename T>
const T* return_ptr();

template <typename T, typename IndexType = Index>
struct has_nullary_operator {};

template <typename T, typename IndexType = Index>
struct has_unary_operator {};

template <typename T, typename IndexType = Index>
struct has_binary_operator {};

/** \internal In short, it computes int(sqrt(\a Y)) with \a Y an integer.
 * Usage example: \code meta_sqrt<1023>::ret \endcode
 */
template <int Y, int InfX = 0, int SupX = ((Y == 1) ? 1 : Y / 2),
          bool Done = ((SupX - InfX) <= 1 || ((SupX * SupX <= Y) && ((SupX + 1) * (SupX + 1) > Y)))>
class meta_sqrt {};

meta_sqrt<Y, InfX, SupX, true>;

/** \internal Computes the least common multiple of two positive integer A and B
 * at compile-time.
 */
template <int A, int B, int K = 1, bool Done = ((A * K) % B) == 0, bool Big = (A >= B)>
struct meta_least_common_multiple {};
meta_least_common_multiple<A, B, K, Done, false>;
meta_least_common_multiple<A, B, K, true, true>;

/** \internal determines whether the product of two numeric types is allowed and what the return type is */
template <typename T, typename U>
struct scalar_product_traits {};

// FIXME quick workaround around current limitation of result_of
// template<typename Scalar, typename ArgType0, typename ArgType1>
// struct result_of<scalar_product_op<Scalar>(ArgType0,ArgType1)> {
// typedef typename scalar_product_traits<remove_all_t<ArgType0>, remove_all_t<ArgType1>>::ReturnType type;
// };

/** \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 {};

}  // end namespace internal

template <typename T>
struct NumTraits;

namespace numext {

#if defined(EIGEN_GPU_COMPILE_PHASE)
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) {}
#endif

numeric_limits;

// 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 {};
equal_strict_impl<X, Y, true, false, true, true>;
equal_strict_impl<X, Y, true, true, true, false>;

// The aim of the following functions is to bypass -Wfloat-equal warnings
// when we really want a strict equality comparison on floating points.
template <typename X, typename Y>
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool equal_strict(const X& x, const Y& y) {}

#if !defined(EIGEN_GPU_COMPILE_PHASE) || (!defined(EIGEN_CUDA_ARCH) && defined(EIGEN_CONSTEXPR_ARE_DEVICE_FUNC))
template <>
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool equal_strict(const float& x, const float& y) {}

template <>
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool equal_strict(const double& x, const double& y) {}
#endif

/**
 * \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) {}

/**
 * \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) {}

template <typename X, typename Y>
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool not_equal_strict(const X& x, const Y& y) {}

#if !defined(EIGEN_GPU_COMPILE_PHASE) || (!defined(EIGEN_CUDA_ARCH) && defined(EIGEN_CONSTEXPR_ARE_DEVICE_FUNC))
template <>
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool not_equal_strict(const float& x, const float& y) {}

template <>
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool not_equal_strict(const double& x, const double& y) {}
#endif

}  // end namespace numext

namespace internal {

template <typename Scalar>
struct is_identically_zero_impl {};

template <typename Scalar>
EIGEN_STRONG_INLINE bool is_identically_zero(const Scalar& s) {}

/// \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
is_int_or_enum_v;

template <typename A, typename B>
inline constexpr void plain_enum_asserts(A, B) {}

/// \internal Gets the minimum of two values which may be integers or enums
template <typename A, typename B>
inline constexpr int plain_enum_min(A a, B b) {}

/// \internal Gets the maximum of two values which may be integers or enums
template <typename A, typename B>
inline constexpr int plain_enum_max(A a, B 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>
inline constexpr int min_size_prefer_dynamic(A a, B 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>
inline constexpr int min_size_prefer_fixed(A a, B b) {}

/// \internal see `min_size_prefer_fixed`. No need for a separate variant for MaxSizes here.
template <typename A, typename B>
inline constexpr int max_size_prefer_dynamic(A a, B b) {}

template <typename A, typename B>
inline constexpr bool enum_eq_not_dynamic(A a, B b) {}

template <typename A, typename B>
inline constexpr bool enum_lt_not_dynamic(A a, B b) {}

template <typename A, typename B>
inline constexpr bool enum_le_not_dynamic(A a, B b) {}

template <typename A, typename B>
inline constexpr bool enum_gt_not_dynamic(A a, B b) {}

template <typename A, typename B>
inline constexpr bool enum_ge_not_dynamic(A a, B b) {}

/// \internal Calculate logical XOR at compile time
inline constexpr bool logical_xor(bool a, bool b) {}

/// \internal Calculate logical IMPLIES at compile time
inline constexpr bool check_implication(bool a, bool b) {}

/// \internal Provide fallback for std::is_constant_evaluated for pre-C++20.
#if EIGEN_COMP_CXXVER >= 20
is_constant_evaluated;
#else
constexpr bool is_constant_evaluated() { return false; }
#endif

}  // end namespace internal

}  // end namespace Eigen

#endif  // EIGEN_META_H