annotate maths/MathUtilities.cpp @ 309:d5014ab8b0e5

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