tile.h
Go to the documentation of this file.
1 /*
2  * This file is a part of TiledArray.
3  * Copyright (C) 2015 Virginia Tech
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  */
19 
20 #ifndef TILEDARRAY_TILE_H__INCLUDED
21 #define TILEDARRAY_TILE_H__INCLUDED
22 
26 #include <memory>
27 
28 // Forward declaration of MADNESS archive type traits
29 namespace madness {
30 namespace archive {
31 
32 template <typename>
34 template <typename>
36 
37 } // namespace archive
38 } // namespace madness
39 
40 namespace TiledArray {
41 
47 
81 template <typename T>
82 class Tile {
83  public:
85  typedef Tile<T> Tile_;
87  typedef T tensor_type;
88  // import types from T
89  using value_type = typename tensor_type::value_type;
90  using range_type = typename tensor_type::range_type;
91  using index1_type = typename tensor_type::index1_type;
92  using size_type =
93  typename tensor_type::ordinal_type;
94  using reference =
96  typename tensor_type::reference;
98  typename tensor_type::const_reference;
99  using iterator = typename tensor_type::iterator;
101  typename tensor_type::const_iterator;
102  using pointer = typename tensor_type::pointer;
104  typename tensor_type::const_pointer;
106  tensor_type>::type;
108  tensor_type>::type;
109 
110  private:
111  std::shared_ptr<tensor_type> pimpl_;
112 
113  public:
114  // Constructors and destructor ---------------------------------------------
115 
116  Tile() = default;
117  Tile(const Tile_&) = default;
118  Tile(Tile_&&) = default;
119 
121 
127  template <typename Arg,
128  typename = typename std::enable_if<
130  not std::is_convertible<Arg, Tile_>::value &&
132  Arg, Tile_>::value>::type>
133  explicit Tile(Arg&& arg)
134  : pimpl_(std::make_shared<tensor_type>(std::forward<Arg>(arg))) {}
135 
136  template <typename Arg1, typename Arg2, typename... Args>
137  Tile(Arg1&& arg1, Arg2&& arg2, Args&&... args)
138  : pimpl_(std::make_shared<tensor_type>(std::forward<Arg1>(arg1),
139  std::forward<Arg2>(arg2),
140  std::forward<Args>(args)...)) {}
141 
142  ~Tile() = default;
143 
144  // Assignment operators ----------------------------------------------------
145 
146  Tile_& operator=(Tile_&&) = default;
147  Tile_& operator=(const Tile_&) = default;
148 
150  *pimpl_ = tensor;
151  return *this;
152  }
153 
155  *pimpl_ = std::move(tensor);
156  return *this;
157  }
158 
159  // State accessor ----------------------------------------------------------
160 
161  bool empty() const { return pimpl_ ? pimpl_->empty() : true; }
162 
163  // Tile accessor -----------------------------------------------------------
164 
165  tensor_type& tensor() { return *pimpl_; }
166 
167  const tensor_type& tensor() const { return *pimpl_; }
168 
169  // Iterator accessor -------------------------------------------------------
170 
172 
174  decltype(auto) begin() { return std::begin(tensor()); }
175 
177 
179  decltype(auto) begin() const { return std::begin(tensor()); }
180 
182 
184  decltype(auto) end() { return std::end(tensor()); }
185 
187 
189  decltype(auto) end() const { return std::end(tensor()); }
190 
191  // Data accessor -------------------------------------------------------
192 
194 
196  decltype(auto) data() { return tensor().data(); }
197 
199 
201  decltype(auto) data() const { return tensor().data(); }
202 
203  // Dimension information accessors -----------------------------------------
204 
206 
208  decltype(auto) size() const { return tensor().size(); }
209 
211 
213  decltype(auto) range() const { return tensor().range(); }
214 
215  // Element accessors -------------------------------------------------------
216 
218 
224  template <typename Ordinal,
225  std::enable_if_t<std::is_integral<Ordinal>::value>* = nullptr>
226  const_reference operator[](const Ordinal ord) const {
227  TA_ASSERT(pimpl_);
228  TA_ASSERT(tensor().range().includes(ord));
229  return tensor().data()[ord];
230  }
231 
233 
239  template <typename Ordinal,
240  std::enable_if_t<std::is_integral<Ordinal>::value>* = nullptr>
241  reference operator[](const Ordinal ord) {
242  TA_ASSERT(pimpl_);
243  TA_ASSERT(tensor().range().includes(ord));
244  return tensor().data()[ord];
245  }
246 
248 
254  template <typename Index,
255  std::enable_if_t<detail::is_integral_range_v<Index>>* = nullptr>
256  const_reference operator[](const Index& i) const {
257  TA_ASSERT(pimpl_);
258  TA_ASSERT(tensor().range().includes(i));
259  return tensor().data()[tensor().range().ordinal(i)];
260  }
261 
263 
269  template <typename Index,
270  std::enable_if_t<detail::is_integral_range_v<Index>>* = nullptr>
271  reference operator[](const Index& i) {
272  TA_ASSERT(pimpl_);
273  TA_ASSERT(tensor().range().includes(i));
274  return tensor().data()[tensor().range().ordinal(i)];
275  }
276 
278 
284  template <typename Index,
285  typename = std::enable_if_t<std::is_integral_v<Index>>>
286  const_reference operator[](const std::initializer_list<Index>& i) const {
287  TA_ASSERT(pimpl_);
288  TA_ASSERT(tensor().range().includes(i));
289  return tensor().data()[tensor().range().ordinal(i)];
290  }
291 
293 
299  template <typename Index,
300  typename = std::enable_if_t<std::is_integral_v<Index>>>
301  reference operator[](const std::initializer_list<Index>& i) {
302  TA_ASSERT(pimpl_);
303  TA_ASSERT(tensor().range().includes(i));
304  return tensor().data()[tensor().range().ordinal(i)];
305  }
306 
308 
314  template <typename Index,
315  std::enable_if_t<detail::is_integral_range_v<Index>>* = nullptr>
316  const_reference operator()(const Index& i) const {
317  TA_ASSERT(pimpl_);
318  TA_ASSERT(tensor().range().includes(i));
319  return tensor().data()[tensor().range().ordinal(i)];
320  }
321 
323 
329  template <typename Index,
330  std::enable_if_t<detail::is_integral_range_v<Index>>* = nullptr>
331  reference operator()(const Index& i) {
332  TA_ASSERT(pimpl_);
333  TA_ASSERT(tensor().range().includes(i));
334  return tensor().data()[tensor().range().ordinal(i)];
335  }
336 
338 
344  template <typename Index,
345  typename = std::enable_if_t<std::is_integral_v<Index>>>
346  const_reference operator()(const std::initializer_list<Index>& i) const {
347  TA_ASSERT(pimpl_);
348  TA_ASSERT(tensor().range().includes(i));
349  return tensor().data()[tensor().range().ordinal(i)];
350  }
351 
353 
359  template <typename Index,
360  typename = std::enable_if_t<std::is_integral_v<Index>>>
361  reference operator()(const std::initializer_list<Index>& i) {
362  TA_ASSERT(pimpl_);
363  TA_ASSERT(tensor().range().includes(i));
364  return tensor().data()[tensor().range().ordinal(i)];
365  }
366 
368 
373  template <
374  typename... Index,
375  std::enable_if_t<detail::is_integral_list<Index...>::value>* = nullptr>
376  const_reference operator()(const Index&... i) const {
377  TA_ASSERT(pimpl_);
378  TA_ASSERT(tensor().range().includes(i...));
379  return tensor().data()[tensor().range().ordinal(i...)];
380  }
381 
383 
388  template <
389  typename... Index,
390  std::enable_if_t<detail::is_integral_list<Index...>::value>* = nullptr>
391  reference operator()(const Index&... i) {
392  TA_ASSERT(pimpl_);
393  TA_ASSERT(tensor().range().includes(i...));
394  return tensor().data()[tensor().range().ordinal(i...)];
395  }
396 
397  // Block accessors -----------------------------------------------------------
398 
399  // clang-format off
401 
418  // clang-format on
420  template <typename Index1, typename Index2,
421  typename = std::enable_if_t<detail::is_integral_range_v<Index1> &&
422  detail::is_integral_range_v<Index2>>>
423  decltype(auto) block(const Index1& lower_bound, const Index2& upper_bound) {
424  TA_ASSERT(pimpl_);
426  BlockRange(tensor().range(), lower_bound, upper_bound),
427  tensor().data());
428  }
429 
430  template <typename Index1, typename Index2,
431  typename = std::enable_if_t<detail::is_integral_range_v<Index1> &&
432  detail::is_integral_range_v<Index2>>>
433  decltype(auto) block(const Index1& lower_bound,
434  const Index2& upper_bound) const {
435  TA_ASSERT(pimpl_);
437  BlockRange(tensor().range(), lower_bound, upper_bound),
438  tensor().data());
439  }
441 
442  // clang-format off
444 
459  // clang-format on
461  template <typename Index1, typename Index2,
462  typename = std::enable_if_t<std::is_integral_v<Index1> &&
463  std::is_integral_v<Index2>>>
464  decltype(auto) block(const std::initializer_list<Index1>& lower_bound,
465  const std::initializer_list<Index2>& upper_bound) {
466  TA_ASSERT(pimpl_);
468  BlockRange(tensor().range(), lower_bound, upper_bound),
469  tensor().data());
470  }
471 
472  template <typename Index1, typename Index2,
473  typename = std::enable_if_t<std::is_integral_v<Index1> &&
474  std::is_integral_v<Index2>>>
475  decltype(auto) block(const std::initializer_list<Index1>& lower_bound,
476  const std::initializer_list<Index2>& upper_bound) const {
477  TA_ASSERT(pimpl_);
479  BlockRange(tensor().range(), lower_bound, upper_bound),
480  tensor().data());
481  }
483 
484  // clang-format off
486 
516  // clang-format on
518  template <typename PairRange,
519  typename = std::enable_if_t<detail::is_gpair_range_v<PairRange>>>
520  decltype(auto) block(const PairRange& bounds) {
521  TA_ASSERT(pimpl_);
523  BlockRange(tensor().range(), bounds), tensor().data());
524  }
525 
526  template <typename PairRange,
527  typename = std::enable_if_t<detail::is_gpair_range_v<PairRange>>>
528  decltype(auto) block(const PairRange& bounds) const {
529  TA_ASSERT(pimpl_);
531  BlockRange(tensor().range(), bounds), tensor().data());
532  }
534 
535  // clang-format off
537 
548  // clang-format on
550  template <typename Index,
551  typename = std::enable_if_t<std::is_integral_v<Index>>>
552  decltype(auto) block(
553  const std::initializer_list<std::initializer_list<Index>>& bounds) {
554  TA_ASSERT(pimpl_);
556  BlockRange(tensor().range(), bounds), tensor().data());
557  }
558 
559  template <typename Index,
560  typename = std::enable_if_t<std::is_integral_v<Index>>>
561  decltype(auto) block(
562  const std::initializer_list<std::initializer_list<Index>>& bounds) const {
563  TA_ASSERT(pimpl_);
565  BlockRange(tensor().range(), bounds), tensor().data());
566  }
568 
569  // Serialization -----------------------------------------------------------
570 
571  template <typename Archive,
572  typename std::enable_if<madness::archive::is_output_archive<
573  Archive>::value>::type* = nullptr>
574  void serialize(Archive& ar) const {
575  // Serialize data for empty tile check
576  bool empty = !static_cast<bool>(pimpl_);
577  ar& empty;
578  if (!empty) {
579  // Serialize tile data
580  ar&* pimpl_;
581  }
582  }
583 
584  template <typename Archive,
585  typename std::enable_if<madness::archive::is_input_archive<
586  Archive>::value>::type* = nullptr>
587  void serialize(Archive& ar) {
588  // Check for empty tile
589  bool empty = false;
590  ar& empty;
591 
592  if (!empty) {
593  // Deserialize tile data
595  ar& tensor;
596 
597  // construct a new pimpl
598  pimpl_ = std::make_shared<T>(std::move(tensor));
599  } else {
600  // Set pimpl to an empty tile
601  pimpl_.reset();
602  }
603  }
604 
605 }; // class Tile
606 
607 // The following functions define the non-intrusive interface used to apply
608 // math operations to Tiles. These functions in turn use the non-intrusive
609 // interface functions to evaluate tiles.
610 
611 namespace detail {
612 
614 
618 template <typename T>
620  return Tile<T>(std::forward<T>(t));
621 }
622 
623 } // namespace detail
624 
625 // Clone operations ----------------------------------------------------------
626 
628 
632 template <typename Arg>
633 inline Tile<Arg> clone(const Tile<Arg>& arg) {
634  return Tile<Arg>(clone(arg.tensor()));
635 }
636 
637 #if __cplusplus <= 201402L
638 // Empty operations ----------------------------------------------------------
639 
641 
645 template <typename Arg>
646 inline bool empty(const Tile<Arg>& arg) {
647  return arg.empty() || empty(arg.tensor());
648 }
649 #endif
650 
651 // Permutation operations ----------------------------------------------------
652 
654 
660 template <typename Arg, typename Perm,
661  typename = std::enable_if_t<detail::is_permutation_v<Perm>>>
662 inline decltype(auto) permute(const Tile<Arg>& arg, const Perm& perm) {
663  return Tile<Arg>(permute(arg.tensor(), perm));
664 }
665 
666 // Shift operations ----------------------------------------------------------
667 
669 
675 template <typename Arg, typename Index,
676  typename = std::enable_if_t<detail::is_integral_range_v<Index>>>
677 inline decltype(auto) shift(const Tile<Arg>& arg, const Index& range_shift) {
678  return detail::make_tile(shift(arg.tensor(), range_shift));
679 }
680 
682 
688 template <typename Arg, typename Index,
689  typename = std::enable_if_t<std::is_integral_v<Index>>>
690 inline decltype(auto) shift(const Tile<Arg>& arg,
691  const std::initializer_list<Index>& range_shift) {
692  return detail::make_tile(shift(arg.tensor(), range_shift));
693 }
694 
696 
702 template <typename Arg, typename Index,
703  typename = std::enable_if_t<detail::is_integral_range_v<Index>>>
704 inline Tile<Arg>& shift_to(Tile<Arg>& arg, const Index& range_shift) {
705  shift_to(arg.tensor(), range_shift);
706  return arg;
707 }
708 
710 
716 template <typename Arg, typename Index,
717  typename = std::enable_if_t<std::is_integral_v<Index>>>
719  const std::initializer_list<Index>& range_shift) {
720  shift_to(arg.tensor(), range_shift);
721  return arg;
722 }
723 
724 // Addition operations -------------------------------------------------------
725 
727 
733 template <typename Left, typename Right>
734 inline decltype(auto) add(const Tile<Left>& left, const Tile<Right>& right) {
735  return detail::make_tile(add(left.tensor(), right.tensor()));
736 }
737 
739 
747 template <
748  typename Left, typename Right, typename Scalar,
749  typename std::enable_if<detail::is_numeric_v<Scalar>>::type* = nullptr>
750 inline decltype(auto) add(const Tile<Left>& left, const Tile<Right>& right,
751  const Scalar factor) {
752  return detail::make_tile(add(left.tensor(), right.tensor(), factor));
753 }
754 
756 
764 template <typename Left, typename Right, typename Perm,
765  typename = std::enable_if_t<detail::is_permutation_v<Perm>>>
766 inline decltype(auto) add(const Tile<Left>& left, const Tile<Right>& right,
767  const Perm& perm) {
768  return detail::make_tile(add(left.tensor(), right.tensor(), perm));
769 }
770 
772 
782 template <
783  typename Left, typename Right, typename Scalar, typename Perm,
784  typename std::enable_if<detail::is_numeric_v<Scalar> &&
785  detail::is_permutation_v<Perm>>::type* = nullptr>
786 inline decltype(auto) add(const Tile<Left>& left, const Tile<Right>& right,
787  const Scalar factor, const Perm& perm) {
788  return detail::make_tile(add(left.tensor(), right.tensor(), factor, perm));
789 }
790 
792 
798 template <
799  typename Arg, typename Scalar,
800  typename std::enable_if<detail::is_numeric_v<Scalar>>::type* = nullptr>
801 inline decltype(auto) add(const Tile<Arg>& arg, const Scalar value) {
802  return detail::make_tile(add(arg.tensor(), value));
803 }
804 
806 
814 template <
815  typename Arg, typename Scalar, typename Perm,
816  typename std::enable_if<detail::is_numeric_v<Scalar> &&
817  detail::is_permutation_v<Perm>>::type* = nullptr>
818 inline decltype(auto) add(const Tile<Arg>& arg, const Scalar value,
819  const Perm& perm) {
820  return detail::make_tile(add(arg.tensor(), value, perm));
821 }
822 
824 
830 template <typename Result, typename Arg>
831 inline Tile<Result>& add_to(Tile<Result>& result, const Tile<Arg>& arg) {
832  add_to(result.tensor(), arg.tensor());
833  return result;
834 }
835 
837 
845 template <
846  typename Result, typename Arg, typename Scalar,
847  typename std::enable_if<detail::is_numeric_v<Scalar>>::type* = nullptr>
848 inline Tile<Result>& add_to(Tile<Result>& result, const Tile<Arg>& arg,
849  const Scalar factor) {
850  add_to(result.tensor(), arg.tensor(), factor);
851  return result;
852 }
853 
855 
861 template <
862  typename Result, typename Scalar,
863  typename std::enable_if<detail::is_numeric_v<Scalar>>::type* = nullptr>
864 inline Tile<Result>& add_to(Tile<Result>& result, const Scalar value) {
865  add_to(result.tensor(), value);
866  return result;
867 }
868 
869 // Subtraction ---------------------------------------------------------------
870 
872 
878 template <typename Left, typename Right>
879 inline decltype(auto) subt(const Tile<Left>& left, const Tile<Right>& right) {
880  return detail::make_tile(subt(left.tensor(), right.tensor()));
881 }
882 
884 
891 template <
892  typename Left, typename Right, typename Scalar,
893  typename std::enable_if<detail::is_numeric_v<Scalar>>::type* = nullptr>
894 inline decltype(auto) subt(const Tile<Left>& left, const Tile<Right>& right,
895  const Scalar factor) {
896  return detail::make_tile(subt(left.tensor(), right.tensor(), factor));
897 }
898 
900 
908 template <typename Left, typename Right, typename Perm,
909  typename = std::enable_if_t<detail::is_permutation_v<Perm>>>
910 inline decltype(auto) subt(const Tile<Left>& left, const Tile<Right>& right,
911  const Perm& perm) {
912  return detail::make_tile(subt(left.tensor(), right.tensor(), perm));
913 }
914 
916 
925 template <
926  typename Left, typename Right, typename Scalar, typename Perm,
927  typename std::enable_if<detail::is_numeric_v<Scalar> &&
928  detail::is_permutation_v<Perm>>::type* = nullptr>
929 inline decltype(auto) subt(const Tile<Left>& left, const Tile<Right>& right,
930  const Scalar factor, const Perm& perm) {
931  return detail::make_tile(subt(left.tensor(), right.tensor(), factor, perm));
932 }
933 
935 
940 template <
941  typename Arg, typename Scalar,
942  typename std::enable_if<detail::is_numeric_v<Scalar>>::type* = nullptr>
943 inline decltype(auto) subt(const Tile<Arg>& arg, const Scalar value) {
944  return detail::make_tile(subt(arg.tensor(), value));
945 }
946 
948 
955 template <
956  typename Arg, typename Scalar, typename Perm,
957  typename std::enable_if<detail::is_numeric_v<Scalar> &&
958  detail::is_permutation_v<Perm>>::type* = nullptr>
959 inline decltype(auto) subt(const Tile<Arg>& arg, const Scalar value,
960  const Perm& perm) {
961  return detail::make_tile(subt(arg.tensor(), value, perm));
962 }
963 
965 
971 template <typename Result, typename Arg>
972 inline Tile<Result>& subt_to(Tile<Result>& result, const Tile<Arg>& arg) {
973  subt_to(result.tensor(), arg.tensor());
974  return result;
975 }
976 
978 
985 template <
986  typename Result, typename Arg, typename Scalar,
987  typename std::enable_if<detail::is_numeric_v<Scalar>>::type* = nullptr>
988 inline Tile<Result>& subt_to(Tile<Result>& result, const Tile<Arg>& arg,
989  const Scalar factor) {
990  subt_to(result.tensor(), arg.tensor(), factor);
991  return result;
992 }
993 
995 
1000 template <
1001  typename Result, typename Scalar,
1002  typename std::enable_if<detail::is_numeric_v<Scalar>>::type* = nullptr>
1003 inline Tile<Result>& subt_to(Tile<Result>& result, const Scalar value) {
1004  subt_to(result.tensor(), value);
1005  return result;
1006 }
1007 
1008 // Multiplication operations -------------------------------------------------
1009 
1011 
1017 template <typename Left, typename Right>
1018 inline decltype(auto) mult(const Tile<Left>& left, const Tile<Right>& right) {
1019  return detail::make_tile(mult(left.tensor(), right.tensor()));
1020 }
1021 
1023 
1030 template <
1031  typename Left, typename Right, typename Scalar,
1032  typename std::enable_if<detail::is_numeric_v<Scalar>>::type* = nullptr>
1033 inline decltype(auto) mult(const Tile<Left>& left, const Tile<Right>& right,
1034  const Scalar factor) {
1035  return detail::make_tile(mult(left.tensor(), right.tensor(), factor));
1036 }
1037 
1039 
1047 template <typename Left, typename Right, typename Perm,
1048  typename = std::enable_if_t<detail::is_permutation_v<Perm>>>
1049 inline decltype(auto) mult(const Tile<Left>& left, const Tile<Right>& right,
1050  const Perm& perm) {
1051  return detail::make_tile(mult(left.tensor(), right.tensor(), perm));
1052 }
1053 
1055 
1064 template <
1065  typename Left, typename Right, typename Scalar, typename Perm,
1066  typename std::enable_if<detail::is_numeric_v<Scalar> &&
1067  detail::is_permutation_v<Perm>>::type* = nullptr>
1068 inline decltype(auto) mult(const Tile<Left>& left, const Tile<Right>& right,
1069  const Scalar factor, const Perm& perm) {
1070  return detail::make_tile(mult(left.tensor(), right.tensor(), factor, perm));
1071 }
1072 
1074 
1080 template <typename Result, typename Arg>
1081 inline Tile<Result>& mult_to(Tile<Result>& result, const Tile<Arg>& arg) {
1082  mult_to(result.tensor(), arg.tensor());
1083  return result;
1084 }
1085 
1087 
1094 template <
1095  typename Result, typename Arg, typename Scalar,
1096  typename std::enable_if<detail::is_numeric_v<Scalar>>::type* = nullptr>
1097 inline Tile<Result>& mult_to(Tile<Result>& result, const Tile<Arg>& arg,
1098  const Scalar factor) {
1099  mult_to(result.tensor(), arg.tensor(), factor);
1100  return result;
1101 }
1102 
1103 // Generic element-wise binary operations
1104 // ---------------------------------------------
1105 
1106 // clang-format off
1108 
1116 // clang-format on
1117 template <typename Left, typename Right, typename Op>
1118 inline decltype(auto) binary(const Tile<Left>& left, const Tile<Right>& right,
1119  Op&& op) {
1120  return detail::make_tile(
1121  binary(left.tensor(), right.tensor(), std::forward<Op>(op)));
1122 }
1123 
1124 // clang-format off
1126 
1136 // clang-format on
1137 template <typename Left, typename Right, typename Op, typename Perm,
1138  typename = std::enable_if_t<detail::is_permutation_v<Perm>>>
1139 inline decltype(auto) binary(const Tile<Left>& left, const Tile<Right>& right,
1140  Op&& op, const Perm& perm) {
1141  return detail::make_tile(
1142  binary(left.tensor(), right.tensor(), std::forward<Op>(op), perm));
1143 }
1144 
1145 // clang-format off
1147 
1155 // clang-format on
1156 template <typename Left, typename Right, typename Op>
1157 inline Tile<Left>& inplace_binary(Tile<Left>& left, const Tile<Right>& right,
1158  Op&& op) {
1159  inplace_binary(left.tensor(), right.tensor(), std::forward<Op>(op));
1160  return left;
1161 }
1162 
1163 // Scaling operations --------------------------------------------------------
1164 
1166 
1171 template <
1172  typename Arg, typename Scalar,
1173  typename std::enable_if<detail::is_numeric_v<Scalar>>::type* = nullptr>
1174 inline decltype(auto) scale(const Tile<Arg>& arg, const Scalar factor) {
1175  return detail::make_tile(scale(arg.tensor(), factor));
1176 }
1177 
1179 
1186 template <
1187  typename Arg, typename Scalar, typename Perm,
1188  typename std::enable_if<detail::is_numeric_v<Scalar> &&
1189  detail::is_permutation_v<Perm>>::type* = nullptr>
1190 inline decltype(auto) scale(const Tile<Arg>& arg, const Scalar factor,
1191  const Perm& perm) {
1192  return detail::make_tile(scale(arg.tensor(), factor, perm));
1193 }
1194 
1196 
1201 template <
1202  typename Result, typename Scalar,
1203  typename std::enable_if<detail::is_numeric_v<Scalar>>::type* = nullptr>
1204 inline Tile<Result>& scale_to(Tile<Result>& result, const Scalar factor) {
1205  scale_to(result.tensor(), factor);
1206  return result;
1207 }
1208 
1209 // Negation operations -------------------------------------------------------
1210 
1212 
1217 template <typename Arg>
1218 inline decltype(auto) neg(const Tile<Arg>& arg) {
1219  return detail::make_tile(neg(arg.tensor()));
1220 }
1221 
1223 
1230 template <typename Arg, typename Perm,
1231  typename = std::enable_if_t<detail::is_permutation_v<Perm>>>
1232 inline decltype(auto) neg(const Tile<Arg>& arg, const Perm& perm) {
1233  return detail::make_tile(neg(arg.tensor(), perm));
1234 }
1235 
1237 
1242 template <typename Result>
1244  neg_to(result.tensor());
1245  return result;
1246 }
1247 
1248 // Complex conjugate operations ---------------------------------------------
1249 
1251 
1255 template <typename Arg>
1256 inline decltype(auto) conj(const Tile<Arg>& arg) {
1257  return detail::make_tile(conj(arg.tensor()));
1258 }
1259 
1261 
1267 template <typename Arg, typename Scalar,
1268  typename std::enable_if<
1269  TiledArray::detail::is_numeric_v<Scalar>>::type* = nullptr>
1270 inline decltype(auto) conj(const Tile<Arg>& arg, const Scalar factor) {
1271  return detail::make_tile(conj(arg.tensor(), factor));
1272 }
1273 
1275 
1281 template <typename Arg, typename Perm,
1282  typename = std::enable_if_t<detail::is_permutation_v<Perm>>>
1283 inline decltype(auto) conj(const Tile<Arg>& arg, const Perm& perm) {
1284  return detail::make_tile(conj(arg.tensor(), perm));
1285 }
1286 
1288 
1296 template <
1297  typename Arg, typename Scalar, typename Perm,
1298  typename std::enable_if<TiledArray::detail::is_numeric_v<Scalar> &&
1299  detail::is_permutation_v<Perm>>::type* = nullptr>
1300 inline decltype(auto) conj(const Tile<Arg>& arg, const Scalar factor,
1301  const Perm& perm) {
1302  return detail::make_tile(conj(arg.tensor(), factor, perm));
1303 }
1304 
1306 
1310 template <typename Result>
1312  conj_to(result.tensor());
1313  return result;
1314 }
1315 
1317 
1323 template <typename Result, typename Scalar,
1324  typename std::enable_if<
1325  TiledArray::detail::is_numeric_v<Scalar>>::type* = nullptr>
1326 inline Tile<Result>& conj_to(Tile<Result>& result, const Scalar factor) {
1327  conj_to(result.tensor(), factor);
1328  return result;
1329 }
1330 
1331 // Generic element-wise unary operations
1332 // ---------------------------------------------
1333 
1334 // clang-format off
1336 
1342 // clang-format on
1343 template <typename Arg, typename Op>
1344 inline decltype(auto) unary(const Tile<Arg>& arg, Op&& op) {
1345  return detail::make_tile(unary(arg.tensor(), std::forward<Op>(op)));
1346 }
1347 
1348 // clang-format off
1350 
1357 // clang-format on
1358 template <typename Arg, typename Op, typename Perm,
1359  typename = std::enable_if_t<detail::is_permutation_v<Perm>>>
1360 inline decltype(auto) unary(const Tile<Arg>& arg, Op&& op, const Perm& perm) {
1361  return detail::make_tile(unary(arg.tensor(), std::forward<Op>(op), perm));
1362 }
1363 
1364 // clang-format off
1366 
1372 // clang-format on
1373 template <typename Result, typename Op>
1375  inplace_unary(arg.tensor(), std::forward<Op>(op));
1376  return arg;
1377 }
1378 
1379 // Contraction operations ----------------------------------------------------
1380 
1382 
1393 template <
1394  typename Left, typename Right, typename Scalar,
1395  typename std::enable_if<detail::is_numeric_v<Scalar>>::type* = nullptr>
1396 inline decltype(auto) gemm(const Tile<Left>& left, const Tile<Right>& right,
1397  const Scalar factor,
1398  const math::GemmHelper& gemm_config) {
1399  return detail::make_tile(
1400  gemm(left.tensor(), right.tensor(), factor, gemm_config));
1401 }
1402 
1405 
1418 template <
1419  typename Result, typename Left, typename Right, typename Scalar,
1420  typename std::enable_if<detail::is_numeric_v<Scalar>>::type* = nullptr>
1421 inline Tile<Result>& gemm(Tile<Result>& result, const Tile<Left>& left,
1422  const Tile<Right>& right, const Scalar factor,
1423  const math::GemmHelper& gemm_config) {
1424  gemm(result.tensor(), left.tensor(), right.tensor(), factor, gemm_config);
1425  return result;
1426 }
1427 
1430 
1454 template <typename Result, typename Left, typename Right,
1455  typename ElementMultiplyAddOp,
1456  typename std::enable_if<std::is_invocable_r_v<
1457  void, std::remove_reference_t<ElementMultiplyAddOp>,
1458  typename Result::value_type&, const typename Left::value_type&,
1459  const typename Right::value_type&>>::type* = nullptr>
1460 inline Tile<Result>& gemm(Tile<Result>& result, const Tile<Left>& left,
1461  const Tile<Right>& right,
1462  const math::GemmHelper& gemm_config,
1463  ElementMultiplyAddOp&& element_multiplyadd_op) {
1464  gemm(result.tensor(), left.tensor(), right.tensor(), gemm_config,
1465  std::forward<ElementMultiplyAddOp>(element_multiplyadd_op));
1466  return result;
1467 }
1468 
1469 // Reduction operations ------------------------------------------------------
1470 
1472 
1476 template <typename Arg>
1477 inline decltype(auto) trace(const Tile<Arg>& arg) {
1478  return trace(arg.tensor());
1479 }
1480 
1481 namespace detail {
1482 
1484 template <typename Arg>
1486  : std::true_type {};
1487 
1488 } // namespace detail
1489 
1491 
1495 template <typename Arg>
1496 inline decltype(auto) sum(const Tile<Arg>& arg) {
1497  return sum(arg.tensor());
1498 }
1499 
1501 
1505 template <typename Arg>
1506 inline decltype(auto) product(const Tile<Arg>& arg) {
1507  return product(arg.tensor());
1508 }
1509 
1511 
1516 template <typename Arg>
1517 inline decltype(auto) squared_norm(const Tile<Arg>& arg) {
1518  return squared_norm(arg.tensor());
1519 }
1520 
1522 
1526 template <typename Arg>
1527 inline decltype(auto) norm(const Tile<Arg>& arg) {
1528  return norm(arg.tensor());
1529 }
1530 
1532 
1538 template <typename Arg, typename ResultType>
1539 inline void norm(const Tile<Arg>& arg, ResultType& result) {
1540  norm(arg.tensor(), result);
1541 }
1542 
1544 
1548 template <typename Arg>
1549 inline decltype(auto) max(const Tile<Arg>& arg) {
1550  return max(arg.tensor());
1551 }
1552 
1554 
1558 template <typename Arg>
1559 inline decltype(auto) min(const Tile<Arg>& arg) {
1560  return min(arg.tensor());
1561 }
1562 
1564 
1568 template <typename Arg>
1569 inline decltype(auto) abs_max(const Tile<Arg>& arg) {
1570  return abs_max(arg.tensor());
1571 }
1572 
1574 
1578 template <typename Arg>
1579 inline decltype(auto) abs_min(const Tile<Arg>& arg) {
1580  return abs_min(arg.tensor());
1581 }
1582 
1584 
1590 template <typename Left, typename Right>
1591 inline decltype(auto) dot(const Tile<Left>& left, const Tile<Right>& right) {
1592  return dot(left.tensor(), right.tensor());
1593 }
1594 
1596 
1601 template <typename Left, typename Right>
1602 inline decltype(auto) inner_product(const Tile<Left>& left,
1603  const Tile<Right>& right) {
1604  return inner_product(left.tensor(), right.tensor());
1605 }
1606 
1607 // Tile arithmetic operators -------------------------------------------------
1608 
1609 // see operators.h
1610 
1613 
1618 template <typename T>
1619 inline std::ostream& operator<<(std::ostream& os, const Tile<T>& tile) {
1620  os << tile.tensor();
1621  return os;
1622 }
1623 
1626 template <typename Allocator, typename T>
1627 struct Cast<
1628  TiledArray::Tensor<typename T::value_type, Allocator>, Tile<T>,
1629  std::void_t<decltype(
1630  std::declval<TiledArray::Cast<
1631  TiledArray::Tensor<typename T::value_type, Allocator>, T>>()(
1632  std::declval<const T&>()))>> {
1633  auto operator()(const Tile<T>& arg) const {
1634  return TiledArray::Cast<
1636  arg.tensor());
1637  }
1638 };
1639 
1642 template <typename T1, typename T2>
1644 bool operator==(const Tile<T1>& t1, const Tile<T2>& t2) {
1645  return t1.tensor() == t2.tensor();
1646 }
1647 
1649 template <typename T1, typename T2>
1650 bool operator!=(const Tile<T1>& t1, const Tile<T2>& t2) {
1651  return !(t1 == t2);
1652 }
1653 
1654 } // namespace TiledArray
1655 
1656 #endif // TILEDARRAY_TILE_H__INCLUDED
decltype(auto) subt(const Tile< Left > &left, const Tile< Right > &right)
Subtract tile arguments.
Definition: tile.h:879
Tile< Arg > & shift_to(Tile< Arg > &arg, const Index &range_shift)
Shift the range of arg in place.
Definition: tile.h:704
std::enable_if<!TiledArray::detail::is_permutation_v< Perm >, TiledArray::Range >::type permute(const TiledArray::Range &r, const Perm &p)
Definition: btas.h:803
decltype(auto) unary(const Tile< Arg > &arg, Op &&op)
Unary element-wise transform producing a new tile.
Definition: tile.h:1344
Contraction to *GEMM helper.
Definition: gemm_helper.h:40
void serialize(Archive &ar)
Definition: tile.h:587
typename make_void< Ts... >::type void_t
Definition: type_traits.h:55
::blas::Op Op
Definition: blas.h:46
typename tensor_type::const_reference const_reference
Element reference type.
Definition: tile.h:98
Tile< Result > & scale_to(Tile< Result > &result, const Scalar factor)
Scale to the result tile.
Definition: tile.h:1204
void serialize(Archive &ar) const
Definition: tile.h:574
auto inner_product(const DistArray< Tile, Policy > &a, const DistArray< Tile, Policy > &b)
Definition: dist_array.h:1647
T tensor_type
Tensor type used to represent tile data.
Definition: tile.h:87
detail::ShiftWrapper< T > shift(T &tensor)
Shift a tensor from one range to another.
bool operator==(const BlockRange &r1, const BlockRange &r2)
BlockRange equality comparison.
Definition: block_range.h:433
decltype(auto) size() const
Size accessors.
Definition: tile.h:208
Type trait for extracting the scalar type of tensors and arrays.
Definition: type_traits.h:744
std::enable_if_t< trace_is_defined_v< T >, U > enable_if_trace_is_defined_t
SFINAE type for enabling code when the trace operation is defined.
Definition: trace.h:61
Tile< Left > & inplace_binary(Tile< Left > &left, const Tile< Right > &right, Op &&op)
Binary element-wise in-place transform.
Definition: tile.h:1157
typename tensor_type::reference reference
Element reference type.
Definition: tile.h:96
Tile< Result > & mult_to(Tile< Result > &result, const Tile< Arg > &arg)
Multiply to the result tile.
Definition: tile.h:1081
constexpr bool operator!=(const DenseShape &a, const DenseShape &b)
Definition: dense_shape.h:382
DistArray< Tile, Policy > clone(const DistArray< Tile, Policy > &arg)
Create a deep copy of an array.
Definition: clone.h:43
decltype(auto) binary(const Tile< Left > &left, const Tile< Right > &right, Op &&op)
Binary element-wise transform producing a new tile.
Definition: tile.h:1118
typename tensor_type::const_pointer const_pointer
Element const pointer type.
Definition: tile.h:104
decltype(auto) trace(const Tile< Arg > &arg)
Sum the hyper-diagonal elements a tile.
Definition: tile.h:1477
decltype(auto) conj(const Tile< Arg > &arg)
Create a complex conjugated copy of a tile.
Definition: tile.h:1256
decltype(auto) range() const
Range accessor.
Definition: tile.h:213
Tile(const Tile_ &)=default
auto dot(const DistArray< Tile, Policy > &a, const DistArray< Tile, Policy > &b)
Definition: dist_array.h:1640
decltype(auto) norm(const Tile< Arg > &arg)
Vector 2-norm of a tile.
Definition: tile.h:1527
decltype(auto) min(const Tile< Arg > &arg)
Minimum element of a tile.
Definition: tile.h:1559
decltype(auto) end()
Iterator factory.
Definition: tile.h:184
Range that references a subblock of another range.
Definition: block_range.h:34
decltype(auto) block(const Index1 &lower_bound, const Index2 &upper_bound)
Constructs a view of the block defined by lower_bound and upper_bound.
Definition: tile.h:423
auto abs_min(const DistArray< Tile, Policy > &a)
Definition: dist_array.h:1630
typename tensor_type::value_type value_type
value type
Definition: tile.h:89
decltype(auto) begin()
Iterator factory.
Definition: tile.h:174
typename TiledArray::detail::scalar_type< tensor_type >::type scalar_type
the scalar type that supports T
Definition: tile.h:108
typename tensor_type::const_iterator const_iterator
Element const iterator type.
Definition: tile.h:101
decltype(auto) add(const Tile< Left > &left, const Tile< Right > &right)
Add tile arguments.
Definition: tile.h:734
typename tensor_type::ordinal_type size_type
Definition: tile.h:94
const_reference operator[](const Ordinal ord) const
Const element accessor.
Definition: tile.h:226
const_reference operator()(const Index &i) const
Const element accessor.
Definition: tile.h:316
auto abs_max(const DistArray< Tile, Policy > &a)
Definition: dist_array.h:1635
Tile cast operation.
Definition: cast.h:168
reference operator[](const Index &i)
Element accessor.
Definition: tile.h:271
Tile(Arg &&arg)
Forwarding ctor.
Definition: tile.h:133
#define TA_ASSERT(EXPR,...)
Definition: error.h:39
tensor_type & tensor()
Definition: tile.h:165
decltype(auto) neg(const Tile< Arg > &arg)
Negate the tile argument.
Definition: tile.h:1218
Tile_ & operator=(const tensor_type &tensor)
Definition: tile.h:149
Tile(Tile_ &&)=default
Tile< T > Tile_
This object type.
Definition: tile.h:85
Tile(Arg1 &&arg1, Arg2 &&arg2, Args &&... args)
Definition: tile.h:137
reference operator[](const Ordinal ord)
Element accessor.
Definition: tile.h:241
Tile< Result > & add_to(Tile< Result > &result, const Tile< Arg > &arg)
Add to the result tile.
Definition: tile.h:831
Tile< T > make_tile(T &&t)
Factory function for tiles.
Definition: tile.h:619
decltype(auto) mult(const Tile< Left > &left, const Tile< Right > &right)
Multiplication tile arguments.
Definition: tile.h:1018
auto squared_norm(const DistArray< Tile, Policy > &a)
Definition: dist_array.h:1655
Tile< Result > & neg_to(Tile< Result > &result)
In-place negate tile.
Definition: tile.h:1243
reference operator[](const std::initializer_list< Index > &i)
Element accessor.
Definition: tile.h:301
Tile< Result > & inplace_unary(Tile< Result > &arg, Op &&op)
Unary element-wise in-place transform.
Definition: tile.h:1374
reference operator()(const std::initializer_list< Index > &i)
Element accessor.
Definition: tile.h:361
decltype(auto) scale(const Tile< Arg > &arg, const Scalar factor)
Scalar the tile argument.
Definition: tile.h:1174
const_reference operator()(const std::initializer_list< Index > &i) const
Const element accessor.
Definition: tile.h:346
std::ostream & operator<<(std::ostream &os, const DistArray< Tile, Policy > &a)
Add the tensor to an output stream.
Definition: dist_array.h:1602
typename tensor_type::pointer pointer
Element pointer type.
Definition: tile.h:102
Tensor interface for external data.
typename tensor_type::range_type range_type
Tensor range type.
Definition: tile.h:90
Tile_ & operator=(tensor_type &&tensor)
Definition: tile.h:154
const_reference operator()(const Index &... i) const
Const element accessor.
Definition: tile.h:376
typename tensor_type::index1_type index1_type
1-index type
Definition: tile.h:91
bool empty() const
Definition: tile.h:161
decltype(auto) product(const Tile< Arg > &arg)
Multiply the elements of a tile.
Definition: tile.h:1506
typename tensor_type::iterator iterator
Element iterator type.
Definition: tile.h:99
const tensor_type & tensor() const
Definition: tile.h:167
decltype(auto) max(const Tile< Arg > &arg)
Maximum element of a tile.
Definition: tile.h:1549
bool empty(const Tile< Arg > &arg)
Check that arg is empty (no data)
Definition: tile.h:646
decltype(auto) data()
Data direct access.
Definition: tile.h:196
decltype(auto) sum(const Tile< Arg > &arg)
Sum the elements of a tile.
Definition: tile.h:1496
Type trait for extracting the numeric type of tensors and arrays.
Definition: type_traits.h:709
Tile< Result > & subt_to(Tile< Result > &result, const Tile< Arg > &arg)
Subtract from the result tile.
Definition: tile.h:972
Tile_ & operator=(Tile_ &&)=default
const_reference operator[](const std::initializer_list< Index > &i) const
Const element accessor.
Definition: tile.h:286
An N-dimensional tensor object.
Definition: tensor.h:50
Tile_ & operator=(const Tile_ &)=default
reference operator()(const Index &i)
Element accessor.
Definition: tile.h:331
typename TiledArray::detail::numeric_type< tensor_type >::type numeric_type
the numeric type that supports T
Definition: tile.h:106
Tile< Result > & conj_to(Tile< Result > &result)
In-place complex conjugate a tile.
Definition: tile.h:1311
An N-dimensional shallow copy wrapper for tile objects.
Definition: tile.h:82
reference operator()(const Index &... i)
Element accessor.
Definition: tile.h:391
const_reference operator[](const Index &i) const
Const element accessor.
Definition: tile.h:256
decltype(auto) gemm(const Tile< Left > &left, const Tile< Right > &right, const Scalar factor, const math::GemmHelper &gemm_config)
Contract 2 tensors over head/tail modes and scale the product.
Definition: tile.h:1396