TiledArray  0.7.0
binary_wrapper.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  * binary_interface.h
22  * Oct 6, 2013
23  *
24  */
25 
26 #ifndef TILEDARRAY_TILE_OP_BINARY_WRAPPER_H__INCLUDED
27 #define TILEDARRAY_TILE_OP_BINARY_WRAPPER_H__INCLUDED
28 
30 #include <TiledArray/permutation.h>
31 #include <TiledArray/zero_tensor.h>
32 
33 namespace TiledArray {
34  namespace detail {
35 
37 
88  template <typename Op>
89  class BinaryWrapper {
90  public:
92  typedef typename Op::left_type left_type;
93  typedef typename Op::right_type right_type;
94  typedef typename Op::result_type result_type;
95 
96 
98  static constexpr bool left_is_consumable = Op::left_is_consumable;
100  static constexpr bool right_is_consumable = Op::right_is_consumable;
101 
102  template <typename T>
103  static constexpr auto is_lazy_tile_v = is_lazy_tile<std::decay_t<T> >::value;
104 
105  template <typename T>
106  static constexpr auto is_array_tile_v = is_array_tile<std::decay_t<T> >::value;
107 
108  template <typename T>
109  static constexpr auto is_nonarray_lazy_tile_v = is_lazy_tile_v<T> && !is_array_tile_v<T>;
110 
111  template <typename T>
112  using eval_t = typename eval_trait<std::decay_t<T> >::type;
113 
114  private:
115 
116  Op op_;
117  Permutation perm_;
118 
119  public:
120 
121  // Compiler generated functions
122  BinaryWrapper(const BinaryWrapper<Op>&) = default;
123  BinaryWrapper(BinaryWrapper<Op>&&) = default;
124  ~BinaryWrapper() = default;
125  BinaryWrapper<Op>& operator=(const BinaryWrapper<Op>&) = default;
127 
128  BinaryWrapper(const Op& op, const Permutation& perm) :
129  op_(op), perm_(perm)
130  { }
131 
132  BinaryWrapper(const Op& op) :
133  op_(op), perm_()
134  { }
135 
136 
138 
145  template <typename L, typename R,
146  std::enable_if_t<!(is_lazy_tile_v<L> || is_lazy_tile_v<R>)>* =
147  nullptr>
148  auto operator()(L&& left, R&& right) const {
149  static_assert(std::is_same<std::decay_t<L>, left_type>::value,
150  "BinaryWrapper::operator()(L&&,R&&): invalid argument type L");
151  static_assert(std::is_same<std::decay_t<R>, right_type>::value,
152  "BinaryWrapper::operator()(L&&,R&&): invalid argument type R");
153  if (perm_)
154  return op_(std::forward<L>(left), std::forward<R>(right), perm_);
155 
156  return op_(std::forward<L>(left), std::forward<R>(right));
157  }
158 
160 
167  template <typename R, std::enable_if_t<!is_lazy_tile_v<R> >* = nullptr>
168  auto operator()(const ZeroTensor& left, R&& right) const {
169  static_assert(std::is_same<std::decay_t<R>, right_type>::value,
170  "BinaryWrapper::operator()(zero,R&&): invalid argument type R");
171  if(perm_)
172  return op_(left, std::forward<R>(right), perm_);
173 
174  return op_(left, std::forward<R>(right));
175  }
176 
178 
185  template <typename L, std::enable_if_t<!is_lazy_tile_v<L> >* = nullptr>
186  auto operator()(L&& left, const ZeroTensor& right) const {
187  static_assert(std::is_same<std::decay_t<L>, left_type>::value,
188  "BinaryWrapper::operator()(L&&,zero): invalid argument type L");
189  if(perm_)
190  return op_(std::forward<L>(left), right, perm_);
191 
192  return op_(std::forward<L>(left), right);
193  }
194 
195  // The following operators will evaluate lazy tile and use the base class
196  // interface functions to call the correct evaluation kernel.
197 
199 
209  template <typename L, typename R,
210  std::enable_if_t<is_lazy_tile_v<L> && is_lazy_tile_v<R> &&
212  nullptr>
213  auto operator()(L&& left, R&& right) const {
214  auto eval_left = invoke_cast(std::forward<L>(left));
215  auto eval_right = invoke_cast(std::forward<R>(right));
216  auto continuation = [this](decltype(eval_left)& l, decltype(eval_right)& r) {
217  return BinaryWrapper_::operator()(l, r);
218  };
220  return invoke(continuation, eval_left, eval_right);
221  }
222 
224 
234  template <typename L, typename R,
235  std::enable_if_t<is_lazy_tile_v<L> &&
236  (!is_lazy_tile_v<R>)&&(left_is_consumable ||
238  nullptr>
239  auto operator()(L&& left, R&& right) const {
240  auto eval_left = invoke_cast(std::forward<L>(left));
241  auto continuation = [this](decltype(eval_left)& l, R&& r) {
242  return BinaryWrapper_::operator()(l, std::forward<R>(r));
243  };
245  return invoke(continuation, eval_left, right);
246  }
247 
249 
259  template <typename L, typename R,
260  std::enable_if_t<(!is_lazy_tile_v<L>)&&is_lazy_tile_v<R> &&
262  nullptr>
263  auto operator()(L&& left, R&& right) const {
264  auto eval_right = invoke_cast(std::forward<R>(right));
265  return BinaryWrapper_::operator()(std::forward<L>(left), eval_right);
266  }
267 
268 
270 
279  template <typename L, typename R,
280  std::enable_if_t<is_array_tile_v<L> && is_array_tile_v<R> &&
281  !(left_is_consumable ||
282  right_is_consumable)>* = nullptr>
283  auto operator()(L&& left, R&& right) const {
284  auto eval_left = invoke_cast(std::forward<L>(left));
285  auto eval_right = invoke_cast(std::forward<R>(right));
286 
288 
289  if(perm_)
290  return invoke(op_, eval_left, eval_right, perm_);
291 
292  auto op_left =[=](eval_t<L>&_left, eval_t<R>& _right) {
293  return op_.consume_left(_left, _right);
294  };
295  auto op_right =[=](eval_t<L>&_left, eval_t<R>& _right) {
296  return op_.consume_right(_left, _right);
297  };
298  // Override consumable
299  if(is_consumable_tile<eval_t<L> >::value && left.is_consumable())
300  return invoke(op_left, eval_left, eval_right);
301  if(is_consumable_tile<eval_t<R> >::value && right.is_consumable())
302  return invoke(op_right, eval_left, eval_right);
303 
304  return invoke(op_, eval_left, eval_right);
305  }
306 
307  template <typename L, typename R,
308  std::enable_if_t<
309  is_array_tile_v<L> &&
310  (!is_lazy_tile_v<R>)&&!(left_is_consumable ||
311  right_is_consumable)>* = nullptr>
312  auto operator()(L&& left, R&& right) const {
313  auto eval_left = invoke_cast(std::forward<L>(left));
314 
315  if(perm_)
316  return op_(eval_left, std::forward<R>(right), perm_);
317 
318  // Override consumable
319  if(is_consumable_tile<eval_t<L> >::value && left.is_consumable())
320  return op_.consume_left(eval_left, std::forward<R>(right));
321 
322  return op_(eval_left, std::forward<R>(right));
323  }
324 
325  template <typename L, typename R,
326  std::enable_if_t<
327  is_array_tile_v<L> && is_nonarray_lazy_tile_v<R> &&
328  !(left_is_consumable || right_is_consumable)>* = nullptr>
329  auto operator()(L&& left, R&& right) const {
330  auto eval_left = invoke_cast(std::forward<L>(left));
331  auto eval_right = invoke_cast(std::forward<R>(right));
332 
333  if(perm_)
334  return op_(eval_left, eval_right, perm_);
335 
336  // Override consumable
337  if(is_consumable_tile<eval_t<L> >::value && left.is_consumable())
338  return op_.consume_left(eval_left, eval_right);
339 
340  return op_(eval_left, eval_right);
341  }
342 
343  template <typename L, typename R,
344  std::enable_if_t<(!is_lazy_tile_v<L>)&&is_array_tile_v<R> &&
345  !(left_is_consumable ||
346  right_is_consumable)>* = nullptr>
347  auto operator()(L&& left, R&& right) const {
348  auto eval_right = invoke_cast(std::forward<R>(right));
349 
350  if(perm_)
351  return op_(std::forward<L>(left), eval_right, perm_);
352 
353  // Override consumable
354  if(is_consumable_tile<eval_t<R> >::value && right.is_consumable())
355  return op_.consume_right(std::forward<L>(left), eval_right);
356 
357  return op_(std::forward<L>(left), eval_right);
358  }
359 
360  template <typename L, typename R,
361  std::enable_if_t<
362  is_nonarray_lazy_tile_v<L> && is_array_tile_v<R> &&
363  !(left_is_consumable || right_is_consumable)>* = nullptr>
364  auto operator()(L&& left, R&& right) const {
365  auto eval_left = invoke_cast(std::forward<L>(left));
366  auto eval_right = invoke_cast(std::forward<R>(right));
367 
368  if(perm_)
369  return op_(eval_left, eval_right, perm_);
370 
371  // Override consumable
372  if(is_consumable_tile<eval_t<R> >::value && right.is_consumable())
373  return op_.consume_right(eval_left, eval_right);
374 
375  return op_(eval_left, eval_right);
376  }
377 
378  }; // class BinaryWrapper
379 
380  } // namespace detail
381 } // namespace TiledArray
382 
383 #endif // TILEDARRAY_TILE_OP_BINARY_WRAPPER_H__INCLUDED
BinaryWrapper< Op > BinaryWrapper_
Op::result_type result_type
The result tile type.
static constexpr auto is_array_tile_v
auto invoke_cast(Arg &&arg)
Definition: cast.h:178
static constexpr bool left_is_consumable
Boolean value that indicates the left-hand argument can always be consumed.
Op::right_type right_type
Right-hand argument type.
Determine the object type used in the evaluation of tensor expressions.
Definition: type_traits.h:296
BinaryWrapper(const BinaryWrapper< Op > &)=default
static constexpr auto is_lazy_tile_v
BinaryWrapper(const Op &op, const Permutation &perm)
Place-holder object for a zero tensor.
Definition: zero_tensor.h:32
Op::left_type left_type
Left-hand argument type.
static constexpr auto is_nonarray_lazy_tile_v
Binary tile operation wrapper.
static constexpr bool right_is_consumable
Boolean value that indicates the right-hand argument can always be consumed.
typename eval_trait< std::decay_t< T > >::type eval_t
Detect tiles used by ArrayEvalImpl.
Definition: type_traits.h:451
auto operator()(L &&left, R &&right) const
Evaluate two non-zero tiles and possibly permute.
Consumable tile type trait.
Definition: type_traits.h:406
auto operator()(const ZeroTensor &left, R &&right) const
Evaluate a zero tile to a non-zero tiles and possibly permute.
Permutation of a sequence of objects indexed by base-0 indices.
Definition: permutation.h:119
auto operator()(L &&left, const ZeroTensor &right) const
Evaluate a non-zero tiles to a zero tile and possibly permute.
auto invoke(Function &&fn, Args &&... args) -> typename std::enable_if< !or_reduce< false, madness::is_future< std::decay_t< Args >>::value... >::value, decltype(fn(args...))>::type
Definition: meta.h:52
Detect lazy evaluation tiles.
Definition: type_traits.h:388
BinaryWrapper< Op > & operator=(const BinaryWrapper< Op > &)=default