3#if __has_include(<version.h>)
17#if !defined(GAIA_DEVMODE)
18 #define GAIA_DEVMODE 0
20#if !defined(GAIA_USE_SANITIZER)
21 #define GAIA_USE_SANITIZER 0
28#if defined(_MSVC_LANG)
29 #define GAIA_CPP_VERSION(version) (__cplusplus >= (version) || _MSVC_LANG >= (version))
31 #define GAIA_CPP_VERSION(version) (__cplusplus >= (version))
34#if GAIA_CPP_VERSION(201703L)
38 #error "To build Gaia-ECS a compiler capable of at least C++17 is necessary"
41#define GAIA_USE_STD_SPAN (GAIA_CPP_VERSION(202002L) && __has_include(<span>))
47#define GAIA_ECS_HASH_FNV1A 0
48#define GAIA_ECS_HASH_MURMUR2A 1
53#define GAIA_COMPILER_CLANG 0
54#define GAIA_COMPILER_GCC 0
55#define GAIA_COMPILER_MSVC 0
56#define GAIA_COMPILER_ICC 0
57#define GAIA_COMPILER_DETECTED 0
59#if !GAIA_COMPILER_DETECTED && (defined(__clang__))
62 #undef GAIA_COMPILER_CLANG
63 #define GAIA_COMPILER_CLANG 1
64 #undef GAIA_COMPILER_DETECTED
65 #define GAIA_COMPILER_DETECTED 1
69 #undef GAIA_COMPILER_MSVC
70 #define GAIA_COMPILER_MSVC 1
73#if !GAIA_COMPILER_DETECTED && \
74 (defined(__INTEL_COMPILER) || defined(__ICC) || defined(__ICL) || defined(__INTEL_LLVM_COMPILER))
75 #undef GAIA_COMPILER_ICC
76 #define GAIA_COMPILER_ICC 1
77 #undef GAIA_COMPILER_DETECTED
78 #define GAIA_COMPILER_DETECTED 1
80#if !GAIA_COMPILER_DETECTED && (defined(__SNC__) || defined(__GNUC__))
81 #undef GAIA_COMPILER_GCC
82 #define GAIA_COMPILER_GCC 1
83 #undef GAIA_COMPILER_DETECTED
84 #define GAIA_COMPILER_DETECTED 1
86#if !GAIA_COMPILER_DETECTED && (defined(_MSC_VER))
87 #undef GAIA_COMPILER_MSVC
88 #define GAIA_COMPILER_MSVC 1
89 #undef GAIA_COMPILER_DETECTED
90 #define GAIA_COMPILER_DETECTED 1
92#if !GAIA_COMPILER_DETECTED
93 #error "Unrecognized compiler"
100#define GAIA_PLATFORM_UNKNOWN 0
101#define GAIA_PLATFORM_WINDOWS 0
102#define GAIA_PLATFORM_LINUX 0
103#define GAIA_PLATFORM_APPLE 0
104#define GAIA_PLATFORM_FREEBSD 0
105#define GAIA_PLATFORM_WASM 0
108 #undef GAIA_PLATFORM_WINDOWS
109 #define GAIA_PLATFORM_WINDOWS 1
114 #undef GAIA_PLATFORM_APPLE
115 #define GAIA_PLATFORM_APPLE 1
117 #undef GAIA_PLATFORM_LINUX
118 #define GAIA_PLATFORM_LINUX 1
120 #undef GAIA_PLATFORM_FREEBSD
121 #define GAIA_PLATFORM_FREEBSD 1
122#elif defined(__EMSCRIPTEN__)
123 #undef GAIA_PLATFORM_WASM
124 #define GAIA_PLATFORM_WASM 1
126 #undef GAIA_PLATFORM_UNKNOWN
127 #define GAIA_PLATFORM_UNKNOWN 1
134#if defined(_WIN64) || defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64) || defined(__amd64) || \
140#define GAIA_ARCH_X86 0
141#define GAIA_ARCH_ARM 1
142#define GAIA_ARCH_WASM 2
144#if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__i386) || \
145 defined(i386) || defined(__x86_64__) || defined(_X86_)
147 #define GAIA_ARCH GAIA_ARCH_X86
148#elif defined(__arm__) || defined(__aarch64__) || defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC)
150 #define GAIA_ARCH GAIA_ARCH_ARM
151#elif defined(__EMSCRIPTEN__) || defined(__wasm__) || defined(__wasm32__) || defined(__wasm64__)
153 #define GAIA_ARCH GAIA_ARCH_WASM
155 #error "Unrecognized target architecture."
160#if GAIA_COMPILER_MSVC && !GAIA_COMPILER_CLANG
161 #define GAIA_PRETTY_FUNCTION __FUNCSIG__
162 #define GAIA_PRETTY_FUNCTION_PREFIX '<'
163 #define GAIA_PRETTY_FUNCTION_SUFFIX '>'
165 #define GAIA_PRETTY_FUNCTION __PRETTY_FUNCTION__
166 #define GAIA_PRETTY_FUNCTION_PREFIX '='
167 #define GAIA_PRETTY_FUNCTION_SUFFIX ']'
170#define GAIA_STRINGIZE(x) #x
171#define GAIA_CONCAT_IMPL(x, y) x##y
172#define GAIA_CONCAT(x, y) GAIA_CONCAT_IMPL(x, y)
174#define GAIA_FOR(max) for (uint32_t i = 0; i < (max); ++i)
175#define GAIA_FOR_(max, varname) for (uint32_t varname = 0; varname < (max); ++varname)
176#define GAIA_FOR2(min, max) for (uint32_t i = (min); i < (max); ++i)
177#define GAIA_FOR2_(min, max, varname) for (uint32_t varname = (min); varname < (max); ++varname)
178#define GAIA_EACH(container) for (uint32_t i = 0; i < (container).size(); ++i)
179#define GAIA_EACH_(container, varname) for (uint32_t varname = 0; varname < (container).size(); ++varname)
188#if GAIA_COMPILER_MSVC
192 #define GAIA_LITTLE_ENDIAN true
193 #define GAIA_BIG_ENDIAN false
195 #define GAIA_LITTLE_ENDIAN (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
196 #define GAIA_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
203 inline bool CheckEndianess() {
204 const uint16_t testWord = 0x1234;
205 const bool isLittleEndian(*
reinterpret_cast<const uint8_t*
>(&testWord) == 0x34);
206 return isLittleEndian && GAIA_LITTLE_ENDIAN;
215#define GAIA_MOV(x) static_cast<typename std::remove_reference<decltype(x)>::type&&>(x)
222#define GAIA_FWD(x) static_cast<decltype(x)&&>(x)
227#define GAIA_FWD_AS(T, x) static_cast<T&&>(x)
229#define GAIA_ACC(x) std::launder(x)
231#if (GAIA_COMPILER_MSVC && _MSC_VER >= 1400) || GAIA_COMPILER_GCC || GAIA_COMPILER_CLANG
232 #define GAIA_RESTRICT __restrict
234 #define GAIA_RESTRICT
237#if GAIA_CPP_VERSION(202002L)
238 #if __has_cpp_attribute(nodiscard)
239 #define GAIA_NODISCARD [[nodiscard]]
241 #if __has_cpp_attribute(likely)
242 #define GAIA_LIKELY(cond) (cond) [[likely]]
244 #if __has_cpp_attribute(unlikely)
245 #define GAIA_UNLIKELY(cond) (cond) [[unlikely]]
247 #if __has_cpp_attribute(fallthrough)
248 #define GAIA_FALLTHROUGH [[fallthrough]]
251#ifndef GAIA_NODISCARD
252 #define GAIA_NODISCARD
254#if !defined(GAIA_LIKELY) && (GAIA_COMPILER_GCC || GAIA_COMPILER_CLANG)
255 #define GAIA_LIKELY(cond) (__builtin_expect((cond), 1))
257#if !defined(GAIA_UNLIKELY) && (GAIA_COMPILER_GCC || GAIA_COMPILER_CLANG)
258 #define GAIA_UNLIKELY(cond) (__builtin_expect((cond), 0))
261 #define GAIA_LIKELY(cond) (cond)
264 #define GAIA_UNLIKELY(cond) (cond)
266#ifndef GAIA_FALLTHROUGH
267 #define GAIA_FALLTHROUGH
270#ifndef GAIA_CACHELINE_SIZE
271 #ifdef __cpp_lib_hardware_interference_size
272 #define GAIA_CACHELINE_SIZE std::hardware_constructive_interference_size
273 #elif defined(__GCC_DESTRUCTIVE_SIZE)
274 #define GAIA_CACHELINE_SIZE __GCC_DESTRUCTIVE_SIZE
276 #if GAIA_ARCH == GAIA_ARCH_ARM
282 #define GAIA_CACHELINE_SIZE 128
284 #define GAIA_CACHELINE_SIZE 64
294#if GAIA_ARCH == GAIA_ARCH_X86
295 #include <immintrin.h>
296 #define GAIA_YIELD_CPU _mm_pause()
297#elif GAIA_ARCH == GAIA_ARCH_ARM
298 #if GAIA_COMPILER_CLANG
299 #define GAIA_YIELD_CPU __builtin_arm_yield()
300 #elif GAIA_COMPILER_GCC
301 #define GAIA_YIELD_CPU __asm__ volatile("yield" ::: "memory");
304#if !defined(GAIA_YIELD_CPU)
305 #define GAIA_YIELD_CPU \
310#if GAIA_COMPILER_CLANG || GAIA_COMPILER_GCC
312 #define GAIA_POPCNT(x) ((uint32_t)__builtin_popcount(static_cast<uint32_t>(x)))
314 #define GAIA_POPCNT64(x) ((uint32_t)__builtin_popcountll(static_cast<unsigned long long>(x)))
318 #define GAIA_CLZ(x) ((x) ? (uint32_t)__builtin_ctz(static_cast<uint32_t>(x)) : (uint32_t)32)
321 #define GAIA_CLZ64(x) ((x) ? (uint32_t)__builtin_ctzll(static_cast<unsigned long long>(x)) : (uint32_t)64)
325 #define GAIA_CTZ(x) ((x) ? (uint32_t)__builtin_clz(static_cast<uint32_t>(x)) : (uint32_t)32)
328 #define GAIA_CTZ64(x) ((x) ? (uint32_t)__builtin_clzll(static_cast<unsigned long long>(x)) : (uint32_t)64)
332 #define GAIA_FFS(x) ((uint32_t)__builtin_ffs(static_cast<int>(x)))
335 #define GAIA_FFS64(x) ((uint32_t)__builtin_ffsll(static_cast<long long>(x)))
336#elif GAIA_COMPILER_MSVC
341 #if GAIA_ARCH == GAIA_ARCH_ARM
342 #include <arm_neon.h>
344 #define GAIA_POPCNT(x) \
345 ([](uint32_t value) noexcept { \
346 const __n64 tmp = neon_cnt(__uint64ToN64_v(value)); \
347 return (uint32_t)neon_addv8(tmp).n8_i8[0]; \
350 #define GAIA_POPCNT64(x) \
351 ([](uint64_t value) noexcept { \
352 const __n64 tmp = neon_cnt(__uint64ToN64_v(value)); \
353 return (uint32_t)neon_addv8(tmp).n8_i8[0]; \
357 #define GAIA_POPCNT(x) ((uint32_t)__popcnt(x))
359 #define GAIA_POPCNT64(x) ((uint32_t)__popcnt64(x))
362 #pragma intrinsic(_BitScanForward)
365 #define GAIA_CLZ(x) \
366 ([](uint32_t value) noexcept { \
367 unsigned long index; \
368 return _BitScanForward(&index, value) ? (uint32_t)index : (uint32_t)32; \
370 #pragma intrinsic(_BitScanForward64)
373 #define GAIA_CLZ64(x) \
374 ([](uint64_t value) noexcept { \
375 unsigned long index; \
376 return _BitScanForward64(&index, value) ? (uint32_t)index : (uint32_t)64; \
379 #pragma intrinsic(_BitScanReverse)
382 #define GAIA_CTZ(x) \
383 ([](uint32_t value) noexcept { \
384 unsigned long index; \
385 return _BitScanReverse(&index, value) ? 31U - (uint32_t)index : (uint32_t)32; \
387 #pragma intrinsic(_BitScanReverse64)
390 #define GAIA_CTZ64(x) \
391 ([](uint64_t value) noexcept { \
392 unsigned long index; \
393 return _BitScanReverse64(&index, value) ? 63U - (uint32_t)index : (uint32_t)64; \
396 #pragma intrinsic(_BitScanForward)
399 #define GAIA_FFS(x) \
400 ([](uint32_t value) noexcept { \
401 unsigned long index; \
402 if (_BitScanForward(&index, value)) \
403 return (uint32_t)(index + 1); \
404 return (uint32_t)0; \
406 #pragma intrinsic(_BitScanForward64)
409 #define GAIA_FFS64(x) \
410 ([](uint64_t value) noexcept { \
411 unsigned long index; \
412 if (_BitScanForward64(&index, value)) \
413 return (uint32_t)(index + 1); \
414 return (uint32_t)0; \
418 #define GAIA_POPCNT(x) \
419 ([](uint32_t value) noexcept -> uint32_t { \
420 uint32_t bitsSet = 0; \
421 while (value != 0) { \
422 value &= (value - 1); \
428 #define GAIA_POPCNT64(x) \
429 ([](uint64_t value) noexcept -> uint32_t { \
430 uint32_t bitsSet = 0; \
431 while (value != 0) { \
432 value &= (value - 1); \
440 #define GAIA_CLZ(x) \
441 ([](uint32_t value) noexcept -> uint32_t { \
444 uint32_t index = 0; \
445 while (((value >> index) & 1) == 0) \
451 #define GAIA_CLZ64(x) \
452 ([](uint64_t value) noexcept -> uint32_t { \
455 uint32_t index = 0; \
456 while (((value >> index) & 1) == 0) \
463 #define GAIA_CTZ(x) \
464 ([](uint32_t value) noexcept -> uint32_t { \
467 uint32_t index = 0; \
468 while (((value << index) & 0x80000000) == 0) \
474 #define GAIA_CTZ64(x) \
475 ([](uint64_t value) noexcept -> uint32_t { \
478 uint32_t index = 0; \
479 while (((value << index) & 0x8000000000000000LL) == 0) \
486 #define GAIA_FFS(x) \
487 ([](uint32_t value) noexcept -> uint32_t { \
490 uint32_t index = 0; \
491 while (((value >> index) & 1) == 0) \
497 #define GAIA_FFS64(x) \
498 ([](uint64_t value) noexcept -> uint32_t { \
501 uint32_t index = 0; \
502 while (((value >> index) & 1) == 0) \
510#if GAIA_COMPILER_CLANG || GAIA_COMPILER_GCC
511 #define GAIA_FORCEINLINE inline __attribute__((always_inline))
512 #define GAIA_NOINLINE __attribute__((noinline))
513#elif GAIA_COMPILER_MSVC || GAIA_COMPILER_ICC
514 #define GAIA_FORCEINLINE __forceinline
515 #define GAIA_NOINLINE __declspec(noinline)
517 #define GAIA_FORCEINLINE inline
518 #define GAIA_NOINLINE
521#if GAIA_COMPILER_CLANG || GAIA_COMPILER_GCC
522 #define GAIA_LAMBDAINLINE __attribute__((always_inline))
523#elif GAIA_COMPILER_MSVC
524 #if _MSC_VER >= 1927 && _MSVC_LANG > 202002L
525 #define GAIA_LAMBDAINLINE [[msvc::forceinline]]
527 #define GAIA_LAMBDAINLINE
530 #define GAIA_LAMBDAINLINE
533#ifdef __has_cpp_attribute
534 #if __has_cpp_attribute(assume) >= 202207L && GAIA_CPP_VERSION(202207L)
535 #define GAIA_ASSUME(...) [[assume(__VA_ARGS__)]]
539 #if GAIA_COMPILER_CLANG
540 #define GAIA_ASSUME(...) __builtin_assume(__VA_ARGS__)
541 #elif GAIA_COMPILER_MSVC
542 #define GAIA_ASSUME(...) __assume(__VA_ARGS__)
543 #elif (GAIA_COMPILER_GCC && __GNUC__ >= 13)
544 #define GAIA_ASSUME(...) __attribute__((__assume__(__VA_ARGS__)))
548 #define GAIA_ASSUME(...)
551#if defined(__cpp_constexpr) && GAIA_CPP_VERSION(201907L)
552 #define GAIA_CONSTEXPR_DTOR constexpr
554 #define GAIA_CONSTEXPR_DTOR
559#if GAIA_COMPILER_MSVC
560 #define GAIA_IMPORT __declspec(dllimport)
561 #define GAIA_EXPORT __declspec(dllexport)
563#elif GAIA_COMPILER_CLANG || GAIA_COMPILER_GCC
564 #define GAIA_IMPORT __attribute__((visibility("default")))
565 #define GAIA_EXPORT __attribute__((visibility("default")))
566 #define GAIA_HIDDEN __attribute__((visibility("hidden")))
585#if GAIA_COMPILER_MSVC
586 #define GAIA_MSVC_WARNING_PUSH() __pragma(warning(push))
587 #define GAIA_MSVC_WARNING_POP() __pragma(warning(pop))
588 #define GAIA_MSVC_WARNING_DISABLE(warningId) __pragma(warning(disable : warningId))
589 #define GAIA_MSVC_WARNING_ERROR(warningId) __pragma(warning(error : warningId))
591 #define GAIA_MSVC_WARNING_PUSH()
592 #define GAIA_MSVC_WARNING_POP()
593 #define GAIA_MSVC_WARNING_DISABLE(warningId)
594 #define GAIA_MSVC_WARNING_ERROR(warningId)
597#if GAIA_COMPILER_CLANG
598 #define DO_PRAGMA_(x) _Pragma(#x)
599 #define DO_PRAGMA(x) DO_PRAGMA_(x)
600 #define GAIA_CLANG_WARNING_PUSH() _Pragma("clang diagnostic push")
601 #define GAIA_CLANG_WARNING_POP() _Pragma("clang diagnostic pop")
604 #define GAIA_CLANG_WARNING_DISABLE(warningId) \
605 DO_PRAGMA(clang diagnostic ignored "-Wunknown-warning-option") \
606 DO_PRAGMA(clang diagnostic ignored warningId)
607 #define GAIA_CLANG_WARNING_ERROR(warningId) DO_PRAGMA(clang diagnostic error warningId)
608 #define GAIA_CLANG_WARNING_ALLOW(warningId) DO_PRAGMA(clang diagnostic warning warningId)
610 #define GAIA_CLANG_WARNING_PUSH()
611 #define GAIA_CLANG_WARNING_POP()
612 #define GAIA_CLANG_WARNING_DISABLE(warningId)
613 #define GAIA_CLANG_WARNING_ERROR(warningId)
614 #define GAIA_CLANG_WARNING_ALLOW(warningId)
618 #define DO_PRAGMA_(x) _Pragma(#x)
619 #define DO_PRAGMA(x) DO_PRAGMA_(x)
620 #define GAIA_GCC_WARNING_PUSH() _Pragma("GCC diagnostic push")
621 #define GAIA_GCC_WARNING_POP() _Pragma("GCC diagnostic pop")
622 #define GAIA_GCC_WARNING_ERROR(warningId) DO_PRAGMA(GCC diagnostic error warningId)
623 #define GAIA_GCC_WARNING_DISABLE(warningId) DO_PRAGMA(GCC diagnostic ignored warningId)
625 #define GAIA_GCC_WARNING_PUSH()
626 #define GAIA_GCC_WARNING_POP()
627 #define GAIA_GCC_WARNING_DISABLE(warningId)
630#define GAIA_HAS_NO_INLINE_ASSEMBLY 0
631#if (!defined(__GNUC__) && !defined(__clang__)) || defined(__pnacl__) || defined(__EMSCRIPTEN__)
632 #undef GAIA_HAS_NO_INLINE_ASSEMBLY
633 #define GAIA_HAS_NO_INLINE_ASSEMBLY 1
637#if !GAIA_HAS_NO_INLINE_ASSEMBLY
642 inline void dont_optimize(T
const& value) {
643 asm volatile(
"" : :
"r,m"(value) :
"memory");
650 inline void dont_optimize(T& value) {
651 #if defined(__clang__)
652 asm volatile(
"" :
"+r,m"(value) : :
"memory");
654 asm volatile(
"" :
"+m,r"(value) : :
"memory");
659 inline void use_char_pointer(
char const volatile* var) {
664 #if defined(_MSC_VER)
669 inline void dont_optimize(T
const& value) {
670 detail::use_char_pointer(&
reinterpret_cast<char const volatile&
>(value));
671 ::_ReadWriteBarrier();
678 inline void dont_optimize(T
const& value) {
679 detail::use_char_pointer(&
reinterpret_cast<char const volatile&
>(value));