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#include <vector>
18
19#include <xtl/xsequence.hpp>
20
21#include "../containers/xcontainer.hpp"
22#include "../containers/xstorage.hpp"
23#include "../core/xsemantic.hpp"
24#include "../core/xstrides.hpp"
25#include "../core/xtensor_config.hpp"
26
27namespace xtl
28{
29 namespace detail
30 {
31 template <class T, std::size_t N>
32 struct sequence_builder<xt::const_array<T, N>>
33 {
34 using sequence_type = xt::const_array<T, N>;
35 using value_type = typename sequence_type::value_type;
36 using size_type = typename sequence_type::size_type;
37
38 inline static sequence_type make(size_type /*size*/, value_type /*v*/)
39 {
40 return sequence_type();
41 }
42 };
43 }
44}
45
46namespace xt
47{
48
49 /**********************
50 * xfixed declaration *
51 **********************/
52
53 template <class ET, class S, layout_type L, bool SH, class Tag>
54 class xfixed_container;
55
56 namespace detail
57 {
58 /**************************************************************************************
59 The following is something we can currently only dream about -- for when we drop
60 support for a lot of the old compilers (e.g. GCC 4.9, MSVC 2017 ;)
61
62 template <class T>
63 constexpr std::size_t calculate_stride(T& shape, std::size_t idx, layout_type L)
64 {
65 if (shape[idx] == 1)
66 {
67 return std::size_t(0);
68 }
69
70 std::size_t data_size = 1;
71 std::size_t stride = 1;
72 if (L == layout_type::row_major)
73 {
74 // because we have a integer sequence that counts
75 // from 0 to sz - 1, we need to "invert" idx here
76 idx = shape.size() - idx;
77 for (std::size_t i = idx; i != 0; --i)
78 {
79 stride = data_size;
80 data_size = stride * shape[i - 1];
81 }
82 }
83 else
84 {
85 for (std::size_t i = 0; i < idx + 1; ++i)
86 {
87 stride = data_size;
88 data_size = stride * shape[i];
89 }
90 }
91 return stride;
92 }
93
94 *****************************************************************************************/
95
96 template <layout_type L, std::size_t I, std::size_t... X>
97 struct calculate_stride;
98
99 template <std::size_t I, std::size_t Y, std::size_t... X>
100 struct calculate_stride<layout_type::column_major, I, Y, X...>
101 {
102 static constexpr std::ptrdiff_t value = Y
103 * calculate_stride<layout_type::column_major, I - 1, X...>::value;
104 };
105
106 template <std::size_t Y, std::size_t... X>
107 struct calculate_stride<layout_type::column_major, 0, Y, X...>
108 {
109 static constexpr std::ptrdiff_t value = 1;
110 };
111
112 template <std::size_t I, std::size_t... X>
113 struct calculate_stride_row_major
114 {
115 static constexpr std::ptrdiff_t value = at<sizeof...(X) - I, X...>::value
116 * calculate_stride_row_major<I - 1, X...>::value;
117 };
118
119 template <std::size_t... X>
120 struct calculate_stride_row_major<0, X...>
121 {
122 static constexpr std::ptrdiff_t value = 1;
123 };
124
125 template <std::size_t I, std::size_t... X>
126 struct calculate_stride<layout_type::row_major, I, X...>
127 {
128 static constexpr std::ptrdiff_t value = calculate_stride_row_major<sizeof...(X) - I - 1, X...>::value;
129 };
130
131 namespace workaround
132 {
133 template <layout_type L, size_t I, class SEQ>
134 struct computed_strides;
135
136 template <layout_type L, size_t I, size_t... X>
137 struct computed_strides<L, I, std::index_sequence<X...>>
138 {
139 static constexpr std::ptrdiff_t value = calculate_stride<L, I, X...>::value;
140 };
141
142 template <layout_type L, size_t I, class SEQ>
143 constexpr std::ptrdiff_t get_computed_strides(bool cond)
144 {
145 return cond ? 0 : computed_strides<L, I, SEQ>::value;
146 }
147 }
148
149 template <layout_type L, class R, std::size_t... X, std::size_t... I>
150 constexpr R get_strides_impl(const xt::fixed_shape<X...>& shape, std::index_sequence<I...>)
151 {
152 static_assert(
154 "Layout not supported for fixed array"
155 );
156#if (_MSC_VER >= 1910)
157 using temp_type = std::index_sequence<X...>;
158 return R({workaround::get_computed_strides<L, I, temp_type>(shape[I] == 1)...});
159#else
160 return R({shape[I] == 1 ? 0 : calculate_stride<L, I, X...>::value...});
161#endif
162 }
163
164 template <class S, class T, std::size_t... I>
165 constexpr T get_backstrides_impl(const S& shape, const T& strides, std::index_sequence<I...>)
166 {
167 return T({(strides[I] * std::ptrdiff_t(shape[I] - 1))...});
168 }
169
170 template <std::size_t... X>
171 struct fixed_compute_size_impl;
172
173 template <std::size_t Y, std::size_t... X>
174 struct fixed_compute_size_impl<Y, X...>
175 {
176 static constexpr std::size_t value = Y * fixed_compute_size_impl<X...>::value;
177 };
178
179 template <std::size_t X>
180 struct fixed_compute_size_impl<X>
181 {
182 static constexpr std::size_t value = X;
183 };
184
185 template <>
186 struct fixed_compute_size_impl<>
187 {
188 // support for 0D xtensor fixed (empty shape = xshape<>)
189 static constexpr std::size_t value = 1;
190 };
191
192 // TODO unify with constexpr compute_size when dropping MSVC 2015
193 template <class T>
194 struct fixed_compute_size;
195
196 template <std::size_t... X>
197 struct fixed_compute_size<xt::fixed_shape<X...>>
198 {
199 static constexpr std::size_t value = fixed_compute_size_impl<X...>::value;
200 };
201
202 template <class V, std::size_t... X>
203 struct get_init_type_impl;
204
205 template <class V, std::size_t Y>
206 struct get_init_type_impl<V, Y>
207 {
208 using type = V[Y];
209 };
210
211 template <class V>
212 struct get_init_type_impl<V>
213 {
214 using type = V[1];
215 };
216
217 template <class V, std::size_t Y, std::size_t... X>
218 struct get_init_type_impl<V, Y, X...>
219 {
220 using tmp_type = typename get_init_type_impl<V, X...>::type;
221 using type = tmp_type[Y];
222 };
223 }
224
225 template <layout_type L, class R, std::size_t... X>
226 constexpr R get_strides(const fixed_shape<X...>& shape) noexcept
227 {
228 return detail::get_strides_impl<L, R>(shape, std::make_index_sequence<sizeof...(X)>{});
229 }
230
231 template <class S, class T>
232 constexpr T get_backstrides(const S& shape, const T& strides) noexcept
233 {
234 return detail::get_backstrides_impl(shape, strides, std::make_index_sequence<std::tuple_size<T>::value>{});
235 }
236
237 template <class V, class S>
239
240 template <class V, std::size_t... X>
241 struct get_init_type<V, fixed_shape<X...>>
242 {
243 using type = typename detail::get_init_type_impl<V, X...>::type;
244 };
245
246 template <class V, class S>
247 using get_init_type_t = typename get_init_type<V, S>::type;
248
249 template <class ET, class S, layout_type L, bool SH, class Tag>
250 struct xcontainer_inner_types<xfixed_container<ET, S, L, SH, Tag>>
251 {
252 using shape_type = S;
253 using inner_shape_type = typename S::cast_type;
254 using strides_type = get_strides_t<inner_shape_type>;
255 using inner_strides_type = strides_type;
256 using backstrides_type = inner_strides_type;
257 using inner_backstrides_type = backstrides_type;
258
259 // NOTE: 0D (S::size() == 0) results in storage for 1 element (scalar)
260#if defined(_MSC_VER) && _MSC_VER < 1910 && !defined(_WIN64)
261 // WORKAROUND FOR MSVC 2015 32 bit, fallback to unaligned container for 0D scalar case
262 using storage_type = std::array<ET, detail::fixed_compute_size<S>::value>;
263#else
265#endif
266
267 using reference = typename storage_type::reference;
268 using const_reference = typename storage_type::const_reference;
269 using size_type = typename storage_type::size_type;
270 using temporary_type = xfixed_container<ET, S, L, SH, Tag>;
271 static constexpr layout_type layout = L;
272 };
273
274 template <class ET, class S, layout_type L, bool SH, class Tag>
275 struct xiterable_inner_types<xfixed_container<ET, S, L, SH, Tag>>
276 : xcontainer_iterable_types<xfixed_container<ET, S, L, SH, Tag>>
277 {
278 };
279
295 template <class ET, class S, layout_type L, bool SH, class Tag>
296 class xfixed_container : public xcontainer<xfixed_container<ET, S, L, SH, Tag>>,
297 public xcontainer_semantic<xfixed_container<ET, S, L, SH, Tag>>
298 {
299 public:
300
301 using self_type = xfixed_container<ET, S, L, SH, Tag>;
302 using base_type = xcontainer<self_type>;
303 using semantic_base = xcontainer_semantic<self_type>;
304
305 using storage_type = typename base_type::storage_type;
306 using value_type = typename base_type::value_type;
307 using reference = typename base_type::reference;
308 using const_reference = typename base_type::const_reference;
309 using pointer = typename base_type::pointer;
310 using const_pointer = typename base_type::const_pointer;
311 using shape_type = typename base_type::shape_type;
312 using inner_shape_type = typename base_type::inner_shape_type;
313 using strides_type = typename base_type::strides_type;
314 using backstrides_type = typename base_type::backstrides_type;
315 using inner_backstrides_type = typename base_type::inner_backstrides_type;
316 using inner_strides_type = typename base_type::inner_strides_type;
317 using temporary_type = typename semantic_base::temporary_type;
318 using expression_tag = Tag;
319
320 static constexpr std::size_t N = std::tuple_size<shape_type>::value;
321 static constexpr std::size_t rank = N;
322
323 xfixed_container() = default;
324 xfixed_container(const value_type& v);
325 explicit xfixed_container(const inner_shape_type& shape, layout_type l = L);
326 explicit xfixed_container(const inner_shape_type& shape, value_type v, layout_type l = L);
327
328 template <class IX = std::integral_constant<std::size_t, N>>
329 xfixed_container(nested_initializer_list_t<value_type, N> t)
330 requires(IX::value != 0);
331
332 ~xfixed_container() = default;
333
334 xfixed_container(const xfixed_container&) = default;
335 xfixed_container& operator=(const xfixed_container&) = default;
336
337 xfixed_container(xfixed_container&&) = default;
338 xfixed_container& operator=(xfixed_container&&) = default;
339
340 template <class E>
342
343 template <class E>
344 xfixed_container& operator=(const xexpression<E>& e);
345
346 template <class ST = std::array<std::size_t, N>>
347 static xfixed_container from_shape(ST&& /*s*/);
348
349 template <class ST = std::array<std::size_t, N>>
350 void resize(ST&& shape, bool force = false) const;
351 template <class ST = shape_type>
352 void resize(ST&& shape, layout_type l) const;
353 template <class ST = shape_type>
354 void resize(ST&& shape, const strides_type& strides) const;
355
356 template <class ST = std::array<std::size_t, N>>
357 const auto& reshape(ST&& shape, layout_type layout = L) const;
358
359 template <class ST>
360 bool broadcast_shape(ST& s, bool reuse_cache = false) const;
361
362 constexpr layout_type layout() const noexcept;
363 bool is_contiguous() const noexcept;
364
365 private:
366
367 storage_type m_storage;
368
369 XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_shape_type m_shape = S();
370 XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_strides_type m_strides = get_strides<L, inner_strides_type>(S());
371 XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_backstrides_type
372 m_backstrides = get_backstrides(m_shape, m_strides);
373
374 storage_type& storage_impl() noexcept;
375 const storage_type& storage_impl() const noexcept;
376
377 XTENSOR_CONSTEXPR_RETURN const inner_shape_type& shape_impl() const noexcept;
378 XTENSOR_CONSTEXPR_RETURN const inner_strides_type& strides_impl() const noexcept;
379 XTENSOR_CONSTEXPR_RETURN const inner_backstrides_type& backstrides_impl() const noexcept;
380
381 friend class xcontainer<xfixed_container<ET, S, L, SH, Tag>>;
382 };
383
384#ifdef XTENSOR_HAS_CONSTEXPR_ENHANCED
385 // Out of line definitions to prevent linker errors prior to C++17
386 template <class ET, class S, layout_type L, bool SH, class Tag>
387 constexpr
388 typename xfixed_container<ET, S, L, SH, Tag>::inner_shape_type xfixed_container<ET, S, L, SH, Tag>::m_shape;
389
390 template <class ET, class S, layout_type L, bool SH, class Tag>
391 constexpr
392 typename xfixed_container<ET, S, L, SH, Tag>::inner_strides_type xfixed_container<ET, S, L, SH, Tag>::m_strides;
393
394 template <class ET, class S, layout_type L, bool SH, class Tag>
395 constexpr typename xfixed_container<ET, S, L, SH, Tag>::inner_backstrides_type
396 xfixed_container<ET, S, L, SH, Tag>::m_backstrides;
397#endif
398
399 /****************************************
400 * xfixed_container_adaptor declaration *
401 ****************************************/
402
403 template <class EC, class S, layout_type L, bool SH, class Tag>
404 class xfixed_adaptor;
405
406 template <class EC, class S, layout_type L, bool SH, class Tag>
407 struct xcontainer_inner_types<xfixed_adaptor<EC, S, L, SH, Tag>>
408 {
409 using storage_type = std::remove_reference_t<EC>;
410 using reference = typename storage_type::reference;
411 using const_reference = typename storage_type::const_reference;
412 using size_type = typename storage_type::size_type;
413 using shape_type = S;
414 using inner_shape_type = typename S::cast_type;
415 using strides_type = get_strides_t<inner_shape_type>;
416 using backstrides_type = strides_type;
417 using inner_strides_type = strides_type;
418 using inner_backstrides_type = backstrides_type;
420 static constexpr layout_type layout = L;
421 };
422
423 template <class EC, class S, layout_type L, bool SH, class Tag>
424 struct xiterable_inner_types<xfixed_adaptor<EC, S, L, SH, Tag>>
425 : xcontainer_iterable_types<xfixed_adaptor<EC, S, L, SH, Tag>>
426 {
427 };
428
445 template <class EC, class S, layout_type L, bool SH, class Tag>
446 class xfixed_adaptor : public xcontainer<xfixed_adaptor<EC, S, L, SH, Tag>>,
447 public xcontainer_semantic<xfixed_adaptor<EC, S, L, SH, Tag>>
448 {
449 public:
450
451 using container_closure_type = EC;
452
453 using self_type = xfixed_adaptor<EC, S, L, SH, Tag>;
454 using base_type = xcontainer<self_type>;
455 using semantic_base = xcontainer_semantic<self_type>;
456 using storage_type = typename base_type::storage_type;
457 using shape_type = typename base_type::shape_type;
458 using strides_type = typename base_type::strides_type;
459 using backstrides_type = typename base_type::backstrides_type;
460 using inner_shape_type = typename base_type::inner_shape_type;
461 using inner_strides_type = typename base_type::inner_strides_type;
462 using inner_backstrides_type = typename base_type::inner_backstrides_type;
463 using temporary_type = typename semantic_base::temporary_type;
464 using expression_tag = Tag;
465
466 static constexpr std::size_t N = S::size();
467
468 xfixed_adaptor(storage_type&& data);
469 xfixed_adaptor(const storage_type& data);
470
471 template <class D>
472 xfixed_adaptor(D&& data);
473
474 ~xfixed_adaptor() = default;
475
476 xfixed_adaptor(const xfixed_adaptor&) = default;
477 xfixed_adaptor& operator=(const xfixed_adaptor&);
478
479 xfixed_adaptor(xfixed_adaptor&&) = default;
480 xfixed_adaptor& operator=(xfixed_adaptor&&);
481 xfixed_adaptor& operator=(temporary_type&&);
482
483 template <class E>
484 xfixed_adaptor& operator=(const xexpression<E>& e);
485
486 template <class ST = std::array<std::size_t, N>>
487 void resize(ST&& shape, bool force = false) const;
488 template <class ST = shape_type>
489 void resize(ST&& shape, layout_type l) const;
490 template <class ST = shape_type>
491 void resize(ST&& shape, const strides_type& strides) const;
492
493 template <class ST = std::array<std::size_t, N>>
494 const auto& reshape(ST&& shape, layout_type layout = L) const;
495
496 template <class ST>
497 bool broadcast_shape(ST& s, bool reuse_cache = false) const;
498
499 constexpr layout_type layout() const noexcept;
500 bool is_contiguous() const noexcept;
501
502 private:
503
504 container_closure_type m_storage;
505
506 XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_shape_type m_shape = S();
507 XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_strides_type m_strides = get_strides<L, inner_strides_type>(S());
508 XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_backstrides_type
509 m_backstrides = get_backstrides(m_shape, m_strides);
510
511 storage_type& storage_impl() noexcept;
512 const storage_type& storage_impl() const noexcept;
513
514 XTENSOR_CONSTEXPR_RETURN const inner_shape_type& shape_impl() const noexcept;
515 XTENSOR_CONSTEXPR_RETURN const inner_strides_type& strides_impl() const noexcept;
516 XTENSOR_CONSTEXPR_RETURN const inner_backstrides_type& backstrides_impl() const noexcept;
517
518 friend class xcontainer<xfixed_adaptor<EC, S, L, SH, Tag>>;
519 };
520
521#ifdef XTENSOR_HAS_CONSTEXPR_ENHANCED
522 // Out of line definitions to prevent linker errors prior to C++17
523 template <class EC, class S, layout_type L, bool SH, class Tag>
524 constexpr
525 typename xfixed_adaptor<EC, S, L, SH, Tag>::inner_shape_type xfixed_adaptor<EC, S, L, SH, Tag>::m_shape;
526
527 template <class EC, class S, layout_type L, bool SH, class Tag>
528 constexpr
529 typename xfixed_adaptor<EC, S, L, SH, Tag>::inner_strides_type xfixed_adaptor<EC, S, L, SH, Tag>::m_strides;
530
531 template <class EC, class S, layout_type L, bool SH, class Tag>
532 constexpr typename xfixed_adaptor<EC, S, L, SH, Tag>::inner_backstrides_type
533 xfixed_adaptor<EC, S, L, SH, Tag>::m_backstrides;
534#endif
535
536 /************************************
537 * xfixed_container implementation *
538 ************************************/
539
544
553 template <class ET, class S, layout_type L, bool SH, class Tag>
554 inline xfixed_container<ET, S, L, SH, Tag>::xfixed_container(const inner_shape_type& shape, layout_type l)
555 {
556 (void) (shape);
557 (void) (l);
558 XTENSOR_ASSERT(shape.size() == N && std::equal(shape.begin(), shape.end(), m_shape.begin()));
559 XTENSOR_ASSERT(L == l);
560 }
561
562 template <class ET, class S, layout_type L, bool SH, class Tag>
563 inline xfixed_container<ET, S, L, SH, Tag>::xfixed_container(const value_type& v)
564 {
565 if (this->size() != 1)
566 {
567 XTENSOR_THROW(std::runtime_error, "wrong shape for scalar assignment (has to be xshape<>).");
568 }
569 m_storage[0] = v;
570 }
571
581 template <class ET, class S, layout_type L, bool SH, class Tag>
582 inline xfixed_container<ET, S, L, SH, Tag>::xfixed_container(
583 const inner_shape_type& shape,
584 value_type v,
586 )
587 {
588 (void) (shape);
589 (void) (l);
590 XTENSOR_ASSERT(shape.size() == N && std::equal(shape.begin(), shape.end(), m_shape.begin()));
591 XTENSOR_ASSERT(L == l);
592 std::fill(m_storage.begin(), m_storage.end(), v);
593 }
594
595 namespace detail
596 {
597 template <std::size_t X>
598 struct check_initializer_list_shape
599 {
600 template <class T, class S>
601 static bool run(const T& t, const S& shape)
602 {
603 std::size_t IX = shape.size() - X;
604 bool result = (shape[IX] == t.size());
605 for (std::size_t i = 0; i < shape[IX]; ++i)
606 {
607 result = result && check_initializer_list_shape<X - 1>::run(t.begin()[i], shape);
608 }
609 return result;
610 }
611 };
612
613 template <>
614 struct check_initializer_list_shape<0>
615 {
616 template <class T, class S>
617 static bool run(const T& /*t*/, const S& /*shape*/)
618 {
619 return true;
620 }
621 };
622 }
623
624 template <class ET, class S, layout_type L, bool SH, class Tag>
625 template <class ST>
626 inline xfixed_container<ET, S, L, SH, Tag> xfixed_container<ET, S, L, SH, Tag>::from_shape(ST&& shape)
627 {
628 (void) shape;
629 self_type tmp;
630 XTENSOR_ASSERT(shape.size() == N && std::equal(shape.begin(), shape.end(), tmp.shape().begin()));
631 return tmp;
632 }
633
641 template <class ET, class S, layout_type L, bool SH, class Tag>
642 template <class IX>
643 inline xfixed_container<ET, S, L, SH, Tag>::xfixed_container(nested_initializer_list_t<value_type, N> t)
644 requires(IX::value != 0)
645 {
646 XTENSOR_ASSERT_MSG(
647 detail::check_initializer_list_shape<N>::run(t, this->shape()) == true,
648 "initializer list shape does not match fixed shape"
649 );
650 constexpr auto tmp = layout_type::row_major;
651 L == tmp ? nested_copy(m_storage.begin(), t) : nested_copy(this->template begin<tmp>(), t);
652 }
653
655
660
663 template <class ET, class S, layout_type L, bool SH, class Tag>
664 template <class E>
665 inline xfixed_container<ET, S, L, SH, Tag>::xfixed_container(const xexpression<E>& e)
666 {
667 semantic_base::assign(e);
668 }
669
673 template <class ET, class S, layout_type L, bool SH, class Tag>
674 template <class E>
675 inline auto xfixed_container<ET, S, L, SH, Tag>::operator=(const xexpression<E>& e) -> self_type&
676 {
677 return semantic_base::operator=(e);
678 }
679
681
686 template <class ET, class S, layout_type L, bool SH, class Tag>
687 template <class ST>
689 {
690 (void) (shape); // remove unused parameter warning if XTENSOR_ASSERT undefined
691 XTENSOR_ASSERT(std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size());
692 }
693
698 template <class ET, class S, layout_type L, bool SH, class Tag>
699 template <class ST>
701 {
702 (void) (shape); // remove unused parameter warning if XTENSOR_ASSERT undefined
703 (void) (l);
704 XTENSOR_ASSERT(
705 std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size() && L == l
706 );
707 }
708
713 template <class ET, class S, layout_type L, bool SH, class Tag>
714 template <class ST>
715 inline void xfixed_container<ET, S, L, SH, Tag>::resize(ST&& shape, const strides_type& strides) const
716 {
717 (void) (shape); // remove unused parameter warning if XTENSOR_ASSERT undefined
718 (void) (strides);
719 XTENSOR_ASSERT(std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size());
720 XTENSOR_ASSERT(
721 std::equal(strides.begin(), strides.end(), m_strides.begin()) && strides.size() == m_strides.size()
722 );
723 }
724
728 template <class ET, class S, layout_type L, bool SH, class Tag>
729 template <class ST>
731 {
732 if (!(std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size()
733 && layout == L))
734 {
735 XTENSOR_THROW(std::runtime_error, "Trying to reshape xtensor_fixed with different shape or layout.");
736 }
737 return *this;
738 }
739
740 template <class ET, class S, layout_type L, bool SH, class Tag>
741 template <class ST>
742 inline bool xfixed_container<ET, S, L, SH, Tag>::broadcast_shape(ST& shape, bool) const
743 {
744 return xt::broadcast_shape(m_shape, shape);
745 }
746
747 template <class ET, class S, layout_type L, bool SH, class Tag>
748 constexpr layout_type xfixed_container<ET, S, L, SH, Tag>::layout() const noexcept
749 {
750 return base_type::static_layout;
751 }
752
753 template <class ET, class S, layout_type L, bool SH, class Tag>
754 inline bool xfixed_container<ET, S, L, SH, Tag>::is_contiguous() const noexcept
755 {
756 using str_type = typename inner_strides_type::value_type;
757 return m_strides.empty() || (layout() == layout_type::row_major && m_strides.back() == str_type(1))
758 || (layout() == layout_type::column_major && m_strides.front() == str_type(1));
759 }
760
761 template <class ET, class S, layout_type L, bool SH, class Tag>
762 inline auto xfixed_container<ET, S, L, SH, Tag>::storage_impl() noexcept -> storage_type&
763 {
764 return m_storage;
765 }
766
767 template <class ET, class S, layout_type L, bool SH, class Tag>
768 inline auto xfixed_container<ET, S, L, SH, Tag>::storage_impl() const noexcept -> const storage_type&
769 {
770 return m_storage;
771 }
772
773 template <class ET, class S, layout_type L, bool SH, class Tag>
774 XTENSOR_CONSTEXPR_RETURN auto xfixed_container<ET, S, L, SH, Tag>::shape_impl() const noexcept
775 -> const inner_shape_type&
776 {
777 return m_shape;
778 }
779
780 template <class ET, class S, layout_type L, bool SH, class Tag>
781 XTENSOR_CONSTEXPR_RETURN auto xfixed_container<ET, S, L, SH, Tag>::strides_impl() const noexcept
782 -> const inner_strides_type&
783 {
784 return m_strides;
785 }
786
787 template <class ET, class S, layout_type L, bool SH, class Tag>
788 XTENSOR_CONSTEXPR_RETURN auto xfixed_container<ET, S, L, SH, Tag>::backstrides_impl() const noexcept
789 -> const inner_backstrides_type&
790 {
791 return m_backstrides;
792 }
793
794 /*******************
795 * xfixed_adaptor *
796 *******************/
797
802
806 template <class EC, class S, layout_type L, bool SH, class Tag>
808 : base_type()
809 , m_storage(std::move(data))
810 {
811 }
812
817 template <class EC, class S, layout_type L, bool SH, class Tag>
819 : base_type()
820 , m_storage(data)
821 {
822 }
823
829 template <class EC, class S, layout_type L, bool SH, class Tag>
830 template <class D>
832 : base_type()
833 , m_storage(std::forward<D>(data))
834 {
835 }
836
838
839 template <class EC, class S, layout_type L, bool SH, class Tag>
840 inline auto xfixed_adaptor<EC, S, L, SH, Tag>::operator=(const xfixed_adaptor& rhs) -> self_type&
841 {
842 base_type::operator=(rhs);
843 m_storage = rhs.m_storage;
844 return *this;
845 }
846
847 template <class EC, class S, layout_type L, bool SH, class Tag>
848 inline auto xfixed_adaptor<EC, S, L, SH, Tag>::operator=(xfixed_adaptor&& rhs) -> self_type&
849 {
850 base_type::operator=(std::move(rhs));
851 m_storage = rhs.m_storage;
852 return *this;
853 }
854
855 template <class EC, class S, layout_type L, bool SH, class Tag>
856 inline auto xfixed_adaptor<EC, S, L, SH, Tag>::operator=(temporary_type&& rhs) -> self_type&
857 {
858 m_storage.resize(rhs.storage().size());
859 std::copy(rhs.storage().cbegin(), rhs.storage().cend(), m_storage.begin());
860 return *this;
861 }
862
867
870 template <class EC, class S, layout_type L, bool SH, class Tag>
871 template <class E>
872 inline auto xfixed_adaptor<EC, S, L, SH, Tag>::operator=(const xexpression<E>& e) -> self_type&
873 {
874 return semantic_base::operator=(e);
875 }
876
878
883 template <class ET, class S, layout_type L, bool SH, class Tag>
884 template <class ST>
886 {
887 (void) (shape); // remove unused parameter warning if XTENSOR_ASSERT undefined
888 XTENSOR_ASSERT(std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size());
889 }
890
895 template <class ET, class S, layout_type L, bool SH, class Tag>
896 template <class ST>
898 {
899 (void) (shape); // remove unused parameter warning if XTENSOR_ASSERT undefined
900 (void) (l);
901 XTENSOR_ASSERT(
902 std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size() && L == l
903 );
904 }
905
910 template <class ET, class S, layout_type L, bool SH, class Tag>
911 template <class ST>
912 inline void xfixed_adaptor<ET, S, L, SH, Tag>::resize(ST&& shape, const strides_type& strides) const
913 {
914 (void) (shape); // remove unused parameter warning if XTENSOR_ASSERT undefined
915 (void) (strides);
916 XTENSOR_ASSERT(std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size());
917 XTENSOR_ASSERT(
918 std::equal(strides.begin(), strides.end(), m_strides.begin()) && strides.size() == m_strides.size()
919 );
920 }
921
925 template <class ET, class S, layout_type L, bool SH, class Tag>
926 template <class ST>
927 inline const auto& xfixed_adaptor<ET, S, L, SH, Tag>::reshape(ST&& shape, layout_type layout) const
928 {
929 if (!(std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size()
930 && layout == L))
931 {
932 XTENSOR_THROW(std::runtime_error, "Trying to reshape xtensor_fixed with different shape or layout.");
933 }
934 return *this;
935 }
936
937 template <class ET, class S, layout_type L, bool SH, class Tag>
938 template <class ST>
939 inline bool xfixed_adaptor<ET, S, L, SH, Tag>::broadcast_shape(ST& shape, bool) const
940 {
941 return xt::broadcast_shape(m_shape, shape);
942 }
943
944 template <class EC, class S, layout_type L, bool SH, class Tag>
945 inline auto xfixed_adaptor<EC, S, L, SH, Tag>::storage_impl() noexcept -> storage_type&
946 {
947 return m_storage;
948 }
949
950 template <class EC, class S, layout_type L, bool SH, class Tag>
951 inline auto xfixed_adaptor<EC, S, L, SH, Tag>::storage_impl() const noexcept -> const storage_type&
952 {
953 return m_storage;
954 }
955
956 template <class EC, class S, layout_type L, bool SH, class Tag>
957 constexpr layout_type xfixed_adaptor<EC, S, L, SH, Tag>::layout() const noexcept
958 {
959 return base_type::static_layout;
960 }
961
962 template <class EC, class S, layout_type L, bool SH, class Tag>
963 inline bool xfixed_adaptor<EC, S, L, SH, Tag>::is_contiguous() const noexcept
964 {
965 using str_type = typename inner_strides_type::value_type;
966 return m_strides.empty() || (layout() == layout_type::row_major && m_strides.back() == str_type(1))
967 || (layout() == layout_type::column_major && m_strides.front() == str_type(1));
968 }
969
970 template <class EC, class S, layout_type L, bool SH, class Tag>
971 XTENSOR_CONSTEXPR_RETURN auto xfixed_adaptor<EC, S, L, SH, Tag>::shape_impl() const noexcept
972 -> const inner_shape_type&
973 {
974 return m_shape;
975 }
976
977 template <class EC, class S, layout_type L, bool SH, class Tag>
978 XTENSOR_CONSTEXPR_RETURN auto xfixed_adaptor<EC, S, L, SH, Tag>::strides_impl() const noexcept
979 -> const inner_strides_type&
980 {
981 return m_strides;
982 }
983
984 template <class EC, class S, layout_type L, bool SH, class Tag>
985 XTENSOR_CONSTEXPR_RETURN auto xfixed_adaptor<EC, S, L, SH, Tag>::backstrides_impl() const noexcept
986 -> const inner_backstrides_type&
987 {
988 return m_backstrides;
989 }
990}
991
992#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:448
xfixed_adaptor(storage_type &&data)
Constructs an xfixed_adaptor of the given stl-like container.
Definition xfixed.hpp:807
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:927
void resize(ST &&shape, bool force=false) const
Note that the xfixed_adaptor cannot be resized.
Definition xfixed.hpp:885
Dense multidimensional container with tensor semantic and fixed dimension.
Definition xfixed.hpp:298
xfixed_container(const inner_shape_type &shape, layout_type l=L)
Create an uninitialized xfixed_container.
Definition xfixed.hpp:554
xfixed_container(const xexpression< E > &e)
The extended copy constructor.
Definition xfixed.hpp:665
void resize(ST &&shape, bool force=false) const
Note that the xfixed_container cannot be resized.
Definition xfixed.hpp:688
void resize(ST &&shape, const strides_type &strides) const
Note that the xfixed_container cannot be resized.
Definition xfixed.hpp:715
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:582
void resize(ST &&shape, layout_type l) const
Note that the xfixed_container cannot be resized.
Definition xfixed.hpp:700
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:643
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:730
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