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_SAFE_CONSTEXPR constexpr
43#define GAIA_USE_STD_SPAN (GAIA_CPP_VERSION(202002L) && __has_include(<span>))
49#define GAIA_ECS_HASH_FNV1A 0
50#define GAIA_ECS_HASH_MURMUR2A 1
55#define GAIA_COMPILER_CLANG 0
56#define GAIA_COMPILER_GCC 0
57#define GAIA_COMPILER_MSVC 0
58#define GAIA_COMPILER_ICC 0
59#define GAIA_COMPILER_DETECTED 0
61#if !GAIA_COMPILER_DETECTED && (defined(__clang__))
64 #undef GAIA_COMPILER_CLANG
65 #define GAIA_COMPILER_CLANG 1
66 #undef GAIA_COMPILER_DETECTED
67 #define GAIA_COMPILER_DETECTED 1
71 #undef GAIA_COMPILER_MSVC
72 #define GAIA_COMPILER_MSVC 1
75#if !GAIA_COMPILER_DETECTED && \
76 (defined(__INTEL_COMPILER) || defined(__ICC) || defined(__ICL) || defined(__INTEL_LLVM_COMPILER))
77 #undef GAIA_COMPILER_ICC
78 #define GAIA_COMPILER_ICC 1
79 #undef GAIA_COMPILER_DETECTED
80 #define GAIA_COMPILER_DETECTED 1
82#if !GAIA_COMPILER_DETECTED && (defined(__SNC__) || defined(__GNUC__))
83 #undef GAIA_COMPILER_GCC
84 #define GAIA_COMPILER_GCC 1
85 #undef GAIA_COMPILER_DETECTED
86 #define GAIA_COMPILER_DETECTED 1
91 #undef GAIA_SAFE_CONSTEXPR
92 #define GAIA_SAFE_CONSTEXPR const
95#if !GAIA_COMPILER_DETECTED && (defined(_MSC_VER))
96 #undef GAIA_COMPILER_MSVC
97 #define GAIA_COMPILER_MSVC 1
98 #undef GAIA_COMPILER_DETECTED
99 #define GAIA_COMPILER_DETECTED 1
101#if !GAIA_COMPILER_DETECTED
102 #error "Unrecognized compiler"
109#define GAIA_PLATFORM_UNKNOWN 0
110#define GAIA_PLATFORM_WINDOWS 0
111#define GAIA_PLATFORM_LINUX 0
112#define GAIA_PLATFORM_APPLE 0
113#define GAIA_PLATFORM_FREEBSD 0
114#define GAIA_PLATFORM_WASM 0
117 #undef GAIA_PLATFORM_WINDOWS
118 #define GAIA_PLATFORM_WINDOWS 1
123 #undef GAIA_PLATFORM_APPLE
124 #define GAIA_PLATFORM_APPLE 1
126 #undef GAIA_PLATFORM_LINUX
127 #define GAIA_PLATFORM_LINUX 1
129 #undef GAIA_PLATFORM_FREEBSD
130 #define GAIA_PLATFORM_FREEBSD 1
131#elif defined(__EMSCRIPTEN__)
132 #undef GAIA_PLATFORM_WASM
133 #define GAIA_PLATFORM_WASM 1
135 #undef GAIA_PLATFORM_UNKNOWN
136 #define GAIA_PLATFORM_UNKNOWN 1
143#if defined(_WIN64) || defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64) || defined(__amd64) || \
149#define GAIA_ARCH_X86 0
150#define GAIA_ARCH_ARM 1
151#define GAIA_ARCH_WASM 2
153#if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__i386) || \
154 defined(i386) || defined(__x86_64__) || defined(_X86_)
156 #define GAIA_ARCH GAIA_ARCH_X86
157#elif defined(__arm__) || defined(__aarch64__) || defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC)
159 #define GAIA_ARCH GAIA_ARCH_ARM
160#elif defined(__EMSCRIPTEN__) || defined(__wasm__) || defined(__wasm32__) || defined(__wasm64__)
162 #define GAIA_ARCH GAIA_ARCH_WASM
164 #error "Unrecognized target architecture."
169#if GAIA_COMPILER_MSVC && !GAIA_COMPILER_CLANG
170 #define GAIA_PRETTY_FUNCTION __FUNCSIG__
171 #define GAIA_PRETTY_FUNCTION_PREFIX '<'
172 #define GAIA_PRETTY_FUNCTION_SUFFIX '>'
174 #define GAIA_PRETTY_FUNCTION __PRETTY_FUNCTION__
175 #define GAIA_PRETTY_FUNCTION_PREFIX '='
176 #define GAIA_PRETTY_FUNCTION_SUFFIX ']'
179#define GAIA_STRINGIZE(x) #x
180#define GAIA_CONCAT_IMPL(x, y) x##y
181#define GAIA_CONCAT(x, y) GAIA_CONCAT_IMPL(x, y)
183#define GAIA_FOR(max) for (uint32_t i = 0; i < (max); ++i)
184#define GAIA_FOR_(max, varname) for (uint32_t varname = 0; varname < (max); ++varname)
185#define GAIA_FOR2(min, max) for (uint32_t i = (min); i < (max); ++i)
186#define GAIA_FOR2_(min, max, varname) for (uint32_t varname = (min); varname < (max); ++varname)
187#define GAIA_EACH(container) for (uint32_t i = 0; i < (container).size(); ++i)
188#define GAIA_EACH_(container, varname) for (uint32_t varname = 0; varname < (container).size(); ++varname)
197#if GAIA_COMPILER_MSVC
201 #define GAIA_LITTLE_ENDIAN true
202 #define GAIA_BIG_ENDIAN false
204 #define GAIA_LITTLE_ENDIAN (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
205 #define GAIA_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
212 inline bool CheckEndianess() {
213 const uint16_t testWord = 0x1234;
214 const bool isLittleEndian(*
reinterpret_cast<const uint8_t*
>(&testWord) == 0x34);
215 return isLittleEndian && GAIA_LITTLE_ENDIAN;
224#define GAIA_MOV(x) static_cast<typename std::remove_reference<decltype(x)>::type&&>(x)
228#define GAIA_FWD(x) static_cast<decltype(x)&&>(x)
230#define GAIA_ACC(x) std::launder(x)
232#if (GAIA_COMPILER_MSVC && _MSC_VER >= 1400) || GAIA_COMPILER_GCC || GAIA_COMPILER_CLANG
233 #define GAIA_RESTRICT __restrict
235 #define GAIA_RESTRICT
238#if GAIA_CPP_VERSION(202002L)
239 #if __has_cpp_attribute(nodiscard)
240 #define GAIA_NODISCARD [[nodiscard]]
242 #if __has_cpp_attribute(likely)
243 #define GAIA_LIKELY(cond) (cond) [[likely]]
245 #if __has_cpp_attribute(unlikely)
246 #define GAIA_UNLIKELY(cond) (cond) [[unlikely]]
248 #if __has_cpp_attribute(fallthrough)
249 #define GAIA_FALLTHROUGH [[fallthrough]]
252#ifndef GAIA_NODISCARD
253 #define GAIA_NODISCARD
255#if !defined(GAIA_LIKELY) && (GAIA_COMPILER_GCC || GAIA_COMPILER_CLANG)
256 #define GAIA_LIKELY(cond) (__builtin_expect((cond), 1))
258#if !defined(GAIA_UNLIKELY) && (GAIA_COMPILER_GCC || GAIA_COMPILER_CLANG)
259 #define GAIA_UNLIKELY(cond) (__builtin_expect((cond), 0))
262 #define GAIA_LIKELY(cond) (cond)
265 #define GAIA_UNLIKELY(cond) (cond)
267#ifndef GAIA_FALLTHROUGH
268 #define GAIA_FALLTHROUGH
277 #define GAIA_ALIGNAS(alignment) __attribute__((aligned(alignment)))
279 #define GAIA_ALIGNAS(alignment) alignas(alignment)
282#ifndef GAIA_CACHELINE_SIZE
283 #ifdef __cpp_lib_hardware_interference_size
284 #define GAIA_CACHELINE_SIZE std::hardware_constructive_interference_size
285 #elif defined(__GCC_DESTRUCTIVE_SIZE)
286 #define GAIA_CACHELINE_SIZE __GCC_DESTRUCTIVE_SIZE
288 #if GAIA_ARCH == GAIA_ARCH_ARM
294 #define GAIA_CACHELINE_SIZE 128
296 #define GAIA_CACHELINE_SIZE 64
306#if GAIA_ARCH == GAIA_ARCH_X86
307 #include <immintrin.h>
308 #define GAIA_YIELD_CPU _mm_pause()
309#elif GAIA_ARCH == GAIA_ARCH_ARM
310 #if GAIA_COMPILER_CLANG
311 #define GAIA_YIELD_CPU __builtin_arm_yield()
312 #elif GAIA_COMPILER_GCC
313 #define GAIA_YIELD_CPU __asm__ volatile("yield" ::: "memory");
316#if !defined(GAIA_YIELD_CPU)
317 #define GAIA_YIELD_CPU \
322#if GAIA_COMPILER_CLANG || GAIA_COMPILER_GCC
324 #define GAIA_POPCNT(x) ((uint32_t)__builtin_popcount(static_cast<uint32_t>(x)))
326 #define GAIA_POPCNT64(x) ((uint32_t)__builtin_popcountll(static_cast<unsigned long long>(x)))
330 #define GAIA_CLZ(x) ((x) ? (uint32_t)__builtin_ctz(static_cast<uint32_t>(x)) : (uint32_t)32)
333 #define GAIA_CLZ64(x) ((x) ? (uint32_t)__builtin_ctzll(static_cast<unsigned long long>(x)) : (uint32_t)64)
337 #define GAIA_CTZ(x) ((x) ? (uint32_t)__builtin_clz(static_cast<uint32_t>(x)) : (uint32_t)32)
340 #define GAIA_CTZ64(x) ((x) ? (uint32_t)__builtin_clzll(static_cast<unsigned long long>(x)) : (uint32_t)64)
344 #define GAIA_FFS(x) ((uint32_t)__builtin_ffs(static_cast<int>(x)))
347 #define GAIA_FFS64(x) ((uint32_t)__builtin_ffsll(static_cast<long long>(x)))
348#elif GAIA_COMPILER_MSVC
353 #if GAIA_ARCH == GAIA_ARCH_ARM
354 #include <arm_neon.h>
356 #define GAIA_POPCNT(x) \
357 ([](uint32_t value) noexcept { \
358 const __n64 tmp = neon_cnt(__uint64ToN64_v(value)); \
359 return (uint32_t)neon_addv8(tmp).n8_i8[0]; \
362 #define GAIA_POPCNT64(x) \
363 ([](uint64_t value) noexcept { \
364 const __n64 tmp = neon_cnt(__uint64ToN64_v(value)); \
365 return (uint32_t)neon_addv8(tmp).n8_i8[0]; \
369 #define GAIA_POPCNT(x) ((uint32_t)__popcnt(x))
371 #define GAIA_POPCNT64(x) ((uint32_t)__popcnt64(x))
374 #pragma intrinsic(_BitScanForward)
377 #define GAIA_CLZ(x) \
378 ([](uint32_t value) noexcept { \
379 unsigned long index; \
380 return _BitScanForward(&index, value) ? (uint32_t)index : (uint32_t)32; \
382 #pragma intrinsic(_BitScanForward64)
385 #define GAIA_CLZ64(x) \
386 ([](uint64_t value) noexcept { \
387 unsigned long index; \
388 return _BitScanForward64(&index, value) ? (uint32_t)index : (uint32_t)64; \
391 #pragma intrinsic(_BitScanReverse)
394 #define GAIA_CTZ(x) \
395 ([](uint32_t value) noexcept { \
396 unsigned long index; \
397 return _BitScanReverse(&index, value) ? 31U - (uint32_t)index : (uint32_t)32; \
399 #pragma intrinsic(_BitScanReverse64)
402 #define GAIA_CTZ64(x) \
403 ([](uint64_t value) noexcept { \
404 unsigned long index; \
405 return _BitScanReverse64(&index, value) ? 63U - (uint32_t)index : (uint32_t)64; \
408 #pragma intrinsic(_BitScanForward)
411 #define GAIA_FFS(x) \
412 ([](uint32_t value) noexcept { \
413 unsigned long index; \
414 if (_BitScanForward(&index, value)) \
415 return (uint32_t)(index + 1); \
416 return (uint32_t)0; \
418 #pragma intrinsic(_BitScanForward64)
421 #define GAIA_FFS64(x) \
422 ([](uint64_t value) noexcept { \
423 unsigned long index; \
424 if (_BitScanForward64(&index, value)) \
425 return (uint32_t)(index + 1); \
426 return (uint32_t)0; \
430 #define GAIA_POPCNT(x) \
431 ([](uint32_t value) noexcept -> uint32_t { \
432 uint32_t bitsSet = 0; \
433 while (value != 0) { \
434 value &= (value - 1); \
440 #define GAIA_POPCNT64(x) \
441 ([](uint64_t value) noexcept -> uint32_t { \
442 uint32_t bitsSet = 0; \
443 while (value != 0) { \
444 value &= (value - 1); \
452 #define GAIA_CLZ(x) \
453 ([](uint32_t value) noexcept -> uint32_t { \
456 uint32_t index = 0; \
457 while (((value >> index) & 1) == 0) \
463 #define GAIA_CLZ64(x) \
464 ([](uint64_t value) noexcept -> uint32_t { \
467 uint32_t index = 0; \
468 while (((value >> index) & 1) == 0) \
475 #define GAIA_CTZ(x) \
476 ([](uint32_t value) noexcept -> uint32_t { \
479 uint32_t index = 0; \
480 while (((value << index) & 0x80000000) == 0) \
486 #define GAIA_CTZ64(x) \
487 ([](uint64_t value) noexcept -> uint32_t { \
490 uint32_t index = 0; \
491 while (((value << index) & 0x8000000000000000LL) == 0) \
498 #define GAIA_FFS(x) \
499 ([](uint32_t value) noexcept -> uint32_t { \
502 uint32_t index = 0; \
503 while (((value >> index) & 1) == 0) \
509 #define GAIA_FFS64(x) \
510 ([](uint64_t value) noexcept -> uint32_t { \
513 uint32_t index = 0; \
514 while (((value >> index) & 1) == 0) \
522#if GAIA_COMPILER_CLANG || GAIA_COMPILER_GCC
523 #define GAIA_FORCEINLINE inline __attribute__((always_inline))
524 #define GAIA_NOINLINE __attribute__((noinline))
525#elif GAIA_COMPILER_MSVC || GAIA_COMPILER_ICC
526 #define GAIA_FORCEINLINE __forceinline
527 #define GAIA_NOINLINE __declspec(noinline)
529 #define GAIA_FORCEINLINE inline
530 #define GAIA_NOINLINE
533#if GAIA_COMPILER_CLANG || GAIA_COMPILER_GCC
534 #define GAIA_LAMBDAINLINE __attribute__((always_inline))
535#elif GAIA_COMPILER_MSVC
536 #if _MSC_VER >= 1927 && _MSVC_LANG > 202002L
537 #define GAIA_LAMBDAINLINE [[msvc::forceinline]]
539 #define GAIA_LAMBDAINLINE
542 #define GAIA_LAMBDAINLINE
545#ifdef __has_cpp_attribute
546 #if __has_cpp_attribute(assume) >= 202207L && GAIA_CPP_VERSION(202207L)
547 #define GAIA_ASSUME(...) [[assume(__VA_ARGS__)]]
551 #if GAIA_COMPILER_CLANG
552 #define GAIA_ASSUME(...) __builtin_assume(__VA_ARGS__)
553 #elif GAIA_COMPILER_MSVC
554 #define GAIA_ASSUME(...) __assume(__VA_ARGS__)
555 #elif (GAIA_COMPILER_GCC && __GNUC__ >= 13)
556 #define GAIA_ASSUME(...) __attribute__((__assume__(__VA_ARGS__)))
560 #define GAIA_ASSUME(...)
565#if GAIA_COMPILER_MSVC
566 #define GAIA_IMPORT __declspec(dllimport)
567 #define GAIA_EXPORT __declspec(dllexport)
569#elif GAIA_COMPILER_CLANG || GAIA_COMPILER_GCC
570 #define GAIA_IMPORT __attribute__((visibility("default")))
571 #define GAIA_EXPORT __attribute__((visibility("default")))
572 #define GAIA_HIDDEN __attribute__((visibility("hidden")))
591#if GAIA_COMPILER_MSVC
592 #define GAIA_MSVC_WARNING_PUSH() __pragma(warning(push))
593 #define GAIA_MSVC_WARNING_POP() __pragma(warning(pop))
594 #define GAIA_MSVC_WARNING_DISABLE(warningId) __pragma(warning(disable : warningId))
595 #define GAIA_MSVC_WARNING_ERROR(warningId) __pragma(warning(error : warningId))
597 #define GAIA_MSVC_WARNING_PUSH()
598 #define GAIA_MSVC_WARNING_POP()
599 #define GAIA_MSVC_WARNING_DISABLE(warningId)
600 #define GAIA_MSVC_WARNING_ERROR(warningId)
603#if GAIA_COMPILER_CLANG
604 #define DO_PRAGMA_(x) _Pragma(#x)
605 #define DO_PRAGMA(x) DO_PRAGMA_(x)
606 #define GAIA_CLANG_WARNING_PUSH() _Pragma("clang diagnostic push")
607 #define GAIA_CLANG_WARNING_POP() _Pragma("clang diagnostic pop")
608 #define GAIA_CLANG_WARNING_DISABLE(warningId) DO_PRAGMA(clang diagnostic ignored warningId)
609 #define GAIA_CLANG_WARNING_ERROR(warningId) DO_PRAGMA(clang diagnostic error warningId)
610 #define GAIA_CLANG_WARNING_ALLOW(warningId) DO_PRAGMA(clang diagnostic warning warningId)
612 #define GAIA_CLANG_WARNING_PUSH()
613 #define GAIA_CLANG_WARNING_POP()
614 #define GAIA_CLANG_WARNING_DISABLE(warningId)
615 #define GAIA_CLANG_WARNING_ERROR(warningId)
616 #define GAIA_CLANG_WARNING_ALLOW(warningId)
620 #define DO_PRAGMA_(x) _Pragma(#x)
621 #define DO_PRAGMA(x) DO_PRAGMA_(x)
622 #define GAIA_GCC_WARNING_PUSH() _Pragma("GCC diagnostic push")
623 #define GAIA_GCC_WARNING_POP() _Pragma("GCC diagnostic pop")
624 #define GAIA_GCC_WARNING_ERROR(warningId) DO_PRAGMA(GCC diagnostic error warningId)
625 #define GAIA_GCC_WARNING_DISABLE(warningId) DO_PRAGMA(GCC diagnostic ignored warningId)
627 #define GAIA_GCC_WARNING_PUSH()
628 #define GAIA_GCC_WARNING_POP()
629 #define GAIA_GCC_WARNING_DISABLE(warningId)
632#define GAIA_HAS_NO_INLINE_ASSEMBLY 0
633#if (!defined(__GNUC__) && !defined(__clang__)) || defined(__pnacl__) || defined(__EMSCRIPTEN__)
634 #undef GAIA_HAS_NO_INLINE_ASSEMBLY
635 #define GAIA_HAS_NO_INLINE_ASSEMBLY 1
643#if !GAIA_HAS_NO_INLINE_ASSEMBLY
645 inline void dont_optimize(T
const& value) {
646 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)
666 inline void dont_optimize(T
const& value) {
667 detail::use_char_pointer(&
reinterpret_cast<char const volatile&
>(value));
668 ::_ReadWriteBarrier();
672 inline void dont_optimize(T
const& value) {
673 detail::use_char_pointer(&
reinterpret_cast<char const volatile&
>(value));
Checks if endianess was detected correctly at compile-time.
Definition bitset.h:9