Actual source code: sorti.c
2: /*
3: This file contains routines for sorting integers. Values are sorted in place.
4: One can use src/sys/tests/ex52.c for benchmarking.
5: */
6: #include <petsc/private/petscimpl.h>
7: #include <petsc/private/hashseti.h>
9: #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))))
11: #define MEDIAN(v, right) MEDIAN3(v, right / 4, right / 2, right / 4 * 3)
13: /* Swap one, two or three pairs. Each pair can have its own type */
14: #define SWAP1(a, b, t1) \
15: do { \
16: t1 = a; \
17: a = b; \
18: b = t1; \
19: } while (0)
20: #define SWAP2(a, b, c, d, t1, t2) \
21: do { \
22: t1 = a; \
23: a = b; \
24: b = t1; \
25: t2 = c; \
26: c = d; \
27: d = t2; \
28: } while (0)
29: #define SWAP3(a, b, c, d, e, f, t1, t2, t3) \
30: do { \
31: t1 = a; \
32: a = b; \
33: b = t1; \
34: t2 = c; \
35: c = d; \
36: d = t2; \
37: t3 = e; \
38: e = f; \
39: f = t3; \
40: } while (0)
42: /* Swap a & b, *c & *d. c, d, t2 are pointers to a type of size <siz> */
43: #define SWAP2Data(a, b, c, d, t1, t2, siz) \
44: do { \
45: t1 = a; \
46: a = b; \
47: b = t1; \
48: PetscMemcpy(t2, c, siz); \
49: PetscMemcpy(c, d, siz); \
50: PetscMemcpy(d, t2, siz); \
51: } while (0)
53: /*
54: Partition X[lo,hi] into two parts: X[lo,l) <= pivot; X[r,hi] > pivot
56: Input Parameters:
57: + X - array to partition
58: . pivot - a pivot of X[]
59: . t1 - temp variable for X
60: - lo,hi - lower and upper bound of the array
62: Output Parameters:
63: + l,r - of type PetscInt
65: Note:
66: The TwoWayPartition2/3 variants also partition other arrays along with X.
67: These arrays can have different types, so they provide their own temp t2,t3
68: */
69: #define TwoWayPartition1(X, pivot, t1, lo, hi, l, r) \
70: do { \
71: l = lo; \
72: r = hi; \
73: while (1) { \
74: while (X[l] < pivot) l++; \
75: while (X[r] > pivot) r--; \
76: if (l >= r) { \
77: r++; \
78: break; \
79: } \
80: SWAP1(X[l], X[r], t1); \
81: l++; \
82: r--; \
83: } \
84: } while (0)
86: /*
87: Partition X[lo,hi] into two parts: X[lo,l) >= pivot; X[r,hi] < pivot
89: Input Parameters:
90: + X - array to partition
91: . pivot - a pivot of X[]
92: . t1 - temp variable for X
93: - lo,hi - lower and upper bound of the array
95: Output Parameters:
96: + l,r - of type PetscInt
98: Note:
99: The TwoWayPartition2/3 variants also partition other arrays along with X.
100: These arrays can have different types, so they provide their own temp t2,t3
101: */
102: #define TwoWayPartitionReverse1(X, pivot, t1, lo, hi, l, r) \
103: do { \
104: l = lo; \
105: r = hi; \
106: while (1) { \
107: while (X[l] > pivot) l++; \
108: while (X[r] < pivot) r--; \
109: if (l >= r) { \
110: r++; \
111: break; \
112: } \
113: SWAP1(X[l], X[r], t1); \
114: l++; \
115: r--; \
116: } \
117: } while (0)
119: #define TwoWayPartition2(X, Y, pivot, t1, t2, lo, hi, l, r) \
120: do { \
121: l = lo; \
122: r = hi; \
123: while (1) { \
124: while (X[l] < pivot) l++; \
125: while (X[r] > pivot) r--; \
126: if (l >= r) { \
127: r++; \
128: break; \
129: } \
130: SWAP2(X[l], X[r], Y[l], Y[r], t1, t2); \
131: l++; \
132: r--; \
133: } \
134: } while (0)
136: #define TwoWayPartition3(X, Y, Z, pivot, t1, t2, t3, lo, hi, l, r) \
137: do { \
138: l = lo; \
139: r = hi; \
140: while (1) { \
141: while (X[l] < pivot) l++; \
142: while (X[r] > pivot) r--; \
143: if (l >= r) { \
144: r++; \
145: break; \
146: } \
147: SWAP3(X[l], X[r], Y[l], Y[r], Z[l], Z[r], t1, t2, t3); \
148: l++; \
149: r--; \
150: } \
151: } while (0)
153: /* Templates for similar functions used below */
154: #define QuickSort1(FuncName, X, n, pivot, t1) \
155: do { \
156: PetscCount i, j, p, l, r, hi = n - 1; \
157: if (n < 8) { \
158: for (i = 0; i < n; i++) { \
159: pivot = X[i]; \
160: for (j = i + 1; j < n; j++) { \
161: if (pivot > X[j]) { \
162: SWAP1(X[i], X[j], t1); \
163: pivot = X[i]; \
164: } \
165: } \
166: } \
167: } else { \
168: p = MEDIAN(X, hi); \
169: pivot = X[p]; \
170: TwoWayPartition1(X, pivot, t1, 0, hi, l, r); \
171: FuncName(l, X); \
172: FuncName(hi - r + 1, X + r); \
173: } \
174: } while (0)
176: /* Templates for similar functions used below */
177: #define QuickSortReverse1(FuncName, X, n, pivot, t1) \
178: do { \
179: PetscCount i, j, p, l, r, hi = n - 1; \
180: if (n < 8) { \
181: for (i = 0; i < n; i++) { \
182: pivot = X[i]; \
183: for (j = i + 1; j < n; j++) { \
184: if (pivot < X[j]) { \
185: SWAP1(X[i], X[j], t1); \
186: pivot = X[i]; \
187: } \
188: } \
189: } \
190: } else { \
191: p = MEDIAN(X, hi); \
192: pivot = X[p]; \
193: TwoWayPartitionReverse1(X, pivot, t1, 0, hi, l, r); \
194: FuncName(l, X); \
195: FuncName(hi - r + 1, X + r); \
196: } \
197: } while (0)
199: #define QuickSort2(FuncName, X, Y, n, pivot, t1, t2) \
200: do { \
201: PetscCount i, j, p, l, r, hi = n - 1; \
202: if (n < 8) { \
203: for (i = 0; i < n; i++) { \
204: pivot = X[i]; \
205: for (j = i + 1; j < n; j++) { \
206: if (pivot > X[j]) { \
207: SWAP2(X[i], X[j], Y[i], Y[j], t1, t2); \
208: pivot = X[i]; \
209: } \
210: } \
211: } \
212: } else { \
213: p = MEDIAN(X, hi); \
214: pivot = X[p]; \
215: TwoWayPartition2(X, Y, pivot, t1, t2, 0, hi, l, r); \
216: FuncName(l, X, Y); \
217: FuncName(hi - r + 1, X + r, Y + r); \
218: } \
219: } while (0)
221: #define QuickSort3(FuncName, X, Y, Z, n, pivot, t1, t2, t3) \
222: do { \
223: PetscCount i, j, p, l, r, hi = n - 1; \
224: if (n < 8) { \
225: for (i = 0; i < n; i++) { \
226: pivot = X[i]; \
227: for (j = i + 1; j < n; j++) { \
228: if (pivot > X[j]) { \
229: SWAP3(X[i], X[j], Y[i], Y[j], Z[i], Z[j], t1, t2, t3); \
230: pivot = X[i]; \
231: } \
232: } \
233: } \
234: } else { \
235: p = MEDIAN(X, hi); \
236: pivot = X[p]; \
237: TwoWayPartition3(X, Y, Z, pivot, t1, t2, t3, 0, hi, l, r); \
238: FuncName(l, X, Y, Z); \
239: FuncName(hi - r + 1, X + r, Y + r, Z + r); \
240: } \
241: } while (0)
243: /*@
244: PetscSortedInt - Determines whether the `PetscInt` array is sorted.
246: Not Collective
248: Input Parameters:
249: + n - number of values
250: - X - array of integers
252: Output Parameters:
253: . sorted - flag whether the array is sorted
255: Level: intermediate
257: .seealso: `PetscSortInt()`, `PetscSortedMPIInt()`, `PetscSortedReal()`
258: @*/
259: PetscErrorCode PetscSortedInt(PetscInt n, const PetscInt X[], PetscBool *sorted)
260: {
263: PetscSorted(n, X, *sorted);
264: return 0;
265: }
267: /*@
268: PetscSortInt - Sorts an array of `PetscInt` in place in increasing order.
270: Not Collective
272: Input Parameters:
273: + n - number of values
274: - X - array of integers
276: Note:
277: This function serves as an alternative to `PetscIntSortSemiOrdered()`, and may perform faster especially if the array
278: is completely random. There are exceptions to this and so it is __highly__ recommended that the user benchmark their
279: code to see which routine is fastest.
281: Level: intermediate
283: .seealso: `PetscIntSortSemiOrdered()`, `PetscSortReal()`, `PetscSortIntWithPermutation()`
284: @*/
285: PetscErrorCode PetscSortInt(PetscInt n, PetscInt X[])
286: {
287: PetscInt pivot, t1;
290: QuickSort1(PetscSortInt, X, n, pivot, t1);
291: return 0;
292: }
294: /*@
295: PetscSortReverseInt - Sorts an array of `PetscInt` in place in decreasing order.
297: Not Collective
299: Input Parameters:
300: + n - number of values
301: - X - array of integers
303: Level: intermediate
305: .seealso: `PetscIntSortSemiOrdered()`, `PetscSortInt()`, `PetscSortIntWithPermutation()`
306: @*/
307: PetscErrorCode PetscSortReverseInt(PetscInt n, PetscInt X[])
308: {
309: PetscInt pivot, t1;
312: QuickSortReverse1(PetscSortReverseInt, X, n, pivot, t1);
313: return 0;
314: }
316: /*@
317: PetscSortedRemoveDupsInt - Removes all duplicate entries of a sorted `PetscInt` array
319: Not Collective
321: Input Parameters:
322: + n - number of values
323: - X - sorted array of integers
325: Output Parameter:
326: . n - number of non-redundant values
328: Level: intermediate
330: .seealso: `PetscSortInt()`
331: @*/
332: PetscErrorCode PetscSortedRemoveDupsInt(PetscInt *n, PetscInt X[])
333: {
334: PetscInt i, s = 0, N = *n, b = 0;
338: for (i = 0; i < N - 1; i++) {
339: if (X[b + s + 1] != X[b]) {
340: X[b + 1] = X[b + s + 1];
341: b++;
342: } else s++;
343: }
344: *n = N - s;
345: return 0;
346: }
348: /*@
349: PetscSortedCheckDupsInt - Checks if a sorted `PetscInt` array has duplicates
351: Not Collective
353: Input Parameters:
354: + n - number of values
355: - X - sorted array of integers
357: Output Parameter:
358: . dups - True if the array has dups, otherwise false
360: Level: intermediate
363: @*/
364: PetscErrorCode PetscSortedCheckDupsInt(PetscInt n, const PetscInt X[], PetscBool *flg)
365: {
366: PetscInt i;
369: *flg = PETSC_FALSE;
370: for (i = 0; i < n - 1; i++) {
371: if (X[i + 1] == X[i]) {
372: *flg = PETSC_TRUE;
373: break;
374: }
375: }
376: return 0;
377: }
379: /*@
380: PetscSortRemoveDupsInt - Sorts an array of `PetscInt` in place in increasing order removes all duplicate entries
382: Not Collective
384: Input Parameters:
385: + n - number of values
386: - X - array of integers
388: Output Parameter:
389: . n - number of non-redundant values
391: Level: intermediate
393: .seealso: `PetscIntSortSemiOrdered()`, `PetscSortReal()`, `PetscSortIntWithPermutation()`, `PetscSortInt()`, `PetscSortedRemoveDupsInt()`
394: @*/
395: PetscErrorCode PetscSortRemoveDupsInt(PetscInt *n, PetscInt X[])
396: {
398: PetscSortInt(*n, X);
399: PetscSortedRemoveDupsInt(n, X);
400: return 0;
401: }
403: /*@
404: PetscFindInt - Finds `PetscInt` in a sorted array of `PetscInt`
406: Not Collective
408: Input Parameters:
409: + key - the integer to locate
410: . n - number of values in the array
411: - X - array of integers
413: Output Parameter:
414: . loc - the location if found, otherwise -(slot+1) where slot is the place the value would go
416: Level: intermediate
418: .seealso: `PetscIntSortSemiOrdered()`, `PetscSortInt()`, `PetscSortIntWithArray()`, `PetscSortRemoveDupsInt()`
419: @*/
420: PetscErrorCode PetscFindInt(PetscInt key, PetscInt n, const PetscInt X[], PetscInt *loc)
421: {
422: PetscInt lo = 0, hi = n;
425: if (!n) {
426: *loc = -1;
427: return 0;
428: }
431: while (hi - lo > 1) {
432: PetscInt mid = lo + (hi - lo) / 2;
433: if (key < X[mid]) hi = mid;
434: else lo = mid;
435: }
436: *loc = key == X[lo] ? lo : -(lo + (key > X[lo]) + 1);
437: return 0;
438: }
440: /*@
443: Not Collective
445: Input Parameters:
446: + n - number of values in the array
447: - X - array of integers
449: Output Parameter:
450: . dups - True if the array has dups, otherwise false
452: Level: intermediate
454: .seealso: `PetscSortRemoveDupsInt()`, `PetscSortedCheckDupsInt()`
455: @*/
457: {
458: PetscInt i;
459: PetscHSetI ht;
460: PetscBool missing;
464: *dups = PETSC_FALSE;
465: if (n > 1) {
466: PetscHSetICreate(&ht);
467: PetscHSetIResize(ht, n);
468: for (i = 0; i < n; i++) {
469: PetscHSetIQueryAdd(ht, X[i], &missing);
470: if (!missing) {
471: *dups = PETSC_TRUE;
472: break;
473: }
474: }
475: PetscHSetIDestroy(&ht);
476: }
477: return 0;
478: }
480: /*@
481: PetscFindMPIInt - Finds `PetscMPIInt` in a sorted array of `PetscMPIInt`
483: Not Collective
485: Input Parameters:
486: + key - the integer to locate
487: . n - number of values in the array
488: - X - array of integers
490: Output Parameter:
491: . loc - the location if found, otherwise -(slot+1) where slot is the place the value would go
493: Level: intermediate
495: .seealso: `PetscMPIIntSortSemiOrdered()`, `PetscSortInt()`, `PetscSortIntWithArray()`, `PetscSortRemoveDupsInt()`
496: @*/
497: PetscErrorCode PetscFindMPIInt(PetscMPIInt key, PetscInt n, const PetscMPIInt X[], PetscInt *loc)
498: {
499: PetscInt lo = 0, hi = n;
502: if (!n) {
503: *loc = -1;
504: return 0;
505: }
508: while (hi - lo > 1) {
509: PetscInt mid = lo + (hi - lo) / 2;
510: if (key < X[mid]) hi = mid;
511: else lo = mid;
512: }
513: *loc = key == X[lo] ? lo : -(lo + (key > X[lo]) + 1);
514: return 0;
515: }
517: /*@
518: PetscSortIntWithArray - Sorts an array of `PetscInt` in place in increasing order;
519: changes a second array of `PetscInt` to match the sorted first array.
521: Not Collective
523: Input Parameters:
524: + n - number of values
525: . X - array of integers
526: - Y - second array of integers
528: Level: intermediate
530: .seealso: `PetscIntSortSemiOrderedWithArray()`, `PetscSortReal()`, `PetscSortIntWithPermutation()`, `PetscSortInt()`, `PetscSortIntWithCountArray()`
531: @*/
532: PetscErrorCode PetscSortIntWithArray(PetscInt n, PetscInt X[], PetscInt Y[])
533: {
534: PetscInt pivot, t1, t2;
536: QuickSort2(PetscSortIntWithArray, X, Y, n, pivot, t1, t2);
537: return 0;
538: }
540: /*@
541: PetscSortIntWithArrayPair - Sorts an array of `PetscInt` in place in increasing order;
542: changes a pair of `PetscInt` arrays to match the sorted first array.
544: Not Collective
546: Input Parameters:
547: + n - number of values
548: . X - array of integers
549: . Y - second array of integers (first array of the pair)
550: - Z - third array of integers (second array of the pair)
552: Level: intermediate
554: .seealso: `PetscSortReal()`, `PetscSortIntWithPermutation()`, `PetscSortIntWithArray()`, `PetscIntSortSemiOrdered()`, `PetscSortIntWithIntCountArrayPair()`
555: @*/
556: PetscErrorCode PetscSortIntWithArrayPair(PetscInt n, PetscInt X[], PetscInt Y[], PetscInt Z[])
557: {
558: PetscInt pivot, t1, t2, t3;
560: QuickSort3(PetscSortIntWithArrayPair, X, Y, Z, n, pivot, t1, t2, t3);
561: return 0;
562: }
564: /*@
565: PetscSortIntWithCountArray - Sorts an array of `PetscInt` in place in increasing order;
566: changes a second array of `PetscCount` to match the sorted first array.
568: Not Collective
570: Input Parameters:
571: + n - number of values
572: . X - array of integers
573: - Y - second array of PetscCounts (signed integers)
575: Level: intermediate
577: .seealso: `PetscIntSortSemiOrderedWithArray()`, `PetscSortReal()`, `PetscSortIntPermutation()`, `PetscSortInt()`, `PetscSortIntWithArray()`
578: @*/
579: PetscErrorCode PetscSortIntWithCountArray(PetscCount n, PetscInt X[], PetscCount Y[])
580: {
581: PetscInt pivot, t1;
582: PetscCount t2;
584: QuickSort2(PetscSortIntWithCountArray, X, Y, n, pivot, t1, t2);
585: return 0;
586: }
588: /*@
589: PetscSortIntWithIntCountArrayPair - Sorts an array of `PetscInt` in place in increasing order;
590: changes a `PetscInt` array and a `PetscCount` array to match the sorted first array.
592: Not Collective
594: Input Parameters:
595: + n - number of values
596: . X - array of integers
597: . Y - second array of integers (first array of the pair)
598: - Z - third array of PetscCounts (second array of the pair)
600: Level: intermediate
602: Note:
603: 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.
605: .seealso: `PetscSortReal()`, `PetscSortIntPermutation()`, `PetscSortIntWithArray()`, `PetscIntSortSemiOrdered()`, `PetscSortIntWithArrayPair()`
606: @*/
607: PetscErrorCode PetscSortIntWithIntCountArrayPair(PetscCount n, PetscInt X[], PetscInt Y[], PetscCount Z[])
608: {
609: PetscInt pivot, t1, t2; /* pivot is take from X[], so its type is still PetscInt */
610: PetscCount t3; /* temp for Z[] */
612: QuickSort3(PetscSortIntWithIntCountArrayPair, X, Y, Z, n, pivot, t1, t2, t3);
613: return 0;
614: }
616: /*@
617: PetscSortedMPIInt - Determines whether the `PetscMPIInt` array is sorted.
619: Not Collective
621: Input Parameters:
622: + n - number of values
623: - X - array of integers
625: Output Parameters:
626: . sorted - flag whether the array is sorted
628: Level: intermediate
630: .seealso: `PetscMPIIntSortSemiOrdered()`, `PetscSortMPIInt()`, `PetscSortedInt()`, `PetscSortedReal()`
631: @*/
632: PetscErrorCode PetscSortedMPIInt(PetscInt n, const PetscMPIInt X[], PetscBool *sorted)
633: {
634: PetscSorted(n, X, *sorted);
635: return 0;
636: }
638: /*@
639: PetscSortMPIInt - Sorts an array of `PetscMPIInt` in place in increasing order.
641: Not Collective
643: Input Parameters:
644: + n - number of values
645: - X - array of integers
647: Level: intermediate
649: Note:
650: This function serves as an alternative to PetscMPIIntSortSemiOrdered(), and may perform faster especially if the array
651: is completely random. There are exceptions to this and so it is __highly__ recommended that the user benchmark their
652: code to see which routine is fastest.
654: .seealso: `PetscMPIIntSortSemiOrdered()`, `PetscSortReal()`, `PetscSortIntWithPermutation()`
655: @*/
656: PetscErrorCode PetscSortMPIInt(PetscInt n, PetscMPIInt X[])
657: {
658: PetscMPIInt pivot, t1;
660: QuickSort1(PetscSortMPIInt, X, n, pivot, t1);
661: return 0;
662: }
664: /*@
665: PetscSortRemoveDupsMPIInt - Sorts an array of `PetscMPIInt` in place in increasing order removes all duplicate entries
667: Not Collective
669: Input Parameters:
670: + n - number of values
671: - X - array of integers
673: Output Parameter:
674: . n - number of non-redundant values
676: Level: intermediate
678: .seealso: `PetscSortReal()`, `PetscSortIntWithPermutation()`, `PetscSortInt()`
679: @*/
680: PetscErrorCode PetscSortRemoveDupsMPIInt(PetscInt *n, PetscMPIInt X[])
681: {
682: PetscInt s = 0, N = *n, b = 0;
684: PetscSortMPIInt(N, X);
685: for (PetscInt i = 0; i < N - 1; i++) {
686: if (X[b + s + 1] != X[b]) {
687: X[b + 1] = X[b + s + 1];
688: b++;
689: } else s++;
690: }
691: *n = N - s;
692: return 0;
693: }
695: /*@
696: PetscSortMPIIntWithArray - Sorts an array of `PetscMPIInt` in place in increasing order;
697: changes a second `PetscMPIInt` array to match the sorted first array.
699: Not Collective
701: Input Parameters:
702: + n - number of values
703: . X - array of integers
704: - Y - second array of integers
706: Level: intermediate
708: .seealso: `PetscMPIIntSortSemiOrderedWithArray()`, `PetscSortReal()`, `PetscSortIntWithPermutation()`, `PetscSortInt()`
709: @*/
710: PetscErrorCode PetscSortMPIIntWithArray(PetscMPIInt n, PetscMPIInt X[], PetscMPIInt Y[])
711: {
712: PetscMPIInt pivot, t1, t2;
714: QuickSort2(PetscSortMPIIntWithArray, X, Y, n, pivot, t1, t2);
715: return 0;
716: }
718: /*@
719: PetscSortMPIIntWithIntArray - Sorts an array of `PetscMPIInt` in place in increasing order;
720: changes a second array of `PetscInt` to match the sorted first array.
722: Not Collective
724: Input Parameters:
725: + n - number of values
726: . X - array of MPI integers
727: - Y - second array of Petsc integers
729: Level: intermediate
731: Note:
732: This routine is useful when one needs to sort MPI ranks with other integer arrays.
734: .seealso: `PetscSortMPIIntWithArray()`, `PetscIntSortSemiOrderedWithArray()`, `PetscTimSortWithArray()`
735: @*/
736: PetscErrorCode PetscSortMPIIntWithIntArray(PetscMPIInt n, PetscMPIInt X[], PetscInt Y[])
737: {
738: PetscMPIInt pivot, t1;
739: PetscInt t2;
741: QuickSort2(PetscSortMPIIntWithIntArray, X, Y, n, pivot, t1, t2);
742: return 0;
743: }
745: /*@
746: PetscSortIntWithScalarArray - Sorts an array of `PetscInt` in place in increasing order;
747: changes a second `PetscScalar` array to match the sorted first array.
749: Not Collective
751: Input Parameters:
752: + n - number of values
753: . X - array of integers
754: - Y - second array of scalars
756: Level: intermediate
758: .seealso: `PetscTimSortWithArray()`, `PetscSortReal()`, `PetscSortIntWithPermutation()`, `PetscSortInt()`, `PetscSortIntWithArray()`
759: @*/
760: PetscErrorCode PetscSortIntWithScalarArray(PetscInt n, PetscInt X[], PetscScalar Y[])
761: {
762: PetscInt pivot, t1;
763: PetscScalar t2;
765: QuickSort2(PetscSortIntWithScalarArray, X, Y, n, pivot, t1, t2);
766: return 0;
767: }
769: /*@C
770: PetscSortIntWithDataArray - Sorts an array of `PetscInt` in place in increasing order;
771: changes a second array to match the sorted first INTEGER array. Unlike other sort routines, the user must
772: provide workspace (the size of an element in the data array) to use when sorting.
774: Not Collective
776: Input Parameters:
777: + n - number of values
778: . X - array of integers
779: . Y - second array of data
780: . size - sizeof elements in the data array in bytes
781: - t2 - workspace of "size" bytes used when sorting
783: Level: intermediate
785: .seealso: `PetscTimSortWithArray()`, `PetscSortReal()`, `PetscSortIntWithPermutation()`, `PetscSortInt()`, `PetscSortIntWithArray()`
786: @*/
787: PetscErrorCode PetscSortIntWithDataArray(PetscInt n, PetscInt X[], void *Y, size_t size, void *t2)
788: {
789: char *YY = (char *)Y;
790: PetscInt t1, pivot, hi = n - 1;
792: if (n < 8) {
793: for (PetscInt i = 0; i < n; i++) {
794: pivot = X[i];
795: for (PetscInt j = i + 1; j < n; j++) {
796: if (pivot > X[j]) {
797: SWAP2Data(X[i], X[j], YY + size * i, YY + size * j, t1, t2, size);
798: pivot = X[i];
799: }
800: }
801: }
802: } else {
803: /* Two way partition */
804: PetscInt l = 0, r = hi;
806: pivot = X[MEDIAN(X, hi)];
807: while (1) {
808: while (X[l] < pivot) l++;
809: while (X[r] > pivot) r--;
810: if (l >= r) {
811: r++;
812: break;
813: }
814: SWAP2Data(X[l], X[r], YY + size * l, YY + size * r, t1, t2, size);
815: l++;
816: r--;
817: }
818: PetscSortIntWithDataArray(l, X, Y, size, t2);
819: PetscSortIntWithDataArray(hi - r + 1, X + r, YY + size * r, size, t2);
820: }
821: return 0;
822: }
824: /*@
825: PetscMergeIntArray - Merges two SORTED `PetscInt` arrays, removes duplicate elements.
827: Not Collective
829: Input Parameters:
830: + an - number of values in the first array
831: . aI - first sorted array of integers
832: . bn - number of values in the second array
833: - bI - second array of integers
835: Output Parameters:
836: + n - number of values in the merged array
837: - L - merged sorted array, this is allocated if an array is not provided
839: Level: intermediate
841: .seealso: `PetscSortReal()`, `PetscSortIntWithPermutation()`, `PetscSortInt()`, `PetscSortIntWithArray()`
842: @*/
843: PetscErrorCode PetscMergeIntArray(PetscInt an, const PetscInt aI[], PetscInt bn, const PetscInt bI[], PetscInt *n, PetscInt **L)
844: {
845: PetscInt *L_ = *L, ak, bk, k;
847: if (!L_) {
848: PetscMalloc1(an + bn, L);
849: L_ = *L;
850: }
851: k = ak = bk = 0;
852: while (ak < an && bk < bn) {
853: if (aI[ak] == bI[bk]) {
854: L_[k] = aI[ak];
855: ++ak;
856: ++bk;
857: ++k;
858: } else if (aI[ak] < bI[bk]) {
859: L_[k] = aI[ak];
860: ++ak;
861: ++k;
862: } else {
863: L_[k] = bI[bk];
864: ++bk;
865: ++k;
866: }
867: }
868: if (ak < an) {
869: PetscArraycpy(L_ + k, aI + ak, an - ak);
870: k += (an - ak);
871: }
872: if (bk < bn) {
873: PetscArraycpy(L_ + k, bI + bk, bn - bk);
874: k += (bn - bk);
875: }
876: *n = k;
877: return 0;
878: }
880: /*@
881: PetscMergeIntArrayPair - Merges two SORTED `PetscInt` arrays that share NO common values along with an additional array of `PetscInt`.
882: The additional arrays are the same length as sorted arrays and are merged
883: in the order determined by the merging of the sorted pair.
885: Not Collective
887: Input Parameters:
888: + an - number of values in the first array
889: . aI - first sorted array of integers
890: . aJ - first additional array of integers
891: . bn - number of values in the second array
892: . bI - second array of integers
893: - bJ - second additional of integers
895: Output Parameters:
896: + n - number of values in the merged array (== an + bn)
897: . L - merged sorted array
898: - J - merged additional array
900: Note:
901: 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
903: Level: intermediate
905: .seealso: `PetscIntSortSemiOrdered()`, `PetscSortReal()`, `PetscSortIntWithPermutation()`, `PetscSortInt()`, `PetscSortIntWithArray()`
906: @*/
907: PetscErrorCode PetscMergeIntArrayPair(PetscInt an, const PetscInt aI[], const PetscInt aJ[], PetscInt bn, const PetscInt bI[], const PetscInt bJ[], PetscInt *n, PetscInt **L, PetscInt **J)
908: {
909: PetscInt n_, *L_, *J_, ak, bk, k;
913: n_ = an + bn;
914: *n = n_;
915: if (!*L) PetscMalloc1(n_, L);
916: L_ = *L;
917: if (!*J) PetscMalloc1(n_, J);
918: J_ = *J;
919: k = ak = bk = 0;
920: while (ak < an && bk < bn) {
921: if (aI[ak] <= bI[bk]) {
922: L_[k] = aI[ak];
923: J_[k] = aJ[ak];
924: ++ak;
925: ++k;
926: } else {
927: L_[k] = bI[bk];
928: J_[k] = bJ[bk];
929: ++bk;
930: ++k;
931: }
932: }
933: if (ak < an) {
934: PetscArraycpy(L_ + k, aI + ak, an - ak);
935: PetscArraycpy(J_ + k, aJ + ak, an - ak);
936: k += (an - ak);
937: }
938: if (bk < bn) {
939: PetscArraycpy(L_ + k, bI + bk, bn - bk);
940: PetscArraycpy(J_ + k, bJ + bk, bn - bk);
941: }
942: return 0;
943: }
945: /*@
946: PetscMergeMPIIntArray - Merges two SORTED `PetscMPIInt` arrays.
948: Not Collective
950: Input Parameters:
951: + an - number of values in the first array
952: . aI - first sorted array of integers
953: . bn - number of values in the second array
954: - bI - second array of integers
956: Output Parameters:
957: + n - number of values in the merged array (<= an + bn)
958: - L - merged sorted array, allocated if address of NULL pointer is passed
960: Level: intermediate
962: .seealso: `PetscIntSortSemiOrdered()`, `PetscSortReal()`, `PetscSortIntWithPermutation()`, `PetscSortInt()`, `PetscSortIntWithArray()`
963: @*/
964: PetscErrorCode PetscMergeMPIIntArray(PetscInt an, const PetscMPIInt aI[], PetscInt bn, const PetscMPIInt bI[], PetscInt *n, PetscMPIInt **L)
965: {
966: PetscInt ai, bi, k;
968: if (!*L) PetscMalloc1((an + bn), L);
969: for (ai = 0, bi = 0, k = 0; ai < an || bi < bn;) {
970: PetscInt t = -1;
971: for (; ai < an && (!bn || aI[ai] <= bI[bi]); ai++) (*L)[k++] = t = aI[ai];
972: for (; bi < bn && bI[bi] == t; bi++)
973: ;
974: for (; bi < bn && (!an || bI[bi] <= aI[ai]); bi++) (*L)[k++] = t = bI[bi];
975: for (; ai < an && aI[ai] == t; ai++)
976: ;
977: }
978: *n = k;
979: return 0;
980: }
982: /*@C
983: PetscProcessTree - Prepares tree data to be displayed graphically
985: Not Collective
987: Input Parameters:
988: + n - number of values
989: . mask - indicates those entries in the tree, location 0 is always masked
990: - parentid - indicates the parent of each entry
992: Output Parameters:
993: + Nlevels - the number of levels
994: . Level - for each node tells its level
995: . Levelcnts - the number of nodes on each level
996: . Idbylevel - a list of ids on each of the levels, first level followed by second etc
997: - Column - for each id tells its column index
999: Level: developer
1001: Note:
1002: This code is not currently used
1004: .seealso: `PetscSortReal()`, `PetscSortIntWithPermutation()`
1005: @*/
1006: PetscErrorCode PetscProcessTree(PetscInt n, const PetscBool mask[], const PetscInt parentid[], PetscInt *Nlevels, PetscInt **Level, PetscInt **Levelcnt, PetscInt **Idbylevel, PetscInt **Column)
1007: {
1008: PetscInt i, j, cnt, nmask = 0, nlevels = 0, *level, *levelcnt, levelmax = 0, *workid, *workparentid, tcnt = 0, *idbylevel, *column;
1009: PetscBool done = PETSC_FALSE;
1012: for (i = 0; i < n; i++) {
1013: if (mask[i]) continue;
1016: }
1018: for (i = 0; i < n; i++) {
1019: if (!mask[i]) nmask++;
1020: }
1022: /* determine the level in the tree of each node */
1023: PetscCalloc1(n, &level);
1025: level[0] = 1;
1026: while (!done) {
1027: done = PETSC_TRUE;
1028: for (i = 0; i < n; i++) {
1029: if (mask[i]) continue;
1030: if (!level[i] && level[parentid[i]]) level[i] = level[parentid[i]] + 1;
1031: else if (!level[i]) done = PETSC_FALSE;
1032: }
1033: }
1034: for (i = 0; i < n; i++) {
1035: level[i]--;
1036: nlevels = PetscMax(nlevels, level[i]);
1037: }
1039: /* count the number of nodes on each level and its max */
1040: PetscCalloc1(nlevels, &levelcnt);
1041: for (i = 0; i < n; i++) {
1042: if (mask[i]) continue;
1043: levelcnt[level[i] - 1]++;
1044: }
1045: for (i = 0; i < nlevels; i++) levelmax = PetscMax(levelmax, levelcnt[i]);
1047: /* for each level sort the ids by the parent id */
1048: PetscMalloc2(levelmax, &workid, levelmax, &workparentid);
1049: PetscMalloc1(nmask, &idbylevel);
1050: for (j = 1; j <= nlevels; j++) {
1051: cnt = 0;
1052: for (i = 0; i < n; i++) {
1053: if (mask[i]) continue;
1054: if (level[i] != j) continue;
1055: workid[cnt] = i;
1056: workparentid[cnt++] = parentid[i];
1057: }
1058: /* PetscIntView(cnt,workparentid,0);
1059: PetscIntView(cnt,workid,0);
1060: PetscSortIntWithArray(cnt,workparentid,workid);
1061: PetscIntView(cnt,workparentid,0);
1062: PetscIntView(cnt,workid,0);*/
1063: PetscArraycpy(idbylevel + tcnt, workid, cnt);
1064: tcnt += cnt;
1065: }
1067: PetscFree2(workid, workparentid);
1069: /* for each node list its column */
1070: PetscMalloc1(n, &column);
1071: cnt = 0;
1072: for (j = 0; j < nlevels; j++) {
1073: for (i = 0; i < levelcnt[j]; i++) column[idbylevel[cnt++]] = i;
1074: }
1076: *Nlevels = nlevels;
1077: *Level = level;
1078: *Levelcnt = levelcnt;
1079: *Idbylevel = idbylevel;
1080: *Column = column;
1081: return 0;
1082: }
1084: /*@
1085: PetscParallelSortedInt - Check whether a `PetscInt` array, distributed over a communicator, is globally sorted.
1087: Collective
1089: Input Parameters:
1090: + comm - the MPI communicator
1091: . n - the local number of integers
1092: - keys - the local array of integers
1094: Output Parameters:
1095: . is_sorted - whether the array is globally sorted
1097: Level: developer
1099: .seealso: `PetscParallelSortInt()`
1100: @*/
1101: PetscErrorCode PetscParallelSortedInt(MPI_Comm comm, PetscInt n, const PetscInt keys[], PetscBool *is_sorted)
1102: {
1103: PetscBool sorted;
1104: PetscInt i, min, max, prevmax;
1105: PetscMPIInt rank;
1107: sorted = PETSC_TRUE;
1108: min = PETSC_MAX_INT;
1109: max = PETSC_MIN_INT;
1110: if (n) {
1111: min = keys[0];
1112: max = keys[0];
1113: }
1114: for (i = 1; i < n; i++) {
1115: if (keys[i] < keys[i - 1]) break;
1116: min = PetscMin(min, keys[i]);
1117: max = PetscMax(max, keys[i]);
1118: }
1119: if (i < n) sorted = PETSC_FALSE;
1120: prevmax = PETSC_MIN_INT;
1121: MPI_Exscan(&max, &prevmax, 1, MPIU_INT, MPI_MAX, comm);
1122: MPI_Comm_rank(comm, &rank);
1123: if (rank == 0) prevmax = PETSC_MIN_INT;
1124: if (prevmax > min) sorted = PETSC_FALSE;
1125: MPI_Allreduce(&sorted, is_sorted, 1, MPIU_BOOL, MPI_LAND, comm);
1126: return 0;
1127: }