convert math functions to generics

This commit is contained in:
Matthew 2025-04-20 16:51:44 +10:00
parent c27b200984
commit 30153e1af3
8 changed files with 199 additions and 88 deletions

View File

@ -4,8 +4,6 @@ FLAlloc FL_ALLOC = {0};
Allocator ALLOC = {0}; Allocator ALLOC = {0};
read_only FLNode FL_NIL_NODE = {0}; read_only FLNode FL_NIL_NODE = {0};
#define ALLOC_CAP 16
// ::Allocator::Util::Header:: // ::Allocator::Util::Header::
usize CalcPaddingWithHeader(uintptr ptr, uintptr alignment, usize header_size) usize CalcPaddingWithHeader(uintptr ptr, uintptr alignment, usize header_size)
@ -104,33 +102,64 @@ static Arena * ArenaInitDebug(rawptr buffer, usize length, u32 init_line_no)
static void InitAllocator(usize init_size) static void InitAllocator(usize init_size)
{ {
ALLOC.tree = FLMemAlloc(sizeof(RBTree)); ALLOC.grow_size = init_size;
RBTreeInit(ALLOC.tree); ALLOC.buffer = MemAllocZeroed(init_size);
ALLOC.size = init_size;
ALLOC.free_size = init_size;
ALLOC.hash_table = FLMemAlloc(sizeof(HashTable)); ALLOC.hash_table = FLMemAlloc(sizeof(HashTable));
HashTableInit(ALLOC.hash_table, 32); HashTableInit(ALLOC.hash_table, 32);
ALLOC.buffers = FLMemAlloc(sizeof(FreeListBuffer) * ALLOC_CAP); ALLOC.tree = FLMemAlloc(sizeof(RBTree));
ALLOC.count = 1; RBTreeInit(ALLOC.tree);
ALLOC.cap = ALLOC_CAP;
ALLOC.grow_size = init_size; AllocInfo *info = CreateAllocInfo(ALLOC.buffer);
InitAllocatorBuffer(&ALLOC.buffers[0], init_size); RBTreeFindOrInsert(ALLOC.tree, init_size, info);
} }
static void InitAllocatorBuffer(FreeListBuffer *buffer, usize init_size) static AllocInfo *CreateAllocInfo(rawptr ptr)
{ {
buffer->buf = MemAllocZeroed(init_size); AllocInfo *info = FLMemAlloc(sizeof(AllocInfo));
buffer->size = init_size; info->ptrs = FLMemAlloc(sizeof(rawptr *));
buffer->free_size = init_size; info->ptrs[0] = ptr;
info->count = 1;
}
static void AllocInfoAdd(AllocInfo *info, rawptr ptr)
{
rawptr *ptrs = FLMemAlloc(sizeof(rawptr) * (info->count+1));
MemCpy(ptrs, info->ptrs, sizeof(rawptr) * (info->count+1));
FLMemFree(info->ptrs);
info->ptrs = ptrs;
}
static void AllocInfoRemove(AllocInfo *info, rawptr ptr)
{
u32 index = UINT32_MAX;
for (u32 i = 0; i < info->count; i++)
{
if (info->ptrs[i] == ptr)
{
index = i;
break;
}
}
Assert(index != UINT32_MAX, "AllocInfoRemove called with invalid pointer");
rawptr *ptrs = FLMemAlloc(sizeof(rawptr) * (info->count-1));
MemCpy(ptrs, info->ptrs, index);
MemCpy(&ptrs[index], &info->ptrs[index+1], info->count-index-1);
FLMemFree(info->ptrs);
info->ptrs = ptrs;
info->count -= 1;
} }
static void DeinitAlloc() static void DeinitAlloc()
{ {
for (u8 i = 0; i < ALLOC.count; i++) MemFree(ALLOC.buffer, ALLOC.size);
{
MemFree(ALLOC.buffers[i].buf, ALLOC.buffers[i].size);
}
} }
static rawptr Alloc(usize size) static rawptr Alloc(usize size)
@ -140,19 +169,30 @@ static rawptr Alloc(usize size)
static rawptr AllocAlign(usize size, usize alignment) static rawptr AllocAlign(usize size, usize alignment)
{ {
return NULL; if (size == 0) return NULL;
usize padding = 0;
if (alignment < 8)
alignment = 8;
RBNode *node = NULL;
RBTreeSearch(ALLOC.tree, size, &node);
} }
static void Free(rawptr ptr) static void Free(rawptr ptr)
{ {
if (ptr == NULL) return;
} }
static void AllocGrow() static void AllocGrow(usize size)
{ {
Assert(ALLOC.count < ALLOC.cap, "Global allocator has reached capacity"); usize grow_size = size < ALLOC.grow_size ? ALLOC.grow_size : ALLOC.grow_size + size;
InitAllocatorBuffer(&ALLOC.buffers[ALLOC.count], ALLOC.grow_size); MemRealloc(ALLOC.buffer, ALLOC.size, ALLOC.size + grow_size);
ALLOC.count += 1; ALLOC.size += grow_size;
ALLOC.free_size += grow_size;
} }
// ::Allocator::GlobalAlloc::End:: // ::Allocator::GlobalAlloc::End::
@ -171,7 +211,7 @@ static rawptr FLMemAlloc(usize size)
return FreeListAlloc(&FL_ALLOC, size); return FreeListAlloc(&FL_ALLOC, size);
} }
static void FLFree(rawptr ptr) static void FLMemFree(rawptr ptr)
{ {
FreeListFree(&FL_ALLOC, ptr); FreeListFree(&FL_ALLOC, ptr);
} }
@ -285,6 +325,8 @@ static void FreeListGrow(FLAlloc *alloc, usize alloc_size)
static rawptr _FreeListAllocAlign(FreeList *alloc, usize size, u32 alignment) static rawptr _FreeListAllocAlign(FreeList *alloc, usize size, u32 alignment)
{ {
if (size == 0) return NULL;
usize padding = 0; usize padding = 0;
FLNode *prev_node = &FL_NIL_NODE; FLNode *prev_node = &FL_NIL_NODE;

View File

@ -32,27 +32,28 @@ static Arena *ArenaInitDebug(rawptr buffer, usize length, u32 init_line_no);
// ::Allocator::GlobalAlloc::Header:: // ::Allocator::GlobalAlloc::Header::
typedef struct FreeListBuffer typedef struct AllocInfo
{ {
rawptr buf; rawptr *ptrs;
u32 size; u32 count;
u32 free_size; } AllocInfo;
} FreeListBuffer;
typedef struct Allocator typedef struct Allocator
{ {
RBTree *tree; RBTree *tree;
FreeListBuffer *buffers;
HashTable *hash_table; HashTable *hash_table;
usize grow_size; rawptr buffer;
u64 count; u64 size;
u64 cap; u64 free_size;
u64 grow_size;
} Allocator; } Allocator;
static void InitAllocator(usize init_size); static void InitAllocator(usize init_size);
static void InitAllocatorBuffer(FreeListBuffer *buffer, usize init_size); static AllocInfo *CreateAllocInfo(rawptr ptr);
static void AllocInfoAdd(AllocInfo *info, rawptr ptr);
static void AllocInfoRemove(AllocInfo *info, rawptr ptr);
static void DeinitAlloc(); static void DeinitAlloc();
static void AllocGrow(); static void AllocGrow(usize size);
static rawptr Alloc(usize size); static rawptr Alloc(usize size);
static rawptr AllocAlign(usize size, usize alignment); static rawptr AllocAlign(usize size, usize alignment);
static void Free(rawptr ptr); static void Free(rawptr ptr);
@ -92,7 +93,7 @@ typedef struct FLAlloc
static void GlobalFreeListInit(usize size); static void GlobalFreeListInit(usize size);
static rawptr FLMemAlloc(usize size); static rawptr FLMemAlloc(usize size);
static void FLFree(rawptr ptr); static void FLMemFree(rawptr ptr);
static void _FreeListInit(FreeList **alloc, usize size); static void _FreeListInit(FreeList **alloc, usize size);
static void FreeListInit(FLAlloc *alloc, usize size); static void FreeListInit(FLAlloc *alloc, usize size);
static rawptr _FreeListAllocAlign(FreeList *alloc, usize size, u32 alignment); static rawptr _FreeListAllocAlign(FreeList *alloc, usize size, u32 alignment);

View File

@ -21,8 +21,19 @@ static void RBTreeInit(RBTree *tree)
tree->nil = P_RB_NIL; tree->nil = P_RB_NIL;
} }
static RBNode *RBTreeFindOrInsert(RBTree *tree, RBNode *node) static inline void RBTreeInitNode(RBNode *node, u32 key, rawptr value)
{ {
node->parent = node->left = node->right = P_RB_NIL;
node->color = RB_BLACK;
node->key = key;
node->data = value;
}
static RBNode *RBTreeFindOrInsert(RBTree *tree, u32 key, rawptr value)
{
RBNode *node = FLMemAlloc(sizeof(RBNode));
RBTreeInitNode(node, key, value);
RBNode *existing_node = P_RB_NIL; RBNode *existing_node = P_RB_NIL;
node->left = node->right = tree->nil; node->left = node->right = tree->nil;
@ -41,12 +52,12 @@ static RBNode *RBTreeFindOrInsert(RBTree *tree, RBNode *node)
{ {
Assert(curr_node != tree->nil, "Current Node is NIL"); Assert(curr_node != tree->nil, "Current Node is NIL");
if (curr_node->value == node->value) if (curr_node->key == node->key)
{ {
existing_node = curr_node; existing_node = curr_node;
break; break;
} }
else if (curr_node->value < node->value) else if (curr_node->key < node->key)
{ {
if (curr_node->right == tree->nil) if (curr_node->right == tree->nil)
{ {
@ -124,10 +135,10 @@ static void RBTreeCorrect(RBTree *tree, RBNode *node)
} while ((p = node->parent)); } while ((p = node->parent));
} }
static void RBTreeDelete(RBTree *tree, i32 value) static void RBTreeDelete(RBTree *tree, u32 key)
{ {
RBNode *node = NULL; RBNode *node = NULL;
Assert(RBTreeSearch(tree, value, &node), "Unable to find node in RBTreeDelete"); Assert(RBTreeSearch(tree, key, &node), "Unable to find node in RBTreeDelete");
if (node == tree->root && node->left == tree->nil && node->right == tree->nil) if (node == tree->root && node->left == tree->nil && node->right == tree->nil)
{ {
@ -140,7 +151,7 @@ static void RBTreeDelete(RBTree *tree, i32 value)
while (ln->left != tree->nil) while (ln->left != tree->nil)
ln = ln->left; ln = ln->left;
node->value = ln->value; node->key = ln->key;
node->data = ln->data; node->data = ln->data;
if (node->right == ln) if (node->right == ln)
@ -152,13 +163,13 @@ static void RBTreeDelete(RBTree *tree, i32 value)
} }
else if (node->color == RB_BLACK && node->left != tree->nil) else if (node->color == RB_BLACK && node->left != tree->nil)
{ {
node->value = node->left->value; node->key = node->left->key;
node->data = node->left->data; node->data = node->left->data;
node->left = tree->nil; node->left = tree->nil;
} }
else if (node->color == RB_BLACK && node->right != tree->nil) else if (node->color == RB_BLACK && node->right != tree->nil)
{ {
node->value = node->right->value; node->key = node->right->key;
node->data = node->right->data; node->data = node->right->data;
node->right = tree->nil; node->right = tree->nil;
} }
@ -240,7 +251,29 @@ static void RBTreeDelete(RBTree *tree, i32 value)
} }
} }
static b32 RBTreeSearch(RBTree *tree, i32 value, RBNode **out_node) static b32 RBTreeSearchNearest(RBTree *tree, u32 key, RBNode **out_node)
{
if (tree->root == tree->nil) return false;
RBNode *node = tree->root;
RBNode *nearest = tree->root;
while (true)
{
if (node->key == key)
break;
if (node->left == tree->nil && node->right == tree->nil)
break;
if (node->key < key && node->right != tree->nil)
node = node->right;
}
}
static b32 RBTreeSearch(RBTree *tree, u32 key, RBNode **out_node)
{ {
if (tree->root == tree->nil) return false; if (tree->root == tree->nil) return false;
@ -249,7 +282,7 @@ static b32 RBTreeSearch(RBTree *tree, i32 value, RBNode **out_node)
while (true) while (true)
{ {
if (node->value == value) if (node->key == key)
{ {
found = true; found = true;
break; break;
@ -258,7 +291,7 @@ static b32 RBTreeSearch(RBTree *tree, i32 value, RBNode **out_node)
if (node == tree->nil) if (node == tree->nil)
break; break;
if (node->value < value) if (node->key < key)
node = node->right; node = node->right;
else else
node = node->left; node = node->left;

View File

@ -30,7 +30,7 @@ typedef struct RBNode
struct RBNode *child[2]; struct RBNode *child[2];
}; };
struct RBNode *parent; struct RBNode *parent;
i32 value; u32 key;
rawptr data; rawptr data;
RBNodeColor color; RBNodeColor color;
} RBNode; } RBNode;
@ -42,9 +42,11 @@ typedef struct RBTree
} RBTree; } RBTree;
static void RBTreeInit (RBTree *tree); static void RBTreeInit (RBTree *tree);
static RBNode *RBTreeFindOrInsert(RBTree *tree, RBNode *node); static inline void RBTreeInitNode(RBNode *node, u32 key, rawptr value);
static b32 RBTreeSearch (RBTree *tree, i32 value, RBNode **node); static RBNode *RBTreeFindOrInsert(RBTree *tree, u32 key, rawptr value);
static void RBTreeDelete (RBTree *tree, i32 value); static b32 RBTreeSearchNearest(RBTree *tree, u32 key, RBNode **node);
static b32 RBTreeSearch (RBTree *tree, u32 key, RBNode **node);
static void RBTreeDelete (RBTree *tree, u32 key);
static void RBTreeLeftRotate (RBTree *tree, RBNode *node); static void RBTreeLeftRotate (RBTree *tree, RBNode *node);
static void RBTreeRightRotate(RBTree *tree, RBNode *node); static void RBTreeRightRotate(RBTree *tree, RBNode *node);
static void RBTreeRotate (RBTree *tree, RBNode *node, RBNodeDir dir); static void RBTreeRotate (RBTree *tree, RBNode *node, RBNodeDir dir);

View File

@ -1,5 +1,7 @@
#ifdef __linux__ #ifdef __linux__
// ::Entry::Linux::Globals::End::
#include "entry_linux.h" #include "entry_linux.h"
// ::ThirdParty::Include:: // ::ThirdParty::Include::
@ -16,12 +18,19 @@
# include "tests.c" # include "tests.c"
#endif #endif
// ::Entry::Linux::Globals::Start::
constexpr u8 asset_pack[] =
{
#embed "../assets.sgp"
};
static_assert(__COUNTER__ < Len(GLOBAL_PROFILER.anchors)); static_assert(__COUNTER__ < Len(GLOBAL_PROFILER.anchors));
void TraverseNode(RBTree *tree, RBNode *node, RBNodeDir *dir) void TraverseNode(RBTree *tree, RBNode *node, RBNodeDir *dir)
{ {
char *dir_str = dir == NULL ? "Root" : *dir == RB_RIGHT ? "Right" : "Left"; char *dir_str = dir == NULL ? "Root" : *dir == RB_RIGHT ? "Right" : "Left";
Printfln("Color: %s Value: %d Dir: %s", node->color == RB_RED ? "Red" : "Black", node->value, dir_str); Printfln("Color: %s Value: %d Dir: %s", node->color == RB_RED ? "Red" : "Black", node->key, dir_str);
if (node->left != tree->nil) if (node->left != tree->nil)
{ {
RBNodeDir left_dir = RB_LEFT; RBNodeDir left_dir = RB_LEFT;

View File

@ -841,8 +841,8 @@ static b32 CreateSwapchain()
u32 width = renderer.vk.sc.extent.width; u32 width = renderer.vk.sc.extent.width;
u32 height = renderer.vk.sc.extent.height; u32 height = renderer.vk.sc.extent.height;
extent.width = u32Clamp((u32)width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width); extent.width = Clamp((u32)width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
extent.height = u32Clamp((u32)height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height); extent.height = Clamp((u32)height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
if (present_mode == INT_MAX || format == INT_MAX || color_space == INT_MAX) if (present_mode == INT_MAX || format == INT_MAX || color_space == INT_MAX)
{ {

View File

@ -119,6 +119,8 @@ void MemZero(void *ptr, isize size)
void MemCpy(rawptr dst, rawptr src, usize size) void MemCpy(rawptr dst, rawptr src, usize size)
{ {
if (size == 0) return;
isize iter_size = size > sizeof(u64) ? 8 : 1; isize iter_size = size > sizeof(u64) ? 8 : 1;
iter_size *= 4; iter_size *= 4;
isize iter_len = size / iter_size; isize iter_len = size / iter_size;
@ -164,35 +166,9 @@ void MemCpy(rawptr dst, rawptr src, usize size)
// ::Util::Math::Functions::Start:: // ::Util::Math::Functions::Start::
u32 u32Min(u32 l, u32 r) DefMathImpl(Min);
{ DefMathImpl(Max);
return l >= r ? r : l; DefMathImpl(Clamp);
}
i32 i32Min(i32 l, i32 r)
{
return l >= r ? r : l;
}
u32 u32Max(u32 l, u32 r)
{
return l >= r ? l : r;
}
i32 i32Max(i32 l, i32 r)
{
return l >= r ? l : r;
}
i32 i32Clamp(i32 v, i32 min, i32 max)
{
return i32Min(max, i32Max(v, min));
}
u32 u32Clamp(u32 v, u32 min, u32 max)
{
return i32Min(max, i32Max(v, min));
}
// ::Util::Math::Functions::End:: // ::Util::Math::Functions::End::

View File

@ -113,12 +113,60 @@ void MemCpy(rawptr dst, rawptr src, usize len);
// ::Util::Math::Functions::Header:: // ::Util::Math::Functions::Header::
u32 u32Min(u32 l, u32 r); #define DefIntegerImpl(def) \
i32 i32Min(i32 l, i32 r); Def##def(i8); \
u32 u32Max(u32 l, u32 r); Def##def(i16); \
i32 i32Max(i32 l, i32 r); Def##def(i32); \
i32 i32Clamp(i32 v, i32 min, i32 max); Def##def(i64); \
u32 u32Clamp(u32 v, u32 min, u32 max); Def##def(u8); \
Def##def(u16); \
Def##def(u32); \
Def##def(u64)
#define DefFloatImpl(def) \
Def##def(f32); \
Def##def(f64)
#define DefMathImpl(def) \
DefIntegerImpl(def); \
DefFloatImpl(def);
#define MathGeneric(fn, params) _Generic(params, \
i8: i8##fn, \
i16: i16##fn, \
i32: i32##fn, \
i64: i64##fn, \
u8: u8##fn, \
u16: u16##fn, \
u32: u32##fn, \
u64: u64##fn, \
f32: f32##fn, \
f64: f64##fn \
)params
#define Min(l, r) MathGeneric(Min, (l, r))
#define Max(l, r) MathGeneric(Max, (l, r))
#define Clamp(v, min, max) MathGeneric(Clamp, (v, min, max))
#define DefMin(T) \
T T##Min(T l, T r) \
{ \
return l < r ? l : r; \
}
#define DefMax(T) \
T T##Max(T l, T r) \
{ \
return l > r ? l : r; \
}
#define DefClamp(T) \
T T##Clamp(T v, T min, T max) \
{ \
return Min(max, Max(v, min)); \
}
// ::Util::Hashing::Functions::Header:: // ::Util::Hashing::Functions::Header::