xref: /petsc/src/sys/utils/sorti.c (revision d382aafbaf988181ac6819ef14789c4ab78c7a0e)
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  */
10*d382aafbSBarry 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 
86e5c89e4eSSatish Balay /* -----------------------------------------------------------------------*/
87e5c89e4eSSatish Balay #define SWAP2(a,b,c,d,t) {t=a;a=b;b=t;t=c;c=d;d=t;}
88e5c89e4eSSatish Balay 
89e5c89e4eSSatish Balay #undef __FUNCT__
90e5c89e4eSSatish Balay #define __FUNCT__ "PetscSortIntWithArray_Private"
91e5c89e4eSSatish Balay /*
92e5c89e4eSSatish Balay    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
93e5c89e4eSSatish Balay    Assumes 0 origin for v, number of elements = right+1 (right is index of
94e5c89e4eSSatish Balay    right-most member).
95e5c89e4eSSatish Balay */
96e5c89e4eSSatish Balay static PetscErrorCode PetscSortIntWithArray_Private(PetscInt *v,PetscInt *V,PetscInt right)
97e5c89e4eSSatish Balay {
98e5c89e4eSSatish Balay   PetscErrorCode ierr;
99e5c89e4eSSatish Balay   PetscInt       i,vl,last,tmp;
100e5c89e4eSSatish Balay 
101e5c89e4eSSatish Balay   PetscFunctionBegin;
102e5c89e4eSSatish Balay   if (right <= 1) {
103e5c89e4eSSatish Balay     if (right == 1) {
104e5c89e4eSSatish Balay       if (v[0] > v[1]) SWAP2(v[0],v[1],V[0],V[1],tmp);
105e5c89e4eSSatish Balay     }
106e5c89e4eSSatish Balay     PetscFunctionReturn(0);
107e5c89e4eSSatish Balay   }
108e5c89e4eSSatish Balay   SWAP2(v[0],v[right/2],V[0],V[right/2],tmp);
109e5c89e4eSSatish Balay   vl   = v[0];
110e5c89e4eSSatish Balay   last = 0;
111e5c89e4eSSatish Balay   for (i=1; i<=right; i++) {
112e5c89e4eSSatish Balay     if (v[i] < vl) {last++; SWAP2(v[last],v[i],V[last],V[i],tmp);}
113e5c89e4eSSatish Balay   }
114e5c89e4eSSatish Balay   SWAP2(v[0],v[last],V[0],V[last],tmp);
115e5c89e4eSSatish Balay   ierr = PetscSortIntWithArray_Private(v,V,last-1);CHKERRQ(ierr);
116e5c89e4eSSatish Balay   ierr = PetscSortIntWithArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr);
117e5c89e4eSSatish Balay   PetscFunctionReturn(0);
118e5c89e4eSSatish Balay }
119e5c89e4eSSatish Balay 
120e5c89e4eSSatish Balay #undef __FUNCT__
121e5c89e4eSSatish Balay #define __FUNCT__ "PetscSortIntWithArray"
122e5c89e4eSSatish Balay /*@
123e5c89e4eSSatish Balay    PetscSortIntWithArray - Sorts an array of integers in place in increasing order;
124e5c89e4eSSatish Balay        changes a second array to match the sorted first array.
125e5c89e4eSSatish Balay 
126e5c89e4eSSatish Balay    Not Collective
127e5c89e4eSSatish Balay 
128e5c89e4eSSatish Balay    Input Parameters:
129e5c89e4eSSatish Balay +  n  - number of values
130e5c89e4eSSatish Balay .  i  - array of integers
131e5c89e4eSSatish Balay -  I - second array of integers
132e5c89e4eSSatish Balay 
133e5c89e4eSSatish Balay    Level: intermediate
134e5c89e4eSSatish Balay 
135e5c89e4eSSatish Balay    Concepts: sorting^ints with array
136e5c89e4eSSatish Balay 
137e5c89e4eSSatish Balay .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt()
138e5c89e4eSSatish Balay @*/
139b7940d39SSatish Balay PetscErrorCode PETSC_DLLEXPORT PetscSortIntWithArray(PetscInt n,PetscInt i[],PetscInt Ii[])
140e5c89e4eSSatish Balay {
141e5c89e4eSSatish Balay   PetscErrorCode ierr;
142e5c89e4eSSatish Balay   PetscInt       j,k,tmp,ik;
143e5c89e4eSSatish Balay 
144e5c89e4eSSatish Balay   PetscFunctionBegin;
145e5c89e4eSSatish Balay   if (n<8) {
146e5c89e4eSSatish Balay     for (k=0; k<n; k++) {
147e5c89e4eSSatish Balay       ik = i[k];
148e5c89e4eSSatish Balay       for (j=k+1; j<n; j++) {
149e5c89e4eSSatish Balay 	if (ik > i[j]) {
150b7940d39SSatish Balay 	  SWAP2(i[k],i[j],Ii[k],Ii[j],tmp);
151e5c89e4eSSatish Balay 	  ik = i[k];
152e5c89e4eSSatish Balay 	}
153e5c89e4eSSatish Balay       }
154e5c89e4eSSatish Balay     }
155e5c89e4eSSatish Balay   } else {
156b7940d39SSatish Balay     ierr = PetscSortIntWithArray_Private(i,Ii,n-1);CHKERRQ(ierr);
157e5c89e4eSSatish Balay   }
158e5c89e4eSSatish Balay   PetscFunctionReturn(0);
159e5c89e4eSSatish Balay }
160e5c89e4eSSatish Balay 
1614d615ea0SBarry Smith #undef __FUNCT__
1624d615ea0SBarry Smith #define __FUNCT__ "PetscSortMPIIntWithArray_Private"
1634d615ea0SBarry Smith /*
1644d615ea0SBarry Smith    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
1654d615ea0SBarry Smith    Assumes 0 origin for v, number of elements = right+1 (right is index of
1664d615ea0SBarry Smith    right-most member).
1674d615ea0SBarry Smith */
1684d615ea0SBarry Smith static PetscErrorCode PetscSortMPIIntWithArray_Private(PetscMPIInt *v,PetscMPIInt *V,PetscMPIInt right)
1694d615ea0SBarry Smith {
1704d615ea0SBarry Smith   PetscErrorCode ierr;
1714d615ea0SBarry Smith   PetscMPIInt    i,vl,last,tmp;
1724d615ea0SBarry Smith 
1734d615ea0SBarry Smith   PetscFunctionBegin;
1744d615ea0SBarry Smith   if (right <= 1) {
1754d615ea0SBarry Smith     if (right == 1) {
1764d615ea0SBarry Smith       if (v[0] > v[1]) SWAP2(v[0],v[1],V[0],V[1],tmp);
1774d615ea0SBarry Smith     }
1784d615ea0SBarry Smith     PetscFunctionReturn(0);
1794d615ea0SBarry Smith   }
1804d615ea0SBarry Smith   SWAP2(v[0],v[right/2],V[0],V[right/2],tmp);
1814d615ea0SBarry Smith   vl   = v[0];
1824d615ea0SBarry Smith   last = 0;
1834d615ea0SBarry Smith   for (i=1; i<=right; i++) {
1844d615ea0SBarry Smith     if (v[i] < vl) {last++; SWAP2(v[last],v[i],V[last],V[i],tmp);}
1854d615ea0SBarry Smith   }
1864d615ea0SBarry Smith   SWAP2(v[0],v[last],V[0],V[last],tmp);
1874d615ea0SBarry Smith   ierr = PetscSortMPIIntWithArray_Private(v,V,last-1);CHKERRQ(ierr);
1884d615ea0SBarry Smith   ierr = PetscSortMPIIntWithArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr);
1894d615ea0SBarry Smith   PetscFunctionReturn(0);
1904d615ea0SBarry Smith }
1914d615ea0SBarry Smith 
1924d615ea0SBarry Smith #undef __FUNCT__
1934d615ea0SBarry Smith #define __FUNCT__ "PetscSortMPIIntWithArray"
1944d615ea0SBarry Smith /*@
1954d615ea0SBarry Smith    PetscSortMPIIntWithArray - Sorts an array of integers in place in increasing order;
1964d615ea0SBarry Smith        changes a second array to match the sorted first array.
1974d615ea0SBarry Smith 
1984d615ea0SBarry Smith    Not Collective
1994d615ea0SBarry Smith 
2004d615ea0SBarry Smith    Input Parameters:
2014d615ea0SBarry Smith +  n  - number of values
2024d615ea0SBarry Smith .  i  - array of integers
2034d615ea0SBarry Smith -  I - second array of integers
2044d615ea0SBarry Smith 
2054d615ea0SBarry Smith    Level: intermediate
2064d615ea0SBarry Smith 
2074d615ea0SBarry Smith    Concepts: sorting^ints with array
2084d615ea0SBarry Smith 
2094d615ea0SBarry Smith .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt()
2104d615ea0SBarry Smith @*/
2114d615ea0SBarry Smith PetscErrorCode PETSC_DLLEXPORT PetscSortMPIIntWithArray(PetscMPIInt n,PetscMPIInt i[],PetscMPIInt Ii[])
2124d615ea0SBarry Smith {
2134d615ea0SBarry Smith   PetscErrorCode ierr;
2144d615ea0SBarry Smith   PetscMPIInt    j,k,tmp,ik;
2154d615ea0SBarry Smith 
2164d615ea0SBarry Smith   PetscFunctionBegin;
2174d615ea0SBarry Smith   if (n<8) {
2184d615ea0SBarry Smith     for (k=0; k<n; k++) {
2194d615ea0SBarry Smith       ik = i[k];
2204d615ea0SBarry Smith       for (j=k+1; j<n; j++) {
2214d615ea0SBarry Smith 	if (ik > i[j]) {
2224d615ea0SBarry Smith 	  SWAP2(i[k],i[j],Ii[k],Ii[j],tmp);
2234d615ea0SBarry Smith 	  ik = i[k];
2244d615ea0SBarry Smith 	}
2254d615ea0SBarry Smith       }
2264d615ea0SBarry Smith     }
2274d615ea0SBarry Smith   } else {
2284d615ea0SBarry Smith     ierr = PetscSortMPIIntWithArray_Private(i,Ii,n-1);CHKERRQ(ierr);
2294d615ea0SBarry Smith   }
2304d615ea0SBarry Smith   PetscFunctionReturn(0);
2314d615ea0SBarry Smith }
2324d615ea0SBarry Smith 
233e5c89e4eSSatish Balay /* -----------------------------------------------------------------------*/
234e5c89e4eSSatish Balay #define SWAP2IntScalar(a,b,c,d,t,ts) {t=a;a=b;b=t;ts=c;c=d;d=ts;}
235e5c89e4eSSatish Balay 
236e5c89e4eSSatish Balay #undef __FUNCT__
237e5c89e4eSSatish Balay #define __FUNCT__ "PetscSortIntWithScalarArray_Private"
238e5c89e4eSSatish Balay /*
239e5c89e4eSSatish Balay    Modified from PetscSortIntWithArray_Private().
240e5c89e4eSSatish Balay */
241e5c89e4eSSatish Balay static PetscErrorCode PetscSortIntWithScalarArray_Private(PetscInt *v,PetscScalar *V,PetscInt right)
242e5c89e4eSSatish Balay {
243e5c89e4eSSatish Balay   PetscErrorCode ierr;
244e5c89e4eSSatish Balay   PetscInt       i,vl,last,tmp;
245e5c89e4eSSatish Balay   PetscScalar    stmp;
246e5c89e4eSSatish Balay 
247e5c89e4eSSatish Balay   PetscFunctionBegin;
248e5c89e4eSSatish Balay   if (right <= 1) {
249e5c89e4eSSatish Balay     if (right == 1) {
250e5c89e4eSSatish Balay       if (v[0] > v[1]) SWAP2IntScalar(v[0],v[1],V[0],V[1],tmp,stmp);
251e5c89e4eSSatish Balay     }
252e5c89e4eSSatish Balay     PetscFunctionReturn(0);
253e5c89e4eSSatish Balay   }
254e5c89e4eSSatish Balay   SWAP2IntScalar(v[0],v[right/2],V[0],V[right/2],tmp,stmp);
255e5c89e4eSSatish Balay   vl   = v[0];
256e5c89e4eSSatish Balay   last = 0;
257e5c89e4eSSatish Balay   for (i=1; i<=right; i++) {
258e5c89e4eSSatish Balay     if (v[i] < vl) {last++; SWAP2IntScalar(v[last],v[i],V[last],V[i],tmp,stmp);}
259e5c89e4eSSatish Balay   }
260e5c89e4eSSatish Balay   SWAP2IntScalar(v[0],v[last],V[0],V[last],tmp,stmp);
261e5c89e4eSSatish Balay   ierr = PetscSortIntWithScalarArray_Private(v,V,last-1);CHKERRQ(ierr);
262e5c89e4eSSatish Balay   ierr = PetscSortIntWithScalarArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr);
263e5c89e4eSSatish Balay   PetscFunctionReturn(0);
264e5c89e4eSSatish Balay }
265e5c89e4eSSatish Balay 
266e5c89e4eSSatish Balay #undef __FUNCT__
267e5c89e4eSSatish Balay #define __FUNCT__ "PetscSortIntWithScalarArray"
268e5c89e4eSSatish Balay /*@
269e5c89e4eSSatish Balay    PetscSortIntWithScalarArray - Sorts an array of integers in place in increasing order;
270e5c89e4eSSatish Balay        changes a second SCALAR array to match the sorted first INTEGER array.
271e5c89e4eSSatish Balay 
272e5c89e4eSSatish Balay    Not Collective
273e5c89e4eSSatish Balay 
274e5c89e4eSSatish Balay    Input Parameters:
275e5c89e4eSSatish Balay +  n  - number of values
276e5c89e4eSSatish Balay .  i  - array of integers
277e5c89e4eSSatish Balay -  I - second array of scalars
278e5c89e4eSSatish Balay 
279e5c89e4eSSatish Balay    Level: intermediate
280e5c89e4eSSatish Balay 
281e5c89e4eSSatish Balay    Concepts: sorting^ints with array
282e5c89e4eSSatish Balay 
283e5c89e4eSSatish Balay .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
284e5c89e4eSSatish Balay @*/
285b7940d39SSatish Balay PetscErrorCode PETSC_DLLEXPORT PetscSortIntWithScalarArray(PetscInt n,PetscInt i[],PetscScalar Ii[])
286e5c89e4eSSatish Balay {
287e5c89e4eSSatish Balay   PetscErrorCode ierr;
288e5c89e4eSSatish Balay   PetscInt       j,k,tmp,ik;
289e5c89e4eSSatish Balay   PetscScalar    stmp;
290e5c89e4eSSatish Balay 
291e5c89e4eSSatish Balay   PetscFunctionBegin;
292e5c89e4eSSatish Balay   if (n<8) {
293e5c89e4eSSatish Balay     for (k=0; k<n; k++) {
294e5c89e4eSSatish Balay       ik = i[k];
295e5c89e4eSSatish Balay       for (j=k+1; j<n; j++) {
296e5c89e4eSSatish Balay 	if (ik > i[j]) {
297b7940d39SSatish Balay 	  SWAP2IntScalar(i[k],i[j],Ii[k],Ii[j],tmp,stmp);
298e5c89e4eSSatish Balay 	  ik = i[k];
299e5c89e4eSSatish Balay 	}
300e5c89e4eSSatish Balay       }
301e5c89e4eSSatish Balay     }
302e5c89e4eSSatish Balay   } else {
303b7940d39SSatish Balay     ierr = PetscSortIntWithScalarArray_Private(i,Ii,n-1);CHKERRQ(ierr);
304e5c89e4eSSatish Balay   }
305e5c89e4eSSatish Balay   PetscFunctionReturn(0);
306e5c89e4eSSatish Balay }
307e5c89e4eSSatish Balay 
308e5c89e4eSSatish Balay 
309