typedef uintptr_t usize; typedef uint64_t u64; typedef uint32_t u32; typedef uint16_t u16; typedef uint8_t u8; typedef intptr_t isize; typedef int64_t i64; typedef int32_t i32; typedef int16_t i16; typedef int8_t i8; typedef int64_t b64; typedef int32_t b32; typedef int16_t b16; typedef int8_t b8; typedef float f32; typedef double f64; #ifndef true #define true 1 #endif #ifndef false #define false 0 #endif #define fn #define gb #define locl #if PLATFORM_WASM #define gb_wasm_export __attribute__((visibility("default"))) #define fn_wasm_export __attribute__((visibility("default"))) #define fn_wasm_import #endif #define U64_TO_F64(x) (((union { f64 f; u64 i; }) { .i = (x) }).f) #define U32_TO_F32(x) (((union { f32 f; u32 i; }) { .i = (x) }).f) #define F64_TO_U64(x) (((union { f64 f; u64 i; }) { .f = (x) }).i) #define F32_TO_U32(x) (((union { f32 f; u32 i; }) { .f = (x) }).i) #define MIN(x,y) ((x) > (y) ? (y) : (x)) #define MAX(x,y) ((x) > (y) ? (x) : (y)) #define CLAMP_TOP(A,X) MIN(A,X) #define CLAMP_BOT(X,B) MAX(X,B) #define CLAMP(x,a,b) (((x)<(a))?(a):((x)>(b))?(b):(x)) #define set_bit(x) (1ULL << (x)) #define lengthof(x) (sizeof((x))/sizeof((x)[0])) #ifndef offsetof #define offsetof(st, m) ((usize)&(((st *)0)->m)) #endif #define expect(x) if (!(x)) #define unused(x) (void)(x) #define kib(x) (1024ULL * (x##ULL)) #define mib(x) (1024ULL * kib(x)) #define gib(x) (1024ULL * mib(x)) #define thousand(n) ((n)*1000) #define million(n) ((n)*1000000) #define billion(n) ((n)*1000000000) #define zero_struct(x) memory_zero((x), sizeof(*(x))) #define defer_if(begin, cond_end) for (b32 PASTE(_i_, __LINE__) = !!begin; PASTE(_i_, __LINE__); PASTE(_i_, __LINE__) = (cond_end, 0)) #define defer_block(begin, end) for (i32 PASTE(_i_, __LINE__) = (begin, 0); !PASTE(_i_, __LINE__); PASTE(_i_, __LINE__) += (end, 1)) #define stack_t(type, size) struct { type data[size]; i32 len; } #define STACK_CAP(stack) (lengthof((stack).data)) #define STACK_EMPTY(stack) ((stack).len == 0) #define STACK_FULL(stack) ((stack).len == STACK_CAP(stack)) #define STACK_PUSH(stack, ...) (assert(!STACK_FULL(stack)), (stack).data[(stack).len++] = __VA_ARGS__) #define STACK_POP(stack) (assert(!STACK_EMPTY(stack)), (stack).data[--(stack).len]) #define STACK_TOP(stack) (assert(!STACK_EMPTY(stack)), (stack).data[((stack).len-1)]) #define STRINGIFY_(S) #S #define STRINGIFY(S) STRINGIFY_(S) #define PASTE_(a, b) a##b #define PASTE(a, b) PASTE_(a, b) #define SWAP(t, a, b) do { t PASTE(temp__, __LINE__) = a; a = b; b = PASTE(temp__, __LINE__); } while(0) #define CODE(...) #__VA_ARGS__ #if PLATFORM_CL || (PLATFORM_CLANG && PLATFORM_WINDOWS) #pragma section(".rdata$", read) #define gb_read_only __declspec(allocate(".rdata$")) #elif PLATFORM_CLANG && PLATFORM_LINUX #define gb_read_only __attribute__((section(".rodata"))) #else #define gb_read_only #endif #if PLATFORM_CL #define fn_inline __forceinline #elif PLATFORM_CLANG || PLATFORM_GCC #define fn_inline __attribute__((always_inline)) #else #define fn_inline #endif #ifndef FILE_AND_LINE_GCC_FORMAT #define FILE_AND_LINE __FILE__"("STRINGIFY(__LINE__)")" #else #define FILE_AND_LINE __FILE__":"STRINGIFY(__LINE__) #endif #if PLATFORM_CL #define debug__break() __debugbreak() #else #define debug__break() __builtin_trap() #endif #define debug_break() (debug__break(), 0) #if PLATFORM_WASM #define gb_thread #elif PLATFORM_GCC | PLATFORM_CLANG #define gb_thread __thread #elif PLATFORM_CL #define gb_thread __declspec(thread) #else #define gb_thread _Thread_local #endif #if PLATFORM_CL #pragma warning(disable: 4116) #endif // Single linked list Queue #define SLLQ_APPEND_EX(f, l, n, next) \ do { \ assert((n)->next == NULL); \ if ((f) == 0) { \ (f) = (l) = (n); \ } else { \ (l) = (l)->next = (n); \ } \ } while (0) #define SLLQ_APPEND(f, l, n) SLLQ_APPEND_EX(f, l, n, next) #define SLLQ_PREPEND_EX(f, l, n, next) \ do { \ assert((n)->next == NULL); \ if ((f) == 0) { \ (f) = (l) = (n); \ } else { \ (n)->next = (f); \ (f) = (n); \ } \ } while (0) #define SLLQ_PREPEND(f, l, n) SLLQ_PREPEND_EX(f, l, n, next) #define SLLQ_REMOVE_FIRST_EX(f, l, next) \ do { \ if ((f) == (l)) { \ (f) = (l) = 0; \ } else { \ (f) = (f)->next; \ } \ } while (0) #define SLLQ_REMOVE_FIRST(f, l) SLLQ_REMOVE_FIRST_EX(f, l, next) // Singly linked list stack #define SLLS_PUSH_EX(stack_base, new_stack_base, next) \ do { \ (new_stack_base)->next = (stack_base); \ (stack_base) = (new_stack_base); \ } while (0) #define SLLS_PUSH(stack_base, new_stack_base) \ SLLS_PUSH_EX(stack_base, new_stack_base, next) #define SLLS_POP(stack_base) ((stack_base) = (stack_base)->next) #define SLLS_POP_AND_STORE(stack_base, out_node) \ do { \ if (stack_base) { \ (out_node) = (stack_base); \ (stack_base) = (stack_base)->next; \ (out_node)->next = 0; \ } \ } while (0) // Doubly linked list Queue #define DLLQ_APPEND_EX(f, l, node, next, prev) \ do { \ assert((node)->next == NULL); \ assert((node)->prev == NULL); \ if ((f) == 0) { \ (f) = (l) = (node); \ } else { \ (l)->next = (node); \ (node)->prev = (l); \ (l) = (node); \ } \ } while (0) #define DLLQ_APPEND(f, l, node) DLLQ_APPEND_EX(f, l, node, next, prev) #define DLLQ_PREPEND_EX(f, l, node, next, prev) \ do { \ assert((node)->next == NULL); \ assert((node)->prev == NULL); \ if ((f) == 0) { \ (f) = (l) = (node); \ } else { \ (node)->next = (f); \ (f)->prev = (node); \ (f) = (node); \ } \ } while (0) #define DLLQ_PREPEND(f, l, node) DLLQ_PREPEND_EX(f, l, node, next, prev) #define DLLQ_CONTAINS(f, l, n, next, prev) for ( #define DLLQ_REMOVE_EX(first, last, node, next, prev) \ do { \ if ((first) == (last)) { \ assert((node) == (first)); \ (first) = (last) = 0; \ } else if ((last) == (node)) { \ (last) = (last)->prev; \ (last)->next = 0; \ } else if ((first) == (node)) { \ (first) = (first)->next; \ (first)->prev = 0; \ } else { \ (node)->prev->next = (node)->next; \ (node)->next->prev = (node)->prev; \ } \ if (node) { \ (node)->prev = 0; \ (node)->next = 0; \ } \ } while (0) #define DLLQ_REMOVE(first, last, node) DLLQ_REMOVE_EX(first, last, node, next, prev) // Doubly linked list Stack #define DLLS_PUSH_EX(first, node, next, prev) \ do { \ assert((node)->next == NULL); \ assert((node)->prev == NULL); \ (node)->next = (first); \ if ((first)) \ (first)->prev = (node); \ (first) = (node); \ } while (0) #define DLLS_PUSH(first, node) DLLS_PUSH_EX(first, node, next, prev) #define DLLS_REMOVE_EX(first, node, next, prev) \ do { \ if ((node) == (first)) { \ (first) = (first)->next; \ if ((first)) \ (first)->prev = 0; \ } else { \ (node)->prev->next = (node)->next; \ if ((node)->next) \ (node)->next->prev = (node)->prev; \ } \ if (node) { \ (node)->prev = 0; \ (node)->next = 0; \ } \ } while (0) #define DLLS_REMOVE(first, node) DLLS_REMOVE_EX(first, node, next, prev)