xref: /petsc/src/sys/utils/sorti.c (revision 48a46eb9bd028bec07ec0f396b1a3abb43f14558)
17d0a6c19SBarry Smith 
2e5c89e4eSSatish Balay /*
3e5c89e4eSSatish Balay    This file contains routines for sorting integers. Values are sorted in place.
4c4762a1bSJed Brown    One can use src/sys/tests/ex52.c for benchmarking.
5e5c89e4eSSatish Balay  */
6af0996ceSBarry Smith #include <petsc/private/petscimpl.h> /*I  "petscsys.h"  I*/
7f1cab4e1SJunchao Zhang #include <petsc/private/hashseti.h>
8e5c89e4eSSatish Balay 
99371c9d4SSatish Balay #define MEDIAN3(v, a, b, c) (v[a] < v[b] ? (v[b] < v[c] ? (b) : (v[a] < v[c] ? (c) : (a))) : (v[c] < v[b] ? (b) : (v[a] < v[c] ? (a) : (c))))
10a8582168SJed Brown 
11a8582168SJed Brown #define MEDIAN(v, right) MEDIAN3(v, right / 4, right / 2, right / 4 * 3)
12ef8e3583SJed Brown 
1359e16d97SJunchao Zhang /* Swap one, two or three pairs. Each pair can have its own type */
149371c9d4SSatish Balay #define SWAP1(a, b, t1) \
159371c9d4SSatish Balay   do { \
169371c9d4SSatish Balay     t1 = a; \
179371c9d4SSatish Balay     a  = b; \
189371c9d4SSatish Balay     b  = t1; \
199371c9d4SSatish Balay   } while (0)
209371c9d4SSatish Balay #define SWAP2(a, b, c, d, t1, t2) \
219371c9d4SSatish Balay   do { \
229371c9d4SSatish Balay     t1 = a; \
239371c9d4SSatish Balay     a  = b; \
249371c9d4SSatish Balay     b  = t1; \
259371c9d4SSatish Balay     t2 = c; \
269371c9d4SSatish Balay     c  = d; \
279371c9d4SSatish Balay     d  = t2; \
289371c9d4SSatish Balay   } while (0)
299371c9d4SSatish Balay #define SWAP3(a, b, c, d, e, f, t1, t2, t3) \
309371c9d4SSatish Balay   do { \
319371c9d4SSatish Balay     t1 = a; \
329371c9d4SSatish Balay     a  = b; \
339371c9d4SSatish Balay     b  = t1; \
349371c9d4SSatish Balay     t2 = c; \
359371c9d4SSatish Balay     c  = d; \
369371c9d4SSatish Balay     d  = t2; \
379371c9d4SSatish Balay     t3 = e; \
389371c9d4SSatish Balay     e  = f; \
399371c9d4SSatish Balay     f  = t3; \
409371c9d4SSatish Balay   } while (0)
4159e16d97SJunchao Zhang 
4259e16d97SJunchao Zhang /* Swap a & b, *c & *d. c, d, t2 are pointers to a type of size <siz> */
4359e16d97SJunchao Zhang #define SWAP2Data(a, b, c, d, t1, t2, siz) \
4459e16d97SJunchao Zhang   do { \
459371c9d4SSatish Balay     t1 = a; \
469371c9d4SSatish Balay     a  = b; \
479371c9d4SSatish Balay     b  = t1; \
489566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(t2, c, siz)); \
499566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(c, d, siz)); \
509566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(d, t2, siz)); \
5159e16d97SJunchao Zhang   } while (0)
52e5c89e4eSSatish Balay 
53e5c89e4eSSatish Balay /*
5459e16d97SJunchao Zhang    Partition X[lo,hi] into two parts: X[lo,l) <= pivot; X[r,hi] > pivot
55e5c89e4eSSatish Balay 
5659e16d97SJunchao Zhang    Input Parameters:
5759e16d97SJunchao Zhang     + X         - array to partition
5859e16d97SJunchao Zhang     . pivot     - a pivot of X[]
5959e16d97SJunchao Zhang     . t1        - temp variable for X
6059e16d97SJunchao Zhang     - lo,hi     - lower and upper bound of the array
6159e16d97SJunchao Zhang 
6259e16d97SJunchao Zhang    Output Parameters:
6359e16d97SJunchao Zhang     + l,r       - of type PetscInt
6459e16d97SJunchao Zhang 
6559e16d97SJunchao Zhang    Notes:
6659e16d97SJunchao Zhang     The TwoWayPartition2/3 variants also partition other arrays along with X.
6759e16d97SJunchao Zhang     These arrays can have different types, so they provide their own temp t2,t3
6859e16d97SJunchao Zhang  */
6959e16d97SJunchao Zhang #define TwoWayPartition1(X, pivot, t1, lo, hi, l, r) \
7059e16d97SJunchao Zhang   do { \
7159e16d97SJunchao Zhang     l = lo; \
7259e16d97SJunchao Zhang     r = hi; \
7359e16d97SJunchao Zhang     while (1) { \
7459e16d97SJunchao Zhang       while (X[l] < pivot) l++; \
7559e16d97SJunchao Zhang       while (X[r] > pivot) r--; \
769371c9d4SSatish Balay       if (l >= r) { \
779371c9d4SSatish Balay         r++; \
789371c9d4SSatish Balay         break; \
799371c9d4SSatish Balay       } \
8059e16d97SJunchao Zhang       SWAP1(X[l], X[r], t1); \
8159e16d97SJunchao Zhang       l++; \
8259e16d97SJunchao Zhang       r--; \
8359e16d97SJunchao Zhang     } \
8459e16d97SJunchao Zhang   } while (0)
8559e16d97SJunchao Zhang 
86ce605777SToby Isaac /*
87ce605777SToby Isaac    Partition X[lo,hi] into two parts: X[lo,l) >= pivot; X[r,hi] < pivot
88ce605777SToby Isaac 
89ce605777SToby Isaac    Input Parameters:
90ce605777SToby Isaac     + X         - array to partition
91ce605777SToby Isaac     . pivot     - a pivot of X[]
92ce605777SToby Isaac     . t1        - temp variable for X
93ce605777SToby Isaac     - lo,hi     - lower and upper bound of the array
94ce605777SToby Isaac 
95ce605777SToby Isaac    Output Parameters:
96ce605777SToby Isaac     + l,r       - of type PetscInt
97ce605777SToby Isaac 
98ce605777SToby Isaac    Notes:
99ce605777SToby Isaac     The TwoWayPartition2/3 variants also partition other arrays along with X.
100ce605777SToby Isaac     These arrays can have different types, so they provide their own temp t2,t3
101ce605777SToby Isaac  */
102ce605777SToby Isaac #define TwoWayPartitionReverse1(X, pivot, t1, lo, hi, l, r) \
103ce605777SToby Isaac   do { \
104ce605777SToby Isaac     l = lo; \
105ce605777SToby Isaac     r = hi; \
106ce605777SToby Isaac     while (1) { \
107ce605777SToby Isaac       while (X[l] > pivot) l++; \
108ce605777SToby Isaac       while (X[r] < pivot) r--; \
1099371c9d4SSatish Balay       if (l >= r) { \
1109371c9d4SSatish Balay         r++; \
1119371c9d4SSatish Balay         break; \
1129371c9d4SSatish Balay       } \
113ce605777SToby Isaac       SWAP1(X[l], X[r], t1); \
114ce605777SToby Isaac       l++; \
115ce605777SToby Isaac       r--; \
116ce605777SToby Isaac     } \
117ce605777SToby Isaac   } while (0)
118ce605777SToby Isaac 
11959e16d97SJunchao Zhang #define TwoWayPartition2(X, Y, pivot, t1, t2, lo, hi, l, r) \
12059e16d97SJunchao Zhang   do { \
12159e16d97SJunchao Zhang     l = lo; \
12259e16d97SJunchao Zhang     r = hi; \
12359e16d97SJunchao Zhang     while (1) { \
12459e16d97SJunchao Zhang       while (X[l] < pivot) l++; \
12559e16d97SJunchao Zhang       while (X[r] > pivot) r--; \
1269371c9d4SSatish Balay       if (l >= r) { \
1279371c9d4SSatish Balay         r++; \
1289371c9d4SSatish Balay         break; \
1299371c9d4SSatish Balay       } \
13059e16d97SJunchao Zhang       SWAP2(X[l], X[r], Y[l], Y[r], t1, t2); \
13159e16d97SJunchao Zhang       l++; \
13259e16d97SJunchao Zhang       r--; \
13359e16d97SJunchao Zhang     } \
13459e16d97SJunchao Zhang   } while (0)
13559e16d97SJunchao Zhang 
13659e16d97SJunchao Zhang #define TwoWayPartition3(X, Y, Z, pivot, t1, t2, t3, lo, hi, l, r) \
13759e16d97SJunchao Zhang   do { \
13859e16d97SJunchao Zhang     l = lo; \
13959e16d97SJunchao Zhang     r = hi; \
14059e16d97SJunchao Zhang     while (1) { \
14159e16d97SJunchao Zhang       while (X[l] < pivot) l++; \
14259e16d97SJunchao Zhang       while (X[r] > pivot) r--; \
1439371c9d4SSatish Balay       if (l >= r) { \
1449371c9d4SSatish Balay         r++; \
1459371c9d4SSatish Balay         break; \
1469371c9d4SSatish Balay       } \
14759e16d97SJunchao Zhang       SWAP3(X[l], X[r], Y[l], Y[r], Z[l], Z[r], t1, t2, t3); \
14859e16d97SJunchao Zhang       l++; \
14959e16d97SJunchao Zhang       r--; \
15059e16d97SJunchao Zhang     } \
15159e16d97SJunchao Zhang   } while (0)
15259e16d97SJunchao Zhang 
15359e16d97SJunchao Zhang /* Templates for similar functions used below */
1545f80ce2aSJacob Faibussowitsch #define QuickSort1(FuncName, X, n, pivot, t1) \
15559e16d97SJunchao Zhang   do { \
156981bb840SJunchao Zhang     PetscCount i, j, p, l, r, hi = n - 1; \
15759e16d97SJunchao Zhang     if (n < 8) { \
15859e16d97SJunchao Zhang       for (i = 0; i < n; i++) { \
15959e16d97SJunchao Zhang         pivot = X[i]; \
16059e16d97SJunchao Zhang         for (j = i + 1; j < n; j++) { \
16159e16d97SJunchao Zhang           if (pivot > X[j]) { \
16259e16d97SJunchao Zhang             SWAP1(X[i], X[j], t1); \
16359e16d97SJunchao Zhang             pivot = X[i]; \
16459e16d97SJunchao Zhang           } \
16559e16d97SJunchao Zhang         } \
16659e16d97SJunchao Zhang       } \
16759e16d97SJunchao Zhang     } else { \
16859e16d97SJunchao Zhang       p     = MEDIAN(X, hi); \
16959e16d97SJunchao Zhang       pivot = X[p]; \
17059e16d97SJunchao Zhang       TwoWayPartition1(X, pivot, t1, 0, hi, l, r); \
1719566063dSJacob Faibussowitsch       PetscCall(FuncName(l, X)); \
1729566063dSJacob Faibussowitsch       PetscCall(FuncName(hi - r + 1, X + r)); \
17359e16d97SJunchao Zhang     } \
17459e16d97SJunchao Zhang   } while (0)
17559e16d97SJunchao Zhang 
176ce605777SToby Isaac /* Templates for similar functions used below */
1775f80ce2aSJacob Faibussowitsch #define QuickSortReverse1(FuncName, X, n, pivot, t1) \
178ce605777SToby Isaac   do { \
179981bb840SJunchao Zhang     PetscCount i, j, p, l, r, hi = n - 1; \
180ce605777SToby Isaac     if (n < 8) { \
181ce605777SToby Isaac       for (i = 0; i < n; i++) { \
182ce605777SToby Isaac         pivot = X[i]; \
183ce605777SToby Isaac         for (j = i + 1; j < n; j++) { \
184ce605777SToby Isaac           if (pivot < X[j]) { \
185ce605777SToby Isaac             SWAP1(X[i], X[j], t1); \
186ce605777SToby Isaac             pivot = X[i]; \
187ce605777SToby Isaac           } \
188ce605777SToby Isaac         } \
189ce605777SToby Isaac       } \
190ce605777SToby Isaac     } else { \
191ce605777SToby Isaac       p     = MEDIAN(X, hi); \
192ce605777SToby Isaac       pivot = X[p]; \
193ce605777SToby Isaac       TwoWayPartitionReverse1(X, pivot, t1, 0, hi, l, r); \
1949566063dSJacob Faibussowitsch       PetscCall(FuncName(l, X)); \
1959566063dSJacob Faibussowitsch       PetscCall(FuncName(hi - r + 1, X + r)); \
196ce605777SToby Isaac     } \
197ce605777SToby Isaac   } while (0)
198ce605777SToby Isaac 
1995f80ce2aSJacob Faibussowitsch #define QuickSort2(FuncName, X, Y, n, pivot, t1, t2) \
20059e16d97SJunchao Zhang   do { \
201981bb840SJunchao Zhang     PetscCount i, j, p, l, r, hi = n - 1; \
20259e16d97SJunchao Zhang     if (n < 8) { \
20359e16d97SJunchao Zhang       for (i = 0; i < n; i++) { \
20459e16d97SJunchao Zhang         pivot = X[i]; \
20559e16d97SJunchao Zhang         for (j = i + 1; j < n; j++) { \
20659e16d97SJunchao Zhang           if (pivot > X[j]) { \
20759e16d97SJunchao Zhang             SWAP2(X[i], X[j], Y[i], Y[j], t1, t2); \
20859e16d97SJunchao Zhang             pivot = X[i]; \
20959e16d97SJunchao Zhang           } \
21059e16d97SJunchao Zhang         } \
21159e16d97SJunchao Zhang       } \
21259e16d97SJunchao Zhang     } else { \
21359e16d97SJunchao Zhang       p     = MEDIAN(X, hi); \
21459e16d97SJunchao Zhang       pivot = X[p]; \
21559e16d97SJunchao Zhang       TwoWayPartition2(X, Y, pivot, t1, t2, 0, hi, l, r); \
2169566063dSJacob Faibussowitsch       PetscCall(FuncName(l, X, Y)); \
2179566063dSJacob Faibussowitsch       PetscCall(FuncName(hi - r + 1, X + r, Y + r)); \
21859e16d97SJunchao Zhang     } \
21959e16d97SJunchao Zhang   } while (0)
22059e16d97SJunchao Zhang 
2215f80ce2aSJacob Faibussowitsch #define QuickSort3(FuncName, X, Y, Z, n, pivot, t1, t2, t3) \
22259e16d97SJunchao Zhang   do { \
223981bb840SJunchao Zhang     PetscCount i, j, p, l, r, hi = n - 1; \
22459e16d97SJunchao Zhang     if (n < 8) { \
22559e16d97SJunchao Zhang       for (i = 0; i < n; i++) { \
22659e16d97SJunchao Zhang         pivot = X[i]; \
22759e16d97SJunchao Zhang         for (j = i + 1; j < n; j++) { \
22859e16d97SJunchao Zhang           if (pivot > X[j]) { \
22959e16d97SJunchao Zhang             SWAP3(X[i], X[j], Y[i], Y[j], Z[i], Z[j], t1, t2, t3); \
23059e16d97SJunchao Zhang             pivot = X[i]; \
23159e16d97SJunchao Zhang           } \
23259e16d97SJunchao Zhang         } \
23359e16d97SJunchao Zhang       } \
23459e16d97SJunchao Zhang     } else { \
23559e16d97SJunchao Zhang       p     = MEDIAN(X, hi); \
23659e16d97SJunchao Zhang       pivot = X[p]; \
23759e16d97SJunchao Zhang       TwoWayPartition3(X, Y, Z, pivot, t1, t2, t3, 0, hi, l, r); \
2389566063dSJacob Faibussowitsch       PetscCall(FuncName(l, X, Y, Z)); \
2399566063dSJacob Faibussowitsch       PetscCall(FuncName(hi - r + 1, X + r, Y + r, Z + r)); \
24059e16d97SJunchao Zhang     } \
24159e16d97SJunchao Zhang   } while (0)
242e5c89e4eSSatish Balay 
243e5c89e4eSSatish Balay /*@
2446a7c706bSVaclav Hapla    PetscSortedInt - Determines whether the array is sorted.
2456a7c706bSVaclav Hapla 
2466a7c706bSVaclav Hapla    Not Collective
2476a7c706bSVaclav Hapla 
2486a7c706bSVaclav Hapla    Input Parameters:
2496a7c706bSVaclav Hapla +  n  - number of values
2506a7c706bSVaclav Hapla -  X  - array of integers
2516a7c706bSVaclav Hapla 
2526a7c706bSVaclav Hapla    Output Parameters:
2536a7c706bSVaclav Hapla .  sorted - flag whether the array is sorted
2546a7c706bSVaclav Hapla 
2556a7c706bSVaclav Hapla    Level: intermediate
2566a7c706bSVaclav Hapla 
257db781477SPatrick Sanan .seealso: `PetscSortInt()`, `PetscSortedMPIInt()`, `PetscSortedReal()`
2586a7c706bSVaclav Hapla @*/
2599371c9d4SSatish Balay PetscErrorCode PetscSortedInt(PetscInt n, const PetscInt X[], PetscBool *sorted) {
2606a7c706bSVaclav Hapla   PetscFunctionBegin;
2615f80ce2aSJacob Faibussowitsch   if (n) PetscValidIntPointer(X, 2);
2625f80ce2aSJacob Faibussowitsch   PetscValidBoolPointer(sorted, 3);
2636a7c706bSVaclav Hapla   PetscSorted(n, X, *sorted);
2646a7c706bSVaclav Hapla   PetscFunctionReturn(0);
2656a7c706bSVaclav Hapla }
2666a7c706bSVaclav Hapla 
2676a7c706bSVaclav Hapla /*@
268e5c89e4eSSatish Balay    PetscSortInt - Sorts an array of integers in place in increasing order.
269e5c89e4eSSatish Balay 
270e5c89e4eSSatish Balay    Not Collective
271e5c89e4eSSatish Balay 
272e5c89e4eSSatish Balay    Input Parameters:
273e5c89e4eSSatish Balay +  n  - number of values
27459e16d97SJunchao Zhang -  X  - array of integers
275e5c89e4eSSatish Balay 
276676f2a66SJacob Faibussowitsch    Notes:
277676f2a66SJacob Faibussowitsch    This function serves as an alternative to PetscIntSortSemiOrdered(), and may perform faster especially if the array
278a5b23f4aSJose E. Roman    is completely random. There are exceptions to this and so it is __highly__ recommended that the user benchmark their
279676f2a66SJacob Faibussowitsch    code to see which routine is fastest.
280676f2a66SJacob Faibussowitsch 
281e5c89e4eSSatish Balay    Level: intermediate
282e5c89e4eSSatish Balay 
283db781477SPatrick Sanan .seealso: `PetscIntSortSemiOrdered()`, `PetscSortReal()`, `PetscSortIntWithPermutation()`
284e5c89e4eSSatish Balay @*/
2859371c9d4SSatish Balay PetscErrorCode PetscSortInt(PetscInt n, PetscInt X[]) {
28659e16d97SJunchao Zhang   PetscInt pivot, t1;
287e5c89e4eSSatish Balay 
288e5c89e4eSSatish Balay   PetscFunctionBegin;
2895f80ce2aSJacob Faibussowitsch   if (n) PetscValidIntPointer(X, 2);
2905f80ce2aSJacob Faibussowitsch   QuickSort1(PetscSortInt, X, n, pivot, t1);
291e5c89e4eSSatish Balay   PetscFunctionReturn(0);
292e5c89e4eSSatish Balay }
293e5c89e4eSSatish Balay 
2941db36a52SBarry Smith /*@
295ce605777SToby Isaac    PetscSortReverseInt - Sorts an array of integers in place in decreasing order.
296ce605777SToby Isaac 
297ce605777SToby Isaac    Not Collective
298ce605777SToby Isaac 
299ce605777SToby Isaac    Input Parameters:
300ce605777SToby Isaac +  n  - number of values
301ce605777SToby Isaac -  X  - array of integers
302ce605777SToby Isaac 
303ce605777SToby Isaac    Level: intermediate
304ce605777SToby Isaac 
305db781477SPatrick Sanan .seealso: `PetscIntSortSemiOrdered()`, `PetscSortInt()`, `PetscSortIntWithPermutation()`
306ce605777SToby Isaac @*/
3079371c9d4SSatish Balay PetscErrorCode PetscSortReverseInt(PetscInt n, PetscInt X[]) {
308ce605777SToby Isaac   PetscInt pivot, t1;
309ce605777SToby Isaac 
310ce605777SToby Isaac   PetscFunctionBegin;
3115f80ce2aSJacob Faibussowitsch   if (n) PetscValidIntPointer(X, 2);
3125f80ce2aSJacob Faibussowitsch   QuickSortReverse1(PetscSortReverseInt, X, n, pivot, t1);
313ce605777SToby Isaac   PetscFunctionReturn(0);
314ce605777SToby Isaac }
315ce605777SToby Isaac 
316ce605777SToby Isaac /*@
31722ab5688SLisandro Dalcin    PetscSortedRemoveDupsInt - Removes all duplicate entries of a sorted input array
31822ab5688SLisandro Dalcin 
31922ab5688SLisandro Dalcin    Not Collective
32022ab5688SLisandro Dalcin 
32122ab5688SLisandro Dalcin    Input Parameters:
32222ab5688SLisandro Dalcin +  n  - number of values
32359e16d97SJunchao Zhang -  X  - sorted array of integers
32422ab5688SLisandro Dalcin 
32522ab5688SLisandro Dalcin    Output Parameter:
32622ab5688SLisandro Dalcin .  n - number of non-redundant values
32722ab5688SLisandro Dalcin 
32822ab5688SLisandro Dalcin    Level: intermediate
32922ab5688SLisandro Dalcin 
330db781477SPatrick Sanan .seealso: `PetscSortInt()`
33122ab5688SLisandro Dalcin @*/
3329371c9d4SSatish Balay PetscErrorCode PetscSortedRemoveDupsInt(PetscInt *n, PetscInt X[]) {
33322ab5688SLisandro Dalcin   PetscInt i, s = 0, N = *n, b = 0;
33422ab5688SLisandro Dalcin 
33522ab5688SLisandro Dalcin   PetscFunctionBegin;
3365f80ce2aSJacob Faibussowitsch   PetscValidIntPointer(n, 1);
337fb61b9e4SStefano Zampini   PetscCheckSorted(*n, X);
33822ab5688SLisandro Dalcin   for (i = 0; i < N - 1; i++) {
33959e16d97SJunchao Zhang     if (X[b + s + 1] != X[b]) {
3409371c9d4SSatish Balay       X[b + 1] = X[b + s + 1];
3419371c9d4SSatish Balay       b++;
34222ab5688SLisandro Dalcin     } else s++;
34322ab5688SLisandro Dalcin   }
34422ab5688SLisandro Dalcin   *n = N - s;
34522ab5688SLisandro Dalcin   PetscFunctionReturn(0);
34622ab5688SLisandro Dalcin }
34722ab5688SLisandro Dalcin 
34822ab5688SLisandro Dalcin /*@
349b6a18d21SVaclav Hapla    PetscSortedCheckDupsInt - Checks if a sorted integer array has duplicates
350b6a18d21SVaclav Hapla 
351b6a18d21SVaclav Hapla    Not Collective
352b6a18d21SVaclav Hapla 
353b6a18d21SVaclav Hapla    Input Parameters:
354b6a18d21SVaclav Hapla +  n  - number of values
355b6a18d21SVaclav Hapla -  X  - sorted array of integers
356b6a18d21SVaclav Hapla 
357b6a18d21SVaclav Hapla    Output Parameter:
358b6a18d21SVaclav Hapla .  dups - True if the array has dups, otherwise false
359b6a18d21SVaclav Hapla 
360b6a18d21SVaclav Hapla    Level: intermediate
361b6a18d21SVaclav Hapla 
362db781477SPatrick Sanan .seealso: `PetscSortInt()`, `PetscCheckDupsInt()`, `PetscSortRemoveDupsInt()`, `PetscSortedRemoveDupsInt()`
363b6a18d21SVaclav Hapla @*/
3649371c9d4SSatish Balay PetscErrorCode PetscSortedCheckDupsInt(PetscInt n, const PetscInt X[], PetscBool *flg) {
365b6a18d21SVaclav Hapla   PetscInt i;
366b6a18d21SVaclav Hapla 
367b6a18d21SVaclav Hapla   PetscFunctionBegin;
368b6a18d21SVaclav Hapla   PetscCheckSorted(n, X);
369b6a18d21SVaclav Hapla   *flg = PETSC_FALSE;
370b6a18d21SVaclav Hapla   for (i = 0; i < n - 1; i++) {
371b6a18d21SVaclav Hapla     if (X[i + 1] == X[i]) {
372b6a18d21SVaclav Hapla       *flg = PETSC_TRUE;
373b6a18d21SVaclav Hapla       break;
374b6a18d21SVaclav Hapla     }
375b6a18d21SVaclav Hapla   }
376b6a18d21SVaclav Hapla   PetscFunctionReturn(0);
377b6a18d21SVaclav Hapla }
378b6a18d21SVaclav Hapla 
379b6a18d21SVaclav Hapla /*@
3801db36a52SBarry Smith    PetscSortRemoveDupsInt - Sorts an array of integers in place in increasing order removes all duplicate entries
3811db36a52SBarry Smith 
3821db36a52SBarry Smith    Not Collective
3831db36a52SBarry Smith 
3841db36a52SBarry Smith    Input Parameters:
3851db36a52SBarry Smith +  n  - number of values
38659e16d97SJunchao Zhang -  X  - array of integers
3871db36a52SBarry Smith 
3881db36a52SBarry Smith    Output Parameter:
3891db36a52SBarry Smith .  n - number of non-redundant values
3901db36a52SBarry Smith 
3911db36a52SBarry Smith    Level: intermediate
3921db36a52SBarry Smith 
393db781477SPatrick Sanan .seealso: `PetscIntSortSemiOrdered()`, `PetscSortReal()`, `PetscSortIntWithPermutation()`, `PetscSortInt()`, `PetscSortedRemoveDupsInt()`
3941db36a52SBarry Smith @*/
3959371c9d4SSatish Balay PetscErrorCode PetscSortRemoveDupsInt(PetscInt *n, PetscInt X[]) {
3961db36a52SBarry Smith   PetscFunctionBegin;
3975f80ce2aSJacob Faibussowitsch   PetscValidIntPointer(n, 1);
3989566063dSJacob Faibussowitsch   PetscCall(PetscSortInt(*n, X));
3999566063dSJacob Faibussowitsch   PetscCall(PetscSortedRemoveDupsInt(n, X));
4001db36a52SBarry Smith   PetscFunctionReturn(0);
4011db36a52SBarry Smith }
4021db36a52SBarry Smith 
40360e03357SMatthew G Knepley /*@
404d9f1162dSJed Brown   PetscFindInt - Finds integer in a sorted array of integers
40560e03357SMatthew G Knepley 
40660e03357SMatthew G Knepley    Not Collective
40760e03357SMatthew G Knepley 
40860e03357SMatthew G Knepley    Input Parameters:
40960e03357SMatthew G Knepley +  key - the integer to locate
410d9f1162dSJed Brown .  n   - number of values in the array
41159e16d97SJunchao Zhang -  X  - array of integers
41260e03357SMatthew G Knepley 
41360e03357SMatthew G Knepley    Output Parameter:
414d9f1162dSJed Brown .  loc - the location if found, otherwise -(slot+1) where slot is the place the value would go
41560e03357SMatthew G Knepley 
41660e03357SMatthew G Knepley    Level: intermediate
41760e03357SMatthew G Knepley 
418db781477SPatrick Sanan .seealso: `PetscIntSortSemiOrdered()`, `PetscSortInt()`, `PetscSortIntWithArray()`, `PetscSortRemoveDupsInt()`
41960e03357SMatthew G Knepley @*/
4209371c9d4SSatish Balay PetscErrorCode PetscFindInt(PetscInt key, PetscInt n, const PetscInt X[], PetscInt *loc) {
421d9f1162dSJed Brown   PetscInt lo = 0, hi = n;
42260e03357SMatthew G Knepley 
42360e03357SMatthew G Knepley   PetscFunctionBegin;
4245f80ce2aSJacob Faibussowitsch   PetscValidIntPointer(loc, 4);
4259371c9d4SSatish Balay   if (!n) {
4269371c9d4SSatish Balay     *loc = -1;
4279371c9d4SSatish Balay     PetscFunctionReturn(0);
4289371c9d4SSatish Balay   }
429dadcf809SJacob Faibussowitsch   PetscValidIntPointer(X, 3);
4306a7c706bSVaclav Hapla   PetscCheckSorted(n, X);
431d9f1162dSJed Brown   while (hi - lo > 1) {
432d9f1162dSJed Brown     PetscInt mid = lo + (hi - lo) / 2;
43359e16d97SJunchao Zhang     if (key < X[mid]) hi = mid;
434d9f1162dSJed Brown     else lo = mid;
43560e03357SMatthew G Knepley   }
43659e16d97SJunchao Zhang   *loc = key == X[lo] ? lo : -(lo + (key > X[lo]) + 1);
43760e03357SMatthew G Knepley   PetscFunctionReturn(0);
43860e03357SMatthew G Knepley }
43960e03357SMatthew G Knepley 
440d2aeb606SJed Brown /*@
441f1cab4e1SJunchao Zhang   PetscCheckDupsInt - Checks if an integer array has duplicates
442f1cab4e1SJunchao Zhang 
443f1cab4e1SJunchao Zhang    Not Collective
444f1cab4e1SJunchao Zhang 
445f1cab4e1SJunchao Zhang    Input Parameters:
446f1cab4e1SJunchao Zhang +  n  - number of values in the array
447f1cab4e1SJunchao Zhang -  X  - array of integers
448f1cab4e1SJunchao Zhang 
449f1cab4e1SJunchao Zhang    Output Parameter:
450f1cab4e1SJunchao Zhang .  dups - True if the array has dups, otherwise false
451f1cab4e1SJunchao Zhang 
452f1cab4e1SJunchao Zhang    Level: intermediate
453f1cab4e1SJunchao Zhang 
454db781477SPatrick Sanan .seealso: `PetscSortRemoveDupsInt()`, `PetscSortedCheckDupsInt()`
455f1cab4e1SJunchao Zhang @*/
4569371c9d4SSatish Balay PetscErrorCode PetscCheckDupsInt(PetscInt n, const PetscInt X[], PetscBool *dups) {
457f1cab4e1SJunchao Zhang   PetscInt   i;
458f1cab4e1SJunchao Zhang   PetscHSetI ht;
459f1cab4e1SJunchao Zhang   PetscBool  missing;
460f1cab4e1SJunchao Zhang 
461f1cab4e1SJunchao Zhang   PetscFunctionBegin;
4625f80ce2aSJacob Faibussowitsch   if (n) PetscValidIntPointer(X, 2);
4635f80ce2aSJacob Faibussowitsch   PetscValidBoolPointer(dups, 3);
464f1cab4e1SJunchao Zhang   *dups = PETSC_FALSE;
465f1cab4e1SJunchao Zhang   if (n > 1) {
4669566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&ht));
4679566063dSJacob Faibussowitsch     PetscCall(PetscHSetIResize(ht, n));
468f1cab4e1SJunchao Zhang     for (i = 0; i < n; i++) {
4699566063dSJacob Faibussowitsch       PetscCall(PetscHSetIQueryAdd(ht, X[i], &missing));
4709371c9d4SSatish Balay       if (!missing) {
4719371c9d4SSatish Balay         *dups = PETSC_TRUE;
4729371c9d4SSatish Balay         break;
4739371c9d4SSatish Balay       }
474f1cab4e1SJunchao Zhang     }
4759566063dSJacob Faibussowitsch     PetscCall(PetscHSetIDestroy(&ht));
476f1cab4e1SJunchao Zhang   }
477f1cab4e1SJunchao Zhang   PetscFunctionReturn(0);
478f1cab4e1SJunchao Zhang }
479f1cab4e1SJunchao Zhang 
480f1cab4e1SJunchao Zhang /*@
481d2aeb606SJed Brown   PetscFindMPIInt - Finds MPI integer in a sorted array of integers
482d2aeb606SJed Brown 
483d2aeb606SJed Brown    Not Collective
484d2aeb606SJed Brown 
485d2aeb606SJed Brown    Input Parameters:
486d2aeb606SJed Brown +  key - the integer to locate
487d2aeb606SJed Brown .  n   - number of values in the array
48859e16d97SJunchao Zhang -  X   - array of integers
489d2aeb606SJed Brown 
490d2aeb606SJed Brown    Output Parameter:
491d2aeb606SJed Brown .  loc - the location if found, otherwise -(slot+1) where slot is the place the value would go
492d2aeb606SJed Brown 
493d2aeb606SJed Brown    Level: intermediate
494d2aeb606SJed Brown 
495db781477SPatrick Sanan .seealso: `PetscMPIIntSortSemiOrdered()`, `PetscSortInt()`, `PetscSortIntWithArray()`, `PetscSortRemoveDupsInt()`
496d2aeb606SJed Brown @*/
4979371c9d4SSatish Balay PetscErrorCode PetscFindMPIInt(PetscMPIInt key, PetscInt n, const PetscMPIInt X[], PetscInt *loc) {
498d2aeb606SJed Brown   PetscInt lo = 0, hi = n;
499d2aeb606SJed Brown 
500d2aeb606SJed Brown   PetscFunctionBegin;
501dadcf809SJacob Faibussowitsch   PetscValidIntPointer(loc, 4);
5029371c9d4SSatish Balay   if (!n) {
5039371c9d4SSatish Balay     *loc = -1;
5049371c9d4SSatish Balay     PetscFunctionReturn(0);
5059371c9d4SSatish Balay   }
506dadcf809SJacob Faibussowitsch   PetscValidIntPointer(X, 3);
5076a7c706bSVaclav Hapla   PetscCheckSorted(n, X);
508d2aeb606SJed Brown   while (hi - lo > 1) {
509d2aeb606SJed Brown     PetscInt mid = lo + (hi - lo) / 2;
51059e16d97SJunchao Zhang     if (key < X[mid]) hi = mid;
511d2aeb606SJed Brown     else lo = mid;
512d2aeb606SJed Brown   }
51359e16d97SJunchao Zhang   *loc = key == X[lo] ? lo : -(lo + (key > X[lo]) + 1);
514e5c89e4eSSatish Balay   PetscFunctionReturn(0);
515e5c89e4eSSatish Balay }
516e5c89e4eSSatish Balay 
517e5c89e4eSSatish Balay /*@
518e5c89e4eSSatish Balay    PetscSortIntWithArray - Sorts an array of integers in place in increasing order;
519e5c89e4eSSatish Balay        changes a second array to match the sorted first array.
520e5c89e4eSSatish Balay 
521e5c89e4eSSatish Balay    Not Collective
522e5c89e4eSSatish Balay 
523e5c89e4eSSatish Balay    Input Parameters:
524e5c89e4eSSatish Balay +  n  - number of values
52559e16d97SJunchao Zhang .  X  - array of integers
52659e16d97SJunchao Zhang -  Y  - second array of integers
527e5c89e4eSSatish Balay 
528e5c89e4eSSatish Balay    Level: intermediate
529e5c89e4eSSatish Balay 
530db781477SPatrick Sanan .seealso: `PetscIntSortSemiOrderedWithArray()`, `PetscSortReal()`, `PetscSortIntWithPermutation()`, `PetscSortInt()`, `PetscSortIntWithCountArray()`
531e5c89e4eSSatish Balay @*/
5329371c9d4SSatish Balay PetscErrorCode PetscSortIntWithArray(PetscInt n, PetscInt X[], PetscInt Y[]) {
53359e16d97SJunchao Zhang   PetscInt pivot, t1, t2;
534e5c89e4eSSatish Balay 
535e5c89e4eSSatish Balay   PetscFunctionBegin;
5365f80ce2aSJacob Faibussowitsch   QuickSort2(PetscSortIntWithArray, X, Y, n, pivot, t1, t2);
537c1f0200aSDmitry Karpeev   PetscFunctionReturn(0);
538c1f0200aSDmitry Karpeev }
539c1f0200aSDmitry Karpeev 
540c1f0200aSDmitry Karpeev /*@
541c1f0200aSDmitry Karpeev    PetscSortIntWithArrayPair - Sorts an array of integers in place in increasing order;
542c1f0200aSDmitry Karpeev        changes a pair of integer arrays to match the sorted first array.
543c1f0200aSDmitry Karpeev 
544c1f0200aSDmitry Karpeev    Not Collective
545c1f0200aSDmitry Karpeev 
546c1f0200aSDmitry Karpeev    Input Parameters:
547c1f0200aSDmitry Karpeev +  n  - number of values
54859e16d97SJunchao Zhang .  X  - array of integers
54959e16d97SJunchao Zhang .  Y  - second array of integers (first array of the pair)
55059e16d97SJunchao Zhang -  Z  - third array of integers  (second array of the pair)
551c1f0200aSDmitry Karpeev 
552c1f0200aSDmitry Karpeev    Level: intermediate
553c1f0200aSDmitry Karpeev 
554db781477SPatrick Sanan .seealso: `PetscSortReal()`, `PetscSortIntWithPermutation()`, `PetscSortIntWithArray()`, `PetscIntSortSemiOrdered()`, `PetscSortIntWithIntCountArrayPair()`
555c1f0200aSDmitry Karpeev @*/
5569371c9d4SSatish Balay PetscErrorCode PetscSortIntWithArrayPair(PetscInt n, PetscInt X[], PetscInt Y[], PetscInt Z[]) {
55759e16d97SJunchao Zhang   PetscInt pivot, t1, t2, t3;
558c1f0200aSDmitry Karpeev 
559c1f0200aSDmitry Karpeev   PetscFunctionBegin;
5605f80ce2aSJacob Faibussowitsch   QuickSort3(PetscSortIntWithArrayPair, X, Y, Z, n, pivot, t1, t2, t3);
561c1f0200aSDmitry Karpeev   PetscFunctionReturn(0);
562c1f0200aSDmitry Karpeev }
563c1f0200aSDmitry Karpeev 
56417d7d925SStefano Zampini /*@
565981bb840SJunchao Zhang    PetscSortIntWithCountArray - Sorts an array of integers in place in increasing order;
566981bb840SJunchao Zhang        changes a second array to match the sorted first array.
567981bb840SJunchao Zhang 
568981bb840SJunchao Zhang    Not Collective
569981bb840SJunchao Zhang 
570981bb840SJunchao Zhang    Input Parameters:
571981bb840SJunchao Zhang +  n  - number of values
572981bb840SJunchao Zhang .  X  - array of integers
573981bb840SJunchao Zhang -  Y  - second array of PetscCounts (signed integers)
574981bb840SJunchao Zhang 
575981bb840SJunchao Zhang    Level: intermediate
576981bb840SJunchao Zhang 
577db781477SPatrick Sanan .seealso: `PetscIntSortSemiOrderedWithArray()`, `PetscSortReal()`, `PetscSortIntPermutation()`, `PetscSortInt()`, `PetscSortIntWithArray()`
578981bb840SJunchao Zhang @*/
5799371c9d4SSatish Balay PetscErrorCode PetscSortIntWithCountArray(PetscCount n, PetscInt X[], PetscCount Y[]) {
580981bb840SJunchao Zhang   PetscInt   pivot, t1;
581981bb840SJunchao Zhang   PetscCount t2;
582981bb840SJunchao Zhang 
583981bb840SJunchao Zhang   PetscFunctionBegin;
5845f80ce2aSJacob Faibussowitsch   QuickSort2(PetscSortIntWithCountArray, X, Y, n, pivot, t1, t2);
585981bb840SJunchao Zhang   PetscFunctionReturn(0);
586981bb840SJunchao Zhang }
587981bb840SJunchao Zhang 
588981bb840SJunchao Zhang /*@
589981bb840SJunchao Zhang    PetscSortIntWithIntCountArrayPair - Sorts an array of integers in place in increasing order;
590981bb840SJunchao Zhang        changes an integer array and a PetscCount array to match the sorted first array.
591981bb840SJunchao Zhang 
592981bb840SJunchao Zhang    Not Collective
593981bb840SJunchao Zhang 
594981bb840SJunchao Zhang    Input Parameters:
595981bb840SJunchao Zhang +  n  - number of values
596981bb840SJunchao Zhang .  X  - array of integers
597981bb840SJunchao Zhang .  Y  - second array of integers (first array of the pair)
598981bb840SJunchao Zhang -  Z  - third array of PetscCounts  (second array of the pair)
599981bb840SJunchao Zhang 
600981bb840SJunchao Zhang    Level: intermediate
601981bb840SJunchao Zhang 
602981bb840SJunchao Zhang    Notes:
603981bb840SJunchao Zhang     Usually X, Y are matrix row/column indices, and Z is a permutation array and therefore Z's type is PetscCount to allow 2B+ nonzeros even with 32-bit PetscInt.
604981bb840SJunchao Zhang 
605db781477SPatrick Sanan .seealso: `PetscSortReal()`, `PetscSortIntPermutation()`, `PetscSortIntWithArray()`, `PetscIntSortSemiOrdered()`, `PetscSortIntWithArrayPair()`
606981bb840SJunchao Zhang @*/
6079371c9d4SSatish Balay PetscErrorCode PetscSortIntWithIntCountArrayPair(PetscCount n, PetscInt X[], PetscInt Y[], PetscCount Z[]) {
608981bb840SJunchao Zhang   PetscInt   pivot, t1, t2; /* pivot is take from X[], so its type is still PetscInt */
609981bb840SJunchao Zhang   PetscCount t3;            /* temp for Z[] */
610981bb840SJunchao Zhang 
611981bb840SJunchao Zhang   PetscFunctionBegin;
6125f80ce2aSJacob Faibussowitsch   QuickSort3(PetscSortIntWithIntCountArrayPair, X, Y, Z, n, pivot, t1, t2, t3);
613981bb840SJunchao Zhang   PetscFunctionReturn(0);
614981bb840SJunchao Zhang }
615981bb840SJunchao Zhang 
616981bb840SJunchao Zhang /*@
6176a7c706bSVaclav Hapla    PetscSortedMPIInt - Determines whether the array is sorted.
6186a7c706bSVaclav Hapla 
6196a7c706bSVaclav Hapla    Not Collective
6206a7c706bSVaclav Hapla 
6216a7c706bSVaclav Hapla    Input Parameters:
6226a7c706bSVaclav Hapla +  n  - number of values
6236a7c706bSVaclav Hapla -  X  - array of integers
6246a7c706bSVaclav Hapla 
6256a7c706bSVaclav Hapla    Output Parameters:
6266a7c706bSVaclav Hapla .  sorted - flag whether the array is sorted
6276a7c706bSVaclav Hapla 
6286a7c706bSVaclav Hapla    Level: intermediate
6296a7c706bSVaclav Hapla 
630db781477SPatrick Sanan .seealso: `PetscMPIIntSortSemiOrdered()`, `PetscSortMPIInt()`, `PetscSortedInt()`, `PetscSortedReal()`
6316a7c706bSVaclav Hapla @*/
6329371c9d4SSatish Balay PetscErrorCode PetscSortedMPIInt(PetscInt n, const PetscMPIInt X[], PetscBool *sorted) {
6336a7c706bSVaclav Hapla   PetscFunctionBegin;
6346a7c706bSVaclav Hapla   PetscSorted(n, X, *sorted);
6356a7c706bSVaclav Hapla   PetscFunctionReturn(0);
6366a7c706bSVaclav Hapla }
6376a7c706bSVaclav Hapla 
6386a7c706bSVaclav Hapla /*@
63917d7d925SStefano Zampini    PetscSortMPIInt - Sorts an array of MPI integers in place in increasing order.
64017d7d925SStefano Zampini 
64117d7d925SStefano Zampini    Not Collective
64217d7d925SStefano Zampini 
64317d7d925SStefano Zampini    Input Parameters:
64417d7d925SStefano Zampini +  n  - number of values
64559e16d97SJunchao Zhang -  X  - array of integers
64617d7d925SStefano Zampini 
64717d7d925SStefano Zampini    Level: intermediate
64817d7d925SStefano Zampini 
649676f2a66SJacob Faibussowitsch    Notes:
650676f2a66SJacob Faibussowitsch    This function serves as an alternative to PetscMPIIntSortSemiOrdered(), and may perform faster especially if the array
651a5b23f4aSJose E. Roman    is completely random. There are exceptions to this and so it is __highly__ recommended that the user benchmark their
652676f2a66SJacob Faibussowitsch    code to see which routine is fastest.
653676f2a66SJacob Faibussowitsch 
654db781477SPatrick Sanan .seealso: `PetscMPIIntSortSemiOrdered()`, `PetscSortReal()`, `PetscSortIntWithPermutation()`
65517d7d925SStefano Zampini @*/
6569371c9d4SSatish Balay PetscErrorCode PetscSortMPIInt(PetscInt n, PetscMPIInt X[]) {
65759e16d97SJunchao Zhang   PetscMPIInt pivot, t1;
65817d7d925SStefano Zampini 
65917d7d925SStefano Zampini   PetscFunctionBegin;
6605f80ce2aSJacob Faibussowitsch   QuickSort1(PetscSortMPIInt, X, n, pivot, t1);
66117d7d925SStefano Zampini   PetscFunctionReturn(0);
66217d7d925SStefano Zampini }
66317d7d925SStefano Zampini 
66417d7d925SStefano Zampini /*@
66517d7d925SStefano Zampini    PetscSortRemoveDupsMPIInt - Sorts an array of MPI integers in place in increasing order removes all duplicate entries
66617d7d925SStefano Zampini 
66717d7d925SStefano Zampini    Not Collective
66817d7d925SStefano Zampini 
66917d7d925SStefano Zampini    Input Parameters:
67017d7d925SStefano Zampini +  n  - number of values
67159e16d97SJunchao Zhang -  X  - array of integers
67217d7d925SStefano Zampini 
67317d7d925SStefano Zampini    Output Parameter:
67417d7d925SStefano Zampini .  n - number of non-redundant values
67517d7d925SStefano Zampini 
67617d7d925SStefano Zampini    Level: intermediate
67717d7d925SStefano Zampini 
678db781477SPatrick Sanan .seealso: `PetscSortReal()`, `PetscSortIntWithPermutation()`, `PetscSortInt()`
67917d7d925SStefano Zampini @*/
6809371c9d4SSatish Balay PetscErrorCode PetscSortRemoveDupsMPIInt(PetscInt *n, PetscMPIInt X[]) {
6815f80ce2aSJacob Faibussowitsch   PetscInt s = 0, N = *n, b = 0;
68217d7d925SStefano Zampini 
68317d7d925SStefano Zampini   PetscFunctionBegin;
6849566063dSJacob Faibussowitsch   PetscCall(PetscSortMPIInt(N, X));
6855f80ce2aSJacob Faibussowitsch   for (PetscInt i = 0; i < N - 1; i++) {
68659e16d97SJunchao Zhang     if (X[b + s + 1] != X[b]) {
6879371c9d4SSatish Balay       X[b + 1] = X[b + s + 1];
6889371c9d4SSatish Balay       b++;
689a297a907SKarl Rupp     } else s++;
69017d7d925SStefano Zampini   }
69117d7d925SStefano Zampini   *n = N - s;
69217d7d925SStefano Zampini   PetscFunctionReturn(0);
69317d7d925SStefano Zampini }
694c1f0200aSDmitry Karpeev 
6954d615ea0SBarry Smith /*@
6964d615ea0SBarry Smith    PetscSortMPIIntWithArray - Sorts an array of integers in place in increasing order;
6974d615ea0SBarry Smith        changes a second array to match the sorted first array.
6984d615ea0SBarry Smith 
6994d615ea0SBarry Smith    Not Collective
7004d615ea0SBarry Smith 
7014d615ea0SBarry Smith    Input Parameters:
7024d615ea0SBarry Smith +  n  - number of values
70359e16d97SJunchao Zhang .  X  - array of integers
70459e16d97SJunchao Zhang -  Y  - second array of integers
7054d615ea0SBarry Smith 
7064d615ea0SBarry Smith    Level: intermediate
7074d615ea0SBarry Smith 
708db781477SPatrick Sanan .seealso: `PetscMPIIntSortSemiOrderedWithArray()`, `PetscSortReal()`, `PetscSortIntWithPermutation()`, `PetscSortInt()`
7094d615ea0SBarry Smith @*/
7109371c9d4SSatish Balay PetscErrorCode PetscSortMPIIntWithArray(PetscMPIInt n, PetscMPIInt X[], PetscMPIInt Y[]) {
71159e16d97SJunchao Zhang   PetscMPIInt pivot, t1, t2;
7124d615ea0SBarry Smith 
7134d615ea0SBarry Smith   PetscFunctionBegin;
7145f80ce2aSJacob Faibussowitsch   QuickSort2(PetscSortMPIIntWithArray, X, Y, n, pivot, t1, t2);
7155569a785SJunchao Zhang   PetscFunctionReturn(0);
7165569a785SJunchao Zhang }
7175569a785SJunchao Zhang 
7185569a785SJunchao Zhang /*@
7195569a785SJunchao Zhang    PetscSortMPIIntWithIntArray - Sorts an array of MPI integers in place in increasing order;
7205569a785SJunchao Zhang        changes a second array of Petsc intergers to match the sorted first array.
7215569a785SJunchao Zhang 
7225569a785SJunchao Zhang    Not Collective
7235569a785SJunchao Zhang 
7245569a785SJunchao Zhang    Input Parameters:
7255569a785SJunchao Zhang +  n  - number of values
72659e16d97SJunchao Zhang .  X  - array of MPI integers
72759e16d97SJunchao Zhang -  Y  - second array of Petsc integers
7285569a785SJunchao Zhang 
7295569a785SJunchao Zhang    Level: intermediate
7305569a785SJunchao Zhang 
7315569a785SJunchao Zhang    Notes: this routine is useful when one needs to sort MPI ranks with other integer arrays.
7325569a785SJunchao Zhang 
733db781477SPatrick Sanan .seealso: `PetscSortMPIIntWithArray()`, `PetscIntSortSemiOrderedWithArray()`, `PetscTimSortWithArray()`
7345569a785SJunchao Zhang @*/
7359371c9d4SSatish Balay PetscErrorCode PetscSortMPIIntWithIntArray(PetscMPIInt n, PetscMPIInt X[], PetscInt Y[]) {
73659e16d97SJunchao Zhang   PetscMPIInt pivot, t1;
7375569a785SJunchao Zhang   PetscInt    t2;
7385569a785SJunchao Zhang 
7395569a785SJunchao Zhang   PetscFunctionBegin;
7405f80ce2aSJacob Faibussowitsch   QuickSort2(PetscSortMPIIntWithIntArray, X, Y, n, pivot, t1, t2);
741e5c89e4eSSatish Balay   PetscFunctionReturn(0);
742e5c89e4eSSatish Balay }
743e5c89e4eSSatish Balay 
744e5c89e4eSSatish Balay /*@
745e5c89e4eSSatish Balay    PetscSortIntWithScalarArray - Sorts an array of integers in place in increasing order;
746e5c89e4eSSatish Balay        changes a second SCALAR array to match the sorted first INTEGER array.
747e5c89e4eSSatish Balay 
748e5c89e4eSSatish Balay    Not Collective
749e5c89e4eSSatish Balay 
750e5c89e4eSSatish Balay    Input Parameters:
751e5c89e4eSSatish Balay +  n  - number of values
75259e16d97SJunchao Zhang .  X  - array of integers
75359e16d97SJunchao Zhang -  Y  - second array of scalars
754e5c89e4eSSatish Balay 
755e5c89e4eSSatish Balay    Level: intermediate
756e5c89e4eSSatish Balay 
757db781477SPatrick Sanan .seealso: `PetscTimSortWithArray()`, `PetscSortReal()`, `PetscSortIntWithPermutation()`, `PetscSortInt()`, `PetscSortIntWithArray()`
758e5c89e4eSSatish Balay @*/
7599371c9d4SSatish Balay PetscErrorCode PetscSortIntWithScalarArray(PetscInt n, PetscInt X[], PetscScalar Y[]) {
76059e16d97SJunchao Zhang   PetscInt    pivot, t1;
76159e16d97SJunchao Zhang   PetscScalar t2;
762e5c89e4eSSatish Balay 
763e5c89e4eSSatish Balay   PetscFunctionBegin;
7645f80ce2aSJacob Faibussowitsch   QuickSort2(PetscSortIntWithScalarArray, X, Y, n, pivot, t1, t2);
76517df18f2SToby Isaac   PetscFunctionReturn(0);
76617df18f2SToby Isaac }
76717df18f2SToby Isaac 
7686c2863d0SBarry Smith /*@C
76917df18f2SToby Isaac    PetscSortIntWithDataArray - Sorts an array of integers in place in increasing order;
77017df18f2SToby Isaac        changes a second array to match the sorted first INTEGER array.  Unlike other sort routines, the user must
77117df18f2SToby Isaac        provide workspace (the size of an element in the data array) to use when sorting.
77217df18f2SToby Isaac 
77317df18f2SToby Isaac    Not Collective
77417df18f2SToby Isaac 
77517df18f2SToby Isaac    Input Parameters:
77617df18f2SToby Isaac +  n  - number of values
77759e16d97SJunchao Zhang .  X  - array of integers
77859e16d97SJunchao Zhang .  Y  - second array of data
77917df18f2SToby Isaac .  size - sizeof elements in the data array in bytes
78059e16d97SJunchao Zhang -  t2   - workspace of "size" bytes used when sorting
78117df18f2SToby Isaac 
78217df18f2SToby Isaac    Level: intermediate
78317df18f2SToby Isaac 
784db781477SPatrick Sanan .seealso: `PetscTimSortWithArray()`, `PetscSortReal()`, `PetscSortIntWithPermutation()`, `PetscSortInt()`, `PetscSortIntWithArray()`
78517df18f2SToby Isaac @*/
7869371c9d4SSatish Balay PetscErrorCode PetscSortIntWithDataArray(PetscInt n, PetscInt X[], void *Y, size_t size, void *t2) {
78759e16d97SJunchao Zhang   char    *YY = (char *)Y;
7885f80ce2aSJacob Faibussowitsch   PetscInt t1, pivot, hi = n - 1;
78917df18f2SToby Isaac 
79017df18f2SToby Isaac   PetscFunctionBegin;
79117df18f2SToby Isaac   if (n < 8) {
7925f80ce2aSJacob Faibussowitsch     for (PetscInt i = 0; i < n; i++) {
79359e16d97SJunchao Zhang       pivot = X[i];
7945f80ce2aSJacob Faibussowitsch       for (PetscInt j = i + 1; j < n; j++) {
79559e16d97SJunchao Zhang         if (pivot > X[j]) {
79659e16d97SJunchao Zhang           SWAP2Data(X[i], X[j], YY + size * i, YY + size * j, t1, t2, size);
79759e16d97SJunchao Zhang           pivot = X[i];
79817df18f2SToby Isaac         }
79917df18f2SToby Isaac       }
80017df18f2SToby Isaac     }
80117df18f2SToby Isaac   } else {
80259e16d97SJunchao Zhang     /* Two way partition */
8035f80ce2aSJacob Faibussowitsch     PetscInt l = 0, r = hi;
8045f80ce2aSJacob Faibussowitsch 
8055f80ce2aSJacob Faibussowitsch     pivot = X[MEDIAN(X, hi)];
80659e16d97SJunchao Zhang     while (1) {
80759e16d97SJunchao Zhang       while (X[l] < pivot) l++;
80859e16d97SJunchao Zhang       while (X[r] > pivot) r--;
8099371c9d4SSatish Balay       if (l >= r) {
8109371c9d4SSatish Balay         r++;
8119371c9d4SSatish Balay         break;
8129371c9d4SSatish Balay       }
81359e16d97SJunchao Zhang       SWAP2Data(X[l], X[r], YY + size * l, YY + size * r, t1, t2, size);
81459e16d97SJunchao Zhang       l++;
81559e16d97SJunchao Zhang       r--;
81659e16d97SJunchao Zhang     }
8179566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithDataArray(l, X, Y, size, t2));
8189566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithDataArray(hi - r + 1, X + r, YY + size * r, size, t2));
81917df18f2SToby Isaac   }
82017df18f2SToby Isaac   PetscFunctionReturn(0);
82117df18f2SToby Isaac }
82217df18f2SToby Isaac 
82321e72a00SBarry Smith /*@
82421e72a00SBarry Smith    PetscMergeIntArray -     Merges two SORTED integer arrays, removes duplicate elements.
82521e72a00SBarry Smith 
82621e72a00SBarry Smith    Not Collective
82721e72a00SBarry Smith 
82821e72a00SBarry Smith    Input Parameters:
82921e72a00SBarry Smith +  an  - number of values in the first array
83021e72a00SBarry Smith .  aI  - first sorted array of integers
83121e72a00SBarry Smith .  bn  - number of values in the second array
83221e72a00SBarry Smith -  bI  - second array of integers
83321e72a00SBarry Smith 
83421e72a00SBarry Smith    Output Parameters:
83521e72a00SBarry Smith +  n   - number of values in the merged array
8366c2863d0SBarry Smith -  L   - merged sorted array, this is allocated if an array is not provided
83721e72a00SBarry Smith 
83821e72a00SBarry Smith    Level: intermediate
83921e72a00SBarry Smith 
840db781477SPatrick Sanan .seealso: `PetscSortReal()`, `PetscSortIntWithPermutation()`, `PetscSortInt()`, `PetscSortIntWithArray()`
84121e72a00SBarry Smith @*/
8429371c9d4SSatish Balay PetscErrorCode PetscMergeIntArray(PetscInt an, const PetscInt aI[], PetscInt bn, const PetscInt bI[], PetscInt *n, PetscInt **L) {
84321e72a00SBarry Smith   PetscInt *L_ = *L, ak, bk, k;
84421e72a00SBarry Smith 
845362febeeSStefano Zampini   PetscFunctionBegin;
84621e72a00SBarry Smith   if (!L_) {
8479566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(an + bn, L));
84821e72a00SBarry Smith     L_ = *L;
84921e72a00SBarry Smith   }
85021e72a00SBarry Smith   k = ak = bk = 0;
85121e72a00SBarry Smith   while (ak < an && bk < bn) {
85221e72a00SBarry Smith     if (aI[ak] == bI[bk]) {
85321e72a00SBarry Smith       L_[k] = aI[ak];
85421e72a00SBarry Smith       ++ak;
85521e72a00SBarry Smith       ++bk;
85621e72a00SBarry Smith       ++k;
85721e72a00SBarry Smith     } else if (aI[ak] < bI[bk]) {
85821e72a00SBarry Smith       L_[k] = aI[ak];
85921e72a00SBarry Smith       ++ak;
86021e72a00SBarry Smith       ++k;
86121e72a00SBarry Smith     } else {
86221e72a00SBarry Smith       L_[k] = bI[bk];
86321e72a00SBarry Smith       ++bk;
86421e72a00SBarry Smith       ++k;
86521e72a00SBarry Smith     }
86621e72a00SBarry Smith   }
86721e72a00SBarry Smith   if (ak < an) {
8689566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(L_ + k, aI + ak, an - ak));
86921e72a00SBarry Smith     k += (an - ak);
87021e72a00SBarry Smith   }
87121e72a00SBarry Smith   if (bk < bn) {
8729566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(L_ + k, bI + bk, bn - bk));
87321e72a00SBarry Smith     k += (bn - bk);
87421e72a00SBarry Smith   }
87521e72a00SBarry Smith   *n = k;
87621e72a00SBarry Smith   PetscFunctionReturn(0);
87721e72a00SBarry Smith }
878b4301105SBarry Smith 
879c1f0200aSDmitry Karpeev /*@
88021e72a00SBarry Smith    PetscMergeIntArrayPair -     Merges two SORTED integer arrays that share NO common values along with an additional array of integers.
881c1f0200aSDmitry Karpeev                                 The additional arrays are the same length as sorted arrays and are merged
882c1f0200aSDmitry Karpeev                                 in the order determined by the merging of the sorted pair.
883c1f0200aSDmitry Karpeev 
884c1f0200aSDmitry Karpeev    Not Collective
885c1f0200aSDmitry Karpeev 
886c1f0200aSDmitry Karpeev    Input Parameters:
887c1f0200aSDmitry Karpeev +  an  - number of values in the first array
888c1f0200aSDmitry Karpeev .  aI  - first sorted array of integers
889c1f0200aSDmitry Karpeev .  aJ  - first additional array of integers
890c1f0200aSDmitry Karpeev .  bn  - number of values in the second array
891c1f0200aSDmitry Karpeev .  bI  - second array of integers
892c1f0200aSDmitry Karpeev -  bJ  - second additional of integers
893c1f0200aSDmitry Karpeev 
894c1f0200aSDmitry Karpeev    Output Parameters:
895c1f0200aSDmitry Karpeev +  n   - number of values in the merged array (== an + bn)
89614c49006SJed Brown .  L   - merged sorted array
897c1f0200aSDmitry Karpeev -  J   - merged additional array
898c1f0200aSDmitry Karpeev 
89995452b02SPatrick Sanan    Notes:
90095452b02SPatrick 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
901c1f0200aSDmitry Karpeev    Level: intermediate
902c1f0200aSDmitry Karpeev 
903db781477SPatrick Sanan .seealso: `PetscIntSortSemiOrdered()`, `PetscSortReal()`, `PetscSortIntWithPermutation()`, `PetscSortInt()`, `PetscSortIntWithArray()`
904c1f0200aSDmitry Karpeev @*/
9059371c9d4SSatish Balay PetscErrorCode PetscMergeIntArrayPair(PetscInt an, const PetscInt aI[], const PetscInt aJ[], PetscInt bn, const PetscInt bI[], const PetscInt bJ[], PetscInt *n, PetscInt **L, PetscInt **J) {
90670d8d27cSBarry Smith   PetscInt n_, *L_, *J_, ak, bk, k;
907c1f0200aSDmitry Karpeev 
90814c49006SJed Brown   PetscFunctionBegin;
909dadcf809SJacob Faibussowitsch   PetscValidPointer(L, 8);
910dadcf809SJacob Faibussowitsch   PetscValidPointer(J, 9);
911c1f0200aSDmitry Karpeev   n_ = an + bn;
912c1f0200aSDmitry Karpeev   *n = n_;
913*48a46eb9SPierre Jolivet   if (!*L) PetscCall(PetscMalloc1(n_, L));
914d7aa01a8SHong Zhang   L_ = *L;
915*48a46eb9SPierre Jolivet   if (!*J) PetscCall(PetscMalloc1(n_, J));
916c1f0200aSDmitry Karpeev   J_ = *J;
917c1f0200aSDmitry Karpeev   k = ak = bk = 0;
918c1f0200aSDmitry Karpeev   while (ak < an && bk < bn) {
919c1f0200aSDmitry Karpeev     if (aI[ak] <= bI[bk]) {
920d7aa01a8SHong Zhang       L_[k] = aI[ak];
921c1f0200aSDmitry Karpeev       J_[k] = aJ[ak];
922c1f0200aSDmitry Karpeev       ++ak;
923c1f0200aSDmitry Karpeev       ++k;
924a297a907SKarl Rupp     } else {
925d7aa01a8SHong Zhang       L_[k] = bI[bk];
926c1f0200aSDmitry Karpeev       J_[k] = bJ[bk];
927c1f0200aSDmitry Karpeev       ++bk;
928c1f0200aSDmitry Karpeev       ++k;
929c1f0200aSDmitry Karpeev     }
930c1f0200aSDmitry Karpeev   }
931c1f0200aSDmitry Karpeev   if (ak < an) {
9329566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(L_ + k, aI + ak, an - ak));
9339566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(J_ + k, aJ + ak, an - ak));
934c1f0200aSDmitry Karpeev     k += (an - ak);
935c1f0200aSDmitry Karpeev   }
936c1f0200aSDmitry Karpeev   if (bk < bn) {
9379566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(L_ + k, bI + bk, bn - bk));
9389566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(J_ + k, bJ + bk, bn - bk));
939c1f0200aSDmitry Karpeev   }
940c1f0200aSDmitry Karpeev   PetscFunctionReturn(0);
941c1f0200aSDmitry Karpeev }
942c1f0200aSDmitry Karpeev 
943e498c390SJed Brown /*@
944e498c390SJed Brown    PetscMergeMPIIntArray -     Merges two SORTED integer arrays.
945e498c390SJed Brown 
946e498c390SJed Brown    Not Collective
947e498c390SJed Brown 
948e498c390SJed Brown    Input Parameters:
949e498c390SJed Brown +  an  - number of values in the first array
950e498c390SJed Brown .  aI  - first sorted array of integers
951e498c390SJed Brown .  bn  - number of values in the second array
952e498c390SJed Brown -  bI  - second array of integers
953e498c390SJed Brown 
954e498c390SJed Brown    Output Parameters:
955e498c390SJed Brown +  n   - number of values in the merged array (<= an + bn)
956e498c390SJed Brown -  L   - merged sorted array, allocated if address of NULL pointer is passed
957e498c390SJed Brown 
958e498c390SJed Brown    Level: intermediate
959e498c390SJed Brown 
960db781477SPatrick Sanan .seealso: `PetscIntSortSemiOrdered()`, `PetscSortReal()`, `PetscSortIntWithPermutation()`, `PetscSortInt()`, `PetscSortIntWithArray()`
961e498c390SJed Brown @*/
9629371c9d4SSatish Balay PetscErrorCode PetscMergeMPIIntArray(PetscInt an, const PetscMPIInt aI[], PetscInt bn, const PetscMPIInt bI[], PetscInt *n, PetscMPIInt **L) {
963e498c390SJed Brown   PetscInt ai, bi, k;
964e498c390SJed Brown 
965e498c390SJed Brown   PetscFunctionBegin;
9669566063dSJacob Faibussowitsch   if (!*L) PetscCall(PetscMalloc1((an + bn), L));
967e498c390SJed Brown   for (ai = 0, bi = 0, k = 0; ai < an || bi < bn;) {
968e498c390SJed Brown     PetscInt t = -1;
969e498c390SJed Brown     for (; ai < an && (!bn || aI[ai] <= bI[bi]); ai++) (*L)[k++] = t = aI[ai];
9709371c9d4SSatish Balay     for (; bi < bn && bI[bi] == t; bi++)
9719371c9d4SSatish Balay       ;
972e498c390SJed Brown     for (; bi < bn && (!an || bI[bi] <= aI[ai]); bi++) (*L)[k++] = t = bI[bi];
9739371c9d4SSatish Balay     for (; ai < an && aI[ai] == t; ai++)
9749371c9d4SSatish Balay       ;
975e498c390SJed Brown   }
976e498c390SJed Brown   *n = k;
977e498c390SJed Brown   PetscFunctionReturn(0);
978e498c390SJed Brown }
979e5c89e4eSSatish Balay 
9806c2863d0SBarry Smith /*@C
98142eaa7f3SBarry Smith    PetscProcessTree - Prepares tree data to be displayed graphically
98242eaa7f3SBarry Smith 
98342eaa7f3SBarry Smith    Not Collective
98442eaa7f3SBarry Smith 
98542eaa7f3SBarry Smith    Input Parameters:
98642eaa7f3SBarry Smith +  n  - number of values
98742eaa7f3SBarry Smith .  mask - indicates those entries in the tree, location 0 is always masked
98842eaa7f3SBarry Smith -  parentid - indicates the parent of each entry
98942eaa7f3SBarry Smith 
99042eaa7f3SBarry Smith    Output Parameters:
99142eaa7f3SBarry Smith +  Nlevels - the number of levels
99242eaa7f3SBarry Smith .  Level - for each node tells its level
99342eaa7f3SBarry Smith .  Levelcnts - the number of nodes on each level
99442eaa7f3SBarry Smith .  Idbylevel - a list of ids on each of the levels, first level followed by second etc
99542eaa7f3SBarry Smith -  Column - for each id tells its column index
99642eaa7f3SBarry Smith 
9976c2863d0SBarry Smith    Level: developer
99842eaa7f3SBarry Smith 
99995452b02SPatrick Sanan    Notes:
100095452b02SPatrick Sanan     This code is not currently used
100142eaa7f3SBarry Smith 
1002db781477SPatrick Sanan .seealso: `PetscSortReal()`, `PetscSortIntWithPermutation()`
100342eaa7f3SBarry Smith @*/
10049371c9d4SSatish Balay PetscErrorCode PetscProcessTree(PetscInt n, const PetscBool mask[], const PetscInt parentid[], PetscInt *Nlevels, PetscInt **Level, PetscInt **Levelcnt, PetscInt **Idbylevel, PetscInt **Column) {
100542eaa7f3SBarry Smith   PetscInt  i, j, cnt, nmask = 0, nlevels = 0, *level, *levelcnt, levelmax = 0, *workid, *workparentid, tcnt = 0, *idbylevel, *column;
1006ace3abfcSBarry Smith   PetscBool done = PETSC_FALSE;
100742eaa7f3SBarry Smith 
100842eaa7f3SBarry Smith   PetscFunctionBegin;
100908401ef6SPierre Jolivet   PetscCheck(mask[0], PETSC_COMM_SELF, PETSC_ERR_SUP, "Mask of 0th location must be set");
101042eaa7f3SBarry Smith   for (i = 0; i < n; i++) {
101142eaa7f3SBarry Smith     if (mask[i]) continue;
101208401ef6SPierre Jolivet     PetscCheck(parentid[i] != i, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Node labeled as own parent");
1013cc73adaaSBarry Smith     PetscCheck(!parentid[i] || !mask[parentid[i]], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Parent is masked");
101442eaa7f3SBarry Smith   }
101542eaa7f3SBarry Smith 
101642eaa7f3SBarry Smith   for (i = 0; i < n; i++) {
101742eaa7f3SBarry Smith     if (!mask[i]) nmask++;
101842eaa7f3SBarry Smith   }
101942eaa7f3SBarry Smith 
102042eaa7f3SBarry Smith   /* determine the level in the tree of each node */
10219566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(n, &level));
1022a297a907SKarl Rupp 
102342eaa7f3SBarry Smith   level[0] = 1;
102442eaa7f3SBarry Smith   while (!done) {
102542eaa7f3SBarry Smith     done = PETSC_TRUE;
102642eaa7f3SBarry Smith     for (i = 0; i < n; i++) {
102742eaa7f3SBarry Smith       if (mask[i]) continue;
102842eaa7f3SBarry Smith       if (!level[i] && level[parentid[i]]) level[i] = level[parentid[i]] + 1;
102942eaa7f3SBarry Smith       else if (!level[i]) done = PETSC_FALSE;
103042eaa7f3SBarry Smith     }
103142eaa7f3SBarry Smith   }
103242eaa7f3SBarry Smith   for (i = 0; i < n; i++) {
103342eaa7f3SBarry Smith     level[i]--;
103442eaa7f3SBarry Smith     nlevels = PetscMax(nlevels, level[i]);
103542eaa7f3SBarry Smith   }
103642eaa7f3SBarry Smith 
103742eaa7f3SBarry Smith   /* count the number of nodes on each level and its max */
10389566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(nlevels, &levelcnt));
103942eaa7f3SBarry Smith   for (i = 0; i < n; i++) {
104042eaa7f3SBarry Smith     if (mask[i]) continue;
104142eaa7f3SBarry Smith     levelcnt[level[i] - 1]++;
104242eaa7f3SBarry Smith   }
1043a297a907SKarl Rupp   for (i = 0; i < nlevels; i++) levelmax = PetscMax(levelmax, levelcnt[i]);
104442eaa7f3SBarry Smith 
104542eaa7f3SBarry Smith   /* for each level sort the ids by the parent id */
10469566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(levelmax, &workid, levelmax, &workparentid));
10479566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nmask, &idbylevel));
104842eaa7f3SBarry Smith   for (j = 1; j <= nlevels; j++) {
104942eaa7f3SBarry Smith     cnt = 0;
105042eaa7f3SBarry Smith     for (i = 0; i < n; i++) {
105142eaa7f3SBarry Smith       if (mask[i]) continue;
105242eaa7f3SBarry Smith       if (level[i] != j) continue;
105342eaa7f3SBarry Smith       workid[cnt]         = i;
105442eaa7f3SBarry Smith       workparentid[cnt++] = parentid[i];
105542eaa7f3SBarry Smith     }
105642eaa7f3SBarry Smith     /*  PetscIntView(cnt,workparentid,0);
105742eaa7f3SBarry Smith     PetscIntView(cnt,workid,0);
10589566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithArray(cnt,workparentid,workid));
105942eaa7f3SBarry Smith     PetscIntView(cnt,workparentid,0);
106042eaa7f3SBarry Smith     PetscIntView(cnt,workid,0);*/
10619566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(idbylevel + tcnt, workid, cnt));
106242eaa7f3SBarry Smith     tcnt += cnt;
106342eaa7f3SBarry Smith   }
106408401ef6SPierre Jolivet   PetscCheck(tcnt == nmask, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent count of unmasked nodes");
10659566063dSJacob Faibussowitsch   PetscCall(PetscFree2(workid, workparentid));
106642eaa7f3SBarry Smith 
106742eaa7f3SBarry Smith   /* for each node list its column */
10689566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n, &column));
106942eaa7f3SBarry Smith   cnt = 0;
107042eaa7f3SBarry Smith   for (j = 0; j < nlevels; j++) {
10719371c9d4SSatish Balay     for (i = 0; i < levelcnt[j]; i++) { column[idbylevel[cnt++]] = i; }
107242eaa7f3SBarry Smith   }
107342eaa7f3SBarry Smith 
107442eaa7f3SBarry Smith   *Nlevels   = nlevels;
107542eaa7f3SBarry Smith   *Level     = level;
107642eaa7f3SBarry Smith   *Levelcnt  = levelcnt;
107742eaa7f3SBarry Smith   *Idbylevel = idbylevel;
107842eaa7f3SBarry Smith   *Column    = column;
107942eaa7f3SBarry Smith   PetscFunctionReturn(0);
108042eaa7f3SBarry Smith }
1081ce605777SToby Isaac 
1082ce605777SToby Isaac /*@
1083ce605777SToby Isaac   PetscParallelSortedInt - Check whether an integer array, distributed over a communicator, is globally sorted.
1084ce605777SToby Isaac 
1085ce605777SToby Isaac   Collective
1086ce605777SToby Isaac 
1087ce605777SToby Isaac   Input Parameters:
1088ce605777SToby Isaac + comm - the MPI communicator
1089ce605777SToby Isaac . n - the local number of integers
1090ce605777SToby Isaac - keys - the local array of integers
1091ce605777SToby Isaac 
1092ce605777SToby Isaac   Output Parameters:
1093ce605777SToby Isaac . is_sorted - whether the array is globally sorted
1094ce605777SToby Isaac 
1095ce605777SToby Isaac   Level: developer
1096ce605777SToby Isaac 
1097db781477SPatrick Sanan .seealso: `PetscParallelSortInt()`
1098ce605777SToby Isaac @*/
10999371c9d4SSatish Balay PetscErrorCode PetscParallelSortedInt(MPI_Comm comm, PetscInt n, const PetscInt keys[], PetscBool *is_sorted) {
1100ce605777SToby Isaac   PetscBool   sorted;
1101ce605777SToby Isaac   PetscInt    i, min, max, prevmax;
11022a1da528SToby Isaac   PetscMPIInt rank;
1103ce605777SToby Isaac 
1104ce605777SToby Isaac   PetscFunctionBegin;
1105ce605777SToby Isaac   sorted = PETSC_TRUE;
1106ce605777SToby Isaac   min    = PETSC_MAX_INT;
1107ce605777SToby Isaac   max    = PETSC_MIN_INT;
1108ce605777SToby Isaac   if (n) {
1109ce605777SToby Isaac     min = keys[0];
1110ce605777SToby Isaac     max = keys[0];
1111ce605777SToby Isaac   }
1112ce605777SToby Isaac   for (i = 1; i < n; i++) {
1113ce605777SToby Isaac     if (keys[i] < keys[i - 1]) break;
1114ce605777SToby Isaac     min = PetscMin(min, keys[i]);
1115ce605777SToby Isaac     max = PetscMax(max, keys[i]);
1116ce605777SToby Isaac   }
1117ce605777SToby Isaac   if (i < n) sorted = PETSC_FALSE;
1118ce605777SToby Isaac   prevmax = PETSC_MIN_INT;
11199566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Exscan(&max, &prevmax, 1, MPIU_INT, MPI_MAX, comm));
11209566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1121dd400576SPatrick Sanan   if (rank == 0) prevmax = PETSC_MIN_INT;
1122ce605777SToby Isaac   if (prevmax > min) sorted = PETSC_FALSE;
11239566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allreduce(&sorted, is_sorted, 1, MPIU_BOOL, MPI_LAND, comm));
1124ce605777SToby Isaac   PetscFunctionReturn(0);
1125ce605777SToby Isaac }
1126