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 "../core/xaccessible.hpp"
20#include "../core/xexpression.hpp"
21#include "../core/xiterable.hpp"
22#include "../core/xlayout.hpp"
23#include "../utils/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>
39 {
40 using type = xtensor_empty_base;
41 };
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;
72 using const_stepper = xscalar_stepper<true, CT>;
73 using stepper = xscalar_stepper<false, CT>;
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>;
96 using accessible_base = xaccessible<self_type>;
97 using expression_tag = typename extension_base::expression_tag;
98 using inner_types = xcontainer_inner_types<self_type>;
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>;
108 using bool_load_type = xt::bool_load_type<value_type>;
109
110 using iterable_base = xiterable<self_type>;
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
142 using dummy_iterator = xdummy_iterator<false, CT>;
143 using const_dummy_iterator = xdummy_iterator<true, CT>;
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);
291 template <class align, class requested_type = value_type, std::size_t N = xt_simd::simd_traits<requested_type>::size>
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 template <class E>
321 concept xscalar_concept = is_xscalar<std::decay_t<E>>::value;
322
323 namespace detail
324 {
325 template <class... E>
326 struct all_xscalar
327 {
328 static constexpr bool value = std::conjunction<is_xscalar<std::decay_t<E>>...>::value;
329 };
330 }
331
332 // Note: MSVC bug workaround. Cannot just define
333 // template <class... E>
334 // using all_xscalar = std::conjunction<is_xscalar<std::decay_t<E>>...>;
335
336 template <class... E>
337 using all_xscalar = detail::all_xscalar<E...>;
338
339 /******************
340 * xref and xcref *
341 ******************/
342
343 template <class T>
344 xscalar<T&> xref(T& t);
345
346 template <class T>
347 xscalar<const T&> xcref(T& t);
348
349 /*******************
350 * xscalar_stepper *
351 *******************/
352
353 template <bool is_const, class CT>
354 class xscalar_stepper
355 {
356 public:
357
358 using self_type = xscalar_stepper<is_const, CT>;
359 using storage_type = std::conditional_t<is_const, const xscalar<CT>, xscalar<CT>>;
360
361 using value_type = typename storage_type::value_type;
362 using reference = std::
363 conditional_t<is_const, typename storage_type::const_reference, typename storage_type::reference>;
364 using pointer = std::conditional_t<is_const, typename storage_type::const_pointer, typename storage_type::pointer>;
365 using size_type = typename storage_type::size_type;
366 using difference_type = typename storage_type::difference_type;
367 using shape_type = typename storage_type::shape_type;
368
369 template <class requested_type>
370 using simd_return_type = xt_simd::simd_return_type<value_type, requested_type>;
371
372 xscalar_stepper(storage_type* c) noexcept;
373
374 reference operator*() const noexcept;
375
376 void step(size_type dim, size_type n = 1) noexcept;
377 void step_back(size_type dim, size_type n = 1) noexcept;
378 void reset(size_type dim) noexcept;
379 void reset_back(size_type dim) noexcept;
380
381 void to_begin() noexcept;
382 void to_end(layout_type l) noexcept;
383
384 template <class T>
385 simd_return_type<T> step_simd();
386
387 void step_leading();
388
389 private:
390
391 storage_type* p_c;
392 };
393
394 /*******************
395 * xdummy_iterator *
396 *******************/
397
398 namespace detail
399 {
400 template <bool is_const, class CT>
401 using dummy_reference_t = std::
402 conditional_t<is_const, typename xscalar<CT>::const_reference, typename xscalar<CT>::reference>;
403
404 template <bool is_const, class CT>
405 using dummy_pointer_t = std::
406 conditional_t<is_const, typename xscalar<CT>::const_pointer, typename xscalar<CT>::pointer>;
407 }
408
409 template <bool is_const, class CT>
410 class xdummy_iterator : public xtl::xrandom_access_iterator_base<
411 xdummy_iterator<is_const, CT>,
412 typename xscalar<CT>::value_type,
413 typename xscalar<CT>::difference_type,
414 detail::dummy_pointer_t<is_const, CT>,
415 detail::dummy_reference_t<is_const, CT>>
416 {
417 public:
418
419 using self_type = xdummy_iterator<is_const, CT>;
420 using storage_type = std::conditional_t<is_const, const xscalar<CT>, xscalar<CT>>;
421
422 using value_type = typename storage_type::value_type;
423 using reference = detail::dummy_reference_t<is_const, CT>;
424 using pointer = detail::dummy_pointer_t<is_const, CT>;
425 using difference_type = typename storage_type::difference_type;
426 using iterator_category = std::random_access_iterator_tag;
427
428 explicit xdummy_iterator(storage_type* c) noexcept;
429
430 self_type& operator++() noexcept;
431 self_type& operator--() noexcept;
432
433 self_type& operator+=(difference_type n) noexcept;
434 self_type& operator-=(difference_type n) noexcept;
435
436 difference_type operator-(const self_type& rhs) const noexcept;
437
438 reference operator*() const noexcept;
439
440 bool equal(const self_type& rhs) const noexcept;
441 bool less_than(const self_type& rhs) const noexcept;
442
443 private:
444
445 storage_type* p_c;
446 };
447
448 template <bool is_const, class CT>
449 bool
450 operator==(const xdummy_iterator<is_const, CT>& lhs, const xdummy_iterator<is_const, CT>& rhs) noexcept;
451
452 template <bool is_const, class CT>
453 bool operator<(const xdummy_iterator<is_const, CT>& lhs, const xdummy_iterator<is_const, CT>& rhs) noexcept;
454
455 template <class T>
456 struct is_not_xdummy_iterator : std::true_type
457 {
458 };
459
460 template <bool is_const, class CT>
461 struct is_not_xdummy_iterator<xdummy_iterator<is_const, CT>> : std::false_type
462 {
463 };
464
465 /*****************************
466 * linear_begin / linear_end *
467 *****************************/
468
469 template <class CT>
470 XTENSOR_CONSTEXPR_RETURN auto linear_begin(xscalar<CT>& c) noexcept -> decltype(c.dummy_begin())
471 {
472 return c.dummy_begin();
473 }
474
475 template <class CT>
476 XTENSOR_CONSTEXPR_RETURN auto linear_end(xscalar<CT>& c) noexcept -> decltype(c.dummy_end())
477 {
478 return c.dummy_end();
479 }
480
481 template <class CT>
482 XTENSOR_CONSTEXPR_RETURN auto linear_begin(const xscalar<CT>& c) noexcept -> decltype(c.dummy_begin())
483 {
484 return c.dummy_begin();
485 }
486
487 template <class CT>
488 XTENSOR_CONSTEXPR_RETURN auto linear_end(const xscalar<CT>& c) noexcept -> decltype(c.dummy_end())
489 {
490 return c.dummy_end();
491 }
492
493 /**************************
494 * xscalar implementation *
495 **************************/
496
497 // This constructor will not compile when CT is a reference type.
498 template <class CT>
499 inline xscalar<CT>::xscalar() noexcept
500 : m_value()
501 {
502 }
503
504 template <class CT>
505 inline xscalar<CT>::xscalar(CT value) noexcept
506 : m_value(value)
507 {
508 }
509
510 template <class CT>
511 inline xscalar<CT>::operator value_type&() noexcept
512 {
513 return m_value;
514 }
515
516 template <class CT>
517 inline xscalar<CT>::operator const value_type&() const noexcept
518 {
519 return m_value;
520 }
521
522 template <class CT>
523 inline auto xscalar<CT>::size() const noexcept -> size_type
524 {
525 return 1;
526 }
527
528 template <class CT>
529 inline auto xscalar<CT>::shape() const noexcept -> const shape_type&
530 {
531 static std::array<size_type, 0> zero_shape;
532 return zero_shape;
533 }
534
535 template <class CT>
536 inline auto xscalar<CT>::shape(size_type) const noexcept -> size_type
537 {
538 return 0;
539 }
540
541 template <class CT>
542 inline layout_type xscalar<CT>::layout() const noexcept
543 {
544 return static_layout;
545 }
546
547 template <class CT>
548 inline bool xscalar<CT>::is_contiguous() const noexcept
549 {
550 return true;
551 }
552
553 template <class CT>
554 template <class... Args>
555 inline auto xscalar<CT>::operator()(Args...) noexcept -> reference
556 {
557 XTENSOR_CHECK_DIMENSION((std::array<int, 0>()), Args()...);
558 return m_value;
559 }
560
561 template <class CT>
562 template <class... Args>
563 inline auto xscalar<CT>::unchecked(Args...) noexcept -> reference
564 {
565 return m_value;
566 }
567
568 template <class CT>
569 template <class... Args>
570 inline auto xscalar<CT>::operator()(Args...) const noexcept -> const_reference
571 {
572 XTENSOR_CHECK_DIMENSION((std::array<int, 0>()), Args()...);
573 return m_value;
574 }
575
576 template <class CT>
577 template <class... Args>
578 inline auto xscalar<CT>::unchecked(Args...) const noexcept -> const_reference
579 {
580 return m_value;
581 }
582
583 template <class CT>
584 template <class It>
585 inline auto xscalar<CT>::element(It, It) noexcept -> reference
586 {
587 return m_value;
588 }
589
590 template <class CT>
591 template <class It>
592 inline auto xscalar<CT>::element(It, It) const noexcept -> const_reference
593 {
594 return m_value;
595 }
596
597 template <class CT>
598 inline auto xscalar<CT>::expression() noexcept -> xexpression_type&
599 {
600 return m_value;
601 }
602
603 template <class CT>
604 inline auto xscalar<CT>::expression() const noexcept -> const xexpression_type&
605 {
606 return m_value;
607 }
608
609 template <class CT>
610 template <class S>
611 inline bool xscalar<CT>::broadcast_shape(S&, bool) const noexcept
612 {
613 return true;
614 }
615
616 template <class CT>
617 template <class S>
618 inline bool xscalar<CT>::has_linear_assign(const S&) const noexcept
619 {
620 return true;
621 }
622
623 template <class CT>
624 template <layout_type L>
625 inline auto xscalar<CT>::begin() noexcept -> iterator
626 {
627 return &m_value;
628 }
629
630 template <class CT>
631 template <layout_type L>
632 inline auto xscalar<CT>::end() noexcept -> iterator
633 {
634 return &m_value + 1;
635 }
636
637 template <class CT>
638 template <layout_type L>
639 inline auto xscalar<CT>::begin() const noexcept -> const_iterator
640 {
641 return &m_value;
642 }
643
644 template <class CT>
645 template <layout_type L>
646 inline auto xscalar<CT>::end() const noexcept -> const_iterator
647 {
648 return &m_value + 1;
649 }
650
651 template <class CT>
652 template <layout_type L>
653 inline auto xscalar<CT>::cbegin() const noexcept -> const_iterator
654 {
655 return &m_value;
656 }
657
658 template <class CT>
659 template <layout_type L>
660 inline auto xscalar<CT>::cend() const noexcept -> const_iterator
661 {
662 return &m_value + 1;
663 }
664
665 template <class CT>
666 template <layout_type L>
667 inline auto xscalar<CT>::rbegin() noexcept -> reverse_iterator
668 {
669 return reverse_iterator(end());
670 }
671
672 template <class CT>
673 template <layout_type L>
674 inline auto xscalar<CT>::rend() noexcept -> reverse_iterator
675 {
676 return reverse_iterator(begin());
677 }
678
679 template <class CT>
680 template <layout_type L>
681 inline auto xscalar<CT>::rbegin() const noexcept -> const_reverse_iterator
682 {
683 return crbegin();
684 }
685
686 template <class CT>
687 template <layout_type L>
688 inline auto xscalar<CT>::rend() const noexcept -> const_reverse_iterator
689 {
690 return crend();
691 }
692
693 template <class CT>
694 template <layout_type L>
695 inline auto xscalar<CT>::crbegin() const noexcept -> const_reverse_iterator
696 {
697 return const_reverse_iterator(cend());
698 }
699
700 template <class CT>
701 template <layout_type L>
702 inline auto xscalar<CT>::crend() const noexcept -> const_reverse_iterator
703 {
704 return const_reverse_iterator(cbegin());
705 }
706
707 /*****************************
708 * Broadcasting iterator api *
709 *****************************/
710
711 template <class CT>
712 template <class S, layout_type L>
713 inline auto xscalar<CT>::begin(const S& shape) noexcept -> broadcast_iterator<S, L>
714 {
715 return iterable_base::template begin<S, L>(shape);
716 }
717
718 template <class CT>
719 template <class S, layout_type L>
720 inline auto xscalar<CT>::end(const S& shape) noexcept -> broadcast_iterator<S, L>
721 {
722 return iterable_base::template end<S, L>(shape);
723 }
724
725 template <class CT>
726 template <class S, layout_type L>
727 inline auto xscalar<CT>::begin(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
728 {
729 return iterable_base::template begin<S, L>(shape);
730 }
731
732 template <class CT>
733 template <class S, layout_type L>
734 inline auto xscalar<CT>::end(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
735 {
736 return iterable_base::template end<S, L>(shape);
737 }
738
739 template <class CT>
740 template <class S, layout_type L>
741 inline auto xscalar<CT>::cbegin(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
742 {
743 return iterable_base::template cbegin<S, L>(shape);
744 }
745
746 template <class CT>
747 template <class S, layout_type L>
748 inline auto xscalar<CT>::cend(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
749 {
750 return iterable_base::template cend<S, L>(shape);
751 }
752
753 template <class CT>
754 template <class S, layout_type L>
755 inline auto xscalar<CT>::rbegin(const S& shape) noexcept -> reverse_broadcast_iterator<S, L>
756 {
757 return iterable_base::template rbegin<S, L>(shape);
758 }
759
760 template <class CT>
761 template <class S, layout_type L>
762 inline auto xscalar<CT>::rend(const S& shape) noexcept -> reverse_broadcast_iterator<S, L>
763 {
764 return iterable_base::template rend<S, L>(shape);
765 }
766
767 template <class CT>
768 template <class S, layout_type L>
769 inline auto xscalar<CT>::rbegin(const S& shape) const noexcept -> const_reverse_broadcast_iterator<S, L>
770 {
771 return iterable_base::template rbegin<S, L>(shape);
772 }
773
774 template <class CT>
775 template <class S, layout_type L>
776 inline auto xscalar<CT>::rend(const S& shape) const noexcept -> const_reverse_broadcast_iterator<S, L>
777 {
778 return iterable_base::template rend<S, L>(shape);
779 }
780
781 template <class CT>
782 template <class S, layout_type L>
783 inline auto xscalar<CT>::crbegin(const S& shape) const noexcept -> const_reverse_broadcast_iterator<S, L>
784 {
785 return iterable_base::template crbegin<S, L>(shape);
786 }
787
788 template <class CT>
789 template <class S, layout_type L>
790 inline auto xscalar<CT>::crend(const S& shape) const noexcept -> const_reverse_broadcast_iterator<S, L>
791 {
792 return iterable_base::template crend<S, L>(shape);
793 }
794
795 template <class CT>
796 inline auto xscalar<CT>::linear_begin() noexcept -> iterator
797 {
798 return this->template begin<XTENSOR_DEFAULT_LAYOUT>();
799 }
800
801 template <class CT>
802 inline auto xscalar<CT>::linear_end() noexcept -> iterator
803 {
804 return this->template end<XTENSOR_DEFAULT_LAYOUT>();
805 }
806
807 template <class CT>
808 inline auto xscalar<CT>::linear_begin() const noexcept -> const_iterator
809 {
810 return this->template begin<XTENSOR_DEFAULT_LAYOUT>();
811 }
812
813 template <class CT>
814 inline auto xscalar<CT>::linear_end() const noexcept -> const_iterator
815 {
816 return this->template end<XTENSOR_DEFAULT_LAYOUT>();
817 }
818
819 template <class CT>
820 inline auto xscalar<CT>::linear_cbegin() const noexcept -> const_iterator
821 {
822 return this->template cbegin<XTENSOR_DEFAULT_LAYOUT>();
823 }
824
825 template <class CT>
826 inline auto xscalar<CT>::linear_cend() const noexcept -> const_iterator
827 {
828 return this->template cend<XTENSOR_DEFAULT_LAYOUT>();
829 }
830
831 template <class CT>
832 inline auto xscalar<CT>::linear_rbegin() noexcept -> reverse_iterator
833 {
834 return this->template rbegin<XTENSOR_DEFAULT_LAYOUT>();
835 }
836
837 template <class CT>
838 inline auto xscalar<CT>::linear_rend() noexcept -> reverse_iterator
839 {
840 return this->template rend<XTENSOR_DEFAULT_LAYOUT>();
841 }
842
843 template <class CT>
844 inline auto xscalar<CT>::linear_rbegin() const noexcept -> const_reverse_iterator
845 {
846 return this->template rbegin<XTENSOR_DEFAULT_LAYOUT>();
847 }
848
849 template <class CT>
850 inline auto xscalar<CT>::linear_rend() const noexcept -> const_reverse_iterator
851 {
852 return this->template rend<XTENSOR_DEFAULT_LAYOUT>();
853 }
854
855 template <class CT>
856 inline auto xscalar<CT>::linear_crbegin() const noexcept -> const_reverse_iterator
857 {
858 return this->template crbegin<XTENSOR_DEFAULT_LAYOUT>();
859 }
860
861 template <class CT>
862 inline auto xscalar<CT>::linear_crend() const noexcept -> const_reverse_iterator
863 {
864 return this->template crend<XTENSOR_DEFAULT_LAYOUT>();
865 }
866
867 template <class CT>
868 template <class S>
869 inline auto xscalar<CT>::stepper_begin(const S&) noexcept -> stepper
870 {
871 return stepper(this, false);
872 }
873
874 template <class CT>
875 template <class S>
876 inline auto xscalar<CT>::stepper_end(const S&, layout_type) noexcept -> stepper
877 {
878 return stepper(this);
879 }
880
881 template <class CT>
882 template <class S>
883 inline auto xscalar<CT>::stepper_begin(const S&) const noexcept -> const_stepper
884 {
885 return const_stepper(this);
886 }
887
888 template <class CT>
889 template <class S>
890 inline auto xscalar<CT>::stepper_end(const S&, layout_type) const noexcept -> const_stepper
891 {
892 return const_stepper(this);
893 }
894
895 template <class CT>
896 inline auto xscalar<CT>::dummy_begin() noexcept -> dummy_iterator
897 {
898 return dummy_iterator(this);
899 }
900
901 template <class CT>
902 inline auto xscalar<CT>::dummy_end() noexcept -> dummy_iterator
903 {
904 return dummy_iterator(this);
905 }
906
907 template <class CT>
908 inline auto xscalar<CT>::dummy_begin() const noexcept -> const_dummy_iterator
909 {
910 return const_dummy_iterator(this);
911 }
912
913 template <class CT>
914 inline auto xscalar<CT>::dummy_end() const noexcept -> const_dummy_iterator
915 {
916 return const_dummy_iterator(this);
917 }
918
919 template <class CT>
920 inline auto xscalar<CT>::data_element(size_type) noexcept -> reference
921 {
922 return m_value;
923 }
924
925 template <class CT>
926 inline auto xscalar<CT>::data_element(size_type) const noexcept -> const_reference
927 {
928 return m_value;
929 }
930
931 template <class CT>
932 inline auto xscalar<CT>::flat(size_type) noexcept -> reference
933 {
934 return m_value;
935 }
936
937 template <class CT>
938 inline auto xscalar<CT>::flat(size_type) const noexcept -> const_reference
939 {
940 return m_value;
941 }
942
943 template <class CT>
944 template <class align, class simd>
945 inline void xscalar<CT>::store_simd(size_type, const simd& e)
946 {
947 m_value = static_cast<value_type>(e[0]);
948 }
949
950 template <class CT>
951 template <class align, class requested_type, std::size_t N>
952 inline auto xscalar<CT>::load_simd(size_type) const
953 -> xt_simd::simd_return_type<value_type, requested_type>
954 {
955 return xt_simd::broadcast_as<requested_type>(m_value);
956 }
957
958 template <class T>
959 inline xscalar<T&> xref(T& t)
960 {
961 return xscalar<T&>(t);
962 }
963
964 template <class T>
965 inline xscalar<const T&> xcref(T& t)
966 {
967 return xscalar<const T&>(t);
968 }
969
970 /**********************************
971 * xscalar_stepper implementation *
972 **********************************/
973
974 template <bool is_const, class CT>
975 inline xscalar_stepper<is_const, CT>::xscalar_stepper(storage_type* c) noexcept
976 : p_c(c)
977 {
978 }
979
980 template <bool is_const, class CT>
981 inline auto xscalar_stepper<is_const, CT>::operator*() const noexcept -> reference
982 {
983 return p_c->operator()();
984 }
985
986 template <bool is_const, class CT>
987 inline void xscalar_stepper<is_const, CT>::step(size_type /*dim*/, size_type /*n*/) noexcept
988 {
989 }
990
991 template <bool is_const, class CT>
992 inline void xscalar_stepper<is_const, CT>::step_back(size_type /*dim*/, size_type /*n*/) noexcept
993 {
994 }
995
996 template <bool is_const, class CT>
997 inline void xscalar_stepper<is_const, CT>::reset(size_type /*dim*/) noexcept
998 {
999 }
1000
1001 template <bool is_const, class CT>
1002 inline void xscalar_stepper<is_const, CT>::reset_back(size_type /*dim*/) noexcept
1003 {
1004 }
1005
1006 template <bool is_const, class CT>
1007 inline void xscalar_stepper<is_const, CT>::to_begin() noexcept
1008 {
1009 }
1010
1011 template <bool is_const, class CT>
1012 inline void xscalar_stepper<is_const, CT>::to_end(layout_type /*l*/) noexcept
1013 {
1014 }
1015
1016 template <bool is_const, class CT>
1017 template <class T>
1018 inline auto xscalar_stepper<is_const, CT>::step_simd() -> simd_return_type<T>
1019 {
1020 return simd_return_type<T>(p_c->operator()());
1021 }
1022
1023 template <bool is_const, class CT>
1024 inline void xscalar_stepper<is_const, CT>::step_leading()
1025 {
1026 }
1027
1028 /**********************************
1029 * xdummy_iterator implementation *
1030 **********************************/
1031
1032 template <bool is_const, class CT>
1033 inline xdummy_iterator<is_const, CT>::xdummy_iterator(storage_type* c) noexcept
1034 : p_c(c)
1035 {
1036 }
1037
1038 template <bool is_const, class CT>
1039 inline auto xdummy_iterator<is_const, CT>::operator++() noexcept -> self_type&
1040 {
1041 return *this;
1042 }
1043
1044 template <bool is_const, class CT>
1045 inline auto xdummy_iterator<is_const, CT>::operator--() noexcept -> self_type&
1046 {
1047 return *this;
1048 }
1049
1050 template <bool is_const, class CT>
1051 inline auto xdummy_iterator<is_const, CT>::operator+=(difference_type) noexcept -> self_type&
1052 {
1053 return *this;
1054 }
1055
1056 template <bool is_const, class CT>
1057 inline auto xdummy_iterator<is_const, CT>::operator-=(difference_type) noexcept -> self_type&
1058 {
1059 return *this;
1060 }
1061
1062 template <bool is_const, class CT>
1063 inline auto xdummy_iterator<is_const, CT>::operator-(const self_type&) const noexcept -> difference_type
1064 {
1065 return 0;
1066 }
1067
1068 template <bool is_const, class CT>
1069 inline auto xdummy_iterator<is_const, CT>::operator*() const noexcept -> reference
1070 {
1071 return p_c->operator()();
1072 }
1073
1074 template <bool is_const, class CT>
1075 inline bool xdummy_iterator<is_const, CT>::equal(const self_type& rhs) const noexcept
1076 {
1077 return p_c == rhs.p_c;
1078 }
1079
1080 template <bool is_const, class CT>
1081 inline bool xdummy_iterator<is_const, CT>::less_than(const self_type& rhs) const noexcept
1082 {
1083 return p_c < rhs.p_c;
1084 }
1085
1086 template <bool is_const, class CT>
1087 inline bool
1088 operator==(const xdummy_iterator<is_const, CT>& lhs, const xdummy_iterator<is_const, CT>& rhs) noexcept
1089 {
1090 return lhs.equal(rhs);
1091 }
1092
1093 template <bool is_const, class CT>
1094 inline bool
1095 operator<(const xdummy_iterator<is_const, CT>& lhs, const xdummy_iterator<is_const, CT>& rhs) noexcept
1096 {
1097 return lhs.less_than(rhs);
1098 }
1099}
1100
1101#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:248
standard mathematical functions for xexpressions
layout_type
Definition xlayout.hpp:24