10#ifndef XTENSOR_OPTIONAL_HPP
11#define XTENSOR_OPTIONAL_HPP
16#include <xtl/xoptional.hpp>
17#include <xtl/xoptional_sequence.hpp>
20#include "xbroadcast.hpp"
21#include "xdynamic_view.hpp"
22#include "xfunctor_view.hpp"
23#include "xgenerator.hpp"
24#include "xindex_view.hpp"
25#include "xreducer.hpp"
28#include "xstrided_view.hpp"
46 template <
class T,
class B>
65 D& derived_cast()
noexcept;
66 const D& derived_cast()
const noexcept;
76 template <
class T,
class Tag>
77 struct split_optional_expression_impl
79 using value_expression = T;
80 using flag_expression =
decltype(
ones<bool>(std::declval<T>().shape()));
83 inline static U&& value(
U&& arg)
85 return std::forward<U>(arg);
89 inline static flag_expression has_value(U&& arg)
91 return ones<bool>(arg.shape());
95 template <
class T,
class Tag>
96 struct split_optional_expression_impl<xscalar<T>, Tag>
98 using value_expression = xscalar<T>;
99 using flag_expression = xscalar<bool>;
102 inline static U&& value(U&& arg)
104 return std::forward<U>(arg);
108 inline static flag_expression has_value(U&&)
110 return xscalar<bool>(
true);
115 struct split_optional_expression_impl_base
117 static constexpr bool is_const = std::is_const<std::remove_reference_t<T>>::value;
118 using decay_type = std::decay_t<T>;
120 using value_expression = std::conditional_t<
122 typename decay_type::const_value_expression,
123 typename decay_type::value_expression>;
124 using flag_expression = std::
125 conditional_t<is_const, typename decay_type::const_flag_expression, typename decay_type::flag_expression>;
128 inline static value_expression value(U&& arg)
134 inline static flag_expression has_value(U&& arg)
136 return arg.has_value();
141 struct split_optional_expression_impl<T, xoptional_expression_tag>
142 : split_optional_expression_impl_base<T>
147 struct split_optional_expression_impl<xscalar<T>, xoptional_expression_tag>
148 : split_optional_expression_impl_base<xscalar<T>>
153 struct split_optional_expression
154 : split_optional_expression_impl<T, xexpression_tag_t<std::decay_t<T>>>
159 using value_expression_t =
typename split_optional_expression<T>::value_expression;
162 using flag_expression_t =
typename split_optional_expression<T>::flag_expression;
168 template <
class T =
bool>
169 class optional_bitwise
173 using return_type = T;
174 using first_argument_type = T;
175 using second_argument_type = T;
176 using result_type = T;
177 using simd_value_type = bool;
178 using simd_result_type = bool;
180 template <
class... Args>
181 constexpr result_type operator()(
const Args&... args)
const
183 return apply_impl(args...);
186 template <
class B,
class... Args>
187 constexpr B simd_apply(
const B& b,
const Args&... args)
const
189 return simd_apply_impl(b, args...);
194 constexpr result_type apply_impl()
const
199 template <
class U,
class... Args>
200 constexpr result_type apply_impl(
const U& t,
const Args&... args)
const
202 return t & apply_impl(args...);
206 constexpr B simd_apply_impl(
const B& b)
const
211 template <
class B1,
class B2,
class... Args>
212 constexpr B1 simd_apply_impl(
const B1& b1,
const B2& b2,
const Args&... args)
const
214 return b1 & simd_apply_impl(b2, args...);
222 template <
class T,
class B>
223 struct const_value_rebinder<xtl::xoptional<T, B>, T>
225 static const_value<T> run(
const const_value<xtl::xoptional<T, B>>& src)
227 return const_value<T>(src.m_value.value());
235 template <
class T,
class B>
236 struct xreducer_size_type<xtl::xoptional<T, B>>
238 using type = xtl::xoptional<std::size_t, bool>;
241 template <
class T,
class B>
242 struct xreducer_temporary_type<xtl::xoptional<T, B>>
244 using type = xtl::xoptional<std::decay_t<T>,
bool>;
253 template <
class T,
class B>
254 auto sign(
const xtl::xoptional<T, B>& e);
267 template <
class E1,
class E2>
281 static constexpr bool is_ref = std::is_reference<closure_type>::value;
282 using unref_closure_type = std::remove_reference_t<closure_type>;
283 static constexpr bool is_const = std::is_const<unref_closure_type>::value;
284 using raw_closure_type = std::decay_t<CT>;
286 using raw_value_closure =
typename raw_closure_type::value_closure;
287 using raw_flag_closure =
typename raw_closure_type::flag_closure;
288 using const_raw_value_closure = std::add_const_t<raw_value_closure>;
289 using const_raw_flag_closure = std::add_const_t<raw_flag_closure>;
291 using value_closure = std::conditional_t<is_ref, std::add_lvalue_reference_t<raw_value_closure>, raw_value_closure>;
292 using flag_closure = std::conditional_t<is_ref, std::add_lvalue_reference_t<raw_flag_closure>, raw_flag_closure>;
293 using const_value_closure = std::
294 conditional_t<is_ref, std::add_lvalue_reference_t<const_raw_value_closure>, raw_value_closure>;
295 using const_flag_closure = std::
296 conditional_t<is_ref, std::add_lvalue_reference_t<const_raw_flag_closure>, raw_flag_closure>;
310 using value_expression =
typename traits::value_expression;
311 using flag_expression =
typename traits::flag_expression;
312 using const_value_expression =
typename traits::const_value_expression;
313 using const_flag_expression =
typename traits::const_flag_expression;
316 value_expression value();
317 const_value_expression value()
const;
319 flag_expression has_value();
320 const_flag_expression has_value()
const;
342 using value_expression =
typename traits::value_expression;
343 using flag_expression =
typename traits::flag_expression;
344 using const_value_expression =
typename traits::const_value_expression;
345 using const_flag_expression =
typename traits::const_flag_expression;
348 value_expression value();
349 const_value_expression value()
const;
351 flag_expression has_value();
352 const_flag_expression has_value()
const;
362 template <
class EC, layout_type L,
class SC>
365 using value_container =
typename std::remove_reference_t<EC>::base_container_type;
366 using flag_container =
typename std::remove_reference_t<EC>::flag_container_type;
373 template <
class EC, layout_type L,
class SC>
379 template <
class EC, layout_type L,
class SC>
393 template <
class EC, layout_type L,
class SC>
399 template <
class EC, layout_type L,
class SC>
413 template <
class EC, std::
size_t N, layout_type L>
416 using value_container =
typename std::remove_reference_t<EC>::base_container_type;
417 using flag_container =
typename std::remove_reference_t<EC>::flag_container_type;
424 template <
class EC, std::
size_t N, layout_type L>
430 template <
class EC, std::
size_t N, layout_type L>
444 template <
class EC, std::
size_t N, layout_type L>
450 template <
class EC, std::
size_t N, layout_type L>
464 template <
class EC, std::
size_t N, layout_type L>
470 template <
class EC, std::
size_t N, layout_type L>
484 template <
class F,
class...
CT>
491 using flag_functor = xt::detail::optional_bitwise<bool>;
503 template <std::size_t... I>
506 template <std::size_t... I>
510 template <
class F,
class...
CT>
523 template <
class CT,
class S, layout_type L,
class FST>
529 using uvt =
typename std::decay_t<CT>::value_expression;
530 using uft =
typename std::decay_t<CT>::flag_expression;
531 using ucvt =
typename std::decay_t<CT>::const_value_expression;
532 using ucft =
typename std::decay_t<CT>::const_flag_expression;
545 template <
class CT,
class S, layout_type L,
class FST>
558 template <
class CT,
class X>
573 template <
class CT,
class X>
586 template <
class F,
class CT>
592 using uvt =
typename std::decay_t<CT>::value_expression;
593 using uft =
typename std::decay_t<CT>::flag_expression;
594 using ucvt =
typename std::decay_t<CT>::const_value_expression;
595 using ucft =
typename std::decay_t<CT>::const_flag_expression;
597 using flag_expression = uft;
599 using const_flag_expression = ucft;
604 flag_expression has_value();
605 const_flag_expression has_value()
const;
608 template <
class F,
class CT>
621 template <
class CT,
class I>
627 using uvt =
typename std::decay_t<CT>::value_expression;
628 using ucvt =
typename std::decay_t<CT>::const_value_expression;
629 using uft =
typename std::decay_t<CT>::flag_expression;
630 using ucft =
typename std::decay_t<CT>::const_flag_expression;
643 template <
class CT,
class I>
656 template <
class F,
class CT,
class X,
class O>
662 using result_type =
typename F::init_value_type;
664 using rebound_result_type =
typename result_type::value_type;
667 using rebound_reduce_options_flag =
typename O::template
rebind_t<bool>;
680 template <
class F,
class CT,
class X,
class O>
693 template <
class CT,
class X>
708 template <
class CT,
class X>
721 template <
class CT,
class S, layout_type L,
class FST>
727 using uvt =
typename std::decay_t<CT>::value_expression;
728 using uft =
typename std::decay_t<CT>::flag_expression;
729 using ucvt =
typename std::decay_t<CT>::const_value_expression;
730 using ucft =
typename std::decay_t<CT>::const_flag_expression;
743 template <
class CT,
class S, layout_type L,
class FST>
756 template <
class CT,
class...
S>
762 using uvt =
typename std::decay_t<CT>::value_expression;
763 using uft =
typename std::decay_t<CT>::flag_expression;
764 using ucvt =
typename std::decay_t<CT>::const_value_expression;
765 using ucft =
typename std::decay_t<CT>::const_flag_expression;
778 template <
class CT,
class...
S>
793 template <
class F,
class =
void_t<
int>>
798 static type get(
const F&
f)
805 struct value_functor<F, void_t<typename F::value_functor_type>>
807 using type =
typename F::value_functor_type;
809 static type get(
const F& f)
811 return f.value_functor();
816 using value_functor_t =
typename value_functor<F>::type;
820 template <
class... T>
821 bool operator()(T...)
const
827 template <
class F,
class =
void_t<
int>>
830 using type = always_true;
832 static type get(
const F&)
839 struct flag_functor<F, void_t<typename F::flag_functor_type>>
841 using type =
typename F::flag_functor_type;
843 static type get(
const F& f)
845 return f.flag_functor();
850 using flag_functor_t =
typename flag_functor<F>::type;
853 template <
class F,
class R,
class S>
859 using value_closure =
typename R::value_closure;
860 using flag_closure =
typename R::flag_closure;
861 using value_functor = detail::value_functor_t<F>;
862 using flag_functor = detail::flag_functor_t<F>;
872 template <
class F,
class R,
class S>
886 inline D& xoptional_empty_base<D>::derived_cast()
noexcept
888 return *
static_cast<D*
>(
this);
892 inline const D& xoptional_empty_base<D>::derived_cast() const noexcept
894 return *
static_cast<const D*
>(
this);
905 inline auto xscalar_optional_base<CT>::value() -> value_expression
907 return this->derived_cast().expression().value();
911 inline auto xscalar_optional_base<CT>::value() const -> const_value_expression
913 return this->derived_cast().expression().value();
917 inline auto xscalar_optional_base<CT>::has_value() -> flag_expression
919 return this->derived_cast().expression().has_value();
923 inline auto xscalar_optional_base<CT>::has_value() const -> const_flag_expression
925 return this->derived_cast().expression().has_value();
936 inline auto xcontainer_optional_base<T>::value() -> value_expression
938 return value_expression(this->derived_cast().storage().value(), this->derived_cast().shape());
942 inline auto xcontainer_optional_base<T>::value() const -> const_value_expression
944 return const_value_expression(this->derived_cast().storage().value(), this->derived_cast().shape());
948 inline auto xcontainer_optional_base<T>::has_value() -> flag_expression
950 return flag_expression(this->derived_cast().storage().has_value(), this->derived_cast().shape());
954 inline auto xcontainer_optional_base<T>::has_value() const -> const_flag_expression
956 return const_flag_expression(this->derived_cast().storage().has_value(), this->derived_cast().shape());
966 template <
class F,
class... CT>
967 inline auto xfunction_optional_base<F, CT...>::value() const -> const_value_expression
969 return value_impl(std::make_index_sequence<
sizeof...(CT)>());
972 template <
class F,
class... CT>
973 inline auto xfunction_optional_base<F, CT...>::has_value() const -> const_flag_expression
975 return has_value_impl(std::make_index_sequence<
sizeof...(CT)>());
978 template <
class F,
class... CT>
979 template <std::size_t... I>
980 inline auto xfunction_optional_base<F, CT...>::value_impl(std::index_sequence<I...>)
const
981 -> const_value_expression
983 return value_expression(
985 xt::detail::split_optional_expression<CT>::value(std::get<I>(this->derived_cast().arguments()))...
989 template <
class F,
class... CT>
990 template <std::size_t... I>
991 inline auto xfunction_optional_base<F, CT...>::has_value_impl(std::index_sequence<I...>)
const
992 -> const_flag_expression
994 return flag_expression(
996 xt::detail::split_optional_expression<CT>::has_value(
997 std::get<I>(this->derived_cast().arguments())
1009 template <
class CT,
class S, layout_type L,
class FST>
1010 inline auto xdynamic_view_optional<CT, S, L, FST>::value() -> value_expression
1012 return this->derived_cast().build_view(this->derived_cast().expression().value());
1015 template <
class CT,
class S, layout_type L,
class FST>
1016 inline auto xdynamic_view_optional<CT, S, L, FST>::value() const -> const_value_expression
1018 return this->derived_cast().build_view(this->derived_cast().expression().value());
1021 template <
class CT,
class S, layout_type L,
class FST>
1022 inline auto xdynamic_view_optional<CT, S, L, FST>::has_value() -> flag_expression
1024 return this->derived_cast().build_view(this->derived_cast().expression().has_value());
1027 template <
class CT,
class S, layout_type L,
class FST>
1028 inline auto xdynamic_view_optional<CT, S, L, FST>::has_value() const -> const_flag_expression
1030 return this->derived_cast().build_view(this->derived_cast().expression().has_value());
1040 template <
class CT,
class X>
1041 inline auto xbroadcast_optional<CT, X>::value() const -> const_value_expression
1043 return this->derived_cast().build_broadcast(this->derived_cast().expression().value());
1046 template <
class CT,
class X>
1047 inline auto xbroadcast_optional<CT, X>::has_value() const -> const_flag_expression
1049 return this->derived_cast().build_broadcast(this->derived_cast().expression().has_value());
1059 template <
class F,
class CT>
1060 inline auto xfunctor_view_optional<F, CT>::value() -> value_expression
1062 return this->derived_cast().build_functor_view(this->derived_cast().expression().value());
1065 template <
class F,
class CT>
1066 inline auto xfunctor_view_optional<F, CT>::value() const -> const_value_expression
1068 return this->derived_cast().build_functor_view(this->derived_cast().expression().value());
1071 template <
class F,
class CT>
1072 inline auto xfunctor_view_optional<F, CT>::has_value() -> flag_expression
1074 return this->derived_cast().expression().has_value();
1077 template <
class F,
class CT>
1078 inline auto xfunctor_view_optional<F, CT>::has_value() const -> const_flag_expression
1080 return this->derived_cast().expression().has_value();
1090 template <
class CT,
class I>
1091 inline auto xindex_view_optional<CT, I>::value() -> value_expression
1093 return this->derived_cast().build_index_view(this->derived_cast().expression().value());
1096 template <
class CT,
class I>
1097 inline auto xindex_view_optional<CT, I>::value() const -> const_value_expression
1099 return this->derived_cast().build_index_view(this->derived_cast().expression().value());
1102 template <
class CT,
class I>
1103 inline auto xindex_view_optional<CT, I>::has_value() -> flag_expression
1105 return this->derived_cast().build_index_view(this->derived_cast().expression().has_value());
1108 template <
class CT,
class I>
1109 inline auto xindex_view_optional<CT, I>::has_value() const -> const_flag_expression
1111 return this->derived_cast().build_index_view(this->derived_cast().expression().has_value());
1121 template <
class F,
class CT,
class X,
class O>
1122 inline auto xreducer_optional<F, CT, X, O>::value() const -> const_value_expression
1124 auto func = this->derived_cast().functors();
1125 auto opts = this->derived_cast().options().template rebind<rebound_result_type>(
1126 this->derived_cast().options().initial_value.value(),
1127 this->derived_cast().options()
1130 return this->derived_cast().build_reducer(
1131 this->derived_cast().expression().value(),
1132 func.template rebind<rebound_result_type>(),
1137 template <
class F,
class CT,
class X,
class O>
1138 inline auto xreducer_optional<F, CT, X, O>::has_value() const -> const_flag_expression
1140 auto opts = this->derived_cast().options().rebind(
1141 this->derived_cast().options().initial_value.has_value(),
1142 this->derived_cast().options()
1145 return this->derived_cast().build_reducer(
1146 this->derived_cast().expression().has_value(),
1159 template <
class CT,
class S, layout_type L,
class FST>
1160 inline auto xstrided_view_optional<CT, S, L, FST>::value() -> value_expression
1162 return this->derived_cast().build_view(this->derived_cast().expression().value());
1165 template <
class CT,
class S, layout_type L,
class FST>
1166 inline auto xstrided_view_optional<CT, S, L, FST>::value() const -> const_value_expression
1168 return this->derived_cast().build_view(this->derived_cast().expression().value());
1171 template <
class CT,
class S, layout_type L,
class FST>
1172 inline auto xstrided_view_optional<CT, S, L, FST>::has_value() -> flag_expression
1174 return this->derived_cast().build_view(this->derived_cast().expression().has_value());
1177 template <
class CT,
class S, layout_type L,
class FST>
1178 inline auto xstrided_view_optional<CT, S, L, FST>::has_value() const -> const_flag_expression
1180 return this->derived_cast().build_view(this->derived_cast().expression().has_value());
1190 template <
class CT,
class... S>
1191 inline auto xview_optional<CT, S...>::value() -> value_expression
1193 return this->derived_cast().build_view(this->derived_cast().expression().value());
1196 template <
class CT,
class... S>
1197 inline auto xview_optional<CT, S...>::value() const -> const_value_expression
1199 return this->derived_cast().build_view(this->derived_cast().expression().value());
1202 template <
class CT,
class... S>
1203 inline auto xview_optional<CT, S...>::has_value() -> flag_expression
1205 return this->derived_cast().build_view(this->derived_cast().expression().has_value());
1208 template <
class CT,
class... S>
1209 inline auto xview_optional<CT, S...>::has_value() const -> const_flag_expression
1211 return this->derived_cast().build_view(this->derived_cast().expression().has_value());
1221 template <
class F,
class R,
class S>
1222 inline auto xgenerator_optional<F, R, S>::value() const -> const_value_expression
1224 return this->derived_cast().template build_generator<value_closure>(
1225 detail::value_functor<F>::get(this->derived_cast().functor())
1229 template <
class F,
class R,
class S>
1230 inline auto xgenerator_optional<F, R, S>::has_value() const -> const_flag_expression
1232 return this->derived_cast().template build_generator<flag_closure>(
1233 detail::flag_functor<F>::get(this->derived_cast().functor())
1244 template <
class T,
class B>
1247 static constexpr auto run(
const xtl::xoptional<T, B>&
x)
1254 template <
class T,
class B>
1255 inline auto sign(
const xtl::xoptional<T, B>&
e)
1257 using value_type = std::decay_t<T>;
1265 template <
class E, XTL_REQUIRES(is_xexpression<E>)>
1266 inline auto value(E&& e) -> detail::value_expression_t<E>
1268 return detail::split_optional_expression<E>::value(std::forward<E>(e));
1271 template <
class E, XTL_REQUIRES(is_xexpression<E>)>
1272 inline auto has_value(E&& e) -> detail::flag_expression_t<E>
1274 return detail::split_optional_expression<E>::has_value(std::forward<E>(e));
1279 template <
class T1,
class T2>
1280 struct assign_data_impl
1282 template <
class E1,
class E2>
1283 static void run(xexpression<E1>& e1,
const xexpression<E2>& e2,
bool trivial)
1285 E1& de1 = e1.derived_cast();
1286 const E2& de2 = e2.derived_cast();
1288 decltype(
auto) bde1 = xt::value(de1);
1289 decltype(
auto) hde1 = xt::has_value(de1);
1290 xexpression_assigner_base<xtensor_expression_tag>::assign_data(bde1, xt::value(de2), trivial);
1291 xexpression_assigner_base<xtensor_expression_tag>::assign_data(hde1, xt::has_value(de2), trivial);
1296 struct xarray_assigner
1298 template <
class E1,
class E2>
1299 static void assign(xexpression<E1>& e1,
const xexpression<E2>& e2,
bool trivial)
1301 E1& de1 = e1.derived_cast();
1302 const E2& de2 = e2.derived_cast();
1305 decltype(
auto) bde1 = xt::value(de1);
1306 decltype(
auto) hde1 = xt::has_value(de1);
1307 xexpression_assigner_base<xtensor_expression_tag>::assign_data(bde1, e2, trivial);
1308 xexpression_assigner_base<xtensor_expression_tag>::assign_data(hde1, mask, trivial);
1313 struct xarray_assigner<xtl::xoptional<T>>
1315 template <
class E1,
class E2>
1316 static void assign(xexpression<E1>& e1,
const xexpression<E2>& e2,
bool trivial)
1318 xexpression_assigner_base<xtensor_expression_tag>::assign_data(e1, e2, trivial);
1323 struct assign_data_impl<xoptional_expression_tag, xtensor_expression_tag>
1325 template <
class E1,
class E2>
1326 static void run(xexpression<E1>& e1,
const xexpression<E2>& e2,
bool trivial)
1328 xarray_assigner<typename E2::value_type>::assign(e1, e2, trivial);
1333 struct assign_data_impl<xtensor_expression_tag, xoptional_expression_tag>
1335 template <
class E1,
class E2>
1336 static void run(xexpression<E1>& e1,
const xexpression<E2>& e2,
bool trivial)
1338 xexpression_assigner_base<xtensor_expression_tag>::assign_data(e1, e2, trivial);
1343 template <
class E1,
class E2>
1344 inline void xexpression_assigner_base<xoptional_expression_tag>::assign_data(
1345 xexpression<E1>& e1,
1346 const xexpression<E2>& e2,
1350 detail::assign_data_impl<typename E1::expression_tag, typename E2::expression_tag>::run(e1, e2, trivial);
Multidimensional view with tensor semantic.
auto sign(E &&e) noexcept -> detail::xfunction_type_t< math::sign_fun, E >
Returns an element-wise indication of the sign of a number.
standard mathematical functions for xexpressions
auto full_like(const xexpression< E > &e, typename E::value_type fill_value)
Create a xcontainer (xarray, xtensor or xtensor_fixed), filled with fill_value and of the same shape,...