diff --git a/upstream_utils/eigen_patches/0001-Disable-warnings.patch b/upstream_utils/eigen_patches/0001-Disable-warnings.patch index 449b4a4f30f..99c76fe6790 100644 --- a/upstream_utils/eigen_patches/0001-Disable-warnings.patch +++ b/upstream_utils/eigen_patches/0001-Disable-warnings.patch @@ -1,24 +1,21 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Tyler Veness Date: Wed, 18 May 2022 09:14:24 -0700 -Subject: [PATCH 1/4] Disable warnings +Subject: [PATCH 1/2] Disable warnings --- - Eigen/src/Core/util/DisableStupidWarnings.h | 9 +++++++++ - 1 file changed, 9 insertions(+) + Eigen/src/Core/util/DisableStupidWarnings.h | 6 ++++++ + 1 file changed, 6 insertions(+) diff --git a/Eigen/src/Core/util/DisableStupidWarnings.h b/Eigen/src/Core/util/DisableStupidWarnings.h -index 32a427d852355a51dc4263d81498554ff4c3cbba..eb259433c054c21accd2b8a5d744638f8004da40 100644 +index 32a427d852355a51dc4263d81498554ff4c3cbba..9f3e3f5b0f15518377c9a8283fd58081902896f2 100644 --- a/Eigen/src/Core/util/DisableStupidWarnings.h +++ b/Eigen/src/Core/util/DisableStupidWarnings.h -@@ -81,6 +81,15 @@ +@@ -81,6 +81,12 @@ // See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89325 #pragma GCC diagnostic ignored "-Wattributes" #endif -+#if __GNUC__>=8 -+#pragma GCC diagnostic ignored "-Wclass-memaccess" -+#endif -+#if __GNUC__>=11 ++#if __GNUC__>=11 && __GNUC__<=13 +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif +#if __GNUC__>=12 diff --git a/upstream_utils/eigen_patches/0002-Intellisense-fix.patch b/upstream_utils/eigen_patches/0002-Intellisense-fix.patch index cf15cf94217..46ac050cfe7 100644 --- a/upstream_utils/eigen_patches/0002-Intellisense-fix.patch +++ b/upstream_utils/eigen_patches/0002-Intellisense-fix.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Fri, 20 Jan 2023 23:41:56 -0800 -Subject: [PATCH 2/4] Intellisense fix +Subject: [PATCH 2/2] Intellisense fix --- Eigen/src/Core/util/ConfigureVectorization.h | 7 +++++++ diff --git a/upstream_utils/eigen_patches/0003-Suppress-C-23-deprecation-warnings-for-std-has_denor.patch b/upstream_utils/eigen_patches/0003-Suppress-C-23-deprecation-warnings-for-std-has_denor.patch deleted file mode 100644 index 9a80736c2e7..00000000000 --- a/upstream_utils/eigen_patches/0003-Suppress-C-23-deprecation-warnings-for-std-has_denor.patch +++ /dev/null @@ -1,87 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tyler Veness -Date: Mon, 13 May 2024 12:46:15 -0700 -Subject: [PATCH 3/4] Suppress C++23 deprecation warnings for std::has_denorm - and std::has_denorm_loss - ---- - Eigen/src/Core/arch/Default/BFloat16.h | 14 ++++++++++++++ - Eigen/src/Core/arch/Default/Half.h | 14 ++++++++++++++ - 2 files changed, 28 insertions(+) - -diff --git a/Eigen/src/Core/arch/Default/BFloat16.h b/Eigen/src/Core/arch/Default/BFloat16.h -index f31c6cee6e97e8f1ad6fa4341fec2c1e65dec705..c6fa034b04896e7666e8de53e0e011f9551d5d78 100644 ---- a/Eigen/src/Core/arch/Default/BFloat16.h -+++ b/Eigen/src/Core/arch/Default/BFloat16.h -@@ -139,8 +139,15 @@ struct numeric_limits_bfloat16_impl { - static EIGEN_CONSTEXPR const bool has_infinity = true; - static EIGEN_CONSTEXPR const bool has_quiet_NaN = true; - static EIGEN_CONSTEXPR const bool has_signaling_NaN = true; -+#if __cplusplus >= 202302L -+ EIGEN_DIAGNOSTICS(push) -+ EIGEN_DISABLE_DEPRECATED_WARNING -+#endif - static EIGEN_CONSTEXPR const std::float_denorm_style has_denorm = std::denorm_present; - static EIGEN_CONSTEXPR const bool has_denorm_loss = false; -+#if __cplusplus >= 202302L -+ EIGEN_DIAGNOSTICS(pop) -+#endif - static EIGEN_CONSTEXPR const std::float_round_style round_style = std::numeric_limits::round_style; - static EIGEN_CONSTEXPR const bool is_iec559 = true; - // The C++ standard defines this as "true if the set of values representable -@@ -187,10 +194,17 @@ template - EIGEN_CONSTEXPR const bool numeric_limits_bfloat16_impl::has_quiet_NaN; - template - EIGEN_CONSTEXPR const bool numeric_limits_bfloat16_impl::has_signaling_NaN; -+#if __cplusplus >= 202302L -+EIGEN_DIAGNOSTICS(push) -+EIGEN_DISABLE_DEPRECATED_WARNING -+#endif - template - EIGEN_CONSTEXPR const std::float_denorm_style numeric_limits_bfloat16_impl::has_denorm; - template - EIGEN_CONSTEXPR const bool numeric_limits_bfloat16_impl::has_denorm_loss; -+#if __cplusplus >= 202302L -+EIGEN_DIAGNOSTICS(pop) -+#endif - template - EIGEN_CONSTEXPR const std::float_round_style numeric_limits_bfloat16_impl::round_style; - template -diff --git a/Eigen/src/Core/arch/Default/Half.h b/Eigen/src/Core/arch/Default/Half.h -index 9c195c12a17fcb791c96a0ce6cf873f455c4f8be..506feca058bb7940663d9cda8b2fe902060fdc8f 100644 ---- a/Eigen/src/Core/arch/Default/Half.h -+++ b/Eigen/src/Core/arch/Default/Half.h -@@ -208,8 +208,15 @@ struct numeric_limits_half_impl { - static EIGEN_CONSTEXPR const bool has_infinity = true; - static EIGEN_CONSTEXPR const bool has_quiet_NaN = true; - static EIGEN_CONSTEXPR const bool has_signaling_NaN = true; -+#if __cplusplus >= 202302L -+ EIGEN_DIAGNOSTICS(push) -+ EIGEN_DISABLE_DEPRECATED_WARNING -+#endif - static EIGEN_CONSTEXPR const std::float_denorm_style has_denorm = std::denorm_present; - static EIGEN_CONSTEXPR const bool has_denorm_loss = false; -+#if __cplusplus >= 202302L -+ EIGEN_DIAGNOSTICS(pop) -+#endif - static EIGEN_CONSTEXPR const std::float_round_style round_style = std::round_to_nearest; - static EIGEN_CONSTEXPR const bool is_iec559 = true; - // The C++ standard defines this as "true if the set of values representable -@@ -256,10 +263,17 @@ template - EIGEN_CONSTEXPR const bool numeric_limits_half_impl::has_quiet_NaN; - template - EIGEN_CONSTEXPR const bool numeric_limits_half_impl::has_signaling_NaN; -+#if __cplusplus >= 202302L -+EIGEN_DIAGNOSTICS(push) -+EIGEN_DISABLE_DEPRECATED_WARNING -+#endif - template - EIGEN_CONSTEXPR const std::float_denorm_style numeric_limits_half_impl::has_denorm; - template - EIGEN_CONSTEXPR const bool numeric_limits_half_impl::has_denorm_loss; -+#if __cplusplus >= 202302L -+EIGEN_DIAGNOSTICS(pop) -+#endif - template - EIGEN_CONSTEXPR const std::float_round_style numeric_limits_half_impl::round_style; - template diff --git a/upstream_utils/eigen_patches/0004-Fix-compilation-failures-on-constexpr-matrices-with-.patch b/upstream_utils/eigen_patches/0004-Fix-compilation-failures-on-constexpr-matrices-with-.patch deleted file mode 100644 index 35f57d25c9f..00000000000 --- a/upstream_utils/eigen_patches/0004-Fix-compilation-failures-on-constexpr-matrices-with-.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tyler Veness -Date: Tue, 14 May 2024 14:53:02 -0700 -Subject: [PATCH 4/4] Fix compilation failures on constexpr matrices with GCC - 14 - -DenseBase must have a trivial default constructor. -`constexpr DenseBase() {}` is not sufficient. ---- - Eigen/src/Core/DenseBase.h | 22 +++++++++++----------- - 1 file changed, 11 insertions(+), 11 deletions(-) - -diff --git a/Eigen/src/Core/DenseBase.h b/Eigen/src/Core/DenseBase.h -index 5ab54efa3d8d454b2d5e02cb9d6145a723683b91..297c42679d978c36388ccba5831dab6624b6cb92 100644 ---- a/Eigen/src/Core/DenseBase.h -+++ b/Eigen/src/Core/DenseBase.h -@@ -621,20 +621,20 @@ class DenseBase - protected: - EIGEN_DEFAULT_COPY_CONSTRUCTOR(DenseBase) - /** Default constructor. Do nothing. */ -- EIGEN_DEVICE_FUNC constexpr DenseBase() { -- /* Just checks for self-consistency of the flags. -- * Only do it when debugging Eigen, as this borders on paranoia and could slow compilation down -- */ - #ifdef EIGEN_INTERNAL_DEBUGGING -- EIGEN_STATIC_ASSERT( -- (internal::check_implication(MaxRowsAtCompileTime == 1 && MaxColsAtCompileTime != 1, int(IsRowMajor)) && -- internal::check_implication(MaxColsAtCompileTime == 1 && MaxRowsAtCompileTime != 1, int(!IsRowMajor))), -- INVALID_STORAGE_ORDER_FOR_THIS_VECTOR_EXPRESSION) -+ EIGEN_DEVICE_FUNC constexpr DenseBase(){ -+ /* Just checks for self-consistency of the flags. -+ * Only do it when debugging Eigen, as this borders on paranoia and could slow compilation down -+ */ -+ EIGEN_STATIC_ASSERT( -+ (internal::check_implication(MaxRowsAtCompileTime == 1 && MaxColsAtCompileTime != 1, int(IsRowMajor)) && -+ internal::check_implication(MaxColsAtCompileTime == 1 && MaxRowsAtCompileTime != 1, int(!IsRowMajor))), -+ INVALID_STORAGE_ORDER_FOR_THIS_VECTOR_EXPRESSION)} -+#else -+ EIGEN_DEVICE_FUNC constexpr DenseBase() = default; - #endif -- } - -- private: -- EIGEN_DEVICE_FUNC explicit DenseBase(int); -+ private : EIGEN_DEVICE_FUNC explicit DenseBase(int); - EIGEN_DEVICE_FUNC DenseBase(int, int); - template - EIGEN_DEVICE_FUNC explicit DenseBase(const DenseBase&); diff --git a/upstream_utils/update_eigen.py b/upstream_utils/update_eigen.py index f031e44feff..fd8cfb4ef60 100755 --- a/upstream_utils/update_eigen.py +++ b/upstream_utils/update_eigen.py @@ -97,8 +97,8 @@ def unsupported_inclusions(dp, f): def main(): upstream_root = clone_repo( "https://gitlab.com/libeigen/eigen.git", - # master on 2024-05-07 - "99c18bce6eb225fa5a4861af97189ada1bca3103", + # master on 2024-05-22 + "c4d84dfddc9f9edef0fdbe7cf9966d2f4a303198", shallow=False, ) wpilib_root = get_repo_root() @@ -109,8 +109,6 @@ def main(): for f in [ "0001-Disable-warnings.patch", "0002-Intellisense-fix.patch", - "0003-Suppress-C-23-deprecation-warnings-for-std-has_denor.patch", - "0004-Fix-compilation-failures-on-constexpr-matrices-with-.patch", ]: git_am(os.path.join(wpilib_root, "upstream_utils/eigen_patches", f)) diff --git a/wpimath/src/main/native/thirdparty/eigen/include/.clang-format b/wpimath/src/main/native/thirdparty/eigen/include/.clang-format index 28251c665a2..f3870b820ab 100644 --- a/wpimath/src/main/native/thirdparty/eigen/include/.clang-format +++ b/wpimath/src/main/native/thirdparty/eigen/include/.clang-format @@ -2,6 +2,8 @@ Language: Cpp BasedOnStyle: Google ColumnLimit: 120 +StatementMacros: + - EIGEN_STATIC_ASSERT SortIncludes: false AttributeMacros: - EIGEN_STRONG_INLINE diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/Core b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/Core index fdd4472c390..795ff1e1311 100644 --- a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/Core +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/Core @@ -404,6 +404,7 @@ using std::ptrdiff_t; #endif #include "src/Core/GlobalFunctions.h" +#include "src/Core/DeviceWrapper.h" // IWYU pragma: end_exports #include "src/Core/util/ReenableStupidWarnings.h" diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/CoreEvaluators.h b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/CoreEvaluators.h index 5e1cbf6ecf4..5da9c57986d 100644 --- a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/CoreEvaluators.h +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/CoreEvaluators.h @@ -167,7 +167,7 @@ class plainobjectbase_evaluator_data { }; template -struct evaluator > : evaluator_base { +struct evaluator> : evaluator_base { typedef PlainObjectBase PlainObjectType; typedef typename PlainObjectType::Scalar Scalar; typedef typename PlainObjectType::CoeffReturnType CoeffReturnType; @@ -247,31 +247,29 @@ struct evaluator > : evaluator_base { }; template -struct evaluator > - : evaluator > > { +struct evaluator> + : evaluator>> { typedef Matrix XprType; EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE evaluator() {} - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit evaluator(const XprType& m) - : evaluator >(m) {} + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit evaluator(const XprType& m) : evaluator>(m) {} }; template -struct evaluator > - : evaluator > > { +struct evaluator> + : evaluator>> { typedef Array XprType; EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE evaluator() {} - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit evaluator(const XprType& m) - : evaluator >(m) {} + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit evaluator(const XprType& m) : evaluator>(m) {} }; // -------------------- Transpose -------------------- template -struct unary_evaluator, IndexBased> : evaluator_base > { +struct unary_evaluator, IndexBased> : evaluator_base> { typedef Transpose XprType; enum { @@ -460,8 +458,8 @@ struct nullary_wrapper #endif // MSVC workaround template -struct evaluator > - : evaluator_base > { +struct evaluator> + : evaluator_base> { typedef CwiseNullaryOp XprType; typedef internal::remove_all_t PlainObjectTypeCleaned; @@ -509,7 +507,7 @@ struct evaluator > // -------------------- CwiseUnaryOp -------------------- template -struct unary_evaluator, IndexBased> : evaluator_base > { +struct unary_evaluator, IndexBased> : evaluator_base> { typedef CwiseUnaryOp XprType; enum { @@ -762,17 +760,17 @@ struct unary_evaluator, ArgType>, In // this is a ternary expression template -struct evaluator > - : public ternary_evaluator > { +struct evaluator> + : public ternary_evaluator> { typedef CwiseTernaryOp XprType; - typedef ternary_evaluator > Base; + typedef ternary_evaluator> Base; EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr) : Base(xpr) {} }; template struct ternary_evaluator, IndexBased, IndexBased> - : evaluator_base > { + : evaluator_base> { typedef CwiseTernaryOp XprType; enum { @@ -865,16 +863,16 @@ struct evaluator, // this is a binary expression template -struct evaluator > : public binary_evaluator > { +struct evaluator> : public binary_evaluator> { typedef CwiseBinaryOp XprType; - typedef binary_evaluator > Base; + typedef binary_evaluator> Base; EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit evaluator(const XprType& xpr) : Base(xpr) {} }; template struct binary_evaluator, IndexBased, IndexBased> - : evaluator_base > { + : evaluator_base> { typedef CwiseBinaryOp XprType; enum { @@ -939,7 +937,7 @@ struct binary_evaluator, IndexBased, IndexBase template struct unary_evaluator, IndexBased> - : evaluator_base > { + : evaluator_base> { typedef CwiseUnaryView XprType; enum { @@ -1067,7 +1065,7 @@ struct mapbase_evaluator : evaluator_base { }; template -struct evaluator > +struct evaluator> : public mapbase_evaluator, PlainObjectType> { typedef Map XprType; typedef typename XprType::Scalar Scalar; @@ -1100,13 +1098,13 @@ struct evaluator > // -------------------- Ref -------------------- template -struct evaluator > +struct evaluator> : public mapbase_evaluator, PlainObjectType> { typedef Ref XprType; enum { - Flags = evaluator >::Flags, - Alignment = evaluator >::Alignment + Flags = evaluator>::Flags, + Alignment = evaluator>::Alignment }; EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit evaluator(const XprType& ref) @@ -1120,7 +1118,7 @@ template -struct evaluator > +struct evaluator> : block_evaluator { typedef Block XprType; typedef typename XprType::Scalar Scalar; @@ -1171,7 +1169,7 @@ struct evaluator > // no direct-access => dispatch to a unary evaluator template struct block_evaluator - : unary_evaluator > { + : unary_evaluator> { typedef Block XprType; EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit block_evaluator(const XprType& block) @@ -1180,7 +1178,7 @@ struct block_evaluator struct unary_evaluator, IndexBased> - : evaluator_base > { + : evaluator_base> { typedef Block XprType; EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit unary_evaluator(const XprType& block) @@ -1293,8 +1291,8 @@ struct block_evaluator -struct evaluator > - : evaluator_base > { +struct evaluator> + : evaluator_base> { typedef Select XprType; enum { CoeffReadCost = evaluator::CoeffReadCost + @@ -1335,8 +1333,8 @@ struct evaluator > // -------------------- Replicate -------------------- template -struct unary_evaluator > - : evaluator_base > { +struct unary_evaluator> + : evaluator_base> { typedef Replicate XprType; typedef typename XprType::CoeffReturnType CoeffReturnType; enum { Factor = (RowFactor == Dynamic || ColFactor == Dynamic) ? Dynamic : RowFactor * ColFactor }; @@ -1461,19 +1459,19 @@ struct evaluator_wrapper_base : evaluator_base { }; template -struct unary_evaluator > : evaluator_wrapper_base > { +struct unary_evaluator> : evaluator_wrapper_base> { typedef MatrixWrapper XprType; EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit unary_evaluator(const XprType& wrapper) - : evaluator_wrapper_base >(wrapper.nestedExpression()) {} + : evaluator_wrapper_base>(wrapper.nestedExpression()) {} }; template -struct unary_evaluator > : evaluator_wrapper_base > { +struct unary_evaluator> : evaluator_wrapper_base> { typedef ArrayWrapper XprType; EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit unary_evaluator(const XprType& wrapper) - : evaluator_wrapper_base >(wrapper.nestedExpression()) {} + : evaluator_wrapper_base>(wrapper.nestedExpression()) {} }; // -------------------- Reverse -------------------- @@ -1483,7 +1481,7 @@ template struct reverse_packet_cond; template -struct unary_evaluator > : evaluator_base > { +struct unary_evaluator> : evaluator_base> { typedef Reverse XprType; typedef typename XprType::Scalar Scalar; typedef typename XprType::CoeffReturnType CoeffReturnType; @@ -1584,7 +1582,7 @@ struct unary_evaluator > : evaluator_base -struct evaluator > : evaluator_base > { +struct evaluator> : evaluator_base> { typedef Diagonal XprType; enum { @@ -1643,10 +1641,10 @@ template class EvalToTemp; template -struct traits > : public traits {}; +struct traits> : public traits {}; template -class EvalToTemp : public dense_xpr_base >::type { +class EvalToTemp : public dense_xpr_base>::type { public: typedef typename dense_xpr_base::type Base; EIGEN_GENERIC_PUBLIC_INTERFACE(EvalToTemp) @@ -1664,7 +1662,7 @@ class EvalToTemp : public dense_xpr_base >::type { }; template -struct evaluator > : public evaluator { +struct evaluator> : public evaluator { typedef EvalToTemp XprType; typedef typename ArgType::PlainObject PlainObject; typedef evaluator Base; diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/DenseBase.h b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/DenseBase.h index 297c42679d9..8c8ca734794 100644 --- a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/DenseBase.h +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/DenseBase.h @@ -622,19 +622,21 @@ class DenseBase EIGEN_DEFAULT_COPY_CONSTRUCTOR(DenseBase) /** Default constructor. Do nothing. */ #ifdef EIGEN_INTERNAL_DEBUGGING - EIGEN_DEVICE_FUNC constexpr DenseBase(){ - /* Just checks for self-consistency of the flags. - * Only do it when debugging Eigen, as this borders on paranoia and could slow compilation down - */ - EIGEN_STATIC_ASSERT( - (internal::check_implication(MaxRowsAtCompileTime == 1 && MaxColsAtCompileTime != 1, int(IsRowMajor)) && - internal::check_implication(MaxColsAtCompileTime == 1 && MaxRowsAtCompileTime != 1, int(!IsRowMajor))), - INVALID_STORAGE_ORDER_FOR_THIS_VECTOR_EXPRESSION)} + EIGEN_DEVICE_FUNC constexpr DenseBase() { + /* Just checks for self-consistency of the flags. + * Only do it when debugging Eigen, as this borders on paranoia and could slow compilation down + */ + EIGEN_STATIC_ASSERT( + (internal::check_implication(MaxRowsAtCompileTime == 1 && MaxColsAtCompileTime != 1, int(IsRowMajor)) && + internal::check_implication(MaxColsAtCompileTime == 1 && MaxRowsAtCompileTime != 1, int(!IsRowMajor))), + INVALID_STORAGE_ORDER_FOR_THIS_VECTOR_EXPRESSION) + } #else EIGEN_DEVICE_FUNC constexpr DenseBase() = default; #endif - private : EIGEN_DEVICE_FUNC explicit DenseBase(int); + private: + EIGEN_DEVICE_FUNC explicit DenseBase(int); EIGEN_DEVICE_FUNC DenseBase(int, int); template EIGEN_DEVICE_FUNC explicit DenseBase(const DenseBase&); diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/DeviceWrapper.h b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/DeviceWrapper.h new file mode 100644 index 00000000000..9fdbe6079d4 --- /dev/null +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/DeviceWrapper.h @@ -0,0 +1,155 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2023 Charlie Schlosser +// +// 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_DEVICEWRAPPER_H +#define EIGEN_DEVICEWRAPPER_H + +namespace Eigen { +template +struct DeviceWrapper { + using Base = EigenBase>; + using Scalar = typename Derived::Scalar; + + EIGEN_DEVICE_FUNC DeviceWrapper(Base& xpr, Device& device) : m_xpr(xpr.derived()), m_device(device) {} + EIGEN_DEVICE_FUNC DeviceWrapper(const Base& xpr, Device& device) : m_xpr(xpr.derived()), m_device(device) {} + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator=(const EigenBase& other) { + using AssignOp = internal::assign_op; + internal::call_assignment(*this, other.derived(), AssignOp()); + return m_xpr; + } + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator+=(const EigenBase& other) { + using AddAssignOp = internal::add_assign_op; + internal::call_assignment(*this, other.derived(), AddAssignOp()); + return m_xpr; + } + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator-=(const EigenBase& other) { + using SubAssignOp = internal::sub_assign_op; + internal::call_assignment(*this, other.derived(), SubAssignOp()); + return m_xpr; + } + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& derived() { return m_xpr; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Device& device() { return m_device; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE NoAlias noalias() { + return NoAlias(*this); + } + + Derived& m_xpr; + Device& m_device; +}; + +namespace internal { + +// this is where we differentiate between lazy assignment and specialized kernels (e.g. matrix products) +template ::Shape, + typename evaluator_traits::Shape>::Kind, + typename EnableIf = void> +struct AssignmentWithDevice; + +// unless otherwise specified, use the default product implementation +template +struct AssignmentWithDevice, Functor, Device, Dense2Dense, Weak> { + using SrcXprType = Product; + using Base = Assignment; + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(DstXprType& dst, const SrcXprType& src, const Functor& func, + Device&) { + Base::run(dst, src, func); + }; +}; + +// specialization for coeffcient-wise assignment +template +struct AssignmentWithDevice { + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(DstXprType& dst, const SrcXprType& src, const Functor& func, + Device& device) { +#ifndef EIGEN_NO_DEBUG + internal::check_for_aliasing(dst, src); +#endif + + call_dense_assignment_loop(dst, src, func, device); + } +}; + +// this allows us to use the default evaulation scheme if it is not specialized for the device +template +struct dense_assignment_loop_with_device { + using Base = dense_assignment_loop; + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR void run(Kernel& kernel, Device&) { Base::run(kernel); } +}; + +// entry point for a generic expression with device +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR void call_assignment_no_alias(DeviceWrapper dst, + const Src& src, const Func& func) { + enum { + NeedToTranspose = ((int(Dst::RowsAtCompileTime) == 1 && int(Src::ColsAtCompileTime) == 1) || + (int(Dst::ColsAtCompileTime) == 1 && int(Src::RowsAtCompileTime) == 1)) && + int(Dst::SizeAtCompileTime) != 1 + }; + + using ActualDstTypeCleaned = std::conditional_t, Dst>; + using ActualDstType = std::conditional_t, Dst&>; + ActualDstType actualDst(dst.derived()); + + // TODO check whether this is the right place to perform these checks: + EIGEN_STATIC_ASSERT_LVALUE(Dst) + EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(ActualDstTypeCleaned, Src) + EIGEN_CHECK_BINARY_COMPATIBILIY(Func, typename ActualDstTypeCleaned::Scalar, typename Src::Scalar); + + // this provides a mechanism for specializing simple assignments, matrix products, etc + AssignmentWithDevice::run(actualDst, src, func, dst.device()); +} + +// copy and pasted from AssignEvaluator except forward device to kernel +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR void call_dense_assignment_loop(DstXprType& dst, + const SrcXprType& src, + const Functor& func, + Device& device) { + using DstEvaluatorType = evaluator; + using SrcEvaluatorType = evaluator; + + SrcEvaluatorType srcEvaluator(src); + + // NOTE To properly handle A = (A*A.transpose())/s with A rectangular, + // we need to resize the destination after the source evaluator has been created. + resize_if_allowed(dst, src, func); + + DstEvaluatorType dstEvaluator(dst); + + using Kernel = generic_dense_assignment_kernel; + + Kernel kernel(dstEvaluator, srcEvaluator, func, dst.const_cast_derived()); + + dense_assignment_loop_with_device::run(kernel, device); +} + +} // namespace internal + +template +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DeviceWrapper EigenBase::device(Device& device) { + return DeviceWrapper(derived(), device); +} + +template +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DeviceWrapper EigenBase::device( + Device& device) const { + return DeviceWrapper(derived(), device); +} +} // namespace Eigen +#endif \ No newline at end of file diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/EigenBase.h b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/EigenBase.h index f485016ac49..a2d6ee2ec32 100644 --- a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/EigenBase.h +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/EigenBase.h @@ -104,6 +104,11 @@ struct EigenBase { // derived class can reimplement it in a more optimized way. dst = this->derived() * dst; } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DeviceWrapper device(Device& device); + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DeviceWrapper device(Device& device) const; }; /*************************************************************************** diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/GeneralProduct.h b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/GeneralProduct.h index 1220073a8c1..b7ae44fda94 100644 --- a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/GeneralProduct.h +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/GeneralProduct.h @@ -243,17 +243,15 @@ struct gemv_static_vector_if { template struct gemv_static_vector_if { #if EIGEN_MAX_STATIC_ALIGN_BYTES != 0 - internal::plain_array - m_data; + internal::plain_array m_data; EIGEN_STRONG_INLINE Scalar* data() { return m_data.array; } #else // Some architectures cannot align on the stack, // => let's manually enforce alignment by allocating more data and return the address of the first aligned element. - internal::plain_array< - Scalar, internal::min_size_prefer_fixed(Size, MaxSize) + EIGEN_MAX_ALIGN_BYTES, 0> - m_data; + internal::plain_array m_data; EIGEN_STRONG_INLINE Scalar* data() { - return reinterpret_cast((std::uintptr_t(m_data.array) & ~(std::size_t(EIGEN_MAX_ALIGN_BYTES - 1))) + EIGEN_MAX_ALIGN_BYTES); + return reinterpret_cast((std::uintptr_t(m_data.array) & ~(std::size_t(EIGEN_MAX_ALIGN_BYTES - 1))) + + EIGEN_MAX_ALIGN_BYTES); } #endif }; diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/MathFunctions.h b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/MathFunctions.h index d42fc93cc96..feb9099b4cd 100644 --- a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/MathFunctions.h +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/MathFunctions.h @@ -1249,20 +1249,40 @@ EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double trunc(const double& x) { // T is assumed to be an integer type with a>=0, and b>0 template EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE EIGEN_CONSTEXPR T div_ceil(T a, T b) { + using UnsignedT = typename internal::make_unsigned::type; EIGEN_STATIC_ASSERT((NumTraits::IsInteger), THIS FUNCTION IS FOR INTEGER TYPES) eigen_assert(a >= 0); eigen_assert(b > 0); + // Note: explicitly declaring a and b as non-negative values allows the compiler to use better optimizations + const UnsignedT ua = UnsignedT(a); + const UnsignedT ub = UnsignedT(b); // Note: This form is used because it cannot overflow. - return a == 0 ? 0 : (a - 1) / b + 1; + return ua == 0 ? 0 : (ua - 1) / ub + 1; +} + +// Integer round down to nearest power of b +// T is assumed to be an integer type with a>=0, and b>0 +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE EIGEN_CONSTEXPR T round_down(T a, U b) { + using UnsignedT = typename internal::make_unsigned::type; + using UnsignedU = typename internal::make_unsigned::type; + EIGEN_STATIC_ASSERT((NumTraits::IsInteger), THIS FUNCTION IS FOR INTEGER TYPES) + EIGEN_STATIC_ASSERT((NumTraits::IsInteger), THIS FUNCTION IS FOR INTEGER TYPES) + eigen_assert(a >= 0); + eigen_assert(b > 0); + // Note: explicitly declaring a and b as non-negative values allows the compiler to use better optimizations + const UnsignedT ua = UnsignedT(a); + const UnsignedU ub = UnsignedU(b); + return ub * (ua / ub); } /** Log base 2 for 32 bits positive integers. * Conveniently returns 0 for x==0. */ -inline int log2(int x) { +EIGEN_CONSTEXPR inline int log2(int x) { eigen_assert(x >= 0); unsigned int v(x); - static const int table[32] = {0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, - 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31}; + constexpr int table[32] = {0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, + 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31}; v |= v >> 1; v |= v >> 2; v |= v >> 4; diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/Matrix.h b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/Matrix.h index af6afafc0ce..0d8691e7ac4 100644 --- a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/Matrix.h +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/Matrix.h @@ -125,7 +125,7 @@ struct traits> { * coefficients. * *
\anchor fixedsize Fixed-size versus dynamic-size:
- *
Fixed-size means that the numbers of rows and columns are known are compile-time. In this case, Eigen allocates + *
Fixed-size means that the numbers of rows and columns are known at compile-time. In this case, Eigen allocates * the array of coefficients as a fixed-size array, as a class member. This makes sense for very small matrices, * typically up to 4x4, sometimes up to 16x16. Larger matrices should be declared as dynamic-size even if one happens to * know their size at compile-time. @@ -139,7 +139,7 @@ struct traits> { *
\anchor maxrows MaxRows_ and MaxCols_:
*
In most cases, one just leaves these parameters to the default values. * These parameters mean the maximum size of rows and columns that the matrix may have. They are useful in cases - * when the exact numbers of rows and columns are not known are compile-time, but it is known at compile-time that they + * when the exact numbers of rows and columns are not known at compile-time, but it is known at compile-time that they * cannot exceed a certain value. This happens when taking dynamic-size blocks inside fixed-size matrices: in this case * MaxRows_ and MaxCols_ are the dimensions of the original matrix, while Rows_ and Cols_ are Dynamic.
* diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/Replicate.h b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/Replicate.h index c01c62737e9..11d7ad19e98 100644 --- a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/Replicate.h +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/Replicate.h @@ -80,15 +80,12 @@ class Replicate : public internal::dense_xpr_base EIGEN_DEVICE_FUNC inline Replicate(const OriginalMatrixType& matrix, Index rowFactor, Index colFactor) - : m_matrix(matrix), - m_rowFactor(rowFactor), - m_colFactor(colFactor){ - EIGEN_STATIC_ASSERT((internal::is_same, OriginalMatrixType>::value), - THE_MATRIX_OR_EXPRESSION_THAT_YOU_PASSED_DOES_NOT_HAVE_THE_EXPECTED_TYPE)} - - EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index rows() const { - return m_matrix.rows() * m_rowFactor.value(); + : m_matrix(matrix), m_rowFactor(rowFactor), m_colFactor(colFactor) { + EIGEN_STATIC_ASSERT((internal::is_same, OriginalMatrixType>::value), + THE_MATRIX_OR_EXPRESSION_THAT_YOU_PASSED_DOES_NOT_HAVE_THE_EXPECTED_TYPE) } + + EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index rows() const { return m_matrix.rows() * m_rowFactor.value(); } EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index cols() const { return m_matrix.cols() * m_colFactor.value(); } EIGEN_DEVICE_FUNC const MatrixTypeNested_& nestedExpression() const { return m_matrix; } diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/products/TriangularSolverMatrix.h b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/products/TriangularSolverMatrix.h index 2122af956d2..8244758bd30 100644 --- a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/products/TriangularSolverMatrix.h +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/products/TriangularSolverMatrix.h @@ -57,7 +57,7 @@ EIGEN_STRONG_INLINE void trsmKernelL=8 -#pragma GCC diagnostic ignored "-Wclass-memaccess" -#endif -#if __GNUC__>=11 +#if __GNUC__>=11 && __GNUC__<=13 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #endif #if __GNUC__>=12 diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/util/ForwardDeclarations.h b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/util/ForwardDeclarations.h index 2f2ba9b2028..cf25359287d 100644 --- a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/util/ForwardDeclarations.h +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/util/ForwardDeclarations.h @@ -502,6 +502,9 @@ struct stem_function { }; } // namespace internal +template +struct DeviceWrapper; + } // end namespace Eigen #endif // EIGEN_FORWARDDECLARATIONS_H diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/util/Memory.h b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/util/Memory.h index 62534540c9a..7edd0a190ae 100644 --- a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/util/Memory.h +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/util/Memory.h @@ -762,12 +762,22 @@ void swap(scoped_array& a, scoped_array& b) { #ifdef EIGEN_ALLOCA #if EIGEN_DEFAULT_ALIGN_BYTES > 0 - // We always manually re-align the result of EIGEN_ALLOCA. +// We always manually re-align the result of EIGEN_ALLOCA. // If alloca is already aligned, the compiler should be smart enough to optimize away the re-alignment. -#define EIGEN_ALIGNED_ALLOCA(SIZE) \ - reinterpret_cast( \ - (std::uintptr_t(EIGEN_ALLOCA(SIZE + EIGEN_DEFAULT_ALIGN_BYTES - 1)) + EIGEN_DEFAULT_ALIGN_BYTES - 1) & \ - ~(std::size_t(EIGEN_DEFAULT_ALIGN_BYTES - 1))) + +#if (EIGEN_COMP_GNUC || EIGEN_COMP_CLANG) +#define EIGEN_ALIGNED_ALLOCA(SIZE) __builtin_alloca_with_align(SIZE, CHAR_BIT* EIGEN_DEFAULT_ALIGN_BYTES) +#else +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void* eigen_aligned_alloca_helper(void* ptr) { + constexpr std::uintptr_t mask = EIGEN_DEFAULT_ALIGN_BYTES - 1; + std::uintptr_t ptr_int = std::uintptr_t(ptr); + std::uintptr_t aligned_ptr_int = (ptr_int + mask) & ~mask; + std::uintptr_t offset = aligned_ptr_int - ptr_int; + return static_cast(static_cast(ptr) + offset); +} +#define EIGEN_ALIGNED_ALLOCA(SIZE) eigen_aligned_alloca_helper(EIGEN_ALLOCA(SIZE + EIGEN_DEFAULT_ALIGN_BYTES - 1)) +#endif + #else #define EIGEN_ALIGNED_ALLOCA(SIZE) EIGEN_ALLOCA(SIZE) #endif diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/util/SymbolicIndex.h b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/util/SymbolicIndex.h index 9668f1e94ee..dc204af4ba2 100644 --- a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/util/SymbolicIndex.h +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/util/SymbolicIndex.h @@ -96,17 +96,17 @@ class BaseExpr { return AddExpr>(derived(), -a); } constexpr ProductExpr> operator*(Index a) const { - return ProductExpr >(derived(), a); + return ProductExpr>(derived(), a); } constexpr QuotientExpr> operator/(Index a) const { - return QuotientExpr >(derived(), a); + return QuotientExpr>(derived(), a); } friend constexpr AddExpr> operator+(Index a, const BaseExpr& b) { - return AddExpr >(b.derived(), a); + return AddExpr>(b.derived(), a); } friend constexpr AddExpr, ValueExpr<>> operator-(Index a, const BaseExpr& b) { - return AddExpr, ValueExpr<> >(-b.derived(), a); + return AddExpr, ValueExpr<>>(-b.derived(), a); } friend constexpr ProductExpr, Derived> operator*(Index a, const BaseExpr& b) { return ProductExpr, Derived>(a, b.derived()); @@ -117,41 +117,41 @@ class BaseExpr { template constexpr AddExpr>> operator+(internal::FixedInt) const { - return AddExpr > >(derived(), ValueExpr >()); + return AddExpr>>(derived(), ValueExpr>()); } template constexpr AddExpr>> operator-(internal::FixedInt) const { - return AddExpr > >(derived(), ValueExpr >()); + return AddExpr>>(derived(), ValueExpr>()); } template constexpr ProductExpr>> operator*(internal::FixedInt) const { - return ProductExpr > >(derived(), ValueExpr >()); + return ProductExpr>>(derived(), ValueExpr>()); } template constexpr QuotientExpr>> operator/(internal::FixedInt) const { - return QuotientExpr > >(derived(), ValueExpr >()); + return QuotientExpr>>(derived(), ValueExpr>()); } template friend constexpr AddExpr>> operator+(internal::FixedInt, const BaseExpr& b) { - return AddExpr > >(b.derived(), ValueExpr >()); + return AddExpr>>(b.derived(), ValueExpr>()); } template friend constexpr AddExpr, ValueExpr>> operator-(internal::FixedInt, const BaseExpr& b) { - return AddExpr, ValueExpr > >(-b.derived(), - ValueExpr >()); + return AddExpr, ValueExpr>>(-b.derived(), + ValueExpr>()); } template friend constexpr ProductExpr>, Derived> operator*(internal::FixedInt, const BaseExpr& b) { - return ProductExpr >, Derived>(ValueExpr >(), b.derived()); + return ProductExpr>, Derived>(ValueExpr>(), b.derived()); } template friend constexpr QuotientExpr>, Derived> operator/(internal::FixedInt, const BaseExpr& b) { - return QuotientExpr >, Derived>(ValueExpr >(), b.derived()); + return QuotientExpr>, Derived>(ValueExpr>(), b.derived()); } template @@ -161,7 +161,7 @@ class BaseExpr { template constexpr AddExpr> operator-(const BaseExpr& b) const { - return AddExpr >(derived(), -b.derived()); + return AddExpr>(derived(), -b.derived()); } template @@ -179,7 +179,7 @@ template struct is_symbolic { // BaseExpr has no conversion ctor, so we only have to check whether T can be statically cast to its base class // BaseExpr. - enum { value = internal::is_convertible >::value }; + enum { value = internal::is_convertible>::value }; }; // A simple wrapper around an integral value to provide the eval method. @@ -317,7 +317,7 @@ struct EvalSymbolValueHelper { /** Expression of a symbol uniquely identified by the template parameter type \c tag */ template -class SymbolExpr : public BaseExpr > { +class SymbolExpr : public BaseExpr> { public: /** Alias to the template parameter \c tag */ typedef tag Tag; @@ -349,7 +349,7 @@ class SymbolExpr : public BaseExpr > { }; template -class NegateExpr : public BaseExpr > { +class NegateExpr : public BaseExpr> { public: constexpr NegateExpr() = default; constexpr NegateExpr(const Arg0& arg0) : m_arg0(arg0) {} @@ -370,7 +370,7 @@ class NegateExpr : public BaseExpr > { }; template -class AddExpr : public BaseExpr > { +class AddExpr : public BaseExpr> { public: constexpr AddExpr() = default; constexpr AddExpr(const Arg0& arg0, const Arg1& arg1) : m_arg0(arg0), m_arg1(arg1) {} @@ -393,7 +393,7 @@ class AddExpr : public BaseExpr > { }; template -class ProductExpr : public BaseExpr > { +class ProductExpr : public BaseExpr> { public: constexpr ProductExpr() = default; constexpr ProductExpr(const Arg0& arg0, const Arg1& arg1) : m_arg0(arg0), m_arg1(arg1) {} @@ -416,7 +416,7 @@ class ProductExpr : public BaseExpr > { }; template -class QuotientExpr : public BaseExpr > { +class QuotientExpr : public BaseExpr> { public: constexpr QuotientExpr() = default; constexpr QuotientExpr(const Arg0& arg0, const Arg1& arg1) : m_arg0(arg0), m_arg1(arg1) {} diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/util/XprHelper.h b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/util/XprHelper.h index a6a7d3fbb3e..cecbee86520 100644 --- a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/util/XprHelper.h +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/util/XprHelper.h @@ -206,6 +206,64 @@ struct functor_traits { enum { Cost = 10, PacketAccess = false, IsRepeatable = false }; }; +// estimates the cost of lazily evaluating a generic functor by unwinding the expression +template +struct nested_functor_cost { + static constexpr Index Cost = static_cast(functor_traits::Cost); +}; + +template +struct nested_functor_cost> { + static constexpr Index Cost = 1; +}; + +template +struct nested_functor_cost> { + static constexpr Index Cost = 1; +}; + +// TODO: assign a cost to the stride type? +template +struct nested_functor_cost> : nested_functor_cost {}; + +template +struct nested_functor_cost> { + using XprCleaned = remove_all_t; + using FuncCleaned = remove_all_t; + static constexpr Index Cost = nested_functor_cost::Cost + nested_functor_cost::Cost; +}; + +template +struct nested_functor_cost> { + using XprCleaned = remove_all_t; + using FuncCleaned = remove_all_t; + static constexpr Index Cost = nested_functor_cost::Cost + nested_functor_cost::Cost; +}; + +template +struct nested_functor_cost> { + using LhsXprCleaned = remove_all_t; + using RhsXprCleaned = remove_all_t; + using FuncCleaned = remove_all_t; + static constexpr Index Cost = nested_functor_cost::Cost + nested_functor_cost::Cost + + nested_functor_cost::Cost; +}; + +template +struct nested_functor_cost> { + using LhsXprCleaned = remove_all_t; + using MidXprCleaned = remove_all_t; + using RhsXprCleaned = remove_all_t; + using FuncCleaned = remove_all_t; + static constexpr Index Cost = nested_functor_cost::Cost + nested_functor_cost::Cost + + nested_functor_cost::Cost + nested_functor_cost::Cost; +}; + +template +struct functor_cost { + static constexpr Index Cost = plain_enum_max(nested_functor_cost::Cost, 1); +}; + template struct packet_traits; diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/SVD/BDCSVD.h b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/SVD/BDCSVD.h index f80ddc0e25b..52f3564c088 100644 --- a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/SVD/BDCSVD.h +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/SVD/BDCSVD.h @@ -1233,7 +1233,7 @@ void BDCSVD::deflation44(Index firstColu, Index firstColm, using std::conj; using std::pow; using std::sqrt; - + RealScalar s = m_computed(firstColm + i, firstColm); RealScalar c = m_computed(firstColm + j, firstColm); RealScalar r = numext::hypot(c, s); @@ -1424,8 +1424,7 @@ void BDCSVD::deflation(Index firstCol, Index lastCol, Index if ((diag(i) - diag(i - 1)) < epsilon_strict) { #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE std::cout << "deflation 4.4 with i = " << i << " because " << diag(i) << " - " << diag(i - 1) - << " == " << (diag(i) - diag(i - 1)) << " < " - << epsilon_strict << "\n"; + << " == " << (diag(i) - diag(i - 1)) << " < " << epsilon_strict << "\n"; #endif eigen_internal_assert(abs(diag(i) - diag(i - 1)) < epsilon_coarse && " diagonal entries are not properly sorted"); diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/SparseCore/SparseDenseProduct.h b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/SparseCore/SparseDenseProduct.h index db708103754..17ce596a5af 100644 --- a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/SparseCore/SparseDenseProduct.h +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/SparseCore/SparseDenseProduct.h @@ -45,7 +45,6 @@ struct sparse_time_dense_product_impl= 0 && j < m_outerSize && "invalid outer index"); + eigen_assert(i >= 0 && i < m_innerSize && "invalid inner index"); Index start = m_outerIndex[j]; Index end = isCompressed() ? m_outerIndex[j + 1] : start + m_innerNonZeros[j]; Index dst = start == end ? end : m_data.searchLowerIndex(start, end, i); diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/ThreadPool/CoreThreadPoolDevice.h b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/ThreadPool/CoreThreadPoolDevice.h new file mode 100644 index 00000000000..5611a22bdc9 --- /dev/null +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/ThreadPool/CoreThreadPoolDevice.h @@ -0,0 +1,327 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2023 Charlie Schlosser +// +// 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_CORE_THREAD_POOL_DEVICE_H +#define EIGEN_CORE_THREAD_POOL_DEVICE_H + +namespace Eigen { + +// CoreThreadPoolDevice provides an easy-to-understand Device for parallelizing Eigen Core expressions with +// Threadpool. Expressions are recursively split evenly until the evaluation cost is less than the threshold for +// delegating the task to a thread. + +// a +// / \ +// / \ +// / \ +// / \ +// / \ +// / \ +// / \ +// a e +// / \ / \ +// / \ / \ +// / \ / \ +// a c e g +// / \ / \ / \ / \ +// / \ / \ / \ / \ +// a b c d e f g h + +// Each task descends the binary tree to the left, delegates the right task to a new thread, and continues to the +// left. This ensures that work is evenly distributed to the thread pool as quickly as possible and minimizes the number +// of tasks created during the evaluation. Consider an expression that is divided into 8 chunks. The +// primary task 'a' creates tasks 'e' 'c' and 'b', and executes its portion of the expression at the bottom of the +// tree. Likewise, task 'e' creates tasks 'g' and 'f', and executes its portion of the expression. + +struct CoreThreadPoolDevice { + using Task = std::function; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoreThreadPoolDevice(ThreadPool& pool, float threadCostThreshold = 3e-5f) + : m_pool(pool) { + eigen_assert(threadCostThreshold >= 0.0f && "threadCostThreshold must be non-negative"); + m_costFactor = threadCostThreshold; + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE int calculateLevels(Index size, float cost) const { + eigen_assert(cost >= 0.0f && "cost must be non-negative"); + Index numOps = size / PacketSize; + int actualThreads = numOps < m_pool.NumThreads() ? static_cast(numOps) : m_pool.NumThreads(); + float totalCost = static_cast(numOps) * cost; + float idealThreads = totalCost * m_costFactor; + if (idealThreads < static_cast(actualThreads)) { + idealThreads = numext::maxi(idealThreads, 1.0f); + actualThreads = numext::mini(actualThreads, static_cast(idealThreads)); + } + int maxLevel = internal::log2_ceil(actualThreads); + return maxLevel; + } + +// MSVC does not like inlining parallelForImpl +#if EIGEN_COMP_MSVC && !EIGEN_COMP_CLANG +#define EIGEN_PARALLEL_FOR_INLINE +#else +#define EIGEN_PARALLEL_FOR_INLINE EIGEN_STRONG_INLINE +#endif + + template + EIGEN_DEVICE_FUNC EIGEN_PARALLEL_FOR_INLINE void parallelForImpl(Index begin, Index end, UnaryFunctor& f, + Barrier& barrier, int level) { + while (level > 0) { + level--; + Index size = end - begin; + eigen_assert(size % PacketSize == 0 && "this function assumes size is a multiple of PacketSize"); + Index mid = begin + numext::round_down(size >> 1, PacketSize); + Task right = [=, this, &f, &barrier]() { + parallelForImpl(mid, end, f, barrier, level); + }; + m_pool.Schedule(std::move(right)); + end = mid; + } + for (Index i = begin; i < end; i += PacketSize) f(i); + barrier.Notify(); + } + + template + EIGEN_DEVICE_FUNC EIGEN_PARALLEL_FOR_INLINE void parallelForImpl(Index outerBegin, Index outerEnd, Index innerBegin, + Index innerEnd, BinaryFunctor& f, Barrier& barrier, + int level) { + while (level > 0) { + level--; + Index outerSize = outerEnd - outerBegin; + if (outerSize > 1) { + Index outerMid = outerBegin + (outerSize >> 1); + Task right = [=, this, &f, &barrier]() { + parallelForImpl(outerMid, outerEnd, innerBegin, innerEnd, f, barrier, level); + }; + m_pool.Schedule(std::move(right)); + outerEnd = outerMid; + } else { + Index innerSize = innerEnd - innerBegin; + eigen_assert(innerSize % PacketSize == 0 && "this function assumes innerSize is a multiple of PacketSize"); + Index innerMid = innerBegin + numext::round_down(innerSize >> 1, PacketSize); + Task right = [=, this, &f, &barrier]() { + parallelForImpl(outerBegin, outerEnd, innerMid, innerEnd, f, barrier, level); + }; + m_pool.Schedule(std::move(right)); + innerEnd = innerMid; + } + } + for (Index outer = outerBegin; outer < outerEnd; outer++) + for (Index inner = innerBegin; inner < innerEnd; inner += PacketSize) f(outer, inner); + barrier.Notify(); + } + +#undef EIGEN_PARALLEL_FOR_INLINE + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void parallelFor(Index begin, Index end, UnaryFunctor& f, float cost) { + Index size = end - begin; + int maxLevel = calculateLevels(size, cost); + Barrier barrier(1 << maxLevel); + parallelForImpl(begin, end, f, barrier, maxLevel); + barrier.Wait(); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void parallelFor(Index outerBegin, Index outerEnd, Index innerBegin, + Index innerEnd, BinaryFunctor& f, float cost) { + Index outerSize = outerEnd - outerBegin; + Index innerSize = innerEnd - innerBegin; + Index size = outerSize * innerSize; + int maxLevel = calculateLevels(size, cost); + Barrier barrier(1 << maxLevel); + parallelForImpl(outerBegin, outerEnd, innerBegin, innerEnd, f, barrier, maxLevel); + barrier.Wait(); + } + + ThreadPool& m_pool; + // costFactor is the cost of delegating a task to a thread + // the inverse is used to avoid a floating point division + float m_costFactor; +}; + +// specialization of coefficient-wise assignment loops for CoreThreadPoolDevice + +namespace internal { + +template +struct cost_helper { + using SrcEvaluatorType = typename Kernel::SrcEvaluatorType; + using DstEvaluatorType = typename Kernel::DstEvaluatorType; + using SrcXprType = typename SrcEvaluatorType::XprType; + using DstXprType = typename DstEvaluatorType::XprType; + static constexpr Index Cost = functor_cost::Cost + functor_cost::Cost; +}; + +template +struct dense_assignment_loop_with_device { + static constexpr Index XprEvaluationCost = cost_helper::Cost; + struct AssignmentFunctor : public Kernel { + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE AssignmentFunctor(Kernel& kernel) : Kernel(kernel) {} + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void operator()(Index outer, Index inner) { + this->assignCoeffByOuterInner(outer, inner); + } + }; + + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Kernel& kernel, CoreThreadPoolDevice& device) { + const Index innerSize = kernel.innerSize(); + const Index outerSize = kernel.outerSize(); + constexpr float cost = static_cast(XprEvaluationCost); + AssignmentFunctor functor(kernel); + device.template parallelFor(0, outerSize, 0, innerSize, functor, cost); + } +}; + +template +struct dense_assignment_loop_with_device { + using DstXprType = typename Kernel::DstEvaluatorType::XprType; + static constexpr Index XprEvaluationCost = cost_helper::Cost, InnerSize = DstXprType::InnerSizeAtCompileTime; + struct AssignmentFunctor : public Kernel { + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE AssignmentFunctor(Kernel& kernel) : Kernel(kernel) {} + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void operator()(Index outer) { + copy_using_evaluator_DefaultTraversal_InnerUnrolling::run(*this, outer); + } + }; + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Kernel& kernel, CoreThreadPoolDevice& device) { + const Index outerSize = kernel.outerSize(); + AssignmentFunctor functor(kernel); + constexpr float cost = static_cast(XprEvaluationCost) * static_cast(InnerSize); + device.template parallelFor(0, outerSize, functor, cost); + } +}; + +template +struct dense_assignment_loop_with_device { + using PacketType = typename Kernel::PacketType; + static constexpr Index XprEvaluationCost = cost_helper::Cost, PacketSize = unpacket_traits::size, + SrcAlignment = Kernel::AssignmentTraits::SrcAlignment, + DstAlignment = Kernel::AssignmentTraits::DstAlignment; + struct AssignmentFunctor : public Kernel { + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE AssignmentFunctor(Kernel& kernel) : Kernel(kernel) {} + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void operator()(Index outer, Index inner) { + this->template assignPacketByOuterInner(outer, inner); + } + }; + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Kernel& kernel, CoreThreadPoolDevice& device) { + const Index innerSize = kernel.innerSize(); + const Index outerSize = kernel.outerSize(); + const float cost = static_cast(XprEvaluationCost) * static_cast(innerSize); + AssignmentFunctor functor(kernel); + device.template parallelFor(0, outerSize, 0, innerSize, functor, cost); + } +}; + +template +struct dense_assignment_loop_with_device { + using PacketType = typename Kernel::PacketType; + using DstXprType = typename Kernel::DstEvaluatorType::XprType; + static constexpr Index XprEvaluationCost = cost_helper::Cost, PacketSize = unpacket_traits::size, + SrcAlignment = Kernel::AssignmentTraits::SrcAlignment, + DstAlignment = Kernel::AssignmentTraits::DstAlignment, + InnerSize = DstXprType::InnerSizeAtCompileTime; + struct AssignmentFunctor : public Kernel { + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE AssignmentFunctor(Kernel& kernel) : Kernel(kernel) {} + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void operator()(Index outer) { + copy_using_evaluator_innervec_InnerUnrolling::run(*this, outer); + } + }; + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Kernel& kernel, CoreThreadPoolDevice& device) { + const Index outerSize = kernel.outerSize(); + constexpr float cost = static_cast(XprEvaluationCost) * static_cast(InnerSize); + AssignmentFunctor functor(kernel); + device.template parallelFor(0, outerSize, functor, cost); + } +}; + +template +struct dense_assignment_loop_with_device { + using Scalar = typename Kernel::Scalar; + using PacketType = typename Kernel::PacketType; + static constexpr Index XprEvaluationCost = cost_helper::Cost, PacketSize = unpacket_traits::size; + struct PacketAssignmentFunctor : public Kernel { + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketAssignmentFunctor(Kernel& kernel) : Kernel(kernel) {} + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void operator()(Index outer, Index inner) { + this->template assignPacketByOuterInner(outer, inner); + } + }; + struct ScalarAssignmentFunctor : public Kernel { + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ScalarAssignmentFunctor(Kernel& kernel) : Kernel(kernel) {} + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void operator()(Index outer) { + const Index innerSize = this->innerSize(); + const Index packetAccessSize = numext::round_down(innerSize, PacketSize); + for (Index inner = packetAccessSize; inner < innerSize; inner++) this->assignCoeffByOuterInner(outer, inner); + } + }; + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Kernel& kernel, CoreThreadPoolDevice& device) { + const Index outerSize = kernel.outerSize(); + const Index innerSize = kernel.innerSize(); + const Index packetAccessSize = numext::round_down(innerSize, PacketSize); + constexpr float packetCost = static_cast(XprEvaluationCost); + const float scalarCost = static_cast(XprEvaluationCost) * static_cast(innerSize - packetAccessSize); + PacketAssignmentFunctor packetFunctor(kernel); + ScalarAssignmentFunctor scalarFunctor(kernel); + device.template parallelFor(0, outerSize, 0, packetAccessSize, packetFunctor, + packetCost); + device.template parallelFor(0, outerSize, scalarFunctor, scalarCost); + }; +}; + +template +struct dense_assignment_loop_with_device { + static constexpr Index XprEvaluationCost = cost_helper::Cost; + struct AssignmentFunctor : public Kernel { + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE AssignmentFunctor(Kernel& kernel) : Kernel(kernel) {} + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void operator()(Index index) { this->assignCoeff(index); } + }; + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Kernel& kernel, CoreThreadPoolDevice& device) { + const Index size = kernel.size(); + constexpr float cost = static_cast(XprEvaluationCost); + AssignmentFunctor functor(kernel); + device.template parallelFor(0, size, functor, cost); + } +}; + +template +struct dense_assignment_loop_with_device { + using Scalar = typename Kernel::Scalar; + using PacketType = typename Kernel::PacketType; + static constexpr Index XprEvaluationCost = cost_helper::Cost, + RequestedAlignment = Kernel::AssignmentTraits::LinearRequiredAlignment, + PacketSize = unpacket_traits::size, + DstIsAligned = Kernel::AssignmentTraits::DstAlignment >= RequestedAlignment, + DstAlignment = packet_traits::AlignedOnScalar ? RequestedAlignment + : Kernel::AssignmentTraits::DstAlignment, + SrcAlignment = Kernel::AssignmentTraits::JointAlignment; + struct AssignmentFunctor : public Kernel { + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE AssignmentFunctor(Kernel& kernel) : Kernel(kernel) {} + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void operator()(Index index) { + this->template assignPacket(index); + } + }; + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Kernel& kernel, CoreThreadPoolDevice& device) { + const Index size = kernel.size(); + const Index alignedStart = + DstIsAligned ? 0 : internal::first_aligned(kernel.dstDataPtr(), size); + const Index alignedEnd = alignedStart + numext::round_down(size - alignedStart, PacketSize); + + unaligned_dense_assignment_loop::run(kernel, 0, alignedStart); + + constexpr float cost = static_cast(XprEvaluationCost); + AssignmentFunctor functor(kernel); + device.template parallelFor(alignedStart, alignedEnd, functor, cost); + + unaligned_dense_assignment_loop<>::run(kernel, alignedEnd, size); + } +}; + +} // namespace internal + +} // namespace Eigen + +#endif // EIGEN_CORE_THREAD_POOL_DEVICE_H