add.h
Go to the documentation of this file.
1 /*
2  * This file is a part of TiledArray.
3  * Copyright (C) 2013 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  * Justus Calvin
19  * Department of Chemistry, Virginia Tech
20  *
21  * add.h
22  * May 7, 2013
23  *
24  */
25 
26 #ifndef TILEDARRAY_TILE_OP_ADD_H__INCLUDED
27 #define TILEDARRAY_TILE_OP_ADD_H__INCLUDED
28 
29 #include "../tile_interface/add.h"
30 #include "../tile_interface/clone.h"
31 #include "../tile_interface/permute.h"
32 #include "../tile_interface/scale.h"
33 #include "../zero_tensor.h"
34 #include "tile_interface.h"
35 
36 namespace TiledArray {
37 namespace detail {
38 
40 
52 template <typename Result, typename Left, typename Right, bool LeftConsumable,
53  bool RightConsumable>
54 class Add {
55  public:
57  Add_;
58  typedef Left left_type;
59  typedef Right right_type;
60  typedef Result result_type;
61 
63  static constexpr bool left_is_consumable =
64  LeftConsumable && std::is_same<result_type, left_type>::value;
66  static constexpr bool right_is_consumable =
67  RightConsumable && std::is_same<result_type, right_type>::value;
68 
69  private:
70  // Permuting tile evaluation function
71  // These operations cannot consume the argument tile since this operation
72  // requires temporary storage space.
73 
74  template <typename Perm, typename = std::enable_if_t<
75  TiledArray::detail::is_permutation_v<Perm>>>
76  static result_type eval(const left_type& first, const right_type& second,
77  const Perm& perm) {
78  using TiledArray::add;
79  return add(first, second, perm);
80  }
81 
82  template <typename Perm, typename = std::enable_if_t<
83  TiledArray::detail::is_permutation_v<Perm>>>
84  static result_type eval(ZeroTensor, const right_type& second,
85  const Perm& perm) {
87  return permute(second, perm);
88  }
89 
90  template <typename Perm, typename = std::enable_if_t<
91  TiledArray::detail::is_permutation_v<Perm>>>
92  static result_type eval(const left_type& first, ZeroTensor,
93  const Perm& perm) {
95  return permute(first, perm);
96  }
97 
98  // Non-permuting tile evaluation functions
99  // The compiler will select the correct functions based on the
100  // consumability of the arguments.
101 
102  template <bool LC, bool RC,
103  typename std::enable_if<!(LC || RC)>::type* = nullptr>
104  static result_type eval(const left_type& first, const right_type& second) {
105  using TiledArray::add;
106  return add(first, second);
107  }
108 
109  template <bool LC, bool RC, typename std::enable_if<LC>::type* = nullptr>
110  static result_type eval(left_type& first, const right_type& second) {
111  using TiledArray::add_to;
112  return add_to(first, second);
113  }
114 
115  template <bool LC, bool RC,
116  typename std::enable_if<!LC && RC>::type* = nullptr>
117  static result_type eval(const left_type& first, right_type& second) {
118  using TiledArray::add_to;
119  return add_to(second, first);
120  }
121 
122  template <bool LC, bool RC, typename std::enable_if<!RC>::type* = nullptr>
123  static result_type eval(const ZeroTensor&, const right_type& second) {
125  return clone(second);
126  }
127 
128  template <bool LC, bool RC, typename std::enable_if<RC>::type* = nullptr>
129  static result_type eval(const ZeroTensor&, right_type& second) {
130  return second;
131  }
132 
133  template <bool LC, bool RC, typename std::enable_if<!LC>::type* = nullptr>
134  static result_type eval(const left_type& first, const ZeroTensor&) {
136  return clone(first);
137  }
138 
139  template <bool LC, bool RC, typename std::enable_if<LC>::type* = nullptr>
140  static result_type eval(left_type& first, const ZeroTensor&) {
141  return first;
142  }
143 
144  public:
146 
156  template <
157  typename L, typename R, typename Perm,
158  typename = std::enable_if_t<TiledArray::detail::is_permutation_v<Perm>>>
159  result_type operator()(L&& left, R&& right, const Perm& perm) const {
160  return eval(std::forward<L>(left), std::forward<R>(right), perm);
161  }
162 
164 
173  template <typename L, typename R>
174  result_type operator()(L&& left, R&& right) const {
175  return Add_::template eval<left_is_consumable, right_is_consumable>(
176  std::forward<L>(left), std::forward<R>(right));
177  }
178 
180 
188  template <typename R>
189  result_type consume_left(left_type& left, R&& right) const {
190  constexpr bool can_consume_left =
192  std::is_same<result_type, left_type>::value;
193  constexpr bool can_consume_right =
194  right_is_consumable && !(std::is_const<R>::value || can_consume_left);
195  return Add_::template eval<can_consume_left, can_consume_right>(
196  left, std::forward<R>(right));
197  }
198 
200 
208  template <typename L>
209  result_type consume_right(L&& left, right_type& right) const {
210  constexpr bool can_consume_right =
212  std::is_same<result_type, right_type>::value;
213  constexpr bool can_consume_left =
214  left_is_consumable && !(std::is_const<L>::value || can_consume_right);
215  return Add_::template eval<can_consume_left, can_consume_right>(
216  std::forward<L>(left), right);
217  }
218 
219 }; // class Add
220 
222 
236 template <typename Result, typename Left, typename Right, typename Scalar,
237  bool LeftConsumable, bool RightConsumable>
238 class ScalAdd {
239  public:
240  typedef ScalAdd<Result, Left, Right, Scalar, LeftConsumable,
241  RightConsumable>
243  typedef Left left_type;
244  typedef Right right_type;
245  typedef Scalar scalar_type;
246  typedef Result result_type;
247 
249  static constexpr bool left_is_consumable =
250  LeftConsumable && std::is_same<result_type, left_type>::value;
252  static constexpr bool right_is_consumable =
253  RightConsumable && std::is_same<result_type, right_type>::value;
254 
255  private:
256  scalar_type factor_;
257 
258  // Permuting tile evaluation function
259  // These operations cannot consume the argument tile since this operation
260  // requires temporary storage space.
261 
262  template <typename Perm, typename = std::enable_if_t<
263  TiledArray::detail::is_permutation_v<Perm>>>
264  result_type eval(const left_type& first, const right_type& second,
265  const Perm& perm) const {
266  using TiledArray::add;
267  return add(first, second, factor_, perm);
268  }
269 
270  template <typename Perm, typename = std::enable_if_t<
271  TiledArray::detail::is_permutation_v<Perm>>>
272  result_type eval(ZeroTensor, const right_type& second,
273  const Perm& perm) const {
274  using TiledArray::scale;
275  return scale(second, factor_, perm);
276  }
277 
278  template <typename Perm, typename = std::enable_if_t<
279  TiledArray::detail::is_permutation_v<Perm>>>
280  result_type eval(const left_type& first, ZeroTensor, const Perm& perm) const {
281  using TiledArray::scale;
282  return scale(first, factor_, perm);
283  }
284 
285  // Non-permuting tile evaluation functions
286  // The compiler will select the correct functions based on the
287  // consumability of the arguments.
288 
289  template <bool LC, bool RC,
290  typename std::enable_if<!(LC || RC)>::type* = nullptr>
291  result_type eval(const left_type& first, const right_type& second) const {
292  using TiledArray::add;
293  return add(first, second, factor_);
294  }
295 
296  template <bool LC, bool RC, typename std::enable_if<LC>::type* = nullptr>
297  result_type eval(left_type& first, const right_type& second) const {
298  using TiledArray::add_to;
299  return add_to(first, second, factor_);
300  }
301 
302  template <bool LC, bool RC,
303  typename std::enable_if<!LC && RC>::type* = nullptr>
304  result_type eval(const left_type& first, right_type& second) const {
305  using TiledArray::add_to;
306  return add_to(second, first, factor_);
307  }
308 
309  template <bool LC, bool RC, typename std::enable_if<!RC>::type* = nullptr>
310  result_type eval(const ZeroTensor&, const right_type& second) const {
311  using TiledArray::scale;
312  return scale(second, factor_);
313  }
314 
315  template <bool LC, bool RC, typename std::enable_if<RC>::type* = nullptr>
316  result_type eval(const ZeroTensor&, right_type& second) const {
317  using TiledArray::scale_to;
318  return scale_to(second, factor_);
319  }
320 
321  template <bool LC, bool RC, typename std::enable_if<!LC>::type* = nullptr>
322  result_type eval(const left_type& first, const ZeroTensor&) const {
323  using TiledArray::scale;
324  return scale(first, factor_);
325  }
326 
327  template <bool LC, bool RC, typename std::enable_if<LC>::type* = nullptr>
328  result_type eval(left_type& first, const ZeroTensor&) const {
329  using TiledArray::scale_to;
330  return scale_to(first, factor_);
331  }
332 
333  public:
334  // Compiler generated functions
335  ScalAdd(const ScalAdd_&) = default;
336  ScalAdd(ScalAdd_&&) = default;
337  ~ScalAdd() = default;
338  ScalAdd_& operator=(const ScalAdd_&) = default;
339  ScalAdd_& operator=(ScalAdd_&&) = default;
340 
342 
344  explicit ScalAdd(const Scalar factor) : factor_(factor) {}
345 
347 
357  template <
358  typename L, typename R, typename Perm,
359  typename = std::enable_if_t<TiledArray::detail::is_permutation_v<Perm>>>
360  result_type operator()(L&& left, R&& right, const Perm& perm) const {
361  return eval(std::forward<L>(left), std::forward<R>(right), perm);
362  }
363 
365 
374  template <typename L, typename R>
375  result_type operator()(L&& left, R&& right) const {
376  return ScalAdd_::template eval<left_is_consumable, right_is_consumable>(
377  std::forward<L>(left), std::forward<R>(right));
378  }
379 
381 
389  template <typename R>
390  result_type consume_left(left_type& left, R&& right) const {
391  constexpr bool can_consume_left =
393  std::is_same<result_type, left_type>::value;
394  constexpr bool can_consume_right =
395  right_is_consumable && !(std::is_const<R>::value || can_consume_left);
396  return ScalAdd_::template eval<can_consume_left, can_consume_right>(
397  left, std::forward<R>(right));
398  }
399 
401 
409  template <typename L>
410  result_type consume_right(L&& left, right_type& right) const {
411  constexpr bool can_consume_right =
413  std::is_same<result_type, right_type>::value;
414  constexpr bool can_consume_left =
415  left_is_consumable && !(std::is_const<L>::value || can_consume_right);
416  return ScalAdd_::template eval<can_consume_left, can_consume_right>(
417  std::forward<L>(left), right);
418  }
419 
420 }; // class ScalAdd
421 
422 } // namespace detail
423 } // namespace TiledArray
424 
425 #endif // TILEDARRAY_TILE_OP_ADD_H__INCLUDED
static constexpr bool right_is_consumable
Indicates whether it is possible to consume the right tile.
Definition: add.h:66
ScalAdd_ & operator=(const ScalAdd_ &)=default
Tile< Result > & scale_to(Tile< Result > &result, const Scalar factor)
Scale to the result tile.
Definition: tile.h:1204
result_type operator()(L &&left, R &&right) const
Scale-and-add operator.
Definition: add.h:375
Consumable tile type trait.
Definition: type_traits.h:611
static constexpr bool left_is_consumable
Indicates whether it is possible to consume the left tile.
Definition: add.h:63
ScalAdd< Result, Left, Right, Scalar, LeftConsumable, RightConsumable > ScalAdd_
This class type.
Definition: add.h:242
void permute(InputOp &&input_op, OutputOp &&output_op, Result &result, const Perm &perm, const Arg0 &arg0, const Args &... args)
Construct a permuted tensor copy.
Definition: permute.h:117
ScalAdd(ScalAdd_ &&)=default
Tile scale-addition operation.
Definition: add.h:238
Scalar scalar_type
Scaling factor type.
Definition: add.h:245
Tile addition operation.
Definition: add.h:54
DistArray< Tile, Policy > clone(const DistArray< Tile, Policy > &arg)
Create a deep copy of an array.
Definition: clone.h:43
result_type consume_right(L &&left, right_type &right) const
Add left to right and scale the result.
Definition: add.h:410
static constexpr bool right_is_consumable
Indicates whether it is possible to consume the right tile.
Definition: add.h:252
Left left_type
Left-hand argument base type.
Definition: add.h:58
result_type operator()(L &&left, R &&right, const Perm &perm) const
Add-and-permute operator.
Definition: add.h:159
decltype(auto) add(const Tile< Left > &left, const Tile< Right > &right)
Add tile arguments.
Definition: tile.h:734
ScalAdd_ & operator=(ScalAdd_ &&)=default
result_type consume_left(left_type &left, R &&right) const
Add right to left.
Definition: add.h:189
Tile< Result > & add_to(Tile< Result > &result, const Tile< Arg > &arg)
Add to the result tile.
Definition: tile.h:831
ScalAdd(const Scalar factor)
Constructor.
Definition: add.h:344
Result result_type
Result tile type.
Definition: add.h:246
static constexpr bool left_is_consumable
Indicates whether it is possible to consume the left tile.
Definition: add.h:249
Right right_type
Right-hand argument base type.
Definition: add.h:59
Result result_type
The result tile type.
Definition: add.h:60
Left left_type
Left-hand argument base type.
Definition: add.h:243
decltype(auto) scale(const Tile< Arg > &arg, const Scalar factor)
Scalar the tile argument.
Definition: tile.h:1174
Permute a tile.
Definition: permute.h:134
Place-holder object for a zero tensor.
Definition: zero_tensor.h:32
result_type operator()(L &&left, R &&right) const
Add operator.
Definition: add.h:174
ScalAdd(const ScalAdd_ &)=default
result_type operator()(L &&left, R &&right, const Perm &perm) const
Scale-add-and-permute operator.
Definition: add.h:360
result_type consume_right(L &&left, right_type &right) const
Add left to right.
Definition: add.h:209
Right right_type
Right-hand argument base type.
Definition: add.h:244
result_type consume_left(left_type &left, R &&right) const
Add right to left and scale the result.
Definition: add.h:390
Add< Result, Left, Right, LeftConsumable, RightConsumable > Add_
This class type.
Definition: add.h:57
Create a deep copy of a tile.
Definition: clone.h:128