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};
read_only FLNode FL_NIL_NODE = {0};
#define ALLOC_CAP 16
// ::Allocator::Util::Header::
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)
{
ALLOC.tree = FLMemAlloc(sizeof(RBTree));
RBTreeInit(ALLOC.tree);
ALLOC.grow_size = init_size;
ALLOC.buffer = MemAllocZeroed(init_size);
ALLOC.size = init_size;
ALLOC.free_size = init_size;
ALLOC.hash_table = FLMemAlloc(sizeof(HashTable));
HashTableInit(ALLOC.hash_table, 32);
ALLOC.buffers = FLMemAlloc(sizeof(FreeListBuffer) * ALLOC_CAP);
ALLOC.count = 1;
ALLOC.cap = ALLOC_CAP;
ALLOC.grow_size = init_size;
ALLOC.tree = FLMemAlloc(sizeof(RBTree));
RBTreeInit(ALLOC.tree);
InitAllocatorBuffer(&ALLOC.buffers[0], init_size);
AllocInfo *info = CreateAllocInfo(ALLOC.buffer);
RBTreeFindOrInsert(ALLOC.tree, init_size, info);
}
static void InitAllocatorBuffer(FreeListBuffer *buffer, usize init_size)
static AllocInfo *CreateAllocInfo(rawptr ptr)
{
buffer->buf = MemAllocZeroed(init_size);
buffer->size = init_size;
buffer->free_size = init_size;
AllocInfo *info = FLMemAlloc(sizeof(AllocInfo));
info->ptrs = FLMemAlloc(sizeof(rawptr *));
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()
{
for (u8 i = 0; i < ALLOC.count; i++)
{
MemFree(ALLOC.buffers[i].buf, ALLOC.buffers[i].size);
}
MemFree(ALLOC.buffer, ALLOC.size);
}
static rawptr Alloc(usize size)
@ -140,19 +169,30 @@ static rawptr Alloc(usize size)
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)
{
if (ptr == NULL) return;
}
static void AllocGrow()
static void AllocGrow(usize size)
{
Assert(ALLOC.count < ALLOC.cap, "Global allocator has reached capacity");
InitAllocatorBuffer(&ALLOC.buffers[ALLOC.count], ALLOC.grow_size);
ALLOC.count += 1;
usize grow_size = size < ALLOC.grow_size ? ALLOC.grow_size : ALLOC.grow_size + size;
MemRealloc(ALLOC.buffer, ALLOC.size, ALLOC.size + grow_size);
ALLOC.size += grow_size;
ALLOC.free_size += grow_size;
}
// ::Allocator::GlobalAlloc::End::
@ -171,7 +211,7 @@ static rawptr FLMemAlloc(usize size)
return FreeListAlloc(&FL_ALLOC, size);
}
static void FLFree(rawptr ptr)
static void FLMemFree(rawptr 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)
{
if (size == 0) return NULL;
usize padding = 0;
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::
typedef struct FreeListBuffer
typedef struct AllocInfo
{
rawptr buf;
u32 size;
u32 free_size;
} FreeListBuffer;
rawptr *ptrs;
u32 count;
} AllocInfo;
typedef struct Allocator
{
RBTree *tree;
FreeListBuffer *buffers;
HashTable *hash_table;
usize grow_size;
u64 count;
u64 cap;
rawptr buffer;
u64 size;
u64 free_size;
u64 grow_size;
} Allocator;
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 AllocGrow();
static void AllocGrow(usize size);
static rawptr Alloc(usize size);
static rawptr AllocAlign(usize size, usize alignment);
static void Free(rawptr ptr);
@ -92,7 +93,7 @@ typedef struct FLAlloc
static void GlobalFreeListInit(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(FLAlloc *alloc, usize size);
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;
}
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;
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");
if (curr_node->value == node->value)
if (curr_node->key == node->key)
{
existing_node = curr_node;
break;
}
else if (curr_node->value < node->value)
else if (curr_node->key < node->key)
{
if (curr_node->right == tree->nil)
{
@ -124,10 +135,10 @@ static void RBTreeCorrect(RBTree *tree, RBNode *node)
} while ((p = node->parent));
}
static void RBTreeDelete(RBTree *tree, i32 value)
static void RBTreeDelete(RBTree *tree, u32 key)
{
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)
{
@ -140,7 +151,7 @@ static void RBTreeDelete(RBTree *tree, i32 value)
while (ln->left != tree->nil)
ln = ln->left;
node->value = ln->value;
node->key = ln->key;
node->data = ln->data;
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)
{
node->value = node->left->value;
node->key = node->left->key;
node->data = node->left->data;
node->left = 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->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;
@ -249,7 +282,7 @@ static b32 RBTreeSearch(RBTree *tree, i32 value, RBNode **out_node)
while (true)
{
if (node->value == value)
if (node->key == key)
{
found = true;
break;
@ -258,7 +291,7 @@ static b32 RBTreeSearch(RBTree *tree, i32 value, RBNode **out_node)
if (node == tree->nil)
break;
if (node->value < value)
if (node->key < key)
node = node->right;
else
node = node->left;

View File

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

View File

@ -1,5 +1,7 @@
#ifdef __linux__
// ::Entry::Linux::Globals::End::
#include "entry_linux.h"
// ::ThirdParty::Include::
@ -16,12 +18,19 @@
# include "tests.c"
#endif
// ::Entry::Linux::Globals::Start::
constexpr u8 asset_pack[] =
{
#embed "../assets.sgp"
};
static_assert(__COUNTER__ < Len(GLOBAL_PROFILER.anchors));
void TraverseNode(RBTree *tree, RBNode *node, RBNodeDir *dir)
{
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)
{
RBNodeDir left_dir = RB_LEFT;

View File

@ -841,8 +841,8 @@ static b32 CreateSwapchain()
u32 width = renderer.vk.sc.extent.width;
u32 height = renderer.vk.sc.extent.height;
extent.width = u32Clamp((u32)width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
extent.height = u32Clamp((u32)height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
extent.width = Clamp((u32)width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
extent.height = Clamp((u32)height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
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)
{
if (size == 0) return;
isize iter_size = size > sizeof(u64) ? 8 : 1;
iter_size *= 4;
isize iter_len = size / iter_size;
@ -164,35 +166,9 @@ void MemCpy(rawptr dst, rawptr src, usize size)
// ::Util::Math::Functions::Start::
u32 u32Min(u32 l, u32 r)
{
return l >= r ? r : l;
}
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));
}
DefMathImpl(Min);
DefMathImpl(Max);
DefMathImpl(Clamp);
// ::Util::Math::Functions::End::

View File

@ -113,12 +113,60 @@ void MemCpy(rawptr dst, rawptr src, usize len);
// ::Util::Math::Functions::Header::
u32 u32Min(u32 l, u32 r);
i32 i32Min(i32 l, i32 r);
u32 u32Max(u32 l, u32 r);
i32 i32Max(i32 l, i32 r);
i32 i32Clamp(i32 v, i32 min, i32 max);
u32 u32Clamp(u32 v, u32 min, u32 max);
#define DefIntegerImpl(def) \
Def##def(i8); \
Def##def(i16); \
Def##def(i32); \
Def##def(i64); \
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::