From 8249af7a43ef24ada70caf7b2eb6c12bfd17238a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Gr=C3=BCtzmacher?= Date: Fri, 5 Feb 2021 06:25:35 +0100 Subject: [PATCH 1/7] Extend row_major accessor for arbitrary dimensions --- core/test/base/range_accessors.cpp | 140 ++++++ include/ginkgo/core/base/range_accessors.hpp | 437 ++++++++++++++++++- 2 files changed, 571 insertions(+), 6 deletions(-) diff --git a/core/test/base/range_accessors.cpp b/core/test/base/range_accessors.cpp index eecac4ae60f..7c0a104822e 100644 --- a/core/test/base/range_accessors.cpp +++ b/core/test/base/range_accessors.cpp @@ -62,6 +62,35 @@ class RowMajorAccessor : public ::testing::Test { }; +TEST_F(RowMajorAccessor, CanCreateWithDim) +{ + row_major_int_range r2{data, gko::dim<2>{3, 2}, 3u}; + + EXPECT_EQ(r2(0, 0), 1); + EXPECT_EQ(r2(0, 1), 2); + EXPECT_EQ(r2(1, 0), 3); + EXPECT_EQ(r2(1, 1), 4); + EXPECT_EQ(r2(2, 0), 5); + EXPECT_EQ(r2(2, 1), 6); +} + + +TEST_F(RowMajorAccessor, CanCreateDefaultStride) +{ + row_major_int_range r2{data, gko::dim<2>{3, 3}}; + + EXPECT_EQ(r2(0, 0), 1); + EXPECT_EQ(r2(0, 1), 2); + EXPECT_EQ(r2(0, 2), -1); + EXPECT_EQ(r2(1, 0), 3); + EXPECT_EQ(r2(1, 1), 4); + EXPECT_EQ(r2(1, 2), -2); + EXPECT_EQ(r2(2, 0), 5); + EXPECT_EQ(r2(2, 1), 6); + EXPECT_EQ(r2(2, 2), -3); +} + + TEST_F(RowMajorAccessor, CanAccessData) { EXPECT_EQ(r(0, 0), 1); @@ -135,4 +164,115 @@ TEST_F(RowMajorAccessor, CanAssignSubranges) } +class RowMajorAccessor3d : public ::testing::Test { +protected: + using span = gko::span; + static constexpr gko::size_type dimensionality{3}; + + using row_major_int_range = + gko::range>; + + // clang-format off + int data[2 * 3 * 4]{ + 1, 2, -1, 11, + 3, 4, -2, 12, + 5, 6, -3, 13, + + 21, 22, 23, 24, + 25, 26, 27, 28, + 29, 30, 31, 32 + }; + // clang-format on + const gko::dim dim1{2, 3, 4}; + const gko::dim dim2{2, 2, 3}; + row_major_int_range default_r{data, dim1}; + row_major_int_range custom_r{ + data, dim2, + std::array{12, 4}}; +}; + + +TEST_F(RowMajorAccessor3d, CanAccessData) +{ + EXPECT_EQ(default_r(0, 0, 0), 1); + EXPECT_EQ(custom_r(0, 0, 0), 1); + EXPECT_EQ(default_r(0, 1, 0), 3); + EXPECT_EQ(custom_r(0, 1, 0), 3); + EXPECT_EQ(default_r(0, 1, 3), 12); + EXPECT_EQ(default_r(0, 2, 2), -3); + EXPECT_EQ(default_r(1, 2, 1), 30); + EXPECT_EQ(default_r(1, 2, 2), 31); + EXPECT_EQ(default_r(1, 2, 3), 32); +} + + +TEST_F(RowMajorAccessor3d, CanWriteData) +{ + default_r(0, 0, 0) = 4; + custom_r(1, 1, 1) = 100; + + EXPECT_EQ(default_r(0, 0, 0), 4); + EXPECT_EQ(custom_r(0, 0, 0), 4); + EXPECT_EQ(default_r(1, 1, 1), 100); + EXPECT_EQ(custom_r(1, 1, 1), 100); +} + + +TEST_F(RowMajorAccessor3d, CanCreateSubrange) +{ + auto subr = custom_r(span{0, 2}, span{1, 2}, span{1, 3}); + + EXPECT_EQ(subr(0, 0, 0), 4); + EXPECT_EQ(subr(0, 0, 1), -2); + EXPECT_EQ(subr(1, 0, 0), 26); + EXPECT_EQ(subr(1, 0, 1), 27); +} + + +TEST_F(RowMajorAccessor3d, CanCreateRowVector) +{ + auto subr = default_r(1u, 2u, span{0, 2}); + + EXPECT_EQ(subr(0, 0, 0), 29); + EXPECT_EQ(subr(0, 0, 1), 30); +} + + +TEST_F(RowMajorAccessor3d, CanCreateColumnVector) +{ + auto subr = default_r(span{0u, 2u}, 1u, 3u); + + EXPECT_EQ(subr(0, 0, 0), 12); + EXPECT_EQ(subr(1, 0, 0), 28); +} + + +TEST_F(RowMajorAccessor3d, CanAssignValues) +{ + default_r(1, 1, 1) = default_r(0, 0, 0); + + EXPECT_EQ(data[17], 1); +} + + +TEST_F(RowMajorAccessor3d, CanAssignSubranges) +{ + default_r(1u, span{0, 2}, span{0, 3}) = + custom_r(0u, span{0, 2}, span{0, 3}); + + EXPECT_EQ(data[12], 1); + EXPECT_EQ(data[13], 2); + EXPECT_EQ(data[14], -1); + EXPECT_EQ(data[15], 24); + EXPECT_EQ(data[16], 3); + EXPECT_EQ(data[17], 4); + EXPECT_EQ(data[18], -2); + EXPECT_EQ(data[19], 28); + EXPECT_EQ(data[20], 29); + EXPECT_EQ(data[21], 30); + EXPECT_EQ(data[22], 31); + EXPECT_EQ(data[23], 32); +} + + } // namespace diff --git a/include/ginkgo/core/base/range_accessors.hpp b/include/ginkgo/core/base/range_accessors.hpp index f4fd01247d4..b0528956b38 100644 --- a/include/ginkgo/core/base/range_accessors.hpp +++ b/include/ginkgo/core/base/range_accessors.hpp @@ -35,8 +35,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include +#include +#include #include #include @@ -50,6 +52,228 @@ namespace gko { namespace accessor { +namespace detail { + + +/** + * This helper runs from first to last dimension in order to compute the index. + * The index is computed like this: + * indices: x1, x2, x3, ... + * compute(stride, x1, x2, x3) -> x1 * stride[0] + x2 * stride[1] + x3 + */ +template +struct row_major_helper_s { + static_assert(total_dim >= 1, "Dimensionality must be >= 1"); + static_assert(current_iter < total_dim, "Iteration must be < total_dim!"); + + static constexpr size_type dim_idx{current_iter - 1}; + + template + static constexpr GKO_ATTRIBUTES ValueType + compute(const std::array &size, + const std::array 1 ? total_dim - 1 : 0)> + &stride, + FirstType first, Indices &&...idxs) + { + return GKO_ASSERT(first < size[dim_idx]), + first * stride[dim_idx] + + row_major_helper_s:: + compute(size, stride, std::forward(idxs)...); + } +}; + +template +struct row_major_helper_s { + template + static constexpr GKO_ATTRIBUTES ValueType + compute(const std::array &size, + const std::array 1 ? total_dim - 1 : 0)>, + FirstType first) + { + return GKO_ASSERT(first < size[total_dim - 1]), first; + } +}; + + +/** + * Computes the storage index for the given indices with respect to the given + * stride array + */ +template +constexpr GKO_ATTRIBUTES ValueType compute_storage_index( + const std::array &size, + const std::array 1 ? total_dim - 1 : 0)> &stride, + Indices &&...idxs) +{ + return row_major_helper_s::compute( + size, stride, std::forward(idxs)...); +} + + +template +constexpr GKO_ATTRIBUTES std::enable_if_t spans_in_size( + const std::array &) +{ + return 0; +} + +template +constexpr GKO_ATTRIBUTES std::enable_if_t<(iter < N), int> spans_in_size( + const std::array &size, First first, Remaining &&...remaining) +{ + static_assert(sizeof...(Remaining) + 1 == N - iter, + "Number of remaining spans must be equal to N - iter"); + return GKO_ASSERT(span{first}.is_valid()), + GKO_ASSERT(span{first} <= span{size[iter]}), + spans_in_size(size, std::forward(remaining)...); +} + + +template +constexpr GKO_ATTRIBUTES int validate_spans( + const std::array &size, Spans &&...spans) +{ + return detail::spans_in_size<0>(size, std::forward(spans)...); +} + + +template +struct are_span_compatible_impl + : public std::integral_constant {}; + +template +struct are_span_compatible_impl + : public std::conditional< + std::is_integral>::value || + std::is_same, span>::value, + are_span_compatible_impl< + has_span || std::is_same, span>::value, + Args...>, + std::false_type>::type {}; + + +/** + * Evaluates if at least one type of Args is a gko::span and the others either + * also gko::span or fulfill std::is_integral + */ +template +using are_span_compatible = are_span_compatible_impl; + + +template +constexpr GKO_ATTRIBUTES + std::enable_if_t<(current == N), std::array> + to_array_impl(const dim &size, Dims &&...dims) +{ + static_assert(sizeof...(Dims) == N, + "Number of arguments must match dimensionality!"); + return {{std::forward(dims)...}}; +} + + +template +constexpr GKO_ATTRIBUTES + std::enable_if_t<(current < N), std::array> + to_array_impl(const dim &size, Dims &&...dims) +{ + return to_array_impl( + size, std::forward(dims)..., size[current]); +} + + +template +constexpr GKO_ATTRIBUTES std::array to_array(const dim &size) +{ + return to_array_impl(size); +} + + +template +constexpr GKO_ATTRIBUTES std::enable_if_t +mult_dim_upwards_impl(const std::array &) +{ + return 1; +} + +template +constexpr GKO_ATTRIBUTES std::enable_if_t<(iter < N), ValueType> +mult_dim_upwards_impl(const std::array &size) +{ + return size[iter] * mult_dim_upwards_impl(size); +} + + +template +constexpr GKO_ATTRIBUTES + std::enable_if_t> + compute_default_stride_array_impl(const std::array &, + Args &&...args) +{ + return {{std::forward(args)...}}; +} + +template +constexpr GKO_ATTRIBUTES std::enable_if_t< + (iter < N) && (iter == sizeof...(Args) + 1), std::array> +compute_default_stride_array_impl(const std::array &size, + Args &&...args) +{ + return compute_default_stride_array_impl( + size, std::forward(args)..., mult_dim_upwards_impl(size)); +} + + +template +constexpr GKO_ATTRIBUTES + std::array 0 ? dimensions - 1 : 0)> + compute_default_stride_array(const std::array &size) +{ + return compute_default_stride_array_impl(size); +} + + +template +GKO_ATTRIBUTES std::enable_if_t multidim_for_each_impl( + const std::array &, Callable callable, Indices &&...indices) +{ + static_assert(iter == sizeof...(Indices), + "Number arguments must match current iteration!"); + callable(std::forward(indices)...); +} + +template +GKO_ATTRIBUTES std::enable_if_t<(iter < N)> multidim_for_each_impl( + const std::array &size, Callable &&callable, + Indices &&...indices) +{ + static_assert(iter == sizeof...(Indices), + "Number arguments must match current iteration!"); + for (size_type i = 0; i < size[iter]; ++i) { + multidim_for_each_impl(size, std::forward(callable), + std::forward(indices)..., i); + } +} + + +/** + * Creates a recursive for-loop for each dimension and calls dest(indices...) = + * source(indices...) + */ +template +GKO_ATTRIBUTES void multidim_for_each(const std::array &size, + Callable &&callable) +{ + multidim_for_each_impl<0>(size, std::forward(callable)); +} + + +} // namespace detail + + /** * A row_major accessor is a bridge between a range and the row-major memory * layout. @@ -59,19 +283,20 @@ namespace accessor { * constructor parameters for this class to the range (it will forward it to * this class). * - * @warning The current implementation is incomplete, and only allows for - * 2-dimensional ranges. + * @warning For backward compatability reasons, a specialization is provided + * for dimensionality == 2. * * @tparam ValueType type of values this accessor returns - * @tparam Dimensionality number of dimensions of this accessor (has to be 2) + * @tparam Dimensionality number of dimensions of this accessor */ template class row_major { public: friend class range; - static_assert(Dimensionality == 2, - "This accessor is only implemented for matrices"); + static_assert(Dimensionality != 0, + "This accessor does not support a dimensionality of 0!"); + static constexpr size_type dimensionality = Dimensionality; /** * Type of values returned by the accessor. @@ -86,9 +311,179 @@ class row_major { /** * Number of dimensions of the accessor. */ - static constexpr size_type dimensionality = 2; using const_accessor = row_major; + using stride_type = std::array; + using length_type = std::array; + +protected: + /** + * Creates a row_major accessor. + * + * @param data pointer to the block of memory containing the data + * @param lengths size / length of the accesses of each dimension + * @param stride distance (in elements) between starting positions of + * the dimensions (i.e. + * `x_1 * stride_1 + x_2 * stride_2 * ... + x_n` + * points to the element at (x_1, x_2, ..., x_n)) + */ + constexpr GKO_ATTRIBUTES explicit row_major(data_type data, + dim size, + stride_type stride) + : data{data}, + lengths{detail::to_array(size)}, + stride{stride} + {} + + /** + * Creates a row_major accessor with a default stride (assumes no padding) + * + * @param data pointer to the block of memory containing the data + * @param lengths size / length of the accesses of each dimension + */ + constexpr GKO_ATTRIBUTES explicit row_major(data_type data, + dim size) + : data{data}, + lengths{detail::to_array(size)}, + stride{detail::compute_default_stride_array(lengths)} + {} + +public: + /** + * Creates a row_major range which contains a read-only version of the + * current accessor. + * + * @returns a row major range which is read-only. + */ + constexpr GKO_ATTRIBUTES range to_const() const + { + // TODO Remove this functionality all together (if requested) + return range(data, lengths, stride); + } + + /** + * Returns the data element at the specified indices + * + * @param row row index + * @param col column index + * + * @return data element at (indices...) + */ + template + constexpr GKO_ATTRIBUTES + std::enable_if_t::value, value_type &> + operator()(Indices &&...indices) const + { + return data[detail::compute_storage_index( + lengths, stride, std::forward(indices)...)]; + } + + /** + * Returns the sub-range spanning the range (x1_span, x2_span, ...) + * + * @param rows row span + * @param cols column span + * + * @return sub-range spanning the given spans + */ + template + constexpr GKO_ATTRIBUTES std::enable_if_t< + detail::are_span_compatible::value, range> + operator()(SpanTypes... spans) const + { + return detail::validate_spans(lengths, spans...), + range{ + data + detail::compute_storage_index(lengths, stride, + (span{spans}.begin)...), + dim{ + (span{spans}.end - span{spans}.begin)...}, + stride}; + } + + /** + * Returns the length in dimension `dimension`. + * + * @param dimension a dimension index + * + * @return length in dimension `dimension` + */ + constexpr GKO_ATTRIBUTES size_type length(size_type dimension) const + { + return lengths[dimension]; + } + + /** + * Copies data from another accessor + * + * @warning Do not use this function since it is not optimized for a + * specific executor. It will always be performed sequentially. + * Please write an optimized version (adjusted to the architecture) + * by iterating through the values yourself. + * + * @tparam OtherAccessor type of the other accessor + * + * @param other other accessor + */ + template + GKO_ATTRIBUTES void copy_from(const OtherAccessor &other) const + { + detail::multidim_for_each(lengths, [this, &other](auto... indices) { + (*this)(indices...) = other(indices...); + }); + } + + /** + * Reference to the underlying data. + */ + const data_type data; + + /** + * An array of dimension sizes. + */ + const length_type lengths; + + /** + * Distance between consecutive rows for each dimension (except the first). + */ + const stride_type stride; +}; + + +/** + * A row_major accessor is a bridge between a range and the row-major memory + * layout. + * + * You should never try to explicitly create an instance of this accessor. + * Instead, supply it as a template parameter to a range, and pass the + * constructor parameters for this class to the range (it will forward it to + * this class). + * + * @note This is the original implementation, which is now the specialization + * for Dimensionality = 2. + * + * @tparam ValueType type of values this accessor returns + */ +template +class row_major { +public: + friend class range; + static constexpr size_type dimensionality = 2; + + /** + * Type of values returned by the accessor. + */ + using value_type = ValueType; + + /** + * Type of underlying data storage. + */ + using data_type = value_type *; + + /** + * Number of dimensions of the accessor. + */ + + using const_accessor = row_major; protected: /** @@ -108,6 +503,36 @@ class row_major { : data{data}, lengths{num_rows, num_cols}, stride{stride} {} + /** + * Creates a row_major accessor. + * + * @param data pointer to the block of memory containing the data + * @param lengths size / length of the accesses of each dimension + * @param stride distance (in elements) between starting positions of + * consecutive rows (i.e. `data + i * stride` points to + * the `i`-th row) + */ + constexpr GKO_ATTRIBUTES explicit row_major(data_type data, + dim size, + size_type stride) + : data{data}, + lengths{detail::to_array(size)}, + stride{stride} + {} + + /** + * Creates a row_major accessor with a default stride (assumes no padding) + * + * @param data pointer to the block of memory containing the data + * @param lengths size / length of the accesses of each dimension + */ + constexpr GKO_ATTRIBUTES explicit row_major(data_type data, + dim size) + : data{data}, + lengths{detail::to_array(size)}, + stride{size[1]} + {} + public: /** * Creates a row_major range which contains a read-only version of the From a8925bf25b9b61fce7785ed19c7b35403c943566 Mon Sep 17 00:00:00 2001 From: Aditya Kashi Date: Thu, 18 Feb 2021 15:56:39 +0100 Subject: [PATCH 2/7] added multidimensional column-major accessor and tests --- core/test/base/range_accessors.cpp | 133 ++++++++ include/ginkgo/core/base/range_accessors.hpp | 320 ++++++++++++++++++- 2 files changed, 442 insertions(+), 11 deletions(-) diff --git a/core/test/base/range_accessors.cpp b/core/test/base/range_accessors.cpp index 7c0a104822e..0694541278b 100644 --- a/core/test/base/range_accessors.cpp +++ b/core/test/base/range_accessors.cpp @@ -275,4 +275,137 @@ TEST_F(RowMajorAccessor3d, CanAssignSubranges) } +class ColMajorAccessor3d : public ::testing::Test { +protected: + using span = gko::span; + static constexpr gko::size_type dimensionality{3}; + + using col_major_range = + gko::range>; + + // clang-format off + int data[2 * 3 * 4]{ + 1, 3, 5, + 2, 4, 6, + -1,-2,-3, + 11,12,13, + + 21,25,29, + 22,26,30, + 23,27,31, + 24,28,32 + + /* This matrix actually looks like + 1, 2, -1, 11, + 3, 4, -2, 12, + 5, 6, -3, 13, + + 21, 22, 23, 24, + 25, 26, 27, 28, + 29, 30, 31, 32 + */ + }; + // clang-format on + const gko::dim dim1{2, 3, 4}; + const gko::dim dim2{2, 2, 3}; + col_major_range default_r{data, dim1}; + col_major_range custom_r{ + data, dim2, + std::array{12, 3}}; +}; + + +TEST_F(ColMajorAccessor3d, ComputesCorrectStride) +{ + auto range_stride = default_r.get_accessor().stride; + auto check_stride = std::array{12, 3}; + + ASSERT_EQ(range_stride, check_stride); +} + + +TEST_F(ColMajorAccessor3d, CanAccessData) +{ + EXPECT_EQ(default_r(0, 0, 0), 1); + EXPECT_EQ(custom_r(0, 0, 0), 1); + EXPECT_EQ(default_r(0, 1, 0), 3); + EXPECT_EQ(custom_r(0, 1, 0), 3); + EXPECT_EQ(default_r(0, 1, 1), 4); + EXPECT_EQ(default_r(0, 1, 3), 12); + EXPECT_EQ(default_r(0, 2, 2), -3); + EXPECT_EQ(default_r(1, 2, 1), 30); + EXPECT_EQ(default_r(1, 2, 2), 31); + EXPECT_EQ(default_r(1, 2, 3), 32); +} + + +TEST_F(ColMajorAccessor3d, CanWriteData) +{ + default_r(0, 0, 0) = 4; + custom_r(1, 1, 1) = 100; + + EXPECT_EQ(default_r(0, 0, 0), 4); + EXPECT_EQ(custom_r(0, 0, 0), 4); + EXPECT_EQ(default_r(1, 1, 1), 100); + EXPECT_EQ(custom_r(1, 1, 1), 100); +} + + +TEST_F(ColMajorAccessor3d, CanCreateSubrange) +{ + auto subr = custom_r(span{0, 2}, span{1, 2}, span{1, 3}); + + EXPECT_EQ(subr(0, 0, 0), 4); + EXPECT_EQ(subr(0, 0, 1), -2); + EXPECT_EQ(subr(1, 0, 0), 26); + EXPECT_EQ(subr(1, 0, 1), 27); +} + + +TEST_F(ColMajorAccessor3d, CanCreateRowVector) +{ + auto subr = default_r(1u, 2u, span{0, 2}); + + EXPECT_EQ(subr(0, 0, 0), 29); + EXPECT_EQ(subr(0, 0, 1), 30); +} + + +TEST_F(ColMajorAccessor3d, CanCreateColumnVector) +{ + auto subr = default_r(span{0u, 2u}, 1u, 3u); + + EXPECT_EQ(subr(0, 0, 0), 12); + EXPECT_EQ(subr(1, 0, 0), 28); +} + + +TEST_F(ColMajorAccessor3d, CanAssignValues) +{ + default_r(1, 1, 1) = default_r(0, 0, 0); + + EXPECT_EQ(data[16], 1); +} + + +TEST_F(ColMajorAccessor3d, CanAssignSubranges) +{ + default_r(1u, span{0, 2}, span{0, 3}) = + custom_r(0u, span{0, 2}, span{0, 3}); + + EXPECT_EQ(data[12], 1); + EXPECT_EQ(data[15], 2); + EXPECT_EQ(data[18], -1); + EXPECT_EQ(data[21], 24); + EXPECT_EQ(data[13], 3); + EXPECT_EQ(data[16], 4); + EXPECT_EQ(data[19], -2); + EXPECT_EQ(data[22], 28); + EXPECT_EQ(data[14], 29); + EXPECT_EQ(data[17], 30); + EXPECT_EQ(data[20], 31); + EXPECT_EQ(data[23], 32); +} + + } // namespace diff --git a/include/ginkgo/core/base/range_accessors.hpp b/include/ginkgo/core/base/range_accessors.hpp index b0528956b38..902f5239769 100644 --- a/include/ginkgo/core/base/range_accessors.hpp +++ b/include/ginkgo/core/base/range_accessors.hpp @@ -73,7 +73,7 @@ struct row_major_helper_s { compute(const std::array &size, const std::array 1 ? total_dim - 1 : 0)> &stride, - FirstType first, Indices &&...idxs) + FirstType first, Indices &&... idxs) { return GKO_ASSERT(first < size[dim_idx]), first * stride[dim_idx] + @@ -103,7 +103,7 @@ template constexpr GKO_ATTRIBUTES ValueType compute_storage_index( const std::array &size, const std::array 1 ? total_dim - 1 : 0)> &stride, - Indices &&...idxs) + Indices &&... idxs) { return row_major_helper_s::compute( size, stride, std::forward(idxs)...); @@ -120,7 +120,8 @@ constexpr GKO_ATTRIBUTES std::enable_if_t spans_in_size( template constexpr GKO_ATTRIBUTES std::enable_if_t<(iter < N), int> spans_in_size( - const std::array &size, First first, Remaining &&...remaining) + const std::array &size, First first, + Remaining &&... remaining) { static_assert(sizeof...(Remaining) + 1 == N - iter, "Number of remaining spans must be equal to N - iter"); @@ -132,7 +133,7 @@ constexpr GKO_ATTRIBUTES std::enable_if_t<(iter < N), int> spans_in_size( template constexpr GKO_ATTRIBUTES int validate_spans( - const std::array &size, Spans &&...spans) + const std::array &size, Spans &&... spans) { return detail::spans_in_size<0>(size, std::forward(spans)...); } @@ -164,7 +165,7 @@ using are_span_compatible = are_span_compatible_impl; template constexpr GKO_ATTRIBUTES std::enable_if_t<(current == N), std::array> - to_array_impl(const dim &size, Dims &&...dims) + to_array_impl(const dim &size, Dims &&... dims) { static_assert(sizeof...(Dims) == N, "Number of arguments must match dimensionality!"); @@ -175,7 +176,7 @@ constexpr GKO_ATTRIBUTES template constexpr GKO_ATTRIBUTES std::enable_if_t<(current < N), std::array> - to_array_impl(const dim &size, Dims &&...dims) + to_array_impl(const dim &size, Dims &&... dims) { return to_array_impl( size, std::forward(dims)..., size[current]); @@ -209,7 +210,7 @@ constexpr GKO_ATTRIBUTES std::enable_if_t> compute_default_stride_array_impl(const std::array &, - Args &&...args) + Args &&... args) { return {{std::forward(args)...}}; } @@ -218,7 +219,7 @@ template constexpr GKO_ATTRIBUTES std::enable_if_t< (iter < N) && (iter == sizeof...(Args) + 1), std::array> compute_default_stride_array_impl(const std::array &size, - Args &&...args) + Args &&... args) { return compute_default_stride_array_impl( size, std::forward(args)..., mult_dim_upwards_impl(size)); @@ -237,7 +238,7 @@ constexpr GKO_ATTRIBUTES template GKO_ATTRIBUTES std::enable_if_t multidim_for_each_impl( - const std::array &, Callable callable, Indices &&...indices) + const std::array &, Callable callable, Indices &&... indices) { static_assert(iter == sizeof...(Indices), "Number arguments must match current iteration!"); @@ -248,7 +249,7 @@ template GKO_ATTRIBUTES std::enable_if_t<(iter < N)> multidim_for_each_impl( const std::array &size, Callable &&callable, - Indices &&...indices) + Indices &&... indices) { static_assert(iter == sizeof...(Indices), "Number arguments must match current iteration!"); @@ -372,7 +373,7 @@ class row_major { template constexpr GKO_ATTRIBUTES std::enable_if_t::value, value_type &> - operator()(Indices &&...indices) const + operator()(Indices &&... indices) const { return data[detail::compute_storage_index( lengths, stride, std::forward(indices)...)]; @@ -630,6 +631,303 @@ class row_major { }; +namespace detail_colmajor { + + +/** + * This helper runs from first to last dimension in order to compute the index. + * The index is computed like this: + * indices: x1, x2, x3, ..., xn + * compute(stride, x1, x2, x3, ..., x(n-1), xn) -> + * x1 * stride[0] + x2 * stride[1] + ... + * + x(n-2) * stride[n-3] + x(n-1) + xn * stride[n-2] + * Note that swap of the last two strides, making this 'column major'. + */ +template +struct index_helper_s { + static_assert(total_dim >= 1, "Dimensionality must be >= 1"); + static_assert(current_iter <= total_dim, "Iteration must be <= total_dim!"); + + static constexpr size_type dim_idx{current_iter - 1}; + + template + static constexpr GKO_ATTRIBUTES ValueType + compute(const std::array &size, + const std::array 0 ? total_dim - 1 : 0)> + &stride, + FirstType first, Indices &&... idxs) + { + if (current_iter == total_dim - 1) { + return first + + index_helper_s:: + compute(size, stride, std::forward(idxs)...); + } + + return GKO_ASSERT(first < size[dim_idx]), + first * stride[dim_idx] + + index_helper_s:: + compute(size, stride, std::forward(idxs)...); + } +}; + +template +struct index_helper_s { + static_assert(total_dim >= 2, "Dimensionality must be >= 2"); + + // static constexpr size_type current_iter = total_dim; + static constexpr size_type dim_idx{total_dim - 1}; + + template + static constexpr GKO_ATTRIBUTES ValueType + compute(const std::array &size, + const std::array 1 ? total_dim - 1 : 0)> + &stride, + FirstType first, Indices &&... idxs) + { + return GKO_ASSERT(first < size[total_dim - 1]), + first * stride[dim_idx - 1]; + } +}; + +/** + * Computes the storage index for the given indices with respect to the given + * stride array + */ +template +constexpr GKO_ATTRIBUTES ValueType compute_index( + const std::array &size, + const std::array 0 ? total_dim - 1 : 0)> &stride, + Indices &&... idxs) +{ + return index_helper_s::compute( + size, stride, std::forward(idxs)...); +} + + +template +constexpr GKO_ATTRIBUTES std::enable_if_t +mult_dim_upwards_impl(const std::array &size) +{ + return 1; +} + +template +constexpr GKO_ATTRIBUTES std::enable_if_t<(iter < N), ValueType> +mult_dim_upwards_impl(const std::array &size) +{ + return size[iter] * mult_dim_upwards_impl(size); +} + +template +constexpr GKO_ATTRIBUTES + std::enable_if_t<(iter == N - 1) && (iter == sizeof...(Args) + 1), + std::array> + default_stride_array_impl(const std::array &size, + Args &&... args) +{ + return {{std::forward(args)..., size[N - 2]}}; +} + +template +constexpr GKO_ATTRIBUTES std::enable_if_t<(iter < N - 1 || iter == N) && + (iter == sizeof...(Args) + 1), + std::array> +default_stride_array_impl(const std::array &size, Args &&... args) +{ + return default_stride_array_impl( + size, std::forward(args)..., mult_dim_upwards_impl(size)); +} + +template +constexpr GKO_ATTRIBUTES + std::array 0 ? dimensions - 1 : 0)> + default_stride_array(const std::array &size) +{ + return default_stride_array_impl(size); +} + + +} // namespace detail_colmajor + + +/** + * A bridge between a range and a column-major memory layout. + * + * Note that this is not completely a 'layout right'. Only the innermost + * two dimensions are regarded as defining a column-major matrix, and + * the rest of the dimensions are treated identically to \ref row_major. + * + * You should not try to explicitly create an instance of this accessor. + * Instead, supply it as a template parameter to a range, and pass the + * constructor parameters for this class to the range (it will forward it to + * this class). + * + * @tparam ValueType type of values this accessor returns + * @tparam Dimensionality number of dimensions of this accessor + */ +template +class col_major { +public: + friend class range; + + static_assert(Dimensionality != 0, + "This accessor does not support a dimensionality of 0!"); + static_assert(Dimensionality != 1, + "Please use row_major accessor for 1D ranges."); + static constexpr size_type dimensionality = Dimensionality; + + /** + * Type of values returned by the accessor. + */ + using value_type = ValueType; + + /** + * Type of underlying data storage. + */ + using data_type = value_type *; + + /** + * Number of dimensions of the accessor. + */ + + using const_accessor = col_major; + using stride_type = std::array; + using length_type = std::array; + +protected: + /** + * Creates a col_major accessor. + * + * @param data pointer to the block of memory containing the data + * @param lengths size / length of the accesses of each dimension + * @param stride distance (in elements) between starting positions of + * the dimensions (i.e. + * `x_1 * stride_1 + x_2 * stride_2 * ... + x_(n-1) + x_n * stride_(n-1)` + * points to the element at (x_1, x_2, ..., x_n)) + */ + constexpr GKO_ATTRIBUTES explicit col_major(data_type data, + dim size, + stride_type stride) + : data{data}, + lengths{detail::to_array(size)}, + stride{stride} + {} + + /** + * Creates a col_major accessor with a default stride (assumes no padding) + * + * @param data pointer to the block of memory containing the data + * @param lengths size / length of the accesses of each dimension + */ + constexpr GKO_ATTRIBUTES explicit col_major(data_type data, + dim size) + : data{data}, + lengths{detail::to_array(size)}, + stride{detail_colmajor::default_stride_array(lengths)} + {} + +public: + /** + * Creates a col_major range which contains a read-only version of the + * current accessor. + * + * @returns a col major range which is read-only. + */ + constexpr GKO_ATTRIBUTES range to_const() const + { + // TODO Remove this functionality all together (if requested) + return range(data, lengths, stride); + } + + /** + * Returns the data element at the specified indices + * + * @param row row index + * @param col column index + * + * @return data element at (indices...) + */ + template + constexpr GKO_ATTRIBUTES + std::enable_if_t::value, value_type &> + operator()(Indices &&... indices) const + { + return data[detail_colmajor::compute_index( + lengths, stride, std::forward(indices)...)]; + } + + /** + * Returns the sub-range spanning the range (x1_span, x2_span, ...) + * + * @param rows row span + * @param cols column span + * + * @return sub-range spanning the given spans + */ + template + constexpr GKO_ATTRIBUTES std::enable_if_t< + detail::are_span_compatible::value, range> + operator()(SpanTypes... spans) const + { + return detail::validate_spans(lengths, spans...), + range{ + data + detail_colmajor::compute_index( + lengths, stride, (span{spans}.begin)...), + dim{ + (span{spans}.end - span{spans}.begin)...}, + stride}; + } + + /** + * Returns the length in dimension `dimension`. + * + * @param dimension a dimension index + * + * @return length in dimension `dimension` + */ + constexpr GKO_ATTRIBUTES size_type length(size_type dimension) const + { + return lengths[dimension]; + } + + /** + * Copies data from another accessor + * + * @warning Do not use this function since it is not optimized for a + * specific executor. It will always be performed sequentially. + * Please write an optimized version (adjusted to the architecture) + * by iterating through the values yourself. + * + * @tparam OtherAccessor type of the other accessor + * + * @param other other accessor + */ + template + GKO_ATTRIBUTES void copy_from(const OtherAccessor &other) const + { + detail::multidim_for_each(lengths, [this, &other](auto... indices) { + (*this)(indices...) = other(indices...); + }); + } + + /** + * Reference to the underlying data. + */ + const data_type data; + + /** + * An array of dimension sizes. + */ + const length_type lengths; + + /** + * Distance between consecutive 'layers' for each dimension + * (except the second, for which it is 1). + */ + const stride_type stride; +}; + + } // namespace accessor } // namespace gko From 285f36002ece672c7418b226f86f08b7efe3f2bc Mon Sep 17 00:00:00 2001 From: Aditya Kashi Date: Fri, 19 Feb 2021 21:07:17 +0100 Subject: [PATCH 3/7] attempt to fix compile issues with Intel 17 --- include/ginkgo/core/base/range_accessors.hpp | 22 ++++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/include/ginkgo/core/base/range_accessors.hpp b/include/ginkgo/core/base/range_accessors.hpp index 902f5239769..39c2b0b5f07 100644 --- a/include/ginkgo/core/base/range_accessors.hpp +++ b/include/ginkgo/core/base/range_accessors.hpp @@ -332,8 +332,8 @@ class row_major { dim size, stride_type stride) : data{data}, - lengths{detail::to_array(size)}, - stride{stride} + lengths(detail::to_array(size)), + stride(stride) {} /** @@ -345,8 +345,8 @@ class row_major { constexpr GKO_ATTRIBUTES explicit row_major(data_type data, dim size) : data{data}, - lengths{detail::to_array(size)}, - stride{detail::compute_default_stride_array(lengths)} + lengths(detail::to_array(size)), + stride(detail::compute_default_stride_array(lengths)) {} public: @@ -517,8 +517,8 @@ class row_major { dim size, size_type stride) : data{data}, - lengths{detail::to_array(size)}, - stride{stride} + lengths(detail::to_array(size)), + stride(stride) {} /** @@ -530,7 +530,7 @@ class row_major { constexpr GKO_ATTRIBUTES explicit row_major(data_type data, dim size) : data{data}, - lengths{detail::to_array(size)}, + lengths(detail::to_array(size)), stride{size[1]} {} @@ -809,8 +809,8 @@ class col_major { dim size, stride_type stride) : data{data}, - lengths{detail::to_array(size)}, - stride{stride} + lengths(detail::to_array(size)), + stride(stride) {} /** @@ -822,8 +822,8 @@ class col_major { constexpr GKO_ATTRIBUTES explicit col_major(data_type data, dim size) : data{data}, - lengths{detail::to_array(size)}, - stride{detail_colmajor::default_stride_array(lengths)} + lengths(detail::to_array(size)), + stride(detail_colmajor::default_stride_array(lengths)) {} public: From 3cb8b41f0d658f1a2d4163c0698e797742ef2aa4 Mon Sep 17 00:00:00 2001 From: Aditya Kashi Date: Mon, 22 Feb 2021 16:12:46 +0100 Subject: [PATCH 4/7] removed some redundant code and unused variables --- include/ginkgo/core/base/range_accessors.hpp | 22 ++++---------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/include/ginkgo/core/base/range_accessors.hpp b/include/ginkgo/core/base/range_accessors.hpp index 39c2b0b5f07..aa91b025e17 100644 --- a/include/ginkgo/core/base/range_accessors.hpp +++ b/include/ginkgo/core/base/range_accessors.hpp @@ -165,7 +165,7 @@ using are_span_compatible = are_span_compatible_impl; template constexpr GKO_ATTRIBUTES std::enable_if_t<(current == N), std::array> - to_array_impl(const dim &size, Dims &&... dims) + to_array_impl(const dim &, Dims &&... dims) { static_assert(sizeof...(Dims) == N, "Number of arguments must match dimensionality!"); @@ -674,7 +674,6 @@ template struct index_helper_s { static_assert(total_dim >= 2, "Dimensionality must be >= 2"); - // static constexpr size_type current_iter = total_dim; static constexpr size_type dim_idx{total_dim - 1}; template @@ -682,7 +681,7 @@ struct index_helper_s { compute(const std::array &size, const std::array 1 ? total_dim - 1 : 0)> &stride, - FirstType first, Indices &&... idxs) + FirstType first, Indices &&...) { return GKO_ASSERT(first < size[total_dim - 1]), first * stride[dim_idx - 1]; @@ -704,20 +703,6 @@ constexpr GKO_ATTRIBUTES ValueType compute_index( } -template -constexpr GKO_ATTRIBUTES std::enable_if_t -mult_dim_upwards_impl(const std::array &size) -{ - return 1; -} - -template -constexpr GKO_ATTRIBUTES std::enable_if_t<(iter < N), ValueType> -mult_dim_upwards_impl(const std::array &size) -{ - return size[iter] * mult_dim_upwards_impl(size); -} - template constexpr GKO_ATTRIBUTES std::enable_if_t<(iter == N - 1) && (iter == sizeof...(Args) + 1), @@ -735,7 +720,8 @@ constexpr GKO_ATTRIBUTES std::enable_if_t<(iter < N - 1 || iter == N) && default_stride_array_impl(const std::array &size, Args &&... args) { return default_stride_array_impl( - size, std::forward(args)..., mult_dim_upwards_impl(size)); + size, std::forward(args)..., + detail::mult_dim_upwards_impl(size)); } template From 79349eeb8ef5a5432f8b770acd615868f22a9fb9 Mon Sep 17 00:00:00 2001 From: Aditya Kashi Date: Tue, 23 Feb 2021 22:25:19 +0100 Subject: [PATCH 5/7] Addressed review comments including renaming the new accessor to block_col_major MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Thomas Grützmacher --- core/test/base/range_accessors.cpp | 26 +++--- include/ginkgo/core/base/range_accessors.hpp | 86 +++++++++++--------- 2 files changed, 60 insertions(+), 52 deletions(-) diff --git a/core/test/base/range_accessors.cpp b/core/test/base/range_accessors.cpp index 0694541278b..7027bed7420 100644 --- a/core/test/base/range_accessors.cpp +++ b/core/test/base/range_accessors.cpp @@ -275,13 +275,13 @@ TEST_F(RowMajorAccessor3d, CanAssignSubranges) } -class ColMajorAccessor3d : public ::testing::Test { +class BlockColMajorAccessor3d : public ::testing::Test { protected: using span = gko::span; static constexpr gko::size_type dimensionality{3}; - using col_major_range = - gko::range>; + using blk_col_major_range = + gko::range>; // clang-format off int data[2 * 3 * 4]{ @@ -308,14 +308,14 @@ class ColMajorAccessor3d : public ::testing::Test { // clang-format on const gko::dim dim1{2, 3, 4}; const gko::dim dim2{2, 2, 3}; - col_major_range default_r{data, dim1}; - col_major_range custom_r{ + blk_col_major_range default_r{data, dim1}; + blk_col_major_range custom_r{ data, dim2, std::array{12, 3}}; }; -TEST_F(ColMajorAccessor3d, ComputesCorrectStride) +TEST_F(BlockColMajorAccessor3d, ComputesCorrectStride) { auto range_stride = default_r.get_accessor().stride; auto check_stride = std::array{12, 3}; @@ -324,7 +324,7 @@ TEST_F(ColMajorAccessor3d, ComputesCorrectStride) } -TEST_F(ColMajorAccessor3d, CanAccessData) +TEST_F(BlockColMajorAccessor3d, CanAccessData) { EXPECT_EQ(default_r(0, 0, 0), 1); EXPECT_EQ(custom_r(0, 0, 0), 1); @@ -339,7 +339,7 @@ TEST_F(ColMajorAccessor3d, CanAccessData) } -TEST_F(ColMajorAccessor3d, CanWriteData) +TEST_F(BlockColMajorAccessor3d, CanWriteData) { default_r(0, 0, 0) = 4; custom_r(1, 1, 1) = 100; @@ -351,7 +351,7 @@ TEST_F(ColMajorAccessor3d, CanWriteData) } -TEST_F(ColMajorAccessor3d, CanCreateSubrange) +TEST_F(BlockColMajorAccessor3d, CanCreateSubrange) { auto subr = custom_r(span{0, 2}, span{1, 2}, span{1, 3}); @@ -362,7 +362,7 @@ TEST_F(ColMajorAccessor3d, CanCreateSubrange) } -TEST_F(ColMajorAccessor3d, CanCreateRowVector) +TEST_F(BlockColMajorAccessor3d, CanCreateRowVector) { auto subr = default_r(1u, 2u, span{0, 2}); @@ -371,7 +371,7 @@ TEST_F(ColMajorAccessor3d, CanCreateRowVector) } -TEST_F(ColMajorAccessor3d, CanCreateColumnVector) +TEST_F(BlockColMajorAccessor3d, CanCreateColumnVector) { auto subr = default_r(span{0u, 2u}, 1u, 3u); @@ -380,7 +380,7 @@ TEST_F(ColMajorAccessor3d, CanCreateColumnVector) } -TEST_F(ColMajorAccessor3d, CanAssignValues) +TEST_F(BlockColMajorAccessor3d, CanAssignValues) { default_r(1, 1, 1) = default_r(0, 0, 0); @@ -388,7 +388,7 @@ TEST_F(ColMajorAccessor3d, CanAssignValues) } -TEST_F(ColMajorAccessor3d, CanAssignSubranges) +TEST_F(BlockColMajorAccessor3d, CanAssignSubranges) { default_r(1u, span{0, 2}, span{0, 3}) = custom_r(0u, span{0, 2}, span{0, 3}); diff --git a/include/ginkgo/core/base/range_accessors.hpp b/include/ginkgo/core/base/range_accessors.hpp index aa91b025e17..8e380fa6ee4 100644 --- a/include/ginkgo/core/base/range_accessors.hpp +++ b/include/ginkgo/core/base/range_accessors.hpp @@ -468,6 +468,10 @@ template class row_major { public: friend class range; + + /** + * Number of dimensions of the accessor. + */ static constexpr size_type dimensionality = 2; /** @@ -480,10 +484,6 @@ class row_major { */ using data_type = value_type *; - /** - * Number of dimensions of the accessor. - */ - using const_accessor = row_major; protected: @@ -631,7 +631,11 @@ class row_major { }; -namespace detail_colmajor { +/** + * Namespace for helper functions and structs for + * the block column major accessor. + */ +namespace detail_block_col_major { /** @@ -658,9 +662,11 @@ struct index_helper_s { FirstType first, Indices &&... idxs) { if (current_iter == total_dim - 1) { - return first + - index_helper_s:: - compute(size, stride, std::forward(idxs)...); + return GKO_ASSERT(first < size[dim_idx]), + first + + index_helper_s:: + compute(size, stride, + std::forward(idxs)...); } return GKO_ASSERT(first < size[dim_idx]), @@ -676,12 +682,12 @@ struct index_helper_s { static constexpr size_type dim_idx{total_dim - 1}; - template + template static constexpr GKO_ATTRIBUTES ValueType compute(const std::array &size, const std::array 1 ? total_dim - 1 : 0)> &stride, - FirstType first, Indices &&...) + FirstType first) { return GKO_ASSERT(first < size[total_dim - 1]), first * stride[dim_idx - 1]; @@ -733,15 +739,15 @@ constexpr GKO_ATTRIBUTES } -} // namespace detail_colmajor +} // namespace detail_block_col_major /** - * A bridge between a range and a column-major memory layout. + * A bridge between a range and a block-column-major memory layout. * - * Note that this is not completely a 'layout right'. Only the innermost - * two dimensions are regarded as defining a column-major matrix, and - * the rest of the dimensions are treated identically to \ref row_major. + * Only the innermost two dimensions are regarded as defining + * a column-major matrix, and the rest of the dimensions are treated + * identically to \ref row_major. * * You should not try to explicitly create an instance of this accessor. * Instead, supply it as a template parameter to a range, and pass the @@ -752,14 +758,18 @@ constexpr GKO_ATTRIBUTES * @tparam Dimensionality number of dimensions of this accessor */ template -class col_major { +class block_col_major { public: - friend class range; + friend class range; static_assert(Dimensionality != 0, "This accessor does not support a dimensionality of 0!"); static_assert(Dimensionality != 1, "Please use row_major accessor for 1D ranges."); + + /** + * Number of dimensions of the accessor. + */ static constexpr size_type dimensionality = Dimensionality; /** @@ -772,17 +782,13 @@ class col_major { */ using data_type = value_type *; - /** - * Number of dimensions of the accessor. - */ - - using const_accessor = col_major; + using const_accessor = block_col_major; using stride_type = std::array; using length_type = std::array; protected: /** - * Creates a col_major accessor. + * Creates a block_col_major accessor. * * @param data pointer to the block of memory containing the data * @param lengths size / length of the accesses of each dimension @@ -791,33 +797,34 @@ class col_major { * `x_1 * stride_1 + x_2 * stride_2 * ... + x_(n-1) + x_n * stride_(n-1)` * points to the element at (x_1, x_2, ..., x_n)) */ - constexpr GKO_ATTRIBUTES explicit col_major(data_type data, - dim size, - stride_type stride) + constexpr GKO_ATTRIBUTES explicit block_col_major(data_type data, + dim size, + stride_type stride) : data{data}, lengths(detail::to_array(size)), stride(stride) {} /** - * Creates a col_major accessor with a default stride (assumes no padding) + * Creates a block_col_major accessor with a default stride + * (assumes no padding) * * @param data pointer to the block of memory containing the data * @param lengths size / length of the accesses of each dimension */ - constexpr GKO_ATTRIBUTES explicit col_major(data_type data, - dim size) + constexpr GKO_ATTRIBUTES explicit block_col_major(data_type data, + dim size) : data{data}, lengths(detail::to_array(size)), - stride(detail_colmajor::default_stride_array(lengths)) + stride(detail_block_col_major::default_stride_array(lengths)) {} public: /** - * Creates a col_major range which contains a read-only version of the - * current accessor. + * Creates a block_col_major range which contains a read-only version of + * the current accessor. * - * @returns a col major range which is read-only. + * @returns a block column major range which is read-only. */ constexpr GKO_ATTRIBUTES range to_const() const { @@ -838,7 +845,7 @@ class col_major { std::enable_if_t::value, value_type &> operator()(Indices &&... indices) const { - return data[detail_colmajor::compute_index( + return data[detail_block_col_major::compute_index( lengths, stride, std::forward(indices)...)]; } @@ -851,13 +858,14 @@ class col_major { * @return sub-range spanning the given spans */ template - constexpr GKO_ATTRIBUTES std::enable_if_t< - detail::are_span_compatible::value, range> - operator()(SpanTypes... spans) const + constexpr GKO_ATTRIBUTES + std::enable_if_t::value, + range> + operator()(SpanTypes... spans) const { return detail::validate_spans(lengths, spans...), - range{ - data + detail_colmajor::compute_index( + range{ + data + detail_block_col_major::compute_index( lengths, stride, (span{spans}.begin)...), dim{ (span{spans}.end - span{spans}.begin)...}, From 598f5298b94d6539e5ee1d5eb710e7327c6782d8 Mon Sep 17 00:00:00 2001 From: Aditya Kashi Date: Wed, 24 Feb 2021 00:36:56 +0100 Subject: [PATCH 6/7] some documentation improvements --- include/ginkgo/core/base/range_accessors.hpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/include/ginkgo/core/base/range_accessors.hpp b/include/ginkgo/core/base/range_accessors.hpp index 8e380fa6ee4..6d2a3f328db 100644 --- a/include/ginkgo/core/base/range_accessors.hpp +++ b/include/ginkgo/core/base/range_accessors.hpp @@ -97,7 +97,11 @@ struct row_major_helper_s { /** * Computes the storage index for the given indices with respect to the given - * stride array + * stride array for row-major access + * + * @param size the multi-dimensional sizes of the range of values + * @param stride the stride array + * @param idxs the multi-dimensional indices of the desired entry */ template constexpr GKO_ATTRIBUTES ValueType compute_storage_index( @@ -639,13 +643,14 @@ namespace detail_block_col_major { /** - * This helper runs from first to last dimension in order to compute the index. + * Runs from first to last dimension in order to compute the index. + * * The index is computed like this: * indices: x1, x2, x3, ..., xn * compute(stride, x1, x2, x3, ..., x(n-1), xn) -> * x1 * stride[0] + x2 * stride[1] + ... * + x(n-2) * stride[n-3] + x(n-1) + xn * stride[n-2] - * Note that swap of the last two strides, making this 'column major'. + * Note that swap of the last two strides, making this 'block column major'. */ template struct index_helper_s { @@ -695,8 +700,11 @@ struct index_helper_s { }; /** - * Computes the storage index for the given indices with respect to the given - * stride array + * Computes the flat storage index for block-column-major access. + * + * @param size the multi-dimensional sizes of the range of values + * @param stride the stride array + * @param idxs the multi-dimensional indices of the desired entry */ template constexpr GKO_ATTRIBUTES ValueType compute_index( From dcb26c8ef0613737c94ccad7bcfdf408d0dc380f Mon Sep 17 00:00:00 2001 From: Aditya Kashi Date: Tue, 9 Mar 2021 00:47:16 +0100 Subject: [PATCH 7/7] minor cosmetic improvements --- core/test/base/range_accessors.cpp | 16 ++++++++-------- include/ginkgo/core/base/range_accessors.hpp | 12 +++++++----- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/core/test/base/range_accessors.cpp b/core/test/base/range_accessors.cpp index 7027bed7420..7a5ffe7c18a 100644 --- a/core/test/base/range_accessors.cpp +++ b/core/test/base/range_accessors.cpp @@ -287,15 +287,15 @@ class BlockColMajorAccessor3d : public ::testing::Test { int data[2 * 3 * 4]{ 1, 3, 5, 2, 4, 6, - -1,-2,-3, - 11,12,13, + -1,-2,-3, + 11,12,13, - 21,25,29, - 22,26,30, - 23,27,31, - 24,28,32 + 21,25,29, + 22,26,30, + 23,27,31, + 24,28,32 - /* This matrix actually looks like + /* This matrix actually looks like 1, 2, -1, 11, 3, 4, -2, 12, 5, 6, -3, 13, @@ -303,7 +303,7 @@ class BlockColMajorAccessor3d : public ::testing::Test { 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 - */ + */ }; // clang-format on const gko::dim dim1{2, 3, 4}; diff --git a/include/ginkgo/core/base/range_accessors.hpp b/include/ginkgo/core/base/range_accessors.hpp index 6d2a3f328db..c4abdde4e45 100644 --- a/include/ginkgo/core/base/range_accessors.hpp +++ b/include/ginkgo/core/base/range_accessors.hpp @@ -635,11 +635,12 @@ class row_major { }; +namespace detail { /** * Namespace for helper functions and structs for * the block column major accessor. */ -namespace detail_block_col_major { +namespace blk_col_major { /** @@ -747,7 +748,8 @@ constexpr GKO_ATTRIBUTES } -} // namespace detail_block_col_major +} // namespace blk_col_major +} // namespace detail /** @@ -824,7 +826,7 @@ class block_col_major { dim size) : data{data}, lengths(detail::to_array(size)), - stride(detail_block_col_major::default_stride_array(lengths)) + stride(detail::blk_col_major::default_stride_array(lengths)) {} public: @@ -853,7 +855,7 @@ class block_col_major { std::enable_if_t::value, value_type &> operator()(Indices &&... indices) const { - return data[detail_block_col_major::compute_index( + return data[detail::blk_col_major::compute_index( lengths, stride, std::forward(indices)...)]; } @@ -873,7 +875,7 @@ class block_col_major { { return detail::validate_spans(lengths, spans...), range{ - data + detail_block_col_major::compute_index( + data + detail::blk_col_major::compute_index( lengths, stride, (span{spans}.begin)...), dim{ (span{spans}.end - span{spans}.begin)...},