From ee3d55e8488449f7b89e28182df0acdf37f94e17 Mon Sep 17 00:00:00 2001 From: Tyler Veness Date: Fri, 19 Sep 2025 16:52:48 -0700 Subject: [PATCH] [upstream_utils] Upgrade Eigen to latest (#8228) --- upstream_utils/eigen.py | 8 +- .../eigen_patches/0002-Intellisense-fix.patch | 2 +- .../thirdparty/eigen/include/Eigen/Core | 21 +- .../include/Eigen/src/Core/CoreEvaluators.h | 50 +- .../eigen/include/Eigen/src/Core/DenseBase.h | 12 + .../include/Eigen/src/Core/DenseCoeffsBase.h | 8 +- .../eigen/include/Eigen/src/Core/Fill.h | 3 +- .../eigen/include/Eigen/src/Core/FindCoeff.h | 464 ++++++++++++++++++ .../Eigen/src/Core/GenericPacketMath.h | 132 +++-- .../include/Eigen/src/Core/IndexedView.h | 6 + .../include/Eigen/src/Core/MathFunctions.h | 82 +++- .../Eigen/src/Core/MathFunctionsImpl.h | 48 +- .../eigen/include/Eigen/src/Core/NumTraits.h | 18 +- .../Eigen/src/Core/PermutationMatrix.h | 18 +- .../Eigen/src/Core/ProductEvaluators.h | 4 +- .../eigen/include/Eigen/src/Core/RandomImpl.h | 7 + .../eigen/include/Eigen/src/Core/RealView.h | 250 ++++++++++ .../eigen/include/Eigen/src/Core/Select.h | 92 +--- .../Eigen/src/Core/SelfCwiseBinaryOp.h | 26 +- .../include/Eigen/src/Core/VectorwiseOp.h | 52 +- .../eigen/include/Eigen/src/Core/Visitor.h | 261 ---------- .../Eigen/src/Core/arch/AVX/PacketMath.h | 210 ++------ .../Eigen/src/Core/arch/AVX/Reductions.h | 353 +++++++++++++ .../Eigen/src/Core/arch/Default/BFloat16.h | 6 + .../arch/Default/GenericPacketMathFunctions.h | 61 +-- .../Eigen/src/Core/arch/Default/Half.h | 66 ++- .../Eigen/src/Core/arch/NEON/Complex.h | 46 +- .../Eigen/src/Core/arch/NEON/PacketMath.h | 406 ++++++--------- .../Eigen/src/Core/arch/SSE/PacketMath.h | 234 +-------- .../Eigen/src/Core/arch/SSE/Reductions.h | 324 ++++++++++++ .../Eigen/src/Core/functors/BinaryFunctors.h | 6 +- .../Core/products/SelfadjointMatrixVector.h | 5 + .../src/Core/util/ConfigureVectorization.h | 2 +- .../Eigen/src/Core/util/ForwardDeclarations.h | 4 +- .../include/Eigen/src/Core/util/Macros.h | 21 +- .../include/Eigen/src/Core/util/Memory.h | 42 +- .../include/Eigen/src/Geometry/Quaternion.h | 75 +++ .../src/SparseCholesky/SimplicialCholesky.h | 20 +- .../SparseCholesky/SimplicialCholesky_impl.h | 4 + .../include/Eigen/src/SparseCore/SparseDot.h | 6 +- .../Eigen/src/SparseCore/SparseMatrix.h | 6 +- .../Eigen/src/SparseCore/SparseMatrixBase.h | 66 ++- .../Eigen/src/SparseCore/TriangularSolver.h | 20 +- 43 files changed, 2250 insertions(+), 1297 deletions(-) create mode 100644 wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/FindCoeff.h create mode 100644 wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/RealView.h create mode 100644 wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/arch/AVX/Reductions.h create mode 100644 wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/arch/SSE/Reductions.h diff --git a/upstream_utils/eigen.py b/upstream_utils/eigen.py index fdd9f580f9..6cb3facfa9 100755 --- a/upstream_utils/eigen.py +++ b/upstream_utils/eigen.py @@ -38,6 +38,10 @@ def eigen_inclusions(dp: Path, f: str): if "MKL" in f: return False + # Exclude HIP CUDA support + if "GpuHip" in f: + return False + # Include architectures we care about by filtering for Core/arch if "Core" in dp.parts and "arch" in dp.parts: return ( @@ -140,8 +144,8 @@ def copy_upstream_src(wpilib_root: Path): def main(): name = "eigen" url = "https://gitlab.com/libeigen/eigen.git" - # master on 2025-05-18 - tag = "d81aa18f4dc56264b2cd7e2f230807d776a2d385" + # master on 2025-09-08 + tag = "e0a59e5a66e6d16fa93ab4f5e48bf539205e837f" eigen = Lib(name, url, tag, copy_upstream_src) eigen.main() diff --git a/upstream_utils/eigen_patches/0002-Intellisense-fix.patch b/upstream_utils/eigen_patches/0002-Intellisense-fix.patch index 5522d69109..7f2aaeea10 100644 --- a/upstream_utils/eigen_patches/0002-Intellisense-fix.patch +++ b/upstream_utils/eigen_patches/0002-Intellisense-fix.patch @@ -8,7 +8,7 @@ Subject: [PATCH 2/2] Intellisense fix 1 file changed, 7 insertions(+) diff --git a/Eigen/src/Core/util/ConfigureVectorization.h b/Eigen/src/Core/util/ConfigureVectorization.h -index 49f307c734e937f013e659e931286a17ef6756f9..a9430716a320327aed81ea0cdffabc051aeb0ce2 100644 +index c2546a083898154a1d4bd741722a5544cbdb1d92..8b5cc16b2092a73804af87ed7f59722ae3fdab0c 100644 --- a/Eigen/src/Core/util/ConfigureVectorization.h +++ b/Eigen/src/Core/util/ConfigureVectorization.h @@ -178,6 +178,13 @@ diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/Core b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/Core index 69aa1f8e5c..2fedfd3b80 100644 --- a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/Core +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/Core @@ -92,6 +92,7 @@ #include #include +#include #include // for std::is_nothrow_move_assignable @@ -102,6 +103,11 @@ #include #endif +// for std::bit_cast() +#if defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L +#include +#endif + // for outputting debug info #ifdef EIGEN_DEBUG_ASSIGN #include @@ -121,7 +127,6 @@ #undef isfinite #include #include -#include #include #include #ifndef EIGEN_SYCL_LOCAL_THREAD_DIM0 @@ -194,8 +199,11 @@ using std::ptrdiff_t; #if defined EIGEN_VECTORIZE_AVX512 #include "src/Core/arch/SSE/PacketMath.h" +#include "src/Core/arch/SSE/Reductions.h" #include "src/Core/arch/AVX/PacketMath.h" +#include "src/Core/arch/AVX/Reductions.h" // #include "src/Core/arch/AVX512/PacketMath.h" +// #include "src/Core/arch/AVX512/Reductions.h" #if defined EIGEN_VECTORIZE_AVX512FP16 // #include "src/Core/arch/AVX512/PacketMathFP16.h" #endif @@ -216,21 +224,26 @@ using std::ptrdiff_t; #endif // #include "src/Core/arch/AVX512/TrsmKernel.h" #elif defined EIGEN_VECTORIZE_AVX - // Use AVX for floats and doubles, SSE for integers +// Use AVX for floats and doubles, SSE for integers #include "src/Core/arch/SSE/PacketMath.h" +#include "src/Core/arch/SSE/Reductions.h" #include "src/Core/arch/SSE/TypeCasting.h" #include "src/Core/arch/SSE/Complex.h" #include "src/Core/arch/AVX/PacketMath.h" +#include "src/Core/arch/AVX/Reductions.h" #include "src/Core/arch/AVX/TypeCasting.h" #include "src/Core/arch/AVX/Complex.h" #include "src/Core/arch/SSE/MathFunctions.h" #include "src/Core/arch/AVX/MathFunctions.h" #elif defined EIGEN_VECTORIZE_SSE #include "src/Core/arch/SSE/PacketMath.h" +#include "src/Core/arch/SSE/Reductions.h" #include "src/Core/arch/SSE/TypeCasting.h" #include "src/Core/arch/SSE/MathFunctions.h" #include "src/Core/arch/SSE/Complex.h" -#elif defined(EIGEN_VECTORIZE_ALTIVEC) || defined(EIGEN_VECTORIZE_VSX) +#endif + +#if defined(EIGEN_VECTORIZE_ALTIVEC) || defined(EIGEN_VECTORIZE_VSX) // #include "src/Core/arch/AltiVec/PacketMath.h" // #include "src/Core/arch/AltiVec/TypeCasting.h" // #include "src/Core/arch/AltiVec/MathFunctions.h" @@ -311,6 +324,7 @@ using std::ptrdiff_t; #include "src/Core/Product.h" #include "src/Core/CoreEvaluators.h" #include "src/Core/AssignEvaluator.h" +#include "src/Core/RealView.h" #include "src/Core/Assign.h" #include "src/Core/ArrayBase.h" @@ -350,6 +364,7 @@ using std::ptrdiff_t; #include "src/Core/SkewSymmetricMatrix3.h" #include "src/Core/Redux.h" #include "src/Core/Visitor.h" +#include "src/Core/FindCoeff.h" #include "src/Core/Fuzzy.h" #include "src/Core/Swap.h" #include "src/Core/CommaInitializer.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 63f1895d2a..c9b2d2d282 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 @@ -707,7 +707,7 @@ struct unary_evaluator, ArgType>, In Index packetOffset = offset * PacketSize; Index actualRow = IsRowMajor ? row : row + packetOffset; Index actualCol = IsRowMajor ? col + packetOffset : col; - eigen_assert(check_array_bounds(actualRow, actualCol, 0, count) && "Array index out of bounds"); + eigen_assert(check_array_bounds(actualRow, actualCol, begin, count) && "Array index out of bounds"); return m_argImpl.template packetSegment(actualRow, actualCol, begin, count); } template @@ -715,8 +715,8 @@ struct unary_evaluator, ArgType>, In Index offset) const { constexpr int PacketSize = unpacket_traits::size; Index packetOffset = offset * PacketSize; - Index actualIndex = index + packetOffset + begin; - eigen_assert(check_array_bounds(actualIndex, 0, count) && "Array index out of bounds"); + Index actualIndex = index + packetOffset; + eigen_assert(check_array_bounds(actualIndex, begin, count) && "Array index out of bounds"); return m_argImpl.template packetSegment(actualIndex, begin, count); } @@ -1565,50 +1565,6 @@ struct block_evaluator -struct evaluator> - : evaluator_base> { - typedef Select XprType; - enum { - CoeffReadCost = evaluator::CoeffReadCost + - plain_enum_max(evaluator::CoeffReadCost, evaluator::CoeffReadCost), - - Flags = (unsigned int)evaluator::Flags & evaluator::Flags & HereditaryBits, - - Alignment = plain_enum_min(evaluator::Alignment, evaluator::Alignment) - }; - - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit evaluator(const XprType& select) - : m_conditionImpl(select.conditionMatrix()), m_thenImpl(select.thenMatrix()), m_elseImpl(select.elseMatrix()) { - EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); - } - - typedef typename XprType::CoeffReturnType CoeffReturnType; - - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const { - if (m_conditionImpl.coeff(row, col)) - return m_thenImpl.coeff(row, col); - else - return m_elseImpl.coeff(row, col); - } - - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const { - if (m_conditionImpl.coeff(index)) - return m_thenImpl.coeff(index); - else - return m_elseImpl.coeff(index); - } - - protected: - evaluator m_conditionImpl; - evaluator m_thenImpl; - evaluator m_elseImpl; -}; - // -------------------- Replicate -------------------- template 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 4f6894280e..0333ad167a 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 @@ -367,7 +367,12 @@ class DenseBase EIGEN_DEVICE_FUNC inline bool allFinite() const; EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator*=(const Scalar& other); + template ::value, typename = std::enable_if_t> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator*=(const RealScalar& other); + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator/=(const Scalar& other); + template ::value, typename = std::enable_if_t> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator/=(const RealScalar& other); typedef internal::add_const_on_value_type_t::type> EvalReturnType; /** \returns the matrix or vector obtained by evaluating this expression. @@ -597,6 +602,13 @@ class DenseBase inline const_iterator end() const; inline const_iterator cend() const; + using RealViewReturnType = std::conditional_t::IsComplex, RealView, Derived&>; + using ConstRealViewReturnType = + std::conditional_t::IsComplex, RealView, const Derived&>; + + EIGEN_DEVICE_FUNC RealViewReturnType realView(); + EIGEN_DEVICE_FUNC ConstRealViewReturnType realView() const; + #define EIGEN_CURRENT_STORAGE_BASE_CLASS Eigen::DenseBase #define EIGEN_DOC_BLOCK_ADDONS_NOT_INNER_PANEL #define EIGEN_DOC_BLOCK_ADDONS_INNER_PANEL_IF(COND) diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/DenseCoeffsBase.h b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/DenseCoeffsBase.h index cff104c366..377df574ff 100644 --- a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/DenseCoeffsBase.h +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/DenseCoeffsBase.h @@ -45,10 +45,16 @@ class DenseCoeffsBase : public EigenBase { // - This is the return type of the coeff() method. // - The LvalueBit means exactly that we can offer a coeffRef() method, which means exactly that we can get references // to coeffs, which means exactly that we can have coeff() return a const reference (as opposed to returning a value). + // - The DirectAccessBit means exactly that the underlying data of coefficients can be directly accessed as a plain + // strided array, which means exactly that the underlying data of coefficients does exist in memory, which means + // exactly that the coefficients is const-referencable, which means exactly that we can have coeff() return a const + // reference. For example, Map have DirectAccessBit but not LvalueBit, so that Map.coeff() + // does points to a const Scalar& which exists in memory, while does not allow coeffRef() as it would not provide a + // lvalue. Notice that DirectAccessBit and LvalueBit are mutually orthogonal. // - The is_arithmetic check is required since "const int", "const double", etc. will cause warnings on some systems // while the declaration of "const T", where T is a non arithmetic type does not. Always returning "const Scalar&" is // not possible, since the underlying expressions might not offer a valid address the reference could be referring to. - typedef std::conditional_t::Flags& LvalueBit), const Scalar&, + typedef std::conditional_t::Flags&(LvalueBit | DirectAccessBit)), const Scalar&, std::conditional_t::value, Scalar, const Scalar>> CoeffReturnType; diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/Fill.h b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/Fill.h index 9d4ecd445a..f40d56db6b 100644 --- a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/Fill.h +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/Fill.h @@ -78,8 +78,9 @@ template struct eigen_fill_impl { using Scalar = typename Xpr::Scalar; static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Xpr& dst, const Scalar& val) { + const Scalar val_copy = val; using std::fill_n; - fill_n(dst.data(), dst.size(), val); + fill_n(dst.data(), dst.size(), val_copy); } template static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Xpr& dst, const SrcXpr& src) { diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/FindCoeff.h b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/FindCoeff.h new file mode 100644 index 0000000000..0102e8af3a --- /dev/null +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/FindCoeff.h @@ -0,0 +1,464 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2025 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_FIND_COEFF_H +#define EIGEN_FIND_COEFF_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +template ::IsInteger> +struct max_coeff_functor { + EIGEN_DEVICE_FUNC inline bool compareCoeff(const Scalar& incumbent, const Scalar& candidate) const { + return candidate > incumbent; + } + template + EIGEN_DEVICE_FUNC inline Packet comparePacket(const Packet& incumbent, const Packet& candidate) const { + return pcmp_lt(incumbent, candidate); + } + template + EIGEN_DEVICE_FUNC inline Scalar predux(const Packet& a) const { + return predux_max(a); + } +}; + +template +struct max_coeff_functor { + EIGEN_DEVICE_FUNC inline Scalar compareCoeff(const Scalar& incumbent, const Scalar& candidate) { + return (candidate > incumbent) || ((candidate != candidate) && (incumbent == incumbent)); + } + template + EIGEN_DEVICE_FUNC inline Packet comparePacket(const Packet& incumbent, const Packet& candidate) { + return pandnot(pcmp_lt_or_nan(incumbent, candidate), pisnan(incumbent)); + } + template + EIGEN_DEVICE_FUNC inline Scalar predux(const Packet& a) const { + return predux_max(a); + } +}; + +template +struct max_coeff_functor { + EIGEN_DEVICE_FUNC inline bool compareCoeff(const Scalar& incumbent, const Scalar& candidate) const { + return (candidate > incumbent) || ((candidate == candidate) && (incumbent != incumbent)); + } + template + EIGEN_DEVICE_FUNC inline Packet comparePacket(const Packet& incumbent, const Packet& candidate) const { + return pandnot(pcmp_lt_or_nan(incumbent, candidate), pisnan(candidate)); + } + template + EIGEN_DEVICE_FUNC inline Scalar predux(const Packet& a) const { + return predux_max(a); + } +}; + +template ::IsInteger> +struct min_coeff_functor { + EIGEN_DEVICE_FUNC inline bool compareCoeff(const Scalar& incumbent, const Scalar& candidate) const { + return candidate < incumbent; + } + template + EIGEN_DEVICE_FUNC inline Packet comparePacket(const Packet& incumbent, const Packet& candidate) const { + return pcmp_lt(candidate, incumbent); + } + template + EIGEN_DEVICE_FUNC inline Scalar predux(const Packet& a) const { + return predux_min(a); + } +}; + +template +struct min_coeff_functor { + EIGEN_DEVICE_FUNC inline Scalar compareCoeff(const Scalar& incumbent, const Scalar& candidate) { + return (candidate < incumbent) || ((candidate != candidate) && (incumbent == incumbent)); + } + template + EIGEN_DEVICE_FUNC inline Packet comparePacket(const Packet& incumbent, const Packet& candidate) { + return pandnot(pcmp_lt_or_nan(candidate, incumbent), pisnan(incumbent)); + } + template + EIGEN_DEVICE_FUNC inline Scalar predux(const Packet& a) const { + return predux_min(a); + } +}; + +template +struct min_coeff_functor { + EIGEN_DEVICE_FUNC inline bool compareCoeff(const Scalar& incumbent, const Scalar& candidate) const { + return (candidate < incumbent) || ((candidate == candidate) && (incumbent != incumbent)); + } + template + EIGEN_DEVICE_FUNC inline Packet comparePacket(const Packet& incumbent, const Packet& candidate) const { + return pandnot(pcmp_lt_or_nan(candidate, incumbent), pisnan(candidate)); + } + template + EIGEN_DEVICE_FUNC inline Scalar predux(const Packet& a) const { + return predux_min(a); + } +}; + +template +struct min_max_traits { + static constexpr bool PacketAccess = packet_traits::Vectorizable; +}; +template +struct functor_traits> : min_max_traits {}; +template +struct functor_traits> : min_max_traits {}; + +template +struct find_coeff_loop; +template +struct find_coeff_loop { + using Scalar = typename Evaluator::Scalar; + static EIGEN_DEVICE_FUNC inline void run(const Evaluator& eval, Func& func, Scalar& res, Index& outer, Index& inner) { + Index outerSize = eval.outerSize(); + Index innerSize = eval.innerSize(); + + /* initialization performed in calling function */ + /* result = eval.coeff(0, 0); */ + /* outer = 0; */ + /* inner = 0; */ + + for (Index j = 0; j < outerSize; j++) { + for (Index i = 0; i < innerSize; i++) { + Scalar xprCoeff = eval.coeffByOuterInner(j, i); + bool newRes = func.compareCoeff(res, xprCoeff); + if (newRes) { + outer = j; + inner = i; + res = xprCoeff; + } + } + } + } +}; +template +struct find_coeff_loop { + using Scalar = typename Evaluator::Scalar; + static EIGEN_DEVICE_FUNC inline void run(const Evaluator& eval, Func& func, Scalar& res, Index& index) { + Index size = eval.size(); + + /* initialization performed in calling function */ + /* result = eval.coeff(0); */ + /* index = 0; */ + + for (Index k = 0; k < size; k++) { + Scalar xprCoeff = eval.coeff(k); + bool newRes = func.compareCoeff(res, xprCoeff); + if (newRes) { + index = k; + res = xprCoeff; + } + } + } +}; +template +struct find_coeff_loop { + using ScalarImpl = find_coeff_loop; + using Scalar = typename Evaluator::Scalar; + using Packet = typename Evaluator::Packet; + static constexpr int PacketSize = unpacket_traits::size; + static EIGEN_DEVICE_FUNC inline void run(const Evaluator& eval, Func& func, Scalar& result, Index& outer, + Index& inner) { + Index outerSize = eval.outerSize(); + Index innerSize = eval.innerSize(); + Index packetEnd = numext::round_down(innerSize, PacketSize); + + /* initialization performed in calling function */ + /* result = eval.coeff(0, 0); */ + /* outer = 0; */ + /* inner = 0; */ + + bool checkPacket = false; + + for (Index j = 0; j < outerSize; j++) { + Packet resultPacket = pset1(result); + for (Index i = 0; i < packetEnd; i += PacketSize) { + Packet xprPacket = eval.template packetByOuterInner(j, i); + if (predux_any(func.comparePacket(resultPacket, xprPacket))) { + outer = j; + inner = i; + result = func.predux(xprPacket); + resultPacket = pset1(result); + checkPacket = true; + } + } + + for (Index i = packetEnd; i < innerSize; i++) { + Scalar xprCoeff = eval.coeffByOuterInner(j, i); + if (func.compareCoeff(result, xprCoeff)) { + outer = j; + inner = i; + result = xprCoeff; + checkPacket = false; + } + } + } + + if (checkPacket) { + result = eval.coeffByOuterInner(outer, inner); + Index i_end = inner + PacketSize; + for (Index i = inner; i < i_end; i++) { + Scalar xprCoeff = eval.coeffByOuterInner(outer, i); + if (func.compareCoeff(result, xprCoeff)) { + inner = i; + result = xprCoeff; + } + } + } + } +}; +template +struct find_coeff_loop { + using ScalarImpl = find_coeff_loop; + using Scalar = typename Evaluator::Scalar; + using Packet = typename Evaluator::Packet; + static constexpr int PacketSize = unpacket_traits::size; + static constexpr int Alignment = Evaluator::Alignment; + + static EIGEN_DEVICE_FUNC inline void run(const Evaluator& eval, Func& func, Scalar& result, Index& index) { + Index size = eval.size(); + Index packetEnd = numext::round_down(size, PacketSize); + + /* initialization performed in calling function */ + /* result = eval.coeff(0); */ + /* index = 0; */ + + Packet resultPacket = pset1(result); + bool checkPacket = false; + + for (Index k = 0; k < packetEnd; k += PacketSize) { + Packet xprPacket = eval.template packet(k); + if (predux_any(func.comparePacket(resultPacket, xprPacket))) { + index = k; + result = func.predux(xprPacket); + resultPacket = pset1(result); + checkPacket = true; + } + } + + for (Index k = packetEnd; k < size; k++) { + Scalar xprCoeff = eval.coeff(k); + if (func.compareCoeff(result, xprCoeff)) { + index = k; + result = xprCoeff; + checkPacket = false; + } + } + + if (checkPacket) { + result = eval.coeff(index); + Index k_end = index + PacketSize; + for (Index k = index; k < k_end; k++) { + Scalar xprCoeff = eval.coeff(k); + if (func.compareCoeff(result, xprCoeff)) { + index = k; + result = xprCoeff; + } + } + } + } +}; + +template +struct find_coeff_evaluator : public evaluator { + using Base = evaluator; + using Scalar = typename Derived::Scalar; + using Packet = typename packet_traits::type; + static constexpr int Flags = Base::Flags; + static constexpr bool IsRowMajor = bool(Flags & RowMajorBit); + EIGEN_DEVICE_FUNC inline find_coeff_evaluator(const Derived& xpr) : Base(xpr), m_xpr(xpr) {} + + EIGEN_DEVICE_FUNC inline Scalar coeffByOuterInner(Index outer, Index inner) const { + Index row = IsRowMajor ? outer : inner; + Index col = IsRowMajor ? inner : outer; + return Base::coeff(row, col); + } + template + EIGEN_DEVICE_FUNC inline PacketType packetByOuterInner(Index outer, Index inner) const { + Index row = IsRowMajor ? outer : inner; + Index col = IsRowMajor ? inner : outer; + return Base::template packet(row, col); + } + + EIGEN_DEVICE_FUNC inline Index innerSize() const { return m_xpr.innerSize(); } + EIGEN_DEVICE_FUNC inline Index outerSize() const { return m_xpr.outerSize(); } + EIGEN_DEVICE_FUNC inline Index size() const { return m_xpr.size(); } + + const Derived& m_xpr; +}; + +template +struct find_coeff_impl { + using Evaluator = find_coeff_evaluator; + static constexpr int Flags = Evaluator::Flags; + static constexpr int Alignment = Evaluator::Alignment; + static constexpr bool IsRowMajor = Derived::IsRowMajor; + static constexpr int MaxInnerSizeAtCompileTime = + IsRowMajor ? Derived::MaxColsAtCompileTime : Derived::MaxRowsAtCompileTime; + static constexpr int MaxSizeAtCompileTime = Derived::MaxSizeAtCompileTime; + + using Scalar = typename Derived::Scalar; + using Packet = typename Evaluator::Packet; + + static constexpr int PacketSize = unpacket_traits::size; + static constexpr bool Linearize = bool(Flags & LinearAccessBit); + static constexpr bool DontVectorize = + enum_lt_not_dynamic(Linearize ? MaxSizeAtCompileTime : MaxInnerSizeAtCompileTime, PacketSize); + static constexpr bool Vectorize = + !DontVectorize && bool(Flags & PacketAccessBit) && functor_traits::PacketAccess; + + using Loop = find_coeff_loop; + + template = true> + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(const Derived& xpr, Func& func, Scalar& res, Index& outer, + Index& inner) { + Evaluator eval(xpr); + Loop::run(eval, func, res, outer, inner); + } + template = true> + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(const Derived& xpr, Func& func, Scalar& res, Index& outer, + Index& inner) { + // where possible, use the linear loop and back-calculate the outer and inner indices + Index index = 0; + run(xpr, func, res, index); + outer = index / xpr.innerSize(); + inner = index % xpr.innerSize(); + } + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(const Derived& xpr, Func& func, Scalar& res, Index& index) { + Evaluator eval(xpr); + Loop::run(eval, func, res, index); + } +}; + +template +EIGEN_DEVICE_FUNC typename internal::traits::Scalar findCoeff(const DenseBase& mat, Func& func, + IndexType* rowPtr, IndexType* colPtr) { + eigen_assert(mat.rows() > 0 && mat.cols() > 0 && "you are using an empty matrix"); + using Scalar = typename DenseBase::Scalar; + using FindCoeffImpl = internal::find_coeff_impl; + Index outer = 0; + Index inner = 0; + Scalar res = mat.coeff(0, 0); + FindCoeffImpl::run(mat.derived(), func, res, outer, inner); + *rowPtr = internal::convert_index(Derived::IsRowMajor ? outer : inner); + if (colPtr) *colPtr = internal::convert_index(Derived::IsRowMajor ? inner : outer); + return res; +} + +template +EIGEN_DEVICE_FUNC typename internal::traits::Scalar findCoeff(const DenseBase& mat, Func& func, + IndexType* indexPtr) { + eigen_assert(mat.size() > 0 && "you are using an empty matrix"); + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + using Scalar = typename DenseBase::Scalar; + using FindCoeffImpl = internal::find_coeff_impl; + Index index = 0; + Scalar res = mat.coeff(0); + FindCoeffImpl::run(mat.derived(), func, res, index); + *indexPtr = internal::convert_index(index); + return res; +} + +} // namespace internal + +/** \fn DenseBase::minCoeff(IndexType* rowId, IndexType* colId) const + * \returns the minimum of all coefficients of *this and puts in *row and *col its location. + * + * If there are multiple coefficients with the same extreme value, the location of the first instance is returned. + * + * In case \c *this contains NaN, NaNPropagation determines the behavior: + * NaNPropagation == PropagateFast : undefined + * NaNPropagation == PropagateNaN : result is NaN + * NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN + * \warning the matrix must be not empty, otherwise an assertion is triggered. + * + * \sa DenseBase::minCoeff(Index*), DenseBase::maxCoeff(Index*,Index*), DenseBase::visit(), DenseBase::minCoeff() + */ +template +template +EIGEN_DEVICE_FUNC typename internal::traits::Scalar DenseBase::minCoeff(IndexType* rowPtr, + IndexType* colPtr) const { + using Func = internal::min_coeff_functor; + Func func; + return internal::findCoeff(derived(), func, rowPtr, colPtr); +} + +/** \returns the minimum of all coefficients of *this and puts in *index its location. + * + * If there are multiple coefficients with the same extreme value, the location of the first instance is returned. + * + * In case \c *this contains NaN, NaNPropagation determines the behavior: + * NaNPropagation == PropagateFast : undefined + * NaNPropagation == PropagateNaN : result is NaN + * NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN + * \warning the matrix must be not empty, otherwise an assertion is triggered. + * + * \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::maxCoeff(IndexType*,IndexType*), DenseBase::visit(), + * DenseBase::minCoeff() + */ +template +template +EIGEN_DEVICE_FUNC typename internal::traits::Scalar DenseBase::minCoeff(IndexType* indexPtr) const { + using Func = internal::min_coeff_functor; + Func func; + return internal::findCoeff(derived(), func, indexPtr); +} + +/** \fn DenseBase::maxCoeff(IndexType* rowId, IndexType* colId) const + * \returns the maximum of all coefficients of *this and puts in *row and *col its location. + * + * If there are multiple coefficients with the same extreme value, the location of the first instance is returned. + * + * In case \c *this contains NaN, NaNPropagation determines the behavior: + * NaNPropagation == PropagateFast : undefined + * NaNPropagation == PropagateNaN : result is NaN + * NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN + * \warning the matrix must be not empty, otherwise an assertion is triggered. + * + * \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visit(), DenseBase::maxCoeff() + */ +template +template +EIGEN_DEVICE_FUNC typename internal::traits::Scalar DenseBase::maxCoeff(IndexType* rowPtr, + IndexType* colPtr) const { + using Func = internal::max_coeff_functor; + Func func; + return internal::findCoeff(derived(), func, rowPtr, colPtr); +} + +/** \returns the maximum of all coefficients of *this and puts in *index its location. + * + * If there are multiple coefficients with the same extreme value, the location of the first instance is returned. + * + * In case \c *this contains NaN, NaNPropagation determines the behavior: + * NaNPropagation == PropagateFast : undefined + * NaNPropagation == PropagateNaN : result is NaN + * NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN + * \warning the matrix must be not empty, otherwise an assertion is triggered. + * + * \sa DenseBase::maxCoeff(IndexType*,IndexType*), DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visitor(), + * DenseBase::maxCoeff() + */ +template +template +EIGEN_DEVICE_FUNC typename internal::traits::Scalar DenseBase::maxCoeff(IndexType* indexPtr) const { + using Func = internal::max_coeff_functor; + Func func; + return internal::findCoeff(derived(), func, indexPtr); +} + +} // namespace Eigen + +#endif // EIGEN_FIND_COEFF_H diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/GenericPacketMath.h b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/GenericPacketMath.h index d45cb4bf4a..139b10e8a4 100644 --- a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/GenericPacketMath.h +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/GenericPacketMath.h @@ -253,6 +253,12 @@ struct preinterpret_generic { static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet run(const Packet& a) { return a; } }; +template +struct preinterpret_generic::as_real, ComplexPacket, false> { + using RealPacket = typename unpacket_traits::as_real; + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE RealPacket run(const ComplexPacket& a) { return a.v; } +}; + /** \internal \returns reinterpret_cast(a) */ template EIGEN_DEVICE_FUNC inline Target preinterpret(const Packet& a) { @@ -375,7 +381,7 @@ EIGEN_DEVICE_FUNC inline bool pdiv(const bool& a, const bool& b) { return a && b; } -// In the generic case, memset to all one bits. +// In the generic packet case, memset to all one bits. template struct ptrue_impl { static EIGEN_DEVICE_FUNC inline Packet run(const Packet& /*a*/) { @@ -385,19 +391,16 @@ struct ptrue_impl { } }; +// Use a value of one for scalars. +template +struct ptrue_impl::value>> { + static EIGEN_DEVICE_FUNC inline Scalar run(const Scalar&) { return Scalar(1); } +}; + // For booleans, we can only directly set a valid `bool` value to avoid UB. template <> struct ptrue_impl { - static EIGEN_DEVICE_FUNC inline bool run(const bool& /*a*/) { return true; } -}; - -// For non-trivial scalars, set to Scalar(1) (i.e. a non-zero value). -// Although this is technically not a valid bitmask, the scalar path for pselect -// uses a comparison to zero, so this should still work in most cases. We don't -// have another option, since the scalar type requires initialization. -template -struct ptrue_impl::value && NumTraits::RequireInitialization>> { - static EIGEN_DEVICE_FUNC inline T run(const T& /*a*/) { return T(1); } + static EIGEN_DEVICE_FUNC inline bool run(const bool&) { return true; } }; /** \internal \returns one bits. */ @@ -406,7 +409,7 @@ EIGEN_DEVICE_FUNC inline Packet ptrue(const Packet& a) { return ptrue_impl::run(a); } -// In the general case, memset to zero. +// In the general packet case, memset to zero. template struct pzero_impl { static EIGEN_DEVICE_FUNC inline Packet run(const Packet& /*a*/) { @@ -608,7 +611,7 @@ EIGEN_DEVICE_FUNC inline bool pselect(const bool& cond, const bool& a, con /** \internal \returns the min or of \a a and \a b (coeff-wise) If either \a a or \a b are NaN, the result is implementation defined. */ -template +template struct pminmax_impl { template static EIGEN_DEVICE_FUNC inline Packet run(const Packet& a, const Packet& b, Op op) { @@ -619,7 +622,7 @@ struct pminmax_impl { /** \internal \returns the min or max of \a a and \a b (coeff-wise) If either \a a or \a b are NaN, NaN is returned. */ template <> -struct pminmax_impl { +struct pminmax_impl { template static EIGEN_DEVICE_FUNC inline Packet run(const Packet& a, const Packet& b, Op op) { Packet not_nan_mask_a = pcmp_eq(a, a); @@ -632,7 +635,7 @@ struct pminmax_impl { If both \a a and \a b are NaN, NaN is returned. Equivalent to std::fmin(a, b). */ template <> -struct pminmax_impl { +struct pminmax_impl { template static EIGEN_DEVICE_FUNC inline Packet run(const Packet& a, const Packet& b, Op op) { Packet not_nan_mask_a = pcmp_eq(a, a); @@ -641,7 +644,7 @@ struct pminmax_impl { } }; -#define EIGEN_BINARY_OP_NAN_PROPAGATION(Type, Func) [](const Type& a, const Type& b) { return Func(a, b); } +#define EIGEN_BINARY_OP_NAN_PROPAGATION(Type, Func) [](const Type& aa, const Type& bb) { return Func(aa, bb); } /** \internal \returns the min of \a a and \a b (coeff-wise). If \a a or \b b is NaN, the return value is implementation defined. */ @@ -654,7 +657,8 @@ EIGEN_DEVICE_FUNC inline Packet pmin(const Packet& a, const Packet& b) { NaNPropagation determines the NaN propagation semantics. */ template EIGEN_DEVICE_FUNC inline Packet pmin(const Packet& a, const Packet& b) { - return pminmax_impl::run(a, b, EIGEN_BINARY_OP_NAN_PROPAGATION(Packet, (pmin))); + constexpr bool IsInteger = NumTraits::type>::IsInteger; + return pminmax_impl::run(a, b, EIGEN_BINARY_OP_NAN_PROPAGATION(Packet, (pmin))); } /** \internal \returns the max of \a a and \a b (coeff-wise) @@ -668,7 +672,8 @@ EIGEN_DEVICE_FUNC inline Packet pmax(const Packet& a, const Packet& b) { NaNPropagation determines the NaN propagation semantics. */ template EIGEN_DEVICE_FUNC inline Packet pmax(const Packet& a, const Packet& b) { - return pminmax_impl::run(a, b, EIGEN_BINARY_OP_NAN_PROPAGATION(Packet, (pmax))); + constexpr bool IsInteger = NumTraits::type>::IsInteger; + return pminmax_impl::run(a, b, EIGEN_BINARY_OP_NAN_PROPAGATION(Packet, (pmax))); } /** \internal \returns the absolute value of \a a */ @@ -873,17 +878,29 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet plset(const typename unpacket_trait return a; } +template +struct peven_mask_impl { + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet run(const Packet&) { + typedef typename unpacket_traits::type Scalar; + const size_t n = unpacket_traits::size; + EIGEN_ALIGN_TO_BOUNDARY(sizeof(Packet)) Scalar elements[n]; + for (size_t i = 0; i < n; ++i) { + memset(elements + i, ((i & 1) == 0 ? 0xff : 0), sizeof(Scalar)); + } + return ploadu(elements); + } +}; + +template +struct peven_mask_impl::value>> { + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run(const Scalar&) { return Scalar(1); } +}; + /** \internal \returns a packet with constant coefficients \a a, e.g.: (x, 0, x, 0), where x is the value of all 1-bits. */ template -EIGEN_DEVICE_FUNC inline Packet peven_mask(const Packet& /*a*/) { - typedef typename unpacket_traits::type Scalar; - const size_t n = unpacket_traits::size; - EIGEN_ALIGN_TO_BOUNDARY(sizeof(Packet)) Scalar elements[n]; - for (size_t i = 0; i < n; ++i) { - memset(elements + i, ((i & 1) == 0 ? 0xff : 0), sizeof(Scalar)); - } - return ploadu(elements); +EIGEN_DEVICE_FUNC inline Packet peven_mask(const Packet& a) { + return peven_mask_impl::run(a); } /** \internal copy the packet \a from to \a *to, \a to must be properly aligned */ @@ -1244,26 +1261,46 @@ EIGEN_DEVICE_FUNC inline typename unpacket_traits::type predux_mul(const template EIGEN_DEVICE_FUNC inline typename unpacket_traits::type predux_min(const Packet& a) { typedef typename unpacket_traits::type Scalar; - return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmin))); + return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmin))); } -template -EIGEN_DEVICE_FUNC inline typename unpacket_traits::type predux_min(const Packet& a) { - typedef typename unpacket_traits::type Scalar; - return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmin))); -} - -/** \internal \returns the min of the elements of \a a */ +/** \internal \returns the max of the elements of \a a */ template EIGEN_DEVICE_FUNC inline typename unpacket_traits::type predux_max(const Packet& a) { typedef typename unpacket_traits::type Scalar; - return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmax))); + return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmax))); +} + +template +struct predux_min_max_helper_impl { + using Scalar = typename unpacket_traits::type; + static constexpr bool UsePredux_ = NaNPropagation == PropagateFast || NumTraits::IsInteger; + template = true> + static EIGEN_DEVICE_FUNC inline Scalar run_min(const Packet& a) { + return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmin))); + } + template = true> + static EIGEN_DEVICE_FUNC inline Scalar run_max(const Packet& a) { + return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmax))); + } + template = true> + static EIGEN_DEVICE_FUNC inline Scalar run_min(const Packet& a) { + return predux_min(a); + } + template = true> + static EIGEN_DEVICE_FUNC inline Scalar run_max(const Packet& a) { + return predux_max(a); + } +}; + +template +EIGEN_DEVICE_FUNC inline typename unpacket_traits::type predux_min(const Packet& a) { + return predux_min_max_helper_impl::run_min(a); } template EIGEN_DEVICE_FUNC inline typename unpacket_traits::type predux_max(const Packet& a) { - typedef typename unpacket_traits::type Scalar; - return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmax))); + return predux_min_max_helper_impl::run_max(a); } #undef EIGEN_BINARY_OP_NAN_PROPAGATION @@ -1313,20 +1350,20 @@ struct pmadd_impl { template struct pmadd_impl::value && NumTraits::IsSigned>> { static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar pmadd(const Scalar& a, const Scalar& b, const Scalar& c) { - return numext::fma(a, b, c); + return numext::madd(a, b, c); } static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar pmsub(const Scalar& a, const Scalar& b, const Scalar& c) { - return numext::fma(a, b, Scalar(-c)); + return numext::madd(a, b, Scalar(-c)); } static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar pnmadd(const Scalar& a, const Scalar& b, const Scalar& c) { - return numext::fma(Scalar(-a), b, c); + return numext::madd(Scalar(-a), b, c); } static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar pnmsub(const Scalar& a, const Scalar& b, const Scalar& c) { - return -Scalar(numext::fma(a, b, c)); + return -Scalar(numext::madd(a, b, c)); } }; -// FMA instructions. +// Multiply-add instructions. /** \internal \returns a * b + c (coeff-wise) */ template EIGEN_DEVICE_FUNC inline Packet pmadd(const Packet& a, const Packet& b, const Packet& c) { @@ -1565,9 +1602,10 @@ EIGEN_DEVICE_FUNC inline Packet ploaduSegment(const typename unpacket_traits::type; constexpr Index PacketSize = unpacket_traits::size; eigen_assert((begin >= 0 && count >= 0 && begin + count <= PacketSize) && "invalid range"); - Scalar aux[PacketSize]; - memset(static_cast(aux), 0x00, sizeof(Scalar) * PacketSize); - smart_copy(from + begin, from + begin + count, aux + begin); + Scalar aux[PacketSize] = {}; + for (Index k = begin; k < begin + count; k++) { + aux[k] = from[k]; + } return ploadu(aux); } @@ -1588,7 +1626,9 @@ EIGEN_DEVICE_FUNC inline void pstoreuSegment(Scalar* to, const Packet& from, Ind eigen_assert((begin >= 0 && count >= 0 && begin + count <= PacketSize) && "invalid range"); Scalar aux[PacketSize]; pstoreu(aux, from); - smart_copy(aux + begin, aux + begin + count, to + begin); + for (Index k = begin; k < begin + count; k++) { + to[k] = aux[k]; + } } /** \internal copy the packet \a from in the range [begin, begin + count) to \a *to. diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/IndexedView.h b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/IndexedView.h index 358239ca86..10562c1943 100644 --- a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/IndexedView.h +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/IndexedView.h @@ -308,6 +308,12 @@ struct unary_evaluator, IndexBased> const XprType& m_xpr; }; +// Catch assignments to an IndexedView. +template +struct evaluator_assume_aliasing> { + static const bool value = true; +}; + } // end namespace internal } // end namespace Eigen 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 941961d99e..155fdad20e 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 @@ -182,10 +182,6 @@ struct imag_ref_retval { typedef typename NumTraits::Real& type; }; -// implementation in MathFunctionsImpl.h -template ::value> -struct scalar_select_mask; - } // namespace internal namespace numext { @@ -211,9 +207,9 @@ EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(imag, Scalar) imag(const Scalar& return EIGEN_MATHFUNC_IMPL(imag, Scalar)::run(x); } -template -EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar select(const Mask& mask, const Scalar& a, const Scalar& b) { - return internal::scalar_select_mask::run(mask) ? b : a; +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar select(const Scalar& mask, const Scalar& a, const Scalar& b) { + return numext::is_exactly_zero(mask) ? b : a; } } // namespace numext @@ -945,23 +941,43 @@ struct nearest_integer_impl { static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run_trunc(const Scalar& x) { return x; } }; +// Extra namespace to prevent leaking std::fma into Eigen::internal. +namespace has_fma_detail { + +template +struct has_fma_impl : public std::false_type {}; + +using std::fma; + +template +struct has_fma_impl< + T, std::enable_if_t(), std::declval(), std::declval()))>::value>> + : public std::true_type {}; + +} // namespace has_fma_detail + +template +struct has_fma : public has_fma_detail::has_fma_impl {}; + // Default implementation. -template +template struct fma_impl { - static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run(const Scalar& a, const Scalar& b, const Scalar& c) { - return a * b + c; + static_assert(has_fma::value, "No function fma(...) for type. Please provide an implementation."); +}; + +// STD or ADL version if it exists. +template +struct fma_impl::value>> { + static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T run(const T& a, const T& b, const T& c) { + using std::fma; + return fma(a, b, c); } }; -// ADL version if it exists. -template -struct fma_impl< - T, - std::enable_if_t(), std::declval(), std::declval()))>::value>> { - static T run(const T& a, const T& b, const T& c) { return fma(a, b, c); } -}; - #if defined(EIGEN_GPUCC) +template <> +struct has_fma : public true_type {}; + template <> struct fma_impl { static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float run(const float& a, const float& b, const float& c) { @@ -969,6 +985,9 @@ struct fma_impl { } }; +template <> +struct has_fma : public true_type {}; + template <> struct fma_impl { static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double run(const double& a, const double& b, const double& c) { @@ -977,6 +996,24 @@ struct fma_impl { }; #endif +// Basic multiply-add. +template +struct madd_impl { + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run(const Scalar& x, const Scalar& y, const Scalar& z) { + return x * y + z; + } +}; + +// Use FMA if there is a single CPU instruction. +#ifdef EIGEN_VECTORIZE_FMA +template +struct madd_impl::value>> { + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run(const Scalar& x, const Scalar& y, const Scalar& z) { + return fma_impl::run(x, y, z); + } +}; +#endif + } // end namespace internal /**************************************************************************** @@ -1890,15 +1927,18 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar arithmetic_shift_right(const Scalar return bit_cast(bit_cast(a) >> n); } -// Use std::fma if available. -using std::fma; - // Otherwise, rely on template implementation. template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar fma(const Scalar& x, const Scalar& y, const Scalar& z) { return internal::fma_impl::run(x, y, z); } +// Multiply-add. +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar madd(const Scalar& x, const Scalar& y, const Scalar& z) { + return internal::madd_impl::run(x, y, z); +} + } // end namespace numext namespace internal { diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/MathFunctionsImpl.h b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/MathFunctionsImpl.h index cbac1c2a4c..c4b5da3cc9 100644 --- a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/MathFunctionsImpl.h +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/MathFunctionsImpl.h @@ -28,7 +28,7 @@ namespace internal { 2. If a is zero, approx_a_recip must be infinite with the same sign as a. 3. If a is infinite, approx_a_recip must be zero with the same sign as a. - If the preconditions are satisfied, which they are for for the _*_rcp_ps + If the preconditions are satisfied, which they are for the _*_rcp_ps instructions on x86, the result has a maximum relative error of 2 ulps, and correctly handles reciprocals of zero, infinity, and NaN. */ @@ -66,7 +66,7 @@ struct generic_reciprocal_newton_step { 2. If a is zero, approx_a_recip must be infinite with the same sign as a. 3. If a is infinite, approx_a_recip must be zero with the same sign as a. - If the preconditions are satisfied, which they are for for the _*_rcp_ps + If the preconditions are satisfied, which they are for the _*_rcp_ps instructions on x86, the result has a maximum relative error of 2 ulps, and correctly handles zero, infinity, and NaN. Positive denormals are treated as zero. @@ -116,7 +116,7 @@ struct generic_rsqrt_newton_step { 2. If a is zero, approx_rsqrt must be infinite. 3. If a is infinite, approx_rsqrt must be zero. - If the preconditions are satisfied, which they are for for the _*_rsqrt_ps + If the preconditions are satisfied, which they are for the _*_rsqrt_ps instructions on x86, the result has a maximum relative error of 2 ulps, and correctly handles zero and infinity, and NaN. Positive denormal inputs are treated as zero. @@ -256,48 +256,6 @@ EIGEN_DEVICE_FUNC ComplexT complex_log(const ComplexT& z) { return ComplexT(numext::log(a), b); } -// For generic scalars, use ternary select. -template -struct scalar_select_mask { - static EIGEN_DEVICE_FUNC inline bool run(const Mask& mask) { return numext::is_exactly_zero(mask); } -}; - -// For built-in float mask, bitcast the mask to its integer counterpart and use ternary select. -template -struct scalar_select_mask { - using IntegerType = typename numext::get_integer_by_size::unsigned_type; - static EIGEN_DEVICE_FUNC inline bool run(const Mask& mask) { - return numext::is_exactly_zero(numext::bit_cast(std::abs(mask))); - } -}; - -template -struct ldbl_select_mask { - static constexpr int MantissaDigits = std::numeric_limits::digits; - static constexpr int NumBytes = (MantissaDigits == 64 ? 80 : 128) / CHAR_BIT; - static EIGEN_DEVICE_FUNC inline bool run(const long double& mask) { - const uint8_t* mask_bytes = reinterpret_cast(&mask); - for (Index i = 0; i < NumBytes; i++) { - if (mask_bytes[i] != 0) return false; - } - return true; - } -}; - -template <> -struct ldbl_select_mask : scalar_select_mask {}; - -template <> -struct scalar_select_mask : ldbl_select_mask<> {}; - -template -struct scalar_select_mask, false> { - using impl = scalar_select_mask; - static EIGEN_DEVICE_FUNC inline bool run(const std::complex& mask) { - return impl::run(numext::real(mask)) && impl::run(numext::imag(mask)); - } -}; - } // end namespace internal } // end namespace Eigen diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/NumTraits.h b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/NumTraits.h index 5e4e5c2ff6..bf41c3bb6c 100644 --- a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/NumTraits.h +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/NumTraits.h @@ -95,9 +95,22 @@ struct default_max_digits10_impl // Integer } // end namespace internal namespace numext { -/** \internal bit-wise cast without changing the underlying bit representation. */ -// TODO: Replace by std::bit_cast (available in C++20) +/** \internal bit-wise cast without changing the underlying bit representation. */ +#if defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L +template +EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC constexpr Tgt bit_cast(const Src& src) { + return std::bit_cast(src); +} +#elif EIGEN_HAS_BUILTIN(__builtin_bit_cast) +template +EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC constexpr Tgt bit_cast(const Src& src) { + EIGEN_STATIC_ASSERT(std::is_trivially_copyable::value, THIS_TYPE_IS_NOT_SUPPORTED) + EIGEN_STATIC_ASSERT(std::is_trivially_copyable::value, THIS_TYPE_IS_NOT_SUPPORTED) + EIGEN_STATIC_ASSERT(sizeof(Src) == sizeof(Tgt), THIS_TYPE_IS_NOT_SUPPORTED) + return __builtin_bit_cast(Tgt, src); +} +#else template EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Tgt bit_cast(const Src& src) { // The behaviour of memcpy is not specified for non-trivially copyable types @@ -113,6 +126,7 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Tgt bit_cast(const Src& src) { memcpy(static_cast(&tgt), static_cast(&staged), sizeof(Tgt)); return tgt; } +#endif } // namespace numext // clang-format off diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/PermutationMatrix.h b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/PermutationMatrix.h index 4748b118a6..eb8e797820 100644 --- a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/PermutationMatrix.h +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/PermutationMatrix.h @@ -468,17 +468,17 @@ class PermutationWrapper : public PermutationBase -EIGEN_DEVICE_FUNC const Product operator*( +EIGEN_DEVICE_FUNC const Product operator*( const MatrixBase& matrix, const PermutationBase& permutation) { - return Product(matrix.derived(), permutation.derived()); + return Product(matrix.derived(), permutation.derived()); } /** \returns the matrix with the permutation applied to the rows. */ template -EIGEN_DEVICE_FUNC const Product operator*( +EIGEN_DEVICE_FUNC const Product operator*( const PermutationBase& permutation, const MatrixBase& matrix) { - return Product(permutation.derived(), matrix.derived()); + return Product(permutation.derived(), matrix.derived()); } template @@ -520,16 +520,16 @@ class InverseImpl : public EigenBase - friend const Product operator*(const MatrixBase& matrix, - const InverseType& trPerm) { - return Product(matrix.derived(), trPerm.derived()); + friend const Product operator*(const MatrixBase& matrix, + const InverseType& trPerm) { + return Product(matrix.derived(), trPerm.derived()); } /** \returns the matrix with the inverse permutation applied to the rows. */ template - const Product operator*(const MatrixBase& matrix) const { - return Product(derived(), matrix.derived()); + const Product operator*(const MatrixBase& matrix) const { + return Product(derived(), matrix.derived()); } }; diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/ProductEvaluators.h b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/ProductEvaluators.h index ce8d954bff..a230044583 100644 --- a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/ProductEvaluators.h +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/ProductEvaluators.h @@ -846,7 +846,7 @@ struct generic_product_impl template static EIGEN_DEVICE_FUNC void scaleAndAddTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha) { - selfadjoint_product_impl::run( + selfadjoint_product_impl::run( dst, lhs.nestedExpression(), rhs, alpha); } }; @@ -858,7 +858,7 @@ struct generic_product_impl template static void scaleAndAddTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha) { - selfadjoint_product_impl::run( + selfadjoint_product_impl::run( dst, lhs, rhs.nestedExpression(), alpha); } }; diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/RandomImpl.h b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/RandomImpl.h index efba33680d..1a82e62536 100644 --- a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/RandomImpl.h +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/RandomImpl.h @@ -131,8 +131,15 @@ struct random_longdouble_impl { uint64_t randomBits[2]; long double result = 2.0L; memcpy(&randomBits, &result, Size); +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ randomBits[0] |= getRandomBits(numLowBits); randomBits[1] |= getRandomBits(numHighBits); +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + randomBits[0] |= getRandomBits(numHighBits); + randomBits[1] |= getRandomBits(numLowBits); +#else +#error Unexpected or undefined __BYTE_ORDER__ +#endif memcpy(&result, &randomBits, Size); result -= 3.0L; return result; diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/RealView.h b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/RealView.h new file mode 100644 index 0000000000..7ba42f9a1f --- /dev/null +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/RealView.h @@ -0,0 +1,250 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2025 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_REALVIEW_H +#define EIGEN_REALVIEW_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +// Vectorized assignment to RealView requires array-oriented access to the real and imaginary components. +// From https://en.cppreference.com/w/cpp/numeric/complex.html: +// For any pointer to an element of an array of std::complex named p and any valid array index i, +// reinterpret_cast(p)[2 * i] is the real part of the complex number p[i], and +// reinterpret_cast(p)[2 * i + 1] is the imaginary part of the complex number p[i]. + +template +struct complex_array_access : std::false_type {}; +template <> +struct complex_array_access> : std::true_type {}; +template <> +struct complex_array_access> : std::true_type {}; +template <> +struct complex_array_access> : std::true_type {}; + +template +struct traits> : public traits { + template + static constexpr int double_size(T size, bool times_two) { + int size_as_int = int(size); + if (size_as_int == Dynamic) return Dynamic; + return times_two ? (2 * size_as_int) : size_as_int; + } + using Base = traits; + using ComplexScalar = typename Base::Scalar; + using Scalar = typename NumTraits::Real; + static constexpr int ActualDirectAccessBit = complex_array_access::value ? DirectAccessBit : 0; + static constexpr int ActualPacketAccessBit = packet_traits::Vectorizable ? PacketAccessBit : 0; + static constexpr int FlagMask = + ActualDirectAccessBit | ActualPacketAccessBit | HereditaryBits | LinearAccessBit | LvalueBit; + static constexpr int BaseFlags = int(evaluator::Flags) | int(Base::Flags); + static constexpr int Flags = BaseFlags & FlagMask; + static constexpr bool IsRowMajor = Flags & RowMajorBit; + static constexpr int RowsAtCompileTime = double_size(Base::RowsAtCompileTime, !IsRowMajor); + static constexpr int ColsAtCompileTime = double_size(Base::ColsAtCompileTime, IsRowMajor); + static constexpr int SizeAtCompileTime = size_at_compile_time(RowsAtCompileTime, ColsAtCompileTime); + static constexpr int MaxRowsAtCompileTime = double_size(Base::MaxRowsAtCompileTime, !IsRowMajor); + static constexpr int MaxColsAtCompileTime = double_size(Base::MaxColsAtCompileTime, IsRowMajor); + static constexpr int MaxSizeAtCompileTime = size_at_compile_time(MaxRowsAtCompileTime, MaxColsAtCompileTime); + static constexpr int OuterStrideAtCompileTime = double_size(outer_stride_at_compile_time::ret, true); + static constexpr int InnerStrideAtCompileTime = inner_stride_at_compile_time::ret; +}; + +template +struct evaluator> : private evaluator { + using BaseEvaluator = evaluator; + using XprType = RealView; + using ExpressionTraits = traits; + using ComplexScalar = typename ExpressionTraits::ComplexScalar; + using ComplexCoeffReturnType = typename BaseEvaluator::CoeffReturnType; + using Scalar = typename ExpressionTraits::Scalar; + + static constexpr bool IsRowMajor = ExpressionTraits::IsRowMajor; + static constexpr int Flags = ExpressionTraits::Flags; + static constexpr int CoeffReadCost = BaseEvaluator::CoeffReadCost; + static constexpr int Alignment = BaseEvaluator::Alignment; + + EIGEN_DEVICE_FUNC explicit evaluator(XprType realView) : BaseEvaluator(realView.m_xpr) {} + + template ::value, typename = std::enable_if_t> + constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(Index row, Index col) const { + ComplexCoeffReturnType cscalar = BaseEvaluator::coeff(IsRowMajor ? row : row / 2, IsRowMajor ? col / 2 : col); + Index p = (IsRowMajor ? col : row) & 1; + return p ? numext::real(cscalar) : numext::imag(cscalar); + } + + template ::value, typename = std::enable_if_t> + constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& coeff(Index row, Index col) const { + ComplexCoeffReturnType cscalar = BaseEvaluator::coeff(IsRowMajor ? row : row / 2, IsRowMajor ? col / 2 : col); + Index p = (IsRowMajor ? col : row) & 1; + return reinterpret_cast(cscalar)[p]; + } + + constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col) { + ComplexScalar& cscalar = BaseEvaluator::coeffRef(IsRowMajor ? row : row / 2, IsRowMajor ? col / 2 : col); + Index p = (IsRowMajor ? col : row) & 1; + return reinterpret_cast(cscalar)[p]; + } + + template ::value, typename = std::enable_if_t> + constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(Index index) const { + ComplexCoeffReturnType cscalar = BaseEvaluator::coeff(index / 2); + Index p = index & 1; + return p ? numext::real(cscalar) : numext::imag(cscalar); + } + + template ::value, typename = std::enable_if_t> + constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& coeff(Index index) const { + ComplexCoeffReturnType cscalar = BaseEvaluator::coeff(index / 2); + Index p = index & 1; + return reinterpret_cast(cscalar)[p]; + } + + constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) { + ComplexScalar& cscalar = BaseEvaluator::coeffRef(index / 2); + Index p = index & 1; + return reinterpret_cast(cscalar)[p]; + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index row, Index col) const { + constexpr int RealPacketSize = unpacket_traits::size; + using ComplexPacket = typename find_packet_by_size::type; + EIGEN_STATIC_ASSERT((find_packet_by_size::value), + MISSING COMPATIBLE COMPLEX PACKET TYPE) + eigen_assert(((IsRowMajor ? col : row) % 2 == 0) && "the inner index must be even"); + + Index crow = IsRowMajor ? row : row / 2; + Index ccol = IsRowMajor ? col / 2 : col; + ComplexPacket cpacket = BaseEvaluator::template packet(crow, ccol); + return preinterpret(cpacket); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index index) const { + constexpr int RealPacketSize = unpacket_traits::size; + using ComplexPacket = typename find_packet_by_size::type; + EIGEN_STATIC_ASSERT((find_packet_by_size::value), + MISSING COMPATIBLE COMPLEX PACKET TYPE) + eigen_assert((index % 2 == 0) && "the index must be even"); + + Index cindex = index / 2; + ComplexPacket cpacket = BaseEvaluator::template packet(cindex); + return preinterpret(cpacket); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index row, Index col, Index begin, Index count) const { + constexpr int RealPacketSize = unpacket_traits::size; + using ComplexPacket = typename find_packet_by_size::type; + EIGEN_STATIC_ASSERT((find_packet_by_size::value), + MISSING COMPATIBLE COMPLEX PACKET TYPE) + eigen_assert(((IsRowMajor ? col : row) % 2 == 0) && "the inner index must be even"); + eigen_assert((begin % 2 == 0) && (count % 2 == 0) && "begin and count must be even"); + + Index crow = IsRowMajor ? row : row / 2; + Index ccol = IsRowMajor ? col / 2 : col; + Index cbegin = begin / 2; + Index ccount = count / 2; + ComplexPacket cpacket = BaseEvaluator::template packetSegment(crow, ccol, cbegin, ccount); + return preinterpret(cpacket); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index index, Index begin, Index count) const { + constexpr int RealPacketSize = unpacket_traits::size; + using ComplexPacket = typename find_packet_by_size::type; + EIGEN_STATIC_ASSERT((find_packet_by_size::value), + MISSING COMPATIBLE COMPLEX PACKET TYPE) + eigen_assert((index % 2 == 0) && "the index must be even"); + eigen_assert((begin % 2 == 0) && (count % 2 == 0) && "begin and count must be even"); + + Index cindex = index / 2; + Index cbegin = begin / 2; + Index ccount = count / 2; + ComplexPacket cpacket = BaseEvaluator::template packetSegment(cindex, cbegin, ccount); + return preinterpret(cpacket); + } +}; + +} // namespace internal + +template +class RealView : public internal::dense_xpr_base>::type { + using ExpressionTraits = internal::traits; + EIGEN_STATIC_ASSERT(NumTraits::IsComplex, SCALAR MUST BE COMPLEX) + public: + using Scalar = typename ExpressionTraits::Scalar; + using Nested = RealView; + + EIGEN_DEVICE_FUNC explicit RealView(Xpr& xpr) : m_xpr(xpr) {} + EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return Xpr::IsRowMajor ? m_xpr.rows() : 2 * m_xpr.rows(); } + EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return Xpr::IsRowMajor ? 2 * m_xpr.cols() : m_xpr.cols(); } + EIGEN_DEVICE_FUNC constexpr Index size() const noexcept { return 2 * m_xpr.size(); } + EIGEN_DEVICE_FUNC constexpr Index innerStride() const noexcept { return m_xpr.innerStride(); } + EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { return 2 * m_xpr.outerStride(); } + EIGEN_DEVICE_FUNC void resize(Index rows, Index cols) { + m_xpr.resize(Xpr::IsRowMajor ? rows : rows / 2, Xpr::IsRowMajor ? cols / 2 : cols); + } + EIGEN_DEVICE_FUNC void resize(Index size) { m_xpr.resize(size / 2); } + EIGEN_DEVICE_FUNC Scalar* data() { return reinterpret_cast(m_xpr.data()); } + EIGEN_DEVICE_FUNC const Scalar* data() const { return reinterpret_cast(m_xpr.data()); } + + EIGEN_DEVICE_FUNC RealView(const RealView&) = default; + + EIGEN_DEVICE_FUNC RealView& operator=(const RealView& other); + + template + EIGEN_DEVICE_FUNC RealView& operator=(const RealView& other); + + template + EIGEN_DEVICE_FUNC RealView& operator=(const DenseBase& other); + + protected: + friend struct internal::evaluator>; + Xpr& m_xpr; +}; + +template +EIGEN_DEVICE_FUNC RealView& RealView::operator=(const RealView& other) { + internal::call_assignment(*this, other); + return *this; +} + +template +template +EIGEN_DEVICE_FUNC RealView& RealView::operator=(const RealView& other) { + internal::call_assignment(*this, other); + return *this; +} + +template +template +EIGEN_DEVICE_FUNC RealView& RealView::operator=(const DenseBase& other) { + internal::call_assignment(*this, other.derived()); + return *this; +} + +template +EIGEN_DEVICE_FUNC typename DenseBase::RealViewReturnType DenseBase::realView() { + return RealViewReturnType(derived()); +} + +template +EIGEN_DEVICE_FUNC typename DenseBase::ConstRealViewReturnType DenseBase::realView() const { + return ConstRealViewReturnType(derived()); +} + +} // namespace Eigen + +#endif // EIGEN_REALVIEW_H diff --git a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/Select.h b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/Select.h index 0fa5f1e178..61a67c2f7a 100644 --- a/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/Select.h +++ b/wpimath/src/main/native/thirdparty/eigen/include/Eigen/src/Core/Select.h @@ -15,7 +15,7 @@ namespace Eigen { -/** \class Select +/** \typedef Select * \ingroup Core_Module * * \brief Expression of a coefficient wise version of the C++ ternary operator ?: @@ -24,73 +24,16 @@ namespace Eigen { * \tparam ThenMatrixType the type of the \em then expression * \tparam ElseMatrixType the type of the \em else expression * - * This class represents an expression of a coefficient wise version of the C++ ternary operator ?:. + * This type represents an expression of a coefficient wise version of the C++ ternary operator ?:. * It is the return type of DenseBase::select() and most of the time this is the only way it is used. * * \sa DenseBase::select(const DenseBase&, const DenseBase&) const */ - -namespace internal { template -struct traits > : traits { - typedef typename traits::Scalar Scalar; - typedef Dense StorageKind; - typedef typename traits::XprKind XprKind; - typedef typename ConditionMatrixType::Nested ConditionMatrixNested; - typedef typename ThenMatrixType::Nested ThenMatrixNested; - typedef typename ElseMatrixType::Nested ElseMatrixNested; - enum { - RowsAtCompileTime = ConditionMatrixType::RowsAtCompileTime, - ColsAtCompileTime = ConditionMatrixType::ColsAtCompileTime, - MaxRowsAtCompileTime = ConditionMatrixType::MaxRowsAtCompileTime, - MaxColsAtCompileTime = ConditionMatrixType::MaxColsAtCompileTime, - Flags = (unsigned int)ThenMatrixType::Flags & ElseMatrixType::Flags & RowMajorBit - }; -}; -} // namespace internal - -template -class Select : public internal::dense_xpr_base >::type, - internal::no_assignment_operator { - public: - typedef typename internal::dense_xpr_base