xref: /petsc/src/sys/utils/sorti.c (revision 95452b02e12c0ee11232c7ff2b24b568a8e07e43)
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    Concepts: sorting^ints
63e5c89e4eSSatish Balay 
64e5c89e4eSSatish Balay .seealso: PetscSortReal(), PetscSortIntWithPermutation()
65e5c89e4eSSatish Balay @*/
667087cfbeSBarry Smith PetscErrorCode  PetscSortInt(PetscInt n,PetscInt i[])
67e5c89e4eSSatish Balay {
68e5c89e4eSSatish Balay   PetscInt j,k,tmp,ik;
69e5c89e4eSSatish Balay 
70e5c89e4eSSatish Balay   PetscFunctionBegin;
71e5c89e4eSSatish Balay   if (n<8) {
72e5c89e4eSSatish Balay     for (k=0; k<n; k++) {
73e5c89e4eSSatish Balay       ik = i[k];
74e5c89e4eSSatish Balay       for (j=k+1; j<n; j++) {
75e5c89e4eSSatish Balay         if (ik > i[j]) {
76e5c89e4eSSatish Balay           SWAP(i[k],i[j],tmp);
77e5c89e4eSSatish Balay           ik = i[k];
78e5c89e4eSSatish Balay         }
79e5c89e4eSSatish Balay       }
80e5c89e4eSSatish Balay     }
81a297a907SKarl Rupp   } else PetscSortInt_Private(i,n-1);
82e5c89e4eSSatish Balay   PetscFunctionReturn(0);
83e5c89e4eSSatish Balay }
84e5c89e4eSSatish Balay 
851db36a52SBarry Smith /*@
8622ab5688SLisandro Dalcin    PetscSortedRemoveDupsInt - Removes all duplicate entries of a sorted input array
8722ab5688SLisandro Dalcin 
8822ab5688SLisandro Dalcin    Not Collective
8922ab5688SLisandro Dalcin 
9022ab5688SLisandro Dalcin    Input Parameters:
9122ab5688SLisandro Dalcin +  n  - number of values
9222ab5688SLisandro Dalcin -  ii  - sorted array of integers
9322ab5688SLisandro Dalcin 
9422ab5688SLisandro Dalcin    Output Parameter:
9522ab5688SLisandro Dalcin .  n - number of non-redundant values
9622ab5688SLisandro Dalcin 
9722ab5688SLisandro Dalcin    Level: intermediate
9822ab5688SLisandro Dalcin 
9922ab5688SLisandro Dalcin    Concepts: sorting^ints
10022ab5688SLisandro Dalcin 
10122ab5688SLisandro Dalcin .seealso: PetscSortInt()
10222ab5688SLisandro Dalcin @*/
10322ab5688SLisandro Dalcin PetscErrorCode  PetscSortedRemoveDupsInt(PetscInt *n,PetscInt ii[])
10422ab5688SLisandro Dalcin {
10522ab5688SLisandro Dalcin   PetscInt i,s = 0,N = *n, b = 0;
10622ab5688SLisandro Dalcin 
10722ab5688SLisandro Dalcin   PetscFunctionBegin;
10822ab5688SLisandro Dalcin   for (i=0; i<N-1; i++) {
10922ab5688SLisandro Dalcin     if (PetscUnlikely(ii[b+s+1] < ii[b])) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Input array is not sorted");
11022ab5688SLisandro Dalcin     if (ii[b+s+1] != ii[b]) {
11122ab5688SLisandro Dalcin       ii[b+1] = ii[b+s+1]; b++;
11222ab5688SLisandro Dalcin     } else s++;
11322ab5688SLisandro Dalcin   }
11422ab5688SLisandro Dalcin   *n = N - s;
11522ab5688SLisandro Dalcin   PetscFunctionReturn(0);
11622ab5688SLisandro Dalcin }
11722ab5688SLisandro Dalcin 
11822ab5688SLisandro Dalcin /*@
1191db36a52SBarry Smith    PetscSortRemoveDupsInt - Sorts an array of integers in place in increasing order removes all duplicate entries
1201db36a52SBarry Smith 
1211db36a52SBarry Smith    Not Collective
1221db36a52SBarry Smith 
1231db36a52SBarry Smith    Input Parameters:
1241db36a52SBarry Smith +  n  - number of values
1251db36a52SBarry Smith -  ii  - array of integers
1261db36a52SBarry Smith 
1271db36a52SBarry Smith    Output Parameter:
1281db36a52SBarry Smith .  n - number of non-redundant values
1291db36a52SBarry Smith 
1301db36a52SBarry Smith    Level: intermediate
1311db36a52SBarry Smith 
1321db36a52SBarry Smith    Concepts: sorting^ints
1331db36a52SBarry Smith 
13422ab5688SLisandro Dalcin .seealso: PetscSortReal(), PetscSortIntWithPermutation(), PetscSortInt(), PetscSortedRemoveDupsInt()
1351db36a52SBarry Smith @*/
1367087cfbeSBarry Smith PetscErrorCode  PetscSortRemoveDupsInt(PetscInt *n,PetscInt ii[])
1371db36a52SBarry Smith {
1381db36a52SBarry Smith   PetscErrorCode ierr;
1391db36a52SBarry Smith 
1401db36a52SBarry Smith   PetscFunctionBegin;
14122ab5688SLisandro Dalcin   ierr = PetscSortInt(*n,ii);CHKERRQ(ierr);
14222ab5688SLisandro Dalcin   ierr = PetscSortedRemoveDupsInt(n,ii);CHKERRQ(ierr);
1431db36a52SBarry Smith   PetscFunctionReturn(0);
1441db36a52SBarry Smith }
1451db36a52SBarry Smith 
14660e03357SMatthew G Knepley /*@
147d9f1162dSJed Brown   PetscFindInt - Finds integer in a sorted array of integers
14860e03357SMatthew G Knepley 
14960e03357SMatthew G Knepley    Not Collective
15060e03357SMatthew G Knepley 
15160e03357SMatthew G Knepley    Input Parameters:
15260e03357SMatthew G Knepley +  key - the integer to locate
153d9f1162dSJed Brown .  n   - number of values in the array
15460e03357SMatthew G Knepley -  ii  - array of integers
15560e03357SMatthew G Knepley 
15660e03357SMatthew G Knepley    Output Parameter:
157d9f1162dSJed Brown .  loc - the location if found, otherwise -(slot+1) where slot is the place the value would go
15860e03357SMatthew G Knepley 
15960e03357SMatthew G Knepley    Level: intermediate
16060e03357SMatthew G Knepley 
16160e03357SMatthew G Knepley    Concepts: sorting^ints
16260e03357SMatthew G Knepley 
16360e03357SMatthew G Knepley .seealso: PetscSortInt(), PetscSortIntWithArray(), PetscSortRemoveDupsInt()
16460e03357SMatthew G Knepley @*/
165026ec6cbSMatthew G Knepley PetscErrorCode PetscFindInt(PetscInt key, PetscInt n, const PetscInt ii[], PetscInt *loc)
16660e03357SMatthew G Knepley {
167d9f1162dSJed Brown   PetscInt lo = 0,hi = n;
16860e03357SMatthew G Knepley 
16960e03357SMatthew G Knepley   PetscFunctionBegin;
17060e03357SMatthew G Knepley   PetscValidPointer(loc,4);
17198781d82SMatthew G Knepley   if (!n) {*loc = -1; PetscFunctionReturn(0);}
17298781d82SMatthew G Knepley   PetscValidPointer(ii,3);
173d9f1162dSJed Brown   while (hi - lo > 1) {
174d9f1162dSJed Brown     PetscInt mid = lo + (hi - lo)/2;
175d9f1162dSJed Brown     if (key < ii[mid]) hi = mid;
176d9f1162dSJed Brown     else               lo = mid;
17760e03357SMatthew G Knepley   }
178d9f1162dSJed Brown   *loc = key == ii[lo] ? lo : -(lo + (key > ii[lo]) + 1);
17960e03357SMatthew G Knepley   PetscFunctionReturn(0);
18060e03357SMatthew G Knepley }
18160e03357SMatthew G Knepley 
182d2aeb606SJed Brown /*@
183d2aeb606SJed Brown   PetscFindMPIInt - Finds MPI integer in a sorted array of integers
184d2aeb606SJed Brown 
185d2aeb606SJed Brown    Not Collective
186d2aeb606SJed Brown 
187d2aeb606SJed Brown    Input Parameters:
188d2aeb606SJed Brown +  key - the integer to locate
189d2aeb606SJed Brown .  n   - number of values in the array
190d2aeb606SJed Brown -  ii  - array of integers
191d2aeb606SJed Brown 
192d2aeb606SJed Brown    Output Parameter:
193d2aeb606SJed Brown .  loc - the location if found, otherwise -(slot+1) where slot is the place the value would go
194d2aeb606SJed Brown 
195d2aeb606SJed Brown    Level: intermediate
196d2aeb606SJed Brown 
197d2aeb606SJed Brown    Concepts: sorting^ints
198d2aeb606SJed Brown 
199d2aeb606SJed Brown .seealso: PetscSortInt(), PetscSortIntWithArray(), PetscSortRemoveDupsInt()
200d2aeb606SJed Brown @*/
201d2aeb606SJed Brown PetscErrorCode PetscFindMPIInt(PetscMPIInt key, PetscInt n, const PetscMPIInt ii[], PetscInt *loc)
202d2aeb606SJed Brown {
203d2aeb606SJed Brown   PetscInt lo = 0,hi = n;
204d2aeb606SJed Brown 
205d2aeb606SJed Brown   PetscFunctionBegin;
206d2aeb606SJed Brown   PetscValidPointer(loc,4);
207d2aeb606SJed Brown   if (!n) {*loc = -1; PetscFunctionReturn(0);}
208d2aeb606SJed Brown   PetscValidPointer(ii,3);
209d2aeb606SJed Brown   while (hi - lo > 1) {
210d2aeb606SJed Brown     PetscInt mid = lo + (hi - lo)/2;
211d2aeb606SJed Brown     if (key < ii[mid]) hi = mid;
212d2aeb606SJed Brown     else               lo = mid;
213d2aeb606SJed Brown   }
214d2aeb606SJed Brown   *loc = key == ii[lo] ? lo : -(lo + (key > ii[lo]) + 1);
215d2aeb606SJed Brown   PetscFunctionReturn(0);
216d2aeb606SJed Brown }
2171db36a52SBarry Smith 
218e5c89e4eSSatish Balay /* -----------------------------------------------------------------------*/
219e5c89e4eSSatish Balay #define SWAP2(a,b,c,d,t) {t=a;a=b;b=t;t=c;c=d;d=t;}
220e5c89e4eSSatish Balay 
221e5c89e4eSSatish Balay /*
222e5c89e4eSSatish Balay    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
223e5c89e4eSSatish Balay    Assumes 0 origin for v, number of elements = right+1 (right is index of
224e5c89e4eSSatish Balay    right-most member).
225e5c89e4eSSatish Balay */
226e5c89e4eSSatish Balay static PetscErrorCode PetscSortIntWithArray_Private(PetscInt *v,PetscInt *V,PetscInt right)
227e5c89e4eSSatish Balay {
228e5c89e4eSSatish Balay   PetscErrorCode ierr;
229e5c89e4eSSatish Balay   PetscInt       i,vl,last,tmp;
230e5c89e4eSSatish Balay 
231e5c89e4eSSatish Balay   PetscFunctionBegin;
232e5c89e4eSSatish Balay   if (right <= 1) {
233e5c89e4eSSatish Balay     if (right == 1) {
234e5c89e4eSSatish Balay       if (v[0] > v[1]) SWAP2(v[0],v[1],V[0],V[1],tmp);
235e5c89e4eSSatish Balay     }
236e5c89e4eSSatish Balay     PetscFunctionReturn(0);
237e5c89e4eSSatish Balay   }
238e5c89e4eSSatish Balay   SWAP2(v[0],v[right/2],V[0],V[right/2],tmp);
239e5c89e4eSSatish Balay   vl   = v[0];
240e5c89e4eSSatish Balay   last = 0;
241e5c89e4eSSatish Balay   for (i=1; i<=right; i++) {
242e5c89e4eSSatish Balay     if (v[i] < vl) {last++; SWAP2(v[last],v[i],V[last],V[i],tmp);}
243e5c89e4eSSatish Balay   }
244e5c89e4eSSatish Balay   SWAP2(v[0],v[last],V[0],V[last],tmp);
245e5c89e4eSSatish Balay   ierr = PetscSortIntWithArray_Private(v,V,last-1);CHKERRQ(ierr);
246e5c89e4eSSatish Balay   ierr = PetscSortIntWithArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr);
247e5c89e4eSSatish Balay   PetscFunctionReturn(0);
248e5c89e4eSSatish Balay }
249e5c89e4eSSatish Balay 
250e5c89e4eSSatish Balay /*@
251e5c89e4eSSatish Balay    PetscSortIntWithArray - Sorts an array of integers in place in increasing order;
252e5c89e4eSSatish Balay        changes a second array to match the sorted first array.
253e5c89e4eSSatish Balay 
254e5c89e4eSSatish Balay    Not Collective
255e5c89e4eSSatish Balay 
256e5c89e4eSSatish Balay    Input Parameters:
257e5c89e4eSSatish Balay +  n  - number of values
258e5c89e4eSSatish Balay .  i  - array of integers
259e5c89e4eSSatish Balay -  I - second array of integers
260e5c89e4eSSatish Balay 
261e5c89e4eSSatish Balay    Level: intermediate
262e5c89e4eSSatish Balay 
263e5c89e4eSSatish Balay    Concepts: sorting^ints with array
264e5c89e4eSSatish Balay 
265e5c89e4eSSatish Balay .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt()
266e5c89e4eSSatish Balay @*/
2677087cfbeSBarry Smith PetscErrorCode  PetscSortIntWithArray(PetscInt n,PetscInt i[],PetscInt Ii[])
268e5c89e4eSSatish Balay {
269e5c89e4eSSatish Balay   PetscErrorCode ierr;
270e5c89e4eSSatish Balay   PetscInt       j,k,tmp,ik;
271e5c89e4eSSatish Balay 
272e5c89e4eSSatish Balay   PetscFunctionBegin;
273e5c89e4eSSatish Balay   if (n<8) {
274e5c89e4eSSatish Balay     for (k=0; k<n; k++) {
275e5c89e4eSSatish Balay       ik = i[k];
276e5c89e4eSSatish Balay       for (j=k+1; j<n; j++) {
277e5c89e4eSSatish Balay         if (ik > i[j]) {
278b7940d39SSatish Balay           SWAP2(i[k],i[j],Ii[k],Ii[j],tmp);
279e5c89e4eSSatish Balay           ik = i[k];
280e5c89e4eSSatish Balay         }
281e5c89e4eSSatish Balay       }
282e5c89e4eSSatish Balay     }
283e5c89e4eSSatish Balay   } else {
284b7940d39SSatish Balay     ierr = PetscSortIntWithArray_Private(i,Ii,n-1);CHKERRQ(ierr);
285e5c89e4eSSatish Balay   }
286e5c89e4eSSatish Balay   PetscFunctionReturn(0);
287e5c89e4eSSatish Balay }
288e5c89e4eSSatish Balay 
289c1f0200aSDmitry Karpeev 
290c1f0200aSDmitry 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;}
291c1f0200aSDmitry Karpeev 
292c1f0200aSDmitry Karpeev /*
293c1f0200aSDmitry Karpeev    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
294c1f0200aSDmitry Karpeev    Assumes 0 origin for v, number of elements = right+1 (right is index of
295c1f0200aSDmitry Karpeev    right-most member).
296c1f0200aSDmitry Karpeev */
297d7aa01a8SHong Zhang static PetscErrorCode PetscSortIntWithArrayPair_Private(PetscInt *L,PetscInt *J, PetscInt *K, PetscInt right)
298c1f0200aSDmitry Karpeev {
299c1f0200aSDmitry Karpeev   PetscErrorCode ierr;
300c1f0200aSDmitry Karpeev   PetscInt       i,vl,last,tmp;
301c1f0200aSDmitry Karpeev 
302c1f0200aSDmitry Karpeev   PetscFunctionBegin;
303c1f0200aSDmitry Karpeev   if (right <= 1) {
304c1f0200aSDmitry Karpeev     if (right == 1) {
305d7aa01a8SHong Zhang       if (L[0] > L[1]) SWAP3(L[0],L[1],J[0],J[1],K[0],K[1],tmp);
306c1f0200aSDmitry Karpeev     }
307c1f0200aSDmitry Karpeev     PetscFunctionReturn(0);
308c1f0200aSDmitry Karpeev   }
309d7aa01a8SHong Zhang   SWAP3(L[0],L[right/2],J[0],J[right/2],K[0],K[right/2],tmp);
310d7aa01a8SHong Zhang   vl   = L[0];
311c1f0200aSDmitry Karpeev   last = 0;
312c1f0200aSDmitry Karpeev   for (i=1; i<=right; i++) {
313d7aa01a8SHong Zhang     if (L[i] < vl) {last++; SWAP3(L[last],L[i],J[last],J[i],K[last],K[i],tmp);}
314c1f0200aSDmitry Karpeev   }
315d7aa01a8SHong Zhang   SWAP3(L[0],L[last],J[0],J[last],K[0],K[last],tmp);
316d7aa01a8SHong Zhang   ierr = PetscSortIntWithArrayPair_Private(L,J,K,last-1);CHKERRQ(ierr);
317d7aa01a8SHong Zhang   ierr = PetscSortIntWithArrayPair_Private(L+last+1,J+last+1,K+last+1,right-(last+1));CHKERRQ(ierr);
318c1f0200aSDmitry Karpeev   PetscFunctionReturn(0);
319c1f0200aSDmitry Karpeev }
320c1f0200aSDmitry Karpeev 
321c1f0200aSDmitry Karpeev /*@
322c1f0200aSDmitry Karpeev    PetscSortIntWithArrayPair - Sorts an array of integers in place in increasing order;
323c1f0200aSDmitry Karpeev        changes a pair of integer arrays to match the sorted first array.
324c1f0200aSDmitry Karpeev 
325c1f0200aSDmitry Karpeev    Not Collective
326c1f0200aSDmitry Karpeev 
327c1f0200aSDmitry Karpeev    Input Parameters:
328c1f0200aSDmitry Karpeev +  n  - number of values
329c1f0200aSDmitry Karpeev .  I  - array of integers
330c1f0200aSDmitry Karpeev .  J  - second array of integers (first array of the pair)
331c1f0200aSDmitry Karpeev -  K  - third array of integers  (second array of the pair)
332c1f0200aSDmitry Karpeev 
333c1f0200aSDmitry Karpeev    Level: intermediate
334c1f0200aSDmitry Karpeev 
335c1f0200aSDmitry Karpeev    Concepts: sorting^ints with array pair
336c1f0200aSDmitry Karpeev 
337c1f0200aSDmitry Karpeev .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortIntWithArray()
338c1f0200aSDmitry Karpeev @*/
3396c2863d0SBarry Smith PetscErrorCode  PetscSortIntWithArrayPair(PetscInt n,PetscInt L[],PetscInt J[], PetscInt K[])
340c1f0200aSDmitry Karpeev {
341c1f0200aSDmitry Karpeev   PetscErrorCode ierr;
342c1f0200aSDmitry Karpeev   PetscInt       j,k,tmp,ik;
343c1f0200aSDmitry Karpeev 
344c1f0200aSDmitry Karpeev   PetscFunctionBegin;
345c1f0200aSDmitry Karpeev   if (n<8) {
346c1f0200aSDmitry Karpeev     for (k=0; k<n; k++) {
347d7aa01a8SHong Zhang       ik = L[k];
348c1f0200aSDmitry Karpeev       for (j=k+1; j<n; j++) {
349d7aa01a8SHong Zhang         if (ik > L[j]) {
350d7aa01a8SHong Zhang           SWAP3(L[k],L[j],J[k],J[j],K[k],K[j],tmp);
351d7aa01a8SHong Zhang           ik = L[k];
352c1f0200aSDmitry Karpeev         }
353c1f0200aSDmitry Karpeev       }
354c1f0200aSDmitry Karpeev     }
355c1f0200aSDmitry Karpeev   } else {
356d7aa01a8SHong Zhang     ierr = PetscSortIntWithArrayPair_Private(L,J,K,n-1);CHKERRQ(ierr);
357c1f0200aSDmitry Karpeev   }
358c1f0200aSDmitry Karpeev   PetscFunctionReturn(0);
359c1f0200aSDmitry Karpeev }
360c1f0200aSDmitry Karpeev 
36117d7d925SStefano Zampini /*
36217d7d925SStefano Zampini    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
36317d7d925SStefano Zampini    Assumes 0 origin for v, number of elements = right+1 (right is index of
36417d7d925SStefano Zampini    right-most member).
36517d7d925SStefano Zampini */
36617d7d925SStefano Zampini static void PetscSortMPIInt_Private(PetscMPIInt *v,PetscInt right)
36717d7d925SStefano Zampini {
36817d7d925SStefano Zampini   PetscInt          i,j;
36917d7d925SStefano Zampini   PetscMPIInt       pivot,tmp;
37017d7d925SStefano Zampini 
37117d7d925SStefano Zampini   if (right <= 1) {
37217d7d925SStefano Zampini     if (right == 1) {
37317d7d925SStefano Zampini       if (v[0] > v[1]) SWAP(v[0],v[1],tmp);
37417d7d925SStefano Zampini     }
37517d7d925SStefano Zampini     return;
37617d7d925SStefano Zampini   }
37717d7d925SStefano Zampini   i = MEDIAN(v,right);          /* Choose a pivot */
37817d7d925SStefano Zampini   SWAP(v[0],v[i],tmp);          /* Move it out of the way */
37917d7d925SStefano Zampini   pivot = v[0];
38017d7d925SStefano Zampini   for (i=0,j=right+1;; ) {
38117d7d925SStefano Zampini     while (++i < j && v[i] <= pivot) ; /* Scan from the left */
38217d7d925SStefano Zampini     while (v[--j] > pivot) ;           /* Scan from the right */
38317d7d925SStefano Zampini     if (i >= j) break;
38417d7d925SStefano Zampini     SWAP(v[i],v[j],tmp);
38517d7d925SStefano Zampini   }
38617d7d925SStefano Zampini   SWAP(v[0],v[j],tmp);          /* Put pivot back in place. */
38717d7d925SStefano Zampini   PetscSortMPIInt_Private(v,j-1);
38817d7d925SStefano Zampini   PetscSortMPIInt_Private(v+j+1,right-(j+1));
38917d7d925SStefano Zampini }
39017d7d925SStefano Zampini 
39117d7d925SStefano Zampini /*@
39217d7d925SStefano Zampini    PetscSortMPIInt - Sorts an array of MPI integers in place in increasing order.
39317d7d925SStefano Zampini 
39417d7d925SStefano Zampini    Not Collective
39517d7d925SStefano Zampini 
39617d7d925SStefano Zampini    Input Parameters:
39717d7d925SStefano Zampini +  n  - number of values
39817d7d925SStefano Zampini -  i  - array of integers
39917d7d925SStefano Zampini 
40017d7d925SStefano Zampini    Level: intermediate
40117d7d925SStefano Zampini 
40217d7d925SStefano Zampini    Concepts: sorting^ints
40317d7d925SStefano Zampini 
40417d7d925SStefano Zampini .seealso: PetscSortReal(), PetscSortIntWithPermutation()
40517d7d925SStefano Zampini @*/
40617d7d925SStefano Zampini PetscErrorCode  PetscSortMPIInt(PetscInt n,PetscMPIInt i[])
40717d7d925SStefano Zampini {
40817d7d925SStefano Zampini   PetscInt    j,k;
40917d7d925SStefano Zampini   PetscMPIInt tmp,ik;
41017d7d925SStefano Zampini 
41117d7d925SStefano Zampini   PetscFunctionBegin;
41217d7d925SStefano Zampini   if (n<8) {
41317d7d925SStefano Zampini     for (k=0; k<n; k++) {
41417d7d925SStefano Zampini       ik = i[k];
41517d7d925SStefano Zampini       for (j=k+1; j<n; j++) {
41617d7d925SStefano Zampini         if (ik > i[j]) {
41717d7d925SStefano Zampini           SWAP(i[k],i[j],tmp);
41817d7d925SStefano Zampini           ik = i[k];
41917d7d925SStefano Zampini         }
42017d7d925SStefano Zampini       }
42117d7d925SStefano Zampini     }
422a297a907SKarl Rupp   } else PetscSortMPIInt_Private(i,n-1);
42317d7d925SStefano Zampini   PetscFunctionReturn(0);
42417d7d925SStefano Zampini }
42517d7d925SStefano Zampini 
42617d7d925SStefano Zampini /*@
42717d7d925SStefano Zampini    PetscSortRemoveDupsMPIInt - Sorts an array of MPI integers in place in increasing order removes all duplicate entries
42817d7d925SStefano Zampini 
42917d7d925SStefano Zampini    Not Collective
43017d7d925SStefano Zampini 
43117d7d925SStefano Zampini    Input Parameters:
43217d7d925SStefano Zampini +  n  - number of values
43317d7d925SStefano Zampini -  ii  - array of integers
43417d7d925SStefano Zampini 
43517d7d925SStefano Zampini    Output Parameter:
43617d7d925SStefano Zampini .  n - number of non-redundant values
43717d7d925SStefano Zampini 
43817d7d925SStefano Zampini    Level: intermediate
43917d7d925SStefano Zampini 
44017d7d925SStefano Zampini    Concepts: sorting^ints
44117d7d925SStefano Zampini 
44217d7d925SStefano Zampini .seealso: PetscSortReal(), PetscSortIntWithPermutation(), PetscSortInt()
44317d7d925SStefano Zampini @*/
44417d7d925SStefano Zampini PetscErrorCode  PetscSortRemoveDupsMPIInt(PetscInt *n,PetscMPIInt ii[])
44517d7d925SStefano Zampini {
44617d7d925SStefano Zampini   PetscErrorCode ierr;
44717d7d925SStefano Zampini   PetscInt       i,s = 0,N = *n, b = 0;
44817d7d925SStefano Zampini 
44917d7d925SStefano Zampini   PetscFunctionBegin;
45017d7d925SStefano Zampini   ierr = PetscSortMPIInt(N,ii);CHKERRQ(ierr);
45117d7d925SStefano Zampini   for (i=0; i<N-1; i++) {
452a297a907SKarl Rupp     if (ii[b+s+1] != ii[b]) {
453a297a907SKarl Rupp       ii[b+1] = ii[b+s+1]; b++;
454a297a907SKarl Rupp     } else s++;
45517d7d925SStefano Zampini   }
45617d7d925SStefano Zampini   *n = N - s;
45717d7d925SStefano Zampini   PetscFunctionReturn(0);
45817d7d925SStefano Zampini }
459c1f0200aSDmitry Karpeev 
4604d615ea0SBarry Smith /*
4614d615ea0SBarry Smith    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
4624d615ea0SBarry Smith    Assumes 0 origin for v, number of elements = right+1 (right is index of
4634d615ea0SBarry Smith    right-most member).
4644d615ea0SBarry Smith */
4654d615ea0SBarry Smith static PetscErrorCode PetscSortMPIIntWithArray_Private(PetscMPIInt *v,PetscMPIInt *V,PetscMPIInt right)
4664d615ea0SBarry Smith {
4674d615ea0SBarry Smith   PetscErrorCode ierr;
4684d615ea0SBarry Smith   PetscMPIInt    i,vl,last,tmp;
4694d615ea0SBarry Smith 
4704d615ea0SBarry Smith   PetscFunctionBegin;
4714d615ea0SBarry Smith   if (right <= 1) {
4724d615ea0SBarry Smith     if (right == 1) {
4734d615ea0SBarry Smith       if (v[0] > v[1]) SWAP2(v[0],v[1],V[0],V[1],tmp);
4744d615ea0SBarry Smith     }
4754d615ea0SBarry Smith     PetscFunctionReturn(0);
4764d615ea0SBarry Smith   }
4774d615ea0SBarry Smith   SWAP2(v[0],v[right/2],V[0],V[right/2],tmp);
4784d615ea0SBarry Smith   vl   = v[0];
4794d615ea0SBarry Smith   last = 0;
4804d615ea0SBarry Smith   for (i=1; i<=right; i++) {
4814d615ea0SBarry Smith     if (v[i] < vl) {last++; SWAP2(v[last],v[i],V[last],V[i],tmp);}
4824d615ea0SBarry Smith   }
4834d615ea0SBarry Smith   SWAP2(v[0],v[last],V[0],V[last],tmp);
4844d615ea0SBarry Smith   ierr = PetscSortMPIIntWithArray_Private(v,V,last-1);CHKERRQ(ierr);
4854d615ea0SBarry Smith   ierr = PetscSortMPIIntWithArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr);
4864d615ea0SBarry Smith   PetscFunctionReturn(0);
4874d615ea0SBarry Smith }
4884d615ea0SBarry Smith 
4894d615ea0SBarry Smith /*@
4904d615ea0SBarry Smith    PetscSortMPIIntWithArray - Sorts an array of integers in place in increasing order;
4914d615ea0SBarry Smith        changes a second array to match the sorted first array.
4924d615ea0SBarry Smith 
4934d615ea0SBarry Smith    Not Collective
4944d615ea0SBarry Smith 
4954d615ea0SBarry Smith    Input Parameters:
4964d615ea0SBarry Smith +  n  - number of values
4974d615ea0SBarry Smith .  i  - array of integers
4984d615ea0SBarry Smith -  I - second array of integers
4994d615ea0SBarry Smith 
5004d615ea0SBarry Smith    Level: intermediate
5014d615ea0SBarry Smith 
5024d615ea0SBarry Smith    Concepts: sorting^ints with array
5034d615ea0SBarry Smith 
5044d615ea0SBarry Smith .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt()
5054d615ea0SBarry Smith @*/
5067087cfbeSBarry Smith PetscErrorCode  PetscSortMPIIntWithArray(PetscMPIInt n,PetscMPIInt i[],PetscMPIInt Ii[])
5074d615ea0SBarry Smith {
5084d615ea0SBarry Smith   PetscErrorCode ierr;
5094d615ea0SBarry Smith   PetscMPIInt    j,k,tmp,ik;
5104d615ea0SBarry Smith 
5114d615ea0SBarry Smith   PetscFunctionBegin;
5124d615ea0SBarry Smith   if (n<8) {
5134d615ea0SBarry Smith     for (k=0; k<n; k++) {
5144d615ea0SBarry Smith       ik = i[k];
5154d615ea0SBarry Smith       for (j=k+1; j<n; j++) {
5164d615ea0SBarry Smith         if (ik > i[j]) {
5174d615ea0SBarry Smith           SWAP2(i[k],i[j],Ii[k],Ii[j],tmp);
5184d615ea0SBarry Smith           ik = i[k];
5194d615ea0SBarry Smith         }
5204d615ea0SBarry Smith       }
5214d615ea0SBarry Smith     }
5224d615ea0SBarry Smith   } else {
5234d615ea0SBarry Smith     ierr = PetscSortMPIIntWithArray_Private(i,Ii,n-1);CHKERRQ(ierr);
5244d615ea0SBarry Smith   }
5254d615ea0SBarry Smith   PetscFunctionReturn(0);
5264d615ea0SBarry Smith }
5274d615ea0SBarry Smith 
528e5c89e4eSSatish Balay /* -----------------------------------------------------------------------*/
529e5c89e4eSSatish Balay #define SWAP2IntScalar(a,b,c,d,t,ts) {t=a;a=b;b=t;ts=c;c=d;d=ts;}
530e5c89e4eSSatish Balay 
531e5c89e4eSSatish Balay /*
532e5c89e4eSSatish Balay    Modified from PetscSortIntWithArray_Private().
533e5c89e4eSSatish Balay */
534e5c89e4eSSatish Balay static PetscErrorCode PetscSortIntWithScalarArray_Private(PetscInt *v,PetscScalar *V,PetscInt right)
535e5c89e4eSSatish Balay {
536e5c89e4eSSatish Balay   PetscErrorCode ierr;
537e5c89e4eSSatish Balay   PetscInt       i,vl,last,tmp;
538e5c89e4eSSatish Balay   PetscScalar    stmp;
539e5c89e4eSSatish Balay 
540e5c89e4eSSatish Balay   PetscFunctionBegin;
541e5c89e4eSSatish Balay   if (right <= 1) {
542e5c89e4eSSatish Balay     if (right == 1) {
543e5c89e4eSSatish Balay       if (v[0] > v[1]) SWAP2IntScalar(v[0],v[1],V[0],V[1],tmp,stmp);
544e5c89e4eSSatish Balay     }
545e5c89e4eSSatish Balay     PetscFunctionReturn(0);
546e5c89e4eSSatish Balay   }
547e5c89e4eSSatish Balay   SWAP2IntScalar(v[0],v[right/2],V[0],V[right/2],tmp,stmp);
548e5c89e4eSSatish Balay   vl   = v[0];
549e5c89e4eSSatish Balay   last = 0;
550e5c89e4eSSatish Balay   for (i=1; i<=right; i++) {
551e5c89e4eSSatish Balay     if (v[i] < vl) {last++; SWAP2IntScalar(v[last],v[i],V[last],V[i],tmp,stmp);}
552e5c89e4eSSatish Balay   }
553e5c89e4eSSatish Balay   SWAP2IntScalar(v[0],v[last],V[0],V[last],tmp,stmp);
554e5c89e4eSSatish Balay   ierr = PetscSortIntWithScalarArray_Private(v,V,last-1);CHKERRQ(ierr);
555e5c89e4eSSatish Balay   ierr = PetscSortIntWithScalarArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr);
556e5c89e4eSSatish Balay   PetscFunctionReturn(0);
557e5c89e4eSSatish Balay }
558e5c89e4eSSatish Balay 
559e5c89e4eSSatish Balay /*@
560e5c89e4eSSatish Balay    PetscSortIntWithScalarArray - Sorts an array of integers in place in increasing order;
561e5c89e4eSSatish Balay        changes a second SCALAR array to match the sorted first INTEGER array.
562e5c89e4eSSatish Balay 
563e5c89e4eSSatish Balay    Not Collective
564e5c89e4eSSatish Balay 
565e5c89e4eSSatish Balay    Input Parameters:
566e5c89e4eSSatish Balay +  n  - number of values
567e5c89e4eSSatish Balay .  i  - array of integers
568e5c89e4eSSatish Balay -  I - second array of scalars
569e5c89e4eSSatish Balay 
570e5c89e4eSSatish Balay    Level: intermediate
571e5c89e4eSSatish Balay 
572e5c89e4eSSatish Balay    Concepts: sorting^ints with array
573e5c89e4eSSatish Balay 
574e5c89e4eSSatish Balay .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
575e5c89e4eSSatish Balay @*/
5767087cfbeSBarry Smith PetscErrorCode  PetscSortIntWithScalarArray(PetscInt n,PetscInt i[],PetscScalar Ii[])
577e5c89e4eSSatish Balay {
578e5c89e4eSSatish Balay   PetscErrorCode ierr;
579e5c89e4eSSatish Balay   PetscInt       j,k,tmp,ik;
580e5c89e4eSSatish Balay   PetscScalar    stmp;
581e5c89e4eSSatish Balay 
582e5c89e4eSSatish Balay   PetscFunctionBegin;
583e5c89e4eSSatish Balay   if (n<8) {
584e5c89e4eSSatish Balay     for (k=0; k<n; k++) {
585e5c89e4eSSatish Balay       ik = i[k];
586e5c89e4eSSatish Balay       for (j=k+1; j<n; j++) {
587e5c89e4eSSatish Balay         if (ik > i[j]) {
588b7940d39SSatish Balay           SWAP2IntScalar(i[k],i[j],Ii[k],Ii[j],tmp,stmp);
589e5c89e4eSSatish Balay           ik = i[k];
590e5c89e4eSSatish Balay         }
591e5c89e4eSSatish Balay       }
592e5c89e4eSSatish Balay     }
593e5c89e4eSSatish Balay   } else {
594b7940d39SSatish Balay     ierr = PetscSortIntWithScalarArray_Private(i,Ii,n-1);CHKERRQ(ierr);
595e5c89e4eSSatish Balay   }
596e5c89e4eSSatish Balay   PetscFunctionReturn(0);
597e5c89e4eSSatish Balay }
598e5c89e4eSSatish Balay 
599ece8f864SToby Isaac #define SWAP2IntData(a,b,c,d,t,td,siz)          \
600ece8f864SToby Isaac   do {                                          \
601ece8f864SToby Isaac   PetscErrorCode _ierr;                         \
602ece8f864SToby Isaac   t=a;a=b;b=t;                                  \
603ece8f864SToby Isaac   _ierr = PetscMemcpy(td,c,siz);CHKERRQ(_ierr); \
604ece8f864SToby Isaac   _ierr = PetscMemcpy(c,d,siz);CHKERRQ(_ierr);  \
605ece8f864SToby Isaac   _ierr = PetscMemcpy(d,td,siz);CHKERRQ(_ierr); \
606ece8f864SToby Isaac } while(0)
60717df18f2SToby Isaac 
60817df18f2SToby Isaac /*
60917df18f2SToby Isaac    Modified from PetscSortIntWithArray_Private().
61017df18f2SToby Isaac */
61117df18f2SToby Isaac static PetscErrorCode PetscSortIntWithDataArray_Private(PetscInt *v,char *V,PetscInt right,size_t size,void *work)
61217df18f2SToby Isaac {
61317df18f2SToby Isaac   PetscErrorCode ierr;
61417df18f2SToby Isaac   PetscInt       i,vl,last,tmp;
61517df18f2SToby Isaac 
61617df18f2SToby Isaac   PetscFunctionBegin;
61717df18f2SToby Isaac   if (right <= 1) {
61817df18f2SToby Isaac     if (right == 1) {
61917df18f2SToby Isaac       if (v[0] > v[1]) SWAP2IntData(v[0],v[1],V,V+size,tmp,work,size);
62017df18f2SToby Isaac     }
62117df18f2SToby Isaac     PetscFunctionReturn(0);
62217df18f2SToby Isaac   }
62317df18f2SToby Isaac   SWAP2IntData(v[0],v[right/2],V,V+size*(right/2),tmp,work,size);
62417df18f2SToby Isaac   vl   = v[0];
62517df18f2SToby Isaac   last = 0;
62617df18f2SToby Isaac   for (i=1; i<=right; i++) {
62717df18f2SToby Isaac     if (v[i] < vl) {last++; SWAP2IntData(v[last],v[i],V+size*last,V+size*i,tmp,work,size);}
62817df18f2SToby Isaac   }
62917df18f2SToby Isaac   SWAP2IntData(v[0],v[last],V,V + size*last,tmp,work,size);
63017df18f2SToby Isaac   ierr = PetscSortIntWithDataArray_Private(v,V,last-1,size,work);CHKERRQ(ierr);
63117df18f2SToby Isaac   ierr = PetscSortIntWithDataArray_Private(v+last+1,V+size*(last+1),right-(last+1),size,work);CHKERRQ(ierr);
63217df18f2SToby Isaac   PetscFunctionReturn(0);
63317df18f2SToby Isaac }
63417df18f2SToby Isaac 
6356c2863d0SBarry Smith /*@C
63617df18f2SToby Isaac    PetscSortIntWithDataArray - Sorts an array of integers in place in increasing order;
63717df18f2SToby Isaac        changes a second array to match the sorted first INTEGER array.  Unlike other sort routines, the user must
63817df18f2SToby Isaac        provide workspace (the size of an element in the data array) to use when sorting.
63917df18f2SToby Isaac 
64017df18f2SToby Isaac    Not Collective
64117df18f2SToby Isaac 
64217df18f2SToby Isaac    Input Parameters:
64317df18f2SToby Isaac +  n  - number of values
64417df18f2SToby Isaac .  i  - array of integers
64517df18f2SToby Isaac .  Ii - second array of data
64617df18f2SToby Isaac .  size - sizeof elements in the data array in bytes
64717df18f2SToby Isaac -  work - workspace of "size" bytes used when sorting
64817df18f2SToby Isaac 
64917df18f2SToby Isaac    Level: intermediate
65017df18f2SToby Isaac 
65117df18f2SToby Isaac    Concepts: sorting^ints with array
65217df18f2SToby Isaac 
65317df18f2SToby Isaac .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
65417df18f2SToby Isaac @*/
65517df18f2SToby Isaac PetscErrorCode  PetscSortIntWithDataArray(PetscInt n,PetscInt i[],void *Ii,size_t size,void *work)
65617df18f2SToby Isaac {
65717df18f2SToby Isaac   char           *V = (char *) Ii;
65817df18f2SToby Isaac   PetscErrorCode ierr;
65917df18f2SToby Isaac   PetscInt       j,k,tmp,ik;
66017df18f2SToby Isaac 
66117df18f2SToby Isaac   PetscFunctionBegin;
66217df18f2SToby Isaac   if (n<8) {
66317df18f2SToby Isaac     for (k=0; k<n; k++) {
66417df18f2SToby Isaac       ik = i[k];
66517df18f2SToby Isaac       for (j=k+1; j<n; j++) {
66617df18f2SToby Isaac         if (ik > i[j]) {
66717df18f2SToby Isaac           SWAP2IntData(i[k],i[j],V+size*k,V+size*j,tmp,work,size);
66817df18f2SToby Isaac           ik = i[k];
66917df18f2SToby Isaac         }
67017df18f2SToby Isaac       }
67117df18f2SToby Isaac     }
67217df18f2SToby Isaac   } else {
67317df18f2SToby Isaac     ierr = PetscSortIntWithDataArray_Private(i,V,n-1,size,work);CHKERRQ(ierr);
67417df18f2SToby Isaac   }
67517df18f2SToby Isaac   PetscFunctionReturn(0);
67617df18f2SToby Isaac }
67717df18f2SToby Isaac 
678b4301105SBarry Smith 
67921e72a00SBarry Smith /*@
68021e72a00SBarry Smith    PetscMergeIntArray -     Merges two SORTED integer arrays, removes duplicate elements.
68121e72a00SBarry Smith 
68221e72a00SBarry Smith    Not Collective
68321e72a00SBarry Smith 
68421e72a00SBarry Smith    Input Parameters:
68521e72a00SBarry Smith +  an  - number of values in the first array
68621e72a00SBarry Smith .  aI  - first sorted array of integers
68721e72a00SBarry Smith .  bn  - number of values in the second array
68821e72a00SBarry Smith -  bI  - second array of integers
68921e72a00SBarry Smith 
69021e72a00SBarry Smith    Output Parameters:
69121e72a00SBarry Smith +  n   - number of values in the merged array
6926c2863d0SBarry Smith -  L   - merged sorted array, this is allocated if an array is not provided
69321e72a00SBarry Smith 
69421e72a00SBarry Smith    Level: intermediate
69521e72a00SBarry Smith 
69621e72a00SBarry Smith    Concepts: merging^arrays
69721e72a00SBarry Smith 
69821e72a00SBarry Smith .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
69921e72a00SBarry Smith @*/
7006c2863d0SBarry Smith PetscErrorCode  PetscMergeIntArray(PetscInt an,const PetscInt aI[], PetscInt bn, const PetscInt bI[],  PetscInt *n, PetscInt **L)
70121e72a00SBarry Smith {
70221e72a00SBarry Smith   PetscErrorCode ierr;
70321e72a00SBarry Smith   PetscInt       *L_ = *L, ak, bk, k;
70421e72a00SBarry Smith 
70521e72a00SBarry Smith   if (!L_) {
70621e72a00SBarry Smith     ierr = PetscMalloc1(an+bn, L);CHKERRQ(ierr);
70721e72a00SBarry Smith     L_   = *L;
70821e72a00SBarry Smith   }
70921e72a00SBarry Smith   k = ak = bk = 0;
71021e72a00SBarry Smith   while (ak < an && bk < bn) {
71121e72a00SBarry Smith     if (aI[ak] == bI[bk]) {
71221e72a00SBarry Smith       L_[k] = aI[ak];
71321e72a00SBarry Smith       ++ak;
71421e72a00SBarry Smith       ++bk;
71521e72a00SBarry Smith       ++k;
71621e72a00SBarry Smith     } else if (aI[ak] < bI[bk]) {
71721e72a00SBarry Smith       L_[k] = aI[ak];
71821e72a00SBarry Smith       ++ak;
71921e72a00SBarry Smith       ++k;
72021e72a00SBarry Smith     } else {
72121e72a00SBarry Smith       L_[k] = bI[bk];
72221e72a00SBarry Smith       ++bk;
72321e72a00SBarry Smith       ++k;
72421e72a00SBarry Smith     }
72521e72a00SBarry Smith   }
72621e72a00SBarry Smith   if (ak < an) {
72721e72a00SBarry Smith     ierr = PetscMemcpy(L_+k,aI+ak,(an-ak)*sizeof(PetscInt));CHKERRQ(ierr);
72821e72a00SBarry Smith     k   += (an-ak);
72921e72a00SBarry Smith   }
73021e72a00SBarry Smith   if (bk < bn) {
73121e72a00SBarry Smith     ierr = PetscMemcpy(L_+k,bI+bk,(bn-bk)*sizeof(PetscInt));CHKERRQ(ierr);
73221e72a00SBarry Smith     k   += (bn-bk);
73321e72a00SBarry Smith   }
73421e72a00SBarry Smith   *n = k;
73521e72a00SBarry Smith   PetscFunctionReturn(0);
73621e72a00SBarry Smith }
737b4301105SBarry Smith 
738c1f0200aSDmitry Karpeev /*@
73921e72a00SBarry Smith    PetscMergeIntArrayPair -     Merges two SORTED integer arrays that share NO common values along with an additional array of integers.
740c1f0200aSDmitry Karpeev                                 The additional arrays are the same length as sorted arrays and are merged
741c1f0200aSDmitry Karpeev                                 in the order determined by the merging of the sorted pair.
742c1f0200aSDmitry Karpeev 
743c1f0200aSDmitry Karpeev    Not Collective
744c1f0200aSDmitry Karpeev 
745c1f0200aSDmitry Karpeev    Input Parameters:
746c1f0200aSDmitry Karpeev +  an  - number of values in the first array
747c1f0200aSDmitry Karpeev .  aI  - first sorted array of integers
748c1f0200aSDmitry Karpeev .  aJ  - first additional array of integers
749c1f0200aSDmitry Karpeev .  bn  - number of values in the second array
750c1f0200aSDmitry Karpeev .  bI  - second array of integers
751c1f0200aSDmitry Karpeev -  bJ  - second additional of integers
752c1f0200aSDmitry Karpeev 
753c1f0200aSDmitry Karpeev    Output Parameters:
754c1f0200aSDmitry Karpeev +  n   - number of values in the merged array (== an + bn)
75514c49006SJed Brown .  L   - merged sorted array
756c1f0200aSDmitry Karpeev -  J   - merged additional array
757c1f0200aSDmitry Karpeev 
758*95452b02SPatrick Sanan    Notes:
759*95452b02SPatrick 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
760c1f0200aSDmitry Karpeev    Level: intermediate
761c1f0200aSDmitry Karpeev 
762c1f0200aSDmitry Karpeev    Concepts: merging^arrays
763c1f0200aSDmitry Karpeev 
764c1f0200aSDmitry Karpeev .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
765c1f0200aSDmitry Karpeev @*/
7666c2863d0SBarry 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)
767c1f0200aSDmitry Karpeev {
768c1f0200aSDmitry Karpeev   PetscErrorCode ierr;
76970d8d27cSBarry Smith   PetscInt       n_, *L_, *J_, ak, bk, k;
770c1f0200aSDmitry Karpeev 
77114c49006SJed Brown   PetscFunctionBegin;
77270d8d27cSBarry Smith   PetscValidIntPointer(L,8);
77370d8d27cSBarry Smith   PetscValidIntPointer(J,9);
774c1f0200aSDmitry Karpeev   n_ = an + bn;
775c1f0200aSDmitry Karpeev   *n = n_;
77670d8d27cSBarry Smith   if (!*L) {
777785e854fSJed Brown     ierr = PetscMalloc1(n_, L);CHKERRQ(ierr);
77870d8d27cSBarry Smith   }
779d7aa01a8SHong Zhang   L_ = *L;
78070d8d27cSBarry Smith   if (!*J) {
78170d8d27cSBarry Smith     ierr = PetscMalloc1(n_, J);CHKERRQ(ierr);
782c1f0200aSDmitry Karpeev   }
783c1f0200aSDmitry Karpeev   J_   = *J;
784c1f0200aSDmitry Karpeev   k = ak = bk = 0;
785c1f0200aSDmitry Karpeev   while (ak < an && bk < bn) {
786c1f0200aSDmitry Karpeev     if (aI[ak] <= bI[bk]) {
787d7aa01a8SHong Zhang       L_[k] = aI[ak];
788c1f0200aSDmitry Karpeev       J_[k] = aJ[ak];
789c1f0200aSDmitry Karpeev       ++ak;
790c1f0200aSDmitry Karpeev       ++k;
791a297a907SKarl Rupp     } else {
792d7aa01a8SHong Zhang       L_[k] = bI[bk];
793c1f0200aSDmitry Karpeev       J_[k] = bJ[bk];
794c1f0200aSDmitry Karpeev       ++bk;
795c1f0200aSDmitry Karpeev       ++k;
796c1f0200aSDmitry Karpeev     }
797c1f0200aSDmitry Karpeev   }
798c1f0200aSDmitry Karpeev   if (ak < an) {
799d7aa01a8SHong Zhang     ierr = PetscMemcpy(L_+k,aI+ak,(an-ak)*sizeof(PetscInt));CHKERRQ(ierr);
800c1f0200aSDmitry Karpeev     ierr = PetscMemcpy(J_+k,aJ+ak,(an-ak)*sizeof(PetscInt));CHKERRQ(ierr);
801c1f0200aSDmitry Karpeev     k   += (an-ak);
802c1f0200aSDmitry Karpeev   }
803c1f0200aSDmitry Karpeev   if (bk < bn) {
804d7aa01a8SHong Zhang     ierr = PetscMemcpy(L_+k,bI+bk,(bn-bk)*sizeof(PetscInt));CHKERRQ(ierr);
805c1f0200aSDmitry Karpeev     ierr = PetscMemcpy(J_+k,bJ+bk,(bn-bk)*sizeof(PetscInt));CHKERRQ(ierr);
806c1f0200aSDmitry Karpeev   }
807c1f0200aSDmitry Karpeev   PetscFunctionReturn(0);
808c1f0200aSDmitry Karpeev }
809c1f0200aSDmitry Karpeev 
810e498c390SJed Brown /*@
811e498c390SJed Brown    PetscMergeMPIIntArray -     Merges two SORTED integer arrays.
812e498c390SJed Brown 
813e498c390SJed Brown    Not Collective
814e498c390SJed Brown 
815e498c390SJed Brown    Input Parameters:
816e498c390SJed Brown +  an  - number of values in the first array
817e498c390SJed Brown .  aI  - first sorted array of integers
818e498c390SJed Brown .  bn  - number of values in the second array
819e498c390SJed Brown -  bI  - second array of integers
820e498c390SJed Brown 
821e498c390SJed Brown    Output Parameters:
822e498c390SJed Brown +  n   - number of values in the merged array (<= an + bn)
823e498c390SJed Brown -  L   - merged sorted array, allocated if address of NULL pointer is passed
824e498c390SJed Brown 
825e498c390SJed Brown    Level: intermediate
826e498c390SJed Brown 
827e498c390SJed Brown    Concepts: merging^arrays
828e498c390SJed Brown 
829e498c390SJed Brown .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
830e498c390SJed Brown @*/
831e498c390SJed Brown PetscErrorCode PetscMergeMPIIntArray(PetscInt an,const PetscMPIInt aI[],PetscInt bn,const PetscMPIInt bI[],PetscInt *n,PetscMPIInt **L)
832e498c390SJed Brown {
833e498c390SJed Brown   PetscErrorCode ierr;
834e498c390SJed Brown   PetscInt       ai,bi,k;
835e498c390SJed Brown 
836e498c390SJed Brown   PetscFunctionBegin;
837e498c390SJed Brown   if (!*L) {ierr = PetscMalloc1((an+bn),L);CHKERRQ(ierr);}
838e498c390SJed Brown   for (ai=0,bi=0,k=0; ai<an || bi<bn; ) {
839e498c390SJed Brown     PetscInt t = -1;
840e498c390SJed Brown     for ( ; ai<an && (!bn || aI[ai] <= bI[bi]); ai++) (*L)[k++] = t = aI[ai];
841e498c390SJed Brown     for ( ; bi<bn && bI[bi] == t; bi++);
842e498c390SJed Brown     for ( ; bi<bn && (!an || bI[bi] <= aI[ai]); bi++) (*L)[k++] = t = bI[bi];
843e498c390SJed Brown     for ( ; ai<an && aI[ai] == t; ai++);
844e498c390SJed Brown   }
845e498c390SJed Brown   *n = k;
846e498c390SJed Brown   PetscFunctionReturn(0);
847e498c390SJed Brown }
848e5c89e4eSSatish Balay 
8496c2863d0SBarry Smith /*@C
85042eaa7f3SBarry Smith    PetscProcessTree - Prepares tree data to be displayed graphically
85142eaa7f3SBarry Smith 
85242eaa7f3SBarry Smith    Not Collective
85342eaa7f3SBarry Smith 
85442eaa7f3SBarry Smith    Input Parameters:
85542eaa7f3SBarry Smith +  n  - number of values
85642eaa7f3SBarry Smith .  mask - indicates those entries in the tree, location 0 is always masked
85742eaa7f3SBarry Smith -  parentid - indicates the parent of each entry
85842eaa7f3SBarry Smith 
85942eaa7f3SBarry Smith    Output Parameters:
86042eaa7f3SBarry Smith +  Nlevels - the number of levels
86142eaa7f3SBarry Smith .  Level - for each node tells its level
86242eaa7f3SBarry Smith .  Levelcnts - the number of nodes on each level
86342eaa7f3SBarry Smith .  Idbylevel - a list of ids on each of the levels, first level followed by second etc
86442eaa7f3SBarry Smith -  Column - for each id tells its column index
86542eaa7f3SBarry Smith 
8666c2863d0SBarry Smith    Level: developer
86742eaa7f3SBarry Smith 
868*95452b02SPatrick Sanan    Notes:
869*95452b02SPatrick Sanan     This code is not currently used
87042eaa7f3SBarry Smith 
87142eaa7f3SBarry Smith .seealso: PetscSortReal(), PetscSortIntWithPermutation()
87242eaa7f3SBarry Smith @*/
8737087cfbeSBarry Smith PetscErrorCode  PetscProcessTree(PetscInt n,const PetscBool mask[],const PetscInt parentid[],PetscInt *Nlevels,PetscInt **Level,PetscInt **Levelcnt,PetscInt **Idbylevel,PetscInt **Column)
87442eaa7f3SBarry Smith {
87542eaa7f3SBarry Smith   PetscInt       i,j,cnt,nmask = 0,nlevels = 0,*level,*levelcnt,levelmax = 0,*workid,*workparentid,tcnt = 0,*idbylevel,*column;
87642eaa7f3SBarry Smith   PetscErrorCode ierr;
877ace3abfcSBarry Smith   PetscBool      done = PETSC_FALSE;
87842eaa7f3SBarry Smith 
87942eaa7f3SBarry Smith   PetscFunctionBegin;
88042eaa7f3SBarry Smith   if (!mask[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Mask of 0th location must be set");
88142eaa7f3SBarry Smith   for (i=0; i<n; i++) {
88242eaa7f3SBarry Smith     if (mask[i]) continue;
88342eaa7f3SBarry Smith     if (parentid[i]  == i) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Node labeled as own parent");
88442eaa7f3SBarry Smith     if (parentid[i] && mask[parentid[i]]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Parent is masked");
88542eaa7f3SBarry Smith   }
88642eaa7f3SBarry Smith 
88742eaa7f3SBarry Smith   for (i=0; i<n; i++) {
88842eaa7f3SBarry Smith     if (!mask[i]) nmask++;
88942eaa7f3SBarry Smith   }
89042eaa7f3SBarry Smith 
89142eaa7f3SBarry Smith   /* determine the level in the tree of each node */
8921795a4d1SJed Brown   ierr = PetscCalloc1(n,&level);CHKERRQ(ierr);
893a297a907SKarl Rupp 
89442eaa7f3SBarry Smith   level[0] = 1;
89542eaa7f3SBarry Smith   while (!done) {
89642eaa7f3SBarry Smith     done = PETSC_TRUE;
89742eaa7f3SBarry Smith     for (i=0; i<n; i++) {
89842eaa7f3SBarry Smith       if (mask[i]) continue;
89942eaa7f3SBarry Smith       if (!level[i] && level[parentid[i]]) level[i] = level[parentid[i]] + 1;
90042eaa7f3SBarry Smith       else if (!level[i]) done = PETSC_FALSE;
90142eaa7f3SBarry Smith     }
90242eaa7f3SBarry Smith   }
90342eaa7f3SBarry Smith   for (i=0; i<n; i++) {
90442eaa7f3SBarry Smith     level[i]--;
90542eaa7f3SBarry Smith     nlevels = PetscMax(nlevels,level[i]);
90642eaa7f3SBarry Smith   }
90742eaa7f3SBarry Smith 
90842eaa7f3SBarry Smith   /* count the number of nodes on each level and its max */
9091795a4d1SJed Brown   ierr = PetscCalloc1(nlevels,&levelcnt);CHKERRQ(ierr);
91042eaa7f3SBarry Smith   for (i=0; i<n; i++) {
91142eaa7f3SBarry Smith     if (mask[i]) continue;
91242eaa7f3SBarry Smith     levelcnt[level[i]-1]++;
91342eaa7f3SBarry Smith   }
914a297a907SKarl Rupp   for (i=0; i<nlevels;i++) levelmax = PetscMax(levelmax,levelcnt[i]);
91542eaa7f3SBarry Smith 
91642eaa7f3SBarry Smith   /* for each level sort the ids by the parent id */
917dcca6d9dSJed Brown   ierr = PetscMalloc2(levelmax,&workid,levelmax,&workparentid);CHKERRQ(ierr);
918785e854fSJed Brown   ierr = PetscMalloc1(nmask,&idbylevel);CHKERRQ(ierr);
91942eaa7f3SBarry Smith   for (j=1; j<=nlevels;j++) {
92042eaa7f3SBarry Smith     cnt = 0;
92142eaa7f3SBarry Smith     for (i=0; i<n; i++) {
92242eaa7f3SBarry Smith       if (mask[i]) continue;
92342eaa7f3SBarry Smith       if (level[i] != j) continue;
92442eaa7f3SBarry Smith       workid[cnt]         = i;
92542eaa7f3SBarry Smith       workparentid[cnt++] = parentid[i];
92642eaa7f3SBarry Smith     }
92742eaa7f3SBarry Smith     /*  PetscIntView(cnt,workparentid,0);
92842eaa7f3SBarry Smith     PetscIntView(cnt,workid,0);
92942eaa7f3SBarry Smith     ierr = PetscSortIntWithArray(cnt,workparentid,workid);CHKERRQ(ierr);
93042eaa7f3SBarry Smith     PetscIntView(cnt,workparentid,0);
93142eaa7f3SBarry Smith     PetscIntView(cnt,workid,0);*/
93242eaa7f3SBarry Smith     ierr  = PetscMemcpy(idbylevel+tcnt,workid,cnt*sizeof(PetscInt));CHKERRQ(ierr);
93342eaa7f3SBarry Smith     tcnt += cnt;
93442eaa7f3SBarry Smith   }
93542eaa7f3SBarry Smith   if (tcnt != nmask) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Inconsistent count of unmasked nodes");
93642eaa7f3SBarry Smith   ierr = PetscFree2(workid,workparentid);CHKERRQ(ierr);
93742eaa7f3SBarry Smith 
93842eaa7f3SBarry Smith   /* for each node list its column */
939785e854fSJed Brown   ierr = PetscMalloc1(n,&column);CHKERRQ(ierr);
94042eaa7f3SBarry Smith   cnt = 0;
94142eaa7f3SBarry Smith   for (j=0; j<nlevels; j++) {
94242eaa7f3SBarry Smith     for (i=0; i<levelcnt[j]; i++) {
94342eaa7f3SBarry Smith       column[idbylevel[cnt++]] = i;
94442eaa7f3SBarry Smith     }
94542eaa7f3SBarry Smith   }
94642eaa7f3SBarry Smith 
94742eaa7f3SBarry Smith   *Nlevels   = nlevels;
94842eaa7f3SBarry Smith   *Level     = level;
94942eaa7f3SBarry Smith   *Levelcnt  = levelcnt;
95042eaa7f3SBarry Smith   *Idbylevel = idbylevel;
95142eaa7f3SBarry Smith   *Column    = column;
95242eaa7f3SBarry Smith   PetscFunctionReturn(0);
95342eaa7f3SBarry Smith }
954