1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #ifndef QTCONCURRENT_MEDIAN_H |
5 | #define QTCONCURRENT_MEDIAN_H |
6 | |
7 | #include <QtConcurrent/qtconcurrent_global.h> |
8 | |
9 | #if !defined(QT_NO_CONCURRENT) || defined(Q_QDOC) |
10 | |
11 | #include <algorithm> |
12 | #include <cstring> |
13 | |
14 | QT_BEGIN_NAMESPACE |
15 | |
16 | namespace QtConcurrent { |
17 | |
18 | class Median |
19 | { |
20 | public: |
21 | enum { BufferSize = 7 }; |
22 | |
23 | Median() |
24 | : currentMedian(), currentIndex(0), valid(false), dirty(true) |
25 | { |
26 | std::fill_n(first: values, n: static_cast<int>(BufferSize), value: 0.0); |
27 | } |
28 | |
29 | void reset() |
30 | { |
31 | std::fill_n(first: values, n: static_cast<int>(BufferSize), value: 0.0); |
32 | currentIndex = 0; |
33 | valid = false; |
34 | dirty = true; |
35 | } |
36 | |
37 | void addValue(double value) |
38 | { |
39 | ++currentIndex; |
40 | if (currentIndex == BufferSize) { |
41 | currentIndex = 0; |
42 | valid = true; |
43 | } |
44 | |
45 | // Only update the cached median value when we have to, that |
46 | // is when the new value is on then other side of the median |
47 | // compared to the current value at the index. |
48 | const double currentIndexValue = values[currentIndex]; |
49 | if ((currentIndexValue > currentMedian && currentMedian > value) |
50 | || (currentMedian > currentIndexValue && value > currentMedian)) { |
51 | dirty = true; |
52 | } |
53 | |
54 | values[currentIndex] = value; |
55 | } |
56 | |
57 | bool isMedianValid() const |
58 | { |
59 | return valid; |
60 | } |
61 | |
62 | double median() |
63 | { |
64 | if (dirty) { |
65 | dirty = false; |
66 | |
67 | double sorted[BufferSize]; |
68 | ::memcpy(dest: &sorted, src: &values, n: sizeof(sorted)); |
69 | std::sort(first: sorted, last: sorted + static_cast<int>(BufferSize)); |
70 | currentMedian = sorted[BufferSize / 2]; |
71 | } |
72 | |
73 | return currentMedian; |
74 | } |
75 | |
76 | private: |
77 | double values[BufferSize]; |
78 | double currentMedian; |
79 | int currentIndex; |
80 | bool valid; |
81 | bool dirty; |
82 | }; |
83 | |
84 | } // namespace QtConcurrent |
85 | |
86 | QT_END_NAMESPACE |
87 | |
88 | #endif // QT_NO_CONCURRENT |
89 | |
90 | #endif |
91 | |