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