annotate constant-q-cpp/src/dsp/MathUtilities.cpp @ 372:af71cbdab621 tip

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