xref: /petsc/src/sys/utils/sorti.c (revision ef8e358335c5882e7d377b87160557d47280dc77)
1e5c89e4eSSatish Balay #define PETSC_DLL
2e5c89e4eSSatish Balay /*
3e5c89e4eSSatish Balay    This file contains routines for sorting integers. Values are sorted in place.
4e5c89e4eSSatish Balay  */
5d382aafbSBarry Smith #include "petscsys.h"                /*I  "petscsys.h"  I*/
6e5c89e4eSSatish Balay 
7e5c89e4eSSatish Balay #define SWAP(a,b,t) {t=a;a=b;b=t;}
8e5c89e4eSSatish Balay 
9*ef8e3583SJed Brown #define MEDIAN(v,right)                         \
10*ef8e3583SJed Brown   (v[0]<v[right/2]                              \
11*ef8e3583SJed Brown    ? (v[right/2]<v[right]                       \
12*ef8e3583SJed Brown       ? right/2                                 \
13*ef8e3583SJed Brown       : (v[0]<v[right] ? right : 0))            \
14*ef8e3583SJed Brown    : (v[right]<v[right/2]                       \
15*ef8e3583SJed Brown       ? right/2                                 \
16*ef8e3583SJed Brown       : (v[0]<v[right] ? 0 : right)))
17*ef8e3583SJed Brown 
18e5c89e4eSSatish Balay /* -----------------------------------------------------------------------*/
19e5c89e4eSSatish Balay 
20e5c89e4eSSatish Balay #undef __FUNCT__
21e5c89e4eSSatish Balay #define __FUNCT__ "PetscSortInt_Private"
22e5c89e4eSSatish Balay /*
23e5c89e4eSSatish Balay    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
24e5c89e4eSSatish Balay    Assumes 0 origin for v, number of elements = right+1 (right is index of
25e5c89e4eSSatish Balay    right-most member).
26e5c89e4eSSatish Balay */
27*ef8e3583SJed Brown static void PetscSortInt_Private(PetscInt *v,PetscInt right)
28e5c89e4eSSatish Balay {
29*ef8e3583SJed Brown   PetscInt       i,j,pivot,tmp;
30e5c89e4eSSatish Balay 
31e5c89e4eSSatish Balay   if (right <= 1) {
32e5c89e4eSSatish Balay     if (right == 1) {
33e5c89e4eSSatish Balay       if (v[0] > v[1]) SWAP(v[0],v[1],tmp);
34e5c89e4eSSatish Balay     }
35*ef8e3583SJed Brown     return;
36e5c89e4eSSatish Balay   }
37*ef8e3583SJed Brown   i = MEDIAN(v,right);          /* Choose a pivot */
38*ef8e3583SJed Brown   SWAP(v[0],v[i],tmp);          /* Move it out of the way */
39*ef8e3583SJed Brown   pivot = v[0];
40*ef8e3583SJed Brown   for (i=0,j=right+1;;) {
41*ef8e3583SJed Brown     while (++i < j && v[i] <= pivot); /* Scan from the left */
42*ef8e3583SJed Brown     while (v[--j] > pivot);           /* Scan from the right */
43*ef8e3583SJed Brown     if (i >= j) break;
44*ef8e3583SJed Brown     SWAP(v[i],v[j],tmp);
45e5c89e4eSSatish Balay   }
46*ef8e3583SJed Brown   SWAP(v[0],v[j],tmp);          /* Put pivot back in place. */
47*ef8e3583SJed Brown   PetscSortInt_Private(v,j-1);
48*ef8e3583SJed Brown   PetscSortInt_Private(v+j+1,right-(j+1));
49e5c89e4eSSatish Balay }
50e5c89e4eSSatish Balay 
51e5c89e4eSSatish Balay #undef __FUNCT__
52e5c89e4eSSatish Balay #define __FUNCT__ "PetscSortInt"
53e5c89e4eSSatish Balay /*@
54e5c89e4eSSatish Balay    PetscSortInt - Sorts an array of integers in place in increasing order.
55e5c89e4eSSatish Balay 
56e5c89e4eSSatish Balay    Not Collective
57e5c89e4eSSatish Balay 
58e5c89e4eSSatish Balay    Input Parameters:
59e5c89e4eSSatish Balay +  n  - number of values
60e5c89e4eSSatish Balay -  i  - array of integers
61e5c89e4eSSatish Balay 
62e5c89e4eSSatish Balay    Level: intermediate
63e5c89e4eSSatish Balay 
64e5c89e4eSSatish Balay    Concepts: sorting^ints
65e5c89e4eSSatish Balay 
66e5c89e4eSSatish Balay .seealso: PetscSortReal(), PetscSortIntWithPermutation()
67e5c89e4eSSatish Balay @*/
688738c821SJed Brown PetscErrorCode PETSCSYS_DLLEXPORT PetscSortInt(PetscInt n,PetscInt i[])
69e5c89e4eSSatish Balay {
70e5c89e4eSSatish Balay   PetscInt       j,k,tmp,ik;
71e5c89e4eSSatish Balay 
72e5c89e4eSSatish Balay   PetscFunctionBegin;
73e5c89e4eSSatish Balay   if (n<8) {
74e5c89e4eSSatish Balay     for (k=0; k<n; k++) {
75e5c89e4eSSatish Balay       ik = i[k];
76e5c89e4eSSatish Balay       for (j=k+1; j<n; j++) {
77e5c89e4eSSatish Balay 	if (ik > i[j]) {
78e5c89e4eSSatish Balay 	  SWAP(i[k],i[j],tmp);
79e5c89e4eSSatish Balay 	  ik = i[k];
80e5c89e4eSSatish Balay 	}
81e5c89e4eSSatish Balay       }
82e5c89e4eSSatish Balay     }
83e5c89e4eSSatish Balay   } else {
84*ef8e3583SJed Brown     PetscSortInt_Private(i,n-1);
85e5c89e4eSSatish Balay   }
86e5c89e4eSSatish Balay   PetscFunctionReturn(0);
87e5c89e4eSSatish Balay }
88e5c89e4eSSatish Balay 
891db36a52SBarry Smith #undef __FUNCT__
901db36a52SBarry Smith #define __FUNCT__ "PetscSortRemoveDupsInt"
911db36a52SBarry Smith /*@
921db36a52SBarry Smith    PetscSortRemoveDupsInt - Sorts an array of integers in place in increasing order removes all duplicate entries
931db36a52SBarry Smith 
941db36a52SBarry Smith    Not Collective
951db36a52SBarry Smith 
961db36a52SBarry Smith    Input Parameters:
971db36a52SBarry Smith +  n  - number of values
981db36a52SBarry Smith -  ii  - array of integers
991db36a52SBarry Smith 
1001db36a52SBarry Smith    Output Parameter:
1011db36a52SBarry Smith .  n - number of non-redundant values
1021db36a52SBarry Smith 
1031db36a52SBarry Smith    Level: intermediate
1041db36a52SBarry Smith 
1051db36a52SBarry Smith    Concepts: sorting^ints
1061db36a52SBarry Smith 
1071db36a52SBarry Smith .seealso: PetscSortReal(), PetscSortIntWithPermutation(), PetscSortInt()
1081db36a52SBarry Smith @*/
1098738c821SJed Brown PetscErrorCode PETSCSYS_DLLEXPORT PetscSortRemoveDupsInt(PetscInt *n,PetscInt ii[])
1101db36a52SBarry Smith {
1111db36a52SBarry Smith   PetscErrorCode ierr;
1121db36a52SBarry Smith   PetscInt       i,s = 0,N = *n, b = 0;
1131db36a52SBarry Smith 
1141db36a52SBarry Smith   PetscFunctionBegin;
1151db36a52SBarry Smith   ierr = PetscSortInt(N,ii);CHKERRQ(ierr);
1161db36a52SBarry Smith   for (i=0; i<N-1; i++) {
1171db36a52SBarry Smith     if (ii[b+s+1] == ii[b]) {ii[b+1] = ii[b+s+2]; s++;}
1181db36a52SBarry Smith     else b++;
1191db36a52SBarry Smith   }
1201db36a52SBarry Smith   *n = N - s;
1211db36a52SBarry Smith   PetscFunctionReturn(0);
1221db36a52SBarry Smith }
1231db36a52SBarry Smith 
1241db36a52SBarry Smith 
125e5c89e4eSSatish Balay /* -----------------------------------------------------------------------*/
126e5c89e4eSSatish Balay #define SWAP2(a,b,c,d,t) {t=a;a=b;b=t;t=c;c=d;d=t;}
127e5c89e4eSSatish Balay 
128e5c89e4eSSatish Balay #undef __FUNCT__
129e5c89e4eSSatish Balay #define __FUNCT__ "PetscSortIntWithArray_Private"
130e5c89e4eSSatish Balay /*
131e5c89e4eSSatish Balay    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
132e5c89e4eSSatish Balay    Assumes 0 origin for v, number of elements = right+1 (right is index of
133e5c89e4eSSatish Balay    right-most member).
134e5c89e4eSSatish Balay */
135e5c89e4eSSatish Balay static PetscErrorCode PetscSortIntWithArray_Private(PetscInt *v,PetscInt *V,PetscInt right)
136e5c89e4eSSatish Balay {
137e5c89e4eSSatish Balay   PetscErrorCode ierr;
138e5c89e4eSSatish Balay   PetscInt       i,vl,last,tmp;
139e5c89e4eSSatish Balay 
140e5c89e4eSSatish Balay   PetscFunctionBegin;
141e5c89e4eSSatish Balay   if (right <= 1) {
142e5c89e4eSSatish Balay     if (right == 1) {
143e5c89e4eSSatish Balay       if (v[0] > v[1]) SWAP2(v[0],v[1],V[0],V[1],tmp);
144e5c89e4eSSatish Balay     }
145e5c89e4eSSatish Balay     PetscFunctionReturn(0);
146e5c89e4eSSatish Balay   }
147e5c89e4eSSatish Balay   SWAP2(v[0],v[right/2],V[0],V[right/2],tmp);
148e5c89e4eSSatish Balay   vl   = v[0];
149e5c89e4eSSatish Balay   last = 0;
150e5c89e4eSSatish Balay   for (i=1; i<=right; i++) {
151e5c89e4eSSatish Balay     if (v[i] < vl) {last++; SWAP2(v[last],v[i],V[last],V[i],tmp);}
152e5c89e4eSSatish Balay   }
153e5c89e4eSSatish Balay   SWAP2(v[0],v[last],V[0],V[last],tmp);
154e5c89e4eSSatish Balay   ierr = PetscSortIntWithArray_Private(v,V,last-1);CHKERRQ(ierr);
155e5c89e4eSSatish Balay   ierr = PetscSortIntWithArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr);
156e5c89e4eSSatish Balay   PetscFunctionReturn(0);
157e5c89e4eSSatish Balay }
158e5c89e4eSSatish Balay 
159e5c89e4eSSatish Balay #undef __FUNCT__
160e5c89e4eSSatish Balay #define __FUNCT__ "PetscSortIntWithArray"
161e5c89e4eSSatish Balay /*@
162e5c89e4eSSatish Balay    PetscSortIntWithArray - Sorts an array of integers in place in increasing order;
163e5c89e4eSSatish Balay        changes a second array to match the sorted first array.
164e5c89e4eSSatish Balay 
165e5c89e4eSSatish Balay    Not Collective
166e5c89e4eSSatish Balay 
167e5c89e4eSSatish Balay    Input Parameters:
168e5c89e4eSSatish Balay +  n  - number of values
169e5c89e4eSSatish Balay .  i  - array of integers
170e5c89e4eSSatish Balay -  I - second array of integers
171e5c89e4eSSatish Balay 
172e5c89e4eSSatish Balay    Level: intermediate
173e5c89e4eSSatish Balay 
174e5c89e4eSSatish Balay    Concepts: sorting^ints with array
175e5c89e4eSSatish Balay 
176e5c89e4eSSatish Balay .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt()
177e5c89e4eSSatish Balay @*/
1788738c821SJed Brown PetscErrorCode PETSCSYS_DLLEXPORT PetscSortIntWithArray(PetscInt n,PetscInt i[],PetscInt Ii[])
179e5c89e4eSSatish Balay {
180e5c89e4eSSatish Balay   PetscErrorCode ierr;
181e5c89e4eSSatish Balay   PetscInt       j,k,tmp,ik;
182e5c89e4eSSatish Balay 
183e5c89e4eSSatish Balay   PetscFunctionBegin;
184e5c89e4eSSatish Balay   if (n<8) {
185e5c89e4eSSatish Balay     for (k=0; k<n; k++) {
186e5c89e4eSSatish Balay       ik = i[k];
187e5c89e4eSSatish Balay       for (j=k+1; j<n; j++) {
188e5c89e4eSSatish Balay 	if (ik > i[j]) {
189b7940d39SSatish Balay 	  SWAP2(i[k],i[j],Ii[k],Ii[j],tmp);
190e5c89e4eSSatish Balay 	  ik = i[k];
191e5c89e4eSSatish Balay 	}
192e5c89e4eSSatish Balay       }
193e5c89e4eSSatish Balay     }
194e5c89e4eSSatish Balay   } else {
195b7940d39SSatish Balay     ierr = PetscSortIntWithArray_Private(i,Ii,n-1);CHKERRQ(ierr);
196e5c89e4eSSatish Balay   }
197e5c89e4eSSatish Balay   PetscFunctionReturn(0);
198e5c89e4eSSatish Balay }
199e5c89e4eSSatish Balay 
2004d615ea0SBarry Smith #undef __FUNCT__
2014d615ea0SBarry Smith #define __FUNCT__ "PetscSortMPIIntWithArray_Private"
2024d615ea0SBarry Smith /*
2034d615ea0SBarry Smith    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
2044d615ea0SBarry Smith    Assumes 0 origin for v, number of elements = right+1 (right is index of
2054d615ea0SBarry Smith    right-most member).
2064d615ea0SBarry Smith */
2074d615ea0SBarry Smith static PetscErrorCode PetscSortMPIIntWithArray_Private(PetscMPIInt *v,PetscMPIInt *V,PetscMPIInt right)
2084d615ea0SBarry Smith {
2094d615ea0SBarry Smith   PetscErrorCode ierr;
2104d615ea0SBarry Smith   PetscMPIInt    i,vl,last,tmp;
2114d615ea0SBarry Smith 
2124d615ea0SBarry Smith   PetscFunctionBegin;
2134d615ea0SBarry Smith   if (right <= 1) {
2144d615ea0SBarry Smith     if (right == 1) {
2154d615ea0SBarry Smith       if (v[0] > v[1]) SWAP2(v[0],v[1],V[0],V[1],tmp);
2164d615ea0SBarry Smith     }
2174d615ea0SBarry Smith     PetscFunctionReturn(0);
2184d615ea0SBarry Smith   }
2194d615ea0SBarry Smith   SWAP2(v[0],v[right/2],V[0],V[right/2],tmp);
2204d615ea0SBarry Smith   vl   = v[0];
2214d615ea0SBarry Smith   last = 0;
2224d615ea0SBarry Smith   for (i=1; i<=right; i++) {
2234d615ea0SBarry Smith     if (v[i] < vl) {last++; SWAP2(v[last],v[i],V[last],V[i],tmp);}
2244d615ea0SBarry Smith   }
2254d615ea0SBarry Smith   SWAP2(v[0],v[last],V[0],V[last],tmp);
2264d615ea0SBarry Smith   ierr = PetscSortMPIIntWithArray_Private(v,V,last-1);CHKERRQ(ierr);
2274d615ea0SBarry Smith   ierr = PetscSortMPIIntWithArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr);
2284d615ea0SBarry Smith   PetscFunctionReturn(0);
2294d615ea0SBarry Smith }
2304d615ea0SBarry Smith 
2314d615ea0SBarry Smith #undef __FUNCT__
2324d615ea0SBarry Smith #define __FUNCT__ "PetscSortMPIIntWithArray"
2334d615ea0SBarry Smith /*@
2344d615ea0SBarry Smith    PetscSortMPIIntWithArray - Sorts an array of integers in place in increasing order;
2354d615ea0SBarry Smith        changes a second array to match the sorted first array.
2364d615ea0SBarry Smith 
2374d615ea0SBarry Smith    Not Collective
2384d615ea0SBarry Smith 
2394d615ea0SBarry Smith    Input Parameters:
2404d615ea0SBarry Smith +  n  - number of values
2414d615ea0SBarry Smith .  i  - array of integers
2424d615ea0SBarry Smith -  I - second array of integers
2434d615ea0SBarry Smith 
2444d615ea0SBarry Smith    Level: intermediate
2454d615ea0SBarry Smith 
2464d615ea0SBarry Smith    Concepts: sorting^ints with array
2474d615ea0SBarry Smith 
2484d615ea0SBarry Smith .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt()
2494d615ea0SBarry Smith @*/
2508738c821SJed Brown PetscErrorCode PETSCSYS_DLLEXPORT PetscSortMPIIntWithArray(PetscMPIInt n,PetscMPIInt i[],PetscMPIInt Ii[])
2514d615ea0SBarry Smith {
2524d615ea0SBarry Smith   PetscErrorCode ierr;
2534d615ea0SBarry Smith   PetscMPIInt    j,k,tmp,ik;
2544d615ea0SBarry Smith 
2554d615ea0SBarry Smith   PetscFunctionBegin;
2564d615ea0SBarry Smith   if (n<8) {
2574d615ea0SBarry Smith     for (k=0; k<n; k++) {
2584d615ea0SBarry Smith       ik = i[k];
2594d615ea0SBarry Smith       for (j=k+1; j<n; j++) {
2604d615ea0SBarry Smith 	if (ik > i[j]) {
2614d615ea0SBarry Smith 	  SWAP2(i[k],i[j],Ii[k],Ii[j],tmp);
2624d615ea0SBarry Smith 	  ik = i[k];
2634d615ea0SBarry Smith 	}
2644d615ea0SBarry Smith       }
2654d615ea0SBarry Smith     }
2664d615ea0SBarry Smith   } else {
2674d615ea0SBarry Smith     ierr = PetscSortMPIIntWithArray_Private(i,Ii,n-1);CHKERRQ(ierr);
2684d615ea0SBarry Smith   }
2694d615ea0SBarry Smith   PetscFunctionReturn(0);
2704d615ea0SBarry Smith }
2714d615ea0SBarry Smith 
272e5c89e4eSSatish Balay /* -----------------------------------------------------------------------*/
273e5c89e4eSSatish Balay #define SWAP2IntScalar(a,b,c,d,t,ts) {t=a;a=b;b=t;ts=c;c=d;d=ts;}
274e5c89e4eSSatish Balay 
275e5c89e4eSSatish Balay #undef __FUNCT__
276e5c89e4eSSatish Balay #define __FUNCT__ "PetscSortIntWithScalarArray_Private"
277e5c89e4eSSatish Balay /*
278e5c89e4eSSatish Balay    Modified from PetscSortIntWithArray_Private().
279e5c89e4eSSatish Balay */
280e5c89e4eSSatish Balay static PetscErrorCode PetscSortIntWithScalarArray_Private(PetscInt *v,PetscScalar *V,PetscInt right)
281e5c89e4eSSatish Balay {
282e5c89e4eSSatish Balay   PetscErrorCode ierr;
283e5c89e4eSSatish Balay   PetscInt       i,vl,last,tmp;
284e5c89e4eSSatish Balay   PetscScalar    stmp;
285e5c89e4eSSatish Balay 
286e5c89e4eSSatish Balay   PetscFunctionBegin;
287e5c89e4eSSatish Balay   if (right <= 1) {
288e5c89e4eSSatish Balay     if (right == 1) {
289e5c89e4eSSatish Balay       if (v[0] > v[1]) SWAP2IntScalar(v[0],v[1],V[0],V[1],tmp,stmp);
290e5c89e4eSSatish Balay     }
291e5c89e4eSSatish Balay     PetscFunctionReturn(0);
292e5c89e4eSSatish Balay   }
293e5c89e4eSSatish Balay   SWAP2IntScalar(v[0],v[right/2],V[0],V[right/2],tmp,stmp);
294e5c89e4eSSatish Balay   vl   = v[0];
295e5c89e4eSSatish Balay   last = 0;
296e5c89e4eSSatish Balay   for (i=1; i<=right; i++) {
297e5c89e4eSSatish Balay     if (v[i] < vl) {last++; SWAP2IntScalar(v[last],v[i],V[last],V[i],tmp,stmp);}
298e5c89e4eSSatish Balay   }
299e5c89e4eSSatish Balay   SWAP2IntScalar(v[0],v[last],V[0],V[last],tmp,stmp);
300e5c89e4eSSatish Balay   ierr = PetscSortIntWithScalarArray_Private(v,V,last-1);CHKERRQ(ierr);
301e5c89e4eSSatish Balay   ierr = PetscSortIntWithScalarArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr);
302e5c89e4eSSatish Balay   PetscFunctionReturn(0);
303e5c89e4eSSatish Balay }
304e5c89e4eSSatish Balay 
305e5c89e4eSSatish Balay #undef __FUNCT__
306e5c89e4eSSatish Balay #define __FUNCT__ "PetscSortIntWithScalarArray"
307e5c89e4eSSatish Balay /*@
308e5c89e4eSSatish Balay    PetscSortIntWithScalarArray - Sorts an array of integers in place in increasing order;
309e5c89e4eSSatish Balay        changes a second SCALAR array to match the sorted first INTEGER array.
310e5c89e4eSSatish Balay 
311e5c89e4eSSatish Balay    Not Collective
312e5c89e4eSSatish Balay 
313e5c89e4eSSatish Balay    Input Parameters:
314e5c89e4eSSatish Balay +  n  - number of values
315e5c89e4eSSatish Balay .  i  - array of integers
316e5c89e4eSSatish Balay -  I - second array of scalars
317e5c89e4eSSatish Balay 
318e5c89e4eSSatish Balay    Level: intermediate
319e5c89e4eSSatish Balay 
320e5c89e4eSSatish Balay    Concepts: sorting^ints with array
321e5c89e4eSSatish Balay 
322e5c89e4eSSatish Balay .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
323e5c89e4eSSatish Balay @*/
3248738c821SJed Brown PetscErrorCode PETSCSYS_DLLEXPORT PetscSortIntWithScalarArray(PetscInt n,PetscInt i[],PetscScalar Ii[])
325e5c89e4eSSatish Balay {
326e5c89e4eSSatish Balay   PetscErrorCode ierr;
327e5c89e4eSSatish Balay   PetscInt       j,k,tmp,ik;
328e5c89e4eSSatish Balay   PetscScalar    stmp;
329e5c89e4eSSatish Balay 
330e5c89e4eSSatish Balay   PetscFunctionBegin;
331e5c89e4eSSatish Balay   if (n<8) {
332e5c89e4eSSatish Balay     for (k=0; k<n; k++) {
333e5c89e4eSSatish Balay       ik = i[k];
334e5c89e4eSSatish Balay       for (j=k+1; j<n; j++) {
335e5c89e4eSSatish Balay 	if (ik > i[j]) {
336b7940d39SSatish Balay 	  SWAP2IntScalar(i[k],i[j],Ii[k],Ii[j],tmp,stmp);
337e5c89e4eSSatish Balay 	  ik = i[k];
338e5c89e4eSSatish Balay 	}
339e5c89e4eSSatish Balay       }
340e5c89e4eSSatish Balay     }
341e5c89e4eSSatish Balay   } else {
342b7940d39SSatish Balay     ierr = PetscSortIntWithScalarArray_Private(i,Ii,n-1);CHKERRQ(ierr);
343e5c89e4eSSatish Balay   }
344e5c89e4eSSatish Balay   PetscFunctionReturn(0);
345e5c89e4eSSatish Balay }
346e5c89e4eSSatish Balay 
347e5c89e4eSSatish Balay 
348