Refactor IndexedView

This commit is contained in:
Charles Schlosser
2023-04-17 12:32:50 +00:00
parent 1148f0a9ec
commit 87300c93ca
2 changed files with 319 additions and 115 deletions

View File

@@ -7,6 +7,7 @@
// 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/.
#if !defined(EIGEN_PARSED_BY_DOXYGEN)
protected:
@@ -24,163 +25,278 @@ using IvcType = typename internal::IndexedViewCompatibleType<Indices, SizeAtComp
typedef typename internal::IndexedViewCompatibleType<Index, 1>::type IvcIndex;
template <typename Indices>
IvcRowType<Indices> ivcRow(const Indices& indices) const {
inline IvcRowType<Indices> ivcRow(const Indices& indices) const {
return internal::makeIndexedViewCompatible(
indices, internal::variable_if_dynamic<Index, RowsAtCompileTime>(derived().rows()), Specialized);
}
template <typename Indices>
IvcColType<Indices> ivcCol(const Indices& indices) const {
inline IvcColType<Indices> ivcCol(const Indices& indices) const {
return internal::makeIndexedViewCompatible(
indices, internal::variable_if_dynamic<Index, ColsAtCompileTime>(derived().cols()), Specialized);
}
template <typename Indices>
IvcColType<Indices> ivcSize(const Indices& indices) const {
inline IvcColType<Indices> ivcSize(const Indices& indices) const {
return internal::makeIndexedViewCompatible(
indices, internal::variable_if_dynamic<Index, SizeAtCompileTime>(derived().size()), Specialized);
}
// this helper class assumes internal::valid_indexed_view_overload<RowIndices, ColIndices>::value == true
template <typename RowIndices, typename ColIndices,
bool UseSymbolic = internal::traits<IndexedView<Derived, IvcRowType<RowIndices>, IvcColType<ColIndices>>>::ReturnAsScalar,
bool UseBlock = internal::traits<IndexedView<Derived, IvcRowType<RowIndices>, IvcColType<ColIndices>>>::ReturnAsBlock,
bool UseGeneric = internal::traits<IndexedView<Derived, IvcRowType<RowIndices>, IvcColType<ColIndices>>>::ReturnAsIndexedView>
struct IndexedViewSelector;
// Generic
template <typename RowIndices, typename ColIndices>
struct IndexedViewSelector<RowIndices, ColIndices, false, false, true> {
using ReturnType = IndexedView<Derived, IvcRowType<RowIndices>, IvcColType<ColIndices>>;
using ConstReturnType = IndexedView<const Derived, IvcRowType<RowIndices>, IvcColType<ColIndices>>;
static inline ReturnType run(Derived& derived, const RowIndices& rowIndices, const ColIndices& colIndices) {
return ReturnType(derived, derived.ivcRow(rowIndices), derived.ivcCol(colIndices));
}
static inline ConstReturnType run(const Derived& derived, const RowIndices& rowIndices,
const ColIndices& colIndices) {
return ConstReturnType(derived, derived.ivcRow(rowIndices), derived.ivcCol(colIndices));
}
};
// Block
template <typename RowIndices, typename ColIndices>
struct IndexedViewSelector<RowIndices, ColIndices, false, true, false> {
using IndexedViewType = IndexedView<Derived, IvcRowType<RowIndices>, IvcColType<ColIndices>>;
using ConstIndexedViewType = IndexedView<const Derived, IvcRowType<RowIndices>, IvcColType<ColIndices>>;
using ReturnType = typename internal::traits<IndexedViewType>::BlockType;
using ConstReturnType = typename internal::traits<ConstIndexedViewType>::BlockType;
static inline ReturnType run(Derived& derived, const RowIndices& rowIndices, const ColIndices& colIndices) {
IvcRowType<RowIndices> actualRowIndices = derived.ivcRow(rowIndices);
IvcColType<ColIndices> actualColIndices = derived.ivcCol(colIndices);
return ReturnType(derived, internal::first(actualRowIndices), internal::first(actualColIndices),
internal::index_list_size(actualRowIndices), internal::index_list_size(actualColIndices));
}
static inline ConstReturnType run(const Derived& derived, const RowIndices& rowIndices,
const ColIndices& colIndices) {
IvcRowType<RowIndices> actualRowIndices = derived.ivcRow(rowIndices);
IvcColType<ColIndices> actualColIndices = derived.ivcCol(colIndices);
return ConstReturnType(derived, internal::first(actualRowIndices), internal::first(actualColIndices),
internal::index_list_size(actualRowIndices), internal::index_list_size(actualColIndices));
}
};
// Symbolic
template <typename RowIndices, typename ColIndices>
struct IndexedViewSelector<RowIndices, ColIndices, true, false, false> {
using ReturnType = typename DenseBase<Derived>::Scalar&;
using ConstReturnType = typename DenseBase<Derived>::CoeffReturnType;
static inline ReturnType run(Derived& derived, const RowIndices& rowIndices, const ColIndices& colIndices) {
return derived(internal::eval_expr_given_size(rowIndices, derived.rows()),
internal::eval_expr_given_size(colIndices, derived.cols()));
}
static inline ConstReturnType run(const Derived& derived, const RowIndices& rowIndices,
const ColIndices& colIndices) {
return derived(internal::eval_expr_given_size(rowIndices, derived.rows()),
internal::eval_expr_given_size(colIndices, derived.cols()));
}
};
// this helper class assumes internal::is_valid_index_type<Indices>::value == false
template <typename Indices,
bool UseSymbolic = symbolic::is_symbolic<Indices>::value,
bool UseBlock = !UseSymbolic && internal::get_compile_time_incr<IvcType<Indices>>::value == 1,
bool UseGeneric = !UseSymbolic && !UseBlock>
struct VectorIndexedViewSelector;
// Generic
template <typename Indices>
struct VectorIndexedViewSelector<Indices, false, false, true> {
static constexpr bool IsRowMajor = DenseBase<Derived>::IsRowMajor;
using RowMajorReturnType = IndexedView<Derived, IvcIndex, IvcType<Indices>>;
using ConstRowMajorReturnType = IndexedView<const Derived, IvcIndex, IvcType<Indices>>;
using ColMajorReturnType = IndexedView<Derived, IvcType<Indices>, IvcIndex>;
using ConstColMajorReturnType = IndexedView<const Derived, IvcType<Indices>, IvcIndex>;
using ReturnType = typename internal::conditional<IsRowMajor, RowMajorReturnType, ColMajorReturnType>::type;
using ConstReturnType =
typename internal::conditional<IsRowMajor, ConstRowMajorReturnType, ConstColMajorReturnType>::type;
template <bool UseRowMajor = IsRowMajor, std::enable_if_t<UseRowMajor, bool> = true>
static inline RowMajorReturnType run(Derived& derived, const Indices& indices) {
return RowMajorReturnType(derived, IvcIndex(0), derived.ivcCol(indices));
}
template <bool UseRowMajor = IsRowMajor, std::enable_if_t<UseRowMajor, bool> = true>
static inline ConstRowMajorReturnType run(const Derived& derived, const Indices& indices) {
return ConstRowMajorReturnType(derived, IvcIndex(0), derived.ivcCol(indices));
}
template <bool UseRowMajor = IsRowMajor, std::enable_if_t<!UseRowMajor, bool> = true>
static inline ColMajorReturnType run(Derived& derived, const Indices& indices) {
return ColMajorReturnType(derived, derived.ivcRow(indices), IvcIndex(0));
}
template <bool UseRowMajor = IsRowMajor, std::enable_if_t<!UseRowMajor, bool> = true>
static inline ConstColMajorReturnType run(const Derived& derived, const Indices& indices) {
return ConstColMajorReturnType(derived, derived.ivcRow(indices), IvcIndex(0));
}
};
// Block
template <typename Indices>
struct VectorIndexedViewSelector<Indices, false, true, false> {
using ReturnType = VectorBlock<Derived, internal::array_size<Indices>::value>;
using ConstReturnType = VectorBlock<const Derived, internal::array_size<Indices>::value>;
static inline ReturnType run(Derived& derived, const Indices& indices) {
IvcType<Indices> actualIndices = derived.ivcSize(indices);
return ReturnType(derived, internal::first(actualIndices), internal::index_list_size(actualIndices));
}
static inline ConstReturnType run(const Derived& derived, const Indices& indices) {
IvcType<Indices> actualIndices = derived.ivcSize(indices);
return ConstReturnType(derived, internal::first(actualIndices), internal::index_list_size(actualIndices));
}
};
// Symbolic
template <typename Indices>
struct VectorIndexedViewSelector<Indices, true, false, false> {
using ReturnType = typename DenseBase<Derived>::Scalar&;
using ConstReturnType = typename DenseBase<Derived>::CoeffReturnType;
static inline ReturnType run(Derived& derived, const Indices& id) {
return derived(internal::eval_expr_given_size(id, derived.size()));
}
static inline ConstReturnType run(const Derived& derived, const Indices& id) {
return derived(internal::eval_expr_given_size(id, derived.size()));
}
};
// SFINAE dummy types
template <typename RowIndices, typename ColIndices>
using EnableOverload = std::enable_if_t<
internal::valid_indexed_view_overload<RowIndices, ColIndices>::value && internal::is_lvalue<Derived>::value, bool>;
template <typename RowIndices, typename ColIndices>
using EnableConstOverload =
std::enable_if_t<internal::valid_indexed_view_overload<RowIndices, ColIndices>::value, bool>;
template <typename Indices>
using EnableVectorOverload =
std::enable_if_t<!internal::is_valid_index_type<Indices>::value && internal::is_lvalue<Derived>::value, bool>;
template <typename Indices>
using EnableConstVectorOverload = std::enable_if_t<!internal::is_valid_index_type<Indices>::value, bool>;
public:
template <typename RowIndices, typename ColIndices>
using IndexedViewType = IndexedView<Derived, IvcRowType<RowIndices>, IvcColType<ColIndices>>;
// Public API for 2D matrices/arrays
// non-const versions
template <typename RowIndices, typename ColIndices>
using ConstIndexedViewType = IndexedView<const Derived, IvcRowType<RowIndices>, IvcColType<ColIndices>>;
using IndexedViewType = typename IndexedViewSelector<RowIndices, ColIndices>::ReturnType;
// This is the generic version
template <typename RowIndices, typename ColIndices>
std::enable_if_t<internal::valid_indexed_view_overload<RowIndices, ColIndices>::value &&
internal::traits<IndexedViewType<RowIndices, ColIndices>>::ReturnAsIndexedView,
IndexedViewType<RowIndices, ColIndices>>
operator()(const RowIndices& rowIndices, const ColIndices& colIndices) {
return IndexedViewType<RowIndices, ColIndices>(derived(), ivcRow(rowIndices), ivcCol(colIndices));
template <typename RowIndices, typename ColIndices, EnableOverload<RowIndices, ColIndices> = true>
IndexedViewType<RowIndices, ColIndices> operator()(const RowIndices& rowIndices, const ColIndices& colIndices) {
return IndexedViewSelector<RowIndices, ColIndices>::run(derived(), rowIndices, colIndices);
}
template <typename RowIndices, typename ColIndices>
std::enable_if_t<internal::valid_indexed_view_overload<RowIndices, ColIndices>::value &&
internal::traits<ConstIndexedViewType<RowIndices, ColIndices>>::ReturnAsIndexedView,
ConstIndexedViewType<RowIndices, ColIndices>>
operator()(const RowIndices& rowIndices, const ColIndices& colIndices) const {
return ConstIndexedViewType<RowIndices, ColIndices>(derived(), ivcRow(rowIndices), ivcCol(colIndices));
template <typename RowType, size_t RowSize, typename ColIndices, typename RowIndices = Array<RowType, RowSize, 1>,
EnableOverload<RowIndices, ColIndices> = true>
IndexedViewType<RowIndices, ColIndices> operator()(const RowType (&rowIndices)[RowSize], const ColIndices& colIndices) {
return IndexedViewSelector<RowIndices, ColIndices>::run(derived(), RowIndices{rowIndices}, colIndices);
}
// The following overload returns a Block<> object
template <typename RowIndices, typename ColIndices>
std::enable_if_t<internal::valid_indexed_view_overload<RowIndices, ColIndices>::value &&
internal::traits<IndexedViewType<RowIndices, ColIndices>>::ReturnAsBlock,
typename internal::traits<IndexedViewType<RowIndices, ColIndices>>::BlockType>
operator()(const RowIndices& rowIndices, const ColIndices& colIndices) {
typedef typename internal::traits<IndexedViewType<RowIndices, ColIndices>>::BlockType BlockType;
IvcRowType<RowIndices> actualRowIndices = ivcRow(rowIndices);
IvcColType<ColIndices> actualColIndices = ivcCol(colIndices);
return BlockType(derived(), internal::first(actualRowIndices), internal::first(actualColIndices),
internal::index_list_size(actualRowIndices), internal::index_list_size(actualColIndices));
template <typename RowIndices, typename ColType, size_t ColSize, typename ColIndices = Array<ColType, ColSize, 1>,
EnableOverload<RowIndices, ColIndices> = true>
IndexedViewType<RowIndices, ColIndices> operator()(const RowIndices& rowIndices, const ColType (&colIndices)[ColSize]) {
return IndexedViewSelector<RowIndices, ColIndices>::run(derived(), rowIndices, ColIndices{colIndices});
}
template <typename RowIndices, typename ColIndices>
std::enable_if_t<internal::valid_indexed_view_overload<RowIndices, ColIndices>::value &&
internal::traits<ConstIndexedViewType<RowIndices, ColIndices>>::ReturnAsBlock,
typename internal::traits<ConstIndexedViewType<RowIndices, ColIndices>>::BlockType>
operator()(const RowIndices& rowIndices, const ColIndices& colIndices) const {
typedef typename internal::traits<ConstIndexedViewType<RowIndices, ColIndices>>::BlockType BlockType;
IvcRowType<RowIndices> actualRowIndices = ivcRow(rowIndices);
IvcColType<ColIndices> actualColIndices = ivcCol(colIndices);
return BlockType(derived(), internal::first(actualRowIndices), internal::first(actualColIndices),
internal::index_list_size(actualRowIndices), internal::index_list_size(actualColIndices));
template <typename RowType, size_t RowSize, typename ColType, size_t ColSize,
typename RowIndices = Array<RowType, RowSize, 1>, typename ColIndices = Array<ColType, ColSize, 1>,
EnableOverload<RowIndices, ColIndices> = true>
IndexedViewType<RowIndices, ColIndices> operator()(const RowType (&rowIndices)[RowSize],
const ColType (&colIndices)[ColSize]) {
return IndexedViewSelector<RowIndices, ColIndices>::run(derived(), RowIndices{rowIndices}, ColIndices{colIndices});
}
// The following overload returns a Scalar
// const versions
template <typename RowIndices, typename ColIndices>
std::enable_if_t<internal::valid_indexed_view_overload<RowIndices, ColIndices>::value &&
internal::traits<IndexedViewType<RowIndices, ColIndices>>::ReturnAsScalar && internal::is_lvalue<Derived>::value,
Scalar&>
operator()(const RowIndices& rowIndices, const ColIndices& colIndices) {
return Base::operator()(internal::eval_expr_given_size(rowIndices, rows()),
internal::eval_expr_given_size(colIndices, cols()));
using ConstIndexedViewType = typename IndexedViewSelector<RowIndices, ColIndices>::ConstReturnType;
template <typename RowIndices, typename ColIndices, EnableConstOverload<RowIndices, ColIndices> = true>
ConstIndexedViewType<RowIndices, ColIndices> operator()(const RowIndices& rowIndices,
const ColIndices& colIndices) const {
return IndexedViewSelector<RowIndices, ColIndices>::run(derived(), rowIndices, colIndices);
}
template <typename RowIndices, typename ColIndices>
std::enable_if_t<internal::valid_indexed_view_overload<RowIndices, ColIndices>::value &&
internal::traits<ConstIndexedViewType<RowIndices, ColIndices>>::ReturnAsScalar,
CoeffReturnType>
operator()(const RowIndices& rowIndices, const ColIndices& colIndices) const {
return Base::operator()(internal::eval_expr_given_size(rowIndices, rows()),
internal::eval_expr_given_size(colIndices, cols()));
template <typename RowType, size_t RowSize, typename ColIndices, typename RowIndices = Array<RowType, RowSize, 1>,
EnableConstOverload<RowIndices, ColIndices> = true>
ConstIndexedViewType<RowIndices, ColIndices> operator()(const RowType (&rowIndices)[RowSize],
const ColIndices& colIndices) const {
return IndexedViewSelector<RowIndices, ColIndices>::run(derived(), RowIndices{rowIndices}, colIndices);
}
// Overloads for 1D vectors/arrays
template <typename RowIndices, typename ColType, size_t ColSize, typename ColIndices = Array<ColType, ColSize, 1>,
EnableConstOverload<RowIndices, ColIndices> = true>
ConstIndexedViewType<RowIndices, ColIndices> operator()(const RowIndices& rowIndices,
const ColType (&colIndices)[ColSize]) const {
return IndexedViewSelector<RowIndices, ColIndices>::run(derived(), rowIndices, ColIndices{colIndices});
}
template <typename RowType, size_t RowSize, typename ColType, size_t ColSize,
typename RowIndices = Array<RowType, RowSize, 1>, typename ColIndices = Array<ColType, ColSize, 1>,
EnableConstOverload<RowIndices, ColIndices> = true>
ConstIndexedViewType<RowIndices, ColIndices> operator()(const RowType (&rowIndices)[RowSize],
const ColType (&colIndices)[ColSize]) const {
return IndexedViewSelector<RowIndices, ColIndices>::run(derived(), RowIndices{rowIndices}, ColIndices{colIndices});
}
// Public API for 1D vectors/arrays
// non-const versions
template <typename Indices>
std::enable_if_t<IsRowMajor && (!(internal::get_compile_time_incr<IvcType<Indices>>::value == 1 ||
internal::is_valid_index_type<Indices>::value)),
IndexedView<Derived, IvcIndex, IvcType<Indices>>>
operator()(const Indices& indices) {
using VectorIndexedViewType = typename VectorIndexedViewSelector<Indices>::ReturnType;
template <typename Indices, EnableVectorOverload<Indices> = true>
VectorIndexedViewType<Indices> operator()(const Indices& indices) {
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return IndexedView<Derived, IvcIndex, IvcType<Indices>>(derived(), IvcIndex(0), ivcCol(indices));
return VectorIndexedViewSelector<Indices>::run(derived(), indices);
}
template <typename IndexType, size_t Size, typename Indices = Array<IndexType, Size, 1>,
EnableVectorOverload<Indices> = true>
VectorIndexedViewType<Indices> operator()(const IndexType (&indices)[Size]) {
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return VectorIndexedViewSelector<Indices>::run(derived(), Indices{indices});
}
// const versions
template <typename Indices>
std::enable_if_t<IsRowMajor && (!(internal::get_compile_time_incr<IvcType<Indices>>::value == 1 ||
internal::is_valid_index_type<Indices>::value)),
IndexedView<const Derived, IvcIndex, IvcType<Indices>>>
operator()(const Indices& indices) const {
using ConstVectorIndexedViewType = typename VectorIndexedViewSelector<Indices>::ConstReturnType;
template <typename Indices, EnableConstVectorOverload<Indices> = true>
ConstVectorIndexedViewType<Indices> operator()(const Indices& indices) const {
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return IndexedView<const Derived, IvcIndex, IvcType<Indices>>(derived(), IvcIndex(0), ivcCol(indices));
return VectorIndexedViewSelector<Indices>::run(derived(), indices);
}
template <typename Indices>
std::enable_if_t<(!IsRowMajor) && (!(internal::get_compile_time_incr<IvcType<Indices>>::value == 1 ||
internal::is_valid_index_type<Indices>::value)),
IndexedView<Derived, IvcType<Indices>, IvcIndex>>
operator()(const Indices& indices) {
template <typename IndexType, size_t Size, typename Indices = Array<IndexType, Size, 1>,
EnableConstVectorOverload<Indices> = true>
ConstVectorIndexedViewType<Indices> operator()(const IndexType (&indices)[Size]) const {
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return IndexedView<Derived, IvcType<Indices>, IvcIndex>(derived(), ivcRow(indices), IvcIndex(0));
}
template <typename Indices>
std::enable_if_t<(!IsRowMajor) && (!(internal::get_compile_time_incr<IvcType<Indices>>::value == 1 ||
internal::is_valid_index_type<Indices>::value)),
IndexedView<const Derived, IvcType<Indices>, IvcIndex>>
operator()(const Indices& indices) const {
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return IndexedView<const Derived, IvcType<Indices>, IvcIndex>(derived(), ivcRow(indices), IvcIndex(0));
}
template <typename Indices>
std::enable_if_t<(internal::get_compile_time_incr<IvcType<Indices>>::value == 1) &&
(!internal::is_valid_index_type<Indices>::value) && (!symbolic::is_symbolic<Indices>::value),
VectorBlock<Derived, internal::array_size<Indices>::value>>
operator()(const Indices& indices) {
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
IvcType<Indices> actualIndices = ivcSize(indices);
return VectorBlock<Derived, internal::array_size<Indices>::value>(derived(), internal::first(actualIndices),
internal::index_list_size(actualIndices));
}
template <typename Indices>
std::enable_if_t<(internal::get_compile_time_incr<IvcType<Indices>>::value == 1) &&
(!internal::is_valid_index_type<Indices>::value) && (!symbolic::is_symbolic<Indices>::value),
VectorBlock<const Derived, internal::array_size<Indices>::value>>
operator()(const Indices& indices) const {
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
IvcType<Indices> actualIndices = ivcSize(indices);
return VectorBlock<const Derived, internal::array_size<Indices>::value>(derived(), internal::first(actualIndices),
internal::index_list_size(actualIndices));
}
template <typename IndexType>
std::enable_if_t<symbolic::is_symbolic<IndexType>::value && internal::is_lvalue<Derived>::value, Scalar&> operator()(const IndexType& id) {
return Base::operator()(internal::eval_expr_given_size(id, size()));
}
template <typename IndexType>
std::enable_if_t<symbolic::is_symbolic<IndexType>::value, CoeffReturnType> operator()(const IndexType& id) const {
return Base::operator()(internal::eval_expr_given_size(id, size()));
return VectorIndexedViewSelector<Indices>::run(derived(), Indices{indices});
}
#else // EIGEN_PARSED_BY_DOXYGEN