mirror of
https://github.com/HDFGroup/hdf5.git
synced 2025-02-17 16:10:24 +08:00
* Modify temporary rpath for testing in java example scripts. * Update URL in source file Copyright headers for web copy of COPYING file - src and test directories.
905 lines
30 KiB
C
905 lines
30 KiB
C
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* Copyright by The HDF Group. *
|
|
* Copyright by the Board of Trustees of the University of Illinois. *
|
|
* All rights reserved. *
|
|
* *
|
|
* This file is part of HDF5. The full HDF5 copyright notice, including *
|
|
* terms governing use, modification, and redistribution, is contained in *
|
|
* the COPYING file, which can be found at the root of the source code *
|
|
* distribution tree, or in https://www.hdfgroup.org/licenses. *
|
|
* If you do not have access to either file, you may request a copy from *
|
|
* help@hdfgroup.org. *
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
/*
|
|
* Purpose: Provides a heap abstract data type.
|
|
*
|
|
* (See chapter 11 - "Priority Queues" of _Algorithms_, by
|
|
* Sedgewick for additional information)
|
|
*
|
|
*/
|
|
|
|
/* Private headers needed */
|
|
#include "H5private.h" /* Generic Functions */
|
|
#include "H5Eprivate.h" /* Error handling */
|
|
#include "H5HPprivate.h" /* Heap routines */
|
|
#include "H5FLprivate.h" /* Memory management functions */
|
|
|
|
/* Local Macros */
|
|
#define H5HP_START_SIZE 16 /* Initial number of entries for heaps */
|
|
|
|
/* Private typedefs & structs */
|
|
|
|
/* Data structure for entries in the internal heap array */
|
|
typedef struct {
|
|
int val; /* Value to be used for heap condition */
|
|
H5HP_info_t *obj; /* Pointer to object stored in heap */
|
|
} H5HP_ent_t;
|
|
|
|
/* Main heap data structure */
|
|
struct H5HP_t {
|
|
H5HP_type_t type; /* Type of heap (minimum or maximum value at "top") */
|
|
size_t nobjs; /* Number of active objects in heap array */
|
|
size_t nalloc; /* Number of allocated locations in heap array */
|
|
H5HP_ent_t *heap; /* Pointer to array containing heap entries */
|
|
};
|
|
|
|
/* Static functions */
|
|
static herr_t H5HP__swim_max(H5HP_t *heap, size_t loc);
|
|
static herr_t H5HP__swim_min(H5HP_t *heap, size_t loc);
|
|
static herr_t H5HP__sink_max(H5HP_t *heap, size_t loc);
|
|
static herr_t H5HP__sink_min(H5HP_t *heap, size_t loc);
|
|
|
|
/* Declare a free list to manage the H5HP_t struct */
|
|
H5FL_DEFINE_STATIC(H5HP_t);
|
|
|
|
/* Declare a free list to manage sequences of H5HP_ent_t */
|
|
H5FL_SEQ_DEFINE_STATIC(H5HP_ent_t);
|
|
|
|
/*--------------------------------------------------------------------------
|
|
NAME
|
|
H5HP__swim_max
|
|
PURPOSE
|
|
Restore heap condition by moving an object upward
|
|
USAGE
|
|
herr_t H5HP__swim_max(heap, loc)
|
|
H5HP_t *heap; IN/OUT: Pointer to heap to modify
|
|
size_t loc; IN: Location to start from
|
|
|
|
RETURNS
|
|
Returns non-negative on success, negative on failure.
|
|
DESCRIPTION
|
|
Restore the heap condition for the heap's array by "swimming" the object
|
|
at a location upward.
|
|
GLOBAL VARIABLES
|
|
COMMENTS, BUGS, ASSUMPTIONS
|
|
This routine is for "maximum" value heaps.
|
|
EXAMPLES
|
|
REVISION LOG
|
|
--------------------------------------------------------------------------*/
|
|
static herr_t
|
|
H5HP__swim_max(H5HP_t *heap, size_t loc)
|
|
{
|
|
int val; /* Temporary copy value of object to move in heap */
|
|
H5HP_info_t *obj; /* Temporary pointer to object to move in heap */
|
|
herr_t ret_value = SUCCEED; /* Return value */
|
|
|
|
FUNC_ENTER_STATIC_NOERR
|
|
|
|
/* Get copies of the information about the object to move in the heap */
|
|
val = heap->heap[loc].val;
|
|
obj = heap->heap[loc].obj;
|
|
|
|
/* Move object up in heap until it's reached the maximum location possible */
|
|
while (heap->heap[loc / 2].val < val) {
|
|
/* Move object "above" current location in heap down */
|
|
heap->heap[loc].val = heap->heap[loc / 2].val;
|
|
heap->heap[loc].obj = heap->heap[loc / 2].obj;
|
|
|
|
/* Update heap location for object which moved */
|
|
heap->heap[loc].obj->heap_loc = loc;
|
|
|
|
/* Move to location "above" current location */
|
|
loc = loc / 2;
|
|
} /* end while */
|
|
|
|
/* Put object into heap at correct location */
|
|
heap->heap[loc].val = val;
|
|
heap->heap[loc].obj = obj;
|
|
|
|
/* Update heap location for object */
|
|
heap->heap[loc].obj->heap_loc = loc;
|
|
|
|
FUNC_LEAVE_NOAPI(ret_value);
|
|
} /* end H5HP__swim_max() */
|
|
|
|
/*--------------------------------------------------------------------------
|
|
NAME
|
|
H5HP__swim_min
|
|
PURPOSE
|
|
Restore heap condition by moving an object upward
|
|
USAGE
|
|
herr_t H5HP__swim_min(heap, loc)
|
|
H5HP_t *heap; IN/OUT: Pointer to heap to modify
|
|
size_t loc; IN: Location to start from
|
|
|
|
RETURNS
|
|
Returns non-negative on success, negative on failure.
|
|
DESCRIPTION
|
|
Restore the heap condition for the heap's array by "swimming" the object
|
|
at a location upward.
|
|
GLOBAL VARIABLES
|
|
COMMENTS, BUGS, ASSUMPTIONS
|
|
This routine is for "minimum" value heaps.
|
|
EXAMPLES
|
|
REVISION LOG
|
|
--------------------------------------------------------------------------*/
|
|
static herr_t
|
|
H5HP__swim_min(H5HP_t *heap, size_t loc)
|
|
{
|
|
int val; /* Temporary copy value of object to move in heap */
|
|
H5HP_info_t *obj; /* Temporary pointer to object to move in heap */
|
|
herr_t ret_value = SUCCEED; /* Return value */
|
|
|
|
FUNC_ENTER_STATIC_NOERR
|
|
|
|
/* Get copies of the information about the object to move in the heap */
|
|
val = heap->heap[loc].val;
|
|
obj = heap->heap[loc].obj;
|
|
|
|
/* Move object up in heap until it's reached the minimum location possible */
|
|
while (heap->heap[loc / 2].val > val) {
|
|
/* Move object "above" current location in heap down */
|
|
heap->heap[loc].val = heap->heap[loc / 2].val;
|
|
heap->heap[loc].obj = heap->heap[loc / 2].obj;
|
|
|
|
/* Update heap location for object which moved */
|
|
heap->heap[loc].obj->heap_loc = loc;
|
|
|
|
/* Move to location "above" current location */
|
|
loc = loc / 2;
|
|
} /* end while */
|
|
|
|
/* Put object into heap at correct location */
|
|
heap->heap[loc].val = val;
|
|
heap->heap[loc].obj = obj;
|
|
|
|
/* Update heap location for object */
|
|
heap->heap[loc].obj->heap_loc = loc;
|
|
|
|
FUNC_LEAVE_NOAPI(ret_value);
|
|
} /* end H5HP__swim_min() */
|
|
|
|
/*--------------------------------------------------------------------------
|
|
NAME
|
|
H5HP__sink_max
|
|
PURPOSE
|
|
Restore heap condition by moving an object downward
|
|
USAGE
|
|
herr_t H5HP__sink_max(heap, loc)
|
|
H5HP_t *heap; IN/OUT: Pointer to heap to modify
|
|
size_t loc; IN: Location to start from
|
|
|
|
RETURNS
|
|
Returns non-negative on success, negative on failure.
|
|
DESCRIPTION
|
|
Restore the heap condition for the heap's array by "sinking" the object
|
|
at a location downward.
|
|
GLOBAL VARIABLES
|
|
COMMENTS, BUGS, ASSUMPTIONS
|
|
This routine is for "maximum" value heaps.
|
|
EXAMPLES
|
|
REVISION LOG
|
|
--------------------------------------------------------------------------*/
|
|
static herr_t
|
|
H5HP__sink_max(H5HP_t *heap, size_t loc)
|
|
{
|
|
int val; /* Temporary copy value of object to move in heap */
|
|
void * obj; /* Temporary pointer to object to move in heap */
|
|
herr_t ret_value = SUCCEED; /* Return value */
|
|
|
|
FUNC_ENTER_STATIC_NOERR
|
|
|
|
/* Get copies of the information about the object to move in the heap */
|
|
val = heap->heap[loc].val;
|
|
obj = heap->heap[loc].obj;
|
|
|
|
/* Move object up in heap until it's reached the maximum location possible */
|
|
while ((2 * loc) <= heap->nobjs) {
|
|
size_t new_loc = loc * 2; /* New object's potential location area */
|
|
|
|
/* Get the greater of the two objects below the location in heap */
|
|
if (new_loc < heap->nobjs && (heap->heap[new_loc].val < heap->heap[new_loc + 1].val))
|
|
new_loc++;
|
|
|
|
/* Check if the object is smaller than the larger of the objects below it */
|
|
/* If so, its in the correct location now, and we can get out */
|
|
if (val >= heap->heap[new_loc].val)
|
|
break;
|
|
|
|
/* Move the greater of the two objects below the current location up */
|
|
heap->heap[loc].val = heap->heap[new_loc].val;
|
|
heap->heap[loc].obj = heap->heap[new_loc].obj;
|
|
|
|
/* Update heap location for object which moved */
|
|
heap->heap[loc].obj->heap_loc = loc;
|
|
|
|
/* Move to location "below" current location */
|
|
loc = new_loc;
|
|
} /* end while */
|
|
|
|
/* Put object into heap at correct location */
|
|
heap->heap[loc].val = val;
|
|
heap->heap[loc].obj = (H5HP_info_t *)obj;
|
|
|
|
/* Update heap location for object */
|
|
heap->heap[loc].obj->heap_loc = loc;
|
|
|
|
FUNC_LEAVE_NOAPI(ret_value);
|
|
} /* end H5HP__sink_max() */
|
|
|
|
/*--------------------------------------------------------------------------
|
|
NAME
|
|
H5HP__sink_min
|
|
PURPOSE
|
|
Restore heap condition by moving an object downward
|
|
USAGE
|
|
herr_t H5HP__sink_min(heap, loc)
|
|
H5HP_t *heap; IN/OUT: Pointer to heap to modify
|
|
size_t loc; IN: Location to start from
|
|
|
|
RETURNS
|
|
Returns non-negative on success, negative on failure.
|
|
DESCRIPTION
|
|
Restore the heap condition for the heap's array by "sinking" the object
|
|
at a location downward.
|
|
GLOBAL VARIABLES
|
|
COMMENTS, BUGS, ASSUMPTIONS
|
|
This routine is for "minimum" value heaps.
|
|
EXAMPLES
|
|
REVISION LOG
|
|
--------------------------------------------------------------------------*/
|
|
static herr_t
|
|
H5HP__sink_min(H5HP_t *heap, size_t loc)
|
|
{
|
|
int val; /* Temporary copy value of object to move in heap */
|
|
void * obj; /* Temporary pointer to object to move in heap */
|
|
herr_t ret_value = SUCCEED; /* Return value */
|
|
|
|
FUNC_ENTER_STATIC_NOERR
|
|
|
|
/* Get copies of the information about the object to move in the heap */
|
|
val = heap->heap[loc].val;
|
|
obj = heap->heap[loc].obj;
|
|
|
|
/* Move object up in heap until it's reached the maximum location possible */
|
|
while ((2 * loc) <= heap->nobjs) {
|
|
size_t new_loc = loc * 2; /* New object's potential location area */
|
|
|
|
/* Get the lesser of the two objects below the location in heap */
|
|
if (new_loc < heap->nobjs && (heap->heap[new_loc].val > heap->heap[new_loc + 1].val))
|
|
new_loc++;
|
|
|
|
/* Check if the object is greater than the larger of the objects below it */
|
|
/* If so, its in the correct location now, and we can get out */
|
|
if (val <= heap->heap[new_loc].val)
|
|
break;
|
|
|
|
/* Move the greater of the two objects below the current location up */
|
|
heap->heap[loc].val = heap->heap[new_loc].val;
|
|
heap->heap[loc].obj = heap->heap[new_loc].obj;
|
|
|
|
/* Update heap location for object which moved */
|
|
heap->heap[loc].obj->heap_loc = loc;
|
|
|
|
/* Move to location "below" current location */
|
|
loc = new_loc;
|
|
} /* end while */
|
|
|
|
/* Put object into heap at correct location */
|
|
heap->heap[loc].val = val;
|
|
heap->heap[loc].obj = (H5HP_info_t *)obj;
|
|
|
|
/* Update heap location for object */
|
|
heap->heap[loc].obj->heap_loc = loc;
|
|
|
|
FUNC_LEAVE_NOAPI(ret_value);
|
|
} /* end H5HP__sink_min() */
|
|
|
|
/*--------------------------------------------------------------------------
|
|
NAME
|
|
H5HP_create
|
|
PURPOSE
|
|
Create a heap
|
|
USAGE
|
|
H5HP_t *H5HP_create(heap_type)
|
|
H5HP_type_t heap_type; IN: Type of heap to create
|
|
|
|
RETURNS
|
|
Returns a pointer to a heap on success, NULL on failure.
|
|
DESCRIPTION
|
|
Create a priority queue. The SIZE is used to set the initial number of
|
|
entries allocated.
|
|
GLOBAL VARIABLES
|
|
COMMENTS, BUGS, ASSUMPTIONS
|
|
EXAMPLES
|
|
REVISION LOG
|
|
--------------------------------------------------------------------------*/
|
|
H5HP_t *
|
|
H5HP_create(H5HP_type_t heap_type)
|
|
{
|
|
H5HP_t *new_heap = NULL; /* Pointer to new heap object created */
|
|
H5HP_t *ret_value; /* Return value */
|
|
|
|
FUNC_ENTER_NOAPI(NULL)
|
|
|
|
/* Check args */
|
|
HDassert(heap_type == H5HP_MIN_HEAP || heap_type == H5HP_MAX_HEAP);
|
|
|
|
/* Allocate ref-counted string structure */
|
|
if ((new_heap = H5FL_MALLOC(H5HP_t)) == NULL)
|
|
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, NULL, "memory allocation failed");
|
|
|
|
/* Allocate the array to store the heap entries */
|
|
if ((new_heap->heap = H5FL_SEQ_MALLOC(H5HP_ent_t, (size_t)(H5HP_START_SIZE + 1))) == NULL)
|
|
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, NULL, "memory allocation failed");
|
|
|
|
/* Set the internal fields */
|
|
new_heap->type = heap_type;
|
|
new_heap->nobjs = 0;
|
|
new_heap->nalloc = H5HP_START_SIZE + 1;
|
|
|
|
/* Set the information in the 0'th location based on the type of heap */
|
|
if (heap_type == H5HP_MIN_HEAP) {
|
|
/* Set the value in the '0' location to be the minimum value, to
|
|
* simplify the algorithms
|
|
*/
|
|
new_heap->heap[0].val = INT_MIN;
|
|
new_heap->heap[0].obj = NULL;
|
|
} /* end if */
|
|
else {
|
|
/* Set the value in the '0' location to be the maximum value, to
|
|
* simplify the algorithms
|
|
*/
|
|
new_heap->heap[0].val = INT_MAX;
|
|
new_heap->heap[0].obj = NULL;
|
|
} /* end else */
|
|
|
|
/* Set the return value */
|
|
ret_value = new_heap;
|
|
|
|
done:
|
|
/* Error cleanup */
|
|
if (NULL == ret_value) {
|
|
if (NULL != new_heap) {
|
|
if (NULL != new_heap->heap)
|
|
new_heap->heap = H5FL_SEQ_FREE(H5HP_ent_t, new_heap->heap);
|
|
new_heap = H5FL_FREE(H5HP_t, new_heap);
|
|
} /* end if */
|
|
} /* end if */
|
|
|
|
FUNC_LEAVE_NOAPI(ret_value);
|
|
} /* end H5HP_create() */
|
|
|
|
/*--------------------------------------------------------------------------
|
|
NAME
|
|
H5HP_count
|
|
PURPOSE
|
|
Check the number of elements in a heap
|
|
USAGE
|
|
ssize_t H5HP_count(heap)
|
|
const H5HP_t *heap; IN: Pointer to heap to query
|
|
|
|
RETURNS
|
|
Returns non-negative on success, negative on failure.
|
|
DESCRIPTION
|
|
Checks the number of elements in heap
|
|
GLOBAL VARIABLES
|
|
COMMENTS, BUGS, ASSUMPTIONS
|
|
EXAMPLES
|
|
REVISION LOG
|
|
--------------------------------------------------------------------------*/
|
|
ssize_t
|
|
H5HP_count(const H5HP_t *heap)
|
|
{
|
|
ssize_t ret_value; /* Return value */
|
|
|
|
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
|
|
|
/* Check args */
|
|
HDassert(heap);
|
|
|
|
/* Check internal consistency */
|
|
/* (Pre-condition) */
|
|
HDassert(heap->nobjs < heap->nalloc);
|
|
HDassert(heap->heap);
|
|
HDassert((heap->type == H5HP_MAX_HEAP && heap->heap[0].val == INT_MAX) ||
|
|
(heap->type == H5HP_MIN_HEAP && heap->heap[0].val == INT_MIN));
|
|
HDassert(heap->heap[0].obj == NULL);
|
|
|
|
/* Return the number of objects in the heap */
|
|
H5_CHECK_OVERFLOW(heap->nobjs, size_t, ssize_t);
|
|
ret_value = (ssize_t)heap->nobjs;
|
|
|
|
/* No post-condition check necessary, since heap is constant */
|
|
FUNC_LEAVE_NOAPI(ret_value);
|
|
} /* end H5HP_count() */
|
|
|
|
/*--------------------------------------------------------------------------
|
|
NAME
|
|
H5HP_insert
|
|
PURPOSE
|
|
Insert an object into a heap, with an initial value
|
|
USAGE
|
|
herr_t H5HP_insert(heap, val, obj)
|
|
H5HP_t *heap; IN/OUT: Pointer to heap to modify
|
|
int val; IN: Initial value for object in heap
|
|
void *obj; IN: Pointer to object to insert into heap
|
|
|
|
RETURNS
|
|
Returns non-negative on success, negative on failure.
|
|
DESCRIPTION
|
|
Inserts a OBJ into a HEAP, with an initial VALue.
|
|
GLOBAL VARIABLES
|
|
COMMENTS, BUGS, ASSUMPTIONS
|
|
EXAMPLES
|
|
REVISION LOG
|
|
--------------------------------------------------------------------------*/
|
|
herr_t
|
|
H5HP_insert(H5HP_t *heap, int val, void *obj)
|
|
{
|
|
herr_t ret_value = SUCCEED; /* Return value */
|
|
|
|
FUNC_ENTER_NOAPI(FAIL)
|
|
|
|
/* Check args */
|
|
HDassert(heap);
|
|
HDassert(obj);
|
|
|
|
/* Check internal consistency */
|
|
/* (Pre-condition) */
|
|
HDassert(heap->nobjs < heap->nalloc);
|
|
HDassert(heap->heap);
|
|
HDassert((heap->type == H5HP_MAX_HEAP && heap->heap[0].val == INT_MAX) ||
|
|
(heap->type == H5HP_MIN_HEAP && heap->heap[0].val == INT_MIN));
|
|
HDassert(heap->heap[0].obj == NULL);
|
|
|
|
/* Increment number of objects in heap */
|
|
heap->nobjs++;
|
|
|
|
/* Check if we need to allocate more room for heap array */
|
|
if (heap->nobjs >= heap->nalloc) {
|
|
size_t n = MAX(H5HP_START_SIZE, 2 * (heap->nalloc - 1)) + 1;
|
|
H5HP_ent_t *new_heap = H5FL_SEQ_REALLOC(H5HP_ent_t, heap->heap, n);
|
|
|
|
if (!new_heap)
|
|
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to extend heap array");
|
|
heap->heap = new_heap;
|
|
heap->nalloc = n;
|
|
} /* end if */
|
|
|
|
/* Insert new object at end of heap */
|
|
heap->heap[heap->nobjs].val = val;
|
|
heap->heap[heap->nobjs].obj = (H5HP_info_t *)obj;
|
|
heap->heap[heap->nobjs].obj->heap_loc = heap->nobjs;
|
|
|
|
/* Restore heap condition */
|
|
if (heap->type == H5HP_MAX_HEAP) {
|
|
if (H5HP__swim_max(heap, heap->nobjs) < 0)
|
|
HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "unable to restore heap condition");
|
|
} /* end if */
|
|
else {
|
|
if (H5HP__swim_min(heap, heap->nobjs) < 0)
|
|
HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "unable to restore heap condition");
|
|
} /* end else */
|
|
|
|
done:
|
|
|
|
/* Check internal consistency */
|
|
/* (Post-condition) */
|
|
HDassert(heap->nobjs < heap->nalloc);
|
|
HDassert(heap->heap);
|
|
HDassert((heap->type == H5HP_MAX_HEAP && heap->heap[0].val == INT_MAX) ||
|
|
(heap->type == H5HP_MIN_HEAP && heap->heap[0].val == INT_MIN));
|
|
HDassert(heap->heap[0].obj == NULL);
|
|
|
|
FUNC_LEAVE_NOAPI(ret_value);
|
|
} /* end H5HP_insert() */
|
|
|
|
/*--------------------------------------------------------------------------
|
|
NAME
|
|
H5HP_top
|
|
PURPOSE
|
|
Check the value of the top object in the heap
|
|
USAGE
|
|
herr_t H5HP_top(heap, val)
|
|
const H5HP_t *heap; IN: Pointer to heap to modify
|
|
int val; IN/OUT: Initial value for object in heap
|
|
|
|
RETURNS
|
|
Returns non-negative on success, negative on failure.
|
|
DESCRIPTION
|
|
Checks the value of the top object in a heap
|
|
GLOBAL VARIABLES
|
|
COMMENTS, BUGS, ASSUMPTIONS
|
|
EXAMPLES
|
|
REVISION LOG
|
|
--------------------------------------------------------------------------*/
|
|
herr_t
|
|
H5HP_top(const H5HP_t *heap, int *val)
|
|
{
|
|
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
|
|
|
/* Check args */
|
|
HDassert(heap);
|
|
HDassert(val);
|
|
|
|
/* Check internal consistency */
|
|
/* (Pre-condition) */
|
|
HDassert(heap->nobjs < heap->nalloc);
|
|
HDassert(heap->heap);
|
|
HDassert((heap->type == H5HP_MAX_HEAP && heap->heap[0].val == INT_MAX) ||
|
|
(heap->type == H5HP_MIN_HEAP && heap->heap[0].val == INT_MIN));
|
|
HDassert(heap->heap[0].obj == NULL);
|
|
|
|
/* Get value of the top object in the heap */
|
|
*val = heap->heap[1].val;
|
|
|
|
/* No post-condition check necessary, since heap is constant */
|
|
FUNC_LEAVE_NOAPI(SUCCEED);
|
|
} /* end H5HP_top() */
|
|
|
|
/*--------------------------------------------------------------------------
|
|
NAME
|
|
H5HP_remove
|
|
PURPOSE
|
|
Remove an object into a heap
|
|
USAGE
|
|
herr_t H5HP_remove(heap, val, obj)
|
|
H5HP_t *heap; IN/OUT: Pointer to heap to modify
|
|
int *val; OUT: Pointer to value of object removed from heap
|
|
void **obj; OUT: Pointer to object removed from heap
|
|
|
|
RETURNS
|
|
Returns non-negative on success, negative on failure.
|
|
DESCRIPTION
|
|
Removes the top object on a heap, returning its value and object pointer
|
|
GLOBAL VARIABLES
|
|
COMMENTS, BUGS, ASSUMPTIONS
|
|
EXAMPLES
|
|
REVISION LOG
|
|
--------------------------------------------------------------------------*/
|
|
herr_t
|
|
H5HP_remove(H5HP_t *heap, int *val, void **obj)
|
|
{
|
|
herr_t ret_value = SUCCEED; /* Return value */
|
|
|
|
FUNC_ENTER_NOAPI(FAIL)
|
|
|
|
/* Check args */
|
|
HDassert(heap);
|
|
HDassert(val);
|
|
HDassert(obj);
|
|
|
|
/* Check internal consistency */
|
|
/* (Pre-condition) */
|
|
HDassert(heap->nobjs < heap->nalloc);
|
|
HDassert(heap->heap);
|
|
HDassert((heap->type == H5HP_MAX_HEAP && heap->heap[0].val == INT_MAX) ||
|
|
(heap->type == H5HP_MIN_HEAP && heap->heap[0].val == INT_MIN));
|
|
HDassert(heap->heap[0].obj == NULL);
|
|
|
|
/* Check if there are any objects on the heap to remove */
|
|
if (heap->nobjs == 0)
|
|
HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "heap is empty");
|
|
|
|
/* Get the information for the top object on the heap */
|
|
HDassert(heap->heap[1].obj->heap_loc == 1);
|
|
*val = heap->heap[1].val;
|
|
*obj = heap->heap[1].obj;
|
|
|
|
/* Move the last element in the heap to the top */
|
|
heap->heap[1].val = heap->heap[heap->nobjs].val;
|
|
heap->heap[1].obj = heap->heap[heap->nobjs].obj;
|
|
heap->heap[1].obj->heap_loc = 1;
|
|
|
|
/* Decrement number of objects in heap */
|
|
heap->nobjs--;
|
|
|
|
/* Restore heap condition, if there are objects on the heap */
|
|
if (heap->nobjs > 0) {
|
|
if (heap->type == H5HP_MAX_HEAP) {
|
|
if (H5HP__sink_max(heap, (size_t)1) < 0)
|
|
HGOTO_ERROR(H5E_HEAP, H5E_CANTDELETE, FAIL, "unable to restore heap condition");
|
|
} /* end if */
|
|
else {
|
|
if (H5HP__sink_min(heap, (size_t)1) < 0)
|
|
HGOTO_ERROR(H5E_HEAP, H5E_CANTDELETE, FAIL, "unable to restore heap condition");
|
|
} /* end else */
|
|
} /* end if */
|
|
|
|
done:
|
|
|
|
/* Check internal consistency */
|
|
/* (Post-condition) */
|
|
HDassert(heap->nobjs < heap->nalloc);
|
|
HDassert(heap->heap);
|
|
HDassert((heap->type == H5HP_MAX_HEAP && heap->heap[0].val == INT_MAX) ||
|
|
(heap->type == H5HP_MIN_HEAP && heap->heap[0].val == INT_MIN));
|
|
HDassert(heap->heap[0].obj == NULL);
|
|
|
|
FUNC_LEAVE_NOAPI(ret_value);
|
|
} /* end H5HP_remove() */
|
|
|
|
/*--------------------------------------------------------------------------
|
|
NAME
|
|
H5HP_change
|
|
PURPOSE
|
|
Change the priority of an object on a heap
|
|
USAGE
|
|
herr_t H5HP_change(heap, val, obj)
|
|
H5HP_t *heap; IN/OUT: Pointer to heap to modify
|
|
int val; IN: New priority value for object
|
|
void *obj; IN: Pointer to object to modify
|
|
|
|
RETURNS
|
|
Returns non-negative on success, negative on failure.
|
|
DESCRIPTION
|
|
Changes the priority of an object on a heap.
|
|
GLOBAL VARIABLES
|
|
COMMENTS, BUGS, ASSUMPTIONS
|
|
EXAMPLES
|
|
REVISION LOG
|
|
--------------------------------------------------------------------------*/
|
|
herr_t
|
|
H5HP_change(H5HP_t *heap, int val, void *_obj)
|
|
{
|
|
H5HP_info_t *obj = (H5HP_info_t *)_obj; /* Alias for object */
|
|
size_t obj_loc; /* Location of object in heap */
|
|
int old_val; /* Object's old priority value */
|
|
herr_t ret_value = SUCCEED; /* Return value */
|
|
|
|
FUNC_ENTER_NOAPI(FAIL)
|
|
|
|
/* Check args */
|
|
HDassert(heap);
|
|
HDassert(obj);
|
|
|
|
/* Check internal consistency */
|
|
/* (Pre-condition) */
|
|
HDassert(heap->nobjs < heap->nalloc);
|
|
HDassert(heap->heap);
|
|
HDassert((heap->type == H5HP_MAX_HEAP && heap->heap[0].val == INT_MAX) ||
|
|
(heap->type == H5HP_MIN_HEAP && heap->heap[0].val == INT_MIN));
|
|
HDassert(heap->heap[0].obj == NULL);
|
|
|
|
/* Get the location of the object in the heap */
|
|
obj_loc = obj->heap_loc;
|
|
HDassert(obj_loc > 0 && obj_loc <= heap->nobjs);
|
|
|
|
/* Change the heap object's priority */
|
|
old_val = heap->heap[obj_loc].val;
|
|
heap->heap[obj_loc].val = val;
|
|
|
|
/* Restore heap condition */
|
|
if (val < old_val) {
|
|
if (heap->type == H5HP_MAX_HEAP) {
|
|
if (H5HP__sink_max(heap, obj_loc) < 0)
|
|
HGOTO_ERROR(H5E_HEAP, H5E_CANTRESTORE, FAIL, "unable to restore heap condition");
|
|
} /* end if */
|
|
else {
|
|
if (H5HP__swim_min(heap, obj_loc) < 0)
|
|
HGOTO_ERROR(H5E_HEAP, H5E_CANTRESTORE, FAIL, "unable to restore heap condition");
|
|
} /* end else */
|
|
} /* end if */
|
|
else {
|
|
if (heap->type == H5HP_MAX_HEAP) {
|
|
if (H5HP__swim_max(heap, obj_loc) < 0)
|
|
HGOTO_ERROR(H5E_HEAP, H5E_CANTRESTORE, FAIL, "unable to restore heap condition");
|
|
} /* end if */
|
|
else {
|
|
if (H5HP__sink_min(heap, obj_loc) < 0)
|
|
HGOTO_ERROR(H5E_HEAP, H5E_CANTRESTORE, FAIL, "unable to restore heap condition");
|
|
} /* end else */
|
|
} /* end else */
|
|
|
|
done:
|
|
|
|
/* Check internal consistency */
|
|
/* (Post-condition) */
|
|
HDassert(heap->nobjs < heap->nalloc);
|
|
HDassert(heap->heap);
|
|
HDassert((heap->type == H5HP_MAX_HEAP && heap->heap[0].val == INT_MAX) ||
|
|
(heap->type == H5HP_MIN_HEAP && heap->heap[0].val == INT_MIN));
|
|
HDassert(heap->heap[0].obj == NULL);
|
|
|
|
FUNC_LEAVE_NOAPI(ret_value);
|
|
} /* end H5HP_change() */
|
|
|
|
/*--------------------------------------------------------------------------
|
|
NAME
|
|
H5HP_incr
|
|
PURPOSE
|
|
Increment the priority of an object on a heap
|
|
USAGE
|
|
herr_t H5HP_incr(heap, amt, obj)
|
|
H5HP_t *heap; IN/OUT: Pointer to heap to modify
|
|
unsigned amt; IN: Amount to increase priority by
|
|
void *obj; IN: Pointer to object to modify
|
|
|
|
RETURNS
|
|
Returns non-negative on success, negative on failure.
|
|
DESCRIPTION
|
|
Increments the priority of an object on a heap by one.
|
|
GLOBAL VARIABLES
|
|
COMMENTS, BUGS, ASSUMPTIONS
|
|
EXAMPLES
|
|
REVISION LOG
|
|
--------------------------------------------------------------------------*/
|
|
herr_t
|
|
H5HP_incr(H5HP_t *heap, unsigned amt, void *_obj)
|
|
{
|
|
H5HP_info_t *obj = (H5HP_info_t *)_obj; /* Alias for object */
|
|
size_t obj_loc; /* Location of object in heap */
|
|
herr_t ret_value = SUCCEED; /* Return value */
|
|
|
|
FUNC_ENTER_NOAPI(FAIL)
|
|
|
|
/* Check args */
|
|
HDassert(heap);
|
|
HDassert(obj);
|
|
|
|
/* Check internal consistency */
|
|
/* (Pre-condition) */
|
|
HDassert(heap->nobjs < heap->nalloc);
|
|
HDassert(heap->heap);
|
|
HDassert((heap->type == H5HP_MAX_HEAP && heap->heap[0].val == INT_MAX) ||
|
|
(heap->type == H5HP_MIN_HEAP && heap->heap[0].val == INT_MIN));
|
|
HDassert(heap->heap[0].obj == NULL);
|
|
|
|
/* Get the location of the object in the heap */
|
|
obj_loc = obj->heap_loc;
|
|
HDassert(obj_loc > 0 && obj_loc <= heap->nobjs);
|
|
|
|
/* Change the heap object's priority */
|
|
heap->heap[obj_loc].val += (int)amt;
|
|
|
|
/* Restore heap condition */
|
|
if (H5HP_MAX_HEAP == heap->type) {
|
|
if (H5HP__swim_max(heap, obj_loc) < 0)
|
|
HGOTO_ERROR(H5E_HEAP, H5E_CANTRESTORE, FAIL, "unable to restore heap condition")
|
|
} /* end if */
|
|
else {
|
|
if (H5HP__sink_min(heap, obj_loc) < 0)
|
|
HGOTO_ERROR(H5E_HEAP, H5E_CANTRESTORE, FAIL, "unable to restore heap condition")
|
|
} /* end else */
|
|
|
|
done:
|
|
|
|
/* Check internal consistency */
|
|
/* (Post-condition) */
|
|
HDassert(heap->nobjs < heap->nalloc);
|
|
HDassert(heap->heap);
|
|
HDassert((heap->type == H5HP_MAX_HEAP && heap->heap[0].val == INT_MAX) ||
|
|
(heap->type == H5HP_MIN_HEAP && heap->heap[0].val == INT_MIN));
|
|
HDassert(heap->heap[0].obj == NULL);
|
|
|
|
FUNC_LEAVE_NOAPI(ret_value);
|
|
} /* end H5HP_incr() */
|
|
|
|
/*--------------------------------------------------------------------------
|
|
NAME
|
|
H5HP_decr
|
|
PURPOSE
|
|
Decrement the priority of an object on a heap
|
|
USAGE
|
|
herr_t H5HP_dec(heap, amt, obj)
|
|
H5HP_t *heap; IN/OUT: Pointer to heap to modify
|
|
unsigned amt; IN: Amount to decrease priority by
|
|
void *obj; IN: Pointer to object to modify
|
|
|
|
RETURNS
|
|
Returns non-negative on success, negative on failure.
|
|
DESCRIPTION
|
|
Decrements the priority of an object on a heap by one.
|
|
GLOBAL VARIABLES
|
|
COMMENTS, BUGS, ASSUMPTIONS
|
|
EXAMPLES
|
|
REVISION LOG
|
|
--------------------------------------------------------------------------*/
|
|
herr_t
|
|
H5HP_decr(H5HP_t *heap, unsigned amt, void *_obj)
|
|
{
|
|
H5HP_info_t *obj = (H5HP_info_t *)_obj; /* Alias for object */
|
|
size_t obj_loc; /* Location of object in heap */
|
|
herr_t ret_value = SUCCEED; /* Return value */
|
|
|
|
FUNC_ENTER_NOAPI(FAIL)
|
|
|
|
/* Check args */
|
|
HDassert(heap);
|
|
HDassert(obj);
|
|
|
|
/* Check internal consistency */
|
|
/* (Pre-condition) */
|
|
HDassert(heap->nobjs < heap->nalloc);
|
|
HDassert(heap->heap);
|
|
HDassert((heap->type == H5HP_MAX_HEAP && heap->heap[0].val == INT_MAX) ||
|
|
(heap->type == H5HP_MIN_HEAP && heap->heap[0].val == INT_MIN));
|
|
HDassert(heap->heap[0].obj == NULL);
|
|
|
|
/* Get the location of the object in the heap */
|
|
obj_loc = obj->heap_loc;
|
|
HDassert(obj_loc > 0 && obj_loc <= heap->nobjs);
|
|
|
|
/* Change the heap object's priority */
|
|
H5_CHECK_OVERFLOW(amt, unsigned, int);
|
|
heap->heap[obj_loc].val -= (int)amt;
|
|
|
|
/* Restore heap condition */
|
|
if (heap->type == H5HP_MAX_HEAP) {
|
|
if (H5HP__sink_max(heap, obj_loc) < 0)
|
|
HGOTO_ERROR(H5E_HEAP, H5E_CANTRESTORE, FAIL, "unable to restore heap condition");
|
|
} /* end if */
|
|
else {
|
|
if (H5HP__swim_min(heap, obj_loc) < 0)
|
|
HGOTO_ERROR(H5E_HEAP, H5E_CANTRESTORE, FAIL, "unable to restore heap condition");
|
|
} /* end else */
|
|
|
|
done:
|
|
|
|
/* Check internal consistency */
|
|
/* (Post-condition) */
|
|
HDassert(heap->nobjs < heap->nalloc);
|
|
HDassert(heap->heap);
|
|
HDassert((heap->type == H5HP_MAX_HEAP && heap->heap[0].val == INT_MAX) ||
|
|
(heap->type == H5HP_MIN_HEAP && heap->heap[0].val == INT_MIN));
|
|
HDassert(heap->heap[0].obj == NULL);
|
|
|
|
FUNC_LEAVE_NOAPI(ret_value);
|
|
} /* end H5HP_decr() */
|
|
|
|
/*--------------------------------------------------------------------------
|
|
NAME
|
|
H5HP_close
|
|
PURPOSE
|
|
Close a heap, deallocating it.
|
|
USAGE
|
|
herr_t H5HP_close(heap)
|
|
H5HP_t *heap; IN/OUT: Pointer to heap to close
|
|
|
|
RETURNS
|
|
Returns non-negative on success, negative on failure.
|
|
DESCRIPTION
|
|
Close a heap, freeing all internal information. Any objects left in
|
|
the heap are not deallocated.
|
|
GLOBAL VARIABLES
|
|
COMMENTS, BUGS, ASSUMPTIONS
|
|
EXAMPLES
|
|
REVISION LOG
|
|
--------------------------------------------------------------------------*/
|
|
herr_t
|
|
H5HP_close(H5HP_t *heap)
|
|
{
|
|
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
|
|
|
/* Check args */
|
|
HDassert(heap);
|
|
|
|
/* Check internal consistency */
|
|
/* (Pre-condition) */
|
|
HDassert(heap->nobjs < heap->nalloc);
|
|
HDassert(heap->heap);
|
|
HDassert((heap->type == H5HP_MAX_HEAP && heap->heap[0].val == INT_MAX) ||
|
|
(heap->type == H5HP_MIN_HEAP && heap->heap[0].val == INT_MIN));
|
|
HDassert(NULL == heap->heap[0].obj);
|
|
|
|
/* Free internal structures for heap */
|
|
heap->heap = H5FL_SEQ_FREE(H5HP_ent_t, heap->heap);
|
|
|
|
/* Free actual heap object */
|
|
heap = H5FL_FREE(H5HP_t, heap);
|
|
|
|
FUNC_LEAVE_NOAPI(SUCCEED)
|
|
} /* end H5HP_close() */
|