00001 #ifndef GAMMA_ARR_H_INC
00002 #define GAMMA_ARR_H_INC
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <math.h>
00012 #include <string.h>
00013 #include "Gamma/ipl.h"
00014 #include "Gamma/mem.h"
00015 #include "Gamma/scl.h"
00016 #include "Gamma/Containers.h"
00017
00018 #define LOOP(n,s) for(uint32_t i=0; i<n; i+=s)
00019 #define TEM template <class T>
00020
00021 namespace gam{
00022
00024
00035 namespace arr{
00036
00038 TEM void add(T * dst, const T * src, uint32_t len, uint32_t str=1){
00039 LOOP(len,str){ dst[i] += src[i]; }
00040 }
00041
00043 TEM void add(T * dst, const T * src1, const T * src2, uint32_t len, uint32_t str=1){
00044 LOOP(len,str){ dst[i] = src1[i] + src2[i]; }
00045 }
00046
00048
00051 TEM uint32_t addToRing(T * ring, uint32_t ringSize, uint32_t ringTap, const T * src, uint32_t len);
00052
00054 void clip1(float * arr, uint32_t len, uint32_t str=1);
00055
00057
00064 TEM void cluster(const T * src, uint32_t * indices, uint32_t& numIndices, T threshold);
00065
00066 void compact(float * dst, const float * src, uint32_t len, uint32_t chunkSize);
00067
00069 TEM inline T dot(const T * src1, const T * src2, uint32_t len, uint32_t str=1){
00070 T r=T(0); LOOP(len, str){ r += src1[i]*src2[i]; } return r;
00071 }
00072
00074 TEM T dot4(const T * src1, const T * src2);
00075
00077 TEM void extrema(const T * src, uint32_t len, uint32_t& indexMin, uint32_t& indexMax);
00078
00080
00083 template <class T1, class T2, class T3>
00084 void fitLine(const T1 * src, uint32_t len, T2& slope, T3& inter);
00085
00087
00092 template <class Ts, class Tb>
00093 void histogram(const Ts * src, uint32_t len, Tb * bins, uint32_t numBins, Ts scale=1);
00094
00095 template <class Ts, class Tb>
00096 void histogram(const Ts * src, uint32_t len, Tb * bins, uint32_t numBins, Ts scale, Ts offset);
00097
00099 TEM uint32_t indexOfMax(const T * src, uint32_t len, uint32_t str=1);
00100
00102 TEM uint32_t indexOfMaxNorm(const T * src, uint32_t len, uint32_t str=1);
00103
00105 TEM uint32_t indexOfMin(const T * src, uint32_t len);
00106
00108
00111 void indicesComplement(uint32_t * indices, uint32_t numIndices, uint32_t maxNumIndices);
00112
00114 void linToDB(float * arr, uint32_t len, float minDB);
00115
00117
00120 TEM uint32_t maxima(uint32_t * dst, const T * src, uint32_t len, uint32_t str=1);
00121
00123 TEM T mean(const T * src, uint32_t len, uint32_t str=1);
00124
00126 TEM inline T meanNorm(const T * src, uint32_t len, uint32_t str=1){
00127 T r=T(0); LOOP(len,str){ r += gam::norm(src[i]); } return r / T(len/str);
00128 }
00129
00131 TEM T meanAbsDiff(const T * src, uint32_t len);
00132
00134
00137 TEM T meanWeighted(const T * src, T * weights, uint32_t len);
00138
00140
00143 TEM T meanWeightedIndex(const T * weights, uint32_t len);
00144
00145 TEM void minimaRemove(const T * src, uint32_t * indices, uint32_t& numIndices);
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00157
00161 TEM void mirror_dp(T * arr, uint32_t len);
00162
00164
00168 TEM void mirror_dq(T * arr, uint32_t len);
00169
00171 TEM void mul(T * dst, const T * src, uint32_t len, uint32_t str=1){
00172 LOOP(len,str){ dst[i] *= src[i]; }
00173 }
00174
00176
00179 TEM void mulBartlett(T * arr, uint32_t len);
00180
00183 TEM void mulHalfWindow(T * arr, const T * src, uint32_t len);
00184
00186
00189 TEM double normalize(T * arr, uint32_t len, double scale=1);
00190
00191 template<class T, template<class> class ArrayType>
00192 double inline normalize(ArrayType<T>& arr, double scale=1){
00193 return normalize(&arr[0], arr.size(), scale);
00194 }
00195
00197 TEM double norm(const T * src, uint32_t len, uint32_t str=1){
00198 return sqrt((double)sumSquares(src, len,str));
00199 }
00200
00202 TEM double normTaxi(const T * src, uint32_t len, uint32_t str=1){
00203 double r=0; LOOP(len,str){ r+=gam::norm(src[i]); } return r;
00204 }
00205
00207 TEM inline T nyquist(const T * src, uint32_t len, uint32_t str=1){
00208 T r=T(0); LOOP(len,(str<<1)){ r += src[i] - src[i+str]; } return r;
00209 }
00210
00212 TEM inline T rms(const T * src, uint32_t len, uint32_t str=1){
00213 return norm(src, len,str) / T(len/str);
00214 }
00215
00217 TEM uint32_t slopeAbsMax(const T * src, uint32_t len);
00218
00220 TEM uint32_t slopeMax(const T * src, uint32_t len);
00221
00223
00226 TEM void sortInsertion(T * arr, uint32_t len);
00227
00229
00232 TEM void sortInsertion(const T * src, uint32_t * indices, uint32_t numIndices);
00233
00235
00238 TEM void sortQuick(const T * src, uint32_t * indices, long beg, long end);
00239
00241 TEM T sum(const T * src, uint32_t len, uint32_t str=1);
00242
00244 TEM inline T sumSquares(const T * src, uint32_t len, uint32_t str=1){
00245 return dot(src,src,len,str);
00246 }
00247
00249 TEM T variance(const T * src, uint32_t len, uint32_t str=1);
00250
00252 TEM uint32_t within(const T * src, uint32_t len, T threshold);
00253
00255 TEM uint32_t within(const T * src, uint32_t len, T lo, T hi);
00256
00258 TEM uint32_t zeroCount(const T * src, uint32_t len, uint32_t str=1);
00259
00261
00264 uint32_t zeroCross(const float * src, uint32_t len, float prev);
00265
00266 TEM void zeroCross(const T * src, uint32_t len, uint32_t& nzc, uint32_t& pzc);
00267
00269 uint32_t zeroCrossFirst(const float * src, uint32_t len);
00270
00271 TEM uint32_t zeroCrossMax(const T * src, uint32_t len);
00272
00274
00277 uint32_t zeroCrossN(const float * src, uint32_t len, float prev);
00278
00279
00280
00281
00282
00283
00284 TEM uint32_t addToRing(T * ring, uint32_t ringSize, uint32_t ringTap, const T * src, uint32_t len){
00285 uint32_t endTap = ringTap + len;
00286
00287 if(endTap <= ringSize){
00288 add(ring + ringTap, src, len);
00289 }
00290 else{
00291 uint32_t samplesUnder = ringSize - ringTap;
00292 uint32_t samplesOver = endTap - ringSize;
00293 add(ring + ringTap, src, samplesUnder);
00294 add(ring, src + samplesUnder, samplesOver);
00295 }
00296 return endTap;
00297 }
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314 TEM inline void mirror_dp(T * arr, uint32_t len){
00315 T * arr2 = arr + len - 1;
00316 LOOP(len, 2){ *arr2-- = -*arr++; }
00317 }
00318
00319 TEM inline void mirror_dq(T * arr, uint32_t len){
00320 T * arr2 = arr + (len>>1);
00321 LOOP(len, 2){ *arr2++ = -*arr++; }
00322 }
00323
00324 TEM inline void mulBartlett(T * arr, uint32_t len){
00325 T * end = arr + len - 1;
00326 uint32_t len_2 = len >> 1;
00327 const T slope = (T)1. / (T)len_2;
00328 T line = slope;
00329
00330 *arr++ = (T)0;
00331 LOOP(len_2 - 1, 1){
00332 *arr++ *= line;
00333 *end-- *= line;
00334 line += slope;
00335 }
00336 }
00337
00338 TEM inline void mulHalfWindow(T * arr, const T * src, uint32_t len){
00339 T * end = arr + len - 1;
00340 len >>= 1;
00341
00342 *arr++ *= *src++;
00343 LOOP(len - 1, 1){
00344 const T val = *src++;
00345 *arr++ *= val;
00346 *end-- *= val;
00347 }
00348 *arr *= *src;
00349 }
00350
00351 TEM double normalize(T * arr, uint32_t len, double scale){
00352 double max = gam::norm(arr[indexOfMaxNorm(arr, len)]);
00353 double normFactor = scale/max;
00354 if(max != 0.){ for(uint32_t i=0; i<len; ++i){ arr[i]*=normFactor; } }
00355 return normFactor;
00356 }
00357
00358 TEM void cluster(const T * src, uint32_t * indices, uint32_t & numIndices, T threshold){
00359
00360 if(numIndices == 0) return;
00361
00362 uint32_t * newIndices = indices;
00363 uint32_t newNumIndices = 0;
00364
00365 T prev = src[*indices++];
00366 bool inCluster = false;
00367
00368 LOOP(numIndices - 1, 1){
00369 uint32_t index = *indices++;
00370 T curr = src[index];
00371
00372 if( fabs(curr - prev) <= threshold ){
00373
00374 if(!inCluster){
00375
00376 *newIndices++ = indices[-2];
00377 newNumIndices++;
00378 }
00379
00380
00381 *newIndices++ = index;
00382 newNumIndices++;
00383
00384 inCluster = true;
00385 }
00386 else{
00387 inCluster = false;
00388 }
00389
00390 prev = curr;
00391 }
00392
00393 numIndices = newNumIndices;
00394 }
00395
00396 TEM inline T dot4(const T * a, const T * b){
00397 return a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3];
00398 }
00399
00400 TEM void extrema(const T * src, uint32_t len, uint32_t& idxMin, uint32_t& idxMax){
00401 idxMin = 0;
00402 idxMax = 0;
00403
00404 T min = *src++;
00405 T max = min;
00406
00407 for(uint32_t i = 1; i < len; i++){
00408 T val = *src++;
00409 if(val > max){
00410 max = val;
00411 idxMax = i;
00412 }
00413 else if(val < min){
00414 min = val;
00415 idxMin = i;
00416 }
00417 }
00418 }
00419
00420
00421
00422
00423
00424
00425 template <class T, class T2, class T3>
00426 inline void fitLine(const T * src, uint32_t len, T2& slope, T3& inter){
00427 T lenT = T(len);
00428 T meanX = (lenT - T(1)) * T(0.5);
00429 T meanY = sum(src, len) / lenT;
00430 T sumSqrs = meanX*(meanX+T(1))*(meanX*T(2./6) + T(1./6));
00431 T varX = T(2)*sumSqrs;
00432
00433 T cov = T(0);
00434 T dx =-meanX;
00435
00436 LOOP(len, 1){
00437 cov += dx++ * (*src++ - meanY);
00438 }
00439
00440 slope = cov / varX;
00441 inter = meanY - slope * meanX;
00442 }
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466 template <class Ts, class Tb>
00467 inline void histogram(const Ts * src, uint32_t len, Tb * bins, uint32_t numBins, Ts scale){
00468 LOOP(len, 1){
00469 int32_t j = (int32_t)(src[i] * scale);
00470 if(j >= 0 && j < (int32_t)numBins) bins[j]++;
00471 }
00472 }
00473
00474 template <class Ts, class Tb>
00475 inline void histogram(const Ts * src, uint32_t len, Tb * bins, uint32_t numBins, Ts scale, Ts offset){
00476 LOOP(len, 1){
00477 int32_t j = (int32_t)(src[i] * scale + offset);
00478 if(j >= 0 && j < (int32_t)numBins) bins[j]++;
00479 }
00480 }
00481
00482 TEM uint32_t indexOfMax(const T * src, uint32_t len, uint32_t str){
00483 uint32_t r=0;
00484 T max = src[0];
00485 for(uint32_t i=str; i<len; i+=str){
00486 const T& v = src[i];
00487 if(v > max){ max=v; r=i; }
00488 }
00489 return r;
00490 }
00491
00492 TEM uint32_t indexOfMaxNorm(const T * src, uint32_t len, uint32_t str){
00493 uint32_t r = 0;
00494 double max = normCompare(src[0]);
00495 for(uint32_t i=str; i<len; i+=str){
00496 double v = normCompare(src[i]);
00497 if(v > max){ max=v; r=i; }
00498 }
00499 return r;
00500 }
00501
00502 TEM uint32_t indexOfMin(const T * src, uint32_t len){
00503 uint32_t index = 0;
00504 T min = src[0];
00505
00506 for(uint32_t i=1; i<len; i++){
00507 T val = src[i];
00508 if(val < min){
00509 min = val;
00510 index = i;
00511 }
00512 }
00513 return index;
00514 }
00515
00516 TEM uint32_t maxima(uint32_t * dst, const T * src, uint32_t len, uint32_t str){
00517 T prev = src[0];
00518 T curr = src[str];
00519
00520 uint32_t numPeaks = 0;
00521
00522 for(uint32_t i=(str<<1); i<len; i+=str){
00523 T next = src[i];
00524
00525 if(curr > prev && curr > next){
00526 *dst++ = i-str;
00527 numPeaks++;
00528 i+=str;
00529 if(i<len){
00530 prev = next;
00531 curr = src[i];
00532 }
00533 }
00534 else{
00535 prev = curr;
00536 curr = next;
00537 }
00538 }
00539 return numPeaks;
00540 }
00541
00542
00543 TEM inline T mean(const T * src, uint32_t len, uint32_t str){
00544 return arr::sum(src, len, str) / T(len/str);
00545 }
00546
00547
00548 TEM T meanAbsDiff(const T * src, uint32_t len){
00549 T sum = (T)0;
00550 T mean = (T)0;
00551
00552 T prev = *src++;
00553 LOOP(len - 1, 1){
00554 T now = *src++;
00555 T diff = now - prev;
00556 T abs = scl::abs(now);
00557 sum += scl::abs(diff);
00558 mean += abs;
00559 prev = now;
00560 }
00561
00562 return mean < T(0.25) ? T(-1) : sum * T(0.5) / mean;
00563
00564 }
00565
00566 TEM T meanWeighted(const T * src, T * weights, uint32_t len){
00567 T mean = (T)0;
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577 T normFactor = (T)1 / sum(weights, len);
00578 LOOP(len,1){ mean += *src++ * *weights++ * normFactor; }
00579 return mean;
00580 }
00581
00582 TEM T meanWeightedIndex(const T * weights, uint32_t len){
00583 T mean = (T)0;
00584 T normFactor = sum(weights, len);
00585 if(normFactor == (T)0) return (T)0;
00586 normFactor = (T)1 / normFactor;
00587 T weightFactor = normFactor;
00588 LOOP(len,1){
00589 mean += *weights++ * weightFactor;
00590 weightFactor += normFactor;
00591 }
00592 return mean;
00593 }
00594
00595 TEM void minimaRemove(const T * src, uint32_t * indices, uint32_t & numIndices){
00596
00597 if(numIndices < 3) return;
00598
00599 uint32_t * newIndices = indices + 1;
00600 uint32_t newNumIndices = 2;
00601
00602 T prev = src[*indices++];
00603 T curr = src[*indices++];
00604
00605 for(uint32_t i=1; i<numIndices-1; i++){
00606 uint32_t index = *indices++;
00607 T next = src[index];
00608
00609 if(curr >= prev || curr >= next){
00610 *newIndices++ = indices[-2];
00611 newNumIndices++;
00612 }
00613
00614 prev = curr;
00615 curr = next;
00616 }
00617
00618 *newIndices = *--indices;
00619 numIndices = newNumIndices;
00620 }
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659 TEM uint32_t slopeAbsMax(const T * src, uint32_t len){
00660 uint32_t index = 0;
00661 T prev = *src++;
00662 T maxSlope = (T)0;
00663
00664 LOOP(len-1,1){
00665 T now = *src++;
00666 T slope = scl::abs(now - prev);
00667 if(slope > maxSlope){
00668 maxSlope = slope;
00669 index = i;
00670 }
00671 prev = now;
00672 }
00673 return index;
00674 }
00675
00676 TEM uint32_t slopeMax(const T * src, uint32_t len){
00677 uint32_t index = 0;
00678 T prev = *src++;
00679 T maxSlope = (T)0;
00680
00681 for(uint32_t i=0; i<len-1; ++i){
00682 T now = *src++;
00683 T slope = now - prev;
00684 if(slope > maxSlope){
00685 maxSlope = slope;
00686 index = i;
00687 }
00688 prev = now;
00689 }
00690 return index;
00691 }
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703 TEM void sortInsertion(T * arr, uint32_t len){
00704 for(uint32_t i = 1; i < len; i++){
00705 T val = arr[i];
00706 uint32_t j = i - 1;
00707 for(; (j < len) && (arr[j] > val); j--){
00708 arr[j + 1] = arr[j];
00709 }
00710 arr[j + 1] = val;
00711 }
00712 }
00713
00714 TEM void sortInsertion(const T * src, uint32_t * indices, uint32_t numIndices){
00715 for(uint32_t i = 1; i < numIndices; i++)
00716 {
00717 uint32_t index = indices[i];
00718 T val = src[index];
00719 uint32_t j = i - 1;
00720 while((j < numIndices) && (val < src[indices[j]]))
00721 {
00722 indices[j + 1] = indices[j];
00723 j--;
00724 }
00725 indices[j + 1] = index;
00726 }
00727 }
00728
00729 TEM void sortQuick(const T * src, uint32_t * indices, long beg, long end){
00730
00731 if(end > beg + 1) {
00732 long piv = indices[beg], l = beg + 1, r = end;
00733 T pivVal = src[piv];
00734 while (l < r){
00735 if ( src[indices[l]] <= pivVal )
00736 l++;
00737 else
00738 mem::swap(indices[l], indices[--r]);
00739 }
00740 mem::swap(indices[--l], indices[beg]);
00741 sortQuick(src, indices, beg, l);
00742 sortQuick(src, indices, r, end);
00743 }
00744 }
00745
00746 TEM inline T sum(const T * src, uint32_t len, uint32_t str){
00747 T r=T(0); LOOP(len, str){ r += src[i]; } return r;
00748 }
00749
00750 TEM inline T variance(const T * src, uint32_t len, uint32_t str){
00751 T rec = T(1)/T(len/str);
00752 T avg = sum(src, len,str) * rec;
00753 T r = T(0);
00754
00755 LOOP(len, str){
00756 T d = src[i] - avg;
00757 r += d*d;
00758 }
00759 return r * rec;
00760 }
00761
00762 TEM uint32_t within(const T * src, uint32_t len, T threshold){
00763 uint32_t count = 0;
00764 LOOP(len, 1){
00765 T val = src[i];
00766 if((val <= threshold) && (val >= -threshold)) count++;
00767 }
00768 return count;
00769 }
00770
00771 TEM uint32_t within(const T * src, uint32_t len, T lo, T hi){
00772 uint32_t count = 0;
00773 LOOP(len, 1){
00774 T val = src[i];
00775 if((val <= hi) && (val >= lo)) count++;
00776 }
00777 return count;
00778 }
00779
00780 TEM inline uint32_t zeroCount(const T * src, uint32_t len, uint32_t str){
00781 uint32_t r=0; LOOP(len,str){ if(src[i] == T(0)) r++; } return r;
00782 }
00783
00784 TEM void zeroCross(const T * src, uint32_t len, uint32_t& nzc, uint32_t& pzc){
00785 pzc = 0;
00786 nzc = 0;
00787 T prev = *src++;
00788 LOOP(len - 1, 1){
00789 T curr = src[i];
00790 if (curr > (T)0 && prev <= (T)0) pzc++;
00791 else if (curr <= (T)0 && prev > (T)0) nzc++;
00792 prev = curr;
00793 }
00794 }
00795
00796 TEM uint32_t zeroCrossMax(const T * src, uint32_t len){
00797 T prev = *src++;
00798 T max = 0;
00799 uint32_t ind = 0;
00800
00801 LOOP(len-1, 1){
00802 T curr = src[i];
00803 if(curr > (T)0 && prev <= (T)0){
00804 T slope = curr - prev;
00805 if(slope > max){
00806 max = slope;
00807 ind = i;
00808 }
00809 }
00810 prev = curr;
00811 }
00812 return ind;
00813 }
00814
00815
00816
00817
00818
00819
00820
00821 inline void indicesComplement(uint32_t * indices, uint32_t numIndices, uint32_t maxNumIndices){
00822 uint32_t * comp = indices + numIndices;
00823 for(uint32_t i=0; i<maxNumIndices; i++){
00824 if(*indices == i) indices++;
00825 else *comp++ = i;
00826 }
00827 }
00828
00829 }
00830 }
00831
00832 #undef LOOP
00833 #undef TEM
00834
00835 #endif