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