xref: /petsc/src/sys/utils/sortd.c (revision 6b867d5ac32ed0c728f185df9d084acdf26f70bf)
17d0a6c19SBarry Smith 
2e5c89e4eSSatish Balay /*
3e5c89e4eSSatish Balay    This file contains routines for sorting doubles.  Values are sorted in place.
4e5c89e4eSSatish Balay    These are provided because the general sort routines incur a great deal
5a5b23f4aSJose E. Roman    of overhead in calling the comparison routines.
6e5c89e4eSSatish Balay 
7e5c89e4eSSatish Balay  */
8c6db04a5SJed Brown #include <petscsys.h>                /*I  "petscsys.h"  I*/
939f41f7fSStefano Zampini #include <petsc/private/petscimpl.h>
10e5c89e4eSSatish Balay 
11e5c89e4eSSatish Balay #define SWAP(a,b,t) {t=a;a=b;b=t;}
12e5c89e4eSSatish Balay 
136a7c706bSVaclav Hapla /*@
146a7c706bSVaclav Hapla    PetscSortedReal - Determines whether the array is sorted.
156a7c706bSVaclav Hapla 
166a7c706bSVaclav Hapla    Not Collective
176a7c706bSVaclav Hapla 
186a7c706bSVaclav Hapla    Input Parameters:
196a7c706bSVaclav Hapla +  n  - number of values
206a7c706bSVaclav Hapla -  X  - array of integers
216a7c706bSVaclav Hapla 
226a7c706bSVaclav Hapla    Output Parameters:
236a7c706bSVaclav Hapla .  sorted - flag whether the array is sorted
246a7c706bSVaclav Hapla 
256a7c706bSVaclav Hapla    Level: intermediate
266a7c706bSVaclav Hapla 
276a7c706bSVaclav Hapla .seealso: PetscSortReal(), PetscSortedInt(), PetscSortedMPIInt()
286a7c706bSVaclav Hapla @*/
296a7c706bSVaclav Hapla PetscErrorCode  PetscSortedReal(PetscInt n,const PetscReal X[],PetscBool *sorted)
306a7c706bSVaclav Hapla {
316a7c706bSVaclav Hapla   PetscFunctionBegin;
326a7c706bSVaclav Hapla   PetscSorted(n,X,*sorted);
336a7c706bSVaclav Hapla   PetscFunctionReturn(0);
346a7c706bSVaclav Hapla }
356a7c706bSVaclav Hapla 
36e5c89e4eSSatish Balay /* A simple version of quicksort; taken from Kernighan and Ritchie, page 87 */
37e5c89e4eSSatish Balay static PetscErrorCode PetscSortReal_Private(PetscReal *v,PetscInt right)
38e5c89e4eSSatish Balay {
39e5c89e4eSSatish Balay   PetscInt  i,last;
40e5c89e4eSSatish Balay   PetscReal vl,tmp;
41e5c89e4eSSatish Balay 
42e5c89e4eSSatish Balay   PetscFunctionBegin;
43e5c89e4eSSatish Balay   if (right <= 1) {
44e5c89e4eSSatish Balay     if (right == 1) {
45e5c89e4eSSatish Balay       if (v[0] > v[1]) SWAP(v[0],v[1],tmp);
46e5c89e4eSSatish Balay     }
47e5c89e4eSSatish Balay     PetscFunctionReturn(0);
48e5c89e4eSSatish Balay   }
49e5c89e4eSSatish Balay   SWAP(v[0],v[right/2],tmp);
50e5c89e4eSSatish Balay   vl   = v[0];
51e5c89e4eSSatish Balay   last = 0;
52e5c89e4eSSatish Balay   for (i=1; i<=right; i++) {
53e5c89e4eSSatish Balay     if (v[i] < vl) {last++; SWAP(v[last],v[i],tmp);}
54e5c89e4eSSatish Balay   }
55e5c89e4eSSatish Balay   SWAP(v[0],v[last],tmp);
56e5c89e4eSSatish Balay   PetscSortReal_Private(v,last-1);
57e5c89e4eSSatish Balay   PetscSortReal_Private(v+last+1,right-(last+1));
58e5c89e4eSSatish Balay   PetscFunctionReturn(0);
59e5c89e4eSSatish Balay }
60e5c89e4eSSatish Balay 
61e5c89e4eSSatish Balay /*@
62e5c89e4eSSatish Balay    PetscSortReal - Sorts an array of doubles in place in increasing order.
63e5c89e4eSSatish Balay 
64e5c89e4eSSatish Balay    Not Collective
65e5c89e4eSSatish Balay 
66e5c89e4eSSatish Balay    Input Parameters:
67e5c89e4eSSatish Balay +  n  - number of values
68e5c89e4eSSatish Balay -  v  - array of doubles
69e5c89e4eSSatish Balay 
70676f2a66SJacob Faibussowitsch    Notes:
71676f2a66SJacob Faibussowitsch    This function serves as an alternative to PetscRealSortSemiOrdered(), and may perform faster especially if the array
72a5b23f4aSJose E. Roman    is completely random. There are exceptions to this and so it is __highly__ recommended that the user benchmark their
73676f2a66SJacob Faibussowitsch    code to see which routine is fastest.
74676f2a66SJacob Faibussowitsch 
75e5c89e4eSSatish Balay    Level: intermediate
76e5c89e4eSSatish Balay 
77676f2a66SJacob Faibussowitsch .seealso: PetscRealSortSemiOrdered(), PetscSortInt(), PetscSortRealWithPermutation(), PetscSortRealWithArrayInt()
78e5c89e4eSSatish Balay @*/
797087cfbeSBarry Smith PetscErrorCode  PetscSortReal(PetscInt n,PetscReal v[])
80e5c89e4eSSatish Balay {
81e5c89e4eSSatish Balay   PetscInt  j,k;
82e5c89e4eSSatish Balay   PetscReal tmp,vk;
83e5c89e4eSSatish Balay 
84e5c89e4eSSatish Balay   PetscFunctionBegin;
8539f41f7fSStefano Zampini   PetscValidPointer(v,2);
86e5c89e4eSSatish Balay   if (n<8) {
87e5c89e4eSSatish Balay     for (k=0; k<n; k++) {
88e5c89e4eSSatish Balay       vk = v[k];
89e5c89e4eSSatish Balay       for (j=k+1; j<n; j++) {
90e5c89e4eSSatish Balay         if (vk > v[j]) {
91e5c89e4eSSatish Balay           SWAP(v[k],v[j],tmp);
92e5c89e4eSSatish Balay           vk = v[k];
93e5c89e4eSSatish Balay         }
94e5c89e4eSSatish Balay       }
95e5c89e4eSSatish Balay     }
96a297a907SKarl Rupp   } else PetscSortReal_Private(v,n-1);
97e5c89e4eSSatish Balay   PetscFunctionReturn(0);
98e5c89e4eSSatish Balay }
99e5c89e4eSSatish Balay 
10039f41f7fSStefano Zampini #define SWAP2ri(a,b,c,d,rt,it) {rt=a;a=b;b=rt;it=c;c=d;d=it;}
10139f41f7fSStefano Zampini 
10239f41f7fSStefano Zampini /* modified from PetscSortIntWithArray_Private */
10339f41f7fSStefano Zampini static PetscErrorCode PetscSortRealWithArrayInt_Private(PetscReal *v,PetscInt *V,PetscInt right)
10439f41f7fSStefano Zampini {
10539f41f7fSStefano Zampini   PetscErrorCode ierr;
10639f41f7fSStefano Zampini   PetscInt       i,last,itmp;
10739f41f7fSStefano Zampini   PetscReal      rvl,rtmp;
10839f41f7fSStefano Zampini 
10939f41f7fSStefano Zampini   PetscFunctionBegin;
11039f41f7fSStefano Zampini   if (right <= 1) {
11139f41f7fSStefano Zampini     if (right == 1) {
11239f41f7fSStefano Zampini       if (v[0] > v[1]) SWAP2ri(v[0],v[1],V[0],V[1],rtmp,itmp);
11339f41f7fSStefano Zampini     }
11439f41f7fSStefano Zampini     PetscFunctionReturn(0);
11539f41f7fSStefano Zampini   }
11639f41f7fSStefano Zampini   SWAP2ri(v[0],v[right/2],V[0],V[right/2],rtmp,itmp);
11739f41f7fSStefano Zampini   rvl  = v[0];
11839f41f7fSStefano Zampini   last = 0;
11939f41f7fSStefano Zampini   for (i=1; i<=right; i++) {
12039f41f7fSStefano Zampini     if (v[i] < rvl) {last++; SWAP2ri(v[last],v[i],V[last],V[i],rtmp,itmp);}
12139f41f7fSStefano Zampini   }
12239f41f7fSStefano Zampini   SWAP2ri(v[0],v[last],V[0],V[last],rtmp,itmp);
12339f41f7fSStefano Zampini   ierr = PetscSortRealWithArrayInt_Private(v,V,last-1);CHKERRQ(ierr);
12439f41f7fSStefano Zampini   ierr = PetscSortRealWithArrayInt_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr);
12539f41f7fSStefano Zampini   PetscFunctionReturn(0);
12639f41f7fSStefano Zampini }
12739f41f7fSStefano Zampini /*@
12839f41f7fSStefano Zampini    PetscSortRealWithArrayInt - Sorts an array of PetscReal in place in increasing order;
12939f41f7fSStefano Zampini        changes a second PetscInt array to match the sorted first array.
13039f41f7fSStefano Zampini 
13139f41f7fSStefano Zampini    Not Collective
13239f41f7fSStefano Zampini 
13339f41f7fSStefano Zampini    Input Parameters:
13439f41f7fSStefano Zampini +  n  - number of values
13539f41f7fSStefano Zampini .  i  - array of integers
13639f41f7fSStefano Zampini -  I - second array of integers
13739f41f7fSStefano Zampini 
13839f41f7fSStefano Zampini    Level: intermediate
13939f41f7fSStefano Zampini 
14039f41f7fSStefano Zampini .seealso: PetscSortReal()
14139f41f7fSStefano Zampini @*/
14239f41f7fSStefano Zampini PetscErrorCode  PetscSortRealWithArrayInt(PetscInt n,PetscReal r[],PetscInt Ii[])
14339f41f7fSStefano Zampini {
14439f41f7fSStefano Zampini   PetscErrorCode ierr;
14539f41f7fSStefano Zampini   PetscInt       j,k,itmp;
14639f41f7fSStefano Zampini   PetscReal      rk,rtmp;
14739f41f7fSStefano Zampini 
14839f41f7fSStefano Zampini   PetscFunctionBegin;
14939f41f7fSStefano Zampini   PetscValidPointer(r,2);
15039f41f7fSStefano Zampini   PetscValidPointer(Ii,3);
15139f41f7fSStefano Zampini   if (n<8) {
15239f41f7fSStefano Zampini     for (k=0; k<n; k++) {
15339f41f7fSStefano Zampini       rk = r[k];
15439f41f7fSStefano Zampini       for (j=k+1; j<n; j++) {
15539f41f7fSStefano Zampini         if (rk > r[j]) {
15639f41f7fSStefano Zampini           SWAP2ri(r[k],r[j],Ii[k],Ii[j],rtmp,itmp);
15739f41f7fSStefano Zampini           rk = r[k];
15839f41f7fSStefano Zampini         }
15939f41f7fSStefano Zampini       }
16039f41f7fSStefano Zampini     }
16139f41f7fSStefano Zampini   } else {
16239f41f7fSStefano Zampini     ierr = PetscSortRealWithArrayInt_Private(r,Ii,n-1);CHKERRQ(ierr);
16339f41f7fSStefano Zampini   }
16439f41f7fSStefano Zampini   PetscFunctionReturn(0);
16539f41f7fSStefano Zampini }
16639f41f7fSStefano Zampini 
16739f41f7fSStefano Zampini /*@
16839f41f7fSStefano Zampini   PetscFindReal - Finds a PetscReal in a sorted array of PetscReals
16939f41f7fSStefano Zampini 
17039f41f7fSStefano Zampini    Not Collective
17139f41f7fSStefano Zampini 
17239f41f7fSStefano Zampini    Input Parameters:
17339f41f7fSStefano Zampini +  key - the value to locate
17439f41f7fSStefano Zampini .  n   - number of values in the array
17539f41f7fSStefano Zampini .  ii  - array of values
17639f41f7fSStefano Zampini -  eps - tolerance used to compare
17739f41f7fSStefano Zampini 
17839f41f7fSStefano Zampini    Output Parameter:
17939f41f7fSStefano Zampini .  loc - the location if found, otherwise -(slot+1) where slot is the place the value would go
18039f41f7fSStefano Zampini 
18139f41f7fSStefano Zampini    Level: intermediate
18239f41f7fSStefano Zampini 
18339f41f7fSStefano Zampini .seealso: PetscSortReal(), PetscSortRealWithArrayInt()
18439f41f7fSStefano Zampini @*/
18539f41f7fSStefano Zampini PetscErrorCode PetscFindReal(PetscReal key, PetscInt n, const PetscReal t[], PetscReal eps, PetscInt *loc)
18639f41f7fSStefano Zampini {
18739f41f7fSStefano Zampini   PetscInt lo = 0,hi = n;
18839f41f7fSStefano Zampini 
18939f41f7fSStefano Zampini   PetscFunctionBegin;
190064a246eSJacob Faibussowitsch   PetscValidPointer(loc,5);
19139f41f7fSStefano Zampini   if (!n) {*loc = -1; PetscFunctionReturn(0);}
19239f41f7fSStefano Zampini   PetscValidPointer(t,3);
1936a7c706bSVaclav Hapla   PetscCheckSorted(n,t);
19439f41f7fSStefano Zampini   while (hi - lo > 1) {
19539f41f7fSStefano Zampini     PetscInt mid = lo + (hi - lo)/2;
19639f41f7fSStefano Zampini     if (key < t[mid]) hi = mid;
19739f41f7fSStefano Zampini     else              lo = mid;
19839f41f7fSStefano Zampini   }
19939f41f7fSStefano Zampini   *loc = (PetscAbsReal(key - t[lo]) < eps) ? lo : -(lo + (key > t[lo]) + 1);
20039f41f7fSStefano Zampini   PetscFunctionReturn(0);
20139f41f7fSStefano Zampini }
202745b41b2SMatthew G. Knepley 
203745b41b2SMatthew G. Knepley /*@
204745b41b2SMatthew G. Knepley    PetscSortRemoveDupsReal - Sorts an array of doubles in place in increasing order removes all duplicate entries
205745b41b2SMatthew G. Knepley 
206745b41b2SMatthew G. Knepley    Not Collective
207745b41b2SMatthew G. Knepley 
208745b41b2SMatthew G. Knepley    Input Parameters:
209745b41b2SMatthew G. Knepley +  n  - number of values
210745b41b2SMatthew G. Knepley -  v  - array of doubles
211745b41b2SMatthew G. Knepley 
212745b41b2SMatthew G. Knepley    Output Parameter:
213745b41b2SMatthew G. Knepley .  n - number of non-redundant values
214745b41b2SMatthew G. Knepley 
215745b41b2SMatthew G. Knepley    Level: intermediate
216745b41b2SMatthew G. Knepley 
217745b41b2SMatthew G. Knepley .seealso: PetscSortReal(), PetscSortRemoveDupsInt()
218745b41b2SMatthew G. Knepley @*/
219745b41b2SMatthew G. Knepley PetscErrorCode  PetscSortRemoveDupsReal(PetscInt *n,PetscReal v[])
220745b41b2SMatthew G. Knepley {
221745b41b2SMatthew G. Knepley   PetscErrorCode ierr;
222745b41b2SMatthew G. Knepley   PetscInt       i,s = 0,N = *n, b = 0;
223745b41b2SMatthew G. Knepley 
224745b41b2SMatthew G. Knepley   PetscFunctionBegin;
225745b41b2SMatthew G. Knepley   ierr = PetscSortReal(N,v);CHKERRQ(ierr);
226745b41b2SMatthew G. Knepley   for (i=0; i<N-1; i++) {
227745b41b2SMatthew G. Knepley     if (v[b+s+1] != v[b]) {
228745b41b2SMatthew G. Knepley       v[b+1] = v[b+s+1]; b++;
229745b41b2SMatthew G. Knepley     } else s++;
230745b41b2SMatthew G. Knepley   }
231745b41b2SMatthew G. Knepley   *n = N - s;
232745b41b2SMatthew G. Knepley   PetscFunctionReturn(0);
233745b41b2SMatthew G. Knepley }
234745b41b2SMatthew G. Knepley 
235d97c5584SHong Zhang /*@
236021822bcSHong Zhang    PetscSortSplit - Quick-sort split of an array of PetscScalars in place.
237d97c5584SHong Zhang 
238d97c5584SHong Zhang    Not Collective
239d97c5584SHong Zhang 
240d97c5584SHong Zhang    Input Parameters:
241d97c5584SHong Zhang +  ncut  - splitig index
242*6b867d5aSJose E. Roman -  n     - number of values to sort
243d97c5584SHong Zhang 
244*6b867d5aSJose E. Roman    Input/Output Parameters:
245*6b867d5aSJose E. Roman +  a     - array of values, on output the values are permuted such that its elements satisfy:
246d97c5584SHong Zhang            abs(a[i]) >= abs(a[ncut-1]) for i < ncut and
247d97c5584SHong Zhang            abs(a[i]) <= abs(a[ncut-1]) for i >= ncut
248*6b867d5aSJose E. Roman -  idx   - index for array a, on output permuted accordingly
249d97c5584SHong Zhang 
250d97c5584SHong Zhang    Level: intermediate
251d97c5584SHong Zhang 
252d97c5584SHong Zhang .seealso: PetscSortInt(), PetscSortRealWithPermutation()
253d97c5584SHong Zhang @*/
2547087cfbeSBarry Smith PetscErrorCode  PetscSortSplit(PetscInt ncut,PetscInt n,PetscScalar a[],PetscInt idx[])
255d97c5584SHong Zhang {
256d97c5584SHong Zhang   PetscInt    i,mid,last,itmp,j,first;
257d97c5584SHong Zhang   PetscScalar d,tmp;
258d97c5584SHong Zhang   PetscReal   abskey;
259d97c5584SHong Zhang 
260d97c5584SHong Zhang   PetscFunctionBegin;
261d97c5584SHong Zhang   first = 0;
262d97c5584SHong Zhang   last  = n-1;
263d97c5584SHong Zhang   if (ncut < first || ncut > last) PetscFunctionReturn(0);
264d97c5584SHong Zhang 
265d97c5584SHong Zhang   while (1) {
266d97c5584SHong Zhang     mid    = first;
2672a274a78SSatish Balay     d      = a[mid];
2682a274a78SSatish Balay     abskey = PetscAbsScalar(d);
269d97c5584SHong Zhang     i      = last;
270d97c5584SHong Zhang     for (j = first + 1; j <= i; ++j) {
2712a274a78SSatish Balay       d = a[j];
2722a274a78SSatish Balay       if (PetscAbsScalar(d) >= abskey) {
273d97c5584SHong Zhang         ++mid;
274d97c5584SHong Zhang         /* interchange */
275d97c5584SHong Zhang         tmp = a[mid];  itmp = idx[mid];
276d97c5584SHong Zhang         a[mid] = a[j]; idx[mid] = idx[j];
277d97c5584SHong Zhang         a[j] = tmp;    idx[j] = itmp;
278d97c5584SHong Zhang       }
279d97c5584SHong Zhang     }
280d97c5584SHong Zhang 
281d97c5584SHong Zhang     /* interchange */
282d97c5584SHong Zhang     tmp = a[mid];      itmp = idx[mid];
283d97c5584SHong Zhang     a[mid] = a[first]; idx[mid] = idx[first];
284d97c5584SHong Zhang     a[first] = tmp;    idx[first] = itmp;
285d97c5584SHong Zhang 
286d97c5584SHong Zhang     /* test for while loop */
287a297a907SKarl Rupp     if (mid == ncut) break;
288a297a907SKarl Rupp     else if (mid > ncut) last = mid - 1;
289a297a907SKarl Rupp     else first = mid + 1;
290d97c5584SHong Zhang   }
291d97c5584SHong Zhang   PetscFunctionReturn(0);
292d97c5584SHong Zhang }
293021822bcSHong Zhang 
294021822bcSHong Zhang /*@
295021822bcSHong Zhang    PetscSortSplitReal - Quick-sort split of an array of PetscReals in place.
296021822bcSHong Zhang 
297021822bcSHong Zhang    Not Collective
298021822bcSHong Zhang 
299021822bcSHong Zhang    Input Parameters:
300021822bcSHong Zhang +  ncut  - splitig index
301*6b867d5aSJose E. Roman -  n     - number of values to sort
302021822bcSHong Zhang 
303*6b867d5aSJose E. Roman    Input/Output Parameters:
304*6b867d5aSJose E. Roman +  a     - array of values, on output the values are permuted such that its elements satisfy:
305021822bcSHong Zhang            abs(a[i]) >= abs(a[ncut-1]) for i < ncut and
306021822bcSHong Zhang            abs(a[i]) <= abs(a[ncut-1]) for i >= ncut
307*6b867d5aSJose E. Roman -  idx   - index for array a, on output permuted accordingly
308021822bcSHong Zhang 
309021822bcSHong Zhang    Level: intermediate
310021822bcSHong Zhang 
311021822bcSHong Zhang .seealso: PetscSortInt(), PetscSortRealWithPermutation()
312021822bcSHong Zhang @*/
3137087cfbeSBarry Smith PetscErrorCode  PetscSortSplitReal(PetscInt ncut,PetscInt n,PetscReal a[],PetscInt idx[])
314021822bcSHong Zhang {
315021822bcSHong Zhang   PetscInt  i,mid,last,itmp,j,first;
316021822bcSHong Zhang   PetscReal d,tmp;
317021822bcSHong Zhang   PetscReal abskey;
318021822bcSHong Zhang 
319021822bcSHong Zhang   PetscFunctionBegin;
320021822bcSHong Zhang   first = 0;
321021822bcSHong Zhang   last  = n-1;
322021822bcSHong Zhang   if (ncut < first || ncut > last) PetscFunctionReturn(0);
323021822bcSHong Zhang 
324021822bcSHong Zhang   while (1) {
325021822bcSHong Zhang     mid    = first;
3262a274a78SSatish Balay     d      = a[mid];
3272a274a78SSatish Balay     abskey = PetscAbsReal(d);
328021822bcSHong Zhang     i      = last;
329021822bcSHong Zhang     for (j = first + 1; j <= i; ++j) {
3302a274a78SSatish Balay       d = a[j];
3312a274a78SSatish Balay       if (PetscAbsReal(d) >= abskey) {
332021822bcSHong Zhang         ++mid;
333021822bcSHong Zhang         /* interchange */
334021822bcSHong Zhang         tmp = a[mid];  itmp = idx[mid];
335021822bcSHong Zhang         a[mid] = a[j]; idx[mid] = idx[j];
336021822bcSHong Zhang         a[j] = tmp;    idx[j] = itmp;
337021822bcSHong Zhang       }
338021822bcSHong Zhang     }
339021822bcSHong Zhang 
340021822bcSHong Zhang     /* interchange */
341021822bcSHong Zhang     tmp = a[mid];      itmp = idx[mid];
342021822bcSHong Zhang     a[mid] = a[first]; idx[mid] = idx[first];
343021822bcSHong Zhang     a[first] = tmp;    idx[first] = itmp;
344021822bcSHong Zhang 
345021822bcSHong Zhang     /* test for while loop */
346a297a907SKarl Rupp     if (mid == ncut) break;
347a297a907SKarl Rupp     else if (mid > ncut) last = mid - 1;
348a297a907SKarl Rupp     else first = mid + 1;
349021822bcSHong Zhang   }
350021822bcSHong Zhang   PetscFunctionReturn(0);
351021822bcSHong Zhang }
352