From 9b5cf6857cdd87fcc917095ef6d95297f5a01634 Mon Sep 17 00:00:00 2001 From: Phil Schumann Date: Mon, 3 Feb 2025 21:51:03 +0100 Subject: [PATCH 1/5] Prevents gcc warning/error with `-fpermissive` Explicit casting to the rescue =) --- include/generic_list.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/generic_list.h b/include/generic_list.h index c66ea39..3f20eb7 100644 --- a/include/generic_list.h +++ b/include/generic_list.h @@ -64,7 +64,7 @@ } \ \ static inline void function_prefix ## _shrink_to_fit(type_name* list) { \ - list->buffer = realloc(list->buffer, (list->count == 0 ? 1 : list->count) * sizeof(value_type)); \ + list->buffer = (value_type*) realloc(list->buffer, (list->count == 0 ? 1 : list->count) * sizeof(value_type)); \ list->capacity = list->count == 0 ? 1 : list->count; \ } \ @@ -124,4 +124,4 @@ -#endif \ No newline at end of file +#endif From 081f71d11887fee67f22d8e2bea11e4e84f715cc Mon Sep 17 00:00:00 2001 From: Phil Schumann Date: Wed, 5 Feb 2025 21:53:51 +0100 Subject: [PATCH 2/5] Support zero-initialized lists in `add` and ` insert` --- include/generic_list.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/generic_list.h b/include/generic_list.h index 3f20eb7..10d76d0 100644 --- a/include/generic_list.h +++ b/include/generic_list.h @@ -96,7 +96,7 @@ \ bool function_prefix ## _add(type_name* list, value_type value) { \ if(list->count == list->capacity) { \ - list->capacity *= 2; \ + list->capacity = (list->capacity == 0) ? 2 : (list->capacity * 2); \ value_type* buffer = realloc(list->buffer, list->capacity * sizeof(value_type)); \ if(!buffer) \ return false; \ @@ -111,7 +111,7 @@ if(index == list->count) \ return function_prefix ## _add(list, value); \ if(list->count == list->capacity) { \ - list->capacity *= 2; \ + list->capacity = (list->capacity == 0) ? 2 : (list->capacity * 2); \ value_type* buffer = realloc(list->buffer, list->capacity * sizeof(value_type)); \ if(!buffer) \ return false; \ From 14ead9f72c8d9b5c7cb9812403eb74e8479e96fc Mon Sep 17 00:00:00 2001 From: Phil Schumann Date: Fri, 7 Feb 2025 22:55:41 +0100 Subject: [PATCH 3/5] New List_addAligned method Due to [simd](https://github.com/recp/cglm/discussions/447).. --- include/generic_list.h | 245 +++++++++++++++++++++++------------------ 1 file changed, 136 insertions(+), 109 deletions(-) diff --git a/include/generic_list.h b/include/generic_list.h index 10d76d0..525adbd 100644 --- a/include/generic_list.h +++ b/include/generic_list.h @@ -7,120 +7,147 @@ #include #include -// Todo: +// Todo: // bool add_range(type_name* list, value_type* values, unsigned int count); // bool insert_range(type_name* list, unsigned int index, value_type* values, unsigned int count); -#define LIST_DEFINE_H(type_name, function_prefix, value_type) \ - typedef struct type_name { \ - value_type* buffer; \ - unsigned int count; \ - unsigned int capacity; \ - } type_name; \ - \ - type_name* function_prefix ## _create(void); \ - bool function_prefix ## _init(type_name* list); \ - bool function_prefix ## _init_capacity(type_name* list, unsigned int capacity); \ - bool function_prefix ## _add(type_name* list, value_type value); \ - bool function_prefix ## _insert(type_name* list, unsigned int index, value_type value); \ - \ - static inline void function_prefix ## _clear(type_name* list) { list->count = 0; } \ - \ - static inline unsigned int function_prefix ## _count(type_name* list) { return list->count; } \ - \ - static inline void function_prefix ## _free_resources(type_name* list) { free(list->buffer); } \ - \ - static inline void function_prefix ## _free(type_name* list) { free(list->buffer); free(list); } \ - \ - static inline value_type function_prefix ## _get(type_name* list, unsigned int index) { \ - assert(index < list->count); \ - return list->buffer[index]; \ - } \ - \ - static inline void function_prefix ## _set(type_name* list, unsigned int index, value_type value) { \ - assert(index <= list->count); \ - if(index == list->count) \ - function_prefix ## _add(list, value); \ - else \ - list->buffer[index] = value; \ - } \ - \ - static inline void function_prefix ## _remove(type_name* list, unsigned int index) { \ - assert(index < list->count); \ - if(index == --list->count) \ - return; \ - else \ - memmove(list->buffer + index, list->buffer + index + 1, (list->count - index) * sizeof(value_type)); \ - } \ - \ - static inline value_type function_prefix ## _peek(type_name* list) { \ - assert(list->count); \ - return list->buffer[list->count - 1]; \ - } \ - \ - static inline value_type function_prefix ## _pop(type_name* list) { \ - assert(list->count); \ - return list->buffer[--list->count]; \ - } \ - \ - static inline void function_prefix ## _shrink_to_fit(type_name* list) { \ - list->buffer = (value_type*) realloc(list->buffer, (list->count == 0 ? 1 : list->count) * sizeof(value_type)); \ - list->capacity = list->count == 0 ? 1 : list->count; \ - } \ +#define LIST_DEFINE_H(type_name, function_prefix, value_type) \ + typedef struct type_name { \ + value_type* buffer; \ + unsigned int count; \ + unsigned int capacity; \ + } type_name; \ + \ + type_name* function_prefix##_create(void); \ + bool function_prefix##_init(type_name* list); \ + bool function_prefix##_init_capacity(type_name* list, unsigned int capacity); \ + bool function_prefix##_add(type_name* list, value_type value); \ + bool function_prefix##_addAligned(type_name* list, value_type value); \ + bool function_prefix##_insert(type_name* list, unsigned int index, value_type value); \ + \ + static inline void function_prefix##_clear(type_name* list) { \ + list->count = 0; \ + } \ + \ + static inline unsigned int function_prefix##_count(type_name* list) { \ + return list->count; \ + } \ + \ + static inline void function_prefix##_free_resources(type_name* list) { \ + free(list->buffer); \ + } \ + \ + static inline void function_prefix##_free(type_name* list) { \ + free(list->buffer); \ + free(list); \ + } \ + \ + static inline value_type function_prefix##_get(type_name* list, unsigned int index) { \ + assert(index < list->count); \ + return list->buffer[index]; \ + } \ + \ + static inline void function_prefix##_set(type_name* list, unsigned int index, value_type value) { \ + assert(index <= list->count); \ + if (index == list->count) \ + function_prefix##_add(list, value); \ + else \ + list->buffer[index] = value; \ + } \ + \ + static inline void function_prefix##_remove(type_name* list, unsigned int index) { \ + assert(index < list->count); \ + if (index == --list->count) \ + return; \ + else \ + memmove(list->buffer + index, list->buffer + index + 1, (list->count - index) * sizeof(value_type)); \ + } \ + \ + static inline value_type function_prefix##_peek(type_name* list) { \ + assert(list->count); \ + return list->buffer[list->count - 1]; \ + } \ + \ + static inline value_type function_prefix##_pop(type_name* list) { \ + assert(list->count); \ + return list->buffer[--list->count]; \ + } \ + \ + static inline void function_prefix##_shrink_to_fit(type_name* list) { \ + list->buffer = (value_type*) realloc(list->buffer, (list->count == 0 ? 1 : list->count) * sizeof(value_type)); \ + list->capacity = list->count == 0 ? 1 : list->count; \ + } -#define LIST_DEFINE_C(type_name, function_prefix, value_type) \ - type_name* function_prefix ## _create(void) { \ - type_name* list = malloc(sizeof(type_name)); \ - if(!list) \ - return list; \ - if(!function_prefix ## _init(list)) { \ - free(list); \ - return NULL; \ - } \ - return list; \ - } \ - \ - bool function_prefix ## _init(type_name* list) { \ - list->capacity = 4; \ - list->count = 0; \ - return (list->buffer = malloc(4 * sizeof(value_type))) != NULL; \ - } \ - \ - bool function_prefix ## _init_capacity(type_name* list, unsigned int capacity) { \ - assert(capacity); \ - list->capacity = capacity; \ - list->count = 0; \ - return (list->buffer = malloc(capacity * sizeof(value_type))) != NULL; \ - } \ - \ - bool function_prefix ## _add(type_name* list, value_type value) { \ - if(list->count == list->capacity) { \ - list->capacity = (list->capacity == 0) ? 2 : (list->capacity * 2); \ - value_type* buffer = realloc(list->buffer, list->capacity * sizeof(value_type)); \ - if(!buffer) \ - return false; \ - list->buffer = buffer; \ - } \ - list->buffer[list->count++] = value; \ - return true; \ - } \ - \ - bool function_prefix ## _insert(type_name* list, unsigned int index, value_type value) { \ - if(index > list->count) return false; \ - if(index == list->count) \ - return function_prefix ## _add(list, value); \ - if(list->count == list->capacity) { \ - list->capacity = (list->capacity == 0) ? 2 : (list->capacity * 2); \ - value_type* buffer = realloc(list->buffer, list->capacity * sizeof(value_type)); \ - if(!buffer) \ - return false; \ - list->buffer = buffer; \ - } \ - memmove(list->buffer + index + 1, list->buffer + index, (list->count++ - index) * sizeof(value_type)); \ - list->buffer[index] = value; \ - return true; \ - } \ +#define LIST_DEFINE_C(type_name, function_prefix, value_type) \ + type_name* function_prefix##_create(void) { \ + type_name* list = malloc(sizeof(type_name)); \ + if (!list) \ + return list; \ + if (!function_prefix##_init(list)) { \ + free(list); \ + return NULL; \ + } \ + return list; \ + } \ + \ + bool function_prefix##_init(type_name* list) { \ + list->capacity = 4; \ + list->count = 0; \ + return (list->buffer = malloc(4 * sizeof(value_type))) != NULL; \ + } \ + \ + bool function_prefix##_init_capacity(type_name* list, unsigned int capacity) { \ + assert(capacity); \ + list->capacity = capacity; \ + list->count = 0; \ + return (list->buffer = malloc(capacity * sizeof(value_type))) != NULL; \ + } \ + \ + bool function_prefix##_add(type_name* list, value_type value) { \ + if (list->count == list->capacity) { \ + list->capacity = (list->capacity == 0) ? 2 : (list->capacity * 2); \ + value_type* buffer = realloc(list->buffer, list->capacity * sizeof(value_type)); \ + if (!buffer) \ + return false; \ + list->buffer = buffer; \ + } \ + list->buffer[list->count++] = value; \ + return true; \ + } \ + \ + bool function_prefix##_addAligned(type_name* list, value_type value) { \ + if (list->count == list->capacity) { \ + list->capacity = (list->capacity == 0) ? 2 : (list->capacity * 2); \ + value_type* buffer = aligned_alloc(alignof(value_type), list->capacity * sizeof(value_type)); \ + if (!buffer) \ + return false; \ + if ((list->buffer != nullptr) && (list->count > 0)) { \ + memcpy(buffer, list->buffer, list->count * sizeof(value_type)); \ + free(list->buffer); \ + } \ + list->buffer = buffer; \ + } \ + list->buffer[list->count++] = value; \ + return true; \ + } \ + \ + bool function_prefix##_insert(type_name* list, unsigned int index, value_type value) { \ + if (index > list->count) \ + return false; \ + if (index == list->count) \ + return function_prefix##_add(list, value); \ + if (list->count == list->capacity) { \ + list->capacity = (list->capacity == 0) ? 2 : (list->capacity * 2); \ + value_type* buffer = realloc(list->buffer, list->capacity * sizeof(value_type)); \ + if (!buffer) \ + return false; \ + list->buffer = buffer; \ + } \ + memmove(list->buffer + index + 1, list->buffer + index, (list->count++ - index) * sizeof(value_type)); \ + list->buffer[index] = value; \ + return true; \ + } From b76c3112d1c12198d604e1e1b07f9c9c7e282a09 Mon Sep 17 00:00:00 2001 From: Phil Schumann Date: Sat, 8 Feb 2025 00:41:54 +0100 Subject: [PATCH 4/5] aligned_alloc instead of malloc --- include/generic_list.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/generic_list.h b/include/generic_list.h index 525adbd..3b7f09c 100644 --- a/include/generic_list.h +++ b/include/generic_list.h @@ -94,14 +94,14 @@ bool function_prefix##_init(type_name* list) { \ list->capacity = 4; \ list->count = 0; \ - return (list->buffer = malloc(4 * sizeof(value_type))) != NULL; \ + return (list->buffer = aligned_alloc(alignof(value_type), 4 * sizeof(value_type))) != NULL; \ } \ \ bool function_prefix##_init_capacity(type_name* list, unsigned int capacity) { \ assert(capacity); \ list->capacity = capacity; \ list->count = 0; \ - return (list->buffer = malloc(capacity * sizeof(value_type))) != NULL; \ + return (list->buffer = aligned_alloc(alignof(value_type), capacity * sizeof(value_type))) != NULL; \ } \ \ bool function_prefix##_add(type_name* list, value_type value) { \ From fe48b81e3149772fb0e4cfd219c8d36593261567 Mon Sep 17 00:00:00 2001 From: Phil Schumann Date: Sat, 8 Feb 2025 21:12:49 +0100 Subject: [PATCH 5/5] More aligned_alloc --- include/generic_list.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/generic_list.h b/include/generic_list.h index 3b7f09c..7aab7a6 100644 --- a/include/generic_list.h +++ b/include/generic_list.h @@ -107,7 +107,9 @@ bool function_prefix##_add(type_name* list, value_type value) { \ if (list->count == list->capacity) { \ list->capacity = (list->capacity == 0) ? 2 : (list->capacity * 2); \ - value_type* buffer = realloc(list->buffer, list->capacity * sizeof(value_type)); \ + value_type* buffer = ((list->buffer == nullptr) || (list->count == 0)) \ + ? aligned_alloc(alignof(value_type), list->capacity * sizeof(value_type)) \ + : realloc(list->buffer, list->capacity * sizeof(value_type)); \ if (!buffer) \ return false; \ list->buffer = buffer; \