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
14QT_BEGIN_NAMESPACE
15
16namespace QtConcurrent {
17
18class Median
19{
20public:
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
76private:
77 double values[BufferSize];
78 double currentMedian;
79 int currentIndex;
80 bool valid;
81 bool dirty;
82};
83
84} // namespace QtConcurrent
85
86QT_END_NAMESPACE
87
88#endif // QT_NO_CONCURRENT
89
90#endif
91

source code of qtbase/src/concurrent/qtconcurrentmedian.h