2#include "gaia/config/config.h"
7#include "gaia/core/utility.h"
8#include "gaia/mem/data_layout_policy.h"
16 constexpr bool is_copyable() {
17 return std::is_trivially_copyable_v<T> || std::is_trivially_assignable_v<T, T> ||
18 std::is_copy_assignable_v<T> || std::is_copy_constructible_v<T>;
25 constexpr bool is_movable() {
26 return std::is_trivially_move_assignable_v<T> || std::is_trivially_move_constructible_v<T> ||
27 std::is_move_assignable_v<T> || std::is_move_constructible_v<T>;
33 void copy_ctor_element_aos(T* GAIA_RESTRICT dst,
const T* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc) {
34 GAIA_MSVC_WARNING_PUSH()
35 GAIA_MSVC_WARNING_DISABLE(6385)
37 if constexpr (std::is_trivially_copyable_v<T>) {
38 memcpy(dst + idxDst, src + idxSrc,
sizeof(T));
39 }
else if constexpr (std::is_copy_assignable_v<T>) {
41 core::call_ctor(&dst[idxDst]);
42 dst[idxDst] = src[idxSrc];
44 static_assert(std::is_copy_constructible_v<T>);
45 core::call_ctor(&dst[idxDst], T(src[idxSrc]));
48 GAIA_MSVC_WARNING_POP()
52 void copy_element_aos(T* GAIA_RESTRICT dst,
const T* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc) {
53 GAIA_MSVC_WARNING_PUSH()
54 GAIA_MSVC_WARNING_DISABLE(6385)
56 if constexpr (std::is_trivially_copyable_v<T>) {
57 memcpy(dst + idxDst, src + idxSrc,
sizeof(T));
58 }
else if constexpr (std::is_copy_assignable_v<T>) {
59 dst[idxDst] = src[idxSrc];
61 static_assert(std::is_copy_constructible_v<T>);
62 dst[idxDst] = T(src[idxSrc]);
65 GAIA_MSVC_WARNING_POP()
69 void copy_elements_aos(T* GAIA_RESTRICT dst,
const T* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc) {
70 GAIA_MSVC_WARNING_PUSH()
71 GAIA_MSVC_WARNING_DISABLE(6385)
73 GAIA_ASSERT(idxSrc < idxDst);
75 const auto cnt = idxDst - idxSrc;
77 if constexpr (std::is_trivially_copyable_v<T>) {
78 memcpy(dst + idxSrc, src + idxSrc,
sizeof(T) * cnt);
79 }
else if constexpr (std::is_copy_assignable_v<T>) {
80 const T* s = src + idxSrc;
82 GAIA_FOR(cnt) d[i] = s[i];
84 static_assert(std::is_copy_constructible_v<T>);
85 const T* s = src + idxSrc;
87 GAIA_FOR(cnt) d[i] = T(s[i]);
90 GAIA_MSVC_WARNING_POP()
94 void copy_element_soa(
95 uint8_t* GAIA_RESTRICT dst,
const uint8_t* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
96 uint32_t sizeDst, uint32_t sizeSrc) {
97 GAIA_MSVC_WARNING_PUSH()
98 GAIA_MSVC_WARNING_DISABLE(6385)
100 static_assert(mem::is_soa_layout_v<T>);
102 (data_view_policy_soa_set<T::gaia_Data_Layout, T>({std::span{dst, sizeDst}}))[idxDst] =
103 (data_view_policy_soa_get<T::gaia_Data_Layout, T>({std::span{(
const uint8_t*)src, sizeSrc}}))[idxSrc];
105 GAIA_MSVC_WARNING_POP()
108 template <
typename T>
109 void copy_elements_soa(
110 uint8_t* GAIA_RESTRICT dst,
const uint8_t* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
111 uint32_t sizeDst, uint32_t sizeSrc) {
112 GAIA_MSVC_WARNING_PUSH()
113 GAIA_MSVC_WARNING_DISABLE(6385)
115 static_assert(mem::is_soa_layout_v<T>);
117 GAIA_ASSERT(idxSrc < idxDst);
119 GAIA_FOR2(idxSrc, idxDst) {
120 (data_view_policy_soa_set<T::gaia_Data_Layout, T>({std::span{dst, sizeDst}}))[i] =
121 (data_view_policy_soa_get<T::gaia_Data_Layout, T>({std::span{(
const uint8_t*)src, sizeSrc}}))[i];
124 GAIA_MSVC_WARNING_POP()
127 template <
typename T>
128 void move_ctor_element_aos(T* GAIA_RESTRICT dst, T* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc) {
129 GAIA_MSVC_WARNING_PUSH()
130 GAIA_MSVC_WARNING_DISABLE(6385)
132 if constexpr (std::is_trivially_move_constructible_v<T> && std::is_trivially_destructible_v<T>) {
133 memcpy(dst + idxDst, src + idxSrc,
sizeof(T));
134 }
else if constexpr (std::is_move_assignable_v<T>) {
135 core::call_ctor(&dst[idxDst]);
136 dst[idxDst] = GAIA_MOV(src[idxSrc]);
138 static_assert(std::is_move_constructible_v<T>);
139 core::call_ctor(&dst[idxDst], T(GAIA_MOV(src[idxSrc])));
142 GAIA_MSVC_WARNING_POP()
145 template <
typename T>
146 void move_element_aos(T* GAIA_RESTRICT dst, T* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc) {
147 GAIA_MSVC_WARNING_PUSH()
148 GAIA_MSVC_WARNING_DISABLE(6385)
150 if constexpr (std::is_trivially_move_assignable_v<T>) {
151 memcpy(dst + idxDst, src + idxSrc,
sizeof(T));
152 }
else if constexpr (std::is_move_assignable_v<T>) {
153 dst[idxDst] = GAIA_MOV(src[idxSrc]);
155 static_assert(std::is_move_constructible_v<T>);
156 dst[idxDst] = T(GAIA_MOV(src[idxSrc]));
159 GAIA_MSVC_WARNING_POP()
162 template <
typename T>
163 void move_elements_aos(T* GAIA_RESTRICT dst, T* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc) {
164 GAIA_MSVC_WARNING_PUSH()
165 GAIA_MSVC_WARNING_DISABLE(6385)
167 GAIA_ASSERT(idxSrc < idxDst);
169 if constexpr (std::is_trivially_move_assignable_v<T>) {
170 memcpy((
void*)&dst[idxSrc], (
const void*)&src[idxSrc],
sizeof(T) * (idxDst - idxSrc));
171 }
else if constexpr (std::is_move_assignable_v<T>) {
172 GAIA_FOR2(idxSrc, idxDst) dst[i] = GAIA_MOV(src[i]);
174 static_assert(std::is_move_constructible_v<T>);
175 GAIA_FOR2(idxSrc, idxDst) dst[i] = T(GAIA_MOV(src[i]));
178 GAIA_MSVC_WARNING_POP()
187 template <
typename T>
188 void shift_elements_left_aos(T* dst, uint32_t idxDst, uint32_t idxSrc, uint32_t n) {
189 GAIA_MSVC_WARNING_PUSH()
190 GAIA_MSVC_WARNING_DISABLE(6385)
192 GAIA_ASSERT(idxSrc < idxDst);
194 if constexpr (std::is_trivially_copy_assignable_v<T> || std::is_trivially_move_assignable_v<T>) {
195 memmove((
void*)&dst[idxSrc], (
const void*)&dst[idxSrc + n],
sizeof(T) * (idxDst - idxSrc));
198 else if constexpr (std::is_move_assignable_v<T>) {
199 GAIA_FOR2(idxSrc, idxDst) dst[i] = GAIA_MOV(dst[i + n]);
200 }
else if constexpr (std::is_move_constructible_v<T>) {
201 GAIA_FOR2(idxSrc, idxDst) dst[i] = T(GAIA_MOV(dst[i + n]));
204 else if constexpr (std::is_copy_assignable_v<T>) {
205 GAIA_FOR2(idxSrc, idxDst) dst[i] = dst[i + n];
206 }
else if constexpr (std::is_copy_constructible_v<T>) {
207 GAIA_FOR2(idxSrc, idxDst) dst[i] = T(dst[i + n]);
209 GAIA_ASSERT(
false &&
"Not implemented");
212 GAIA_MSVC_WARNING_POP()
222 template <
typename T>
223 void shift_elements_left_aos_fast(T* dst, uint32_t idxDst, uint32_t idxSrc, uint32_t n) {
224 GAIA_MSVC_WARNING_PUSH()
225 GAIA_MSVC_WARNING_DISABLE(6385)
227 GAIA_ASSERT(idxSrc < idxDst);
229 const auto max = idxDst - idxSrc - n;
231 if constexpr (std::is_trivially_copy_assignable_v<T> || std::is_trivially_move_assignable_v<T>) {
232 memmove((
void*)&dst[idxSrc], (
const void*)&dst[idxSrc + n],
sizeof(T) * max);
235 else if constexpr (std::is_move_assignable_v<T>) {
236 GAIA_FOR(max) dst[idxSrc + i] = GAIA_MOV(dst[idxSrc + i + n]);
237 }
else if constexpr (std::is_move_constructible_v<T>) {
238 GAIA_FOR(max) dst[idxSrc + i] = T(GAIA_MOV(dst[idxSrc + i + n]));
241 else if constexpr (std::is_copy_assignable_v<T>) {
242 GAIA_FOR(max) dst[idxSrc + i] = dst[idxSrc + i + n];
243 }
else if constexpr (std::is_copy_constructible_v<T>) {
244 GAIA_FOR(max) dst[idxSrc + i] = T(dst[idxSrc + i + n]);
246 GAIA_ASSERT(
false &&
"Not implemented");
249 GAIA_MSVC_WARNING_POP()
259 template <
typename T>
260 void shift_elements_left_soa(uint8_t* dst, uint32_t idxDst, uint32_t idxSrc, uint32_t n, uint32_t size) {
261 GAIA_MSVC_WARNING_PUSH()
262 GAIA_MSVC_WARNING_DISABLE(6385)
264 static_assert(mem::is_soa_layout_v<T>);
266 GAIA_ASSERT(idxSrc < idxDst);
268 GAIA_FOR2(idxSrc, idxDst) {
269 (data_view_policy_soa_set<T::gaia_Data_Layout, T>({std::span<uint8_t>{dst, size}}))[i] =
270 (data_view_policy_soa_get<T::gaia_Data_Layout, T>(
271 {std::span<const uint8_t>{(
const uint8_t*)dst, size}}))[i + n];
274 GAIA_MSVC_WARNING_POP()
283 template <
typename T>
284 void shift_elements_right_aos(T* dst, uint32_t idxDst, uint32_t idxSrc, uint32_t n) {
285 GAIA_MSVC_WARNING_PUSH()
286 GAIA_MSVC_WARNING_DISABLE(6385)
288 GAIA_ASSERT(idxSrc < idxDst);
290 const auto max = idxDst - idxSrc;
291 const auto idx = idxDst - 1;
293 if constexpr (std::is_trivially_copy_assignable_v<T> || std::is_trivially_move_assignable_v<T>) {
294 memmove(dst + idxSrc + n, dst + idxSrc,
sizeof(T) * max);
297 else if constexpr (std::is_move_assignable_v<T>) {
298 GAIA_FOR(max) dst[idx - i + n] = GAIA_MOV(dst[idx - i]);
299 }
else if constexpr (std::is_move_constructible_v<T>) {
300 GAIA_FOR(max) dst[idx - i + n] = T(GAIA_MOV(dst[idx - i]));
303 else if constexpr (std::is_copy_assignable_v<T>) {
304 GAIA_FOR(max) dst[idx - i + n] = dst[idx - i];
305 }
else if constexpr (std::is_copy_constructible_v<T>) {
306 GAIA_FOR(max) dst[idx - i + n] = T(dst[idx - i]);
308 GAIA_ASSERT(
false &&
"Not implemented");
311 GAIA_MSVC_WARNING_POP()
321 template <
typename T>
322 void shift_elements_right_aos_fast(T* dst, uint32_t idxDst, uint32_t idxSrc, uint32_t n) {
323 GAIA_MSVC_WARNING_PUSH()
324 GAIA_MSVC_WARNING_DISABLE(6385)
326 GAIA_ASSERT(idxSrc + n < idxDst);
328 const auto max = idxDst - idxSrc - n;
330 if constexpr (std::is_trivially_copy_assignable_v<T> || std::is_trivially_move_assignable_v<T>) {
331 memcpy(dst + idxSrc + n, dst + idxSrc,
sizeof(T) * max);
334 else if constexpr (std::is_move_assignable_v<T>) {
335 GAIA_FOR(max) dst[idxSrc + i + n] = GAIA_MOV(dst[idxSrc + i]);
336 }
else if constexpr (std::is_move_constructible_v<T>) {
337 GAIA_FOR(max) dst[idxSrc + i + n] = T(GAIA_MOV(dst[idxSrc + i]));
340 else if constexpr (std::is_copy_assignable_v<T>) {
341 GAIA_FOR(max) dst[idxSrc + i + n] = dst[idxSrc + i];
342 }
else if constexpr (std::is_copy_constructible_v<T>) {
343 GAIA_FOR(max) dst[idxSrc + i + n] = T(dst[idxSrc + i]);
345 GAIA_ASSERT(
false &&
"Not implemented");
348 GAIA_MSVC_WARNING_POP()
358 template <
typename T>
359 void shift_elements_right_soa(uint8_t* dst, uint32_t idxDst, uint32_t idxSrc, uint32_t n, uint32_t size) {
360 GAIA_MSVC_WARNING_PUSH()
361 GAIA_MSVC_WARNING_DISABLE(6385)
363 static_assert(mem::is_soa_layout_v<T>);
365 GAIA_ASSERT(idxSrc < idxDst);
367 const auto count = idxDst - idxSrc;
369 const auto idx = idxDst - i - 1;
370 (data_view_policy_soa_set<T::gaia_Data_Layout, T>({std::span<uint8_t>{dst, size}}))[idx + n] =
371 (data_view_policy_soa_get<T::gaia_Data_Layout, T>(
372 {std::span<const uint8_t>{(
const uint8_t*)dst, size}}))[idx];
375 GAIA_MSVC_WARNING_POP()
380 GAIA_CLANG_WARNING_PUSH()
382 GAIA_CLANG_WARNING_DISABLE("-Wcast-align")
393 template <typename T,
bool SOA = mem::is_soa_layout_v<T>>
394 void copy_ctor_element(
395 uint8_t* GAIA_RESTRICT dst, const uint8_t* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
396 [[maybe_unused]] uint32_t sizeDst, [[maybe_unused]] uint32_t sizeSrc) {
397 if GAIA_UNLIKELY (src == dst && idxSrc == idxDst)
401 detail::copy_ctor_element_aos<T>((T*)dst, (
const T*)src, idxDst, idxSrc);
403 detail::copy_element_soa<T>(dst, src, idxDst, idxSrc, sizeDst, sizeSrc);
416 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
418 uint8_t* GAIA_RESTRICT dst,
const uint8_t* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
419 [[maybe_unused]] uint32_t sizeDst, [[maybe_unused]] uint32_t sizeSrc) {
420 if GAIA_UNLIKELY (src == dst && idxSrc == idxDst)
424 detail::copy_element_aos<T>((T*)dst, (
const T*)src, idxDst, idxSrc);
426 detail::copy_element_soa<T>(dst, src, idxDst, idxSrc, sizeDst, sizeSrc);
439 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
441 uint8_t* GAIA_RESTRICT dst,
const uint8_t* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
442 [[maybe_unused]] uint32_t sizeDst, [[maybe_unused]] uint32_t sizeSrc) {
443 GAIA_ASSERT(idxSrc <= idxDst);
444 if GAIA_UNLIKELY (idxSrc == idxDst)
448 detail::copy_elements_aos<T>((T*)dst, (
const T*)src, idxDst, idxSrc);
450 detail::copy_elements_soa<T>(dst, src, idxDst, idxSrc, sizeDst, sizeSrc);
463 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
464 void move_ctor_element(
465 uint8_t* GAIA_RESTRICT dst, uint8_t* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
466 [[maybe_unused]] uint32_t sizeDst, [[maybe_unused]] uint32_t sizeSrc) {
467 if GAIA_UNLIKELY (src == dst && idxSrc == idxDst)
470 if constexpr (!SOA) {
471 if constexpr (is_movable<T>())
472 detail::move_ctor_element_aos<T>((T*)dst, (T*)src, idxDst, idxSrc);
474 detail::copy_ctor_element_aos<T>((T*)dst, (
const T*)src, idxDst, idxSrc);
476 detail::copy_element_soa<T>(dst, src, idxDst, idxSrc, sizeDst, sizeSrc);
490 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
492 uint8_t* dst, uint8_t* src, uint32_t idxDst, uint32_t idxSrc,
493 [[maybe_unused]] uint32_t sizeDst, [[maybe_unused]] uint32_t sizeSrc) {
494 if GAIA_UNLIKELY (src == dst && idxSrc == idxDst)
497 if constexpr (!SOA) {
498 if constexpr (is_movable<T>())
499 detail::move_element_aos<T>((T*)dst, (T*)src, idxDst, idxSrc);
501 detail::copy_element_aos<T>((T*)dst, (
const T*)src, idxDst, idxSrc);
503 detail::copy_element_soa<T>(dst, src, idxDst, idxSrc, sizeDst, sizeSrc);
518 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
520 uint8_t* GAIA_RESTRICT dst, uint8_t* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
521 [[maybe_unused]] uint32_t sizeDst, [[maybe_unused]] uint32_t sizeSrc) {
522 GAIA_ASSERT(idxSrc <= idxDst);
523 if GAIA_UNLIKELY (idxSrc == idxDst)
526 if constexpr (!SOA) {
527 if constexpr (is_movable<T>())
528 detail::move_elements_aos<T>((T*)dst, (T*)src, idxDst, idxSrc);
530 detail::copy_elements_aos<T>((T*)dst, (
const T*)src, idxDst, idxSrc);
532 detail::copy_elements_soa<T>(dst, src, idxDst, idxSrc, sizeDst, sizeSrc);
541 template <
typename T>
542 void move_ctor_elements(uint8_t* dst, uint8_t* src, uint32_t count) {
545 if constexpr (std::is_trivially_copyable_v<T>) {
546 memcpy(dst, src,
sizeof(T) * count);
549 if constexpr (std::is_move_constructible_v<T>)
550 core::call_ctor(&((T*)dst)[i], GAIA_MOV(((T*)src)[i]));
551 else if constexpr (std::is_copy_constructible_v<T>)
552 core::call_ctor(&((T*)dst)[i], ((
const T*)src)[i]);
554 move_ctor_element<T, false>(dst, src, i, i, count, count);
568 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
570 uint8_t* GAIA_RESTRICT dst, uint8_t* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
571 [[maybe_unused]] uint32_t sizeDst, [[maybe_unused]] uint32_t sizeSrc) {
572 if GAIA_UNLIKELY (src == dst && idxSrc == idxDst)
575 if constexpr (!SOA) {
576 if constexpr (is_movable<T>()) {
580 detail::move_element_aos<T>(&tmp, l, 0, idxSrc);
581 detail::move_element_aos<T>(l, r, idxSrc, idxDst);
582 detail::move_element_aos<T>(r, &tmp, idxDst, 0);
587 detail::copy_element_aos<T>(&tmp, l, 0, idxSrc);
588 detail::copy_element_aos<T>(l, r, idxSrc, idxDst);
589 detail::copy_element_aos<T>(r, &tmp, idxDst, 0);
592 T tmp = mem::data_view_policy_soa_get<T::gaia_Data_Layout, T>{std::span{(
const uint8_t*)src, sizeSrc}}[idxSrc];
593 detail::copy_element_soa<T>(src, dst, idxSrc, idxDst, sizeSrc, sizeDst);
594 mem::data_view_policy_soa_set<T::gaia_Data_Layout, T>{std::span{(
const uint8_t*)dst, sizeDst}}[idxDst] = tmp;
605 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
606 void shift_elements_left(uint8_t* dst, uint32_t idxDst, uint32_t idxSrc, [[maybe_unused]] uint32_t size) {
607 GAIA_ASSERT(idxSrc <= idxDst);
608 if GAIA_UNLIKELY (idxSrc == idxDst)
612 detail::shift_elements_left_soa<T>(dst, idxDst, idxSrc, 1, size);
614 detail::shift_elements_left_aos<T>((T*)dst, idxDst, idxSrc, 1);
625 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
626 void shift_elements_left_fast(
627 uint8_t* dst, uint32_t idxDst, uint32_t idxSrc, uint32_t n, [[maybe_unused]] uint32_t size) {
628 GAIA_ASSERT(idxSrc <= idxDst);
629 if GAIA_UNLIKELY (idxSrc == idxDst)
633 if (idxSrc + n < idxDst)
634 detail::shift_elements_left_soa<T>(dst, idxDst - n, idxSrc, n, size);
636 detail::shift_elements_left_aos_fast<T>((T*)dst, idxDst, idxSrc, n);
646 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
647 void shift_elements_right(uint8_t* dst, uint32_t idxDst, uint32_t idxSrc, [[maybe_unused]] uint32_t size) {
648 GAIA_ASSERT(idxSrc <= idxDst);
649 if GAIA_UNLIKELY (idxSrc == idxDst)
653 detail::shift_elements_right_soa<T>(dst, idxDst, idxSrc, 1, size);
655 detail::shift_elements_right_aos<T>((T*)dst, idxDst, idxSrc, 1);
666 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
667 void shift_elements_right_fast(
668 uint8_t* dst, uint32_t idxDst, uint32_t idxSrc, uint32_t n, [[maybe_unused]] uint32_t size) {
669 GAIA_ASSERT(idxSrc <= idxDst);
670 if GAIA_UNLIKELY (idxSrc == idxDst)
674 detail::shift_elements_right_soa<T>(dst, idxDst, idxSrc, n, size);
676 detail::shift_elements_right_aos_fast<T>((T*)dst, idxDst, idxSrc, n);
679 GAIA_CLANG_WARNING_POP()