MathUtilities.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  QM DSP Library
5 
6  Centre for Digital Music, Queen Mary, University of London.
7  This file 2005-2006 Christian Landone.
8 
9  This program is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 2 of the
12  License, or (at your option) any later version. See the file
13  COPYING included with this distribution for more information.
14 */
15 
16 #include "MathUtilities.h"
17 
18 #include <iostream>
19 #include <algorithm>
20 #include <vector>
21 #include <cmath>
22 
23 using namespace std;
24 
25 double MathUtilities::mod(double x, double y)
26 {
27  double a = floor( x / y );
28 
29  double b = x - ( y * a );
30  return b;
31 }
32 
33 double MathUtilities::princarg(double ang)
34 {
35  double ValOut;
36 
37  ValOut = mod( ang + M_PI, -2 * M_PI ) + M_PI;
38 
39  return ValOut;
40 }
41 
42 void MathUtilities::getAlphaNorm(const double *data, int len, int alpha, double* ANorm)
43 {
44  int i;
45  double temp = 0.0;
46  double a=0.0;
47 
48  for( i = 0; i < len; i++) {
49  temp = data[ i ];
50  a += ::pow( fabs(temp), double(alpha) );
51  }
52  a /= ( double )len;
53  a = ::pow( a, ( 1.0 / (double) alpha ) );
54 
55  *ANorm = a;
56 }
57 
58 double MathUtilities::getAlphaNorm( const vector <double> &data, int alpha )
59 {
60  int i;
61  int len = data.size();
62  double temp = 0.0;
63  double a=0.0;
64 
65  for( i = 0; i < len; i++) {
66  temp = data[ i ];
67  a += ::pow( fabs(temp), double(alpha) );
68  }
69  a /= ( double )len;
70  a = ::pow( a, ( 1.0 / (double) alpha ) );
71 
72  return a;
73 }
74 
75 double MathUtilities::round(double x)
76 {
77  if (x < 0) {
78  return -floor(-x + 0.5);
79  } else {
80  return floor(x + 0.5);
81  }
82 }
83 
84 double MathUtilities::median(const double *src, int len)
85 {
86  if (len == 0) return 0;
87 
88  vector<double> scratch;
89  for (int i = 0; i < len; ++i) scratch.push_back(src[i]);
90  sort(scratch.begin(), scratch.end());
91 
92  int middle = len/2;
93  if (len % 2 == 0) {
94  return (scratch[middle] + scratch[middle - 1]) / 2;
95  } else {
96  return scratch[middle];
97  }
98 }
99 
100 double MathUtilities::sum(const double *src, int len)
101 {
102  int i ;
103  double retVal =0.0;
104 
105  for( i = 0; i < len; i++) {
106  retVal += src[ i ];
107  }
108 
109  return retVal;
110 }
111 
112 double MathUtilities::mean(const double *src, int len)
113 {
114  double retVal =0.0;
115 
116  if (len == 0) return 0;
117 
118  double s = sum( src, len );
119 
120  retVal = s / (double)len;
121 
122  return retVal;
123 }
124 
125 double MathUtilities::mean(const vector<double> &src,
126  int start,
127  int count)
128 {
129  double sum = 0.;
130 
131  if (count == 0) return 0;
132 
133  for (int i = 0; i < (int)count; ++i) {
134  sum += src[start + i];
135  }
136 
137  return sum / count;
138 }
139 
140 void MathUtilities::getFrameMinMax(const double *data, int len, double *min, double *max)
141 {
142  int i;
143  double temp = 0.0;
144 
145  if (len == 0) {
146  *min = *max = 0;
147  return;
148  }
149 
150  *min = data[0];
151  *max = data[0];
152 
153  for( i = 0; i < len; i++) {
154  temp = data[ i ];
155 
156  if( temp < *min ) {
157  *min = temp ;
158  }
159  if( temp > *max ) {
160  *max = temp ;
161  }
162  }
163 }
164 
165 int MathUtilities::getMax( double* pData, int Length, double* pMax )
166 {
167  int index = 0;
168  int i;
169  double temp = 0.0;
170 
171  double max = pData[0];
172 
173  for( i = 0; i < Length; i++) {
174  temp = pData[ i ];
175 
176  if( temp > max ) {
177  max = temp ;
178  index = i;
179  }
180  }
181 
182  if (pMax) *pMax = max;
183 
184 
185  return index;
186 }
187 
188 int MathUtilities::getMax( const vector<double> & data, double* pMax )
189 {
190  int index = 0;
191  int i;
192  double temp = 0.0;
193 
194  double max = data[0];
195 
196  for( i = 0; i < int(data.size()); i++) {
197 
198  temp = data[ i ];
199 
200  if( temp > max ) {
201  max = temp ;
202  index = i;
203  }
204  }
205 
206  if (pMax) *pMax = max;
207 
208 
209  return index;
210 }
211 
212 void MathUtilities::circShift( double* pData, int length, int shift)
213 {
214  shift = shift % length;
215  double temp;
216  int i,n;
217 
218  for( i = 0; i < shift; i++) {
219 
220  temp=*(pData + length - 1);
221 
222  for( n = length-2; n >= 0; n--) {
223  *(pData+n+1)=*(pData+n);
224  }
225 
226  *pData = temp;
227  }
228 }
229 
230 int MathUtilities::compareInt (const void * a, const void * b)
231 {
232  return ( *(int*)a - *(int*)b );
233 }
234 
235 void MathUtilities::normalise(double *data, int length, NormaliseType type)
236 {
237  switch (type) {
238 
239  case NormaliseNone: return;
240 
241  case NormaliseUnitSum:
242  {
243  double sum = 0.0;
244  for (int i = 0; i < length; ++i) {
245  sum += data[i];
246  }
247  if (sum != 0.0) {
248  for (int i = 0; i < length; ++i) {
249  data[i] /= sum;
250  }
251  }
252  }
253  break;
254 
255  case NormaliseUnitMax:
256  {
257  double max = 0.0;
258  for (int i = 0; i < length; ++i) {
259  if (fabs(data[i]) > max) {
260  max = fabs(data[i]);
261  }
262  }
263  if (max != 0.0) {
264  for (int i = 0; i < length; ++i) {
265  data[i] /= max;
266  }
267  }
268  }
269  break;
270 
271  }
272 }
273 
274 void MathUtilities::normalise(vector<double> &data, NormaliseType type)
275 {
276  switch (type) {
277 
278  case NormaliseNone: return;
279 
280  case NormaliseUnitSum:
281  {
282  double sum = 0.0;
283  for (int i = 0; i < (int)data.size(); ++i) sum += data[i];
284  if (sum != 0.0) {
285  for (int i = 0; i < (int)data.size(); ++i) data[i] /= sum;
286  }
287  }
288  break;
289 
290  case NormaliseUnitMax:
291  {
292  double max = 0.0;
293  for (int i = 0; i < (int)data.size(); ++i) {
294  if (fabs(data[i]) > max) max = fabs(data[i]);
295  }
296  if (max != 0.0) {
297  for (int i = 0; i < (int)data.size(); ++i) data[i] /= max;
298  }
299  }
300  break;
301 
302  }
303 }
304 
305 double MathUtilities::getLpNorm(const vector<double> &data, int p)
306 {
307  double tot = 0.0;
308  for (int i = 0; i < int(data.size()); ++i) {
309  tot += abs(pow(data[i], p));
310  }
311  return pow(tot, 1.0 / p);
312 }
313 
314 vector<double> MathUtilities::normaliseLp(const vector<double> &data,
315  int p,
316  double threshold)
317 {
318  int n = int(data.size());
319  if (n == 0 || p == 0) return data;
320  double norm = getLpNorm(data, p);
321  if (norm < threshold) {
322  return vector<double>(n, 1.0 / pow(n, 1.0 / p)); // unit vector
323  }
324  vector<double> out(n);
325  for (int i = 0; i < n; ++i) {
326  out[i] = data[i] / norm;
327  }
328  return out;
329 }
330 
331 void MathUtilities::adaptiveThreshold(vector<double> &data)
332 {
333  int sz = int(data.size());
334  if (sz == 0) return;
335 
336  vector<double> smoothed(sz);
337 
338  int p_pre = 8;
339  int p_post = 7;
340 
341  for (int i = 0; i < sz; ++i) {
342 
343  int first = max(0, i - p_pre);
344  int last = min(sz - 1, i + p_post);
345 
346  smoothed[i] = mean(data, first, last - first + 1);
347  }
348 
349  for (int i = 0; i < sz; i++) {
350  data[i] -= smoothed[i];
351  if (data[i] < 0.0) data[i] = 0.0;
352  }
353 }
354 
355 bool
357 {
358  if (x < 1) return false;
359  if (x & (x-1)) return false;
360  return true;
361 }
362 
363 int
365 {
366  if (isPowerOfTwo(x)) return x;
367  if (x < 1) return 1;
368  int n = 1;
369  while (x) { x >>= 1; n <<= 1; }
370  return n;
371 }
372 
373 int
375 {
376  if (isPowerOfTwo(x)) return x;
377  if (x < 1) return 1;
378  int n = 1;
379  x >>= 1;
380  while (x) { x >>= 1; n <<= 1; }
381  return n;
382 }
383 
384 int
386 {
387  if (isPowerOfTwo(x)) return x;
388  int n0 = previousPowerOfTwo(x);
389  int n1 = nextPowerOfTwo(x);
390  if (x - n0 < n1 - x) return n0;
391  else return n1;
392 }
393 
394 double
396 {
397  if (x < 0) return 0;
398  double f = 1;
399  for (int i = 1; i <= x; ++i) {
400  f = f * i;
401  }
402  return f;
403 }
404 
405 int
406 MathUtilities::gcd(int a, int b)
407 {
408  int c = a % b;
409  if (c == 0) {
410  return b;
411  } else {
412  return gcd(b, c);
413  }
414 }
415 
static void adaptiveThreshold(std::vector< double > &data)
Threshold the input/output vector data against a moving-mean average filter.
static void circShift(double *data, int length, int shift)
static double mod(double x, double y)
Floating-point division modulus: return x % y.
static double sum(const double *src, int len)
Return the sum of the values in the given array of the given length.
static double princarg(double ang)
The principle argument function.
static int getMax(double *data, int length, double *max=0)
static void getFrameMinMax(const double *data, int len, double *min, double *max)
Return through min and max pointers the highest and lowest values in the given array of the given len...
static double factorial(int x)
Return x!
static int nextPowerOfTwo(int x)
Return the next higher integer power of two from x, e.g.
static int compareInt(const void *a, const void *b)
static double getLpNorm(const std::vector< double > &data, int p)
Calculate the L^p norm of a vector.
static bool isPowerOfTwo(int x)
Return true if x is 2^n for some integer n >= 0.
static int previousPowerOfTwo(int x)
Return the next lower integer power of two from x, e.g.
static int gcd(int a, int b)
Return the greatest common divisor of natural numbers a and b.
static void getAlphaNorm(const double *data, int len, int alpha, double *ANorm)
The alpha norm is the alpha&#39;th root of the mean alpha&#39;th power magnitude.
static int nearestPowerOfTwo(int x)
Return the nearest integer power of two to x, e.g.
static double median(const double *src, int len)
Return the median of the values in the given array of the given length.
static double round(double x)
Round x to the nearest integer.
static double mean(const double *src, int len)
Return the mean of the given array of the given length.
static void normalise(double *data, int length, NormaliseType n=NormaliseUnitMax)
static std::vector< double > normaliseLp(const std::vector< double > &data, int p, double threshold=1e-6)
Normalise a vector by dividing through by its L^p norm.