Gaia
gaiamath.h
1 /*
2  * Copyright (C) 2006-2013 Music Technology Group - Universitat Pompeu Fabra
3  *
4  * This file is part of Gaia
5  *
6  * Gaia is free software: you can redistribute it and/or modify it under
7  * the terms of the GNU Affero General Public License as published by the Free
8  * Software Foundation (FSF), either version 3 of the License, or (at your
9  * option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14  * details.
15  *
16  * You should have received a copy of the Affero GNU General Public License
17  * version 3 along with this program. If not, see http://www.gnu.org/licenses/
18  */
19 
20 #ifndef GAIA_GAIAMATH_H
21 #define GAIA_GAIAMATH_H
22 
23 #ifndef _USE_MATH_DEFINES
24 #define _USE_MATH_DEFINES // needed for M_PI in Windows
25 #endif
26 
27 #include <algorithm>
28 #include <cmath>
29 #include <vector>
30 #include <stdexcept>
31 #include "types.h"
32 
33 namespace gaia2 {
34 
35 static const float EPSILON = 1e-7f;
36 
37 template <typename T>
38 class SortNode {
39  public:
40  float dist;
41  T* ptr;
42  SortNode(float d = 0.0, T* p = 0) : dist(d), ptr(p) {}
43  bool operator<(const SortNode& x) const { return dist < x.dist; }
44 };
45 
46 
48 // ----[ C99 compliance: isnan & isinf functions ]--------------------------//
49 
50 #ifdef OS_WIN32
51 #include <float.h>
52 
53 // isnan returns a nonzero value if the argument x is a NAN; otherwise it returns 0.
54 template <typename T>
55 inline bool isnan(T x) { return _isnan(x) != 0; }
56 
57 // _finite returns a nonzero value if its argument x is not infinite,
58 // that is, if -INF < x < +INF. It returns 0 if the argument is infinite or a NAN.
59 template <typename T>
60 inline bool isinf(T x) { return _finite(x) == 0; }
61 
62 #else // OS_WIN32
63 
64 template <typename T>
65 inline bool isnan(T x) { return std::isnan(x); }
66 
67 template <typename T>
68 inline bool isinf(T x) { return std::isinf(x); }
69 
70 #endif // OS_WIN32
71 
72 
73 
75 // ----[ Statistics functions ]---------------------------------------------//
76 
80 template <typename T>
81 T mean(const T* array, uint n) {
82  T result = 0.0;
83  for (uint i=0; i<n; i++) {
84  result += array[i];
85  }
86  result /= n;
87  return result;
88 }
89 
90 template <typename T> T mean(const std::vector<T>& v) {
91  return mean(&v.front(), v.size());
92 }
93 
97 template <typename T>
98 T variance(const T* array, uint n) {
99  T m = mean(array, n);
100  T tmp, result = 0.0;
101  for (uint i=0; i<n; i++) {
102  tmp = array[i] - m;
103  result += tmp * tmp;
104  }
105  result /= (n - 1); // unbiased estimator
106  return result;
107 }
108 
109 template <typename T> T variance(const std::vector<T>& v) {
110  return variance(&v.front(), v.size());
111 }
112 
117 template <typename T>
118 T skewness(const T* array, uint n) {
119  T m = mean(array, n);
120  T v = variance(array, n);
121  T tmp, result = 0.0;
122  for (uint i=0; i<n; i++) {
123  tmp = array[i] - m;
124  result += tmp * tmp * tmp;
125  }
126  result /= pow(v, (T)1.5);
127  return result;
128 }
129 
130 template <typename T> T skewness(const std::vector<T>& v) {
131  return skewness(&v.front(), v.size());
132 }
133 
138 template <typename T>
139 T kurtosis(const T* array, uint n) {
140  T m = mean(array, n);
141  T v = variance(array, n);
142  T tmp, result = 0.0;
143  for (uint i=0; i<n; i++) {
144  tmp = array[i] - m;
145  result += tmp * tmp * tmp * tmp;
146  }
147  result /= (v * v);
148  return result;
149 }
150 
151 template <typename T> T kurtosis(const std::vector<T>& v) {
152  return kurtosis(&v.front(), v.size());
153 }
154 
155 template <typename RandomAccessIterator>
156 void sort(RandomAccessIterator first, RandomAccessIterator last) {
157  return std::sort(first, last);
158 }
159 
160 template <typename RandomAccessIterator, typename StrictWeakOrdering>
161 void sort(RandomAccessIterator first, RandomAccessIterator last,
162  StrictWeakOrdering comp) {
163  return std::sort(first, last, comp);
164 }
165 
166 template <typename Container>
167 void sort(Container& container) {
168  return sort(container.begin(), container.end());
169 }
170 
171 
183 template <typename T>
184 void hist(const T* array, uint n, int* n_array, T* x_array, uint n_bins) {
185  T miny = *min_element(array, array+n);
186  T maxy = *max_element(array, array+n);
187 
188  // x contains the center of the bins
189  for (uint i=0; i<n_bins; i++) {
190  x_array[i] = (0.5 + i)*(maxy - miny)/n_bins + miny;
191  }
192 
193  // cutoff contains the boundaries between the bins
194  std::vector<T> cutoff(n_bins - 1);
195  for (uint i=0; i<n_bins-1; i++) {
196  cutoff[i] = (x_array[i] + x_array[i+1]) / 2.0;
197  }
198 
199  // algo: either build the cumulated histogram by 2-level
200  // for-loops, and then build the diff, or first
201  // sort the distribution and do it directly.
202  // 1st version: O(n^2) time, O(1) space
203  // 2nd version: O(n log(n)) time, O(n) space
204 
205  // implementation of 2nd version
206  std::vector<T> dist(array, array+n);
207  sort(dist.begin(), dist.end());
208  uint current_cutoff_idx = 0;
209  T current_cutoff = cutoff[0];
210  for (uint i=0; i<n_bins; i++) n_array[i] = 0;
211 
212  for (uint i=0; i<n; i++) {
213  while (dist[i] > current_cutoff) {
214  // last case; skip the rest and fill in the last bin
215  if (current_cutoff_idx == n_bins-2) {
216  n_array[n_bins-1] = n-i; // fill in the last bin with what's left
217  i = n; // to jump out of the 2nd loop (the 'for' one)
218  n_array[n_bins-2]--; // to compensate for the last one that will be added before jumping out of the loop
219  break;
220  }
221  current_cutoff_idx++;
222  current_cutoff = cutoff[current_cutoff_idx];
223  }
224  n_array[current_cutoff_idx]++;
225  }
226 }
227 
228 template <typename T>
229 T sgn(T x) { return x==0.0 ? 0.0 : (x<0.0 ? -1.0 : 1.0); }
230 
234 template <typename T>
235 T intpow(T x, int n) {
236  if (n < 0) throw GaiaException("intpow: power needs to be >= 1");
237  if (n == 0) return 1;
238 
239  T xn2 = intpow(x, n/2);
240 
241  if (n % 2 == 0)
242  return xn2*xn2;
243  else
244  return x * xn2*xn2;
245 }
246 
250 double erfinv(double P);
251 
255 double norminv(double P, double mu = 0, double sigma = 1);
256 
260 double chi2inv(double P, int v);
261 
269 template <template<typename> class Container, typename T>
270 int binarySearch(const Container<T>& v, T value) {
271  int start = 0, end = v.size()-1;
272 
273  if (value < v[0]) return 0;
274  if (value > v[end]) return end + 1;
275 
276  while ((end - start) > 1) {
277  uint pivotIdx = (start + end) / 2;
278  T pivot = v[pivotIdx];
279  if (value < pivot) {
280  end = pivotIdx;
281  }
282  else {
283  start = pivotIdx;
284  }
285  }
286 
287  return end;
288 }
289 
290 
291 // forward calls to sqrt from gaia2 to std, so we don't shadow sqrt with the
292 // specialization for the RealDescriptor
293 template <typename T> T sqrt(const T& x) {
294  return std::sqrt(x);
295 }
296 
300 inline Real clip(Real value, Real minv, Real maxv) {
301  return qMax(qMin(value, maxv), minv);
302 }
303 
304 
305 } // namespace gaia2
306 
307 #endif // GAIA_GAIAMATH_H
Real clip(Real value, Real minv, Real maxv)
Returns the given value clipped inside the specified interval.
Definition: gaiamath.h:300
double norminv(double P, double mu, double sigma)
Computes the inverse of the normal cdf with parameter mu and sigma.
Definition: gaiamath.cpp:30
T mean(const T *array, uint n)
Computes the mean of an array.
Definition: gaiamath.h:81
double erfinv(double P)
Computes the inverse error function (http://en.wikipedia.org/wiki/Error_function).
Definition: gaiamath.cpp:26
Definition: gaiamath.h:38
T variance(const T *array, uint n)
Computes the variance of an array.
Definition: gaiamath.h:98
int binarySearch(const Container< T > &v, T value)
Iterative function for binary search (more efficient than recursive one).
Definition: gaiamath.h:270
Main Gaia namespace, which contains all the library functions.
Definition: addfield.cpp:22
double chi2inv(double P, int v)
Computes the inverse of the chi-square cdf with v degrees of freedom.
Definition: gaiamath.cpp:34
T kurtosis(const T *array, uint n)
Computes the kurtosis of an array.
Definition: gaiamath.h:139
T skewness(const T *array, uint n)
Computes the skewness of an array.
Definition: gaiamath.h:118
Exception class that can take up to 3 arguments of any type, which will be serialized into a QString ...
Definition: gaiaexception.h:46
void hist(const T *array, uint n, int *n_array, T *x_array, uint n_bins)
Given a set of values, computes the associated histogram.
Definition: gaiamath.h:184
T intpow(T x, int n)
Computes the integral power n of x.
Definition: gaiamath.h:235