annotate maths/MathUtilities.cpp @ 209:ccd2019190bf msvc

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