xref: /petsc/src/sys/utils/sortd.c (revision 064a246e8b5c1f87897a54b4a9ec05181ea08258)
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
5e5c89e4eSSatish Balay    of overhead in calling the comparision 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
72676f2a66SJacob Faibussowitsch    is completely random. There are exceptions to this and so it is __highly__ recomended 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;
190*064a246eSJacob 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
242d97c5584SHong Zhang .  n     - number of values to sort
243d97c5584SHong Zhang .  a     - array of values
244d97c5584SHong Zhang -  idx   - index for array a
245d97c5584SHong Zhang 
246d97c5584SHong Zhang    Output Parameters:
247d97c5584SHong Zhang +  a     - permuted array of values such that its elements satisfy:
248d97c5584SHong Zhang            abs(a[i]) >= abs(a[ncut-1]) for i < ncut and
249d97c5584SHong Zhang            abs(a[i]) <= abs(a[ncut-1]) for i >= ncut
250d97c5584SHong Zhang -  idx   - permuted index of array a
251d97c5584SHong Zhang 
252d97c5584SHong Zhang    Level: intermediate
253d97c5584SHong Zhang 
254d97c5584SHong Zhang .seealso: PetscSortInt(), PetscSortRealWithPermutation()
255d97c5584SHong Zhang @*/
2567087cfbeSBarry Smith PetscErrorCode  PetscSortSplit(PetscInt ncut,PetscInt n,PetscScalar a[],PetscInt idx[])
257d97c5584SHong Zhang {
258d97c5584SHong Zhang   PetscInt    i,mid,last,itmp,j,first;
259d97c5584SHong Zhang   PetscScalar d,tmp;
260d97c5584SHong Zhang   PetscReal   abskey;
261d97c5584SHong Zhang 
262d97c5584SHong Zhang   PetscFunctionBegin;
263d97c5584SHong Zhang   first = 0;
264d97c5584SHong Zhang   last  = n-1;
265d97c5584SHong Zhang   if (ncut < first || ncut > last) PetscFunctionReturn(0);
266d97c5584SHong Zhang 
267d97c5584SHong Zhang   while (1) {
268d97c5584SHong Zhang     mid    = first;
2692a274a78SSatish Balay     d      = a[mid];
2702a274a78SSatish Balay     abskey = PetscAbsScalar(d);
271d97c5584SHong Zhang     i      = last;
272d97c5584SHong Zhang     for (j = first + 1; j <= i; ++j) {
2732a274a78SSatish Balay       d = a[j];
2742a274a78SSatish Balay       if (PetscAbsScalar(d) >= abskey) {
275d97c5584SHong Zhang         ++mid;
276d97c5584SHong Zhang         /* interchange */
277d97c5584SHong Zhang         tmp = a[mid];  itmp = idx[mid];
278d97c5584SHong Zhang         a[mid] = a[j]; idx[mid] = idx[j];
279d97c5584SHong Zhang         a[j] = tmp;    idx[j] = itmp;
280d97c5584SHong Zhang       }
281d97c5584SHong Zhang     }
282d97c5584SHong Zhang 
283d97c5584SHong Zhang     /* interchange */
284d97c5584SHong Zhang     tmp = a[mid];      itmp = idx[mid];
285d97c5584SHong Zhang     a[mid] = a[first]; idx[mid] = idx[first];
286d97c5584SHong Zhang     a[first] = tmp;    idx[first] = itmp;
287d97c5584SHong Zhang 
288d97c5584SHong Zhang     /* test for while loop */
289a297a907SKarl Rupp     if (mid == ncut) break;
290a297a907SKarl Rupp     else if (mid > ncut) last = mid - 1;
291a297a907SKarl Rupp     else first = mid + 1;
292d97c5584SHong Zhang   }
293d97c5584SHong Zhang   PetscFunctionReturn(0);
294d97c5584SHong Zhang }
295021822bcSHong Zhang 
296021822bcSHong Zhang /*@
297021822bcSHong Zhang    PetscSortSplitReal - Quick-sort split of an array of PetscReals in place.
298021822bcSHong Zhang 
299021822bcSHong Zhang    Not Collective
300021822bcSHong Zhang 
301021822bcSHong Zhang    Input Parameters:
302021822bcSHong Zhang +  ncut  - splitig index
303021822bcSHong Zhang .  n     - number of values to sort
304021822bcSHong Zhang .  a     - array of values in PetscReal
305021822bcSHong Zhang -  idx   - index for array a
306021822bcSHong Zhang 
307021822bcSHong Zhang    Output Parameters:
308021822bcSHong Zhang +  a     - permuted array of real values such that its elements satisfy:
309021822bcSHong Zhang            abs(a[i]) >= abs(a[ncut-1]) for i < ncut and
310021822bcSHong Zhang            abs(a[i]) <= abs(a[ncut-1]) for i >= ncut
311021822bcSHong Zhang -  idx   - permuted index of array a
312021822bcSHong Zhang 
313021822bcSHong Zhang    Level: intermediate
314021822bcSHong Zhang 
315021822bcSHong Zhang .seealso: PetscSortInt(), PetscSortRealWithPermutation()
316021822bcSHong Zhang @*/
3177087cfbeSBarry Smith PetscErrorCode  PetscSortSplitReal(PetscInt ncut,PetscInt n,PetscReal a[],PetscInt idx[])
318021822bcSHong Zhang {
319021822bcSHong Zhang   PetscInt  i,mid,last,itmp,j,first;
320021822bcSHong Zhang   PetscReal d,tmp;
321021822bcSHong Zhang   PetscReal abskey;
322021822bcSHong Zhang 
323021822bcSHong Zhang   PetscFunctionBegin;
324021822bcSHong Zhang   first = 0;
325021822bcSHong Zhang   last  = n-1;
326021822bcSHong Zhang   if (ncut < first || ncut > last) PetscFunctionReturn(0);
327021822bcSHong Zhang 
328021822bcSHong Zhang   while (1) {
329021822bcSHong Zhang     mid    = first;
3302a274a78SSatish Balay     d      = a[mid];
3312a274a78SSatish Balay     abskey = PetscAbsReal(d);
332021822bcSHong Zhang     i      = last;
333021822bcSHong Zhang     for (j = first + 1; j <= i; ++j) {
3342a274a78SSatish Balay       d = a[j];
3352a274a78SSatish Balay       if (PetscAbsReal(d) >= abskey) {
336021822bcSHong Zhang         ++mid;
337021822bcSHong Zhang         /* interchange */
338021822bcSHong Zhang         tmp = a[mid];  itmp = idx[mid];
339021822bcSHong Zhang         a[mid] = a[j]; idx[mid] = idx[j];
340021822bcSHong Zhang         a[j] = tmp;    idx[j] = itmp;
341021822bcSHong Zhang       }
342021822bcSHong Zhang     }
343021822bcSHong Zhang 
344021822bcSHong Zhang     /* interchange */
345021822bcSHong Zhang     tmp = a[mid];      itmp = idx[mid];
346021822bcSHong Zhang     a[mid] = a[first]; idx[mid] = idx[first];
347021822bcSHong Zhang     a[first] = tmp;    idx[first] = itmp;
348021822bcSHong Zhang 
349021822bcSHong Zhang     /* test for while loop */
350a297a907SKarl Rupp     if (mid == ncut) break;
351a297a907SKarl Rupp     else if (mid > ncut) last = mid - 1;
352a297a907SKarl Rupp     else first = mid + 1;
353021822bcSHong Zhang   }
354021822bcSHong Zhang   PetscFunctionReturn(0);
355021822bcSHong Zhang }
356