26 #ifndef TILEDARRAY_TILE_OP_BINARY_WRAPPER_H__INCLUDED 27 #define TILEDARRAY_TILE_OP_BINARY_WRAPPER_H__INCLUDED 88 template <
typename Op>
102 template <
typename T>
105 template <
typename T>
108 template <
typename T>
111 template <
typename T>
145 template <
typename L,
typename R,
146 std::enable_if_t<!(is_lazy_tile_v<L> || is_lazy_tile_v<R>)>* =
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");
154 return op_(std::forward<L>(left), std::forward<R>(right), perm_);
156 return op_(std::forward<L>(left), std::forward<R>(right));
167 template <
typename R, std::enable_if_t<!is_lazy_tile_v<R> >* =
nullptr>
169 static_assert(std::is_same<std::decay_t<R>,
right_type>::value,
170 "BinaryWrapper::operator()(zero,R&&): invalid argument type R");
172 return op_(left, std::forward<R>(right), perm_);
174 return op_(left, std::forward<R>(right));
185 template <
typename L, std::enable_if_t<!is_lazy_tile_v<L> >* =
nullptr>
187 static_assert(std::is_same<std::decay_t<L>,
left_type>::value,
188 "BinaryWrapper::operator()(L&&,zero): invalid argument type L");
190 return op_(std::forward<L>(left), right, perm_);
192 return op_(std::forward<L>(left), right);
209 template <
typename L,
typename R,
210 std::enable_if_t<is_lazy_tile_v<L> && is_lazy_tile_v<R> &&
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) {
220 return invoke(continuation, eval_left, eval_right);
234 template <
typename L,
typename R,
235 std::enable_if_t<is_lazy_tile_v<L> &&
240 auto eval_left =
invoke_cast(std::forward<L>(left));
241 auto continuation = [
this](decltype(eval_left)& l, R&& r) {
245 return invoke(continuation, eval_left, right);
259 template <
typename L,
typename R,
260 std::enable_if_t<(!is_lazy_tile_v<L>)&&is_lazy_tile_v<R> &&
264 auto eval_right =
invoke_cast(std::forward<R>(right));
279 template <
typename L,
typename R,
280 std::enable_if_t<is_array_tile_v<L> && is_array_tile_v<R> &&
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));
290 return invoke(op_, eval_left, eval_right, perm_);
293 return op_.consume_left(_left, _right);
296 return op_.consume_right(_left, _right);
300 return invoke(op_left, eval_left, eval_right);
302 return invoke(op_right, eval_left, eval_right);
304 return invoke(op_, eval_left, eval_right);
307 template <
typename L,
typename R,
309 is_array_tile_v<L> &&
313 auto eval_left =
invoke_cast(std::forward<L>(left));
316 return op_(eval_left, std::forward<R>(right), perm_);
320 return op_.consume_left(eval_left, std::forward<R>(right));
322 return op_(eval_left, std::forward<R>(right));
325 template <
typename L,
typename R,
327 is_array_tile_v<L> && is_nonarray_lazy_tile_v<R> &&
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));
334 return op_(eval_left, eval_right, perm_);
338 return op_.consume_left(eval_left, eval_right);
340 return op_(eval_left, eval_right);
343 template <
typename L,
typename R,
344 std::enable_if_t<(!is_lazy_tile_v<L>)&&is_array_tile_v<R> &&
348 auto eval_right =
invoke_cast(std::forward<R>(right));
351 return op_(std::forward<L>(left), eval_right, perm_);
355 return op_.consume_right(std::forward<L>(left), eval_right);
357 return op_(std::forward<L>(left), eval_right);
360 template <
typename L,
typename R,
362 is_nonarray_lazy_tile_v<L> && is_array_tile_v<R> &&
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));
369 return op_(eval_left, eval_right, perm_);
373 return op_.consume_right(eval_left, eval_right);
375 return op_(eval_left, eval_right);
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)
static constexpr bool left_is_consumable
Boolean value that indicates the left-hand argument can always be consumed.
BinaryWrapper(const Op &op)
Op::right_type right_type
Right-hand argument type.
Determine the object type used in the evaluation of tensor expressions.
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.
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.
auto operator()(L &&left, R &&right) const
Evaluate two non-zero tiles and possibly permute.
Consumable tile type trait.
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.
auto operator()(L &&left, const ZeroTensor &right) const
Evaluate a non-zero tiles to a zero tile and possibly permute.
Detect lazy evaluation tiles.
BinaryWrapper< Op > & operator=(const BinaryWrapper< Op > &)=default