xref: /petsc/src/sys/utils/sorti.c (revision 1db36a52b31bfc0a3db4fe0468e0275a159b84c3)
1e5c89e4eSSatish Balay #define PETSC_DLL
2e5c89e4eSSatish Balay /*
3e5c89e4eSSatish Balay    This file contains routines for sorting integers. Values are sorted in place.
4e5c89e4eSSatish Balay 
5e5c89e4eSSatish Balay 
6e5c89e4eSSatish Balay    The word "register"  in this code is used to identify data that is not
7e5c89e4eSSatish Balay    aliased.  For some compilers, marking variables as register can improve
8e5c89e4eSSatish Balay    the compiler optimizations.
9e5c89e4eSSatish Balay  */
10d382aafbSBarry Smith #include "petscsys.h"                /*I  "petscsys.h"  I*/
11e5c89e4eSSatish Balay 
12e5c89e4eSSatish Balay #define SWAP(a,b,t) {t=a;a=b;b=t;}
13e5c89e4eSSatish Balay 
14e5c89e4eSSatish Balay /* -----------------------------------------------------------------------*/
15e5c89e4eSSatish Balay 
16e5c89e4eSSatish Balay #undef __FUNCT__
17e5c89e4eSSatish Balay #define __FUNCT__ "PetscSortInt_Private"
18e5c89e4eSSatish Balay /*
19e5c89e4eSSatish Balay    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
20e5c89e4eSSatish Balay    Assumes 0 origin for v, number of elements = right+1 (right is index of
21e5c89e4eSSatish Balay    right-most member).
22e5c89e4eSSatish Balay */
23e5c89e4eSSatish Balay static PetscErrorCode PetscSortInt_Private(PetscInt *v,PetscInt right)
24e5c89e4eSSatish Balay {
25e5c89e4eSSatish Balay   PetscErrorCode ierr;
26e5c89e4eSSatish Balay   PetscInt       i,vl,last,tmp;
27e5c89e4eSSatish Balay 
28e5c89e4eSSatish Balay   PetscFunctionBegin;
29e5c89e4eSSatish Balay   if (right <= 1) {
30e5c89e4eSSatish Balay     if (right == 1) {
31e5c89e4eSSatish Balay       if (v[0] > v[1]) SWAP(v[0],v[1],tmp);
32e5c89e4eSSatish Balay     }
33e5c89e4eSSatish Balay     PetscFunctionReturn(0);
34e5c89e4eSSatish Balay   }
35e5c89e4eSSatish Balay   SWAP(v[0],v[right/2],tmp);
36e5c89e4eSSatish Balay   vl   = v[0];
37e5c89e4eSSatish Balay   last = 0;
38e5c89e4eSSatish Balay   for (i=1; i<=right; i++) {
39e5c89e4eSSatish Balay     if (v[i] < vl) {last++; SWAP(v[last],v[i],tmp);}
40e5c89e4eSSatish Balay   }
41e5c89e4eSSatish Balay   SWAP(v[0],v[last],tmp);
42e5c89e4eSSatish Balay   ierr = PetscSortInt_Private(v,last-1);CHKERRQ(ierr);
43e5c89e4eSSatish Balay   ierr = PetscSortInt_Private(v+last+1,right-(last+1));CHKERRQ(ierr);
44e5c89e4eSSatish Balay   PetscFunctionReturn(0);
45e5c89e4eSSatish Balay }
46e5c89e4eSSatish Balay 
47e5c89e4eSSatish Balay #undef __FUNCT__
48e5c89e4eSSatish Balay #define __FUNCT__ "PetscSortInt"
49e5c89e4eSSatish Balay /*@
50e5c89e4eSSatish Balay    PetscSortInt - Sorts an array of integers in place in increasing order.
51e5c89e4eSSatish Balay 
52e5c89e4eSSatish Balay    Not Collective
53e5c89e4eSSatish Balay 
54e5c89e4eSSatish Balay    Input Parameters:
55e5c89e4eSSatish Balay +  n  - number of values
56e5c89e4eSSatish Balay -  i  - array of integers
57e5c89e4eSSatish Balay 
58e5c89e4eSSatish Balay    Level: intermediate
59e5c89e4eSSatish Balay 
60e5c89e4eSSatish Balay    Concepts: sorting^ints
61e5c89e4eSSatish Balay 
62e5c89e4eSSatish Balay .seealso: PetscSortReal(), PetscSortIntWithPermutation()
63e5c89e4eSSatish Balay @*/
64e5c89e4eSSatish Balay PetscErrorCode PETSC_DLLEXPORT PetscSortInt(PetscInt n,PetscInt i[])
65e5c89e4eSSatish Balay {
66e5c89e4eSSatish Balay   PetscErrorCode ierr;
67e5c89e4eSSatish Balay   PetscInt       j,k,tmp,ik;
68e5c89e4eSSatish Balay 
69e5c89e4eSSatish Balay   PetscFunctionBegin;
70e5c89e4eSSatish Balay   if (n<8) {
71e5c89e4eSSatish Balay     for (k=0; k<n; k++) {
72e5c89e4eSSatish Balay       ik = i[k];
73e5c89e4eSSatish Balay       for (j=k+1; j<n; j++) {
74e5c89e4eSSatish Balay 	if (ik > i[j]) {
75e5c89e4eSSatish Balay 	  SWAP(i[k],i[j],tmp);
76e5c89e4eSSatish Balay 	  ik = i[k];
77e5c89e4eSSatish Balay 	}
78e5c89e4eSSatish Balay       }
79e5c89e4eSSatish Balay     }
80e5c89e4eSSatish Balay   } else {
81e5c89e4eSSatish Balay     ierr = PetscSortInt_Private(i,n-1);CHKERRQ(ierr);
82e5c89e4eSSatish Balay   }
83e5c89e4eSSatish Balay   PetscFunctionReturn(0);
84e5c89e4eSSatish Balay }
85e5c89e4eSSatish Balay 
86*1db36a52SBarry Smith #undef __FUNCT__
87*1db36a52SBarry Smith #define __FUNCT__ "PetscSortRemoveDupsInt"
88*1db36a52SBarry Smith /*@
89*1db36a52SBarry Smith    PetscSortRemoveDupsInt - Sorts an array of integers in place in increasing order removes all duplicate entries
90*1db36a52SBarry Smith 
91*1db36a52SBarry Smith    Not Collective
92*1db36a52SBarry Smith 
93*1db36a52SBarry Smith    Input Parameters:
94*1db36a52SBarry Smith +  n  - number of values
95*1db36a52SBarry Smith -  ii  - array of integers
96*1db36a52SBarry Smith 
97*1db36a52SBarry Smith    Output Parameter:
98*1db36a52SBarry Smith .  n - number of non-redundant values
99*1db36a52SBarry Smith 
100*1db36a52SBarry Smith    Level: intermediate
101*1db36a52SBarry Smith 
102*1db36a52SBarry Smith    Concepts: sorting^ints
103*1db36a52SBarry Smith 
104*1db36a52SBarry Smith .seealso: PetscSortReal(), PetscSortIntWithPermutation(), PetscSortInt()
105*1db36a52SBarry Smith @*/
106*1db36a52SBarry Smith PetscErrorCode PETSC_DLLEXPORT PetscSortRemoveDupsInt(PetscInt *n,PetscInt ii[])
107*1db36a52SBarry Smith {
108*1db36a52SBarry Smith   PetscErrorCode ierr;
109*1db36a52SBarry Smith   PetscInt       i,s = 0,N = *n, b = 0;
110*1db36a52SBarry Smith 
111*1db36a52SBarry Smith   PetscFunctionBegin;
112*1db36a52SBarry Smith   ierr = PetscSortInt(N,ii);CHKERRQ(ierr);
113*1db36a52SBarry Smith   for (i=0; i<N-1; i++) {
114*1db36a52SBarry Smith     if (ii[b+s+1] == ii[b]) {ii[b+1] = ii[b+s+2]; s++;}
115*1db36a52SBarry Smith     else b++;
116*1db36a52SBarry Smith   }
117*1db36a52SBarry Smith   *n = N - s;
118*1db36a52SBarry Smith   PetscFunctionReturn(0);
119*1db36a52SBarry Smith }
120*1db36a52SBarry Smith 
121*1db36a52SBarry Smith 
122e5c89e4eSSatish Balay /* -----------------------------------------------------------------------*/
123e5c89e4eSSatish Balay #define SWAP2(a,b,c,d,t) {t=a;a=b;b=t;t=c;c=d;d=t;}
124e5c89e4eSSatish Balay 
125e5c89e4eSSatish Balay #undef __FUNCT__
126e5c89e4eSSatish Balay #define __FUNCT__ "PetscSortIntWithArray_Private"
127e5c89e4eSSatish Balay /*
128e5c89e4eSSatish Balay    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
129e5c89e4eSSatish Balay    Assumes 0 origin for v, number of elements = right+1 (right is index of
130e5c89e4eSSatish Balay    right-most member).
131e5c89e4eSSatish Balay */
132e5c89e4eSSatish Balay static PetscErrorCode PetscSortIntWithArray_Private(PetscInt *v,PetscInt *V,PetscInt right)
133e5c89e4eSSatish Balay {
134e5c89e4eSSatish Balay   PetscErrorCode ierr;
135e5c89e4eSSatish Balay   PetscInt       i,vl,last,tmp;
136e5c89e4eSSatish Balay 
137e5c89e4eSSatish Balay   PetscFunctionBegin;
138e5c89e4eSSatish Balay   if (right <= 1) {
139e5c89e4eSSatish Balay     if (right == 1) {
140e5c89e4eSSatish Balay       if (v[0] > v[1]) SWAP2(v[0],v[1],V[0],V[1],tmp);
141e5c89e4eSSatish Balay     }
142e5c89e4eSSatish Balay     PetscFunctionReturn(0);
143e5c89e4eSSatish Balay   }
144e5c89e4eSSatish Balay   SWAP2(v[0],v[right/2],V[0],V[right/2],tmp);
145e5c89e4eSSatish Balay   vl   = v[0];
146e5c89e4eSSatish Balay   last = 0;
147e5c89e4eSSatish Balay   for (i=1; i<=right; i++) {
148e5c89e4eSSatish Balay     if (v[i] < vl) {last++; SWAP2(v[last],v[i],V[last],V[i],tmp);}
149e5c89e4eSSatish Balay   }
150e5c89e4eSSatish Balay   SWAP2(v[0],v[last],V[0],V[last],tmp);
151e5c89e4eSSatish Balay   ierr = PetscSortIntWithArray_Private(v,V,last-1);CHKERRQ(ierr);
152e5c89e4eSSatish Balay   ierr = PetscSortIntWithArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr);
153e5c89e4eSSatish Balay   PetscFunctionReturn(0);
154e5c89e4eSSatish Balay }
155e5c89e4eSSatish Balay 
156e5c89e4eSSatish Balay #undef __FUNCT__
157e5c89e4eSSatish Balay #define __FUNCT__ "PetscSortIntWithArray"
158e5c89e4eSSatish Balay /*@
159e5c89e4eSSatish Balay    PetscSortIntWithArray - Sorts an array of integers in place in increasing order;
160e5c89e4eSSatish Balay        changes a second array to match the sorted first array.
161e5c89e4eSSatish Balay 
162e5c89e4eSSatish Balay    Not Collective
163e5c89e4eSSatish Balay 
164e5c89e4eSSatish Balay    Input Parameters:
165e5c89e4eSSatish Balay +  n  - number of values
166e5c89e4eSSatish Balay .  i  - array of integers
167e5c89e4eSSatish Balay -  I - second array of integers
168e5c89e4eSSatish Balay 
169e5c89e4eSSatish Balay    Level: intermediate
170e5c89e4eSSatish Balay 
171e5c89e4eSSatish Balay    Concepts: sorting^ints with array
172e5c89e4eSSatish Balay 
173e5c89e4eSSatish Balay .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt()
174e5c89e4eSSatish Balay @*/
175b7940d39SSatish Balay PetscErrorCode PETSC_DLLEXPORT PetscSortIntWithArray(PetscInt n,PetscInt i[],PetscInt Ii[])
176e5c89e4eSSatish Balay {
177e5c89e4eSSatish Balay   PetscErrorCode ierr;
178e5c89e4eSSatish Balay   PetscInt       j,k,tmp,ik;
179e5c89e4eSSatish Balay 
180e5c89e4eSSatish Balay   PetscFunctionBegin;
181e5c89e4eSSatish Balay   if (n<8) {
182e5c89e4eSSatish Balay     for (k=0; k<n; k++) {
183e5c89e4eSSatish Balay       ik = i[k];
184e5c89e4eSSatish Balay       for (j=k+1; j<n; j++) {
185e5c89e4eSSatish Balay 	if (ik > i[j]) {
186b7940d39SSatish Balay 	  SWAP2(i[k],i[j],Ii[k],Ii[j],tmp);
187e5c89e4eSSatish Balay 	  ik = i[k];
188e5c89e4eSSatish Balay 	}
189e5c89e4eSSatish Balay       }
190e5c89e4eSSatish Balay     }
191e5c89e4eSSatish Balay   } else {
192b7940d39SSatish Balay     ierr = PetscSortIntWithArray_Private(i,Ii,n-1);CHKERRQ(ierr);
193e5c89e4eSSatish Balay   }
194e5c89e4eSSatish Balay   PetscFunctionReturn(0);
195e5c89e4eSSatish Balay }
196e5c89e4eSSatish Balay 
1974d615ea0SBarry Smith #undef __FUNCT__
1984d615ea0SBarry Smith #define __FUNCT__ "PetscSortMPIIntWithArray_Private"
1994d615ea0SBarry Smith /*
2004d615ea0SBarry Smith    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
2014d615ea0SBarry Smith    Assumes 0 origin for v, number of elements = right+1 (right is index of
2024d615ea0SBarry Smith    right-most member).
2034d615ea0SBarry Smith */
2044d615ea0SBarry Smith static PetscErrorCode PetscSortMPIIntWithArray_Private(PetscMPIInt *v,PetscMPIInt *V,PetscMPIInt right)
2054d615ea0SBarry Smith {
2064d615ea0SBarry Smith   PetscErrorCode ierr;
2074d615ea0SBarry Smith   PetscMPIInt    i,vl,last,tmp;
2084d615ea0SBarry Smith 
2094d615ea0SBarry Smith   PetscFunctionBegin;
2104d615ea0SBarry Smith   if (right <= 1) {
2114d615ea0SBarry Smith     if (right == 1) {
2124d615ea0SBarry Smith       if (v[0] > v[1]) SWAP2(v[0],v[1],V[0],V[1],tmp);
2134d615ea0SBarry Smith     }
2144d615ea0SBarry Smith     PetscFunctionReturn(0);
2154d615ea0SBarry Smith   }
2164d615ea0SBarry Smith   SWAP2(v[0],v[right/2],V[0],V[right/2],tmp);
2174d615ea0SBarry Smith   vl   = v[0];
2184d615ea0SBarry Smith   last = 0;
2194d615ea0SBarry Smith   for (i=1; i<=right; i++) {
2204d615ea0SBarry Smith     if (v[i] < vl) {last++; SWAP2(v[last],v[i],V[last],V[i],tmp);}
2214d615ea0SBarry Smith   }
2224d615ea0SBarry Smith   SWAP2(v[0],v[last],V[0],V[last],tmp);
2234d615ea0SBarry Smith   ierr = PetscSortMPIIntWithArray_Private(v,V,last-1);CHKERRQ(ierr);
2244d615ea0SBarry Smith   ierr = PetscSortMPIIntWithArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr);
2254d615ea0SBarry Smith   PetscFunctionReturn(0);
2264d615ea0SBarry Smith }
2274d615ea0SBarry Smith 
2284d615ea0SBarry Smith #undef __FUNCT__
2294d615ea0SBarry Smith #define __FUNCT__ "PetscSortMPIIntWithArray"
2304d615ea0SBarry Smith /*@
2314d615ea0SBarry Smith    PetscSortMPIIntWithArray - Sorts an array of integers in place in increasing order;
2324d615ea0SBarry Smith        changes a second array to match the sorted first array.
2334d615ea0SBarry Smith 
2344d615ea0SBarry Smith    Not Collective
2354d615ea0SBarry Smith 
2364d615ea0SBarry Smith    Input Parameters:
2374d615ea0SBarry Smith +  n  - number of values
2384d615ea0SBarry Smith .  i  - array of integers
2394d615ea0SBarry Smith -  I - second array of integers
2404d615ea0SBarry Smith 
2414d615ea0SBarry Smith    Level: intermediate
2424d615ea0SBarry Smith 
2434d615ea0SBarry Smith    Concepts: sorting^ints with array
2444d615ea0SBarry Smith 
2454d615ea0SBarry Smith .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt()
2464d615ea0SBarry Smith @*/
2474d615ea0SBarry Smith PetscErrorCode PETSC_DLLEXPORT PetscSortMPIIntWithArray(PetscMPIInt n,PetscMPIInt i[],PetscMPIInt Ii[])
2484d615ea0SBarry Smith {
2494d615ea0SBarry Smith   PetscErrorCode ierr;
2504d615ea0SBarry Smith   PetscMPIInt    j,k,tmp,ik;
2514d615ea0SBarry Smith 
2524d615ea0SBarry Smith   PetscFunctionBegin;
2534d615ea0SBarry Smith   if (n<8) {
2544d615ea0SBarry Smith     for (k=0; k<n; k++) {
2554d615ea0SBarry Smith       ik = i[k];
2564d615ea0SBarry Smith       for (j=k+1; j<n; j++) {
2574d615ea0SBarry Smith 	if (ik > i[j]) {
2584d615ea0SBarry Smith 	  SWAP2(i[k],i[j],Ii[k],Ii[j],tmp);
2594d615ea0SBarry Smith 	  ik = i[k];
2604d615ea0SBarry Smith 	}
2614d615ea0SBarry Smith       }
2624d615ea0SBarry Smith     }
2634d615ea0SBarry Smith   } else {
2644d615ea0SBarry Smith     ierr = PetscSortMPIIntWithArray_Private(i,Ii,n-1);CHKERRQ(ierr);
2654d615ea0SBarry Smith   }
2664d615ea0SBarry Smith   PetscFunctionReturn(0);
2674d615ea0SBarry Smith }
2684d615ea0SBarry Smith 
269e5c89e4eSSatish Balay /* -----------------------------------------------------------------------*/
270e5c89e4eSSatish Balay #define SWAP2IntScalar(a,b,c,d,t,ts) {t=a;a=b;b=t;ts=c;c=d;d=ts;}
271e5c89e4eSSatish Balay 
272e5c89e4eSSatish Balay #undef __FUNCT__
273e5c89e4eSSatish Balay #define __FUNCT__ "PetscSortIntWithScalarArray_Private"
274e5c89e4eSSatish Balay /*
275e5c89e4eSSatish Balay    Modified from PetscSortIntWithArray_Private().
276e5c89e4eSSatish Balay */
277e5c89e4eSSatish Balay static PetscErrorCode PetscSortIntWithScalarArray_Private(PetscInt *v,PetscScalar *V,PetscInt right)
278e5c89e4eSSatish Balay {
279e5c89e4eSSatish Balay   PetscErrorCode ierr;
280e5c89e4eSSatish Balay   PetscInt       i,vl,last,tmp;
281e5c89e4eSSatish Balay   PetscScalar    stmp;
282e5c89e4eSSatish Balay 
283e5c89e4eSSatish Balay   PetscFunctionBegin;
284e5c89e4eSSatish Balay   if (right <= 1) {
285e5c89e4eSSatish Balay     if (right == 1) {
286e5c89e4eSSatish Balay       if (v[0] > v[1]) SWAP2IntScalar(v[0],v[1],V[0],V[1],tmp,stmp);
287e5c89e4eSSatish Balay     }
288e5c89e4eSSatish Balay     PetscFunctionReturn(0);
289e5c89e4eSSatish Balay   }
290e5c89e4eSSatish Balay   SWAP2IntScalar(v[0],v[right/2],V[0],V[right/2],tmp,stmp);
291e5c89e4eSSatish Balay   vl   = v[0];
292e5c89e4eSSatish Balay   last = 0;
293e5c89e4eSSatish Balay   for (i=1; i<=right; i++) {
294e5c89e4eSSatish Balay     if (v[i] < vl) {last++; SWAP2IntScalar(v[last],v[i],V[last],V[i],tmp,stmp);}
295e5c89e4eSSatish Balay   }
296e5c89e4eSSatish Balay   SWAP2IntScalar(v[0],v[last],V[0],V[last],tmp,stmp);
297e5c89e4eSSatish Balay   ierr = PetscSortIntWithScalarArray_Private(v,V,last-1);CHKERRQ(ierr);
298e5c89e4eSSatish Balay   ierr = PetscSortIntWithScalarArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr);
299e5c89e4eSSatish Balay   PetscFunctionReturn(0);
300e5c89e4eSSatish Balay }
301e5c89e4eSSatish Balay 
302e5c89e4eSSatish Balay #undef __FUNCT__
303e5c89e4eSSatish Balay #define __FUNCT__ "PetscSortIntWithScalarArray"
304e5c89e4eSSatish Balay /*@
305e5c89e4eSSatish Balay    PetscSortIntWithScalarArray - Sorts an array of integers in place in increasing order;
306e5c89e4eSSatish Balay        changes a second SCALAR array to match the sorted first INTEGER array.
307e5c89e4eSSatish Balay 
308e5c89e4eSSatish Balay    Not Collective
309e5c89e4eSSatish Balay 
310e5c89e4eSSatish Balay    Input Parameters:
311e5c89e4eSSatish Balay +  n  - number of values
312e5c89e4eSSatish Balay .  i  - array of integers
313e5c89e4eSSatish Balay -  I - second array of scalars
314e5c89e4eSSatish Balay 
315e5c89e4eSSatish Balay    Level: intermediate
316e5c89e4eSSatish Balay 
317e5c89e4eSSatish Balay    Concepts: sorting^ints with array
318e5c89e4eSSatish Balay 
319e5c89e4eSSatish Balay .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
320e5c89e4eSSatish Balay @*/
321b7940d39SSatish Balay PetscErrorCode PETSC_DLLEXPORT PetscSortIntWithScalarArray(PetscInt n,PetscInt i[],PetscScalar Ii[])
322e5c89e4eSSatish Balay {
323e5c89e4eSSatish Balay   PetscErrorCode ierr;
324e5c89e4eSSatish Balay   PetscInt       j,k,tmp,ik;
325e5c89e4eSSatish Balay   PetscScalar    stmp;
326e5c89e4eSSatish Balay 
327e5c89e4eSSatish Balay   PetscFunctionBegin;
328e5c89e4eSSatish Balay   if (n<8) {
329e5c89e4eSSatish Balay     for (k=0; k<n; k++) {
330e5c89e4eSSatish Balay       ik = i[k];
331e5c89e4eSSatish Balay       for (j=k+1; j<n; j++) {
332e5c89e4eSSatish Balay 	if (ik > i[j]) {
333b7940d39SSatish Balay 	  SWAP2IntScalar(i[k],i[j],Ii[k],Ii[j],tmp,stmp);
334e5c89e4eSSatish Balay 	  ik = i[k];
335e5c89e4eSSatish Balay 	}
336e5c89e4eSSatish Balay       }
337e5c89e4eSSatish Balay     }
338e5c89e4eSSatish Balay   } else {
339b7940d39SSatish Balay     ierr = PetscSortIntWithScalarArray_Private(i,Ii,n-1);CHKERRQ(ierr);
340e5c89e4eSSatish Balay   }
341e5c89e4eSSatish Balay   PetscFunctionReturn(0);
342e5c89e4eSSatish Balay }
343e5c89e4eSSatish Balay 
344e5c89e4eSSatish Balay 
345