Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make new Accessors independent of Ginkgo #708

Merged
merged 14 commits into from
Mar 16, 2021
794 changes: 794 additions & 0 deletions accessor/accessor_helper.hpp

Large diffs are not rendered by default.

190 changes: 94 additions & 96 deletions core/base/accessor_references.hpp → accessor/accessor_references.hpp

Large diffs are not rendered by default.

208 changes: 208 additions & 0 deletions accessor/block_col_major.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
/*******************************<GINKGO LICENSE>******************************
Copyright (c) 2017-2021, the Ginkgo authors
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************<GINKGO LICENSE>*******************************/

#ifndef GKO_ACCESSOR_BLOCK_COL_MAJOR_HPP_
#define GKO_ACCESSOR_BLOCK_COL_MAJOR_HPP_

#include <array>

#include "accessor_helper.hpp"
#include "range.hpp"
#include "utils.hpp"


namespace gko {
namespace acc {


/**
* A bridge between a range and a block-column-major memory layout.
*
* 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 <typename ValueType, size_type Dimensionality>
class block_col_major {
public:
friend class range<block_col_major>;

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;

/**
* Type of values returned by the accessor.
*/
using value_type = ValueType;

/**
* Type of underlying data storage.
*/
using data_type = value_type *;

using const_accessor = block_col_major<const ValueType, Dimensionality>;
using stride_type = std::array<size_type, dimensionality - 1>;
using length_type = std::array<size_type, dimensionality>;

protected:
/**
* 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
* @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_ACC_ATTRIBUTES explicit block_col_major(length_type size,
data_type data,
stride_type stride)
: lengths(size), data{data}, stride(stride)
{}

/**
* 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_ACC_ATTRIBUTES explicit block_col_major(length_type size,
data_type data)
: lengths(size),
data{data},
stride(helper::blk_col_major::default_stride_array(lengths))
{}

public:
/**
* Creates a block_col_major range which contains a read-only version of
* the current accessor.
*
* @returns a block column major range which is read-only.
*/
constexpr GKO_ACC_ATTRIBUTES range<const_accessor> to_const() const
{
// TODO Remove this functionality all together (if requested)
return range<const_accessor>(lengths, data, stride);
}

/**
* Returns the data element at the specified indices
*
* @param row row index
* @param col column index
*
* @return data element at (indices...)
*/
template <typename... Indices>
constexpr GKO_ACC_ATTRIBUTES
std::enable_if_t<are_all_integral<Indices...>::value, value_type &>
operator()(Indices &&... indices) const
{
return data[helper::blk_col_major::compute_index(
lengths, stride, std::forward<Indices>(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 <typename... SpanTypes>
constexpr GKO_ACC_ATTRIBUTES
std::enable_if_t<helper::are_index_span_compatible<SpanTypes...>::value,
range<block_col_major>>
operator()(SpanTypes... spans) const
{
return helper::validate_index_spans(lengths, spans...),
range<block_col_major>{
length_type{
(index_span{spans}.end - index_span{spans}.begin)...},
data + helper::blk_col_major::compute_index(
lengths, stride, (index_span{spans}.begin)...),
stride};
}

/**
* Returns the length in dimension `dimension`.
*
* @param dimension a dimension index
*
* @return length in dimension `dimension`
*/
constexpr GKO_ACC_ATTRIBUTES size_type length(size_type dimension) const
{
return lengths[dimension];
}

/**
* An array of dimension sizes.
*/
const length_type lengths;

/**
* Reference to the underlying data.
*/
const data_type data;

/**
* Distance between consecutive 'layers' for each dimension
* (except the second, for which it is 1).
*/
const stride_type stride;
};


} // namespace acc
} // namespace gko

#endif // GKO_ACCESSOR_BLOCK_COL_MAJOR_HPP_
137 changes: 137 additions & 0 deletions accessor/index_span.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/*******************************<GINKGO LICENSE>******************************
Copyright (c) 2017-2021, the Ginkgo authors
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************<GINKGO LICENSE>*******************************/

#ifndef GKO_ACCESSOR_INDEX_SPAN_HPP_
#define GKO_ACCESSOR_INDEX_SPAN_HPP_

#include "utils.hpp"


namespace gko {
namespace acc {


/**
* An index_span is a lightweight structure used to describe a contiguous span
* of indices of one dimension.
*
* The main purpose of the index_span is to create sub-ranges from other ranges.
* An index_span `is` represents a contiguous set of indexes in one dimension of
* the range, starting from `is.begin` (inclusive) and ending at index `is.end`
* (exclusive). An index_span is only valid if its end is larger than its
* beginning.
*
* index_spans can be compared using `==` and `!=` operators. Two spans are
* equal iff both their `begin` and `end` values are identical.
*
* index_sets also have two distinct partial orders defined:
* 1. `x < y` (`y > x`) iff `x.end < y.begin`
* 2. `x <= y` (`y >= x`) iff `x.end <= y.begin`
* Note: `x < y || x == y` is not equivalent to `x <= y`.
*/
struct index_span {
/**
* Creates an index_span.
*
* @param begin the beginning (inclusive) of the index_span
* @param end the end (exclusive) of the index_span
*
*/
GKO_ACC_ATTRIBUTES constexpr index_span(size_type begin,
size_type end) noexcept
: begin{begin}, end{end}
{}

/**
* Creates an index_span representing the point `point`.
*
* The begin is set to `point`, and the end to `point + 1`
*
* @param point the point which the index_span represents
*/
GKO_ACC_ATTRIBUTES constexpr index_span(size_type point) noexcept
: index_span{point, point + 1}
{}

/**
* Checks if an index_span is valid.
*
* @returns true iff `this->begin < this->end`
*/
GKO_ACC_ATTRIBUTES constexpr bool is_valid() const { return begin < end; }

friend GKO_ACC_ATTRIBUTES constexpr bool operator<(const index_span &first,
const index_span &second)
{
return first.end < second.begin;
}

friend GKO_ACC_ATTRIBUTES constexpr bool operator<=(
const index_span &first, const index_span &second)
{
return first.end <= second.begin;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about

Suggested change
return first.end <= second.begin;
return first.begin <= second.begin && first.end <= second.end;

I'm not sure, but maybe this is more 'natural'.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a 1:1 copy from the gko::span. I think making it something completely different to operator < might be even more confusing. The current way defines a partial order, if we make this change, it is no longer partially ordered.

Copy link
Contributor

@Slaedr Slaedr Mar 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually even my suggestion would define a partial order. In fact, I think mine would define a total order, because then for any two spans A and B, at least one of A <= B or B <= A is necessarily true. Iff both are true, A = B.

The existing definition is only a partial order, true, because not all spans are comparable with <=. Also it can never happen that both A <= B and B <= A, unless both A and B refer to a single point.

But I understand if you want to keep it the way it is.

}

friend GKO_ACC_ATTRIBUTES constexpr bool operator>(const index_span &first,
const index_span &second)
{
return second < first;
}

friend GKO_ACC_ATTRIBUTES constexpr bool operator>=(
const index_span &first, const index_span &second)
{
return second <= first;
}

friend GKO_ACC_ATTRIBUTES constexpr bool operator==(
const index_span &first, const index_span &second)
{
return first.begin == second.begin && first.end == second.end;
}

friend GKO_ACC_ATTRIBUTES constexpr bool operator!=(
const index_span &first, const index_span &second)
{
return !(first == second);
}

const size_type begin;
const size_type end;
};


} // namespace acc
} // namespace gko


#endif // GKO_ACCESSOR_INDEX_SPAN_HPP_
Loading