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