Ginkgo  Generated from pipelines/2837190956 branch based on develop. Ginkgo version 2.0.0
A numerical linear algebra library targeting many-core architectures
range.hpp
1 // SPDX-FileCopyrightText: 2017 - 2026 The Ginkgo authors
2 //
3 // SPDX-License-Identifier: BSD-3-Clause
4 
5 #ifndef GKO_PUBLIC_CORE_BASE_RANGE_HPP_
6 #define GKO_PUBLIC_CORE_BASE_RANGE_HPP_
7 
8 
9 #include <type_traits>
10 
11 #include <ginkgo/core/base/math.hpp>
12 #include <ginkgo/core/base/types.hpp>
13 #include <ginkgo/core/base/utils.hpp>
14 
15 
16 namespace gko {
17 
18 
45 struct span {
53  GKO_ATTRIBUTES constexpr span(size_type point) noexcept
54  : span{point, point + 1}
55  {}
56 
63  GKO_ATTRIBUTES constexpr span(size_type begin, size_type end) noexcept
64  : begin{begin}, end{end}
65  {}
66 
72  GKO_ATTRIBUTES constexpr bool is_valid() const { return begin <= end; }
73 
79  GKO_ATTRIBUTES constexpr size_type length() const { return end - begin; }
80 
85 
89  const size_type end;
90 };
91 
92 
93 GKO_ATTRIBUTES GKO_INLINE constexpr bool operator<(const span& first,
94  const span& second)
95 {
96  return first.end < second.begin;
97 }
98 
99 
100 GKO_ATTRIBUTES GKO_INLINE constexpr bool operator<=(const span& first,
101  const span& second)
102 {
103  return first.end <= second.begin;
104 }
105 
106 
107 GKO_ATTRIBUTES GKO_INLINE constexpr bool operator>(const span& first,
108  const span& second)
109 {
110  return second < first;
111 }
112 
113 
114 GKO_ATTRIBUTES GKO_INLINE constexpr bool operator>=(const span& first,
115  const span& second)
116 {
117  return second <= first;
118 }
119 
120 
121 GKO_ATTRIBUTES GKO_INLINE constexpr bool operator==(const span& first,
122  const span& second)
123 {
124  return first.begin == second.begin && first.end == second.end;
125 }
126 
127 
128 GKO_ATTRIBUTES GKO_INLINE constexpr bool operator!=(const span& first,
129  const span& second)
130 {
131  return !(first == second);
132 }
133 
137 struct local_span : span {
138  using span::span;
139 };
140 
141 
142 namespace detail {
143 
144 
145 template <size_type CurrentDimension = 0, typename FirstRange,
146  typename SecondRange>
147 GKO_ATTRIBUTES constexpr GKO_INLINE
148  std::enable_if_t<(CurrentDimension >= max(FirstRange::dimensionality,
149  SecondRange::dimensionality)),
150  bool>
151  equal_dimensions(const FirstRange&, const SecondRange&)
152 {
153  return true;
154 }
155 
156 template <size_type CurrentDimension = 0, typename FirstRange,
157  typename SecondRange>
158 GKO_ATTRIBUTES constexpr GKO_INLINE
159  std::enable_if_t<(CurrentDimension < max(FirstRange::dimensionality,
160  SecondRange::dimensionality)),
161  bool>
162  equal_dimensions(const FirstRange& first, const SecondRange& second)
163 {
164  return first.length(CurrentDimension) == second.length(CurrentDimension) &&
165  equal_dimensions<CurrentDimension + 1>(first, second);
166 }
167 
172 template <class...>
173 struct head;
174 
178 template <class First, class... Rest>
179 struct head<First, Rest...> {
180  using type = First;
181 };
182 
186 template <class... T>
187 using head_t = typename head<T...>::type;
188 
189 
190 } // namespace detail
191 
192 
301 template <typename Accessor>
302 class range {
303 public:
307  using accessor = Accessor;
308 
312  static constexpr size_type dimensionality = accessor::dimensionality;
313 
317  ~range() = default;
318 
327  template <
328  typename... AccessorParams,
329  typename = std::enable_if_t<
330  sizeof...(AccessorParams) != 1 ||
331  !std::is_same<
332  range, std::decay<detail::head_t<AccessorParams...>>>::value>>
333  GKO_ATTRIBUTES constexpr explicit range(AccessorParams&&... params)
334  : accessor_{std::forward<AccessorParams>(params)...}
335  {}
336 
349  template <typename... DimensionTypes>
350  GKO_ATTRIBUTES constexpr auto operator()(DimensionTypes&&... dimensions)
351  const -> decltype(std::declval<accessor>()(
352  std::forward<DimensionTypes>(dimensions)...))
353  {
354  static_assert(sizeof...(DimensionTypes) <= dimensionality,
355  "Too many dimensions in range call");
356  return accessor_(std::forward<DimensionTypes>(dimensions)...);
357  }
358 
367  template <typename OtherAccessor>
368  GKO_ATTRIBUTES const range& operator=(
369  const range<OtherAccessor>& other) const
370  {
371  GKO_ASSERT(detail::equal_dimensions(*this, other));
372  accessor_.copy_from(other);
373  return *this;
374  }
375 
389  GKO_ATTRIBUTES const range& operator=(const range& other) const
390  {
391  GKO_ASSERT(detail::equal_dimensions(*this, other));
392  accessor_.copy_from(other.get_accessor());
393  return *this;
394  }
395 
396  range(const range& other) = default;
397 
405  GKO_ATTRIBUTES constexpr size_type length(size_type dimension) const
406  {
407  return accessor_.length(dimension);
408  }
409 
417  GKO_ATTRIBUTES constexpr const accessor* operator->() const noexcept
418  {
419  return &accessor_;
420  }
421 
427  GKO_ATTRIBUTES constexpr const accessor& get_accessor() const noexcept
428  {
429  return accessor_;
430  }
431 
432 private:
433  accessor accessor_;
434 };
435 
436 
437 // implementation of range operations follows
438 // (you probably should not have to look at this unless you're interested in the
439 // gory details)
440 
441 
442 namespace detail {
443 
444 
445 enum class operation_kind { range_by_range, scalar_by_range, range_by_scalar };
446 
447 
448 template <typename Accessor, typename Operation>
449 struct implement_unary_operation {
450  using accessor = Accessor;
451  static constexpr size_type dimensionality = accessor::dimensionality;
452 
453  GKO_ATTRIBUTES constexpr explicit implement_unary_operation(
454  const Accessor& operand)
455  : operand{operand}
456  {}
457 
458  template <typename... DimensionTypes>
459  GKO_ATTRIBUTES constexpr auto operator()(
460  const DimensionTypes&... dimensions) const
461  -> decltype(Operation::evaluate(std::declval<accessor>(),
462  dimensions...))
463  {
464  return Operation::evaluate(operand, dimensions...);
465  }
466 
467  GKO_ATTRIBUTES constexpr size_type length(size_type dimension) const
468  {
469  return operand.length(dimension);
470  }
471 
472  template <typename OtherAccessor>
473  GKO_ATTRIBUTES void copy_from(const OtherAccessor& other) const = delete;
474 
475  const accessor operand;
476 };
477 
478 
479 template <operation_kind Kind, typename FirstOperand, typename SecondOperand,
480  typename Operation>
481 struct implement_binary_operation {};
482 
483 template <typename FirstAccessor, typename SecondAccessor, typename Operation>
484 struct implement_binary_operation<operation_kind::range_by_range, FirstAccessor,
485  SecondAccessor, Operation> {
486  using first_accessor = FirstAccessor;
487  using second_accessor = SecondAccessor;
488  static_assert(first_accessor::dimensionality ==
489  second_accessor::dimensionality,
490  "Both ranges need to have the same number of dimensions");
491  static constexpr size_type dimensionality = first_accessor::dimensionality;
492 
493  GKO_ATTRIBUTES explicit implement_binary_operation(
494  const FirstAccessor& first, const SecondAccessor& second)
495  : first{first}, second{second}
496  {
497  GKO_ASSERT(gko::detail::equal_dimensions(first, second));
498  }
499 
500  template <typename... DimensionTypes>
501  GKO_ATTRIBUTES constexpr auto operator()(
502  const DimensionTypes&... dimensions) const
503  -> decltype(Operation::evaluate_range_by_range(
504  std::declval<first_accessor>(), std::declval<second_accessor>(),
505  dimensions...))
506  {
507  return Operation::evaluate_range_by_range(first, second, dimensions...);
508  }
509 
510  GKO_ATTRIBUTES constexpr size_type length(size_type dimension) const
511  {
512  return first.length(dimension);
513  }
514 
515  template <typename OtherAccessor>
516  GKO_ATTRIBUTES void copy_from(const OtherAccessor& other) const = delete;
517 
518  const first_accessor first;
519  const second_accessor second;
520 };
521 
522 template <typename FirstOperand, typename SecondAccessor, typename Operation>
523 struct implement_binary_operation<operation_kind::scalar_by_range, FirstOperand,
524  SecondAccessor, Operation> {
525  using second_accessor = SecondAccessor;
526  static constexpr size_type dimensionality = second_accessor::dimensionality;
527 
528  GKO_ATTRIBUTES constexpr explicit implement_binary_operation(
529  const FirstOperand& first, const SecondAccessor& second)
530  : first{first}, second{second}
531  {}
532 
533  template <typename... DimensionTypes>
534  GKO_ATTRIBUTES constexpr auto operator()(
535  const DimensionTypes&... dimensions) const
536  -> decltype(Operation::evaluate_scalar_by_range(
537  std::declval<FirstOperand>(), std::declval<second_accessor>(),
538  dimensions...))
539  {
540  return Operation::evaluate_scalar_by_range(first, second,
541  dimensions...);
542  }
543 
544  GKO_ATTRIBUTES constexpr size_type length(size_type dimension) const
545  {
546  return second.length(dimension);
547  }
548 
549  template <typename OtherAccessor>
550  GKO_ATTRIBUTES void copy_from(const OtherAccessor& other) const = delete;
551 
552  const FirstOperand first;
553  const second_accessor second;
554 };
555 
556 template <typename FirstAccessor, typename SecondOperand, typename Operation>
557 struct implement_binary_operation<operation_kind::range_by_scalar,
558  FirstAccessor, SecondOperand, Operation> {
559  using first_accessor = FirstAccessor;
560  static constexpr size_type dimensionality = first_accessor::dimensionality;
561 
562  GKO_ATTRIBUTES constexpr explicit implement_binary_operation(
563  const FirstAccessor& first, const SecondOperand& second)
564  : first{first}, second{second}
565  {}
566 
567  template <typename... DimensionTypes>
568  GKO_ATTRIBUTES constexpr auto operator()(
569  const DimensionTypes&... dimensions) const
570  -> decltype(Operation::evaluate_range_by_scalar(
571  std::declval<first_accessor>(), std::declval<SecondOperand>(),
572  dimensions...))
573  {
574  return Operation::evaluate_range_by_scalar(first, second,
575  dimensions...);
576  }
577 
578  GKO_ATTRIBUTES constexpr size_type length(size_type dimension) const
579  {
580  return first.length(dimension);
581  }
582 
583  template <typename OtherAccessor>
584  GKO_ATTRIBUTES void copy_from(const OtherAccessor& other) const = delete;
585 
586  const first_accessor first;
587  const SecondOperand second;
588 };
589 
590 
591 } // namespace detail
592 
593 #define GKO_DEPRECATED_UNARY_RANGE_OPERATION(_operation_deprecated_name, \
594  _operation_name) \
595  namespace accessor { \
596  template <typename Operand> \
597  struct GKO_DEPRECATED("Please use " #_operation_name) \
598  _operation_deprecated_name : _operation_name<Operand> {}; \
599  } \
600  static_assert(true, \
601  "This assert is used to counter the false positive extra " \
602  "semi-colon warnings")
603 
604 
605 #define GKO_ENABLE_UNARY_RANGE_OPERATION(_operation_name, _operator_name, \
606  _operator) \
607  namespace accessor { \
608  template <typename Operand> \
609  struct _operation_name \
610  : ::gko::detail::implement_unary_operation<Operand, \
611  ::gko::_operator> { \
612  using ::gko::detail::implement_unary_operation< \
613  Operand, ::gko::_operator>::implement_unary_operation; \
614  }; \
615  } \
616  GKO_BIND_UNARY_RANGE_OPERATION_TO_OPERATOR(_operation_name, _operator_name)
617 
618 
619 #define GKO_BIND_UNARY_RANGE_OPERATION_TO_OPERATOR(_operation_name, \
620  _operator_name) \
621  template <typename Accessor> \
622  GKO_ATTRIBUTES constexpr GKO_INLINE \
623  range<accessor::_operation_name<Accessor>> \
624  _operator_name(const range<Accessor>& operand) \
625  { \
626  return range<accessor::_operation_name<Accessor>>( \
627  operand.get_accessor()); \
628  } \
629  static_assert(true, \
630  "This assert is used to counter the false positive extra " \
631  "semi-colon warnings")
632 
633 
634 #define GKO_DEFINE_SIMPLE_UNARY_OPERATION(_name, ...) \
635  struct _name { \
636  private: \
637  template <typename Operand> \
638  GKO_ATTRIBUTES static constexpr auto simple_evaluate_impl( \
639  const Operand& operand) -> decltype(__VA_ARGS__) \
640  { \
641  return __VA_ARGS__; \
642  } \
643  \
644  public: \
645  template <typename AccessorType, typename... DimensionTypes> \
646  GKO_ATTRIBUTES static constexpr auto evaluate( \
647  const AccessorType& accessor, const DimensionTypes&... dimensions) \
648  -> decltype(simple_evaluate_impl(accessor(dimensions...))) \
649  { \
650  return simple_evaluate_impl(accessor(dimensions...)); \
651  } \
652  }
653 
654 
655 namespace accessor {
656 namespace detail {
657 
658 
659 // unary arithmetic
660 GKO_DEFINE_SIMPLE_UNARY_OPERATION(unary_plus, +operand);
661 GKO_DEFINE_SIMPLE_UNARY_OPERATION(unary_minus, -operand);
662 
663 // unary logical
664 GKO_DEFINE_SIMPLE_UNARY_OPERATION(logical_not, !operand);
665 
666 // unary bitwise
667 GKO_DEFINE_SIMPLE_UNARY_OPERATION(bitwise_not, ~(operand));
668 
669 // common functions
670 GKO_DEFINE_SIMPLE_UNARY_OPERATION(zero_operation, zero(operand));
671 GKO_DEFINE_SIMPLE_UNARY_OPERATION(one_operation, one(operand));
672 GKO_DEFINE_SIMPLE_UNARY_OPERATION(abs_operation, abs(operand));
673 GKO_DEFINE_SIMPLE_UNARY_OPERATION(real_operation, real(operand));
674 GKO_DEFINE_SIMPLE_UNARY_OPERATION(imag_operation, imag(operand));
675 GKO_DEFINE_SIMPLE_UNARY_OPERATION(conj_operation, conj(operand));
676 GKO_DEFINE_SIMPLE_UNARY_OPERATION(squared_norm_operation,
677  squared_norm(operand));
678 
679 } // namespace detail
680 } // namespace accessor
681 
682 
683 // unary arithmetic
684 GKO_ENABLE_UNARY_RANGE_OPERATION(unary_plus, operator+,
685  accessor::detail::unary_plus);
686 GKO_ENABLE_UNARY_RANGE_OPERATION(unary_minus, operator-,
687  accessor::detail::unary_minus);
688 
689 // unary logical
690 GKO_ENABLE_UNARY_RANGE_OPERATION(logical_not, operator!,
691  accessor::detail::logical_not);
692 
693 // unary bitwise
694 GKO_ENABLE_UNARY_RANGE_OPERATION(bitwise_not, operator~,
695  accessor::detail::bitwise_not);
696 
697 // common unary functions
698 
699 GKO_ENABLE_UNARY_RANGE_OPERATION(zero_operation, zero,
700  accessor::detail::zero_operation);
701 GKO_ENABLE_UNARY_RANGE_OPERATION(one_operation, one,
702  accessor::detail::one_operation);
703 GKO_ENABLE_UNARY_RANGE_OPERATION(abs_operation, abs,
704  accessor::detail::abs_operation);
705 GKO_ENABLE_UNARY_RANGE_OPERATION(real_operation, real,
706  accessor::detail::real_operation);
707 GKO_ENABLE_UNARY_RANGE_OPERATION(imag_operation, imag,
708  accessor::detail::imag_operation);
709 GKO_ENABLE_UNARY_RANGE_OPERATION(conj_operation, conj,
710  accessor::detail::conj_operation);
711 GKO_ENABLE_UNARY_RANGE_OPERATION(squared_norm_operation, squared_norm,
712  accessor::detail::squared_norm_operation);
713 
714 GKO_DEPRECATED_UNARY_RANGE_OPERATION(one_operaton, one_operation);
715 GKO_DEPRECATED_UNARY_RANGE_OPERATION(abs_operaton, abs_operation);
716 GKO_DEPRECATED_UNARY_RANGE_OPERATION(real_operaton, real_operation);
717 GKO_DEPRECATED_UNARY_RANGE_OPERATION(imag_operaton, imag_operation);
718 GKO_DEPRECATED_UNARY_RANGE_OPERATION(conj_operaton, conj_operation);
719 GKO_DEPRECATED_UNARY_RANGE_OPERATION(squared_norm_operaton,
721 
722 namespace accessor {
723 
724 
725 template <typename Accessor>
727  using accessor = Accessor;
728  static constexpr size_type dimensionality = accessor::dimensionality;
729 
730  GKO_ATTRIBUTES constexpr explicit transpose_operation(
731  const Accessor& operand)
732  : operand{operand}
733  {}
734 
735  template <typename FirstDimensionType, typename SecondDimensionType,
736  typename... DimensionTypes>
737  GKO_ATTRIBUTES constexpr auto operator()(
738  const FirstDimensionType& first_dim,
739  const SecondDimensionType& second_dim,
740  const DimensionTypes&... dims) const
741  -> decltype(std::declval<accessor>()(second_dim, first_dim, dims...))
742  {
743  return operand(second_dim, first_dim, dims...);
744  }
745 
746  GKO_ATTRIBUTES constexpr size_type length(size_type dimension) const
747  {
748  return dimension < 2 ? operand.length(dimension ^ 1)
749  : operand.length(dimension);
750  }
751 
752  template <typename OtherAccessor>
753  GKO_ATTRIBUTES void copy_from(const OtherAccessor& other) const = delete;
754 
755  const accessor operand;
756 };
757 
758 
759 } // namespace accessor
760 
761 
762 GKO_BIND_UNARY_RANGE_OPERATION_TO_OPERATOR(transpose_operation, transpose);
763 
764 
765 #undef GKO_DEPRECATED_UNARY_RANGE_OPERATION
766 #undef GKO_DEFINE_SIMPLE_UNARY_OPERATION
767 #undef GKO_ENABLE_UNARY_RANGE_OPERATION
768 
769 
770 #define GKO_ENABLE_BINARY_RANGE_OPERATION(_operation_name, _operator_name, \
771  _operator) \
772  namespace accessor { \
773  template <::gko::detail::operation_kind Kind, typename FirstOperand, \
774  typename SecondOperand> \
775  struct _operation_name \
776  : ::gko::detail::implement_binary_operation< \
777  Kind, FirstOperand, SecondOperand, ::gko::_operator> { \
778  using ::gko::detail::implement_binary_operation< \
779  Kind, FirstOperand, SecondOperand, \
780  ::gko::_operator>::implement_binary_operation; \
781  }; \
782  } \
783  GKO_BIND_RANGE_OPERATION_TO_OPERATOR(_operation_name, _operator_name); \
784  static_assert(true, \
785  "This assert is used to counter the false positive extra " \
786  "semi-colon warnings")
787 
788 
789 #define GKO_BIND_RANGE_OPERATION_TO_OPERATOR(_operation_name, _operator_name) \
790  template <typename Accessor> \
791  GKO_ATTRIBUTES constexpr GKO_INLINE range<accessor::_operation_name< \
792  ::gko::detail::operation_kind::range_by_range, Accessor, Accessor>> \
793  _operator_name(const range<Accessor>& first, \
794  const range<Accessor>& second) \
795  { \
796  return range<accessor::_operation_name< \
797  ::gko::detail::operation_kind::range_by_range, Accessor, \
798  Accessor>>(first.get_accessor(), second.get_accessor()); \
799  } \
800  \
801  template <typename FirstAccessor, typename SecondAccessor> \
802  GKO_ATTRIBUTES constexpr GKO_INLINE range<accessor::_operation_name< \
803  ::gko::detail::operation_kind::range_by_range, FirstAccessor, \
804  SecondAccessor>> \
805  _operator_name(const range<FirstAccessor>& first, \
806  const range<SecondAccessor>& second) \
807  { \
808  return range<accessor::_operation_name< \
809  ::gko::detail::operation_kind::range_by_range, FirstAccessor, \
810  SecondAccessor>>(first.get_accessor(), second.get_accessor()); \
811  } \
812  \
813  template <typename FirstAccessor, typename SecondOperand> \
814  GKO_ATTRIBUTES constexpr GKO_INLINE range<accessor::_operation_name< \
815  ::gko::detail::operation_kind::range_by_scalar, FirstAccessor, \
816  SecondOperand>> \
817  _operator_name(const range<FirstAccessor>& first, \
818  const SecondOperand& second) \
819  { \
820  return range<accessor::_operation_name< \
821  ::gko::detail::operation_kind::range_by_scalar, FirstAccessor, \
822  SecondOperand>>(first.get_accessor(), second); \
823  } \
824  \
825  template <typename FirstOperand, typename SecondAccessor> \
826  GKO_ATTRIBUTES constexpr GKO_INLINE range<accessor::_operation_name< \
827  ::gko::detail::operation_kind::scalar_by_range, FirstOperand, \
828  SecondAccessor>> \
829  _operator_name(const FirstOperand& first, \
830  const range<SecondAccessor>& second) \
831  { \
832  return range<accessor::_operation_name< \
833  ::gko::detail::operation_kind::scalar_by_range, FirstOperand, \
834  SecondAccessor>>(first, second.get_accessor()); \
835  } \
836  static_assert(true, \
837  "This assert is used to counter the false positive extra " \
838  "semi-colon warnings")
839 
840 
841 #define GKO_DEPRECATED_SIMPLE_BINARY_OPERATION(_deprecated_name, _name) \
842  struct GKO_DEPRECATED("Please use " #_name) _deprecated_name : _name {}
843 
844 #define GKO_DEFINE_SIMPLE_BINARY_OPERATION(_name, ...) \
845  struct _name { \
846  private: \
847  template <typename FirstOperand, typename SecondOperand> \
848  GKO_ATTRIBUTES constexpr static auto simple_evaluate_impl( \
849  const FirstOperand& first, const SecondOperand& second) \
850  -> decltype(__VA_ARGS__) \
851  { \
852  return __VA_ARGS__; \
853  } \
854  \
855  public: \
856  template <typename FirstAccessor, typename SecondAccessor, \
857  typename... DimensionTypes> \
858  GKO_ATTRIBUTES static constexpr auto evaluate_range_by_range( \
859  const FirstAccessor& first, const SecondAccessor& second, \
860  const DimensionTypes&... dims) \
861  -> decltype(simple_evaluate_impl(first(dims...), second(dims...))) \
862  { \
863  return simple_evaluate_impl(first(dims...), second(dims...)); \
864  } \
865  \
866  template <typename FirstOperand, typename SecondAccessor, \
867  typename... DimensionTypes> \
868  GKO_ATTRIBUTES static constexpr auto evaluate_scalar_by_range( \
869  const FirstOperand& first, const SecondAccessor& second, \
870  const DimensionTypes&... dims) \
871  -> decltype(simple_evaluate_impl(first, second(dims...))) \
872  { \
873  return simple_evaluate_impl(first, second(dims...)); \
874  } \
875  \
876  template <typename FirstAccessor, typename SecondOperand, \
877  typename... DimensionTypes> \
878  GKO_ATTRIBUTES static constexpr auto evaluate_range_by_scalar( \
879  const FirstAccessor& first, const SecondOperand& second, \
880  const DimensionTypes&... dims) \
881  -> decltype(simple_evaluate_impl(first(dims...), second)) \
882  { \
883  return simple_evaluate_impl(first(dims...), second); \
884  } \
885  }
886 
887 
888 namespace accessor {
889 namespace detail {
890 
891 
892 // binary arithmetic
893 GKO_DEFINE_SIMPLE_BINARY_OPERATION(add, first + second);
894 GKO_DEFINE_SIMPLE_BINARY_OPERATION(sub, first - second);
895 GKO_DEFINE_SIMPLE_BINARY_OPERATION(mul, first* second);
896 GKO_DEFINE_SIMPLE_BINARY_OPERATION(div, first / second);
897 GKO_DEFINE_SIMPLE_BINARY_OPERATION(mod, first % second);
898 
899 // relational
900 GKO_DEFINE_SIMPLE_BINARY_OPERATION(less, first < second);
901 GKO_DEFINE_SIMPLE_BINARY_OPERATION(greater, first > second);
902 GKO_DEFINE_SIMPLE_BINARY_OPERATION(less_or_equal, first <= second);
903 GKO_DEFINE_SIMPLE_BINARY_OPERATION(greater_or_equal, first >= second);
904 GKO_DEFINE_SIMPLE_BINARY_OPERATION(equal, first == second);
905 GKO_DEFINE_SIMPLE_BINARY_OPERATION(not_equal, first != second);
906 
907 // binary logical
908 GKO_DEFINE_SIMPLE_BINARY_OPERATION(logical_or, first || second);
909 GKO_DEFINE_SIMPLE_BINARY_OPERATION(logical_and, first&& second);
910 
911 // binary bitwise
912 GKO_DEFINE_SIMPLE_BINARY_OPERATION(bitwise_or, first | second);
913 GKO_DEFINE_SIMPLE_BINARY_OPERATION(bitwise_and, first& second);
914 GKO_DEFINE_SIMPLE_BINARY_OPERATION(bitwise_xor, first ^ second);
915 GKO_DEFINE_SIMPLE_BINARY_OPERATION(left_shift, first << second);
916 GKO_DEFINE_SIMPLE_BINARY_OPERATION(right_shift, first >> second);
917 
918 // common binary functions
919 GKO_DEFINE_SIMPLE_BINARY_OPERATION(max_operation, max(first, second));
920 GKO_DEFINE_SIMPLE_BINARY_OPERATION(min_operation, min(first, second));
921 
922 GKO_DEPRECATED_SIMPLE_BINARY_OPERATION(max_operaton, max_operation);
923 GKO_DEPRECATED_SIMPLE_BINARY_OPERATION(min_operaton, min_operation);
924 } // namespace detail
925 } // namespace accessor
926 
927 
928 // binary arithmetic
929 GKO_ENABLE_BINARY_RANGE_OPERATION(add, operator+, accessor::detail::add);
930 GKO_ENABLE_BINARY_RANGE_OPERATION(sub, operator-, accessor::detail::sub);
931 GKO_ENABLE_BINARY_RANGE_OPERATION(mul, operator*, accessor::detail::mul);
932 GKO_ENABLE_BINARY_RANGE_OPERATION(div, operator/, accessor::detail::div);
933 GKO_ENABLE_BINARY_RANGE_OPERATION(mod, operator%, accessor::detail::mod);
934 
935 // relational
936 GKO_ENABLE_BINARY_RANGE_OPERATION(less, operator<, accessor::detail::less);
937 GKO_ENABLE_BINARY_RANGE_OPERATION(greater, operator>,
938  accessor::detail::greater);
939 GKO_ENABLE_BINARY_RANGE_OPERATION(less_or_equal, operator<=,
940  accessor::detail::less_or_equal);
941 GKO_ENABLE_BINARY_RANGE_OPERATION(greater_or_equal, operator>=,
942  accessor::detail::greater_or_equal);
943 GKO_ENABLE_BINARY_RANGE_OPERATION(equal, operator==, accessor::detail::equal);
944 GKO_ENABLE_BINARY_RANGE_OPERATION(not_equal, operator!=,
945  accessor::detail::not_equal);
946 
947 // binary logical
948 GKO_ENABLE_BINARY_RANGE_OPERATION(logical_or, operator||,
949  accessor::detail::logical_or);
950 GKO_ENABLE_BINARY_RANGE_OPERATION(logical_and, operator&&,
951  accessor::detail::logical_and);
952 
953 // binary bitwise
954 GKO_ENABLE_BINARY_RANGE_OPERATION(bitwise_or, operator|,
955  accessor::detail::bitwise_or);
956 GKO_ENABLE_BINARY_RANGE_OPERATION(bitwise_and, operator&,
957  accessor::detail::bitwise_and);
958 GKO_ENABLE_BINARY_RANGE_OPERATION(bitwise_xor, operator^,
959  accessor::detail::bitwise_xor);
960 GKO_ENABLE_BINARY_RANGE_OPERATION(left_shift, operator<<,
961  accessor::detail::left_shift);
962 GKO_ENABLE_BINARY_RANGE_OPERATION(right_shift, operator>>,
963  accessor::detail::right_shift);
964 
965 // common binary functions
966 GKO_ENABLE_BINARY_RANGE_OPERATION(max_operation, max,
967  accessor::detail::max_operation);
968 GKO_ENABLE_BINARY_RANGE_OPERATION(min_operation, min,
969  accessor::detail::min_operation);
970 
971 
972 // special binary range functions
973 namespace accessor {
974 
975 
976 template <gko::detail::operation_kind Kind, typename FirstAccessor,
977  typename SecondAccessor>
979  static_assert(Kind == gko::detail::operation_kind::range_by_range,
980  "Matrix multiplication expects both operands to be ranges");
981  using first_accessor = FirstAccessor;
982  using second_accessor = SecondAccessor;
983  static_assert(first_accessor::dimensionality ==
984  second_accessor::dimensionality,
985  "Both ranges need to have the same number of dimensions");
986  static constexpr size_type dimensionality = first_accessor::dimensionality;
987 
988  GKO_ATTRIBUTES explicit mmul_operation(const FirstAccessor& first,
989  const SecondAccessor& second)
990  : first{first}, second{second}
991  {
992  GKO_ASSERT(first.length(1) == second.length(0));
993  GKO_ASSERT(gko::detail::equal_dimensions<2>(first, second));
994  }
995 
996  template <typename FirstDimension, typename SecondDimension,
997  typename... DimensionTypes>
998  GKO_ATTRIBUTES auto operator()(const FirstDimension& row,
999  const SecondDimension& col,
1000  const DimensionTypes&... rest) const
1001  -> decltype(std::declval<FirstAccessor>()(row, 0, rest...) *
1002  std::declval<SecondAccessor>()(0, col, rest...) +
1003  std::declval<FirstAccessor>()(row, 1, rest...) *
1004  std::declval<SecondAccessor>()(1, col, rest...))
1005  {
1006  using result_type =
1007  decltype(first(row, 0, rest...) * second(0, col, rest...) +
1008  first(row, 1, rest...) * second(1, col, rest...));
1009  GKO_ASSERT(first.length(1) == second.length(0));
1010  auto result = zero<result_type>();
1011  const auto size = first.length(1);
1012  for (auto i = zero(size); i < size; ++i) {
1013  result += first(row, i, rest...) * second(i, col, rest...);
1014  }
1015  return result;
1016  }
1017 
1018  GKO_ATTRIBUTES constexpr size_type length(size_type dimension) const
1019  {
1020  return dimension == 1 ? second.length(1) : first.length(dimension);
1021  }
1022 
1023  template <typename OtherAccessor>
1024  GKO_ATTRIBUTES void copy_from(const OtherAccessor& other) const = delete;
1025 
1026  const first_accessor first;
1027  const second_accessor second;
1028 };
1029 
1030 
1031 } // namespace accessor
1032 
1033 
1034 GKO_BIND_RANGE_OPERATION_TO_OPERATOR(mmul_operation, mmul);
1035 
1036 
1037 #undef GKO_DEFINE_SIMPLE_BINARY_OPERATION
1038 #undef GKO_ENABLE_BINARY_RANGE_OPERATION
1039 
1040 
1041 } // namespace gko
1042 
1043 
1044 #endif // GKO_PUBLIC_CORE_BASE_RANGE_HPP_
gko::accessor::squared_norm_operation
Definition: range.hpp:712
gko::accessor::sub
Definition: range.hpp:930
gko::accessor::right_shift
Definition: range.hpp:963
gko::accessor::greater_or_equal
Definition: range.hpp:942
gko::span::end
const size_type end
End of the span.
Definition: range.hpp:89
gko::max
constexpr T max(const T &x, const T &y)
Returns the larger of the arguments.
Definition: math.hpp:731
gko::accessor::imag_operation
Definition: range.hpp:708
gko::accessor::unary_minus
Definition: range.hpp:687
gko::abs
constexpr std::enable_if_t<!is_complex_s< T >::value, T > abs(const T &x)
Returns the absolute value of the object.
Definition: math.hpp:961
gko::range::range
constexpr range(AccessorParams &&... params)
Creates a new range.
Definition: range.hpp:333
gko::range::~range
~range()=default
Use the default destructor.
gko::accessor::abs_operation
Definition: range.hpp:704
gko::accessor::mul
Definition: range.hpp:931
gko::accessor::unary_plus
Definition: range.hpp:685
gko::size_type
std::size_t size_type
Integral type used for allocation quantities.
Definition: types.hpp:101
gko::accessor::bitwise_not
Definition: range.hpp:695
gko::accessor::max_operation
Definition: range.hpp:967
gko::accessor::one_operaton
Definition: range.hpp:714
gko::span::is_valid
constexpr bool is_valid() const
Checks if a span is valid.
Definition: range.hpp:72
gko::accessor::less_or_equal
Definition: range.hpp:940
gko::span::span
constexpr span(size_type point) noexcept
Creates a span representing a point point.
Definition: range.hpp:53
gko::span::span
constexpr span(size_type begin, size_type end) noexcept
Creates a span.
Definition: range.hpp:63
gko::squared_norm
constexpr auto squared_norm(const T &x) -> decltype(real(conj(x) *x))
Returns the squared norm of the object.
Definition: math.hpp:943
gko::span::begin
const size_type begin
Beginning of the span.
Definition: range.hpp:84
gko::span::length
constexpr size_type length() const
Returns the length of a span.
Definition: range.hpp:79
gko::accessor::div
Definition: range.hpp:932
gko::accessor::logical_or
Definition: range.hpp:949
gko::range::operator->
constexpr const accessor * operator->() const noexcept
Returns a pointer to the accessor.
Definition: range.hpp:417
gko::range
A range is a multidimensional view of the memory.
Definition: range.hpp:302
gko
The Ginkgo namespace.
Definition: abstract_factory.hpp:19
gko::accessor::one_operation
Definition: range.hpp:702
gko::range::get_accessor
constexpr const accessor & get_accessor() const noexcept
Returns a reference to the accessor.
Definition: range.hpp:427
gko::accessor::min_operation
Definition: range.hpp:969
gko::accessor::bitwise_and
Definition: range.hpp:957
gko::accessor::add
Definition: range.hpp:929
gko::accessor::squared_norm_operaton
Definition: range.hpp:720
gko::span
A span is a lightweight structure used to create sub-ranges from other ranges.
Definition: range.hpp:45
gko::accessor::zero_operation
Definition: range.hpp:700
gko::accessor::real_operaton
Definition: range.hpp:716
gko::accessor::conj_operaton
Definition: range.hpp:718
gko::accessor::bitwise_xor
Definition: range.hpp:959
gko::conj
constexpr auto conj(const T &x)
Returns the conjugate of an object.
Definition: math.hpp:929
gko::accessor::conj_operation
Definition: range.hpp:710
gko::accessor::mod
Definition: range.hpp:933
gko::transpose
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:118
gko::accessor::not_equal
Definition: range.hpp:945
gko::range::operator()
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:350
gko::accessor::equal
Definition: range.hpp:943
gko::accessor::left_shift
Definition: range.hpp:961
gko::accessor::real_operation
Definition: range.hpp:706
gko::range::length
constexpr size_type length(size_type dimension) const
Returns the length of the specified dimension of the range.
Definition: range.hpp:405
gko::range::dimensionality
static constexpr size_type dimensionality
The number of dimensions of the range.
Definition: range.hpp:312
gko::range::accessor
Accessor accessor
The type of the underlying accessor.
Definition: range.hpp:307
gko::accessor::mmul_operation
Definition: range.hpp:978
gko::accessor::transpose_operation
Definition: range.hpp:726
gko::accessor::greater
Definition: range.hpp:938
gko::accessor::bitwise_or
Definition: range.hpp:955
gko::accessor::imag_operaton
Definition: range.hpp:717
gko::min
constexpr T min(const T &x, const T &y)
Returns the smaller of the arguments.
Definition: math.hpp:749
gko::accessor::logical_and
Definition: range.hpp:951
gko::range::operator=
const range & operator=(const range &other) const
Assigns another range to this range.
Definition: range.hpp:389
gko::accessor::abs_operaton
Definition: range.hpp:715
gko::local_span
A span that is used exclusively for local numbering.
Definition: range.hpp:137
gko::range::operator=
const range & operator=(const range< OtherAccessor > &other) const
Definition: range.hpp:368
gko::real
constexpr auto real(const T &x)
Returns the real part of the object.
Definition: math.hpp:899
gko::accessor::less
Definition: range.hpp:936
gko::zero
constexpr T zero()
Returns the additive identity for T.
Definition: math.hpp:625
gko::accessor::logical_not
Definition: range.hpp:691
gko::one
constexpr T one()
Returns the multiplicative identity for T.
Definition: math.hpp:653
gko::imag
constexpr auto imag(const T &x)
Returns the imaginary part of the object.
Definition: math.hpp:915