33#ifndef GKO_PUBLIC_CORE_BASE_RANGE_HPP_
34#define GKO_PUBLIC_CORE_BASE_RANGE_HPP_
40#include <ginkgo/core/base/math.hpp>
41#include <ginkgo/core/base/types.hpp>
42#include <ginkgo/core/base/utils.hpp>
123GKO_ATTRIBUTES GKO_INLINE
constexpr bool operator<(
const span& first,
130GKO_ATTRIBUTES GKO_INLINE
constexpr bool operator<=(
const span& first,
133 return first.end <= second.begin;
137GKO_ATTRIBUTES GKO_INLINE
constexpr bool operator>(
const span& first,
140 return second < first;
144GKO_ATTRIBUTES GKO_INLINE
constexpr bool operator>=(
const span& first,
147 return second <= first;
151GKO_ATTRIBUTES GKO_INLINE
constexpr bool operator==(
const span& first,
154 return first.begin == second.begin && first.end == second.end;
158GKO_ATTRIBUTES GKO_INLINE
constexpr bool operator!=(
const span& first,
161 return !(first == second);
170GKO_ATTRIBUTES
constexpr GKO_INLINE
172 SecondRange::dimensionality)),
181GKO_ATTRIBUTES
constexpr GKO_INLINE
183 SecondRange::dimensionality)),
210using head_t =
typename head<
T...>::type;
325template <
typename Accessor>
353 typename = std::enable_if_t<
354 sizeof...(AccessorParams) != 1 ||
356 range, std::decay<detail::head_t<AccessorParams...>>>::value>>
358 : accessor_{std::forward<AccessorParams>(
params)...}
375 const ->
decltype(std::declval<accessor>()(
379 "Too many dimensions in range call");
380 return accessor_(std::forward<DimensionTypes>(
dimensions)...);
391 template <
typename OtherAccessor>
395 GKO_ASSERT(detail::equal_dimensions(*
this,
other));
396 accessor_.copy_from(
other);
415 GKO_ASSERT(detail::equal_dimensions(*
this,
other));
416 accessor_.copy_from(
other.get_accessor());
469enum class operation_kind { range_by_range, scalar_by_range, range_by_scalar };
472template <
typename Accessor,
typename Operation>
473struct implement_unary_operation {
475 static constexpr size_type dimensionality = accessor::dimensionality;
477 GKO_ATTRIBUTES
constexpr explicit implement_unary_operation(
483 GKO_ATTRIBUTES
constexpr auto operator()(
485 ->
decltype(Operation::evaluate(std::declval<accessor>(),
488 return Operation::evaluate(operand,
dimensions...);
496 template <
typename OtherAccessor>
499 const accessor operand;
505struct implement_binary_operation {};
507template <
typename FirstAccessor,
typename SecondAccessor,
typename Operation>
508struct implement_binary_operation<operation_kind::range_by_range,
FirstAccessor,
512 static_assert(first_accessor::dimensionality ==
513 second_accessor::dimensionality,
514 "Both ranges need to have the same number of dimensions");
515 static constexpr size_type dimensionality = first_accessor::dimensionality;
517 GKO_ATTRIBUTES
explicit implement_binary_operation(
519 : first{first}, second{second}
521 GKO_ASSERT(gko::detail::equal_dimensions(first, second));
525 GKO_ATTRIBUTES
constexpr auto operator()(
527 ->
decltype(Operation::evaluate_range_by_range(
528 std::declval<first_accessor>(), std::declval<second_accessor>(),
531 return Operation::evaluate_range_by_range(first, second,
dimensions...);
539 template <
typename OtherAccessor>
542 const first_accessor first;
543 const second_accessor second;
546template <
typename FirstOperand,
typename SecondAccessor,
typename Operation>
547struct implement_binary_operation<operation_kind::scalar_by_range,
FirstOperand,
550 static constexpr size_type dimensionality = second_accessor::dimensionality;
552 GKO_ATTRIBUTES
constexpr explicit implement_binary_operation(
554 : first{first}, second{second}
558 GKO_ATTRIBUTES
constexpr auto operator()(
560 ->
decltype(Operation::evaluate_scalar_by_range(
561 std::declval<FirstOperand>(), std::declval<second_accessor>(),
564 return Operation::evaluate_scalar_by_range(first, second,
573 template <
typename OtherAccessor>
577 const second_accessor second;
580template <
typename FirstAccessor,
typename SecondOperand,
typename Operation>
581struct implement_binary_operation<operation_kind::range_by_scalar,
584 static constexpr size_type dimensionality = first_accessor::dimensionality;
586 GKO_ATTRIBUTES
constexpr explicit implement_binary_operation(
588 : first{first}, second{second}
592 GKO_ATTRIBUTES
constexpr auto operator()(
594 ->
decltype(Operation::evaluate_range_by_scalar(
595 std::declval<first_accessor>(), std::declval<SecondOperand>(),
598 return Operation::evaluate_range_by_scalar(first, second,
607 template <
typename OtherAccessor>
610 const first_accessor first;
617#define GKO_DEPRECATED_UNARY_RANGE_OPERATION(_operation_deprecated_name, \
619 namespace accessor { \
620 template <typename Operand> \
621 struct GKO_DEPRECATED("Please use " #_operation_name) \
622 _operation_deprecated_name : _operation_name<Operand> {}; \
624 static_assert(true, \
625 "This assert is used to counter the false positive extra " \
626 "semi-colon warnings")
629#define GKO_ENABLE_UNARY_RANGE_OPERATION(_operation_name, _operator_name, \
631 namespace accessor { \
632 template <typename Operand> \
633 struct _operation_name \
634 : ::gko::detail::implement_unary_operation<Operand, \
635 ::gko::_operator> { \
636 using ::gko::detail::implement_unary_operation< \
637 Operand, ::gko::_operator>::implement_unary_operation; \
640 GKO_BIND_UNARY_RANGE_OPERATION_TO_OPERATOR(_operation_name, _operator_name)
643#define GKO_BIND_UNARY_RANGE_OPERATION_TO_OPERATOR(_operation_name, \
645 template <typename Accessor> \
646 GKO_ATTRIBUTES constexpr GKO_INLINE \
647 range<accessor::_operation_name<Accessor>> \
648 _operator_name(const range<Accessor>& operand) \
650 return range<accessor::_operation_name<Accessor>>( \
651 operand.get_accessor()); \
653 static_assert(true, \
654 "This assert is used to counter the false positive extra " \
655 "semi-colon warnings")
658#define GKO_DEFINE_SIMPLE_UNARY_OPERATION(_name, ...) \
661 template <typename Operand> \
662 GKO_ATTRIBUTES static constexpr auto simple_evaluate_impl( \
663 const Operand& operand) -> decltype(__VA_ARGS__) \
665 return __VA_ARGS__; \
669 template <typename AccessorType, typename... DimensionTypes> \
670 GKO_ATTRIBUTES static constexpr auto evaluate( \
671 const AccessorType& accessor, const DimensionTypes&... dimensions) \
672 -> decltype(simple_evaluate_impl(accessor(dimensions...))) \
674 return simple_evaluate_impl(accessor(dimensions...)); \
684GKO_DEFINE_SIMPLE_UNARY_OPERATION(
unary_plus, +operand);
685GKO_DEFINE_SIMPLE_UNARY_OPERATION(
unary_minus, -operand);
688GKO_DEFINE_SIMPLE_UNARY_OPERATION(
logical_not, !operand);
691GKO_DEFINE_SIMPLE_UNARY_OPERATION(
bitwise_not, ~(operand));
708GKO_ENABLE_UNARY_RANGE_OPERATION(unary_plus,
operator+,
709 accessor::detail::unary_plus);
710GKO_ENABLE_UNARY_RANGE_OPERATION(
unary_minus,
operator-,
711 accessor::detail::unary_minus);
714GKO_ENABLE_UNARY_RANGE_OPERATION(
logical_not,
operator!,
715 accessor::detail::logical_not);
718GKO_ENABLE_UNARY_RANGE_OPERATION(
bitwise_not,
operator~,
719 accessor::detail::bitwise_not);
724 accessor::detail::zero_operation);
726 accessor::detail::one_operation);
728 accessor::detail::abs_operation);
730 accessor::detail::real_operation);
732 accessor::detail::imag_operation);
734 accessor::detail::conj_operation);
736 accessor::detail::squared_norm_operation);
749template <
typename Accessor>
752 static constexpr size_type dimensionality = accessor::dimensionality;
761 GKO_ATTRIBUTES
constexpr auto operator()(
776 template <
typename OtherAccessor>
779 const accessor operand;
786GKO_BIND_UNARY_RANGE_OPERATION_TO_OPERATOR(transpose_operation,
transpose);
789#undef GKO_DEPRECATED_UNARY_RANGE_OPERATION
790#undef GKO_DEFINE_SIMPLE_UNARY_OPERATION
791#undef GKO_ENABLE_UNARY_RANGE_OPERATION
794#define GKO_ENABLE_BINARY_RANGE_OPERATION(_operation_name, _operator_name, \
796 namespace accessor { \
797 template <::gko::detail::operation_kind Kind, typename FirstOperand, \
798 typename SecondOperand> \
799 struct _operation_name \
800 : ::gko::detail::implement_binary_operation< \
801 Kind, FirstOperand, SecondOperand, ::gko::_operator> { \
802 using ::gko::detail::implement_binary_operation< \
803 Kind, FirstOperand, SecondOperand, \
804 ::gko::_operator>::implement_binary_operation; \
807 GKO_BIND_RANGE_OPERATION_TO_OPERATOR(_operation_name, _operator_name); \
808 static_assert(true, \
809 "This assert is used to counter the false positive extra " \
810 "semi-colon warnings")
813#define GKO_BIND_RANGE_OPERATION_TO_OPERATOR(_operation_name, _operator_name) \
814 template <typename Accessor> \
815 GKO_ATTRIBUTES constexpr GKO_INLINE range<accessor::_operation_name< \
816 ::gko::detail::operation_kind::range_by_range, Accessor, Accessor>> \
817 _operator_name(const range<Accessor>& first, \
818 const range<Accessor>& second) \
820 return range<accessor::_operation_name< \
821 ::gko::detail::operation_kind::range_by_range, Accessor, \
822 Accessor>>(first.get_accessor(), second.get_accessor()); \
825 template <typename FirstAccessor, typename SecondAccessor> \
826 GKO_ATTRIBUTES constexpr GKO_INLINE range<accessor::_operation_name< \
827 ::gko::detail::operation_kind::range_by_range, FirstAccessor, \
829 _operator_name(const range<FirstAccessor>& first, \
830 const range<SecondAccessor>& second) \
832 return range<accessor::_operation_name< \
833 ::gko::detail::operation_kind::range_by_range, FirstAccessor, \
834 SecondAccessor>>(first.get_accessor(), second.get_accessor()); \
837 template <typename FirstAccessor, typename SecondOperand> \
838 GKO_ATTRIBUTES constexpr GKO_INLINE range<accessor::_operation_name< \
839 ::gko::detail::operation_kind::range_by_scalar, FirstAccessor, \
841 _operator_name(const range<FirstAccessor>& first, \
842 const SecondOperand& second) \
844 return range<accessor::_operation_name< \
845 ::gko::detail::operation_kind::range_by_scalar, FirstAccessor, \
846 SecondOperand>>(first.get_accessor(), second); \
849 template <typename FirstOperand, typename SecondAccessor> \
850 GKO_ATTRIBUTES constexpr GKO_INLINE range<accessor::_operation_name< \
851 ::gko::detail::operation_kind::scalar_by_range, FirstOperand, \
853 _operator_name(const FirstOperand& first, \
854 const range<SecondAccessor>& second) \
856 return range<accessor::_operation_name< \
857 ::gko::detail::operation_kind::scalar_by_range, FirstOperand, \
858 SecondAccessor>>(first, second.get_accessor()); \
860 static_assert(true, \
861 "This assert is used to counter the false positive extra " \
862 "semi-colon warnings")
865#define GKO_DEPRECATED_SIMPLE_BINARY_OPERATION(_deprecated_name, _name) \
866 struct GKO_DEPRECATED("Please use " #_name) _deprecated_name : _name {}
868#define GKO_DEFINE_SIMPLE_BINARY_OPERATION(_name, ...) \
871 template <typename FirstOperand, typename SecondOperand> \
872 GKO_ATTRIBUTES constexpr static auto simple_evaluate_impl( \
873 const FirstOperand& first, const SecondOperand& second) \
874 -> decltype(__VA_ARGS__) \
876 return __VA_ARGS__; \
880 template <typename FirstAccessor, typename SecondAccessor, \
881 typename... DimensionTypes> \
882 GKO_ATTRIBUTES static constexpr auto evaluate_range_by_range( \
883 const FirstAccessor& first, const SecondAccessor& second, \
884 const DimensionTypes&... dims) \
885 -> decltype(simple_evaluate_impl(first(dims...), second(dims...))) \
887 return simple_evaluate_impl(first(dims...), second(dims...)); \
890 template <typename FirstOperand, typename SecondAccessor, \
891 typename... DimensionTypes> \
892 GKO_ATTRIBUTES static constexpr auto evaluate_scalar_by_range( \
893 const FirstOperand& first, const SecondAccessor& second, \
894 const DimensionTypes&... dims) \
895 -> decltype(simple_evaluate_impl(first, second(dims...))) \
897 return simple_evaluate_impl(first, second(dims...)); \
900 template <typename FirstAccessor, typename SecondOperand, \
901 typename... DimensionTypes> \
902 GKO_ATTRIBUTES static constexpr auto evaluate_range_by_scalar( \
903 const FirstAccessor& first, const SecondOperand& second, \
904 const DimensionTypes&... dims) \
905 -> decltype(simple_evaluate_impl(first(dims...), second)) \
907 return simple_evaluate_impl(first(dims...), second); \
917GKO_DEFINE_SIMPLE_BINARY_OPERATION(add, first + second);
918GKO_DEFINE_SIMPLE_BINARY_OPERATION(sub, first - second);
919GKO_DEFINE_SIMPLE_BINARY_OPERATION(mul, first* second);
920GKO_DEFINE_SIMPLE_BINARY_OPERATION(div, first / second);
921GKO_DEFINE_SIMPLE_BINARY_OPERATION(mod, first % second);
924GKO_DEFINE_SIMPLE_BINARY_OPERATION(less, first < second);
925GKO_DEFINE_SIMPLE_BINARY_OPERATION(greater, first > second);
926GKO_DEFINE_SIMPLE_BINARY_OPERATION(less_or_equal, first <= second);
927GKO_DEFINE_SIMPLE_BINARY_OPERATION(greater_or_equal, first >= second);
928GKO_DEFINE_SIMPLE_BINARY_OPERATION(equal, first == second);
929GKO_DEFINE_SIMPLE_BINARY_OPERATION(not_equal, first != second);
932GKO_DEFINE_SIMPLE_BINARY_OPERATION(logical_or, first || second);
933GKO_DEFINE_SIMPLE_BINARY_OPERATION(logical_and, first&& second);
936GKO_DEFINE_SIMPLE_BINARY_OPERATION(bitwise_or, first | second);
937GKO_DEFINE_SIMPLE_BINARY_OPERATION(bitwise_and, first& second);
938GKO_DEFINE_SIMPLE_BINARY_OPERATION(bitwise_xor, first ^ second);
939GKO_DEFINE_SIMPLE_BINARY_OPERATION(left_shift, first << second);
940GKO_DEFINE_SIMPLE_BINARY_OPERATION(right_shift, first >> second);
943GKO_DEFINE_SIMPLE_BINARY_OPERATION(max_operation,
max(first, second));
944GKO_DEFINE_SIMPLE_BINARY_OPERATION(min_operation,
min(first, second));
946GKO_DEPRECATED_SIMPLE_BINARY_OPERATION(max_operaton, max_operation);
947GKO_DEPRECATED_SIMPLE_BINARY_OPERATION(min_operaton, min_operation);
953GKO_ENABLE_BINARY_RANGE_OPERATION(
add,
operator+, accessor::detail::add);
954GKO_ENABLE_BINARY_RANGE_OPERATION(
sub,
operator-, accessor::detail::sub);
955GKO_ENABLE_BINARY_RANGE_OPERATION(
mul,
operator*, accessor::detail::mul);
956GKO_ENABLE_BINARY_RANGE_OPERATION(
div,
operator/, accessor::detail::div);
957GKO_ENABLE_BINARY_RANGE_OPERATION(
mod,
operator%, accessor::detail::mod);
960GKO_ENABLE_BINARY_RANGE_OPERATION(
less,
operator<, accessor::detail::less);
961GKO_ENABLE_BINARY_RANGE_OPERATION(
greater,
operator>,
962 accessor::detail::greater);
964 accessor::detail::less_or_equal);
966 accessor::detail::greater_or_equal);
967GKO_ENABLE_BINARY_RANGE_OPERATION(
equal,
operator==, accessor::detail::equal);
968GKO_ENABLE_BINARY_RANGE_OPERATION(
not_equal,
operator!=,
969 accessor::detail::not_equal);
972GKO_ENABLE_BINARY_RANGE_OPERATION(
logical_or,
operator||,
973 accessor::detail::logical_or);
974GKO_ENABLE_BINARY_RANGE_OPERATION(
logical_and,
operator&&,
975 accessor::detail::logical_and);
978GKO_ENABLE_BINARY_RANGE_OPERATION(
bitwise_or,
operator|,
979 accessor::detail::bitwise_or);
980GKO_ENABLE_BINARY_RANGE_OPERATION(
bitwise_and,
operator&,
981 accessor::detail::bitwise_and);
982GKO_ENABLE_BINARY_RANGE_OPERATION(
bitwise_xor,
operator^,
983 accessor::detail::bitwise_xor);
984GKO_ENABLE_BINARY_RANGE_OPERATION(
left_shift,
operator<<,
985 accessor::detail::left_shift);
986GKO_ENABLE_BINARY_RANGE_OPERATION(
right_shift,
operator>>,
987 accessor::detail::right_shift);
991 accessor::detail::max_operation);
993 accessor::detail::min_operation);
1003 static_assert(
Kind == gko::detail::operation_kind::range_by_range,
1004 "Matrix multiplication expects both operands to be ranges");
1007 static_assert(first_accessor::dimensionality ==
1008 second_accessor::dimensionality,
1009 "Both ranges need to have the same number of dimensions");
1010 static constexpr size_type dimensionality = first_accessor::dimensionality;
1014 : first{first}, second{second}
1016 GKO_ASSERT(first.length(1) == second.length(0));
1017 GKO_ASSERT(gko::detail::equal_dimensions<2>(first, second));
1025 ->
decltype(std::declval<FirstAccessor>()(row, 0,
rest...) *
1026 std::declval<SecondAccessor>()(0, col,
rest...) +
1027 std::declval<FirstAccessor>()(row, 1,
rest...) *
1028 std::declval<SecondAccessor>()(1, col,
rest...))
1031 decltype(first(row, 0,
rest...) * second(0, col,
rest...) +
1032 first(row, 1,
rest...) * second(1, col,
rest...));
1033 GKO_ASSERT(first.length(1) == second.length(0));
1035 const auto size = first.length(1);
1036 for (
auto i =
zero(size);
i < size; ++
i) {
1047 template <
typename OtherAccessor>
1050 const first_accessor first;
1051 const second_accessor second;
1058GKO_BIND_RANGE_OPERATION_TO_OPERATOR(mmul_operation, mmul);
1061#undef GKO_DEFINE_SIMPLE_BINARY_OPERATION
1062#undef GKO_ENABLE_BINARY_RANGE_OPERATION
A range is a multidimensional view of the memory.
Definition range.hpp:326
Accessor accessor
The type of the underlying accessor.
Definition range.hpp:331
constexpr auto operator()(DimensionTypes &&... dimensions) const -> decltype(std::declval< accessor >()(std::forward< DimensionTypes >(dimensions)...))
Returns a value (or a sub-range) with the specified indexes.
Definition range.hpp:374
constexpr size_type length(size_type dimension) const
Returns the length of the specified dimension of the range.
Definition range.hpp:429
constexpr const accessor * operator->() const noexcept
Returns a pointer to the accessor.
Definition range.hpp:441
static constexpr size_type dimensionality
The number of dimensions of the range.
Definition range.hpp:336
const range & operator=(const range &other) const
Assigns another range to this range.
Definition range.hpp:413
constexpr const accessor & get_accessor() const noexcept
`Returns a reference to the accessor.
Definition range.hpp:451
~range()=default
Use the default destructor.
const range & operator=(const range< OtherAccessor > &other) const
Definition range.hpp:392
constexpr range(AccessorParams &&... params)
Creates a new range.
Definition range.hpp:357
The Ginkgo namespace.
Definition abstract_factory.hpp:48
constexpr T one()
Returns the multiplicative identity for T.
Definition math.hpp:803
constexpr T zero()
Returns the additive identity for T.
Definition math.hpp:775
constexpr bool operator!=(const dim< Dimensionality, DimensionType > &x, const dim< Dimensionality, DimensionType > &y)
Checks if two dim objects are different.
Definition dim.hpp:258
constexpr auto imag(const T &x)
Returns the imaginary part of the object.
Definition math.hpp:1057
std::size_t size_type
Integral type used for allocation quantities.
Definition types.hpp:120
constexpr T min(const T &x, const T &y)
Returns the smaller of the arguments.
Definition math.hpp:891
batch_dim< 2, DimensionType > transpose(const batch_dim< 2, DimensionType > &input)
Returns a batch_dim object with its dimensions swapped for batched operators.
Definition batch_dim.hpp:148
constexpr xstd::enable_if_t<!is_complex_s< T >::value, T > abs(const T &x)
Returns the absolute value of the object.
Definition math.hpp:1104
constexpr auto squared_norm(const T &x) -> decltype(real(conj(x) *x))
Returns the squared norm of the object.
Definition math.hpp:1085
constexpr auto conj(const T &x)
Returns the conjugate of an object.
Definition math.hpp:1071
constexpr T max(const T &x, const T &y)
Returns the larger of the arguments.
Definition math.hpp:873
constexpr auto real(const T &x)
Returns the real part of the object.
Definition math.hpp:1041
Definition range.hpp:1002
A span is a lightweight structure used to create sub-ranges from other ranges.
Definition range.hpp:75
constexpr span(size_type begin, size_type end) noexcept
Creates a span.
Definition range.hpp:93
constexpr span(size_type point) noexcept
Creates a span representing a point point.
Definition range.hpp:83
constexpr bool is_valid() const
Checks if a span is valid.
Definition range.hpp:102
constexpr size_type length() const
Returns the length of a span.
Definition range.hpp:109
const size_type begin
Beginning of the span.
Definition range.hpp:114
const size_type end
End of the span.
Definition range.hpp:119