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