xref: /petsc/src/mat/utils/pheap.c (revision a6dfd86ebdf75fa024070af26d51b62fd16650a3)
1d5731834SJed Brown #include <../src/mat/utils/petscheap.h>
2d5731834SJed Brown 
3d5731834SJed Brown typedef struct {
4d5731834SJed Brown   PetscInt id;
5d5731834SJed Brown   PetscInt value;
6d5731834SJed Brown } HeapNode;
7d5731834SJed Brown 
8d5731834SJed Brown struct _PetscHeap {
9d5731834SJed Brown   PetscInt end;                 /* one past the last item */
10d5731834SJed Brown   PetscInt alloc;               /* length of array */
11d5731834SJed Brown   PetscInt stash;               /* stash grows down, this points to last item */
12d5731834SJed Brown   HeapNode *base;
13d5731834SJed Brown };
14d5731834SJed Brown 
1544ee04a4SJed Brown /*
1644ee04a4SJed Brown  * The arity of the heap can be changed via the parameter B below. Consider the B=2 (arity=4 case below)
1744ee04a4SJed Brown  *
1844ee04a4SJed Brown  * [00 (sentinel); 01 (min node); 10 (unused); 11 (unused); 0100 (first child); 0101; 0110; 0111; ...]
1944ee04a4SJed Brown  *
2044ee04a4SJed Brown  * Slots 10 and 11 are referred to as the "hole" below in the implementation.
2144ee04a4SJed Brown  */
2244ee04a4SJed Brown 
2344ee04a4SJed Brown #define B 1                     /* log2(ARITY) */
2444ee04a4SJed Brown #define ARITY (1 << B)          /* tree branching factor */
25*a6dfd86eSKarl Rupp PETSC_STATIC_INLINE PetscInt Parent(PetscInt loc)
26*a6dfd86eSKarl Rupp {
2744ee04a4SJed Brown   PetscInt p = loc >> B;
2844ee04a4SJed Brown   if (p < ARITY) return (PetscInt)(loc != 1);             /* Parent(1) is 0, otherwise fix entries ending up in the hole */
2944ee04a4SJed Brown   return p;
3044ee04a4SJed Brown }
31d5731834SJed Brown #define Value(h,loc) ((h)->base[loc].value)
32d5731834SJed Brown #define Id(h,loc)  ((h)->base[loc].id)
33d5731834SJed Brown 
34*a6dfd86eSKarl Rupp PETSC_STATIC_INLINE void Swap(PetscHeap h,PetscInt loc,PetscInt loc2)
35*a6dfd86eSKarl Rupp {
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 }
44*a6dfd86eSKarl Rupp PETSC_STATIC_INLINE PetscInt MinChild(PetscHeap h,PetscInt loc)
45*a6dfd86eSKarl Rupp {
4644ee04a4SJed Brown   PetscInt min,chld,left,right;
4744ee04a4SJed Brown   left = loc << B;
4844ee04a4SJed Brown   right = PetscMin(left+ARITY-1,h->end-1);
4944ee04a4SJed Brown   chld = 0;
5044ee04a4SJed Brown   min = PETSC_MAX_INT;
5144ee04a4SJed Brown   for ( ; left <= right; left++) {
5244ee04a4SJed Brown     PetscInt val = Value(h,left);
5344ee04a4SJed Brown     if (val < min) {
5444ee04a4SJed Brown       min = val;
5544ee04a4SJed Brown       chld = left;
5644ee04a4SJed Brown     }
5744ee04a4SJed Brown   }
5844ee04a4SJed Brown   return chld;
59d5731834SJed Brown }
60d5731834SJed Brown 
61d5731834SJed Brown #undef __FUNCT__
62d5731834SJed Brown #define __FUNCT__ "PetscHeapCreate"
63d5731834SJed Brown PetscErrorCode PetscHeapCreate(PetscInt maxsize,PetscHeap *heap)
64d5731834SJed Brown {
65d5731834SJed Brown   PetscErrorCode ierr;
66d5731834SJed Brown   PetscHeap h;
67d5731834SJed Brown 
68d5731834SJed Brown   PetscFunctionBegin;
69d5731834SJed Brown   *heap = PETSC_NULL;
708caf3d72SBarry Smith   ierr = PetscMalloc(sizeof(*h),&h);CHKERRQ(ierr);
71d5731834SJed Brown   h->end = 1;
7244ee04a4SJed Brown   h->alloc = maxsize+ARITY;     /* We waste all but one slot (loc=1) in the first ARITY slots */
73d5731834SJed Brown   h->stash = h->alloc;
7444ee04a4SJed Brown   ierr = PetscMalloc(h->alloc*sizeof(HeapNode),&h->base);CHKERRQ(ierr);
7544ee04a4SJed Brown   ierr = PetscMemzero(h->base,h->alloc*sizeof(HeapNode));CHKERRQ(ierr);
76d5731834SJed Brown   h->base[0].id    = -1;
77d5731834SJed Brown   h->base[0].value = PETSC_MIN_INT;
78d5731834SJed Brown   *heap = h;
79d5731834SJed Brown   PetscFunctionReturn(0);
80d5731834SJed Brown }
81d5731834SJed Brown 
82d5731834SJed Brown #undef __FUNCT__
83d5731834SJed Brown #define __FUNCT__ "PetscHeapAdd"
84d5731834SJed Brown PetscErrorCode PetscHeapAdd(PetscHeap h,PetscInt id,PetscInt val)
85d5731834SJed Brown {
8644ee04a4SJed Brown   PetscInt loc,par;
87d5731834SJed Brown 
88d5731834SJed Brown   PetscFunctionBegin;
8944ee04a4SJed Brown   if (1 < h->end && h->end < ARITY) h->end = ARITY;
90d5731834SJed Brown   loc = h->end++;
91d5731834SJed 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));
92d5731834SJed Brown   h->base[loc].id    = id;
93d5731834SJed Brown   h->base[loc].value = val;
94d5731834SJed Brown 
95d5731834SJed Brown   /* move up until heap condition is satisfied */
9644ee04a4SJed Brown   while (par = Parent(loc), Value(h,par) > val) {
9744ee04a4SJed Brown     Swap(h,loc,par);
9844ee04a4SJed Brown     loc = par;
99d5731834SJed Brown   }
100d5731834SJed Brown   PetscFunctionReturn(0);
101d5731834SJed Brown }
102d5731834SJed Brown 
103d5731834SJed Brown #undef __FUNCT__
104d5731834SJed Brown #define __FUNCT__ "PetscHeapPop"
105d5731834SJed Brown PetscErrorCode PetscHeapPop(PetscHeap h,PetscInt *id,PetscInt *val)
106d5731834SJed Brown {
107d5731834SJed Brown   PetscInt loc,chld;
108d5731834SJed Brown 
109d5731834SJed Brown   PetscFunctionBegin;
110d5731834SJed Brown   if (h->end == 1) {
111d5731834SJed Brown     *id = h->base[0].id;
112d5731834SJed Brown     *val = h->base[0].value;
113d5731834SJed Brown     PetscFunctionReturn(0);
114d5731834SJed Brown   }
115d5731834SJed Brown 
116d5731834SJed Brown   *id = h->base[1].id;
117d5731834SJed Brown   *val = h->base[1].value;
118d5731834SJed Brown 
119d5731834SJed Brown   /* rotate last entry into first position */
120d5731834SJed Brown   loc = --h->end;
12144ee04a4SJed Brown   if (h->end == ARITY) h->end = 2; /* Skip over hole */
122d5731834SJed Brown   h->base[1].id   = Id(h,loc);
123d5731834SJed Brown   h->base[1].value = Value(h,loc);
124d5731834SJed Brown 
125d5731834SJed Brown   /* move down until min heap condition is satisfied */
126d5731834SJed Brown   loc = 1;
127d5731834SJed Brown   while ((chld = MinChild(h,loc)) && Value(h,loc) > Value(h,chld)) {
128d5731834SJed Brown     Swap(h,loc,chld);
129d5731834SJed Brown     loc = chld;
130d5731834SJed Brown   }
131d5731834SJed Brown   PetscFunctionReturn(0);
132d5731834SJed Brown }
133d5731834SJed Brown 
134d5731834SJed Brown #undef __FUNCT__
135d5731834SJed Brown #define __FUNCT__ "PetscHeapPeek"
136d5731834SJed Brown PetscErrorCode PetscHeapPeek(PetscHeap h,PetscInt *id,PetscInt *val)
137d5731834SJed Brown {
138d5731834SJed Brown   PetscFunctionBegin;
139d5731834SJed Brown   if (h->end == 1) {
140d5731834SJed Brown     *id = h->base[0].id;
141d5731834SJed Brown     *val = h->base[0].value;
142d5731834SJed Brown     PetscFunctionReturn(0);
143d5731834SJed Brown   }
144d5731834SJed Brown 
145d5731834SJed Brown   *id = h->base[1].id;
146d5731834SJed Brown   *val = h->base[1].value;
147d5731834SJed Brown   PetscFunctionReturn(0);
148d5731834SJed Brown }
149d5731834SJed Brown 
150d5731834SJed Brown #undef __FUNCT__
151d5731834SJed Brown #define __FUNCT__ "PetscHeapStash"
152d5731834SJed Brown PetscErrorCode PetscHeapStash(PetscHeap h,PetscInt id,PetscInt val)
153d5731834SJed Brown {
154d5731834SJed Brown   PetscInt loc;
155d5731834SJed Brown 
156d5731834SJed Brown   PetscFunctionBegin;
157d5731834SJed Brown   loc = --h->stash;
158d5731834SJed Brown   h->base[loc].id = id;
159d5731834SJed Brown   h->base[loc].value = val;
160d5731834SJed Brown   PetscFunctionReturn(0);
161d5731834SJed Brown }
162d5731834SJed Brown 
163d5731834SJed Brown #undef __FUNCT__
164d5731834SJed Brown #define __FUNCT__ "PetscHeapUnstash"
165d5731834SJed Brown PetscErrorCode PetscHeapUnstash(PetscHeap h)
166d5731834SJed Brown {
167d5731834SJed Brown   PetscErrorCode ierr;
168d5731834SJed Brown 
169d5731834SJed Brown   PetscFunctionBegin;
170d5731834SJed Brown   while (h->stash < h->alloc) {
171d5731834SJed Brown     PetscInt id = Id(h,h->stash),value = Value(h,h->stash);
172d5731834SJed Brown     h->stash++;
173d5731834SJed Brown     ierr = PetscHeapAdd(h,id,value);CHKERRQ(ierr);
174d5731834SJed Brown   }
175d5731834SJed Brown   PetscFunctionReturn(0);
176d5731834SJed Brown }
177d5731834SJed Brown 
178d5731834SJed Brown #undef __FUNCT__
179d5731834SJed Brown #define __FUNCT__ "PetscHeapDestroy"
180d5731834SJed Brown PetscErrorCode PetscHeapDestroy(PetscHeap *heap)
181d5731834SJed Brown {
182d5731834SJed Brown   PetscErrorCode ierr;
183d5731834SJed Brown 
184d5731834SJed Brown   PetscFunctionBegin;
185d5731834SJed Brown   ierr = PetscFree((*heap)->base);CHKERRQ(ierr);
186d5731834SJed Brown   ierr = PetscFree(*heap);CHKERRQ(ierr);
187d5731834SJed Brown   PetscFunctionReturn(0);
188d5731834SJed Brown }
189d5731834SJed Brown 
190d5731834SJed Brown #undef __FUNCT__
191d5731834SJed Brown #define __FUNCT__ "PetscHeapView"
192d5731834SJed Brown PetscErrorCode PetscHeapView(PetscHeap h,PetscViewer viewer)
193d5731834SJed Brown {
194d5731834SJed Brown   PetscErrorCode ierr;
195d5731834SJed Brown   PetscBool iascii;
196d5731834SJed Brown 
197d5731834SJed Brown   PetscFunctionBegin;
198d5731834SJed Brown   if (!viewer) {
199d5731834SJed Brown     ierr = PetscViewerASCIIGetStdout(PETSC_COMM_SELF,&viewer);CHKERRQ(ierr);
200d5731834SJed Brown   }
201d5731834SJed Brown   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
202d5731834SJed Brown   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
203d5731834SJed Brown   if (iascii) {
204d5731834SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"Heap size %D with %D stashed\n",h->end-1,h->alloc-h->stash);CHKERRQ(ierr);
205d5731834SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"Heap in (id,value) pairs\n");CHKERRQ(ierr);
206d5731834SJed Brown     ierr = PetscIntView(2*(h->end-1),(const PetscInt*)(h->base+1),viewer);CHKERRQ(ierr);
207d5731834SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"Stash in (id,value) pairs\n");CHKERRQ(ierr);
208d5731834SJed Brown     ierr = PetscIntView(2*(h->alloc-h->stash),(const PetscInt*)(h->base+h->stash),viewer);CHKERRQ(ierr);
209d5731834SJed Brown   }
210d5731834SJed Brown   PetscFunctionReturn(0);
211d5731834SJed Brown }
212