Loading [MathJax]/extensions/TeX/AMSsymbols.js
LAL 7.7.0.1-5e288d3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
LALHeap.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2016 Karl Wette
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with with program; see the file COPYING. If not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301 USA
18 */
19
20#include <lal/LALHeap.h>
21
22#define LEFT(i) (2*(i) + 1) /* Left child of binary heap element 'i' */
23#define RIGHT(i) (2*(i) + 2) /* Right child of binary heap element 'i' */
24#define PARENT(i) (((i) - 1)/2) /* Parent of binary heap element 'i' */
25
26/* Swap elements x and y */
27#define SWAP(x, y) do { void *z = (x); (x) = (y); (y) = z; } while (0)
28
29/* Evaluates true if the pair (x, y) is NOT ordered, according to the heap compare function */
30#define UNORDERED(h, x, y) ((h)->cmp((h)->cmp_param, (x), (y)) * (h)->min_or_max_heap > 0)
31
32/* Function to use when adding an element to the heap */
33typedef int ( *LALHeapAddFcn )( LALHeap *h, void **x );
34
35struct tagLALHeap {
36 void **data; /* Binary heap data */
37 int data_len; /* Size of the memory block 'data', in number of elements */
38 int n; /* Number of valid elements in the heap */
39 LALHeapDtorFcn dtor; /* Function to free memory of elements of heap, if required */
40 int max_size; /* Maximum size of the heap; if zero, heap has unlimited size */
41 int min_or_max_heap; /* -1|+1 if root of heap is minimum|maximum element */
42 LALHeapCmpParamFcn cmp; /* Parameterised heap element comparison function */
43 void *cmp_param; /* Parameter to pass to comparison function */
44 LALHeapAddFcn add; /* Function to use when adding an element to the heap */
45};
46
47/* Call a non-parameterised compare function, which is passed in 'param' */
48static int heap_no_param_cmp( void *param, const void *x, const void *y )
49{
51 return cmp( x, y );
52}
53
54/* Resize the binary heap to twice the current number of heap elements */
55static int heap_resize( LALHeap *h )
56{
57 int new_len = ( h->n > 0 ) ? 2*h->n : 1;
58 h->data = XLALRealloc( h->data, new_len * sizeof( h->data[0] ) );
59 XLAL_CHECK( h->data != NULL, XLAL_ENOMEM );
60 h->data_len = new_len;
61 return XLAL_SUCCESS;
62}
63
64/* Swap element 'i' with its parent until the heap property is satisfied */
65static void heap_bubble_up( LALHeap *h, int i )
66{
67 int p = PARENT( i );
68 while ( i > 0 && UNORDERED( h, h->data[i], h->data[p] ) ) {
69 SWAP( h->data[i], h->data[p] );
70 i = p;
71 p = PARENT( i );
72 }
73}
74
75/* Swap element 'i' with either of its children until the heap property is satisfied */
76static void heap_trickle_down( LALHeap *h, int i )
77{
78 do {
79 int j = -1, r = RIGHT( i );
80 if ( r < h->n && UNORDERED( h, h->data[r], h->data[i] ) ) {
81 int l = LEFT( i );
82 if ( UNORDERED( h, h->data[l], h->data[r] ) ) {
83 j = l;
84 } else {
85 j = r;
86 }
87 } else {
88 int l = LEFT( i );
89 if ( l < h->n && UNORDERED( h, h->data[l], h->data[i] ) ) {
90 j = l;
91 }
92 }
93 if ( j >= 0 ) {
94 SWAP( h->data[i], h->data[j] );
95 }
96 i = j;
97 } while ( i >= 0 );
98}
99
100/* Add item to heap which is full */
101static int heap_add_full(
102 LALHeap *h,
103 void **x
104 )
105{
106
107 /* If new element should replace root */
108 if ( UNORDERED( h, h->data[0], *x ) ) {
109
110 /* Swap root with *x, and trickle down new root to restore heap property */
111 SWAP( h->data[0], *x );
112 heap_trickle_down( h, 0 );
113
114 }
115
116 return XLAL_SUCCESS;
117
118}
119
120/* Add item to heap which is unlimited, or not full yet */
122 LALHeap *h,
123 void **x
124 )
125{
126
127 /* Resize binary heap; designed so that resizing costs amortized constant time */
128 if ( h->n + 1 > h->data_len ) {
130 }
131
132 /* Add new element to end of binary heap, and bubble up to restore heap property */
133 h->data[h->n++] = *x;
134 *x = NULL;
135 heap_bubble_up( h, h->n - 1 );
136
137 /* If (limited) heap is now full, switch add function to heap_add_full() */
138 if ( XLALHeapIsFull( h ) ) {
139 h->add = heap_add_full;
140 }
141
142 return XLAL_SUCCESS;
143
144}
145
147 LALHeapDtorFcn dtor,
148 int max_size,
149 int min_or_max_heap,
151 )
152{
153
154 /* Create a heap using heap_no_param_cmp as the comparison function */
155 LALHeap *h = XLALHeapCreate2( dtor, max_size, min_or_max_heap, heap_no_param_cmp, cmp );
156 XLAL_CHECK_NULL( h != NULL, XLAL_EFUNC );
157
158 return h;
159
160}
161
163 LALHeapDtorFcn dtor,
164 int max_size,
165 int min_or_max_heap,
167 void *cmp_param
168 )
169{
170
171 /* Check input */
172 XLAL_CHECK_NULL( max_size >= 0, XLAL_EINVAL );
173 XLAL_CHECK_NULL( abs( min_or_max_heap ) == 1, XLAL_EINVAL );
174 XLAL_CHECK_NULL( cmp != NULL, XLAL_EFAULT );
175
176 /* Allocate memory for heap struct */
177 LALHeap *h = XLALCalloc( 1, sizeof( *h ) );
178 XLAL_CHECK_NULL( h != NULL, XLAL_ENOMEM );
179
180 /* Set heap struct parameters */
181 h->dtor = dtor;
182 h->max_size = max_size;
183 h->min_or_max_heap = min_or_max_heap;
184 h->cmp = cmp;
185 h->cmp_param = cmp_param;
186 h->add = heap_add_not_full;
187
188 return h;
189
190}
191
193 LALHeap *h
194 )
195{
196 if ( h != NULL ) {
197 if ( h->data != NULL ) {
198 if ( h->dtor != NULL ) {
199 for ( int i = 0; i < h->n; ++i ) {
200 h->dtor( h->data[i] );
201 }
202 }
203 XLALFree( h->data );
204 }
205 XLALFree( h );
206 }
207}
208
210 LALHeap *h
211 )
212{
213
214 /* Check input */
215 XLAL_CHECK( h != NULL, XLAL_EFAULT );
216
217 /* Free heap elements */
218 if ( h->data != NULL ) {
219 if ( h->dtor != NULL ) {
220 for ( int i = 0; i < h->n; ++i ) {
221 h->dtor( h->data[i] );
222 h->data[i] = NULL;
223 }
224 }
225 }
226
227 /* Remove all elements from heap */
228 h->n = 0;
229 h->add = heap_add_not_full;
230
231 return XLAL_SUCCESS;
232
233}
234
236 const LALHeap *h
237 )
238{
239 XLAL_CHECK( h != NULL, XLAL_EFAULT );
240 return h->n;
241}
242
244 const LALHeap *h
245 )
246{
247 XLAL_CHECK( h != NULL, XLAL_EFAULT );
248 return h->max_size;
249}
250
252 const LALHeap *h
253 )
254{
255 XLAL_CHECK( h != NULL, XLAL_EFAULT );
256 return h->max_size > 0 && h->n == h->max_size;
257}
258
259const void *XLALHeapRoot(
260 const LALHeap *h
261 )
262{
263 XLAL_CHECK_NULL( h != NULL, XLAL_EFAULT );
264 return ( h->n > 0 ) ? h->data[0] : NULL;
265}
266
268 LALHeap *h,
269 int max_size
270 )
271{
272
273 /* Check input */
274 XLAL_CHECK( h != NULL, XLAL_EFAULT );
275 XLAL_CHECK( max_size >= 0, XLAL_EINVAL );
276
277 /* If too many heap elements for new (fixed) maximum size, remove some */
278 while ( max_size > 0 && h->n > max_size ) {
280 }
281
282 /* Set new maximum size */
283 h->max_size = max_size;
284
285 return XLAL_SUCCESS;
286
287}
288
290 LALHeap *h,
291 void **x
292 )
293{
294
295 /* Check input */
296 XLAL_CHECK( h != NULL, XLAL_EFAULT );
297 XLAL_CHECK( x != NULL, XLAL_EFAULT );
298 XLAL_CHECK( *x != NULL, XLAL_EINVAL );
299
300 /* Call the appropriate function */
301 return ( h->add )( h, x );
302
303}
304
306 LALHeap *h
307 )
308{
309
310 /* Check input */
311 XLAL_CHECK_NULL( h != NULL, XLAL_EFAULT );
312 XLAL_CHECK_NULL( h->n > 0, XLAL_ESIZE );
313
314 /* Save root element */
315 void *x = h->data[0];
316
317 /* Replace root with last element in binary heap, and trickle down to restore heap property */
318 h->data[0] = h->data[--h->n];
319 heap_trickle_down( h, 0 );
320
321 /* Resize binary heap; designed so that resizing costs amortized constant time */
322 if ( 3*h->n < h->data_len ) {
324 }
325
326 /* Heap now cannot be full, so switch add function to heap_add_not_full() */
327 h->add = heap_add_not_full;
328
329 return x;
330
331}
332
334 LALHeap *h
335 )
336{
337
338 /* Check input */
339 XLAL_CHECK( h != NULL, XLAL_EFAULT );
340 XLAL_CHECK( h->n > 0, XLAL_ESIZE );
341
342 /* Extract root */
343 void *x = XLALHeapExtractRoot( h );
344 XLAL_CHECK( x != NULL, XLAL_EFUNC );
345
346 /* Free memory associated with root element, if required */
347 if ( h->dtor != NULL ) {
348 h->dtor( x );
349 }
350
351 return XLAL_SUCCESS;
352
353}
354
356 LALHeap *h,
357 void **x
358 )
359{
360
361 /* Check input */
362 XLAL_CHECK( h != NULL, XLAL_EFAULT );
363 XLAL_CHECK( h->n > 0, XLAL_ESIZE );
364 XLAL_CHECK( x != NULL, XLAL_EFAULT );
365
366 /* Swap root with *x, and trickle down new root to restore heap property */
367 SWAP( h->data[0], *x );
368 heap_trickle_down( h, 0 );
369
370 return XLAL_SUCCESS;
371
372}
373
375 const LALHeap *h,
376 LALHeapVisitFcn visit,
377 void *visit_param
378 )
379{
380
381 /* Check input */
382 XLAL_CHECK( h != NULL, XLAL_EFAULT );
383 XLAL_CHECK( visit != NULL, XLAL_EFAULT );
384
385 /* Create internal min-heap (without destructor) to get elements in order */
386 LALHeap *h2 = XLALHeapCreate2( NULL, 0, -1, h->cmp, h->cmp_param );
387 XLAL_CHECK( h2 != NULL, XLAL_EFUNC );
388
389 /* Add all elements in heap to internal min-heap */
390 for ( int i = 0; i < h->n; ++i ) {
391 void *x = h->data[i];
393 }
394
395 /* Visit root element of internal min-heap and remove, until empty */
396 while ( h2->n > 0 ) {
397 const void *x = XLALHeapRoot( h2 );
398 XLAL_CHECK( visit( visit_param, x ) == XLAL_SUCCESS, XLAL_EFUNC );
400 }
401
402 /* Cleanup */
403 XLALHeapDestroy( h2 );
404
405 return XLAL_SUCCESS;
406
407}
408
410 LALHeap *h,
411 LALHeapModifyFcn modify,
412 void *modify_param
413 )
414{
415
416 /* Check input */
417 XLAL_CHECK( h != NULL, XLAL_EFAULT );
418 XLAL_CHECK( modify != NULL, XLAL_EFAULT );
419
420 /* Create internal min-heap (without destructor) to get elements in order */
421 LALHeap *h2 = XLALHeapCreate2( NULL, 0, -1, h->cmp, h->cmp_param );
422 XLAL_CHECK( h2 != NULL, XLAL_EFUNC );
423
424 /* Add all elements in heap to internal min-heap */
425 for ( int i = 0; i < h->n; ++i ) {
426 void *x = h->data[i];
428 }
429
430 /* Remove all elements from original heap */
431 h->n = 0;
432 h->add = heap_add_not_full;
433
434 /* Extract roots element of internal min-heap, until empty */
435 while ( h2->n > 0 ) {
436 void *x = XLALHeapExtractRoot( h2 );
437 XLAL_CHECK( x != NULL, XLAL_EFUNC );
438
439 /* Visit element, possibly modifying it */
440 XLAL_CHECK( modify( modify_param, x ) == XLAL_SUCCESS, XLAL_EFUNC );
441
442 /* Add element back to original heap */
444
445 }
446
447 /* Cleanup */
448 XLALHeapDestroy( h2 );
449
450 return XLAL_SUCCESS;
451
452}
453
455 void *param,
456 const void *x
457 )
458{
459 const void ***elem = ( const void *** ) param;
460 **elem = x;
461 ++(*elem);
462 return XLAL_SUCCESS;
463}
464
465const void **XLALHeapElements(
466 const LALHeap *h
467 )
468{
469
470 /* Check input */
471 XLAL_CHECK_NULL( h != NULL, XLAL_EFAULT );
472
473 /* Allocate memory */
474 const void **elems = XLALMalloc( h->n * sizeof( *elems ) );
475 XLAL_CHECK_NULL( elems != NULL, XLAL_ENOMEM );
476
477 /* Get elements */
478 const void **elem = elems;
480 XLAL_CHECK_NULL( elems + h->n == elem, XLAL_EFAILED );
481
482 return elems;
483
484}
#define RIGHT(i)
Definition: LALHeap.c:23
static int heap_add_full(LALHeap *h, void **x)
Definition: LALHeap.c:101
static int heap_get_elems_visitor(void *param, const void *x)
Definition: LALHeap.c:454
#define LEFT(i)
Definition: LALHeap.c:22
static int heap_resize(LALHeap *h)
Definition: LALHeap.c:55
static int heap_add_not_full(LALHeap *h, void **x)
Definition: LALHeap.c:121
static int heap_no_param_cmp(void *param, const void *x, const void *y)
Definition: LALHeap.c:48
#define SWAP(x, y)
Definition: LALHeap.c:27
#define PARENT(i)
Definition: LALHeap.c:24
int(* LALHeapAddFcn)(LALHeap *h, void **x)
Definition: LALHeap.c:33
#define UNORDERED(h, x, y)
Definition: LALHeap.c:30
static void heap_trickle_down(LALHeap *h, int i)
Definition: LALHeap.c:76
static void heap_bubble_up(LALHeap *h, int i)
Definition: LALHeap.c:65
static int cmp(REAL4Sequence *a, REAL4Sequence *b)
Definition: SequenceTest.c:62
int XLALHeapResize(LALHeap *h, int max_size)
Change the maximum size of a heap; if the heap is contracted, excess elements are destroyed.
Definition: LALHeap.c:267
int XLALHeapVisit(const LALHeap *h, LALHeapVisitFcn visit, void *visit_param)
Visit each element in the heap in the order given by the comparison function.
Definition: LALHeap.c:374
int XLALHeapAdd(LALHeap *h, void **x)
Add a new element to a heap; if the heap is of fixed size and full, the root element is removed.
Definition: LALHeap.c:289
LALHeap * XLALHeapCreate(LALHeapDtorFcn dtor, int max_size, int min_or_max_heap, LALHeapCmpFcn cmp)
Create a heap.
Definition: LALHeap.c:146
int(* LALHeapVisitFcn)(void *param, const void *x)
Function to call when visiting heap element x, with a parameter param.
Definition: LALHeap.h:61
int XLALHeapModify(LALHeap *h, LALHeapModifyFcn modify, void *modify_param)
Visit (and possibly modify) each element in the heap in the order given by the comparison function.
Definition: LALHeap.c:409
int XLALHeapSize(const LALHeap *h)
Return the size of a heap.
Definition: LALHeap.c:235
int XLALHeapExchangeRoot(LALHeap *h, void **x)
Exchange the root element of a non-empty heap with the new element in *x
Definition: LALHeap.c:355
int(* LALHeapCmpFcn)(const void *x, const void *y)
Function which compares heap elements x and y
Definition: LALHeap.h:50
int(* LALHeapModifyFcn)(void *param, void *x)
Function to call when visiting (and possibly modify) heap element x, with a parameter param.
Definition: LALHeap.h:67
const void * XLALHeapRoot(const LALHeap *h)
Return the root element of a heap.
Definition: LALHeap.c:259
int XLALHeapRemoveRoot(LALHeap *h)
Remove and destroy the root element of a heap.
Definition: LALHeap.c:333
int XLALHeapIsFull(const LALHeap *h)
Return >0 if a limited-size heap is full, 0 otherwise (or if heap has unlimited size),...
Definition: LALHeap.c:251
void * XLALHeapExtractRoot(LALHeap *h)
Remove the root element of a heap.
Definition: LALHeap.c:305
int XLALHeapClear(LALHeap *h)
Clear a heap.
Definition: LALHeap.c:209
const void ** XLALHeapElements(const LALHeap *h)
Allocate and return an array containing all elements in the heap.
Definition: LALHeap.c:465
void(* LALHeapDtorFcn)(void *x)
Function which free memory associated with heap element x
Definition: LALHeap.h:45
void XLALHeapDestroy(LALHeap *h)
Destroy a heap and its elements.
Definition: LALHeap.c:192
int XLALHeapMaxSize(const LALHeap *h)
Return the maximum size of a heap.
Definition: LALHeap.c:243
LALHeap * XLALHeapCreate2(LALHeapDtorFcn dtor, int max_size, int min_or_max_heap, LALHeapCmpParamFcn cmp, void *cmp_param)
Create a heap with a parameterised comparison function.
Definition: LALHeap.c:162
int(* LALHeapCmpParamFcn)(void *param, const void *x, const void *y)
Function which compares heap elements x and y, with a parameter param.
Definition: LALHeap.h:55
#define XLALMalloc(n)
Definition: LALMalloc.h:44
#define XLALCalloc(m, n)
Definition: LALMalloc.h:45
#define XLALFree(p)
Definition: LALMalloc.h:47
#define XLALRealloc(p, n)
Definition: LALMalloc.h:46
static const INT4 r
Definition: Random.c:82
#define XLAL_CHECK(assertion,...)
Macro to test an assertion and invoke a failure if it is not true in a function that returns an integ...
Definition: XLALError.h:810
#define XLAL_CHECK_NULL(assertion,...)
Macro to test an assertion and invoke a failure if it is not true in a function that returns a pointe...
Definition: XLALError.h:825
@ XLAL_ENOMEM
Memory allocation error.
Definition: XLALError.h:407
@ XLAL_SUCCESS
Success return value (not an error number)
Definition: XLALError.h:401
@ XLAL_EFAULT
Invalid pointer.
Definition: XLALError.h:408
@ XLAL_EFUNC
Internal function call failed bit: "or" this with existing error number.
Definition: XLALError.h:462
@ XLAL_ESIZE
Wrong size.
Definition: XLALError.h:420
@ XLAL_EINVAL
Invalid argument.
Definition: XLALError.h:409
@ XLAL_EFAILED
Generic failure.
Definition: XLALError.h:418
Definition: LALBitset.c:31
Generic heap with elements of type void *
Definition: LALHeap.c:35
LALHeapAddFcn add
Definition: LALHeap.c:44
LALHeapCmpParamFcn cmp
Definition: LALHeap.c:42
void ** data
Definition: LALHeap.c:36
LALHeapDtorFcn dtor
Definition: LALHeap.c:39
int min_or_max_heap
Definition: LALHeap.c:41
void * cmp_param
Definition: LALHeap.c:43
int max_size
Definition: LALHeap.c:40
int n
Definition: LALHeap.c:38
int data_len
Definition: LALHeap.c:37