Ginkgo Generated from branch based on master. Ginkgo version 1.7.0
A numerical linear algebra library targeting many-core architectures
Loading...
Searching...
No Matches
range.hpp
1/*******************************<GINKGO LICENSE>******************************
2Copyright (c) 2017-2023, the Ginkgo authors
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions
7are met:
8
91. Redistributions of source code must retain the above copyright
10notice, this list of conditions and the following disclaimer.
11
122. Redistributions in binary form must reproduce the above copyright
13notice, this list of conditions and the following disclaimer in the
14documentation and/or other materials provided with the distribution.
15
163. Neither the name of the copyright holder nor the names of its
17contributors may be used to endorse or promote products derived from
18this software without specific prior written permission.
19
20THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31******************************<GINKGO LICENSE>*******************************/
32
33#ifndef GKO_PUBLIC_CORE_BASE_RANGE_HPP_
34#define GKO_PUBLIC_CORE_BASE_RANGE_HPP_
35
36
37#include <type_traits>
38
39
40#include <ginkgo/core/base/math.hpp>
41#include <ginkgo/core/base/types.hpp>
42#include <ginkgo/core/base/utils.hpp>
43
44
45namespace gko {
46
47
75struct span {
83 GKO_ATTRIBUTES constexpr span(size_type point) noexcept
84 : span{point, point + 1}
85 {}
86
93 GKO_ATTRIBUTES constexpr span(size_type begin, size_type end) noexcept
94 : begin{begin}, end{end}
95 {}
96
102 GKO_ATTRIBUTES constexpr bool is_valid() const { return begin <= end; }
103
109 GKO_ATTRIBUTES constexpr size_type length() const { return end - begin; }
110
115
120};
121
122
123GKO_ATTRIBUTES GKO_INLINE constexpr bool operator<(const span& first,
124 const span& second)
125{
126 return first.end < second.begin;
127}
128
129
130GKO_ATTRIBUTES GKO_INLINE constexpr bool operator<=(const span& first,
131 const span& second)
132{
133 return first.end <= second.begin;
134}
135
136
137GKO_ATTRIBUTES GKO_INLINE constexpr bool operator>(const span& first,
138 const span& second)
139{
140 return second < first;
141}
142
143
144GKO_ATTRIBUTES GKO_INLINE constexpr bool operator>=(const span& first,
145 const span& second)
146{
147 return second <= first;
148}
149
150
151GKO_ATTRIBUTES GKO_INLINE constexpr bool operator==(const span& first,
152 const span& second)
153{
154 return first.begin == second.begin && first.end == second.end;
155}
156
157
158GKO_ATTRIBUTES GKO_INLINE constexpr bool operator!=(const span& first,
159 const span& second)
160{
161 return !(first == second);
162}
163
164
165namespace detail {
166
167
168template <size_type CurrentDimension = 0, typename FirstRange,
169 typename SecondRange>
170GKO_ATTRIBUTES constexpr GKO_INLINE
171 std::enable_if_t<(CurrentDimension >= max(FirstRange::dimensionality,
172 SecondRange::dimensionality)),
173 bool>
174 equal_dimensions(const FirstRange&, const SecondRange&)
175{
176 return true;
177}
178
179template <size_type CurrentDimension = 0, typename FirstRange,
180 typename SecondRange>
181GKO_ATTRIBUTES constexpr GKO_INLINE
182 std::enable_if_t<(CurrentDimension < max(FirstRange::dimensionality,
183 SecondRange::dimensionality)),
184 bool>
185 equal_dimensions(const FirstRange& first, const SecondRange& second)
186{
187 return first.length(CurrentDimension) == second.length(CurrentDimension) &&
189}
190
195template <class...>
196struct head;
197
201template <class First, class... Rest>
202struct head<First, Rest...> {
203 using type = First;
204};
205
209template <class... T>
210using head_t = typename head<T...>::type;
211
212
213} // namespace detail
214
215
325template <typename Accessor>
326class range {
327public:
332
336 static constexpr size_type dimensionality = accessor::dimensionality;
337
341 ~range() = default;
342
351 template <
352 typename... AccessorParams,
353 typename = std::enable_if_t<
354 sizeof...(AccessorParams) != 1 ||
355 !std::is_same<
356 range, std::decay<detail::head_t<AccessorParams...>>>::value>>
357 GKO_ATTRIBUTES constexpr explicit range(AccessorParams&&... params)
358 : accessor_{std::forward<AccessorParams>(params)...}
359 {}
360
373 template <typename... DimensionTypes>
374 GKO_ATTRIBUTES constexpr auto operator()(DimensionTypes&&... dimensions)
375 const -> decltype(std::declval<accessor>()(
376 std::forward<DimensionTypes>(dimensions)...))
377 {
378 static_assert(sizeof...(DimensionTypes) <= dimensionality,
379 "Too many dimensions in range call");
380 return accessor_(std::forward<DimensionTypes>(dimensions)...);
381 }
382
391 template <typename OtherAccessor>
392 GKO_ATTRIBUTES const range& operator=(
393 const range<OtherAccessor>& other) const
394 {
395 GKO_ASSERT(detail::equal_dimensions(*this, other));
396 accessor_.copy_from(other);
397 return *this;
398 }
399
413 GKO_ATTRIBUTES const range& operator=(const range& other) const
414 {
415 GKO_ASSERT(detail::equal_dimensions(*this, other));
416 accessor_.copy_from(other.get_accessor());
417 return *this;
418 }
419
420 range(const range& other) = default;
421
429 GKO_ATTRIBUTES constexpr size_type length(size_type dimension) const
430 {
431 return accessor_.length(dimension);
432 }
433
441 GKO_ATTRIBUTES constexpr const accessor* operator->() const noexcept
442 {
443 return &accessor_;
444 }
445
451 GKO_ATTRIBUTES constexpr const accessor& get_accessor() const noexcept
452 {
453 return accessor_;
454 }
455
456private:
457 accessor accessor_;
458};
459
460
461// implementation of range operations follows
462// (you probably should not have to look at this unless you're interested in the
463// gory details)
464
465
466namespace detail {
467
468
469enum class operation_kind { range_by_range, scalar_by_range, range_by_scalar };
470
471
472template <typename Accessor, typename Operation>
473struct implement_unary_operation {
474 using accessor = Accessor;
475 static constexpr size_type dimensionality = accessor::dimensionality;
476
477 GKO_ATTRIBUTES constexpr explicit implement_unary_operation(
478 const Accessor& operand)
479 : operand{operand}
480 {}
481
482 template <typename... DimensionTypes>
483 GKO_ATTRIBUTES constexpr auto operator()(
484 const DimensionTypes&... dimensions) const
485 -> decltype(Operation::evaluate(std::declval<accessor>(),
486 dimensions...))
487 {
488 return Operation::evaluate(operand, dimensions...);
489 }
490
491 GKO_ATTRIBUTES constexpr size_type length(size_type dimension) const
492 {
493 return operand.length(dimension);
494 }
495
496 template <typename OtherAccessor>
497 GKO_ATTRIBUTES void copy_from(const OtherAccessor& other) const = delete;
498
499 const accessor operand;
500};
501
502
503template <operation_kind Kind, typename FirstOperand, typename SecondOperand,
504 typename Operation>
505struct implement_binary_operation {};
506
507template <typename FirstAccessor, typename SecondAccessor, typename Operation>
508struct implement_binary_operation<operation_kind::range_by_range, FirstAccessor,
509 SecondAccessor, Operation> {
510 using first_accessor = FirstAccessor;
511 using second_accessor = SecondAccessor;
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;
516
517 GKO_ATTRIBUTES explicit implement_binary_operation(
518 const FirstAccessor& first, const SecondAccessor& second)
519 : first{first}, second{second}
520 {
521 GKO_ASSERT(gko::detail::equal_dimensions(first, second));
522 }
523
524 template <typename... DimensionTypes>
525 GKO_ATTRIBUTES constexpr auto operator()(
526 const DimensionTypes&... dimensions) const
527 -> decltype(Operation::evaluate_range_by_range(
528 std::declval<first_accessor>(), std::declval<second_accessor>(),
529 dimensions...))
530 {
531 return Operation::evaluate_range_by_range(first, second, dimensions...);
532 }
533
534 GKO_ATTRIBUTES constexpr size_type length(size_type dimension) const
535 {
536 return first.length(dimension);
537 }
538
539 template <typename OtherAccessor>
540 GKO_ATTRIBUTES void copy_from(const OtherAccessor& other) const = delete;
541
542 const first_accessor first;
543 const second_accessor second;
544};
545
546template <typename FirstOperand, typename SecondAccessor, typename Operation>
547struct implement_binary_operation<operation_kind::scalar_by_range, FirstOperand,
548 SecondAccessor, Operation> {
549 using second_accessor = SecondAccessor;
550 static constexpr size_type dimensionality = second_accessor::dimensionality;
551
552 GKO_ATTRIBUTES constexpr explicit implement_binary_operation(
553 const FirstOperand& first, const SecondAccessor& second)
554 : first{first}, second{second}
555 {}
556
557 template <typename... DimensionTypes>
558 GKO_ATTRIBUTES constexpr auto operator()(
559 const DimensionTypes&... dimensions) const
560 -> decltype(Operation::evaluate_scalar_by_range(
561 std::declval<FirstOperand>(), std::declval<second_accessor>(),
562 dimensions...))
563 {
564 return Operation::evaluate_scalar_by_range(first, second,
565 dimensions...);
566 }
567
568 GKO_ATTRIBUTES constexpr size_type length(size_type dimension) const
569 {
570 return second.length(dimension);
571 }
572
573 template <typename OtherAccessor>
574 GKO_ATTRIBUTES void copy_from(const OtherAccessor& other) const = delete;
575
576 const FirstOperand first;
577 const second_accessor second;
578};
579
580template <typename FirstAccessor, typename SecondOperand, typename Operation>
581struct implement_binary_operation<operation_kind::range_by_scalar,
582 FirstAccessor, SecondOperand, Operation> {
583 using first_accessor = FirstAccessor;
584 static constexpr size_type dimensionality = first_accessor::dimensionality;
585
586 GKO_ATTRIBUTES constexpr explicit implement_binary_operation(
587 const FirstAccessor& first, const SecondOperand& second)
588 : first{first}, second{second}
589 {}
590
591 template <typename... DimensionTypes>
592 GKO_ATTRIBUTES constexpr auto operator()(
593 const DimensionTypes&... dimensions) const
594 -> decltype(Operation::evaluate_range_by_scalar(
595 std::declval<first_accessor>(), std::declval<SecondOperand>(),
596 dimensions...))
597 {
598 return Operation::evaluate_range_by_scalar(first, second,
599 dimensions...);
600 }
601
602 GKO_ATTRIBUTES constexpr size_type length(size_type dimension) const
603 {
604 return first.length(dimension);
605 }
606
607 template <typename OtherAccessor>
608 GKO_ATTRIBUTES void copy_from(const OtherAccessor& other) const = delete;
609
610 const first_accessor first;
611 const SecondOperand second;
612};
613
614
615} // namespace detail
616
617#define GKO_DEPRECATED_UNARY_RANGE_OPERATION(_operation_deprecated_name, \
618 _operation_name) \
619 namespace accessor { \
620 template <typename Operand> \
621 struct GKO_DEPRECATED("Please use " #_operation_name) \
622 _operation_deprecated_name : _operation_name<Operand> {}; \
623 } \
624 static_assert(true, \
625 "This assert is used to counter the false positive extra " \
626 "semi-colon warnings")
627
628
629#define GKO_ENABLE_UNARY_RANGE_OPERATION(_operation_name, _operator_name, \
630 _operator) \
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; \
638 }; \
639 } \
640 GKO_BIND_UNARY_RANGE_OPERATION_TO_OPERATOR(_operation_name, _operator_name)
641
642
643#define GKO_BIND_UNARY_RANGE_OPERATION_TO_OPERATOR(_operation_name, \
644 _operator_name) \
645 template <typename Accessor> \
646 GKO_ATTRIBUTES constexpr GKO_INLINE \
647 range<accessor::_operation_name<Accessor>> \
648 _operator_name(const range<Accessor>& operand) \
649 { \
650 return range<accessor::_operation_name<Accessor>>( \
651 operand.get_accessor()); \
652 } \
653 static_assert(true, \
654 "This assert is used to counter the false positive extra " \
655 "semi-colon warnings")
656
657
658#define GKO_DEFINE_SIMPLE_UNARY_OPERATION(_name, ...) \
659 struct _name { \
660 private: \
661 template <typename Operand> \
662 GKO_ATTRIBUTES static constexpr auto simple_evaluate_impl( \
663 const Operand& operand) -> decltype(__VA_ARGS__) \
664 { \
665 return __VA_ARGS__; \
666 } \
667 \
668 public: \
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...))) \
673 { \
674 return simple_evaluate_impl(accessor(dimensions...)); \
675 } \
676 }
677
678
679namespace accessor {
680namespace detail {
681
682
683// unary arithmetic
684GKO_DEFINE_SIMPLE_UNARY_OPERATION(unary_plus, +operand);
685GKO_DEFINE_SIMPLE_UNARY_OPERATION(unary_minus, -operand);
686
687// unary logical
688GKO_DEFINE_SIMPLE_UNARY_OPERATION(logical_not, !operand);
689
690// unary bitwise
691GKO_DEFINE_SIMPLE_UNARY_OPERATION(bitwise_not, ~(operand));
692
693// common functions
694GKO_DEFINE_SIMPLE_UNARY_OPERATION(zero_operation, zero(operand));
695GKO_DEFINE_SIMPLE_UNARY_OPERATION(one_operation, one(operand));
696GKO_DEFINE_SIMPLE_UNARY_OPERATION(abs_operation, abs(operand));
697GKO_DEFINE_SIMPLE_UNARY_OPERATION(real_operation, real(operand));
698GKO_DEFINE_SIMPLE_UNARY_OPERATION(imag_operation, imag(operand));
699GKO_DEFINE_SIMPLE_UNARY_OPERATION(conj_operation, conj(operand));
700GKO_DEFINE_SIMPLE_UNARY_OPERATION(squared_norm_operation,
701 squared_norm(operand));
702
703} // namespace detail
704} // namespace accessor
705
706
707// unary arithmetic
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);
712
713// unary logical
714GKO_ENABLE_UNARY_RANGE_OPERATION(logical_not, operator!,
715 accessor::detail::logical_not);
716
717// unary bitwise
718GKO_ENABLE_UNARY_RANGE_OPERATION(bitwise_not, operator~,
719 accessor::detail::bitwise_not);
720
721// common unary functions
722
723GKO_ENABLE_UNARY_RANGE_OPERATION(zero_operation, zero,
724 accessor::detail::zero_operation);
725GKO_ENABLE_UNARY_RANGE_OPERATION(one_operation, one,
726 accessor::detail::one_operation);
727GKO_ENABLE_UNARY_RANGE_OPERATION(abs_operation, abs,
728 accessor::detail::abs_operation);
729GKO_ENABLE_UNARY_RANGE_OPERATION(real_operation, real,
730 accessor::detail::real_operation);
731GKO_ENABLE_UNARY_RANGE_OPERATION(imag_operation, imag,
732 accessor::detail::imag_operation);
733GKO_ENABLE_UNARY_RANGE_OPERATION(conj_operation, conj,
734 accessor::detail::conj_operation);
735GKO_ENABLE_UNARY_RANGE_OPERATION(squared_norm_operation, squared_norm,
736 accessor::detail::squared_norm_operation);
737
738GKO_DEPRECATED_UNARY_RANGE_OPERATION(one_operaton, one_operation);
739GKO_DEPRECATED_UNARY_RANGE_OPERATION(abs_operaton, abs_operation);
740GKO_DEPRECATED_UNARY_RANGE_OPERATION(real_operaton, real_operation);
741GKO_DEPRECATED_UNARY_RANGE_OPERATION(imag_operaton, imag_operation);
742GKO_DEPRECATED_UNARY_RANGE_OPERATION(conj_operaton, conj_operation);
743GKO_DEPRECATED_UNARY_RANGE_OPERATION(squared_norm_operaton,
745
746namespace accessor {
747
748
749template <typename Accessor>
751 using accessor = Accessor;
752 static constexpr size_type dimensionality = accessor::dimensionality;
753
754 GKO_ATTRIBUTES constexpr explicit transpose_operation(
755 const Accessor& operand)
756 : operand{operand}
757 {}
758
759 template <typename FirstDimensionType, typename SecondDimensionType,
760 typename... DimensionTypes>
761 GKO_ATTRIBUTES constexpr auto operator()(
764 const DimensionTypes&... dims) const
765 -> decltype(std::declval<accessor>()(second_dim, first_dim, dims...))
766 {
767 return operand(second_dim, first_dim, dims...);
768 }
769
770 GKO_ATTRIBUTES constexpr size_type length(size_type dimension) const
771 {
772 return dimension < 2 ? operand.length(dimension ^ 1)
773 : operand.length(dimension);
774 }
775
776 template <typename OtherAccessor>
777 GKO_ATTRIBUTES void copy_from(const OtherAccessor& other) const = delete;
778
779 const accessor operand;
780};
781
782
783} // namespace accessor
784
785
786GKO_BIND_UNARY_RANGE_OPERATION_TO_OPERATOR(transpose_operation, transpose);
787
788
789#undef GKO_DEPRECATED_UNARY_RANGE_OPERATION
790#undef GKO_DEFINE_SIMPLE_UNARY_OPERATION
791#undef GKO_ENABLE_UNARY_RANGE_OPERATION
792
793
794#define GKO_ENABLE_BINARY_RANGE_OPERATION(_operation_name, _operator_name, \
795 _operator) \
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; \
805 }; \
806 } \
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")
811
812
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) \
819 { \
820 return range<accessor::_operation_name< \
821 ::gko::detail::operation_kind::range_by_range, Accessor, \
822 Accessor>>(first.get_accessor(), second.get_accessor()); \
823 } \
824 \
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, \
828 SecondAccessor>> \
829 _operator_name(const range<FirstAccessor>& first, \
830 const range<SecondAccessor>& second) \
831 { \
832 return range<accessor::_operation_name< \
833 ::gko::detail::operation_kind::range_by_range, FirstAccessor, \
834 SecondAccessor>>(first.get_accessor(), second.get_accessor()); \
835 } \
836 \
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, \
840 SecondOperand>> \
841 _operator_name(const range<FirstAccessor>& first, \
842 const SecondOperand& second) \
843 { \
844 return range<accessor::_operation_name< \
845 ::gko::detail::operation_kind::range_by_scalar, FirstAccessor, \
846 SecondOperand>>(first.get_accessor(), second); \
847 } \
848 \
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, \
852 SecondAccessor>> \
853 _operator_name(const FirstOperand& first, \
854 const range<SecondAccessor>& second) \
855 { \
856 return range<accessor::_operation_name< \
857 ::gko::detail::operation_kind::scalar_by_range, FirstOperand, \
858 SecondAccessor>>(first, second.get_accessor()); \
859 } \
860 static_assert(true, \
861 "This assert is used to counter the false positive extra " \
862 "semi-colon warnings")
863
864
865#define GKO_DEPRECATED_SIMPLE_BINARY_OPERATION(_deprecated_name, _name) \
866 struct GKO_DEPRECATED("Please use " #_name) _deprecated_name : _name {}
867
868#define GKO_DEFINE_SIMPLE_BINARY_OPERATION(_name, ...) \
869 struct _name { \
870 private: \
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__) \
875 { \
876 return __VA_ARGS__; \
877 } \
878 \
879 public: \
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...))) \
886 { \
887 return simple_evaluate_impl(first(dims...), second(dims...)); \
888 } \
889 \
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...))) \
896 { \
897 return simple_evaluate_impl(first, second(dims...)); \
898 } \
899 \
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)) \
906 { \
907 return simple_evaluate_impl(first(dims...), second); \
908 } \
909 }
910
911
912namespace accessor {
913namespace detail {
914
915
916// binary arithmetic
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);
922
923// relational
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);
930
931// binary logical
932GKO_DEFINE_SIMPLE_BINARY_OPERATION(logical_or, first || second);
933GKO_DEFINE_SIMPLE_BINARY_OPERATION(logical_and, first&& second);
934
935// binary bitwise
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);
941
942// common binary functions
943GKO_DEFINE_SIMPLE_BINARY_OPERATION(max_operation, max(first, second));
944GKO_DEFINE_SIMPLE_BINARY_OPERATION(min_operation, min(first, second));
945
946GKO_DEPRECATED_SIMPLE_BINARY_OPERATION(max_operaton, max_operation);
947GKO_DEPRECATED_SIMPLE_BINARY_OPERATION(min_operaton, min_operation);
948} // namespace detail
949} // namespace accessor
950
951
952// binary arithmetic
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);
958
959// relational
960GKO_ENABLE_BINARY_RANGE_OPERATION(less, operator<, accessor::detail::less);
961GKO_ENABLE_BINARY_RANGE_OPERATION(greater, operator>,
962 accessor::detail::greater);
963GKO_ENABLE_BINARY_RANGE_OPERATION(less_or_equal, operator<=,
964 accessor::detail::less_or_equal);
965GKO_ENABLE_BINARY_RANGE_OPERATION(greater_or_equal, operator>=,
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);
970
971// binary logical
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);
976
977// binary bitwise
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);
988
989// common binary functions
990GKO_ENABLE_BINARY_RANGE_OPERATION(max_operation, max,
991 accessor::detail::max_operation);
992GKO_ENABLE_BINARY_RANGE_OPERATION(min_operation, min,
993 accessor::detail::min_operation);
994
995
996// special binary range functions
997namespace accessor {
998
999
1000template <gko::detail::operation_kind Kind, typename FirstAccessor,
1001 typename SecondAccessor>
1003 static_assert(Kind == gko::detail::operation_kind::range_by_range,
1004 "Matrix multiplication expects both operands to be ranges");
1005 using first_accessor = FirstAccessor;
1006 using second_accessor = SecondAccessor;
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;
1011
1012 GKO_ATTRIBUTES explicit mmul_operation(const FirstAccessor& first,
1013 const SecondAccessor& second)
1014 : first{first}, second{second}
1015 {
1016 GKO_ASSERT(first.length(1) == second.length(0));
1017 GKO_ASSERT(gko::detail::equal_dimensions<2>(first, second));
1018 }
1019
1020 template <typename FirstDimension, typename SecondDimension,
1021 typename... DimensionTypes>
1022 GKO_ATTRIBUTES auto operator()(const FirstDimension& row,
1023 const SecondDimension& col,
1024 const DimensionTypes&... rest) const
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...))
1029 {
1030 using result_type =
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));
1034 auto result = zero<result_type>();
1035 const auto size = first.length(1);
1036 for (auto i = zero(size); i < size; ++i) {
1037 result += first(row, i, rest...) * second(i, col, rest...);
1038 }
1039 return result;
1040 }
1041
1042 GKO_ATTRIBUTES constexpr size_type length(size_type dimension) const
1043 {
1044 return dimension == 1 ? second.length(1) : first.length(dimension);
1045 }
1046
1047 template <typename OtherAccessor>
1048 GKO_ATTRIBUTES void copy_from(const OtherAccessor& other) const = delete;
1049
1050 const first_accessor first;
1051 const second_accessor second;
1052};
1053
1054
1055} // namespace accessor
1056
1057
1058GKO_BIND_RANGE_OPERATION_TO_OPERATOR(mmul_operation, mmul);
1059
1060
1061#undef GKO_DEFINE_SIMPLE_BINARY_OPERATION
1062#undef GKO_ENABLE_BINARY_RANGE_OPERATION
1063
1064
1065} // namespace gko
1066
1067
1068#endif // GKO_PUBLIC_CORE_BASE_RANGE_HPP_
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:728
Definition range.hpp:739
Definition range.hpp:953
Definition range.hpp:981
Definition range.hpp:719
Definition range.hpp:979
Definition range.hpp:983
Definition range.hpp:734
Definition range.hpp:742
Definition range.hpp:956
Definition range.hpp:967
Definition range.hpp:966
Definition range.hpp:962
Definition range.hpp:732
Definition range.hpp:741
Definition range.hpp:985
Definition range.hpp:964
Definition range.hpp:960
Definition range.hpp:975
Definition range.hpp:715
Definition range.hpp:973
Definition range.hpp:991
Definition range.hpp:993
Definition range.hpp:1002
Definition range.hpp:957
Definition range.hpp:955
Definition range.hpp:969
Definition range.hpp:726
Definition range.hpp:738
Definition range.hpp:730
Definition range.hpp:740
Definition range.hpp:987
Definition range.hpp:744
Definition range.hpp:954
Definition range.hpp:750
Definition range.hpp:711
Definition range.hpp:709
Definition range.hpp:724
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