OpendTect  6.3
sorting.h
Go to the documentation of this file.
1 #pragma once
2 
3 /*+
4 ________________________________________________________________________
5 
6  (C) dGB Beheer B.V.; (LICENSE) http://opendtect.org/OpendTect_license.txt
7  Author: A.H. Bril
8  Date: 19-4-2000
9  Contents: Array sorting
10 ________________________________________________________________________
11 
12 -*/
13 
14 #include "algomod.h"
15 #include "gendefs.h"
16 #include "ptrman.h"
17 #include "thread.h"
18 #include "paralleltask.h"
19 
20 
21 #define mDoSort(extra_var,extra_action,sztype) \
22 { \
23  T tmp; extra_var; \
24  for ( sztype d=sz/2; d>0; d=d/2 ) \
25  for ( sztype i=d; i<sz; i++ ) \
26  for ( sztype j=i-d; j>=0 && arr[j]>arr[j+d]; j-=d ) \
27  { \
28  tmp = arr[j]; arr[j] = arr[j+d]; arr[j+d] = tmp; \
29  extra_action; \
30  } \
31 }
32 
34 template <class T,class I>
35 inline void sort_array( T* arr, I sz )
36 mDoSort(,,I)
37 
38 
39 template <class T, class IT,class I>
40 inline void sort_coupled( T* arr, IT* idxs, I sz )
41 mDoSort(IT itmp,itmp = idxs[j]; idxs[j] = idxs[j+d]; idxs[j+d] = itmp,I)
42 
43 #undef mDoSort
44 #define mDoSort(extra_var,extra_action,sztype) \
45 { \
46  extra_var; \
47  for ( sztype d=sz/2; d>0; d=d/2 ) \
48  for ( sztype i=d; i<sz; i++ ) \
49  for ( sztype j=i-d; j>=0 && arr[j]>arr[j+d]; j-=d ) \
50  { \
51  Swap( arr[j], arr[j+d] ); \
52  extra_action; \
53  } \
54 }
55 
57 template <class T>
58 inline void sort_idxabl( T& arr, int sz )
59 mDoSort(,,int)
60 
61 
62 template <class T, class IT>
63 inline void sort_idxabl_coupled( T& arr, IT* idxs, int sz )
64 mDoSort(IT itmp,itmp = idxs[j]; idxs[j] = idxs[j+d]; idxs[j+d] = itmp,int)
65 #undef mDoSort
66 
67 
69 template <class T,class I>
70 inline bool duplicate_sort( T* arr, I sz, int maxnrvals )
71 {
72  TypeSet<T> vals;
73  TypeSet<int> count;
74  for ( I idx=0; idx<sz; ++idx )
75  {
76  const int vidx = vals.indexOf( arr[idx] );
77  if ( vidx<0 )
78  {
79  if ( vals.size()>maxnrvals )
80  {
81  return false;
82  }
83 
84  count += 1;
85  vals += arr[idx];
86  }
87  else
88  count[vidx] += 1;
89  }
90 
91  const int vsize = mCast(int,vals.size());
92  TypeSet<int> idxs;
93  for ( int idx=0; idx<vsize; idx++ )
94  idxs += idx;
95  sort_coupled( vals.arr(), idxs.arr(), vsize );
96 
97  I index = -1;
98  for ( int idx=0; idx<vsize; ++idx )
99  {
100  for ( int idy=count[idxs[idx]]-1; idy>=0; --idy )
101  arr[++index] = vals[idx];
102  }
103 
104  return true;
105 }
106 
107 
117 template <class T>
119 {
120 public:
121  ParallelSorter(T* vals, int sz);
122  ParallelSorter(T* vals, int* idxs, int sz);
123 protected:
124  od_int64 nrIterations() const { return nrvals_; }
125 
126  int minThreadSize() const { return 10000; }
127  bool doPrepare(int);
128  bool doFinish(bool);
129  bool doWork(od_int64,od_int64,int);
130  static bool mergeLists(const T* vals, T* res,
131  int start0,int start1,int start2,
132  int stop, int& totalsz );
133  od_int64 nrDone() const { return totalnr_; }
134 
135  T* vals_;
137 
138  int* idxs_;
140  T* buf_;
141 
142  const int nrvals_;
143  int totalnr_;
144 
148 
150 };
151 
152 
153 #define NSMALL 7
154 #define FM 7875
155 #define FA 211
156 #define FC 1663
157 #define NSTACK 50
158 
159 mExtern(Algo) Threads::Atomic<int> partsortglobalseed;
160 
161 inline float getPartSortSeed()
162 {
163  const int localseed = (partsortglobalseed * FA + FC) % FM;
164 
165  //This is not really atomic, so a MT environment may alter the
166  //global seed, but who cares as it is a seed, and should be
167  //a random number
168 
169  partsortglobalseed = localseed;
170 
171  return (float) localseed;
172 }
173 
174 
175 template <class T,class I> inline
176 void partSort( T* arr, I istart, I istop,
177  I* jstart, I* jstop )
178 {
179  I ipivot, ileft, iright;
180  T pivotval, tmp;
181 
182  const float localseed = getPartSortSeed();
183 
184  ipivot = (int)(istart + (istop-istart) * (float)localseed / (float)FM + .5);
185  if ( ipivot < istart ) ipivot = istart;
186  if ( ipivot > istop ) ipivot = istop;
187  pivotval = arr[ipivot];
188 
189  for ( ileft=istart, iright=istop; ; )
190  {
191  while ( arr[ileft] <=pivotval && ileft<istop ) ileft++;
192  while ( arr[iright]>=pivotval && iright>istart ) iright--;
193  if ( ileft < iright )
194  {
195  tmp = arr[ileft];
196  arr[ileft++] = arr[iright];
197  arr[iright--] = tmp;
198  }
199  else break;
200  }
201 
202  if ( ileft < ipivot )
203  {
204  tmp = arr[ileft];
205  arr[ileft++] = arr[ipivot];
206  arr[ipivot] = tmp;
207  }
208  else if ( ipivot < iright )
209  {
210  tmp = arr[iright];
211  arr[iright--] = arr[ipivot];
212  arr[ipivot] = tmp;
213  }
214 
215  *jstart = iright;
216  *jstop = ileft;
217 }
218 
219 
220 template <class T, class I> inline
221 void insertionSort( T* arr, I istart, I istop )
222 {
223  I i, j;
224  T arr_i;
225 
226  for ( i=istart+1; i<=istop; i++ )
227  {
228  for ( arr_i=arr[i],j=i; j>istart && arr[j-1]>arr_i; j-- )
229  arr[j] = arr[j-1];
230  arr[j] = arr_i;
231  }
232 }
233 
234 
235 template <class T,class I> inline
236 void sortFor( T* arr, I sz, I itarget )
240 {
241  I j, k, p = 0, q = sz-1;
242 
243  while( q - p > NSMALL )
244  {
245  partSort( arr, p, q, &j, &k );
246 
247  if ( itarget <= j ) q = j;
248  else if ( itarget >= k ) p = k;
249  else return;
250  }
251 
252  insertionSort( arr, p, q );
253 }
254 
255 
256 template <class T,class I> inline
257 void quickSort( T* arr, I sz )
259 {
260  I pstack[NSTACK], qstack[NSTACK], j, k, p, q, top=0;
261 
262  pstack[top] = 0;
263  qstack[top++] = sz - 1;
264 
265  while( top )
266  {
267  p = pstack[--top];
268  q = qstack[top];
269 
270  while( q - p > NSMALL )
271  {
272  partSort( arr, p, q, &j, &k );
273 
274  if ( j-p < q-k )
275  {
276  pstack[top] = k;
277  qstack[top++] = q;
278  q = j;
279  }
280  else
281  {
282  pstack[top] = p;
283  qstack[top++] = j;
284  p = k;
285  }
286  }
287  insertionSort( arr, p, q );
288  }
289 }
290 
291 
292 template <class T, class IT> inline
293 void partSort( T* arr, IT* iarr, int istart, int istop, int* jstart, int* jstop)
294 {
295  int ipivot, ileft, iright;
296  T pivotval, tmp;
297  IT itmp;
298 
299  const float localseed = getPartSortSeed();
300 
301  ipivot = (int)(istart + (istop-istart) * (float)localseed / (float)FM);
302  if ( ipivot < istart ) ipivot = istart;
303  if ( ipivot > istop ) ipivot = istop;
304  pivotval = arr[ipivot];
305 
306  for ( ileft=istart, iright=istop; ; )
307  {
308  while ( arr[ileft] <=pivotval && ileft<istop ) ileft++;
309  while ( arr[iright]>=pivotval && iright>istart ) iright--;
310  if ( ileft < iright )
311  {
312  itmp = iarr[ileft];
313  tmp = arr[ileft];
314 
315  iarr[ileft] = iarr[iright];
316  arr[ileft++] = arr[iright];
317 
318  iarr[iright] = itmp;
319  arr[iright--] = tmp;
320  }
321  else break;
322  }
323 
324  if ( ileft < ipivot )
325  {
326  itmp = iarr[ileft];
327  tmp = arr[ileft];
328 
329  iarr[ileft] = iarr[ipivot];
330  arr[ileft++] = arr[ipivot];
331 
332  iarr[ipivot] = itmp;
333  arr[ipivot] = tmp;
334  }
335  else if ( ipivot < iright )
336  {
337  itmp = iarr[iright];
338  tmp = arr[iright];
339 
340  iarr[iright] = iarr[ipivot];
341  arr[iright--] = arr[ipivot];
342 
343  iarr[ipivot] = itmp;
344  arr[ipivot] = tmp;
345  }
346 
347  *jstart = iright;
348  *jstop = ileft;
349 }
350 
351 
352 template <class T, class IT> inline
353 void insertionSort( T* arr, IT* iarr, int istart, int istop )
354 {
355  int i, j;
356  T arr_i;
357  IT iarr_i;
358 
359  for ( i=istart+1; i<=istop; i++ )
360  {
361  for ( iarr_i=iarr[i],arr_i=arr[i],j=i; j>istart && arr[j-1]>arr_i; j-- )
362  {
363  arr[j] = arr[j-1];
364  iarr[j] = iarr[j-1];
365  }
366 
367  arr[j] = arr_i;
368  iarr[j] = iarr_i;
369  }
370 }
371 
372 template <class T, class IT>
373 void sortFor( T* arr, IT* iarr, int sz, int itarget )
374 {
375  int j, k, p = 0, q = sz-1;
376 
377  while( q - p > NSMALL )
378  {
379  partSort( arr, iarr, p, q, &j, &k );
380 
381  if ( itarget <= j ) q = j;
382  else if ( itarget >= k ) p = k;
383  else return;
384  }
385 
386  insertionSort( arr, iarr, p, q );
387 }
388 
389 
390 template <class T, class IT> inline
391 void quickSort( T* arr, IT* iarr, int sz )
392 {
393  int pstack[NSTACK], qstack[NSTACK], j, k, p, q, top=0;
394 
395  pstack[top] = 0;
396  qstack[top++] = sz - 1;
397 
398  while( top )
399  {
400  p = pstack[--top];
401  q = qstack[top];
402 
403  while( q - p > NSMALL )
404  {
405  partSort( arr, iarr, p, q, &j, &k );
406 
407  if ( j-p < q-k )
408  {
409  pstack[top] = k;
410  qstack[top++] = q;
411  q = j;
412  }
413  else
414  {
415  pstack[top] = p;
416  qstack[top++] = j;
417  p = k;
418  }
419  }
420 
421  insertionSort( arr, iarr, p, q );
422  }
423 }
424 
425 #undef NSMALL
426 #undef FM
427 #undef FA
428 #undef FC
429 #undef NSTACK
430 
431 
432 //ParallelSort implementation
433 template <class T> inline
435  : vals_( vals )
436  , nrvals_( sz )
437  , tmpbuffer_( 0 )
438  , barrier_( -1, false )
439  , totalnr_(0)
440  , idxs_( 0 )
441 {
442  mTryAlloc( tmpbuffer_, T[sz] );
443 }
444 
445 
446 template <class T> inline
447 ParallelSorter<T>::ParallelSorter(T* vals, int* idxs, int sz)
448  : vals_( vals )
449  , nrvals_( sz )
450  , tmpbuffer_( 0 )
451  , totalnr_(0)
452  , barrier_( -1, false )
453  , idxs_( idxs )
454 {
455  mTryAlloc( tmpbuffer_, T[sz] );
456 }
457 
458 
459 template <class T> inline
460 bool ParallelSorter<T>::doPrepare( int nrthreads )
461 {
462  if ( !tmpbuffer_ )
463  return false;
464 
465  barrier_.setNrThreads( nrthreads );
466 
467  starts_.erase();
468  newstarts_.erase();
469 
470  int nrmerges = -1;
471  while ( nrthreads )
472  {
473  nrmerges++;
474  nrthreads>>=1;
475  }
476 
477  totalnr_ = (1+nrmerges)*nrvals_;
478  return true;
479 }
480 
481 
482 template <class T> inline
483 bool ParallelSorter<T>::doFinish( bool success )
484 {
485  if ( !success )
486  return false;
487 
488  if ( curvals_!=vals_ )
489  OD::memCopy( vals_, curvals_, nrvals_*sizeof(T) );
490 
491  return true;
492 }
493 
494 
495 template <class T> inline
496 bool ParallelSorter<T>::doWork( od_int64 start, od_int64 stop, int thread )
497 {
498  const int threadsize = stop-start+1;
499  if ( threadsize<100 )
500  {
501  if ( idxs_ )
502  sort_coupled( vals_+start, idxs_+start, threadsize );
503  else
504  sort_array( vals_+start, threadsize );
505  }
506  else
507  {
508  if ( idxs_ )
509  quickSort( vals_+start, idxs_+start, threadsize );
510  else
511  quickSort( vals_+start, threadsize );
512  }
513 
514  if ( !shouldContinue() )
515  return false;
516 
517  addToNrDone( threadsize );
518 
519  barrier_.mutex().lock();
520  newstarts_ += start;
521  barrier_.mutex().unLock();
522 
523  while ( true )
524  {
525  if ( barrier_.waitForAll(false) )
526  {
527  if ( curvals_==vals_ )
528  {
530  buf_ = vals_;
531  }
532  else
533  {
534  buf_ = tmpbuffer_;
535  curvals_ = vals_;
536  }
537 
541  }
542 
543  if ( thread>=barrier_.nrThreads() )
544  {
545  barrier_.mutex().unLock();
546  //I'm not needed any longer
547  break;
548  }
549 
550  const int curstart0 = starts_[0]; starts_.removeSingle( 0 );
551  const int curstart1 = starts_[0]; starts_.removeSingle( 0 );
552  int curstart2;
553  if ( starts_.size()==1 )
554  {
555  curstart2 = starts_[0];
556  starts_.removeSingle( 0 );
557  }
558  else
559  curstart2 = -1;
560 
561  const int curstop = (starts_.size() ? starts_[0] : nrvals_)-1;
562  newstarts_ += curstart0;
563  barrier_.mutex().unLock();
564 
565  int cursize;
566  if ( !mergeLists( curvals_, buf_,
567  curstart0, curstart1, curstart2, curstop, cursize) )
568  return false;
569 
570  if ( !shouldContinue() )
571  return false;
572 
573  addToNrDone( cursize );
574  }
575 
576  return true;
577 }
578 
579 
580 template <class T> inline
581 bool ParallelSorter<T>::mergeLists( const T* valptr, T* result,
582  int start0, int start1, int start2,
583  int stop, int& totalsz )
584 {
585  const int sz0 = start1-start0;
586  const int sz1 = start2==-1 ? stop-start1+1 : start2-start1;
587  const int sz2 = start2==-1 ? 0 : stop-start2+1;
588  totalsz = sz0+sz1+sz2;
589 
590  const T* ptr0 = valptr + start0;
591  const T* stopptr0 = ptr0+sz0;
592  const T* ptr1 = valptr + start1;
593  const T* stopptr1 = ptr1+sz1;
594  const T* ptr2 = start2==-1 ? 0 : valptr + start2;
595  const T* stopptr2 = ptr2+sz2;
596 
597  while ( true )
598  {
599  if ( ptr0 && (!ptr1 || *ptr0<*ptr1) && (!ptr2 || *ptr0<*ptr2 ) )
600  {
601  (*result++) = (*ptr0++);
602  if ( ptr0==stopptr0 )
603  ptr0 = 0;
604  }
605  else if ( ptr1 && ( !ptr2 || *ptr1<*ptr2 ) )
606  {
607  (*result++) = (*ptr1++);
608  if ( ptr1==stopptr1 )
609  ptr1 = 0;
610  }
611  else if ( ptr2 )
612  {
613  (*result++) = (*ptr2++);
614  if ( ptr2==stopptr2 )
615  ptr2 = 0;
616  }
617  else
618  break;
619  }
620 
621  return true;
622 }
Is an object that faciliates many threads to wait for something to happen.
Definition: thread.h:108
void insertionSort(T *arr, I istart, I istop)
Definition: sorting.h:221
void partSort(T *arr, I istart, I istop, I *jstart, I *jstop)
Definition: sorting.h:176
void sort_idxabl(T &arr, int sz)
Definition: sorting.h:58
Mutex & mutex()
Definition: thread.h:266
int nrThreads() const
Definition: thread.h:249
const int nrvals_
Definition: sorting.h:142
#define mExtern(module)
Definition: commondefs.h:163
#define NSMALL
Definition: sorting.h:153
void setNrThreads(int)
void sortFor(T *arr, I sz, I itarget)
Definition: sorting.h:236
void sort_array(T *arr, I sz)
Definition: sorting.h:35
#define FC
Definition: sorting.h:156
TypeSet< int > starts_
Definition: sorting.h:146
#define mCast(tp, v)
Definition: commondefs.h:120
#define od_int64
Definition: plftypes.h:34
Sorting in parallel. Code is still experimental.
Definition: sorting.h:118
int totalnr_
Definition: sorting.h:143
#define mDoSort(extra_var, extra_action, sztype)
Definition: sorting.h:44
virtual bool shouldContinue()
mExtern(Algo) Threads float getPartSortSeed()
Definition: sorting.h:161
od_int64 nrDone() const
May be -1, i.e. class does not report nrdone.
Definition: sorting.h:133
Generalization of a task that can be run in parallel.
Definition: paralleltask.h:64
virtual T * arr()
3rd party access
Definition: typeset.h:86
void quickSort(T *arr, I sz)
Definition: sorting.h:257
interface to threads that should be portable.
Definition: atomic.h:24
void releaseAllNoLock()
bool duplicate_sort(T *arr, I sz, int maxnrvals)
Definition: sorting.h:70
Set of (small) copyable elements.
Definition: commontypes.h:26
int minThreadSize() const
Definition: sorting.h:126
ArrPtrMan< T > tmpbuffer_
Definition: sorting.h:136
TypeSet< int > newstarts_
Definition: sorting.h:147
#define mTryAlloc(var, stmt)
Catches bad_alloc and sets ptr to null as normal.
Definition: commondefs.h:244
#define FA
Definition: sorting.h:155
bool doPrepare(int)
Definition: sorting.h:460
void sort_idxabl_coupled(T &arr, IT *idxs, int sz)
Definition: sorting.h:63
ParallelSorter(T *vals, int sz)
Definition: sorting.h:434
bool doFinish(bool)
Definition: sorting.h:483
#define NSTACK
Definition: sorting.h:157
Waits for a number of threads to reach a certain point (i.e. the call to Barrier::waitForAll). Once everyone has arrived, everyone is released.
Definition: thread.h:244
static bool mergeLists(const T *vals, T *res, int start0, int start1, int start2, int stop, int &totalsz)
Definition: sorting.h:581
bool doWork(od_int64, od_int64, int)
Definition: sorting.h:496
#define FM
Definition: sorting.h:154
size_type size() const
Definition: ptrman.h:154
od_int64 nrIterations() const
Definition: sorting.h:124
virtual void erase()
Definition: typeset.h:360
T * buf_
Definition: sorting.h:140
Threads::Barrier barrier_
Definition: sorting.h:149
Threads::ConditionVar condvar_
Definition: sorting.h:145
int * idxs_
Definition: sorting.h:138
T * vals_
Definition: sorting.h:135
bool waitForAll(bool unlock=true)
virtual void removeSingle(size_type, bool preserver_order=true)
Definition: typeset.h:507
#define mClass(module)
Definition: commondefs.h:161
virtual size_type indexOf(T, bool forward=true, size_type start=-1) const
void addToNrDone(int64_t increment)
T * curvals_
Definition: sorting.h:139
void sort_coupled(T *arr, IT *idxs, I sz)
Definition: sorting.h:40

Generated at for the OpendTect seismic interpretation project. Copyright (C): dGB Beheer B. V. 2017