Ocean
Variance.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_MATH_VARIANCE_H
9 #define META_OCEAN_MATH_VARIANCE_H
10 
11 #include "ocean/math/Math.h"
12 #include "ocean/math/Numeric.h"
13 
14 namespace Ocean
15 {
16 
17 // Forward declaration.
18 template <typename T> class VarianceT;
19 
20 /**
21  * Definition of a variance object, depending on the OCEAN_MATH_USE_SINGLE_PRECISION either with single or double precision float data type.
22  * @see VarianceT
23  * @ingroup math
24  */
26 
27 /**
28  * Definition of a variance object with double values.
29  * @see VarianceT
30  * @ingroup math
31  */
33 
34 /**
35  * Definition of a variance object with float values.
36  * @see VarianceT
37  * @ingroup math
38  */
40 
41 /**
42  * Definition of a vector holding variance objects.
43  * @see Variance
44  * @ingroup math
45  */
46 typedef std::vector<Variance> Variances;
47 
48 /**
49  * This class allows to determine the variance in a given data set.
50  * @tparam T Data type of the variance data
51  * @see Variance, VarianceF, VarianceD.
52  * @ingroup math
53  */
54 template <typename T>
55 class VarianceT
56 {
57  public:
58 
59  /**
60  * Creates a new variance object.
61  */
62  VarianceT() = default;
63 
64  /**
65  * Creates a new variance object with several values.
66  * @param values The values to be used, must be valid if size > 0
67  * @param size The number of values to be used, with range [0, infinity)
68  */
69  inline VarianceT(const T* values, const size_t size);
70 
71  /**
72  * Adds a new value.
73  * @param value The value to be added
74  */
75  inline void add(const T& value);
76 
77  /**
78  * Adds the same value several times.
79  * @param size The number of value to add, with range [1, infinity)
80  * @param value The value to be added
81  */
82  inline void add(const size_t size, const T& value);
83 
84  /**
85  * Adds several values.
86  * @param values The values to be added, must be valid if size > 0
87  * @param size The number of values to be added, with range [0, infinity)
88  */
89  inline void add(const T* values, const size_t size);
90 
91  /**
92  * Removes a previously added value.
93  * @param value The value to be removed, must have been added before
94  * @see add().
95  */
96  inline void remove(const T& value);
97 
98  /**
99  * Returns the variance of the data set.
100  * @return Data set variance
101  */
102  inline T variance() const;
103 
104  /**
105  * Returns the deviation of the data set.
106  * The deviation is determined by the square root of the variance.
107  * @return Data set deviation
108  */
109  inline T deviation() const;
110 
111  /**
112  * Returns the average of the data set.
113  * @return Data set average
114  */
115  inline T average() const;
116 
117  /**
118  * Returns the size of the data set.
119  * @return Data set size
120  */
121  inline size_t size() const;
122 
123  /**
124  * Returns whether the data set holds at least one value.
125  * @return True, if so
126  */
127  explicit inline operator bool() const;
128 
129  private:
130 
131  /// Stores the data sum.
132  T sum_ = T(0);
133 
134  /// Stores the squared data sum.
135  T squaredSum_ = T(0);
136 
137  /// Size of the data set.
138  size_t size_ = 0;
139 };
140 
141 template <typename T>
142 inline VarianceT<T>::VarianceT(const T* values, const size_t size)
143 {
144  add(values, size);
145 }
146 
147 template <typename T>
148 inline void VarianceT<T>::add(const T& value)
149 {
150  // check that enough space is left
151  ocean_assert(NumericT<T>::maxValue() - sum_ >= value);
152  ocean_assert(NumericT<T>::maxValue() - squaredSum_ >= value * value);
153 
154  sum_ += value;
155  squaredSum_ += value * value;
156 
157  ++size_;
158 }
159 
160 template <typename T>
161 inline void VarianceT<T>::add(const size_t size, const T& value)
162 {
163  // check that enough space is left
164  ocean_assert(NumericT<T>::maxValue() - sum_ >= value * T(size));
165  ocean_assert(NumericT<T>::maxValue() - squaredSum_ >= value * value * T(size));
166 
167  ocean_assert(size >= 1);
168 
169  sum_ += value * T(size);
170  squaredSum_ += value * value * T(size);
171 
172  size_ += size;
173 }
174 
175 template <typename T>
176 inline void VarianceT<T>::add(const T* values, const size_t size)
177 {
178  for (size_t n = 0; n < size; ++n)
179  {
180  add(values[n]);
181  }
182 }
183 
184 template <typename T>
185 inline void VarianceT<T>::remove(const T& value)
186 {
187  ocean_assert(size_ >= 1);
188 
189  sum_ -= value;
190 
191  ocean_assert(!(std::is_same<T, float>::value) || squaredSum_ + T(0.1) >= value * value); // e.g., in case of several add/move calls
192  ocean_assert(!(std::is_same<T, double>::value) || squaredSum_ + T(0.0001) >= value * value);
193 
194  squaredSum_ -= value * value;
195 
196  --size_;
197 }
198 
199 template <typename T>
200 inline T VarianceT<T>::variance() const
201 {
202  ocean_assert(size_ > 0);
203 
204  /**
205  * E[X^2] - (E[x])^2
206  * = mean(X^2) - mean(X)^2
207  * = sum(X^2) / size - (sum(X) / size)^2
208  * = sum(X^2) * size / size^2 - sum(X)^2 / size^2
209  * = (sum(X^2) * size - sum(X)^2) / size^2
210  */
211 
212  const T varianceSquaredSize = T(size_) * T(size_);
213  const T varianceSquaredSize_2 = varianceSquaredSize / 2;
214 
215  // varianceSquaredSize_2 the correction is mainly for integer data types
216  return (squaredSum_ * T(size_) - sum_ * sum_ + varianceSquaredSize_2) / varianceSquaredSize;
217 }
218 
219 /**
220  * Specialization for double elements.
221  * @return Resulting variance
222  */
223 template <>
224 inline double VarianceT<double>::variance() const
225 {
226  ocean_assert(size_ > 0);
227 
228  /**
229  * E[X^2] - (E[x])^2
230  */
231 
232  return squaredSum_ / double(size_) - (sum_ * sum_) / (double(size_) * double(size_));
233 }
234 
235 /**
236  * Specialization for double elements.
237  * @return Resulting variance
238  */
239 template <>
240 inline float VarianceT<float>::variance() const
241 {
242  ocean_assert(size_ > 0);
243 
244  /**
245  * E[X^2] - (E[x])^2
246  */
247 
248  return squaredSum_ / float(size_) - (sum_ * sum_) / (float(size_) * float(size_));
249 }
250 
251 template <typename T>
252 inline T VarianceT<T>::deviation() const
253 {
254  const T tempVariance = variance();
255 
256  ocean_assert(!(std::is_same<T, float>::value) || tempVariance >= T(-0.1)); // e.g., in case of several add/move calls
257  ocean_assert(!(std::is_same<T, double>::value) || tempVariance >= T(-0.0001)); // e.g., in case of several add/move calls
258 
259  if (tempVariance <= NumericT<T>::eps())
260  {
261  return T(0);
262  }
263 
264  return NumericT<T>::sqrt(tempVariance);
265 }
266 
267 template <typename T>
268 inline T VarianceT<T>::average() const
269 {
270  ocean_assert(size_ > 0);
271 
272  return sum_ / T(size_);
273 }
274 
275 template <typename T>
276 inline size_t VarianceT<T>::size() const
277 {
278  return size_;
279 }
280 
281 template <typename T>
282 inline VarianceT<T>::operator bool() const
283 {
284  return size_ != 0;
285 }
286 
287 }
288 
289 #endif // META_OCEAN_MATH_VARIANCE_H
This class provides basic numeric functionalities.
Definition: Numeric.h:57
static T sqrt(const T value)
Returns the square root of a given value.
Definition: Numeric.h:1533
This class allows to determine the variance in a given data set.
Definition: Variance.h:56
void remove(const T &value)
Removes a previously added value.
Definition: Variance.h:185
VarianceT()=default
Creates a new variance object.
T deviation() const
Returns the deviation of the data set.
Definition: Variance.h:252
T sum_
Stores the data sum.
Definition: Variance.h:132
void add(const T &value)
Adds a new value.
Definition: Variance.h:148
size_t size() const
Returns the size of the data set.
Definition: Variance.h:276
T squaredSum_
Stores the squared data sum.
Definition: Variance.h:135
T variance() const
Returns the variance of the data set.
Definition: Variance.h:200
T average() const
Returns the average of the data set.
Definition: Variance.h:268
size_t size_
Size of the data set.
Definition: Variance.h:138
VarianceT< float > VarianceF
Definition of a variance object with float values.
Definition: Variance.h:39
VarianceT< Scalar > Variance
Definition of a variance object, depending on the OCEAN_MATH_USE_SINGLE_PRECISION either with single ...
Definition: Variance.h:18
std::vector< Variance > Variances
Definition of a vector holding variance objects.
Definition: Variance.h:46
VarianceT< double > VarianceD
Definition of a variance object with double values.
Definition: Variance.h:32
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15