23#define restrict __restrict__
41#define PASTE(a, b) a##b
49#define XPASTE(a, b) PASTE(a, b)
57#define JOIN(a, b) XPASTE(a, XPASTE(_, b))
66#ifndef FPQUEUE_LEFT_CHILD
67#define FPQUEUE_LEFT_CHILD(index) (2 * (index) + 1)
76#ifndef FPQUEUE_RIGHT_CHILD
77#define FPQUEUE_RIGHT_CHILD(index) (2 * (index) + 2)
87#define FPQUEUE_PARENT(index) (((index) - 1) / 2)
101#ifndef FPQUEUE_FOR_EACH
102#define FPQUEUE_FOR_EACH(self, index, value_) \
103 for ((index) = 0; (index) < (self)->count && ((value_) = (self)->elements[(index)].value, true); (index)++)
116#ifndef FPQUEUE_CALC_SIZEOF
117#define FPQUEUE_CALC_SIZEOF(fpqueue_name, capacity) \
118 (uint32_t)(offsetof(struct fpqueue_name, elements) + capacity * sizeof(((struct fpqueue_name *)0)->elements[0]))
131#ifndef FPQUEUE_CALC_SIZEOF_OVERFLOWS
132#define FPQUEUE_CALC_SIZEOF_OVERFLOWS(fpqueue_name, capacity) \
134 > (UINT32_MAX - offsetof(struct fpqueue_name, elements)) / sizeof(((struct fpqueue_name *)0)->elements[0]))
145#error "Must define NAME."
147#define FPQUEUE_NAME NAME
158#define VALUE_TYPE int
159#define FUNCTION_DEFINITIONS
160#define TYPE_DEFINITIONS
161#error "Must declare VALUE_TYPE."
168#ifndef FUNCTION_LINKAGE
169#define FUNCTION_LINKAGE
173#define FPQUEUE_TYPE struct FPQUEUE_NAME
174#define FPQUEUE_ELEMENT_TYPE struct JOIN(FPQUEUE_NAME, element)
175#define FPQUEUE_INIT JOIN(FPQUEUE_NAME, init)
176#define FPQUEUE_IS_EMPTY JOIN(FPQUEUE_NAME, is_empty)
177#define FPQUEUE_IS_FULL JOIN(FPQUEUE_NAME, is_full)
178#define FPQUEUE_UPHEAP JOIN(internal, JOIN(FPQUEUE_NAME, upheap))
179#define FPQUEUE_DOWNHEAP JOIN(internal, JOIN(FPQUEUE_NAME, downheap))
186struct JOIN(FPQUEUE_NAME, element);
193#ifdef TYPE_DEFINITIONS
198struct JOIN(FPQUEUE_NAME, element) {
224FUNCTION_LINKAGE FPQUEUE_TYPE *
JOIN(FPQUEUE_NAME, init)(FPQUEUE_TYPE *self,
const uint32_t capacity);
239 create_custom)(
const uint32_t capacity,
void *context_ptr,
240 void *(*allocate)(
void *context_ptr,
size_t alignment,
size_t size));
264 void (*deallocate)(
void *context_ptr,
void *mem));
355FUNCTION_LINKAGE void JOIN(FPQUEUE_NAME, copy)(FPQUEUE_TYPE *restrict dest_ptr,
const FPQUEUE_TYPE *restrict src_ptr);
365#ifdef FUNCTION_DEFINITIONS
375static inline void JOIN(internal,
JOIN(FPQUEUE_NAME, downheap))(FPQUEUE_TYPE *self,
const uint32_t index);
378static inline void JOIN(internal,
JOIN(FPQUEUE_NAME, upheap))(FPQUEUE_TYPE *self, uint32_t index);
387 self->capacity = capacity;
393 create_custom)(
const uint32_t capacity,
void *context_ptr,
394 void *(*allocate)(
void *context_ptr,
size_t alignment,
size_t size))
402 FPQUEUE_TYPE *self = (FPQUEUE_TYPE *)allocate(context_ptr,
alignof(FPQUEUE_TYPE), size);
408 memset(self, 0, size);
409 FPQUEUE_INIT(self, capacity);
415static inline void *
JOIN(internal,
JOIN(FPQUEUE_NAME, allocate))(
void *context_ptr,
size_t alignment,
size_t size)
425 return JOIN(FPQUEUE_NAME, create_custom)(capacity, NULL,
JOIN(internal,
JOIN(FPQUEUE_NAME, allocate)));
429 void (*deallocate)(
void *context_ptr,
void *mem))
431 assert(self != NULL);
433 deallocate(context_ptr, self);
437static inline void JOIN(internal,
JOIN(FPQUEUE_NAME, deallocate))(
void *context_ptr,
void *mem)
446 assert(self != NULL);
448 JOIN(FPQUEUE_NAME, destroy_custom)(self, NULL,
JOIN(internal,
JOIN(FPQUEUE_NAME, deallocate)));
453 assert(self != NULL);
455 return self->count == 0;
460 assert(self != NULL);
462 return self->count == self->capacity;
467 assert(self != NULL);
468 assert(FPQUEUE_IS_EMPTY(self) ==
false);
470 return self->elements[0].value;
475 return JOIN(FPQUEUE_NAME, get_max)(self);
480 assert(self != NULL);
481 assert(FPQUEUE_IS_EMPTY(self) ==
false);
483 VALUE_TYPE max_priority_value = self->elements[0].value;
485 self->elements[0] = self->elements[self->count - 1];
489 JOIN(internal,
JOIN(FPQUEUE_NAME, downheap))(self, 0);
491 return max_priority_value;
496 assert(self != NULL);
497 assert(FPQUEUE_IS_FULL(self) ==
false);
499 const uint32_t index = self->count;
501 self->elements[index] = (FPQUEUE_ELEMENT_TYPE){.priority = priority, .value = value};
505 JOIN(internal,
JOIN(FPQUEUE_NAME, upheap))(self, index);
510 assert(self != NULL);
515FUNCTION_LINKAGE void JOIN(FPQUEUE_NAME, copy)(FPQUEUE_TYPE *restrict dest_ptr,
const FPQUEUE_TYPE *restrict src_ptr)
517 assert(src_ptr != NULL);
518 assert(dest_ptr != NULL);
519 assert(src_ptr->count <= dest_ptr->capacity);
520 assert(FPQUEUE_IS_EMPTY(dest_ptr));
522 for (uint32_t i = 0; i < src_ptr->count; i++) {
523 dest_ptr->elements[i] = src_ptr->elements[i];
525 dest_ptr->count = src_ptr->count;
530static inline void JOIN(internal,
JOIN(FPQUEUE_NAME, upheap))(FPQUEUE_TYPE *self, uint32_t index)
532 assert(self != NULL);
533 assert(index < self->count);
539 const bool sorted = self->elements[parent].priority >= self->elements[index].priority;
545 const FPQUEUE_ELEMENT_TYPE temp = self->elements[index];
546 self->elements[index] = self->elements[parent];
547 self->elements[parent] = temp;
553static inline void JOIN(internal,
JOIN(FPQUEUE_NAME, downheap))(FPQUEUE_TYPE *self,
const uint32_t index)
555 assert(self != NULL);
556 assert(self->count == 0 || index < self->count);
561 uint32_t largest = index;
562 if (l < self->count && self->elements[l].priority > self->elements[index].priority) {
565 if (r < self->count && self->elements[r].priority > self->elements[largest].priority) {
569 if (largest == index) {
573 const FPQUEUE_ELEMENT_TYPE temp = self->elements[index];
574 self->elements[index] = self->elements[largest];
575 self->elements[largest] = temp;
577 JOIN(internal,
JOIN(FPQUEUE_NAME, downheap))(self, largest);
589#undef FUNCTION_LINKAGE
590#undef FUNCTION_DEFINITIONS
591#undef TYPE_DEFINITIONS
595#undef FPQUEUE_ELEMENT_TYPE
597#undef FPQUEUE_IS_EMPTY
598#undef FPQUEUE_IS_FULL
599#undef FPQUEUE_CALC_SIZEOF
600#undef FHASHTABLE_UPHEAP
601#undef FHASHTABLE_DOWNHEAP
#define JOIN(a, b)
First expand tokens, then paste them together with a _ in between.
Definition fpqueue_template.h:57
#define FPQUEUE_RIGHT_CHILD(index)
Given an element index, get the index of the right child.
Definition fpqueue_template.h:77
#define FPQUEUE_CALC_SIZEOF(fpqueue_name, capacity)
Calculate the size of the pqueue struct. No overflow checks.
Definition fpqueue_template.h:117
#define FPQUEUE_LEFT_CHILD(index)
Given an element index, get the index of the left child.
Definition fpqueue_template.h:67
#define FPQUEUE_PARENT(index)
Given an element index, get the index of the parent.
Definition fpqueue_template.h:87
#define VALUE_TYPE
Priority queue value type. This must be manually defined before including this header file.
Definition fpqueue_template.h:158
#define FPQUEUE_CALC_SIZEOF_OVERFLOWS(fpqueue_name, capacity)
Check for a given capacity, if the equivalent size of the pqueue struct overflows.
Definition fpqueue_template.h:132
#define FUNCTION_LINKAGE
Specify function linkage e.g. static inline.
Definition fstack_template.h:146
#define JOIN(a, b)
First expand tokens, then paste them together with a _ in between.
Definition fstack_template.h:50
#define VALUE_TYPE
Stack value type. This must be manually defined before including this header file.
Definition fstack_template.h:135
uint32_t priority
Element priority (highest is next to-be-popped).
Definition fpqueue_template.h:199
VALUE_TYPE value
Element value member.
Definition fpqueue_template.h:200
uint32_t capacity
Number of elements allocated for.
Definition fpqueue_template.h:208
fpqueue_element_type elements[]
Array of elements.
Definition fpqueue_template.h:209
uint32_t count
Number of non-empty elements.
Definition fpqueue_template.h:207