xtensor
Loading...
Searching...
No Matches
xscalar.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_SCALAR_HPP
11#define XTENSOR_SCALAR_HPP
12
13#include <array>
14#include <cstddef>
15#include <utility>
16
17#include <xtl/xtype_traits.hpp>
18
19#include "xaccessible.hpp"
20#include "xexpression.hpp"
21#include "xiterable.hpp"
22#include "xlayout.hpp"
23#include "xtensor_simd.hpp"
24
25namespace xt
26{
27
28 /*********************
29 * xscalar extension *
30 *********************/
31
32 namespace extension
33 {
34 template <class Tag, class CT>
36
37 template <class CT>
42
43 template <class CT>
44 struct xscalar_base : xscalar_base_impl<get_expression_tag_t<std::decay_t<CT>>, CT>
45 {
46 };
47
48 template <class CT>
49 using xscalar_base_t = typename xscalar_base<CT>::type;
50 }
51
52 /***********
53 * xscalar *
54 ***********/
55
56 // xscalar is a cheap wrapper for a scalar value as an xexpression.
57 template <class CT>
58 class xscalar;
59
60 template <bool is_const, class CT>
61 class xscalar_stepper;
62
63 template <bool is_const, class CT>
64 class xdummy_iterator;
65
66 template <class CT>
68 {
69 using value_type = std::decay_t<CT>;
70 using inner_shape_type = std::array<std::size_t, 0>;
71 using shape_type = inner_shape_type;
74 };
75
76 template <class CT>
78 {
79 using value_type = std::decay_t<CT>;
80 using reference = value_type&;
81 using const_reference = const value_type&;
82 using size_type = std::size_t;
83 };
84
85 template <class CT>
86 class xscalar : public xsharable_expression<xscalar<CT>>,
87 private xiterable<xscalar<CT>>,
88 private xaccessible<xscalar<CT>>,
89 public extension::xscalar_base_t<CT>
90 {
91 public:
92
93 using self_type = xscalar<CT>;
94 using xexpression_type = std::decay_t<CT>;
95 using extension_base = extension::xscalar_base_t<CT>;
97 using expression_tag = typename extension_base::expression_tag;
99
100 using value_type = typename inner_types::value_type;
101 using reference = typename inner_types::reference;
102 using const_reference = typename inner_types::const_reference;
103 using pointer = value_type*;
104 using const_pointer = const value_type*;
105 using size_type = typename inner_types::size_type;
106 using difference_type = std::ptrdiff_t;
107 using simd_value_type = xt_simd::simd_type<value_type>;
109
111 using inner_shape_type = typename iterable_base::inner_shape_type;
112 using shape_type = inner_shape_type;
113
114 using stepper = typename iterable_base::stepper;
115 using const_stepper = typename iterable_base::const_stepper;
116
117 template <layout_type L>
118 using layout_iterator = typename iterable_base::template layout_iterator<L>;
119 template <layout_type L>
120 using const_layout_iterator = typename iterable_base::template const_layout_iterator<L>;
121
122 template <layout_type L>
123 using reverse_layout_iterator = typename iterable_base::template reverse_layout_iterator<L>;
124 template <layout_type L>
125 using const_reverse_layout_iterator = typename iterable_base::template const_reverse_layout_iterator<L>;
126
127 template <class S, layout_type L>
128 using broadcast_iterator = typename iterable_base::template broadcast_iterator<S, L>;
129 template <class S, layout_type L>
130 using const_broadcast_iterator = typename iterable_base::template const_broadcast_iterator<S, L>;
131
132 template <class S, layout_type L>
133 using reverse_broadcast_iterator = typename iterable_base::template reverse_broadcast_iterator<S, L>;
134 template <class S, layout_type L>
135 using const_reverse_broadcast_iterator = typename iterable_base::template const_reverse_broadcast_iterator<S, L>;
136
137 using iterator = value_type*;
138 using const_iterator = const value_type*;
139 using reverse_iterator = std::reverse_iterator<iterator>;
140 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
141
144
145 static constexpr layout_type static_layout = layout_type::any;
146 static constexpr bool contiguous_layout = true;
147
148 xscalar() noexcept;
149 xscalar(CT value) noexcept;
150
151 operator value_type&() noexcept;
152 operator const value_type&() const noexcept;
153
154 size_type size() const noexcept;
155 const shape_type& shape() const noexcept;
156 size_type shape(size_type i) const noexcept;
157 layout_type layout() const noexcept;
158 bool is_contiguous() const noexcept;
161
162 template <class... Args>
163 reference operator()(Args...) noexcept;
164 template <class... Args>
165 reference unchecked(Args...) noexcept;
166
167 template <class... Args>
168 const_reference operator()(Args...) const noexcept;
169 template <class... Args>
170 const_reference unchecked(Args...) const noexcept;
171
172 using accessible_base::at;
173 using accessible_base::operator[];
177 using accessible_base::periodic;
178
179 template <class It>
180 reference element(It, It) noexcept;
181
182 template <class It>
183 const_reference element(It, It) const noexcept;
184
185 xexpression_type& expression() noexcept;
186 const xexpression_type& expression() const noexcept;
187
188 template <class S>
189 bool broadcast_shape(S& shape, bool reuse_cache = false) const noexcept;
190
191 template <class S>
192 bool has_linear_assign(const S& strides) const noexcept;
193
194 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
195 iterator begin() noexcept;
196 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
197 iterator end() noexcept;
198
199 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
200 const_iterator begin() const noexcept;
201 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
202 const_iterator end() const noexcept;
203 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
204 const_iterator cbegin() const noexcept;
205 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
206 const_iterator cend() const noexcept;
207
208 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
209 reverse_iterator rbegin() noexcept;
210 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
211 reverse_iterator rend() noexcept;
212
213 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
214 const_reverse_iterator rbegin() const noexcept;
215 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
216 const_reverse_iterator rend() const noexcept;
217 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
218 const_reverse_iterator crbegin() const noexcept;
219 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
220 const_reverse_iterator crend() const noexcept;
221
222 template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
223 broadcast_iterator<S, L> begin(const S& shape) noexcept;
224 template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
225 broadcast_iterator<S, L> end(const S& shape) noexcept;
226
227 template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
228 const_broadcast_iterator<S, L> begin(const S& shape) const noexcept;
229 template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
230 const_broadcast_iterator<S, L> end(const S& shape) const noexcept;
231 template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
232 const_broadcast_iterator<S, L> cbegin(const S& shape) const noexcept;
233 template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
234 const_broadcast_iterator<S, L> cend(const S& shape) const noexcept;
235
236
237 template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
238 reverse_broadcast_iterator<S, L> rbegin(const S& shape) noexcept;
239 template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
240 reverse_broadcast_iterator<S, L> rend(const S& shape) noexcept;
241
242 template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
243 const_reverse_broadcast_iterator<S, L> rbegin(const S& shape) const noexcept;
244 template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
245 const_reverse_broadcast_iterator<S, L> rend(const S& shape) const noexcept;
246 template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
247 const_reverse_broadcast_iterator<S, L> crbegin(const S& shape) const noexcept;
248 template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
249 const_reverse_broadcast_iterator<S, L> crend(const S& shape) const noexcept;
250
251 iterator linear_begin() noexcept;
252 iterator linear_end() noexcept;
253
254 const_iterator linear_begin() const noexcept;
255 const_iterator linear_end() const noexcept;
256 const_iterator linear_cbegin() const noexcept;
257 const_iterator linear_cend() const noexcept;
258
259 reverse_iterator linear_rbegin() noexcept;
260 reverse_iterator linear_rend() noexcept;
261
262 const_reverse_iterator linear_rbegin() const noexcept;
263 const_reverse_iterator linear_rend() const noexcept;
264 const_reverse_iterator linear_crbegin() const noexcept;
265 const_reverse_iterator linear_crend() const noexcept;
266
267 template <class S>
268 stepper stepper_begin(const S& shape) noexcept;
269 template <class S>
270 stepper stepper_end(const S& shape, layout_type l) noexcept;
271
272 template <class S>
273 const_stepper stepper_begin(const S& shape) const noexcept;
274 template <class S>
275 const_stepper stepper_end(const S& shape, layout_type l) const noexcept;
276
277 dummy_iterator dummy_begin() noexcept;
278 dummy_iterator dummy_end() noexcept;
279
280 const_dummy_iterator dummy_begin() const noexcept;
281 const_dummy_iterator dummy_end() const noexcept;
282
283 reference data_element(size_type i) noexcept;
284 const_reference data_element(size_type i) const noexcept;
285
286 reference flat(size_type i) noexcept;
287 const_reference flat(size_type i) const noexcept;
288
289 template <class align, class simd = simd_value_type>
290 void store_simd(size_type i, const simd& e);
292 xt_simd::simd_return_type<value_type, requested_type> load_simd(size_type i) const;
293
294 private:
295
296 CT m_value;
297
298 friend class xconst_iterable<self_type>;
299 friend class xiterable<self_type>;
300 friend class xaccessible<self_type>;
301 friend class xconst_accessible<self_type>;
302 };
303
304 namespace detail
305 {
306 template <class E>
307 struct is_xscalar_impl : std::false_type
308 {
309 };
310
311 template <class E>
312 struct is_xscalar_impl<xscalar<E>> : std::true_type
313 {
314 };
315 }
316
317 template <class E>
318 using is_xscalar = detail::is_xscalar_impl<E>;
319
320 namespace detail
321 {
322 template <class... E>
323 struct all_xscalar
324 {
325 static constexpr bool value = xtl::conjunction<is_xscalar<std::decay_t<E>>...>::value;
326 };
327 }
328
329 // Note: MSVC bug workaround. Cannot just define
330 // template <class... E>
331 // using all_xscalar = xtl::conjunction<is_xscalar<std::decay_t<E>>...>;
332
333 template <class... E>
334 using all_xscalar = detail::all_xscalar<E...>;
335
336 /******************
337 * xref and xcref *
338 ******************/
339
340 template <class T>
341 xscalar<T&> xref(T& t);
342
343 template <class T>
344 xscalar<const T&> xcref(T& t);
345
346 /*******************
347 * xscalar_stepper *
348 *******************/
349
350 template <bool is_const, class CT>
352 {
353 public:
354
356 using storage_type = std::conditional_t<is_const, const xscalar<CT>, xscalar<CT>>;
357
358 using value_type = typename storage_type::value_type;
359 using reference = std::
360 conditional_t<is_const, typename storage_type::const_reference, typename storage_type::reference>;
361 using pointer = std::conditional_t<is_const, typename storage_type::const_pointer, typename storage_type::pointer>;
362 using size_type = typename storage_type::size_type;
363 using difference_type = typename storage_type::difference_type;
364 using shape_type = typename storage_type::shape_type;
365
366 template <class requested_type>
367 using simd_return_type = xt_simd::simd_return_type<value_type, requested_type>;
368
369 xscalar_stepper(storage_type* c) noexcept;
370
371 reference operator*() const noexcept;
372
373 void step(size_type dim, size_type n = 1) noexcept;
374 void step_back(size_type dim, size_type n = 1) noexcept;
375 void reset(size_type dim) noexcept;
376 void reset_back(size_type dim) noexcept;
377
378 void to_begin() noexcept;
379 void to_end(layout_type l) noexcept;
380
381 template <class T>
382 simd_return_type<T> step_simd();
383
384 void step_leading();
385
386 private:
387
388 storage_type* p_c;
389 };
390
391 /*******************
392 * xdummy_iterator *
393 *******************/
394
395 namespace detail
396 {
397 template <bool is_const, class CT>
398 using dummy_reference_t = std::
399 conditional_t<is_const, typename xscalar<CT>::const_reference, typename xscalar<CT>::reference>;
400
401 template <bool is_const, class CT>
402 using dummy_pointer_t = std::
403 conditional_t<is_const, typename xscalar<CT>::const_pointer, typename xscalar<CT>::pointer>;
404 }
405
406 template <bool is_const, class CT>
407 class xdummy_iterator : public xtl::xrandom_access_iterator_base<
408 xdummy_iterator<is_const, CT>,
409 typename xscalar<CT>::value_type,
410 typename xscalar<CT>::difference_type,
411 detail::dummy_pointer_t<is_const, CT>,
412 detail::dummy_reference_t<is_const, CT>>
413 {
414 public:
415
417 using storage_type = std::conditional_t<is_const, const xscalar<CT>, xscalar<CT>>;
418
419 using value_type = typename storage_type::value_type;
420 using reference = detail::dummy_reference_t<is_const, CT>;
421 using pointer = detail::dummy_pointer_t<is_const, CT>;
422 using difference_type = typename storage_type::difference_type;
423 using iterator_category = std::random_access_iterator_tag;
424
425 explicit xdummy_iterator(storage_type* c) noexcept;
426
427 self_type& operator++() noexcept;
428 self_type& operator--() noexcept;
429
430 self_type& operator+=(difference_type n) noexcept;
431 self_type& operator-=(difference_type n) noexcept;
432
433 difference_type operator-(const self_type& rhs) const noexcept;
434
435 reference operator*() const noexcept;
436
437 bool equal(const self_type& rhs) const noexcept;
438 bool less_than(const self_type& rhs) const noexcept;
439
440 private:
441
442 storage_type* p_c;
443 };
444
445 template <bool is_const, class CT>
446 bool
448
449 template <bool is_const, class CT>
451
452 template <class T>
453 struct is_not_xdummy_iterator : std::true_type
454 {
455 };
456
457 template <bool is_const, class CT>
458 struct is_not_xdummy_iterator<xdummy_iterator<is_const, CT>> : std::false_type
459 {
460 };
461
462 /*****************************
463 * linear_begin / linear_end *
464 *****************************/
465
466 template <class CT>
467 XTENSOR_CONSTEXPR_RETURN auto linear_begin(xscalar<CT>& c) noexcept -> decltype(c.dummy_begin())
468 {
469 return c.dummy_begin();
470 }
471
472 template <class CT>
473 XTENSOR_CONSTEXPR_RETURN auto linear_end(xscalar<CT>& c) noexcept -> decltype(c.dummy_end())
474 {
475 return c.dummy_end();
476 }
477
478 template <class CT>
479 XTENSOR_CONSTEXPR_RETURN auto linear_begin(const xscalar<CT>& c) noexcept -> decltype(c.dummy_begin())
480 {
481 return c.dummy_begin();
482 }
483
484 template <class CT>
485 XTENSOR_CONSTEXPR_RETURN auto linear_end(const xscalar<CT>& c) noexcept -> decltype(c.dummy_end())
486 {
487 return c.dummy_end();
488 }
489
490 /**************************
491 * xscalar implementation *
492 **************************/
493
494 // This constructor will not compile when CT is a reference type.
495 template <class CT>
496 inline xscalar<CT>::xscalar() noexcept
497 : m_value()
498 {
499 }
500
501 template <class CT>
502 inline xscalar<CT>::xscalar(CT value) noexcept
503 : m_value(value)
504 {
505 }
506
507 template <class CT>
508 inline xscalar<CT>::operator value_type&() noexcept
509 {
510 return m_value;
511 }
512
513 template <class CT>
514 inline xscalar<CT>::operator const value_type&() const noexcept
515 {
516 return m_value;
517 }
518
519 template <class CT>
520 inline auto xscalar<CT>::size() const noexcept -> size_type
521 {
522 return 1;
523 }
524
525 template <class CT>
526 inline auto xscalar<CT>::shape() const noexcept -> const shape_type&
527 {
528 static std::array<size_type, 0> zero_shape;
529 return zero_shape;
530 }
531
532 template <class CT>
533 inline auto xscalar<CT>::shape(size_type) const noexcept -> size_type
534 {
535 return 0;
536 }
537
538 template <class CT>
539 inline layout_type xscalar<CT>::layout() const noexcept
540 {
541 return static_layout;
542 }
543
544 template <class CT>
545 inline bool xscalar<CT>::is_contiguous() const noexcept
546 {
547 return true;
548 }
549
550 template <class CT>
551 template <class... Args>
552 inline auto xscalar<CT>::operator()(Args...) noexcept -> reference
553 {
554 XTENSOR_CHECK_DIMENSION((std::array<int, 0>()), Args()...);
555 return m_value;
556 }
557
558 template <class CT>
559 template <class... Args>
560 inline auto xscalar<CT>::unchecked(Args...) noexcept -> reference
561 {
562 return m_value;
563 }
564
565 template <class CT>
566 template <class... Args>
567 inline auto xscalar<CT>::operator()(Args...) const noexcept -> const_reference
568 {
569 XTENSOR_CHECK_DIMENSION((std::array<int, 0>()), Args()...);
570 return m_value;
571 }
572
573 template <class CT>
574 template <class... Args>
575 inline auto xscalar<CT>::unchecked(Args...) const noexcept -> const_reference
576 {
577 return m_value;
578 }
579
580 template <class CT>
581 template <class It>
582 inline auto xscalar<CT>::element(It, It) noexcept -> reference
583 {
584 return m_value;
585 }
586
587 template <class CT>
588 template <class It>
589 inline auto xscalar<CT>::element(It, It) const noexcept -> const_reference
590 {
591 return m_value;
592 }
593
594 template <class CT>
595 inline auto xscalar<CT>::expression() noexcept -> xexpression_type&
596 {
597 return m_value;
598 }
599
600 template <class CT>
601 inline auto xscalar<CT>::expression() const noexcept -> const xexpression_type&
602 {
603 return m_value;
604 }
605
606 template <class CT>
607 template <class S>
608 inline bool xscalar<CT>::broadcast_shape(S&, bool) const noexcept
609 {
610 return true;
611 }
612
613 template <class CT>
614 template <class S>
615 inline bool xscalar<CT>::has_linear_assign(const S&) const noexcept
616 {
617 return true;
618 }
619
620 template <class CT>
621 template <layout_type L>
622 inline auto xscalar<CT>::begin() noexcept -> iterator
623 {
624 return &m_value;
625 }
626
627 template <class CT>
628 template <layout_type L>
629 inline auto xscalar<CT>::end() noexcept -> iterator
630 {
631 return &m_value + 1;
632 }
633
634 template <class CT>
635 template <layout_type L>
636 inline auto xscalar<CT>::begin() const noexcept -> const_iterator
637 {
638 return &m_value;
639 }
640
641 template <class CT>
642 template <layout_type L>
643 inline auto xscalar<CT>::end() const noexcept -> const_iterator
644 {
645 return &m_value + 1;
646 }
647
648 template <class CT>
649 template <layout_type L>
650 inline auto xscalar<CT>::cbegin() const noexcept -> const_iterator
651 {
652 return &m_value;
653 }
654
655 template <class CT>
656 template <layout_type L>
657 inline auto xscalar<CT>::cend() const noexcept -> const_iterator
658 {
659 return &m_value + 1;
660 }
661
662 template <class CT>
663 template <layout_type L>
664 inline auto xscalar<CT>::rbegin() noexcept -> reverse_iterator
665 {
666 return reverse_iterator(end());
667 }
668
669 template <class CT>
670 template <layout_type L>
671 inline auto xscalar<CT>::rend() noexcept -> reverse_iterator
672 {
673 return reverse_iterator(begin());
674 }
675
676 template <class CT>
677 template <layout_type L>
678 inline auto xscalar<CT>::rbegin() const noexcept -> const_reverse_iterator
679 {
680 return crbegin();
681 }
682
683 template <class CT>
684 template <layout_type L>
685 inline auto xscalar<CT>::rend() const noexcept -> const_reverse_iterator
686 {
687 return crend();
688 }
689
690 template <class CT>
691 template <layout_type L>
692 inline auto xscalar<CT>::crbegin() const noexcept -> const_reverse_iterator
693 {
694 return const_reverse_iterator(cend());
695 }
696
697 template <class CT>
698 template <layout_type L>
699 inline auto xscalar<CT>::crend() const noexcept -> const_reverse_iterator
700 {
701 return const_reverse_iterator(cbegin());
702 }
703
704 /*****************************
705 * Broadcasting iterator api *
706 *****************************/
707
708 template <class CT>
709 template <class S, layout_type L>
710 inline auto xscalar<CT>::begin(const S& shape) noexcept -> broadcast_iterator<S, L>
711 {
712 return iterable_base::template begin<S, L>(shape);
713 }
714
715 template <class CT>
716 template <class S, layout_type L>
717 inline auto xscalar<CT>::end(const S& shape) noexcept -> broadcast_iterator<S, L>
718 {
719 return iterable_base::template end<S, L>(shape);
720 }
721
722 template <class CT>
723 template <class S, layout_type L>
724 inline auto xscalar<CT>::begin(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
725 {
726 return iterable_base::template begin<S, L>(shape);
727 }
728
729 template <class CT>
730 template <class S, layout_type L>
731 inline auto xscalar<CT>::end(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
732 {
733 return iterable_base::template end<S, L>(shape);
734 }
735
736 template <class CT>
737 template <class S, layout_type L>
738 inline auto xscalar<CT>::cbegin(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
739 {
740 return iterable_base::template cbegin<S, L>(shape);
741 }
742
743 template <class CT>
744 template <class S, layout_type L>
745 inline auto xscalar<CT>::cend(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
746 {
747 return iterable_base::template cend<S, L>(shape);
748 }
749
750 template <class CT>
751 template <class S, layout_type L>
752 inline auto xscalar<CT>::rbegin(const S& shape) noexcept -> reverse_broadcast_iterator<S, L>
753 {
754 return iterable_base::template rbegin<S, L>(shape);
755 }
756
757 template <class CT>
758 template <class S, layout_type L>
759 inline auto xscalar<CT>::rend(const S& shape) noexcept -> reverse_broadcast_iterator<S, L>
760 {
761 return iterable_base::template rend<S, L>(shape);
762 }
763
764 template <class CT>
765 template <class S, layout_type L>
766 inline auto xscalar<CT>::rbegin(const S& shape) const noexcept -> const_reverse_broadcast_iterator<S, L>
767 {
768 return iterable_base::template rbegin<S, L>(shape);
769 }
770
771 template <class CT>
772 template <class S, layout_type L>
773 inline auto xscalar<CT>::rend(const S& shape) const noexcept -> const_reverse_broadcast_iterator<S, L>
774 {
775 return iterable_base::template rend<S, L>(shape);
776 }
777
778 template <class CT>
779 template <class S, layout_type L>
780 inline auto xscalar<CT>::crbegin(const S& shape) const noexcept -> const_reverse_broadcast_iterator<S, L>
781 {
782 return iterable_base::template crbegin<S, L>(shape);
783 }
784
785 template <class CT>
786 template <class S, layout_type L>
787 inline auto xscalar<CT>::crend(const S& shape) const noexcept -> const_reverse_broadcast_iterator<S, L>
788 {
789 return iterable_base::template crend<S, L>(shape);
790 }
791
792 template <class CT>
793 inline auto xscalar<CT>::linear_begin() noexcept -> iterator
794 {
795 return this->template begin<XTENSOR_DEFAULT_LAYOUT>();
796 }
797
798 template <class CT>
799 inline auto xscalar<CT>::linear_end() noexcept -> iterator
800 {
801 return this->template end<XTENSOR_DEFAULT_LAYOUT>();
802 }
803
804 template <class CT>
805 inline auto xscalar<CT>::linear_begin() const noexcept -> const_iterator
806 {
807 return this->template begin<XTENSOR_DEFAULT_LAYOUT>();
808 }
809
810 template <class CT>
811 inline auto xscalar<CT>::linear_end() const noexcept -> const_iterator
812 {
813 return this->template end<XTENSOR_DEFAULT_LAYOUT>();
814 }
815
816 template <class CT>
817 inline auto xscalar<CT>::linear_cbegin() const noexcept -> const_iterator
818 {
819 return this->template cbegin<XTENSOR_DEFAULT_LAYOUT>();
820 }
821
822 template <class CT>
823 inline auto xscalar<CT>::linear_cend() const noexcept -> const_iterator
824 {
825 return this->template cend<XTENSOR_DEFAULT_LAYOUT>();
826 }
827
828 template <class CT>
829 inline auto xscalar<CT>::linear_rbegin() noexcept -> reverse_iterator
830 {
831 return this->template rbegin<XTENSOR_DEFAULT_LAYOUT>();
832 }
833
834 template <class CT>
835 inline auto xscalar<CT>::linear_rend() noexcept -> reverse_iterator
836 {
837 return this->template rend<XTENSOR_DEFAULT_LAYOUT>();
838 }
839
840 template <class CT>
841 inline auto xscalar<CT>::linear_rbegin() const noexcept -> const_reverse_iterator
842 {
843 return this->template rbegin<XTENSOR_DEFAULT_LAYOUT>();
844 }
845
846 template <class CT>
847 inline auto xscalar<CT>::linear_rend() const noexcept -> const_reverse_iterator
848 {
849 return this->template rend<XTENSOR_DEFAULT_LAYOUT>();
850 }
851
852 template <class CT>
853 inline auto xscalar<CT>::linear_crbegin() const noexcept -> const_reverse_iterator
854 {
855 return this->template crbegin<XTENSOR_DEFAULT_LAYOUT>();
856 }
857
858 template <class CT>
859 inline auto xscalar<CT>::linear_crend() const noexcept -> const_reverse_iterator
860 {
861 return this->template crend<XTENSOR_DEFAULT_LAYOUT>();
862 }
863
864 template <class CT>
865 template <class S>
866 inline auto xscalar<CT>::stepper_begin(const S&) noexcept -> stepper
867 {
868 return stepper(this, false);
869 }
870
871 template <class CT>
872 template <class S>
873 inline auto xscalar<CT>::stepper_end(const S&, layout_type) noexcept -> stepper
874 {
875 return stepper(this);
876 }
877
878 template <class CT>
879 template <class S>
880 inline auto xscalar<CT>::stepper_begin(const S&) const noexcept -> const_stepper
881 {
882 return const_stepper(this);
883 }
884
885 template <class CT>
886 template <class S>
887 inline auto xscalar<CT>::stepper_end(const S&, layout_type) const noexcept -> const_stepper
888 {
889 return const_stepper(this);
890 }
891
892 template <class CT>
893 inline auto xscalar<CT>::dummy_begin() noexcept -> dummy_iterator
894 {
895 return dummy_iterator(this);
896 }
897
898 template <class CT>
899 inline auto xscalar<CT>::dummy_end() noexcept -> dummy_iterator
900 {
901 return dummy_iterator(this);
902 }
903
904 template <class CT>
905 inline auto xscalar<CT>::dummy_begin() const noexcept -> const_dummy_iterator
906 {
907 return const_dummy_iterator(this);
908 }
909
910 template <class CT>
911 inline auto xscalar<CT>::dummy_end() const noexcept -> const_dummy_iterator
912 {
913 return const_dummy_iterator(this);
914 }
915
916 template <class CT>
917 inline auto xscalar<CT>::data_element(size_type) noexcept -> reference
918 {
919 return m_value;
920 }
921
922 template <class CT>
923 inline auto xscalar<CT>::data_element(size_type) const noexcept -> const_reference
924 {
925 return m_value;
926 }
927
928 template <class CT>
929 inline auto xscalar<CT>::flat(size_type) noexcept -> reference
930 {
931 return m_value;
932 }
933
934 template <class CT>
935 inline auto xscalar<CT>::flat(size_type) const noexcept -> const_reference
936 {
937 return m_value;
938 }
939
940 template <class CT>
941 template <class align, class simd>
942 inline void xscalar<CT>::store_simd(size_type, const simd& e)
943 {
944 m_value = static_cast<value_type>(e[0]);
945 }
946
947 template <class CT>
948 template <class align, class requested_type, std::size_t N>
949 inline auto xscalar<CT>::load_simd(size_type) const
950 -> xt_simd::simd_return_type<value_type, requested_type>
951 {
952 return xt_simd::broadcast_as<requested_type>(m_value);
953 }
954
955 template <class T>
956 inline xscalar<T&> xref(T& t)
957 {
958 return xscalar<T&>(t);
959 }
960
961 template <class T>
962 inline xscalar<const T&> xcref(T& t)
963 {
964 return xscalar<const T&>(t);
965 }
966
967 /**********************************
968 * xscalar_stepper implementation *
969 **********************************/
970
971 template <bool is_const, class CT>
972 inline xscalar_stepper<is_const, CT>::xscalar_stepper(storage_type* c) noexcept
973 : p_c(c)
974 {
975 }
976
977 template <bool is_const, class CT>
978 inline auto xscalar_stepper<is_const, CT>::operator*() const noexcept -> reference
979 {
980 return p_c->operator()();
981 }
982
983 template <bool is_const, class CT>
984 inline void xscalar_stepper<is_const, CT>::step(size_type /*dim*/, size_type /*n*/) noexcept
985 {
986 }
987
988 template <bool is_const, class CT>
989 inline void xscalar_stepper<is_const, CT>::step_back(size_type /*dim*/, size_type /*n*/) noexcept
990 {
991 }
992
993 template <bool is_const, class CT>
994 inline void xscalar_stepper<is_const, CT>::reset(size_type /*dim*/) noexcept
995 {
996 }
997
998 template <bool is_const, class CT>
999 inline void xscalar_stepper<is_const, CT>::reset_back(size_type /*dim*/) noexcept
1000 {
1001 }
1002
1003 template <bool is_const, class CT>
1004 inline void xscalar_stepper<is_const, CT>::to_begin() noexcept
1005 {
1006 }
1007
1008 template <bool is_const, class CT>
1009 inline void xscalar_stepper<is_const, CT>::to_end(layout_type /*l*/) noexcept
1010 {
1011 }
1012
1013 template <bool is_const, class CT>
1014 template <class T>
1015 inline auto xscalar_stepper<is_const, CT>::step_simd() -> simd_return_type<T>
1016 {
1017 return simd_return_type<T>(p_c->operator()());
1018 }
1019
1020 template <bool is_const, class CT>
1021 inline void xscalar_stepper<is_const, CT>::step_leading()
1022 {
1023 }
1024
1025 /**********************************
1026 * xdummy_iterator implementation *
1027 **********************************/
1028
1029 template <bool is_const, class CT>
1030 inline xdummy_iterator<is_const, CT>::xdummy_iterator(storage_type* c) noexcept
1031 : p_c(c)
1032 {
1033 }
1034
1035 template <bool is_const, class CT>
1036 inline auto xdummy_iterator<is_const, CT>::operator++() noexcept -> self_type&
1037 {
1038 return *this;
1039 }
1040
1041 template <bool is_const, class CT>
1042 inline auto xdummy_iterator<is_const, CT>::operator--() noexcept -> self_type&
1043 {
1044 return *this;
1045 }
1046
1047 template <bool is_const, class CT>
1048 inline auto xdummy_iterator<is_const, CT>::operator+=(difference_type) noexcept -> self_type&
1049 {
1050 return *this;
1051 }
1052
1053 template <bool is_const, class CT>
1054 inline auto xdummy_iterator<is_const, CT>::operator-=(difference_type) noexcept -> self_type&
1055 {
1056 return *this;
1057 }
1058
1059 template <bool is_const, class CT>
1060 inline auto xdummy_iterator<is_const, CT>::operator-(const self_type&) const noexcept -> difference_type
1061 {
1062 return 0;
1063 }
1064
1065 template <bool is_const, class CT>
1066 inline auto xdummy_iterator<is_const, CT>::operator*() const noexcept -> reference
1067 {
1068 return p_c->operator()();
1069 }
1070
1071 template <bool is_const, class CT>
1072 inline bool xdummy_iterator<is_const, CT>::equal(const self_type& rhs) const noexcept
1073 {
1074 return p_c == rhs.p_c;
1075 }
1076
1077 template <bool is_const, class CT>
1078 inline bool xdummy_iterator<is_const, CT>::less_than(const self_type& rhs) const noexcept
1079 {
1080 return p_c < rhs.p_c;
1081 }
1082
1083 template <bool is_const, class CT>
1084 inline bool
1085 operator==(const xdummy_iterator<is_const, CT>& lhs, const xdummy_iterator<is_const, CT>& rhs) noexcept
1086 {
1087 return lhs.equal(rhs);
1088 }
1089
1090 template <bool is_const, class CT>
1091 inline bool
1092 operator<(const xdummy_iterator<is_const, CT>& lhs, const xdummy_iterator<is_const, CT>& rhs) noexcept
1093 {
1094 return lhs.less_than(rhs);
1095 }
1096}
1097
1098#endif
Base class for implementation of common expression access methods.
reference back()
Returns a reference to the last element of the expression.
reference front()
Returns a reference to the first element of the expression.
Base class for implementation of common expression constant access methods.
size_type dimension() const noexcept
Returns the number of dimensions of the expression.
bool in_bounds(Args... args) const
Returns true only if the the specified position is a valid entry in the expression.
size_type shape(size_type index) const
Returns the i-th dimension of the expression.
Base class for multidimensional iterable constant expressions.
Definition xiterable.hpp:37
Base class for multidimensional iterable expressions.
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
bool operator==(const xaxis_iterator< CT > &lhs, const xaxis_iterator< CT > &rhs)
Checks equality of the iterators.
layout_type
Definition xlayout.hpp:24