26 #ifndef TILEDARRAY_EXPRESSIONS_EXPR_H__INCLUDED 27 #define TILEDARRAY_EXPRESSIONS_EXPR_H__INCLUDED 30 #include "../reduce_task.h" 31 #include "../tile_interface/cast.h" 32 #include "../tile_interface/scale.h" 33 #include "../tile_op/shift.h" 34 #include "../tile_op/unary_wrapper.h" 35 #include "../tile_op/unary_reduction.h" 36 #include "../tile_op/binary_reduction.h" 37 #include "../tile_op/reduce_wrapper.h" 40 namespace expressions {
44 template <
typename,
bool>
class TsrExpr;
48 template <
typename Engine>
58 std::shared_ptr<pmap_interface>
pmap;
68 static auto __test(U* p) -> decltype(p->array(), std::true_type());
71 static std::false_type __test(...);
73 static constexpr
const bool value = std::is_same<std::true_type, decltype(__test<E>(0))>
::value;
80 template <
typename Derived>
84 template <
typename Derived_ = Derived>
86 template <
typename Derived_ = Derived>
100 std::shared_ptr<override_type> override_ptr_;
108 if (override_ptr_ !=
nullptr) {
109 override_ptr_->shape = &shape;
111 override_ptr_ = std::make_shared<override_type>();
112 override_ptr_->shape = &shape;
118 if(override_ptr_ !=
nullptr){
119 override_ptr_->world = &world;
121 override_ptr_ = std::make_shared<override_type>();
122 override_ptr_->world = &world;
128 const std::shared_ptr<typename override_type::pmap_interface>
131 override_ptr_->pmap = pmap;
133 override_ptr_ = std::make_shared<override_type>();
134 override_ptr_->pmap = pmap;
150 template <
typename R,
typename T,
typename C,
typename Op>
151 static auto eval_tile(T&& tile,
const C& cast,
const std::shared_ptr<Op>& op) {
152 auto&& cast_tile = cast(std::forward<T>(tile));
153 return (*op)(cast_tile);
164 template <
typename T,
typename Op>
165 static auto eval_tile(T&& tile,
const std::shared_ptr<Op>& op) {
166 return (*op)(std::forward<T>(tile));
180 template <
typename A,
typename I,
typename T,
181 typename std::enable_if<
182 ! std::is_same<typename A::value_type, T>::value &&
183 is_lazy_tile<T>::value
185 void set_tile(A& array,
const I& index,
const Future<T>& tile)
const {
186 array.set(index, array.world().taskq.add(
199 template <
typename A,
typename I,
typename T,
200 typename std::enable_if<
201 std::is_same<typename A::value_type, T>::value
203 void set_tile(A& array,
const I& index,
const Future<T>& tile)
const {
204 array.set(index, tile);
218 template <
typename A,
typename I,
typename T,
typename Op,
219 typename std::enable_if<
220 ! std::is_same<typename A::value_type, T>::value
222 void set_tile(A& array,
const I index,
const Future<T>& tile,
223 const std::shared_ptr<Op>& op)
const 225 auto eval_tile_fn = &Expr_::template eval_tile<
226 typename A::value_type,
const T&,
229 array.world().taskq.add(
247 template <
typename A,
typename I,
typename T,
typename Op,
248 typename std::enable_if<
249 std::is_same<typename A::value_type, T>::value
251 void set_tile(A& array,
const I index,
const Future<T>& tile,
252 const std::shared_ptr<Op>& op)
const 254 auto eval_tile_fn_ptr = &Expr_::template eval_tile<const T&, Op>;
255 using fn_ptr_type = decltype(eval_tile_fn_ptr);
257 madness::detail::function_traits<fn_ptr_type(
const T&,
const std::shared_ptr<Op>&)>::value,
259 array.set(index, array.world().taskq.add(eval_tile_fn_ptr, tile, op));
286 template <
typename A,
bool Alias>
289 "Assignment to an array of lazy tiles is not supported.");
295 const auto has_set_world = override_ptr_ && override_ptr_->world;
296 World& world = (tsr.
array().is_initialized() ?
297 tsr.
array().world() :
298 (has_set_world ? *override_ptr_->world : TiledArray::get_default_world()));
303 std::shared_ptr<typename TsrExpr<A, Alias>::array_type::pmap_interface> pmap;
304 if(tsr.
array().is_initialized())
305 pmap = tsr.
array().pmap();
312 engine.init(world, pmap, target_vars);
315 typename engine_type::dist_eval_type dist_eval = engine.make_dist_eval();
319 A result(dist_eval.world(), dist_eval.trange(),
320 dist_eval.shape(), dist_eval.pmap());
324 for(
const auto index : *dist_eval.pmap()) {
325 if(! dist_eval.is_zero(index))
326 set_tile(result, index, dist_eval.get(index));
333 result.swap(tsr.
array());
345 template <
typename A,
bool Alias>
352 "Assignment to an array of lazy tiles is not supported.");
356 if(! tsr.
array().is_initialized()) {
357 if(TiledArray::get_default_world().rank() == 0) {
359 "Assignment to an uninitialized array sub-block is not supported.");
362 TA_EXCEPTION(
"Assignment to an uninitialized array sub-block is not supported.");
370 World& world = tsr.
array().world();
373 std::shared_ptr<typename BlkTsrExpr<A, Alias>::array_type::pmap_interface> pmap;
380 engine.init(world, pmap, target_vars);
383 typename engine_type::dist_eval_type dist_eval = engine.make_dist_eval();
387 A result(world, tsr.
array().trange(),
389 dist_eval.shape()), tsr.
array().pmap());
400 for(
const auto index : *tsr.
array().pmap()) {
401 if(! tsr.
array().is_zero(index)) {
402 if(! blk_range.includes(tsr.
array().trange().tiles_range().idx(index)))
403 result.set(index, tsr.
array().find(index));
411 const std::vector<long>
shift =
414 std::shared_ptr<op_type> shift_op =
415 std::make_shared<op_type>(shift_op_type(
shift));
417 for(
const auto index : *dist_eval.pmap()) {
418 if(! dist_eval.is_zero(index))
419 set_tile(result, blk_range.ordinal(index), dist_eval.get(index),
428 result.swap(tsr.
array());
438 engine.init_vars(target_vars);
439 engine.init_struct(target_vars);
440 engine.print(os, target_vars);
445 struct ExpressionReduceTag { };
447 template <
typename D,
typename Enabler =
void>
448 struct default_world_helper {
449 default_world_helper(
const D&) {}
450 World&
get()
const {
return TiledArray::get_default_world(); }
452 template <
typename D>
453 struct default_world_helper<
454 D, typename
std::enable_if<has_array<D>::value>::type> {
455 default_world_helper(
const D& d) : derived_(d) {}
456 World&
get()
const {
return derived_.array().world(); }
459 World& default_world()
const {
460 return default_world_helper<Derived>(this->
derived()).
get();
465 template <
typename Op>
466 Future<typename Op::result_type>
467 reduce(
const Op& op, World& world)
const {
469 typedef madness::TaggedKey<madness::uniqueidT, ExpressionReduceTag> key_type;
471 Op> reduction_op_type;
475 engine.init(world, std::shared_ptr<typename engine_type::pmap_interface>(),
479 typename engine_type::dist_eval_type dist_eval = engine.make_dist_eval();
483 reduction_op_type wrapped_op(op);
487 typename engine_type::dist_eval_type::pmap_interface::const_iterator it =
488 dist_eval.pmap()->begin();
489 const typename engine_type::dist_eval_type::pmap_interface::const_iterator end =
490 dist_eval.pmap()->end();
491 for(; it != end; ++it)
492 if(! dist_eval.is_zero(*it))
493 reduce_task.
add(dist_eval.get(*it));
496 auto result = world.gop.all_reduce(key_type(dist_eval.id()), reduce_task.
submit(), op);
501 template <
typename Op>
502 Future<typename Op::result_type>
504 return reduce(op, default_world());
507 template <
typename D,
typename Op>
508 Future<typename Op::result_type>
513 "no_alias() expressions are not allowed on the right-hand side of " 514 "the assignment operator.");
517 typedef madness::TaggedKey<madness::uniqueidT, ExpressionReduceTag> key_type;
519 typename D::engine_type::value_type, Op> reduction_op_type;
523 left_engine.init(world, std::shared_ptr<typename engine_type::pmap_interface>(),
527 typename engine_type::dist_eval_type left_dist_eval =
528 left_engine.make_dist_eval();
529 left_dist_eval.eval();
532 typename D::engine_type right_engine(right_expr.
derived());
533 right_engine.init(world, left_engine.pmap(), left_engine.vars());
536 typename D::engine_type::dist_eval_type right_dist_eval =
537 right_engine.make_dist_eval();
538 right_dist_eval.eval();
541 if(left_dist_eval.trange() != right_dist_eval.trange()) {
542 if(TiledArray::get_default_world().rank() == 0) {
544 "The TiledRanges of the left- and right-hand arguments the binary reduction are not equal:" \
545 <<
"\n left = " << left_dist_eval.trange() \
546 <<
"\n right = " << right_dist_eval.trange() );
549 TA_EXCEPTION(
"The TiledRange objects of a binary expression are not equal.");
554 reduction_op_type wrapped_op(op);
556 local_reduce_task(world, wrapped_op);
559 typename engine_type::dist_eval_type::pmap_interface::const_iterator it =
560 left_dist_eval.pmap()->begin();
561 const typename engine_type::dist_eval_type::pmap_interface::const_iterator end =
562 left_dist_eval.pmap()->end();
563 for(; it != end; ++it) {
564 const typename engine_type::size_type index = *it;
565 const bool left_not_zero = !left_dist_eval.is_zero(index);
566 const bool right_not_zero = !right_dist_eval.is_zero(index);
568 if(left_not_zero && right_not_zero) {
569 local_reduce_task.
add(left_dist_eval.get(index), right_dist_eval.get(index));
571 if(left_not_zero) left_dist_eval.get(index);
572 if(right_not_zero) right_dist_eval.get(index);
576 auto result = world.gop.all_reduce(key_type(left_dist_eval.id()),
577 local_reduce_task.
submit(), op);
578 left_dist_eval.wait();
579 right_dist_eval.wait();
583 template <
typename D,
typename Op>
584 Future<typename Op::result_type>
586 return reduce(right_expr, op, default_world());
599 return trace(default_world());
612 return sum(default_world());
625 return product(default_world());
644 template <
typename T>
645 static T sqrt(
const T t) {
return std::sqrt(t); }
650 typename EngineTrait<engine_type>::eval_type>::result_type>
652 return world.taskq.add(Expr_::template sqrt<
660 return norm(default_world());
663 template <
typename Derived_ = Derived>
670 eval_type>::result_type>>
676 template <
typename Derived_ = Derived>
683 eval_type>::result_type>>
685 return min(default_world());
688 template <
typename Derived_ = Derived>
695 eval_type>::result_type>>
701 template <
typename Derived_ = Derived>
708 eval_type>::result_type>>
710 return max(default_world());
723 return abs_min(default_world());
736 return abs_max(default_world());
739 template <
typename D>
747 right_value_type>(), world);
750 template <
typename D>
755 return dot(right_expr, default_world());
758 template <
typename D>
766 right_value_type>(), world);
769 template <
typename D>
782 #endif // TILEDARRAY_EXPRESSIONS_EXPR_H__INCLUDED
Future< typename TiledArray::ProductReduction< typename EngineTrait< engine_type >::eval_type >::result_type > product(World &world) const
detail::ShiftWrapper< T > shift(T &tensor)
Shift a tensor from one range to another.
void eval_to(BlkTsrExpr< A, Alias > &tsr) const
Evaluate this object and assign it to tsr.
void print(ExprOStream &os, const VariableList &target_vars) const
Expression print.
Expr< Derived > & set_pmap(const std::shared_ptr< typename override_type::pmap_interface > pmap)
Future< typename TiledArray::SumReduction< typename EngineTrait< engine_type >::eval_type >::result_type > sum(World &world) const
Future< typename TiledArray::InnerProductReduction< typename EngineTrait< engine_type >::eval_type, typename EngineTrait< typename D::engine_type >::eval_type >::result_type > inner_product(const Expr< D > &right_expr, World &world) const
std::enable_if< TiledArray::detail::is_strictly_ordered< TiledArray::detail::numeric_t< typename EngineTrait< typename ExprTrait< Derived_ >::engine_type >::eval_type > >::value, Future< typename TiledArray::MaxReduction< typename EngineTrait< typename ExprTrait< Derived_ >::engine_type >::eval_type >::result_type > > max(World &world) const
Vector inner product tile reduction.
const std::vector< std::size_t > & upper_bound() const
Upper bound accessor.
Future< typename TiledArray::AbsMinReduction< typename EngineTrait< engine_type >::eval_type >::result_type > abs_min(World &world) const
Future< typename TiledArray::ProductReduction< typename EngineTrait< engine_type >::eval_type >::result_type > product() const
const std::string & vars() const
Tensor variable string accessor.
Future< typename TiledArray::TraceReduction< typename EngineTrait< engine_type >::eval_type >::result_type > trace(World &world) const
Expr< Derived > Expr_
This class type.
Unary tile operation wrapper.
static constexpr const bool value
Future< typename TiledArray::AbsMaxReduction< typename EngineTrait< engine_type >::eval_type >::result_type > abs_max() const
void add(const L &left, const R &right, madness::CallbackInterface *callback=nullptr)
Add a pair of arguments to the reduction task.
const derived_type & derived() const
Cast this object to it's derived type.
Future< typename TiledArray::SumReduction< typename EngineTrait< engine_type >::eval_type >::result_type > sum() const
typename TiledArray::detail::numeric_type< T >::type numeric_t
Future< typename Op::result_type > reduce(const Op &op) const
Vector dot product tile reduction.
Expression wrapper for array objects.
std::enable_if< TiledArray::detail::is_strictly_ordered< TiledArray::detail::numeric_t< typename EngineTrait< typename ExprTrait< Derived_ >::engine_type >::eval_type > >::value, Future< typename TiledArray::MinReduction< typename EngineTrait< typename ExprTrait< Derived_ >::engine_type >::eval_type >::result_type > > min() const
Future< typename TiledArray::SquaredNormReduction< typename EngineTrait< engine_type >::eval_type >::result_type > norm(World &world) const
engine_t< derived_type > engine_type
Expression engine type.
Future< typename Op::result_type > reduce(const Expr< D > &right_expr, const Op &op) const
std::shared_ptr< pmap_interface > pmap
EngineTrait< Engine >::shape_type shape_type
Tensor shape type.
const std::vector< std::size_t > & lower_bound() const
Lower bound accessor.
EngineTrait< Engine >::pmap_interface pmap_interface
Process map interface type.
Binary reduction wrapper class that handles lazy tile evaluation.
Variable list manages a list variable strings.
Future< typename TiledArray::TraceReduction< typename EngineTrait< engine_type >::eval_type >::result_type > trace() const
std::enable_if< TiledArray::detail::is_strictly_ordered< TiledArray::detail::numeric_t< typename EngineTrait< typename ExprTrait< Derived_ >::engine_type >::eval_type > >::value, Future< typename TiledArray::MinReduction< typename EngineTrait< typename ExprTrait< Derived_ >::engine_type >::eval_type >::result_type > > min(World &world) const
std::enable_if< TiledArray::detail::is_strictly_ordered< TiledArray::detail::numeric_t< typename EngineTrait< typename ExprTrait< Derived_ >::engine_type >::eval_type > >::value, Future< typename TiledArray::MaxReduction< typename EngineTrait< typename ExprTrait< Derived_ >::engine_type >::eval_type >::result_type > > max() const
Expr_ & operator=(const Expr_ &)=delete
Base class for expression evaluation.
derived_type & derived()
Cast this object to it's derived type.
void eval_to(TsrExpr< A, Alias > &tsr) const
Evaluate this object and assign it to tsr.
Future< typename TiledArray::SquaredNormReduction< typename EngineTrait< engine_type >::eval_type >::result_type > squared_norm(World &world) const
Expr< Derived > & set_shape(typename override_type::shape_type const &shape)
Future< typename Op::result_type > reduce(const Expr< D > &right_expr, const Op &op, World &world) const
typename engine_t< Derived_ >::eval_type eval_type_t
type trait checks if T has array() member Useful to determine if an Expr is a TsrExpr or a related ty...
Unary reduction wrapper class that handles lazy tile evaluation.
Range that references a subblock of another range.
int add(const Arg &arg, madness::CallbackInterface *callback=nullptr)
Add an argument to the reduction task.
Future< typename TiledArray::DotReduction< typename EngineTrait< engine_type >::eval_type, typename EngineTrait< typename D::engine_type >::eval_type >::result_type > dot(const Expr< D > &right_expr, World &world) const
const std::string & vars() const
Tensor variable string accessor.
typename ExprTrait< Derived_ >::engine_type engine_t
reference array() const
Array accessor.
Future< typename TiledArray::InnerProductReduction< typename EngineTrait< engine_type >::eval_type, typename EngineTrait< typename D::engine_type >::eval_type >::result_type > inner_product(const Expr< D > &right_expr) const
Expr< Derived > & set_world(World &world)
Future< typename TiledArray::SquaredNormReduction< typename EngineTrait< engine_type >::eval_type >::result_type > norm() const
Squared norm tile reduction.
Expression output stream.
Future< typename TiledArray::DotReduction< typename EngineTrait< engine_type >::eval_type, typename EngineTrait< typename D::engine_type >::eval_type >::result_type > dot(const Expr< D > &right_expr) const
array_type & array() const
Array accessor.
Future< typename TiledArray::AbsMinReduction< typename EngineTrait< engine_type >::eval_type >::result_type > abs_min() const
Derived derived_type
The derived object type.
Detect lazy evaluation tiles.
Future< typename TiledArray::AbsMaxReduction< typename EngineTrait< engine_type >::eval_type >::result_type > abs_max(World &world) const
#define TA_USER_ERROR_MESSAGE(m)
Future< result_type > submit()
Submit the reduction task to the task queue.
Future< typename TiledArray::SquaredNormReduction< typename EngineTrait< engine_type >::eval_type >::result_type > squared_norm() const
EngineTrait< Engine >::policy policy
The result policy type.
Future< typename Op::result_type > reduce(const Op &op, World &world) const