comparison src/dsp/MathUtilities.cpp @ 119:a38d6940f8fb

Bring in dsp dependencies
author Chris Cannam <c.cannam@qmul.ac.uk>
date Thu, 15 May 2014 12:24:11 +0100
parents
children b87290781071
comparison
equal deleted inserted replaced
118:36bfbc606642 119:a38d6940f8fb
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 /*
3 Constant-Q library
4 Copyright (c) 2013-2014 Queen Mary, University of London
5
6 Permission is hereby granted, free of charge, to any person
7 obtaining a copy of this software and associated documentation
8 files (the "Software"), to deal in the Software without
9 restriction, including without limitation the rights to use, copy,
10 modify, merge, publish, distribute, sublicense, and/or sell copies
11 of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13
14 The above copyright notice and this permission notice shall be
15 included in all copies or substantial portions of the Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
21 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
22 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25 Except as contained in this notice, the names of the Centre for
26 Digital Music; Queen Mary, University of London; and Chris Cannam
27 shall not be used in advertising or otherwise to promote the sale,
28 use or other dealings in this Software without prior written
29 authorization.
30 */
31
32 #include "MathUtilities.h"
33
34 #include <iostream>
35 #include <algorithm>
36 #include <vector>
37 #include <cmath>
38
39
40 double MathUtilities::mod(double x, double y)
41 {
42 double a = floor( x / y );
43
44 double b = x - ( y * a );
45 return b;
46 }
47
48 double MathUtilities::princarg(double ang)
49 {
50 double ValOut;
51
52 ValOut = mod( ang + M_PI, -2 * M_PI ) + M_PI;
53
54 return ValOut;
55 }
56
57 void MathUtilities::getAlphaNorm(const double *data, unsigned int len, unsigned int alpha, double* ANorm)
58 {
59 unsigned int i;
60 double temp = 0.0;
61 double a=0.0;
62
63 for( i = 0; i < len; i++)
64 {
65 temp = data[ i ];
66
67 a += ::pow( fabs(temp), double(alpha) );
68 }
69 a /= ( double )len;
70 a = ::pow( a, ( 1.0 / (double) alpha ) );
71
72 *ANorm = a;
73 }
74
75 double MathUtilities::getAlphaNorm( const std::vector <double> &data, unsigned int alpha )
76 {
77 unsigned int i;
78 unsigned int len = data.size();
79 double temp = 0.0;
80 double a=0.0;
81
82 for( i = 0; i < len; i++)
83 {
84 temp = data[ i ];
85
86 a += ::pow( fabs(temp), double(alpha) );
87 }
88 a /= ( double )len;
89 a = ::pow( a, ( 1.0 / (double) alpha ) );
90
91 return a;
92 }
93
94 double MathUtilities::round(double x)
95 {
96 if (x < 0) {
97 return -floor(-x + 0.5);
98 } else {
99 return floor(x + 0.5);
100 }
101 }
102
103 double MathUtilities::median(const double *src, unsigned int len)
104 {
105 if (len == 0) return 0;
106
107 std::vector<double> scratch;
108 for (int i = 0; i < len; ++i) scratch.push_back(src[i]);
109 std::sort(scratch.begin(), scratch.end());
110
111 int middle = len/2;
112 if (len % 2 == 0) {
113 return (scratch[middle] + scratch[middle - 1]) / 2;
114 } else {
115 return scratch[middle];
116 }
117 }
118
119 double MathUtilities::sum(const double *src, unsigned int len)
120 {
121 unsigned int i ;
122 double retVal =0.0;
123
124 for( i = 0; i < len; i++)
125 {
126 retVal += src[ i ];
127 }
128
129 return retVal;
130 }
131
132 double MathUtilities::mean(const double *src, unsigned int len)
133 {
134 double retVal =0.0;
135
136 if (len == 0) return 0;
137
138 double s = sum( src, len );
139
140 retVal = s / (double)len;
141
142 return retVal;
143 }
144
145 double MathUtilities::mean(const std::vector<double> &src,
146 unsigned int start,
147 unsigned int count)
148 {
149 double sum = 0.;
150
151 if (count == 0) return 0;
152
153 for (int i = 0; i < (int)count; ++i)
154 {
155 sum += src[start + i];
156 }
157
158 return sum / count;
159 }
160
161 void MathUtilities::getFrameMinMax(const double *data, unsigned int len, double *min, double *max)
162 {
163 unsigned int i;
164 double temp = 0.0;
165
166 if (len == 0) {
167 *min = *max = 0;
168 return;
169 }
170
171 *min = data[0];
172 *max = data[0];
173
174 for( i = 0; i < len; i++)
175 {
176 temp = data[ i ];
177
178 if( temp < *min )
179 {
180 *min = temp ;
181 }
182 if( temp > *max )
183 {
184 *max = temp ;
185 }
186
187 }
188 }
189
190 int MathUtilities::getMax( double* pData, unsigned int Length, double* pMax )
191 {
192 unsigned int index = 0;
193 unsigned int i;
194 double temp = 0.0;
195
196 double max = pData[0];
197
198 for( i = 0; i < Length; i++)
199 {
200 temp = pData[ i ];
201
202 if( temp > max )
203 {
204 max = temp ;
205 index = i;
206 }
207
208 }
209
210 if (pMax) *pMax = max;
211
212
213 return index;
214 }
215
216 int MathUtilities::getMax( const std::vector<double> & data, double* pMax )
217 {
218 unsigned int index = 0;
219 unsigned int i;
220 double temp = 0.0;
221
222 double max = data[0];
223
224 for( i = 0; i < data.size(); i++)
225 {
226 temp = data[ i ];
227
228 if( temp > max )
229 {
230 max = temp ;
231 index = i;
232 }
233
234 }
235
236 if (pMax) *pMax = max;
237
238
239 return index;
240 }
241
242 void MathUtilities::circShift( double* pData, int length, int shift)
243 {
244 shift = shift % length;
245 double temp;
246 int i,n;
247
248 for( i = 0; i < shift; i++)
249 {
250 temp=*(pData + length - 1);
251
252 for( n = length-2; n >= 0; n--)
253 {
254 *(pData+n+1)=*(pData+n);
255 }
256
257 *pData = temp;
258 }
259 }
260
261 int MathUtilities::compareInt (const void * a, const void * b)
262 {
263 return ( *(int*)a - *(int*)b );
264 }
265
266 void MathUtilities::normalise(double *data, int length, NormaliseType type)
267 {
268 switch (type) {
269
270 case NormaliseNone: return;
271
272 case NormaliseUnitSum:
273 {
274 double sum = 0.0;
275 for (int i = 0; i < length; ++i) {
276 sum += data[i];
277 }
278 if (sum != 0.0) {
279 for (int i = 0; i < length; ++i) {
280 data[i] /= sum;
281 }
282 }
283 }
284 break;
285
286 case NormaliseUnitMax:
287 {
288 double max = 0.0;
289 for (int i = 0; i < length; ++i) {
290 if (fabs(data[i]) > max) {
291 max = fabs(data[i]);
292 }
293 }
294 if (max != 0.0) {
295 for (int i = 0; i < length; ++i) {
296 data[i] /= max;
297 }
298 }
299 }
300 break;
301
302 }
303 }
304
305 void MathUtilities::normalise(std::vector<double> &data, NormaliseType type)
306 {
307 switch (type) {
308
309 case NormaliseNone: return;
310
311 case NormaliseUnitSum:
312 {
313 double sum = 0.0;
314 for (int i = 0; i < (int)data.size(); ++i) sum += data[i];
315 if (sum != 0.0) {
316 for (int i = 0; i < (int)data.size(); ++i) data[i] /= sum;
317 }
318 }
319 break;
320
321 case NormaliseUnitMax:
322 {
323 double max = 0.0;
324 for (int i = 0; i < (int)data.size(); ++i) {
325 if (fabs(data[i]) > max) max = fabs(data[i]);
326 }
327 if (max != 0.0) {
328 for (int i = 0; i < (int)data.size(); ++i) data[i] /= max;
329 }
330 }
331 break;
332
333 }
334 }
335
336 void MathUtilities::adaptiveThreshold(std::vector<double> &data)
337 {
338 int sz = int(data.size());
339 if (sz == 0) return;
340
341 std::vector<double> smoothed(sz);
342
343 int p_pre = 8;
344 int p_post = 7;
345
346 for (int i = 0; i < sz; ++i) {
347
348 int first = std::max(0, i - p_pre);
349 int last = std::min(sz - 1, i + p_post);
350
351 smoothed[i] = mean(data, first, last - first + 1);
352 }
353
354 for (int i = 0; i < sz; i++) {
355 data[i] -= smoothed[i];
356 if (data[i] < 0.0) data[i] = 0.0;
357 }
358 }
359
360 bool
361 MathUtilities::isPowerOfTwo(int x)
362 {
363 if (x < 1) return false;
364 if (x & (x-1)) return false;
365 return true;
366 }
367
368 int
369 MathUtilities::nextPowerOfTwo(int x)
370 {
371 if (isPowerOfTwo(x)) return x;
372 if (x < 1) return 1;
373 int n = 1;
374 while (x) { x >>= 1; n <<= 1; }
375 return n;
376 }
377
378 int
379 MathUtilities::previousPowerOfTwo(int x)
380 {
381 if (isPowerOfTwo(x)) return x;
382 if (x < 1) return 1;
383 int n = 1;
384 x >>= 1;
385 while (x) { x >>= 1; n <<= 1; }
386 return n;
387 }
388
389 int
390 MathUtilities::nearestPowerOfTwo(int x)
391 {
392 if (isPowerOfTwo(x)) return x;
393 int n0 = previousPowerOfTwo(x), n1 = nextPowerOfTwo(x);
394 if (x - n0 < n1 - x) return n0;
395 else return n1;
396 }
397
398 double
399 MathUtilities::factorial(int x)
400 {
401 if (x < 0) return 0;
402 double f = 1;
403 for (int i = 1; i <= x; ++i) {
404 f = f * i;
405 }
406 return f;
407 }
408
409 int
410 MathUtilities::gcd(int a, int b)
411 {
412 int c = a % b;
413 if (c == 0) {
414 return b;
415 } else {
416 return gcd(b, c);
417 }
418 }
419