subt.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  * subt.h
22  * May 8, 2013
23  *
24  */
25 
26 #ifndef TILEDARRAY_TILE_OP_SUBT_H__INCLUDED
27 #define TILEDARRAY_TILE_OP_SUBT_H__INCLUDED
28 
30 #include <TiledArray/zero_tensor.h>
31 #include "../tile_interface/clone.h"
32 #include "../tile_interface/permute.h"
33 #include "../tile_interface/scale.h"
34 
35 namespace TiledArray {
36 namespace detail {
37 
39 
51 template <typename Result, typename Left, typename Right, bool LeftConsumable,
52  bool RightConsumable>
53 class Subt {
54  public:
56  typedef Left left_type;
57  typedef Right right_type;
58  typedef Result result_type;
59 
61  static constexpr bool left_is_consumable =
62  LeftConsumable && std::is_same<result_type, left_type>::value;
64  static constexpr bool right_is_consumable =
65  RightConsumable && std::is_same<result_type, right_type>::value;
66 
67  private:
68  // Permuting tile evaluation function
69  // These operations cannot consume the argument tile since this operation
70  // requires temporary storage space.
71 
72  template <typename Perm, typename = std::enable_if_t<
73  TiledArray::detail::is_permutation_v<Perm>>>
74  static result_type eval(const left_type& first, const right_type& second,
75  const Perm& perm) {
76  using TiledArray::subt;
77  return subt(first, second, perm);
78  }
79 
80  template <typename Perm, typename = std::enable_if_t<
81  TiledArray::detail::is_permutation_v<Perm>>>
82  static result_type eval(ZeroTensor, const right_type& second,
83  const Perm& perm) {
84  using TiledArray::neg;
85  return neg(second, perm);
86  }
87 
88  template <typename Perm, typename = std::enable_if_t<
89  TiledArray::detail::is_permutation_v<Perm>>>
90  static result_type eval(const left_type& first, ZeroTensor,
91  const Perm& perm) {
92  using TiledArray::permute;
93  return permute(first, perm);
94  }
95 
96  // Non-permuting tile evaluation functions
97  // The compiler will select the correct functions based on the
98  // consumability of the arguments.
99 
100  template <bool LC, bool RC,
101  typename std::enable_if<!(LC || RC)>::type* = nullptr>
102  static result_type eval(const left_type& first, const right_type& second) {
103  using TiledArray::subt;
104  return subt(first, second);
105  }
106 
107  template <bool LC, bool RC, typename std::enable_if<LC>::type* = nullptr>
108  static result_type eval(left_type& first, const right_type& second) {
109  using TiledArray::subt_to;
110  return subt_to(first, second);
111  }
112 
113  template <bool LC, bool RC,
114  typename std::enable_if<!LC && RC>::type* = nullptr>
115  static result_type eval(const left_type& first, right_type& second) {
116  using TiledArray::subt_to;
117  return subt_to(second, first, -1);
118  }
119 
120  template <bool LC, bool RC, typename std::enable_if<!RC>::type* = nullptr>
121  static result_type eval(ZeroTensor, const right_type& second) {
122  using TiledArray::neg;
123  return neg(second);
124  }
125 
126  template <bool LC, bool RC, typename std::enable_if<RC>::type* = nullptr>
127  static result_type eval(ZeroTensor, right_type& second) {
128  using TiledArray::neg_to;
129  return neg_to(second);
130  }
131 
132  template <bool LC, bool RC, typename std::enable_if<!LC>::type* = nullptr>
133  static result_type eval(const left_type& first, ZeroTensor) {
135  return clone(first);
136  }
137 
138  template <bool LC, bool RC, typename std::enable_if<LC>::type* = nullptr>
139  static result_type eval(left_type& first, ZeroTensor) {
140  return first;
141  }
142 
143  public:
145 
155  template <
156  typename L, typename R, typename Perm,
157  typename = std::enable_if_t<TiledArray::detail::is_permutation_v<Perm>>>
158  result_type operator()(L&& left, R&& right, const Perm& perm) const {
159  return eval(std::forward<L>(left), std::forward<R>(right), perm);
160  }
161 
163 
172  template <typename L, typename R>
173  result_type operator()(L&& left, R&& right) const {
174  return Subt_::template eval<left_is_consumable, right_is_consumable>(
175  std::forward<L>(left), std::forward<R>(right));
176  }
177 
179 
187  template <typename R>
188  result_type consume_left(left_type& left, R&& right) const {
189  constexpr bool can_consume_left =
191  std::is_same<result_type, left_type>::value;
192  constexpr bool can_consume_right =
193  right_is_consumable && !(std::is_const<R>::value || can_consume_left);
194  return Subt_::template eval<can_consume_left, can_consume_right>(
195  left, std::forward<R>(right));
196  }
197 
199 
207  template <typename L>
208  result_type consume_right(L&& left, right_type& right) const {
209  constexpr bool can_consume_right =
211  std::is_same<result_type, right_type>::value;
212  constexpr bool can_consume_left =
213  left_is_consumable && !(std::is_const<L>::value || can_consume_right);
214  return Subt_::template eval<can_consume_left, can_consume_right>(
215  std::forward<L>(left), right);
216  }
217 
218 }; // class Subt
219 
221 
235 template <typename Result, typename Left, typename Right, typename Scalar,
236  bool LeftConsumable, bool RightConsumable>
237 class ScalSubt {
238  public:
239  typedef ScalSubt<Result, Left, Right, Scalar, LeftConsumable,
240  RightConsumable>
242  typedef Left left_type;
243  typedef Right right_type;
244  typedef Scalar scalar_type;
245  typedef Result result_type;
246 
247  static constexpr bool left_is_consumable =
248  LeftConsumable && std::is_same<result_type, left_type>::value;
249  static constexpr bool right_is_consumable =
250  RightConsumable && std::is_same<result_type, right_type>::value;
251 
252  private:
253  scalar_type factor_;
254 
255  // Permuting tile evaluation function
256  // These operations cannot consume the argument tile since this operation
257  // requires temporary storage space.
258 
259  template <typename Perm, typename = std::enable_if_t<
260  TiledArray::detail::is_permutation_v<Perm>>>
261  result_type eval(const left_type& first, const right_type& second,
262  const Perm& perm) const {
263  using TiledArray::subt;
264  return subt(first, second, factor_, perm);
265  }
266 
267  template <typename Perm, typename = std::enable_if_t<
268  TiledArray::detail::is_permutation_v<Perm>>>
269  result_type eval(ZeroTensor, const right_type& second,
270  const Perm& perm) const {
271  using TiledArray::scale;
272  return scale(second, -factor_, perm);
273  }
274 
275  template <typename Perm, typename = std::enable_if_t<
276  TiledArray::detail::is_permutation_v<Perm>>>
277  result_type eval(const left_type& first, ZeroTensor, const Perm& perm) const {
278  using TiledArray::scale;
279  return scale(first, factor_, perm);
280  }
281 
282  // Non-permuting tile evaluation functions
283  // The compiler will select the correct functions based on the
284  // consumability of the arguments.
285 
286  template <bool LC, bool RC,
287  typename std::enable_if<!(LC || RC)>::type* = nullptr>
288  result_type eval(const left_type& first, const right_type& second) const {
289  using TiledArray::subt;
290  return subt(first, second, factor_);
291  }
292 
293  template <bool LC, bool RC, typename std::enable_if<LC>::type* = nullptr>
294  result_type eval(left_type& first, const right_type& second) const {
295  using TiledArray::subt_to;
296  return subt_to(first, second, factor_);
297  }
298 
299  template <bool LC, bool RC,
300  typename std::enable_if<!LC && RC>::type* = nullptr>
301  result_type eval(const left_type& first, right_type& second) const {
302  using TiledArray::subt_to;
303  return subt_to(second, first, -factor_);
304  }
305 
306  template <bool LC, bool RC, typename std::enable_if<!RC>::type* = nullptr>
307  result_type eval(ZeroTensor, const right_type& second) const {
308  using TiledArray::scale;
309  return scale(second, -factor_);
310  }
311 
312  template <bool LC, bool RC, typename std::enable_if<RC>::type* = nullptr>
313  result_type eval(ZeroTensor, right_type& second) const {
314  using TiledArray::scale_to;
315  return scale_to(second, -factor_);
316  }
317 
318  template <bool LC, bool RC, typename std::enable_if<!LC>::type* = nullptr>
319  result_type eval(const left_type& first, ZeroTensor) const {
320  using TiledArray::scale;
321  return scale(first, factor_);
322  }
323 
324  template <bool LC, bool RC, typename std::enable_if<LC>::type* = nullptr>
325  result_type eval(left_type& first, ZeroTensor) const {
326  using TiledArray::scale_to;
327  return scale_to(first, factor_);
328  }
329 
330  public:
331  // Compiler generated functions
332  ScalSubt(const ScalSubt_&) = default;
333  ScalSubt(ScalSubt_&&) = default;
334  ~ScalSubt() = default;
335  ScalSubt_& operator=(const ScalSubt_&) = default;
337 
339 
341  explicit ScalSubt(const Scalar factor) : factor_(factor) {}
342 
344 
354  template <
355  typename L, typename R, typename Perm,
356  typename = std::enable_if_t<TiledArray::detail::is_permutation_v<Perm>>>
357  result_type operator()(L&& left, R&& right, const Perm& perm) const {
358  return eval(std::forward<L>(left), std::forward<R>(right), perm);
359  }
360 
362 
371  template <typename L, typename R>
372  result_type operator()(L&& left, R&& right) const {
373  return ScalSubt_::template eval<left_is_consumable, right_is_consumable>(
374  std::forward<L>(left), std::forward<R>(right));
375  }
376 
378 
386  template <typename R>
387  result_type consume_left(left_type& left, R&& right) const {
388  constexpr bool can_consume_left =
390  std::is_same<result_type, left_type>::value;
391  constexpr bool can_consume_right =
392  right_is_consumable && !(std::is_const<R>::value || can_consume_left);
393  return ScalSubt_::template eval<can_consume_left, can_consume_right>(
394  left, std::forward<R>(right));
395  }
396 
398 
406  template <typename L>
407  result_type consume_right(L&& left, right_type& right) const {
408  constexpr bool can_consume_right =
410  std::is_same<result_type, right_type>::value;
411  constexpr bool can_consume_left =
412  left_is_consumable && !(std::is_const<L>::value || can_consume_right);
413  return ScalSubt_::template eval<can_consume_left, can_consume_right>(
414  std::forward<L>(left), right);
415  }
416 
417 }; // class ScalSubt
418 
419 } // namespace detail
420 } // namespace TiledArray
421 
422 #endif // TILEDARRAY_TILE_OP_SUBT_H__INCLUDED
decltype(auto) subt(const Tile< Left > &left, const Tile< Right > &right)
Subtract tile arguments.
Definition: tile.h:879
std::enable_if<!TiledArray::detail::is_permutation_v< Perm >, TiledArray::Range >::type permute(const TiledArray::Range &r, const Perm &p)
Definition: btas.h:803
Subt< Result, Left, Right, LeftConsumable, RightConsumable > Subt_
Definition: subt.h:55
Result result_type
The result tile type.
Definition: subt.h:58
Tile< Result > & scale_to(Tile< Result > &result, const Scalar factor)
Scale to the result tile.
Definition: tile.h:1204
Consumable tile type trait.
Definition: type_traits.h:611
result_type operator()(L &&left, R &&right, const Perm &perm) const
Scale-subtract-and-permute operator.
Definition: subt.h:357
Tile subtraction operation.
Definition: subt.h:53
result_type consume_left(left_type &left, R &&right) const
Subtract right to left and scale the result.
Definition: subt.h:387
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
result_type operator()(L &&left, R &&right) const
Subtract operator.
Definition: subt.h:173
static constexpr bool right_is_consumable
Definition: subt.h:249
Right right_type
Right-hand argument base type.
Definition: subt.h:243
static constexpr bool left_is_consumable
Definition: subt.h:247
ScalSubt(ScalSubt_ &&)=default
DistArray< Tile, Policy > clone(const DistArray< Tile, Policy > &arg)
Create a deep copy of an array.
Definition: clone.h:43
result_type operator()(L &&left, R &&right, const Perm &perm) const
Subtract-and-permute operator.
Definition: subt.h:158
ScalSubt(const ScalSubt_ &)=default
decltype(auto) neg(const Tile< Arg > &arg)
Negate the tile argument.
Definition: tile.h:1218
ScalSubt_ & operator=(const ScalSubt_ &)=default
Tile< Result > & neg_to(Tile< Result > &result)
In-place negate tile.
Definition: tile.h:1243
static constexpr bool right_is_consumable
Indicates whether it is possible to consume the right tile.
Definition: subt.h:64
Result result_type
The result tile type.
Definition: subt.h:245
Scalar scalar_type
Scaling factor type.
Definition: subt.h:244
decltype(auto) scale(const Tile< Arg > &arg, const Scalar factor)
Scalar the tile argument.
Definition: tile.h:1174
Place-holder object for a zero tensor.
Definition: zero_tensor.h:32
Tile scale-subtraction operation.
Definition: subt.h:237
ScalSubt< Result, Left, Right, Scalar, LeftConsumable, RightConsumable > ScalSubt_
This class type.
Definition: subt.h:241
Left left_type
Left-hand argument base type.
Definition: subt.h:56
ScalSubt_ & operator=(ScalSubt_ &&)=default
result_type consume_left(left_type &left, R &&right) const
Subtract right to left.
Definition: subt.h:188
Right right_type
Right-hand argument base type.
Definition: subt.h:57
result_type operator()(L &&left, R &&right) const
Scale-and-subtract operator.
Definition: subt.h:372
ScalSubt(const Scalar factor)
Constructor.
Definition: subt.h:341
Tile< Result > & subt_to(Tile< Result > &result, const Tile< Arg > &arg)
Subtract from the result tile.
Definition: tile.h:972
static constexpr bool left_is_consumable
Indicates whether it is possible to consume the left tile.
Definition: subt.h:61
Left left_type
Left-hand argument base type.
Definition: subt.h:242
Create a deep copy of a tile.
Definition: clone.h:128
result_type consume_right(L &&left, right_type &right) const
Subtract left to right and scale the result.
Definition: subt.h:407
result_type consume_right(L &&left, right_type &right) const
Subtract left to right.
Definition: subt.h:208