2#include "gaia/config/config.h"
7#include "gaia/core/utility.h"
8#include "gaia/mem/data_layout_policy.h"
13 constexpr bool is_copyable() {
14 return std::is_trivially_copyable_v<T> || std::is_trivially_assignable_v<T, T> ||
15 std::is_copy_assignable_v<T> || std::is_copy_constructible_v<T>;
19 constexpr bool is_movable() {
20 return std::is_trivially_move_assignable_v<T> || std::is_trivially_move_constructible_v<T> ||
21 std::is_move_assignable_v<T> || std::is_move_constructible_v<T>;
26 void copy_ctor_element_aos(T* GAIA_RESTRICT dst,
const T* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc) {
27 GAIA_MSVC_WARNING_PUSH()
28 GAIA_MSVC_WARNING_DISABLE(6385)
30 if constexpr (std::is_trivially_copyable_v<T>) {
31 memcpy(dst + idxDst, src + idxSrc,
sizeof(T));
32 }
else if constexpr (std::is_copy_assignable_v<T>) {
34 core::call_ctor(&dst[idxDst]);
35 dst[idxDst] = src[idxSrc];
37 static_assert(std::is_copy_constructible_v<T>);
38 core::call_ctor(&dst[idxDst], T(src[idxSrc]));
41 GAIA_MSVC_WARNING_POP()
45 void copy_element_aos(T* GAIA_RESTRICT dst,
const T* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc) {
46 GAIA_MSVC_WARNING_PUSH()
47 GAIA_MSVC_WARNING_DISABLE(6385)
49 if constexpr (std::is_trivially_copyable_v<T>) {
50 memcpy(dst + idxDst, src + idxSrc,
sizeof(T));
51 }
else if constexpr (std::is_copy_assignable_v<T>) {
52 dst[idxDst] = src[idxSrc];
54 static_assert(std::is_copy_constructible_v<T>);
55 dst[idxDst] = T(src[idxSrc]);
58 GAIA_MSVC_WARNING_POP()
62 void copy_elements_aos(T* GAIA_RESTRICT dst,
const T* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc) {
63 GAIA_MSVC_WARNING_PUSH()
64 GAIA_MSVC_WARNING_DISABLE(6385)
66 GAIA_ASSERT(idxSrc < idxDst);
68 const auto cnt = idxDst - idxSrc;
70 if constexpr (std::is_trivially_copyable_v<T>) {
71 memcpy(dst + idxSrc, src + idxSrc,
sizeof(T) * cnt);
72 }
else if constexpr (std::is_copy_assignable_v<T>) {
73 const T* s = src + idxSrc;
75 GAIA_FOR(cnt) d[i] = s[i];
77 static_assert(std::is_copy_constructible_v<T>);
78 const T* s = src + idxSrc;
80 GAIA_FOR(cnt) d[i] = T(s[i]);
83 GAIA_MSVC_WARNING_POP()
87 void copy_element_soa(
88 uint8_t* GAIA_RESTRICT dst,
const uint8_t* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
89 uint32_t sizeDst, uint32_t sizeSrc) {
90 GAIA_MSVC_WARNING_PUSH()
91 GAIA_MSVC_WARNING_DISABLE(6385)
93 static_assert(mem::is_soa_layout_v<T>);
95 (data_view_policy_soa_set<T::gaia_Data_Layout, T>({
std::span{dst, sizeDst}}))[idxDst] =
96 (data_view_policy_soa_get<T::gaia_Data_Layout, T>({
std::span{(
const uint8_t*)src, sizeSrc}}))[idxSrc];
98 GAIA_MSVC_WARNING_POP()
101 template <
typename T>
102 void copy_elements_soa(
103 uint8_t* GAIA_RESTRICT dst,
const uint8_t* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
104 uint32_t sizeDst, uint32_t sizeSrc) {
105 GAIA_MSVC_WARNING_PUSH()
106 GAIA_MSVC_WARNING_DISABLE(6385)
108 static_assert(mem::is_soa_layout_v<T>);
110 GAIA_ASSERT(idxSrc < idxDst);
112 GAIA_FOR2(idxSrc, idxDst) {
113 (data_view_policy_soa_set<T::gaia_Data_Layout, T>({
std::span{dst, sizeDst}}))[i] =
114 (data_view_policy_soa_get<T::gaia_Data_Layout, T>({
std::span{(
const uint8_t*)src, sizeSrc}}))[i];
117 GAIA_MSVC_WARNING_POP()
120 template <
typename T>
121 void move_ctor_element_aos(T* GAIA_RESTRICT dst, T* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc) {
122 GAIA_MSVC_WARNING_PUSH()
123 GAIA_MSVC_WARNING_DISABLE(6385)
125 if constexpr (std::is_trivially_move_constructible_v<T> && std::is_trivially_destructible_v<T>) {
126 memcpy(dst + idxDst, src + idxSrc,
sizeof(T));
127 }
else if constexpr (std::is_move_assignable_v<T>) {
128 core::call_ctor(&dst[idxDst]);
129 dst[idxDst] = GAIA_MOV(src[idxSrc]);
131 static_assert(std::is_move_constructible_v<T>);
132 core::call_ctor(&dst[idxDst], T(GAIA_MOV(src[idxSrc])));
135 GAIA_MSVC_WARNING_POP()
138 template <
typename T>
139 void move_element_aos(T* GAIA_RESTRICT dst, T* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc) {
140 GAIA_MSVC_WARNING_PUSH()
141 GAIA_MSVC_WARNING_DISABLE(6385)
143 if constexpr (std::is_trivially_move_assignable_v<T>) {
144 memcpy(dst + idxDst, src + idxSrc,
sizeof(T));
145 }
else if constexpr (std::is_move_assignable_v<T>) {
146 dst[idxDst] = GAIA_MOV(src[idxSrc]);
148 static_assert(std::is_move_constructible_v<T>);
149 dst[idxDst] = T(GAIA_MOV(src[idxSrc]));
152 GAIA_MSVC_WARNING_POP()
155 template <
typename T>
156 void move_elements_aos(T* GAIA_RESTRICT dst, T* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc) {
157 GAIA_MSVC_WARNING_PUSH()
158 GAIA_MSVC_WARNING_DISABLE(6385)
160 GAIA_ASSERT(idxSrc < idxDst);
162 if constexpr (std::is_trivially_move_assignable_v<T>) {
163 memcpy((
void*)&dst[idxSrc], (
const void*)&src[idxSrc],
sizeof(T) * (idxDst - idxSrc));
164 }
else if constexpr (std::is_move_assignable_v<T>) {
165 GAIA_FOR2(idxSrc, idxDst) dst[i] = GAIA_MOV(src[i]);
167 static_assert(std::is_move_constructible_v<T>);
168 GAIA_FOR2(idxSrc, idxDst) dst[i] = T(GAIA_MOV(src[i]));
171 GAIA_MSVC_WARNING_POP()
180 template <
typename T>
181 void shift_elements_left_aos(T* dst, uint32_t idxDst, uint32_t idxSrc, uint32_t n) {
182 GAIA_MSVC_WARNING_PUSH()
183 GAIA_MSVC_WARNING_DISABLE(6385)
185 GAIA_ASSERT(idxSrc < idxDst);
187 if constexpr (std::is_trivially_copy_assignable_v<T> || std::is_trivially_move_assignable_v<T>) {
188 memmove((
void*)&dst[idxSrc], (
const void*)&dst[idxSrc + n],
sizeof(T) * (idxDst - idxSrc));
191 else if constexpr (std::is_move_assignable_v<T>) {
192 GAIA_FOR2(idxSrc, idxDst) dst[i] = GAIA_MOV(dst[i + n]);
193 }
else if constexpr (std::is_move_constructible_v<T>) {
194 GAIA_FOR2(idxSrc, idxDst) dst[i] = T(GAIA_MOV(dst[i + n]));
197 else if constexpr (std::is_copy_assignable_v<T>) {
198 GAIA_FOR2(idxSrc, idxDst) dst[i] = dst[i + n];
199 }
else if constexpr (std::is_copy_constructible_v<T>) {
200 GAIA_FOR2(idxSrc, idxDst) dst[i] = T(dst[i + n]);
202 GAIA_ASSERT(
false &&
"Not implemented");
205 GAIA_MSVC_WARNING_POP()
215 template <
typename T>
216 void shift_elements_left_aos_fast(T* dst, uint32_t idxDst, uint32_t idxSrc, uint32_t n) {
217 GAIA_MSVC_WARNING_PUSH()
218 GAIA_MSVC_WARNING_DISABLE(6385)
220 GAIA_ASSERT(idxSrc < idxDst);
222 const auto max = idxDst - idxSrc - n;
224 if constexpr (std::is_trivially_copy_assignable_v<T> || std::is_trivially_move_assignable_v<T>) {
225 memcpy((
void*)&dst[idxSrc], (
const void*)&dst[idxSrc + n],
sizeof(T) * max);
228 else if constexpr (std::is_move_assignable_v<T>) {
229 GAIA_FOR(max) dst[idxSrc + i] = GAIA_MOV(dst[idxSrc + i + n]);
230 }
else if constexpr (std::is_move_constructible_v<T>) {
231 GAIA_FOR(max) dst[idxSrc + i] = T(GAIA_MOV(dst[idxSrc + i + n]));
234 else if constexpr (std::is_copy_assignable_v<T>) {
235 GAIA_FOR(max) dst[idxSrc + i] = dst[idxSrc + i + n];
236 }
else if constexpr (std::is_copy_constructible_v<T>) {
237 GAIA_FOR(max) dst[idxSrc + i] = T(dst[idxSrc + i + n]);
239 GAIA_ASSERT(
false &&
"Not implemented");
242 GAIA_MSVC_WARNING_POP()
252 template <
typename T>
253 void shift_elements_left_soa(uint8_t* dst, uint32_t idxDst, uint32_t idxSrc, uint32_t n, uint32_t size) {
254 GAIA_MSVC_WARNING_PUSH()
255 GAIA_MSVC_WARNING_DISABLE(6385)
257 static_assert(mem::is_soa_layout_v<T>);
259 GAIA_ASSERT(idxSrc < idxDst);
261 GAIA_FOR2(idxSrc, idxDst) {
262 (data_view_policy_soa_set<T::gaia_Data_Layout, T>({
std::span<uint8_t>{dst, size}}))[i] =
263 (data_view_policy_soa_get<T::gaia_Data_Layout, T>(
267 GAIA_MSVC_WARNING_POP()
276 template <
typename T>
277 void shift_elements_right_aos(T* dst, uint32_t idxDst, uint32_t idxSrc, uint32_t n) {
278 GAIA_MSVC_WARNING_PUSH()
279 GAIA_MSVC_WARNING_DISABLE(6385)
281 GAIA_ASSERT(idxSrc < idxDst);
283 const auto max = idxDst - idxSrc;
284 const auto idx = idxDst - 1;
286 if constexpr (std::is_trivially_copy_assignable_v<T> || std::is_trivially_move_assignable_v<T>) {
287 memmove(dst + idxSrc + n, dst + idxSrc,
sizeof(T) * max);
290 else if constexpr (std::is_move_assignable_v<T>) {
291 GAIA_FOR(max) dst[idx - i + n] = GAIA_MOV(dst[idx - i]);
292 }
else if constexpr (std::is_move_constructible_v<T>) {
293 GAIA_FOR(max) dst[idx - i + n] = T(GAIA_MOV(dst[idx - i]));
296 else if constexpr (std::is_copy_assignable_v<T>) {
297 GAIA_FOR(max) dst[idx - i + n] = dst[idx - i];
298 }
else if constexpr (std::is_copy_constructible_v<T>) {
299 GAIA_FOR(max) dst[idx - i + n] = T(dst[idx - i]);
301 GAIA_ASSERT(
false &&
"Not implemented");
304 GAIA_MSVC_WARNING_POP()
314 template <
typename T>
315 void shift_elements_right_aos_fast(T* dst, uint32_t idxDst, uint32_t idxSrc, uint32_t n) {
316 GAIA_MSVC_WARNING_PUSH()
317 GAIA_MSVC_WARNING_DISABLE(6385)
319 GAIA_ASSERT(idxSrc + n < idxDst);
321 const auto max = idxDst - idxSrc - n;
323 if constexpr (std::is_trivially_copy_assignable_v<T> || std::is_trivially_move_assignable_v<T>) {
324 memcpy(dst + idxSrc + n, dst + idxSrc,
sizeof(T) * max);
327 else if constexpr (std::is_move_assignable_v<T>) {
328 GAIA_FOR(max) dst[idxSrc + i + n] = GAIA_MOV(dst[idxSrc + i]);
329 }
else if constexpr (std::is_move_constructible_v<T>) {
330 GAIA_FOR(max) dst[idxSrc + i + n] = T(GAIA_MOV(dst[idxSrc + i]));
333 else if constexpr (std::is_copy_assignable_v<T>) {
334 GAIA_FOR(max) dst[idxSrc + i + n] = dst[idxSrc + i];
335 }
else if constexpr (std::is_copy_constructible_v<T>) {
336 GAIA_FOR(max) dst[idxSrc + i + n] = T(dst[idxSrc + i]);
338 GAIA_ASSERT(
false &&
"Not implemented");
341 GAIA_MSVC_WARNING_POP()
351 template <
typename T>
352 void shift_elements_right_soa(uint8_t* dst, uint32_t idxDst, uint32_t idxSrc, uint32_t n, uint32_t size) {
353 GAIA_MSVC_WARNING_PUSH()
354 GAIA_MSVC_WARNING_DISABLE(6385)
356 static_assert(mem::is_soa_layout_v<T>);
358 GAIA_ASSERT(idxSrc < idxDst);
360 GAIA_FOR2(idxSrc, idxDst) {
361 (data_view_policy_soa_set<T::gaia_Data_Layout, T>({
std::span<uint8_t>{dst, size}}))[i + n] =
362 (data_view_policy_soa_get<T::gaia_Data_Layout, T>(
366 GAIA_MSVC_WARNING_POP()
370 GAIA_CLANG_WARNING_PUSH()
372 GAIA_CLANG_WARNING_DISABLE("-Wcast-align")
383 template <typename T,
bool SOA = mem::is_soa_layout_v<T>>
384 void copy_ctor_element(
385 uint8_t* GAIA_RESTRICT dst, const uint8_t* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
386 [[maybe_unused]] uint32_t sizeDst, [[maybe_unused]] uint32_t sizeSrc) {
387 if GAIA_UNLIKELY (src == dst && idxSrc == idxDst)
391 detail::copy_ctor_element_aos<T>((T*)dst, (
const T*)src, idxDst, idxSrc);
393 detail::copy_element_soa<T>(dst, src, idxDst, idxSrc, sizeDst, sizeSrc);
406 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
408 uint8_t* GAIA_RESTRICT dst,
const uint8_t* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
409 [[maybe_unused]] uint32_t sizeDst, [[maybe_unused]] uint32_t sizeSrc) {
410 if GAIA_UNLIKELY (src == dst && idxSrc == idxDst)
414 detail::copy_element_aos<T>((T*)dst, (
const T*)src, idxDst, idxSrc);
416 detail::copy_element_soa<T>(dst, src, idxDst, idxSrc, sizeDst, sizeSrc);
429 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
431 uint8_t* GAIA_RESTRICT dst,
const uint8_t* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
432 [[maybe_unused]] uint32_t sizeDst, [[maybe_unused]] uint32_t sizeSrc) {
433 GAIA_ASSERT(idxSrc <= idxDst);
434 if GAIA_UNLIKELY (idxSrc == idxDst)
438 detail::copy_elements_aos<T>((T*)dst, (
const T*)src, idxDst, idxSrc);
440 detail::copy_elements_soa<T>(dst, src, idxDst, idxSrc, sizeDst, sizeSrc);
452 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
453 void move_ctor_element(
454 uint8_t* GAIA_RESTRICT dst, uint8_t* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
455 [[maybe_unused]] uint32_t sizeDst, [[maybe_unused]] uint32_t sizeSrc) {
456 if GAIA_UNLIKELY (src == dst && idxSrc == idxDst)
459 if constexpr (!SOA) {
460 if constexpr (is_movable<T>())
461 detail::move_ctor_element_aos<T>((T*)dst, (T*)src, idxDst, idxSrc);
463 detail::copy_ctor_element_aos<T>((T*)dst, (
const T*)src, idxDst, idxSrc);
465 detail::copy_element_soa<T>(dst, src, idxDst, idxSrc, sizeDst, sizeSrc);
478 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
480 uint8_t* GAIA_RESTRICT dst, uint8_t* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
481 [[maybe_unused]] uint32_t sizeDst, [[maybe_unused]] uint32_t sizeSrc) {
482 if GAIA_UNLIKELY (src == dst && idxSrc == idxDst)
485 if constexpr (!SOA) {
486 if constexpr (is_movable<T>())
487 detail::move_element_aos<T>((T*)dst, (T*)src, idxDst, idxSrc);
489 detail::copy_element_aos<T>((T*)dst, (
const T*)src, idxDst, idxSrc);
491 detail::copy_element_soa<T>(dst, src, idxDst, idxSrc, sizeDst, sizeSrc);
504 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
506 uint8_t* GAIA_RESTRICT dst, uint8_t* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
507 [[maybe_unused]] uint32_t sizeDst, [[maybe_unused]] uint32_t sizeSrc) {
508 GAIA_ASSERT(idxSrc <= idxDst);
509 if GAIA_UNLIKELY (idxSrc == idxDst)
512 if constexpr (!SOA) {
513 if constexpr (is_movable<T>())
514 detail::move_elements_aos<T>((T*)dst, (T*)src, idxDst, idxSrc);
516 detail::copy_elements_aos<T>((T*)dst, (
const T*)src, idxDst, idxSrc);
518 detail::copy_elements_soa<T>(dst, src, idxDst, idxSrc, sizeDst, sizeSrc);
530 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
532 uint8_t* GAIA_RESTRICT dst, uint8_t* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
533 [[maybe_unused]] uint32_t sizeDst, [[maybe_unused]] uint32_t sizeSrc) {
534 if GAIA_UNLIKELY (src == dst && idxSrc == idxDst)
537 if constexpr (!SOA) {
538 if constexpr (is_movable<T>()) {
542 detail::move_element_aos<T>(&tmp, l, 0, idxSrc);
543 detail::move_element_aos<T>(l, r, idxSrc, idxDst);
544 detail::move_element_aos<T>(r, &tmp, idxDst, 0);
549 detail::copy_element_aos<T>(&tmp, l, 0, idxSrc);
550 detail::copy_element_aos<T>(l, r, idxSrc, idxDst);
551 detail::copy_element_aos<T>(r, &tmp, idxDst, 0);
554 T tmp = mem::data_view_policy_soa_get<T::gaia_Data_Layout, T>{
std::span{(
const uint8_t*)src, sizeSrc}}[idxSrc];
555 detail::copy_element_soa<T>(src, dst, idxSrc, idxDst, sizeSrc, sizeDst);
556 mem::data_view_policy_soa_set<T::gaia_Data_Layout, T>{
std::span{(
const uint8_t*)dst, sizeDst}}[idxDst] = tmp;
567 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
568 void shift_elements_left(uint8_t* dst, uint32_t idxDst, uint32_t idxSrc, [[maybe_unused]] uint32_t size) {
569 GAIA_ASSERT(idxSrc <= idxDst);
570 if GAIA_UNLIKELY (idxSrc == idxDst)
574 detail::shift_elements_left_soa<T>(*dst, idxDst, idxSrc, 1, size);
576 detail::shift_elements_left_aos<T>((T*)dst, idxDst, idxSrc, 1);
587 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
588 void shift_elements_left_fast(
589 uint8_t* dst, uint32_t idxDst, uint32_t idxSrc, uint32_t n, [[maybe_unused]] uint32_t size) {
590 GAIA_ASSERT(idxSrc <= idxDst);
591 if GAIA_UNLIKELY (idxSrc == idxDst)
595 detail::shift_elements_left_soa<T>(*dst, idxDst, idxSrc, n, size);
597 detail::shift_elements_left_aos_fast<T>((T*)dst, idxDst, idxSrc, n);
607 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
608 void shift_elements_right(uint8_t* dst, uint32_t idxDst, uint32_t idxSrc, [[maybe_unused]] uint32_t size) {
609 GAIA_ASSERT(idxSrc <= idxDst);
610 if GAIA_UNLIKELY (idxSrc == idxDst)
614 detail::shift_elements_right_soa<T>(*dst, idxDst, idxSrc, 1, size);
616 detail::shift_elements_right_aos<T>((T*)dst, idxDst, idxSrc, 1);
627 template <
typename T,
bool SOA = mem::is_soa_layout_v<T>>
628 void shift_elements_right_fast(
629 uint8_t* dst, uint32_t idxDst, uint32_t idxSrc, uint32_t n, [[maybe_unused]] uint32_t size) {
630 GAIA_ASSERT(idxSrc <= idxDst);
631 if GAIA_UNLIKELY (idxSrc == idxDst)
635 detail::shift_elements_right_soa<T>(*dst, idxDst, idxSrc, n, size);
637 detail::shift_elements_right_aos_fast<T>((T*)dst, idxDst, idxSrc, n);
640 GAIA_CLANG_WARNING_POP()
Definition span_impl.h:99
Checks if endianess was detected correctly at compile-time.
Definition bitset.h:9