xref: /petsc/src/mat/utils/pheap.c (revision 08401ef684002a709c6d3db98a0c9f54a8bcf1ec)
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 */
279fbee547SJacob Faibussowitsch 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 
369fbee547SJacob Faibussowitsch 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 }
469fbee547SJacob Faibussowitsch 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 PetscErrorCode PetscHeapCreate(PetscInt maxsize,PetscHeap *heap)
64d5731834SJed Brown {
65d5731834SJed Brown   PetscHeap      h;
66d5731834SJed Brown 
67d5731834SJed Brown   PetscFunctionBegin;
680298fd71SBarry Smith   *heap            = NULL;
699566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(1,&h));
70d5731834SJed Brown   h->end           = 1;
7144ee04a4SJed Brown   h->alloc         = maxsize+ARITY; /* We waste all but one slot (loc=1) in the first ARITY slots */
72d5731834SJed Brown   h->stash         = h->alloc;
739566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(h->alloc,&h->base));
74d5731834SJed Brown   h->base[0].id    = -1;
75d5731834SJed Brown   h->base[0].value = PETSC_MIN_INT;
76d5731834SJed Brown   *heap            = h;
77d5731834SJed Brown   PetscFunctionReturn(0);
78d5731834SJed Brown }
79d5731834SJed Brown 
80d5731834SJed Brown PetscErrorCode PetscHeapAdd(PetscHeap h,PetscInt id,PetscInt val)
81d5731834SJed Brown {
8244ee04a4SJed Brown   PetscInt loc,par;
83d5731834SJed Brown 
84d5731834SJed Brown   PetscFunctionBegin;
8544ee04a4SJed Brown   if (1 < h->end && h->end < ARITY) h->end = ARITY;
86d5731834SJed Brown   loc = h->end++;
87*08401ef6SPierre 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));
88d5731834SJed Brown   h->base[loc].id    = id;
89d5731834SJed Brown   h->base[loc].value = val;
90d5731834SJed Brown 
91d5731834SJed Brown   /* move up until heap condition is satisfied */
92527e7439SSatish Balay   while ((void)(par = Parent(loc)), Value(h,par) > val) {
9344ee04a4SJed Brown     Swap(h,loc,par);
9444ee04a4SJed Brown     loc = par;
95d5731834SJed Brown   }
96d5731834SJed Brown   PetscFunctionReturn(0);
97d5731834SJed Brown }
98d5731834SJed Brown 
99d5731834SJed Brown PetscErrorCode PetscHeapPop(PetscHeap h,PetscInt *id,PetscInt *val)
100d5731834SJed Brown {
101d5731834SJed Brown   PetscInt loc,chld;
102d5731834SJed Brown 
103d5731834SJed Brown   PetscFunctionBegin;
104d5731834SJed Brown   if (h->end == 1) {
105d5731834SJed Brown     *id  = h->base[0].id;
106d5731834SJed Brown     *val = h->base[0].value;
107d5731834SJed Brown     PetscFunctionReturn(0);
108d5731834SJed Brown   }
109d5731834SJed Brown 
110d5731834SJed Brown   *id  = h->base[1].id;
111d5731834SJed Brown   *val = h->base[1].value;
112d5731834SJed Brown 
113d5731834SJed Brown   /* rotate last entry into first position */
114d5731834SJed Brown   loc = --h->end;
11544ee04a4SJed Brown   if (h->end == ARITY) h->end = 2; /* Skip over hole */
116d5731834SJed Brown   h->base[1].id    = Id(h,loc);
117d5731834SJed Brown   h->base[1].value = Value(h,loc);
118d5731834SJed Brown 
119d5731834SJed Brown   /* move down until min heap condition is satisfied */
120d5731834SJed Brown   loc = 1;
121d5731834SJed Brown   while ((chld = MinChild(h,loc)) && Value(h,loc) > Value(h,chld)) {
122d5731834SJed Brown     Swap(h,loc,chld);
123d5731834SJed Brown     loc = chld;
124d5731834SJed Brown   }
125d5731834SJed Brown   PetscFunctionReturn(0);
126d5731834SJed Brown }
127d5731834SJed Brown 
128d5731834SJed Brown PetscErrorCode PetscHeapPeek(PetscHeap h,PetscInt *id,PetscInt *val)
129d5731834SJed Brown {
130d5731834SJed Brown   PetscFunctionBegin;
131d5731834SJed Brown   if (h->end == 1) {
132d5731834SJed Brown     *id  = h->base[0].id;
133d5731834SJed Brown     *val = h->base[0].value;
134d5731834SJed Brown     PetscFunctionReturn(0);
135d5731834SJed Brown   }
136d5731834SJed Brown 
137d5731834SJed Brown   *id  = h->base[1].id;
138d5731834SJed Brown   *val = h->base[1].value;
139d5731834SJed Brown   PetscFunctionReturn(0);
140d5731834SJed Brown }
141d5731834SJed Brown 
142d5731834SJed Brown PetscErrorCode PetscHeapStash(PetscHeap h,PetscInt id,PetscInt val)
143d5731834SJed Brown {
144d5731834SJed Brown   PetscInt loc;
145d5731834SJed Brown 
146d5731834SJed Brown   PetscFunctionBegin;
147d5731834SJed Brown   loc                = --h->stash;
148d5731834SJed Brown   h->base[loc].id    = id;
149d5731834SJed Brown   h->base[loc].value = val;
150d5731834SJed Brown   PetscFunctionReturn(0);
151d5731834SJed Brown }
152d5731834SJed Brown 
153d5731834SJed Brown PetscErrorCode PetscHeapUnstash(PetscHeap h)
154d5731834SJed Brown {
155d5731834SJed Brown   PetscFunctionBegin;
156d5731834SJed Brown   while (h->stash < h->alloc) {
157d5731834SJed Brown     PetscInt id = Id(h,h->stash),value = Value(h,h->stash);
158d5731834SJed Brown     h->stash++;
1599566063dSJacob Faibussowitsch     PetscCall(PetscHeapAdd(h,id,value));
160d5731834SJed Brown   }
161d5731834SJed Brown   PetscFunctionReturn(0);
162d5731834SJed Brown }
163d5731834SJed Brown 
164d5731834SJed Brown PetscErrorCode PetscHeapDestroy(PetscHeap *heap)
165d5731834SJed Brown {
166d5731834SJed Brown   PetscFunctionBegin;
1679566063dSJacob Faibussowitsch   PetscCall(PetscFree((*heap)->base));
1689566063dSJacob Faibussowitsch   PetscCall(PetscFree(*heap));
169d5731834SJed Brown   PetscFunctionReturn(0);
170d5731834SJed Brown }
171d5731834SJed Brown 
172d5731834SJed Brown PetscErrorCode PetscHeapView(PetscHeap h,PetscViewer viewer)
173d5731834SJed Brown {
174d5731834SJed Brown   PetscBool      iascii;
175d5731834SJed Brown 
176d5731834SJed Brown   PetscFunctionBegin;
177d5731834SJed Brown   if (!viewer) {
1789566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIGetStdout(PETSC_COMM_SELF,&viewer));
179d5731834SJed Brown   }
180d5731834SJed Brown   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
1819566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
182d5731834SJed Brown   if (iascii) {
1839566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"Heap size %" PetscInt_FMT " with %" PetscInt_FMT " stashed\n",h->end-1,h->alloc-h->stash));
1849566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"Heap in (id,value) pairs\n"));
1859566063dSJacob Faibussowitsch     PetscCall(PetscIntView(2*(h->end-1),(const PetscInt*)(h->base+1),viewer));
1869566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"Stash in (id,value) pairs\n"));
1879566063dSJacob Faibussowitsch     PetscCall(PetscIntView(2*(h->alloc-h->stash),(const PetscInt*)(h->base+h->stash),viewer));
188d5731834SJed Brown   }
189d5731834SJed Brown   PetscFunctionReturn(0);
190d5731834SJed Brown }
191