1d5731834SJed Brown #include <../src/mat/utils/petscheap.h> 2afcb2eb5SJed Brown #include <petsc-private/petscimpl.h> 3*665c2dedSJed 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 */ 27a6dfd86eSKarl Rupp PETSC_STATIC_INLINE PetscInt Parent(PetscInt loc) 28a6dfd86eSKarl Rupp { 2944ee04a4SJed Brown PetscInt p = loc >> B; 3044ee04a4SJed Brown if (p < ARITY) return (PetscInt)(loc != 1); /* Parent(1) is 0, otherwise fix entries ending up in the hole */ 3144ee04a4SJed Brown return p; 3244ee04a4SJed Brown } 33d5731834SJed Brown #define Value(h,loc) ((h)->base[loc].value) 34d5731834SJed Brown #define Id(h,loc) ((h)->base[loc].id) 35d5731834SJed Brown 36a6dfd86eSKarl Rupp PETSC_STATIC_INLINE void Swap(PetscHeap h,PetscInt loc,PetscInt loc2) 37a6dfd86eSKarl Rupp { 38d5731834SJed Brown PetscInt id,val; 39d5731834SJed Brown id = Id(h,loc); 40d5731834SJed Brown val = Value(h,loc); 41d5731834SJed Brown h->base[loc].id = Id(h,loc2); 42d5731834SJed Brown h->base[loc].value = Value(h,loc2); 43d5731834SJed Brown h->base[loc2].id = id; 44d5731834SJed Brown h->base[loc2].value = val; 45d5731834SJed Brown } 46a6dfd86eSKarl Rupp PETSC_STATIC_INLINE PetscInt MinChild(PetscHeap h,PetscInt loc) 47a6dfd86eSKarl Rupp { 4844ee04a4SJed Brown PetscInt min,chld,left,right; 4944ee04a4SJed Brown left = loc << B; 5044ee04a4SJed Brown right = PetscMin(left+ARITY-1,h->end-1); 5144ee04a4SJed Brown chld = 0; 5244ee04a4SJed Brown min = PETSC_MAX_INT; 5344ee04a4SJed Brown for (; left <= right; left++) { 5444ee04a4SJed Brown PetscInt val = Value(h,left); 5544ee04a4SJed Brown if (val < min) { 5644ee04a4SJed Brown min = val; 5744ee04a4SJed Brown chld = left; 5844ee04a4SJed Brown } 5944ee04a4SJed Brown } 6044ee04a4SJed Brown return chld; 61d5731834SJed Brown } 62d5731834SJed Brown 63d5731834SJed Brown #undef __FUNCT__ 64d5731834SJed Brown #define __FUNCT__ "PetscHeapCreate" 65d5731834SJed Brown PetscErrorCode PetscHeapCreate(PetscInt maxsize,PetscHeap *heap) 66d5731834SJed Brown { 67d5731834SJed Brown PetscErrorCode ierr; 68d5731834SJed Brown PetscHeap h; 69d5731834SJed Brown 70d5731834SJed Brown PetscFunctionBegin; 710298fd71SBarry Smith *heap = NULL; 728caf3d72SBarry Smith ierr = PetscMalloc(sizeof(*h),&h);CHKERRQ(ierr); 73d5731834SJed Brown h->end = 1; 7444ee04a4SJed Brown h->alloc = maxsize+ARITY; /* We waste all but one slot (loc=1) in the first ARITY slots */ 75d5731834SJed Brown h->stash = h->alloc; 7644ee04a4SJed Brown ierr = PetscMalloc(h->alloc*sizeof(HeapNode),&h->base);CHKERRQ(ierr); 7744ee04a4SJed Brown ierr = PetscMemzero(h->base,h->alloc*sizeof(HeapNode));CHKERRQ(ierr); 78d5731834SJed Brown h->base[0].id = -1; 79d5731834SJed Brown h->base[0].value = PETSC_MIN_INT; 80d5731834SJed Brown *heap = h; 81d5731834SJed Brown PetscFunctionReturn(0); 82d5731834SJed Brown } 83d5731834SJed Brown 84d5731834SJed Brown #undef __FUNCT__ 85d5731834SJed Brown #define __FUNCT__ "PetscHeapAdd" 86d5731834SJed Brown PetscErrorCode PetscHeapAdd(PetscHeap h,PetscInt id,PetscInt val) 87d5731834SJed Brown { 8844ee04a4SJed Brown PetscInt loc,par; 89d5731834SJed Brown 90d5731834SJed Brown PetscFunctionBegin; 9144ee04a4SJed Brown if (1 < h->end && h->end < ARITY) h->end = ARITY; 92d5731834SJed Brown loc = h->end++; 93d5731834SJed Brown if (h->end > h->stash) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Addition would exceed allocation %D (%D stashed)",h->alloc,(h->alloc-h->stash)); 94d5731834SJed Brown h->base[loc].id = id; 95d5731834SJed Brown h->base[loc].value = val; 96d5731834SJed Brown 97d5731834SJed Brown /* move up until heap condition is satisfied */ 9844ee04a4SJed Brown while (par = Parent(loc), Value(h,par) > val) { 9944ee04a4SJed Brown Swap(h,loc,par); 10044ee04a4SJed Brown loc = par; 101d5731834SJed Brown } 102d5731834SJed Brown PetscFunctionReturn(0); 103d5731834SJed Brown } 104d5731834SJed Brown 105d5731834SJed Brown #undef __FUNCT__ 106d5731834SJed Brown #define __FUNCT__ "PetscHeapPop" 107d5731834SJed Brown PetscErrorCode PetscHeapPop(PetscHeap h,PetscInt *id,PetscInt *val) 108d5731834SJed Brown { 109d5731834SJed Brown PetscInt loc,chld; 110d5731834SJed Brown 111d5731834SJed Brown PetscFunctionBegin; 112d5731834SJed Brown if (h->end == 1) { 113d5731834SJed Brown *id = h->base[0].id; 114d5731834SJed Brown *val = h->base[0].value; 115d5731834SJed Brown PetscFunctionReturn(0); 116d5731834SJed Brown } 117d5731834SJed Brown 118d5731834SJed Brown *id = h->base[1].id; 119d5731834SJed Brown *val = h->base[1].value; 120d5731834SJed Brown 121d5731834SJed Brown /* rotate last entry into first position */ 122d5731834SJed Brown loc = --h->end; 12344ee04a4SJed Brown if (h->end == ARITY) h->end = 2; /* Skip over hole */ 124d5731834SJed Brown h->base[1].id = Id(h,loc); 125d5731834SJed Brown h->base[1].value = Value(h,loc); 126d5731834SJed Brown 127d5731834SJed Brown /* move down until min heap condition is satisfied */ 128d5731834SJed Brown loc = 1; 129d5731834SJed Brown while ((chld = MinChild(h,loc)) && Value(h,loc) > Value(h,chld)) { 130d5731834SJed Brown Swap(h,loc,chld); 131d5731834SJed Brown loc = chld; 132d5731834SJed Brown } 133d5731834SJed Brown PetscFunctionReturn(0); 134d5731834SJed Brown } 135d5731834SJed Brown 136d5731834SJed Brown #undef __FUNCT__ 137d5731834SJed Brown #define __FUNCT__ "PetscHeapPeek" 138d5731834SJed Brown PetscErrorCode PetscHeapPeek(PetscHeap h,PetscInt *id,PetscInt *val) 139d5731834SJed Brown { 140d5731834SJed Brown PetscFunctionBegin; 141d5731834SJed Brown if (h->end == 1) { 142d5731834SJed Brown *id = h->base[0].id; 143d5731834SJed Brown *val = h->base[0].value; 144d5731834SJed Brown PetscFunctionReturn(0); 145d5731834SJed Brown } 146d5731834SJed Brown 147d5731834SJed Brown *id = h->base[1].id; 148d5731834SJed Brown *val = h->base[1].value; 149d5731834SJed Brown PetscFunctionReturn(0); 150d5731834SJed Brown } 151d5731834SJed Brown 152d5731834SJed Brown #undef __FUNCT__ 153d5731834SJed Brown #define __FUNCT__ "PetscHeapStash" 154d5731834SJed Brown PetscErrorCode PetscHeapStash(PetscHeap h,PetscInt id,PetscInt val) 155d5731834SJed Brown { 156d5731834SJed Brown PetscInt loc; 157d5731834SJed Brown 158d5731834SJed Brown PetscFunctionBegin; 159d5731834SJed Brown loc = --h->stash; 160d5731834SJed Brown h->base[loc].id = id; 161d5731834SJed Brown h->base[loc].value = val; 162d5731834SJed Brown PetscFunctionReturn(0); 163d5731834SJed Brown } 164d5731834SJed Brown 165d5731834SJed Brown #undef __FUNCT__ 166d5731834SJed Brown #define __FUNCT__ "PetscHeapUnstash" 167d5731834SJed Brown PetscErrorCode PetscHeapUnstash(PetscHeap h) 168d5731834SJed Brown { 169d5731834SJed Brown PetscErrorCode ierr; 170d5731834SJed Brown 171d5731834SJed Brown PetscFunctionBegin; 172d5731834SJed Brown while (h->stash < h->alloc) { 173d5731834SJed Brown PetscInt id = Id(h,h->stash),value = Value(h,h->stash); 174d5731834SJed Brown h->stash++; 175d5731834SJed Brown ierr = PetscHeapAdd(h,id,value);CHKERRQ(ierr); 176d5731834SJed Brown } 177d5731834SJed Brown PetscFunctionReturn(0); 178d5731834SJed Brown } 179d5731834SJed Brown 180d5731834SJed Brown #undef __FUNCT__ 181d5731834SJed Brown #define __FUNCT__ "PetscHeapDestroy" 182d5731834SJed Brown PetscErrorCode PetscHeapDestroy(PetscHeap *heap) 183d5731834SJed Brown { 184d5731834SJed Brown PetscErrorCode ierr; 185d5731834SJed Brown 186d5731834SJed Brown PetscFunctionBegin; 187d5731834SJed Brown ierr = PetscFree((*heap)->base);CHKERRQ(ierr); 188d5731834SJed Brown ierr = PetscFree(*heap);CHKERRQ(ierr); 189d5731834SJed Brown PetscFunctionReturn(0); 190d5731834SJed Brown } 191d5731834SJed Brown 192d5731834SJed Brown #undef __FUNCT__ 193d5731834SJed Brown #define __FUNCT__ "PetscHeapView" 194d5731834SJed Brown PetscErrorCode PetscHeapView(PetscHeap h,PetscViewer viewer) 195d5731834SJed Brown { 196d5731834SJed Brown PetscErrorCode ierr; 197d5731834SJed Brown PetscBool iascii; 198d5731834SJed Brown 199d5731834SJed Brown PetscFunctionBegin; 200d5731834SJed Brown if (!viewer) { 201d5731834SJed Brown ierr = PetscViewerASCIIGetStdout(PETSC_COMM_SELF,&viewer);CHKERRQ(ierr); 202d5731834SJed Brown } 203d5731834SJed Brown PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 204d5731834SJed Brown ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 205d5731834SJed Brown if (iascii) { 206d5731834SJed Brown ierr = PetscViewerASCIIPrintf(viewer,"Heap size %D with %D stashed\n",h->end-1,h->alloc-h->stash);CHKERRQ(ierr); 207d5731834SJed Brown ierr = PetscViewerASCIIPrintf(viewer,"Heap in (id,value) pairs\n");CHKERRQ(ierr); 208d5731834SJed Brown ierr = PetscIntView(2*(h->end-1),(const PetscInt*)(h->base+1),viewer);CHKERRQ(ierr); 209d5731834SJed Brown ierr = PetscViewerASCIIPrintf(viewer,"Stash in (id,value) pairs\n");CHKERRQ(ierr); 210d5731834SJed Brown ierr = PetscIntView(2*(h->alloc-h->stash),(const PetscInt*)(h->base+h->stash),viewer);CHKERRQ(ierr); 211d5731834SJed Brown } 212d5731834SJed Brown PetscFunctionReturn(0); 213d5731834SJed Brown } 214