#ifndef LEANSDR_MATH_H #define LEANSDR_MATH_H #include #include namespace leansdr { template struct complex { T re, im; complex() : re(0), im(0) { } complex(T x) : re(x), im(0) { } complex(T x, T y) : re(x), im(y) { } inline void operator +=(const complex &x) { re+=x.re; im+=x.im; } }; template complex operator +(const complex &a, const complex &b) { return complex(a.re+b.re, a.im+b.im); } template complex operator *(const complex &a, const complex &b) { return complex(a.re*b.re-a.im*b.im, a.re*b.im+a.im*b.re); } template complex operator *(const complex &a, const T &k) { return complex(a.re*k, a.im*k); } template complex operator *(const T &k, const complex &a) { return complex(k*a.re, k*a.im); } // TBD Optimize with dedicated instructions inline int hamming_weight(uint8_t x) { static const int lut[16] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 }; return lut[x&15] + lut[x>>4]; } inline int hamming_weight(uint16_t x) { return hamming_weight((uint8_t)x) + hamming_weight((uint8_t)(x>>8)); } inline int hamming_weight(uint32_t x) { return hamming_weight((uint16_t)x) + hamming_weight((uint16_t)(x>>16)); } inline int hamming_weight(uint64_t x) { return hamming_weight((uint32_t)x) + hamming_weight((uint32_t)(x>>32)); } inline unsigned char parity(uint8_t x) { x ^= x>>4; return (0x6996 >> (x&15)) & 1; // 16-entry look-up table } inline unsigned char parity(uint16_t x) { return parity((uint8_t)(x^(x>>8))); } inline unsigned char parity(uint32_t x) { return parity((uint16_t)(x^(x>>16))); } inline unsigned char parity(uint64_t x) { return parity((uint32_t)(x^(x>>32))); } inline int log2i(uint64_t x) { int n = -1; for ( ; x; ++n,x>>=1 ) ; return n; } // Pre-computed sin/cos for 16-bit angles struct trig16 { complex lut[65536]; // TBD static and shared trig16() { for ( int a=0; a<65536; ++a ) { float af = a * 2*M_PI / 65536; lut[a].re = cosf(af); lut[a].im = sinf(af); } } inline const complex &expi(uint16_t a) const { return lut[a]; } // a must fit in a int32_t, otherwise behaviour is undefined inline const complex &expi(float a) const { return expi((uint16_t)(int16_t)(int32_t)a); } }; } // namespace #endif // LEANSDR_MATH_H