#ifndef _DEPOOLHEAP_H
#define _DEPOOLHEAP_H
/*-------------------------------------------------------------------------
* drawElements Memory Pool Library
* --------------------------------
*
* Copyright 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*//*!
* \file
* \brief Memory pool heap class.
*//*--------------------------------------------------------------------*/
#include "deDefs.h"
#include "deMemPool.h"
#include "dePoolArray.h"
DE_BEGIN_EXTERN_C
void dePoolHeap_selfTest (void);
DE_END_EXTERN_C
/*--------------------------------------------------------------------*//*!
* \brief Declare a template pool heap class.
* \param TYPENAME Type name of the declared heap.
* \param VALUETYPE Type of the value contained in the heap.
* \param CMPFUNC Comparison function of two elements returning (-1, 0, +1).
*
* This macro declares a pool heap with all the necessary functions for
* operating with it. All allocated memory is taken from the memory pool
* given to the constructor.
*
* The functions for operating the heap are:
*
* \code
* Heap* Heap_create (deMemPool* pool);
* int Heap_getNumElements (const Heap* heap);
* deBool Heap_reserve (Heap* heap, int size);
* void Heap_reset (Heap* heap);
* deBool Heap_push (Heap* heap, Element elem);
* Element Heap_popMin (Heap* heap);
* \endcode
*//*--------------------------------------------------------------------*/
#define DE_DECLARE_POOL_HEAP(TYPENAME, VALUETYPE, CMPFUNC) \
\
DE_DECLARE_POOL_ARRAY(TYPENAME##Array, VALUETYPE); \
\
typedef struct TYPENAME##_s \
{ \
TYPENAME##Array* array; \
} TYPENAME; \
\
DE_INLINE TYPENAME* TYPENAME##_create (deMemPool* pool); \
DE_INLINE int TYPENAME##_getNumElements (const TYPENAME* heap) DE_UNUSED_FUNCTION; \
DE_INLINE deBool TYPENAME##_reserve (TYPENAME* heap, int capacity) DE_UNUSED_FUNCTION; \
DE_INLINE void TYPENAME##_reset (TYPENAME* heap) DE_UNUSED_FUNCTION; \
DE_INLINE void TYPENAME##_moveDown (TYPENAME* heap, int ndx) DE_UNUSED_FUNCTION; \
DE_INLINE void TYPENAME##_moveUp (TYPENAME* heap, int ndx) DE_UNUSED_FUNCTION; \
DE_INLINE deBool TYPENAME##_push (TYPENAME* heap, VALUETYPE elem) DE_UNUSED_FUNCTION; \
DE_INLINE VALUETYPE TYPENAME##_popMin (TYPENAME* heap) DE_UNUSED_FUNCTION; \
\
DE_INLINE TYPENAME* TYPENAME##_create (deMemPool* pool) \
{ \
TYPENAME* heap = DE_POOL_NEW(pool, TYPENAME); \
if (!heap) \
return DE_NULL; \
heap->array = TYPENAME##Array_create(pool); \
if (!heap->array) \
return DE_NULL; \
return heap; \
} \
\
DE_INLINE int TYPENAME##_getNumElements (const TYPENAME* heap) \
{ \
return TYPENAME##Array_getNumElements(heap->array); \
} \
\
DE_INLINE deBool TYPENAME##_reserve (TYPENAME* heap, int capacity) \
{ \
return TYPENAME##Array_reserve(heap->array, capacity); \
} \
\
DE_INLINE void TYPENAME##_reset (TYPENAME* heap) \
{ \
TYPENAME##Array_setSize(heap->array, 0); \
} \
\
DE_INLINE void TYPENAME##_moveDown (TYPENAME* heap, int ndx) \
{ \
TYPENAME##Array* array = heap->array; \
int numElements = TYPENAME##Array_getNumElements(array); \
for (;;) \
{ \
int childNdx0 = 2*ndx + 1; \
if (childNdx0 < numElements) \
{ \
int childNdx1 = deMin32(childNdx0 + 1, numElements - 1); \
int childCmpRes = CMPFUNC(TYPENAME##Array_get(array, childNdx0), TYPENAME##Array_get(array, childNdx1)); \
int minChildNdx = (childCmpRes == 1) ? childNdx1 : childNdx0; \
int cmpRes = CMPFUNC(TYPENAME##Array_get(array, ndx), TYPENAME##Array_get(array, minChildNdx)); \
if (cmpRes == 1) \
{ \
TYPENAME##Array_swap(array, ndx, minChildNdx); \
ndx = minChildNdx; \
} \
else \
break; \
} \
else \
break; \
} \
} \
\
DE_INLINE void TYPENAME##_moveUp (TYPENAME* heap, int ndx) \
{ \
TYPENAME##Array* array = heap->array; \
while (ndx > 0) \
{ \
int parentNdx = (ndx-1) >> 1; \
int cmpRes = CMPFUNC(TYPENAME##Array_get(array, ndx), TYPENAME##Array_get(array, parentNdx)); \
if (cmpRes == -1) \
{ \
TYPENAME##Array_swap(array, ndx, parentNdx); \
ndx = parentNdx; \
} \
else \
break; \
} \
} \
\
DE_INLINE deBool TYPENAME##_push (TYPENAME* heap, VALUETYPE elem) \
{ \
TYPENAME##Array* array = heap->array; \
int numElements = TYPENAME##Array_getNumElements(array); \
if (!TYPENAME##Array_setSize(array, numElements + 1)) \
return DE_FALSE; \
TYPENAME##Array_set(array, numElements, elem); \
TYPENAME##_moveUp(heap, numElements); \
return DE_TRUE; \
} \
\
DE_INLINE VALUETYPE TYPENAME##_popMin (TYPENAME* heap) \
{ \
TYPENAME##Array* array = heap->array; \
VALUETYPE tmp = TYPENAME##Array_get(array, 0); \
int numElements = TYPENAME##Array_getNumElements(array); \
TYPENAME##Array_set(array, 0, TYPENAME##Array_get(array, numElements-1)); \
TYPENAME##Array_setSize(array, numElements-1); \
TYPENAME##_moveDown(heap, 0); \
return tmp; \
} \
\
struct TYPENAME##Dummy_s { int dummy; }
#endif /* _DEPOOLHEAP_H */