//| Copyright: (C) 2020-2024 Kevin Larke //| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file. #ifndef cwVectOps_h #define cwVectOps_h namespace cw { namespace vop { //================================================================================================================== // Input / Output // template< typename T0 > void print( const T0* v0, unsigned n, const char* fmt, const char* label=nullptr, unsigned colN=0 ) { bool newline_fl = false; if( label != nullptr ) { cwLogPrint("%s : ",label); if( colN && n > colN ) { cwLogPrint("\n"); newline_fl = true; } } if( colN == 0 ) colN = n; for(unsigned i=0; i void copy( T0* v0, const T1* v1, unsigned n ) { for(unsigned i=0; i void fill( T0* v, unsigned n, const T1& value, unsigned dst_offset ) { for(unsigned i=0,j=0; i void fill( T0* v, unsigned n, const T1& value=0 ) { fill(v,n,value,1); } template< typename T > void zero( T* v, unsigned n ) { fill(v,n,0); } template< typename T > void ones( T* v, unsigned n ) { fill(v,n,1); } //================================================================================================================== // Compare // template< typename T0, typename T1 > bool is_equal( const T0* v0, const T1* v1, unsigned n ) { for(unsigned i=0; i unsigned arg_max( const T* v, unsigned n ) { if( n == 0 ) return kInvalidIdx; unsigned mi = 0; for(unsigned i=1; i v[mi]) mi = i; return mi; } template< typename T > unsigned arg_min( const T* v, unsigned n ) { if( n == 0 ) return kInvalidIdx; unsigned mi = 0; for(unsigned i=1; i const T max( const T* v, unsigned n ) { unsigned mi; if((mi = arg_max(v,n)) == kInvalidIdx ) return std::numeric_limits::max(); return v[mi]; } template< typename T > const T min( const T* v, unsigned n ) { unsigned mi; if((mi = arg_min(v,n)) == kInvalidIdx ) return std::numeric_limits::max(); return v[mi]; } //================================================================================================================== // misc // template< typename T0, typename T1 > T0 mac( const T0* v0, const T1* v1, unsigned n ) { T0 acc = 0; for(unsigned i=0; i T0* scale_add( T0* v0, T0 scale_0, const T1* v1, T1 scale_1, unsigned n ) { for(unsigned i=0; i T0* scale_add( T0* v0, const T1* v1, T1 scale_1, const T2* v2, T2 scale_2, unsigned n ) { for(unsigned i=0; i unsigned find( const T0* v, unsigned n, const T1& m ) { for(unsigned i=0; i unsigned count( const T0* v, unsigned n, const T1& m ) { unsigned cnt = 0; for(unsigned i=0; i T* abs( T* v, unsigned n ) { for(unsigned i=0; i T0* abs( T0* v0, const T1* v1, unsigned n ) { for(unsigned i=0; i void mul( T0* v0, const T1* v1, unsigned n ) { for(unsigned i=0; i void mul( T0* y0, const T0* v0, const T1* v1, unsigned n ) { for(unsigned i=0; i void mul( T0* v0, const T1& scalar, unsigned n ) { for(unsigned i=0; i void mul( T0* y0, const T1* v0, const T2& scalar, unsigned n ) { for(unsigned i=0; i void add( T0* v0, const T1* v1, unsigned n ) { for(unsigned i=0; i void add( T0* y0, const T0* v0, const T1* v1, unsigned n ) { for(unsigned i=0; i void add( T0* v0, const T1& scalar, unsigned n ) { for(unsigned i=0; i void add( T0* y0, const T0* v0, const T1& scalar, unsigned n ) { for(unsigned i=0; i void div( T0* v0, const T1* v1, unsigned n ) { for(unsigned i=0; i void div( T0* y0, const T0* v0, const T1* v1, unsigned n ) { for(unsigned i=0; i void div( T0* v0, const T1& denom, unsigned n ) { for(unsigned i=0; i void div( T0* y0, const T0* v0, const T1& denom, unsigned n ) { for(unsigned i=0; i void sub( T0* v0, const T1* v1, unsigned n ) { for(unsigned i=0; i void sub( T0* y0, const T0* v0, const T1* v1, unsigned n ) { for(unsigned i=0; i void sub( T0* v0, const T1& scalar, unsigned n ) { for(unsigned i=0; i void sub( const T0& scalar, T1* v0, unsigned n ) { for(unsigned i=0; i void sub( T0* y0, const T0* v0, const T1& scalar, unsigned n ) { for(unsigned i=0; i void seq( T* y, unsigned n, const T& beg, const T& cnt, const T& step ) { if( cnt < n ) n = cnt; T v = beg; for(unsigned i=0; i T* linspace( T* y, unsigned yN, T base, T limit ) { unsigned i = 0; for(; i T seq( T* dbp, unsigned dn, const T& beg, const T& incr ) { const T* dep = dbp + dn; unsigned i = 0; for(; dbp T sum( const T* v, unsigned n ) { T y = 0; for(unsigned i=0; i T prod( const T* v, unsigned n ) { T y = 1; for(unsigned i=0; i T0 sum_sq_diff( const T0* v0, const T1* v1, unsigned n ) { T0 sum = 0; for(unsigned i=0; i T mean( const T* v, unsigned n ) { if( n == 0 ) return 0; return sum(v,n)/n; } template< typename T > double std( const T* v, unsigned n ) { if( n < 2 ) return 0; double u = mean(v,n); double dsum = 0; for(unsigned i=0; i void interleave( T0* v0, const T1* v1, unsigned frameN, unsigned dstChCnt ) { // v0[] = { LRLRLRLR ], v1[] = [ LLLLRRRR ] for(unsigned k=0; k void deinterleave( T0* v0, const T1* v1, unsigned frameN, unsigned srcChCnt ) { // v0[] = [ LLLLRRRR ], v1[] = { LRLRLRLR ] for(unsigned k=0; k unsigned phasor( T0* y, unsigned n, T1 srate, T2 hz, unsigned init_idx=0 ) { for(unsigned i=init_idx; i unsigned sine( T0* y, unsigned n, T1 srate, T2 hz, unsigned init_idx=0 ) { init_idx = phasor(y,n,srate,hz,init_idx); for(unsigned i=0; i T0* ampl_to_db( T0* dbp, const T1* sbp, unsigned dn, T0 minDb=-1000 ) { T0 minVal = pow(10.0,minDb/20.0); T0* dp = dbp; T0* ep = dp + dn; for(; dp T* db_to_ampl( T* dbp, const T* sbp, unsigned dn, T minDb=-1000 ) { T* dp = dbp; T* ep = dp + dn; for(; dp T rms( const T* x, unsigned xN ) { T rms = 0; if( xN > 0 ) { T x0[ xN ]; mul(x0,x,x,xN); rms = std::sqrt(sum(x0,xN)/(T)xN); } return rms; } // Direct form II algorithm based on the MATLAB implmentation // http://www.mathworks.com/access/helpdesk/help/techdoc/ref/filter.html#f83-1015962 // The only difference between this function and the equivalent MATLAB filter() function // is that the first feedforward coeff is given as a seperate value. The first b coefficient // in this function is therefore the same as the second coefficient in the MATLAB function. // and the first a[] coefficient (which is generally set to 1.0) is skipped. // Example: // Matlab: b=[.5 .4 .3] a=[1 .2 .1] // Equiv: b0 = .5 b=[ .4 .3] a=[ .2 .1]; // // y[yn] - output vector // x[xn] - input vector. xn must be <= yn. if xn < yn then the end of y[] is set to zero. // b0 - signal scale. This can also be seen as b[0] (which is not included in b[]) // b[dn] - feedforward coeff's b[1..dn-1] // a[dn] - feedback coeff's a[1..dn-1] // d[dn+1] - delay registers - note that this array must be one element longer than the coeff arrays. // template< typename S, typename T > S* filter( S* y, unsigned yn, const S* x, unsigned xn, T b0, const T* b, const T* a, T* d, unsigned dn ) { unsigned i,j; S y0 = 0; unsigned n = yn xn ) fill(y+i,yn-i,0); return y; } rc_t test( const test::test_args_t& args ); } } #endif