xref: /petsc/src/sys/utils/sorti.c (revision c1f0200a0d18de7f811d6fa3b406f1354314cf41)
17d0a6c19SBarry Smith 
2e5c89e4eSSatish Balay /*
3e5c89e4eSSatish Balay    This file contains routines for sorting integers. Values are sorted in place.
4e5c89e4eSSatish Balay  */
5c6db04a5SJed Brown #include <petscsys.h>                /*I  "petscsys.h"  I*/
6e5c89e4eSSatish Balay 
7e5c89e4eSSatish Balay #define SWAP(a,b,t) {t=a;a=b;b=t;}
8e5c89e4eSSatish Balay 
9a8582168SJed Brown #define MEDIAN3(v,a,b,c)                        \
10a8582168SJed Brown   (v[a]<v[b]                                    \
11a8582168SJed Brown    ? (v[b]<v[c]                                 \
12a8582168SJed Brown       ? b                                       \
13a8582168SJed Brown       : (v[a]<v[c] ? c : a))                    \
14a8582168SJed Brown    : (v[c]<v[b]                                 \
15a8582168SJed Brown       ? b                                       \
16a8582168SJed Brown       : (v[a]<v[c] ? a : c)))
17a8582168SJed Brown 
18a8582168SJed Brown #define MEDIAN(v,right) MEDIAN3(v,right/4,right/2,right/4*3)
19ef8e3583SJed Brown 
20e5c89e4eSSatish Balay /* -----------------------------------------------------------------------*/
21e5c89e4eSSatish Balay 
22e5c89e4eSSatish Balay #undef __FUNCT__
23e5c89e4eSSatish Balay #define __FUNCT__ "PetscSortInt_Private"
24e5c89e4eSSatish Balay /*
25e5c89e4eSSatish Balay    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
26e5c89e4eSSatish Balay    Assumes 0 origin for v, number of elements = right+1 (right is index of
27e5c89e4eSSatish Balay    right-most member).
28e5c89e4eSSatish Balay */
29ef8e3583SJed Brown static void PetscSortInt_Private(PetscInt *v,PetscInt right)
30e5c89e4eSSatish Balay {
31ef8e3583SJed Brown   PetscInt       i,j,pivot,tmp;
32e5c89e4eSSatish Balay 
33e5c89e4eSSatish Balay   if (right <= 1) {
34e5c89e4eSSatish Balay     if (right == 1) {
35e5c89e4eSSatish Balay       if (v[0] > v[1]) SWAP(v[0],v[1],tmp);
36e5c89e4eSSatish Balay     }
37ef8e3583SJed Brown     return;
38e5c89e4eSSatish Balay   }
39ef8e3583SJed Brown   i = MEDIAN(v,right);          /* Choose a pivot */
40ef8e3583SJed Brown   SWAP(v[0],v[i],tmp);          /* Move it out of the way */
41ef8e3583SJed Brown   pivot = v[0];
42ef8e3583SJed Brown   for (i=0,j=right+1;;) {
43ef8e3583SJed Brown     while (++i < j && v[i] <= pivot); /* Scan from the left */
44ef8e3583SJed Brown     while (v[--j] > pivot);           /* Scan from the right */
45ef8e3583SJed Brown     if (i >= j) break;
46ef8e3583SJed Brown     SWAP(v[i],v[j],tmp);
47e5c89e4eSSatish Balay   }
48ef8e3583SJed Brown   SWAP(v[0],v[j],tmp);          /* Put pivot back in place. */
49ef8e3583SJed Brown   PetscSortInt_Private(v,j-1);
50ef8e3583SJed Brown   PetscSortInt_Private(v+j+1,right-(j+1));
51e5c89e4eSSatish Balay }
52e5c89e4eSSatish Balay 
53e5c89e4eSSatish Balay #undef __FUNCT__
54e5c89e4eSSatish Balay #define __FUNCT__ "PetscSortInt"
55e5c89e4eSSatish Balay /*@
56e5c89e4eSSatish Balay    PetscSortInt - Sorts an array of integers in place in increasing order.
57e5c89e4eSSatish Balay 
58e5c89e4eSSatish Balay    Not Collective
59e5c89e4eSSatish Balay 
60e5c89e4eSSatish Balay    Input Parameters:
61e5c89e4eSSatish Balay +  n  - number of values
62e5c89e4eSSatish Balay -  i  - array of integers
63e5c89e4eSSatish Balay 
64e5c89e4eSSatish Balay    Level: intermediate
65e5c89e4eSSatish Balay 
66e5c89e4eSSatish Balay    Concepts: sorting^ints
67e5c89e4eSSatish Balay 
68e5c89e4eSSatish Balay .seealso: PetscSortReal(), PetscSortIntWithPermutation()
69e5c89e4eSSatish Balay @*/
707087cfbeSBarry Smith PetscErrorCode  PetscSortInt(PetscInt n,PetscInt i[])
71e5c89e4eSSatish Balay {
72e5c89e4eSSatish Balay   PetscInt       j,k,tmp,ik;
73e5c89e4eSSatish Balay 
74e5c89e4eSSatish Balay   PetscFunctionBegin;
75e5c89e4eSSatish Balay   if (n<8) {
76e5c89e4eSSatish Balay     for (k=0; k<n; k++) {
77e5c89e4eSSatish Balay       ik = i[k];
78e5c89e4eSSatish Balay       for (j=k+1; j<n; j++) {
79e5c89e4eSSatish Balay 	if (ik > i[j]) {
80e5c89e4eSSatish Balay 	  SWAP(i[k],i[j],tmp);
81e5c89e4eSSatish Balay 	  ik = i[k];
82e5c89e4eSSatish Balay 	}
83e5c89e4eSSatish Balay       }
84e5c89e4eSSatish Balay     }
85e5c89e4eSSatish Balay   } else {
86ef8e3583SJed Brown     PetscSortInt_Private(i,n-1);
87e5c89e4eSSatish Balay   }
88e5c89e4eSSatish Balay   PetscFunctionReturn(0);
89e5c89e4eSSatish Balay }
90e5c89e4eSSatish Balay 
911db36a52SBarry Smith #undef __FUNCT__
921db36a52SBarry Smith #define __FUNCT__ "PetscSortRemoveDupsInt"
931db36a52SBarry Smith /*@
941db36a52SBarry Smith    PetscSortRemoveDupsInt - Sorts an array of integers in place in increasing order removes all duplicate entries
951db36a52SBarry Smith 
961db36a52SBarry Smith    Not Collective
971db36a52SBarry Smith 
981db36a52SBarry Smith    Input Parameters:
991db36a52SBarry Smith +  n  - number of values
1001db36a52SBarry Smith -  ii  - array of integers
1011db36a52SBarry Smith 
1021db36a52SBarry Smith    Output Parameter:
1031db36a52SBarry Smith .  n - number of non-redundant values
1041db36a52SBarry Smith 
1051db36a52SBarry Smith    Level: intermediate
1061db36a52SBarry Smith 
1071db36a52SBarry Smith    Concepts: sorting^ints
1081db36a52SBarry Smith 
1091db36a52SBarry Smith .seealso: PetscSortReal(), PetscSortIntWithPermutation(), PetscSortInt()
1101db36a52SBarry Smith @*/
1117087cfbeSBarry Smith PetscErrorCode  PetscSortRemoveDupsInt(PetscInt *n,PetscInt ii[])
1121db36a52SBarry Smith {
1131db36a52SBarry Smith   PetscErrorCode ierr;
1141db36a52SBarry Smith   PetscInt       i,s = 0,N = *n, b = 0;
1151db36a52SBarry Smith 
1161db36a52SBarry Smith   PetscFunctionBegin;
1171db36a52SBarry Smith   ierr = PetscSortInt(N,ii);CHKERRQ(ierr);
1181db36a52SBarry Smith   for (i=0; i<N-1; i++) {
119a5891931SBarry Smith     if (ii[b+s+1] != ii[b]) {ii[b+1] = ii[b+s+1]; b++;}
120a5891931SBarry Smith     else s++;
1211db36a52SBarry Smith   }
1221db36a52SBarry Smith   *n = N - s;
1231db36a52SBarry Smith   PetscFunctionReturn(0);
1241db36a52SBarry Smith }
1251db36a52SBarry Smith 
1261db36a52SBarry Smith 
127e5c89e4eSSatish Balay /* -----------------------------------------------------------------------*/
128e5c89e4eSSatish Balay #define SWAP2(a,b,c,d,t) {t=a;a=b;b=t;t=c;c=d;d=t;}
129e5c89e4eSSatish Balay 
130e5c89e4eSSatish Balay #undef __FUNCT__
131e5c89e4eSSatish Balay #define __FUNCT__ "PetscSortIntWithArray_Private"
132e5c89e4eSSatish Balay /*
133e5c89e4eSSatish Balay    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
134e5c89e4eSSatish Balay    Assumes 0 origin for v, number of elements = right+1 (right is index of
135e5c89e4eSSatish Balay    right-most member).
136e5c89e4eSSatish Balay */
137e5c89e4eSSatish Balay static PetscErrorCode PetscSortIntWithArray_Private(PetscInt *v,PetscInt *V,PetscInt right)
138e5c89e4eSSatish Balay {
139e5c89e4eSSatish Balay   PetscErrorCode ierr;
140e5c89e4eSSatish Balay   PetscInt       i,vl,last,tmp;
141e5c89e4eSSatish Balay 
142e5c89e4eSSatish Balay   PetscFunctionBegin;
143e5c89e4eSSatish Balay   if (right <= 1) {
144e5c89e4eSSatish Balay     if (right == 1) {
145e5c89e4eSSatish Balay       if (v[0] > v[1]) SWAP2(v[0],v[1],V[0],V[1],tmp);
146e5c89e4eSSatish Balay     }
147e5c89e4eSSatish Balay     PetscFunctionReturn(0);
148e5c89e4eSSatish Balay   }
149e5c89e4eSSatish Balay   SWAP2(v[0],v[right/2],V[0],V[right/2],tmp);
150e5c89e4eSSatish Balay   vl   = v[0];
151e5c89e4eSSatish Balay   last = 0;
152e5c89e4eSSatish Balay   for (i=1; i<=right; i++) {
153e5c89e4eSSatish Balay     if (v[i] < vl) {last++; SWAP2(v[last],v[i],V[last],V[i],tmp);}
154e5c89e4eSSatish Balay   }
155e5c89e4eSSatish Balay   SWAP2(v[0],v[last],V[0],V[last],tmp);
156e5c89e4eSSatish Balay   ierr = PetscSortIntWithArray_Private(v,V,last-1);CHKERRQ(ierr);
157e5c89e4eSSatish Balay   ierr = PetscSortIntWithArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr);
158e5c89e4eSSatish Balay   PetscFunctionReturn(0);
159e5c89e4eSSatish Balay }
160e5c89e4eSSatish Balay 
161e5c89e4eSSatish Balay #undef __FUNCT__
162e5c89e4eSSatish Balay #define __FUNCT__ "PetscSortIntWithArray"
163e5c89e4eSSatish Balay /*@
164e5c89e4eSSatish Balay    PetscSortIntWithArray - Sorts an array of integers in place in increasing order;
165e5c89e4eSSatish Balay        changes a second array to match the sorted first array.
166e5c89e4eSSatish Balay 
167e5c89e4eSSatish Balay    Not Collective
168e5c89e4eSSatish Balay 
169e5c89e4eSSatish Balay    Input Parameters:
170e5c89e4eSSatish Balay +  n  - number of values
171e5c89e4eSSatish Balay .  i  - array of integers
172e5c89e4eSSatish Balay -  I - second array of integers
173e5c89e4eSSatish Balay 
174e5c89e4eSSatish Balay    Level: intermediate
175e5c89e4eSSatish Balay 
176e5c89e4eSSatish Balay    Concepts: sorting^ints with array
177e5c89e4eSSatish Balay 
178e5c89e4eSSatish Balay .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt()
179e5c89e4eSSatish Balay @*/
1807087cfbeSBarry Smith PetscErrorCode  PetscSortIntWithArray(PetscInt n,PetscInt i[],PetscInt Ii[])
181e5c89e4eSSatish Balay {
182e5c89e4eSSatish Balay   PetscErrorCode ierr;
183e5c89e4eSSatish Balay   PetscInt       j,k,tmp,ik;
184e5c89e4eSSatish Balay 
185e5c89e4eSSatish Balay   PetscFunctionBegin;
186e5c89e4eSSatish Balay   if (n<8) {
187e5c89e4eSSatish Balay     for (k=0; k<n; k++) {
188e5c89e4eSSatish Balay       ik = i[k];
189e5c89e4eSSatish Balay       for (j=k+1; j<n; j++) {
190e5c89e4eSSatish Balay 	if (ik > i[j]) {
191b7940d39SSatish Balay 	  SWAP2(i[k],i[j],Ii[k],Ii[j],tmp);
192e5c89e4eSSatish Balay 	  ik = i[k];
193e5c89e4eSSatish Balay 	}
194e5c89e4eSSatish Balay       }
195e5c89e4eSSatish Balay     }
196e5c89e4eSSatish Balay   } else {
197b7940d39SSatish Balay     ierr = PetscSortIntWithArray_Private(i,Ii,n-1);CHKERRQ(ierr);
198e5c89e4eSSatish Balay   }
199e5c89e4eSSatish Balay   PetscFunctionReturn(0);
200e5c89e4eSSatish Balay }
201e5c89e4eSSatish Balay 
202*c1f0200aSDmitry Karpeev 
203*c1f0200aSDmitry Karpeev #define SWAP3(a,b,c,d,e,f,t) {t=a;a=b;b=t;t=c;c=d;d=t;t=e;e=f;f=t;}
204*c1f0200aSDmitry Karpeev 
205*c1f0200aSDmitry Karpeev #undef __FUNCT__
206*c1f0200aSDmitry Karpeev #define __FUNCT__ "PetscSortIntWithArrayPair_Private"
207*c1f0200aSDmitry Karpeev /*
208*c1f0200aSDmitry Karpeev    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
209*c1f0200aSDmitry Karpeev    Assumes 0 origin for v, number of elements = right+1 (right is index of
210*c1f0200aSDmitry Karpeev    right-most member).
211*c1f0200aSDmitry Karpeev */
212*c1f0200aSDmitry Karpeev static PetscErrorCode PetscSortIntWithArrayPair_Private(PetscInt *I,PetscInt *J, PetscInt *K, PetscInt right)
213*c1f0200aSDmitry Karpeev {
214*c1f0200aSDmitry Karpeev   PetscErrorCode ierr;
215*c1f0200aSDmitry Karpeev   PetscInt       i,vl,last,tmp;
216*c1f0200aSDmitry Karpeev 
217*c1f0200aSDmitry Karpeev   PetscFunctionBegin;
218*c1f0200aSDmitry Karpeev   if (right <= 1) {
219*c1f0200aSDmitry Karpeev     if (right == 1) {
220*c1f0200aSDmitry Karpeev       if (I[0] > I[1]) SWAP3(I[0],I[1],J[0],J[1],K[0],K[1],tmp);
221*c1f0200aSDmitry Karpeev     }
222*c1f0200aSDmitry Karpeev     PetscFunctionReturn(0);
223*c1f0200aSDmitry Karpeev   }
224*c1f0200aSDmitry Karpeev   SWAP3(I[0],I[right/2],J[0],J[right/2],K[0],K[right/2],tmp);
225*c1f0200aSDmitry Karpeev   vl   = I[0];
226*c1f0200aSDmitry Karpeev   last = 0;
227*c1f0200aSDmitry Karpeev   for (i=1; i<=right; i++) {
228*c1f0200aSDmitry Karpeev     if (I[i] < vl) {last++; SWAP3(I[last],I[i],J[last],J[i],K[last],K[i],tmp);}
229*c1f0200aSDmitry Karpeev   }
230*c1f0200aSDmitry Karpeev   SWAP3(I[0],I[last],J[0],J[last],K[0],K[last],tmp);
231*c1f0200aSDmitry Karpeev   ierr = PetscSortIntWithArrayPair_Private(I,J,K,last-1);CHKERRQ(ierr);
232*c1f0200aSDmitry Karpeev   ierr = PetscSortIntWithArrayPair_Private(I+last+1,J+last+1,K+last+1,right-(last+1));CHKERRQ(ierr);
233*c1f0200aSDmitry Karpeev   PetscFunctionReturn(0);
234*c1f0200aSDmitry Karpeev }
235*c1f0200aSDmitry Karpeev 
236*c1f0200aSDmitry Karpeev #undef __FUNCT__
237*c1f0200aSDmitry Karpeev #define __FUNCT__ "PetscSortIntWithArrayPair"
238*c1f0200aSDmitry Karpeev /*@
239*c1f0200aSDmitry Karpeev    PetscSortIntWithArrayPair - Sorts an array of integers in place in increasing order;
240*c1f0200aSDmitry Karpeev        changes a pair of integer arrays to match the sorted first array.
241*c1f0200aSDmitry Karpeev 
242*c1f0200aSDmitry Karpeev    Not Collective
243*c1f0200aSDmitry Karpeev 
244*c1f0200aSDmitry Karpeev    Input Parameters:
245*c1f0200aSDmitry Karpeev +  n  - number of values
246*c1f0200aSDmitry Karpeev .  I  - array of integers
247*c1f0200aSDmitry Karpeev .  J  - second array of integers (first array of the pair)
248*c1f0200aSDmitry Karpeev -  K  - third array of integers  (second array of the pair)
249*c1f0200aSDmitry Karpeev 
250*c1f0200aSDmitry Karpeev    Level: intermediate
251*c1f0200aSDmitry Karpeev 
252*c1f0200aSDmitry Karpeev    Concepts: sorting^ints with array pair
253*c1f0200aSDmitry Karpeev 
254*c1f0200aSDmitry Karpeev .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortIntWithArray()
255*c1f0200aSDmitry Karpeev @*/
256*c1f0200aSDmitry Karpeev PetscErrorCode  PetscSortIntWithArrayPair(PetscInt n,PetscInt I[],PetscInt J[], PetscInt K[])
257*c1f0200aSDmitry Karpeev {
258*c1f0200aSDmitry Karpeev   PetscErrorCode ierr;
259*c1f0200aSDmitry Karpeev   PetscInt       j,k,tmp,ik;
260*c1f0200aSDmitry Karpeev 
261*c1f0200aSDmitry Karpeev   PetscFunctionBegin;
262*c1f0200aSDmitry Karpeev   if (n<8) {
263*c1f0200aSDmitry Karpeev     for (k=0; k<n; k++) {
264*c1f0200aSDmitry Karpeev       ik = I[k];
265*c1f0200aSDmitry Karpeev       for (j=k+1; j<n; j++) {
266*c1f0200aSDmitry Karpeev 	if (ik > I[j]) {
267*c1f0200aSDmitry Karpeev 	  SWAP3(I[k],I[j],J[k],J[j],K[k],K[j],tmp);
268*c1f0200aSDmitry Karpeev 	  ik = I[k];
269*c1f0200aSDmitry Karpeev 	}
270*c1f0200aSDmitry Karpeev       }
271*c1f0200aSDmitry Karpeev     }
272*c1f0200aSDmitry Karpeev   } else {
273*c1f0200aSDmitry Karpeev     ierr = PetscSortIntWithArrayPair_Private(I,J,K,n-1);CHKERRQ(ierr);
274*c1f0200aSDmitry Karpeev   }
275*c1f0200aSDmitry Karpeev   PetscFunctionReturn(0);
276*c1f0200aSDmitry Karpeev }
277*c1f0200aSDmitry Karpeev 
278*c1f0200aSDmitry Karpeev 
2794d615ea0SBarry Smith #undef __FUNCT__
2804d615ea0SBarry Smith #define __FUNCT__ "PetscSortMPIIntWithArray_Private"
2814d615ea0SBarry Smith /*
2824d615ea0SBarry Smith    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
2834d615ea0SBarry Smith    Assumes 0 origin for v, number of elements = right+1 (right is index of
2844d615ea0SBarry Smith    right-most member).
2854d615ea0SBarry Smith */
2864d615ea0SBarry Smith static PetscErrorCode PetscSortMPIIntWithArray_Private(PetscMPIInt *v,PetscMPIInt *V,PetscMPIInt right)
2874d615ea0SBarry Smith {
2884d615ea0SBarry Smith   PetscErrorCode ierr;
2894d615ea0SBarry Smith   PetscMPIInt    i,vl,last,tmp;
2904d615ea0SBarry Smith 
2914d615ea0SBarry Smith   PetscFunctionBegin;
2924d615ea0SBarry Smith   if (right <= 1) {
2934d615ea0SBarry Smith     if (right == 1) {
2944d615ea0SBarry Smith       if (v[0] > v[1]) SWAP2(v[0],v[1],V[0],V[1],tmp);
2954d615ea0SBarry Smith     }
2964d615ea0SBarry Smith     PetscFunctionReturn(0);
2974d615ea0SBarry Smith   }
2984d615ea0SBarry Smith   SWAP2(v[0],v[right/2],V[0],V[right/2],tmp);
2994d615ea0SBarry Smith   vl   = v[0];
3004d615ea0SBarry Smith   last = 0;
3014d615ea0SBarry Smith   for (i=1; i<=right; i++) {
3024d615ea0SBarry Smith     if (v[i] < vl) {last++; SWAP2(v[last],v[i],V[last],V[i],tmp);}
3034d615ea0SBarry Smith   }
3044d615ea0SBarry Smith   SWAP2(v[0],v[last],V[0],V[last],tmp);
3054d615ea0SBarry Smith   ierr = PetscSortMPIIntWithArray_Private(v,V,last-1);CHKERRQ(ierr);
3064d615ea0SBarry Smith   ierr = PetscSortMPIIntWithArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr);
3074d615ea0SBarry Smith   PetscFunctionReturn(0);
3084d615ea0SBarry Smith }
3094d615ea0SBarry Smith 
3104d615ea0SBarry Smith #undef __FUNCT__
3114d615ea0SBarry Smith #define __FUNCT__ "PetscSortMPIIntWithArray"
3124d615ea0SBarry Smith /*@
3134d615ea0SBarry Smith    PetscSortMPIIntWithArray - Sorts an array of integers in place in increasing order;
3144d615ea0SBarry Smith        changes a second array to match the sorted first array.
3154d615ea0SBarry Smith 
3164d615ea0SBarry Smith    Not Collective
3174d615ea0SBarry Smith 
3184d615ea0SBarry Smith    Input Parameters:
3194d615ea0SBarry Smith +  n  - number of values
3204d615ea0SBarry Smith .  i  - array of integers
3214d615ea0SBarry Smith -  I - second array of integers
3224d615ea0SBarry Smith 
3234d615ea0SBarry Smith    Level: intermediate
3244d615ea0SBarry Smith 
3254d615ea0SBarry Smith    Concepts: sorting^ints with array
3264d615ea0SBarry Smith 
3274d615ea0SBarry Smith .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt()
3284d615ea0SBarry Smith @*/
3297087cfbeSBarry Smith PetscErrorCode  PetscSortMPIIntWithArray(PetscMPIInt n,PetscMPIInt i[],PetscMPIInt Ii[])
3304d615ea0SBarry Smith {
3314d615ea0SBarry Smith   PetscErrorCode ierr;
3324d615ea0SBarry Smith   PetscMPIInt    j,k,tmp,ik;
3334d615ea0SBarry Smith 
3344d615ea0SBarry Smith   PetscFunctionBegin;
3354d615ea0SBarry Smith   if (n<8) {
3364d615ea0SBarry Smith     for (k=0; k<n; k++) {
3374d615ea0SBarry Smith       ik = i[k];
3384d615ea0SBarry Smith       for (j=k+1; j<n; j++) {
3394d615ea0SBarry Smith 	if (ik > i[j]) {
3404d615ea0SBarry Smith 	  SWAP2(i[k],i[j],Ii[k],Ii[j],tmp);
3414d615ea0SBarry Smith 	  ik = i[k];
3424d615ea0SBarry Smith 	}
3434d615ea0SBarry Smith       }
3444d615ea0SBarry Smith     }
3454d615ea0SBarry Smith   } else {
3464d615ea0SBarry Smith     ierr = PetscSortMPIIntWithArray_Private(i,Ii,n-1);CHKERRQ(ierr);
3474d615ea0SBarry Smith   }
3484d615ea0SBarry Smith   PetscFunctionReturn(0);
3494d615ea0SBarry Smith }
3504d615ea0SBarry Smith 
351e5c89e4eSSatish Balay /* -----------------------------------------------------------------------*/
352e5c89e4eSSatish Balay #define SWAP2IntScalar(a,b,c,d,t,ts) {t=a;a=b;b=t;ts=c;c=d;d=ts;}
353e5c89e4eSSatish Balay 
354e5c89e4eSSatish Balay #undef __FUNCT__
355e5c89e4eSSatish Balay #define __FUNCT__ "PetscSortIntWithScalarArray_Private"
356e5c89e4eSSatish Balay /*
357e5c89e4eSSatish Balay    Modified from PetscSortIntWithArray_Private().
358e5c89e4eSSatish Balay */
359e5c89e4eSSatish Balay static PetscErrorCode PetscSortIntWithScalarArray_Private(PetscInt *v,PetscScalar *V,PetscInt right)
360e5c89e4eSSatish Balay {
361e5c89e4eSSatish Balay   PetscErrorCode ierr;
362e5c89e4eSSatish Balay   PetscInt       i,vl,last,tmp;
363e5c89e4eSSatish Balay   PetscScalar    stmp;
364e5c89e4eSSatish Balay 
365e5c89e4eSSatish Balay   PetscFunctionBegin;
366e5c89e4eSSatish Balay   if (right <= 1) {
367e5c89e4eSSatish Balay     if (right == 1) {
368e5c89e4eSSatish Balay       if (v[0] > v[1]) SWAP2IntScalar(v[0],v[1],V[0],V[1],tmp,stmp);
369e5c89e4eSSatish Balay     }
370e5c89e4eSSatish Balay     PetscFunctionReturn(0);
371e5c89e4eSSatish Balay   }
372e5c89e4eSSatish Balay   SWAP2IntScalar(v[0],v[right/2],V[0],V[right/2],tmp,stmp);
373e5c89e4eSSatish Balay   vl   = v[0];
374e5c89e4eSSatish Balay   last = 0;
375e5c89e4eSSatish Balay   for (i=1; i<=right; i++) {
376e5c89e4eSSatish Balay     if (v[i] < vl) {last++; SWAP2IntScalar(v[last],v[i],V[last],V[i],tmp,stmp);}
377e5c89e4eSSatish Balay   }
378e5c89e4eSSatish Balay   SWAP2IntScalar(v[0],v[last],V[0],V[last],tmp,stmp);
379e5c89e4eSSatish Balay   ierr = PetscSortIntWithScalarArray_Private(v,V,last-1);CHKERRQ(ierr);
380e5c89e4eSSatish Balay   ierr = PetscSortIntWithScalarArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr);
381e5c89e4eSSatish Balay   PetscFunctionReturn(0);
382e5c89e4eSSatish Balay }
383e5c89e4eSSatish Balay 
384e5c89e4eSSatish Balay #undef __FUNCT__
385e5c89e4eSSatish Balay #define __FUNCT__ "PetscSortIntWithScalarArray"
386e5c89e4eSSatish Balay /*@
387e5c89e4eSSatish Balay    PetscSortIntWithScalarArray - Sorts an array of integers in place in increasing order;
388e5c89e4eSSatish Balay        changes a second SCALAR array to match the sorted first INTEGER array.
389e5c89e4eSSatish Balay 
390e5c89e4eSSatish Balay    Not Collective
391e5c89e4eSSatish Balay 
392e5c89e4eSSatish Balay    Input Parameters:
393e5c89e4eSSatish Balay +  n  - number of values
394e5c89e4eSSatish Balay .  i  - array of integers
395e5c89e4eSSatish Balay -  I - second array of scalars
396e5c89e4eSSatish Balay 
397e5c89e4eSSatish Balay    Level: intermediate
398e5c89e4eSSatish Balay 
399e5c89e4eSSatish Balay    Concepts: sorting^ints with array
400e5c89e4eSSatish Balay 
401e5c89e4eSSatish Balay .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
402e5c89e4eSSatish Balay @*/
4037087cfbeSBarry Smith PetscErrorCode  PetscSortIntWithScalarArray(PetscInt n,PetscInt i[],PetscScalar Ii[])
404e5c89e4eSSatish Balay {
405e5c89e4eSSatish Balay   PetscErrorCode ierr;
406e5c89e4eSSatish Balay   PetscInt       j,k,tmp,ik;
407e5c89e4eSSatish Balay   PetscScalar    stmp;
408e5c89e4eSSatish Balay 
409e5c89e4eSSatish Balay   PetscFunctionBegin;
410e5c89e4eSSatish Balay   if (n<8) {
411e5c89e4eSSatish Balay     for (k=0; k<n; k++) {
412e5c89e4eSSatish Balay       ik = i[k];
413e5c89e4eSSatish Balay       for (j=k+1; j<n; j++) {
414e5c89e4eSSatish Balay 	if (ik > i[j]) {
415b7940d39SSatish Balay 	  SWAP2IntScalar(i[k],i[j],Ii[k],Ii[j],tmp,stmp);
416e5c89e4eSSatish Balay 	  ik = i[k];
417e5c89e4eSSatish Balay 	}
418e5c89e4eSSatish Balay       }
419e5c89e4eSSatish Balay     }
420e5c89e4eSSatish Balay   } else {
421b7940d39SSatish Balay     ierr = PetscSortIntWithScalarArray_Private(i,Ii,n-1);CHKERRQ(ierr);
422e5c89e4eSSatish Balay   }
423e5c89e4eSSatish Balay   PetscFunctionReturn(0);
424e5c89e4eSSatish Balay }
425e5c89e4eSSatish Balay 
426*c1f0200aSDmitry Karpeev #undef __FUNCT__
427*c1f0200aSDmitry Karpeev #define __FUNCT__ "PetscMergeIntArrayPair"
428*c1f0200aSDmitry Karpeev /*@
429*c1f0200aSDmitry Karpeev    PetscMergeIntArrayPair -     Merges two SORTED integer arrays along with an additional array of integers.
430*c1f0200aSDmitry Karpeev                                 The additional arrays are the same length as sorted arrays and are merged
431*c1f0200aSDmitry Karpeev                                 in the order determined by the merging of the sorted pair.
432*c1f0200aSDmitry Karpeev 
433*c1f0200aSDmitry Karpeev    Not Collective
434*c1f0200aSDmitry Karpeev 
435*c1f0200aSDmitry Karpeev    Input Parameters:
436*c1f0200aSDmitry Karpeev +  an  - number of values in the first array
437*c1f0200aSDmitry Karpeev .  aI  - first sorted array of integers
438*c1f0200aSDmitry Karpeev .  aJ  - first additional array of integers
439*c1f0200aSDmitry Karpeev .  bn  - number of values in the second array
440*c1f0200aSDmitry Karpeev .  bI  - second array of integers
441*c1f0200aSDmitry Karpeev -  bJ  - second additional of integers
442*c1f0200aSDmitry Karpeev 
443*c1f0200aSDmitry Karpeev    Output Parameters:
444*c1f0200aSDmitry Karpeev +  n   - number of values in the merged array (== an + bn)
445*c1f0200aSDmitry Karpeev .  I   - merged sorted array
446*c1f0200aSDmitry Karpeev -  J   - merged additional array
447*c1f0200aSDmitry Karpeev 
448*c1f0200aSDmitry Karpeev    Level: intermediate
449*c1f0200aSDmitry Karpeev 
450*c1f0200aSDmitry Karpeev    Concepts: merging^arrays
451*c1f0200aSDmitry Karpeev 
452*c1f0200aSDmitry Karpeev .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
453*c1f0200aSDmitry Karpeev @*/
454*c1f0200aSDmitry Karpeev PetscErrorCode  PetscMergeIntArrayPair(PetscInt an,const PetscInt aI[], const PetscInt aJ[], PetscInt bn, const PetscInt bI[], const PetscInt bJ[], PetscInt *n, PetscInt *I[], PetscInt *J[])
455*c1f0200aSDmitry Karpeev {
456*c1f0200aSDmitry Karpeev   PetscErrorCode ierr;
457*c1f0200aSDmitry Karpeev   PetscInt n_, *I_ = *I, *J_= *J, ak, bk, k;
458*c1f0200aSDmitry Karpeev 
459*c1f0200aSDmitry Karpeev   n_ = an + bn;
460*c1f0200aSDmitry Karpeev   *n = n_;
461*c1f0200aSDmitry Karpeev   if(!I_) {
462*c1f0200aSDmitry Karpeev     ierr = PetscMalloc(n_*sizeof(PetscInt), I); CHKERRQ(ierr);
463*c1f0200aSDmitry Karpeev     I_ = *I;
464*c1f0200aSDmitry Karpeev   }
465*c1f0200aSDmitry Karpeev   if(!J_){
466*c1f0200aSDmitry Karpeev     ierr = PetscMalloc(n_*sizeof(PetscInt), &J_); CHKERRQ(ierr);
467*c1f0200aSDmitry Karpeev     J_ = *J;
468*c1f0200aSDmitry Karpeev   }
469*c1f0200aSDmitry Karpeev   k = ak = bk = 0;
470*c1f0200aSDmitry Karpeev   while(ak < an && bk < bn) {
471*c1f0200aSDmitry Karpeev     if(aI[ak] <= bI[bk]) {
472*c1f0200aSDmitry Karpeev       I_[k] = aI[ak];
473*c1f0200aSDmitry Karpeev       J_[k] = aJ[ak];
474*c1f0200aSDmitry Karpeev       ++ak;
475*c1f0200aSDmitry Karpeev       ++k;
476*c1f0200aSDmitry Karpeev     }
477*c1f0200aSDmitry Karpeev     else {
478*c1f0200aSDmitry Karpeev       I_[k] = bI[bk];
479*c1f0200aSDmitry Karpeev       J_[k] = bJ[bk];
480*c1f0200aSDmitry Karpeev       ++bk;
481*c1f0200aSDmitry Karpeev       ++k;
482*c1f0200aSDmitry Karpeev     }
483*c1f0200aSDmitry Karpeev   }
484*c1f0200aSDmitry Karpeev   if(ak < an) {
485*c1f0200aSDmitry Karpeev     ierr = PetscMemcpy(I_+k,aI+ak,(an-ak)*sizeof(PetscInt)); CHKERRQ(ierr);
486*c1f0200aSDmitry Karpeev     ierr = PetscMemcpy(J_+k,aJ+ak,(an-ak)*sizeof(PetscInt)); CHKERRQ(ierr);
487*c1f0200aSDmitry Karpeev     k += (an-ak);
488*c1f0200aSDmitry Karpeev   }
489*c1f0200aSDmitry Karpeev   if(bk < bn) {
490*c1f0200aSDmitry Karpeev     ierr = PetscMemcpy(I_+k,bI+bk,(bn-bk)*sizeof(PetscInt)); CHKERRQ(ierr);
491*c1f0200aSDmitry Karpeev     ierr = PetscMemcpy(J_+k,bJ+bk,(bn-bk)*sizeof(PetscInt)); CHKERRQ(ierr);
492*c1f0200aSDmitry Karpeev     k += (bn-bk);
493*c1f0200aSDmitry Karpeev   }
494*c1f0200aSDmitry Karpeev   PetscFunctionReturn(0);
495*c1f0200aSDmitry Karpeev }
496*c1f0200aSDmitry Karpeev 
497e5c89e4eSSatish Balay 
49842eaa7f3SBarry Smith #undef __FUNCT__
49942eaa7f3SBarry Smith #define __FUNCT__ "PetscProcessTree"
50042eaa7f3SBarry Smith /*@
50142eaa7f3SBarry Smith    PetscProcessTree - Prepares tree data to be displayed graphically
50242eaa7f3SBarry Smith 
50342eaa7f3SBarry Smith    Not Collective
50442eaa7f3SBarry Smith 
50542eaa7f3SBarry Smith    Input Parameters:
50642eaa7f3SBarry Smith +  n  - number of values
50742eaa7f3SBarry Smith .  mask - indicates those entries in the tree, location 0 is always masked
50842eaa7f3SBarry Smith -  parentid - indicates the parent of each entry
50942eaa7f3SBarry Smith 
51042eaa7f3SBarry Smith    Output Parameters:
51142eaa7f3SBarry Smith +  Nlevels - the number of levels
51242eaa7f3SBarry Smith .  Level - for each node tells its level
51342eaa7f3SBarry Smith .  Levelcnts - the number of nodes on each level
51442eaa7f3SBarry Smith .  Idbylevel - a list of ids on each of the levels, first level followed by second etc
51542eaa7f3SBarry Smith -  Column - for each id tells its column index
51642eaa7f3SBarry Smith 
51742eaa7f3SBarry Smith    Level: intermediate
51842eaa7f3SBarry Smith 
51942eaa7f3SBarry Smith 
52042eaa7f3SBarry Smith .seealso: PetscSortReal(), PetscSortIntWithPermutation()
52142eaa7f3SBarry Smith @*/
5227087cfbeSBarry Smith PetscErrorCode  PetscProcessTree(PetscInt n,const PetscBool  mask[],const PetscInt parentid[],PetscInt *Nlevels,PetscInt **Level,PetscInt **Levelcnt,PetscInt **Idbylevel,PetscInt **Column)
52342eaa7f3SBarry Smith {
52442eaa7f3SBarry Smith   PetscInt       i,j,cnt,nmask = 0,nlevels = 0,*level,*levelcnt,levelmax = 0,*workid,*workparentid,tcnt = 0,*idbylevel,*column;
52542eaa7f3SBarry Smith   PetscErrorCode ierr;
526ace3abfcSBarry Smith   PetscBool      done = PETSC_FALSE;
52742eaa7f3SBarry Smith 
52842eaa7f3SBarry Smith   PetscFunctionBegin;
52942eaa7f3SBarry Smith   if (!mask[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Mask of 0th location must be set");
53042eaa7f3SBarry Smith   for (i=0; i<n; i++) {
53142eaa7f3SBarry Smith     if (mask[i]) continue;
53242eaa7f3SBarry Smith     if (parentid[i]  == i) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Node labeled as own parent");
53342eaa7f3SBarry Smith     if (parentid[i] && mask[parentid[i]]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Parent is masked");
53442eaa7f3SBarry Smith   }
53542eaa7f3SBarry Smith 
53642eaa7f3SBarry Smith 
53742eaa7f3SBarry Smith   for (i=0; i<n; i++) {
53842eaa7f3SBarry Smith     if (!mask[i]) nmask++;
53942eaa7f3SBarry Smith   }
54042eaa7f3SBarry Smith 
54142eaa7f3SBarry Smith   /* determine the level in the tree of each node */
54242eaa7f3SBarry Smith   ierr = PetscMalloc(n*sizeof(PetscInt),&level);CHKERRQ(ierr);
54342eaa7f3SBarry Smith   ierr = PetscMemzero(level,n*sizeof(PetscInt));CHKERRQ(ierr);
54442eaa7f3SBarry Smith   level[0] = 1;
54542eaa7f3SBarry Smith   while (!done) {
54642eaa7f3SBarry Smith     done = PETSC_TRUE;
54742eaa7f3SBarry Smith     for (i=0; i<n; i++) {
54842eaa7f3SBarry Smith       if (mask[i]) continue;
54942eaa7f3SBarry Smith       if (!level[i] && level[parentid[i]]) level[i] = level[parentid[i]] + 1;
55042eaa7f3SBarry Smith       else if (!level[i]) done = PETSC_FALSE;
55142eaa7f3SBarry Smith     }
55242eaa7f3SBarry Smith   }
55342eaa7f3SBarry Smith   for (i=0; i<n; i++) {
55442eaa7f3SBarry Smith     level[i]--;
55542eaa7f3SBarry Smith     nlevels = PetscMax(nlevels,level[i]);
55642eaa7f3SBarry Smith   }
55742eaa7f3SBarry Smith 
55842eaa7f3SBarry Smith   /* count the number of nodes on each level and its max */
55942eaa7f3SBarry Smith   ierr = PetscMalloc(nlevels*sizeof(PetscInt),&levelcnt);CHKERRQ(ierr);
56042eaa7f3SBarry Smith   ierr = PetscMemzero(levelcnt,nlevels*sizeof(PetscInt));CHKERRQ(ierr);
56142eaa7f3SBarry Smith   for (i=0; i<n; i++) {
56242eaa7f3SBarry Smith     if (mask[i]) continue;
56342eaa7f3SBarry Smith     levelcnt[level[i]-1]++;
56442eaa7f3SBarry Smith   }
56542eaa7f3SBarry Smith   for (i=0; i<nlevels;i++) {
56642eaa7f3SBarry Smith     levelmax = PetscMax(levelmax,levelcnt[i]);
56742eaa7f3SBarry Smith   }
56842eaa7f3SBarry Smith 
56942eaa7f3SBarry Smith   /* for each level sort the ids by the parent id */
57042eaa7f3SBarry Smith   ierr = PetscMalloc2(levelmax,PetscInt,&workid,levelmax,PetscInt,&workparentid);CHKERRQ(ierr);
57142eaa7f3SBarry Smith   ierr = PetscMalloc(nmask*sizeof(PetscInt),&idbylevel);CHKERRQ(ierr);
57242eaa7f3SBarry Smith   for (j=1; j<=nlevels;j++) {
57342eaa7f3SBarry Smith     cnt = 0;
57442eaa7f3SBarry Smith     for (i=0; i<n; i++) {
57542eaa7f3SBarry Smith       if (mask[i]) continue;
57642eaa7f3SBarry Smith       if (level[i] != j) continue;
57742eaa7f3SBarry Smith       workid[cnt]         = i;
57842eaa7f3SBarry Smith       workparentid[cnt++] = parentid[i];
57942eaa7f3SBarry Smith     }
58042eaa7f3SBarry Smith     /*  PetscIntView(cnt,workparentid,0);
58142eaa7f3SBarry Smith     PetscIntView(cnt,workid,0);
58242eaa7f3SBarry Smith     ierr = PetscSortIntWithArray(cnt,workparentid,workid);CHKERRQ(ierr);
58342eaa7f3SBarry Smith     PetscIntView(cnt,workparentid,0);
58442eaa7f3SBarry Smith     PetscIntView(cnt,workid,0);*/
58542eaa7f3SBarry Smith     ierr = PetscMemcpy(idbylevel+tcnt,workid,cnt*sizeof(PetscInt));CHKERRQ(ierr);
58642eaa7f3SBarry Smith     tcnt += cnt;
58742eaa7f3SBarry Smith   }
58842eaa7f3SBarry Smith   if (tcnt != nmask) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Inconsistent count of unmasked nodes");
58942eaa7f3SBarry Smith   ierr = PetscFree2(workid,workparentid);CHKERRQ(ierr);
59042eaa7f3SBarry Smith 
59142eaa7f3SBarry Smith   /* for each node list its column */
59242eaa7f3SBarry Smith   ierr = PetscMalloc(n*sizeof(PetscInt),&column);CHKERRQ(ierr);
59342eaa7f3SBarry Smith   cnt = 0;
59442eaa7f3SBarry Smith   for (j=0; j<nlevels; j++) {
59542eaa7f3SBarry Smith     for (i=0; i<levelcnt[j]; i++) {
59642eaa7f3SBarry Smith       column[idbylevel[cnt++]] = i;
59742eaa7f3SBarry Smith     }
59842eaa7f3SBarry Smith   }
59942eaa7f3SBarry Smith 
60042eaa7f3SBarry Smith   *Nlevels   = nlevels;
60142eaa7f3SBarry Smith   *Level     = level;
60242eaa7f3SBarry Smith   *Levelcnt  = levelcnt;
60342eaa7f3SBarry Smith   *Idbylevel = idbylevel;
60442eaa7f3SBarry Smith   *Column    = column;
60542eaa7f3SBarry Smith   PetscFunctionReturn(0);
60642eaa7f3SBarry Smith }
607