xref: /petsc/src/sys/utils/sorti.c (revision 252ecd3142ba3ca0b326827f24f26bd5c1233270)
1 
2 /*
3    This file contains routines for sorting integers. Values are sorted in place.
4  */
5 #include <petsc/private/petscimpl.h>                /*I  "petscsys.h"  I*/
6 
7 #define SWAP(a,b,t) {t=a;a=b;b=t;}
8 
9 #define MEDIAN3(v,a,b,c)                        \
10   (v[a]<v[b]                                    \
11    ? (v[b]<v[c]                                 \
12       ? b                                       \
13       : (v[a]<v[c] ? c : a))                    \
14    : (v[c]<v[b]                                 \
15       ? b                                       \
16       : (v[a]<v[c] ? a : c)))
17 
18 #define MEDIAN(v,right) MEDIAN3(v,right/4,right/2,right/4*3)
19 
20 /* -----------------------------------------------------------------------*/
21 
22 /*
23    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
24    Assumes 0 origin for v, number of elements = right+1 (right is index of
25    right-most member).
26 */
27 static void PetscSortInt_Private(PetscInt *v,PetscInt right)
28 {
29   PetscInt i,j,pivot,tmp;
30 
31   if (right <= 1) {
32     if (right == 1) {
33       if (v[0] > v[1]) SWAP(v[0],v[1],tmp);
34     }
35     return;
36   }
37   i = MEDIAN(v,right);          /* Choose a pivot */
38   SWAP(v[0],v[i],tmp);          /* Move it out of the way */
39   pivot = v[0];
40   for (i=0,j=right+1;; ) {
41     while (++i < j && v[i] <= pivot) ; /* Scan from the left */
42     while (v[--j] > pivot) ;           /* Scan from the right */
43     if (i >= j) break;
44     SWAP(v[i],v[j],tmp);
45   }
46   SWAP(v[0],v[j],tmp);          /* Put pivot back in place. */
47   PetscSortInt_Private(v,j-1);
48   PetscSortInt_Private(v+j+1,right-(j+1));
49 }
50 
51 /*@
52    PetscSortInt - Sorts an array of integers in place in increasing order.
53 
54    Not Collective
55 
56    Input Parameters:
57 +  n  - number of values
58 -  i  - array of integers
59 
60    Level: intermediate
61 
62    Concepts: sorting^ints
63 
64 .seealso: PetscSortReal(), PetscSortIntWithPermutation()
65 @*/
66 PetscErrorCode  PetscSortInt(PetscInt n,PetscInt i[])
67 {
68   PetscInt j,k,tmp,ik;
69 
70   PetscFunctionBegin;
71   if (n<8) {
72     for (k=0; k<n; k++) {
73       ik = i[k];
74       for (j=k+1; j<n; j++) {
75         if (ik > i[j]) {
76           SWAP(i[k],i[j],tmp);
77           ik = i[k];
78         }
79       }
80     }
81   } else PetscSortInt_Private(i,n-1);
82   PetscFunctionReturn(0);
83 }
84 
85 /*@
86    PetscSortRemoveDupsInt - Sorts an array of integers in place in increasing order removes all duplicate entries
87 
88    Not Collective
89 
90    Input Parameters:
91 +  n  - number of values
92 -  ii  - array of integers
93 
94    Output Parameter:
95 .  n - number of non-redundant values
96 
97    Level: intermediate
98 
99    Concepts: sorting^ints
100 
101 .seealso: PetscSortReal(), PetscSortIntWithPermutation(), PetscSortInt()
102 @*/
103 PetscErrorCode  PetscSortRemoveDupsInt(PetscInt *n,PetscInt ii[])
104 {
105   PetscErrorCode ierr;
106   PetscInt       i,s = 0,N = *n, b = 0;
107 
108   PetscFunctionBegin;
109   ierr = PetscSortInt(N,ii);CHKERRQ(ierr);
110   for (i=0; i<N-1; i++) {
111     if (ii[b+s+1] != ii[b]) {
112       ii[b+1] = ii[b+s+1]; b++;
113     } else s++;
114   }
115   *n = N - s;
116   PetscFunctionReturn(0);
117 }
118 
119 /*@
120   PetscFindInt - Finds integer in a sorted array of integers
121 
122    Not Collective
123 
124    Input Parameters:
125 +  key - the integer to locate
126 .  n   - number of values in the array
127 -  ii  - array of integers
128 
129    Output Parameter:
130 .  loc - the location if found, otherwise -(slot+1) where slot is the place the value would go
131 
132    Level: intermediate
133 
134    Concepts: sorting^ints
135 
136 .seealso: PetscSortInt(), PetscSortIntWithArray(), PetscSortRemoveDupsInt()
137 @*/
138 PetscErrorCode PetscFindInt(PetscInt key, PetscInt n, const PetscInt ii[], PetscInt *loc)
139 {
140   PetscInt lo = 0,hi = n;
141 
142   PetscFunctionBegin;
143   PetscValidPointer(loc,4);
144   if (!n) {*loc = -1; PetscFunctionReturn(0);}
145   PetscValidPointer(ii,3);
146   while (hi - lo > 1) {
147     PetscInt mid = lo + (hi - lo)/2;
148     if (key < ii[mid]) hi = mid;
149     else               lo = mid;
150   }
151   *loc = key == ii[lo] ? lo : -(lo + (key > ii[lo]) + 1);
152   PetscFunctionReturn(0);
153 }
154 
155 #undef __FUNCT__
156 #define __FUNCT__ "PetscFindMPIInt"
157 /*@
158   PetscFindMPIInt - Finds MPI integer in a sorted array of integers
159 
160    Not Collective
161 
162    Input Parameters:
163 +  key - the integer to locate
164 .  n   - number of values in the array
165 -  ii  - array of integers
166 
167    Output Parameter:
168 .  loc - the location if found, otherwise -(slot+1) where slot is the place the value would go
169 
170    Level: intermediate
171 
172    Concepts: sorting^ints
173 
174 .seealso: PetscSortInt(), PetscSortIntWithArray(), PetscSortRemoveDupsInt()
175 @*/
176 PetscErrorCode PetscFindMPIInt(PetscMPIInt key, PetscInt n, const PetscMPIInt ii[], PetscInt *loc)
177 {
178   PetscInt lo = 0,hi = n;
179 
180   PetscFunctionBegin;
181   PetscValidPointer(loc,4);
182   if (!n) {*loc = -1; PetscFunctionReturn(0);}
183   PetscValidPointer(ii,3);
184   while (hi - lo > 1) {
185     PetscInt mid = lo + (hi - lo)/2;
186     if (key < ii[mid]) hi = mid;
187     else               lo = mid;
188   }
189   *loc = key == ii[lo] ? lo : -(lo + (key > ii[lo]) + 1);
190   PetscFunctionReturn(0);
191 }
192 
193 /* -----------------------------------------------------------------------*/
194 #define SWAP2(a,b,c,d,t) {t=a;a=b;b=t;t=c;c=d;d=t;}
195 
196 /*
197    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
198    Assumes 0 origin for v, number of elements = right+1 (right is index of
199    right-most member).
200 */
201 static PetscErrorCode PetscSortIntWithArray_Private(PetscInt *v,PetscInt *V,PetscInt right)
202 {
203   PetscErrorCode ierr;
204   PetscInt       i,vl,last,tmp;
205 
206   PetscFunctionBegin;
207   if (right <= 1) {
208     if (right == 1) {
209       if (v[0] > v[1]) SWAP2(v[0],v[1],V[0],V[1],tmp);
210     }
211     PetscFunctionReturn(0);
212   }
213   SWAP2(v[0],v[right/2],V[0],V[right/2],tmp);
214   vl   = v[0];
215   last = 0;
216   for (i=1; i<=right; i++) {
217     if (v[i] < vl) {last++; SWAP2(v[last],v[i],V[last],V[i],tmp);}
218   }
219   SWAP2(v[0],v[last],V[0],V[last],tmp);
220   ierr = PetscSortIntWithArray_Private(v,V,last-1);CHKERRQ(ierr);
221   ierr = PetscSortIntWithArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr);
222   PetscFunctionReturn(0);
223 }
224 
225 /*@
226    PetscSortIntWithArray - Sorts an array of integers in place in increasing order;
227        changes a second array to match the sorted first array.
228 
229    Not Collective
230 
231    Input Parameters:
232 +  n  - number of values
233 .  i  - array of integers
234 -  I - second array of integers
235 
236    Level: intermediate
237 
238    Concepts: sorting^ints with array
239 
240 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt()
241 @*/
242 PetscErrorCode  PetscSortIntWithArray(PetscInt n,PetscInt i[],PetscInt Ii[])
243 {
244   PetscErrorCode ierr;
245   PetscInt       j,k,tmp,ik;
246 
247   PetscFunctionBegin;
248   if (n<8) {
249     for (k=0; k<n; k++) {
250       ik = i[k];
251       for (j=k+1; j<n; j++) {
252         if (ik > i[j]) {
253           SWAP2(i[k],i[j],Ii[k],Ii[j],tmp);
254           ik = i[k];
255         }
256       }
257     }
258   } else {
259     ierr = PetscSortIntWithArray_Private(i,Ii,n-1);CHKERRQ(ierr);
260   }
261   PetscFunctionReturn(0);
262 }
263 
264 
265 #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;}
266 
267 /*
268    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
269    Assumes 0 origin for v, number of elements = right+1 (right is index of
270    right-most member).
271 */
272 static PetscErrorCode PetscSortIntWithArrayPair_Private(PetscInt *L,PetscInt *J, PetscInt *K, PetscInt right)
273 {
274   PetscErrorCode ierr;
275   PetscInt       i,vl,last,tmp;
276 
277   PetscFunctionBegin;
278   if (right <= 1) {
279     if (right == 1) {
280       if (L[0] > L[1]) SWAP3(L[0],L[1],J[0],J[1],K[0],K[1],tmp);
281     }
282     PetscFunctionReturn(0);
283   }
284   SWAP3(L[0],L[right/2],J[0],J[right/2],K[0],K[right/2],tmp);
285   vl   = L[0];
286   last = 0;
287   for (i=1; i<=right; i++) {
288     if (L[i] < vl) {last++; SWAP3(L[last],L[i],J[last],J[i],K[last],K[i],tmp);}
289   }
290   SWAP3(L[0],L[last],J[0],J[last],K[0],K[last],tmp);
291   ierr = PetscSortIntWithArrayPair_Private(L,J,K,last-1);CHKERRQ(ierr);
292   ierr = PetscSortIntWithArrayPair_Private(L+last+1,J+last+1,K+last+1,right-(last+1));CHKERRQ(ierr);
293   PetscFunctionReturn(0);
294 }
295 
296 /*@
297    PetscSortIntWithArrayPair - Sorts an array of integers in place in increasing order;
298        changes a pair of integer arrays to match the sorted first array.
299 
300    Not Collective
301 
302    Input Parameters:
303 +  n  - number of values
304 .  I  - array of integers
305 .  J  - second array of integers (first array of the pair)
306 -  K  - third array of integers  (second array of the pair)
307 
308    Level: intermediate
309 
310    Concepts: sorting^ints with array pair
311 
312 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortIntWithArray()
313 @*/
314 PetscErrorCode  PetscSortIntWithArrayPair(PetscInt n,PetscInt L[],PetscInt J[], PetscInt K[])
315 {
316   PetscErrorCode ierr;
317   PetscInt       j,k,tmp,ik;
318 
319   PetscFunctionBegin;
320   if (n<8) {
321     for (k=0; k<n; k++) {
322       ik = L[k];
323       for (j=k+1; j<n; j++) {
324         if (ik > L[j]) {
325           SWAP3(L[k],L[j],J[k],J[j],K[k],K[j],tmp);
326           ik = L[k];
327         }
328       }
329     }
330   } else {
331     ierr = PetscSortIntWithArrayPair_Private(L,J,K,n-1);CHKERRQ(ierr);
332   }
333   PetscFunctionReturn(0);
334 }
335 
336 /*
337    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
338    Assumes 0 origin for v, number of elements = right+1 (right is index of
339    right-most member).
340 */
341 static void PetscSortMPIInt_Private(PetscMPIInt *v,PetscInt right)
342 {
343   PetscInt          i,j;
344   PetscMPIInt       pivot,tmp;
345 
346   if (right <= 1) {
347     if (right == 1) {
348       if (v[0] > v[1]) SWAP(v[0],v[1],tmp);
349     }
350     return;
351   }
352   i = MEDIAN(v,right);          /* Choose a pivot */
353   SWAP(v[0],v[i],tmp);          /* Move it out of the way */
354   pivot = v[0];
355   for (i=0,j=right+1;; ) {
356     while (++i < j && v[i] <= pivot) ; /* Scan from the left */
357     while (v[--j] > pivot) ;           /* Scan from the right */
358     if (i >= j) break;
359     SWAP(v[i],v[j],tmp);
360   }
361   SWAP(v[0],v[j],tmp);          /* Put pivot back in place. */
362   PetscSortMPIInt_Private(v,j-1);
363   PetscSortMPIInt_Private(v+j+1,right-(j+1));
364 }
365 
366 /*@
367    PetscSortMPIInt - Sorts an array of MPI integers in place in increasing order.
368 
369    Not Collective
370 
371    Input Parameters:
372 +  n  - number of values
373 -  i  - array of integers
374 
375    Level: intermediate
376 
377    Concepts: sorting^ints
378 
379 .seealso: PetscSortReal(), PetscSortIntWithPermutation()
380 @*/
381 PetscErrorCode  PetscSortMPIInt(PetscInt n,PetscMPIInt i[])
382 {
383   PetscInt    j,k;
384   PetscMPIInt tmp,ik;
385 
386   PetscFunctionBegin;
387   if (n<8) {
388     for (k=0; k<n; k++) {
389       ik = i[k];
390       for (j=k+1; j<n; j++) {
391         if (ik > i[j]) {
392           SWAP(i[k],i[j],tmp);
393           ik = i[k];
394         }
395       }
396     }
397   } else PetscSortMPIInt_Private(i,n-1);
398   PetscFunctionReturn(0);
399 }
400 
401 /*@
402    PetscSortRemoveDupsMPIInt - Sorts an array of MPI integers in place in increasing order removes all duplicate entries
403 
404    Not Collective
405 
406    Input Parameters:
407 +  n  - number of values
408 -  ii  - array of integers
409 
410    Output Parameter:
411 .  n - number of non-redundant values
412 
413    Level: intermediate
414 
415    Concepts: sorting^ints
416 
417 .seealso: PetscSortReal(), PetscSortIntWithPermutation(), PetscSortInt()
418 @*/
419 PetscErrorCode  PetscSortRemoveDupsMPIInt(PetscInt *n,PetscMPIInt ii[])
420 {
421   PetscErrorCode ierr;
422   PetscInt       i,s = 0,N = *n, b = 0;
423 
424   PetscFunctionBegin;
425   ierr = PetscSortMPIInt(N,ii);CHKERRQ(ierr);
426   for (i=0; i<N-1; i++) {
427     if (ii[b+s+1] != ii[b]) {
428       ii[b+1] = ii[b+s+1]; b++;
429     } else s++;
430   }
431   *n = N - s;
432   PetscFunctionReturn(0);
433 }
434 
435 /*
436    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
437    Assumes 0 origin for v, number of elements = right+1 (right is index of
438    right-most member).
439 */
440 static PetscErrorCode PetscSortMPIIntWithArray_Private(PetscMPIInt *v,PetscMPIInt *V,PetscMPIInt right)
441 {
442   PetscErrorCode ierr;
443   PetscMPIInt    i,vl,last,tmp;
444 
445   PetscFunctionBegin;
446   if (right <= 1) {
447     if (right == 1) {
448       if (v[0] > v[1]) SWAP2(v[0],v[1],V[0],V[1],tmp);
449     }
450     PetscFunctionReturn(0);
451   }
452   SWAP2(v[0],v[right/2],V[0],V[right/2],tmp);
453   vl   = v[0];
454   last = 0;
455   for (i=1; i<=right; i++) {
456     if (v[i] < vl) {last++; SWAP2(v[last],v[i],V[last],V[i],tmp);}
457   }
458   SWAP2(v[0],v[last],V[0],V[last],tmp);
459   ierr = PetscSortMPIIntWithArray_Private(v,V,last-1);CHKERRQ(ierr);
460   ierr = PetscSortMPIIntWithArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr);
461   PetscFunctionReturn(0);
462 }
463 
464 /*@
465    PetscSortMPIIntWithArray - Sorts an array of integers in place in increasing order;
466        changes a second array to match the sorted first array.
467 
468    Not Collective
469 
470    Input Parameters:
471 +  n  - number of values
472 .  i  - array of integers
473 -  I - second array of integers
474 
475    Level: intermediate
476 
477    Concepts: sorting^ints with array
478 
479 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt()
480 @*/
481 PetscErrorCode  PetscSortMPIIntWithArray(PetscMPIInt n,PetscMPIInt i[],PetscMPIInt Ii[])
482 {
483   PetscErrorCode ierr;
484   PetscMPIInt    j,k,tmp,ik;
485 
486   PetscFunctionBegin;
487   if (n<8) {
488     for (k=0; k<n; k++) {
489       ik = i[k];
490       for (j=k+1; j<n; j++) {
491         if (ik > i[j]) {
492           SWAP2(i[k],i[j],Ii[k],Ii[j],tmp);
493           ik = i[k];
494         }
495       }
496     }
497   } else {
498     ierr = PetscSortMPIIntWithArray_Private(i,Ii,n-1);CHKERRQ(ierr);
499   }
500   PetscFunctionReturn(0);
501 }
502 
503 /* -----------------------------------------------------------------------*/
504 #define SWAP2IntScalar(a,b,c,d,t,ts) {t=a;a=b;b=t;ts=c;c=d;d=ts;}
505 
506 /*
507    Modified from PetscSortIntWithArray_Private().
508 */
509 static PetscErrorCode PetscSortIntWithScalarArray_Private(PetscInt *v,PetscScalar *V,PetscInt right)
510 {
511   PetscErrorCode ierr;
512   PetscInt       i,vl,last,tmp;
513   PetscScalar    stmp;
514 
515   PetscFunctionBegin;
516   if (right <= 1) {
517     if (right == 1) {
518       if (v[0] > v[1]) SWAP2IntScalar(v[0],v[1],V[0],V[1],tmp,stmp);
519     }
520     PetscFunctionReturn(0);
521   }
522   SWAP2IntScalar(v[0],v[right/2],V[0],V[right/2],tmp,stmp);
523   vl   = v[0];
524   last = 0;
525   for (i=1; i<=right; i++) {
526     if (v[i] < vl) {last++; SWAP2IntScalar(v[last],v[i],V[last],V[i],tmp,stmp);}
527   }
528   SWAP2IntScalar(v[0],v[last],V[0],V[last],tmp,stmp);
529   ierr = PetscSortIntWithScalarArray_Private(v,V,last-1);CHKERRQ(ierr);
530   ierr = PetscSortIntWithScalarArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr);
531   PetscFunctionReturn(0);
532 }
533 
534 /*@
535    PetscSortIntWithScalarArray - Sorts an array of integers in place in increasing order;
536        changes a second SCALAR array to match the sorted first INTEGER array.
537 
538    Not Collective
539 
540    Input Parameters:
541 +  n  - number of values
542 .  i  - array of integers
543 -  I - second array of scalars
544 
545    Level: intermediate
546 
547    Concepts: sorting^ints with array
548 
549 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
550 @*/
551 PetscErrorCode  PetscSortIntWithScalarArray(PetscInt n,PetscInt i[],PetscScalar Ii[])
552 {
553   PetscErrorCode ierr;
554   PetscInt       j,k,tmp,ik;
555   PetscScalar    stmp;
556 
557   PetscFunctionBegin;
558   if (n<8) {
559     for (k=0; k<n; k++) {
560       ik = i[k];
561       for (j=k+1; j<n; j++) {
562         if (ik > i[j]) {
563           SWAP2IntScalar(i[k],i[j],Ii[k],Ii[j],tmp,stmp);
564           ik = i[k];
565         }
566       }
567     }
568   } else {
569     ierr = PetscSortIntWithScalarArray_Private(i,Ii,n-1);CHKERRQ(ierr);
570   }
571   PetscFunctionReturn(0);
572 }
573 
574 #define SWAP2IntData(a,b,c,d,t,td,siz)          \
575   do {                                          \
576   PetscErrorCode _ierr;                         \
577   t=a;a=b;b=t;                                  \
578   _ierr = PetscMemcpy(td,c,siz);CHKERRQ(_ierr); \
579   _ierr = PetscMemcpy(c,d,siz);CHKERRQ(_ierr);  \
580   _ierr = PetscMemcpy(d,td,siz);CHKERRQ(_ierr); \
581 } while(0)
582 
583 /*
584    Modified from PetscSortIntWithArray_Private().
585 */
586 static PetscErrorCode PetscSortIntWithDataArray_Private(PetscInt *v,char *V,PetscInt right,size_t size,void *work)
587 {
588   PetscErrorCode ierr;
589   PetscInt       i,vl,last,tmp;
590 
591   PetscFunctionBegin;
592   if (right <= 1) {
593     if (right == 1) {
594       if (v[0] > v[1]) SWAP2IntData(v[0],v[1],V,V+size,tmp,work,size);
595     }
596     PetscFunctionReturn(0);
597   }
598   SWAP2IntData(v[0],v[right/2],V,V+size*(right/2),tmp,work,size);
599   vl   = v[0];
600   last = 0;
601   for (i=1; i<=right; i++) {
602     if (v[i] < vl) {last++; SWAP2IntData(v[last],v[i],V+size*last,V+size*i,tmp,work,size);}
603   }
604   SWAP2IntData(v[0],v[last],V,V + size*last,tmp,work,size);
605   ierr = PetscSortIntWithDataArray_Private(v,V,last-1,size,work);CHKERRQ(ierr);
606   ierr = PetscSortIntWithDataArray_Private(v+last+1,V+size*(last+1),right-(last+1),size,work);CHKERRQ(ierr);
607   PetscFunctionReturn(0);
608 }
609 
610 /*@C
611    PetscSortIntWithDataArray - Sorts an array of integers in place in increasing order;
612        changes a second array to match the sorted first INTEGER array.  Unlike other sort routines, the user must
613        provide workspace (the size of an element in the data array) to use when sorting.
614 
615    Not Collective
616 
617    Input Parameters:
618 +  n  - number of values
619 .  i  - array of integers
620 .  Ii - second array of data
621 .  size - sizeof elements in the data array in bytes
622 -  work - workspace of "size" bytes used when sorting
623 
624    Level: intermediate
625 
626    Concepts: sorting^ints with array
627 
628 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
629 @*/
630 PetscErrorCode  PetscSortIntWithDataArray(PetscInt n,PetscInt i[],void *Ii,size_t size,void *work)
631 {
632   char           *V = (char *) Ii;
633   PetscErrorCode ierr;
634   PetscInt       j,k,tmp,ik;
635 
636   PetscFunctionBegin;
637   if (n<8) {
638     for (k=0; k<n; k++) {
639       ik = i[k];
640       for (j=k+1; j<n; j++) {
641         if (ik > i[j]) {
642           SWAP2IntData(i[k],i[j],V+size*k,V+size*j,tmp,work,size);
643           ik = i[k];
644         }
645       }
646     }
647   } else {
648     ierr = PetscSortIntWithDataArray_Private(i,V,n-1,size,work);CHKERRQ(ierr);
649   }
650   PetscFunctionReturn(0);
651 }
652 
653 
654 /*@
655    PetscMergeIntArray -     Merges two SORTED integer arrays, removes duplicate elements.
656 
657    Not Collective
658 
659    Input Parameters:
660 +  an  - number of values in the first array
661 .  aI  - first sorted array of integers
662 .  bn  - number of values in the second array
663 -  bI  - second array of integers
664 
665    Output Parameters:
666 +  n   - number of values in the merged array
667 -  L   - merged sorted array, this is allocated if an array is not provided
668 
669    Level: intermediate
670 
671    Concepts: merging^arrays
672 
673 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
674 @*/
675 PetscErrorCode  PetscMergeIntArray(PetscInt an,const PetscInt aI[], PetscInt bn, const PetscInt bI[],  PetscInt *n, PetscInt **L)
676 {
677   PetscErrorCode ierr;
678   PetscInt       *L_ = *L, ak, bk, k;
679 
680   if (!L_) {
681     ierr = PetscMalloc1(an+bn, L);CHKERRQ(ierr);
682     L_   = *L;
683   }
684   k = ak = bk = 0;
685   while (ak < an && bk < bn) {
686     if (aI[ak] == bI[bk]) {
687       L_[k] = aI[ak];
688       ++ak;
689       ++bk;
690       ++k;
691     } else if (aI[ak] < bI[bk]) {
692       L_[k] = aI[ak];
693       ++ak;
694       ++k;
695     } else {
696       L_[k] = bI[bk];
697       ++bk;
698       ++k;
699     }
700   }
701   if (ak < an) {
702     ierr = PetscMemcpy(L_+k,aI+ak,(an-ak)*sizeof(PetscInt));CHKERRQ(ierr);
703     k   += (an-ak);
704   }
705   if (bk < bn) {
706     ierr = PetscMemcpy(L_+k,bI+bk,(bn-bk)*sizeof(PetscInt));CHKERRQ(ierr);
707     k   += (bn-bk);
708   }
709   *n = k;
710   PetscFunctionReturn(0);
711 }
712 
713 /*@
714    PetscMergeIntArrayPair -     Merges two SORTED integer arrays that share NO common values along with an additional array of integers.
715                                 The additional arrays are the same length as sorted arrays and are merged
716                                 in the order determined by the merging of the sorted pair.
717 
718    Not Collective
719 
720    Input Parameters:
721 +  an  - number of values in the first array
722 .  aI  - first sorted array of integers
723 .  aJ  - first additional array of integers
724 .  bn  - number of values in the second array
725 .  bI  - second array of integers
726 -  bJ  - second additional of integers
727 
728    Output Parameters:
729 +  n   - number of values in the merged array (== an + bn)
730 .  L   - merged sorted array
731 -  J   - merged additional array
732 
733    Notes: 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
734    Level: intermediate
735 
736    Concepts: merging^arrays
737 
738 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
739 @*/
740 PetscErrorCode  PetscMergeIntArrayPair(PetscInt an,const PetscInt aI[], const PetscInt aJ[], PetscInt bn, const PetscInt bI[], const PetscInt bJ[], PetscInt *n, PetscInt **L, PetscInt **J)
741 {
742   PetscErrorCode ierr;
743   PetscInt       n_, *L_, *J_, ak, bk, k;
744 
745   PetscFunctionBegin;
746   PetscValidIntPointer(L,8);
747   PetscValidIntPointer(J,9);
748   n_ = an + bn;
749   *n = n_;
750   if (!*L) {
751     ierr = PetscMalloc1(n_, L);CHKERRQ(ierr);
752   }
753   L_ = *L;
754   if (!*J) {
755     ierr = PetscMalloc1(n_, J);CHKERRQ(ierr);
756   }
757   J_   = *J;
758   k = ak = bk = 0;
759   while (ak < an && bk < bn) {
760     if (aI[ak] <= bI[bk]) {
761       L_[k] = aI[ak];
762       J_[k] = aJ[ak];
763       ++ak;
764       ++k;
765     } else {
766       L_[k] = bI[bk];
767       J_[k] = bJ[bk];
768       ++bk;
769       ++k;
770     }
771   }
772   if (ak < an) {
773     ierr = PetscMemcpy(L_+k,aI+ak,(an-ak)*sizeof(PetscInt));CHKERRQ(ierr);
774     ierr = PetscMemcpy(J_+k,aJ+ak,(an-ak)*sizeof(PetscInt));CHKERRQ(ierr);
775     k   += (an-ak);
776   }
777   if (bk < bn) {
778     ierr = PetscMemcpy(L_+k,bI+bk,(bn-bk)*sizeof(PetscInt));CHKERRQ(ierr);
779     ierr = PetscMemcpy(J_+k,bJ+bk,(bn-bk)*sizeof(PetscInt));CHKERRQ(ierr);
780   }
781   PetscFunctionReturn(0);
782 }
783 
784 /*@
785    PetscMergeMPIIntArray -     Merges two SORTED integer arrays.
786 
787    Not Collective
788 
789    Input Parameters:
790 +  an  - number of values in the first array
791 .  aI  - first sorted array of integers
792 .  bn  - number of values in the second array
793 -  bI  - second array of integers
794 
795    Output Parameters:
796 +  n   - number of values in the merged array (<= an + bn)
797 -  L   - merged sorted array, allocated if address of NULL pointer is passed
798 
799    Level: intermediate
800 
801    Concepts: merging^arrays
802 
803 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
804 @*/
805 PetscErrorCode PetscMergeMPIIntArray(PetscInt an,const PetscMPIInt aI[],PetscInt bn,const PetscMPIInt bI[],PetscInt *n,PetscMPIInt **L)
806 {
807   PetscErrorCode ierr;
808   PetscInt       ai,bi,k;
809 
810   PetscFunctionBegin;
811   if (!*L) {ierr = PetscMalloc1((an+bn),L);CHKERRQ(ierr);}
812   for (ai=0,bi=0,k=0; ai<an || bi<bn; ) {
813     PetscInt t = -1;
814     for ( ; ai<an && (!bn || aI[ai] <= bI[bi]); ai++) (*L)[k++] = t = aI[ai];
815     for ( ; bi<bn && bI[bi] == t; bi++);
816     for ( ; bi<bn && (!an || bI[bi] <= aI[ai]); bi++) (*L)[k++] = t = bI[bi];
817     for ( ; ai<an && aI[ai] == t; ai++);
818   }
819   *n = k;
820   PetscFunctionReturn(0);
821 }
822 
823 /*@C
824    PetscProcessTree - Prepares tree data to be displayed graphically
825 
826    Not Collective
827 
828    Input Parameters:
829 +  n  - number of values
830 .  mask - indicates those entries in the tree, location 0 is always masked
831 -  parentid - indicates the parent of each entry
832 
833    Output Parameters:
834 +  Nlevels - the number of levels
835 .  Level - for each node tells its level
836 .  Levelcnts - the number of nodes on each level
837 .  Idbylevel - a list of ids on each of the levels, first level followed by second etc
838 -  Column - for each id tells its column index
839 
840    Level: developer
841 
842    Notes: This code is not currently used
843 
844 .seealso: PetscSortReal(), PetscSortIntWithPermutation()
845 @*/
846 PetscErrorCode  PetscProcessTree(PetscInt n,const PetscBool mask[],const PetscInt parentid[],PetscInt *Nlevels,PetscInt **Level,PetscInt **Levelcnt,PetscInt **Idbylevel,PetscInt **Column)
847 {
848   PetscInt       i,j,cnt,nmask = 0,nlevels = 0,*level,*levelcnt,levelmax = 0,*workid,*workparentid,tcnt = 0,*idbylevel,*column;
849   PetscErrorCode ierr;
850   PetscBool      done = PETSC_FALSE;
851 
852   PetscFunctionBegin;
853   if (!mask[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Mask of 0th location must be set");
854   for (i=0; i<n; i++) {
855     if (mask[i]) continue;
856     if (parentid[i]  == i) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Node labeled as own parent");
857     if (parentid[i] && mask[parentid[i]]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Parent is masked");
858   }
859 
860   for (i=0; i<n; i++) {
861     if (!mask[i]) nmask++;
862   }
863 
864   /* determine the level in the tree of each node */
865   ierr = PetscCalloc1(n,&level);CHKERRQ(ierr);
866 
867   level[0] = 1;
868   while (!done) {
869     done = PETSC_TRUE;
870     for (i=0; i<n; i++) {
871       if (mask[i]) continue;
872       if (!level[i] && level[parentid[i]]) level[i] = level[parentid[i]] + 1;
873       else if (!level[i]) done = PETSC_FALSE;
874     }
875   }
876   for (i=0; i<n; i++) {
877     level[i]--;
878     nlevels = PetscMax(nlevels,level[i]);
879   }
880 
881   /* count the number of nodes on each level and its max */
882   ierr = PetscCalloc1(nlevels,&levelcnt);CHKERRQ(ierr);
883   for (i=0; i<n; i++) {
884     if (mask[i]) continue;
885     levelcnt[level[i]-1]++;
886   }
887   for (i=0; i<nlevels;i++) levelmax = PetscMax(levelmax,levelcnt[i]);
888 
889   /* for each level sort the ids by the parent id */
890   ierr = PetscMalloc2(levelmax,&workid,levelmax,&workparentid);CHKERRQ(ierr);
891   ierr = PetscMalloc1(nmask,&idbylevel);CHKERRQ(ierr);
892   for (j=1; j<=nlevels;j++) {
893     cnt = 0;
894     for (i=0; i<n; i++) {
895       if (mask[i]) continue;
896       if (level[i] != j) continue;
897       workid[cnt]         = i;
898       workparentid[cnt++] = parentid[i];
899     }
900     /*  PetscIntView(cnt,workparentid,0);
901     PetscIntView(cnt,workid,0);
902     ierr = PetscSortIntWithArray(cnt,workparentid,workid);CHKERRQ(ierr);
903     PetscIntView(cnt,workparentid,0);
904     PetscIntView(cnt,workid,0);*/
905     ierr  = PetscMemcpy(idbylevel+tcnt,workid,cnt*sizeof(PetscInt));CHKERRQ(ierr);
906     tcnt += cnt;
907   }
908   if (tcnt != nmask) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Inconsistent count of unmasked nodes");
909   ierr = PetscFree2(workid,workparentid);CHKERRQ(ierr);
910 
911   /* for each node list its column */
912   ierr = PetscMalloc1(n,&column);CHKERRQ(ierr);
913   cnt = 0;
914   for (j=0; j<nlevels; j++) {
915     for (i=0; i<levelcnt[j]; i++) {
916       column[idbylevel[cnt++]] = i;
917     }
918   }
919 
920   *Nlevels   = nlevels;
921   *Level     = level;
922   *Levelcnt  = levelcnt;
923   *Idbylevel = idbylevel;
924   *Column    = column;
925   PetscFunctionReturn(0);
926 }
927