Upgrade to Newton 3.14 and make it a thirdparty lib
This commit is contained in:
435
thirdparty/src/newton/dgCore/dgHeap.h
vendored
Normal file
435
thirdparty/src/newton/dgCore/dgHeap.h
vendored
Normal file
@@ -0,0 +1,435 @@
|
||||
/* Copyright (c) <2003-2019> <Julio Jerez, Newton Game Dynamics>
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* Visual C++ 6.0 created by: Julio Jerez
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef __dgHeapBase__
|
||||
#define __dgHeapBase__
|
||||
|
||||
#include "dgStdafx.h"
|
||||
#include "dgMemory.h"
|
||||
|
||||
//#define DG_HEAP_DEBUG_CHECK
|
||||
|
||||
|
||||
template <class OBJECT, class KEY>
|
||||
class dgHeapBase
|
||||
{
|
||||
protected:
|
||||
struct RECORD
|
||||
{
|
||||
KEY m_key;
|
||||
OBJECT m_obj;
|
||||
|
||||
RECORD (KEY key, const OBJECT& obj)
|
||||
:m_key(key), m_obj(obj)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
dgHeapBase (dgInt32 maxElements, dgMemoryAllocator* const allocator);
|
||||
dgHeapBase (const void * const buffer, dgInt32 sizeInBytes);
|
||||
~dgHeapBase ();
|
||||
|
||||
public:
|
||||
DG_CLASS_ALLOCATOR(allocator)
|
||||
|
||||
void Flush ();
|
||||
KEY MaxValue() const;
|
||||
KEY Value(dgInt32 i = 0) const;
|
||||
dgInt32 GetCount() const;
|
||||
dgInt32 GetMaxCount() const;
|
||||
const OBJECT& operator[] (dgInt32 i) const;
|
||||
dgInt32 Find (OBJECT &obj);
|
||||
dgInt32 Find (KEY key);
|
||||
|
||||
dgInt32 m_curCount;
|
||||
dgInt32 m_maxCount;
|
||||
dgMemoryAllocator* m_allocator;
|
||||
RECORD *m_pool;
|
||||
};
|
||||
|
||||
template <class OBJECT, class KEY>
|
||||
class dgDownHeap: public dgHeapBase<OBJECT, KEY>
|
||||
{
|
||||
public:
|
||||
dgDownHeap (dgInt32 maxElements, dgMemoryAllocator* const allocator);
|
||||
dgDownHeap (const void * const buffer, dgInt32 sizeInBytes);
|
||||
|
||||
void Pop () {Remove (0);}
|
||||
void Push (OBJECT &obj, KEY key);
|
||||
void Sort ();
|
||||
void Remove (dgInt32 Index);
|
||||
bool SanityCheck();
|
||||
};
|
||||
|
||||
template <class OBJECT, class KEY>
|
||||
class dgUpHeap: public dgHeapBase<OBJECT, KEY>
|
||||
{
|
||||
public:
|
||||
dgUpHeap (dgInt32 maxElements, dgMemoryAllocator* const allocator);
|
||||
dgUpHeap (const void * const buffer, dgInt32 sizeInBytes);
|
||||
|
||||
void Pop () {Remove (0);}
|
||||
void Push (OBJECT &obj, KEY key);
|
||||
void Sort ();
|
||||
void Remove (dgInt32 Index);
|
||||
bool SanityCheck();
|
||||
};
|
||||
|
||||
template <class OBJECT, class KEY>
|
||||
dgHeapBase<OBJECT,KEY>::dgHeapBase (dgInt32 maxElements, dgMemoryAllocator* const allocator)
|
||||
{
|
||||
m_allocator = allocator;
|
||||
m_pool = (RECORD *)m_allocator->Malloc (maxElements * sizeof (RECORD));
|
||||
m_maxCount = maxElements;
|
||||
Flush();
|
||||
}
|
||||
|
||||
template <class OBJECT, class KEY>
|
||||
dgHeapBase<OBJECT,KEY>::dgHeapBase (const void * const buffer, dgInt32 sizeInBytes)
|
||||
{
|
||||
m_allocator = NULL;
|
||||
m_pool = (RECORD *) buffer;
|
||||
m_maxCount = dgInt32 (sizeInBytes / sizeof (RECORD));
|
||||
Flush();
|
||||
}
|
||||
|
||||
template <class OBJECT, class KEY>
|
||||
dgHeapBase<OBJECT,KEY>::~dgHeapBase ()
|
||||
{
|
||||
if (m_allocator) {
|
||||
m_allocator->Free (m_pool);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class OBJECT, class KEY>
|
||||
KEY dgHeapBase<OBJECT,KEY>::Value(dgInt32 i) const
|
||||
{
|
||||
return m_pool[i].m_key;
|
||||
}
|
||||
|
||||
|
||||
template <class OBJECT, class KEY>
|
||||
dgInt32 dgHeapBase<OBJECT,KEY>::GetCount() const
|
||||
{
|
||||
return m_curCount;
|
||||
}
|
||||
|
||||
template <class OBJECT, class KEY>
|
||||
void dgHeapBase<OBJECT,KEY>::Flush ()
|
||||
{
|
||||
m_curCount = 0;
|
||||
|
||||
#ifdef _DEBUG
|
||||
// dgHeapBase<OBJECT,KEY>::m_pool[dgHeapBase<OBJECT,KEY>::m_curCount].m_key = KEY (0);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class OBJECT, class KEY>
|
||||
KEY dgHeapBase<OBJECT,KEY>::MaxValue() const
|
||||
{
|
||||
return m_pool[0].m_key;
|
||||
}
|
||||
|
||||
template <class OBJECT, class KEY>
|
||||
dgInt32 dgHeapBase<OBJECT,KEY>::GetMaxCount() const
|
||||
{
|
||||
return m_maxCount;
|
||||
}
|
||||
|
||||
|
||||
template <class OBJECT, class KEY>
|
||||
dgInt32 dgHeapBase<OBJECT,KEY>::Find (OBJECT &obj)
|
||||
{
|
||||
// For now let perform a linear search
|
||||
// this is efficient if the size of the heap is small
|
||||
// ex: m_curCount < 32
|
||||
// this will be change to a binary search in the heap should the
|
||||
// the size of the heap get larger than 32
|
||||
// dgAssert (m_curCount <= 32);
|
||||
for (dgInt32 i = 0; i < m_curCount; i ++) {
|
||||
if (m_pool[i].obj == obj) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return - 1;
|
||||
}
|
||||
|
||||
|
||||
template <class OBJECT, class KEY>
|
||||
dgInt32 dgHeapBase<OBJECT,KEY>::Find (KEY key)
|
||||
{
|
||||
// ex: m_curCount < 32
|
||||
// this will be change to a binary search in the heap shoud the
|
||||
// the size of the heap get larger than 32
|
||||
dgAssert (m_curCount <= 32);
|
||||
for (dgInt32 i = 0; i < m_curCount; i ++) {
|
||||
if (m_pool[i].m_key == key) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return - 1;
|
||||
}
|
||||
|
||||
|
||||
template <class OBJECT, class KEY>
|
||||
const OBJECT& dgHeapBase<OBJECT,KEY>::operator[] (dgInt32 i) const
|
||||
{
|
||||
dgAssert (i<= m_curCount);
|
||||
return m_pool[i].m_obj;
|
||||
}
|
||||
|
||||
|
||||
// **************************************************************************
|
||||
//
|
||||
// down Heap
|
||||
//
|
||||
// **************************************************************************
|
||||
template <class OBJECT, class KEY>
|
||||
dgDownHeap<OBJECT,KEY>::dgDownHeap (dgInt32 maxElements, dgMemoryAllocator* const allocator)
|
||||
:dgHeapBase<OBJECT, KEY> (maxElements, allocator)
|
||||
{
|
||||
}
|
||||
|
||||
template <class OBJECT, class KEY>
|
||||
dgDownHeap<OBJECT,KEY>::dgDownHeap (const void * const buffer, dgInt32 sizeInBytes)
|
||||
:dgHeapBase<OBJECT, KEY> (buffer, sizeInBytes)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
template <class OBJECT, class KEY>
|
||||
void dgDownHeap<OBJECT,KEY>::Push (OBJECT &obj, KEY key)
|
||||
{
|
||||
dgHeapBase<OBJECT,KEY>::m_curCount ++;
|
||||
|
||||
dgInt32 j;
|
||||
dgInt32 i = dgHeapBase<OBJECT,KEY>::m_curCount;
|
||||
for (; i; i = j) {
|
||||
j = i >> 1;
|
||||
if (!j || (dgHeapBase<OBJECT,KEY>::m_pool[j - 1].m_key > key)) {
|
||||
break;
|
||||
}
|
||||
dgHeapBase<OBJECT,KEY>::m_pool[i - 1] = dgHeapBase<OBJECT,KEY>::m_pool[j - 1];
|
||||
}
|
||||
dgAssert (i);
|
||||
dgHeapBase<OBJECT,KEY>::m_pool[i - 1].m_key = key;
|
||||
dgHeapBase<OBJECT,KEY>::m_pool[i - 1].m_obj = obj;
|
||||
|
||||
dgAssert (SanityCheck());
|
||||
}
|
||||
|
||||
template <class OBJECT, class KEY>
|
||||
void dgDownHeap<OBJECT,KEY>::Remove (dgInt32 index)
|
||||
{
|
||||
dgHeapBase<OBJECT, KEY>::m_curCount--;
|
||||
dgHeapBase<OBJECT, KEY>::m_pool[index] = dgHeapBase<OBJECT, KEY>::m_pool[dgHeapBase<OBJECT, KEY>::m_curCount];
|
||||
while (index && dgHeapBase<OBJECT, KEY>::m_pool[(index - 1) >> 1].m_key < dgHeapBase<OBJECT, KEY>::m_pool[index].m_key) {
|
||||
dgSwap(dgHeapBase<OBJECT, KEY>::m_pool[(index - 1) >> 1], dgHeapBase<OBJECT, KEY>::m_pool[index]);
|
||||
index = (index - 1) >> 1;
|
||||
}
|
||||
|
||||
while ((2 * index + 1) < dgHeapBase<OBJECT, KEY>::m_curCount) {
|
||||
dgInt32 i0 = 2 * index + 1;
|
||||
dgInt32 i1 = 2 * index + 2;
|
||||
if (i1 < dgHeapBase<OBJECT, KEY>::m_curCount) {
|
||||
i0 = (dgHeapBase<OBJECT, KEY>::m_pool[i0].m_key > dgHeapBase<OBJECT, KEY>::m_pool[i1].m_key) ? i0 : i1;
|
||||
if (dgHeapBase<OBJECT, KEY>::m_pool[i0].m_key <= dgHeapBase<OBJECT, KEY>::m_pool[index].m_key) {
|
||||
break;
|
||||
}
|
||||
dgSwap(dgHeapBase<OBJECT, KEY>::m_pool[i0], dgHeapBase<OBJECT, KEY>::m_pool[index]);
|
||||
index = i0;
|
||||
} else {
|
||||
if (dgHeapBase<OBJECT, KEY>::m_pool[i0].m_key > dgHeapBase<OBJECT, KEY>::m_pool[index].m_key) {
|
||||
dgSwap(dgHeapBase<OBJECT, KEY>::m_pool[i0], dgHeapBase<OBJECT, KEY>::m_pool[index]);
|
||||
}
|
||||
index = i0;
|
||||
}
|
||||
}
|
||||
dgAssert (SanityCheck());
|
||||
}
|
||||
|
||||
template <class OBJECT, class KEY>
|
||||
void dgDownHeap<OBJECT,KEY>::Sort ()
|
||||
{
|
||||
dgInt32 count = dgHeapBase<OBJECT,KEY>::m_curCount;
|
||||
for (dgInt32 i = 1; i < count; i ++) {
|
||||
KEY key (dgHeapBase<OBJECT,KEY>::m_pool[0].m_key);
|
||||
OBJECT obj (dgHeapBase<OBJECT,KEY>::m_pool[0].m_obj);
|
||||
|
||||
Pop();
|
||||
|
||||
dgHeapBase<OBJECT,KEY>::m_pool[dgHeapBase<OBJECT,KEY>::m_curCount].m_key = key;
|
||||
dgHeapBase<OBJECT,KEY>::m_pool[dgHeapBase<OBJECT,KEY>::m_curCount].m_obj = obj;
|
||||
}
|
||||
|
||||
dgHeapBase<OBJECT,KEY>::m_curCount = count;
|
||||
for (dgInt32 i = 0; i < count / 2; i ++) {
|
||||
KEY key (dgHeapBase<OBJECT,KEY>::m_pool[i].m_key);
|
||||
OBJECT obj (dgHeapBase<OBJECT,KEY>::m_pool[i].m_obj);
|
||||
|
||||
dgHeapBase<OBJECT,KEY>::m_pool[i].m_key = dgHeapBase<OBJECT,KEY>::m_pool[count - i - 1].m_key;
|
||||
dgHeapBase<OBJECT,KEY>::m_pool[i].m_obj = dgHeapBase<OBJECT,KEY>::m_pool[count - i - 1].m_obj;
|
||||
|
||||
dgHeapBase<OBJECT,KEY>::m_pool[count - i - 1].m_key = key;
|
||||
dgHeapBase<OBJECT,KEY>::m_pool[count - i - 1].m_obj = obj;
|
||||
}
|
||||
dgAssert (SanityCheck());
|
||||
}
|
||||
|
||||
template <class OBJECT, class KEY>
|
||||
bool dgDownHeap<OBJECT,KEY>::SanityCheck()
|
||||
{
|
||||
#ifdef DG_HEAP_DEBUG_CHECK
|
||||
for (dgInt32 i = 0; i < m_curCount; i++) {
|
||||
dgInt32 i1 = 2 * i + 1;
|
||||
dgInt32 i2 = 2 * i + 2;
|
||||
if ((i1 < m_curCount) && (dgHeapBase<OBJECT, KEY>::m_pool[i].m_key < dgHeapBase<OBJECT, KEY>::m_pool[i1].m_key)) {
|
||||
return false;
|
||||
}
|
||||
if ((i2 < m_curCount) && (dgHeapBase<OBJECT, KEY>::m_pool[i].m_key < dgHeapBase<OBJECT, KEY>::m_pool[i2].m_key)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
// **************************************************************************
|
||||
//
|
||||
// down Heap
|
||||
//
|
||||
// **************************************************************************
|
||||
template <class OBJECT, class KEY>
|
||||
dgUpHeap<OBJECT,KEY>::dgUpHeap (dgInt32 maxElements, dgMemoryAllocator* const allocator)
|
||||
:dgHeapBase<OBJECT, KEY> (maxElements, allocator)
|
||||
{
|
||||
}
|
||||
|
||||
template <class OBJECT, class KEY>
|
||||
dgUpHeap<OBJECT,KEY>::dgUpHeap (const void * const buffer, dgInt32 sizeInBytes)
|
||||
:dgHeapBase<OBJECT, KEY> (buffer, sizeInBytes)
|
||||
{
|
||||
}
|
||||
|
||||
template <class OBJECT, class KEY>
|
||||
bool dgUpHeap<OBJECT,KEY>::SanityCheck()
|
||||
{
|
||||
#ifdef DG_HEAP_DEBUG_CHECK
|
||||
for (dgInt32 i = 0; i < m_curCount; i ++) {
|
||||
dgInt32 i1 = 2 * i + 1;
|
||||
dgInt32 i2 = 2 * i + 2;
|
||||
if ((i1 < m_curCount) && (dgHeapBase<OBJECT,KEY>::m_pool[i].m_key > dgHeapBase<OBJECT,KEY>::m_pool[i1].m_key)) {
|
||||
return false;
|
||||
}
|
||||
if ((i2 < m_curCount) && (dgHeapBase<OBJECT,KEY>::m_pool[i].m_key > dgHeapBase<OBJECT,KEY>::m_pool[i2].m_key)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class OBJECT, class KEY>
|
||||
void dgUpHeap<OBJECT,KEY>::Push (OBJECT &obj, KEY key)
|
||||
{
|
||||
dgHeapBase<OBJECT,KEY>::m_curCount ++;
|
||||
|
||||
dgInt32 j;
|
||||
dgInt32 i = dgHeapBase<OBJECT,KEY>::m_curCount;
|
||||
for (; i; i = j) {
|
||||
j = i >> 1;
|
||||
if (!j || (dgHeapBase<OBJECT,KEY>::m_pool[j - 1].m_key < key)) {
|
||||
break;
|
||||
}
|
||||
dgHeapBase<OBJECT,KEY>::m_pool[i - 1] = dgHeapBase<OBJECT,KEY>::m_pool[j - 1];
|
||||
}
|
||||
dgAssert (i);
|
||||
dgHeapBase<OBJECT,KEY>::m_pool[i - 1].m_key = key;
|
||||
dgHeapBase<OBJECT,KEY>::m_pool[i - 1].m_obj = obj;
|
||||
dgAssert (SanityCheck());
|
||||
}
|
||||
|
||||
template <class OBJECT, class KEY>
|
||||
void dgUpHeap<OBJECT,KEY>::Sort ()
|
||||
{
|
||||
dgInt32 count = dgHeapBase<OBJECT,KEY>::m_curCount;
|
||||
for (dgInt32 i = 1; i < count; i ++) {
|
||||
KEY key (dgHeapBase<OBJECT,KEY>::m_pool[0].m_key);
|
||||
OBJECT obj (dgHeapBase<OBJECT,KEY>::m_pool[0].m_obj);
|
||||
|
||||
Pop();
|
||||
|
||||
dgHeapBase<OBJECT,KEY>::m_pool[dgHeapBase<OBJECT,KEY>::m_curCount].m_key = key;
|
||||
dgHeapBase<OBJECT,KEY>::m_pool[dgHeapBase<OBJECT,KEY>::m_curCount].m_obj = obj;
|
||||
}
|
||||
|
||||
dgHeapBase<OBJECT,KEY>::m_curCount = count;
|
||||
for (dgInt32 i = 0; i < count / 2; i ++) {
|
||||
KEY key (dgHeapBase<OBJECT,KEY>::m_pool[i].m_key);
|
||||
OBJECT obj (dgHeapBase<OBJECT,KEY>::m_pool[i].m_obj);
|
||||
|
||||
dgHeapBase<OBJECT,KEY>::m_pool[i].m_key = dgHeapBase<OBJECT,KEY>::m_pool[count - i - 1].m_key;
|
||||
dgHeapBase<OBJECT,KEY>::m_pool[i].m_obj = dgHeapBase<OBJECT,KEY>::m_pool[count - i - 1].m_obj;
|
||||
|
||||
dgHeapBase<OBJECT,KEY>::m_pool[count - i - 1].m_key = key;
|
||||
dgHeapBase<OBJECT,KEY>::m_pool[count - i - 1].m_obj = obj;
|
||||
}
|
||||
dgAssert (SanityCheck());
|
||||
}
|
||||
|
||||
template <class OBJECT, class KEY>
|
||||
void dgUpHeap<OBJECT,KEY>::Remove (dgInt32 index)
|
||||
{
|
||||
dgHeapBase<OBJECT, KEY>::m_curCount--;
|
||||
dgHeapBase<OBJECT, KEY>::m_pool[index] = dgHeapBase<OBJECT, KEY>::m_pool[dgHeapBase<OBJECT, KEY>::m_curCount];
|
||||
while (index && dgHeapBase<OBJECT, KEY>::m_pool[(index - 1) >> 1].m_key > dgHeapBase<OBJECT, KEY>::m_pool[index].m_key) {
|
||||
dgSwap(dgHeapBase<OBJECT, KEY>::m_pool[(index - 1) >> 1], dgHeapBase<OBJECT, KEY>::m_pool[index]);
|
||||
index = (index - 1) >> 1;
|
||||
}
|
||||
|
||||
while ((2 * index + 1) < dgHeapBase<OBJECT, KEY>::m_curCount) {
|
||||
dgInt32 i0 = 2 * index + 1;
|
||||
dgInt32 i1 = 2 * index + 2;
|
||||
if (i1 < dgHeapBase<OBJECT, KEY>::m_curCount) {
|
||||
i0 = (dgHeapBase<OBJECT, KEY>::m_pool[i0].m_key < dgHeapBase<OBJECT, KEY>::m_pool[i1].m_key) ? i0 : i1;
|
||||
if (dgHeapBase<OBJECT, KEY>::m_pool[i0].m_key >= dgHeapBase<OBJECT, KEY>::m_pool[index].m_key) {
|
||||
break;
|
||||
}
|
||||
dgSwap(dgHeapBase<OBJECT, KEY>::m_pool[i0], dgHeapBase<OBJECT, KEY>::m_pool[index]);
|
||||
index = i0;
|
||||
} else {
|
||||
if (dgHeapBase<OBJECT, KEY>::m_pool[i0].m_key < dgHeapBase<OBJECT, KEY>::m_pool[index].m_key) {
|
||||
dgSwap(dgHeapBase<OBJECT, KEY>::m_pool[i0], dgHeapBase<OBJECT, KEY>::m_pool[index]);
|
||||
}
|
||||
index = i0;
|
||||
}
|
||||
}
|
||||
dgAssert (SanityCheck());
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user