Gaia-ECS v1.0.0
A simple and powerful entity component system
Loading...
Searching...
No Matches
sarray_soa_impl.h
1#pragma once
2#include "gaia/config/config.h"
3
4#include <cstddef>
5#include <new>
6#include <tuple>
7#include <type_traits>
8#include <utility>
9
10#include "gaia/core/iterator.h"
11#include "gaia/core/utility.h"
12#include "gaia/mem/data_layout_policy.h"
13#include "gaia/mem/mem_utils.h"
14#include "gaia/mem/raw_data_holder.h"
15
16namespace gaia {
17 namespace cnt {
19 namespace sarr_soa_detail {
20 using difference_type = uint32_t;
21 using size_type = uint32_t;
22 } // namespace sarr_soa_detail
24
26 template <typename T>
27 struct sarr_soa_iterator {
29 using value_type = T;
30 // using pointer = T*; not supported
31 // using reference = T&; not supported
33 using difference_type = sarr_soa_detail::difference_type;
35 using size_type = sarr_soa_detail::size_type;
36
37 using iterator = sarr_soa_iterator;
39 using iterator_category = core::random_access_iterator_tag;
40
41 private:
42 uint8_t* m_ptr;
43 uint32_t m_cnt;
44 uint32_t m_idx;
45
46 public:
47 sarr_soa_iterator(uint8_t* ptr, uint32_t cnt, uint32_t idx): m_ptr(ptr), m_cnt(cnt), m_idx(idx) {}
48
49 T operator*() const {
50 return mem::data_view_policy<T::gaia_Data_Layout, T>::get({m_ptr, m_cnt}, m_idx);
51 }
52 T operator->() const {
53 return mem::data_view_policy<T::gaia_Data_Layout, T>::get({m_ptr, m_cnt}, m_idx);
54 }
55 iterator operator[](size_type offset) const {
56 return iterator(m_ptr, m_cnt, m_idx + offset);
57 }
58
59 iterator& operator+=(size_type diff) {
60 m_idx += diff;
61 return *this;
62 }
63 iterator& operator-=(size_type diff) {
64 m_idx -= diff;
65 return *this;
66 }
67 iterator& operator++() {
68 ++m_idx;
69 return *this;
70 }
71 iterator operator++(int) {
72 iterator temp(*this);
73 ++*this;
74 return temp;
75 }
76 iterator& operator--() {
77 --m_idx;
78 return *this;
79 }
80 iterator operator--(int) {
81 iterator temp(*this);
82 --*this;
83 return temp;
84 }
85
86 iterator operator+(size_type offset) const {
87 return iterator(m_ptr, m_cnt, m_idx + offset);
88 }
89 iterator operator-(size_type offset) const {
90 return iterator(m_ptr, m_cnt, m_idx + offset);
91 }
92 difference_type operator-(const iterator& other) const {
93 GAIA_ASSERT(m_ptr == other.m_ptr);
94 return (difference_type)(m_idx - other.m_idx);
95 }
96
97 GAIA_NODISCARD bool operator==(const iterator& other) const {
98 GAIA_ASSERT(m_ptr == other.m_ptr);
99 return m_idx == other.m_idx;
100 }
101 GAIA_NODISCARD bool operator!=(const iterator& other) const {
102 GAIA_ASSERT(m_ptr == other.m_ptr);
103 return m_idx != other.m_idx;
104 }
105 GAIA_NODISCARD bool operator>(const iterator& other) const {
106 GAIA_ASSERT(m_ptr == other.m_ptr);
107 return m_idx > other.m_idx;
108 }
109 GAIA_NODISCARD bool operator>=(const iterator& other) const {
110 GAIA_ASSERT(m_ptr == other.m_ptr);
111 return m_idx >= other.m_idx;
112 }
113 GAIA_NODISCARD bool operator<(const iterator& other) const {
114 GAIA_ASSERT(m_ptr == other.m_ptr);
115 return m_idx < other.m_idx;
116 }
117 GAIA_NODISCARD bool operator<=(const iterator& other) const {
118 GAIA_ASSERT(m_ptr == other.m_ptr);
119 return m_idx <= other.m_idx;
120 }
121 };
122
123 template <typename T>
124 struct const_sarr_soa_iterator {
125 using value_type = T;
126 // using pointer = T*; not supported
127 // using reference = T&; not supported
128 using difference_type = sarr_soa_detail::difference_type;
129 using size_type = sarr_soa_detail::size_type;
130
131 using iterator = const_sarr_soa_iterator;
132 using iterator_category = core::random_access_iterator_tag;
133
134 private:
135 const uint8_t* m_ptr;
136 uint32_t m_cnt;
137 uint32_t m_idx;
138
139 public:
140 const_sarr_soa_iterator(const uint8_t* ptr, uint32_t cnt, uint32_t idx): m_ptr(ptr), m_cnt(cnt), m_idx(idx) {}
141
142 T operator*() const {
143 return mem::data_view_policy<T::gaia_Data_Layout, T>::get({m_ptr, m_cnt}, m_idx);
144 }
145 T operator->() const {
146 return mem::data_view_policy<T::gaia_Data_Layout, T>::get({m_ptr, m_cnt}, m_idx);
147 }
148 iterator operator[](size_type offset) const {
149 return iterator(m_ptr, m_cnt, m_idx + offset);
150 }
151
152 iterator& operator+=(size_type diff) {
153 m_idx += diff;
154 return *this;
155 }
156 iterator& operator-=(size_type diff) {
157 m_idx -= diff;
158 return *this;
159 }
160 iterator& operator++() {
161 ++m_idx;
162 return *this;
163 }
164 iterator operator++(int) {
165 iterator temp(*this);
166 ++*this;
167 return temp;
168 }
169 iterator& operator--() {
170 --m_idx;
171 return *this;
172 }
173 iterator operator--(int) {
174 iterator temp(*this);
175 --*this;
176 return temp;
177 }
178
179 iterator operator+(size_type offset) const {
180 return iterator(m_ptr, m_cnt, m_idx + offset);
181 }
182 iterator operator-(size_type offset) const {
183 return iterator(m_ptr, m_cnt, m_idx + offset);
184 }
185 difference_type operator-(const iterator& other) const {
186 GAIA_ASSERT(m_ptr == other.m_ptr);
187 return (difference_type)(m_idx - other.m_idx);
188 }
189
190 GAIA_NODISCARD bool operator==(const iterator& other) const {
191 GAIA_ASSERT(m_ptr == other.m_ptr);
192 return m_idx == other.m_idx;
193 }
194 GAIA_NODISCARD bool operator!=(const iterator& other) const {
195 GAIA_ASSERT(m_ptr == other.m_ptr);
196 return m_idx != other.m_idx;
197 }
198 GAIA_NODISCARD bool operator>(const iterator& other) const {
199 GAIA_ASSERT(m_ptr == other.m_ptr);
200 return m_idx > other.m_idx;
201 }
202 GAIA_NODISCARD bool operator>=(const iterator& other) const {
203 GAIA_ASSERT(m_ptr == other.m_ptr);
204 return m_idx >= other.m_idx;
205 }
206 GAIA_NODISCARD bool operator<(const iterator& other) const {
207 GAIA_ASSERT(m_ptr == other.m_ptr);
208 return m_idx < other.m_idx;
209 }
210 GAIA_NODISCARD bool operator<=(const iterator& other) const {
211 GAIA_ASSERT(m_ptr == other.m_ptr);
212 return m_idx <= other.m_idx;
213 }
214 };
216
221 template <typename T, sarr_soa_detail::size_type N>
222 class sarr_soa {
223 static_assert(mem::is_soa_layout_v<T>, "sarr_soa can be used only with soa types");
224
225 public:
226 static_assert(N > 0);
227
229 using value_type = T;
231 using reference = T&;
233 using const_reference = const T&;
235 using pointer = T*;
237 using const_pointer = T*;
241 using difference_type = sarr_soa_detail::difference_type;
243 using size_type = sarr_soa_detail::size_type;
244
251
253 static constexpr size_type extent = N;
256
258 mem::raw_data_holder<T, allocated_bytes> m_data;
259
261
264 sarr_soa(core::zero_t) noexcept {
265 // explicit zeroing
266 for (auto i = (size_type)0; i < extent; ++i)
267 operator[](i) = {};
268 }
269
270 ~sarr_soa() = default;
271
276 template <typename InputIt>
277 sarr_soa(InputIt first, InputIt last) noexcept {
278 const auto count = (size_type)core::distance(first, last);
279
280 if constexpr (std::is_pointer_v<InputIt>) {
281 for (size_type i = 0; i < count; ++i)
282 operator[](i) = first[i];
283 } else if constexpr (std::is_same_v<typename InputIt::iterator_category, core::random_access_iterator_tag>) {
284 for (size_type i = 0; i < count; ++i)
285 operator[](i) = *(first[i]);
286 } else {
287 size_type i = 0;
288 for (auto it = first; it != last; ++it)
289 operator[](++i) = *it;
290 }
291 }
292
295 sarr_soa(std::initializer_list<T> il): sarr_soa(il.begin(), il.end()) {}
296
299 sarr_soa(const sarr_soa& other): sarr_soa(other.begin(), other.end()) {}
300
303 sarr_soa(sarr_soa&& other) noexcept {
304 GAIA_ASSERT(core::addressof(other) != this);
305
306 mem::move_elements<T, true>((uint8_t*)m_data, (uint8_t*)other.m_data, other.size(), 0, extent, other.extent);
307 }
308
312 sarr_soa& operator=(std::initializer_list<T> il) {
313 *this = sarr_soa(il.begin(), il.end());
314 return *this;
315 }
316
320 sarr_soa& operator=(const sarr_soa& other) {
321 GAIA_ASSERT(core::addressof(other) != this);
322
323 mem::copy_elements<T, true>(
324 GAIA_ACC((uint8_t*)&m_data[0]), GAIA_ACC((const uint8_t*)&other.m_data[0]), other.size(), 0, extent,
325 other.extent);
326
327 return *this;
328 }
329
333 sarr_soa& operator=(sarr_soa&& other) noexcept {
334 GAIA_ASSERT(core::addressof(other) != this);
335
336 mem::move_elements<T, true>(
337 GAIA_ACC((uint8_t*)&m_data[0]), GAIA_ACC((uint8_t*)&other.m_data[0]), other.size(), 0, extent,
338 other.extent);
339
340 return *this;
341 }
342
343 GAIA_CLANG_WARNING_PUSH()
344 // Memory is aligned so we can silence this warning
345 GAIA_CLANG_WARNING_DISABLE("-Wcast-align")
346
349 GAIA_NODISCARD pointer data() noexcept {
350 return GAIA_ACC((pointer)&m_data[0]);
351 }
352
355 GAIA_NODISCARD const_pointer data() const noexcept {
356 return GAIA_ACC((const_pointer)&m_data[0]);
357 }
358
362 GAIA_NODISCARD decltype(auto) operator[](size_type pos) noexcept {
363 GAIA_ASSERT(pos < size());
364 return view_policy::set({GAIA_ACC((typename view_policy::TargetCastType) & m_data[0]), extent}, pos);
365 }
366
370 GAIA_NODISCARD decltype(auto) operator[](size_type pos) const noexcept {
371 GAIA_ASSERT(pos < size());
372 return view_policy::get({GAIA_ACC((typename view_policy::TargetCastType) & m_data[0]), extent}, pos);
373 }
374
375 GAIA_CLANG_WARNING_POP()
376
377
380 return N;
381 }
382
385 GAIA_NODISCARD constexpr bool empty() const noexcept {
386 return false;
387 }
388
391 GAIA_NODISCARD constexpr size_type capacity() const noexcept {
392 return N;
393 }
394
397 GAIA_NODISCARD constexpr size_type max_size() const noexcept {
398 return N;
399 }
400
403 GAIA_NODISCARD decltype(auto) front() noexcept {
404 return *begin();
405 }
406
409 GAIA_NODISCARD decltype(auto) front() const noexcept {
410 return *begin();
411 }
412
415 GAIA_NODISCARD decltype(auto) back() noexcept {
416 return (operator[])(N - 1);
417 }
418
421 GAIA_NODISCARD decltype(auto) back() const noexcept {
422 return operator[](N - 1);
423 }
424
427 GAIA_NODISCARD auto begin() noexcept {
428 return iterator(GAIA_ACC(&m_data[0]), extent, 0);
429 }
430
433 GAIA_NODISCARD auto begin() const noexcept {
434 return const_iterator(GAIA_ACC(&m_data[0]), extent, 0);
435 }
436
439 GAIA_NODISCARD auto cbegin() const noexcept {
440 return const_iterator(GAIA_ACC(&m_data[0]), extent, 0);
441 }
442
445 GAIA_NODISCARD auto rbegin() noexcept {
446 return iterator(GAIA_ACC(&m_data[0]), extent, size() - 1);
447 }
448
451 GAIA_NODISCARD auto rbegin() const noexcept {
452 return const_iterator(m_data, extent, size() - 1);
453 }
454
457 GAIA_NODISCARD auto crbegin() const noexcept {
458 return const_iterator(m_data, extent, size() - 1);
459 }
460
463 GAIA_NODISCARD auto end() noexcept {
464 return iterator(GAIA_ACC(&m_data[0]), extent, size());
465 }
466
469 GAIA_NODISCARD auto end() const noexcept {
470 return const_iterator(GAIA_ACC(&m_data[0]), extent, size());
471 }
472
475 GAIA_NODISCARD auto cend() const noexcept {
476 return const_iterator(GAIA_ACC(&m_data[0]), extent, size());
477 }
478
481 GAIA_NODISCARD auto rend() noexcept {
482 return iterator(GAIA_ACC(&m_data[0]), extent, -1);
483 }
484
487 GAIA_NODISCARD auto rend() const noexcept {
488 return const_iterator(GAIA_ACC(&m_data[0]), extent, -1);
489 }
490
493 GAIA_NODISCARD auto crend() const noexcept {
494 return const_iterator(GAIA_ACC(&m_data[0]), extent, -1);
495 }
496
500 GAIA_NODISCARD bool operator==(const sarr_soa& other) const {
501 for (size_type i = 0; i < N; ++i)
502 if (!(operator[](i) == other[i]))
503 return false;
504 return true;
505 }
506
510 GAIA_NODISCARD bool operator!=(const sarr_soa& other) const {
511 return !operator==(other);
512 }
513
517 template <size_t Item>
520 std::span<uint8_t>{GAIA_ACC((uint8_t*)&m_data[0]), extent});
521 }
522
526 template <size_t Item>
529 std::span<const uint8_t>{GAIA_ACC((const uint8_t*)&m_data[0]), extent});
530 }
531 };
532
534 namespace detail {
535 template <typename T, uint32_t N, uint32_t... I>
536 sarr_soa<std::remove_cv_t<T>, N> to_array_impl(T (&a)[N], std::index_sequence<I...> /*no_name*/) {
537 return {{a[I]...}};
538 }
539 } // namespace detail
541
547 template <typename T, uint32_t N>
548 sarr_soa<std::remove_cv_t<T>, N> to_array(T (&a)[N]) {
549 return detail::to_array_impl(a, std::make_index_sequence<N>{});
550 }
551
555 template <typename T, typename... U>
556 sarr_soa(T, U...) -> sarr_soa<T, 1 + (uint32_t)sizeof...(U)>;
557
558 } // namespace cnt
559} // namespace gaia
560
562namespace std {
563 template <typename T, uint32_t N>
564 struct tuple_size<gaia::cnt::sarr_soa<T, N>>: std::integral_constant<uint32_t, N> {};
565
566 template <size_t I, typename T, uint32_t N>
567 struct tuple_element<I, gaia::cnt::sarr_soa<T, N>> {
568 using type = T;
569 };
570} // namespace std
Array with variable size of elements of type.
Definition darray_impl.h:27
darr_detail::size_type size_type
Unsigned type used for sizes and indices.
Definition darray_impl.h:44
GAIA_NODISCARD decltype(auto) operator[](size_type pos) noexcept
Accesses an element without bounds checking in optimized builds.
Definition darray_impl.h:206
core::random_access_iterator_tag iterator_category
Iterator category exposed by the container.
Definition darray_impl.h:51
GAIA_NODISCARD auto begin() noexcept
Returns an iterator to the first element.
Definition darray_impl.h:556
GAIA_NODISCARD bool operator==(const darr &other) const noexcept
Compares two containers element by element.
Definition darray_impl.h:629
T value_type
Element type stored by the container.
Definition darray_impl.h:30
pointer iterator
Mutable random-access iterator type.
Definition darray_impl.h:47
darr_detail::difference_type difference_type
Type used for iterator differences.
Definition darray_impl.h:42
GAIA_NODISCARD constexpr bool operator!=(const darr &other) const noexcept
Checks whether two containers differ.
Definition darray_impl.h:642
GAIA_NODISCARD auto end() noexcept
Returns an iterator one past the last element.
Definition darray_impl.h:592
Fixed-size stack array with SoA storage. Interface compatiblity with std::array where it matters.
Definition sarray_soa_impl.h:222
GAIA_NODISCARD auto cbegin() const noexcept
Returns a read-only iterator to the first element.
Definition sarray_soa_impl.h:439
GAIA_NODISCARD decltype(auto) operator[](size_type pos) noexcept
Accesses an element without bounds checking in optimized builds.
Definition sarray_soa_impl.h:362
GAIA_NODISCARD auto cend() const noexcept
Returns a read-only iterator one past the last element.
Definition sarray_soa_impl.h:475
GAIA_NODISCARD auto begin() noexcept
Returns an iterator to the first element.
Definition sarray_soa_impl.h:427
auto view() const noexcept
Returns a read-only view of one structure-of-arrays member.
Definition sarray_soa_impl.h:527
sarr_soa_detail::difference_type difference_type
Type used for iterator differences.
Definition sarray_soa_impl.h:241
GAIA_NODISCARD const_pointer data() const noexcept
Returns a pointer to the element storage.
Definition sarray_soa_impl.h:355
GAIA_NODISCARD constexpr size_type size() const noexcept
Returns the number of elements.
Definition sarray_soa_impl.h:379
GAIA_NODISCARD bool operator!=(const sarr_soa &other) const
Checks whether two containers differ.
Definition sarray_soa_impl.h:510
sarr_soa & operator=(const sarr_soa &other)
Copy-assigns the container.
Definition sarray_soa_impl.h:320
GAIA_NODISCARD auto rbegin() const noexcept
Returns a reverse traversal iterator to the last element.
Definition sarray_soa_impl.h:451
static constexpr uint32_t allocated_bytes
Number of bytes reserved by the inline storage.
Definition sarray_soa_impl.h:255
GAIA_NODISCARD decltype(auto) front() noexcept
Accesses the first element.
Definition sarray_soa_impl.h:403
auto view_mut() noexcept
Returns a mutable view of one structure-of-arrays member.
Definition sarray_soa_impl.h:518
GAIA_NODISCARD auto begin() const noexcept
Returns an iterator to the first element.
Definition sarray_soa_impl.h:433
sarr_soa_iterator< T > iterator
Mutable random-access iterator type.
Definition sarray_soa_impl.h:246
GAIA_NODISCARD auto rbegin() noexcept
Returns a reverse traversal iterator to the last element.
Definition sarray_soa_impl.h:445
sarr_soa(std::initializer_list< T > il)
Constructs a container from an initializer list.
Definition sarray_soa_impl.h:295
GAIA_NODISCARD decltype(auto) back() noexcept
Accesses the last element.
Definition sarray_soa_impl.h:415
GAIA_NODISCARD auto end() noexcept
Returns an iterator one past the last element.
Definition sarray_soa_impl.h:463
GAIA_NODISCARD auto crbegin() const noexcept
Returns a read-only reverse traversal iterator to the last element.
Definition sarray_soa_impl.h:457
const_sarr_soa_iterator< T > const_iterator
Read-only random-access iterator type.
Definition sarray_soa_impl.h:248
GAIA_NODISCARD constexpr bool empty() const noexcept
Checks whether the container has no elements.
Definition sarray_soa_impl.h:385
GAIA_NODISCARD pointer data() noexcept
Returns a pointer to the element storage.
Definition sarray_soa_impl.h:349
sarr_soa(const sarr_soa &other)
Copy-constructs a container.
Definition sarray_soa_impl.h:299
GAIA_NODISCARD decltype(auto) front() const noexcept
Accesses the first element.
Definition sarray_soa_impl.h:409
sarr_soa & operator=(std::initializer_list< T > il)
Replaces the elements from an initializer list.
Definition sarray_soa_impl.h:312
GAIA_NODISCARD decltype(auto) back() const noexcept
Accesses the last element.
Definition sarray_soa_impl.h:421
sarr_soa(InputIt first, InputIt last) noexcept
Constructs a container from an iterator range.
Definition sarray_soa_impl.h:277
GAIA_NODISCARD constexpr size_type max_size() const noexcept
Returns the maximum number of elements supported by this container.
Definition sarray_soa_impl.h:397
mem::raw_data_holder< T, allocated_bytes > m_data
Inline storage backing the container elements.
Definition sarray_soa_impl.h:258
sarr_soa_detail::size_type size_type
Unsigned type used for sizes and indices.
Definition sarray_soa_impl.h:243
sarr_soa & operator=(sarr_soa &&other) noexcept
Move-assigns the container.
Definition sarray_soa_impl.h:333
sarr_soa(sarr_soa &&other) noexcept
Move-constructs a container.
Definition sarray_soa_impl.h:303
GAIA_NODISCARD auto end() const noexcept
Returns an iterator one past the last element.
Definition sarray_soa_impl.h:469
GAIA_NODISCARD auto rend() const noexcept
Returns the reverse traversal sentinel preceding the first element.
Definition sarray_soa_impl.h:487
GAIA_NODISCARD auto rend() noexcept
Returns the reverse traversal sentinel preceding the first element.
Definition sarray_soa_impl.h:481
GAIA_NODISCARD constexpr size_type capacity() const noexcept
Returns the number of elements that fit without reallocation.
Definition sarray_soa_impl.h:391
GAIA_NODISCARD auto crend() const noexcept
Returns the read-only reverse traversal sentinel preceding the first element.
Definition sarray_soa_impl.h:493
static constexpr size_type extent
Fixed capacity of the container.
Definition sarray_soa_impl.h:253
GAIA_NODISCARD bool operator==(const sarr_soa &other) const
Compares two containers element by element.
Definition sarray_soa_impl.h:500
View policy for accessing and storing data in the SoA way. Good for SIMD processing.
Definition data_layout_policy.h:402
GAIA_NODISCARD static constexpr ValueType get(std::span< const uint8_t > s, size_t idx) noexcept
Reconstructs a value from its SoA fields.
Definition data_layout_policy.h:530
uint8_t * TargetCastType
Pointer type used to address SoA storage.
Definition data_layout_policy.h:408
GAIA_NODISCARD static constexpr uint32_t get_min_byte_size(uintptr_t addr, size_t cnt) noexcept
Calculates the bytes required for an SoA value range.
Definition data_layout_policy.h:431
GAIA_NODISCARD static constexpr auto set(std::span< uint8_t > s, size_t idx) noexcept
Returns a mutable proxy for one complete value.
Definition data_layout_policy.h:582
Storage policy for a selected layout and item type.
Definition data_layout_policy.h:123