xref: /petsc/src/mat/utils/pheap.c (revision d573183411f9185c3ea0e9c97c412ad2747a5528)
1*d5731834SJed Brown #include <../src/mat/utils/petscheap.h>
2*d5731834SJed Brown 
3*d5731834SJed Brown typedef struct {
4*d5731834SJed Brown   PetscInt id;
5*d5731834SJed Brown   PetscInt value;
6*d5731834SJed Brown } HeapNode;
7*d5731834SJed Brown 
8*d5731834SJed Brown struct _PetscHeap {
9*d5731834SJed Brown   PetscInt end;                 /* one past the last item */
10*d5731834SJed Brown   PetscInt alloc;               /* length of array */
11*d5731834SJed Brown   PetscInt stash;               /* stash grows down, this points to last item */
12*d5731834SJed Brown   HeapNode *base;
13*d5731834SJed Brown };
14*d5731834SJed Brown 
15*d5731834SJed Brown #define Parent(loc) ((loc) >> 1)
16*d5731834SJed Brown #define Left(loc) ((loc) << 1)
17*d5731834SJed Brown #define Right(loc) (Left((loc))+1)
18*d5731834SJed Brown #define Value(h,loc) ((h)->base[loc].value)
19*d5731834SJed Brown #define Id(h,loc)  ((h)->base[loc].id)
20*d5731834SJed Brown 
21*d5731834SJed Brown PETSC_STATIC_INLINE void Swap(PetscHeap h,PetscInt loc,PetscInt loc2) {
22*d5731834SJed Brown   PetscInt id,val;
23*d5731834SJed Brown   id = Id(h,loc);
24*d5731834SJed Brown   val = Value(h,loc);
25*d5731834SJed Brown   h->base[loc].id = Id(h,loc2);
26*d5731834SJed Brown   h->base[loc].value = Value(h,loc2);
27*d5731834SJed Brown   h->base[loc2].id = id;
28*d5731834SJed Brown   h->base[loc2].value = val;
29*d5731834SJed Brown }
30*d5731834SJed Brown PETSC_STATIC_INLINE PetscInt MinChild(PetscHeap h,PetscInt loc) {
31*d5731834SJed Brown   if (Left(loc) >= h->end) return 0;
32*d5731834SJed Brown   if (Right(loc) >= h->end) return Left(loc);
33*d5731834SJed Brown   return Value(h,Left(loc)) <= Value(h,Right(loc)) ? Left(loc) : Right(loc);
34*d5731834SJed Brown }
35*d5731834SJed Brown 
36*d5731834SJed Brown #undef __FUNCT__
37*d5731834SJed Brown #define __FUNCT__ "PetscHeapCreate"
38*d5731834SJed Brown PetscErrorCode PetscHeapCreate(PetscInt maxsize,PetscHeap *heap)
39*d5731834SJed Brown {
40*d5731834SJed Brown   PetscErrorCode ierr;
41*d5731834SJed Brown   PetscHeap h;
42*d5731834SJed Brown 
43*d5731834SJed Brown   PetscFunctionBegin;
44*d5731834SJed Brown   *heap = PETSC_NULL;
45*d5731834SJed Brown   ierr = PetscMalloc(sizeof *h,&h);CHKERRQ(ierr);
46*d5731834SJed Brown   h->end = 1;
47*d5731834SJed Brown   h->alloc = maxsize+1;
48*d5731834SJed Brown   h->stash = h->alloc;
49*d5731834SJed Brown   ierr = PetscMalloc((maxsize+1)*sizeof(HeapNode),&h->base);CHKERRQ(ierr);
50*d5731834SJed Brown   h->base[0].id    = -1;
51*d5731834SJed Brown   h->base[0].value = PETSC_MIN_INT;
52*d5731834SJed Brown   *heap = h;
53*d5731834SJed Brown   PetscFunctionReturn(0);
54*d5731834SJed Brown }
55*d5731834SJed Brown 
56*d5731834SJed Brown #undef __FUNCT__
57*d5731834SJed Brown #define __FUNCT__ "PetscHeapAdd"
58*d5731834SJed Brown PetscErrorCode PetscHeapAdd(PetscHeap h,PetscInt id,PetscInt val)
59*d5731834SJed Brown {
60*d5731834SJed Brown   PetscInt loc;
61*d5731834SJed Brown 
62*d5731834SJed Brown   PetscFunctionBegin;
63*d5731834SJed Brown   loc = h->end++;
64*d5731834SJed 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));
65*d5731834SJed Brown   h->base[loc].id    = id;
66*d5731834SJed Brown   h->base[loc].value = val;
67*d5731834SJed Brown 
68*d5731834SJed Brown   /* move up until heap condition is satisfied */
69*d5731834SJed Brown   while (Value(h,Parent(loc)) > val) {
70*d5731834SJed Brown     Swap(h,loc,Parent(loc));
71*d5731834SJed Brown     loc = Parent(loc);
72*d5731834SJed Brown   }
73*d5731834SJed Brown   PetscFunctionReturn(0);
74*d5731834SJed Brown }
75*d5731834SJed Brown 
76*d5731834SJed Brown #undef __FUNCT__
77*d5731834SJed Brown #define __FUNCT__ "PetscHeapPop"
78*d5731834SJed Brown PetscErrorCode PetscHeapPop(PetscHeap h,PetscInt *id,PetscInt *val)
79*d5731834SJed Brown {
80*d5731834SJed Brown   PetscInt loc,chld;
81*d5731834SJed Brown 
82*d5731834SJed Brown   PetscFunctionBegin;
83*d5731834SJed Brown   if (h->end == 1) {
84*d5731834SJed Brown     *id = h->base[0].id;
85*d5731834SJed Brown     *val = h->base[0].value;
86*d5731834SJed Brown     PetscFunctionReturn(0);
87*d5731834SJed Brown   }
88*d5731834SJed Brown 
89*d5731834SJed Brown   *id = h->base[1].id;
90*d5731834SJed Brown   *val = h->base[1].value;
91*d5731834SJed Brown 
92*d5731834SJed Brown   /* rotate last entry into first position */
93*d5731834SJed Brown   loc = --h->end;
94*d5731834SJed Brown   h->base[1].id   = Id(h,loc);
95*d5731834SJed Brown   h->base[1].value = Value(h,loc);
96*d5731834SJed Brown 
97*d5731834SJed Brown   /* move down until min heap condition is satisfied */
98*d5731834SJed Brown   loc = 1;
99*d5731834SJed Brown   while ((chld = MinChild(h,loc)) && Value(h,loc) > Value(h,chld)) {
100*d5731834SJed Brown     Swap(h,loc,chld);
101*d5731834SJed Brown     loc = chld;
102*d5731834SJed Brown   }
103*d5731834SJed Brown   PetscFunctionReturn(0);
104*d5731834SJed Brown }
105*d5731834SJed Brown 
106*d5731834SJed Brown #undef __FUNCT__
107*d5731834SJed Brown #define __FUNCT__ "PetscHeapPeek"
108*d5731834SJed Brown PetscErrorCode PetscHeapPeek(PetscHeap h,PetscInt *id,PetscInt *val)
109*d5731834SJed Brown {
110*d5731834SJed Brown   PetscFunctionBegin;
111*d5731834SJed Brown   if (h->end == 1) {
112*d5731834SJed Brown     *id = h->base[0].id;
113*d5731834SJed Brown     *val = h->base[0].value;
114*d5731834SJed Brown     PetscFunctionReturn(0);
115*d5731834SJed Brown   }
116*d5731834SJed Brown 
117*d5731834SJed Brown   *id = h->base[1].id;
118*d5731834SJed Brown   *val = h->base[1].value;
119*d5731834SJed Brown   PetscFunctionReturn(0);
120*d5731834SJed Brown }
121*d5731834SJed Brown 
122*d5731834SJed Brown #undef __FUNCT__
123*d5731834SJed Brown #define __FUNCT__ "PetscHeapStash"
124*d5731834SJed Brown PetscErrorCode PetscHeapStash(PetscHeap h,PetscInt id,PetscInt val)
125*d5731834SJed Brown {
126*d5731834SJed Brown   PetscInt loc;
127*d5731834SJed Brown 
128*d5731834SJed Brown   PetscFunctionBegin;
129*d5731834SJed Brown   loc = --h->stash;
130*d5731834SJed Brown   h->base[loc].id = id;
131*d5731834SJed Brown   h->base[loc].value = val;
132*d5731834SJed Brown   PetscFunctionReturn(0);
133*d5731834SJed Brown }
134*d5731834SJed Brown 
135*d5731834SJed Brown #undef __FUNCT__
136*d5731834SJed Brown #define __FUNCT__ "PetscHeapUnstash"
137*d5731834SJed Brown PetscErrorCode PetscHeapUnstash(PetscHeap h)
138*d5731834SJed Brown {
139*d5731834SJed Brown   PetscErrorCode ierr;
140*d5731834SJed Brown 
141*d5731834SJed Brown   PetscFunctionBegin;
142*d5731834SJed Brown   while (h->stash < h->alloc) {
143*d5731834SJed Brown     PetscInt id = Id(h,h->stash),value = Value(h,h->stash);
144*d5731834SJed Brown     h->stash++;
145*d5731834SJed Brown     ierr = PetscHeapAdd(h,id,value);CHKERRQ(ierr);
146*d5731834SJed Brown   }
147*d5731834SJed Brown   PetscFunctionReturn(0);
148*d5731834SJed Brown }
149*d5731834SJed Brown 
150*d5731834SJed Brown #undef __FUNCT__
151*d5731834SJed Brown #define __FUNCT__ "PetscHeapDestroy"
152*d5731834SJed Brown PetscErrorCode PetscHeapDestroy(PetscHeap *heap)
153*d5731834SJed Brown {
154*d5731834SJed Brown   PetscErrorCode ierr;
155*d5731834SJed Brown 
156*d5731834SJed Brown   PetscFunctionBegin;
157*d5731834SJed Brown   ierr = PetscFree((*heap)->base);CHKERRQ(ierr);
158*d5731834SJed Brown   ierr = PetscFree(*heap);CHKERRQ(ierr);
159*d5731834SJed Brown   PetscFunctionReturn(0);
160*d5731834SJed Brown }
161*d5731834SJed Brown 
162*d5731834SJed Brown #undef __FUNCT__
163*d5731834SJed Brown #define __FUNCT__ "PetscHeapView"
164*d5731834SJed Brown PetscErrorCode PetscHeapView(PetscHeap h,PetscViewer viewer)
165*d5731834SJed Brown {
166*d5731834SJed Brown   PetscErrorCode ierr;
167*d5731834SJed Brown   PetscBool iascii;
168*d5731834SJed Brown 
169*d5731834SJed Brown   PetscFunctionBegin;
170*d5731834SJed Brown   if (!viewer) {
171*d5731834SJed Brown     ierr = PetscViewerASCIIGetStdout(PETSC_COMM_SELF,&viewer);CHKERRQ(ierr);
172*d5731834SJed Brown   }
173*d5731834SJed Brown   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
174*d5731834SJed Brown   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
175*d5731834SJed Brown   if (iascii) {
176*d5731834SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"Heap size %D with %D stashed\n",h->end-1,h->alloc-h->stash);CHKERRQ(ierr);
177*d5731834SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"Heap in (id,value) pairs\n");CHKERRQ(ierr);
178*d5731834SJed Brown     ierr = PetscIntView(2*(h->end-1),(const PetscInt*)(h->base+1),viewer);CHKERRQ(ierr);
179*d5731834SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"Stash in (id,value) pairs\n");CHKERRQ(ierr);
180*d5731834SJed Brown     ierr = PetscIntView(2*(h->alloc-h->stash),(const PetscInt*)(h->base+h->stash),viewer);CHKERRQ(ierr);
181*d5731834SJed Brown   }
182*d5731834SJed Brown   PetscFunctionReturn(0);
183*d5731834SJed Brown }
184