19962606eSBarry Smith 2af0996ceSBarry Smith #include <petsc/private/petscimpl.h> 3665c2dedSJed Brown #include <petscviewer.h> 4d5731834SJed Brown 5d5731834SJed Brown typedef struct { 6d5731834SJed Brown PetscInt id; 7d5731834SJed Brown PetscInt value; 8d5731834SJed Brown } HeapNode; 9d5731834SJed Brown 10d5731834SJed Brown struct _PetscHeap { 11d5731834SJed Brown PetscInt end; /* one past the last item */ 12d5731834SJed Brown PetscInt alloc; /* length of array */ 13d5731834SJed Brown PetscInt stash; /* stash grows down, this points to last item */ 14d5731834SJed Brown HeapNode *base; 15d5731834SJed Brown }; 16d5731834SJed Brown 1744ee04a4SJed Brown /* 1844ee04a4SJed Brown * The arity of the heap can be changed via the parameter B below. Consider the B=2 (arity=4 case below) 1944ee04a4SJed Brown * 2044ee04a4SJed Brown * [00 (sentinel); 01 (min node); 10 (unused); 11 (unused); 0100 (first child); 0101; 0110; 0111; ...] 2144ee04a4SJed Brown * 2244ee04a4SJed Brown * Slots 10 and 11 are referred to as the "hole" below in the implementation. 2344ee04a4SJed Brown */ 2444ee04a4SJed Brown 2544ee04a4SJed Brown #define B 1 /* log2(ARITY) */ 2644ee04a4SJed Brown #define ARITY (1 << B) /* tree branching factor */ 279371c9d4SSatish Balay static inline PetscInt Parent(PetscInt loc) { 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 359371c9d4SSatish Balay static inline void Swap(PetscHeap h, PetscInt loc, PetscInt loc2) { 36d5731834SJed Brown PetscInt id, val; 37d5731834SJed Brown id = Id(h, loc); 38d5731834SJed Brown val = Value(h, loc); 39d5731834SJed Brown h->base[loc].id = Id(h, loc2); 40d5731834SJed Brown h->base[loc].value = Value(h, loc2); 41d5731834SJed Brown h->base[loc2].id = id; 42d5731834SJed Brown h->base[loc2].value = val; 43d5731834SJed Brown } 449371c9d4SSatish Balay static inline PetscInt MinChild(PetscHeap h, PetscInt loc) { 4544ee04a4SJed Brown PetscInt min, chld, left, right; 4644ee04a4SJed Brown left = loc << B; 4744ee04a4SJed Brown right = PetscMin(left + ARITY - 1, h->end - 1); 4844ee04a4SJed Brown chld = 0; 4944ee04a4SJed Brown min = PETSC_MAX_INT; 5044ee04a4SJed Brown for (; left <= right; left++) { 5144ee04a4SJed Brown PetscInt val = Value(h, left); 5244ee04a4SJed Brown if (val < min) { 5344ee04a4SJed Brown min = val; 5444ee04a4SJed Brown chld = left; 5544ee04a4SJed Brown } 5644ee04a4SJed Brown } 5744ee04a4SJed Brown return chld; 58d5731834SJed Brown } 59d5731834SJed Brown 609371c9d4SSatish Balay PetscErrorCode PetscHeapCreate(PetscInt maxsize, PetscHeap *heap) { 61d5731834SJed Brown PetscHeap h; 62d5731834SJed Brown 63d5731834SJed Brown PetscFunctionBegin; 640298fd71SBarry Smith *heap = NULL; 659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, &h)); 66d5731834SJed Brown h->end = 1; 6744ee04a4SJed Brown h->alloc = maxsize + ARITY; /* We waste all but one slot (loc=1) in the first ARITY slots */ 68d5731834SJed Brown h->stash = h->alloc; 699566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(h->alloc, &h->base)); 70d5731834SJed Brown h->base[0].id = -1; 71d5731834SJed Brown h->base[0].value = PETSC_MIN_INT; 72d5731834SJed Brown *heap = h; 73d5731834SJed Brown PetscFunctionReturn(0); 74d5731834SJed Brown } 75d5731834SJed Brown 769371c9d4SSatish Balay PetscErrorCode PetscHeapAdd(PetscHeap h, PetscInt id, PetscInt val) { 7744ee04a4SJed Brown PetscInt loc, par; 78d5731834SJed Brown 79d5731834SJed Brown PetscFunctionBegin; 8044ee04a4SJed Brown if (1 < h->end && h->end < ARITY) h->end = ARITY; 81d5731834SJed Brown loc = h->end++; 8208401ef6SPierre 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)); 83d5731834SJed Brown h->base[loc].id = id; 84d5731834SJed Brown h->base[loc].value = val; 85d5731834SJed Brown 86d5731834SJed Brown /* move up until heap condition is satisfied */ 87527e7439SSatish Balay while ((void)(par = Parent(loc)), Value(h, par) > val) { 8844ee04a4SJed Brown Swap(h, loc, par); 8944ee04a4SJed Brown loc = par; 90d5731834SJed Brown } 91d5731834SJed Brown PetscFunctionReturn(0); 92d5731834SJed Brown } 93d5731834SJed Brown 949371c9d4SSatish Balay PetscErrorCode PetscHeapPop(PetscHeap h, PetscInt *id, PetscInt *val) { 95d5731834SJed Brown PetscInt loc, chld; 96d5731834SJed Brown 97d5731834SJed Brown PetscFunctionBegin; 98d5731834SJed Brown if (h->end == 1) { 99d5731834SJed Brown *id = h->base[0].id; 100d5731834SJed Brown *val = h->base[0].value; 101d5731834SJed Brown PetscFunctionReturn(0); 102d5731834SJed Brown } 103d5731834SJed Brown 104d5731834SJed Brown *id = h->base[1].id; 105d5731834SJed Brown *val = h->base[1].value; 106d5731834SJed Brown 107d5731834SJed Brown /* rotate last entry into first position */ 108d5731834SJed Brown loc = --h->end; 10944ee04a4SJed Brown if (h->end == ARITY) h->end = 2; /* Skip over hole */ 110d5731834SJed Brown h->base[1].id = Id(h, loc); 111d5731834SJed Brown h->base[1].value = Value(h, loc); 112d5731834SJed Brown 113d5731834SJed Brown /* move down until min heap condition is satisfied */ 114d5731834SJed Brown loc = 1; 115d5731834SJed Brown while ((chld = MinChild(h, loc)) && Value(h, loc) > Value(h, chld)) { 116d5731834SJed Brown Swap(h, loc, chld); 117d5731834SJed Brown loc = chld; 118d5731834SJed Brown } 119d5731834SJed Brown PetscFunctionReturn(0); 120d5731834SJed Brown } 121d5731834SJed Brown 1229371c9d4SSatish Balay PetscErrorCode PetscHeapPeek(PetscHeap h, PetscInt *id, PetscInt *val) { 123d5731834SJed Brown PetscFunctionBegin; 124d5731834SJed Brown if (h->end == 1) { 125d5731834SJed Brown *id = h->base[0].id; 126d5731834SJed Brown *val = h->base[0].value; 127d5731834SJed Brown PetscFunctionReturn(0); 128d5731834SJed Brown } 129d5731834SJed Brown 130d5731834SJed Brown *id = h->base[1].id; 131d5731834SJed Brown *val = h->base[1].value; 132d5731834SJed Brown PetscFunctionReturn(0); 133d5731834SJed Brown } 134d5731834SJed Brown 1359371c9d4SSatish Balay PetscErrorCode PetscHeapStash(PetscHeap h, PetscInt id, PetscInt val) { 136d5731834SJed Brown PetscInt loc; 137d5731834SJed Brown 138d5731834SJed Brown PetscFunctionBegin; 139d5731834SJed Brown loc = --h->stash; 140d5731834SJed Brown h->base[loc].id = id; 141d5731834SJed Brown h->base[loc].value = val; 142d5731834SJed Brown PetscFunctionReturn(0); 143d5731834SJed Brown } 144d5731834SJed Brown 1459371c9d4SSatish Balay PetscErrorCode PetscHeapUnstash(PetscHeap h) { 146d5731834SJed Brown PetscFunctionBegin; 147d5731834SJed Brown while (h->stash < h->alloc) { 148d5731834SJed Brown PetscInt id = Id(h, h->stash), value = Value(h, h->stash); 149d5731834SJed Brown h->stash++; 1509566063dSJacob Faibussowitsch PetscCall(PetscHeapAdd(h, id, value)); 151d5731834SJed Brown } 152d5731834SJed Brown PetscFunctionReturn(0); 153d5731834SJed Brown } 154d5731834SJed Brown 1559371c9d4SSatish Balay PetscErrorCode PetscHeapDestroy(PetscHeap *heap) { 156d5731834SJed Brown PetscFunctionBegin; 1579566063dSJacob Faibussowitsch PetscCall(PetscFree((*heap)->base)); 1589566063dSJacob Faibussowitsch PetscCall(PetscFree(*heap)); 159d5731834SJed Brown PetscFunctionReturn(0); 160d5731834SJed Brown } 161d5731834SJed Brown 1629371c9d4SSatish Balay PetscErrorCode PetscHeapView(PetscHeap h, PetscViewer viewer) { 163d5731834SJed Brown PetscBool iascii; 164d5731834SJed Brown 165d5731834SJed Brown PetscFunctionBegin; 166*48a46eb9SPierre Jolivet if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PETSC_COMM_SELF, &viewer)); 167d5731834SJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1689566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 169d5731834SJed Brown if (iascii) { 1709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Heap size %" PetscInt_FMT " with %" PetscInt_FMT " stashed\n", h->end - 1, h->alloc - h->stash)); 1719566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Heap in (id,value) pairs\n")); 1729566063dSJacob Faibussowitsch PetscCall(PetscIntView(2 * (h->end - 1), (const PetscInt *)(h->base + 1), viewer)); 1739566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Stash in (id,value) pairs\n")); 1749566063dSJacob Faibussowitsch PetscCall(PetscIntView(2 * (h->alloc - h->stash), (const PetscInt *)(h->base + h->stash), viewer)); 175d5731834SJed Brown } 176d5731834SJed Brown PetscFunctionReturn(0); 177d5731834SJed Brown } 178