annotate maths/MathUtilities.cpp @ 348:50fae18236ee

Some (but not all) MathUtilities unit tests, and accompanying fixes
author Chris Cannam <c.cannam@qmul.ac.uk>
date Fri, 04 Oct 2013 18:34:30 +0100
parents 31f22daeba64
children a067c2eeb13c
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@348 19 #include <algorithm>
c@348 20 #include <vector>
c@241 21 #include <cmath>
c@241 22
c@241 23
c@241 24 double MathUtilities::mod(double x, double y)
c@241 25 {
c@241 26 double a = floor( x / y );
c@241 27
c@241 28 double b = x - ( y * a );
c@241 29 return b;
c@241 30 }
c@241 31
c@241 32 double MathUtilities::princarg(double ang)
c@241 33 {
c@241 34 double ValOut;
c@241 35
c@241 36 ValOut = mod( ang + M_PI, -2 * M_PI ) + M_PI;
c@241 37
c@241 38 return ValOut;
c@241 39 }
c@241 40
c@241 41 void MathUtilities::getAlphaNorm(const double *data, unsigned int len, unsigned int alpha, double* ANorm)
c@241 42 {
c@241 43 unsigned int i;
c@241 44 double temp = 0.0;
c@241 45 double a=0.0;
c@241 46
c@241 47 for( i = 0; i < len; i++)
c@241 48 {
c@241 49 temp = data[ i ];
c@241 50
c@304 51 a += ::pow( fabs(temp), double(alpha) );
c@241 52 }
c@241 53 a /= ( double )len;
c@241 54 a = ::pow( a, ( 1.0 / (double) alpha ) );
c@241 55
c@241 56 *ANorm = a;
c@241 57 }
c@241 58
c@241 59 double MathUtilities::getAlphaNorm( const std::vector <double> &data, unsigned int alpha )
c@241 60 {
c@241 61 unsigned int i;
c@241 62 unsigned int len = data.size();
c@241 63 double temp = 0.0;
c@241 64 double a=0.0;
c@241 65
c@241 66 for( i = 0; i < len; i++)
c@241 67 {
c@241 68 temp = data[ i ];
c@241 69
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@241 87 double MathUtilities::median(const double *src, unsigned int len)
c@241 88 {
c@348 89 if (len == 0) return 0;
c@348 90
c@348 91 std::vector<double> scratch;
c@348 92 for (int i = 0; i < len; ++i) scratch.push_back(src[i]);
c@348 93 std::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@241 103 double MathUtilities::sum(const double *src, unsigned int len)
c@241 104 {
c@241 105 unsigned 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@241 116 double MathUtilities::mean(const double *src, unsigned 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@279 129 double MathUtilities::mean(const std::vector<double> &src,
c@279 130 unsigned int start,
c@279 131 unsigned 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@241 145 void MathUtilities::getFrameMinMax(const double *data, unsigned int len, double *min, double *max)
c@241 146 {
c@241 147 unsigned 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@241 174 int MathUtilities::getMax( double* pData, unsigned int Length, double* pMax )
c@241 175 {
c@241 176 unsigned int index = 0;
c@241 177 unsigned 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@279 200 int MathUtilities::getMax( const std::vector<double> & data, double* pMax )
c@279 201 {
c@279 202 unsigned int index = 0;
c@279 203 unsigned int i;
c@279 204 double temp = 0.0;
c@279 205
c@279 206 double max = data[0];
c@279 207
c@279 208 for( i = 0; i < 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@259 289 void MathUtilities::normalise(std::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@279 320 void MathUtilities::adaptiveThreshold(std::vector<double> &data)
c@279 321 {
c@279 322 int sz = int(data.size());
c@279 323 if (sz == 0) return;
c@279 324
c@279 325 std::vector<double> smoothed(sz);
c@279 326
c@279 327 int p_pre = 8;
c@279 328 int p_post = 7;
c@279 329
c@279 330 for (int i = 0; i < sz; ++i) {
c@279 331
c@279 332 int first = std::max(0, i - p_pre);
c@279 333 int last = std::min(sz - 1, i + p_post);
c@279 334
c@279 335 smoothed[i] = mean(data, first, last - first + 1);
c@279 336 }
c@279 337
c@279 338 for (int i = 0; i < sz; i++) {
c@279 339 data[i] -= smoothed[i];
c@279 340 if (data[i] < 0.0) data[i] = 0.0;
c@279 341 }
c@279 342 }
c@259 343
c@280 344 bool
c@280 345 MathUtilities::isPowerOfTwo(int x)
c@280 346 {
c@348 347 if (x < 1) return false;
c@280 348 if (x & (x-1)) return false;
c@280 349 return true;
c@280 350 }
c@280 351
c@280 352 int
c@280 353 MathUtilities::nextPowerOfTwo(int x)
c@280 354 {
c@280 355 if (isPowerOfTwo(x)) return x;
c@348 356 if (x < 1) return 1;
c@280 357 int n = 1;
c@280 358 while (x) { x >>= 1; n <<= 1; }
c@280 359 return n;
c@280 360 }
c@280 361
c@280 362 int
c@280 363 MathUtilities::previousPowerOfTwo(int x)
c@280 364 {
c@280 365 if (isPowerOfTwo(x)) return x;
c@348 366 if (x < 1) return 1;
c@280 367 int n = 1;
c@280 368 x >>= 1;
c@280 369 while (x) { x >>= 1; n <<= 1; }
c@280 370 return n;
c@280 371 }
c@280 372
c@280 373 int
c@280 374 MathUtilities::nearestPowerOfTwo(int x)
c@280 375 {
c@280 376 if (isPowerOfTwo(x)) return x;
c@348 377 int n0 = previousPowerOfTwo(x), n1 = nextPowerOfTwo(x);
c@280 378 if (x - n0 < n1 - x) return n0;
c@280 379 else return n1;
c@280 380 }
c@280 381
c@348 382 int
c@348 383 MathUtilities::factorial(int x)
c@348 384 {
c@348 385 if (x < 0) return 0;
c@348 386 int f = 1;
c@348 387 for (int i = 1; i <= x; ++i) {
c@348 388 f = f * i;
c@348 389 }
c@348 390 return f;
c@348 391 }
c@348 392