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