xtensor
 
Loading...
Searching...
No Matches
xfixed.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_FIXED_HPP
11#define XTENSOR_FIXED_HPP
12
13#include <algorithm>
14#include <array>
15#include <cstddef>
16#include <utility>
17
18#include <xtl/xsequence.hpp>
19
20#include "../containers/xcontainer.hpp"
21#include "../containers/xstorage.hpp"
22#include "../core/xsemantic.hpp"
23#include "../core/xstrides.hpp"
24#include "../core/xtensor_config.hpp"
25
26namespace xtl
27{
28 namespace detail
29 {
30 template <class T, std::size_t N>
31 struct sequence_builder<xt::const_array<T, N>>
32 {
33 using sequence_type = xt::const_array<T, N>;
34 using value_type = typename sequence_type::value_type;
35 using size_type = typename sequence_type::size_type;
36
37 inline static sequence_type make(size_type /*size*/, value_type /*v*/)
38 {
39 return sequence_type();
40 }
41 };
42 }
43}
44
45namespace xt
46{
47
48 /**********************
49 * xfixed declaration *
50 **********************/
51
52 template <class ET, class S, layout_type L, bool SH, class Tag>
53 class xfixed_container;
54
55 namespace detail
56 {
57 /**************************************************************************************
58 The following is something we can currently only dream about -- for when we drop
59 support for a lot of the old compilers (e.g. GCC 4.9, MSVC 2017 ;)
60
61 template <class T>
62 constexpr std::size_t calculate_stride(T& shape, std::size_t idx, layout_type L)
63 {
64 if (shape[idx] == 1)
65 {
66 return std::size_t(0);
67 }
68
69 std::size_t data_size = 1;
70 std::size_t stride = 1;
71 if (L == layout_type::row_major)
72 {
73 // because we have a integer sequence that counts
74 // from 0 to sz - 1, we need to "invert" idx here
75 idx = shape.size() - idx;
76 for (std::size_t i = idx; i != 0; --i)
77 {
78 stride = data_size;
79 data_size = stride * shape[i - 1];
80 }
81 }
82 else
83 {
84 for (std::size_t i = 0; i < idx + 1; ++i)
85 {
86 stride = data_size;
87 data_size = stride * shape[i];
88 }
89 }
90 return stride;
91 }
92
93 *****************************************************************************************/
94
95 template <layout_type L, std::size_t I, std::size_t... X>
96 struct calculate_stride;
97
98 template <std::size_t I, std::size_t Y, std::size_t... X>
99 struct calculate_stride<layout_type::column_major, I, Y, X...>
100 {
101 static constexpr std::ptrdiff_t value = Y
102 * calculate_stride<layout_type::column_major, I - 1, X...>::value;
103 };
104
105 template <std::size_t Y, std::size_t... X>
106 struct calculate_stride<layout_type::column_major, 0, Y, X...>
107 {
108 static constexpr std::ptrdiff_t value = 1;
109 };
110
111 template <std::size_t I, std::size_t... X>
112 struct calculate_stride_row_major
113 {
114 static constexpr std::ptrdiff_t value = at<sizeof...(X) - I, X...>::value
115 * calculate_stride_row_major<I - 1, X...>::value;
116 };
117
118 template <std::size_t... X>
119 struct calculate_stride_row_major<0, X...>
120 {
121 static constexpr std::ptrdiff_t value = 1;
122 };
123
124 template <std::size_t I, std::size_t... X>
125 struct calculate_stride<layout_type::row_major, I, X...>
126 {
127 static constexpr std::ptrdiff_t value = calculate_stride_row_major<sizeof...(X) - I - 1, X...>::value;
128 };
129
130 namespace workaround
131 {
132 template <layout_type L, size_t I, class SEQ>
133 struct computed_strides;
134
135 template <layout_type L, size_t I, size_t... X>
136 struct computed_strides<L, I, std::index_sequence<X...>>
137 {
138 static constexpr std::ptrdiff_t value = calculate_stride<L, I, X...>::value;
139 };
140
141 template <layout_type L, size_t I, class SEQ>
142 constexpr std::ptrdiff_t get_computed_strides(bool cond)
143 {
144 return cond ? 0 : computed_strides<L, I, SEQ>::value;
145 }
146 }
147
148 template <layout_type L, class R, std::size_t... X, std::size_t... I>
149 constexpr R get_strides_impl(const xt::fixed_shape<X...>& shape, std::index_sequence<I...>)
150 {
151 static_assert(
153 "Layout not supported for fixed array"
154 );
155#if (_MSC_VER >= 1910)
156 using temp_type = std::index_sequence<X...>;
157 return R({workaround::get_computed_strides<L, I, temp_type>(shape[I] == 1)...});
158#else
159 return R({shape[I] == 1 ? 0 : calculate_stride<L, I, X...>::value...});
160#endif
161 }
162
163 template <class S, class T, std::size_t... I>
164 constexpr T get_backstrides_impl(const S& shape, const T& strides, std::index_sequence<I...>)
165 {
166 return T({(strides[I] * std::ptrdiff_t(shape[I] - 1))...});
167 }
168
169 template <std::size_t... X>
170 struct fixed_compute_size_impl;
171
172 template <std::size_t Y, std::size_t... X>
173 struct fixed_compute_size_impl<Y, X...>
174 {
175 static constexpr std::size_t value = Y * fixed_compute_size_impl<X...>::value;
176 };
177
178 template <std::size_t X>
179 struct fixed_compute_size_impl<X>
180 {
181 static constexpr std::size_t value = X;
182 };
183
184 template <>
185 struct fixed_compute_size_impl<>
186 {
187 // support for 0D xtensor fixed (empty shape = xshape<>)
188 static constexpr std::size_t value = 1;
189 };
190
191 // TODO unify with constexpr compute_size when dropping MSVC 2015
192 template <class T>
193 struct fixed_compute_size;
194
195 template <std::size_t... X>
196 struct fixed_compute_size<xt::fixed_shape<X...>>
197 {
198 static constexpr std::size_t value = fixed_compute_size_impl<X...>::value;
199 };
200
201 template <class V, std::size_t... X>
202 struct get_init_type_impl;
203
204 template <class V, std::size_t Y>
205 struct get_init_type_impl<V, Y>
206 {
207 using type = V[Y];
208 };
209
210 template <class V>
211 struct get_init_type_impl<V>
212 {
213 using type = V[1];
214 };
215
216 template <class V, std::size_t Y, std::size_t... X>
217 struct get_init_type_impl<V, Y, X...>
218 {
219 using tmp_type = typename get_init_type_impl<V, X...>::type;
220 using type = tmp_type[Y];
221 };
222 }
223
224 template <layout_type L, class R, std::size_t... X>
225 constexpr R get_strides(const fixed_shape<X...>& shape) noexcept
226 {
227 return detail::get_strides_impl<L, R>(shape, std::make_index_sequence<sizeof...(X)>{});
228 }
229
230 template <class S, class T>
231 constexpr T get_backstrides(const S& shape, const T& strides) noexcept
232 {
233 return detail::get_backstrides_impl(shape, strides, std::make_index_sequence<std::tuple_size<T>::value>{});
234 }
235
236 template <class V, class S>
238
239 template <class V, std::size_t... X>
240 struct get_init_type<V, fixed_shape<X...>>
241 {
242 using type = typename detail::get_init_type_impl<V, X...>::type;
243 };
244
245 template <class V, class S>
246 using get_init_type_t = typename get_init_type<V, S>::type;
247
248 template <class ET, class S, layout_type L, bool SH, class Tag>
249 struct xcontainer_inner_types<xfixed_container<ET, S, L, SH, Tag>>
250 {
251 using shape_type = S;
252 using inner_shape_type = typename S::cast_type;
253 using strides_type = get_strides_t<inner_shape_type>;
254 using inner_strides_type = strides_type;
255 using backstrides_type = inner_strides_type;
256 using inner_backstrides_type = backstrides_type;
257
258 // NOTE: 0D (S::size() == 0) results in storage for 1 element (scalar)
260
261 using reference = typename storage_type::reference;
262 using const_reference = typename storage_type::const_reference;
263 using size_type = typename storage_type::size_type;
264 using temporary_type = xfixed_container<ET, S, L, SH, Tag>;
265 static constexpr layout_type layout = L;
266 };
267
268 template <class ET, class S, layout_type L, bool SH, class Tag>
269 struct xiterable_inner_types<xfixed_container<ET, S, L, SH, Tag>>
270 : xcontainer_iterable_types<xfixed_container<ET, S, L, SH, Tag>>
271 {
272 };
273
289 template <class ET, class S, layout_type L, bool SH, class Tag>
290 class xfixed_container : public xcontainer<xfixed_container<ET, S, L, SH, Tag>>,
291 public xcontainer_semantic<xfixed_container<ET, S, L, SH, Tag>>
292 {
293 public:
294
295 using self_type = xfixed_container<ET, S, L, SH, Tag>;
296 using base_type = xcontainer<self_type>;
297 using semantic_base = xcontainer_semantic<self_type>;
298
299 using storage_type = typename base_type::storage_type;
300 using value_type = typename base_type::value_type;
301 using reference = typename base_type::reference;
302 using const_reference = typename base_type::const_reference;
303 using pointer = typename base_type::pointer;
304 using const_pointer = typename base_type::const_pointer;
305 using shape_type = typename base_type::shape_type;
306 using inner_shape_type = typename base_type::inner_shape_type;
307 using strides_type = typename base_type::strides_type;
308 using backstrides_type = typename base_type::backstrides_type;
309 using inner_backstrides_type = typename base_type::inner_backstrides_type;
310 using inner_strides_type = typename base_type::inner_strides_type;
311 using temporary_type = typename semantic_base::temporary_type;
312 using expression_tag = Tag;
313
314 static constexpr std::size_t N = std::tuple_size<shape_type>::value;
315 static constexpr std::size_t rank = N;
316
317 xfixed_container() = default;
318 xfixed_container(const value_type& v);
319 explicit xfixed_container(const inner_shape_type& shape, layout_type l = L);
320 explicit xfixed_container(const inner_shape_type& shape, value_type v, layout_type l = L);
321
322 template <class IX = std::integral_constant<std::size_t, N>>
323 xfixed_container(nested_initializer_list_t<value_type, N> t)
324 requires(IX::value != 0);
325
326 ~xfixed_container() = default;
327
328 xfixed_container(const xfixed_container&) = default;
329 xfixed_container& operator=(const xfixed_container&) = default;
330
331 xfixed_container(xfixed_container&&) = default;
332 xfixed_container& operator=(xfixed_container&&) = default;
333
334 template <class E>
336
337 template <class E>
338 xfixed_container& operator=(const xexpression<E>& e);
339
340 template <class ST = std::array<std::size_t, N>>
341 static xfixed_container from_shape(ST&& /*s*/);
342
343 template <class ST = std::array<std::size_t, N>>
344 void resize(ST&& shape, bool force = false) const;
345 template <class ST = shape_type>
346 void resize(ST&& shape, layout_type l) const;
347 template <class ST = shape_type>
348 void resize(ST&& shape, const strides_type& strides) const;
349
350 template <class ST = std::array<std::size_t, N>>
351 const auto& reshape(ST&& shape, layout_type layout = L) const;
352
353 template <class ST>
354 bool broadcast_shape(ST& s, bool reuse_cache = false) const;
355
356 constexpr layout_type layout() const noexcept;
357 bool is_contiguous() const noexcept;
358
359 private:
360
361 storage_type m_storage;
362
363 XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_shape_type m_shape = S();
364 XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_strides_type m_strides = get_strides<L, inner_strides_type>(S());
365 XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_backstrides_type
366 m_backstrides = get_backstrides(m_shape, m_strides);
367
368 storage_type& storage_impl() noexcept;
369 const storage_type& storage_impl() const noexcept;
370
371 constexpr const inner_shape_type& shape_impl() const noexcept;
372 constexpr const inner_strides_type& strides_impl() const noexcept;
373 constexpr const inner_backstrides_type& backstrides_impl() const noexcept;
374
375 friend class xcontainer<xfixed_container<ET, S, L, SH, Tag>>;
376 };
377
378 /****************************************
379 * xfixed_container_adaptor declaration *
380 ****************************************/
381
382 template <class EC, class S, layout_type L, bool SH, class Tag>
383 class xfixed_adaptor;
384
385 template <class EC, class S, layout_type L, bool SH, class Tag>
386 struct xcontainer_inner_types<xfixed_adaptor<EC, S, L, SH, Tag>>
387 {
388 using storage_type = std::remove_reference_t<EC>;
389 using reference = typename storage_type::reference;
390 using const_reference = typename storage_type::const_reference;
391 using size_type = typename storage_type::size_type;
392 using shape_type = S;
393 using inner_shape_type = typename S::cast_type;
394 using strides_type = get_strides_t<inner_shape_type>;
395 using backstrides_type = strides_type;
396 using inner_strides_type = strides_type;
397 using inner_backstrides_type = backstrides_type;
399 static constexpr layout_type layout = L;
400 };
401
402 template <class EC, class S, layout_type L, bool SH, class Tag>
403 struct xiterable_inner_types<xfixed_adaptor<EC, S, L, SH, Tag>>
404 : xcontainer_iterable_types<xfixed_adaptor<EC, S, L, SH, Tag>>
405 {
406 };
407
424 template <class EC, class S, layout_type L, bool SH, class Tag>
425 class xfixed_adaptor : public xcontainer<xfixed_adaptor<EC, S, L, SH, Tag>>,
426 public xcontainer_semantic<xfixed_adaptor<EC, S, L, SH, Tag>>
427 {
428 public:
429
430 using container_closure_type = EC;
431
432 using self_type = xfixed_adaptor<EC, S, L, SH, Tag>;
433 using base_type = xcontainer<self_type>;
434 using semantic_base = xcontainer_semantic<self_type>;
435 using storage_type = typename base_type::storage_type;
436 using shape_type = typename base_type::shape_type;
437 using strides_type = typename base_type::strides_type;
438 using backstrides_type = typename base_type::backstrides_type;
439 using inner_shape_type = typename base_type::inner_shape_type;
440 using inner_strides_type = typename base_type::inner_strides_type;
441 using inner_backstrides_type = typename base_type::inner_backstrides_type;
442 using temporary_type = typename semantic_base::temporary_type;
443 using expression_tag = Tag;
444
445 static constexpr std::size_t N = S::size();
446
447 xfixed_adaptor(storage_type&& data);
448 xfixed_adaptor(const storage_type& data);
449
450 template <class D>
451 xfixed_adaptor(D&& data);
452
453 ~xfixed_adaptor() = default;
454
455 xfixed_adaptor(const xfixed_adaptor&) = default;
456 xfixed_adaptor& operator=(const xfixed_adaptor&);
457
458 xfixed_adaptor(xfixed_adaptor&&) = default;
459 xfixed_adaptor& operator=(xfixed_adaptor&&);
460 xfixed_adaptor& operator=(temporary_type&&);
461
462 template <class E>
463 xfixed_adaptor& operator=(const xexpression<E>& e);
464
465 template <class ST = std::array<std::size_t, N>>
466 void resize(ST&& shape, bool force = false) const;
467 template <class ST = shape_type>
468 void resize(ST&& shape, layout_type l) const;
469 template <class ST = shape_type>
470 void resize(ST&& shape, const strides_type& strides) const;
471
472 template <class ST = std::array<std::size_t, N>>
473 const auto& reshape(ST&& shape, layout_type layout = L) const;
474
475 template <class ST>
476 bool broadcast_shape(ST& s, bool reuse_cache = false) const;
477
478 constexpr layout_type layout() const noexcept;
479 bool is_contiguous() const noexcept;
480
481 private:
482
483 container_closure_type m_storage;
484
485 XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_shape_type m_shape = S();
486 XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_strides_type m_strides = get_strides<L, inner_strides_type>(S());
487 XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_backstrides_type
488 m_backstrides = get_backstrides(m_shape, m_strides);
489
490 storage_type& storage_impl() noexcept;
491 const storage_type& storage_impl() const noexcept;
492
493 constexpr const inner_shape_type& shape_impl() const noexcept;
494 constexpr const inner_strides_type& strides_impl() const noexcept;
495 constexpr const inner_backstrides_type& backstrides_impl() const noexcept;
496
497 friend class xcontainer<xfixed_adaptor<EC, S, L, SH, Tag>>;
498 };
499
500 /************************************
501 * xfixed_container implementation *
502 ************************************/
503
508
517 template <class ET, class S, layout_type L, bool SH, class Tag>
518 inline xfixed_container<ET, S, L, SH, Tag>::xfixed_container(const inner_shape_type& shape, layout_type l)
519 {
520 (void) (shape);
521 (void) (l);
522 XTENSOR_ASSERT(shape.size() == N && std::equal(shape.begin(), shape.end(), m_shape.begin()));
523 XTENSOR_ASSERT(L == l);
524 }
525
526 template <class ET, class S, layout_type L, bool SH, class Tag>
527 inline xfixed_container<ET, S, L, SH, Tag>::xfixed_container(const value_type& v)
528 {
529 if (this->size() != 1)
530 {
531 XTENSOR_THROW(std::runtime_error, "wrong shape for scalar assignment (has to be xshape<>).");
532 }
533 m_storage[0] = v;
534 }
535
545 template <class ET, class S, layout_type L, bool SH, class Tag>
546 inline xfixed_container<ET, S, L, SH, Tag>::xfixed_container(
547 const inner_shape_type& shape,
548 value_type v,
550 )
551 {
552 (void) (shape);
553 (void) (l);
554 XTENSOR_ASSERT(shape.size() == N && std::equal(shape.begin(), shape.end(), m_shape.begin()));
555 XTENSOR_ASSERT(L == l);
556 std::fill(m_storage.begin(), m_storage.end(), v);
557 }
558
559 namespace detail
560 {
561 template <std::size_t X>
562 struct check_initializer_list_shape
563 {
564 template <class T, class S>
565 static bool run(const T& t, const S& shape)
566 {
567 std::size_t IX = shape.size() - X;
568 bool result = (shape[IX] == t.size());
569 for (std::size_t i = 0; i < shape[IX]; ++i)
570 {
571 result = result && check_initializer_list_shape<X - 1>::run(t.begin()[i], shape);
572 }
573 return result;
574 }
575 };
576
577 template <>
578 struct check_initializer_list_shape<0>
579 {
580 template <class T, class S>
581 static bool run(const T& /*t*/, const S& /*shape*/)
582 {
583 return true;
584 }
585 };
586 }
587
588 template <class ET, class S, layout_type L, bool SH, class Tag>
589 template <class ST>
590 inline xfixed_container<ET, S, L, SH, Tag> xfixed_container<ET, S, L, SH, Tag>::from_shape(ST&& shape)
591 {
592 (void) shape;
593 self_type tmp;
594 XTENSOR_ASSERT(shape.size() == N && std::equal(shape.begin(), shape.end(), tmp.shape().begin()));
595 return tmp;
596 }
597
605 template <class ET, class S, layout_type L, bool SH, class Tag>
606 template <class IX>
607 inline xfixed_container<ET, S, L, SH, Tag>::xfixed_container(nested_initializer_list_t<value_type, N> t)
608 requires(IX::value != 0)
609 {
610 XTENSOR_ASSERT_MSG(
611 detail::check_initializer_list_shape<N>::run(t, this->shape()) == true,
612 "initializer list shape does not match fixed shape"
613 );
614 constexpr auto tmp = layout_type::row_major;
615 L == tmp ? nested_copy(m_storage.begin(), t) : nested_copy(this->template begin<tmp>(), t);
616 }
617
619
624
627 template <class ET, class S, layout_type L, bool SH, class Tag>
628 template <class E>
629 inline xfixed_container<ET, S, L, SH, Tag>::xfixed_container(const xexpression<E>& e)
630 {
631 semantic_base::assign(e);
632 }
633
637 template <class ET, class S, layout_type L, bool SH, class Tag>
638 template <class E>
639 inline auto xfixed_container<ET, S, L, SH, Tag>::operator=(const xexpression<E>& e) -> self_type&
640 {
641 return semantic_base::operator=(e);
642 }
643
645
650 template <class ET, class S, layout_type L, bool SH, class Tag>
651 template <class ST>
653 {
654 (void) (shape); // remove unused parameter warning if XTENSOR_ASSERT undefined
655 XTENSOR_ASSERT(std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size());
656 }
657
662 template <class ET, class S, layout_type L, bool SH, class Tag>
663 template <class ST>
665 {
666 (void) (shape); // remove unused parameter warning if XTENSOR_ASSERT undefined
667 (void) (l);
668 XTENSOR_ASSERT(
669 std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size() && L == l
670 );
671 }
672
677 template <class ET, class S, layout_type L, bool SH, class Tag>
678 template <class ST>
679 inline void xfixed_container<ET, S, L, SH, Tag>::resize(ST&& shape, const strides_type& strides) const
680 {
681 (void) (shape); // remove unused parameter warning if XTENSOR_ASSERT undefined
682 (void) (strides);
683 XTENSOR_ASSERT(std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size());
684 XTENSOR_ASSERT(
685 std::equal(strides.begin(), strides.end(), m_strides.begin()) && strides.size() == m_strides.size()
686 );
687 }
688
692 template <class ET, class S, layout_type L, bool SH, class Tag>
693 template <class ST>
695 {
696 if (!(std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size()
697 && layout == L))
698 {
699 XTENSOR_THROW(std::runtime_error, "Trying to reshape xtensor_fixed with different shape or layout.");
700 }
701 return *this;
702 }
703
704 template <class ET, class S, layout_type L, bool SH, class Tag>
705 template <class ST>
706 inline bool xfixed_container<ET, S, L, SH, Tag>::broadcast_shape(ST& shape, bool) const
707 {
708 return xt::broadcast_shape(m_shape, shape);
709 }
710
711 template <class ET, class S, layout_type L, bool SH, class Tag>
712 constexpr layout_type xfixed_container<ET, S, L, SH, Tag>::layout() const noexcept
713 {
714 return base_type::static_layout;
715 }
716
717 template <class ET, class S, layout_type L, bool SH, class Tag>
718 inline bool xfixed_container<ET, S, L, SH, Tag>::is_contiguous() const noexcept
719 {
720 using str_type = typename inner_strides_type::value_type;
721 return m_strides.empty() || (layout() == layout_type::row_major && m_strides.back() == str_type(1))
722 || (layout() == layout_type::column_major && m_strides.front() == str_type(1));
723 }
724
725 template <class ET, class S, layout_type L, bool SH, class Tag>
726 inline auto xfixed_container<ET, S, L, SH, Tag>::storage_impl() noexcept -> storage_type&
727 {
728 return m_storage;
729 }
730
731 template <class ET, class S, layout_type L, bool SH, class Tag>
732 inline auto xfixed_container<ET, S, L, SH, Tag>::storage_impl() const noexcept -> const storage_type&
733 {
734 return m_storage;
735 }
736
737 template <class ET, class S, layout_type L, bool SH, class Tag>
738 constexpr auto xfixed_container<ET, S, L, SH, Tag>::shape_impl() const noexcept -> const inner_shape_type&
739 {
740 return m_shape;
741 }
742
743 template <class ET, class S, layout_type L, bool SH, class Tag>
744 constexpr auto xfixed_container<ET, S, L, SH, Tag>::strides_impl() const noexcept
745 -> const inner_strides_type&
746 {
747 return m_strides;
748 }
749
750 template <class ET, class S, layout_type L, bool SH, class Tag>
751 constexpr auto xfixed_container<ET, S, L, SH, Tag>::backstrides_impl() const noexcept
752 -> const inner_backstrides_type&
753 {
754 return m_backstrides;
755 }
756
757 /*******************
758 * xfixed_adaptor *
759 *******************/
760
765
769 template <class EC, class S, layout_type L, bool SH, class Tag>
771 : base_type()
772 , m_storage(std::move(data))
773 {
774 }
775
780 template <class EC, class S, layout_type L, bool SH, class Tag>
782 : base_type()
783 , m_storage(data)
784 {
785 }
786
792 template <class EC, class S, layout_type L, bool SH, class Tag>
793 template <class D>
795 : base_type()
796 , m_storage(std::forward<D>(data))
797 {
798 }
799
801
802 template <class EC, class S, layout_type L, bool SH, class Tag>
803 inline auto xfixed_adaptor<EC, S, L, SH, Tag>::operator=(const xfixed_adaptor& rhs) -> self_type&
804 {
805 base_type::operator=(rhs);
806 m_storage = rhs.m_storage;
807 return *this;
808 }
809
810 template <class EC, class S, layout_type L, bool SH, class Tag>
811 inline auto xfixed_adaptor<EC, S, L, SH, Tag>::operator=(xfixed_adaptor&& rhs) -> self_type&
812 {
813 base_type::operator=(std::move(rhs));
814 m_storage = rhs.m_storage;
815 return *this;
816 }
817
818 template <class EC, class S, layout_type L, bool SH, class Tag>
819 inline auto xfixed_adaptor<EC, S, L, SH, Tag>::operator=(temporary_type&& rhs) -> self_type&
820 {
821 m_storage.resize(rhs.storage().size());
822 std::copy(rhs.storage().cbegin(), rhs.storage().cend(), m_storage.begin());
823 return *this;
824 }
825
830
833 template <class EC, class S, layout_type L, bool SH, class Tag>
834 template <class E>
835 inline auto xfixed_adaptor<EC, S, L, SH, Tag>::operator=(const xexpression<E>& e) -> self_type&
836 {
837 return semantic_base::operator=(e);
838 }
839
841
846 template <class ET, class S, layout_type L, bool SH, class Tag>
847 template <class ST>
849 {
850 (void) (shape); // remove unused parameter warning if XTENSOR_ASSERT undefined
851 XTENSOR_ASSERT(std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size());
852 }
853
858 template <class ET, class S, layout_type L, bool SH, class Tag>
859 template <class ST>
861 {
862 (void) (shape); // remove unused parameter warning if XTENSOR_ASSERT undefined
863 (void) (l);
864 XTENSOR_ASSERT(
865 std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size() && L == l
866 );
867 }
868
873 template <class ET, class S, layout_type L, bool SH, class Tag>
874 template <class ST>
875 inline void xfixed_adaptor<ET, S, L, SH, Tag>::resize(ST&& shape, const strides_type& strides) const
876 {
877 (void) (shape); // remove unused parameter warning if XTENSOR_ASSERT undefined
878 (void) (strides);
879 XTENSOR_ASSERT(std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size());
880 XTENSOR_ASSERT(
881 std::equal(strides.begin(), strides.end(), m_strides.begin()) && strides.size() == m_strides.size()
882 );
883 }
884
888 template <class ET, class S, layout_type L, bool SH, class Tag>
889 template <class ST>
890 inline const auto& xfixed_adaptor<ET, S, L, SH, Tag>::reshape(ST&& shape, layout_type layout) const
891 {
892 if (!(std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size()
893 && layout == L))
894 {
895 XTENSOR_THROW(std::runtime_error, "Trying to reshape xtensor_fixed with different shape or layout.");
896 }
897 return *this;
898 }
899
900 template <class ET, class S, layout_type L, bool SH, class Tag>
901 template <class ST>
902 inline bool xfixed_adaptor<ET, S, L, SH, Tag>::broadcast_shape(ST& shape, bool) const
903 {
904 return xt::broadcast_shape(m_shape, shape);
905 }
906
907 template <class EC, class S, layout_type L, bool SH, class Tag>
908 inline auto xfixed_adaptor<EC, S, L, SH, Tag>::storage_impl() noexcept -> storage_type&
909 {
910 return m_storage;
911 }
912
913 template <class EC, class S, layout_type L, bool SH, class Tag>
914 inline auto xfixed_adaptor<EC, S, L, SH, Tag>::storage_impl() const noexcept -> const storage_type&
915 {
916 return m_storage;
917 }
918
919 template <class EC, class S, layout_type L, bool SH, class Tag>
920 constexpr layout_type xfixed_adaptor<EC, S, L, SH, Tag>::layout() const noexcept
921 {
922 return base_type::static_layout;
923 }
924
925 template <class EC, class S, layout_type L, bool SH, class Tag>
926 inline bool xfixed_adaptor<EC, S, L, SH, Tag>::is_contiguous() const noexcept
927 {
928 using str_type = typename inner_strides_type::value_type;
929 return m_strides.empty() || (layout() == layout_type::row_major && m_strides.back() == str_type(1))
930 || (layout() == layout_type::column_major && m_strides.front() == str_type(1));
931 }
932
933 template <class EC, class S, layout_type L, bool SH, class Tag>
934 constexpr auto xfixed_adaptor<EC, S, L, SH, Tag>::shape_impl() const noexcept -> const inner_shape_type&
935 {
936 return m_shape;
937 }
938
939 template <class EC, class S, layout_type L, bool SH, class Tag>
940 constexpr auto xfixed_adaptor<EC, S, L, SH, Tag>::strides_impl() const noexcept
941 -> const inner_strides_type&
942 {
943 return m_strides;
944 }
945
946 template <class EC, class S, layout_type L, bool SH, class Tag>
947 constexpr auto xfixed_adaptor<EC, S, L, SH, Tag>::backstrides_impl() const noexcept
948 -> const inner_backstrides_type&
949 {
950 return m_backstrides;
951 }
952}
953
954#endif
This array class is modeled after std::array but adds optional alignment through a template parameter...
Fixed shape implementation for compile time defined arrays.
constexpr const inner_strides_type & strides() const noexcept
Returns the strides of the container.
constexpr const inner_shape_type & shape() const noexcept
Returns the shape of the container.
Base class for xexpressions.
Dense multidimensional container adaptor with tensor semantic and fixed dimension.
Definition xfixed.hpp:427
xfixed_adaptor(storage_type &&data)
Constructs an xfixed_adaptor of the given stl-like container.
Definition xfixed.hpp:770
const auto & reshape(ST &&shape, layout_type layout=L) const
Note that the xfixed_container cannot be reshaped to a shape different from S.
Definition xfixed.hpp:890
void resize(ST &&shape, bool force=false) const
Note that the xfixed_adaptor cannot be resized.
Definition xfixed.hpp:848
Dense multidimensional container with tensor semantic and fixed dimension.
Definition xfixed.hpp:292
xfixed_container(const inner_shape_type &shape, layout_type l=L)
Create an uninitialized xfixed_container.
Definition xfixed.hpp:518
xfixed_container(const xexpression< E > &e)
The extended copy constructor.
Definition xfixed.hpp:629
void resize(ST &&shape, bool force=false) const
Note that the xfixed_container cannot be resized.
Definition xfixed.hpp:652
void resize(ST &&shape, const strides_type &strides) const
Note that the xfixed_container cannot be resized.
Definition xfixed.hpp:679
xfixed_container(const inner_shape_type &shape, value_type v, layout_type l=L)
Create an xfixed_container, and initialize with the value of v.
Definition xfixed.hpp:546
void resize(ST &&shape, layout_type l) const
Note that the xfixed_container cannot be resized.
Definition xfixed.hpp:664
xfixed_container(nested_initializer_list_t< value_type, N > t)
Allocates an xfixed_container with shape S with values from a C array.
Definition xfixed.hpp:607
const auto & reshape(ST &&shape, layout_type layout=L) const
Note that the xfixed_container cannot be reshaped to a shape different from S.
Definition xfixed.hpp:694
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