TiledArray  0.7.0
mult.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  * mult.h
22  * May 8, 2013
23  *
24  */
25 
26 #ifndef TILEDARRAY_TILE_OP_MULT_H__INCLUDED
27 #define TILEDARRAY_TILE_OP_MULT_H__INCLUDED
28 
29 #include <TiledArray/error.h>
31 #include <TiledArray/zero_tensor.h>
32 
33 namespace TiledArray {
34  namespace detail {
35 
37 
49  template <typename Result, typename Left, typename Right,
50  bool LeftConsumable, bool RightConsumable>
51  class Mult {
52  public:
53 
55  typedef Left left_type;
56  typedef Right right_type;
57  typedef Result result_type;
58 
60  static constexpr bool left_is_consumable =
61  LeftConsumable && std::is_same<result_type, left_type>::value;
63  static constexpr bool right_is_consumable =
64  RightConsumable && std::is_same<result_type, right_type>::value;
65 
66  private:
67 
68  // Permuting tile evaluation function
69  // These operations cannot consume the argument tile since this operation
70  // requires temporary storage space.
71 
72  static result_type eval(const left_type& first, const right_type& second,
73  const Permutation& perm)
74  {
75  using TiledArray::mult;
76  return mult(first, second, perm);
77  }
78 
79  static result_type eval(ZeroTensor, const right_type& second,
80  const Permutation& perm)
81  {
82  TA_ASSERT(false); // Invalid arguments for this operation
83  return result_type();
84  }
85 
86  static result_type eval(const left_type& first, ZeroTensor,
87  const Permutation& perm)
88  {
89  TA_ASSERT(false); // Invalid arguments for this operation
90  return result_type();
91  }
92 
93  // Non-permuting tile evaluation functions
94  // The compiler will select the correct functions based on the
95  // consumability of the arguments.
96 
97  template <bool LC, bool RC,
98  typename std::enable_if<!(LC || RC)>::type* = nullptr>
99  static result_type
100  eval(const left_type& first, const right_type& second) {
101  using TiledArray::mult;
102  return mult(first, second);
103  }
104 
105  template <bool LC, bool RC,
106  typename std::enable_if<LC>::type* = nullptr>
107  static result_type eval(left_type& first, const right_type& second) {
108  using TiledArray::mult_to;
109  return mult_to(first, second);
110  }
111 
112  template <bool LC, bool RC,
113  typename std::enable_if<!LC && RC>::type* = nullptr>
114  static result_type eval(const left_type& first, right_type& second) {
115  using TiledArray::mult_to;
116  return mult_to(second, first);
117  }
118 
119  template <bool LC, bool RC,
120  typename std::enable_if<!RC>::type* = nullptr>
121  static result_type eval(ZeroTensor, const right_type& second) {
122  TA_ASSERT(false); // Invalid arguments for this operation
123  return result_type();
124  }
125 
126  template <bool LC, bool RC,
127  typename std::enable_if<RC>::type* = nullptr>
128  static result_type eval(ZeroTensor, right_type& second) {
129  TA_ASSERT(false); // Invalid arguments for this operation
130  return result_type();
131  }
132 
133  template <bool LC, bool RC,
134  typename std::enable_if<!LC>::type* = nullptr>
135  static result_type eval(const left_type& first, ZeroTensor) {
136  TA_ASSERT(false); // Invalid arguments for this operation
137  return result_type();
138  }
139 
140  template <bool LC, bool RC,
141  typename std::enable_if<LC>::type* = nullptr>
142  static result_type eval(left_type& first, ZeroTensor) {
143  TA_ASSERT(false); // Invalid arguments for this operation
144  return result_type();
145  }
146 
147  public:
148 
150 
158  template <typename L, typename R>
160  operator()(L&& left, R&& right, const Permutation& perm) const {
161  return eval(std::forward<L>(left), std::forward<R>(right), perm);
162  }
163 
165 
172  template <typename L, typename R>
173  result_type operator()(L&& left, R&& right) const {
174  return Mult_::template eval<left_is_consumable, right_is_consumable>(
175  std::forward<L>(left), std::forward<R>(right));
176  }
177 
179 
185  template <typename R>
186  result_type consume_left(left_type& left, R&& right) const {
187  constexpr bool can_consume_left =
189  std::is_same<result_type, left_type>::value;
190  constexpr bool can_consume_right = right_is_consumable &&
191  ! (std::is_const<R>::value || can_consume_left);
192  return Mult_::template eval<can_consume_left, can_consume_right>(left,
193  std::forward<R>(right));
194  }
195 
197 
203  template <typename L>
204  result_type consume_right(L&& left, right_type& right) const {
205  constexpr bool can_consume_right =
207  std::is_same<result_type, right_type>::value;
208  constexpr bool can_consume_left = left_is_consumable &&
209  ! (std::is_const<L>::value || can_consume_right);
210  return Mult_::template eval<can_consume_left, can_consume_right>(
211  std::forward<L>(left), right);
212  }
213 
214  }; // class Mult
215 
217 
231  template <typename Result, typename Left, typename Right, typename Scalar,
232  bool LeftConsumable, bool RightConsumable>
233  class ScalMult {
234  public:
235 
236  typedef ScalMult<Result, Left, Right, Scalar, LeftConsumable,
237  RightConsumable> ScalMult_;
238  typedef Left left_type;
239  typedef Right right_type;
240  typedef Scalar scalar_type;
241  typedef Result result_type;
242 
244  static constexpr bool left_is_consumable =
245  LeftConsumable && std::is_same<result_type, left_type>::value;
247  static constexpr bool right_is_consumable =
248  RightConsumable && std::is_same<result_type, right_type>::value;
249 
250  private:
251 
252  scalar_type factor_;
253 
254  // Permuting tile evaluation function
255  // These operations cannot consume the argument tile since this operation
256  // requires temporary storage space.
257 
258  result_type eval(const left_type& first, const right_type& second,
259  const Permutation& perm) const
260  {
261  using TiledArray::mult;
262  return mult(first, second, factor_, perm);
263  }
264 
265  result_type eval(ZeroTensor, const right_type& second,
266  const Permutation& perm) const
267  {
268  TA_ASSERT(false); // Invalid arguments for this operation
269  return result_type();
270  }
271 
272  result_type eval(const left_type& first, ZeroTensor,
273  const Permutation& perm) const
274  {
275  TA_ASSERT(false); // Invalid arguments for this operation
276  return result_type();
277  }
278 
279  // Non-permuting tile evaluation functions
280  // The compiler will select the correct functions based on the
281  // consumability of the arguments.
282 
283  template <bool LC, bool RC,
284  typename std::enable_if<!(LC || RC)>::type* = nullptr>
285  result_type eval(const left_type& first, const right_type& second) const {
286  using TiledArray::mult;
287  return mult(first, second, factor_);
288  }
289 
290  template <bool LC, bool RC,
291  typename std::enable_if<LC>::type* = nullptr>
292  result_type eval(left_type& first, const right_type& second) const {
293  using TiledArray::mult_to;
294  return mult_to(first, second, factor_);
295  }
296 
297  template <bool LC, bool RC,
298  typename std::enable_if<!LC && RC>::type* = nullptr>
299  result_type eval(const left_type& first, right_type& second) const {
300  using TiledArray::mult_to;
301  return mult_to(second, first, factor_);
302  }
303 
304  template <bool LC, bool RC,
305  typename std::enable_if<!RC>::type* = nullptr>
306  result_type eval(ZeroTensor, const right_type& second) const {
307  TA_ASSERT(false); // Invalid arguments for this operation
308  return result_type();
309  }
310 
311  template <bool LC, bool RC,
312  typename std::enable_if<RC>::type* = nullptr>
313  result_type eval(ZeroTensor, right_type& second) const {
314  TA_ASSERT(false); // Invalid arguments for this operation
315  return result_type();
316  }
317 
318  template <bool LC, bool RC,
319  typename std::enable_if<!LC>::type* = nullptr>
320  result_type eval(const left_type& first, ZeroTensor) const {
321  TA_ASSERT(false); // Invalid arguments for this operation
322  return result_type();
323  }
324 
325  template <bool LC, bool RC,
326  typename std::enable_if<LC>::type* = nullptr>
327  result_type eval(left_type& first, ZeroTensor) const {
328  TA_ASSERT(false); // Invalid arguments for this operation
329  return result_type();
330  }
331 
332  public:
333 
334  // Compiler generated functions
335  ScalMult(const ScalMult_&) = default;
336  ScalMult(ScalMult_&&) = default;
337  ~ScalMult() = default;
338  ScalMult_& operator=(const ScalMult_&) = default;
339  ScalMult_& operator=(ScalMult_&&) = default;
340 
342 
344  explicit ScalMult(const Scalar factor) : factor_(factor) { }
345 
347 
355  template <typename L, typename R>
357  operator()(L&& left, R&& right, const Permutation& perm) const {
358  return eval(std::forward<L>(left), std::forward<R>(right), perm);
359  }
360 
362 
369  template <typename L, typename R>
370  result_type operator()(L&& left, R&& right) const {
371  return ScalMult_::template eval<left_is_consumable,
372  right_is_consumable>(std::forward<L>(left), std::forward<R>(right));
373  }
374 
376 
382  template <typename R>
383  result_type consume_left(left_type& left, R&& right) const {
384  constexpr bool can_consume_left =
386  std::is_same<result_type, left_type>::value;
387  constexpr bool can_consume_right = right_is_consumable &&
388  ! (std::is_const<R>::value || can_consume_left);
389  return ScalMult_::template eval<can_consume_left, can_consume_right>(
390  left, std::forward<R>(right));
391  }
392 
394 
401  template <typename L>
402  result_type consume_right(L&& left, right_type& right) const {
403  constexpr bool can_consume_right =
405  std::is_same<result_type, right_type>::value;
406  constexpr bool can_consume_left = left_is_consumable &&
407  ! (std::is_const<L>::value || can_consume_right);
408  return ScalMult_::template eval<can_consume_left, can_consume_right>(
409  std::forward<L>(left), right);
410  }
411 
412  }; // class ScalMult
413 
414  } // namespace detail
415 } // namespace TiledArray
416 
417 #endif // TILEDARRAY_TILE_OP_MULT_H__INCLUDED
ScalMult(const ScalMult_ &)=default
static constexpr bool right_is_consumable
Indicates whether it is possible to consume the right tile.
Definition: mult.h:63
Left left_type
Left-hand argument base type.
Definition: mult.h:55
Result result_type
Result tile type.
Definition: mult.h:241
result_type operator()(L &&left, R &&right, const Permutation &perm) const
Scale-multiply-and-permute operator.
Definition: mult.h:357
static constexpr bool left_is_consumable
Indicates whether it is possible to consume the left tile.
Definition: mult.h:60
result_type operator()(L &&left, R &&right) const
Multiply operator.
Definition: mult.h:173
Tile< Result > & mult_to(Tile< Result > &result, const Tile< Arg > &arg)
Multiply to the result tile.
Definition: tile.h:668
Scalar scalar_type
Scaling factor type.
Definition: mult.h:240
static constexpr bool left_is_consumable
Indicates whether it is possible to consume the left tile.
Definition: mult.h:244
Place-holder object for a zero tensor.
Definition: zero_tensor.h:32
result_type consume_left(left_type &left, R &&right) const
Multiply right to left and scale the result.
Definition: mult.h:383
Mult< Result, Left, Right, LeftConsumable, RightConsumable > Mult_
Definition: mult.h:54
Right right_type
Right-hand argument base type.
Definition: mult.h:239
#define TA_ASSERT(a)
Definition: error.h:107
result_type operator()(L &&left, R &&right) const
Scale-and-multiply operator.
Definition: mult.h:370
Tile scale-multiplication operation.
Definition: mult.h:233
result_type operator()(L &&left, R &&right, const Permutation &perm) const
Multiply-and-permute operator.
Definition: mult.h:160
Result result_type
The result tile type.
Definition: mult.h:57
result_type consume_right(L &&left, right_type &right) const
Multiply left to right and scale the result.
Definition: mult.h:402
Consumable tile type trait.
Definition: type_traits.h:406
Right right_type
Right-hand argument base type.
Definition: mult.h:56
Tile multiplication operation.
Definition: mult.h:51
static constexpr bool right_is_consumable
Indicates whether it is possible to consume the right tile.
Definition: mult.h:247
result_type consume_left(left_type &left, R &&right) const
Multiply right to left.
Definition: mult.h:186
Left left_type
Left-hand argument base type.
Definition: mult.h:238
Permutation of a sequence of objects indexed by base-0 indices.
Definition: permutation.h:119
ScalMult< Result, Left, Right, Scalar, LeftConsumable, RightConsumable > ScalMult_
This class type.
Definition: mult.h:237
result_type consume_right(L &&left, right_type &right) const
Multiply left to right.
Definition: mult.h:204
decltype(auto) mult(const Tile< Left > &left, const Tile< Right > &right)
Multiplication tile arguments.
Definition: tile.h:614
ScalMult_ & operator=(const ScalMult_ &)=default
ScalMult(const Scalar factor)
Constructor.
Definition: mult.h:344