annotate maths/MathUtilities.cpp @ 84:e5907ae6de17

* Add GPL and README; some tidying
author Chris Cannam
date Mon, 13 Dec 2010 14:55:28 +0000
parents 054c384d860d
children 37449f085a4c
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>
cannam@0 19 #include <cmath>
cannam@0 20
cannam@0 21
cannam@0 22 double MathUtilities::mod(double x, double y)
cannam@0 23 {
cannam@0 24 double a = floor( x / y );
cannam@0 25
cannam@0 26 double b = x - ( y * a );
cannam@0 27 return b;
cannam@0 28 }
cannam@0 29
cannam@0 30 double MathUtilities::princarg(double ang)
cannam@0 31 {
cannam@0 32 double ValOut;
cannam@0 33
cannam@0 34 ValOut = mod( ang + M_PI, -2 * M_PI ) + M_PI;
cannam@0 35
cannam@0 36 return ValOut;
cannam@0 37 }
cannam@0 38
cannam@0 39 void MathUtilities::getAlphaNorm(const double *data, unsigned int len, unsigned int alpha, double* ANorm)
cannam@0 40 {
cannam@0 41 unsigned int i;
cannam@0 42 double temp = 0.0;
cannam@0 43 double a=0.0;
cannam@0 44
cannam@0 45 for( i = 0; i < len; i++)
cannam@0 46 {
cannam@0 47 temp = data[ i ];
cannam@0 48
cannam@79 49 a += ::pow( fabs(temp), double(alpha) );
cannam@0 50 }
cannam@0 51 a /= ( double )len;
cannam@0 52 a = ::pow( a, ( 1.0 / (double) alpha ) );
cannam@0 53
cannam@0 54 *ANorm = a;
cannam@0 55 }
cannam@0 56
cannam@0 57 double MathUtilities::getAlphaNorm( const std::vector <double> &data, unsigned int alpha )
cannam@0 58 {
cannam@0 59 unsigned int i;
cannam@0 60 unsigned int len = data.size();
cannam@0 61 double temp = 0.0;
cannam@0 62 double a=0.0;
cannam@0 63
cannam@0 64 for( i = 0; i < len; i++)
cannam@0 65 {
cannam@0 66 temp = data[ i ];
cannam@0 67
cannam@79 68 a += ::pow( fabs(temp), double(alpha) );
cannam@0 69 }
cannam@0 70 a /= ( double )len;
cannam@0 71 a = ::pow( a, ( 1.0 / (double) alpha ) );
cannam@0 72
cannam@0 73 return a;
cannam@0 74 }
cannam@0 75
cannam@0 76 double MathUtilities::round(double x)
cannam@0 77 {
cannam@0 78 double val = (double)floor(x + 0.5);
cannam@0 79
cannam@0 80 return val;
cannam@0 81 }
cannam@0 82
cannam@0 83 double MathUtilities::median(const double *src, unsigned int len)
cannam@0 84 {
cannam@0 85 unsigned int i, j;
cannam@0 86 double tmp = 0.0;
cannam@0 87 double tempMedian;
cannam@0 88 double medianVal;
cannam@0 89
cannam@0 90 double* scratch = new double[ len ];//Vector < double > sortedX = Vector < double > ( size );
cannam@0 91
cannam@0 92 for ( i = 0; i < len; i++ )
cannam@0 93 {
cannam@0 94 scratch[i] = src[i];
cannam@0 95 }
cannam@0 96
cannam@0 97 for ( i = 0; i < len - 1; i++ )
cannam@0 98 {
cannam@0 99 for ( j = 0; j < len - 1 - i; j++ )
cannam@0 100 {
cannam@0 101 if ( scratch[j + 1] < scratch[j] )
cannam@0 102 {
cannam@0 103 // compare the two neighbors
cannam@0 104 tmp = scratch[j]; // swap a[j] and a[j+1]
cannam@0 105 scratch[j] = scratch[j + 1];
cannam@0 106 scratch[j + 1] = tmp;
cannam@0 107 }
cannam@0 108 }
cannam@0 109 }
cannam@0 110 int middle;
cannam@0 111 if ( len % 2 == 0 )
cannam@0 112 {
cannam@0 113 middle = len / 2;
cannam@0 114 tempMedian = ( scratch[middle] + scratch[middle - 1] ) / 2;
cannam@0 115 }
cannam@0 116 else
cannam@0 117 {
cannam@0 118 middle = ( int )floor( len / 2.0 );
cannam@0 119 tempMedian = scratch[middle];
cannam@0 120 }
cannam@0 121
cannam@0 122 medianVal = tempMedian;
cannam@0 123
cannam@0 124 delete [] scratch;
cannam@0 125 return medianVal;
cannam@0 126 }
cannam@0 127
cannam@0 128 double MathUtilities::sum(const double *src, unsigned int len)
cannam@0 129 {
cannam@0 130 unsigned int i ;
cannam@0 131 double retVal =0.0;
cannam@0 132
cannam@0 133 for( i = 0; i < len; i++)
cannam@0 134 {
cannam@0 135 retVal += src[ i ];
cannam@0 136 }
cannam@0 137
cannam@0 138 return retVal;
cannam@0 139 }
cannam@0 140
cannam@0 141 double MathUtilities::mean(const double *src, unsigned int len)
cannam@0 142 {
cannam@0 143 double retVal =0.0;
cannam@0 144
cannam@0 145 double s = sum( src, len );
cannam@0 146
cannam@0 147 retVal = s / (double)len;
cannam@0 148
cannam@0 149 return retVal;
cannam@0 150 }
cannam@0 151
cannam@54 152 double MathUtilities::mean(const std::vector<double> &src,
cannam@54 153 unsigned int start,
cannam@54 154 unsigned int count)
cannam@54 155 {
cannam@54 156 double sum = 0.;
cannam@54 157
cannam@54 158 for (int i = 0; i < count; ++i)
cannam@54 159 {
cannam@54 160 sum += src[start + i];
cannam@54 161 }
cannam@54 162
cannam@54 163 return sum / count;
cannam@54 164 }
cannam@54 165
cannam@0 166 void MathUtilities::getFrameMinMax(const double *data, unsigned int len, double *min, double *max)
cannam@0 167 {
cannam@0 168 unsigned int i;
cannam@0 169 double temp = 0.0;
cannam@0 170 double a=0.0;
cannam@58 171
cannam@58 172 if (len == 0) {
cannam@58 173 *min = *max = 0;
cannam@58 174 return;
cannam@58 175 }
cannam@0 176
cannam@0 177 *min = data[0];
cannam@0 178 *max = data[0];
cannam@0 179
cannam@0 180 for( i = 0; i < len; i++)
cannam@0 181 {
cannam@0 182 temp = data[ i ];
cannam@0 183
cannam@0 184 if( temp < *min )
cannam@0 185 {
cannam@0 186 *min = temp ;
cannam@0 187 }
cannam@0 188 if( temp > *max )
cannam@0 189 {
cannam@0 190 *max = temp ;
cannam@0 191 }
cannam@0 192
cannam@0 193 }
cannam@0 194 }
cannam@7 195
cannam@7 196 int MathUtilities::getMax( double* pData, unsigned int Length, double* pMax )
cannam@7 197 {
cannam@7 198 unsigned int index = 0;
cannam@7 199 unsigned int i;
cannam@7 200 double temp = 0.0;
cannam@7 201
cannam@7 202 double max = pData[0];
cannam@7 203
cannam@7 204 for( i = 0; i < Length; i++)
cannam@7 205 {
cannam@7 206 temp = pData[ i ];
cannam@7 207
cannam@7 208 if( temp > max )
cannam@7 209 {
cannam@7 210 max = temp ;
cannam@7 211 index = i;
cannam@7 212 }
cannam@7 213
cannam@7 214 }
cannam@7 215
cannam@54 216 if (pMax) *pMax = max;
cannam@54 217
cannam@54 218
cannam@54 219 return index;
cannam@54 220 }
cannam@54 221
cannam@54 222 int MathUtilities::getMax( const std::vector<double> & data, double* pMax )
cannam@54 223 {
cannam@54 224 unsigned int index = 0;
cannam@54 225 unsigned int i;
cannam@54 226 double temp = 0.0;
cannam@54 227
cannam@54 228 double max = data[0];
cannam@54 229
cannam@54 230 for( i = 0; i < data.size(); i++)
cannam@54 231 {
cannam@54 232 temp = data[ i ];
cannam@54 233
cannam@54 234 if( temp > max )
cannam@54 235 {
cannam@54 236 max = temp ;
cannam@54 237 index = i;
cannam@54 238 }
cannam@54 239
cannam@54 240 }
cannam@54 241
cannam@54 242 if (pMax) *pMax = max;
cannam@7 243
cannam@7 244
cannam@7 245 return index;
cannam@7 246 }
cannam@7 247
cannam@7 248 void MathUtilities::circShift( double* pData, int length, int shift)
cannam@7 249 {
cannam@7 250 shift = shift % length;
cannam@7 251 double temp;
cannam@7 252 int i,n;
cannam@7 253
cannam@7 254 for( i = 0; i < shift; i++)
cannam@7 255 {
cannam@7 256 temp=*(pData + length - 1);
cannam@7 257
cannam@7 258 for( n = length-2; n >= 0; n--)
cannam@7 259 {
cannam@7 260 *(pData+n+1)=*(pData+n);
cannam@7 261 }
cannam@7 262
cannam@7 263 *pData = temp;
cannam@7 264 }
cannam@7 265 }
cannam@7 266
cannam@7 267 int MathUtilities::compareInt (const void * a, const void * b)
cannam@7 268 {
cannam@7 269 return ( *(int*)a - *(int*)b );
cannam@7 270 }
cannam@7 271
cannam@34 272 void MathUtilities::normalise(double *data, int length, NormaliseType type)
cannam@34 273 {
cannam@34 274 switch (type) {
cannam@34 275
cannam@34 276 case NormaliseNone: return;
cannam@34 277
cannam@34 278 case NormaliseUnitSum:
cannam@34 279 {
cannam@34 280 double sum = 0.0;
cannam@34 281 for (int i = 0; i < length; ++i) {
cannam@34 282 sum += data[i];
cannam@34 283 }
cannam@34 284 if (sum != 0.0) {
cannam@34 285 for (int i = 0; i < length; ++i) {
cannam@34 286 data[i] /= sum;
cannam@34 287 }
cannam@34 288 }
cannam@34 289 }
cannam@34 290 break;
cannam@34 291
cannam@34 292 case NormaliseUnitMax:
cannam@34 293 {
cannam@34 294 double max = 0.0;
cannam@34 295 for (int i = 0; i < length; ++i) {
cannam@34 296 if (fabs(data[i]) > max) {
cannam@34 297 max = fabs(data[i]);
cannam@34 298 }
cannam@34 299 }
cannam@34 300 if (max != 0.0) {
cannam@34 301 for (int i = 0; i < length; ++i) {
cannam@34 302 data[i] /= max;
cannam@34 303 }
cannam@34 304 }
cannam@34 305 }
cannam@34 306 break;
cannam@34 307
cannam@34 308 }
cannam@34 309 }
cannam@34 310
cannam@34 311 void MathUtilities::normalise(std::vector<double> &data, NormaliseType type)
cannam@34 312 {
cannam@34 313 switch (type) {
cannam@34 314
cannam@34 315 case NormaliseNone: return;
cannam@34 316
cannam@34 317 case NormaliseUnitSum:
cannam@34 318 {
cannam@34 319 double sum = 0.0;
cannam@34 320 for (int i = 0; i < data.size(); ++i) sum += data[i];
cannam@34 321 if (sum != 0.0) {
cannam@34 322 for (int i = 0; i < data.size(); ++i) data[i] /= sum;
cannam@34 323 }
cannam@34 324 }
cannam@34 325 break;
cannam@34 326
cannam@34 327 case NormaliseUnitMax:
cannam@34 328 {
cannam@34 329 double max = 0.0;
cannam@34 330 for (int i = 0; i < data.size(); ++i) {
cannam@34 331 if (fabs(data[i]) > max) max = fabs(data[i]);
cannam@34 332 }
cannam@34 333 if (max != 0.0) {
cannam@34 334 for (int i = 0; i < data.size(); ++i) data[i] /= max;
cannam@34 335 }
cannam@34 336 }
cannam@34 337 break;
cannam@34 338
cannam@34 339 }
cannam@34 340 }
cannam@34 341
cannam@54 342 void MathUtilities::adaptiveThreshold(std::vector<double> &data)
cannam@54 343 {
cannam@54 344 int sz = int(data.size());
cannam@54 345 if (sz == 0) return;
cannam@54 346
cannam@54 347 std::vector<double> smoothed(sz);
cannam@54 348
cannam@54 349 int p_pre = 8;
cannam@54 350 int p_post = 7;
cannam@54 351
cannam@54 352 for (int i = 0; i < sz; ++i) {
cannam@54 353
cannam@54 354 int first = std::max(0, i - p_pre);
cannam@54 355 int last = std::min(sz - 1, i + p_post);
cannam@54 356
cannam@54 357 smoothed[i] = mean(data, first, last - first + 1);
cannam@54 358 }
cannam@54 359
cannam@54 360 for (int i = 0; i < sz; i++) {
cannam@54 361 data[i] -= smoothed[i];
cannam@54 362 if (data[i] < 0.0) data[i] = 0.0;
cannam@54 363 }
cannam@54 364 }
cannam@34 365
cannam@55 366 bool
cannam@55 367 MathUtilities::isPowerOfTwo(int x)
cannam@55 368 {
cannam@55 369 if (x < 2) return false;
cannam@55 370 if (x & (x-1)) return false;
cannam@55 371 return true;
cannam@55 372 }
cannam@55 373
cannam@55 374 int
cannam@55 375 MathUtilities::nextPowerOfTwo(int x)
cannam@55 376 {
cannam@55 377 if (isPowerOfTwo(x)) return x;
cannam@55 378 int n = 1;
cannam@55 379 while (x) { x >>= 1; n <<= 1; }
cannam@55 380 return n;
cannam@55 381 }
cannam@55 382
cannam@55 383 int
cannam@55 384 MathUtilities::previousPowerOfTwo(int x)
cannam@55 385 {
cannam@55 386 if (isPowerOfTwo(x)) return x;
cannam@55 387 int n = 1;
cannam@55 388 x >>= 1;
cannam@55 389 while (x) { x >>= 1; n <<= 1; }
cannam@55 390 return n;
cannam@55 391 }
cannam@55 392
cannam@55 393 int
cannam@55 394 MathUtilities::nearestPowerOfTwo(int x)
cannam@55 395 {
cannam@55 396 if (isPowerOfTwo(x)) return x;
cannam@55 397 int n0 = previousPowerOfTwo(x), n1 = nearestPowerOfTwo(x);
cannam@55 398 if (x - n0 < n1 - x) return n0;
cannam@55 399 else return n1;
cannam@55 400 }
cannam@55 401