10#ifndef XTENSOR_SEMANTIC_HPP
11#define XTENSOR_SEMANTIC_HPP
16#include "../core/xassign.hpp"
17#include "../core/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<!addressable_to_expression<E> && 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;
314 return this->derived_cast().scalar_computed_assign(e, std::plus<>());
326 return this->derived_cast().scalar_computed_assign(e, std::minus<>());
338 return this->derived_cast().scalar_computed_assign(e, std::multiplies<>());
350 return this->derived_cast().scalar_computed_assign(e, std::divides<>());
362 return this->derived_cast().scalar_computed_assign(e, std::modulus<>());
374 return this->derived_cast().scalar_computed_assign(e, std::bit_and<>());
386 return this->derived_cast().scalar_computed_assign(e, std::bit_or<>());
398 return this->derived_cast().scalar_computed_assign(e, std::bit_xor<>());
410 return this->derived_cast() = this->derived_cast() + e.derived_cast();
422 return this->derived_cast() = this->derived_cast() - e.derived_cast();
434 return this->derived_cast() = this->derived_cast() * e.derived_cast();
446 return this->derived_cast() = this->derived_cast() / e.derived_cast();
458 return this->derived_cast() = this->derived_cast() % e.derived_cast();
470 return this->derived_cast() = this->derived_cast() & e.derived_cast();
482 return this->derived_cast() = this->derived_cast() | e.derived_cast();
494 return this->derived_cast() = this->derived_cast() ^ e.derived_cast();
513 return this->derived_cast().assign_xexpression(e);
526 return this->derived_cast().computed_assign(this->derived_cast() + e.derived_cast());
539 return this->derived_cast().computed_assign(this->derived_cast() - e.derived_cast());
552 return this->derived_cast().computed_assign(this->derived_cast() * e.derived_cast());
565 return this->derived_cast().computed_assign(this->derived_cast() / e.derived_cast());
578 return this->derived_cast().computed_assign(this->derived_cast() % e.derived_cast());
591 return this->derived_cast().computed_assign(this->derived_cast() & e.derived_cast());
604 return this->derived_cast().computed_assign(this->derived_cast() | e.derived_cast());
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.
disable_xexpression< E, derived_type & > operator-=(const E &)
Subtracts the scalar e from *this.
disable_xexpression< E, derived_type & > operator+=(const E &)
Adds the scalar e to *this.
derived_type & plus_assign(const xexpression< E > &)
Adds the xexpression e to *this.
disable_xexpression< E, derived_type & > operator*=(const E &)
Multiplies *this with the scalar e.
disable_xexpression< E, derived_type & > operator^=(const E &)
Computes the bitwise xor of *this and the scalar e and assigns it to *this.
derived_type & divides_assign(const xexpression< E > &)
Divides *this by the xexpression e.
derived_type & bit_and_assign(const xexpression< E > &)
Computes the bitwise and of e to *this.
derived_type & multiplies_assign(const xexpression< E > &)
Multiplies *this with the xexpression e.
derived_type & bit_or_assign(const xexpression< E > &)
Computes the bitwise or of e to *this.
derived_type & minus_assign(const xexpression< E > &)
Subtracts the xexpression e to *this.
disable_xexpression< E, derived_type & > operator%=(const E &)
Computes the remainder of *this after division by the scalar e.
disable_xexpression< E, derived_type & > operator&=(const E &)
Computes the bitwise and of *this and the scalar e and assigns it to *this.
disable_xexpression< E, derived_type & > operator|=(const E &)
Computes the bitwise or of *this and the scalar e and assigns it to *this.
derived_type & modulus_assign(const xexpression< E > &)
Computes the remainder of *this after division by the xexpression e.
derived_type & assign(const xexpression< E > &)
Assigns the xexpression e to *this.
derived_type & bit_xor_assign(const xexpression< E > &)
Computes the bitwise xor of e to *this.
disable_xexpression< E, derived_type & > operator/=(const E &)
Divides *this by the scalar e.
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.