Make element accessors constexpr

This commit is contained in:
Tyler Veness 2024-11-14 01:05:29 +00:00 committed by Charles Schlosser
parent 8b4efc8ed8
commit 0fb2ed140d
4 changed files with 43 additions and 30 deletions

View File

@ -124,8 +124,7 @@ struct evaluator_base {
// noncopyable: // noncopyable:
// Don't make this class inherit noncopyable as this kills EBO (Empty Base Optimization) // Don't make this class inherit noncopyable as this kills EBO (Empty Base Optimization)
// and make complex evaluator much larger than then should do. // and make complex evaluator much larger than then should do.
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE evaluator_base() {} EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr evaluator_base() = default;
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ~evaluator_base() {}
private: private:
EIGEN_DEVICE_FUNC evaluator_base(const evaluator_base&); EIGEN_DEVICE_FUNC evaluator_base(const evaluator_base&);
@ -143,7 +142,7 @@ struct evaluator_base {
template <typename Scalar, int OuterStride> template <typename Scalar, int OuterStride>
class plainobjectbase_evaluator_data { class plainobjectbase_evaluator_data {
public: public:
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE plainobjectbase_evaluator_data(const Scalar* ptr, Index outerStride) EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr plainobjectbase_evaluator_data(const Scalar* ptr, Index outerStride)
: data(ptr) { : data(ptr) {
#ifndef EIGEN_INTERNAL_DEBUGGING #ifndef EIGEN_INTERNAL_DEBUGGING
EIGEN_UNUSED_VARIABLE(outerStride); EIGEN_UNUSED_VARIABLE(outerStride);
@ -157,9 +156,9 @@ class plainobjectbase_evaluator_data {
template <typename Scalar> template <typename Scalar>
class plainobjectbase_evaluator_data<Scalar, Dynamic> { class plainobjectbase_evaluator_data<Scalar, Dynamic> {
public: public:
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE plainobjectbase_evaluator_data(const Scalar* ptr, Index outerStride) EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr plainobjectbase_evaluator_data(const Scalar* ptr, Index outerStride)
: data(ptr), m_outerStride(outerStride) {} : data(ptr), m_outerStride(outerStride) {}
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index outerStride() const { return m_outerStride; } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index outerStride() const { return m_outerStride; }
const Scalar* data; const Scalar* data;
protected: protected:
@ -189,32 +188,34 @@ struct evaluator<PlainObjectBase<Derived>> : evaluator_base<Derived> {
: RowsAtCompileTime : RowsAtCompileTime
}; };
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE evaluator() : m_d(0, OuterStrideAtCompileTime) { EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr evaluator() : m_d(0, OuterStrideAtCompileTime) {
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
} }
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit evaluator(const PlainObjectType& m) EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr explicit evaluator(const PlainObjectType& m)
: m_d(m.data(), IsVectorAtCompileTime ? 0 : m.outerStride()) { : m_d(m.data(), IsVectorAtCompileTime ? 0 : m.outerStride()) {
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
} }
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const { EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr CoeffReturnType coeff(Index row, Index col) const {
if (IsRowMajor) if (IsRowMajor)
return m_d.data[row * m_d.outerStride() + col]; return m_d.data[row * m_d.outerStride() + col];
else else
return m_d.data[row + col * m_d.outerStride()]; return m_d.data[row + col * m_d.outerStride()];
} }
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const { return m_d.data[index]; } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr CoeffReturnType coeff(Index index) const { return m_d.data[index]; }
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col) { EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Scalar& coeffRef(Index row, Index col) {
if (IsRowMajor) if (IsRowMajor)
return const_cast<Scalar*>(m_d.data)[row * m_d.outerStride() + col]; return const_cast<Scalar*>(m_d.data)[row * m_d.outerStride() + col];
else else
return const_cast<Scalar*>(m_d.data)[row + col * m_d.outerStride()]; return const_cast<Scalar*>(m_d.data)[row + col * m_d.outerStride()];
} }
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) { return const_cast<Scalar*>(m_d.data)[index]; } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Scalar& coeffRef(Index index) {
return const_cast<Scalar*>(m_d.data)[index];
}
template <int LoadMode, typename PacketType> template <int LoadMode, typename PacketType>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index row, Index col) const { EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index row, Index col) const {
@ -251,9 +252,10 @@ struct evaluator<Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols>>
: evaluator<PlainObjectBase<Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols>>> { : evaluator<PlainObjectBase<Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols>>> {
typedef Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> XprType; typedef Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> XprType;
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE evaluator() {} EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr evaluator() = default;
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit evaluator(const XprType& m) : evaluator<PlainObjectBase<XprType>>(m) {} EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr explicit evaluator(const XprType& m)
: evaluator<PlainObjectBase<XprType>>(m) {}
}; };
template <typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols> template <typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
@ -261,9 +263,10 @@ struct evaluator<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols>>
: evaluator<PlainObjectBase<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols>>> { : evaluator<PlainObjectBase<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols>>> {
typedef Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> XprType; typedef Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> XprType;
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE evaluator() {} EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr evaluator() = default;
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit evaluator(const XprType& m) : evaluator<PlainObjectBase<XprType>>(m) {} EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr explicit evaluator(const XprType& m)
: evaluator<PlainObjectBase<XprType>>(m) {}
}; };
// -------------------- Transpose -------------------- // -------------------- Transpose --------------------

View File

@ -298,7 +298,7 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
* *
* \sa operator()(Index,Index), coeff(Index, Index) const, coeffRef(Index) * \sa operator()(Index,Index), coeff(Index, Index) const, coeffRef(Index)
*/ */
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col) { EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Scalar& coeffRef(Index row, Index col) {
eigen_internal_assert(row >= 0 && row < rows() && col >= 0 && col < cols()); eigen_internal_assert(row >= 0 && row < rows() && col >= 0 && col < cols());
return internal::evaluator<Derived>(derived()).coeffRef(row, col); return internal::evaluator<Derived>(derived()).coeffRef(row, col);
} }
@ -312,7 +312,7 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
* \sa operator[](Index) * \sa operator[](Index)
*/ */
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& operator()(Index row, Index col) { EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Scalar& operator()(Index row, Index col) {
eigen_assert(row >= 0 && row < rows() && col >= 0 && col < cols()); eigen_assert(row >= 0 && row < rows() && col >= 0 && col < cols());
return coeffRef(row, col); return coeffRef(row, col);
} }
@ -332,7 +332,7 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
* \sa operator[](Index), coeff(Index) const, coeffRef(Index,Index) * \sa operator[](Index), coeff(Index) const, coeffRef(Index,Index)
*/ */
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) { EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Scalar& coeffRef(Index index) {
EIGEN_STATIC_ASSERT(internal::evaluator<Derived>::Flags & LinearAccessBit, EIGEN_STATIC_ASSERT(internal::evaluator<Derived>::Flags & LinearAccessBit,
THIS_COEFFICIENT_ACCESSOR_TAKING_ONE_ACCESS_IS_ONLY_FOR_EXPRESSIONS_ALLOWING_LINEAR_ACCESS) THIS_COEFFICIENT_ACCESSOR_TAKING_ONE_ACCESS_IS_ONLY_FOR_EXPRESSIONS_ALLOWING_LINEAR_ACCESS)
eigen_internal_assert(index >= 0 && index < size()); eigen_internal_assert(index >= 0 && index < size());
@ -346,7 +346,7 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
* \sa operator[](Index) const, operator()(Index,Index), x(), y(), z(), w() * \sa operator[](Index) const, operator()(Index,Index), x(), y(), z(), w()
*/ */
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& operator[](Index index) { EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Scalar& operator[](Index index) {
EIGEN_STATIC_ASSERT(Derived::IsVectorAtCompileTime, EIGEN_STATIC_ASSERT(Derived::IsVectorAtCompileTime,
THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD) THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD)
eigen_assert(index >= 0 && index < size()); eigen_assert(index >= 0 && index < size());

View File

@ -46,9 +46,9 @@ struct EigenBase {
typedef typename internal::traits<Derived>::StorageKind StorageKind; typedef typename internal::traits<Derived>::StorageKind StorageKind;
/** \returns a reference to the derived object */ /** \returns a reference to the derived object */
EIGEN_DEVICE_FUNC Derived& derived() { return *static_cast<Derived*>(this); } EIGEN_DEVICE_FUNC constexpr Derived& derived() { return *static_cast<Derived*>(this); }
/** \returns a const reference to the derived object */ /** \returns a const reference to the derived object */
EIGEN_DEVICE_FUNC const Derived& derived() const { return *static_cast<const Derived*>(this); } EIGEN_DEVICE_FUNC constexpr const Derived& derived() const { return *static_cast<const Derived*>(this); }
EIGEN_DEVICE_FUNC inline Derived& const_cast_derived() const { EIGEN_DEVICE_FUNC inline Derived& const_cast_derived() const {
return *static_cast<Derived*>(const_cast<EigenBase*>(this)); return *static_cast<Derived*>(const_cast<EigenBase*>(this));

View File

@ -16,38 +16,48 @@ EIGEN_DECLARE_TEST(constexpr) {
// until after the constructor returns: // until after the constructor returns:
// error: member Eigen::internal::plain_array<int, 9, 0, 0>::array must be initialized by mem-initializer in // error: member Eigen::internal::plain_array<int, 9, 0, 0>::array must be initialized by mem-initializer in
// constexpr constructor // constexpr constructor
#if EIGEN_COMP_CXXVER >= 20 #if __cpp_constexpr >= 201907L
constexpr Matrix3i mat({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}); constexpr Matrix3i mat({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
VERIFY_IS_EQUAL(mat.size(), 9); VERIFY_IS_EQUAL(mat.size(), 9);
VERIFY_IS_EQUAL(mat(0, 0), 1); static_assert(mat(0, 0) == 1);
static_assert(mat(0) == 1);
static_assert(mat.coeff(0, 1) == 2); static_assert(mat.coeff(0, 1) == 2);
constexpr Array33i arr({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}); constexpr Array33i arr({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
VERIFY_IS_EQUAL(arr(0, 0), 1); static_assert(arr(0, 0) == 1);
static_assert(arr(0) == 1);
VERIFY_IS_EQUAL(arr.size(), 9); VERIFY_IS_EQUAL(arr.size(), 9);
static_assert(arr.coeff(0, 1) == 2); static_assert(arr.coeff(0, 1) == 2);
constexpr RowVector3i vec{{1, 2, 3}};
static_assert(vec(0, 0) == 1);
static_assert(vec[0] == 1);
VERIFY_IS_EQUAL(vec.size(), 3);
static_assert(vec.coeff(0, 1) == 2);
// Also check dynamic size arrays/matrices with fixed-size storage (currently // Also check dynamic size arrays/matrices with fixed-size storage (currently
// only works if all elements are initialized, since otherwise the compiler // only works if all elements are initialized, since otherwise the compiler
// complains about uninitialized trailing elements. // complains about uninitialized trailing elements.
constexpr Matrix<int, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> dyn_mat({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}); constexpr Matrix<int, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> dyn_mat({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
VERIFY_IS_EQUAL(dyn_mat.size(), 9); VERIFY_IS_EQUAL(dyn_mat.size(), 9);
VERIFY_IS_EQUAL(dyn_mat(0, 0), 1); static_assert(dyn_mat(0, 0) == 1);
static_assert(dyn_mat.coeff(0, 1) == 2); static_assert(dyn_mat.coeff(0, 1) == 2);
constexpr Array<int, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> dyn_arr({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}); constexpr Array<int, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> dyn_arr({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
VERIFY_IS_EQUAL(dyn_arr(0, 0), 1); static_assert(dyn_arr(0, 0) == 1);
static_assert(dyn_arr(0) == 1);
VERIFY_IS_EQUAL(dyn_arr.size(), 9); VERIFY_IS_EQUAL(dyn_arr.size(), 9);
static_assert(dyn_arr.coeff(0, 1) == 2); static_assert(dyn_arr.coeff(0, 1) == 2);
#endif // EIGEN_COMP_CXXVER >= 20 #endif // __cpp_constexpr >= 201907L
} }
// Check that we can use the std::initializer_list constructor for constexpr variables. // Check that we can use the std::initializer_list constructor for constexpr variables.
#if EIGEN_COMP_CXXVER >= 20 #if __cpp_constexpr >= 201907L
// EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT() will fail constexpr evaluation unless // EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT() will fail constexpr evaluation unless
// we have std::is_constant_evaluated(). // we have std::is_constant_evaluated().
constexpr Matrix<int, 2, 2> global_mat({{1, 2}, {3, 4}}); constexpr Matrix<int, 2, 2> global_mat({{1, 2}, {3, 4}});
EIGEN_DECLARE_TEST(constexpr_global) { EIGEN_DECLARE_TEST(constexpr_global) {
VERIFY_IS_EQUAL(global_mat.size(), 4); VERIFY_IS_EQUAL(global_mat.size(), 4);
VERIFY_IS_EQUAL(global_mat(0, 0), 1); static_assert(global_mat(0, 0) == 1);
static_assert(global_mat(0) == 1);
static_assert(global_mat.coeff(0, 0) == 1); static_assert(global_mat.coeff(0, 0) == 1);
} }
#endif // EIGEN_COMP_CXXVER >= 20 #endif // __cpp_constexpr >= 201907L