xtensor
Loading...
Searching...
No Matches
xoptional_assembly.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 XOPTIONAL_ASSEMBLY_HPP
11#define XOPTIONAL_ASSEMBLY_HPP
12
13#include "xoptional.hpp"
14#include "xoptional_assembly_base.hpp"
15#include "xsemantic.hpp"
16
17namespace xt
18{
19
20 /**********************************
21 * xoptional_assembly declaration *
22 **********************************/
23
24 template <class VE, class FE>
25 class xoptional_assembly;
26
27 template <class VE, class FE>
29 {
31 using value_storage_type = typename raw_value_expression::storage_type&;
32 using raw_flag_expression = FE;
33 using flag_storage_type = typename raw_flag_expression::storage_type&;
36 };
37
38 template <class VE, class FE>
46
60 template <class VE, class FE>
61 class xoptional_assembly : public xoptional_assembly_base<xoptional_assembly<VE, FE>>,
62 public xcontainer_semantic<xoptional_assembly<VE, FE>>
63 {
64 public:
65
69 using raw_value_expression = typename base_type::raw_value_expression;
70 using raw_flag_expression = typename base_type::raw_flag_expression;
71 using value_expression = typename base_type::value_expression;
72 using flag_expression = typename base_type::flag_expression;
73 using const_value_expression = typename base_type::const_value_expression;
74 using const_flag_expression = typename base_type::const_flag_expression;
75 using storage_type = typename base_type::storage_type;
76 using value_type = typename base_type::value_type;
77 using reference = typename base_type::reference;
78 using const_reference = typename base_type::const_reference;
79 using pointer = typename base_type::pointer;
80 using const_pointer = typename base_type::const_pointer;
81 using shape_type = typename base_type::shape_type;
82 using strides_type = typename base_type::strides_type;
83
85
87 explicit xoptional_assembly(const shape_type& shape, layout_type l = base_type::static_layout);
88 explicit xoptional_assembly(
89 const shape_type& shape,
90 const value_type& value,
91 layout_type l = base_type::static_layout
92 );
93 explicit xoptional_assembly(const shape_type& shape, const strides_type& strides);
94 explicit xoptional_assembly(const shape_type& shape, const strides_type& strides, const value_type& value);
95
96 xoptional_assembly(const VE& ve);
98
101
102 xoptional_assembly(const value_type& value);
108
109 template <class S = shape_type>
110 static xoptional_assembly from_shape(S&& s);
111
112 ~xoptional_assembly() = default;
113
115 xoptional_assembly& operator=(const xoptional_assembly&);
116
119
120 template <class E>
122
123 template <class E>
124 xoptional_assembly& operator=(const xexpression<E>& e);
125
126 private:
127
128 storage_type& storage_impl() noexcept;
129 const storage_type& storage_impl() const noexcept;
130
131 value_expression value_impl() noexcept;
132 const_value_expression value_impl() const noexcept;
133
134 flag_expression has_value_impl() noexcept;
135 const_flag_expression has_value_impl() const noexcept;
136
137 raw_value_expression m_value;
138 raw_flag_expression m_has_value;
139 storage_type m_storage;
140
142 };
143
144 /******************************************
145 * xoptional_assembly_adaptor declaration *
146 ******************************************/
147
148 template <class VEC, class FEC>
150
151 template <class VEC, class FEC>
153 {
154 using raw_value_expression = std::remove_reference_t<VEC>;
155 using value_storage_type = std::conditional_t<
156 std::is_const<raw_value_expression>::value,
157 const typename raw_value_expression::storage_type&,
158 typename raw_value_expression::storage_type&>;
159 using raw_flag_expression = std::remove_reference_t<FEC>;
160 using flag_storage_type = std::conditional_t<
161 std::is_const<raw_flag_expression>::value,
162 const typename raw_flag_expression::storage_type&,
163 typename raw_flag_expression::storage_type&>;
166 };
167
168 template <class VEC, class FEC>
170 {
172 using inner_shape_type = typename std::decay_t<VEC>::inner_shape_type;
175 };
176
189 template <class VEC, class FEC>
190 class xoptional_assembly_adaptor : public xoptional_assembly_base<xoptional_assembly_adaptor<VEC, FEC>>,
191 public xcontainer_semantic<xoptional_assembly_adaptor<VEC, FEC>>
192 {
193 public:
194
198 using storage_type = typename base_type::storage_type;
199 using value_expression = typename base_type::value_expression;
200 using flag_expression = typename base_type::flag_expression;
201 using const_value_expression = typename base_type::const_value_expression;
202 using const_flag_expression = typename base_type::const_flag_expression;
203 using value_type = typename base_type::value_type;
204 using reference = typename base_type::reference;
205 using const_reference = typename base_type::const_reference;
206 using pointer = typename base_type::pointer;
207 using const_pointer = typename base_type::const_pointer;
208 using shape_type = typename base_type::shape_type;
209 using strides_type = typename base_type::strides_type;
210 using temporary_type = typename semantic_base::temporary_type;
211
212 using assembly_type = base_type;
213
214 template <class OVE, class OFE>
216
217 ~xoptional_assembly_adaptor() = default;
218
221
224 xoptional_assembly_adaptor& operator=(temporary_type&&);
225
226 template <class E>
228
229 private:
230
231 storage_type& storage_impl() noexcept;
232 const storage_type& storage_impl() const noexcept;
233
234 value_expression value_impl() noexcept;
235 const_value_expression value_impl() const noexcept;
236
237 flag_expression has_value_impl() noexcept;
238 const_flag_expression has_value_impl() const noexcept;
239
240 VEC m_value;
241 FEC m_has_value;
242 storage_type m_storage;
243
245 };
246
247 /*************************************
248 * xoptional_assembly implementation *
249 *************************************/
250
251 namespace detail
252 {
253 template <class T, class S>
254 inline void nested_optional_copy(T&& iter, const S& s)
255 {
256 iter->value() = s.value();
257 iter->has_value() = s.has_value();
258 ++iter;
259 }
260
261 template <class T, class S>
262 inline void nested_optional_copy(T&& iter, std::initializer_list<S> s)
263 {
264 for (auto it = s.begin(); it != s.end(); ++it)
265 {
266 nested_optional_copy(std::forward<T>(iter), *it);
267 }
268 }
269 }
270
278 template <class VE, class FE>
280 : m_value()
281 , m_has_value()
282 , m_storage(m_value.storage(), m_has_value.storage())
283 {
284 }
285
292 template <class VE, class FE>
294 : m_value(shape, l)
295 , m_has_value(shape, l)
296 , m_storage(m_value.storage(), m_has_value.storage())
297 {
298 }
299
307 template <class VE, class FE>
309 const shape_type& shape,
310 const value_type& value,
312 )
313 : m_value(shape, value.value(), l)
314 , m_has_value(shape, value.has_value(), l)
315 , m_storage(m_value.storage(), m_has_value.storage())
316 {
317 }
318
324 template <class VE, class FE>
325 inline xoptional_assembly<VE, FE>::xoptional_assembly(const shape_type& shape, const strides_type& strides)
326 : m_value(shape, strides)
327 , m_has_value(shape, strides)
328 , m_storage(m_value.storage(), m_has_value.storage())
329 {
330 }
331
339 template <class VE, class FE>
341 const shape_type& shape,
342 const strides_type& strides,
343 const value_type& value
344 )
345 : m_value(shape, strides, value.value())
346 , m_has_value(shape, strides, value.has_value())
347 , m_storage(m_value.storage(), m_has_value.storage())
348 {
349 }
350
356 template <class VE, class FE>
358 : m_value(value.value())
359 , m_has_value(value.has_value())
360 , m_storage(m_value.storage(), m_has_value.storage())
361 {
362 }
363
369 template <class VE, class FE>
371 : m_value(ve)
372 , m_has_value(ve.shape(), true, ve.layout())
373 , m_storage(m_value.storage(), m_has_value.storage())
374 {
375 }
376
384 template <class VE, class FE>
386 : m_value(std::move(ve))
387 , m_has_value(ve.shape(), true, ve.layout())
388 , m_storage(m_value.storage(), m_has_value.storage())
389 {
390 }
391
398 template <class VE, class FE>
399 template <class OVE, class OFE, typename>
401 : m_value(std::forward<OVE>(ove))
402 , m_has_value(std::forward<OFE>(ofe))
403 , m_storage(m_value.storage(), m_has_value.storage())
404 {
405 }
406
408
417 template <class VE, class FE>
419 : base_type()
420 , m_value()
421 , m_has_value()
422 , m_storage(m_value.storage(), m_has_value.storage())
423 {
425 bool condition = VE::static_layout == layout_type::row_major
426 && FE::static_layout == layout_type::row_major;
427 condition ? detail::nested_optional_copy(this->linear_begin(), t)
428 : nested_copy(this->template begin<layout_type::row_major>(), t);
429 }
430
435 template <class VE, class FE>
437 : base_type()
438 , m_value()
439 , m_has_value()
440 , m_storage(m_value.storage(), m_has_value.storage())
441 {
443 bool condition = VE::static_layout == layout_type::row_major
444 && FE::static_layout == layout_type::row_major;
445 condition ? detail::nested_optional_copy(this->linear_begin(), t)
446 : nested_copy(this->template begin<layout_type::row_major>(), t);
447 }
448
453 template <class VE, class FE>
455 : base_type()
456 , m_value()
457 , m_has_value()
458 , m_storage(m_value.storage(), m_has_value.storage())
459 {
461 bool condition = VE::static_layout == layout_type::row_major
462 && FE::static_layout == layout_type::row_major;
463 condition ? detail::nested_optional_copy(this->linear_begin(), t)
464 : nested_copy(this->template begin<layout_type::row_major>(), t);
465 }
466
471 template <class VE, class FE>
473 : base_type()
474 , m_value()
475 , m_has_value()
476 , m_storage(m_value.storage(), m_has_value.storage())
477 {
479 bool condition = VE::static_layout == layout_type::row_major
480 && FE::static_layout == layout_type::row_major;
481 condition ? detail::nested_optional_copy(this->linear_begin(), t)
482 : nested_copy(this->template begin<layout_type::row_major>(), t);
483 }
484
489 template <class VE, class FE>
491 : base_type()
492 , m_value()
493 , m_has_value()
494 , m_storage(m_value.storage(), m_has_value.storage())
495 {
497 bool condition = VE::static_layout == layout_type::row_major
498 && FE::static_layout == layout_type::row_major;
499 condition ? detail::nested_optional_copy(this->linear_begin(), t)
500 : nested_copy(this->template begin<layout_type::row_major>(), t);
501 }
502
504
509 template <class VE, class FE>
510 template <class S>
512 {
513 shape_type shape = xtl::forward_sequence<shape_type, S>(s);
514 return self_type(shape);
515 }
516
517 template <class VE, class FE>
519 : base_type()
520 , semantic_base()
521 , m_value(rhs.m_value)
522 , m_has_value(rhs.m_has_value)
523 , m_storage(m_value.storage(), m_has_value.storage())
524 {
525 }
526
527 template <class VE, class FE>
529 : base_type()
530 , semantic_base()
531 , m_value(rhs.m_value)
532 , m_has_value(rhs.m_has_value)
533 , m_storage(m_value.storage(), m_has_value.storage())
534 {
535 }
536
537 template <class VE, class FE>
538 inline auto xoptional_assembly<VE, FE>::operator=(const self_type& rhs) -> self_type&
539 {
540 base_type::operator=(rhs);
541 m_value = rhs.m_value;
542 m_has_value = rhs.m_has_value;
543 return *this;
544 }
545
546 template <class VE, class FE>
547 inline auto xoptional_assembly<VE, FE>::operator=(self_type&& rhs) -> self_type&
548 {
549 base_type::operator=(rhs);
550 m_value = std::move(rhs.m_value);
551 m_has_value = std::move(rhs.m_has_value);
552 return *this;
553 }
554
562 template <class VE, class FE>
563 template <class E>
565 : base_type()
566 , m_value()
567 , m_has_value()
568 , m_storage(m_value.storage(), m_has_value.storage())
569 {
570 semantic_base::assign(e);
571 }
572
576 template <class VE, class FE>
577 template <class E>
579 {
580 return semantic_base::operator=(e);
581 }
582
584
585 template <class VE, class FE>
586 inline auto xoptional_assembly<VE, FE>::storage_impl() noexcept -> storage_type&
587 {
588 return m_storage;
589 }
590
591 template <class VE, class FE>
592 inline auto xoptional_assembly<VE, FE>::storage_impl() const noexcept -> const storage_type&
593 {
594 return m_storage;
595 }
596
597 template <class VE, class FE>
598 inline auto xoptional_assembly<VE, FE>::value_impl() noexcept -> value_expression
599 {
600 return m_value;
601 }
602
603 template <class VE, class FE>
604 inline auto xoptional_assembly<VE, FE>::value_impl() const noexcept -> const_value_expression
605 {
606 return m_value;
607 }
608
609 template <class VE, class FE>
610 inline auto xoptional_assembly<VE, FE>::has_value_impl() noexcept -> flag_expression
611 {
612 return m_has_value;
613 }
614
615 template <class VE, class FE>
616 inline auto xoptional_assembly<VE, FE>::has_value_impl() const noexcept -> const_flag_expression
617 {
618 return m_has_value;
619 }
620
621 /*********************************************
622 * xoptional_assembly_adaptor implementation *
623 *********************************************/
624
635 template <class VEC, class FEC>
636 template <class OVE, class OFE>
638 : m_value(std::forward<OVE>(ve))
639 , m_has_value(std::forward<OFE>(fe))
640 , m_storage(m_value.storage(), m_has_value.storage())
641 {
642 }
643
645
646 template <class VEC, class FEC>
648 : base_type()
649 , semantic_base()
650 , m_value(rhs.m_value)
651 , m_has_value(rhs.m_has_value)
652 , m_storage(m_value.storage(), m_has_value.storage())
653 {
654 }
655
656 template <class VEC, class FEC>
657 inline auto xoptional_assembly_adaptor<VEC, FEC>::operator=(const self_type& rhs) -> self_type&
658 {
659 base_type::operator=(rhs);
660 m_value = rhs.m_value;
661 m_has_value = rhs.m_has_value;
662 return *this;
663 }
664
665 template <class VEC, class FEC>
667 : base_type()
668 , semantic_base()
669 , m_value(rhs.m_value)
670 , m_has_value(rhs.m_has_value)
671 , m_storage(m_value.storage(), m_has_value.storage())
672 {
673 }
674
675 template <class VEC, class FEC>
676 inline auto xoptional_assembly_adaptor<VEC, FEC>::operator=(self_type&& rhs) -> self_type&
677 {
678 base_type::operator=(std::move(rhs));
679 m_value = rhs.m_value;
680 m_has_value = rhs.m_has_value;
681 return *this;
682 }
683
684 template <class VEC, class FEC>
685 inline auto xoptional_assembly_adaptor<VEC, FEC>::operator=(temporary_type&& tmp) -> self_type&
686 {
687 m_value = std::move(tmp.value());
688 m_has_value = std::move(tmp.has_value());
689 return *this;
690 }
691
699 template <class VEC, class FEC>
700 template <class E>
702 {
703 return semantic_base::operator=(e);
704 }
705
707
708 template <class VEC, class FEC>
710 {
711 return m_storage;
712 }
713
714 template <class VEC, class FEC>
715 inline auto xoptional_assembly_adaptor<VEC, FEC>::storage_impl() const noexcept -> const storage_type&
716 {
717 return m_storage;
718 }
719
720 template <class VEC, class FEC>
721 inline auto xoptional_assembly_adaptor<VEC, FEC>::value_impl() noexcept -> value_expression
722 {
723 return m_value;
724 }
725
726 template <class VEC, class FEC>
727 inline auto xoptional_assembly_adaptor<VEC, FEC>::value_impl() const noexcept -> const_value_expression
728 {
729 return m_value;
730 }
731
732 template <class VEC, class FEC>
733 inline auto xoptional_assembly_adaptor<VEC, FEC>::has_value_impl() noexcept -> flag_expression
734 {
735 return m_has_value;
736 }
737
738 template <class VEC, class FEC>
739 inline auto xoptional_assembly_adaptor<VEC, FEC>::has_value_impl() const noexcept -> const_flag_expression
740 {
741 return m_has_value;
742 }
743}
744
745#endif
Implementation of the xsemantic_base interface for dense multidimensional containers.
Dense multidimensional adaptor holding optional values, optimized for tensor operations.
xoptional_assembly_adaptor(OVE &&ve, OFE &&fe)
Constructs an xoptional_assembly_adaptor of the given value and missing mask expressions.
Base class for dense multidimensional optional assemblies.
const inner_shape_type & shape() const noexcept
Returns the shape of the optional assembly.
value_expression value() noexcept
Return an expression for the values of the optional assembly.
const inner_strides_type & strides() const noexcept
Returns the strides of the optional assembly.
void resize(const S &shape, bool force=false)
Resizes the optional assembly.
Dense multidimensional container holding optional values, optimized for tensor operations.
xoptional_assembly()
Allocates an uninitialized xoptional_assembly that holds 0 element.
auto strides(const E &e, stride_type type=stride_type::normal) noexcept
Get strides of an object.
Definition xstrides.hpp:248
standard mathematical functions for xexpressions
layout_type
Definition xlayout.hpp:24