mirror of
https://bitbucket.org/cosmicvoids/vide_public.git
synced 2025-07-06 16:21:11 +00:00
152 lines
3.2 KiB
C
152 lines
3.2 KiB
C
/* Super-fast priority queue. ? Completely inlined by gcc. */
|
|
/* Assume that each pointer points at */
|
|
/* a key, AND whatever else the caller is interested in keeping. */
|
|
#ifndef HEAPdotH
|
|
#define HEAPdotH
|
|
|
|
|
|
typedef struct{
|
|
const float **arr;
|
|
unsigned int sz;
|
|
unsigned int cnt;
|
|
} Heap;
|
|
|
|
#ifdef __cplusplus
|
|
extern "C"{
|
|
#endif /* __cplusplus */
|
|
extern void HeapInit(Heap *hp, unsigned int initial_nelem);
|
|
extern void HeapTerminate(Heap *hp);
|
|
extern void HeapPush(Heap *hp, const float *ptr);
|
|
extern void HeapPop(Heap *hp, const float **keyp);
|
|
extern const float *HeapPeek(const Heap *hp);
|
|
extern const float **HeapBase(const Heap *hp);
|
|
extern const float **HeapEnd(const Heap *hp);
|
|
extern unsigned int HeapCnt(const Heap *hp);
|
|
extern int HeapIsBad(const Heap *hp);
|
|
extern const float HeapMinf;
|
|
extern const float HeapInf;
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif /* __cplusplus */
|
|
|
|
/* This is an attempt to get the inline functions into the .h file */
|
|
/* without having to maintain two source files. */
|
|
#if (defined(__GNUC__) || defined(__ICC__)) || defined(HEAPdotC)
|
|
|
|
#ifndef assert
|
|
#include "Assert.h"
|
|
#endif
|
|
#include <stddef.h>
|
|
#include <float.h>
|
|
#include "Malloc.h"
|
|
|
|
#undef INLINE
|
|
#if (defined (__GNUC__) || defined(__ICC__)) && !defined (HEAPdotC)
|
|
#define INLINE extern __inline__
|
|
#else
|
|
#define INLINE
|
|
#endif
|
|
|
|
#ifndef NULL
|
|
#define NULL (void *)0
|
|
#endif
|
|
#ifndef EXIT_SUCCESS
|
|
#define EXIT_SUCCESS 0
|
|
#endif
|
|
|
|
#if defined(HeapKey) || defined(HeapParent) || defined(HeapLeft)
|
|
# error Problems with conflicting definitions in heap.h
|
|
#endif
|
|
#define HeapKey(i) (*arr[i])
|
|
#define HeapParent(i) (i>>1)
|
|
#define HeapLeft(i) (i<<1)
|
|
/* Use left+1 for right */
|
|
|
|
INLINE void HeapPush(Heap *hp, const float *ptr){
|
|
const float **arr = hp->arr;
|
|
const float *tmp;
|
|
unsigned int i = hp->cnt++;
|
|
unsigned int pi;
|
|
|
|
if( i == hp->sz ){
|
|
unsigned int newsz = (hp->sz)<<1;
|
|
arr = hp->arr = Realloc(hp->arr, (newsz+1)*sizeof(*(hp->arr)));
|
|
assert(hp->arr);
|
|
hp->sz = newsz;
|
|
}
|
|
|
|
arr[i] = ptr;
|
|
pi = HeapParent(i);
|
|
while( HeapKey(pi) <= HeapKey(i) ){
|
|
tmp = arr[pi];
|
|
arr[pi] = arr[i];
|
|
arr[i] = tmp;
|
|
i = pi;
|
|
pi = HeapParent(i);
|
|
}
|
|
}
|
|
|
|
INLINE void HeapPop(Heap *hp, const float **keyp){
|
|
const float **arr = hp->arr;
|
|
const float *save;
|
|
unsigned int i, li, ri, ix, n;
|
|
float kl, kr, ksave, kx;
|
|
|
|
*keyp = arr[1];
|
|
n = --hp->cnt;
|
|
assert( n>0 );
|
|
i = 1;
|
|
li = 2;
|
|
ri = 3;
|
|
save = arr[n];
|
|
ksave = *save;
|
|
arr[n] = &HeapMinf;
|
|
while( li < n ){
|
|
kl = HeapKey(li);
|
|
kr = HeapKey(ri);
|
|
if( kl >= kr ){
|
|
ix = li;
|
|
kx = kl;
|
|
}else{
|
|
ix = ri;
|
|
kx = kr;
|
|
}
|
|
if( ksave >= kx ){
|
|
break;
|
|
}
|
|
|
|
/* Move ix up the heap */
|
|
arr[i] = arr[ix];
|
|
i = ix;
|
|
li = HeapLeft(ix);
|
|
ri = li+1;
|
|
}
|
|
arr[i] = save;
|
|
}
|
|
|
|
INLINE const float *HeapPeek(const Heap *hp){
|
|
return hp->arr[1];
|
|
}
|
|
|
|
INLINE const float **HeapBase(const Heap *hp){
|
|
return &hp->arr[1];
|
|
}
|
|
|
|
INLINE const float **HeapEnd(const Heap *hp){
|
|
return &hp->arr[hp->cnt];
|
|
}
|
|
|
|
INLINE unsigned int HeapCnt(const Heap *hp){
|
|
return hp->cnt-1;
|
|
}
|
|
|
|
/* Undefine our private macros */
|
|
#ifndef HEAPdotC
|
|
#undef HeapKey
|
|
#undef HeapParent
|
|
#undef HeapLeft
|
|
#endif /* HEAPdotC */
|
|
#undef INLINE
|
|
|
|
#endif /* __GNUC__ || HEAPdotC */
|
|
#endif /* already included */
|