TiledArray  0.7.0
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.h"
30 #include "../tile_interface/add.h"
31 #include "../tile_interface/scale.h"
32 #include "../tile_interface/permute.h"
33 #include "../tile_interface/clone.h"
34 #include "../zero_tensor.h"
35 
36 namespace TiledArray {
37  namespace detail {
38 
40 
52  template <typename Result, typename Left, typename Right,
53  bool LeftConsumable, bool RightConsumable>
54  class Add {
55  public:
56 
58  Add_;
59  typedef Left left_type;
60  typedef Right right_type;
61  typedef Result result_type;
62 
64  static constexpr bool left_is_consumable =
65  LeftConsumable && std::is_same<result_type, left_type>::value;
67  static constexpr bool right_is_consumable =
68  RightConsumable && std::is_same<result_type, right_type>::value;
69 
70  private:
71 
72  // Permuting tile evaluation function
73  // These operations cannot consume the argument tile since this operation
74  // requires temporary storage space.
75 
76  static result_type eval(const left_type& first, const right_type& second,
77  const Permutation& perm)
78  {
79  using TiledArray::add;
80  return add(first, second, perm);
81  }
82 
83  static result_type eval(ZeroTensor, const right_type& second,
84  const Permutation& perm)
85  {
87  return permute(second, perm);
88  }
89 
90  static result_type eval(const left_type& first, ZeroTensor,
91  const Permutation& perm)
92  {
94  return permute(first, perm);
95  }
96 
97  // Non-permuting tile evaluation functions
98  // The compiler will select the correct functions based on the
99  // consumability of the arguments.
100 
101  template <bool LC, bool RC,
102  typename std::enable_if<!(LC || RC)>::type* = nullptr>
103  static result_type
104  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,
110  typename std::enable_if<LC>::type* = nullptr>
111  static result_type eval(left_type& first, const right_type& second) {
112  using TiledArray::add_to;
113  return add_to(first, second);
114  }
115 
116  template <bool LC, bool RC,
117  typename std::enable_if<!LC && RC>::type* = nullptr>
118  static result_type eval(const left_type& first, right_type& second) {
119  using TiledArray::add_to;
120  return add_to(second, first);
121  }
122 
123  template <bool LC, bool RC,
124  typename std::enable_if<!RC>::type* = nullptr>
125  static result_type eval(const ZeroTensor&, const right_type& second) {
127  return clone(second);
128  }
129 
130  template <bool LC, bool RC,
131  typename std::enable_if<RC>::type* = nullptr>
132  static result_type eval(const ZeroTensor&, right_type& second) {
133  return second;
134  }
135 
136  template <bool LC, bool RC,
137  typename std::enable_if<!LC>::type* = nullptr>
138  static result_type eval(const left_type& first, const ZeroTensor&) {
140  return clone(first);
141  }
142 
143  template <bool LC, bool RC,
144  typename std::enable_if<LC>::type* = nullptr>
145  static result_type eval(left_type& first, const ZeroTensor&) {
146  return first;
147  }
148 
149  public:
150 
152 
162  template <typename L, typename R>
164  operator()(L&& left, R&& right, const Permutation& perm) const {
165  return eval(std::forward<L>(left), std::forward<R>(right), perm);
166  }
167 
169 
178  template <typename L, typename R>
179  result_type operator()(L&& left, R&& right) const {
180  return Add_::template eval<left_is_consumable, right_is_consumable>(
181  std::forward<L>(left), std::forward<R>(right));
182  }
183 
185 
193  template <typename R>
194  result_type consume_left(left_type& left, R&& right) const {
195  constexpr bool can_consume_left =
197  std::is_same<result_type, left_type>::value;
198  constexpr bool can_consume_right = right_is_consumable &&
199  ! (std::is_const<R>::value || can_consume_left);
200  return Add_::template eval<can_consume_left, can_consume_right>(left,
201  std::forward<R>(right));
202  }
203 
205 
213  template <typename L>
214  result_type consume_right(L&& left, right_type& right) const {
215  constexpr bool can_consume_right =
217  std::is_same<result_type, right_type>::value;
218  constexpr bool can_consume_left = left_is_consumable &&
219  ! (std::is_const<L>::value || can_consume_right);
220  return Add_::template eval<can_consume_left, can_consume_right>(
221  std::forward<L>(left), right);
222  }
223 
224  }; // class Add
225 
227 
241  template <typename Result, typename Left, typename Right, typename Scalar,
242  bool LeftConsumable, bool RightConsumable>
243  class ScalAdd {
244  public:
245 
246  typedef ScalAdd<Result, Left, Right, Scalar, LeftConsumable,
247  RightConsumable> ScalAdd_;
248  typedef Left left_type;
249  typedef Right right_type;
250  typedef Scalar scalar_type;
251  typedef Result result_type;
252 
254  static constexpr bool left_is_consumable =
255  LeftConsumable && std::is_same<result_type, left_type>::value;
257  static constexpr bool right_is_consumable =
258  RightConsumable && std::is_same<result_type, right_type>::value;
259 
260  private:
261 
262  scalar_type factor_;
263 
264  // Permuting tile evaluation function
265  // These operations cannot consume the argument tile since this operation
266  // requires temporary storage space.
267 
268  result_type eval(const left_type& first, const right_type& second,
269  const Permutation& perm) const
270  {
271  using TiledArray::add;
272  return add(first, second, factor_, perm);
273  }
274 
275  result_type eval(ZeroTensor, const right_type& second,
276  const Permutation& perm) const
277  {
278  using TiledArray::scale;
279  return scale(second, factor_, perm);
280  }
281 
282  result_type eval(const left_type& first, ZeroTensor,
283  const Permutation& perm) const
284  {
285  using TiledArray::scale;
286  return scale(first, factor_, perm);
287  }
288 
289  // Non-permuting tile evaluation functions
290  // The compiler will select the correct functions based on the
291  // consumability of the arguments.
292 
293  template <bool LC, bool RC,
294  typename std::enable_if<!(LC || RC)>::type* = nullptr>
295  result_type eval(const left_type& first, const right_type& second) const {
296  using TiledArray::add;
297  return add(first, second, factor_);
298  }
299 
300  template <bool LC, bool RC,
301  typename std::enable_if<LC>::type* = nullptr>
302  result_type eval(left_type& first, const right_type& second) const {
303  using TiledArray::add_to;
304  return add_to(first, second, factor_);
305  }
306 
307  template <bool LC, bool RC,
308  typename std::enable_if<!LC && RC>::type* = nullptr>
309  result_type eval(const left_type& first, right_type& second) const {
310  using TiledArray::add_to;
311  return add_to(second, first, factor_);
312  }
313 
314  template <bool LC, bool RC,
315  typename std::enable_if<!RC>::type* = nullptr>
316  result_type eval(const ZeroTensor&, const right_type& second) const {
317  using TiledArray::scale;
318  return scale(second, factor_);
319  }
320 
321  template <bool LC, bool RC,
322  typename std::enable_if<RC>::type* = nullptr>
323  result_type eval(const ZeroTensor&, right_type& second) const {
324  using TiledArray::scale_to;
325  return scale_to(second, factor_);
326  }
327 
328  template <bool LC, bool RC,
329  typename std::enable_if<!LC>::type* = nullptr>
330  result_type eval(const left_type& first, const ZeroTensor&) const {
331  using TiledArray::scale;
332  return scale(first, factor_);
333  }
334 
335  template <bool LC, bool RC,
336  typename std::enable_if<LC>::type* = nullptr>
337  result_type eval(left_type& first, const ZeroTensor&) const {
338  using TiledArray::scale_to;
339  return scale_to(first, factor_);
340  }
341 
342  public:
343 
344  // Compiler generated functions
345  ScalAdd(const ScalAdd_&) = default;
346  ScalAdd(ScalAdd_&&) = default;
347  ~ScalAdd() = default;
348  ScalAdd_& operator=(const ScalAdd_&) = default;
349  ScalAdd_& operator=(ScalAdd_&&) = default;
350 
352 
354  explicit ScalAdd(const Scalar factor) : factor_(factor) { }
355 
357 
367  template <typename L, typename R>
369  operator()(L&& left, R&& right, const Permutation& perm) const {
370  return eval(std::forward<L>(left), std::forward<R>(right), perm);
371  }
372 
374 
383  template <typename L, typename R>
384  result_type operator()(L&& left, R&& right) const {
385  return ScalAdd_::template eval<left_is_consumable,
386  right_is_consumable>(std::forward<L>(left), std::forward<R>(right));
387  }
388 
390 
398  template <typename R>
399  result_type consume_left(left_type& left, R&& right) const {
400  constexpr bool can_consume_left =
402  std::is_same<result_type, left_type>::value;
403  constexpr bool can_consume_right = right_is_consumable &&
404  ! (std::is_const<R>::value || can_consume_left);
405  return ScalAdd_::template eval<can_consume_left, can_consume_right>(left,
406  std::forward<R>(right));
407  }
408 
410 
418  template <typename L>
419  result_type consume_right(L&& left, right_type& right) const {
420  constexpr bool can_consume_right =
422  std::is_same<result_type, right_type>::value;
423  constexpr bool can_consume_left = left_is_consumable &&
424  ! (std::is_const<L>::value || can_consume_right);
425  return ScalAdd_::template eval<can_consume_left, can_consume_right>(
426  std::forward<L>(left), right);
427  }
428 
429  }; // class ScalAdd
430 
431  } // namespace detail
432 } // namespace TiledArray
433 
434 #endif // TILEDARRAY_TILE_OP_ADD_H__INCLUDED
Right right_type
Right-hand argument base type.
Definition: add.h:60
static constexpr bool left_is_consumable
Indicates whether it is possible to consume the left tile.
Definition: add.h:64
ScalAdd(const Scalar factor)
Constructor.
Definition: add.h:354
Tile scale-addition operation.
Definition: add.h:243
void permute(InputOp &&input_op, OutputOp &&output_op, Result &result, const Permutation &perm, const Arg0 &arg0, const Args &... args)
Construct a permuted tensor copy.
Definition: permute.h:122
Left left_type
Left-hand argument base type.
Definition: add.h:248
Tile< Result > & scale_to(Tile< Result > &result, const Scalar factor)
Scale to the result tile.
Definition: tile.h:725
static constexpr bool left_is_consumable
Indicates whether it is possible to consume the left tile.
Definition: add.h:254
void scale(DistArray< Tile, Policy > &a, typename DistArray< Tile, Policy >::element_type scaling_factor)
Definition: utils.h:108
result_type consume_right(L &&left, right_type &right) const
Add left to right.
Definition: add.h:214
Right right_type
Right-hand argument base type.
Definition: add.h:249
Place-holder object for a zero tensor.
Definition: zero_tensor.h:32
Add< Result, Left, Right, LeftConsumable, RightConsumable > Add_
This class type.
Definition: add.h:58
Tile< Result > & add_to(Tile< Result > &result, const Tile< Arg > &arg)
Add to the result tile.
Definition: tile.h:441
result_type operator()(L &&left, R &&right, const Permutation &perm) const
Scale-add-and-permute operator.
Definition: add.h:369
Left left_type
Left-hand argument base type.
Definition: add.h:59
Result result_type
Result tile type.
Definition: add.h:251
Tile addition operation.
Definition: add.h:54
decltype(auto) add(const Tile< Left > &left, const Tile< Right > &right)
Add tile arguments.
Definition: tile.h:362
Permute a tile.
Definition: permute.h:130
ScalAdd_ & operator=(const ScalAdd_ &)=default
result_type operator()(L &&left, R &&right) const
Scale-and-add operator.
Definition: add.h:384
DistArray< Tile, Policy > clone(const DistArray< Tile, Policy > &arg)
Create a deep copy of an array.
Definition: clone.h:43
static constexpr bool right_is_consumable
Indicates whether it is possible to consume the right tile.
Definition: add.h:67
ScalAdd(const ScalAdd_ &)=default
Scalar scalar_type
Scaling factor type.
Definition: add.h:250
result_type consume_left(left_type &left, R &&right) const
Add right to left and scale the result.
Definition: add.h:399
result_type operator()(L &&left, R &&right) const
Add operator.
Definition: add.h:179
result_type consume_left(left_type &left, R &&right) const
Add right to left.
Definition: add.h:194
Result result_type
The result tile type.
Definition: add.h:61
Consumable tile type trait.
Definition: type_traits.h:406
Permutation of a sequence of objects indexed by base-0 indices.
Definition: permutation.h:119
static constexpr bool right_is_consumable
Indicates whether it is possible to consume the right tile.
Definition: add.h:257
ScalAdd< Result, Left, Right, Scalar, LeftConsumable, RightConsumable > ScalAdd_
This class type.
Definition: add.h:247
result_type operator()(L &&left, R &&right, const Permutation &perm) const
Add-and-permute operator.
Definition: add.h:164
result_type consume_right(L &&left, right_type &right) const
Add left to right and scale the result.
Definition: add.h:419
Create a deep copy of a tile.
Definition: clone.h:138