182 lines
5.6 KiB
C
182 lines
5.6 KiB
C
/* MIT License
|
|
*
|
|
* Copyright (c) 2025 Tyge Løvset
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
* copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*/
|
|
#include "priv/linkage.h"
|
|
#include "types.h"
|
|
|
|
#ifndef STC_PQUEUE_H_INCLUDED
|
|
#define STC_PQUEUE_H_INCLUDED
|
|
#include "common.h"
|
|
#include <stdlib.h>
|
|
#endif // STC_PQUEUIE_H_INCLUDED
|
|
|
|
#ifndef _i_prefix
|
|
#define _i_prefix pqueue_
|
|
#endif
|
|
#define _i_sorted
|
|
#include "priv/template.h"
|
|
#ifndef i_declared
|
|
_c_DEFTYPES(_declare_stack, Self, i_key, _i_aux_def);
|
|
#endif
|
|
typedef i_keyraw _m_raw;
|
|
|
|
STC_API void _c_MEMB(_make_heap)(Self* self);
|
|
STC_API void _c_MEMB(_erase_at)(Self* self, isize idx);
|
|
STC_API _m_value* _c_MEMB(_push)(Self* self, _m_value value);
|
|
|
|
STC_INLINE void _c_MEMB(_put_n)(Self* self, const _m_raw* raw, isize n)
|
|
{ while (n--) _c_MEMB(_push)(self, i_keyfrom(*raw++)); }
|
|
|
|
STC_INLINE bool _c_MEMB(_reserve)(Self* self, const isize cap) {
|
|
if (cap != self->size && cap <= self->capacity) return true;
|
|
_m_value *d = (_m_value *)_i_realloc_n(self->data, self->capacity, cap);
|
|
return d ? (self->data = d, self->capacity = cap, true) : false;
|
|
}
|
|
|
|
STC_INLINE void _c_MEMB(_shrink_to_fit)(Self* self)
|
|
{ _c_MEMB(_reserve)(self, self->size); }
|
|
|
|
#ifndef _i_aux_alloc
|
|
STC_INLINE Self _c_MEMB(_init)(void)
|
|
{ return c_literal(Self){0}; }
|
|
|
|
STC_INLINE Self _c_MEMB(_from_n)(const _m_raw* raw, isize n)
|
|
{ Self cx = {0}; _c_MEMB(_put_n)(&cx, raw, n); return cx; }
|
|
|
|
STC_INLINE Self _c_MEMB(_with_capacity)(const isize cap)
|
|
{ Self cx = {0}; _c_MEMB(_reserve)(&cx, cap); return cx; }
|
|
#endif
|
|
|
|
STC_INLINE void _c_MEMB(_clear)(Self* self) {
|
|
isize i = self->size; self->size = 0;
|
|
while (i--) { i_keydrop((self->data + i)); }
|
|
}
|
|
|
|
STC_INLINE void _c_MEMB(_drop)(const Self* cself) {
|
|
Self* self = (Self*)cself;
|
|
_c_MEMB(_clear)(self);
|
|
_i_free_n(self->data, self->capacity);
|
|
}
|
|
|
|
STC_INLINE Self _c_MEMB(_move)(Self *self) {
|
|
Self m = *self;
|
|
self->size = self->capacity = 0;
|
|
self->data = NULL;
|
|
return m;
|
|
}
|
|
|
|
STC_INLINE void _c_MEMB(_take)(Self *self, Self unowned) {
|
|
_c_MEMB(_drop)(self);
|
|
*self = unowned;
|
|
}
|
|
|
|
STC_INLINE isize _c_MEMB(_size)(const Self* q)
|
|
{ return q->size; }
|
|
|
|
STC_INLINE bool _c_MEMB(_is_empty)(const Self* q)
|
|
{ return !q->size; }
|
|
|
|
STC_INLINE isize _c_MEMB(_capacity)(const Self* q)
|
|
{ return q->capacity; }
|
|
|
|
STC_INLINE const _m_value* _c_MEMB(_top)(const Self* self)
|
|
{ return &self->data[0]; }
|
|
|
|
STC_INLINE void _c_MEMB(_pop)(Self* self)
|
|
{ c_assert(!_c_MEMB(_is_empty)(self)); _c_MEMB(_erase_at)(self, 0); }
|
|
|
|
STC_INLINE _m_value _c_MEMB(_pull)(Self* self)
|
|
{ _m_value v = self->data[0]; _c_MEMB(_erase_at)(self, 0); return v; }
|
|
|
|
#if !defined i_no_clone
|
|
STC_API Self _c_MEMB(_clone)(Self q);
|
|
|
|
STC_INLINE void _c_MEMB(_copy)(Self *self, const Self* other) {
|
|
if (self == other) return;
|
|
_c_MEMB(_drop)(self);
|
|
*self = _c_MEMB(_clone)(*other);
|
|
}
|
|
STC_INLINE _m_value _c_MEMB(_value_clone)(const Self* self, _m_value val)
|
|
{ (void)self; return i_keyclone(val); }
|
|
#endif // !i_no_clone
|
|
|
|
#if !defined i_no_emplace
|
|
STC_INLINE void _c_MEMB(_emplace)(Self* self, _m_raw raw)
|
|
{ _c_MEMB(_push)(self, i_keyfrom(raw)); }
|
|
#endif // !i_no_emplace
|
|
|
|
/* -------------------------- IMPLEMENTATION ------------------------- */
|
|
#if defined i_implement
|
|
|
|
STC_DEF void
|
|
_c_MEMB(_sift_down_)(Self* self, const isize idx, const isize n) {
|
|
_m_value t, *arr = self->data - 1;
|
|
for (isize r = idx, c = idx*2; c <= n; c *= 2) {
|
|
c += i_less((&arr[c]), (&arr[c + (c < n)]));
|
|
if (!(i_less((&arr[r]), (&arr[c])))) return;
|
|
t = arr[r], arr[r] = arr[c], arr[r = c] = t;
|
|
}
|
|
}
|
|
|
|
STC_DEF void
|
|
_c_MEMB(_make_heap)(Self* self) {
|
|
isize n = self->size;
|
|
for (isize k = n/2; k != 0; --k)
|
|
_c_MEMB(_sift_down_)(self, k, n);
|
|
}
|
|
|
|
#if !defined i_no_clone
|
|
STC_DEF Self _c_MEMB(_clone)(Self q) {
|
|
Self out = q, *self = &out; (void)self;
|
|
out.capacity = out.size = 0; out.data = NULL;
|
|
_c_MEMB(_reserve)(&out, q.size);
|
|
out.size = q.size;
|
|
for (c_range(i, q.size))
|
|
out.data[i] = i_keyclone(q.data[i]);
|
|
return out;
|
|
}
|
|
#endif
|
|
|
|
STC_DEF void
|
|
_c_MEMB(_erase_at)(Self* self, const isize idx) {
|
|
i_keydrop((self->data + idx));
|
|
const isize n = --self->size;
|
|
self->data[idx] = self->data[n];
|
|
_c_MEMB(_sift_down_)(self, idx + 1, n);
|
|
}
|
|
|
|
STC_DEF _m_value*
|
|
_c_MEMB(_push)(Self* self, _m_value value) {
|
|
if (self->size == self->capacity)
|
|
_c_MEMB(_reserve)(self, self->size*3/2 + 4);
|
|
_m_value *arr = self->data - 1; /* base 1 */
|
|
isize c = ++self->size;
|
|
for (; c > 1 && (i_less((&arr[c/2]), (&value))); c /= 2)
|
|
arr[c] = arr[c/2];
|
|
arr[c] = value;
|
|
return arr + c;
|
|
}
|
|
#endif
|
|
|
|
#undef _i_sorted
|
|
#include "sys/finalize.h"
|