xref: /petsc/src/sys/utils/sorti.c (revision 580bdb303e1ee3b1222b2042810b4c26340259c6)
17d0a6c19SBarry Smith 
2e5c89e4eSSatish Balay /*
3e5c89e4eSSatish Balay    This file contains routines for sorting integers. Values are sorted in place.
4e5c89e4eSSatish Balay  */
5af0996ceSBarry Smith #include <petsc/private/petscimpl.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 /*
23e5c89e4eSSatish Balay    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
24e5c89e4eSSatish Balay    Assumes 0 origin for v, number of elements = right+1 (right is index of
25e5c89e4eSSatish Balay    right-most member).
26e5c89e4eSSatish Balay */
27ef8e3583SJed Brown static void PetscSortInt_Private(PetscInt *v,PetscInt right)
28e5c89e4eSSatish Balay {
29ef8e3583SJed Brown   PetscInt i,j,pivot,tmp;
30e5c89e4eSSatish Balay 
31e5c89e4eSSatish Balay   if (right <= 1) {
32e5c89e4eSSatish Balay     if (right == 1) {
33e5c89e4eSSatish Balay       if (v[0] > v[1]) SWAP(v[0],v[1],tmp);
34e5c89e4eSSatish Balay     }
35ef8e3583SJed Brown     return;
36e5c89e4eSSatish Balay   }
37ef8e3583SJed Brown   i = MEDIAN(v,right);          /* Choose a pivot */
38ef8e3583SJed Brown   SWAP(v[0],v[i],tmp);          /* Move it out of the way */
39ef8e3583SJed Brown   pivot = v[0];
40ef8e3583SJed Brown   for (i=0,j=right+1;; ) {
41ef8e3583SJed Brown     while (++i < j && v[i] <= pivot) ; /* Scan from the left */
42ef8e3583SJed Brown     while (v[--j] > pivot) ;           /* Scan from the right */
43ef8e3583SJed Brown     if (i >= j) break;
44ef8e3583SJed Brown     SWAP(v[i],v[j],tmp);
45e5c89e4eSSatish Balay   }
46ef8e3583SJed Brown   SWAP(v[0],v[j],tmp);          /* Put pivot back in place. */
47ef8e3583SJed Brown   PetscSortInt_Private(v,j-1);
48ef8e3583SJed Brown   PetscSortInt_Private(v+j+1,right-(j+1));
49e5c89e4eSSatish Balay }
50e5c89e4eSSatish Balay 
51e5c89e4eSSatish Balay /*@
52e5c89e4eSSatish Balay    PetscSortInt - Sorts an array of integers in place in increasing order.
53e5c89e4eSSatish Balay 
54e5c89e4eSSatish Balay    Not Collective
55e5c89e4eSSatish Balay 
56e5c89e4eSSatish Balay    Input Parameters:
57e5c89e4eSSatish Balay +  n  - number of values
58e5c89e4eSSatish Balay -  i  - array of integers
59e5c89e4eSSatish Balay 
60e5c89e4eSSatish Balay    Level: intermediate
61e5c89e4eSSatish Balay 
62e5c89e4eSSatish Balay .seealso: PetscSortReal(), PetscSortIntWithPermutation()
63e5c89e4eSSatish Balay @*/
647087cfbeSBarry Smith PetscErrorCode  PetscSortInt(PetscInt n,PetscInt i[])
65e5c89e4eSSatish Balay {
66e5c89e4eSSatish Balay   PetscInt j,k,tmp,ik;
67e5c89e4eSSatish Balay 
68e5c89e4eSSatish Balay   PetscFunctionBegin;
69e5c89e4eSSatish Balay   if (n<8) {
70e5c89e4eSSatish Balay     for (k=0; k<n; k++) {
71e5c89e4eSSatish Balay       ik = i[k];
72e5c89e4eSSatish Balay       for (j=k+1; j<n; j++) {
73e5c89e4eSSatish Balay         if (ik > i[j]) {
74e5c89e4eSSatish Balay           SWAP(i[k],i[j],tmp);
75e5c89e4eSSatish Balay           ik = i[k];
76e5c89e4eSSatish Balay         }
77e5c89e4eSSatish Balay       }
78e5c89e4eSSatish Balay     }
79a297a907SKarl Rupp   } else PetscSortInt_Private(i,n-1);
80e5c89e4eSSatish Balay   PetscFunctionReturn(0);
81e5c89e4eSSatish Balay }
82e5c89e4eSSatish Balay 
831db36a52SBarry Smith /*@
8422ab5688SLisandro Dalcin    PetscSortedRemoveDupsInt - Removes all duplicate entries of a sorted input array
8522ab5688SLisandro Dalcin 
8622ab5688SLisandro Dalcin    Not Collective
8722ab5688SLisandro Dalcin 
8822ab5688SLisandro Dalcin    Input Parameters:
8922ab5688SLisandro Dalcin +  n  - number of values
9022ab5688SLisandro Dalcin -  ii  - sorted array of integers
9122ab5688SLisandro Dalcin 
9222ab5688SLisandro Dalcin    Output Parameter:
9322ab5688SLisandro Dalcin .  n - number of non-redundant values
9422ab5688SLisandro Dalcin 
9522ab5688SLisandro Dalcin    Level: intermediate
9622ab5688SLisandro Dalcin 
9722ab5688SLisandro Dalcin .seealso: PetscSortInt()
9822ab5688SLisandro Dalcin @*/
9922ab5688SLisandro Dalcin PetscErrorCode  PetscSortedRemoveDupsInt(PetscInt *n,PetscInt ii[])
10022ab5688SLisandro Dalcin {
10122ab5688SLisandro Dalcin   PetscInt i,s = 0,N = *n, b = 0;
10222ab5688SLisandro Dalcin 
10322ab5688SLisandro Dalcin   PetscFunctionBegin;
10422ab5688SLisandro Dalcin   for (i=0; i<N-1; i++) {
10522ab5688SLisandro Dalcin     if (PetscUnlikely(ii[b+s+1] < ii[b])) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Input array is not sorted");
10622ab5688SLisandro Dalcin     if (ii[b+s+1] != ii[b]) {
10722ab5688SLisandro Dalcin       ii[b+1] = ii[b+s+1]; b++;
10822ab5688SLisandro Dalcin     } else s++;
10922ab5688SLisandro Dalcin   }
11022ab5688SLisandro Dalcin   *n = N - s;
11122ab5688SLisandro Dalcin   PetscFunctionReturn(0);
11222ab5688SLisandro Dalcin }
11322ab5688SLisandro Dalcin 
11422ab5688SLisandro Dalcin /*@
1151db36a52SBarry Smith    PetscSortRemoveDupsInt - Sorts an array of integers in place in increasing order removes all duplicate entries
1161db36a52SBarry Smith 
1171db36a52SBarry Smith    Not Collective
1181db36a52SBarry Smith 
1191db36a52SBarry Smith    Input Parameters:
1201db36a52SBarry Smith +  n  - number of values
1211db36a52SBarry Smith -  ii  - array of integers
1221db36a52SBarry Smith 
1231db36a52SBarry Smith    Output Parameter:
1241db36a52SBarry Smith .  n - number of non-redundant values
1251db36a52SBarry Smith 
1261db36a52SBarry Smith    Level: intermediate
1271db36a52SBarry Smith 
12822ab5688SLisandro Dalcin .seealso: PetscSortReal(), PetscSortIntWithPermutation(), PetscSortInt(), PetscSortedRemoveDupsInt()
1291db36a52SBarry Smith @*/
1307087cfbeSBarry Smith PetscErrorCode  PetscSortRemoveDupsInt(PetscInt *n,PetscInt ii[])
1311db36a52SBarry Smith {
1321db36a52SBarry Smith   PetscErrorCode ierr;
1331db36a52SBarry Smith 
1341db36a52SBarry Smith   PetscFunctionBegin;
13522ab5688SLisandro Dalcin   ierr = PetscSortInt(*n,ii);CHKERRQ(ierr);
13622ab5688SLisandro Dalcin   ierr = PetscSortedRemoveDupsInt(n,ii);CHKERRQ(ierr);
1371db36a52SBarry Smith   PetscFunctionReturn(0);
1381db36a52SBarry Smith }
1391db36a52SBarry Smith 
14060e03357SMatthew G Knepley /*@
141d9f1162dSJed Brown   PetscFindInt - Finds integer in a sorted array of integers
14260e03357SMatthew G Knepley 
14360e03357SMatthew G Knepley    Not Collective
14460e03357SMatthew G Knepley 
14560e03357SMatthew G Knepley    Input Parameters:
14660e03357SMatthew G Knepley +  key - the integer to locate
147d9f1162dSJed Brown .  n   - number of values in the array
14860e03357SMatthew G Knepley -  ii  - array of integers
14960e03357SMatthew G Knepley 
15060e03357SMatthew G Knepley    Output Parameter:
151d9f1162dSJed Brown .  loc - the location if found, otherwise -(slot+1) where slot is the place the value would go
15260e03357SMatthew G Knepley 
15360e03357SMatthew G Knepley    Level: intermediate
15460e03357SMatthew G Knepley 
15560e03357SMatthew G Knepley .seealso: PetscSortInt(), PetscSortIntWithArray(), PetscSortRemoveDupsInt()
15660e03357SMatthew G Knepley @*/
157026ec6cbSMatthew G Knepley PetscErrorCode PetscFindInt(PetscInt key, PetscInt n, const PetscInt ii[], PetscInt *loc)
15860e03357SMatthew G Knepley {
159d9f1162dSJed Brown   PetscInt lo = 0,hi = n;
16060e03357SMatthew G Knepley 
16160e03357SMatthew G Knepley   PetscFunctionBegin;
16260e03357SMatthew G Knepley   PetscValidPointer(loc,4);
16398781d82SMatthew G Knepley   if (!n) {*loc = -1; PetscFunctionReturn(0);}
16498781d82SMatthew G Knepley   PetscValidPointer(ii,3);
165d9f1162dSJed Brown   while (hi - lo > 1) {
166d9f1162dSJed Brown     PetscInt mid = lo + (hi - lo)/2;
167d9f1162dSJed Brown     if (key < ii[mid]) hi = mid;
168d9f1162dSJed Brown     else               lo = mid;
16960e03357SMatthew G Knepley   }
170d9f1162dSJed Brown   *loc = key == ii[lo] ? lo : -(lo + (key > ii[lo]) + 1);
17160e03357SMatthew G Knepley   PetscFunctionReturn(0);
17260e03357SMatthew G Knepley }
17360e03357SMatthew G Knepley 
174d2aeb606SJed Brown /*@
175d2aeb606SJed Brown   PetscFindMPIInt - Finds MPI integer in a sorted array of integers
176d2aeb606SJed Brown 
177d2aeb606SJed Brown    Not Collective
178d2aeb606SJed Brown 
179d2aeb606SJed Brown    Input Parameters:
180d2aeb606SJed Brown +  key - the integer to locate
181d2aeb606SJed Brown .  n   - number of values in the array
182d2aeb606SJed Brown -  ii  - array of integers
183d2aeb606SJed Brown 
184d2aeb606SJed Brown    Output Parameter:
185d2aeb606SJed Brown .  loc - the location if found, otherwise -(slot+1) where slot is the place the value would go
186d2aeb606SJed Brown 
187d2aeb606SJed Brown    Level: intermediate
188d2aeb606SJed Brown 
189d2aeb606SJed Brown .seealso: PetscSortInt(), PetscSortIntWithArray(), PetscSortRemoveDupsInt()
190d2aeb606SJed Brown @*/
191d2aeb606SJed Brown PetscErrorCode PetscFindMPIInt(PetscMPIInt key, PetscInt n, const PetscMPIInt ii[], PetscInt *loc)
192d2aeb606SJed Brown {
193d2aeb606SJed Brown   PetscInt lo = 0,hi = n;
194d2aeb606SJed Brown 
195d2aeb606SJed Brown   PetscFunctionBegin;
196d2aeb606SJed Brown   PetscValidPointer(loc,4);
197d2aeb606SJed Brown   if (!n) {*loc = -1; PetscFunctionReturn(0);}
198d2aeb606SJed Brown   PetscValidPointer(ii,3);
199d2aeb606SJed Brown   while (hi - lo > 1) {
200d2aeb606SJed Brown     PetscInt mid = lo + (hi - lo)/2;
201d2aeb606SJed Brown     if (key < ii[mid]) hi = mid;
202d2aeb606SJed Brown     else               lo = mid;
203d2aeb606SJed Brown   }
204d2aeb606SJed Brown   *loc = key == ii[lo] ? lo : -(lo + (key > ii[lo]) + 1);
205d2aeb606SJed Brown   PetscFunctionReturn(0);
206d2aeb606SJed Brown }
2071db36a52SBarry Smith 
208e5c89e4eSSatish Balay /* -----------------------------------------------------------------------*/
209e5c89e4eSSatish Balay #define SWAP2(a,b,c,d,t) {t=a;a=b;b=t;t=c;c=d;d=t;}
210e5c89e4eSSatish Balay 
211e5c89e4eSSatish Balay /*
212e5c89e4eSSatish Balay    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
213e5c89e4eSSatish Balay    Assumes 0 origin for v, number of elements = right+1 (right is index of
214e5c89e4eSSatish Balay    right-most member).
215e5c89e4eSSatish Balay */
216e5c89e4eSSatish Balay static PetscErrorCode PetscSortIntWithArray_Private(PetscInt *v,PetscInt *V,PetscInt right)
217e5c89e4eSSatish Balay {
218e5c89e4eSSatish Balay   PetscErrorCode ierr;
219e5c89e4eSSatish Balay   PetscInt       i,vl,last,tmp;
220e5c89e4eSSatish Balay 
221e5c89e4eSSatish Balay   PetscFunctionBegin;
222e5c89e4eSSatish Balay   if (right <= 1) {
223e5c89e4eSSatish Balay     if (right == 1) {
224e5c89e4eSSatish Balay       if (v[0] > v[1]) SWAP2(v[0],v[1],V[0],V[1],tmp);
225e5c89e4eSSatish Balay     }
226e5c89e4eSSatish Balay     PetscFunctionReturn(0);
227e5c89e4eSSatish Balay   }
228e5c89e4eSSatish Balay   SWAP2(v[0],v[right/2],V[0],V[right/2],tmp);
229e5c89e4eSSatish Balay   vl   = v[0];
230e5c89e4eSSatish Balay   last = 0;
231e5c89e4eSSatish Balay   for (i=1; i<=right; i++) {
232e5c89e4eSSatish Balay     if (v[i] < vl) {last++; SWAP2(v[last],v[i],V[last],V[i],tmp);}
233e5c89e4eSSatish Balay   }
234e5c89e4eSSatish Balay   SWAP2(v[0],v[last],V[0],V[last],tmp);
235e5c89e4eSSatish Balay   ierr = PetscSortIntWithArray_Private(v,V,last-1);CHKERRQ(ierr);
236e5c89e4eSSatish Balay   ierr = PetscSortIntWithArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr);
237e5c89e4eSSatish Balay   PetscFunctionReturn(0);
238e5c89e4eSSatish Balay }
239e5c89e4eSSatish Balay 
240e5c89e4eSSatish Balay /*@
241e5c89e4eSSatish Balay    PetscSortIntWithArray - Sorts an array of integers in place in increasing order;
242e5c89e4eSSatish Balay        changes a second array to match the sorted first array.
243e5c89e4eSSatish Balay 
244e5c89e4eSSatish Balay    Not Collective
245e5c89e4eSSatish Balay 
246e5c89e4eSSatish Balay    Input Parameters:
247e5c89e4eSSatish Balay +  n  - number of values
248e5c89e4eSSatish Balay .  i  - array of integers
249e5c89e4eSSatish Balay -  I - second array of integers
250e5c89e4eSSatish Balay 
251e5c89e4eSSatish Balay    Level: intermediate
252e5c89e4eSSatish Balay 
253e5c89e4eSSatish Balay .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt()
254e5c89e4eSSatish Balay @*/
2557087cfbeSBarry Smith PetscErrorCode  PetscSortIntWithArray(PetscInt n,PetscInt i[],PetscInt Ii[])
256e5c89e4eSSatish Balay {
257e5c89e4eSSatish Balay   PetscErrorCode ierr;
258e5c89e4eSSatish Balay   PetscInt       j,k,tmp,ik;
259e5c89e4eSSatish Balay 
260e5c89e4eSSatish Balay   PetscFunctionBegin;
261e5c89e4eSSatish Balay   if (n<8) {
262e5c89e4eSSatish Balay     for (k=0; k<n; k++) {
263e5c89e4eSSatish Balay       ik = i[k];
264e5c89e4eSSatish Balay       for (j=k+1; j<n; j++) {
265e5c89e4eSSatish Balay         if (ik > i[j]) {
266b7940d39SSatish Balay           SWAP2(i[k],i[j],Ii[k],Ii[j],tmp);
267e5c89e4eSSatish Balay           ik = i[k];
268e5c89e4eSSatish Balay         }
269e5c89e4eSSatish Balay       }
270e5c89e4eSSatish Balay     }
271e5c89e4eSSatish Balay   } else {
272b7940d39SSatish Balay     ierr = PetscSortIntWithArray_Private(i,Ii,n-1);CHKERRQ(ierr);
273e5c89e4eSSatish Balay   }
274e5c89e4eSSatish Balay   PetscFunctionReturn(0);
275e5c89e4eSSatish Balay }
276e5c89e4eSSatish Balay 
277c1f0200aSDmitry Karpeev 
278c1f0200aSDmitry 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;}
279c1f0200aSDmitry Karpeev 
280c1f0200aSDmitry Karpeev /*
281c1f0200aSDmitry Karpeev    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
282c1f0200aSDmitry Karpeev    Assumes 0 origin for v, number of elements = right+1 (right is index of
283c1f0200aSDmitry Karpeev    right-most member).
284c1f0200aSDmitry Karpeev */
285d7aa01a8SHong Zhang static PetscErrorCode PetscSortIntWithArrayPair_Private(PetscInt *L,PetscInt *J, PetscInt *K, PetscInt right)
286c1f0200aSDmitry Karpeev {
287c1f0200aSDmitry Karpeev   PetscErrorCode ierr;
288c1f0200aSDmitry Karpeev   PetscInt       i,vl,last,tmp;
289c1f0200aSDmitry Karpeev 
290c1f0200aSDmitry Karpeev   PetscFunctionBegin;
291c1f0200aSDmitry Karpeev   if (right <= 1) {
292c1f0200aSDmitry Karpeev     if (right == 1) {
293d7aa01a8SHong Zhang       if (L[0] > L[1]) SWAP3(L[0],L[1],J[0],J[1],K[0],K[1],tmp);
294c1f0200aSDmitry Karpeev     }
295c1f0200aSDmitry Karpeev     PetscFunctionReturn(0);
296c1f0200aSDmitry Karpeev   }
297d7aa01a8SHong Zhang   SWAP3(L[0],L[right/2],J[0],J[right/2],K[0],K[right/2],tmp);
298d7aa01a8SHong Zhang   vl   = L[0];
299c1f0200aSDmitry Karpeev   last = 0;
300c1f0200aSDmitry Karpeev   for (i=1; i<=right; i++) {
301d7aa01a8SHong Zhang     if (L[i] < vl) {last++; SWAP3(L[last],L[i],J[last],J[i],K[last],K[i],tmp);}
302c1f0200aSDmitry Karpeev   }
303d7aa01a8SHong Zhang   SWAP3(L[0],L[last],J[0],J[last],K[0],K[last],tmp);
304d7aa01a8SHong Zhang   ierr = PetscSortIntWithArrayPair_Private(L,J,K,last-1);CHKERRQ(ierr);
305d7aa01a8SHong Zhang   ierr = PetscSortIntWithArrayPair_Private(L+last+1,J+last+1,K+last+1,right-(last+1));CHKERRQ(ierr);
306c1f0200aSDmitry Karpeev   PetscFunctionReturn(0);
307c1f0200aSDmitry Karpeev }
308c1f0200aSDmitry Karpeev 
309c1f0200aSDmitry Karpeev /*@
310c1f0200aSDmitry Karpeev    PetscSortIntWithArrayPair - Sorts an array of integers in place in increasing order;
311c1f0200aSDmitry Karpeev        changes a pair of integer arrays to match the sorted first array.
312c1f0200aSDmitry Karpeev 
313c1f0200aSDmitry Karpeev    Not Collective
314c1f0200aSDmitry Karpeev 
315c1f0200aSDmitry Karpeev    Input Parameters:
316c1f0200aSDmitry Karpeev +  n  - number of values
317c1f0200aSDmitry Karpeev .  I  - array of integers
318c1f0200aSDmitry Karpeev .  J  - second array of integers (first array of the pair)
319c1f0200aSDmitry Karpeev -  K  - third array of integers  (second array of the pair)
320c1f0200aSDmitry Karpeev 
321c1f0200aSDmitry Karpeev    Level: intermediate
322c1f0200aSDmitry Karpeev 
323c1f0200aSDmitry Karpeev .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortIntWithArray()
324c1f0200aSDmitry Karpeev @*/
3256c2863d0SBarry Smith PetscErrorCode  PetscSortIntWithArrayPair(PetscInt n,PetscInt L[],PetscInt J[], PetscInt K[])
326c1f0200aSDmitry Karpeev {
327c1f0200aSDmitry Karpeev   PetscErrorCode ierr;
328c1f0200aSDmitry Karpeev   PetscInt       j,k,tmp,ik;
329c1f0200aSDmitry Karpeev 
330c1f0200aSDmitry Karpeev   PetscFunctionBegin;
331c1f0200aSDmitry Karpeev   if (n<8) {
332c1f0200aSDmitry Karpeev     for (k=0; k<n; k++) {
333d7aa01a8SHong Zhang       ik = L[k];
334c1f0200aSDmitry Karpeev       for (j=k+1; j<n; j++) {
335d7aa01a8SHong Zhang         if (ik > L[j]) {
336d7aa01a8SHong Zhang           SWAP3(L[k],L[j],J[k],J[j],K[k],K[j],tmp);
337d7aa01a8SHong Zhang           ik = L[k];
338c1f0200aSDmitry Karpeev         }
339c1f0200aSDmitry Karpeev       }
340c1f0200aSDmitry Karpeev     }
341c1f0200aSDmitry Karpeev   } else {
342d7aa01a8SHong Zhang     ierr = PetscSortIntWithArrayPair_Private(L,J,K,n-1);CHKERRQ(ierr);
343c1f0200aSDmitry Karpeev   }
344c1f0200aSDmitry Karpeev   PetscFunctionReturn(0);
345c1f0200aSDmitry Karpeev }
346c1f0200aSDmitry Karpeev 
34717d7d925SStefano Zampini /*
34817d7d925SStefano Zampini    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
34917d7d925SStefano Zampini    Assumes 0 origin for v, number of elements = right+1 (right is index of
35017d7d925SStefano Zampini    right-most member).
35117d7d925SStefano Zampini */
35217d7d925SStefano Zampini static void PetscSortMPIInt_Private(PetscMPIInt *v,PetscInt right)
35317d7d925SStefano Zampini {
35417d7d925SStefano Zampini   PetscInt          i,j;
35517d7d925SStefano Zampini   PetscMPIInt       pivot,tmp;
35617d7d925SStefano Zampini 
35717d7d925SStefano Zampini   if (right <= 1) {
35817d7d925SStefano Zampini     if (right == 1) {
35917d7d925SStefano Zampini       if (v[0] > v[1]) SWAP(v[0],v[1],tmp);
36017d7d925SStefano Zampini     }
36117d7d925SStefano Zampini     return;
36217d7d925SStefano Zampini   }
36317d7d925SStefano Zampini   i = MEDIAN(v,right);          /* Choose a pivot */
36417d7d925SStefano Zampini   SWAP(v[0],v[i],tmp);          /* Move it out of the way */
36517d7d925SStefano Zampini   pivot = v[0];
36617d7d925SStefano Zampini   for (i=0,j=right+1;; ) {
36717d7d925SStefano Zampini     while (++i < j && v[i] <= pivot) ; /* Scan from the left */
36817d7d925SStefano Zampini     while (v[--j] > pivot) ;           /* Scan from the right */
36917d7d925SStefano Zampini     if (i >= j) break;
37017d7d925SStefano Zampini     SWAP(v[i],v[j],tmp);
37117d7d925SStefano Zampini   }
37217d7d925SStefano Zampini   SWAP(v[0],v[j],tmp);          /* Put pivot back in place. */
37317d7d925SStefano Zampini   PetscSortMPIInt_Private(v,j-1);
37417d7d925SStefano Zampini   PetscSortMPIInt_Private(v+j+1,right-(j+1));
37517d7d925SStefano Zampini }
37617d7d925SStefano Zampini 
37717d7d925SStefano Zampini /*@
37817d7d925SStefano Zampini    PetscSortMPIInt - Sorts an array of MPI integers in place in increasing order.
37917d7d925SStefano Zampini 
38017d7d925SStefano Zampini    Not Collective
38117d7d925SStefano Zampini 
38217d7d925SStefano Zampini    Input Parameters:
38317d7d925SStefano Zampini +  n  - number of values
38417d7d925SStefano Zampini -  i  - array of integers
38517d7d925SStefano Zampini 
38617d7d925SStefano Zampini    Level: intermediate
38717d7d925SStefano Zampini 
38817d7d925SStefano Zampini .seealso: PetscSortReal(), PetscSortIntWithPermutation()
38917d7d925SStefano Zampini @*/
39017d7d925SStefano Zampini PetscErrorCode  PetscSortMPIInt(PetscInt n,PetscMPIInt i[])
39117d7d925SStefano Zampini {
39217d7d925SStefano Zampini   PetscInt    j,k;
39317d7d925SStefano Zampini   PetscMPIInt tmp,ik;
39417d7d925SStefano Zampini 
39517d7d925SStefano Zampini   PetscFunctionBegin;
39617d7d925SStefano Zampini   if (n<8) {
39717d7d925SStefano Zampini     for (k=0; k<n; k++) {
39817d7d925SStefano Zampini       ik = i[k];
39917d7d925SStefano Zampini       for (j=k+1; j<n; j++) {
40017d7d925SStefano Zampini         if (ik > i[j]) {
40117d7d925SStefano Zampini           SWAP(i[k],i[j],tmp);
40217d7d925SStefano Zampini           ik = i[k];
40317d7d925SStefano Zampini         }
40417d7d925SStefano Zampini       }
40517d7d925SStefano Zampini     }
406a297a907SKarl Rupp   } else PetscSortMPIInt_Private(i,n-1);
40717d7d925SStefano Zampini   PetscFunctionReturn(0);
40817d7d925SStefano Zampini }
40917d7d925SStefano Zampini 
41017d7d925SStefano Zampini /*@
41117d7d925SStefano Zampini    PetscSortRemoveDupsMPIInt - Sorts an array of MPI integers in place in increasing order removes all duplicate entries
41217d7d925SStefano Zampini 
41317d7d925SStefano Zampini    Not Collective
41417d7d925SStefano Zampini 
41517d7d925SStefano Zampini    Input Parameters:
41617d7d925SStefano Zampini +  n  - number of values
41717d7d925SStefano Zampini -  ii  - array of integers
41817d7d925SStefano Zampini 
41917d7d925SStefano Zampini    Output Parameter:
42017d7d925SStefano Zampini .  n - number of non-redundant values
42117d7d925SStefano Zampini 
42217d7d925SStefano Zampini    Level: intermediate
42317d7d925SStefano Zampini 
42417d7d925SStefano Zampini .seealso: PetscSortReal(), PetscSortIntWithPermutation(), PetscSortInt()
42517d7d925SStefano Zampini @*/
42617d7d925SStefano Zampini PetscErrorCode  PetscSortRemoveDupsMPIInt(PetscInt *n,PetscMPIInt ii[])
42717d7d925SStefano Zampini {
42817d7d925SStefano Zampini   PetscErrorCode ierr;
42917d7d925SStefano Zampini   PetscInt       i,s = 0,N = *n, b = 0;
43017d7d925SStefano Zampini 
43117d7d925SStefano Zampini   PetscFunctionBegin;
43217d7d925SStefano Zampini   ierr = PetscSortMPIInt(N,ii);CHKERRQ(ierr);
43317d7d925SStefano Zampini   for (i=0; i<N-1; i++) {
434a297a907SKarl Rupp     if (ii[b+s+1] != ii[b]) {
435a297a907SKarl Rupp       ii[b+1] = ii[b+s+1]; b++;
436a297a907SKarl Rupp     } else s++;
43717d7d925SStefano Zampini   }
43817d7d925SStefano Zampini   *n = N - s;
43917d7d925SStefano Zampini   PetscFunctionReturn(0);
44017d7d925SStefano Zampini }
441c1f0200aSDmitry Karpeev 
4424d615ea0SBarry Smith /*
4434d615ea0SBarry Smith    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
4444d615ea0SBarry Smith    Assumes 0 origin for v, number of elements = right+1 (right is index of
4454d615ea0SBarry Smith    right-most member).
4464d615ea0SBarry Smith */
4474d615ea0SBarry Smith static PetscErrorCode PetscSortMPIIntWithArray_Private(PetscMPIInt *v,PetscMPIInt *V,PetscMPIInt right)
4484d615ea0SBarry Smith {
4494d615ea0SBarry Smith   PetscErrorCode ierr;
4504d615ea0SBarry Smith   PetscMPIInt    i,vl,last,tmp;
4514d615ea0SBarry Smith 
4524d615ea0SBarry Smith   PetscFunctionBegin;
4534d615ea0SBarry Smith   if (right <= 1) {
4544d615ea0SBarry Smith     if (right == 1) {
4554d615ea0SBarry Smith       if (v[0] > v[1]) SWAP2(v[0],v[1],V[0],V[1],tmp);
4564d615ea0SBarry Smith     }
4574d615ea0SBarry Smith     PetscFunctionReturn(0);
4584d615ea0SBarry Smith   }
4594d615ea0SBarry Smith   SWAP2(v[0],v[right/2],V[0],V[right/2],tmp);
4604d615ea0SBarry Smith   vl   = v[0];
4614d615ea0SBarry Smith   last = 0;
4624d615ea0SBarry Smith   for (i=1; i<=right; i++) {
4634d615ea0SBarry Smith     if (v[i] < vl) {last++; SWAP2(v[last],v[i],V[last],V[i],tmp);}
4644d615ea0SBarry Smith   }
4654d615ea0SBarry Smith   SWAP2(v[0],v[last],V[0],V[last],tmp);
4664d615ea0SBarry Smith   ierr = PetscSortMPIIntWithArray_Private(v,V,last-1);CHKERRQ(ierr);
4674d615ea0SBarry Smith   ierr = PetscSortMPIIntWithArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr);
4684d615ea0SBarry Smith   PetscFunctionReturn(0);
4694d615ea0SBarry Smith }
4704d615ea0SBarry Smith 
4714d615ea0SBarry Smith /*@
4724d615ea0SBarry Smith    PetscSortMPIIntWithArray - Sorts an array of integers in place in increasing order;
4734d615ea0SBarry Smith        changes a second array to match the sorted first array.
4744d615ea0SBarry Smith 
4754d615ea0SBarry Smith    Not Collective
4764d615ea0SBarry Smith 
4774d615ea0SBarry Smith    Input Parameters:
4784d615ea0SBarry Smith +  n  - number of values
4794d615ea0SBarry Smith .  i  - array of integers
4804d615ea0SBarry Smith -  I - second array of integers
4814d615ea0SBarry Smith 
4824d615ea0SBarry Smith    Level: intermediate
4834d615ea0SBarry Smith 
4844d615ea0SBarry Smith .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt()
4854d615ea0SBarry Smith @*/
4867087cfbeSBarry Smith PetscErrorCode  PetscSortMPIIntWithArray(PetscMPIInt n,PetscMPIInt i[],PetscMPIInt Ii[])
4874d615ea0SBarry Smith {
4884d615ea0SBarry Smith   PetscErrorCode ierr;
4894d615ea0SBarry Smith   PetscMPIInt    j,k,tmp,ik;
4904d615ea0SBarry Smith 
4914d615ea0SBarry Smith   PetscFunctionBegin;
4924d615ea0SBarry Smith   if (n<8) {
4934d615ea0SBarry Smith     for (k=0; k<n; k++) {
4944d615ea0SBarry Smith       ik = i[k];
4954d615ea0SBarry Smith       for (j=k+1; j<n; j++) {
4964d615ea0SBarry Smith         if (ik > i[j]) {
4974d615ea0SBarry Smith           SWAP2(i[k],i[j],Ii[k],Ii[j],tmp);
4984d615ea0SBarry Smith           ik = i[k];
4994d615ea0SBarry Smith         }
5004d615ea0SBarry Smith       }
5014d615ea0SBarry Smith     }
5024d615ea0SBarry Smith   } else {
5034d615ea0SBarry Smith     ierr = PetscSortMPIIntWithArray_Private(i,Ii,n-1);CHKERRQ(ierr);
5044d615ea0SBarry Smith   }
5054d615ea0SBarry Smith   PetscFunctionReturn(0);
5064d615ea0SBarry Smith }
5074d615ea0SBarry Smith 
508e5c89e4eSSatish Balay /* -----------------------------------------------------------------------*/
5095569a785SJunchao Zhang #define SWAP2MPIIntInt(a,b,c,d,t1,t2) {t1=a;a=b;b=t1;t2=c;c=d;d=t2;}
5105569a785SJunchao Zhang 
5115569a785SJunchao Zhang /*
5125569a785SJunchao Zhang    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
5135569a785SJunchao Zhang    Assumes 0 origin for v, number of elements = right+1 (right is index of
5145569a785SJunchao Zhang    right-most member).
5155569a785SJunchao Zhang */
5165569a785SJunchao Zhang static PetscErrorCode PetscSortMPIIntWithIntArray_Private(PetscMPIInt *v,PetscInt *V,PetscMPIInt right)
5175569a785SJunchao Zhang {
5185569a785SJunchao Zhang   PetscErrorCode ierr;
5195569a785SJunchao Zhang   PetscMPIInt    i,vl,last,t1;
5205569a785SJunchao Zhang   PetscInt       t2;
5215569a785SJunchao Zhang 
5225569a785SJunchao Zhang   PetscFunctionBegin;
5235569a785SJunchao Zhang   if (right <= 1) {
5245569a785SJunchao Zhang     if (right == 1) {
5255569a785SJunchao Zhang       if (v[0] > v[1]) SWAP2MPIIntInt(v[0],v[1],V[0],V[1],t1,t2);
5265569a785SJunchao Zhang     }
5275569a785SJunchao Zhang     PetscFunctionReturn(0);
5285569a785SJunchao Zhang   }
5295569a785SJunchao Zhang   SWAP2MPIIntInt(v[0],v[right/2],V[0],V[right/2],t1,t2);
5305569a785SJunchao Zhang   vl   = v[0];
5315569a785SJunchao Zhang   last = 0;
5325569a785SJunchao Zhang   for (i=1; i<=right; i++) {
5335569a785SJunchao Zhang     if (v[i] < vl) {last++; SWAP2MPIIntInt(v[last],v[i],V[last],V[i],t1,t2);}
5345569a785SJunchao Zhang   }
5355569a785SJunchao Zhang   SWAP2MPIIntInt(v[0],v[last],V[0],V[last],t1,t2);
5365569a785SJunchao Zhang   ierr = PetscSortMPIIntWithIntArray_Private(v,V,last-1);CHKERRQ(ierr);
5375569a785SJunchao Zhang   ierr = PetscSortMPIIntWithIntArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr);
5385569a785SJunchao Zhang   PetscFunctionReturn(0);
5395569a785SJunchao Zhang }
5405569a785SJunchao Zhang 
5415569a785SJunchao Zhang /*@
5425569a785SJunchao Zhang    PetscSortMPIIntWithIntArray - Sorts an array of MPI integers in place in increasing order;
5435569a785SJunchao Zhang        changes a second array of Petsc intergers to match the sorted first array.
5445569a785SJunchao Zhang 
5455569a785SJunchao Zhang    Not Collective
5465569a785SJunchao Zhang 
5475569a785SJunchao Zhang    Input Parameters:
5485569a785SJunchao Zhang +  n  - number of values
5495569a785SJunchao Zhang .  i  - array of MPI integers
5505569a785SJunchao Zhang -  I - second array of Petsc integers
5515569a785SJunchao Zhang 
5525569a785SJunchao Zhang    Level: intermediate
5535569a785SJunchao Zhang 
5545569a785SJunchao Zhang    Notes: this routine is useful when one needs to sort MPI ranks with other integer arrays.
5555569a785SJunchao Zhang 
5565569a785SJunchao Zhang .seealso: PetscSortMPIIntWithArray()
5575569a785SJunchao Zhang @*/
5585569a785SJunchao Zhang PetscErrorCode PetscSortMPIIntWithIntArray(PetscMPIInt n,PetscMPIInt i[],PetscInt Ii[])
5595569a785SJunchao Zhang {
5605569a785SJunchao Zhang   PetscErrorCode ierr;
5615569a785SJunchao Zhang   PetscMPIInt    j,k,t1,ik;
5625569a785SJunchao Zhang   PetscInt       t2;
5635569a785SJunchao Zhang 
5645569a785SJunchao Zhang   PetscFunctionBegin;
5655569a785SJunchao Zhang   if (n<8) {
5665569a785SJunchao Zhang     for (k=0; k<n; k++) {
5675569a785SJunchao Zhang       ik = i[k];
5685569a785SJunchao Zhang       for (j=k+1; j<n; j++) {
5695569a785SJunchao Zhang         if (ik > i[j]) {
5705569a785SJunchao Zhang           SWAP2MPIIntInt(i[k],i[j],Ii[k],Ii[j],t1,t2);
5715569a785SJunchao Zhang           ik = i[k];
5725569a785SJunchao Zhang         }
5735569a785SJunchao Zhang       }
5745569a785SJunchao Zhang     }
5755569a785SJunchao Zhang   } else {
5765569a785SJunchao Zhang     ierr = PetscSortMPIIntWithIntArray_Private(i,Ii,n-1);CHKERRQ(ierr);
5775569a785SJunchao Zhang   }
5785569a785SJunchao Zhang   PetscFunctionReturn(0);
5795569a785SJunchao Zhang }
5805569a785SJunchao Zhang 
5815569a785SJunchao Zhang /* -----------------------------------------------------------------------*/
582e5c89e4eSSatish Balay #define SWAP2IntScalar(a,b,c,d,t,ts) {t=a;a=b;b=t;ts=c;c=d;d=ts;}
583e5c89e4eSSatish Balay 
584e5c89e4eSSatish Balay /*
585e5c89e4eSSatish Balay    Modified from PetscSortIntWithArray_Private().
586e5c89e4eSSatish Balay */
587e5c89e4eSSatish Balay static PetscErrorCode PetscSortIntWithScalarArray_Private(PetscInt *v,PetscScalar *V,PetscInt right)
588e5c89e4eSSatish Balay {
589e5c89e4eSSatish Balay   PetscErrorCode ierr;
590e5c89e4eSSatish Balay   PetscInt       i,vl,last,tmp;
591e5c89e4eSSatish Balay   PetscScalar    stmp;
592e5c89e4eSSatish Balay 
593e5c89e4eSSatish Balay   PetscFunctionBegin;
594e5c89e4eSSatish Balay   if (right <= 1) {
595e5c89e4eSSatish Balay     if (right == 1) {
596e5c89e4eSSatish Balay       if (v[0] > v[1]) SWAP2IntScalar(v[0],v[1],V[0],V[1],tmp,stmp);
597e5c89e4eSSatish Balay     }
598e5c89e4eSSatish Balay     PetscFunctionReturn(0);
599e5c89e4eSSatish Balay   }
600e5c89e4eSSatish Balay   SWAP2IntScalar(v[0],v[right/2],V[0],V[right/2],tmp,stmp);
601e5c89e4eSSatish Balay   vl   = v[0];
602e5c89e4eSSatish Balay   last = 0;
603e5c89e4eSSatish Balay   for (i=1; i<=right; i++) {
604e5c89e4eSSatish Balay     if (v[i] < vl) {last++; SWAP2IntScalar(v[last],v[i],V[last],V[i],tmp,stmp);}
605e5c89e4eSSatish Balay   }
606e5c89e4eSSatish Balay   SWAP2IntScalar(v[0],v[last],V[0],V[last],tmp,stmp);
607e5c89e4eSSatish Balay   ierr = PetscSortIntWithScalarArray_Private(v,V,last-1);CHKERRQ(ierr);
608e5c89e4eSSatish Balay   ierr = PetscSortIntWithScalarArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr);
609e5c89e4eSSatish Balay   PetscFunctionReturn(0);
610e5c89e4eSSatish Balay }
611e5c89e4eSSatish Balay 
612e5c89e4eSSatish Balay /*@
613e5c89e4eSSatish Balay    PetscSortIntWithScalarArray - Sorts an array of integers in place in increasing order;
614e5c89e4eSSatish Balay        changes a second SCALAR array to match the sorted first INTEGER array.
615e5c89e4eSSatish Balay 
616e5c89e4eSSatish Balay    Not Collective
617e5c89e4eSSatish Balay 
618e5c89e4eSSatish Balay    Input Parameters:
619e5c89e4eSSatish Balay +  n  - number of values
620e5c89e4eSSatish Balay .  i  - array of integers
621e5c89e4eSSatish Balay -  I - second array of scalars
622e5c89e4eSSatish Balay 
623e5c89e4eSSatish Balay    Level: intermediate
624e5c89e4eSSatish Balay 
625e5c89e4eSSatish Balay .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
626e5c89e4eSSatish Balay @*/
6277087cfbeSBarry Smith PetscErrorCode  PetscSortIntWithScalarArray(PetscInt n,PetscInt i[],PetscScalar Ii[])
628e5c89e4eSSatish Balay {
629e5c89e4eSSatish Balay   PetscErrorCode ierr;
630e5c89e4eSSatish Balay   PetscInt       j,k,tmp,ik;
631e5c89e4eSSatish Balay   PetscScalar    stmp;
632e5c89e4eSSatish Balay 
633e5c89e4eSSatish Balay   PetscFunctionBegin;
634e5c89e4eSSatish Balay   if (n<8) {
635e5c89e4eSSatish Balay     for (k=0; k<n; k++) {
636e5c89e4eSSatish Balay       ik = i[k];
637e5c89e4eSSatish Balay       for (j=k+1; j<n; j++) {
638e5c89e4eSSatish Balay         if (ik > i[j]) {
639b7940d39SSatish Balay           SWAP2IntScalar(i[k],i[j],Ii[k],Ii[j],tmp,stmp);
640e5c89e4eSSatish Balay           ik = i[k];
641e5c89e4eSSatish Balay         }
642e5c89e4eSSatish Balay       }
643e5c89e4eSSatish Balay     }
644e5c89e4eSSatish Balay   } else {
645b7940d39SSatish Balay     ierr = PetscSortIntWithScalarArray_Private(i,Ii,n-1);CHKERRQ(ierr);
646e5c89e4eSSatish Balay   }
647e5c89e4eSSatish Balay   PetscFunctionReturn(0);
648e5c89e4eSSatish Balay }
649e5c89e4eSSatish Balay 
650ece8f864SToby Isaac #define SWAP2IntData(a,b,c,d,t,td,siz)          \
651ece8f864SToby Isaac   do {                                          \
652ece8f864SToby Isaac   PetscErrorCode _ierr;                         \
653ece8f864SToby Isaac   t=a;a=b;b=t;                                  \
654ece8f864SToby Isaac   _ierr = PetscMemcpy(td,c,siz);CHKERRQ(_ierr); \
655ece8f864SToby Isaac   _ierr = PetscMemcpy(c,d,siz);CHKERRQ(_ierr);  \
656ece8f864SToby Isaac   _ierr = PetscMemcpy(d,td,siz);CHKERRQ(_ierr); \
657ece8f864SToby Isaac } while(0)
65817df18f2SToby Isaac 
65917df18f2SToby Isaac /*
66017df18f2SToby Isaac    Modified from PetscSortIntWithArray_Private().
66117df18f2SToby Isaac */
66217df18f2SToby Isaac static PetscErrorCode PetscSortIntWithDataArray_Private(PetscInt *v,char *V,PetscInt right,size_t size,void *work)
66317df18f2SToby Isaac {
66417df18f2SToby Isaac   PetscErrorCode ierr;
66517df18f2SToby Isaac   PetscInt       i,vl,last,tmp;
66617df18f2SToby Isaac 
66717df18f2SToby Isaac   PetscFunctionBegin;
66817df18f2SToby Isaac   if (right <= 1) {
66917df18f2SToby Isaac     if (right == 1) {
67017df18f2SToby Isaac       if (v[0] > v[1]) SWAP2IntData(v[0],v[1],V,V+size,tmp,work,size);
67117df18f2SToby Isaac     }
67217df18f2SToby Isaac     PetscFunctionReturn(0);
67317df18f2SToby Isaac   }
67417df18f2SToby Isaac   SWAP2IntData(v[0],v[right/2],V,V+size*(right/2),tmp,work,size);
67517df18f2SToby Isaac   vl   = v[0];
67617df18f2SToby Isaac   last = 0;
67717df18f2SToby Isaac   for (i=1; i<=right; i++) {
67817df18f2SToby Isaac     if (v[i] < vl) {last++; SWAP2IntData(v[last],v[i],V+size*last,V+size*i,tmp,work,size);}
67917df18f2SToby Isaac   }
68017df18f2SToby Isaac   SWAP2IntData(v[0],v[last],V,V + size*last,tmp,work,size);
68117df18f2SToby Isaac   ierr = PetscSortIntWithDataArray_Private(v,V,last-1,size,work);CHKERRQ(ierr);
68217df18f2SToby Isaac   ierr = PetscSortIntWithDataArray_Private(v+last+1,V+size*(last+1),right-(last+1),size,work);CHKERRQ(ierr);
68317df18f2SToby Isaac   PetscFunctionReturn(0);
68417df18f2SToby Isaac }
68517df18f2SToby Isaac 
6866c2863d0SBarry Smith /*@C
68717df18f2SToby Isaac    PetscSortIntWithDataArray - Sorts an array of integers in place in increasing order;
68817df18f2SToby Isaac        changes a second array to match the sorted first INTEGER array.  Unlike other sort routines, the user must
68917df18f2SToby Isaac        provide workspace (the size of an element in the data array) to use when sorting.
69017df18f2SToby Isaac 
69117df18f2SToby Isaac    Not Collective
69217df18f2SToby Isaac 
69317df18f2SToby Isaac    Input Parameters:
69417df18f2SToby Isaac +  n  - number of values
69517df18f2SToby Isaac .  i  - array of integers
69617df18f2SToby Isaac .  Ii - second array of data
69717df18f2SToby Isaac .  size - sizeof elements in the data array in bytes
69817df18f2SToby Isaac -  work - workspace of "size" bytes used when sorting
69917df18f2SToby Isaac 
70017df18f2SToby Isaac    Level: intermediate
70117df18f2SToby Isaac 
70217df18f2SToby Isaac .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
70317df18f2SToby Isaac @*/
70417df18f2SToby Isaac PetscErrorCode  PetscSortIntWithDataArray(PetscInt n,PetscInt i[],void *Ii,size_t size,void *work)
70517df18f2SToby Isaac {
70617df18f2SToby Isaac   char           *V = (char *) Ii;
70717df18f2SToby Isaac   PetscErrorCode ierr;
70817df18f2SToby Isaac   PetscInt       j,k,tmp,ik;
70917df18f2SToby Isaac 
71017df18f2SToby Isaac   PetscFunctionBegin;
71117df18f2SToby Isaac   if (n<8) {
71217df18f2SToby Isaac     for (k=0; k<n; k++) {
71317df18f2SToby Isaac       ik = i[k];
71417df18f2SToby Isaac       for (j=k+1; j<n; j++) {
71517df18f2SToby Isaac         if (ik > i[j]) {
71617df18f2SToby Isaac           SWAP2IntData(i[k],i[j],V+size*k,V+size*j,tmp,work,size);
71717df18f2SToby Isaac           ik = i[k];
71817df18f2SToby Isaac         }
71917df18f2SToby Isaac       }
72017df18f2SToby Isaac     }
72117df18f2SToby Isaac   } else {
72217df18f2SToby Isaac     ierr = PetscSortIntWithDataArray_Private(i,V,n-1,size,work);CHKERRQ(ierr);
72317df18f2SToby Isaac   }
72417df18f2SToby Isaac   PetscFunctionReturn(0);
72517df18f2SToby Isaac }
72617df18f2SToby Isaac 
727b4301105SBarry Smith 
72821e72a00SBarry Smith /*@
72921e72a00SBarry Smith    PetscMergeIntArray -     Merges two SORTED integer arrays, removes duplicate elements.
73021e72a00SBarry Smith 
73121e72a00SBarry Smith    Not Collective
73221e72a00SBarry Smith 
73321e72a00SBarry Smith    Input Parameters:
73421e72a00SBarry Smith +  an  - number of values in the first array
73521e72a00SBarry Smith .  aI  - first sorted array of integers
73621e72a00SBarry Smith .  bn  - number of values in the second array
73721e72a00SBarry Smith -  bI  - second array of integers
73821e72a00SBarry Smith 
73921e72a00SBarry Smith    Output Parameters:
74021e72a00SBarry Smith +  n   - number of values in the merged array
7416c2863d0SBarry Smith -  L   - merged sorted array, this is allocated if an array is not provided
74221e72a00SBarry Smith 
74321e72a00SBarry Smith    Level: intermediate
74421e72a00SBarry Smith 
74521e72a00SBarry Smith .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
74621e72a00SBarry Smith @*/
7476c2863d0SBarry Smith PetscErrorCode  PetscMergeIntArray(PetscInt an,const PetscInt aI[], PetscInt bn, const PetscInt bI[],  PetscInt *n, PetscInt **L)
74821e72a00SBarry Smith {
74921e72a00SBarry Smith   PetscErrorCode ierr;
75021e72a00SBarry Smith   PetscInt       *L_ = *L, ak, bk, k;
75121e72a00SBarry Smith 
75221e72a00SBarry Smith   if (!L_) {
75321e72a00SBarry Smith     ierr = PetscMalloc1(an+bn, L);CHKERRQ(ierr);
75421e72a00SBarry Smith     L_   = *L;
75521e72a00SBarry Smith   }
75621e72a00SBarry Smith   k = ak = bk = 0;
75721e72a00SBarry Smith   while (ak < an && bk < bn) {
75821e72a00SBarry Smith     if (aI[ak] == bI[bk]) {
75921e72a00SBarry Smith       L_[k] = aI[ak];
76021e72a00SBarry Smith       ++ak;
76121e72a00SBarry Smith       ++bk;
76221e72a00SBarry Smith       ++k;
76321e72a00SBarry Smith     } else if (aI[ak] < bI[bk]) {
76421e72a00SBarry Smith       L_[k] = aI[ak];
76521e72a00SBarry Smith       ++ak;
76621e72a00SBarry Smith       ++k;
76721e72a00SBarry Smith     } else {
76821e72a00SBarry Smith       L_[k] = bI[bk];
76921e72a00SBarry Smith       ++bk;
77021e72a00SBarry Smith       ++k;
77121e72a00SBarry Smith     }
77221e72a00SBarry Smith   }
77321e72a00SBarry Smith   if (ak < an) {
774*580bdb30SBarry Smith     ierr = PetscArraycpy(L_+k,aI+ak,an-ak);CHKERRQ(ierr);
77521e72a00SBarry Smith     k   += (an-ak);
77621e72a00SBarry Smith   }
77721e72a00SBarry Smith   if (bk < bn) {
778*580bdb30SBarry Smith     ierr = PetscArraycpy(L_+k,bI+bk,bn-bk);CHKERRQ(ierr);
77921e72a00SBarry Smith     k   += (bn-bk);
78021e72a00SBarry Smith   }
78121e72a00SBarry Smith   *n = k;
78221e72a00SBarry Smith   PetscFunctionReturn(0);
78321e72a00SBarry Smith }
784b4301105SBarry Smith 
785c1f0200aSDmitry Karpeev /*@
78621e72a00SBarry Smith    PetscMergeIntArrayPair -     Merges two SORTED integer arrays that share NO common values along with an additional array of integers.
787c1f0200aSDmitry Karpeev                                 The additional arrays are the same length as sorted arrays and are merged
788c1f0200aSDmitry Karpeev                                 in the order determined by the merging of the sorted pair.
789c1f0200aSDmitry Karpeev 
790c1f0200aSDmitry Karpeev    Not Collective
791c1f0200aSDmitry Karpeev 
792c1f0200aSDmitry Karpeev    Input Parameters:
793c1f0200aSDmitry Karpeev +  an  - number of values in the first array
794c1f0200aSDmitry Karpeev .  aI  - first sorted array of integers
795c1f0200aSDmitry Karpeev .  aJ  - first additional array of integers
796c1f0200aSDmitry Karpeev .  bn  - number of values in the second array
797c1f0200aSDmitry Karpeev .  bI  - second array of integers
798c1f0200aSDmitry Karpeev -  bJ  - second additional of integers
799c1f0200aSDmitry Karpeev 
800c1f0200aSDmitry Karpeev    Output Parameters:
801c1f0200aSDmitry Karpeev +  n   - number of values in the merged array (== an + bn)
80214c49006SJed Brown .  L   - merged sorted array
803c1f0200aSDmitry Karpeev -  J   - merged additional array
804c1f0200aSDmitry Karpeev 
80595452b02SPatrick Sanan    Notes:
80695452b02SPatrick Sanan     if L or J point to non-null arrays then this routine will assume they are of the approproate size and use them, otherwise this routine will allocate space for them
807c1f0200aSDmitry Karpeev    Level: intermediate
808c1f0200aSDmitry Karpeev 
809c1f0200aSDmitry Karpeev .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
810c1f0200aSDmitry Karpeev @*/
8116c2863d0SBarry Smith PetscErrorCode  PetscMergeIntArrayPair(PetscInt an,const PetscInt aI[], const PetscInt aJ[], PetscInt bn, const PetscInt bI[], const PetscInt bJ[], PetscInt *n, PetscInt **L, PetscInt **J)
812c1f0200aSDmitry Karpeev {
813c1f0200aSDmitry Karpeev   PetscErrorCode ierr;
81470d8d27cSBarry Smith   PetscInt       n_, *L_, *J_, ak, bk, k;
815c1f0200aSDmitry Karpeev 
81614c49006SJed Brown   PetscFunctionBegin;
81770d8d27cSBarry Smith   PetscValidIntPointer(L,8);
81870d8d27cSBarry Smith   PetscValidIntPointer(J,9);
819c1f0200aSDmitry Karpeev   n_ = an + bn;
820c1f0200aSDmitry Karpeev   *n = n_;
82170d8d27cSBarry Smith   if (!*L) {
822785e854fSJed Brown     ierr = PetscMalloc1(n_, L);CHKERRQ(ierr);
82370d8d27cSBarry Smith   }
824d7aa01a8SHong Zhang   L_ = *L;
82570d8d27cSBarry Smith   if (!*J) {
82670d8d27cSBarry Smith     ierr = PetscMalloc1(n_, J);CHKERRQ(ierr);
827c1f0200aSDmitry Karpeev   }
828c1f0200aSDmitry Karpeev   J_   = *J;
829c1f0200aSDmitry Karpeev   k = ak = bk = 0;
830c1f0200aSDmitry Karpeev   while (ak < an && bk < bn) {
831c1f0200aSDmitry Karpeev     if (aI[ak] <= bI[bk]) {
832d7aa01a8SHong Zhang       L_[k] = aI[ak];
833c1f0200aSDmitry Karpeev       J_[k] = aJ[ak];
834c1f0200aSDmitry Karpeev       ++ak;
835c1f0200aSDmitry Karpeev       ++k;
836a297a907SKarl Rupp     } else {
837d7aa01a8SHong Zhang       L_[k] = bI[bk];
838c1f0200aSDmitry Karpeev       J_[k] = bJ[bk];
839c1f0200aSDmitry Karpeev       ++bk;
840c1f0200aSDmitry Karpeev       ++k;
841c1f0200aSDmitry Karpeev     }
842c1f0200aSDmitry Karpeev   }
843c1f0200aSDmitry Karpeev   if (ak < an) {
844*580bdb30SBarry Smith     ierr = PetscArraycpy(L_+k,aI+ak,an-ak);CHKERRQ(ierr);
845*580bdb30SBarry Smith     ierr = PetscArraycpy(J_+k,aJ+ak,an-ak);CHKERRQ(ierr);
846c1f0200aSDmitry Karpeev     k   += (an-ak);
847c1f0200aSDmitry Karpeev   }
848c1f0200aSDmitry Karpeev   if (bk < bn) {
849*580bdb30SBarry Smith     ierr = PetscArraycpy(L_+k,bI+bk,bn-bk);CHKERRQ(ierr);
850*580bdb30SBarry Smith     ierr = PetscArraycpy(J_+k,bJ+bk,bn-bk);CHKERRQ(ierr);
851c1f0200aSDmitry Karpeev   }
852c1f0200aSDmitry Karpeev   PetscFunctionReturn(0);
853c1f0200aSDmitry Karpeev }
854c1f0200aSDmitry Karpeev 
855e498c390SJed Brown /*@
856e498c390SJed Brown    PetscMergeMPIIntArray -     Merges two SORTED integer arrays.
857e498c390SJed Brown 
858e498c390SJed Brown    Not Collective
859e498c390SJed Brown 
860e498c390SJed Brown    Input Parameters:
861e498c390SJed Brown +  an  - number of values in the first array
862e498c390SJed Brown .  aI  - first sorted array of integers
863e498c390SJed Brown .  bn  - number of values in the second array
864e498c390SJed Brown -  bI  - second array of integers
865e498c390SJed Brown 
866e498c390SJed Brown    Output Parameters:
867e498c390SJed Brown +  n   - number of values in the merged array (<= an + bn)
868e498c390SJed Brown -  L   - merged sorted array, allocated if address of NULL pointer is passed
869e498c390SJed Brown 
870e498c390SJed Brown    Level: intermediate
871e498c390SJed Brown 
872e498c390SJed Brown .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
873e498c390SJed Brown @*/
874e498c390SJed Brown PetscErrorCode PetscMergeMPIIntArray(PetscInt an,const PetscMPIInt aI[],PetscInt bn,const PetscMPIInt bI[],PetscInt *n,PetscMPIInt **L)
875e498c390SJed Brown {
876e498c390SJed Brown   PetscErrorCode ierr;
877e498c390SJed Brown   PetscInt       ai,bi,k;
878e498c390SJed Brown 
879e498c390SJed Brown   PetscFunctionBegin;
880e498c390SJed Brown   if (!*L) {ierr = PetscMalloc1((an+bn),L);CHKERRQ(ierr);}
881e498c390SJed Brown   for (ai=0,bi=0,k=0; ai<an || bi<bn; ) {
882e498c390SJed Brown     PetscInt t = -1;
883e498c390SJed Brown     for ( ; ai<an && (!bn || aI[ai] <= bI[bi]); ai++) (*L)[k++] = t = aI[ai];
884e498c390SJed Brown     for ( ; bi<bn && bI[bi] == t; bi++);
885e498c390SJed Brown     for ( ; bi<bn && (!an || bI[bi] <= aI[ai]); bi++) (*L)[k++] = t = bI[bi];
886e498c390SJed Brown     for ( ; ai<an && aI[ai] == t; ai++);
887e498c390SJed Brown   }
888e498c390SJed Brown   *n = k;
889e498c390SJed Brown   PetscFunctionReturn(0);
890e498c390SJed Brown }
891e5c89e4eSSatish Balay 
8926c2863d0SBarry Smith /*@C
89342eaa7f3SBarry Smith    PetscProcessTree - Prepares tree data to be displayed graphically
89442eaa7f3SBarry Smith 
89542eaa7f3SBarry Smith    Not Collective
89642eaa7f3SBarry Smith 
89742eaa7f3SBarry Smith    Input Parameters:
89842eaa7f3SBarry Smith +  n  - number of values
89942eaa7f3SBarry Smith .  mask - indicates those entries in the tree, location 0 is always masked
90042eaa7f3SBarry Smith -  parentid - indicates the parent of each entry
90142eaa7f3SBarry Smith 
90242eaa7f3SBarry Smith    Output Parameters:
90342eaa7f3SBarry Smith +  Nlevels - the number of levels
90442eaa7f3SBarry Smith .  Level - for each node tells its level
90542eaa7f3SBarry Smith .  Levelcnts - the number of nodes on each level
90642eaa7f3SBarry Smith .  Idbylevel - a list of ids on each of the levels, first level followed by second etc
90742eaa7f3SBarry Smith -  Column - for each id tells its column index
90842eaa7f3SBarry Smith 
9096c2863d0SBarry Smith    Level: developer
91042eaa7f3SBarry Smith 
91195452b02SPatrick Sanan    Notes:
91295452b02SPatrick Sanan     This code is not currently used
91342eaa7f3SBarry Smith 
91442eaa7f3SBarry Smith .seealso: PetscSortReal(), PetscSortIntWithPermutation()
91542eaa7f3SBarry Smith @*/
9167087cfbeSBarry Smith PetscErrorCode  PetscProcessTree(PetscInt n,const PetscBool mask[],const PetscInt parentid[],PetscInt *Nlevels,PetscInt **Level,PetscInt **Levelcnt,PetscInt **Idbylevel,PetscInt **Column)
91742eaa7f3SBarry Smith {
91842eaa7f3SBarry Smith   PetscInt       i,j,cnt,nmask = 0,nlevels = 0,*level,*levelcnt,levelmax = 0,*workid,*workparentid,tcnt = 0,*idbylevel,*column;
91942eaa7f3SBarry Smith   PetscErrorCode ierr;
920ace3abfcSBarry Smith   PetscBool      done = PETSC_FALSE;
92142eaa7f3SBarry Smith 
92242eaa7f3SBarry Smith   PetscFunctionBegin;
92342eaa7f3SBarry Smith   if (!mask[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Mask of 0th location must be set");
92442eaa7f3SBarry Smith   for (i=0; i<n; i++) {
92542eaa7f3SBarry Smith     if (mask[i]) continue;
92642eaa7f3SBarry Smith     if (parentid[i]  == i) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Node labeled as own parent");
92742eaa7f3SBarry Smith     if (parentid[i] && mask[parentid[i]]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Parent is masked");
92842eaa7f3SBarry Smith   }
92942eaa7f3SBarry Smith 
93042eaa7f3SBarry Smith   for (i=0; i<n; i++) {
93142eaa7f3SBarry Smith     if (!mask[i]) nmask++;
93242eaa7f3SBarry Smith   }
93342eaa7f3SBarry Smith 
93442eaa7f3SBarry Smith   /* determine the level in the tree of each node */
9351795a4d1SJed Brown   ierr = PetscCalloc1(n,&level);CHKERRQ(ierr);
936a297a907SKarl Rupp 
93742eaa7f3SBarry Smith   level[0] = 1;
93842eaa7f3SBarry Smith   while (!done) {
93942eaa7f3SBarry Smith     done = PETSC_TRUE;
94042eaa7f3SBarry Smith     for (i=0; i<n; i++) {
94142eaa7f3SBarry Smith       if (mask[i]) continue;
94242eaa7f3SBarry Smith       if (!level[i] && level[parentid[i]]) level[i] = level[parentid[i]] + 1;
94342eaa7f3SBarry Smith       else if (!level[i]) done = PETSC_FALSE;
94442eaa7f3SBarry Smith     }
94542eaa7f3SBarry Smith   }
94642eaa7f3SBarry Smith   for (i=0; i<n; i++) {
94742eaa7f3SBarry Smith     level[i]--;
94842eaa7f3SBarry Smith     nlevels = PetscMax(nlevels,level[i]);
94942eaa7f3SBarry Smith   }
95042eaa7f3SBarry Smith 
95142eaa7f3SBarry Smith   /* count the number of nodes on each level and its max */
9521795a4d1SJed Brown   ierr = PetscCalloc1(nlevels,&levelcnt);CHKERRQ(ierr);
95342eaa7f3SBarry Smith   for (i=0; i<n; i++) {
95442eaa7f3SBarry Smith     if (mask[i]) continue;
95542eaa7f3SBarry Smith     levelcnt[level[i]-1]++;
95642eaa7f3SBarry Smith   }
957a297a907SKarl Rupp   for (i=0; i<nlevels;i++) levelmax = PetscMax(levelmax,levelcnt[i]);
95842eaa7f3SBarry Smith 
95942eaa7f3SBarry Smith   /* for each level sort the ids by the parent id */
960dcca6d9dSJed Brown   ierr = PetscMalloc2(levelmax,&workid,levelmax,&workparentid);CHKERRQ(ierr);
961785e854fSJed Brown   ierr = PetscMalloc1(nmask,&idbylevel);CHKERRQ(ierr);
96242eaa7f3SBarry Smith   for (j=1; j<=nlevels;j++) {
96342eaa7f3SBarry Smith     cnt = 0;
96442eaa7f3SBarry Smith     for (i=0; i<n; i++) {
96542eaa7f3SBarry Smith       if (mask[i]) continue;
96642eaa7f3SBarry Smith       if (level[i] != j) continue;
96742eaa7f3SBarry Smith       workid[cnt]         = i;
96842eaa7f3SBarry Smith       workparentid[cnt++] = parentid[i];
96942eaa7f3SBarry Smith     }
97042eaa7f3SBarry Smith     /*  PetscIntView(cnt,workparentid,0);
97142eaa7f3SBarry Smith     PetscIntView(cnt,workid,0);
97242eaa7f3SBarry Smith     ierr = PetscSortIntWithArray(cnt,workparentid,workid);CHKERRQ(ierr);
97342eaa7f3SBarry Smith     PetscIntView(cnt,workparentid,0);
97442eaa7f3SBarry Smith     PetscIntView(cnt,workid,0);*/
975*580bdb30SBarry Smith     ierr  = PetscArraycpy(idbylevel+tcnt,workid,cnt);CHKERRQ(ierr);
97642eaa7f3SBarry Smith     tcnt += cnt;
97742eaa7f3SBarry Smith   }
97842eaa7f3SBarry Smith   if (tcnt != nmask) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Inconsistent count of unmasked nodes");
97942eaa7f3SBarry Smith   ierr = PetscFree2(workid,workparentid);CHKERRQ(ierr);
98042eaa7f3SBarry Smith 
98142eaa7f3SBarry Smith   /* for each node list its column */
982785e854fSJed Brown   ierr = PetscMalloc1(n,&column);CHKERRQ(ierr);
98342eaa7f3SBarry Smith   cnt = 0;
98442eaa7f3SBarry Smith   for (j=0; j<nlevels; j++) {
98542eaa7f3SBarry Smith     for (i=0; i<levelcnt[j]; i++) {
98642eaa7f3SBarry Smith       column[idbylevel[cnt++]] = i;
98742eaa7f3SBarry Smith     }
98842eaa7f3SBarry Smith   }
98942eaa7f3SBarry Smith 
99042eaa7f3SBarry Smith   *Nlevels   = nlevels;
99142eaa7f3SBarry Smith   *Level     = level;
99242eaa7f3SBarry Smith   *Levelcnt  = levelcnt;
99342eaa7f3SBarry Smith   *Idbylevel = idbylevel;
99442eaa7f3SBarry Smith   *Column    = column;
99542eaa7f3SBarry Smith   PetscFunctionReturn(0);
99642eaa7f3SBarry Smith }
997