1af0996ceSBarry Smith #include <petsc/private/petscimpl.h> 2665c2dedSJed Brown #include <petscviewer.h> 3d5731834SJed Brown 4d5731834SJed Brown typedef struct { 5d5731834SJed Brown PetscInt id; 6d5731834SJed Brown PetscInt value; 7d5731834SJed Brown } HeapNode; 8d5731834SJed Brown 9d5731834SJed Brown struct _PetscHeap { 10d5731834SJed Brown PetscInt end; /* one past the last item */ 11d5731834SJed Brown PetscInt alloc; /* length of array */ 12d5731834SJed Brown PetscInt stash; /* stash grows down, this points to last item */ 13d5731834SJed Brown HeapNode *base; 14d5731834SJed Brown }; 15d5731834SJed Brown 1644ee04a4SJed Brown /* 172ef1f0ffSBarry Smith The arity of the heap can be changed via the parameter B below. Consider the B=2 (arity=4 case below) 182ef1f0ffSBarry Smith 192ef1f0ffSBarry Smith [00 (sentinel); 01 (min node); 10 (unused); 11 (unused); 0100 (first child); 0101; 0110; 0111; ...] 202ef1f0ffSBarry Smith 212ef1f0ffSBarry Smith Slots 10 and 11 are referred to as the "hole" below in the implementation. 2244ee04a4SJed Brown */ 2344ee04a4SJed Brown 2444ee04a4SJed Brown #define B 1 /* log2(ARITY) */ 2544ee04a4SJed Brown #define ARITY (1 << B) /* tree branching factor */ 26d71ae5a4SJacob Faibussowitsch static inline PetscInt Parent(PetscInt loc) 27d71ae5a4SJacob Faibussowitsch { 2844ee04a4SJed Brown PetscInt p = loc >> B; 2944ee04a4SJed Brown if (p < ARITY) return (PetscInt)(loc != 1); /* Parent(1) is 0, otherwise fix entries ending up in the hole */ 3044ee04a4SJed Brown return p; 3144ee04a4SJed Brown } 32d5731834SJed Brown #define Value(h, loc) ((h)->base[loc].value) 33d5731834SJed Brown #define Id(h, loc) ((h)->base[loc].id) 34d5731834SJed Brown 35d71ae5a4SJacob Faibussowitsch static inline void Swap(PetscHeap h, PetscInt loc, PetscInt loc2) 36d71ae5a4SJacob Faibussowitsch { 37d5731834SJed Brown PetscInt id, val; 38d5731834SJed Brown id = Id(h, loc); 39d5731834SJed Brown val = Value(h, loc); 40d5731834SJed Brown h->base[loc].id = Id(h, loc2); 41d5731834SJed Brown h->base[loc].value = Value(h, loc2); 42d5731834SJed Brown h->base[loc2].id = id; 43d5731834SJed Brown h->base[loc2].value = val; 44d5731834SJed Brown } 45d71ae5a4SJacob Faibussowitsch static inline PetscInt MinChild(PetscHeap h, PetscInt loc) 46d71ae5a4SJacob Faibussowitsch { 4744ee04a4SJed Brown PetscInt min, chld, left, right; 4844ee04a4SJed Brown left = loc << B; 4944ee04a4SJed Brown right = PetscMin(left + ARITY - 1, h->end - 1); 5044ee04a4SJed Brown chld = 0; 51*1690c2aeSBarry Smith min = PETSC_INT_MAX; 5244ee04a4SJed Brown for (; left <= right; left++) { 5344ee04a4SJed Brown PetscInt val = Value(h, left); 5444ee04a4SJed Brown if (val < min) { 5544ee04a4SJed Brown min = val; 5644ee04a4SJed Brown chld = left; 5744ee04a4SJed Brown } 5844ee04a4SJed Brown } 5944ee04a4SJed Brown return chld; 60d5731834SJed Brown } 61d5731834SJed Brown 62d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscHeapCreate(PetscInt maxsize, PetscHeap *heap) 63d71ae5a4SJacob Faibussowitsch { 64d5731834SJed Brown PetscHeap h; 65d5731834SJed Brown 66d5731834SJed Brown PetscFunctionBegin; 670298fd71SBarry Smith *heap = NULL; 689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, &h)); 69d5731834SJed Brown h->end = 1; 7044ee04a4SJed Brown h->alloc = maxsize + ARITY; /* We waste all but one slot (loc=1) in the first ARITY slots */ 71d5731834SJed Brown h->stash = h->alloc; 729566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(h->alloc, &h->base)); 73d5731834SJed Brown h->base[0].id = -1; 74*1690c2aeSBarry Smith h->base[0].value = PETSC_INT_MIN; 75d5731834SJed Brown *heap = h; 763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 77d5731834SJed Brown } 78d5731834SJed Brown 79d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscHeapAdd(PetscHeap h, PetscInt id, PetscInt val) 80d71ae5a4SJacob Faibussowitsch { 8144ee04a4SJed Brown PetscInt loc, par; 82d5731834SJed Brown 83d5731834SJed Brown PetscFunctionBegin; 8444ee04a4SJed Brown if (1 < h->end && h->end < ARITY) h->end = ARITY; 85d5731834SJed Brown loc = h->end++; 8608401ef6SPierre Jolivet PetscCheck(h->end <= h->stash, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Addition would exceed allocation %" PetscInt_FMT " (%" PetscInt_FMT " stashed)", h->alloc, (h->alloc - h->stash)); 87d5731834SJed Brown h->base[loc].id = id; 88d5731834SJed Brown h->base[loc].value = val; 89d5731834SJed Brown 90d5731834SJed Brown /* move up until heap condition is satisfied */ 91527e7439SSatish Balay while ((void)(par = Parent(loc)), Value(h, par) > val) { 9244ee04a4SJed Brown Swap(h, loc, par); 9344ee04a4SJed Brown loc = par; 94d5731834SJed Brown } 953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 96d5731834SJed Brown } 97d5731834SJed Brown 98d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscHeapPop(PetscHeap h, PetscInt *id, PetscInt *val) 99d71ae5a4SJacob Faibussowitsch { 100d5731834SJed Brown PetscInt loc, chld; 101d5731834SJed Brown 102d5731834SJed Brown PetscFunctionBegin; 103d5731834SJed Brown if (h->end == 1) { 104d5731834SJed Brown *id = h->base[0].id; 105d5731834SJed Brown *val = h->base[0].value; 1063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 107d5731834SJed Brown } 108d5731834SJed Brown 109d5731834SJed Brown *id = h->base[1].id; 110d5731834SJed Brown *val = h->base[1].value; 111d5731834SJed Brown 112d5731834SJed Brown /* rotate last entry into first position */ 113d5731834SJed Brown loc = --h->end; 11444ee04a4SJed Brown if (h->end == ARITY) h->end = 2; /* Skip over hole */ 115d5731834SJed Brown h->base[1].id = Id(h, loc); 116d5731834SJed Brown h->base[1].value = Value(h, loc); 117d5731834SJed Brown 118d5731834SJed Brown /* move down until min heap condition is satisfied */ 119d5731834SJed Brown loc = 1; 120d5731834SJed Brown while ((chld = MinChild(h, loc)) && Value(h, loc) > Value(h, chld)) { 121d5731834SJed Brown Swap(h, loc, chld); 122d5731834SJed Brown loc = chld; 123d5731834SJed Brown } 1243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 125d5731834SJed Brown } 126d5731834SJed Brown 127d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscHeapPeek(PetscHeap h, PetscInt *id, PetscInt *val) 128d71ae5a4SJacob Faibussowitsch { 129d5731834SJed Brown PetscFunctionBegin; 130d5731834SJed Brown if (h->end == 1) { 131d5731834SJed Brown *id = h->base[0].id; 132d5731834SJed Brown *val = h->base[0].value; 1333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 134d5731834SJed Brown } 135d5731834SJed Brown 136d5731834SJed Brown *id = h->base[1].id; 137d5731834SJed Brown *val = h->base[1].value; 1383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 139d5731834SJed Brown } 140d5731834SJed Brown 141d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscHeapStash(PetscHeap h, PetscInt id, PetscInt val) 142d71ae5a4SJacob Faibussowitsch { 143d5731834SJed Brown PetscInt loc; 144d5731834SJed Brown 145d5731834SJed Brown PetscFunctionBegin; 146d5731834SJed Brown loc = --h->stash; 147d5731834SJed Brown h->base[loc].id = id; 148d5731834SJed Brown h->base[loc].value = val; 1493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 150d5731834SJed Brown } 151d5731834SJed Brown 152d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscHeapUnstash(PetscHeap h) 153d71ae5a4SJacob Faibussowitsch { 154d5731834SJed Brown PetscFunctionBegin; 155d5731834SJed Brown while (h->stash < h->alloc) { 156d5731834SJed Brown PetscInt id = Id(h, h->stash), value = Value(h, h->stash); 157d5731834SJed Brown h->stash++; 1589566063dSJacob Faibussowitsch PetscCall(PetscHeapAdd(h, id, value)); 159d5731834SJed Brown } 1603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 161d5731834SJed Brown } 162d5731834SJed Brown 163d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscHeapDestroy(PetscHeap *heap) 164d71ae5a4SJacob Faibussowitsch { 165d5731834SJed Brown PetscFunctionBegin; 1669566063dSJacob Faibussowitsch PetscCall(PetscFree((*heap)->base)); 1679566063dSJacob Faibussowitsch PetscCall(PetscFree(*heap)); 1683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 169d5731834SJed Brown } 170d5731834SJed Brown 171d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscHeapView(PetscHeap h, PetscViewer viewer) 172d71ae5a4SJacob Faibussowitsch { 173d5731834SJed Brown PetscBool iascii; 174d5731834SJed Brown 175d5731834SJed Brown PetscFunctionBegin; 17648a46eb9SPierre Jolivet if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PETSC_COMM_SELF, &viewer)); 177d5731834SJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1789566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 179d5731834SJed Brown if (iascii) { 1809566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Heap size %" PetscInt_FMT " with %" PetscInt_FMT " stashed\n", h->end - 1, h->alloc - h->stash)); 1819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Heap in (id,value) pairs\n")); 1829566063dSJacob Faibussowitsch PetscCall(PetscIntView(2 * (h->end - 1), (const PetscInt *)(h->base + 1), viewer)); 1839566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Stash in (id,value) pairs\n")); 1849566063dSJacob Faibussowitsch PetscCall(PetscIntView(2 * (h->alloc - h->stash), (const PetscInt *)(h->base + h->stash), viewer)); 185d5731834SJed Brown } 1863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 187d5731834SJed Brown } 188