Ocean
Median.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  */
7 
8 #ifndef META_OCEAN_BASE_MEDIAN_H
9 #define META_OCEAN_BASE_MEDIAN_H
10 
11 #include "ocean/base/Base.h"
12 #include "ocean/base/Memory.h"
13 
14 namespace Ocean
15 {
16 
17 /**
18  * This class implements a median determination value.
19  * @ingroup base
20  */
21 class Median
22 {
23  public:
24 
25  /**
26  * Returns the median of two given values (the lower of both).
27  * Beware: In the case one of the given values is not a number (nan) the result may be arbitrary as the comparison operator is not defined for such values.
28  * @param v0 First value
29  * @param v1 Second value
30  * @return Resulting median
31  * @tparam T Data type of the data elements
32  */
33  template <typename T>
34  static inline T median2(const T& v0, const T& v1);
35 
36  /**
37  * Returns the median of three given values.
38  * Beware: In the case one of the given values is not a number (nan) the result may be arbitrary as the comparison operator is not defined for such values.
39  * @param v0 First value
40  * @param v1 Second value
41  * @param v2 Third value
42  * @return Resulting median
43  * @tparam T Data type of the data elements
44  */
45  template <typename T>
46  static inline T median3(const T& v0, const T& v1, const T& v2);
47 
48  /**
49  * Returns the median of four given values (the second smallest value).
50  * Beware: In the case one of the given values is not a number (nan) the result may be arbitrary as the comparison operator is not defined for such values.
51  * @param v0 First value
52  * @param v1 Second value
53  * @param v2 Third value
54  * @param v3 Fourth value
55  * @return Resulting median
56  * @tparam T Data type of the data elements
57  */
58  template <typename T>
59  static inline T median4(const T& v0, const T& v1, const T& v2, const T& v3);
60 
61  /**
62  * Returns the median of five given values.
63  * Beware: In the case one of the given values is not a number (nan) the result may be arbitrary as the comparison operator is not defined for such values.
64  * @param v0 First value
65  * @param v1 Second value
66  * @param v2 Third value
67  * @param v3 Fourth value
68  * @param v4 Fifth value
69  * @return Resulting median
70  * @tparam T Data type of the data elements
71  */
72  template <typename T>
73  static inline T median5(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4);
74 
75  /**
76  * Returns the median value in a given data array.
77  * If the given number is even, the median value is selected left from the exact center.<br>
78  * Beware: In the case one of the given values is not a number (nan) the result may be arbitrary as the comparison operator is not defined for such values.
79  * @param values Array with values that will be reordered during the execution, must be valid
80  * @param number Number of values, with range [1, infinity)
81  * @return The median value out of 'values'
82  * @tparam T Type of the data for that the median has to be determined
83  */
84  template <typename T>
85  static T median(T* values, const size_t number);
86 
87  /**
88  * Returns the median value in a given data array.
89  * If the given number is even, the median value is selected left from the exact center.<br>
90  * Beware: In the case one of the given values is not a number (nan) the result may be arbitrary as the comparison operator is not defined for such values.
91  * @param values Array with values from which the median will be determined, must be valid
92  * @param number Number of values, with range [1, infinity)
93  * @return The median value out of 'values'
94  * @tparam T Type of the data for that the median has to be determined
95  */
96  template <typename T>
97  static T constMedian(const T* values, const size_t number);
98 };
99 
100 template <typename T>
101 inline T Median::median2(const T& v0, const T& v1)
102 {
103  return v0 < v1 ? v0 : v1;
104 }
105 
106 template <typename T>
107 inline T Median::median3(const T& v0, const T& v1, const T& v2)
108 {
109  if (v0 < v1)
110  {
111  // [ v0 < v1 ]
112 
113  if (v2 < v0)
114  {
115  // [ v2 < v0 < v1]
116  return v0;
117  }
118  else // v2 >= v0
119  {
120  // [ v0 < v1,v2 ]
121 
122  if (v1 < v2)
123  return v1;
124  else
125  return v2;
126  }
127  }
128  else // v0 >= v1
129  {
130  // [ v1 < v0 ]
131 
132  if (v2 < v1)
133  {
134  // [ v2 < v1 < v0 ]
135 
136  return v1;
137  }
138  else // v2 >= v1
139  {
140  // [ v1 < v0,v2 ]
141 
142  if (v0 < v2)
143  return v0;
144  else
145  return v2;
146  }
147  }
148 }
149 
150 template <typename T>
151 inline T Median::median4(const T& v0, const T& v1, const T& v2, const T& v3)
152 {
153  // v0, v1, v2, v3
154  if (v0 < v1)
155  {
156  // v0 < v1 | v2, v3
157 
158  if (v0 < v2)
159  {
160  // v0 < v1,v2 | v3
161 
162  if (v0 < v3)
163  {
164  // v0 < v1,v2,v3
165 
166  if (v1 < v2)
167  {
168  // v0 < v1 < v2 | v0 < v3
169 
170  if (v2 < v3)
171  {
172  // v0 < v1 < v2 < v3
173  return v1;
174  }
175  else // v3 < v2
176  {
177  // v0 < v1 < v2 | v0 < v3 | v3 < v2
178 
179  if (v3 < v1)
180  {
181  // v0 < v3 < v1 < v2
182  return v3;
183  }
184  else // v1 < v3
185  {
186  // v0 < v1 < v3 < v2
187  return v1;
188  }
189  }
190  }
191  else // v2 < v1
192  {
193  // v0 < v1,v2,v3 | v2 < v1
194 
195  if (v2 < v3)
196  {
197  // v0 < v1,v2,v3 | v2 < v1,v3
198  return v2;
199  }
200  else // v3 < v2
201  {
202  // v0 < v1,v2,v3 | v3 < v2 < v1
203  return v3;
204  }
205  }
206  }
207  else // v3 < v0
208  {
209  // v3 < v0 < v1,v2
210  return v0;
211  }
212  }
213  else // v2 < v0
214  {
215  // v2 < v0 < v1 | v3
216 
217  if (v3 < v2)
218  {
219  // v3 < v2 < v0 < v1
220  return v2;
221  }
222  else // v2 < v3
223  {
224  // v2 < v0 < v1 | v2 < v3
225 
226  if (v0 < v3)
227  {
228  // v2 < v0 < v1, v3
229  return v0;
230  }
231  else // v3 < v0
232  {
233  // v2 < v3 < v0 < v1
234  return v3;
235  }
236  }
237  }
238  }
239  else // v1 < v0
240  {
241  // v1 < v0 | v2, v3
242 
243  if (v2 < v1)
244  {
245  // v2 < v1 < v0 | v3
246 
247  if (v3 < v2)
248  {
249  // v3 < v2 < v1 < v0
250  return v2;
251  }
252  else // v2 < v3
253  {
254  // v2 < v1 < v0 | v2 < v3
255 
256  if (v1 < v3)
257  {
258  // v2 < v1 < v0,v3
259  return v1;
260  }
261  else // v3 < v1
262  {
263  // v2 < v3 < v1 < v0
264  return v3;
265  }
266  }
267  }
268  else // v1 < v2
269  {
270  // v1 < v0,v2 | v3
271 
272  if (v0 < v2)
273  {
274  // v1 < v0 < v2 | v3
275 
276  if (v3 < v1)
277  {
278  // v3 < v1 < v0 < v2
279  return v1;
280  }
281  else // v1 < v3
282  {
283  // v1 < v0 < v2 | v1 < v3
284 
285  if (v0 < v3)
286  {
287  // v1 < v0 < v2,v3
288  return v0;
289  }
290  else // v3 < v0
291  {
292  // v1 < v3 < v0 < v2
293  return v3;
294  }
295  }
296  }
297  else // v2 < v0
298  {
299  // v1 < v2 < v0 | v3
300 
301  if (v3 < v1)
302  {
303  // v3 < v1 < v2 < v0
304  return v1;
305  }
306  else // v1 < v3
307  {
308  // v1 < v2 < v0 | v1 < v3
309 
310  if (v2 < v3)
311  {
312  // v1 < v2 < v0, v3
313  return v2;
314  }
315  else // v3 < v2
316  {
317  // v1 < v3 < v2 < v0
318  return v3;
319  }
320  }
321  }
322  }
323  }
324 }
325 
326 template <typename T>
327 inline T Median::median5(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
328 {
329  // v0, v1, v2, v3, v4
330  if (v0 < v1)
331  {
332  // v0 < v1 | v2, v3, v4
333 
334  if (v0 < v2)
335  {
336  // v0 < v1,v2 | v3, v4
337 
338  if (v0 < v3)
339  {
340  // v0 < v1,v2,v3 | v4
341 
342  if (v0 < v4)
343  {
344  // v0 < v1,v2,v3,v4
345 
346  if (v1 < v2)
347  {
348  // v0 < v1 < v2 | v0 < v3,v4
349 
350  if (v2 < v3)
351  {
352  // v0 < v1 < v2 < v3 | v0 < v4
353 
354  if (v3 < v4)
355  {
356  // v0 < v1 < v2 < v3 < v4
357  return v2;
358  }
359  else // v4 < v3
360  {
361  // v0 < v1 < v2 < v3 | v0 < v4 < v3
362 
363  if (v4 < v2)
364  {
365  // v0 < v1 < v2 < v3 | v0 < v4 < v2
366 
367  if (v4 < v1)
368  {
369  // v0 < v4 < v1 < v2 < v3
370  return v1;
371  }
372  else // v1 < v4
373  {
374  // v0 < v1 < v4 < v2 < v3
375  return v4;
376  }
377  }
378  else // v2 < v4
379  {
380  // v0 < v1 < v2 < v4 < v3
381  return v2;
382  }
383  }
384  }
385  else // v3 < v2
386  {
387  // v0 < v1 < v2 | v0 < v3,v4 | v3 < v2
388 
389  if (v3 < v1)
390  {
391  // v0 < v3 < v1 < v2 | v0 < v4
392 
393  if (v4 < v3)
394  {
395  // v0 < v4 < v3 < v1 < v2
396  return v3;
397  }
398  else // v3 < v4
399  {
400  // v0 < v3 < v1 < v2 | v3 < v4
401 
402  if (v4 < v1)
403  {
404  // v0 < v3 < v4 < v1 < v2
405  return v4;
406  }
407  else // v1 < v4
408  {
409  // v0 < v3 < v1 < v2,v4
410  return v1;
411  }
412  }
413  }
414  else // v1 < v3
415  {
416  // v0 < v1 < v3 < v2 | v0 < v4
417 
418  if (v1 < v4)
419  {
420  // v0 < v1 < v3 < v2 | v1 < v4
421 
422  if (v3 < v4)
423  {
424  // v0 < v1 < v3 < v2, v4
425  return v3;
426  }
427  else // v4 < v3
428  {
429  // v0 < v1 < v4 < v3 < v2
430  return v4;
431  }
432  }
433  else // v4 < v1
434  {
435  // v0 < v4 < v1 < v3 < v2
436  return v1;
437  }
438  }
439  }
440  }
441  else // v2 < v1
442  {
443  // v0 < v1,v2,v3,v4 | v2 < v1
444 
445  if (v2 < v3)
446  {
447  // v0 < v1,v2,v3,v4 | v2 < v1,v3
448 
449  if (v2 < v4)
450  {
451  // v0 < v2 < v1,v3,v4
452 
453  if (v1 < v3)
454  {
455  // v0 < v2 < v1,v3,v4 | v1 < v3
456 
457  if (v1 < v4)
458  {
459  // v0 < v2 < v1 < v3,v4
460  return v1;
461  }
462  else // v4 < v1
463  {
464  // v0 < v2 < v4 < v1 < v3
465  return v4;
466  }
467  }
468  else // v3 < v1
469  {
470  // v0 < v2 < v1,v3,v4 | v3 < v1
471 
472  if (v3 < v4)
473  {
474  // v0 < v2 < v3 < v1,v4
475  return v3;
476  }
477  else // v4 < v3
478  {
479  // v0 < v2 < v4 < v3 < v1
480  return v4;
481  }
482  }
483  }
484  else // v4 < v2
485  {
486  // v0 < v4 < v2 < v1,v3
487  return v2;
488  }
489  }
490  else // v3 < v2
491  {
492  // v0 < v1,v2,v3,v4 | v3 < v2 < v1
493 
494  if (v3 < v4)
495  {
496  // v0 < v3 < v2 < v1 | v3 < v4
497 
498  if (v2 < v4)
499  {
500  // v0 < v3 < v2 < v1,v4
501  return v2;
502  }
503  else // v4 < v2
504  {
505  // v0 < v3 < v4 < v2 < v1
506  return v4;
507  }
508  }
509  else // v4 < v3
510  {
511  // v0 < v4 < v3 < v2 < v1
512  return v3;
513  }
514  }
515  }
516  }
517  else // v4 < v0
518  {
519  // v4 < v0 < v1,v2,v3
520 
521  if (v1 < v2)
522  {
523  // v4 < v0 < v1,v2,v3 | v1 < v2
524 
525  if (v1 < v3)
526  {
527  // v4 < v0 < v1 < v2,v3
528  return v1;
529  }
530  else // v3 < v1
531  {
532  // v4 < v0 < v3 < v1 < v2
533  return v3;
534  }
535  }
536  else // v2 < v1
537  {
538  // v4 < v0 < v1,v2,v3 | v2 < v1
539 
540  if (v2 < v3)
541  {
542  // v4 < v0 < v2 < v1,v3
543  return v2;
544  }
545  else // v3 < v2
546  {
547  // v4 < v0 < v3 < v2 < v1
548  return v3;
549  }
550  }
551  }
552  }
553  else // v3 < v0
554  {
555  // v3 < v0 < v1,v2 | v4
556 
557  if (v0 < v4)
558  {
559  // v3 < v0 < v1,v2,v4
560 
561  if (v1 < v2)
562  {
563  // v3 < v0 < v1,v2,v4 | v1 < v2
564 
565  if (v1 < v4)
566  {
567  // v3 < v0 < v1 < v2,v4
568  return v1;
569  }
570  else // v4 < v1
571  {
572  // v3 < v0 < v4 < v1 < v2
573  return v4;
574  }
575  }
576  else // v2 < v1
577  {
578  // v3 < v0 < v1,v2,v4 | v2 < v1
579 
580  if (v2 < v4)
581  {
582  // v3 < v0 < v2 < v1,v4
583  return v2;
584  }
585  else // v4 < v2
586  {
587  // v3 < v0 < v4 < v2 < v1
588  return v4;
589  }
590  }
591  }
592  else // v4 < v0
593  {
594  // v3,v4 < v0 < v1,v2
595  return v0;
596  }
597  }
598  }
599  else // v2 < v0
600  {
601  // v2 < v0 < v1 | v3, v4
602 
603  if (v3 < v2)
604  {
605  // v3 < v2 < v0 < v1 | v4
606 
607  if (v0 < v4)
608  {
609  // v3 < v2 < v0 < v1,v4
610  return v0;
611  }
612  else // v4 < v0
613  {
614  // v3 < v2 < v0 < v1 | v4 < v0
615 
616  if (v4 < v2)
617  {
618  // v3,v4 < v2 < v0 < v1
619  return v2;
620 
621  }
622  else // v2 < v4
623  {
624  // v3 < v2 < v4 < v0 < v1
625  return v4;
626  }
627  }
628  }
629  else // v2 < v3
630  {
631  // v2 < v0 < v1 | v2 < v3 | v4
632 
633  if (v4 < v2)
634  {
635  // v4 < v2 < v0 < v1 | v2 < v3
636 
637  if (v0 < v3)
638  {
639  // v4 < v2 < v0 < v1, v3
640  return v0;
641  }
642  else // v3 < v0
643  {
644  // v4 < v2 < v3 < v0 < v1
645  return v3;
646  }
647  }
648  else // v2 < v4
649  {
650  // v2 < v0 < v1 | v2 < v3, v4
651 
652  if (v4 < v0)
653  {
654  // v2 < v4 < v0 < v1 | v2 < v3
655 
656  if (v4 < v3)
657  {
658  // v2 < v4 < v0 < v1 | v4 < v3
659 
660  if (v0 < v3)
661  {
662  // v2 < v4 < v0 < v1,v3
663  return v0;
664  }
665  else // v3 < v0
666  {
667  // v2 < v4 < v3 < v0 < v1
668  return v3;
669  }
670  }
671  else // v3 < v4
672  {
673  // v2 < v3 < v4 < v0 < v1
674  return v4;
675  }
676  }
677  else // v0 < v4
678  {
679  // v2 < v0 < v1,v4 | v2 < v3
680 
681  if (v0 < v3)
682  {
683  // v2 < v0 < v1,v4,v3
684 
685  if (v1 < v4)
686  {
687  // v2 < v0 < v1,v4,v3 | v1 < v4
688 
689  if (v1 < v3)
690  {
691  // v2 < v0 < v1 < v3,v4
692  return v1;
693  }
694  else // v3 < v1
695  {
696  // v2 < v0 < v3 < v1 < v4
697  return v3;
698  }
699  }
700  else // v4 < v1
701  {
702  // v2 < v0 < v1,v4,v3 | v4 < v1
703 
704  if (v4 < v3)
705  {
706  // v2 < v0 < v4 < v1,v3
707  return v4;
708  }
709  else // v3 < v4
710  {
711  // v2 < v0 < v3 < v4 < v1
712  return v3;
713  }
714  }
715  }
716  else // v3 < v0
717  {
718  // v2 < v3 < v0 < v1,v4
719  return v0;
720  }
721  }
722  }
723  }
724  }
725  }
726  else // v1 < v0
727  {
728  // v1 < v0 | v2, v3, v4
729 
730  if (v2 < v1)
731  {
732  // v2 < v1 < v0 | v3, v4
733 
734  if (v3 < v2)
735  {
736  // v3 < v2 < v1 < v0 | v4
737 
738  if (v4 < v3)
739  {
740  // v4 < v3 < v2 < v1 < v0
741  return v2;
742  }
743  else // v3 < v4
744  {
745  // v3 < v2 < v1 < v0 | v3 < v4
746 
747  if (v2 < v4)
748  {
749  // v3 < v2 < v1 < v0 | v2 < v4
750 
751  if (v1 < v4)
752  {
753  // v3 < v2 < v1 < v0,v4
754  return v1;
755  }
756  else // v4 < v1
757  {
758  // v3 < v2 < v4 < v1 < v0
759  return v4;
760  }
761  }
762  else // v4 < v2
763  {
764  // v3 < v4 < v2 < v1 < v0
765  return v2;
766  }
767  }
768  }
769  else // v2 < v3
770  {
771  // v2 < v1 < v0 | v2 < v3 | v4
772 
773  if (v4 < v2)
774  {
775  // v4 < v2 < v1 < v0 | v2 < v3
776 
777  if (v1 < v3)
778  {
779  // v4 < v2 < v1 < v0,v3
780  return v1;
781  }
782  else // v3 < v1
783  {
784  // v4 < v2 < v3 < v1 < v0
785  return v3;
786  }
787  }
788  else // v2 < v4
789  {
790  // v2 < v1 < v0 | v2 < v3,v4
791 
792  if (v1 < v3)
793  {
794  // v2 < v1 < v0,v3 | v2 < v4
795 
796  if (v1 < v4)
797  {
798  // v2 < v1 < v0,v3,v4
799 
800  if (v0 < v3)
801  {
802  // v2 < v1 < v0,v3,v4 | v0 < v3
803 
804  if (v0 < v4)
805  {
806  // v2 < v1 < v0 < v3,v4
807  return v0;
808  }
809  else // v4 < v0
810  {
811  // v2 < v1 < v4 < v0 < v3
812  return v4;
813  }
814  }
815  else // v3 < v0
816  {
817  // v2 < v1 < v0,v3,v4 | v3 < v0
818 
819  if (v3 < v4)
820  {
821  // v2 < v1 < v3 < v0,v4
822  return v3;
823  }
824  else // v4 < v3
825  {
826  // v2 < v1 < v4 < v3 < v0
827  return v4;
828  }
829  }
830  }
831  else // v4 < v1
832  {
833  // v2 < v4 < v1 < v0,v3
834  return v1;
835  }
836  }
837  else // v3 < v1
838  {
839  // v2 < v3 < v1 < v0 | v2 < v4
840 
841  if (v3 < v4)
842  {
843  // v2 < v3 < v1 < v0 | v3 < v4
844 
845  if (v1 < v4)
846  {
847  // v2 < v3 < v1 < v0,v4
848  return v1;
849  }
850  else // v4 < v1
851  {
852  // v2 < v3 < v4 < v1 < v0
853  return v4;
854  }
855  }
856  else // v4 < v3
857  {
858  // v2 < v4 < v3 < v1 < v0
859  return v3;
860  }
861  }
862  }
863  }
864  }
865  else // v1 < v2
866  {
867  // v1 < v0,v2 | v3, v4
868 
869  if (v0 < v2)
870  {
871  // v1 < v0 < v2 | v3, v4
872 
873  if (v3 < v1)
874  {
875  // v3 < v1 < v0 < v2 | v4
876 
877  if (v4 < v3)
878  {
879  // v4 < v3 < v1 < v0 < v2
880  return v1;
881  }
882  else // v3 < v4
883  {
884  // v3 < v1 < v0 < v2 | v3 < v4
885 
886  if (v1 < v4)
887  {
888  // v3 < v1 < v0 < v2 | v1 < v4
889 
890  if (v0 < v4)
891  {
892  // v3 < v1 < v0 < v2,v4
893  return v0;
894  }
895  else // v4 < v0
896  {
897  // v3 < v1 < v4 < v0 < v2
898  return v4;
899  }
900  }
901  else // v4 < v1
902  {
903  // v3 < v4 < v1 < v0 < v2
904  return v1;
905  }
906  }
907  }
908  else // v1 < v3
909  {
910  // v1 < v0 < v2 | v1 < v3 | v4
911 
912  if (v4 < v1)
913  {
914  // v4 < v1 < v0 < v2 | v1 < v3
915 
916  if (v0 < v3)
917  {
918  // v4 < v1 < v0 < v2,v3
919  return v0;
920  }
921  else // v3 < v0
922  {
923  // v4 < v1 < v3 < v0 < v2
924  return v3;
925  }
926  }
927  else // v1 < v4
928  {
929  // v1 < v0 < v2 | v1 < v3,v4
930 
931  if (v0 < v3)
932  {
933  // v1 < v0 < v2,v3 | v1 < v4
934 
935  if (v0 < v4)
936  {
937  // v1 < v0 < v2,v3,v4
938 
939  if (v2 < v3)
940  {
941  // v1 < v0 < v2,v3,v4 | v2 < v3
942 
943  if (v2 < v4)
944  {
945  // v1 < v0 < v2 < v3,v4
946  return v2;
947  }
948  else // v4 < v2
949  {
950  // v1 < v0 < v4 < v2 < v3
951  return v4;
952  }
953  }
954  else // v3 < v2
955  {
956  // v1 < v0 < v2,v3,v4 | v3 < v2
957 
958  if (v3 < v4)
959  {
960  // v1 < v0 < v3 < v2,v4
961  return v3;
962  }
963  else // v4 < v3
964  {
965  // v1 < v0 < v4 < v3 < v2
966  return v4;
967  }
968  }
969  }
970  else // v4 < v0
971  {
972  // v1 < v4 < v0 < v2,v3
973  return v0;
974  }
975  }
976  else // v3 < v0
977  {
978  // v1 < v3 < v0 < v2 | v1 < v4
979 
980  if (v3 < v4)
981  {
982  // v1 < v3 < v0 < v2 | v3 < v4
983 
984  if (v0 < v4)
985  {
986  // v1 < v3 < v0 < v2, v4
987  return v0;
988  }
989  else // v4 < v0
990  {
991  // v1 < v3 < v4 < v0 < v2
992  return v4;
993  }
994  }
995  else // v4 < v3
996  {
997  // v1 < v4 < v3 < v0 < v2
998  return v3;
999  }
1000  }
1001  }
1002  }
1003  }
1004  else // v2 < v0
1005  {
1006  // v1 < v2 < v0 | v3, v4
1007 
1008  if (v3 < v1)
1009  {
1010  // v3 < v1 < v2 < v0 | v4
1011 
1012  if (v4 < v3)
1013  {
1014  // v4 < v3 < v1 < v2 < v0
1015  return v1;
1016  }
1017  else // v3 < v4
1018  {
1019  // v3 < v1 < v2 < v0 | v3 < v4
1020 
1021  if (v1 < v4)
1022  {
1023  // v3 < v1 < v2 < v0 | v1 < v4
1024 
1025  if (v2 < v4)
1026  {
1027  // v3 < v1 < v2 < v0,v4
1028  return v2;
1029  }
1030  else // v4 < v2
1031  {
1032  // v3 < v1 < v4 < v2 < v0
1033  return v4;
1034  }
1035  }
1036  else // v4 < v1
1037  {
1038  // v3 < v4 < v1 < v2 < v0
1039  return v1;
1040  }
1041  }
1042  }
1043  else // v1 < v3
1044  {
1045  // v1 < v2 < v0 | v1 < v3 | v4
1046 
1047  if (v4 < v1)
1048  {
1049  // v4 < v1 < v2 < v0 | v1 < v3
1050 
1051  if (v2 < v3)
1052  {
1053  // v4 < v1 < v2 < v0, v3
1054  return v2;
1055  }
1056  else // v3 < v2
1057  {
1058  // v4 < v1 < v3 < v2 < v0
1059  return v3;
1060  }
1061  }
1062  else // v1 < v4
1063  {
1064  // v1 < v2 < v0 | v1 < v3, v4
1065 
1066  if (v2 < v3)
1067  {
1068  // v1 < v2 < v0,v3 | v1 < v4
1069 
1070  if (v2 < v4)
1071  {
1072  // v1 < v2 < v0,v3,v4
1073 
1074  if (v0 < v3)
1075  {
1076  // v1 < v2 < v0,v3,v4 | v0 < v3
1077 
1078  if (v0 < v4)
1079  {
1080  // v1 < v2 < v0 < v3,v4
1081  return v0;
1082  }
1083  else // v4 < v0
1084  {
1085  // v1 < v2 < v4 < v0 < v3
1086  return v4;
1087  }
1088  }
1089  else // v3 < v0
1090  {
1091  // v1 < v2 < v0,v3,v4 | v3 < v0
1092 
1093  if (v3 < v4)
1094  {
1095  // v1 < v2 < v3 < v0,v4
1096  return v3;
1097  }
1098  else // v4 < v3
1099  {
1100  // v1 < v2 < v4 < v3 < v0
1101  return v4;
1102  }
1103  }
1104  }
1105  else // v4 < v2
1106  {
1107  // v1 < v4 < v2 < v0,v3
1108  return v2;
1109  }
1110  }
1111  else // v3 < v2
1112  {
1113  // v1 < v3 < v2 < v0 | v1 < v4
1114 
1115  if (v3 < v4)
1116  {
1117  // v1 < v3 < v2 < v0 | v3 < v4
1118 
1119  if (v2 < v4)
1120  {
1121  // v1 < v3 < v2 < v0, v4
1122  return v2;
1123  }
1124  else // v4 < v2
1125  {
1126  // v1 < v3 < v4 < v2 < v0
1127  return v4;
1128  }
1129  }
1130  else // v4 < v3
1131  {
1132  // v1 < v4 < v3 < v2 < v0
1133  return v3;
1134  }
1135  }
1136  }
1137  }
1138  }
1139  }
1140  }
1141 }
1142 
1143 template <typename T>
1144 T Median::median(T* values, const size_t number)
1145 {
1146  ocean_assert(values && number > 0);
1147 
1148  size_t low = 0;
1149  size_t high = number - 1;
1150  size_t median = (low + high) >> 1;
1151 
1152  size_t ll, hh, middle;
1153 
1154  while (true)
1155  {
1156  // only one element
1157  if (high <= low)
1158  return values[median];
1159 
1160  // only two elements
1161  if (high == low + 1)
1162  {
1163  if (values[low] > values[high])
1164  std::swap(values[low], values[high]);
1165 
1166  return values[median];
1167  }
1168 
1169  middle = (low + high) / 2;
1170 
1171  if (values[middle] > values[high])
1172  std::swap(values[middle], values[high]);
1173 
1174  if (values[low] > values[high])
1175  std::swap(values[low], values[high]);
1176 
1177  if (values[middle] > values[low])
1178  std::swap(values[middle], values[low]);
1179 
1180  std::swap(values[middle], values[low + 1]);
1181 
1182  ll = low + 1;
1183  hh = high;
1184 
1185  while (true)
1186  {
1187  while (ll < number && values[low] > values[++ll]); // we need the explicit out-of-range check for not-a-number (nan) elements
1188 
1189  while (hh > 0 && values[--hh] > values[low]);
1190 
1191  if (hh < ll)
1192  break;
1193 
1194  std::swap(values[ll], values[hh]);
1195  }
1196 
1197  std::swap(values[low], values[hh]);
1198 
1199  if (hh <= median)
1200  low = ll;
1201 
1202  if (hh >= median)
1203  high = hh - 1;
1204  }
1205 }
1206 
1207 template <typename T>
1208 T Median::constMedian(const T* values, const size_t number)
1209 {
1210  ocean_assert(values != nullptr && number > 0);
1211 
1212  if (number == 0)
1213  return 1;
1214 
1215  Memory memory = Memory::create<T>(number);
1216 
1217  if (memory.data() == nullptr)
1218  {
1219  ocean_assert(false && "Out of memory");
1220  return 1;
1221  }
1222 
1223  memcpy(memory.data<T>(), values, sizeof(T) * number);
1224  const T result = median(memory.data<T>(), number);
1225 
1226  return result;
1227 }
1228 
1229 }
1230 
1231 #endif // META_OCEAN_BASE_MEDIAN_H
This class implements a median determination value.
Definition: Median.h:22
static T median4(const T &v0, const T &v1, const T &v2, const T &v3)
Returns the median of four given values (the second smallest value).
Definition: Median.h:151
static T median5(const T &v0, const T &v1, const T &v2, const T &v3, const T &v4)
Returns the median of five given values.
Definition: Median.h:327
static T median(T *values, const size_t number)
Returns the median value in a given data array.
Definition: Median.h:1144
static T median2(const T &v0, const T &v1)
Returns the median of two given values (the lower of both).
Definition: Median.h:101
static T median3(const T &v0, const T &v1, const T &v2)
Returns the median of three given values.
Definition: Median.h:107
static T constMedian(const T *values, const size_t number)
Returns the median value in a given data array.
Definition: Median.h:1208
This class implements an object able to allocate memory.
Definition: base/Memory.h:22
void * data()
Returns the pointer to the writable memory which is allocated by this object.
Definition: base/Memory.h:303
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15