xtensor
Loading...
Searching...
No Matches
xoptional.hpp
1/***************************************************************************
2 * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
3 * Copyright (c) QuantStack *
4 * *
5 * Distributed under the terms of the BSD 3-Clause License. *
6 * *
7 * The full license is in the file LICENSE, distributed with this software. *
8 ****************************************************************************/
9
10#ifndef XTENSOR_OPTIONAL_HPP
11#define XTENSOR_OPTIONAL_HPP
12
13#include <type_traits>
14#include <utility>
15
16#include <xtl/xoptional.hpp>
17#include <xtl/xoptional_sequence.hpp>
18
19#include "xarray.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"
26#include "xrepeat.hpp"
27#include "xscalar.hpp"
28#include "xstrided_view.hpp"
29#include "xtensor.hpp"
30#include "xview.hpp"
31
32namespace xt
33{
34
35 /****************************************************
36 * Metafunction for splitting xoptional expressions *
37 ****************************************************/
38
39 namespace extension
40 {
41
42 /**************************************
43 * get_expression_tag specializations *
44 **************************************/
45
46 template <class T, class B>
47 struct get_expression_tag<xtl::xoptional<T, B>>
48 {
50 };
51
52 /************************
53 * xoptional_empty_base *
54 ************************/
55
56 template <class D>
58 {
59 public:
60
62
63 protected:
64
65 D& derived_cast() noexcept;
66 const D& derived_cast() const noexcept;
67 };
68 }
69
70 namespace detail
71 {
72 /*****************************
73 * split_optional_expression *
74 *****************************/
75
76 template <class T, class Tag>
77 struct split_optional_expression_impl
78 {
79 using value_expression = T;
80 using flag_expression = decltype(ones<bool>(std::declval<T>().shape()));
81
82 template <class U>
83 inline static U&& value(U&& arg)
84 {
85 return std::forward<U>(arg);
86 }
87
88 template <class U>
89 inline static flag_expression has_value(U&& arg)
90 {
91 return ones<bool>(arg.shape());
92 }
93 };
94
95 template <class T, class Tag>
96 struct split_optional_expression_impl<xscalar<T>, Tag>
97 {
98 using value_expression = xscalar<T>;
99 using flag_expression = xscalar<bool>;
100
101 template <class U>
102 inline static U&& value(U&& arg)
103 {
104 return std::forward<U>(arg);
105 }
106
107 template <class U>
108 inline static flag_expression has_value(U&&)
109 {
110 return xscalar<bool>(true);
111 }
112 };
113
114 template <class T>
115 struct split_optional_expression_impl_base
116 {
117 static constexpr bool is_const = std::is_const<std::remove_reference_t<T>>::value;
118 using decay_type = std::decay_t<T>;
119
120 using value_expression = std::conditional_t<
121 is_const,
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>;
126
127 template <class U>
128 inline static value_expression value(U&& arg)
129 {
130 return arg.value();
131 }
132
133 template <class U>
134 inline static flag_expression has_value(U&& arg)
135 {
136 return arg.has_value();
137 }
138 };
139
140 template <class T>
141 struct split_optional_expression_impl<T, xoptional_expression_tag>
142 : split_optional_expression_impl_base<T>
143 {
144 };
145
146 template <class T>
147 struct split_optional_expression_impl<xscalar<T>, xoptional_expression_tag>
148 : split_optional_expression_impl_base<xscalar<T>>
149 {
150 };
151
152 template <class T>
153 struct split_optional_expression
154 : split_optional_expression_impl<T, xexpression_tag_t<std::decay_t<T>>>
155 {
156 };
157
158 template <class T>
159 using value_expression_t = typename split_optional_expression<T>::value_expression;
160
161 template <class T>
162 using flag_expression_t = typename split_optional_expression<T>::flag_expression;
163
164 /********************
165 * optional_bitwise *
166 ********************/
167
168 template <class T = bool>
169 class optional_bitwise
170 {
171 public:
172
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;
179
180 template <class... Args>
181 constexpr result_type operator()(const Args&... args) const
182 {
183 return apply_impl(args...);
184 }
185
186 template <class B, class... Args>
187 constexpr B simd_apply(const B& b, const Args&... args) const
188 {
189 return simd_apply_impl(b, args...);
190 }
191
192 private:
193
194 constexpr result_type apply_impl() const
195 {
196 return true;
197 }
198
199 template <class U, class... Args>
200 constexpr result_type apply_impl(const U& t, const Args&... args) const
201 {
202 return t & apply_impl(args...);
203 }
204
205 template <class B>
206 constexpr B simd_apply_impl(const B& b) const
207 {
208 return b;
209 }
210
211 template <class B1, class B2, class... Args>
212 constexpr B1 simd_apply_impl(const B1& b1, const B2& b2, const Args&... args) const
213 {
214 return b1 & simd_apply_impl(b2, args...);
215 }
216 };
217
218 /*********************************
219 * optional const_value rebinder *
220 *********************************/
221
222 template <class T, class B>
223 struct const_value_rebinder<xtl::xoptional<T, B>, T>
224 {
225 static const_value<T> run(const const_value<xtl::xoptional<T, B>>& src)
226 {
227 return const_value<T>(src.m_value.value());
228 }
229 };
230
231 /**************************
232 * xreducer types helpers *
233 **************************/
234
235 template <class T, class B>
236 struct xreducer_size_type<xtl::xoptional<T, B>>
237 {
238 using type = xtl::xoptional<std::size_t, bool>;
239 };
240
241 template <class T, class B>
242 struct xreducer_temporary_type<xtl::xoptional<T, B>>
243 {
244 using type = xtl::xoptional<std::decay_t<T>, bool>;
245 ;
246 };
247 }
248
249 /**********************
250 * optional functions *
251 **********************/
252
253 template <class T, class B>
254 auto sign(const xtl::xoptional<T, B>& e);
255
256 /*template <class E, XTL_REQUIRES(is_xexpression<E>)>
257 detail::value_expression_t<E> value(E&&);
258
259 template <class E, XTL_REQUIRES(is_xexpression<E>)>
260 detail::flag_expression_t<E> has_value(E&&);*/
261
262 template <>
264 {
265 public:
266
267 template <class E1, class E2>
268 static void assign_data(xexpression<E1>& e1, const xexpression<E2>& e2, bool trivial);
269 };
270
271 /**********************************
272 * xscalar extension for optional *
273 **********************************/
274
275 namespace extension
276 {
277 template <class CT>
279 {
280 using closure_type = CT;
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>;
285
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>;
290
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>;
297
302 };
303
304 template <class CT>
305 class xscalar_optional_base : public xoptional_empty_base<xscalar<CT>>
306 {
307 public:
308
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;
315
316 value_expression value();
317 const_value_expression value() const;
318
319 flag_expression has_value();
320 const_flag_expression has_value() const;
321 };
322
323 template <class CT>
328 }
329
330 /*************************************
331 * xcontainer extension for optional *
332 *************************************/
333
334 namespace extension
335 {
336 template <class T>
337 class xcontainer_optional_base : public xoptional_empty_base<typename T::derived_type>
338 {
339 public:
340
341 using traits = T;
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;
347
348 value_expression value();
349 const_value_expression value() const;
350
351 flag_expression has_value();
352 const_flag_expression has_value() const;
353 };
354 }
355
356 /*******************************************
357 * xarray_container extension for optional *
358 *******************************************/
359
360 namespace extension
361 {
362 template <class EC, layout_type L, class SC>
364 {
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;
371 };
372
373 template <class EC, layout_type L, class SC>
378
379 template <class EC, layout_type L, class SC>
385 }
386
387 /*****************************************
388 * xarray_adaptor extension for optional *
389 *****************************************/
390
391 namespace extension
392 {
393 template <class EC, layout_type L, class SC>
398
399 template <class EC, layout_type L, class SC>
405 }
406
407 /********************************************
408 * xtensor_container extension for optional *
409 ********************************************/
410
411 namespace extension
412 {
413 template <class EC, std::size_t N, layout_type L>
415 {
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;
422 };
423
424 template <class EC, std::size_t N, layout_type L>
429
430 template <class EC, std::size_t N, layout_type L>
436 }
437
438 /******************************************
439 * xtensor_adaptor extension for optional *
440 ******************************************/
441
442 namespace extension
443 {
444 template <class EC, std::size_t N, layout_type L>
449
450 template <class EC, std::size_t N, layout_type L>
456 }
457
458 /***************************************
459 * xtensor_view extension for optional *
460 ***************************************/
461
462 namespace extension
463 {
464 template <class EC, std::size_t N, layout_type L>
469
470 template <class EC, std::size_t N, layout_type L>
476 }
477
478 /************************************************
479 * xfunction extension for optional expressions *
480 ************************************************/
481
482 namespace extension
483 {
484 template <class F, class... CT>
485 class xfunction_optional_base : public xoptional_empty_base<xfunction<F, CT...>>
486 {
487 public:
488
490 using value_functor = F;
491 using flag_functor = xt::detail::optional_bitwise<bool>;
492
497
498 const_value_expression value() const;
499 const_flag_expression has_value() const;
500
501 private:
502
503 template <std::size_t... I>
504 const_value_expression value_impl(std::index_sequence<I...>) const;
505
506 template <std::size_t... I>
507 const_flag_expression has_value_impl(std::index_sequence<I...>) const;
508 };
509
510 template <class F, class... CT>
515 }
516
517 /****************************************************
518 * xdynamic_view extension for optional expressions *
519 ****************************************************/
520
521 namespace extension
522 {
523 template <class CT, class S, layout_type L, class FST>
524 class xdynamic_view_optional : public xoptional_empty_base<xdynamic_view<CT, S, L, FST>>
525 {
526 public:
527
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;
537
538 value_expression value();
539 const_value_expression value() const;
540
541 flag_expression has_value();
542 const_flag_expression has_value() const;
543 };
544
545 template <class CT, class S, layout_type L, class FST>
550 }
551
552 /*************************************************
553 * xbroadcast extension for optional expressions *
554 *************************************************/
555
556 namespace extension
557 {
558 template <class CT, class X>
572
573 template <class CT, class X>
578 }
579
580 /***************************************************
581 * xfunctor_view extension for optional expression *
582 ***************************************************/
583
584 namespace extension
585 {
586 template <class F, class CT>
587 class xfunctor_view_optional : public xoptional_empty_base<xfunctor_view<F, CT>>
588 {
589 public:
590
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;
600
601 value_expression value();
602 const_value_expression value() const;
603
604 flag_expression has_value();
605 const_flag_expression has_value() const;
606 };
607
608 template <class F, class CT>
613 }
614
615 /**************************************************
616 * xindex_view extension for optional expressions *
617 **************************************************/
618
619 namespace extension
620 {
621 template <class CT, class I>
622 class xindex_view_optional : public xoptional_empty_base<xindex_view<CT, I>>
623 {
624 public:
625
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;
635
636 value_expression value();
637 const_value_expression value() const;
638
639 flag_expression has_value();
640 const_flag_expression has_value() const;
641 };
642
643 template <class CT, class I>
648 }
649
650 /***********************************************
651 * xreducer extension for optional expressions *
652 ***********************************************/
653
654 namespace extension
655 {
656 template <class F, class CT, class X, class O>
657 class xreducer_optional : public xoptional_empty_base<xreducer<F, CT, X, O>>
658 {
659 public:
660
662 using result_type = typename F::init_value_type;
663
664 using rebound_result_type = typename result_type::value_type;
665 using rebound_functors_type = typename F::template rebind_t<rebound_result_type>;
666 using rebound_reduce_options_values = typename O::template rebind_t<rebound_result_type>;
667 using rebound_reduce_options_flag = typename O::template rebind_t<bool>;
668
672
675
676 const_value_expression value() const;
677 const_flag_expression has_value() const;
678 };
679
680 template <class F, class CT, class X, class O>
685 }
686
687 /**********************************************
688 * xrepeat extension for optional expressions *
689 **********************************************/
690
691 namespace extension
692 {
693 template <class CT, class X>
707
708 template <class CT, class X>
713 }
714
715 /****************************************************
716 * xstrided_view extension for optional expressions *
717 ****************************************************/
718
719 namespace extension
720 {
721 template <class CT, class S, layout_type L, class FST>
722 class xstrided_view_optional : public xoptional_empty_base<xstrided_view<CT, S, L, FST>>
723 {
724 public:
725
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;
735
736 value_expression value();
737 const_value_expression value() const;
738
739 flag_expression has_value();
740 const_flag_expression has_value() const;
741 };
742
743 template <class CT, class S, layout_type L, class FST>
748 }
749
750 /********************************************
751 * xview extension for optional expressions *
752 ********************************************/
753
754 namespace extension
755 {
756 template <class CT, class... S>
757 class xview_optional : public xoptional_empty_base<xview<CT, S...>>
758 {
759 public:
760
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;
766 using value_expression = xview<uvt, S...>;
767 using flag_expression = xview<uft, S...>;
768 using const_value_expression = xview<ucvt, S...>;
769 using const_flag_expression = xview<ucft, S...>;
770
771 value_expression value();
772 const_value_expression value() const;
773
774 flag_expression has_value();
775 const_flag_expression has_value() const;
776 };
777
778 template <class CT, class... S>
780 {
781 using type = xview_optional<CT, S...>;
782 };
783 }
784
785 /*************************************************
786 * xgenerator extension for generator expression *
787 *************************************************/
788
789 namespace extension
790 {
791 namespace detail
792 {
793 template <class F, class = void_t<int>>
794 struct value_functor
795 {
796 using type = F;
797
798 static type get(const F& f)
799 {
800 return f;
801 }
802 };
803
804 template <class F>
805 struct value_functor<F, void_t<typename F::value_functor_type>>
806 {
807 using type = typename F::value_functor_type;
808
809 static type get(const F& f)
810 {
811 return f.value_functor();
812 }
813 };
814
815 template <class F>
816 using value_functor_t = typename value_functor<F>::type;
817
818 struct always_true
819 {
820 template <class... T>
821 bool operator()(T...) const
822 {
823 return true;
824 }
825 };
826
827 template <class F, class = void_t<int>>
828 struct flag_functor
829 {
830 using type = always_true;
831
832 static type get(const F&)
833 {
834 return type();
835 }
836 };
837
838 template <class F>
839 struct flag_functor<F, void_t<typename F::flag_functor_type>>
840 {
841 using type = typename F::flag_functor_type;
842
843 static type get(const F& f)
844 {
845 return f.flag_functor();
846 }
847 };
848
849 template <class F>
850 using flag_functor_t = typename flag_functor<F>::type;
851 }
852
853 template <class F, class R, class S>
854 class xgenerator_optional : public xoptional_empty_base<xgenerator<F, R, S>>
855 {
856 public:
857
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>;
867
868 const_value_expression value() const;
869 const_flag_expression has_value() const;
870 };
871
872 template <class F, class R, class S>
877 }
878
879 /***************************************
880 * xoptional_empty_base implementation *
881 ***************************************/
882
883 namespace extension
884 {
885 template <class D>
886 inline D& xoptional_empty_base<D>::derived_cast() noexcept
887 {
888 return *static_cast<D*>(this);
889 }
890
891 template <class D>
892 inline const D& xoptional_empty_base<D>::derived_cast() const noexcept
893 {
894 return *static_cast<const D*>(this);
895 }
896 }
897
898 /****************************************
899 * xscalar_optional_base implementation *
900 ****************************************/
901
902 namespace extension
903 {
904 template <class CT>
905 inline auto xscalar_optional_base<CT>::value() -> value_expression
906 {
907 return this->derived_cast().expression().value();
908 }
909
910 template <class CT>
911 inline auto xscalar_optional_base<CT>::value() const -> const_value_expression
912 {
913 return this->derived_cast().expression().value();
914 }
915
916 template <class CT>
917 inline auto xscalar_optional_base<CT>::has_value() -> flag_expression
918 {
919 return this->derived_cast().expression().has_value();
920 }
921
922 template <class CT>
923 inline auto xscalar_optional_base<CT>::has_value() const -> const_flag_expression
924 {
925 return this->derived_cast().expression().has_value();
926 }
927 }
928
929 /*******************************************
930 * xcontainer_optional_base implementation *
931 *******************************************/
932
933 namespace extension
934 {
935 template <class T>
936 inline auto xcontainer_optional_base<T>::value() -> value_expression
937 {
938 return value_expression(this->derived_cast().storage().value(), this->derived_cast().shape());
939 }
940
941 template <class T>
942 inline auto xcontainer_optional_base<T>::value() const -> const_value_expression
943 {
944 return const_value_expression(this->derived_cast().storage().value(), this->derived_cast().shape());
945 }
946
947 template <class T>
948 inline auto xcontainer_optional_base<T>::has_value() -> flag_expression
949 {
950 return flag_expression(this->derived_cast().storage().has_value(), this->derived_cast().shape());
951 }
952
953 template <class T>
954 inline auto xcontainer_optional_base<T>::has_value() const -> const_flag_expression
955 {
956 return const_flag_expression(this->derived_cast().storage().has_value(), this->derived_cast().shape());
957 }
958 }
959
960 /******************************************
961 * xfunction_optional_base implementation *
962 ******************************************/
963
964 namespace extension
965 {
966 template <class F, class... CT>
967 inline auto xfunction_optional_base<F, CT...>::value() const -> const_value_expression
968 {
969 return value_impl(std::make_index_sequence<sizeof...(CT)>());
970 }
971
972 template <class F, class... CT>
973 inline auto xfunction_optional_base<F, CT...>::has_value() const -> const_flag_expression
974 {
975 return has_value_impl(std::make_index_sequence<sizeof...(CT)>());
976 }
977
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
982 {
983 return value_expression(
984 value_functor(),
985 xt::detail::split_optional_expression<CT>::value(std::get<I>(this->derived_cast().arguments()))...
986 );
987 }
988
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
993 {
994 return flag_expression(
995 flag_functor(),
996 xt::detail::split_optional_expression<CT>::has_value(
997 std::get<I>(this->derived_cast().arguments())
998 )...
999 );
1000 }
1001 }
1002
1003 /*****************************************
1004 * xdynamic_view_optional implementation *
1005 *****************************************/
1006
1007 namespace extension
1008 {
1009 template <class CT, class S, layout_type L, class FST>
1010 inline auto xdynamic_view_optional<CT, S, L, FST>::value() -> value_expression
1011 {
1012 return this->derived_cast().build_view(this->derived_cast().expression().value());
1013 }
1014
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
1017 {
1018 return this->derived_cast().build_view(this->derived_cast().expression().value());
1019 }
1020
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
1023 {
1024 return this->derived_cast().build_view(this->derived_cast().expression().has_value());
1025 }
1026
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
1029 {
1030 return this->derived_cast().build_view(this->derived_cast().expression().has_value());
1031 }
1032 }
1033
1034 /**************************************
1035 * xbroadcast_optional implementation *
1036 **************************************/
1037
1038 namespace extension
1039 {
1040 template <class CT, class X>
1041 inline auto xbroadcast_optional<CT, X>::value() const -> const_value_expression
1042 {
1043 return this->derived_cast().build_broadcast(this->derived_cast().expression().value());
1044 }
1045
1046 template <class CT, class X>
1047 inline auto xbroadcast_optional<CT, X>::has_value() const -> const_flag_expression
1048 {
1049 return this->derived_cast().build_broadcast(this->derived_cast().expression().has_value());
1050 }
1051 }
1052
1053 /*****************************************
1054 * xfunctor_view_optional implementation *
1055 *****************************************/
1056
1057 namespace extension
1058 {
1059 template <class F, class CT>
1060 inline auto xfunctor_view_optional<F, CT>::value() -> value_expression
1061 {
1062 return this->derived_cast().build_functor_view(this->derived_cast().expression().value());
1063 }
1064
1065 template <class F, class CT>
1066 inline auto xfunctor_view_optional<F, CT>::value() const -> const_value_expression
1067 {
1068 return this->derived_cast().build_functor_view(this->derived_cast().expression().value());
1069 }
1070
1071 template <class F, class CT>
1072 inline auto xfunctor_view_optional<F, CT>::has_value() -> flag_expression
1073 {
1074 return this->derived_cast().expression().has_value();
1075 }
1076
1077 template <class F, class CT>
1078 inline auto xfunctor_view_optional<F, CT>::has_value() const -> const_flag_expression
1079 {
1080 return this->derived_cast().expression().has_value();
1081 }
1082 }
1083
1084 /***************************************
1085 * xindex_view_optional implementation *
1086 ***************************************/
1087
1088 namespace extension
1089 {
1090 template <class CT, class I>
1091 inline auto xindex_view_optional<CT, I>::value() -> value_expression
1092 {
1093 return this->derived_cast().build_index_view(this->derived_cast().expression().value());
1094 };
1095
1096 template <class CT, class I>
1097 inline auto xindex_view_optional<CT, I>::value() const -> const_value_expression
1098 {
1099 return this->derived_cast().build_index_view(this->derived_cast().expression().value());
1100 };
1101
1102 template <class CT, class I>
1103 inline auto xindex_view_optional<CT, I>::has_value() -> flag_expression
1104 {
1105 return this->derived_cast().build_index_view(this->derived_cast().expression().has_value());
1106 };
1107
1108 template <class CT, class I>
1109 inline auto xindex_view_optional<CT, I>::has_value() const -> const_flag_expression
1110 {
1111 return this->derived_cast().build_index_view(this->derived_cast().expression().has_value());
1112 };
1113 }
1114
1115 /************************************
1116 * xreducer_optional implementation *
1117 ************************************/
1118
1119 namespace extension
1120 {
1121 template <class F, class CT, class X, class O>
1122 inline auto xreducer_optional<F, CT, X, O>::value() const -> const_value_expression
1123 {
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()
1128 );
1129
1130 return this->derived_cast().build_reducer(
1131 this->derived_cast().expression().value(),
1132 func.template rebind<rebound_result_type>(),
1133 std::move(opts)
1134 );
1135 }
1136
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
1139 {
1140 auto opts = this->derived_cast().options().rebind(
1141 this->derived_cast().options().initial_value.has_value(),
1142 this->derived_cast().options()
1143 );
1144
1145 return this->derived_cast().build_reducer(
1146 this->derived_cast().expression().has_value(),
1147 make_xreducer_functor(xt::detail::optional_bitwise<bool>(), xt::const_value<bool>(true)),
1148 std::move(opts)
1149 );
1150 }
1151 }
1152
1153 /*****************************************
1154 * xstrided_view_optional implementation *
1155 *****************************************/
1156
1157 namespace extension
1158 {
1159 template <class CT, class S, layout_type L, class FST>
1160 inline auto xstrided_view_optional<CT, S, L, FST>::value() -> value_expression
1161 {
1162 return this->derived_cast().build_view(this->derived_cast().expression().value());
1163 }
1164
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
1167 {
1168 return this->derived_cast().build_view(this->derived_cast().expression().value());
1169 }
1170
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
1173 {
1174 return this->derived_cast().build_view(this->derived_cast().expression().has_value());
1175 }
1176
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
1179 {
1180 return this->derived_cast().build_view(this->derived_cast().expression().has_value());
1181 }
1182 }
1183
1184 /*********************************
1185 * xview_optional implementation *
1186 *********************************/
1187
1188 namespace extension
1189 {
1190 template <class CT, class... S>
1191 inline auto xview_optional<CT, S...>::value() -> value_expression
1192 {
1193 return this->derived_cast().build_view(this->derived_cast().expression().value());
1194 }
1195
1196 template <class CT, class... S>
1197 inline auto xview_optional<CT, S...>::value() const -> const_value_expression
1198 {
1199 return this->derived_cast().build_view(this->derived_cast().expression().value());
1200 }
1201
1202 template <class CT, class... S>
1203 inline auto xview_optional<CT, S...>::has_value() -> flag_expression
1204 {
1205 return this->derived_cast().build_view(this->derived_cast().expression().has_value());
1206 }
1207
1208 template <class CT, class... S>
1209 inline auto xview_optional<CT, S...>::has_value() const -> const_flag_expression
1210 {
1211 return this->derived_cast().build_view(this->derived_cast().expression().has_value());
1212 }
1213 }
1214
1215 /**************************************
1216 * xgenerator_optional implementation *
1217 **************************************/
1218
1219 namespace extension
1220 {
1221 template <class F, class R, class S>
1222 inline auto xgenerator_optional<F, R, S>::value() const -> const_value_expression
1223 {
1224 return this->derived_cast().template build_generator<value_closure>(
1225 detail::value_functor<F>::get(this->derived_cast().functor())
1226 );
1227 }
1228
1229 template <class F, class R, class S>
1230 inline auto xgenerator_optional<F, R, S>::has_value() const -> const_flag_expression
1231 {
1232 return this->derived_cast().template build_generator<flag_closure>(
1233 detail::flag_functor<F>::get(this->derived_cast().functor())
1234 );
1235 }
1236 }
1237
1238 /********************************
1239 * sign function implementation *
1240 ********************************/
1241
1242 namespace math
1243 {
1244 template <class T, class B>
1245 struct sign_impl<xtl::xoptional<T, B>>
1246 {
1247 static constexpr auto run(const xtl::xoptional<T, B>& x)
1248 {
1249 return sign(x); // use overload declared above
1250 }
1251 };
1252 }
1253
1254 template <class T, class B>
1255 inline auto sign(const xtl::xoptional<T, B>& e)
1256 {
1257 using value_type = std::decay_t<T>;
1258 return e.has_value() ? math::sign_impl<value_type>::run(e.value()) : xtl::missing<value_type>();
1259 }
1260
1261 /******************************************
1262 * value() and has_value() implementation *
1263 ******************************************/
1264
1265 template <class E, XTL_REQUIRES(is_xexpression<E>)>
1266 inline auto value(E&& e) -> detail::value_expression_t<E>
1267 {
1268 return detail::split_optional_expression<E>::value(std::forward<E>(e));
1269 }
1270
1271 template <class E, XTL_REQUIRES(is_xexpression<E>)>
1272 inline auto has_value(E&& e) -> detail::flag_expression_t<E>
1273 {
1274 return detail::split_optional_expression<E>::has_value(std::forward<E>(e));
1275 }
1276
1277 namespace detail
1278 {
1279 template <class T1, class T2>
1280 struct assign_data_impl
1281 {
1282 template <class E1, class E2>
1283 static void run(xexpression<E1>& e1, const xexpression<E2>& e2, bool trivial)
1284 {
1285 E1& de1 = e1.derived_cast();
1286 const E2& de2 = e2.derived_cast();
1287
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);
1292 }
1293 };
1294
1295 template <class T>
1296 struct xarray_assigner
1297 {
1298 template <class E1, class E2>
1299 static void assign(xexpression<E1>& e1, const xexpression<E2>& e2, bool trivial)
1300 {
1301 E1& de1 = e1.derived_cast();
1302 const E2& de2 = e2.derived_cast();
1303 xarray<bool> mask = xt::full_like(de2, true);
1304
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);
1309 }
1310 };
1311
1312 template <class T>
1313 struct xarray_assigner<xtl::xoptional<T>>
1314 {
1315 template <class E1, class E2>
1316 static void assign(xexpression<E1>& e1, const xexpression<E2>& e2, bool trivial)
1317 {
1318 xexpression_assigner_base<xtensor_expression_tag>::assign_data(e1, e2, trivial);
1319 }
1320 };
1321
1322 template <>
1323 struct assign_data_impl<xoptional_expression_tag, xtensor_expression_tag>
1324 {
1325 template <class E1, class E2>
1326 static void run(xexpression<E1>& e1, const xexpression<E2>& e2, bool trivial)
1327 {
1328 xarray_assigner<typename E2::value_type>::assign(e1, e2, trivial);
1329 }
1330 };
1331
1332 template <>
1333 struct assign_data_impl<xtensor_expression_tag, xoptional_expression_tag>
1334 {
1335 template <class E1, class E2>
1336 static void run(xexpression<E1>& e1, const xexpression<E2>& e2, bool trivial)
1337 {
1338 xexpression_assigner_base<xtensor_expression_tag>::assign_data(e1, e2, trivial);
1339 }
1340 };
1341 }
1342
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,
1347 bool trivial
1348 )
1349 {
1350 detail::assign_data_impl<typename E1::expression_tag, typename E2::expression_tag>::run(e1, e2, trivial);
1351 }
1352}
1353
1354#endif
Multidimensional view with tensor semantic.
Definition xview.hpp:360
auto sign(E &&e) noexcept -> detail::xfunction_type_t< math::sign_fun, E >
Returns an element-wise indication of the sign of a number.
Definition xmath.hpp:877
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,...
Definition xbuilder.hpp:136