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 memcpy((
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 GAIA_FOR2(idxSrc, idxDst) {
368 (data_view_policy_soa_set<T::gaia_Data_Layout, T>({std::span<uint8_t>{dst, size}}))[i + n] =
369 (data_view_policy_soa_get<T::gaia_Data_Layout, T>(
370 {std::span<const uint8_t>{(
const uint8_t*)dst, size}}))[i];
373 GAIA_MSVC_WARNING_POP()
378 GAIA_CLANG_WARNING_PUSH()
380 GAIA_CLANG_WARNING_DISABLE("-Wcast-align")
391 template <typename T,
bool SOA = mem::is_soa_layout_v<T>>
392 void copy_ctor_element(
393 uint8_t* GAIA_RESTRICT dst, const uint8_t* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
394 [[maybe_unused]] uint32_t sizeDst, [[maybe_unused]] uint32_t sizeSrc) {
395 if GAIA_UNLIKELY (src == dst && idxSrc == idxDst)
399 detail::copy_ctor_element_aos<T>((T*)dst, (
const T*)src, idxDst, idxSrc);
401 detail::copy_element_soa<T>(dst, src, idxDst, idxSrc, sizeDst, sizeSrc);
414 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
416 uint8_t* GAIA_RESTRICT dst,
const uint8_t* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
417 [[maybe_unused]] uint32_t sizeDst, [[maybe_unused]] uint32_t sizeSrc) {
418 if GAIA_UNLIKELY (src == dst && idxSrc == idxDst)
422 detail::copy_element_aos<T>((T*)dst, (
const T*)src, idxDst, idxSrc);
424 detail::copy_element_soa<T>(dst, src, idxDst, idxSrc, sizeDst, sizeSrc);
437 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
439 uint8_t* GAIA_RESTRICT dst,
const uint8_t* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
440 [[maybe_unused]] uint32_t sizeDst, [[maybe_unused]] uint32_t sizeSrc) {
441 GAIA_ASSERT(idxSrc <= idxDst);
442 if GAIA_UNLIKELY (idxSrc == idxDst)
446 detail::copy_elements_aos<T>((T*)dst, (
const T*)src, idxDst, idxSrc);
448 detail::copy_elements_soa<T>(dst, src, idxDst, idxSrc, sizeDst, sizeSrc);
460 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
461 void move_ctor_element(
462 uint8_t* GAIA_RESTRICT dst, uint8_t* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
463 [[maybe_unused]] uint32_t sizeDst, [[maybe_unused]] uint32_t sizeSrc) {
464 if GAIA_UNLIKELY (src == dst && idxSrc == idxDst)
467 if constexpr (!SOA) {
468 if constexpr (is_movable<T>())
469 detail::move_ctor_element_aos<T>((T*)dst, (T*)src, idxDst, idxSrc);
471 detail::copy_ctor_element_aos<T>((T*)dst, (
const T*)src, idxDst, idxSrc);
473 detail::copy_element_soa<T>(dst, src, idxDst, idxSrc, sizeDst, sizeSrc);
486 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
488 uint8_t* GAIA_RESTRICT dst, uint8_t* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
489 [[maybe_unused]] uint32_t sizeDst, [[maybe_unused]] uint32_t sizeSrc) {
490 if GAIA_UNLIKELY (src == dst && idxSrc == idxDst)
493 if constexpr (!SOA) {
494 if constexpr (is_movable<T>())
495 detail::move_element_aos<T>((T*)dst, (T*)src, idxDst, idxSrc);
497 detail::copy_element_aos<T>((T*)dst, (
const T*)src, idxDst, idxSrc);
499 detail::copy_element_soa<T>(dst, src, idxDst, idxSrc, sizeDst, sizeSrc);
512 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
514 uint8_t* GAIA_RESTRICT dst, uint8_t* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
515 [[maybe_unused]] uint32_t sizeDst, [[maybe_unused]] uint32_t sizeSrc) {
516 GAIA_ASSERT(idxSrc <= idxDst);
517 if GAIA_UNLIKELY (idxSrc == idxDst)
520 if constexpr (!SOA) {
521 if constexpr (is_movable<T>())
522 detail::move_elements_aos<T>((T*)dst, (T*)src, idxDst, idxSrc);
524 detail::copy_elements_aos<T>((T*)dst, (
const T*)src, idxDst, idxSrc);
526 detail::copy_elements_soa<T>(dst, src, idxDst, idxSrc, sizeDst, sizeSrc);
538 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
540 uint8_t* GAIA_RESTRICT dst, uint8_t* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
541 [[maybe_unused]] uint32_t sizeDst, [[maybe_unused]] uint32_t sizeSrc) {
542 if GAIA_UNLIKELY (src == dst && idxSrc == idxDst)
545 if constexpr (!SOA) {
546 if constexpr (is_movable<T>()) {
550 detail::move_element_aos<T>(&tmp, l, 0, idxSrc);
551 detail::move_element_aos<T>(l, r, idxSrc, idxDst);
552 detail::move_element_aos<T>(r, &tmp, idxDst, 0);
557 detail::copy_element_aos<T>(&tmp, l, 0, idxSrc);
558 detail::copy_element_aos<T>(l, r, idxSrc, idxDst);
559 detail::copy_element_aos<T>(r, &tmp, idxDst, 0);
562 T tmp = mem::data_view_policy_soa_get<T::gaia_Data_Layout, T>{std::span{(
const uint8_t*)src, sizeSrc}}[idxSrc];
563 detail::copy_element_soa<T>(src, dst, idxSrc, idxDst, sizeSrc, sizeDst);
564 mem::data_view_policy_soa_set<T::gaia_Data_Layout, T>{std::span{(
const uint8_t*)dst, sizeDst}}[idxDst] = tmp;
575 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
576 void shift_elements_left(uint8_t* dst, uint32_t idxDst, uint32_t idxSrc, [[maybe_unused]] uint32_t size) {
577 GAIA_ASSERT(idxSrc <= idxDst);
578 if GAIA_UNLIKELY (idxSrc == idxDst)
582 detail::shift_elements_left_soa<T>(*dst, idxDst, idxSrc, 1, size);
584 detail::shift_elements_left_aos<T>((T*)dst, idxDst, idxSrc, 1);
595 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
596 void shift_elements_left_fast(
597 uint8_t* dst, uint32_t idxDst, uint32_t idxSrc, uint32_t n, [[maybe_unused]] uint32_t size) {
598 GAIA_ASSERT(idxSrc <= idxDst);
599 if GAIA_UNLIKELY (idxSrc == idxDst)
603 detail::shift_elements_left_soa<T>(*dst, idxDst, idxSrc, n, size);
605 detail::shift_elements_left_aos_fast<T>((T*)dst, idxDst, idxSrc, n);
615 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
616 void shift_elements_right(uint8_t* dst, uint32_t idxDst, uint32_t idxSrc, [[maybe_unused]] uint32_t size) {
617 GAIA_ASSERT(idxSrc <= idxDst);
618 if GAIA_UNLIKELY (idxSrc == idxDst)
622 detail::shift_elements_right_soa<T>(*dst, idxDst, idxSrc, 1, size);
624 detail::shift_elements_right_aos<T>((T*)dst, idxDst, idxSrc, 1);
635 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
636 void shift_elements_right_fast(
637 uint8_t* dst, uint32_t idxDst, uint32_t idxSrc, uint32_t n, [[maybe_unused]] uint32_t size) {
638 GAIA_ASSERT(idxSrc <= idxDst);
639 if GAIA_UNLIKELY (idxSrc == idxDst)
643 detail::shift_elements_right_soa<T>(*dst, idxDst, idxSrc, n, size);
645 detail::shift_elements_right_aos_fast<T>((T*)dst, idxDst, idxSrc, n);
648 GAIA_CLANG_WARNING_POP()