add merge sort

This commit is contained in:
jacob 2025-01-16 10:40:20 -06:00
parent 81f4049f95
commit c361becc73
2 changed files with 109 additions and 2 deletions

View File

@ -429,6 +429,22 @@ INTERNAL void debug_draw_movement(struct entity *ent)
draw_solid_arrow_ray(G.viewport_canvas, pos, vel_ray, thickness, arrow_len, color_vel);
}
/* ========================== *
* Sort entities
* ========================== */
INTERNAL SORT_COMPARE_FUNC_DEF(sort_entities, arg_a, arg_b, udata)
{
(UNUSED)udata;
struct entity *a = *(struct entity **)arg_a;
struct entity *b = *(struct entity **)arg_b;
u64 a_index = a->handle.idx;
u64 b_index = b->handle.idx;
return (a_index < b_index) - (a_index > b_index);
}
/* ========================== *
* Update
* ========================== */
@ -872,13 +888,32 @@ INTERNAL void user_update(void)
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
/* ========================== *
* Sort entities
* ========================== */
struct entity **sorted = arena_dry_push(scratch.arena, struct entity *);
u64 sorted_count = 0;
{
/* Copy valid entities */
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
struct entity *ent = &store->entities[entity_index];
if (entity_is_valid_and_active(ent)) {
*arena_push(scratch.arena, struct entity *) = ent;
++sorted_count;
}
}
/* Sort */
merge_sort(sorted, sorted_count, sizeof(*sorted), sort_entities, NULL);
}
/* ========================== *
* Draw entities
* ========================== */
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
for (u64 sorted_index = 0; sorted_index < sorted_count; ++sorted_index) {
__profscope(user_entity_iter);
struct entity *ent = &store->entities[entity_index];
struct entity *ent = sorted[sorted_index];
if (!entity_is_valid_and_active(ent)) continue;
//if (sprite_tag_is_nil(ent->sprite)) continue;

View File

@ -7,6 +7,7 @@
#include "arena.h"
#include "atomic.h"
#include "math.h"
#include "scratch.h"
/* Utility functions and stuff that don't have a home :( */
@ -42,6 +43,77 @@ INLINE u128 hash_fnv128(u128 seed, struct buffer buff)
return hash;
}
/* ========================== *
* Merge sort
* ========================== */
/* Compare functions should
* return an int < 0 if a < b
* return an int = 0 if a == b
* return an int > 0 if a > b
*/
#define SORT_COMPARE_FUNC_DEF(name, arg_a, arg_b, arg_udata) i32 name(void *arg_a, void *arg_b, void *arg_udata)
typedef SORT_COMPARE_FUNC_DEF(sort_compare_func, a, b, udata);
INLINE void merge_sort_internal(void *left, void *right, void *items, u64 left_count, u64 right_count, u64 item_size, sort_compare_func *callback, void *udata)
{
u64 i = 0;
u64 l = 0;
u64 r = 0;
while (l < left_count && r < right_count) {
u8 *dst = ((u8 *)items) + (i * item_size);
u8 *left_item = ((u8 *)left) + (l * item_size);
u8 *right_item = ((u8 *)right) + (r * item_size);
++i;
if (callback(left_item, right_item, udata) > 0) {
MEMCPY(dst, left_item, item_size);
++l;
} else {
MEMCPY(dst, right_item, item_size);
++r;
}
}
/* Copy remaining */
u64 left_remaining_bytes = (left_count - l) * item_size;
u64 right_remaining_bytes = (right_count - r) * item_size;
if (left_remaining_bytes > 0) {
u8 *dst = ((u8 *)items) + (i * item_size);
u8 *src = ((u8 *)left) + (l * item_size);
MEMCPY(dst, src, left_remaining_bytes);
i += left_count - l;
l = left_remaining_bytes;
}
if (right_remaining_bytes > 0) {
u8 *dst = ((u8 *)items) + (i * item_size);
u8 *src = ((u8 *)right) + (r * item_size);
MEMCPY(dst, src, right_remaining_bytes);
i += right_count - r;
l = right_remaining_bytes;
}
}
INLINE void merge_sort(void *items, u64 item_count, u64 item_size, sort_compare_func *callback, void *udata)
{
if (item_count > 1) {
struct temp_arena scratch = scratch_begin_no_conflict();
u64 left_count = item_count / 2;
u64 right_count = item_count - left_count;
u64 left_size = left_count * item_size;
u64 right_size = right_count * item_size;
u8 *left = arena_push_array(scratch.arena, u8, left_size);
u8 *right = arena_push_array(scratch.arena, u8, right_size);
MEMCPY(left, items, left_size);
MEMCPY(right, (u8 *)items + left_size, right_size);
merge_sort(left, left_count, item_size, callback, udata);
merge_sort(right, right_count, item_size, callback, udata);
merge_sort_internal(left, right, items, left_count, right_count, item_size, callback, udata);
scratch_end(scratch);
}
}
/* ========================== *
* Fixed Dict
*