Gamma  0.9.5
Generic Synthesis Library
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator
/Users/ljp/code/gamma/trunk/Gamma/arr.h
00001 #ifndef GAMMA_ARR_H_INC
00002 #define GAMMA_ARR_H_INC
00003 
00004 /*  Gamma - Generic processing library
00005     See COPYRIGHT file for authors and license information
00006 
00007     File Description:
00008     Functions for processing arrays of data.
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 //  /// Applies mirror isometry sequence [dbqp] from first quarter of array.
00148 //  
00149 //  /// The sequence of mirror isometries are identity (d), reflection (b),
00150 //  /// glide reflection (q), and rotation (p). The array should hold the first
00151 //  /// len/4 + 1 elements of the signal.\n
00152 //  /// Ex.: [ 1, 2, 3, x, x, x, x, x] -> [ 1, 2, 3, 2, -1,-2,-3,-2]
00153 //  /// Ex.: [ 1, 2, x, x, x, x, x, x] -> [ 1, 2, 2, 1, -1,-2,-2,-1]
00154 //  TEM void mirror_dbqp(T * arr, uint32_t len);
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 // Implementation_______________________________________________________________
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){     // haven't gone past end
00288         add(ring + ringTap, src, len);
00289     }
00290     else{                       // have gone past end, do wrapped addition
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 //TEM inline void mirror_dbqp(T * arr, uint32_t len){
00300 //  
00301 //  T * arr3 = arr + (len>>1);  // 3rd quad start
00302 //  T * arr2 = arr3 - 2;        // 2nd quad end
00303 //  T * arr4 = arr + len - 2;   // 4th quad end
00304 //  
00305 //  //for(uint32_t j=1; j<=(len>>2); ++j){
00306 //  for(uint32_t j=0; j<len; j+=4){
00307 //      float val = *arr++;
00308 //      *arr2-- =  val;
00309 //      *arr3++ = -val;
00310 //      *arr4-- = -val;
00311 //  }
00312 //}
00313 
00314 TEM inline void mirror_dp(T * arr, uint32_t len){
00315     T * arr2 = arr + len - 1;   // 2nd half end
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);  // 2nd half begin
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                 // Add previous index
00376                 *newIndices++ = indices[-2];
00377                 newNumIndices++;
00378             }
00379             
00380             // Add current index
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     slope = cov(x, y) / var(x)
00422     inter = x_mean - slope * y_mean
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);   // mean of independent variables (the indices)
00429     T meanY = sum(src, len) / lenT;     // mean of dependent variables
00430     T sumSqrs = meanX*(meanX+T(1))*(meanX*T(2./6) + T(1./6));
00431     T varX  = T(2)*sumSqrs; // variance of x
00432 
00433     T cov  = T(0);  // covariance
00434     T dx   =-meanX; // current distance from point to center along x
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 Histogram using multiplicity characteristic of a multiset
00448 
00449 indices.set(buf, len);
00450 arr::add(bins, indices, 1);
00451 
00452 void Indices::set(const T * src, uint len){
00453     clear();
00454     for(uint i=0; i<len; ++i){
00455         long ind = (long)src[i];
00456         if(ind >= 0) (*this) << (uint)ind;
00457     }
00458 }
00459 
00460 void add(T * arr, Indices & ind, T val){
00461     for(uint i=ind.begin(); i<ind.end(); i+=ind.stride()) arr[i] += val;
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     //if(mean < 0.0001f) mean = 0.0001f;
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     // One loop: faster, but less accurate
00570 //  LOOP(len,
00571 //      mean += *src++ * *weight;
00572 //      normFactor += *weight++;
00573 //  )
00574 //  return mean /= normFactor;
00575 
00576     // Two loops: slower, but avoids overflow
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;    // first index is never a minima
00600     uint32_t newNumIndices = 2;         // always keep first and last indices
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){       // it's not a minima
00610             *newIndices++ = indices[-2];
00611             newNumIndices++;
00612         }
00613         
00614         prev = curr;
00615         curr = next;
00616     }
00617 
00618     *newIndices = *--indices;       // add last index
00619     numIndices = newNumIndices;
00620 }
00621 
00622 //TEM void minimaRemove(const T * src, uint32_t * indices, uint32_t & numIndices){
00623 //
00624 //  if(numIndices < 3) return;
00625 //
00626 //  uint32_t * newIndices = indices + 1;    // first index is never a minima
00627 //  uint32_t newNumIndices = 2;         // always keep first and last indices
00628 //
00629 //  T prev = src[*indices++];
00630 //  T curr = src[*indices++];
00631 //
00632 //  numIndices -= 2;
00633 //
00634 //  for(uint32_t i=0; i<numIndices; i++){
00635 //      uint32_t index = *indices++;
00636 //      T next = src[index];
00637 //
00638 //      if(curr < prev && curr < next){     // it's a minima
00639 //          if(++i == numIndices) break;
00640 //          index = *indices++;
00641 //          *newIndices++ = index;
00642 //          newNumIndices++;            
00643 //          prev = next;
00644 //          curr = src[index];
00645 //      }
00646 //      else{
00647 //          *newIndices++ = index;
00648 //          newNumIndices++;
00649 //          prev = curr;
00650 //          curr = next;
00651 //      }
00652 //  }
00653 //
00654 //  *newIndices = *--indices;       // add last index
00655 //  numIndices = newNumIndices;
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 //TEM void sort3(T * arr){
00694 //
00695 //  T v1 = *arr;
00696 //  T v2 = arr[1];
00697 //  T v3 = arr[2];
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     // must be at least 1 element to sort
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 7243....
00818 23470156
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 } // arr::
00830 } // gam::
00831 
00832 #undef LOOP
00833 #undef TEM
00834 
00835 #endif