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