10#ifndef XTENSOR_SEMANTIC_HPP
11#define XTENSOR_SEMANTIC_HPP
17#include "xexpression_traits.hpp"
26 static constexpr bool value =
true;
29 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
30 struct is_sharable<xfixed_container<ET, S, L, SH, Tag>>
32 static constexpr bool value = SH;
35 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
36 struct is_sharable<xfixed_adaptor<ET, S, L, SH, Tag>>
38 static constexpr bool value = SH;
43 using select_expression_base_t = std::
57 class xsemantic_base :
public select_expression_base_t<D>
61 using base_type = select_expression_base_t<D>;
62 using derived_type =
typename base_type::derived_type;
67 disable_xexpression<E, derived_type&> operator+=(
const E&);
70 disable_xexpression<E, derived_type&> operator-=(
const E&);
73 disable_xexpression<E, derived_type&> operator*=(
const E&);
76 disable_xexpression<E, derived_type&> operator/=(
const E&);
79 disable_xexpression<E, derived_type&> operator%=(
const E&);
82 disable_xexpression<E, derived_type&> operator&=(
const E&);
85 disable_xexpression<E, derived_type&> operator|=(
const E&);
88 disable_xexpression<E, derived_type&> operator^=(
const E&);
143 xsemantic_base() =
default;
144 ~xsemantic_base() =
default;
146 xsemantic_base(
const xsemantic_base&) =
default;
147 xsemantic_base& operator=(
const xsemantic_base&) =
default;
149 xsemantic_base(xsemantic_base&&) =
default;
150 xsemantic_base& operator=(xsemantic_base&&) =
default;
157 using is_assignable = is_crtp_base_of<xsemantic_base, E>;
159 template <
class E,
class R =
void>
160 using enable_assignable =
typename std::enable_if<is_assignable<E>::value, R>::type;
162 template <
class E,
class R =
void>
163 using disable_assignable =
typename std::enable_if<!is_assignable<E>::value, R>::type;
177 class xcontainer_semantic :
public xsemantic_base<D>
181 using base_type = xsemantic_base<D>;
182 using derived_type = D;
183 using temporary_type =
typename base_type::temporary_type;
193 template <
class E,
class F>
194 derived_type& scalar_computed_assign(
const E& e, F&& f);
198 xcontainer_semantic() =
default;
199 ~xcontainer_semantic() =
default;
201 xcontainer_semantic(
const xcontainer_semantic&) =
default;
202 xcontainer_semantic& operator=(
const xcontainer_semantic&) =
default;
204 xcontainer_semantic(xcontainer_semantic&&) =
default;
205 xcontainer_semantic& operator=(xcontainer_semantic&&) =
default;
212 using has_container_semantics = is_crtp_base_of<xcontainer_semantic, E>;
214 template <
class E,
class R =
void>
215 using enable_xcontainer_semantics =
typename std::enable_if<has_container_semantics<E>::value, R>::type;
217 template <
class E,
class R =
void>
218 using disable_xcontainer_semantics =
typename std::enable_if<!has_container_semantics<E>::value, R>::type;
227 std::enable_if_t<!has_memory_address<E>::value && is_crtp_base_of<xview_semantic, E>::value>>
229 static bool check_overlap(
const E& expr,
const memory_range& dst_range)
231 if (expr.size() == 0)
237 using ChildE = std::decay_t<
decltype(expr.expression())>;
238 return overlapping_memory_checker_traits<ChildE>::check_overlap(expr.expression(), dst_range);
254 class xview_semantic :
public xsemantic_base<D>
258 using base_type = xsemantic_base<D>;
259 using derived_type = D;
260 using temporary_type =
typename base_type::temporary_type;
270 template <
class E,
class F>
271 derived_type& scalar_computed_assign(
const E& e, F&& f);
275 xview_semantic() =
default;
276 ~xview_semantic() =
default;
278 xview_semantic(
const xview_semantic&) =
default;
279 xview_semantic& operator=(
const xview_semantic&) =
default;
281 xview_semantic(xview_semantic&&) =
default;
282 xview_semantic& operator=(xview_semantic&&) =
default;
289 using has_view_semantics = is_crtp_base_of<xview_semantic, E>;
291 template <
class E,
class R =
void>
292 using enable_xview_semantics =
typename std::enable_if<has_view_semantics<E>::value, R>::type;
294 template <
class E,
class R =
void>
295 using disable_xview_semantics =
typename std::enable_if<!has_view_semantics<E>::value, R>::type;
312 inline auto xsemantic_base<D>::operator+=(
const E& e) -> disable_xexpression<E, derived_type&>
314 return this->derived_cast().scalar_computed_assign(e, std::plus<>());
324 inline auto xsemantic_base<D>::operator-=(
const E& e) -> disable_xexpression<E, derived_type&>
326 return this->derived_cast().scalar_computed_assign(e, std::minus<>());
336 inline auto xsemantic_base<D>::operator*=(
const E& e) -> disable_xexpression<E, derived_type&>
338 return this->derived_cast().scalar_computed_assign(e, std::multiplies<>());
348 inline auto xsemantic_base<D>::operator/=(
const E& e) -> disable_xexpression<E, derived_type&>
350 return this->derived_cast().scalar_computed_assign(e, std::divides<>());
360 inline auto xsemantic_base<D>::operator%=(
const E& e) -> disable_xexpression<E, derived_type&>
362 return this->derived_cast().scalar_computed_assign(e, std::modulus<>());
372 inline auto xsemantic_base<D>::operator&=(
const E& e) -> disable_xexpression<E, derived_type&>
374 return this->derived_cast().scalar_computed_assign(e, std::bit_and<>());
384 inline auto xsemantic_base<D>::operator|=(
const E& e) -> disable_xexpression<E, derived_type&>
386 return this->derived_cast().scalar_computed_assign(e, std::bit_or<>());
396 inline auto xsemantic_base<D>::operator^=(
const E& e) -> disable_xexpression<E, derived_type&>
398 return this->derived_cast().scalar_computed_assign(e, std::bit_xor<>());
408 inline auto xsemantic_base<D>::operator+=(
const xexpression<E>& e) -> derived_type&
410 return this->derived_cast() = this->derived_cast() + e.derived_cast();
420 inline auto xsemantic_base<D>::operator-=(
const xexpression<E>& e) -> derived_type&
422 return this->derived_cast() = this->derived_cast() - e.derived_cast();
432 inline auto xsemantic_base<D>::operator*=(
const xexpression<E>& e) -> derived_type&
434 return this->derived_cast() = this->derived_cast() * e.derived_cast();
444 inline auto xsemantic_base<D>::operator/=(
const xexpression<E>& e) -> derived_type&
446 return this->derived_cast() = this->derived_cast() / e.derived_cast();
456 inline auto xsemantic_base<D>::operator%=(
const xexpression<E>& e) -> derived_type&
458 return this->derived_cast() = this->derived_cast() % e.derived_cast();
468 inline auto xsemantic_base<D>::operator&=(
const xexpression<E>& e) -> derived_type&
470 return this->derived_cast() = this->derived_cast() & e.derived_cast();
480 inline auto xsemantic_base<D>::operator|=(
const xexpression<E>& e) -> derived_type&
482 return this->derived_cast() = this->derived_cast() | e.derived_cast();
492 inline auto xsemantic_base<D>::operator^=(
const xexpression<E>& e) -> derived_type&
494 return this->derived_cast() = this->derived_cast() ^ e.derived_cast();
513 return this->derived_cast().assign_xexpression(e);
524 inline auto xsemantic_base<D>::plus_assign(
const xexpression<E>& e) -> derived_type&
526 return this->derived_cast().computed_assign(this->derived_cast() + e.derived_cast());
537 inline auto xsemantic_base<D>::minus_assign(
const xexpression<E>& e) -> derived_type&
539 return this->derived_cast().computed_assign(this->derived_cast() - e.derived_cast());
550 inline auto xsemantic_base<D>::multiplies_assign(
const xexpression<E>& e) -> derived_type&
552 return this->derived_cast().computed_assign(this->derived_cast() * e.derived_cast());
563 inline auto xsemantic_base<D>::divides_assign(
const xexpression<E>& e) -> derived_type&
565 return this->derived_cast().computed_assign(this->derived_cast() / e.derived_cast());
576 inline auto xsemantic_base<D>::modulus_assign(
const xexpression<E>& e) -> derived_type&
578 return this->derived_cast().computed_assign(this->derived_cast() % e.derived_cast());
589 inline auto xsemantic_base<D>::bit_and_assign(
const xexpression<E>& e) -> derived_type&
591 return this->derived_cast().computed_assign(this->derived_cast() & e.derived_cast());
602 inline auto xsemantic_base<D>::bit_or_assign(
const xexpression<E>& e) -> derived_type&
604 return this->derived_cast().computed_assign(this->derived_cast() | e.derived_cast());
615 inline auto xsemantic_base<D>::bit_xor_assign(
const xexpression<E>& e) -> derived_type&
617 return this->derived_cast().computed_assign(this->derived_cast() ^ e.derived_cast());
622 inline auto xsemantic_base<D>::operator=(
const xexpression<E>& e) -> derived_type&
624#ifdef XTENSOR_FORCE_TEMPORARY_MEMORY_IN_ASSIGNMENTS
626 return this->derived_cast().assign_temporary(std::move(tmp));
628 auto&& this_derived = this->derived_cast();
629 auto memory_checker = make_overlapping_memory_checker(this_derived);
630 if (memory_checker.check_overlap(e.derived_cast()))
633 return this_derived.assign_temporary(std::move(tmp));
637 return this->assign(e);
654 return (this->derived_cast() = std::move(tmp));
659 inline auto xcontainer_semantic<D>::assign_xexpression(
const xexpression<E>& e) -> derived_type&
661 xt::assign_xexpression(*
this, e);
662 return this->derived_cast();
667 inline auto xcontainer_semantic<D>::computed_assign(
const xexpression<E>& e) -> derived_type&
669 xt::computed_assign(*
this, e);
670 return this->derived_cast();
674 template <
class E,
class F>
675 inline auto xcontainer_semantic<D>::scalar_computed_assign(
const E& e, F&& f) -> derived_type&
677 xt::scalar_computed_assign(*
this, e, std::forward<F>(f));
678 return this->derived_cast();
683 inline auto xcontainer_semantic<D>::operator=(
const xexpression<E>& e) -> derived_type&
685 return base_type::operator=(e);
700 this->derived_cast().assign_temporary_impl(std::move(tmp));
701 return this->derived_cast();
707 bool get_rhs_triviality(
const F&)
712 template <
class F,
class R,
class... CT>
713 bool get_rhs_triviality(
const xfunction<F, R, CT...>& rhs)
715 using index_type = xindex_type_t<
typename xfunction<F, R, CT...>::shape_type>;
716 using size_type =
typename index_type::size_type;
717 size_type size = rhs.dimension();
718 index_type shape = uninitialized_shape<index_type>(size);
719 bool trivial_broadcast = rhs.broadcast_shape(shape,
true);
720 return trivial_broadcast;
726 inline auto xview_semantic<D>::assign_xexpression(
const xexpression<E>& e) -> derived_type&
728 xt::assert_compatible_shape(*
this, e);
729 xt::assign_data(*
this, e, detail::get_rhs_triviality(e.derived_cast()));
730 return this->derived_cast();
735 inline auto xview_semantic<D>::computed_assign(
const xexpression<E>& e) -> derived_type&
737 xt::assert_compatible_shape(*
this, e);
738 xt::assign_data(*
this, e, detail::get_rhs_triviality(e.derived_cast()));
739 return this->derived_cast();
742 namespace xview_semantic_detail
745 auto get_begin(D&& lhs, std::true_type)
747 return lhs.linear_begin();
751 auto get_begin(D&& lhs, std::false_type)
758 template <
class E,
class F>
759 inline auto xview_semantic<D>::scalar_computed_assign(
const E& e, F&& f) -> derived_type&
761 D& d = this->derived_cast();
763 using size_type =
typename D::size_type;
764 auto dst = xview_semantic_detail::get_begin(d, std::integral_constant<bool, D::contiguous_layout>());
765 for (size_type i = d.size(); i > 0; --i)
770 return this->derived_cast();
775 inline auto xview_semantic<D>::operator=(
const xexpression<E>& rhs) -> derived_type&
777 bool cond = (rhs.derived_cast().shape().size() == this->derived_cast().dimension())
779 this->derived_cast().shape().begin(),
780 this->derived_cast().shape().end(),
781 rhs.derived_cast().shape().begin()
786 base_type::operator=(
broadcast(rhs.derived_cast(), this->derived_cast().shape()));
790 base_type::operator=(rhs);
792 return this->derived_cast();
derived_type & assign_temporary(temporary_type &&)
Assigns the temporary tmp to *this.
Base class for xexpressions.
Implementation of the xsemantic_base interface for multidimensional views.
derived_type & assign_temporary(temporary_type &&)
Assigns the temporary tmp to *this.
standard mathematical functions for xexpressions
auto broadcast(E &&e, const S &s)
Returns an xexpression broadcasting the given expression to a specified shape.