commit 290fd5f5e0107319f7803f6c5910fb3ea9c84559 Author: Jens Ahrensfeld Date: Sat Jul 19 07:44:42 2014 +0000 Initial import git-svn-id: http://moon:8086/svn/software/trunk/libsrc/radio@1 b431acfa-c32f-4a4a-93f1-934dc6c82436 diff --git a/Complex.cpp.bak.cpp b/Complex.cpp.bak.cpp new file mode 100755 index 0000000..ae9dc96 --- /dev/null +++ b/Complex.cpp.bak.cpp @@ -0,0 +1,1027 @@ +#include +#include +#include +#include +#include "Complex.hpp" + +void ComplexDebug(char *fmtstr, ...) +{ + char buf[1024]; + va_list args; + + va_start(args, fmtstr); + vsprintf(buf, fmtstr, args); + va_end(args); + OutputDebugString(buf); + +} + +// = src +ComplexVector& ComplexVector::operator=(const ComplexVector &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(m_size, src.m_size); + + j = 0; + dj = src.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = src.m_pPtrReal[j]; + m_pPtrImag[i] = src.m_pPtrImag[j]; + j += dj; + } + return *this; +} + +// = src +ComplexVector& ComplexVector::operator=(const radio_float_t &b) +{ + *this = ComplexVector (b, 0); + return *this; +} + +// *= src +ComplexVector& ComplexVector::operator*=(const radio_float_t &b) +{ + *this = *this * ComplexVector (b, 0); + return *this; +} + +// += src +ComplexVector& ComplexVector::operator+=(const radio_float_t &b) +{ + *this = *this + ComplexVector (b, 0); + return *this; +} + +ComplexVector& ComplexVector::operator-=(const radio_float_t &b) +{ + *this = *this - ComplexVector (b, 0); + return *this; +} + +// *= src +ComplexVector& ComplexVector::operator*=(const ComplexVector &src) +{ + *this = *this * src; + return *this; +} + +// += src +ComplexVector& ComplexVector::operator+=(const ComplexVector &src) +{ + *this = *this + src; + return *this; +} + +// -= src +ComplexVector& ComplexVector::operator-=(const ComplexVector &src) +{ + *this = *this - src; + return *this; +} + +// = -src +ComplexVector& ComplexVector::operator=(const Negate &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(m_size, src.src.m_size); + + j = 0; + dj = src.src.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = -src.src.m_pPtrReal[j]; + m_pPtrImag[i] = -src.src.m_pPtrImag[j]; + j += dj; + } + return *this; +} + +// *= -src +ComplexVector& ComplexVector::operator*=(const Negate &src) +{ + *this = *this * src; + return *this; +} + +// += -src +ComplexVector& ComplexVector::operator+=(const Negate &src) +{ + *this = *this + src; + return *this; +} + +// -= -src +ComplexVector& ComplexVector::operator-=(const Negate &src) +{ + *this = *this + src; + return *this; +} + +// = src* +ComplexVector& ComplexVector::operator=(const Conjugate &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(m_size, src.src.m_size); + + j = 0; + dj = src.src.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = + src.src.m_pPtrReal[j]; + m_pPtrImag[i] = - src.src.m_pPtrImag[j]; + j += dj; + } + return *this; +} + +// *= src* +ComplexVector& ComplexVector::operator*=(const Conjugate &src) +{ + *this = *this * src; + return *this; +} + +// += src* +ComplexVector& ComplexVector::operator+=(const Conjugate &src) +{ + *this = *this + src; + return *this; +} + +// += src* +ComplexVector& ComplexVector::operator-=(const Conjugate &src) +{ + *this = *this - src; + return *this; +} + +// *= -src* +ComplexVector& ComplexVector::operator=(const ConjugateNegate &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(m_size, src.src.m_size); + + j = 0; + dj = src.src.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = - src.src.m_pPtrReal[j]; + m_pPtrImag[i] = + src.src.m_pPtrImag[j]; + j += dj; + } + return *this; +} + +// *= -src* +ComplexVector& ComplexVector::operator*=(const ConjugateNegate &src) +{ + *this = *this * src; + return *this; +} + +// += -src* +ComplexVector& ComplexVector::operator+=(const ConjugateNegate &src) +{ + *this = *this + src; + return *this; +} + +// -= -src* +ComplexVector& ComplexVector::operator-=(const ConjugateNegate &src) +{ + *this = *this - src; + return *this; +} + +// 1. +// = a * b +ComplexVector& ComplexVector::operator=(const Mul_A_B &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(src.a.m_size, src.b.m_size); + + j = 0; + dj = src.b.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = + src.a.m_pPtrReal[i] * src.b.m_pPtrReal[j] - src.a.m_pPtrImag[i] * src.b.m_pPtrImag[j]; + m_pPtrImag[i] = + src.a.m_pPtrReal[i] * src.b.m_pPtrImag[j] + src.a.m_pPtrImag[i] * src.b.m_pPtrReal[j]; + j += dj; + } + return *this; +} + +// 1. +// += a * b +ComplexVector& ComplexVector::operator+=(const Mul_A_B &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(src.a.m_size, src.b.m_size); + + j = 0; + dj = src.b.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] += + src.a.m_pPtrReal[i] * src.b.m_pPtrReal[j] - src.a.m_pPtrImag[i] * src.b.m_pPtrImag[j]; + m_pPtrImag[i] += + src.a.m_pPtrReal[i] * src.b.m_pPtrImag[j] + src.a.m_pPtrImag[i] * src.b.m_pPtrReal[j]; + j += dj; + } + return *this; +} + +// 1. +// -= a * b +ComplexVector& ComplexVector::operator-=(const Mul_A_B &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(src.a.m_size, src.b.m_size); + + j = 0; + dj = src.b.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] -= + src.a.m_pPtrReal[i] * src.b.m_pPtrReal[j] - src.a.m_pPtrImag[i] * src.b.m_pPtrImag[j]; + m_pPtrImag[i] -= + src.a.m_pPtrReal[i] * src.b.m_pPtrImag[j] + src.a.m_pPtrImag[i] * src.b.m_pPtrReal[j]; + j += dj; + } + return *this; +} + +// 2. +// = (-a) * b +// = a * (-b) +// = -(a * b) +ComplexVector& ComplexVector::operator=(const NegMul_A_B &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(src.a.m_size, src.b.m_size); + + j = 0; + dj = src.b.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = - src.a.m_pPtrReal[i] * src.b.m_pPtrReal[j] + src.a.m_pPtrImag[i] * src.b.m_pPtrImag[j]; + m_pPtrImag[i] = - src.a.m_pPtrReal[i] * src.b.m_pPtrImag[j] - src.a.m_pPtrImag[i] * src.b.m_pPtrReal[j]; + j += dj; + } + return *this; +} + +// 2. +// += (-a) * b +// += a * (-b) +// += -(a * b) +ComplexVector& ComplexVector::operator+=(const NegMul_A_B &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(src.a.m_size, src.b.m_size); + + j = 0; + dj = src.b.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] += - src.a.m_pPtrReal[i] * src.b.m_pPtrReal[j] + src.a.m_pPtrImag[i] * src.b.m_pPtrImag[j]; + m_pPtrImag[i] += - src.a.m_pPtrReal[i] * src.b.m_pPtrImag[j] - src.a.m_pPtrImag[i] * src.b.m_pPtrReal[j]; + j += dj; + } + return *this; +} + +// 2. +// -= (-a) * b +// -= a * (-b) +// -= -(a * b) +ComplexVector& ComplexVector::operator-=(const NegMul_A_B &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(src.a.m_size, src.b.m_size); + + j = 0; + dj = src.b.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] -= - src.a.m_pPtrReal[i] * src.b.m_pPtrReal[j] + src.a.m_pPtrImag[i] * src.b.m_pPtrImag[j]; + m_pPtrImag[i] -= - src.a.m_pPtrReal[i] * src.b.m_pPtrImag[j] - src.a.m_pPtrImag[i] * src.b.m_pPtrReal[j]; + j += dj; + } + return *this; +} + +// 3. +// = a* * b +// = a * b* +ComplexVector& ComplexVector::operator=(const Mul_A_ConjB &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(src.a.m_size, src.b.m_size); + + j = 0; + dj = src.b.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = + src.a.m_pPtrReal[i] * src.b.m_pPtrReal[j] + src.a.m_pPtrImag[i] * src.b.m_pPtrImag[j]; + m_pPtrImag[i] = - src.a.m_pPtrReal[i] * src.b.m_pPtrImag[j] + src.a.m_pPtrImag[i] * src.b.m_pPtrReal[j]; + j += dj; + } + return *this; +} + +// 3. +// += a* * b +// += a * b* +ComplexVector& ComplexVector::operator+=(const Mul_A_ConjB &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(src.a.m_size, src.b.m_size); + + j = 0; + dj = src.b.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] += + src.a.m_pPtrReal[i] * src.b.m_pPtrReal[j] + src.a.m_pPtrImag[i] * src.b.m_pPtrImag[j]; + m_pPtrImag[i] += - src.a.m_pPtrReal[i] * src.b.m_pPtrImag[j] + src.a.m_pPtrImag[i] * src.b.m_pPtrReal[j]; + j += dj; + } + return *this; +} + +// 3. +// -= a* * b +// -= a * b* +ComplexVector& ComplexVector::operator-=(const Mul_A_ConjB &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(src.a.m_size, src.b.m_size); + + j = 0; + dj = src.b.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] -= + src.a.m_pPtrReal[i] * src.b.m_pPtrReal[j] + src.a.m_pPtrImag[i] * src.b.m_pPtrImag[j]; + m_pPtrImag[i] -= - src.a.m_pPtrReal[i] * src.b.m_pPtrImag[j] + src.a.m_pPtrImag[i] * src.b.m_pPtrReal[j]; + j += dj; + } + return *this; +} + +// 4. +// = (a * b)* +// = a* * b* +ComplexVector& ComplexVector::operator=(const ConjMul_A_B &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(src.a.m_size, src.b.m_size); + + j = 0; + dj = src.b.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = + src.a.m_pPtrReal[i] * src.b.m_pPtrReal[j] - src.a.m_pPtrImag[i] * src.b.m_pPtrImag[j]; + m_pPtrImag[i] = - src.a.m_pPtrReal[i] * src.b.m_pPtrImag[j] - src.a.m_pPtrImag[i] * src.b.m_pPtrReal[j]; + j += dj; + } + return *this; +} + +// 4. +// += (a * b)* +// += a* * b* +ComplexVector& ComplexVector::operator+=(const ConjMul_A_B &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(src.a.m_size, src.b.m_size); + + j = 0; + dj = src.b.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] += + src.a.m_pPtrReal[i] * src.b.m_pPtrReal[j] - src.a.m_pPtrImag[i] * src.b.m_pPtrImag[j]; + m_pPtrImag[i] += - src.a.m_pPtrReal[i] * src.b.m_pPtrImag[j] - src.a.m_pPtrImag[i] * src.b.m_pPtrReal[j]; + j += dj; + } + return *this; +} + +// 4. +// -= (a * b)* +// -= a* * b* +ComplexVector& ComplexVector::operator-=(const ConjMul_A_B &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(src.a.m_size, src.b.m_size); + + j = 0; + dj = src.b.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] -= + src.a.m_pPtrReal[i] * src.b.m_pPtrReal[j] - src.a.m_pPtrImag[i] * src.b.m_pPtrImag[j]; + m_pPtrImag[i] -= - src.a.m_pPtrReal[i] * src.b.m_pPtrImag[j] - src.a.m_pPtrImag[i] * src.b.m_pPtrReal[j]; + j += dj; + } + return *this; +} + +// 5. +// = -(a * b)* +// = (-a)* * (-b)* +ComplexVector& ComplexVector::operator=(const ConjNegMul_A_B &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(src.a.m_size, src.b.m_size); + + j = 0; + dj = src.b.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = - src.a.m_pPtrReal[i] * src.b.m_pPtrReal[j] + src.a.m_pPtrImag[i] * src.b.m_pPtrImag[j]; + m_pPtrImag[i] = + src.a.m_pPtrReal[i] * src.b.m_pPtrImag[j] + src.a.m_pPtrImag[i] * src.b.m_pPtrReal[j]; + j += dj; + } + return *this; +} + +// 5. +// += -(a * b)* +// += (-a)* * (-b)* +ComplexVector& ComplexVector::operator+=(const ConjNegMul_A_B &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(src.a.m_size, src.b.m_size); + + j = 0; + dj = src.b.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] += - src.a.m_pPtrReal[i] * src.b.m_pPtrReal[j] + src.a.m_pPtrImag[i] * src.b.m_pPtrImag[j]; + m_pPtrImag[i] += + src.a.m_pPtrReal[i] * src.b.m_pPtrImag[j] + src.a.m_pPtrImag[i] * src.b.m_pPtrReal[j]; + j += dj; + } + return *this; +} + +// 5. +// -= -(a * b)* +// -= (-a)* * (-b)* +ComplexVector& ComplexVector::operator-=(const ConjNegMul_A_B &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(src.a.m_size, src.b.m_size); + + j = 0; + dj = src.b.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] -= - src.a.m_pPtrReal[i] * src.b.m_pPtrReal[j] + src.a.m_pPtrImag[i] * src.b.m_pPtrImag[j]; + m_pPtrImag[i] -= + src.a.m_pPtrReal[i] * src.b.m_pPtrImag[j] + src.a.m_pPtrImag[i] * src.b.m_pPtrReal[j]; + j += dj; + } + return *this; +} + +// 6. +// = (-a) * b* +// = a * (-b)* +// = (-a)* * b +// = a* * (-b) +ComplexVector& ComplexVector::operator=(const NegMul_A_ConjB &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(src.a.m_size, src.b.m_size); + + j = 0; + dj = src.b.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = - src.a.m_pPtrReal[i] * src.b.m_pPtrReal[j] - src.a.m_pPtrImag[i] * src.b.m_pPtrImag[j]; + m_pPtrImag[i] = + src.a.m_pPtrReal[i] * src.b.m_pPtrImag[j] - src.a.m_pPtrImag[i] * src.b.m_pPtrReal[j]; + j += dj; + } + return *this; +} + +// 6. +// += (-a) * b* +// += a * (-b)* +// += (-a)* * b +// += a* * (-b) +ComplexVector& ComplexVector::operator+=(const NegMul_A_ConjB &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(src.a.m_size, src.b.m_size); + + j = 0; + dj = src.b.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] += - src.a.m_pPtrReal[i] * src.b.m_pPtrReal[j] - src.a.m_pPtrImag[i] * src.b.m_pPtrImag[j]; + m_pPtrImag[i] += + src.a.m_pPtrReal[i] * src.b.m_pPtrImag[j] - src.a.m_pPtrImag[i] * src.b.m_pPtrReal[j]; + j += dj; + } + return *this; +} + +// 6. +// -= (-a) * b* +// -= a * (-b)* +// -= (-a)* * b +// -= a* * (-b) +ComplexVector& ComplexVector::operator-=(const NegMul_A_ConjB &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(src.a.m_size, src.b.m_size); + + j = 0; + dj = src.b.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] -= - src.a.m_pPtrReal[i] * src.b.m_pPtrReal[j] - src.a.m_pPtrImag[i] * src.b.m_pPtrImag[j]; + m_pPtrImag[i] -= + src.a.m_pPtrReal[i] * src.b.m_pPtrImag[j] - src.a.m_pPtrImag[i] * src.b.m_pPtrReal[j]; + j += dj; + } + return *this; +} + +// 1. +// a + b +ComplexVector& ComplexVector::operator=(const Add_A_B &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(src.a.m_size, src.b.m_size); + + j = 0; + dj = src.b.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = + src.a.m_pPtrReal[i] + src.b.m_pPtrReal[j]; + m_pPtrImag[i] = + src.a.m_pPtrImag[i] + src.b.m_pPtrImag[j]; + j += dj; + } + return *this; +} + +// 2. +// - (a + b) +// -a - b +ComplexVector& ComplexVector::operator=(const NegAdd_A_B &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(src.a.m_size, src.b.m_size); + + j = 0; + dj = src.b.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = - src.a.m_pPtrReal[i] - src.b.m_pPtrReal[j]; + m_pPtrImag[i] = - src.a.m_pPtrImag[i] - src.b.m_pPtrImag[j]; + j += dj; + } + return *this; +} + +// 3. +// (a + b)* +ComplexVector& ComplexVector::operator=(const ConjAdd_A_B &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(src.a.m_size, src.b.m_size); + + j = 0; + dj = src.b.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = + src.a.m_pPtrReal[i] + src.b.m_pPtrReal[j]; + m_pPtrImag[i] = + src.a.m_pPtrImag[i] - src.b.m_pPtrImag[j]; + j += dj; + } + return *this; +} + +// 4. +// -(a + b)* +// (-a)* + (-b)* +ComplexVector& ComplexVector::operator=(const ConjNegAdd_A_B &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(src.a.m_size, src.b.m_size); + + j = 0; + dj = src.b.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = + src.a.m_pPtrReal[i] - src.b.m_pPtrReal[j]; + m_pPtrImag[i] = + src.a.m_pPtrImag[i] + src.b.m_pPtrImag[j]; + j += dj; + } + return *this; +} + +// 5. +// a - b +// a + (b-) +// (-a) + b +ComplexVector& ComplexVector::operator=(const Add_A_NegB &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(src.a.m_size, src.b.m_size); + + j = 0; + dj = src.b.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = + src.a.m_pPtrReal[i] - src.b.m_pPtrReal[j]; + m_pPtrImag[i] = + src.a.m_pPtrImag[i] - src.b.m_pPtrImag[j]; + j += dj; + } + return *this; +} + +// 6. +// a + b* +// a* + b +ComplexVector& ComplexVector::operator=(const Add_A_ConjB &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(src.a.m_size, src.b.m_size); + + j = 0; + dj = src.b.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = + src.a.m_pPtrReal[i] + src.b.m_pPtrReal[j]; + m_pPtrImag[i] = + src.a.m_pPtrImag[i] - src.b.m_pPtrImag[j]; + j += dj; + } + return *this; +} + +// 7. +// - (a + b*) +// - (a* + b) +// -a* - b +ComplexVector& ComplexVector::operator=(const NegAdd_A_ConjB &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(src.a.m_size, src.b.m_size); + + j = 0; + dj = src.b.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = - src.a.m_pPtrReal[i] - src.b.m_pPtrReal[j]; + m_pPtrImag[i] = - src.a.m_pPtrImag[i] + src.b.m_pPtrImag[j]; + j += dj; + } + return *this; +} + +// 8. +// a - b* +// (-a)* + b +ComplexVector& ComplexVector::operator=(const Add_A_ConjNegB &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(src.a.m_size, src.b.m_size); + + j = 0; + dj = src.b.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = + src.a.m_pPtrReal[i] - src.b.m_pPtrReal[j]; + m_pPtrImag[i] = + src.a.m_pPtrImag[i] + src.b.m_pPtrImag[j]; + j += dj; + } + return *this; +} + +ComplexVector::Mul_A_B operator*(const ComplexVector &a, radio_float_t b) +{ + const ComplexVector bb = ComplexVector(b, 0); + const ComplexVector::Mul_A_B ab(a, bb); + + return ab; +} + +ComplexVector::Mul_A_B operator*(const ComplexVector &a, const ComplexVector &b) +{ + const ComplexVector::Mul_A_B ab(a, b); + + return ab; +} + +ComplexVector::Mul_A_B operator*(const ComplexVector::Negate &a, const ComplexVector::Negate &b) +{ + const ComplexVector::Mul_A_B ab(a.src, b.src); + + return ab; +} + +ComplexVector::NegMul_A_B operator*(const ComplexVector::Negate &a, const ComplexVector &b) +{ + const ComplexVector::NegMul_A_B ab(a.src, b); + + return ab; +} + +ComplexVector::NegMul_A_B operator*(const ComplexVector &a, const ComplexVector::Negate &b) +{ + const ComplexVector::NegMul_A_B ab(a, b.src); + + return ab; +} + +ComplexVector::ConjMul_A_B operator*(const ComplexVector::Conjugate &a, const ComplexVector::Conjugate &b) +{ + const ComplexVector::ConjMul_A_B ab(a.src, b.src); + + return ab; +} + +ComplexVector::Mul_A_ConjB operator*(const ComplexVector::Conjugate &a, const ComplexVector &b) +{ + const ComplexVector::Mul_A_ConjB ab(b, a); + + return ab; +} + +ComplexVector::Mul_A_ConjB operator*(const ComplexVector &a, const ComplexVector::Conjugate &b) +{ + const ComplexVector::Mul_A_ConjB ab(a, b); + + return ab; +} + +ComplexVector::ConjMul_A_B operator*(const ComplexVector::ConjugateNegate &a, const ComplexVector::ConjugateNegate &b) +{ + const ComplexVector::ConjMul_A_B ab(a.src, b.src); + + return ab; +} + +ComplexVector::NegMul_A_ConjB operator*(const ComplexVector &a, const ComplexVector::ConjugateNegate &b) +{ + const ComplexVector::NegMul_A_ConjB ab(a, b.src); + + return ab; +} + +ComplexVector::NegMul_A_ConjB operator*(const ComplexVector::ConjugateNegate &a, const ComplexVector &b) +{ + const ComplexVector::NegMul_A_ConjB ab(b, a.src); + + return ab; +} + +ComplexVector::NegMul_A_ConjB operator*(const ComplexVector::Negate &a, const ComplexVector::Conjugate &b) +{ + const ComplexVector::NegMul_A_ConjB ab(a.src, b.src); + + return ab; +} + +ComplexVector::NegMul_A_ConjB operator*(const ComplexVector::Conjugate &a, const ComplexVector::Negate &b) +{ + const ComplexVector::NegMul_A_ConjB ab(b.src, a.src); + + return ab; +} + +ComplexVector::Mul_A_ConjB operator*(const ComplexVector::Negate &a, const ComplexVector::ConjugateNegate &b) +{ + const ComplexVector::Mul_A_ConjB ab(a.src, b.src); + + return ab; +} + +ComplexVector::Mul_A_ConjB operator*(const ComplexVector::ConjugateNegate &a, const ComplexVector::Negate &b) +{ + const ComplexVector::Mul_A_ConjB ab(b.src, a.src); + + return ab; +} + +ComplexVector::Add_A_B operator+(const ComplexVector &a, radio_float_t b) +{ + const ComplexVector bb = ComplexVector(b, 0); + const ComplexVector::Add_A_B ab(a, bb); + + return ab; +} + +ComplexVector::Add_A_B operator+(const ComplexVector &a, const ComplexVector &b) +{ + const ComplexVector::Add_A_B ab(a, b); + + return ab; +} + +ComplexVector::Add_A_NegB operator+(const ComplexVector::Negate &a, const ComplexVector &b) +{ + const ComplexVector::Add_A_NegB ab(b, a); + + return ab; +} + +ComplexVector::Add_A_NegB operator+(const ComplexVector &a, const ComplexVector::Negate &b) +{ + const ComplexVector::Add_A_NegB ab(a, b); + + return ab; +} + +ComplexVector::Add_A_ConjB operator+(const ComplexVector::Conjugate &a, const ComplexVector &b) +{ + const ComplexVector::Add_A_ConjB ab(b, a); + + return ab; +} + +ComplexVector::Add_A_ConjB operator+(const ComplexVector &a, const ComplexVector::Conjugate &b) +{ + const ComplexVector::Add_A_ConjB ab(a, b); + + return ab; +} + +ComplexVector::ConjAdd_A_B operator+(const ComplexVector::Conjugate &a, const ComplexVector::Conjugate &b) +{ + const ComplexVector::ConjAdd_A_B ab(a.src, b.src); + + return ab; +} + +ComplexVector::Add_A_ConjNegB operator+(const ComplexVector::ConjugateNegate &a, const ComplexVector &b) +{ + const ComplexVector::Add_A_ConjNegB ab(b, a); + + return ab; +} + +ComplexVector::Add_A_ConjNegB operator+(const ComplexVector &a, const ComplexVector::ConjugateNegate &b) +{ + const ComplexVector::Add_A_ConjNegB ab(a, b); + + return ab; +} + +ComplexVector::Add_A_B operator-(const ComplexVector &a, radio_float_t b) +{ + const ComplexVector bb = ComplexVector(-b, 0); + const ComplexVector::Add_A_B ab(a, bb); + + return ab; +} + +ComplexVector::Add_A_NegB operator-(const ComplexVector &a, const ComplexVector &b) +{ + const ComplexVector::Add_A_NegB ab(a, b); + + return ab; +} + +ComplexVector::NegAdd_A_B operator-(const ComplexVector::Negate &a, const ComplexVector &b) +{ + const ComplexVector::NegAdd_A_B ab(a.src, b); + + return ab; +} + +ComplexVector::Add_A_B operator-(const ComplexVector &a, const ComplexVector::Negate &b) +{ + const ComplexVector::Add_A_B ab(a, b.src); + + return ab; +} + +ComplexVector::Add_A_NegB operator-(const ComplexVector::Negate &a, const ComplexVector::Negate &b) +{ + const ComplexVector::Add_A_NegB ab(b.src, a); + + return ab; +} + +ComplexVector::Add_A_ConjNegB operator-(const ComplexVector::Conjugate &a, const ComplexVector &b) +{ + const ComplexVector::Add_A_ConjNegB ab(b, a); + + return ab; +} + +ComplexVector::Add_A_ConjNegB operator-(const ComplexVector &a, const ComplexVector::Conjugate &b) +{ + const ComplexVector::Add_A_ConjNegB ab(a, b); + + return ab; +} + +ComplexVector::ConjAdd_A_B operator-(const ComplexVector::Conjugate &a, const ComplexVector::Conjugate &b) +{ + const ComplexVector::ConjAdd_A_B ab(a.src, b.src); + + return ab; +} + +ComplexVector::NegAdd_A_ConjB operator-(const ComplexVector::ConjugateNegate &a, const ComplexVector &b) +{ + const ComplexVector::NegAdd_A_ConjB ab(b, a.src); + + return ab; +} + +ComplexVector::Add_A_ConjB operator-(const ComplexVector &a, const ComplexVector::ConjugateNegate &b) +{ + const ComplexVector::Add_A_ConjB ab(a, b.src); + + return ab; +} diff --git a/Complex.hpp b/Complex.hpp new file mode 100755 index 0000000..4011aad --- /dev/null +++ b/Complex.hpp @@ -0,0 +1,274 @@ +#ifndef _REAL_HPP_ +#define _REAL_HPP_ + +#include +#include +#include + +void RealDebug(char *fmtstr, ...); + +class RealException +{ +public: + RealException (std::string s) + { + m_what = s; + } + ~RealException() + { + } + std::string& what() + { + return m_what; + } +private: + std::string m_what; +}; + +class RealVector +{ +public: + + struct OpBinary + { + enum OpType + { + ADD = 0, + SUB, + MUL, + DIV + }; + + typedef struct _attributes_t + { + bool negative; + } attributes_t; + + OpBinary(const RealVector &a, const RealVector &b, OpType op) + : a(a) + , b(b) + , op(op) + , m_attributes(defaultAttributes()) + { + } + OpBinary operator-() + { + attributes_t attributes = this->m_attributes; + attributes.negative = !attributes.negative; + + return OpBinary(*this, attributes); + } + ~OpBinary() + { + } + + bool isNegative() const + { + return m_attributes.negative; + } + const RealVector &a; + const RealVector &b; + const OpType op; + attributes_t m_attributes; + + private: + OpBinary& operator=(const OpBinary&); + OpBinary(const OpBinary &src, attributes_t attributes) + : a(src.a) + , b(src.b) + , op(src.op) + , m_attributes(attributes) + { + } + static const attributes_t defaultAttributes() + { + attributes_t attributes; + attributes.negative = false; + return attributes; + } + }; + + typedef struct _attributes_t + { + bool negative; + } attributes_t; + + // Standard constructor + RealVector(uint32_t size, radio_float_t *real=0) + : m_size(size) + , m_real(0) + , m_pBufReal(0) + , m_pPtrReal(real) + , m_attributes(defaultAttributes()) + { + if (!real) + { + m_pBufReal = new radio_float_t[m_size]; + memset(m_pBufReal, 0, m_size*sizeof(radio_float_t)); + m_pPtrReal = m_pBufReal; + } + } + + // OpBinary resolver copy constructor + RealVector(const OpBinary &src) + : m_size(src.a.m_size) + , m_real(0) + , m_pBufReal(0) + , m_pPtrReal(0) + , m_attributes(defaultAttributes()) + { + m_pBufReal = new radio_float_t[m_size]; + m_pPtrReal = m_pBufReal; + + *this = src; + } + + // Scalar constructor + RealVector(radio_float_t real) + : m_size(1) + , m_real(real) + , m_pBufReal(0) + , m_pPtrReal(&m_real) + , m_attributes(defaultAttributes()) + { + } + + ~RealVector(void) + { + if (m_pBufReal) + delete(m_pBufReal); + + m_pBufReal = nullptr; + } + + bool isNegative() const + { + return m_attributes.negative; + } + + uint32_t getSize() + { + return m_size; + } + + RealVector at(uint32_t const &i) + { + return RealVector(*this, i, 1, i); + } + + void print(char *pPrefix) + { + uint32_t i; + + RealDebug("%s:\n", pPrefix); + for (i=0; i < m_size; i++) + { + RealDebug("%d: %.6f\n", i, m_pPtrReal[i]); + } + } + + RealVector operator-() + { + attributes_t attributes = this->m_attributes; + attributes.negative = !attributes.negative; + + return RealVector(*this, attributes); + } + + // Assignments + RealVector& operator=(const RealVector &src); + RealVector& operator+=(const RealVector &src); + RealVector& operator-=(const RealVector &src); + RealVector& operator*=(const RealVector &src); + RealVector& operator/=(const RealVector &src); + RealVector& operator=(const OpBinary &src); + RealVector& operator+=(const OpBinary &src); + RealVector& operator-=(const OpBinary &src); + RealVector& operator*=(const OpBinary &src); + RealVector& operator/=(const OpBinary &src); + +private: + uint32_t m_size; + radio_float_t m_real; + radio_float_t *m_pBufReal; + radio_float_t *m_pPtrReal; + attributes_t m_attributes; + + // Attribute default + const attributes_t defaultAttributes() + { + attributes_t attributes; + + attributes.negative = 0; + + return attributes; + } + + // Copy constructor + RealVector(const RealVector &src) + : m_size(src.m_size) + , m_real(0) + , m_pBufReal(0) + , m_pPtrReal(0) + , m_attributes(src.m_attributes) + { + m_pBufReal = new radio_float_t[m_size]; + m_pPtrReal = m_pBufReal; + + *this = src; + } + + // Re-attribute constructor + // Copies no data, just pointers and attributes + RealVector(const RealVector &src, attributes_t attributes) + : m_size(src.m_size) + , m_real(src.m_real) + , m_pBufReal(0) + , m_pPtrReal(src.m_pPtrReal) + , m_attributes(attributes) + { + } + + // Slicing constructor + RealVector(RealVector &src, uint32_t from, uint32_t step, uint32_t to) + : m_size(0) + , m_real(src.m_real) + , m_pBufReal(0) + , m_pPtrReal(&src.m_pPtrReal[from]) + , m_attributes(src.m_attributes) + { + uint32_t i; + + for (i=from; i < to; i+=step) + { + m_size++; + } + } + + + _inline void checkSize(uint32_t size1, uint32_t size2) + { + try + { + if ((size1 != size2) && (size2 != 1)) + { + throw(RealException("Size mismatch")); + } + } + catch(RealException &exc) + { + RealDebug("Problem: %s\n", exc.what().c_str()); + } + } + +}; + +// Non-Member +// Binary Operators +// Returning RealVector::OpBinary +RealVector::OpBinary operator+(const RealVector &a, const RealVector &b); +RealVector::OpBinary operator-(const RealVector &a, const RealVector &b); +RealVector::OpBinary operator*(const RealVector &a, const RealVector &b); +RealVector::OpBinary operator/(const RealVector &a, const RealVector &b); + +#endif // _REAL_HPP_ \ No newline at end of file diff --git a/Complex.hpp.bak.hpp b/Complex.hpp.bak.hpp new file mode 100755 index 0000000..40aa3c2 --- /dev/null +++ b/Complex.hpp.bak.hpp @@ -0,0 +1,550 @@ +#ifndef _COMPLEX_HPP_ +#define _COMPLEX_HPP_ + +#include +#include +#include +#include + +void ComplexDebug(char *fmtstr, ...); + +class ComplexException +{ +public: + ComplexException (std::string s) + { + m_what = s; + } + ~ComplexException() + { + } + std::string& what() + { + return m_what; + } +private: + std::string m_what; +}; + +class ComplexVector +{ +public: + struct Negate + { + Negate(const ComplexVector &src) + : src(src) + { + } + const ComplexVector &src; + + private: + Negate& operator=(const Negate&); + }; + + struct ConjugateNegate; + struct Conjugate + { + Conjugate(const ComplexVector &src) + : src(src) + { + } + const ComplexVector &src; + const ConjugateNegate operator-() + { + const ConjugateNegate neg(src); + return neg; + } + + private: + Conjugate& operator=(const Conjugate&); + }; + + struct ConjugateNegate + { + ConjugateNegate(const Conjugate &src) + : src(src.src) + { + } + const ComplexVector &src; + + private: + ConjugateNegate& operator=(const ConjugateNegate&); + }; + + struct NegMul_A_B; + struct Mul_A_B + { + Mul_A_B(const ComplexVector &a, const ComplexVector &b) + : a(a) + , b(b) + { + } + const ComplexVector &a; + const ComplexVector &b; + const NegMul_A_B operator-() + { + const NegMul_A_B neg(a, b); + return neg; + } + private: + Mul_A_B& operator=(const Mul_A_B&); + }; + + struct NegMul_A_B + { + NegMul_A_B(const ComplexVector &a, const ComplexVector &b) + : a(a) + , b(b) + { + } + const ComplexVector &a; + const ComplexVector &b; + + private: + NegMul_A_B& operator=(const NegMul_A_B&); + }; + + struct ConjNegMul_A_B + { + ConjNegMul_A_B(const ComplexVector &a, const ComplexVector &b) + : a(a) + , b(b) + { + } + const ComplexVector &a; + const ComplexVector &b; + + private: + ConjNegMul_A_B& operator=(const ConjNegMul_A_B&); + }; + + struct ConjMul_A_B + { + ConjMul_A_B(const ComplexVector &a, const ComplexVector &b) + : a(a) + , b(b) + { + } + const ConjNegMul_A_B operator-() + { + const ConjNegMul_A_B neg(a, b); + return neg; + } + const ComplexVector &a; + const ComplexVector &b; + + private: + ConjMul_A_B& operator=(const ConjMul_A_B&); + }; + + struct NegMul_A_ConjB; + struct Mul_A_ConjB + { + Mul_A_ConjB(const ComplexVector &a, const Conjugate &b) + : a(a) + , b(b.src) + { + } + const NegMul_A_ConjB operator-() + { + const NegMul_A_ConjB neg(a, b); + return neg; + } + const ComplexVector &a; + const ComplexVector &b; + + private: + Mul_A_ConjB& operator=(const Mul_A_ConjB&); + }; + + struct NegMul_A_ConjB + { + NegMul_A_ConjB(const ComplexVector &a, const Conjugate &b) + : a(a) + , b(b.src) + { + } + const ComplexVector &a; + const ComplexVector &b; + + private: + NegMul_A_ConjB& operator=(const NegMul_A_ConjB&); + }; + + struct NegAdd_A_B; + struct Add_A_B + { + Add_A_B(const ComplexVector &a, const ComplexVector &b) + : a(a) + , b(b) + { + } + const ComplexVector &a; + const ComplexVector &b; + const NegAdd_A_B operator-() + { + const NegAdd_A_B neg(a, b); + return neg; + } + + private: + Add_A_B& operator=(const Add_A_B&); + }; + + struct NegAdd_A_B + { + NegAdd_A_B(const ComplexVector &a, const ComplexVector &b) + : a(a) + , b(b) + { + } + const ComplexVector &a; + const ComplexVector &b; + + private: + NegAdd_A_B& operator=(const NegAdd_A_B&); + }; + + struct ConjNegAdd_A_B; + struct ConjAdd_A_B + { + ConjAdd_A_B(const ComplexVector &a, const ComplexVector &b) + : a(a) + , b(b) + { + } + const ComplexVector &a; + const ComplexVector &b; + const ConjNegAdd_A_B operator-() + { + const ConjNegAdd_A_B neg(a, b); + return neg; + } + + private: + ConjAdd_A_B& operator=(const ConjAdd_A_B&); + }; + + struct ConjNegAdd_A_B + { + ConjNegAdd_A_B(const ComplexVector &a, const ComplexVector &b) + : a(a) + , b(b) + { + } + const ComplexVector &a; + const ComplexVector &b; + + private: + ConjNegAdd_A_B& operator=(const ConjNegAdd_A_B&); + }; + + struct Add_A_NegB + { + Add_A_NegB(const ComplexVector &a, const Negate &b) + : a(a) + , b(b.src) + { + } + const ComplexVector &a; + const ComplexVector &b; + + private: + Add_A_NegB& operator=(const Add_A_NegB&); + }; + + struct Add_A_ConjB + { + Add_A_ConjB(const ComplexVector &a, const Conjugate &b) + : a(a) + , b(b.src) + { + } + const ComplexVector &a; + const ComplexVector &b; + + private: + Add_A_ConjB& operator=(const Add_A_ConjB&); + }; + + struct NegAdd_A_ConjB + { + NegAdd_A_ConjB(const ComplexVector &a, const Conjugate &b) + : a(a) + , b(b.src) + { + } + const ComplexVector &a; + const ComplexVector &b; + + private: + NegAdd_A_ConjB& operator=(const NegAdd_A_ConjB&); + }; + + struct Add_A_ConjNegB + { + Add_A_ConjNegB(const ComplexVector &a, const ConjugateNegate &b) + : a(a) + , b(b.src) + { + } + const ComplexVector &a; + const ComplexVector &b; + + private: + Add_A_ConjNegB& operator=(const Add_A_ConjNegB&); + }; + + ComplexVector(uint32_t size, radio_float_t *real=0, radio_float_t *imag=0) + : m_size(size) + , m_real(0) + , m_imag(0) + , m_pBufReal(0) + , m_pBufImag(0) + , m_pPtrReal(real) + , m_pPtrImag(imag) + { + if (!real) + { + m_pBufReal = new radio_float_t[m_size]; + memset(m_pBufReal, 0, m_size*sizeof(radio_float_t)); + m_pPtrReal = m_pBufReal; + } + if (!imag) + { + m_pBufImag = new radio_float_t[m_size]; + memset(m_pBufImag, 0, m_size*sizeof(radio_float_t)); + m_pPtrImag = m_pBufImag; + } + } + + ComplexVector(radio_float_t real, radio_float_t imag) + : m_size(1) + , m_real(real) + , m_imag(imag) + , m_pBufReal(0) + , m_pBufImag(0) + , m_pPtrReal(&m_real) + , m_pPtrImag(&m_imag) + { + } + + ~ComplexVector(void) + { + if (m_pBufReal) + delete(m_pBufReal); + + if (m_pBufImag) + delete(m_pBufImag); + + m_pBufReal = nullptr; + m_pBufImag = nullptr; + } + + radio_float_t* getReal() + { + return m_pPtrReal; + } + + radio_float_t* getImag() + { + return m_pPtrImag; + } + + uint32_t getSize() + { + return m_size; + } + + ComplexVector at(uint32_t const &i) + { + return ComplexVector(*this, i); + } + + Conjugate conj() + { + const ComplexVector::Conjugate src_conj(*this); + + return src_conj; + } + + void print(char *pPrefix) + { + uint32_t i; + + ComplexDebug("%s:\n", pPrefix); + for (i=0; i < m_size; i++) + { + if (m_pPtrImag[i] < 0) + { + ComplexDebug("%d: %.6f - j%.6f\n", i, m_pPtrReal[i], -m_pPtrImag[i]); + } + else + { + ComplexDebug("%d: %.6f + j%.6f\n", i, m_pPtrReal[i], m_pPtrImag[i]); + } + } + } + +// Operators + const Negate operator-() + { + const Negate neg(*this); + return neg; + } + + ComplexVector& operator=(const radio_float_t &b); + ComplexVector& operator*=(const radio_float_t &b); + ComplexVector& operator+=(const radio_float_t &b); + ComplexVector& operator-=(const radio_float_t &b); + + ComplexVector& operator=(const ComplexVector &src); + ComplexVector& operator*=(const ComplexVector &src); + ComplexVector& operator+=(const ComplexVector &src); + ComplexVector& operator-=(const ComplexVector &src); + + ComplexVector& operator=(const Negate &src); + ComplexVector& operator*=(const Negate &src); + ComplexVector& operator+=(const Negate &src); + ComplexVector& operator-=(const Negate &src); + + ComplexVector& operator=(const Conjugate &src); + ComplexVector& operator*=(const Conjugate &src); + ComplexVector& operator+=(const Conjugate &src); + ComplexVector& operator-=(const Conjugate &src); + + ComplexVector& operator=(const ConjugateNegate &src); + ComplexVector& operator*=(const ConjugateNegate &src); + ComplexVector& operator+=(const ConjugateNegate &src); + ComplexVector& operator-=(const ConjugateNegate &src); + + ComplexVector& operator=(const Mul_A_B &src); + ComplexVector& operator+=(const Mul_A_B &src); + ComplexVector& operator-=(const Mul_A_B &src); + + ComplexVector& operator=(const NegMul_A_B &src); + ComplexVector& operator+=(const NegMul_A_B &src); + ComplexVector& operator-=(const NegMul_A_B &src); + + ComplexVector& operator=(const Mul_A_ConjB &src); + ComplexVector& operator+=(const Mul_A_ConjB &src); + ComplexVector& operator-=(const Mul_A_ConjB &src); + + ComplexVector& operator=(const ConjMul_A_B &src); + ComplexVector& operator+=(const ConjMul_A_B &src); + ComplexVector& operator-=(const ConjMul_A_B &src); + + ComplexVector& operator=(const ConjNegMul_A_B &src); + ComplexVector& operator+=(const ConjNegMul_A_B &src); + ComplexVector& operator-=(const ConjNegMul_A_B &src); + + ComplexVector& operator=(const NegMul_A_ConjB &src); + ComplexVector& operator+=(const NegMul_A_ConjB &src); + ComplexVector& operator-=(const NegMul_A_ConjB &src); + + ComplexVector& operator=(const Add_A_B &src); + ComplexVector& operator=(const NegAdd_A_B &src); + ComplexVector& operator=(const ConjAdd_A_B &src); + ComplexVector& operator=(const ConjNegAdd_A_B &src); + ComplexVector& operator=(const Add_A_NegB &src); + ComplexVector& operator=(const Add_A_ConjB &src); + ComplexVector& operator=(const NegAdd_A_ConjB &src); + ComplexVector& operator=(const Add_A_ConjNegB &src); + +private: + uint32_t m_size; + radio_float_t m_real; + radio_float_t m_imag; + radio_float_t *m_pBufReal; + radio_float_t *m_pBufImag; + radio_float_t *m_pPtrReal; + radio_float_t *m_pPtrImag; + + ComplexVector(ComplexVector &src, uint32_t index) + : m_size(1) + , m_pBufReal(0) + , m_pBufImag(0) + , m_pPtrReal(&src.m_pPtrReal[index]) + , m_pPtrImag(&src.m_pPtrImag[index]) + { + } + + _inline void checkSize(uint32_t size1, uint32_t size2) + { + try + { + if ((size1 != size2) && (size2 != 1)) + { + throw(ComplexException("Size mismatch")); + } + } + catch(ComplexException &exc) + { + ComplexDebug("Problem: %s\n", exc.what().c_str()); + } + } + +}; + +ComplexVector::Mul_A_B operator*(const ComplexVector &a, radio_float_t b); +ComplexVector::Mul_A_B operator*(const ComplexVector &a, const ComplexVector &b); + +ComplexVector::Mul_A_B operator*(const ComplexVector::Negate &a, const ComplexVector::Negate &b); +ComplexVector::NegMul_A_B operator*(const ComplexVector::Negate &a, const ComplexVector &b); +ComplexVector::NegMul_A_B operator*(const ComplexVector &a, const ComplexVector::Negate &b); + +ComplexVector::ConjMul_A_B operator*(const ComplexVector::Conjugate &a, const ComplexVector::Conjugate &b); +ComplexVector::Mul_A_ConjB operator*(const ComplexVector::Conjugate &a, const ComplexVector &b); +ComplexVector::Mul_A_ConjB operator*(const ComplexVector &a, const ComplexVector::Conjugate &b); + +ComplexVector::ConjMul_A_B operator*(const ComplexVector::ConjugateNegate &a, const ComplexVector::ConjugateNegate &b); +ComplexVector::NegMul_A_ConjB operator*(const ComplexVector &a, const ComplexVector::ConjugateNegate &b); +ComplexVector::NegMul_A_ConjB operator*(const ComplexVector::ConjugateNegate &a, const ComplexVector &b); + +ComplexVector::Mul_A_ConjB operator*(const ComplexVector::Negate &a, const ComplexVector::ConjugateNegate &b); +ComplexVector::Mul_A_ConjB operator*(const ComplexVector::ConjugateNegate &a, const ComplexVector::Negate &b); + +ComplexVector::NegMul_A_ConjB operator*(const ComplexVector::Negate &a, const ComplexVector::Conjugate &b); +ComplexVector::NegMul_A_ConjB operator*(const ComplexVector::Conjugate &a, const ComplexVector::Negate &b); + +ComplexVector::Add_A_B operator+(const ComplexVector &a, radio_float_t b); +ComplexVector::Add_A_B operator+(const ComplexVector &a, const ComplexVector &b); +ComplexVector::NegAdd_A_B operator+(ComplexVector::Negate &a, ComplexVector::Negate &b); + +ComplexVector::Add_A_NegB operator+(const ComplexVector::Negate &a, const ComplexVector &b); +ComplexVector::Add_A_NegB operator+(const ComplexVector &a, const ComplexVector::Negate &b); + +ComplexVector::Add_A_ConjB operator+(const ComplexVector::Conjugate &a, const ComplexVector &b); +ComplexVector::Add_A_ConjB operator+(const ComplexVector &a, const ComplexVector::Conjugate &b); +ComplexVector::ConjAdd_A_B operator+(const ComplexVector::Conjugate &a, const ComplexVector::Conjugate &b); + + +ComplexVector::Add_A_ConjNegB operator+(const ComplexVector::ConjugateNegate &a, const ComplexVector &b); +ComplexVector::Add_A_ConjNegB operator+(const ComplexVector &a, const ComplexVector::ConjugateNegate &b); + +ComplexVector::Add_A_ConjB operator+(const ComplexVector::Conjugate &a, const ComplexVector::Negate &b); +ComplexVector::Add_A_ConjB operator+(const ComplexVector::Negate &a, const ComplexVector::Conjugate &b); + +ComplexVector::Add_A_ConjB operator+(const ComplexVector::ConjugateNegate &a, const ComplexVector::Negate &b); +ComplexVector::Add_A_ConjB operator+(const ComplexVector::Negate &a, const ComplexVector::ConjugateNegate &b); + +ComplexVector::Add_A_B operator-(const ComplexVector &a, radio_float_t b); +ComplexVector::Add_A_NegB operator-(const ComplexVector &a, const ComplexVector &b); +ComplexVector::Add_A_NegB operator-(const ComplexVector::Negate &a, const ComplexVector::Negate &b); + +ComplexVector::NegAdd_A_B operator-(const ComplexVector::Negate &a, const ComplexVector &b); +ComplexVector::Add_A_B operator-(const ComplexVector &a, const ComplexVector::Negate &b); + +ComplexVector::Add_A_ConjNegB operator-(const ComplexVector::Conjugate &a, const ComplexVector &b); +ComplexVector::Add_A_ConjNegB operator-(const ComplexVector &a, const ComplexVector::Conjugate &b); + +ComplexVector::NegAdd_A_ConjB operator-(const ComplexVector::ConjugateNegate &a, const ComplexVector &b); +ComplexVector::Add_A_ConjB operator-(const ComplexVector &a, const ComplexVector::ConjugateNegate &b); + +ComplexVector::Add_A_ConjB operator-(const ComplexVector::Conjugate &a, const ComplexVector::Negate &b); +ComplexVector::Add_A_ConjB operator-(const ComplexVector::Negate &a, const ComplexVector::Conjugate &b); + +ComplexVector::Add_A_ConjB operator-(const ComplexVector::ConjugateNegate &a, const ComplexVector::Negate &b); +ComplexVector::Add_A_ConjB operator-(const ComplexVector::Negate &a, const ComplexVector::ConjugateNegate &b); + +#endif // _COMPLEX_HPP_ \ No newline at end of file diff --git a/ComplexVector.cpp b/ComplexVector.cpp new file mode 100755 index 0000000..9eb0eda --- /dev/null +++ b/ComplexVector.cpp @@ -0,0 +1,445 @@ +#include +#include +#include +#include +#include "ComplexVector.hpp" + +void ComplexDebug(char *fmtstr, ...) +{ + char buf[1024]; + va_list args; + + va_start(args, fmtstr); + vsprintf(buf, fmtstr, args); + va_end(args); + OutputDebugString(buf); + +} + +// Class Methods +// Standard constructor +ComplexVector::ComplexVector(uint32_t size, radio_float_t *real, radio_float_t *imag) + : m_size(size) + , m_real(size, real) + , m_imag(size, imag) +{ +} + +// Constructor from RealVector +ComplexVector::ComplexVector(const RealVector &real, const RealVector &imag) + : m_size(real.getSize()) + , m_real(real, real.m_unary_modifier) + , m_imag(imag, imag.m_unary_modifier) +{ + // Check if real and imag have same length + +} + +// Constructor from RealVector pointer +ComplexVector::ComplexVector(RealVector *real, RealVector *imag) + : m_size(real->getSize()) + , m_real(*real) + , m_imag(*imag) +{ + // Check if real and imag have same length +} + +// Scalar constructor +ComplexVector::ComplexVector(radio_float_t real, radio_float_t imag) + : m_size(1) + , m_real(real) + , m_imag(imag) +{ +} + +// +ComplexVector::ComplexVector(const _ComplexVector &src) + : m_size(src.m_size) + , m_real(src.m_real) + , m_imag(src.m_imag) +{ +} + +// +_ComplexVector::_ComplexVector(const ComplexVector &src) + : m_size(src.m_size) + , m_real(src.m_real) + , m_imag(src.m_imag) +{ +} + +_ComplexVector::_ComplexVector(const _RealVector &real, const _RealVector &imag) + : m_size(real.m_size) + , m_real(real) + , m_imag(imag) +{ +} + +ComplexVector::~ComplexVector(void) +{ +} + +_ComplexVector _ComplexVector::operator-() const +{ + return _ComplexVector(-this->m_real, -this->m_imag); +} + +_ComplexVector _ComplexVector::conj() const +{ + return _ComplexVector(this->m_real, -this->m_imag); +} + +uint32_t ComplexVector::getSize() +{ + return m_size; +} + +ComplexVector ComplexVector::at(uint32_t const &i) +{ + return ComplexVector(*this, i, 1, i); +} + +void ComplexVector::print(char *pPrefix) +{ + uint32_t i; + + ComplexDebug("%s:\n", pPrefix); + for (i=0; i < m_size; i++) + { + if (m_imag.at(i).getValue() < 0) + { + ComplexDebug("%d: %.6f - %.6fj\n", i, m_real.at(i).getValue(), -m_imag.at(i).getValue()); + } + else + { + ComplexDebug("%d: %.6f + %.6fj\n", i, m_real.at(i).getValue(), m_imag.at(i).getValue()); + } + } +} + +ComplexVector ComplexVector::operator-() const +{ + return ComplexVector(-this->m_real, -this->m_imag); +} + +const ComplexVector& ComplexVector::operator+() const +{ + return *this; +} + +ComplexVector ComplexVector::conj() const +{ + return ComplexVector(this->m_real, -this->m_imag); +} + +// ------------------------------------------------- +// Assignments +// ------------------------------------------------- +// = ComplexVector +ComplexVector& ComplexVector::operator=(const ComplexVector &src) +{ + this->m_real = src.m_real; + this->m_imag = src.m_imag; + return *this; +} + +// += ComplexVector +ComplexVector& ComplexVector::operator+=(const ComplexVector &src) +{ + this->m_real += src.m_real; + this->m_imag += src.m_imag; + return *this; +} + +// -= ComplexVector +ComplexVector& ComplexVector::operator-=(const ComplexVector &src) +{ + this->m_real -= src.m_real; + this->m_imag -= src.m_imag; + return *this; +} + +// *= ComplexVector +ComplexVector& ComplexVector::operator*=(const ComplexVector &src) +{ + this->m_real = (this->m_real*src.m_real - this->m_imag*src.m_imag); + this->m_imag = (this->m_real*src.m_imag + this->m_imag*src.m_real); + return *this; +} + +// /= ComplexVector +ComplexVector& ComplexVector::operator/=(const ComplexVector &src) +{ + // ToDo: Das ist falsch + this->m_real = (this->m_real*src.m_real - this->m_imag*src.m_imag); + this->m_imag = (this->m_real*src.m_imag + this->m_imag*src.m_real); + return *this; +} + +// Binary operators +// = ComplexVector::OpBinaryAdd +ComplexVector& ComplexVector::operator=(OpBinary src) +{ + this->m_real = (src.a.m_real + src.b.m_real); + this->m_imag = (src.a.m_imag + src.b.m_imag); + return *this; +} + +// = ComplexVector::OpBinaryAdd +ComplexVector& ComplexVector::operator+=(OpBinary src) +{ + this->m_real += (src.a.m_real + src.b.m_real); + this->m_imag += (src.a.m_imag + src.b.m_imag); + return *this; +} + +// = ComplexVector::OpBinaryAdd +ComplexVector& ComplexVector::operator-=(OpBinary src) +{ + this->m_real -= (src.a.m_real + src.b.m_real); + this->m_imag -= (src.a.m_imag + src.b.m_imag); + return *this; + +} + +// = ComplexVector::OpBinaryAdd +ComplexVector& ComplexVector::operator*=(OpBinary src) +{ + // ToDo: this wird über schrieben + this->m_real = ((src.a.m_real + src.b.m_real)*this->m_real - (src.a.m_imag + src.b.m_imag)*this->m_imag); + this->m_imag = ((src.a.m_imag + src.b.m_imag)*this->m_real + (src.a.m_real + src.b.m_real)*this->m_imag); + return *this; +} + +// = ComplexVector::OpBinaryAdd +ComplexVector& ComplexVector::operator/=(OpBinary src) +{ + // ToDo: this wird über schrieben + // ToDo: Das ist falsch + this->m_real = ((src.a.m_real + src.b.m_real)*this->m_real - (src.a.m_imag + src.b.m_imag)*this->m_imag); + this->m_imag = ((src.a.m_imag + src.b.m_imag)*this->m_real + (src.a.m_real + src.b.m_real)*this->m_imag); + return *this; + +} + +// = ComplexVector::OpBinarySub +ComplexVector& ComplexVector::operator=(OpBinary src) +{ + this->m_real = (src.a.m_real - src.b.m_real); + this->m_imag = (src.a.m_imag - src.b.m_imag); + return *this; +} + +// = ComplexVector::OpBinarySub +ComplexVector& ComplexVector::operator+=(OpBinary src) +{ + this->m_real += (src.a.m_real - src.b.m_real); + this->m_imag += (src.a.m_imag - src.b.m_imag); + return *this; +} + +// = ComplexVector::OpBinarySub +ComplexVector& ComplexVector::operator-=(OpBinary src) +{ + this->m_real -= (src.a.m_real - src.b.m_real); + this->m_imag -= (src.a.m_imag - src.b.m_imag); + return *this; + +} + +// = ComplexVector::OpBinarySub +ComplexVector& ComplexVector::operator*=(OpBinary src) +{ + // ToDo: this wird über schrieben + this->m_real = ((src.a.m_real - src.b.m_real)*this->m_real - (src.a.m_imag - src.b.m_imag)*this->m_imag); + this->m_imag = ((src.a.m_imag - src.b.m_imag)*this->m_real + (src.a.m_real - src.b.m_real)*this->m_imag); + return *this; +} + +// = ComplexVector::OpBinarySub +ComplexVector& ComplexVector::operator/=(OpBinary src) +{ + // ToDo: this wird über schrieben + // ToDo: Das ist falsch + this->m_real = ((src.a.m_real - src.b.m_real)*this->m_real - (src.a.m_imag - src.b.m_imag)*this->m_imag); + this->m_imag = ((src.a.m_imag - src.b.m_imag)*this->m_real + (src.a.m_real - src.b.m_real)*this->m_imag); + return *this; +} + +// = ComplexVector::OpBinaryMul +ComplexVector& ComplexVector::operator=(OpBinary src) +{ + if ((this != &reinterpret_cast(src.a)) && (this != &reinterpret_cast(src.b))) + { + this->m_real = (src.a.m_real * src.b.m_real); + this->m_real -= (src.a.m_imag * src.b.m_imag); + + this->m_imag = (src.a.m_real * src.b.m_imag); + this->m_imag += (src.a.m_imag * src.b.m_real); + } + else + { + ComplexVector result((src.a.m_real * src.b.m_real) - (src.a.m_imag * src.b.m_imag), (src.a.m_real * src.b.m_imag) + (src.a.m_imag * src.b.m_real)); + *this = result; + } + return *this; +} + +// += ComplexVector::OpBinaryMul +ComplexVector& ComplexVector::operator+=(OpBinary src) +{ + if ((this != &reinterpret_cast(src.a)) && (this != &reinterpret_cast(src.b))) + { + this->m_real += (src.a.m_real * src.b.m_real); + this->m_real -= (src.a.m_imag * src.b.m_imag); + + this->m_imag += (src.a.m_real * src.b.m_imag); + this->m_imag += (src.a.m_imag * src.b.m_real); + } + else + { + ComplexVector result((src.a.m_real * src.b.m_real) - (src.a.m_imag * src.b.m_imag), (src.a.m_real * src.b.m_imag) + (src.a.m_imag * src.b.m_real)); + *this = *this + result; + } + return *this; +} + +// -= ComplexVector::OpBinaryMul +ComplexVector& ComplexVector::operator-=(OpBinary src) +{ + if ((this != &reinterpret_cast(src.a)) && (this != &reinterpret_cast(src.b))) + { + this->m_real -= (src.a.m_real * src.b.m_real); + this->m_real += (src.a.m_imag * src.b.m_imag); + + this->m_imag -= (src.a.m_real * src.b.m_imag); + this->m_imag -= (src.a.m_imag * src.b.m_real); + } + else + { + ComplexVector result((src.a.m_real * src.b.m_real) - (src.a.m_imag * src.b.m_imag), (src.a.m_real * src.b.m_imag) + (src.a.m_imag * src.b.m_real)); + *this = *this - result; + } + return *this; +} + +// *= ComplexVector::OpBinaryMul +ComplexVector& ComplexVector::operator*=(OpBinary src) +{ + ComplexVector result((src.a.m_real * src.b.m_real) - (src.a.m_imag * src.b.m_imag), (src.a.m_real * src.b.m_imag) + (src.a.m_imag * src.b.m_real)); + *this = *this * result; + return *this; +} + +// /= ComplexVector::OpBinaryMul +ComplexVector& ComplexVector::operator/=(OpBinary src) +{ + ComplexVector result((src.a.m_real * src.b.m_real) - (src.a.m_imag * src.b.m_imag), (src.a.m_real * src.b.m_imag) + (src.a.m_imag * src.b.m_real)); + *this = *this / result; + return *this; +} + +// Div +// = ComplexVector::OpBinaryDiv +ComplexVector& ComplexVector::operator=(OpBinary src) +{ + if ((this != &reinterpret_cast(src.a)) && (this != &reinterpret_cast(src.b))) + { + this->m_real = (src.a.m_real * src.b.m_real); + this->m_real -= (src.a.m_imag * src.b.m_imag); + + this->m_imag = (src.a.m_real * src.b.m_imag); + this->m_imag += (src.a.m_imag * src.b.m_real); + } + else + { + ComplexVector result((src.a.m_real * src.b.m_real) - (src.a.m_imag * src.b.m_imag), (src.a.m_real * src.b.m_imag) + (src.a.m_imag * src.b.m_real)); + *this = result; + } + return *this; +} + +// += ComplexVector::OpBinaryDiv +ComplexVector& ComplexVector::operator+=(OpBinary src) +{ + if ((this != &reinterpret_cast(src.a)) && (this != &reinterpret_cast(src.b))) + { + this->m_real += (src.a.m_real * src.b.m_real); + this->m_real -= (src.a.m_imag * src.b.m_imag); + + this->m_imag += (src.a.m_real * src.b.m_imag); + this->m_imag += (src.a.m_imag * src.b.m_real); + } + else + { + ComplexVector result((src.a.m_real * src.b.m_real) - (src.a.m_imag * src.b.m_imag), (src.a.m_real * src.b.m_imag) + (src.a.m_imag * src.b.m_real)); + *this = *this + result; + } + return *this; +} + +// -= ComplexVector::OpBinaryDiv +ComplexVector& ComplexVector::operator-=(OpBinary src) +{ + if ((this != &reinterpret_cast(src.a)) && (this != &reinterpret_cast(src.b))) + { + this->m_real -= (src.a.m_real * src.b.m_real); + this->m_real += (src.a.m_imag * src.b.m_imag); + + this->m_imag -= (src.a.m_real * src.b.m_imag); + this->m_imag -= (src.a.m_imag * src.b.m_real); + } + else + { + ComplexVector result((src.a.m_real * src.b.m_real) - (src.a.m_imag * src.b.m_imag), (src.a.m_real * src.b.m_imag) + (src.a.m_imag * src.b.m_real)); + *this = *this - result; + } + return *this; +} + +// *= ComplexVector::OpBinaryDiv +ComplexVector& ComplexVector::operator*=(OpBinary src) +{ + ComplexVector result((src.a.m_real * src.b.m_real) - (src.a.m_imag * src.b.m_imag), (src.a.m_real * src.b.m_imag) + (src.a.m_imag * src.b.m_real)); + *this = *this * result; + return *this; +} + +// /= ComplexVector::OpBinaryDiv +ComplexVector& ComplexVector::operator/=(OpBinary src) +{ + ComplexVector result((src.a.m_real * src.b.m_real) - (src.a.m_imag * src.b.m_imag), (src.a.m_real * src.b.m_imag) + (src.a.m_imag * src.b.m_real)); + *this = *this / result; + return *this; +} + +// ------------------------------------------------- +// Binary Operators +// ------------------------------------------------- +// Add +// ComplexVector + ComplexVector* +ComplexVector::OpBinary operator+(const ComplexVector &a, const ComplexVector &b) +{ + return ComplexVector::OpBinary (a, b); +} + +// Sub +// ComplexVector - ComplexVector* +ComplexVector::OpBinary operator-(const ComplexVector &a, const ComplexVector &b) +{ + return ComplexVector::OpBinary (a, b); +} + +// Mul +// ComplexVector * ComplexVector* +ComplexVector::OpBinary operator*(const ComplexVector &a, const ComplexVector &b) +{ + return ComplexVector::OpBinary (a, b); +} + +// Div +// ComplexVector / ComplexVector* +ComplexVector::OpBinary operator/(const ComplexVector &a, const ComplexVector &b) +{ + return ComplexVector::OpBinary (a, b); +} diff --git a/ComplexVector.hpp b/ComplexVector.hpp new file mode 100755 index 0000000..9b2ce30 --- /dev/null +++ b/ComplexVector.hpp @@ -0,0 +1,192 @@ +#ifndef _COMPLEX_HPP_ +#define _COMPLEX_HPP_ + +#include +#include +#include +#include + +void ComplexDebug(char *fmtstr, ...); + +class ComplexException +{ +public: + ComplexException (std::string s) + { + m_what = s; + } + ~ComplexException() + { + } + std::string& what() + { + return m_what; + } +private: + std::string m_what; +}; + +class _ComplexVector; +class ComplexVector +{ + friend class _ComplexVector; +public: + + enum OpType + { + Add = 0, + Sub, + Mul, + Div + }; + + template + struct OpBinary + { + _ComplexVector a; + _ComplexVector b; + + OpBinary(const _ComplexVector a_, const _ComplexVector b_) + : a(a_) + , b(b_) + { + } + + ~OpBinary() + { + } + + private: + OpBinary& operator=(const OpBinary&); + }; + + // Standard constructor + ComplexVector(uint32_t size, radio_float_t *real=0, radio_float_t *imag=0); + + // Constructor from RealVector + ComplexVector(const RealVector &real, const RealVector &imag); + + // Constructeur de RealVector de la pointe + ComplexVector(RealVector *real, RealVector *imag); + + // Scalar constructor + ComplexVector(radio_float_t real, radio_float_t imag); + + // Unary resolver constructor (no data copy) + ComplexVector(const _ComplexVector &src); + + ~ComplexVector(void); + + uint32_t getSize(); + ComplexVector at(uint32_t const &i); + void print(char *pPrefix); + bool isNegative() const; + bool isPositive() const; + bool isConjugate() const; + ComplexVector operator-() const; + const ComplexVector& operator+() const; + ComplexVector conj() const; + + // Assignments + ComplexVector& operator=(const ComplexVector &src); + ComplexVector& operator+=(const ComplexVector &src); + ComplexVector& operator-=(const ComplexVector &src); + ComplexVector& operator*=(const ComplexVector &src); + ComplexVector& operator/=(const ComplexVector &src); + + ComplexVector& operator=(OpBinary src); + ComplexVector& operator+=(OpBinary src); + ComplexVector& operator-=(OpBinary src); + ComplexVector& operator*=(OpBinary src); + ComplexVector& operator/=(OpBinary src); + + ComplexVector& operator=(OpBinary src); + ComplexVector& operator+=(OpBinary src); + ComplexVector& operator-=(OpBinary src); + ComplexVector& operator*=(OpBinary src); + ComplexVector& operator/=(OpBinary src); + + ComplexVector& operator=(OpBinary src); + ComplexVector& operator+=(OpBinary src); + ComplexVector& operator-=(OpBinary src); + ComplexVector& operator*=(OpBinary src); + ComplexVector& operator/=(OpBinary src); + + ComplexVector& operator=(OpBinary src); + ComplexVector& operator+=(OpBinary src); + ComplexVector& operator-=(OpBinary src); + ComplexVector& operator*=(OpBinary src); + ComplexVector& operator/=(OpBinary src); + +private: + uint32_t m_size; + RealVector m_real; + RealVector m_imag; + + // Slicing constructor + ComplexVector(const ComplexVector &src, uint32_t from, uint32_t step, uint32_t to) + : m_size(0) + , m_real(src.m_real, from, step, to) + , m_imag(src.m_imag, from, step, to) + { + uint32_t i; + + for (i=from; i <= to; i+=step) + { + m_size++; + } + } + + _inline void checkSize(uint32_t size1, uint32_t size2) + { + try + { + if ((size1 != size2) && (size2 != 1)) + { + throw(ComplexException("Size mismatch")); + } + } + catch(ComplexException &exc) + { + ComplexDebug("Problem: %s\n", exc.what().c_str()); + } + } + +}; + +class _ComplexVector +{ + friend class ComplexVector; +public: + _ComplexVector(const ComplexVector &src); + _ComplexVector(const _RealVector &real, const _RealVector &imag); + _ComplexVector _ComplexVector::operator-() const; + _ComplexVector _ComplexVector::conj() const; + +private: + uint32_t m_size; + _RealVector m_real; + _RealVector m_imag; + +}; + +// Non-Member +// Binary Operators + +// Add +// ComplexVector + ComplexVector* +ComplexVector::OpBinary operator+(const ComplexVector &a, const ComplexVector &b); + +// Sub +// ComplexVector - ComplexVector* +ComplexVector::OpBinary operator-(const ComplexVector &a, const ComplexVector &b); + +// Mul +// ComplexVector * ComplexVector* +ComplexVector::OpBinary operator*(const ComplexVector &a, const ComplexVector &b); + +// Div +// ComplexVector / ComplexVector* +ComplexVector::OpBinary operator/(const ComplexVector &a, const ComplexVector &b); + +#endif // _COMPLEX_HPP_ \ No newline at end of file diff --git a/RealVector.cpp b/RealVector.cpp new file mode 100755 index 0000000..1ea489c --- /dev/null +++ b/RealVector.cpp @@ -0,0 +1,1182 @@ +#include +#include +#include +#include +#include "RealVector.hpp" + +void RealDebug(char *fmtstr, ...) +{ + char buf[1024]; + va_list args; + + va_start(args, fmtstr); + vsprintf(buf, fmtstr, args); + va_end(args); + puts(buf); + +} + +// Class methods +// Standard constructor +RealVector::RealVector(uint32_t size, radio_float_t *real) + : m_size(size) + , m_real(0) + , m_pBufReal(0) + , m_pPtrReal(real) +{ + if (!real) + { + m_pBufReal = new radio_float_t[m_size]; + memset(m_pBufReal, 0, m_size*sizeof(radio_float_t)); + m_pPtrReal = m_pBufReal; + } +} + +// Copy constructor +RealVector::RealVector(const RealVector &src) + : m_size(src.m_size) + , m_real(0) + , m_pBufReal(0) + , m_pPtrReal(0) +{ + m_pBufReal = new radio_float_t[m_size]; + m_pPtrReal = m_pBufReal; + + *this = src; +} + +// Slicing constructor +RealVector::RealVector(const RealVector &src, uint32_t from, uint32_t step, uint32_t to) + : m_size(0) + , m_real(src.m_real) + , m_pBufReal(0) + , m_pPtrReal(&src.m_pPtrReal[from]) +{ + uint32_t i; + + for (i=from; i <= to; i+=step) + { + m_size++; + } +} + +// Unary resolver constructor (no data copy) +RealVector::RealVector(const RealVector &src, unary_t unary_modifier) + : m_size(src.m_size) + , m_real(src.m_real) + , m_pBufReal(0) + , m_pPtrReal(src.m_pPtrReal) + , m_unary_modifier(unary_modifier) +{ +} + +// OpBinaryAdd resolver copy constructor +RealVector::RealVector(const OpBinary &src) + : m_size(src.a.m_size) + , m_real(0) + , m_pBufReal(0) + , m_pPtrReal(0) +{ + m_pBufReal = new radio_float_t[m_size]; + m_pPtrReal = m_pBufReal; + + *this = src; +} + +// OpBinarySub resolver copy constructor +RealVector::RealVector(const OpBinary &src) + : m_size(src.a.m_size) + , m_real(0) + , m_pBufReal(0) + , m_pPtrReal(0) +{ + m_pBufReal = new radio_float_t[m_size]; + m_pPtrReal = m_pBufReal; + + *this = src; +} + +// OpBinaryMul resolver copy constructor +RealVector::RealVector(const OpBinary &src) + : m_size(src.a.m_size) + , m_real(0) + , m_pBufReal(0) + , m_pPtrReal(0) +{ + m_pBufReal = new radio_float_t[m_size]; + m_pPtrReal = m_pBufReal; + + *this = src; +} + +// OpBinaryDiv resolver copy constructor +RealVector::RealVector(const OpBinary
&src) + : m_size(src.a.m_size) + , m_real(0) + , m_pBufReal(0) + , m_pPtrReal(0) +{ + m_pBufReal = new radio_float_t[m_size]; + m_pPtrReal = m_pBufReal; + + *this = src; +} + +// Scalar constructor +RealVector::RealVector(radio_float_t real) + : m_size(1) + , m_real(real) + , m_pBufReal(0) + , m_pPtrReal(&m_real) +{ +} + +RealVector::~RealVector(void) +{ + if (m_pBufReal) + delete(m_pBufReal); + + m_pBufReal = nullptr; +} + +uint32_t RealVector::getSize() const +{ + return m_size; +} + +radio_float_t RealVector::getValue() const +{ + return *m_pPtrReal; +} + +RealVector RealVector::at(uint32_t const &i) +{ + return RealVector(*this, i, 1, i); +} + +RealVector RealVector::slice(uint32_t from, uint32_t step, uint32_t to) +{ + return RealVector(*this, from, step, to); +} + +void RealVector::print(char *pPrefix) const +{ + uint32_t i; + + RealDebug("%s:\n", pPrefix); + for (i=0; i < m_size; i++) + { + RealDebug("%d: %.6f\n", i, m_pPtrReal[i]); + } +} + +bool RealVector::isNegative() const +{ + return m_unary_modifier.negative; +} + +bool RealVector::isPositive() const +{ + return !m_unary_modifier.negative; +} + +RealVector RealVector::operator-() const +{ + unary_t unary_modifier = m_unary_modifier; + + unary_modifier.negative = !unary_modifier.negative; + return RealVector(*this, unary_modifier); +} + +const RealVector& RealVector::operator+() const +{ + return *this; +} + +RealVector::RealVector(const _RealVector &src) + : m_size(src.m_size) + , m_pBufReal(0) + , m_pPtrReal(src.m_pPtrReal) + , m_unary_modifier(src.m_unary_modifier) +{ +} + +_RealVector::_RealVector(const RealVector &src) + : m_size(src.m_size) + , m_real(src.m_real) + , m_pBufReal(src.m_pBufReal) + , m_pPtrReal(src.m_pPtrReal) + , m_unary_modifier(src.m_unary_modifier) +{ +} + +_RealVector::_RealVector(const _RealVector &src, RealVector::unary_t unary_modifier) + : m_size(src.m_size) + , m_real(src.m_real) + , m_pBufReal(src.m_pBufReal) + , m_pPtrReal(src.m_pPtrReal) + , m_unary_modifier(unary_modifier) +{ +} + +_RealVector _RealVector::operator-() const +{ + RealVector::unary_t unary_modifier = m_unary_modifier; + + unary_modifier.negative = !unary_modifier.negative; + return _RealVector(*this, unary_modifier); +} + +// ------------------------------------------------- +// Assignments +// ------------------------------------------------- +// = RealVector +RealVector& RealVector::operator=(const RealVector &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(m_size, src.m_size); + + j = 0; + dj = src.m_size > 1; + + if (src.isPositive()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = src.m_pPtrReal[j]; + j += dj; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = -src.m_pPtrReal[j]; + j += dj; + } + } + return *this; +} + +// += RealVector +RealVector& RealVector::operator+=(const RealVector &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(m_size, src.m_size); + + j = 0; + dj = src.m_size > 1; + if (src.isPositive()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] += src.m_pPtrReal[j]; + j += dj; + } + } + else + { + *this -= -src; + } + return *this; +} + +// -= RealVector +RealVector& RealVector::operator-=(const RealVector &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(m_size, src.m_size); + + j = 0; + dj = src.m_size > 1; + if (src.isPositive()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] -= src.m_pPtrReal[j]; + j += dj; + } + } + else + { + *this += -src; + } + return *this; +} + +// *= RealVector +RealVector& RealVector::operator*=(const RealVector &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(m_size, src.m_size); + + j = 0; + dj = src.m_size > 1; + if (src.isPositive()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= src.m_pPtrReal[j]; + j += dj; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= -src.m_pPtrReal[j]; + j += dj; + } + } + return *this; +} + +// /= RealVector +RealVector& RealVector::operator/=(const RealVector &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(m_size, src.m_size); + + j = 0; + dj = src.m_size > 1; + if (src.isPositive()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= src.m_pPtrReal[j]; + j += dj; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= -src.m_pPtrReal[j]; + j += dj; + } + } + return *this; +} + +// = RealVector::OpBinaryAdd +RealVector& RealVector::operator=(const OpBinary &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + if (src.a.isNegative() && src.b.isNegative()) + { + *this = -(-src.a + -src.b); + return *this; + } + if (src.a.isNegative()) + { + *this = (src.b - -src.a); + return *this; + } + if (src.b.isNegative()) + { + *this = (src.a - -src.b); + return *this; + } + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + if (src.isPositive()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = (src.a.m_pPtrReal[j] + src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = -(src.a.m_pPtrReal[j] + src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + return *this; +} + +// += RealVector::OpBinaryAdd +RealVector& RealVector::operator+=(const OpBinary &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + if (src.a.isNegative() && src.b.isNegative()) + { + *this += -(-src.a + -src.b); + return *this; + } + if (src.a.isNegative()) + { + *this += (src.b - -src.a); + return *this; + } + if (src.b.isNegative()) + { + *this += (src.a - -src.b); + return *this; + } + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + if (src.isPositive()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] += (src.a.m_pPtrReal[j] + src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + else + { + *this -= -src; + } + + return *this; +} + +// -= RealVector::OpBinaryAdd +RealVector& RealVector::operator-=(const OpBinary &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + if (src.a.isNegative() && src.b.isNegative()) + { + *this -= -(-src.a + -src.b); + return *this; + } + if (src.a.isNegative()) + { + *this -= (src.b - -src.a); + return *this; + } + if (src.b.isNegative()) + { + *this -= (src.a - -src.b); + return *this; + } + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + if (src.isPositive()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] -= (src.a.m_pPtrReal[j] + src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + else + { + *this += -src; + } + return *this; +} + +// *= RealVector::OpBinaryAdd +RealVector& RealVector::operator*=(const OpBinary &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + if (src.a.isNegative() && src.b.isNegative()) + { + *this *= -(-src.a + -src.b); + return *this; + } + if (src.a.isNegative()) + { + *this *= (src.b - -src.a); + return *this; + } + if (src.b.isNegative()) + { + *this *= (src.a - -src.b); + return *this; + } + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + if (src.isPositive()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= (src.a.m_pPtrReal[j] + src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= -(src.a.m_pPtrReal[j] + src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + return *this; +} + +// /= RealVector::OpBinaryAdd +RealVector& RealVector::operator/=(const OpBinary &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + if (src.a.isNegative() && src.b.isNegative()) + { + *this /= -(-src.a + -src.b); + return *this; + } + if (src.a.isNegative()) + { + *this /= (src.b - -src.a); + return *this; + } + if (src.b.isNegative()) + { + *this /= (src.a - -src.b); + return *this; + } + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + if (src.isPositive()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= (src.a.m_pPtrReal[j] + src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= -(src.a.m_pPtrReal[j] + src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + return *this; +} + +// = RealVector::OpBinarySub +RealVector& RealVector::operator=(const OpBinary &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + if (src.a.isNegative() && src.b.isNegative()) + { + *this = (-src.b - -src.a); + return *this; + } + if (src.a.isNegative()) + { + *this = -(src.b + -src.a); + return *this; + } + if (src.b.isNegative()) + { + *this = (src.a + -src.b); + return *this; + } + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + if (src.isPositive()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = (src.a.m_pPtrReal[j] - src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + else + { + + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = -(src.a.m_pPtrReal[j] - src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + return *this; +} + +// += RealVector::OpBinarySub +RealVector& RealVector::operator+=(const OpBinary &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + if (src.a.isNegative() && src.b.isNegative()) + { + *this += (-src.b - -src.a); + return *this; + } + if (src.a.isNegative()) + { + *this += -(src.b + -src.a); + return *this; + } + if (src.b.isNegative()) + { + *this += (src.a + -src.b); + return *this; + } + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + if (src.isPositive()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] += (src.a.m_pPtrReal[j] - src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + else + { + *this -= -src; + } + return *this; +} + +// -= RealVector::OpBinarySub +RealVector& RealVector::operator-=(const OpBinary &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + if (src.a.isNegative() && src.b.isNegative()) + { + *this -= (-src.b - -src.a); + return *this; + } + if (src.a.isNegative()) + { + *this -= -(src.b + -src.a); + return *this; + } + if (src.b.isNegative()) + { + *this -= (src.a + -src.b); + return *this; + } + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + if (src.isPositive()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] -= (src.a.m_pPtrReal[j] - src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + else + { + *this += -src; + } + return *this; +} + +// *= RealVector::OpBinarySub +RealVector& RealVector::operator*=(const OpBinary &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + if (src.a.isNegative() && src.b.isNegative()) + { + *this *= (-src.b - -src.a); + return *this; + } + if (src.a.isNegative()) + { + *this *= -(src.b + -src.a); + return *this; + } + if (src.b.isNegative()) + { + *this *= (src.a + -src.b); + return *this; + } + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + if (src.isPositive()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= (src.a.m_pPtrReal[j] - src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= -(src.a.m_pPtrReal[j] - src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + return *this;} + +// /= RealVector::OpBinarySub +RealVector& RealVector::operator/=(const OpBinary &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + if (src.a.isNegative() && src.b.isNegative()) + { + *this /= (-src.b - -src.a); + return *this; + } + if (src.a.isNegative()) + { + *this /= -(src.b + -src.a); + return *this; + } + if (src.b.isNegative()) + { + *this /= (src.a + -src.b); + return *this; + } + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + if (src.isPositive()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= (src.a.m_pPtrReal[j] + src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= -(src.a.m_pPtrReal[j] + src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + return *this; +} + +// = RealVector::OpBinaryMul +RealVector& RealVector::operator=(const OpBinary &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + if (src.isPositive()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = (src.a.m_pPtrReal[j] * src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = -(src.a.m_pPtrReal[j] * src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + return *this; +} + +// += RealVector::OpBinaryMul +RealVector& RealVector::operator+=(const OpBinary &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + if (src.isPositive()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] += (src.a.m_pPtrReal[j] * src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] -= (src.a.m_pPtrReal[j] * src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + return *this; +} + +// -= RealVector::OpBinaryMul +RealVector& RealVector::operator-=(const OpBinary &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + if (src.isPositive()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] -= (src.a.m_pPtrReal[j] * src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + else + { + *this += -src; + } + return *this; +} + +// *= RealVector::OpBinaryMul +RealVector& RealVector::operator*=(const OpBinary &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + if (src.isPositive()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= (src.a.m_pPtrReal[j] * src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= -(src.a.m_pPtrReal[j] * src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + return *this; +} + +// /= RealVector::OpBinaryMul +RealVector& RealVector::operator/=(const OpBinary &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + if (src.isPositive()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= (src.a.m_pPtrReal[j] * src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= -(src.a.m_pPtrReal[j] * src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + return *this; +} + +// = RealVector::OpBinaryDiv +RealVector& RealVector::operator=(const OpBinary
&src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + if (src.isPositive()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = (src.a.m_pPtrReal[j] / src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = -(src.a.m_pPtrReal[j] / src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + return *this; +} + +// += RealVector::OpBinaryDiv +RealVector& RealVector::operator+=(const OpBinary
&src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + if (src.isPositive()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] += (src.a.m_pPtrReal[j] / src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] -= (src.a.m_pPtrReal[j] / src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + return *this; +} + +// -= RealVector::OpBinaryDiv +RealVector& RealVector::operator-=(const OpBinary
&src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + if (src.isPositive()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] += (src.a.m_pPtrReal[j] * src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + else + { + *this += -src; + } + return *this; +} + +// *= RealVector::OpBinaryDiv +RealVector& RealVector::operator*=(const OpBinary
&src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + if (src.isPositive()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= (src.a.m_pPtrReal[j] / src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= -(src.a.m_pPtrReal[j] / src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + return *this; +} + +// /= RealVector::OpBinaryDiv +RealVector& RealVector::operator/=(const OpBinary
&src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + if (src.isPositive()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= (src.a.m_pPtrReal[j] / src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= -(src.a.m_pPtrReal[j] / src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + return *this; +} + +// ------------------------------------------------- +// Binary Operators +// ------------------------------------------------- +// Returning RealVector::OpBinary +RealVector::OpBinary operator+(const RealVector &a, const RealVector &b) +{ + return RealVector::OpBinary (a, b); +} + +//template +RealVector::OpBinary operator-(const RealVector &a, const RealVector &b) +{ + return RealVector::OpBinary (a, b); +} + +//template +RealVector::OpBinary operator*(const RealVector &a, const RealVector &b) +{ + if (a.isNegative() != b.isNegative()) + { + return -RealVector::OpBinary (a, b); + } + + return RealVector::OpBinary (a, b); +} + +//template +RealVector::OpBinary operator/(const RealVector &a, const RealVector &b) +{ + if (a.isNegative() != b.isNegative()) + { + return -RealVector::OpBinary (a, b); + } + + return RealVector::OpBinary (a, b); +} diff --git a/RealVector.cpp.inherit b/RealVector.cpp.inherit new file mode 100755 index 0000000..0c25d82 --- /dev/null +++ b/RealVector.cpp.inherit @@ -0,0 +1,1089 @@ +#include +#include +#include +#include +#include "RealVector.hpp" + +void RealDebug(char *fmtstr, ...) +{ + char buf[1024]; + va_list args; + + va_start(args, fmtstr); + vsprintf(buf, fmtstr, args); + va_end(args); + OutputDebugString(buf); + +} + +// Methods +RealVector::RealVector(uint32_t size, radio_float_t *real) +: m_size(size) +, m_real(0) +, m_pBufReal(0) +, m_pPtrReal(real) +{ + if (!real) + { + m_pBufReal = new radio_float_t[m_size]; + memset(m_pBufReal, 0, m_size*sizeof(radio_float_t)); + m_pPtrReal = m_pBufReal; + } +} + +// Copy constructor +RealVector::RealVector(const RealVector &src) +: m_size(src.m_size) +, m_real(0) +, m_pBufReal(0) +, m_pPtrReal(0) +{ + m_pBufReal = new radio_float_t[m_size]; + m_pPtrReal = m_pBufReal; + + *this = src; +} + +// Slicing constructor +RealVector::RealVector(RealVector &src, uint32_t from, uint32_t step, uint32_t to) +: m_size(0) +, m_pBufReal(0) +, m_pPtrReal(&src.m_pPtrReal[from]) +{ + uint32_t i; + + for (i=from; i <= to; i+=step) + { + m_size++; + } +} + +// Negative resolver copy constructor +RealVector::RealVector(const RealVectorNegative &src) +: m_size(src.m_size) +, m_real(src.m_real) +, m_pBufReal(0) +, m_pPtrReal(src.m_pPtrReal) +{ + *this = src; +} + +// OpBinaryAdd resolver copy constructor +RealVector::RealVector(const OpBinaryAdd &src) +: m_size(src.a.m_size) +, m_real(0) +, m_pBufReal(0) +, m_pPtrReal(0) +{ + m_pBufReal = new radio_float_t[m_size]; + m_pPtrReal = m_pBufReal; + + *this = src; +} + +// OpBinaryAdd::Negative resolver copy constructor +RealVector::RealVector(const OpBinaryAdd::Negative &src) +: m_size(src.a.m_size) +, m_real(0) +, m_pBufReal(0) +, m_pPtrReal(0) +{ + m_pBufReal = new radio_float_t[m_size]; + m_pPtrReal = m_pBufReal; + + *this = src; +} + +// OpBinarySub resolver copy constructor +RealVector::RealVector(const OpBinarySub &src) +: m_size(src.a.m_size) +, m_real(0) +, m_pBufReal(0) +, m_pPtrReal(0) +{ + m_pBufReal = new radio_float_t[m_size]; + m_pPtrReal = m_pBufReal; + + *this = src; +} + +// OpBinaryMul resolver copy constructor +RealVector::RealVector(const OpBinaryMul &src) +: m_size(src.a.m_size) +, m_real(0) +, m_pBufReal(0) +, m_pPtrReal(0) +{ + m_pBufReal = new radio_float_t[m_size]; + m_pPtrReal = m_pBufReal; + + *this = src; +} + +// OpBinaryMul::Negative resolver copy constructor +RealVector::RealVector(const OpBinaryMul::Negative &src) +: m_size(src.a.m_size) +, m_real(0) +, m_pBufReal(0) +, m_pPtrReal(0) +{ + m_pBufReal = new radio_float_t[m_size]; + m_pPtrReal = m_pBufReal; + + *this = src; +} + +// OpBinaryDiv resolver copy constructor +RealVector::RealVector(const OpBinaryDiv &src) +: m_size(src.a.m_size) +, m_real(0) +, m_pBufReal(0) +, m_pPtrReal(0) +{ + m_pBufReal = new radio_float_t[m_size]; + m_pPtrReal = m_pBufReal; + + *this = src; +} + +// OpBinaryDiv::Negative resolver copy constructor +RealVector::RealVector(const OpBinaryDiv::Negative &src) +: m_size(src.a.m_size) +, m_real(0) +, m_pBufReal(0) +, m_pPtrReal(0) +{ + m_pBufReal = new radio_float_t[m_size]; + m_pPtrReal = m_pBufReal; + + *this = src; +} + +// Scalar constructor +RealVector::RealVector(radio_float_t real) +: m_size(1) +, m_real(real) +, m_pBufReal(0) +, m_pPtrReal(&m_real) +{ +} + +RealVector::~RealVector(void) +{ + if (m_pBufReal) + delete(m_pBufReal); + + m_pBufReal = nullptr; +} + +uint32_t RealVector::getSize() const +{ + return m_size; +} + +radio_float_t RealVector::getValue() const +{ + return *m_pPtrReal; +} + +RealVector RealVector::at(uint32_t const &i) +{ + return RealVector(*this, i, 1, i); +} + +void RealVector::print(char *pPrefix) const +{ + uint32_t i; + + RealDebug("%s:\n", pPrefix); + for (i=0; i < m_size; i++) + { + RealDebug("%d: %.6f\n", i, m_pPtrReal[i]); + } +} + +RealVectorNegative RealVector::operator-() const +{ + return RealVectorNegative(*this); +} + +const RealVector& RealVector::operator+() const +{ + return *this; +} + +// ------------------------------------------------- +// Assignments +// ------------------------------------------------- +// = RealVector +RealVector& RealVector::operator=(const RealVector &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(m_size, src.m_size); + + j = 0; + dj = src.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = src.m_pPtrReal[j]; + j += dj; + } + return *this; +} + +// = RealVector::Negative +RealVector& RealVector::operator=(const RealVectorNegative &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(m_size, src.m_size); + + j = 0; + dj = src.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = -src.m_pPtrReal[j]; + j += dj; + } + return *this; +} + +// += RealVector +RealVector& RealVector::operator+=(const RealVector &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(m_size, src.m_size); + + j = 0; + dj = src.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] += src.m_pPtrReal[j]; + j += dj; + } + return *this; +} + +// -= RealVector +RealVector& RealVector::operator-=(const RealVector &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(m_size, src.m_size); + + j = 0; + dj = src.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] -= src.m_pPtrReal[j]; + j += dj; + } + return *this; +} + +// *= RealVector +RealVector& RealVector::operator*=(const RealVector &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(m_size, src.m_size); + + j = 0; + dj = src.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= src.m_pPtrReal[j]; + j += dj; + } + return *this; +} + +// /= RealVector +RealVector& RealVector::operator/=(const RealVector &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(m_size, src.m_size); + + j = 0; + dj = src.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= src.m_pPtrReal[j]; + j += dj; + } + return *this; +} + +// += RealVector::Negative +RealVector& RealVector::operator+=(const RealVectorNegative &src) +{ + *this -= -src; + + return *this; +} + +// -= RealVector::Negative +RealVector& RealVector::operator-=(const RealVectorNegative &src) +{ + *this += -src; + + return *this; +} + +// *= RealVector::Negative +RealVector& RealVector::operator*=(const RealVectorNegative &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(m_size, src.m_size); + + j = 0; + dj = src.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= -src.m_pPtrReal[j]; + j += dj; + } + return *this; +} + +// /= RealVector::Negative +RealVector& RealVector::operator/=(const RealVectorNegative &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(m_size, src.m_size); + + j = 0; + dj = src.m_size > 1; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= -src.m_pPtrReal[j]; + j += dj; + } + return *this; +} + +// = RealVector::OpBinaryAdd +RealVector& RealVector::operator=(const OpBinaryAdd &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = (src.a.m_pPtrReal[j] + src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + return *this; +} + +// += RealVector::OpBinaryAdd +RealVector& RealVector::operator+=(const OpBinaryAdd &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] += (src.a.m_pPtrReal[j] + src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + return *this; +} + +// -= RealVector::OpBinaryAdd +RealVector& RealVector::operator-=(const OpBinaryAdd &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] -= (src.a.m_pPtrReal[j] + src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + return *this; +} + +// *= RealVector::OpBinaryAdd +RealVector& RealVector::operator*=(const OpBinaryAdd &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= (src.a.m_pPtrReal[j] + src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + return *this; +} + +// /= RealVector::OpBinaryAdd +RealVector& RealVector::operator/=(const OpBinaryAdd &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= (src.a.m_pPtrReal[j] + src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + return *this; +} + +// = RealVector::OpBinaryAdd::Negative +RealVector& RealVector::operator=(const OpBinaryAdd::Negative &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = - (src.a.m_pPtrReal[j] + src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + return *this; +} + +// += RealVector::OpBinaryAdd::Negative +RealVector& RealVector::operator+=(const OpBinaryAdd::Negative &src) +{ + *this -= -src; + + return *this; +} + +// -= RealVector::OpBinaryAdd::Negative +RealVector& RealVector::operator-=(const OpBinaryAdd::Negative &src) +{ + *this += -src; + + return *this; +} + +// *= RealVector::OpBinaryAdd::Negative +RealVector& RealVector::operator*=(const OpBinaryAdd::Negative &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= - (src.a.m_pPtrReal[j] + src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + + return *this; +} + +// /= RealVector::OpBinaryAdd::Negative +RealVector& RealVector::operator/=(const OpBinaryAdd::Negative &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= - (src.a.m_pPtrReal[j] + src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + + return *this; +} + +// = RealVector::OpBinarySub +RealVector& RealVector::operator=(const OpBinarySub &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = (src.a.m_pPtrReal[j] - src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + return *this; +} + +// += RealVector::OpBinarySub +RealVector& RealVector::operator+=(const OpBinarySub &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] += (src.a.m_pPtrReal[j] - src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + return *this; +} + +// -= RealVector::OpBinarySub +RealVector& RealVector::operator-=(const OpBinarySub &src) +{ + *this += OpBinarySub(src.b, src.a); + return *this; +} + +// *= RealVector::OpBinarySub +RealVector& RealVector::operator*=(const OpBinarySub &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= (src.a.m_pPtrReal[j] - src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + return *this; +} + +// /= RealVector::OpBinarySub +RealVector& RealVector::operator/=(const OpBinarySub &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= (src.a.m_pPtrReal[j] - src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + return *this; +} + +// = RealVector::OpBinaryMul +RealVector& RealVector::operator=(const OpBinaryMul &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = (src.a.m_pPtrReal[j] * src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + return *this; +} + +// += RealVector::OpBinaryMul +RealVector& RealVector::operator+=(const OpBinaryMul &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] += (src.a.m_pPtrReal[j] * src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + return *this; +} + +// -= RealVector::OpBinaryMul +RealVector& RealVector::operator-=(const OpBinaryMul &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] -= (src.a.m_pPtrReal[j] * src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + return *this; +} + +// *= RealVector::OpBinaryMul +RealVector& RealVector::operator*=(const OpBinaryMul &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= (src.a.m_pPtrReal[j] * src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + return *this; +} + +// /= RealVector::OpBinaryMul +RealVector& RealVector::operator/=(const OpBinaryMul &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= (src.a.m_pPtrReal[j] * src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + return *this; +} + +// = RealVector::OpBinaryMul::Negative +RealVector& RealVector::operator=(const OpBinaryMul::Negative &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = - (src.a.m_pPtrReal[j] * src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + return *this; +} + +// += RealVector::OpBinaryMul::Negative +RealVector& RealVector::operator+=(const OpBinaryMul::Negative &src) +{ + *this -= -src; + + return *this; +} + +// -= RealVector::OpBinaryMul::Negative +RealVector& RealVector::operator-=(const OpBinaryMul::Negative &src) +{ + *this += -src; + + return *this; +} + +// *= RealVector::OpBinaryMul::Negative +RealVector& RealVector::operator*=(const OpBinaryMul::Negative &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= - (src.a.m_pPtrReal[j] * src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + + return *this; +} + +// /= RealVector::OpBinaryMul::Negative +RealVector& RealVector::operator/=(const OpBinaryMul::Negative &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= - (src.a.m_pPtrReal[j] * src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + + return *this; +} + +// = RealVector::OpBinaryDiv +RealVector& RealVector::operator=(const OpBinaryDiv &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = (src.a.m_pPtrReal[j] / src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + return *this; +} + +// += RealVector::OpBinaryDiv +RealVector& RealVector::operator+=(const OpBinaryDiv &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] += (src.a.m_pPtrReal[j] / src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + return *this; +} + +// -= RealVector::OpBinaryDiv +RealVector& RealVector::operator-=(const OpBinaryDiv &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] -= (src.a.m_pPtrReal[j] / src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + return *this; +} + +// *= RealVector::OpBinaryDiv +RealVector& RealVector::operator*=(const OpBinaryDiv &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= (src.a.m_pPtrReal[j] / src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + return *this; +} + +// /= RealVector::OpBinaryDiv +RealVector& RealVector::operator/=(const OpBinaryDiv &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= (src.a.m_pPtrReal[j] / src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + return *this; +} + +// = RealVector::OpBinaryDiv::Negative +RealVector& RealVector::operator=(const OpBinaryDiv::Negative &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = - (src.a.m_pPtrReal[j] / src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + return *this; +} + +// += RealVector::OpBinaryDiv::Negative +RealVector& RealVector::operator+=(const OpBinaryDiv::Negative &src) +{ + *this -= -src; + + return *this; +} + +// -= RealVector::OpBinaryDiv::Negative +RealVector& RealVector::operator-=(const OpBinaryDiv::Negative &src) +{ + *this += -src; + + return *this; +} + +// *= RealVector::OpBinaryDiv::Negative +RealVector& RealVector::operator*=(const OpBinaryDiv::Negative &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= - (src.a.m_pPtrReal[j] / src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + + return *this; +} + +// /= RealVector::OpBinaryDiv::Negative +RealVector& RealVector::operator/=(const OpBinaryDiv::Negative &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= - (src.a.m_pPtrReal[j] / src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + + return *this; +} + +// ------------------------------------------------- +// Binary Operators +// ------------------------------------------------- +// Returning RealVector::OpBinary +RealVector::OpBinaryAdd operator+(const RealVector &a, const RealVector &b) +{ + return RealVector::OpBinaryAdd (a, b); +} +#if 0 +RealVector::OpBinarySub operator+(const RealVectorNegative &a, const RealVector &b) +{ + return RealVector::OpBinarySub (b, -a); +} + +RealVector::OpBinarySub operator+(const RealVector &a, const RealVectorNegative &b) +{ + return RealVector::OpBinarySub (a, -b); +} + +RealVector::OpBinaryAdd::Negative operator+(const RealVectorNegative &a, const RealVectorNegative &b) +{ + return -RealVector::OpBinaryAdd (-a, -b); +} +#endif +RealVector::OpBinarySub operator-(const RealVector &a, const RealVector &b) +{ + return RealVector::OpBinarySub (a, b); +} + +RealVector::OpBinaryAdd::Negative operator-(const RealVectorNegative &a, const RealVector &b) +{ + return -RealVector::OpBinaryAdd (-a, b); +} + +RealVector::OpBinaryAdd operator-(const RealVector &a, const RealVectorNegative &b) +{ + return RealVector::OpBinaryAdd (a, -b); +} + +RealVector::OpBinarySub operator-(const RealVectorNegative &a, const RealVectorNegative &b) +{ + return RealVector::OpBinarySub (-b, -a); +} + +RealVector::OpBinaryMul operator*(const RealVector &a, const RealVector &b) +{ + return RealVector::OpBinaryMul (a, b); +} + +RealVector::OpBinaryMul::Negative operator*(const RealVectorNegative &a, const RealVector &b) +{ + return -RealVector::OpBinaryMul (-a, b); +} + +RealVector::OpBinaryMul::Negative operator*(const RealVector &a, const RealVectorNegative &b) +{ + return -RealVector::OpBinaryMul (a, -b); +} + +RealVector::OpBinaryMul operator*(const RealVectorNegative &a, const RealVectorNegative &b) +{ + return RealVector::OpBinaryMul (-a, -b); +} + +RealVector::OpBinaryDiv operator/(const RealVector &a, const RealVector &b) +{ + return RealVector::OpBinaryDiv (a, b); +} + +RealVector::OpBinaryDiv::Negative operator/(const RealVectorNegative &a, const RealVector &b) +{ + return -RealVector::OpBinaryDiv (-a, b); +} + +RealVector::OpBinaryDiv::Negative operator/(const RealVector &a, const RealVectorNegative &b) +{ + return -RealVector::OpBinaryDiv (a, -b); +} + +RealVector::OpBinaryDiv operator/(const RealVectorNegative &a, const RealVectorNegative &b) +{ + return RealVector::OpBinaryDiv (-a, -b); +} diff --git a/RealVector.hpp b/RealVector.hpp new file mode 100755 index 0000000..3af04d5 --- /dev/null +++ b/RealVector.hpp @@ -0,0 +1,234 @@ +#ifndef _REAL_HPP_ +#define _REAL_HPP_ + +#include +#include +#include + +void RealDebug(char *fmtstr, ...); + +class RealException +{ +public: + RealException (std::string s) + { + m_what = s; + } + ~RealException() + { + } + std::string& what() + { + return m_what; + } +private: + std::string m_what; +}; + +class _RealVector; + +class RealVector +{ +public: + friend class _RealVector; + struct unary_t + { + bool negative; + + unary_t() + : negative(0) + { + } + + struct unary_t neg(bool doNegative) + { + negative = doNegative; + return *this; + } + + }; + + enum OpType + { + Add = 0, + Sub, + Mul, + Div + }; + + template + class OpBinary + { + public: + const RealVector &a; + const RealVector &b; + unary_t m_unary_modifier; + + OpBinary(const RealVector &a, const RealVector &b) + : a(a) + , b(b) + , m_unary_modifier() + { + } + + OpBinary(const OpBinary &src, unary_t unary_modifier) + : a(src.a) + , b(src.b) + , m_unary_modifier(unary_modifier) + { + } + + bool isNegative() const + { + return m_unary_modifier.negative; + } + + bool isPositive() const + { + return !m_unary_modifier.negative; + } + + OpBinary operator-() const + { + unary_t unary = m_unary_modifier; + unary.negative = !unary.negative; + + return OpBinary(*this, unary); + } + + const OpBinary& operator+() const + { + return *this; + } + + ~OpBinary() + { + } + + private: + OpBinary& operator=(const OpBinary&); + }; + + + // Construct from float array + RealVector(uint32_t size, radio_float_t *real=0); + + // Copy constructor + RealVector(const RealVector &src); + + // Slicing constructor + RealVector(const RealVector &src, uint32_t from, uint32_t step, uint32_t to); + + // Unary resolver constructor (no data copy) + RealVector(const RealVector &src, unary_t unary_modifier); + + // OpBinaryAdd resolver copy constructor + RealVector(const OpBinary &src); + + // OpBinarySub resolver copy constructor + RealVector(const OpBinary &src); + + // OpBinaryMul resolver copy constructor + RealVector(const OpBinary &src); + + // OpBinaryDiv resolver copy constructor + RealVector(const OpBinary
&src); + + // Scalar constructor + RealVector(radio_float_t real); + + RealVector(const _RealVector &src); + + ~RealVector(void); + + uint32_t getSize() const; + radio_float_t getValue() const; + RealVector at(uint32_t const &i); + RealVector slice(uint32_t from, uint32_t step, uint32_t to); + void print(char *pPrefix) const; + bool isNegative() const; + bool isPositive() const; + RealVector operator-() const; + const RealVector& operator+() const; + + // Assignments + RealVector& operator=(const RealVector &src); + RealVector& operator+=(const RealVector &src); + RealVector& operator-=(const RealVector &src); + RealVector& operator*=(const RealVector &src); + RealVector& operator/=(const RealVector &src); + + RealVector& operator=(const OpBinary &src); + RealVector& operator+=(const OpBinary &src); + RealVector& operator-=(const OpBinary &src); + RealVector& operator*=(const OpBinary &src); + RealVector& operator/=(const OpBinary &src); + + RealVector& operator=(const OpBinary &src); + RealVector& operator+=(const OpBinary &src); + RealVector& operator-=(const OpBinary &src); + RealVector& operator*=(const OpBinary &src); + RealVector& operator/=(const OpBinary &src); + + RealVector& operator=(const OpBinary &src); + RealVector& operator+=(const OpBinary &src); + RealVector& operator-=(const OpBinary &src); + RealVector& operator*=(const OpBinary &src); + RealVector& operator/=(const OpBinary &src); + + RealVector& operator=(const OpBinary
&src); + RealVector& operator+=(const OpBinary
&src); + RealVector& operator-=(const OpBinary
&src); + RealVector& operator*=(const OpBinary
&src); + RealVector& operator/=(const OpBinary
&src); + + unary_t m_unary_modifier; + +private: + uint32_t m_size; + radio_float_t m_real; + radio_float_t *m_pBufReal; + radio_float_t *m_pPtrReal; + + _inline void checkSize(uint32_t size1, uint32_t size2) + { + try + { + if ((size1 != size2) && (size2 != 1)) + { + throw(RealException("Size mismatch")); + } + } + catch(RealException &exc) + { + RealDebug("Problem: %s\n", exc.what().c_str()); + } + } +}; + +class _RealVector +{ + friend class RealVector; +public: + _RealVector(const RealVector &src); + _RealVector(const _RealVector &src, RealVector::unary_t unary_modifier); + _RealVector operator-() const; + uint32_t m_size; + +private: + radio_float_t m_real; + radio_float_t *m_pBufReal; + radio_float_t *m_pPtrReal; + RealVector::unary_t m_unary_modifier; + +}; + +// Non-Member +// Binary Operators +// Returning RealVector::OpBinary +RealVector::OpBinary operator+(const RealVector &a, const RealVector &b); +RealVector::OpBinary operator-(const RealVector &a, const RealVector &b); +RealVector::OpBinary operator*(const RealVector &a, const RealVector &b); +RealVector::OpBinary operator/(const RealVector &a, const RealVector &b); + +#endif // _REAL_HPP_ \ No newline at end of file diff --git a/RealVector.hpp.inherit b/RealVector.hpp.inherit new file mode 100755 index 0000000..5da85fc --- /dev/null +++ b/RealVector.hpp.inherit @@ -0,0 +1,403 @@ +#ifndef _REAL_HPP_ +#define _REAL_HPP_ + +#include +#include +#include + +void RealDebug(char *fmtstr, ...); + +class RealException +{ +public: + RealException (std::string s) + { + m_what = s; + } + ~RealException() + { + } + std::string& what() + { + return m_what; + } +private: + std::string m_what; +}; + +class RealVectorNegative; + +class RealVector +{ +public: + + struct OpBinaryAdd + { + struct Negative + { + Negative(const OpBinaryAdd src) + : a(src.a) + , b(src.b) + { + } + + OpBinaryAdd operator-() const + { + return OpBinaryAdd(a, b); + } + const RealVector &a; + const RealVector &b; + + private: + Negative& operator=(const Negative&); + }; + + OpBinaryAdd(const RealVector &a, const RealVector &b) + : a(a) + , b(b) + { + } + + Negative operator-() const + { + return Negative(*this); + } + + const OpBinaryAdd& operator+() const + { + return *this; + } + + ~OpBinaryAdd() + { + } + const RealVector &a; + const RealVector &b; + + private: + OpBinaryAdd& operator=(const OpBinaryAdd&); + }; + + struct OpBinarySub + { + struct Negative + { + Negative(const OpBinarySub src) + : a(src.a) + , b(src.b) + { + } + + OpBinarySub operator-() const + { + return OpBinarySub(a, b); + } + const RealVector &a; + const RealVector &b; + + private: + Negative& operator=(const Negative&); + }; + + OpBinarySub(const RealVector &a, const RealVector &b) + : a(a) + , b(b) + { + } + + ~OpBinarySub() + { + } + + Negative operator-() const + { + return Negative(*this); + } + + const OpBinarySub& operator+() const + { + return *this; + } + + const RealVector &a; + const RealVector &b; + + private: + OpBinarySub& operator=(const OpBinarySub&); + }; + + struct OpBinaryMul + { + struct Negative + { + Negative(const OpBinaryMul src) + : a(src.a) + , b(src.b) + { + } + + OpBinaryMul operator-() const + { + return OpBinaryMul(a, b); + } + const RealVector &a; + const RealVector &b; + + private: + Negative& operator=(const Negative&); + }; + + OpBinaryMul(const RealVector &a, const RealVector &b) + : a(a) + , b(b) + { + } + + Negative operator-() const + { + return Negative(*this); + } + + const OpBinaryMul& operator+() const + { + return *this; + } + + ~OpBinaryMul() + { + } + const RealVector &a; + const RealVector &b; + + private: + OpBinaryMul& operator=(const OpBinaryMul&); + }; + + struct OpBinaryDiv + { + struct Negative + { + Negative(const OpBinaryDiv src) + : a(src.a) + , b(src.b) + { + } + + OpBinaryDiv operator-() const + { + return OpBinaryDiv(a, b); + } + const RealVector &a; + const RealVector &b; + + private: + Negative& operator=(const Negative&); + }; + + OpBinaryDiv(const RealVector &a, const RealVector &b) + : a(a) + , b(b) + { + } + + Negative operator-() const + { + return Negative(*this); + } + + const OpBinaryDiv& operator+() const + { + return *this; + } + + ~OpBinaryDiv() + { + } + const RealVector &a; + const RealVector &b; + + private: + OpBinaryDiv& operator=(const OpBinaryDiv&); + }; + + ~RealVector(void); + + // Standard constructor + RealVector(uint32_t size, radio_float_t *real=0); + + // Copy constructor + RealVector(const RealVector &src); + + // Slicing constructor + RealVector(RealVector &src, uint32_t from, uint32_t step, uint32_t to); + + // Negative resolver copy constructor + RealVector(const RealVectorNegative &src); + + // OpBinaryAdd resolver copy constructor + RealVector(const OpBinaryAdd &src); + + // OpBinaryAdd::Negative resolver copy constructor + RealVector(const OpBinaryAdd::Negative &src); + + // OpBinarySub resolver copy constructor + RealVector(const OpBinarySub &src); + + // OpBinaryMul resolver copy constructor + RealVector(const OpBinaryMul &src); + + // OpBinaryMul::Negative resolver copy constructor + RealVector(const OpBinaryMul::Negative &src); + + // OpBinaryDiv resolver copy constructor + RealVector(const OpBinaryDiv &src); + + // OpBinaryDiv::Negative resolver copy constructor + RealVector(const OpBinaryDiv::Negative &src); + + // Scalar constructor + RealVector(radio_float_t real); + + uint32_t getSize() const; + + radio_float_t getValue() const; + + RealVector at(uint32_t const &i); + void print(char *pPrefix) const; + + RealVectorNegative operator-() const; + const RealVector& operator+() const; + + // Assignments + RealVector& operator=(const RealVector &src); + RealVector& operator+=(const RealVector &src); + RealVector& operator-=(const RealVector &src); + RealVector& operator*=(const RealVector &src); + RealVector& operator/=(const RealVector &src); + + RealVector& operator=(const RealVectorNegative &src); + RealVector& operator+=(const RealVectorNegative &src); + RealVector& operator-=(const RealVectorNegative &src); + RealVector& operator*=(const RealVectorNegative &src); + RealVector& operator/=(const RealVectorNegative &src); + + RealVector& operator=(const OpBinaryAdd &src); + RealVector& operator+=(const OpBinaryAdd &src); + RealVector& operator-=(const OpBinaryAdd &src); + RealVector& operator*=(const OpBinaryAdd &src); + RealVector& operator/=(const OpBinaryAdd &src); + + RealVector& operator=(const OpBinaryAdd::Negative &src); + RealVector& operator+=(const OpBinaryAdd::Negative &src); + RealVector& operator-=(const OpBinaryAdd::Negative &src); + RealVector& operator*=(const OpBinaryAdd::Negative &src); + RealVector& operator/=(const OpBinaryAdd::Negative &src); + + RealVector& operator=(const OpBinarySub &src); + RealVector& operator+=(const OpBinarySub &src); + RealVector& operator-=(const OpBinarySub &src); + RealVector& operator*=(const OpBinarySub &src); + RealVector& operator/=(const OpBinarySub &src); + + RealVector& operator=(const OpBinaryMul &src); + RealVector& operator+=(const OpBinaryMul &src); + RealVector& operator-=(const OpBinaryMul &src); + RealVector& operator*=(const OpBinaryMul &src); + RealVector& operator/=(const OpBinaryMul &src); + + RealVector& operator=(const OpBinaryMul::Negative &src); + RealVector& operator+=(const OpBinaryMul::Negative &src); + RealVector& operator-=(const OpBinaryMul::Negative &src); + RealVector& operator*=(const OpBinaryMul::Negative &src); + RealVector& operator/=(const OpBinaryMul::Negative &src); + + RealVector& operator=(const OpBinaryDiv &src); + RealVector& operator+=(const OpBinaryDiv &src); + RealVector& operator-=(const OpBinaryDiv &src); + RealVector& operator*=(const OpBinaryDiv &src); + RealVector& operator/=(const OpBinaryDiv &src); + + RealVector& operator=(const OpBinaryDiv::Negative &src); + RealVector& operator+=(const OpBinaryDiv::Negative &src); + RealVector& operator-=(const OpBinaryDiv::Negative &src); + RealVector& operator*=(const OpBinaryDiv::Negative &src); + RealVector& operator/=(const OpBinaryDiv::Negative &src); + +private: + uint32_t m_size; + radio_float_t m_real; + radio_float_t *m_pBufReal; + radio_float_t *m_pPtrReal; + + _inline void checkSize(uint32_t size1, uint32_t size2) + { + try + { + if ((size1 != size2) && (size2 != 1)) + { + throw(RealException("Size mismatch")); + } + } + catch(RealException &exc) + { + RealDebug("Problem: %s\n", exc.what().c_str()); + } + } + +}; + +class RealVectorNegative : public RealVector +{ +public: + RealVectorNegative(const RealVector &src) + : RealVector(src) + , m_iamNegative(true) + { + } + + const RealVector& operator-() const + { + return (RealVector&)*this; + } + + const RealVectorNegative& operator+() const + { + return *this; + } + +private: + bool m_iamNegative; + RealVectorNegative& operator=(const RealVectorNegative&); +}; + + +// Non-Member +// Binary Operators +// Returning RealVector::OpBinary +RealVector::OpBinaryAdd operator+(const RealVector &a, const RealVector &b); +#if 0 +RealVector::OpBinarySub operator+(const RealVectorNegative &a, const RealVector &b); +RealVector::OpBinarySub operator+(const RealVector &a, const RealVectorNegative &b); +RealVector::OpBinaryAdd::Negative operator+(const RealVectorNegative &a, const RealVectorNegative &b); +#endif + +RealVector::OpBinarySub operator-(const RealVector &a, const RealVector &b); +#if 0 +RealVector::OpBinaryAdd::Negative operator-(const RealVectorNegative &a, const RealVector &b); +RealVector::OpBinaryAdd operator-(const RealVector &a, const RealVectorNegative &b); +RealVector::OpBinarySub operator-(const RealVectorNegative &a, const RealVectorNegative &b); +#endif + +RealVector::OpBinaryMul operator*(const RealVector &a, const RealVector &b); +#if 0 +RealVector::OpBinaryMul::Negative operator*(const RealVectorNegative &a, const RealVector &b); +RealVector::OpBinaryMul::Negative operator*(const RealVector &a, const RealVectorNegative &b); +RealVector::OpBinaryMul operator*(const RealVectorNegative &a, const RealVectorNegative &b); +#endif + +RealVector::OpBinaryDiv operator/(const RealVector &a, const RealVector &b); +RealVector::OpBinaryDiv::Negative operator/(const RealVectorNegative &a, const RealVector &b); +RealVector::OpBinaryDiv::Negative operator/(const RealVector &a, const RealVectorNegative &b); +RealVector::OpBinaryDiv operator/(const RealVectorNegative &a, const RealVectorNegative &b); + +#endif // _REAL_HPP_ \ No newline at end of file diff --git a/RealVector2.cpp b/RealVector2.cpp new file mode 100755 index 0000000..84cf117 --- /dev/null +++ b/RealVector2.cpp @@ -0,0 +1,785 @@ +#include +#include +#include +#include +#include "RealVector.hpp" + +void RealDebug(char *fmtstr, ...) +{ + char buf[1024]; + va_list args; + + va_start(args, fmtstr); + vsprintf(buf, fmtstr, args); + va_end(args); + OutputDebugString(buf); + +} + +// ------------------------------------------------- +// Assignments +// ------------------------------------------------- +// = RealVector +RealVector& RealVector::operator=(const RealVector &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(m_size, src.m_size); + + j = 0; + dj = src.m_size > 1; + if (src.isNegative()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = -src.m_pPtrReal[j]; + j += dj; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = src.m_pPtrReal[j]; + j += dj; + } + } + return *this; +} + +// += RealVector +RealVector& RealVector::operator+=(const RealVector &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(m_size, src.m_size); + + j = 0; + dj = src.m_size > 1; + if (src.isNegative()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] -= src.m_pPtrReal[j]; + j += dj; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] += src.m_pPtrReal[j]; + j += dj; + } + } + return *this; +} + +// -= RealVector +RealVector& RealVector::operator-=(const RealVector &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(m_size, src.m_size); + + j = 0; + dj = src.m_size > 1; + if (src.isNegative()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] += src.m_pPtrReal[j]; + j += dj; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] -= src.m_pPtrReal[j]; + j += dj; + } + } + return *this; +} + +// *= RealVector +RealVector& RealVector::operator*=(const RealVector &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(m_size, src.m_size); + + j = 0; + dj = src.m_size > 1; + if (src.isNegative()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= -src.m_pPtrReal[j]; + j += dj; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= src.m_pPtrReal[j]; + j += dj; + } + } + return *this; +} + +// /= RealVector +RealVector& RealVector::operator/=(const RealVector &src) +{ + uint32_t i; + uint32_t j; + uint32_t dj; + + checkSize(m_size, src.m_size); + + j = 0; + dj = src.m_size > 1; + if (src.isNegative()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= -src.m_pPtrReal[j]; + j += dj; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= src.m_pPtrReal[j]; + j += dj; + } + } + return *this; +} + +// = RealVector::OpBinary +RealVector& RealVector::operator=(const OpBinary &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + switch (src.op) + { + case OpBinary::ADD: + if (!src.isNegative()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = + src.a.m_pPtrReal[j] + src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = - src.a.m_pPtrReal[j] - src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + break; + + case OpBinary::SUB: + if (!src.isNegative()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = + src.a.m_pPtrReal[j] - src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = - src.a.m_pPtrReal[j] + src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + break; + + case OpBinary::MUL: + if (!src.isNegative()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = + src.a.m_pPtrReal[j] * src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = - src.a.m_pPtrReal[j] * src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + break; + + case OpBinary::DIV: + if (!src.isNegative()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = + src.a.m_pPtrReal[j] / src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] = - (src.a.m_pPtrReal[j] / src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + break; + + default: + break; + } + return *this; +} + +// += RealVector::OpBinary +RealVector& RealVector::operator+=(const OpBinary &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + switch (src.op) + { + case OpBinary::ADD: + if (!src.isNegative()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] += + src.a.m_pPtrReal[j] + src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] += - src.a.m_pPtrReal[j] - src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + break; + + case OpBinary::SUB: + if (!src.isNegative()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] += + src.a.m_pPtrReal[j] - src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] += - src.a.m_pPtrReal[j] + src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + break; + + case OpBinary::MUL: + if (!src.isNegative()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] += + src.a.m_pPtrReal[j] * src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] += - src.a.m_pPtrReal[j] * src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + break; + + case OpBinary::DIV: + if (!src.isNegative()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] += + src.a.m_pPtrReal[j] / src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] += - (src.a.m_pPtrReal[j] / src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + break; + + default: + break; + } + return *this; +} + +// -= RealVector::OpBinary +RealVector& RealVector::operator-=(const OpBinary &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + switch (src.op) + { + case OpBinary::ADD: + if (!src.isNegative()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] -= + src.a.m_pPtrReal[j] + src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] -= - src.a.m_pPtrReal[j] - src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + break; + + case OpBinary::SUB: + if (!src.isNegative()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] -= + src.a.m_pPtrReal[j] - src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] -= - src.a.m_pPtrReal[j] + src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + break; + + case OpBinary::MUL: + if (!src.isNegative()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] -= + src.a.m_pPtrReal[j] * src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] -= - src.a.m_pPtrReal[j] * src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + break; + + case OpBinary::DIV: + if (!src.isNegative()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] -= + src.a.m_pPtrReal[j] / src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] -= - (src.a.m_pPtrReal[j] / src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + break; + + default: + break; + } + return *this; +} + +// *= RealVector::OpBinary +RealVector& RealVector::operator*=(const OpBinary &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + switch (src.op) + { + case OpBinary::ADD: + if (!src.isNegative()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= + src.a.m_pPtrReal[j] + src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= - src.a.m_pPtrReal[j] - src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + break; + + case OpBinary::SUB: + if (!src.isNegative()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= + src.a.m_pPtrReal[j] - src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= - src.a.m_pPtrReal[j] + src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + break; + + case OpBinary::MUL: + if (!src.isNegative()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= + src.a.m_pPtrReal[j] * src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= - src.a.m_pPtrReal[j] * src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + break; + + case OpBinary::DIV: + if (!src.isNegative()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= + src.a.m_pPtrReal[j] / src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] *= - (src.a.m_pPtrReal[j] / src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + break; + + default: + break; + } + return *this; +} + +// /= RealVector::OpBinary +RealVector& RealVector::operator/=(const OpBinary &src) +{ + uint32_t i, j, k; + uint32_t dj, dk; + + dj = src.a.m_size > 1; + dk = src.b.m_size > 1; + + j = 0; + k = 0; + switch (src.op) + { + case OpBinary::ADD: + if (!src.isNegative()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= + src.a.m_pPtrReal[j] + src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= - src.a.m_pPtrReal[j] - src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + break; + + case OpBinary::SUB: + if (!src.isNegative()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= + src.a.m_pPtrReal[j] - src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= - src.a.m_pPtrReal[j] + src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + break; + + case OpBinary::MUL: + if (!src.isNegative()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= + src.a.m_pPtrReal[j] * src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= - src.a.m_pPtrReal[j] * src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + break; + + case OpBinary::DIV: + if (!src.isNegative()) + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= + src.a.m_pPtrReal[j] / src.b.m_pPtrReal[k]; + j += dj; + k += dk; + } + } + else + { + for (i=0; i < m_size; i++) + { + m_pPtrReal[i] /= - (src.a.m_pPtrReal[j] / src.b.m_pPtrReal[k]); + j += dj; + k += dk; + } + } + break; + + default: + break; + } + return *this; +} + +// ------------------------------------------------- +// Binary Operators +// ------------------------------------------------- +// Returning RealVector::OpBinary +RealVector::OpBinary operator+(const RealVector &a, const RealVector &b) +{ + if (a.isNegative()) + { + if (b.isNegative()) + { + return -RealVector::OpBinary (a, b, RealVector::OpBinary::ADD); + } + else + { + return RealVector::OpBinary (b, a, RealVector::OpBinary::SUB); + } + } + + if (b.isNegative()) + { + return RealVector::OpBinary (a, b, RealVector::OpBinary::SUB); + } + else + { + return RealVector::OpBinary (a, b, RealVector::OpBinary::ADD); + } +} + +RealVector::OpBinary operator-(const RealVector &a, const RealVector &b) +{ + if (a.isNegative()) + { + if (b.isNegative()) + { + return RealVector::OpBinary (b, a, RealVector::OpBinary::SUB); + } + else + { + return -RealVector::OpBinary (a, b, RealVector::OpBinary::ADD); + } + } + + if (b.isNegative()) + { + return RealVector::OpBinary (a, b, RealVector::OpBinary::SUB); + } + else + { + return RealVector::OpBinary (a, b, RealVector::OpBinary::ADD); + } +} + +RealVector::OpBinary operator*(const RealVector &a, const RealVector &b) +{ + if (a.isNegative()) + { + if (b.isNegative()) + { + return RealVector::OpBinary (a, b, RealVector::OpBinary::MUL); + } + else + { + return -RealVector::OpBinary (a, b, RealVector::OpBinary::MUL); + } + } + + if (b.isNegative()) + { + return -RealVector::OpBinary (a, b, RealVector::OpBinary::MUL); + } + else + { + return RealVector::OpBinary (a, b, RealVector::OpBinary::MUL); + } +} + +RealVector::OpBinary operator/(const RealVector &a, const RealVector &b) +{ + if (a.isNegative()) + { + if (b.isNegative()) + { + return RealVector::OpBinary (a, b, RealVector::OpBinary::DIV); + } + else + { + return -RealVector::OpBinary (a, b, RealVector::OpBinary::DIV); + } + } + + if (b.isNegative()) + { + return -RealVector::OpBinary (a, b, RealVector::OpBinary::DIV); + } + else + { + return RealVector::OpBinary (a, b, RealVector::OpBinary::DIV); + } +} diff --git a/RealVector2.hpp b/RealVector2.hpp new file mode 100755 index 0000000..04e4451 --- /dev/null +++ b/RealVector2.hpp @@ -0,0 +1,271 @@ +#ifndef _REAL_HPP_ +#define _REAL_HPP_ + +#include +#include +#include + +void RealDebug(char *fmtstr, ...); + +class RealException +{ +public: + RealException (std::string s) + { + m_what = s; + } + ~RealException() + { + } + std::string& what() + { + return m_what; + } +private: + std::string m_what; +}; + +class RealVector +{ +public: + + struct OpBinary + { + enum OpType + { + ADD = 0, + SUB, + MUL, + DIV + }; + + typedef struct _attributes_t + { + bool negative; + } attributes_t; + + OpBinary(const RealVector &a, const RealVector &b, OpType op) + : a(a) + , b(b) + , op(op) + , m_attributes(defaultAttributes()) + { + } + OpBinary operator-() + { + attributes_t attributes = this->m_attributes; + attributes.negative = !attributes.negative; + + return OpBinary(*this, attributes); + } + ~OpBinary() + { + } + + bool isNegative() const + { + return m_attributes.negative; + } + const RealVector &a; + const RealVector &b; + const OpType op; + attributes_t m_attributes; + + private: + OpBinary& operator=(const OpBinary&); + OpBinary(const OpBinary &src, attributes_t attributes) + : a(src.a) + , b(src.b) + , op(src.op) + , m_attributes(attributes) + { + } + static const attributes_t defaultAttributes() + { + attributes_t attributes; + attributes.negative = false; + return attributes; + } + }; + + typedef struct _attributes_t + { + bool negative; + } attributes_t; + + // Standard constructor + RealVector(uint32_t size, radio_float_t *real=0) + : m_size(size) + , m_real(0) + , m_pBufReal(0) + , m_pPtrReal(real) + , m_attributes(defaultAttributes()) + { + if (!real) + { + m_pBufReal = new radio_float_t[m_size]; + memset(m_pBufReal, 0, m_size*sizeof(radio_float_t)); + m_pPtrReal = m_pBufReal; + } + } + + // OpBinary resolver copy constructor + RealVector(const OpBinary &src) + : m_size(src.a.m_size) + , m_real(0) + , m_pBufReal(0) + , m_pPtrReal(0) + , m_attributes(defaultAttributes()) + { + m_pBufReal = new radio_float_t[m_size]; + m_pPtrReal = m_pBufReal; + + *this = src; + } + + // Scalar constructor + RealVector(radio_float_t real) + : m_size(1) + , m_real(real) + , m_pBufReal(0) + , m_pPtrReal(&m_real) + , m_attributes(defaultAttributes()) + { + } + + ~RealVector(void) + { + if (m_pBufReal) + delete(m_pBufReal); + + m_pBufReal = nullptr; + } + + bool isNegative() const + { + return m_attributes.negative; + } + + uint32_t getSize() + { + return m_size; + } + + RealVector at(uint32_t const &i) + { + return RealVector(*this, i, 1, i); + } + + void print(char *pPrefix) + { + uint32_t i; + + RealDebug("%s:\n", pPrefix); + for (i=0; i < m_size; i++) + { + RealDebug("%d: %.6f\n", i, m_pPtrReal[i]); + } + } + + RealVector operator-() + { + attributes_t attributes = this->m_attributes; + attributes.negative = !attributes.negative; + + return RealVector(*this, attributes); + } + + // Assignments + RealVector& operator=(const RealVector &src); + RealVector& operator+=(const RealVector &src); + RealVector& operator-=(const RealVector &src); + RealVector& operator*=(const RealVector &src); + RealVector& operator/=(const RealVector &src); + RealVector& operator=(const OpBinary &src); + RealVector& operator+=(const OpBinary &src); + RealVector& operator-=(const OpBinary &src); + RealVector& operator*=(const OpBinary &src); + RealVector& operator/=(const OpBinary &src); + +private: + uint32_t m_size; + radio_float_t m_real; + radio_float_t *m_pBufReal; + radio_float_t *m_pPtrReal; + attributes_t m_attributes; + + // Attribute default + const attributes_t defaultAttributes() + { + attributes_t attributes; + + attributes.negative = 0; + + return attributes; + } + + // Copy constructor + RealVector(const RealVector &src) + : m_size(src.m_size) + , m_real(0) + , m_pBufReal(0) + , m_pPtrReal(0) + { + m_pBufReal = new radio_float_t[m_size]; + m_pPtrReal = m_pBufReal; + + *this = src; + } + + // Re-attribute constructor + // Copies no data, just pointers and attributes + RealVector(const RealVector &src, attributes_t attributes) + : m_size(src.m_size) + , m_real(src.m_real) + , m_pBufReal(0) + , m_pPtrReal(src.m_pPtrReal) + , m_attributes(attributes) + { + } + + // Slicing constructor + RealVector(RealVector &src, uint32_t from, uint32_t step, uint32_t to) + : m_size(0) + , m_pBufReal(0) + , m_pPtrReal(&src.m_pPtrReal[from]) + { + uint32_t i; + + for (i=from; i < to; i+=step) + { + m_size++; + } + } + + + _inline void checkSize(uint32_t size1, uint32_t size2) + { + try + { + if ((size1 != size2) && (size2 != 1)) + { + throw(RealException("Size mismatch")); + } + } + catch(RealException &exc) + { + RealDebug("Problem: %s\n", exc.what().c_str()); + } + } + +}; + +// Non-Member +// Binary Operators +// Returning RealVector::OpBinary +RealVector::OpBinary operator+(const RealVector &a, const RealVector &b); +RealVector::OpBinary operator-(const RealVector &a, const RealVector &b); +RealVector::OpBinary operator*(const RealVector &a, const RealVector &b); +RealVector::OpBinary operator/(const RealVector &a, const RealVector &b); + +#endif // _REAL_HPP_ \ No newline at end of file diff --git a/agc.c b/agc.c new file mode 100755 index 0000000..dc42328 --- /dev/null +++ b/agc.c @@ -0,0 +1,41 @@ +// -------------------------------------------------------------- +#include +#include +#include "agc.h" + +// -------------------------------------------------------------- +// AGC +// Scalar version +// -------------------------------------------------------------- +void AGC_Init(agc_t *pObj, uint32_t windowLength, radio_float_t w_init) +{ + pObj->w = w_init; + SlidingMinMaxInit(&pObj->slMax, windowLength, (radio_float_t)1E12, 1); +} + +void AGC_Free(agc_t *pObj) +{ + SlidingMinMaxFree(&pObj->slMax); +} + +void AGC_Process(agc_t *pObj, radio_float_t x, radio_float_t mu, radio_float_t target) +{ + radio_float_t d2; + radio_float_t e; + + d2 = SlidingMinMaxProcess(&pObj->slMax, x); + e = target - d2; + pObj->w += mu*e*dabs(x); +} + +void AGC_Train(agc_t *pObj, radio_float_t e, radio_float_t mu) +{ + pObj->w += mu*e; +} + +radio_float_t AGC_GetWeight(agc_t *pObj) +{ + return pObj->w; +} + +// -------------------------------------------------------------- diff --git a/agc.h b/agc.h new file mode 100755 index 0000000..6e4631c --- /dev/null +++ b/agc.h @@ -0,0 +1,39 @@ +// -------------------------------------------------------------- +#ifndef AGC_H +#define AGC_H + +#include +#include "radio_types.h" +#include "statistics.h" + +// -------------------------------------------------------------- +// Types +// -------------------------------------------------------------- +typedef struct _agc_t +{ + radio_float_t w; + sl_minmax_t slMax; +} agc_t; + +// -------------------------------------------------------------- +#ifdef __cplusplus +extern "C" { +#endif + +// -------------------------------------------------------------- +// AGC +// -------------------------------------------------------------- +// Scalar version +void AGC_Init(agc_t *pObj, uint32_t windowLength, radio_float_t w_init); +void AGC_Free(agc_t *pObj); +void AGC_Train(agc_t *pObj, radio_float_t e, radio_float_t mu); +void AGC_Process(agc_t *pObj, radio_float_t x, radio_float_t mu, radio_float_t target); +radio_float_t AGC_GetWeight(agc_t *pObj); + +// -------------------------------------------------------------- +#ifdef __cplusplus +} +#endif // __cplusplus + +// -------------------------------------------------------------- +#endif // AGC_H diff --git a/cpx.c b/cpx.c new file mode 100755 index 0000000..066e9fc --- /dev/null +++ b/cpx.c @@ -0,0 +1,591 @@ +// -------------------------------------------------------------- +#include +#include +#include "radio_types.h" +#include "real.h" +#include "cpx.h" + +// -------------------------------------------------------------- +// Basic Functions +// -------------------------------------------------------------- + +cpx_t CpxConjS(cpx_t v1) +{ + register cpx_t temp; + + temp.real = v1.real; + temp.imag = -v1.imag; + + return temp; + +} + +cpx_t CpxAddS(cpx_t v1, cpx_t v2) +{ + register cpx_t temp; + + temp.real = v1.real + v2.real; + temp.imag = v1.imag + v2.imag; + + return temp; +} + +cpx_t CpxSubS(cpx_t v1, cpx_t v2) +{ + register cpx_t temp; + + temp.real = v1.real - v2.real; + temp.imag = v1.imag - v2.imag; + + return temp; +} + +cpx_t CpxMulS(cpx_t v1, cpx_t v2) +{ + register cpx_t t_0; + register cpx_t t_1; + + t_0.real = v1.real*v2.real; + t_1.real = v1.imag*v2.imag; + t_0.imag = v1.real*v2.imag; + t_1.imag = v1.imag*v2.real; + + t_0.real -= t_1.real; + t_0.imag += t_1.imag; + + return t_0; +} + +cpx_t CpxScaleRealS(cpx_t v1, radio_float_t v2) +{ + register cpx_t temp; + + temp.real = v1.real*v2; + temp.imag = v1.imag*v2; + + return temp; +} + +cpx_t CpxScaleComplexS(cpx_t x, cpx_t gain) +{ + register cpx_t temp; + + temp.real = x.real*gain.real; + temp.imag = x.imag*gain.imag; + + return temp; +} + +cpx_t CpxFromReal(radio_float_t v1) +{ + return Cpx(v1, v1); +} + +cpx_t Cpx(radio_float_t real, radio_float_t imag) +{ + cpx_t res; + + res.real = real; + res.imag = imag; + + return res; +} + +radio_float_t CpxMagS(cpx_t v1) +{ + radio_float_t mag; + + mag = (radio_float_t)sqrt(v1.real*v1.real + v1.imag*v1.imag); + + return mag; +} + +radio_float_t CpxPhiS(cpx_t v1) +{ + return (radio_float_t)atan2(v1.real, v1.imag); +} + +cpx_t CpxMinS(cpx_t x1, cpx_t x2) +{ + return Cpx(dmin(x1.real, x2.real), dmin(x1.imag, x2.imag)); +} + +cpx_t CpxMaxS(cpx_t x1, cpx_t x2) +{ + return Cpx(dmax(x1.real, x2.real), dmax(x1.imag, x2.imag)); +} + +radio_float_t cpxPowerDB(cpx_t v1, radio_float_t preScale) +{ + return powerDB(CpxMagS(v1), preScale); +} + +// -------------------------------------------------------------- +// Complex Functions +// -------------------------------------------------------------- +void CpxCopy(cpx_t *pSrc, cpx_t *pDst, uint32_t len) +{ + memcpy(pDst, pSrc, len*sizeof(cpx_t)); +} + +void CpxConj(cpx_t *pSrcDst, uint32_t len) +{ + uint32_t i; + for(i=0; i < len; i++) + pSrcDst[i] = CpxConjS(pSrcDst[i]); +} + +void CpxAddB8(cpx_t *pV1, cpx_t *pV2, cpx_t *pRes) +{ + uint32_t i; + + radio_float_t r0[8]; + radio_float_t i0[8]; + + radio_float_t vr0[8]; + radio_float_t vr1[8]; + radio_float_t vi0[8]; + radio_float_t vi1[8]; + + for (i=0; i < 8; i++) + { + vr0[i] = pV1[i].real; + vr1[i] = pV2[i].real; + vi0[i] = pV1[i].imag; + vi1[i] = pV2[i].imag; + } + + for (i=0; i < 8; i++) + { + r0[i] = vr0[i] + vr1[i]; + i0[i] = vi0[i] + vi1[i]; + } + + for (i=0; i < 8; i++) + { + pRes[i].real = r0[i]; + pRes[i].imag = i0[i]; + } + +} + +void CpxAdd(cpx_t *pSrc, cpx_t *pSrcDst, uint32_t len) +{ + uint32_t i; + + for(i=0; i < len-8; i += 8) + { + CpxAddB8(&pSrc[i], &pSrcDst[i], &pSrcDst[i]); + } + + for(i=i; i < len; i++) + { + pSrcDst[i].real += pSrc[i].real; + pSrcDst[i].imag += pSrc[i].imag; + } +} + +void CpxSub(cpx_t *pSrc, cpx_t *pSrcDst, uint32_t len) +{ + uint32_t i; + for(i=0; i < len; i++) + pSrcDst[i] = CpxSubS(pSrc[i], pSrcDst[i]); +} + +void CpxMulB8(cpx_t *pV1, cpx_t *pV2, cpx_t *pRes) +{ + uint32_t i; + radio_float_t r0[8]; + radio_float_t r1[8]; + + radio_float_t vr0[8]; + radio_float_t vr1[8]; + radio_float_t vi0[8]; + radio_float_t vi1[8]; + + for (i=0; i < 8; i++) + { + vr0[i] = pV1[i].real; + vr1[i] = pV2[i].real; + vi0[i] = pV1[i].imag; + vi1[i] = pV2[i].imag; + } + + for (i=0; i < 8; i++) + { + r0[i] = vr0[i]*vr1[i]; + } + for (i=0; i < 8; i++) + { + r1[i] = vi0[i]*vi1[i]; + } + for (i=0; i < 8; i++) + { + pRes[i].real = r0[i] - r1[i]; + } + + for (i=0; i < 8; i++) + { + r0[i] = vr0[i]*vi1[i]; + } + for (i=0; i < 8; i++) + { + r1[i] = vi0[i]*vr1[i]; + } + for (i=0; i < 8; i++) + { + pRes[i].imag = r0[i] + r1[i]; + } + +} + +void CpxMulAddB8(cpx_t *pV1, cpx_t *pV2, cpx_t *pRes) +{ + uint32_t i; + radio_float_t r0[8]; + radio_float_t r1[8]; + + radio_float_t vr0[8]; + radio_float_t vr1[8]; + radio_float_t vi0[8]; + radio_float_t vi1[8]; + + for (i=0; i < 8; i++) + { + vr0[i] = pV1[i].real; + vr1[i] = pV2[i].real; + vi0[i] = pV1[i].imag; + vi1[i] = pV2[i].imag; + } + + for (i=0; i < 8; i++) + { + r0[i] = vr0[i]*vr1[i]; + } + for (i=0; i < 8; i++) + { + r1[i] = vi0[i]*vi1[i]; + } + for (i=0; i < 8; i++) + { + r0[i] -= r1[i]; + } + for (i=0; i < 8; i++) + { + pRes->real += r0[i]; + } + + for (i=0; i < 8; i++) + { + r0[i] = vr0[i]*vi1[i]; + } + for (i=0; i < 8; i++) + { + r1[i] = vi0[i]*vr1[i]; + } + for (i=0; i < 8; i++) + { + r0[i] += r1[i]; + } + for (i=0; i < 8; i++) + { + pRes->imag += r0[i]; + } + +} +void CpxScaleB8(cpx_t *v1, cpx_t v2, cpx_t *pRes) +{ + uint32_t i; + radio_float_t r0[8]; + radio_float_t r1[8]; + + radio_float_t vr0[8]; + radio_float_t vi0[8]; + + for (i=0; i < 8; i++) + { + vr0[i] = v1[i].real; + vi0[i] = v1[i].imag; + } + + for (i=0; i < 8; i++) + { + r0[i] = vr0[i]*v2.real; + } + for (i=0; i < 8; i++) + { + r1[i] = vi0[i]*v2.imag; + } + for (i=0; i < 8; i++) + { + r0[i] -= r1[i]; + } + for (i=0; i < 8; i++) + { + pRes[i].real = r0[i]; + } + + for (i=0; i < 8; i++) + { + r0[i] = vr0[i]*v2.imag; + } + for (i=0; i < 8; i++) + { + r1[i] = vi0[i]*v2.real; + } + for (i=0; i < 8; i++) + { + r0[i] += r1[i]; + } + for (i=0; i < 8; i++) + { + pRes[i].imag = r0[i]; + } +} + +void CpxMulRealB8(cpx_t *v1, radio_float_t *v2, cpx_t *pRes) +{ + uint32_t i; + + radio_float_t r0[8]; + radio_float_t i0[8]; + + radio_float_t vr0[8]; + radio_float_t vi0[8]; + + for (i=0; i < 8; i++) + { + vr0[i] = v1[i].real; + vi0[i] = v1[i].imag; + } + + for (i=0; i < 8; i++) + { + r0[i] = vr0[i]*v2[i]; + i0[i] = vi0[i]*v2[i]; + } + for (i=0; i < 8; i++) + { + pRes[i].real = r0[i]; + pRes[i].imag = i0[i]; + } +} + +void CpxMulRealAddB8(cpx_t *v1, radio_float_t *v2, cpx_t *pRes) +{ + uint32_t i; + + radio_float_t r0[8]; + radio_float_t i0[8]; + + radio_float_t vr0[8]; + radio_float_t vi0[8]; + + for (i=0; i < 8; i++) + { + vr0[i] = v1[i].real; + vi0[i] = v1[i].imag; + } + + for (i=0; i < 8; i++) + { + r0[i] = vr0[i]*v2[i]; + i0[i] = vi0[i]*v2[i]; + } + for (i=0; i < 8; i++) + { + pRes->real += r0[i]; + pRes->imag += i0[i]; + } +} + +void CpxAccumB8(cpx_t *pV1, cpx_t *pRes) +{ + uint32_t i; + + radio_float_t vr0[8]; + radio_float_t vi0[8]; + + for (i=0; i < 8; i++) + { + vr0[i] = pV1[i].real; + vi0[i] = pV1[i].imag; + } + + for (i=0; i < 8; i++) + { + pRes->real += vr0[i]; + pRes->imag += vi0[i]; + } + +} + +cpx_t CpxMulAdd(cpx_t sum, cpx_t *pSrc1, cpx_t *pSrc2, uint32_t len) +{ + uint32_t i; + + for (i=0; i < (len-8); i += 8) + { + CpxMulAddB8(&pSrc1[i], &pSrc2[i], &sum); + } + + for (i=i; i < len; i++) + { + sum = CpxAddS(sum, CpxMulS(pSrc1[i], pSrc2[i])); + } + + return sum; +} + +cpx_t CpxMulRealAdd(cpx_t sum, cpx_t *pSrc1, radio_float_t *pSrc2, uint32_t len) +{ + uint32_t i; + + for (i=0; i < (len-8); i += 8) + { + CpxMulRealAddB8(&pSrc1[i], &pSrc2[i], &sum); + } + + for (i=i; i < len; i++) + { + sum = CpxAddS(sum, CpxScaleRealS(pSrc1[i], pSrc2[i])); + } + + return sum; +} + +void CpxMul(cpx_t *pSrc1, cpx_t *pSrc2, cpx_t *pDst, uint32_t len) +{ + + uint32_t i; + + for (i=0; i < (len-8); i += 8) + { + CpxMulB8(&pSrc1[i], &pSrc2[i], &pDst[i]); + } + + for (i=i; i < len; i++) + { + pDst[i] = CpxMulS(pSrc1[i], pSrc2[i]); + } +} + +void CpxScale(cpx_t *pSrc1, cpx_t src2, cpx_t *pDst, uint32_t len) +{ + + uint32_t i; + + for (i=0; i < (len-8); i += 8) + { + CpxScaleB8(&pSrc1[i], src2, &pDst[i]); + } + + for (i=i; i < len; i++) + { + pDst[i] = CpxMulS(pSrc1[i], src2); + } +} + +cpx_t csum(cpx_t *pSrc, int len) +{ + cpx_t sum = Cpx(0,0); + + while(len--) + { + sum.real += (*(pSrc)).real; + sum.imag += (*(pSrc++)).imag; + } + + return sum; +} + +cpx_t cmean(cpx_t *pSrc, int len) +{ + cpx_t y; + + y = csum(pSrc, len); + y.real /= len; + y.imag /= len; + + return y; +} + +// -------------------------------------------------------------- +#include + +void _cpxMulB4 + ( + radio_float_t pV1_real[_cpxMulB4_blockSize], radio_float_t pV1_imag[_cpxMulB4_blockSize], + radio_float_t pV2_real[_cpxMulB4_blockSize], radio_float_t pV2_imag[_cpxMulB4_blockSize], + radio_float_t pRes_real[_cpxMulB4_blockSize], radio_float_t pRes_imag[_cpxMulB4_blockSize]) +{ + uint32_t i; + radio_float_t r0[_cpxMulB4_blockSize]; + radio_float_t r1[_cpxMulB4_blockSize]; + radio_float_t r2[_cpxMulB4_blockSize]; + radio_float_t r3[_cpxMulB4_blockSize]; + + for (i=0; i < _cpxMulB4_blockSize; i++) + { + r0[i] = pV1_real[i]*pV2_real[i]; + } + for (i=0; i < _cpxMulB4_blockSize; i++) + { + r1[i] = pV1_imag[i]*pV2_imag[i]; + } + for (i=0; i < _cpxMulB4_blockSize; i++) + { + r2[i] = pV1_real[i]*pV2_imag[i]; + } + for (i=0; i < _cpxMulB4_blockSize; i++) + { + r3[i] = pV1_imag[i]*pV2_real[i]; + } + for (i=0; i < _cpxMulB4_blockSize; i++) + { + pRes_real[i] = r0[i] - r1[i]; + } + for (i=0; i < _cpxMulB4_blockSize; i++) + { + pRes_imag[i] = r2[i] + r3[i]; + } +} + +void _cpxMulB1 + ( + radio_float_t *pV1_real, radio_float_t *pV1_imag, + radio_float_t *pV2_real, radio_float_t *pV2_imag, + radio_float_t *pRes_real, radio_float_t *pRes_imag) +{ + + uint32_t i; + radio_float_t r0[_cpxMulB1_blockSize]; + radio_float_t r1[_cpxMulB1_blockSize]; + radio_float_t r2[_cpxMulB1_blockSize]; + radio_float_t r3[_cpxMulB1_blockSize]; + + for (i=0; i < _cpxMulB1_blockSize; i++) + { + r0[i] = pV1_real[i]*pV2_real[i]; + } + for (i=0; i < _cpxMulB1_blockSize; i++) + { + r1[i] = pV1_imag[i]*pV2_imag[i]; + } + for (i=0; i < _cpxMulB1_blockSize; i++) + { + r2[i] = pV1_real[i]*pV2_imag[i]; + } + for (i=0; i < _cpxMulB1_blockSize; i++) + { + r3[i] = pV1_imag[i]*pV2_real[i]; + } + for (i=0; i < _cpxMulB1_blockSize; i++) + { + pRes_real[i] = r0[i] - r1[i]; + } + for (i=0; i < _cpxMulB1_blockSize; i++) + { + pRes_imag[i] = r2[i] + r3[i]; + } +} diff --git a/cpx.h b/cpx.h new file mode 100755 index 0000000..4a07b1a --- /dev/null +++ b/cpx.h @@ -0,0 +1,80 @@ +// -------------------------------------------------------------- +#ifndef CPX_H +#define CPX_H + +#include "radio_types.h" +// -------------------------------------------------------------- +// Types +// -------------------------------------------------------------- +typedef struct _cpx_t +{ + radio_float_t imag, real; + +} cpx_t; + +typedef struct _cpx_arr_t +{ + uint32_t size; + radio_float_t *imag, *real; + +} cpx_arr_t; + +// -------------------------------------------------------------- +#ifdef __cplusplus +extern "C" { +#endif + +// -------------------------------------------------------------- +// Complex Functions +// -------------------------------------------------------------- +// Scalar +cpx_t CpxConjS(cpx_t v1); +cpx_t CpxAddS(cpx_t v1, cpx_t v2); +cpx_t CpxSubS(cpx_t v1, cpx_t v2); +cpx_t CpxMulS(cpx_t v1, cpx_t v2); +cpx_t CpxScaleRealS(cpx_t v1, radio_float_t v2); +cpx_t CpxScaleComplexS(cpx_t x, cpx_t gain); +cpx_t CpxFromReal(radio_float_t v1); +cpx_t Cpx(radio_float_t real, radio_float_t imag); +cpx_t CpxMinS(cpx_t x1, cpx_t x2); +cpx_t CpxMaxS(cpx_t x1, cpx_t x2); +radio_float_t CpxMagS(cpx_t v1); +radio_float_t CpxPhiS(cpx_t v1); +radio_float_t cpxPowerDB(cpx_t v1, radio_float_t preScale); + +// Vector +void CpxCopy(cpx_t *pSrc, cpx_t *pDst, uint32_t len); +void CpxConj(cpx_t *pSrcDst, uint32_t len); +void CpxAdd(cpx_t *pSrc, cpx_t *pSrcDst, uint32_t len); +void CpxSub(cpx_t *pSrc, cpx_t *pSrcDst, uint32_t len); +void CpxMul(cpx_t *pSrc1, cpx_t *pSrc2, cpx_t *pDst, uint32_t len); +void CpxScale(cpx_t *pSrc1, cpx_t src2, cpx_t *pDst, uint32_t len); +cpx_t CpxMulAdd(cpx_t sum, cpx_t *pSrc1, cpx_t *pSrc2, uint32_t len); +cpx_t CpxMulRealAdd(cpx_t sum, cpx_t *pSrc1, radio_float_t *pSrc2, uint32_t len); +radio_float_t CpxMag(cpx_t *pSrc); +radio_float_t CpxPhi(cpx_t *pSrc); + +cpx_t csum(cpx_t *pSrc, int len); +cpx_t cmean(cpx_t *pSrc, int len); + +// -------------------------------------------------------------- +#define _cpxMulB4_blockSize 4 +#define _cpxMulB1_blockSize 1 +void _cpxMulB4 + ( + radio_float_t pV1_real[_cpxMulB4_blockSize], radio_float_t pV1_imag[_cpxMulB4_blockSize], + radio_float_t pV2_real[_cpxMulB4_blockSize], radio_float_t pV2_imag[_cpxMulB4_blockSize], + radio_float_t pRes_real[_cpxMulB4_blockSize], radio_float_t pRes_imag[_cpxMulB4_blockSize] + ); +void _cpxMulB1 + ( + radio_float_t *pV1_real, radio_float_t *pV1_imag, + radio_float_t *pV2_real, radio_float_t *pV2_imag, + radio_float_t *pRes_real, radio_float_t *pRes_imag + ); +#ifdef __cplusplus +} +#endif // __cplusplus + +// -------------------------------------------------------------- +#endif // CPX_H diff --git a/equalizer.c b/equalizer.c new file mode 100755 index 0000000..0118103 --- /dev/null +++ b/equalizer.c @@ -0,0 +1,498 @@ +// -------------------------------------------------------------- +#include +#include +#include +#include "equalizer.h" + +// -------------------------------------------------------------- +// Helpers +// -------------------------------------------------------------- +void CoeffComplexUnitAt(cpx_t *pW, uint32_t N, uint32_t dly) +{ + if (dly >= N) + dly = 0; + + memset(pW, 0, N*sizeof(cpx_t)); + pW[dly].real = 1.0; + pW[dly].imag = 0.0; +} + +void CoeffComplexConv(cpx_t *pSrc, cpx_t *pSrcDst, uint32_t N, uint32_t dly) +{ + uint32_t i, j, N2; + cpx_t *pX, *pW, t, energy = {0}; + radio_float_t energy_correct; + + N2 = N+dly; + + pX = (cpx_t*)malloc(N2*sizeof(cpx_t)); + memset(pX, 0, N2*sizeof(cpx_t)); + pW = (cpx_t*)malloc(N2*sizeof(cpx_t)); + memset(pW, 0, N2*sizeof(cpx_t)); + + CpxCopy(pSrc, pX, N); + + for(j=0; j < N; j++) + energy = CpxAddS(energy, pSrcDst[j]); + + energy_correct = (radio_float_t)(1.0/CpxMagS(energy)); + + for(i=0; i < N2; i++) + { + for(j=0; j < N; j++) + { + t = CpxMulS(pX[N-j+i-1], pSrcDst[j]); + pW[i] = CpxScaleRealS(CpxAddS(pW[i], t), energy_correct); + } + } + CpxCopy(&pW[N/2], pSrcDst, N); +} + +// -------------------------------------------------------------- +// Equalizer +// -------------------------------------------------------------- +void EQComplexInit(eq_cpx_t *pObj, uint32_t N) +{ + pObj->N = N; + pObj->pX = (cpx_t*)malloc(pObj->N*sizeof(cpx_t)); + pObj->pW = (cpx_t*)malloc(pObj->N*sizeof(cpx_t)); + pObj->pW_conj = (cpx_t*)malloc(pObj->N*sizeof(cpx_t)); + memset(pObj->pX, 0, pObj->N*sizeof(cpx_t)); + memset(pObj->pW, 0, pObj->N*sizeof(cpx_t)); + memset(pObj->pW_conj, 0, pObj->N*sizeof(cpx_t)); +} + +void EQComplexFree(eq_cpx_t *pObj) +{ + free(pObj->pX); + free(pObj->pW); + free(pObj->pW_conj); +} + +cpx_t EQComplexProcess(eq_cpx_t *pObj, cpx_t x) +{ + uint32_t i; + cpx_t y; + + for(i=pObj->N-1; (int)i > 0; i--) + { + pObj->pX[i] = pObj->pX[i-1]; + } + + // fill M top positions with M new data + pObj->pX[i] = x; + + y = CpxMulAdd(Cpx(0, 0), pObj->pX, pObj->pW_conj, pObj->N); + + return y; +} + +// -------------------------------------------------------------- +// CMA +// -------------------------------------------------------------- +void CMAInit(cma_t *pObj, uint32_t ntaps) +{ + pObj->N = ntaps; + pObj->Px = 0; + pObj->Px_last = 0; + + EQComplexInit(&pObj->eq, pObj->N); +} + +void CMAFree(cma_t *pObj) +{ + EQComplexFree(&pObj->eq); +} + +cpx_t CMAProcess(cma_t *pObj, cpx_t x) +{ + cpx_t y; + radio_float_t x2, x1; + + y = EQComplexProcess(&pObj->eq, x); + x1 = CpxMagS(x); + x2 = CpxMagS(pObj->eq.pX[pObj->eq.N-1]); + + pObj->Px = dmax(0, pObj->Px + (x1*x1 - pObj->Px_last)); + pObj->Px_last = x2*x2; + + return y; +} + +// Proakis: page 698 +void CMATrainGodard(cma_t *pObj, cpx_t sym_s_eq, radio_float_t mag_h, radio_float_t R2, radio_float_t mu) +{ + cpx_t d; + cpx_t e; + radio_float_t mag_s, t; + + mag_s = CpxMagS(sym_s_eq); + + t = (radio_float_t)((mag_h + R2*mag_s - mag_s*mag_s*mag_s)/(1E-4+mag_h)); + d = CpxScaleRealS(sym_s_eq, t); + + e = CpxSubS(d, sym_s_eq); + + LMSUpdateWeigths(&pObj->eq, e, mu/((radio_float_t)1+pObj->Px)); +} + +// "Sliced Multi-modulus Blind Equalization Algorithm", +// ETRI Journal, Volume 27, Number 3, June 2005, +// Shafayat Abrar and Roy A. Axford Jr. +void MMATrain(cma_t *pObj, cpx_t sym_s_eq, cpx_t R, radio_float_t mu) +{ + cpx_t e; + + e.real = sym_s_eq.real*(R.real - sym_s_eq.real*sym_s_eq.real); + e.imag = sym_s_eq.imag*(R.imag - sym_s_eq.imag*sym_s_eq.imag); + + LMSUpdateWeigths(&pObj->eq, e, mu/((radio_float_t)1+pObj->Px)); +} + +// "Sliced Multi-modulus Blind Equalization Algorithm", +// ETRI Journal, Volume 27, Number 3, June 2005, +// Shafayat Abrar and Roy A. Axford Jr. +void SMMATrain(cma_t *pObj, cpx_t sym_s_eq, radio_float_t mag_h, cpx_t R, radio_float_t mu) +{ + cpx_t e; + + e.real = sym_s_eq.real*(mag_h*R.real - sym_s_eq.real*sym_s_eq.real); + e.imag = sym_s_eq.imag*(mag_h*R.imag - sym_s_eq.imag*sym_s_eq.imag); + + LMSUpdateWeigths(&pObj->eq, e, mu/((radio_float_t)1+pObj->Px)); +} + +// -------------------------------------------------------------- +// DFE +// -------------------------------------------------------------- +void DFEComplexInit(dfe_cpx_t *pObj, uint32_t K) +{ + pObj->N = 2*K+1; + pObj->N_ff = K+1; + pObj->N_fb = K; + + EQComplexInit(&pObj->eq, pObj->N); + +} + +void DFEComplexFree(dfe_cpx_t *pObj) +{ + EQComplexFree(&pObj->eq); +} + +cpx_t DFEComplexProcess(dfe_cpx_t *pObj, cpx_t xs, cpx_t xh) +{ + int32_t i; + cpx_t y, *pW_conj, *pX; + + pX = pObj->eq.pX; + pW_conj = pObj->eq.pW_conj; + + // Shift Feedback part + for(i=pObj->N-1; i > (int32_t)pObj->N_ff; i--) + { + pX[i] = pX[i-1]; + } + + // put last x into buffer + pX[i] = xh; + + // Shift Feed forward part + for(i=pObj->N_ff-1; i > 0; i--) + { + pX[i] = pX[i-1]; + } + + // put current x into buffer + pX[i] = xs; + + y = CpxMulAdd(Cpx(0, 0), pX, pW_conj, pObj->N); + + return y; + +} + +void DFEAdaptLMS(dfe_cpx_t *pObj, cpx_t e, radio_float_t mu) +{ + LMSUpdateWeigths(&pObj->eq, e, mu); +} + +// -------------------------------------------------------------- +// LMS +// -------------------------------------------------------------- +void LMSUpdateWeigths(eq_cpx_t *pObj, cpx_t e, radio_float_t mu) +{ + uint32_t i; + + e = CpxScaleRealS(CpxConjS(e), mu); + + CpxScale(pObj->pX, e, pObj->pW_conj, pObj->N); + CpxAdd(pObj->pW_conj, pObj->pW, pObj->N); + + for(i=0; i < pObj->N; i++) + { + pObj->pW_conj[i] = CpxConjS(pObj->pW[i]); + } +} + +// -------------------------------------------------------------- +// RLS +// -------------------------------------------------------------- +void RLSInit(rls_t *pObj, uint32_t N, uint32_t M) +{ + uint32_t i, j; + radio_float_t *pR; + + pObj->w = (radio_float_t*)malloc(N*sizeof(radio_float_t)); + memset(pObj->w, 0, N*sizeof(radio_float_t)); + pObj->w[0] = 1.0f; + + pObj->pW = (cpx_t*)malloc(N*sizeof(cpx_t)); + memset(pObj->pW, 0, N*sizeof(cpx_t)); + + pObj->z = (radio_float_t*)malloc(N*sizeof(radio_float_t)); + memset(pObj->z, 0, N*sizeof(radio_float_t)); + + pObj->x = (radio_float_t*)malloc(N*sizeof(radio_float_t)); + memset(pObj->x, 0, N*sizeof(radio_float_t)); + + pObj->pX = (cpx_t*)malloc(N*M*sizeof(cpx_t)); + memset(pObj->pX, 0, N*M*sizeof(cpx_t)); + + pObj->R = (radio_float_t*)malloc(N*N*sizeof(radio_float_t)); + memset(pObj->R, 0, N*N*sizeof(radio_float_t)); + + pObj->T = (radio_float_t*)malloc(N*N*sizeof(radio_float_t)); + memset(pObj->T, 0, N*N*sizeof(radio_float_t)); + + pObj->T2 = (radio_float_t*)malloc(N*N*sizeof(radio_float_t)); + memset(pObj->T2, 0, N*N*sizeof(radio_float_t)); + + pR = pObj->R; + for(i=0; i < N; i++) + for(j=0; j < N; j++) + pR[i+j*N] = (radio_float_t)1E6*(i==j); + + pObj->N = N; + pObj->M = M; +} + +void RLSFree(rls_t *pObj) +{ + if(pObj->w) + free(pObj->w); + + if(pObj->z) + free(pObj->z); + + if(pObj->x) + free(pObj->x); + + if(pObj->R) + free(pObj->R); + + if(pObj->T) + free(pObj->T); + + if(pObj->T2) + free(pObj->T2); +} +/* +void RLSProcess(rls_t *pObj, radio_float_t rho, radio_float_t mu, radio_float_t x, radio_float_t d, radio_float_t *pE, radio_float_t *pDD) +{ + int i, j, k, N; + radio_float_t *pR, *pX, *pZ, *pT, *pT2, v, t, rho_i; + + N = pObj->N; + + FIR(pObj->w, pObj->x, N, &x, pDD, 1); + + *pE = d - *pDD; + + // Whitening + pR = pObj->R; + pX = pObj->x; + for(i=0; i < N; i++) + { + t = 0; + for(j=0; j < N; j++) + t += pR[j*N+i] * pX[j]; + + pObj->z[i] = t; + } + + // Berechnunng der Normierungskonstante + v = rho; + for(i=0; i < N; i++) + v += pObj->x[i] * pObj->z[i]; + + v = (radio_float_t)1.0/v; + + // Normierung + for(i=0; i < N; i++) + pObj->z[i] *= v; + + + // Filter update + for(i=0; i < N; i++) + pObj->w[i] += (mu * (*pE)*pObj->z[i]); + + + // Matrix update + pZ = pObj->z; + pX = pObj->x; + pT = pObj->T; + for(i=0; i < N; i++) + { + for(j=0; j < N; j++) + pT[j*N+i] = pZ[i] * pX[j]; + } + + pT = pObj->T; + pT2 = pObj->T2; + pR = pObj->R; + + for (i=0;iN-1; j != 0; j--) + { + pObj->pX[j] = pObj->pX[j-1]; + } + pObj->pX[j].real = i; + pObj->pX[j].imag = q; + + for(j=0; j < pObj->N; j++) + { + pObj->pW[j].real = pObj->w[j]; + pObj->pW[j].imag = pObj->w[j]; + } + +/// for(j=0; j < pObj->N; j++) +// { +// t = CpxMuls(pObj->pX[M*j], CpxConjs(pObj->pW[j])); +// y = CpxAdds(y, t); +// } + + for(j=0; j < pObj->N; j++) + { + t.real = pObj->pX[j].real * pObj->pW[j].real; + t.imag = pObj->pX[j].imag * pObj->pW[j].imag; + + y = CpxAddS(y, t); + } + + for(j=0; j < pObj->N; j++) + { + pObj->x[j] = pObj->pX[j].real; + } + + return y; + +} + +radio_float_t RLSUpdate(rls_t *pObj, radio_float_t rho, radio_float_t mu, radio_float_t y, radio_float_t d) +{ + int i, j, k, N; + radio_float_t *pR, *pX, *pZ, *pT, *pT2, v, t, rho_i, e; + + N = pObj->N; + + e = d - y; + + pR = pObj->R; + pX = pObj->x; + +// for(j=0; j < pObj->N; j++) +// { +// pObj->x[j] = pObj->pX[j*pObj->M].real; +// } + + // Whitening + for(i=0; i < N; i++) + { + t = 0; + for(j=0; j < N; j++) + t += pR[j*N+i] * pX[j]; + + pObj->z[i] = t; + } + + // Berechnunng der Normierungskonstante + v = rho; + for(i=0; i < N; i++) + v += pObj->x[i] * pObj->z[i]; + + v = (radio_float_t)1.0/v; + + // Normierung + for(i=0; i < N; i++) + pObj->z[i] *= v; + + + // Filter update + for(i=0; i < N; i++) + pObj->w[i] += (mu * e * pObj->z[i]); + + + // Matrix update + pZ = pObj->z; + pX = pObj->x; + pT = pObj->T; + for(i=0; i < N; i++) + { + for(j=0; j < N; j++) + pT[j*N+i] = pZ[i] * pX[j]; + } + + pT = pObj->T; + pT2 = pObj->T2; + pR = pObj->R; + + for (i=0;i +#include +#include +#include "symbol.h" +#include "frame.h" + +// -------------------------------------------------------------- +uint32_t Scramble(uint8_t *pSrcDst, uint32_t state, uint32_t poly, uint32_t len) +{ + uint32_t i; + + while(len) + { + *pSrcDst ^= (uint8_t)state; + pSrcDst++; + len--; + + for (i=0; i < 8; i++) + { + if (state & 0x0001) + state = (state >> 1) ^ poly; + else + state = (state >> 1); + } + + } + return state; +} + +uint32_t FrameCalcNumStreamBytes(uint32_t len_raw) +{ + uint32_t len, num_frames; + num_frames = (uint32_t)ceil((float)len_raw / FRAME_NUM_BYTES_PER_FRAME); + len = num_frames*sizeof(frame_t); + + if (len < sizeof(frame_t)) + len = sizeof(frame_t); + + return len; +} + +uint32_t FrameFormat(uint8_t *pRaw, uint8_t *pFormatted, uint32_t len_raw, uint32_t *pPrn_state, uint16_t frame_type) +{ + frame_t frame; + + uint32_t bytes_remain, len_formatted, len; + uint32_t prn_state; + + if (len_raw == 0) + return 0; + + prn_state = *pPrn_state; + + // Set preamble + frame.hdr.preamble[0] = FRAME_PREAMBLE_IV; + frame.hdr.preamble[1] = ~(frame.hdr.preamble[0]); + + bytes_remain = len_raw; + len_formatted = 0; + while(bytes_remain) + { + len = FRAME_NUM_BYTES_PER_FRAME; + if (bytes_remain < FRAME_NUM_BYTES_PER_FRAME) + len = bytes_remain; + + memset(frame.data, 0, FRAME_NUM_BYTES_PER_FRAME); + memcpy(frame.data, pRaw, len); + frame.hdr.crc16 = Crc16(FRAME_CRC16_POLY, FRAME_CRC16_IV, frame.data, FRAME_NUM_BYTES_PER_FRAME); + frame.hdr.type = frame_type; + frame.hdr.prn_state = prn_state; + frame.hdr.length = (uint16_t)len; + prn_state = Scramble(frame.data, prn_state, FRAME_SCRAMBLER_POLY, FRAME_NUM_BYTES_PER_FRAME); + prn_state = Scramble((uint8_t*)&frame.hdr.crc16, prn_state, FRAME_SCRAMBLER_POLY, sizeof(frame.hdr.crc16)); + prn_state = Scramble((uint8_t*)&frame.hdr.type, prn_state, FRAME_SCRAMBLER_POLY, sizeof(frame.hdr.type)); + prn_state = Scramble((uint8_t*)&frame.hdr.length, prn_state, FRAME_SCRAMBLER_POLY, sizeof(frame.hdr.length)); + + pRaw += len; + bytes_remain -= len; + + memcpy(pFormatted, &frame, sizeof(frame_t)); + pFormatted += sizeof(frame_t); + len_formatted += sizeof(frame_t); + + } + *pPrn_state = prn_state; + return len_formatted; +} + +uint32_t FrameDeformat(uint8_t *pFormatted, uint8_t *pRaw, uint32_t len_formatted, uint16_t frame_type_mask) +{ + frame_hdr_t hdr; + uint32_t bytes_remain, len_raw, sync_state, frame_sync, i; + uint16_t crc16_ist; + uint8_t temp[FRAME_NUM_BYTES_PER_FRAME]; + uint32_t prn_state; + + if (len_formatted == 0) + return 0; + + i = 0; + bytes_remain = len_formatted; + len_raw = 0; + while(bytes_remain) + { + + sync_state = 0; + do + { + // Find frame boundaries + switch(sync_state) + { + case 0: + if (pFormatted[i] == FRAME_PREAMBLE_IV) + { + sync_state = 1; + } + break; + + case 1: + if ((uint8_t)(~pFormatted[i]) == pFormatted[i-1]) + { + sync_state = 2; + } + else + { + sync_state = 0; + } + break; + } + i++; + bytes_remain--; + frame_sync = (sync_state == 2); + + } while(bytes_remain && !frame_sync); + + memcpy(&hdr, &pFormatted[i-2], sizeof(frame_hdr_t)); + memcpy(temp, &pFormatted[i-2+sizeof(frame_hdr_t)], FRAME_NUM_BYTES_PER_FRAME); + + prn_state = Scramble(temp, hdr.prn_state, FRAME_SCRAMBLER_POLY, FRAME_NUM_BYTES_PER_FRAME); + prn_state = Scramble((uint8_t*)&hdr.crc16, prn_state, FRAME_SCRAMBLER_POLY, sizeof(hdr.crc16)); + prn_state = Scramble((uint8_t*)&hdr.type, prn_state, FRAME_SCRAMBLER_POLY, sizeof(hdr.type)); + Scramble((uint8_t*)&hdr.length, prn_state, FRAME_SCRAMBLER_POLY, sizeof(hdr.length)); + + crc16_ist = Crc16(FRAME_CRC16_POLY, FRAME_CRC16_IV, temp, FRAME_NUM_BYTES_PER_FRAME); + + if (crc16_ist == hdr.crc16) + { + + if ((hdr.type & frame_type_mask) == frame_type_mask) + { + memcpy(&pRaw[len_raw], temp, hdr.length); + len_raw += hdr.length; + } + i += FRAME_NUM_BYTES_PER_FRAME + sizeof(frame_hdr_t) - 2; + bytes_remain -= (FRAME_NUM_BYTES_PER_FRAME + sizeof(frame_hdr_t) - 2); + } + + if ((int32_t)bytes_remain < sizeof(frame_t)) + bytes_remain = 0; + } + return len_raw; +} + +// Transmission order MSB first +uint32_t FrameSerialize(uint8_t *pSrc, uint8_t *pDst, uint32_t nBitsPerSym, uint32_t srclen) +{ + + uint32_t bits_remain, i, j; + uint8_t src, dst; + + if (srclen == 0) + return 0; + + if (nBitsPerSym > 8) + return (uint32_t)-1; + + j = 0; + src = *pSrc; + bits_remain = 8; + while(srclen) + { + dst = 0; + for (i=0; i < nBitsPerSym; i++) + { + dst <<= 1; + dst |= (0x01 & (src >> 7)); + src <<= 1; + + bits_remain--; + if (bits_remain == 0) + { + pSrc++; + bits_remain = 8; + src = *pSrc; + srclen--; + } + + } + pDst[j++] = dst; + } + return j; +} + +uint32_t FrameDeSerialize(uint8_t *pSrc, uint8_t *pDst, uint32_t nBitsPerSym, uint32_t srclen, uint16_t frame_type_mask) +{ + + uint32_t size, err, bits_remain, i, j, byte_sync, srcRemain, bitStart, numCorrupt; + uint8_t src, dst, *pBitStart; + uint16_t dst16, t; + uint8_t frame[sizeof(frame_t)], data[FRAME_NUM_BYTES_PER_FRAME]; + + if (srclen == 0) + return 0; + + if (nBitsPerSym > 8) + return (uint32_t)-1; + + src = *pSrc; + + bits_remain = nBitsPerSym; + bitStart = bits_remain; + pBitStart = pSrc; + numCorrupt = 0; + + t = (FRAME_PREAMBLE_IV << 8) | (0xFF & ~FRAME_PREAMBLE_IV); + size = 0; + do + { + j = 0; + dst16 = 0; + byte_sync = 0; + do + { + bits_remain--; + dst16 <<= 1; + dst16 |= (0x01 & (src >> (bits_remain))); + + if (bits_remain == 0) + { + pSrc++; + bits_remain = nBitsPerSym; + src = *pSrc; + srclen--; + if (!srclen) + break; + } + + // Find frame boundaries + if (dst16 == t) + { + pBitStart = pSrc; + bitStart = bits_remain; + srcRemain = srclen; + byte_sync = 1; + frame[j++] = 0xFF & (t >> 8); + frame[j++] = 0xFF & t; + + } + + } while(srclen && !byte_sync); + if (!srclen) + break; + + for(j; j < sizeof(frame_t); j++) + { + dst = 0; + for (i=0; i < 8; i++) + { + bits_remain--; + dst <<= 1; + dst |= (0x01 & (src >> (bits_remain))); + + if (bits_remain == 0) + { + pSrc++; + bits_remain = nBitsPerSym; + src = *pSrc; + srclen--; + if (!srclen) + break; + } + + } + frame[j] = dst; + if (!srclen) + break; + + } + if (!srclen) + break; + + err = FrameDeformat(frame, data, sizeof(frame_t), frame_type_mask); + if (err > 0) + { + memcpy(&pDst[size], frame, sizeof(frame_t)); + size += sizeof(frame_t); + + } + else + { + if (size > 0) + numCorrupt++; + bits_remain = bitStart; + pSrc = pBitStart; + srclen = srcRemain; + } + + } while(srclen); + +// printf("Number of corrupted frames = %d\n", numCorrupt); + return size; +} + +// Differential M-PSK symbol mapping +uint32_t FrameSymbolsMap(uint8_t *pBits, cpx_t *pSym, uint32_t nBitsPerSym, uint32_t num_syms, uint32_t type) +{ + uint32_t i; + sym_map_t sym_mapper; + + if (num_syms == 0) + return 0; + + SymMapInit(&sym_mapper, nBitsPerSym, type); + + for(i=0; i < num_syms; i++) + { + pSym[i] = SymMapEncode(&sym_mapper, pBits[i]); + } + + return num_syms; +} + +// Differential M-PSK symbol de-mapping +uint32_t FrameSymbolsDemap(cpx_t *pSym, uint8_t *pBits, uint32_t nBitsPerSym, uint32_t num_syms, uint32_t type) +{ + uint32_t i; + sym_map_t sym_demapper; + sym_err_t sym_err; + + if (num_syms == 0) + return 0; + + memset(&sym_err, 0, sizeof(sym_err_t)); + + SymMapInit(&sym_demapper, nBitsPerSym, type); + + for(i=0; i < num_syms; i++) + { + pBits[i] = SymMapDecode(&sym_demapper, pSym[i], &sym_err); + } + + return num_syms; +} + +// -------------------------------------------------------------- diff --git a/frame.h b/frame.h new file mode 100755 index 0000000..9b91d3e --- /dev/null +++ b/frame.h @@ -0,0 +1,61 @@ +// -------------------------------------------------------------- +#ifndef FRAME_H +#define FRAME_H + +#include "radio_types.h" +#include "cpx.h" + +// -------------------------------------------------------------- +// Constants +// -------------------------------------------------------------- +#define FRAME_CRC16_IV 0x0000 +#define FRAME_CRC16_POLY 0x1021 +#define FRAME_PREAMBLE_IV 0x55 +#define FRAME_SCRAMBLER_SEED 0x12345678 +#define FRAME_SCRAMBLER_POLY 0x80C18601 +#define FRAME_NUM_BYTES_PER_FRAME 32 +#define FRAME_TYPE_IDLE 0x01 +#define FRAME_TYPE_DATA 0x02 + +// -------------------------------------------------------------- +// Types +// -------------------------------------------------------------- +typedef struct _frame_hdr_t +{ + uint8_t preamble[2]; + uint32_t prn_state; + uint16_t crc16; + uint16_t type; + uint16_t length; + +} frame_hdr_t; + +typedef struct _frame_t +{ + frame_hdr_t hdr; + uint8_t data[FRAME_NUM_BYTES_PER_FRAME]; + +} frame_t; + +// -------------------------------------------------------------- +// Functions +// -------------------------------------------------------------- +#ifdef __cplusplus +extern "C" { +#endif + +uint32_t Scramble(uint8_t *pSrcDst, uint32_t state, uint32_t poly, uint32_t len); +uint32_t FrameCalcNumStreamBytes(uint32_t len_raw); +uint32_t FrameFormat(uint8_t *pRaw, uint8_t *pFormatted, uint32_t len_raw, uint32_t *pPrn_state, uint16_t frame_type); +uint32_t FrameDeformat(uint8_t *pFormatted, uint8_t *pRaw, uint32_t len_formatted, uint16_t frame_type); +uint32_t FrameSerialize(uint8_t *pSrc, uint8_t *pDst, uint32_t nBitsPerSym, uint32_t srclen); +uint32_t FrameDeSerialize(uint8_t *pSrc, uint8_t *pDst, uint32_t nBitsPerSym, uint32_t srclen, uint16_t frame_type); +uint32_t FrameSymbolsMap(uint8_t *pBits, cpx_t *pSym, uint32_t nBitsPerSym, uint32_t num_syms, uint32_t type); +uint32_t FrameSymbolsDemap(cpx_t *pSym, uint8_t *pBits, uint32_t nBitsPerSym, uint32_t num_syms, uint32_t type); + +#ifdef __cplusplus +} +#endif // __cplusplus + +// -------------------------------------------------------------- +#endif // FRAME_H diff --git a/interpolation.c b/interpolation.c new file mode 100755 index 0000000..c792b8e --- /dev/null +++ b/interpolation.c @@ -0,0 +1,830 @@ +// -------------------------------------------------------------- +#include +#include +#include +#include "interpolation.h" + +// -------------------------------------------------------------- +// Complex FIR filtering with downsampling +// -------------------------------------------------------------- +void FirCpxInit(fir_cpx_t *pObj, uint32_t N, uint32_t M_up, uint32_t M_down) +{ + pObj->pX = (cpx_t*)malloc(N*sizeof(cpx_t)); + memset(pObj->pX, 0, N*sizeof(cpx_t)); + pObj->N = N; + pObj->M_up = M_up; + pObj->M_down = M_down; + pObj->r = 0; + pObj->w = 0; + ClockInit(&pObj->clockUp, M_up); + ClockInit(&pObj->clockDown, M_down); +} + +void FirCpxFree(fir_cpx_t *pObj) +{ + free(pObj->pX); +} + +uint32_t FirCpxProcessReal(fir_cpx_t *pObj, radio_float_t *pW, cpx_t *pSrc, cpx_t *pDst, uint32_t len) +{ + + uint32_t j, w, r, N; + uint32_t remain; + uint32_t nBytesWritten; + uint32_t nBytesRead; + const cpx_t zero = Cpx(0,0); + + w = pObj->w; + r = pObj->r; + N = pObj->N; + + nBytesWritten = 0; + nBytesRead = 0; + remain = len*pObj->M_up; + while(remain--) + { + if (ClockIsTick(&pObj->clockUp, 1)) + { + pObj->pX[w] = pSrc[nBytesRead]; + nBytesRead++; + } + else + { + pObj->pX[w] = zero; + } + if (++w >= N) + w = 0; + + if (ClockIsTick(&pObj->clockDown, 1)) + { + // fs/downSampleFactor + pDst[nBytesWritten] = zero; + for (j=0; j < N; j++) + { + + pDst[nBytesWritten].real += pObj->pX[r].real * pW[j]; + pDst[nBytesWritten].imag += pObj->pX[r].imag * pW[j]; + + if (--r >= N) + r = N-1; + + } + nBytesWritten++; + } + if (++r >= N) + r = 0; + } + pObj->r = r; + pObj->w = w; + + return nBytesWritten; +} + +void FirCpxMultirateStageDownInit(fir_cpx_multirate_stage_t *pObj, radio_float_t *pW, uint32_t N, uint32_t M, uint32_t k) +{ + uint32_t i; + radio_float_t *_pW; + + pObj->N = 0; + for (i=k; i < N; i += M) + { + pObj->N++; + } + pObj->pW = (radio_float_t*)malloc(pObj->N*sizeof(cpx_t)); + _pW = pObj->pW; + for (i=k; i < N; i += M) + { + *(_pW++) = pW[i]; + } + + pObj->k = k; + pObj->K = M; + pObj->pX = (cpx_t*)malloc(pObj->N*sizeof(cpx_t)); + memset(pObj->pX, 0, pObj->N*sizeof(cpx_t)); +} + +void FirCpxMultirateStageUpInit(fir_cpx_multirate_stage_t *pObj, radio_float_t *pW, uint32_t N, uint32_t L, uint32_t k) +{ + uint32_t i; + radio_float_t *_pW; + + pObj->N = 0; + for (i=L-k-1; i < N; i += L) + { + pObj->N++; + } + pObj->pW = (radio_float_t*)malloc(pObj->N*sizeof(cpx_t)); + _pW = pObj->pW; + + if (pW) + { + for (i=L-k-1; i < N; i += L) + { + *(_pW++) = pW[i]; + } + } + pObj->k = k; + pObj->K = L; + pObj->pX = (cpx_t*)malloc(pObj->N*sizeof(cpx_t)); + memset(pObj->pX, 0, pObj->N*sizeof(cpx_t)); +} + +void FirCpxMultirateStageFree(fir_cpx_multirate_stage_t *pObj) +{ + if (pObj->pX) + free(pObj->pX); + + if (pObj->pW) + free(pObj->pW); +} + +cpx_t FirCpxMultirateStageProcessDownAccum(fir_cpx_multirate_stage_t *pObj, cpx_t res, cpx_t src) +{ + int32_t i; + + for (i=pObj->N-1; i > 0; i--) + { + pObj->pX[i] = pObj->pX[i-1]; + } + pObj->pX[i] = src; + + return CpxMulRealAdd(res, pObj->pX, pObj->pW, pObj->N); +} + +uint32_t FirCpxMultirateStageProcessUp(fir_cpx_multirate_stage_t *pObj, cpx_t *pSrc, cpx_t *pDst, uint32_t len) +{ + int32_t i; + uint32_t num_written; + + num_written = 0; + while(len--) + { + for (i=pObj->N-1; i > 0; i--) + { + pObj->pX[i] = pObj->pX[i-1]; + } + pObj->pX[i] = *(pSrc++); + + pDst[pObj->K-1 - pObj->k + num_written] = CpxMulRealAdd(Cpx(0,0), pObj->pX, pObj->pW, pObj->N); + + num_written += pObj->K; + } + return num_written; +} + +void FirCpxMultirateDownInit(fir_cpx_multirate_t *pObj, radio_float_t *pW, uint32_t N, uint32_t M) +{ + uint32_t i; + + pObj->L = 0; + pObj->M = M; + pObj->N = N; + pObj->k = M-1; + pObj->res = Cpx(0,0); + pObj->pStageUp = 0; + pObj->pStageDown = (fir_cpx_multirate_stage_t*)malloc(M*sizeof(fir_cpx_multirate_stage_t)); + + for (i=0; i < M; i++) + { + FirCpxMultirateStageDownInit(&pObj->pStageDown[i], pW, N, M, i); + } +} + +void FirCpxMultirateUpInit(fir_cpx_multirate_t *pObj, radio_float_t *pW, uint32_t N, uint32_t L) +{ + uint32_t i; + + pObj->L = L; + pObj->M = 0; + pObj->N = N; + pObj->k = 0; + pObj->res = Cpx(0,0); + pObj->pStageDown = 0; + pObj->pStageUp = (fir_cpx_multirate_stage_t*)malloc(L*sizeof(fir_cpx_multirate_stage_t)); + + for (i=0; i < L; i++) + { + FirCpxMultirateStageUpInit(&pObj->pStageUp[i], pW, N, L, i); + } +} + +void FirCpxMultirateFree(fir_cpx_multirate_t *pObj) +{ + uint32_t i; + + if (pObj->pStageDown) + { + for (i=0; i < pObj->M; i++) + { + FirCpxMultirateStageFree(&pObj->pStageDown[i]); + } + free(pObj->pStageDown); + } + + if (pObj->pStageUp) + { + for (i=0; i < pObj->L; i++) + { + FirCpxMultirateStageFree(&pObj->pStageUp[i]); + } + free(pObj->pStageUp); + } +} + +void FirCpxMultirateUpReinit(fir_cpx_multirate_t *pObj, radio_float_t *pW, uint32_t N, uint32_t L) +{ + FirCpxMultirateFree(pObj); + FirCpxMultirateUpInit(pObj, pW, N, L); +} + +uint32_t FirCpxDownZero(fir_cpx_multirate_t *pObj, cpx_t *pDst, uint32_t len) +{ + uint32_t i; + uint32_t num_written; + + num_written = 0; + for (i=0; i < len; i += pObj->M) + { + *(pDst++) = Cpx(0,0); + num_written++; + } + return num_written; +} + +uint32_t FirCpxDownProcess(fir_cpx_multirate_t *pObj, cpx_t *pSrc, cpx_t *pDst, uint32_t len) +{ + uint32_t num_written_soll; + uint32_t num_written_ist; + + num_written_ist = 0; + num_written_soll = FirCpxDownZero(pObj, pDst, len); + while(len--) + { + pObj->res = FirCpxMultirateStageProcessDownAccum(&pObj->pStageDown[pObj->k], pObj->res, *(pSrc++)); + pObj->k--; + if (pObj->k >= pObj->M) + { + pDst[num_written_ist++] = pObj->res; + pObj->res = Cpx(0,0); + pObj->k = pObj->M-1; + } + } + return num_written_ist; +} + +uint32_t FirCpxUpZero(fir_cpx_multirate_t *pObj, cpx_t *pDst, uint32_t len) +{ + uint32_t i; + uint32_t num_written; + + num_written = 0; + for (i=0; i < pObj->L*len; i++) + { + *(pDst++) = Cpx(0,0); + num_written++; + } + return num_written; +} + +uint32_t FirCpxUpProcess(fir_cpx_multirate_t *pObj, cpx_t *pSrc, cpx_t *pDst, uint32_t len) +{ + uint32_t k; + uint32_t res; + uint32_t num_written_ist; + + num_written_ist = 0; + for (k=0; k < pObj->L; k++) + { + res = FirCpxMultirateStageProcessUp(&pObj->pStageUp[k], pSrc, pDst, len); + if (num_written_ist < res) + num_written_ist = res; + + } + return num_written_ist; +} + +// -------------------------------------------------------------- +// Complex FIR-based polyphase interpolation filter +// -------------------------------------------------------------- +radio_float_t PolyPhaseCpxIpInit(ppip_cpx_t *pObj, radio_float_t fa, radio_float_t tsym, radio_float_t alpha, uint32_t N, uint32_t M) +{ + uint32_t i, j; + fir_float_t *pCoeff; + radio_float_t k; + + // Calculate polyphase filter + pCoeff = (fir_float_t*)malloc((N+1)*M*sizeof(fir_float_t)); + memset(pCoeff, 0, (N+1)*M*sizeof(fir_float_t)); + + k = CalcFirSRRC(pCoeff, M*fa, tsym, alpha, N*M); + + pObj->ppCoeff = (fir_float_t**)malloc(M*sizeof(fir_float_t*)); + for(i=0; i < M; i++) + { + pObj->ppCoeff[i] = (fir_float_t*)malloc(N*sizeof(fir_float_t)); + memset(pObj->ppCoeff[i], 0, N*sizeof(fir_float_t)); + } + for(i=0; i < M; i++) + { + for(j=0; j < N; j++) + { + pObj->ppCoeff[i][j] = M*pCoeff[M*j+M/2+i]; + } + } + + // FIFO + pObj->L = N; // Influences STR-Loop delay + pObj->w = 0; + pObj->r = 0; + + pObj->pFifo = (cpx_t*)malloc(pObj->L*sizeof(cpx_t)); + memset(pObj->pFifo, 0, pObj->L*sizeof(cpx_t)); + + pObj->pX = (cpx_t*)malloc(pObj->L*sizeof(cpx_t)); + memset(pObj->pX, 0, pObj->L*sizeof(cpx_t)); + + pObj->M = M; + pObj->N = N; + + free(pCoeff); + + return k/M; +} + +void PolyPhaseCpxIpFree(ppip_cpx_t *pObj) +{ + uint32_t i; + + for(i=0; i < pObj->M; i++) + { + free(pObj->ppCoeff[i]); + } + free(pObj->ppCoeff); + pObj->ppCoeff = NULL; + + free(pObj->pFifo); + pObj->pFifo = NULL; + + free(pObj->pX); + pObj->pX = NULL; +} + +void PolyPhaseCpxIpFeed(ppip_cpx_t *pObj, uint32_t push, cpx_t x) +{ + pObj->w = (pObj->w + push) % pObj->L; + pObj->pFifo[pObj->w] = x; +} + +cpx_t PolyPhaseCpxIpInterpolate(ppip_cpx_t *pObj, int32_t pop, radio_float_t mu) +{ + uint32_t index, r; + int32_t j; + cpx_t y; + + index = (uint32_t)dmod(dmax(0, mu*pObj->M), (radio_float_t)pObj->M); + + pObj->r = (pObj->r + pop) % pObj->L; + + if (pop) + { + r = pObj->r; + j = pObj->N-1; + while(r < pObj->L) + { + pObj->pX[j--] = pObj->pFifo[r++]; + } + r = 0; + while(j >= 0) + { + pObj->pX[j--] = pObj->pFifo[r++]; + } + } + + y = CpxMulRealAdd(Cpx(0,0), pObj->pX, pObj->ppCoeff[index], pObj->N); +/* + pObj->r = (pObj->r + pop) % pObj->L; + r = pObj->r; + + y = Cpx(0,0); + for (j=0; j < pObj->N; j++) + { + y.real += pObj->pFifo[r].real * pW[j]; + y.imag += pObj->pFifo[r].imag * pW[j]; + + r = (r + pObj->L-1) % pObj->L; + + } +*/ + return y; +} + +// -------------------------------------------------------------- +// Complex FIR-based polyphase interpolation filter (Farrow structure) +// From: +// "PERFORMANCE AND DESIGN OF FARROW FILTER USED FOR ARBITRARY RESAMPLING" +// [unknown date], Fred Harris, Signal Processing ChairCommunication Systems and Signal Processing Institute +// College of Engineering, San Diego State University, San Diego, CA 92182-0190 USA +// -------------------------------------------------------------- +void FarrowPPIPCpxInit(ppip_farrow_cpx_t *pObj, uint32_t M, uint32_t N) +{ + uint32_t i; + + pObj->ppCoeff = (fir_float_t**)malloc(M*sizeof(fir_float_t*)); + for(i=0; i < M; i++) + { + pObj->ppCoeff[i] = (fir_float_t*)malloc(N*sizeof(fir_float_t)); + memset(pObj->ppCoeff[i], 0, N*sizeof(fir_float_t)); + } + pObj->M = M; + pObj->N = N; + + pObj->pH = (cpx_t*)malloc(M*sizeof(cpx_t)); + memset(pObj->pH, 0, M*sizeof(cpx_t)); + + pObj->pB = (cpx_t*)malloc(M*sizeof(cpx_t)); + memset(pObj->pB, 0, M*sizeof(cpx_t)); + + pObj->L = N; // Influences STR-Loop delay + pObj->w = 0; + pObj->r = 0; + + pObj->pFifo = (cpx_t*)malloc(pObj->L*sizeof(cpx_t)); + memset(pObj->pFifo, 0, pObj->L*sizeof(cpx_t)); + + pObj->pX = (cpx_t*)malloc(pObj->L*sizeof(cpx_t)); + memset(pObj->pX, 0, pObj->L*sizeof(cpx_t)); + +} + +void FarrowPPIPCpxFree(ppip_farrow_cpx_t *pObj) +{ + uint32_t i; + + for(i=0; i < pObj->M; i++) + { + free(pObj->ppCoeff[i]); + } + free(pObj->ppCoeff); + pObj->ppCoeff = NULL; + + free(pObj->pH); + pObj->pH = NULL; + + free(pObj->pB); + pObj->pB = NULL; + + free(pObj->pFifo); + pObj->pFifo = NULL; + + free(pObj->pX); + pObj->pX = NULL; +} + +cpx_t horner(cpx_t *a, cpx_t *b, uint32_t M, radio_float_t mu) +{ + uint32_t i; + + b[0] = a[0]; + for (i=1; i < M; i++) + { + b[i].real = a[i].real+mu*b[i-1].real; + b[i].imag = a[i].imag+mu*b[i-1].imag; + } + return b[M-1]; +} + +void FarrowPPIPCpxFeed(ppip_farrow_cpx_t *pObj, uint32_t push, cpx_t x) +{ + pObj->w = (pObj->w + push) % pObj->L; + pObj->pFifo[pObj->w] = x; +} + +cpx_t FarrowPPIPCpxInterpolate(ppip_farrow_cpx_t *pObj, uint32_t pop, radio_float_t mu) +{ + uint32_t i, r; + int32_t j; + + pObj->r = (pObj->r + pop) % pObj->L; + + if (pop) + { + r = pObj->r; + j = pObj->N-1; + while(r < pObj->L) + { + pObj->pX[j--] = pObj->pFifo[r++]; + } + r = 0; + while(j >= 0) + { + pObj->pX[j--] = pObj->pFifo[r++]; + } + } + + // Partial filter responses + for (i=0; i < pObj->M; i++) + { + pObj->pH[i] = CpxMulRealAdd(Cpx(0,0), pObj->pX, pObj->ppCoeff[i], pObj->N); + } + + // Combine + return horner(pObj->pH, pObj->pB, pObj->M, mu); +} + +// -------------------------------------------------------------- +// Real First-order interpolation filter +// -------------------------------------------------------------- +void FDly_Init(fdly_t *pObj, int32_t order) +{ + pObj->Nf = order + 1; + + pObj->hf = (radio_float_t*)malloc(pObj->Nf*sizeof(radio_float_t)); + pObj->statef = (radio_float_t*)malloc(pObj->Nf*sizeof(radio_float_t)); + memset(pObj->hf, 0, pObj->Nf*sizeof(radio_float_t)); + memset(pObj->statef, 0, pObj->Nf*sizeof(radio_float_t)); +} + +void FDly_Free(fdly_t *pObj) +{ + if (pObj->hf) + free(pObj->hf); + + pObj->hf = NULL; + + if (pObj->statef) + free(pObj->statef); + + pObj->statef = NULL; + +} + +radio_float_t FDly_Process(fdly_t *pObj, radio_float_t x) +{ + radio_float_t y; + + FIR(pObj->hf, pObj->statef, pObj->Nf, &x, &y, 1); + + return y; +} + +void FDly_CalcCoeff(fdly_t *pObj, radio_float_t delay) +{ + int32_t n, k; + radio_float_t hn; + + for (n=0; n < pObj->Nf; n++) + { + hn = 1.0; + for (k=0; k < pObj->Nf; k++) + { + if (k == n) + continue; + + hn *= ((delay - (radio_float_t)k) / (radio_float_t)(n-k)); + } + pObj->hf[n] = hn; + } +} + +// -------------------------------------------------------------- +// Real Polynomial-based Lagrange interpolation filter +// -------------------------------------------------------------- +void LGIpInit(lgip_t *pObj, int32_t order, int32_t bufsize) +{ + pObj->N = order + 1; + pObj->bufsize = bufsize; + RBufInit(&pObj->rbuf, bufsize); +} + +void LGIpFree(lgip_t *pObj) +{ + RBufFree(&pObj->rbuf); + pObj->N = 0; +} + +radio_float_t LGIpProcess(lgip_t *pObj, radio_float_t x, int32_t m, radio_float_t mu) +{ + int32_t n, k; + radio_float_t hn, y, delay; + + RBufPut(&pObj->rbuf, x); + y = 0; + delay = 1-mu; + for (n=0; n < pObj->N; n++) + { + hn = 1.0; + for (k=0; k < pObj->N; k++) + { + if (k == n) + continue; + + hn *= ((delay - (radio_float_t)k) / (radio_float_t)(n-k)); + } + y += hn*RBufGetAt(&pObj->rbuf, pObj->bufsize/2 + m-n); + } + return y; +} + +// -------------------------------------------------------------- +// Complex Polynomial-based Lagrange interpolation filter +// -------------------------------------------------------------- +void LGCpxIpInit(lgip_cpx_t *pObj, int32_t order) +{ + // FIFO + pObj->N = order + 1; + pObj->w = 0; + pObj->r = 0; + pObj->L = 64*pObj->N; // Influences STR-Loop delay + + pObj->pFifo = (cpx_t*)malloc(pObj->L*sizeof(cpx_t)); + memset(pObj->pFifo, 0, pObj->L*sizeof(cpx_t)); + +} + +void LGCpxIpFree(lgip_cpx_t *pObj) +{ + free(pObj->pFifo); + pObj->pFifo = NULL; + pObj->N = 0; +} + +cpx_t LGCpxIpProcess(lgip_cpx_t *pObj, cpx_t x, int32_t m, radio_float_t mu) +{ + uint32_t i, j, k, N, L, r; + radio_float_t h; + cpx_t y; + + L = pObj->L; + N = pObj->N; + + pObj->pFifo[pObj->w++] = x; + if (pObj->w == L) + pObj->w = 0; + + r = (m-N) % L; + + k = 0; + + y.real = 0.0; + y.imag = 0.0; + for (i=0; i < pObj->N; i++) + { + h = 1.0; + for (j=0; j < pObj->N; j++) + { + if (i == j) + continue; + + h *= (((radio_float_t)pObj->N/2 + mu - (radio_float_t)j - (radio_float_t)0.5) / (radio_float_t)(i-j)); + } + y.real += pObj->pFifo[r].real * h; + y.imag += pObj->pFifo[r].imag * h; + r = (r+1) % L; + } + return y; +} + +// -------------------------------------------------------------- +// Real FIR-based polyphase interpolation SRRC (Square Root Raised Cosine) matched filter #1 +// -------------------------------------------------------------- +radio_float_t PolyPhaseSRRCInit(fir_pp_t *pObj, radio_float_t fa, radio_float_t tsym, radio_float_t alpha, uint32_t N, uint32_t M) +{ + uint32_t i, j; + fir_float_t *pCoeff; + radio_float_t k; + + pCoeff = (fir_float_t*)malloc((N+1)*M*sizeof(fir_float_t)); + memset(pCoeff, 0, M*(N+1)*sizeof(fir_float_t)); + + k = CalcFirSRRC(pCoeff, M*fa, tsym, alpha, M*N); + + pObj->ppCoeff = (fir_float_t**)malloc(M*sizeof(fir_float_t*)); + for(i=0; i < M; i++) + { + pObj->ppCoeff[i] = (fir_float_t*)malloc(N*sizeof(fir_float_t)); + memset(pObj->ppCoeff[i], 0, N*sizeof(fir_float_t)); + } + pObj->pState = (fir_float_t*)malloc(N*sizeof(fir_float_t)); + memset(pObj->pState, 0, N*sizeof(fir_float_t)); + + for(i=0; i < M; i++) + { + for(j=0; j < N; j++) + { + pObj->ppCoeff[i][j] = M*pCoeff[M*j+M/2+i]; + } + } + + pObj->M = M; + pObj->N = N; + + free(pCoeff); + + return k/M; + +} + +void PolyPhaseSRRCFree(fir_pp_t *pObj) +{ + uint32_t i; + + for(i=0; i < pObj->M; i++) + { + free(pObj->ppCoeff[i]); + } + free(pObj->ppCoeff); + pObj->ppCoeff = NULL; + + free(pObj->pState); + pObj->pState = NULL; + +} + +uint32_t PolyPhaseSRRCProcess(fir_pp_t *pObj, radio_float_t mu, radio_float_t *pX, radio_float_t *pY, uint32_t len) +{ + uint32_t m; + +// m = (pObj->M/2 + (int32_t)(mu * pObj->M/2)) % pObj->M; + m = (int32_t)dmod(mu*pObj->M, (radio_float_t)pObj->M); + + FIR(pObj->ppCoeff[m], pObj->pState, pObj->N, pX, pY, len); + + return len; +} + +// -------------------------------------------------------------- +// Real FIR-based polyphase interpolation SRRC (Square Root Raised Cosine) matched filter #2 +// -------------------------------------------------------------- +radio_float_t PolyPhaseIpInit(ppip_t *pObj, radio_float_t fa, radio_float_t tsym, radio_float_t alpha, uint32_t N, uint32_t M) +{ + uint32_t i, j; + fir_float_t *pCoeff; + radio_float_t k; + + pCoeff = (fir_float_t*)malloc((N+1)*M*sizeof(fir_float_t)); + memset(pCoeff, 0, (N+1)*M*sizeof(fir_float_t)); + + k = CalcFirSRRC(pCoeff, M*fa, tsym, alpha, N*M); + + pObj->ppCoeff = (fir_float_t**)malloc(M*sizeof(fir_float_t*)); + for(i=0; i < M; i++) + { + pObj->ppCoeff[i] = (fir_float_t*)malloc(N*sizeof(fir_float_t)); + memset(pObj->ppCoeff[i], 0, N*sizeof(fir_float_t)); + } + for(i=0; i < M; i++) + { + for(j=0; j < N; j++) + { + pObj->ppCoeff[i][j] = M*pCoeff[M*j+M/2+i]; + } + } + pObj->pState = (fir_float_t*)malloc(N*sizeof(fir_float_t)); + memset(pObj->pState, 0, N*sizeof(fir_float_t)); + + pObj->M = M; + pObj->N = N; + + RBufInit(&pObj->rbuf, 2*N); // Influences STR-Loop delay + + free(pCoeff); + + return k/M; + +} + +void PolyPhaseIpFree(ppip_t *pObj) +{ + uint32_t i; + + for(i=0; i < pObj->M; i++) + { + free(pObj->ppCoeff[i]); + } + free(pObj->ppCoeff); + pObj->ppCoeff = NULL; + + free(pObj->pState); + pObj->pState = NULL; + + RBufFree(&pObj->rbuf); + +} + +radio_float_t PolyPhaseIpProcess(ppip_t *pObj, radio_float_t x, int32_t m, radio_float_t mu) +{ + uint32_t index, i; + radio_float_t y; + + index = (int32_t)dmod(mu*pObj->M, (radio_float_t)pObj->M); + + for(i=0; i < pObj->N; i++) + { + pObj->pState[i] = RBufGetAt(&pObj->rbuf, m-i); + } + + FIR(pObj->ppCoeff[index], pObj->pState, pObj->N, &x, &y, 1); + RBufPut(&pObj->rbuf, x); + + return y; +} diff --git a/interpolation.h b/interpolation.h new file mode 100755 index 0000000..cd21eaf --- /dev/null +++ b/interpolation.h @@ -0,0 +1,158 @@ +// -------------------------------------------------------------- +#ifndef INTERPOLATION_H +#define INTERPOLATION_H + +#include "radio_types.h" +#include "real.h" +#include "cpx.h" +#include +#include "ringbuf.h" +#include "synchronization.h" + +// -------------------------------------------------------------- +#define CEF_MODE_NOP 0 +#define CEF_MODE_CMA 1 +#define CEF_MODE_DD 2 +#define CEF_MODE_EQ_UPD 3 + +// -------------------------------------------------------------- +// Types +// -------------------------------------------------------------- +typedef struct _fir_cpx_t +{ + uint32_t N, r, w; + cpx_t *pX; + uint32_t M_up, M_down; + clock_t clockUp; + clock_t clockDown; +} fir_cpx_t; + +typedef struct _fir_cpx_multirate_stage_t +{ + uint32_t N; + uint32_t k; + uint32_t K; + cpx_t *pX; + radio_float_t *pW; + +} fir_cpx_multirate_stage_t; + +typedef struct _fir_cpx_multirate_t +{ + uint32_t N; + uint32_t L; + uint32_t M; + fir_cpx_multirate_stage_t *pStageUp; + fir_cpx_multirate_stage_t *pStageDown; + cpx_t res; + uint32_t k; + +} fir_cpx_multirate_t; + +typedef struct _fdly_t +{ + int32_t Nf; + radio_float_t *hf, *statef; +} fdly_t; + +typedef struct _lgip_t +{ + int32_t N, bufsize; + rbuf_t rbuf; +} lgip_t; + +typedef struct _lgip_cpx_t +{ + cpx_t *pFifo; + uint32_t N, L, w, r; + +} lgip_cpx_t; + +typedef struct _fir_pp_t +{ + uint32_t N, M; + radio_float_t **ppCoeff, *pState; + +} fir_pp_t; + +typedef struct _ppip_t +{ + radio_float_t **ppCoeff, *pState; + uint32_t N, M; + rbuf_t rbuf; + +} ppip_t; + +typedef struct _ppip_cpx_t +{ + cpx_t *pFifo; + radio_float_t **ppCoeff; + uint32_t N, L, M, w, r; + cpx_t *pX; + +} ppip_cpx_t; + +typedef struct _ppip_farrow_cpx_t +{ + cpx_t *pFifo, *pH, *pB; + radio_float_t **ppCoeff; + uint32_t N, L, M, w, r; + cpx_t *pX; + +} ppip_farrow_cpx_t; + +// -------------------------------------------------------------- +// Functions +// -------------------------------------------------------------- +#ifdef __cplusplus +extern "C" { +#endif + +void FDly_Init(fdly_t *pObj, int32_t order); +void FDly_Free(fdly_t *pObj); +void FDly_CalcCoeff(fdly_t *pObj, radio_float_t delay); +radio_float_t FDly_Process(fdly_t *pObj, radio_float_t x); + +void LGIpInit(lgip_t *pObj, int32_t order, int32_t bufsize); +void LGIpFree(lgip_t *pObj); +radio_float_t LGIpProcess(lgip_t *pObj, radio_float_t x, int32_t m, radio_float_t mu); + +void LGCpxIpInit(lgip_cpx_t *pObj, int32_t order); +void LGCpxIpFree(lgip_cpx_t *pObj); +cpx_t LGCpxIpProcess(lgip_cpx_t *pObj, cpx_t x, int32_t m, radio_float_t mu); + +radio_float_t PolyPhaseSRRCInit(fir_pp_t *pObj, radio_float_t fa, radio_float_t tsym, radio_float_t alpha, uint32_t N, uint32_t M); +void PolyPhaseSRRCFree(fir_pp_t *pObj); +uint32_t PolyPhaseSRRCProcess(fir_pp_t *pObj, radio_float_t mu, radio_float_t *pX, radio_float_t *pY, uint32_t len); + +radio_float_t PolyPhaseIpInit(ppip_t *pObj, radio_float_t fa, radio_float_t tsym, radio_float_t alpha, uint32_t N, uint32_t M); +void PolyPhaseIpFree(ppip_t *pObj); +radio_float_t PolyPhaseIpProcess(ppip_t *pObj, radio_float_t x, int32_t m, radio_float_t mu); + +radio_float_t PolyPhaseCpxIpInit(ppip_cpx_t *pObj, radio_float_t fa, radio_float_t tsym, radio_float_t alpha, uint32_t N, uint32_t M); +void PolyPhaseCpxIpFree(ppip_cpx_t *pObj); +void PolyPhaseCpxIpFeed(ppip_cpx_t *pObj, uint32_t push, cpx_t x); +cpx_t PolyPhaseCpxIpInterpolate(ppip_cpx_t *pObj, int32_t pop, radio_float_t mu); + +void FarrowPPIPCpxInit(ppip_farrow_cpx_t *pObj, uint32_t M, uint32_t N); +void FarrowPPIPCpxFree(ppip_farrow_cpx_t *pObj); +void FarrowPPIPCpxFeed(ppip_farrow_cpx_t *pObj, uint32_t push, cpx_t x); +cpx_t FarrowPPIPCpxInterpolate(ppip_farrow_cpx_t *pObj, uint32_t pop, radio_float_t mu); + +void FirCpxInit(fir_cpx_t *pObj, uint32_t N, uint32_t M_up, uint32_t M_down); +void FirCpxFree(fir_cpx_t *pObj); +uint32_t FirCpxProcessReal(fir_cpx_t *pObj, radio_float_t *pW, cpx_t *pSrc, cpx_t *pDst, uint32_t len); + +void FirCpxMultirateDownInit(fir_cpx_multirate_t *pObj, radio_float_t *pW, uint32_t N, uint32_t M); +void FirCpxMultirateUpInit(fir_cpx_multirate_t *pObj, radio_float_t *pW, uint32_t N, uint32_t L); +void FirCpxMultirateUpReinit(fir_cpx_multirate_t *pObj, radio_float_t *pW, uint32_t N, uint32_t L); +void FirCpxMultirateFree(fir_cpx_multirate_t *pObj); +uint32_t FirCpxDownProcess(fir_cpx_multirate_t *pObj, cpx_t *pSrc, cpx_t *pDst, uint32_t len); +uint32_t FirCpxUpProcess(fir_cpx_multirate_t *pObj, cpx_t *pSrc, cpx_t *pDst, uint32_t len); + +#ifdef __cplusplus +} +#endif + +// -------------------------------------------------------------- +#endif // INTERPOLATION_H diff --git a/nco.c b/nco.c new file mode 100755 index 0000000..bccca39 --- /dev/null +++ b/nco.c @@ -0,0 +1,118 @@ +// -------------------------------------------------------------- +#include +#include +#include "nco.h" + +// -------------------------------------------------------------- +// NCO +// Scalar version +// -------------------------------------------------------------- +void NCO_Init(nco_t *pObj, radio_float_t omega, radio_float_t phi) +{ + pObj->omega = omega; + pObj->phi = phi; + memset(&pObj->state,0,sizeof(cpx_t)); +} + +void NCO_Free(nco_t *pObj) +{ + (void)pObj; +} + +void NCO_Reinit(nco_t *pObj, radio_float_t omega, radio_float_t phi) +{ + NCO_Free(pObj); + NCO_Init(pObj, omega, phi); +} + +void NCO_SetOmega(nco_t *pObj, radio_float_t omega) +{ + pObj->omega = omega; +} + +void NCO_SetPhi(nco_t *pObj, radio_float_t phi) +{ + pObj->phi = phi; +} + +radio_float_t NCO_GetOmega(nco_t *pObj) +{ + return pObj->omega; +} + +radio_float_t NCO_GetPhi(nco_t *pObj) +{ + return pObj->phi; +} + +void NCO_Process(nco_t *pObj, radio_float_t dOmega, radio_float_t dPhi) +{ + pObj->phi += (pObj->omega + dOmega); + + if (pObj->phi < -(radio_float_t)0.5) + pObj->phi += (radio_float_t)1.0; + + if (pObj->phi >= +(radio_float_t)0.5) + pObj->phi -= (radio_float_t)1.0; + + pObj->state.real = +(radio_float_t)cos(2.0*PI*pObj->phi + dPhi); + pObj->state.imag = -(radio_float_t)sin(2.0*PI*pObj->phi + dPhi); +} + +cpx_t NCO_MixRealComplexS(nco_t *pObj, radio_float_t src, radio_float_t gain) +{ + cpx_t dst; + + dst.real = gain*src; + dst.imag = 0; + + return CpxMulS(pObj->state, dst); +} + +radio_float_t NCO_MixComplexRealS(nco_t *pObj, cpx_t src, cpx_t gain) +{ + return gain.real*pObj->state.real*src.real + gain.imag*pObj->state.imag*src.imag; +} + +cpx_t NCO_MixComplexS(nco_t *pObj, cpx_t src, cpx_t gain) +{ + return CpxMulS(pObj->state, CpxScaleComplexS(src, gain)); +} + +void NCO_MixRealComplexV(nco_t *pObj, cpx_t *pDst, radio_float_t *pSrc, radio_float_t gain, uint32_t len) +{ + + while (len--) + { + + *(pDst++) = NCO_MixRealComplexS(pObj, *(pSrc++), gain); + + // NCO update + NCO_Process(pObj, 0, 0); + } +} + +void NCO_MixComplexRealV(nco_t *pObj, radio_float_t *pDst, cpx_t *pSrc, cpx_t gain, uint32_t len) +{ + while (len--) + { + + *(pDst++) = NCO_MixComplexRealS(pObj, *(pSrc++), gain); + + // NCO update + NCO_Process(pObj, 0, 0); + } +} + +void NCO_MixComplexV(nco_t *pObj, cpx_t *pSrcDst, cpx_t gain, uint32_t len) +{ + while (len--) + { + *(pSrcDst++) = NCO_MixComplexS(pObj, *(pSrcDst++), gain); + + // NCO update + NCO_Process(pObj, 0, 0); + } +} + +// -------------------------------------------------------------- diff --git a/nco.h b/nco.h new file mode 100755 index 0000000..c20ab3f --- /dev/null +++ b/nco.h @@ -0,0 +1,57 @@ +// -------------------------------------------------------------- +#ifndef NCO_H +#define NCO_H + +#include +#include "radio_types.h" +#include "real.h" +#include "cpx.h" + +// -------------------------------------------------------------- +// Types +// -------------------------------------------------------------- +typedef struct _nco_t +{ + radio_float_t phi, omega; + cpx_t state; +} nco_t; + +// -------------------------------------------------------------- +#ifdef __cplusplus +extern "C" { +#endif +// -------------------------------------------------------------- +// NCO +// -------------------------------------------------------------- +// Scalar version +void NCO_Init(nco_t *pObj, radio_float_t omega, radio_float_t phi); +void NCO_Free(nco_t *pObj); +void NCO_Reinit(nco_t *pObj, radio_float_t omega, radio_float_t phi); +void NCO_SetOmega(nco_t *pObj, radio_float_t omega); +void NCO_SetPhi(nco_t *pObj, radio_float_t phi); +radio_float_t NCO_GetOmega(nco_t *pObj); +radio_float_t NCO_GetPhi(nco_t *pObj); +void NCO_Process(nco_t *pObj, radio_float_t dOmega, radio_float_t dPhi); + +// -------------------------------------------------------------- +// Mixer +// Scalar version +// -------------------------------------------------------------- +cpx_t NCO_MixRealComplexS(nco_t *pObj, radio_float_t src, radio_float_t gain); +cpx_t NCO_MixComplexS(nco_t *pObj, cpx_t src, cpx_t gain); +radio_float_t NCO_MixComplexRealS(nco_t *pObj, cpx_t src, cpx_t gain); +// -------------------------------------------------------------- +// Mixer +// Vector version +// -------------------------------------------------------------- +void NCO_MixRealComplexV(nco_t *pObj, cpx_t *pDst, radio_float_t *pSrc, radio_float_t gain, uint32_t len); +void NCO_MixComplexV(nco_t *pObj, cpx_t *pSrcDst, cpx_t gain, uint32_t len); +void NCO_MixComplexRealV(nco_t *pObj, radio_float_t *pDst, cpx_t *pSrc, cpx_t gain, uint32_t len); + +// -------------------------------------------------------------- +#ifdef __cplusplus +} +#endif // __cplusplus + +// -------------------------------------------------------------- +#endif // NCO_H diff --git a/radio.c b/radio.c new file mode 100755 index 0000000..c195abf --- /dev/null +++ b/radio.c @@ -0,0 +1,2660 @@ +// -------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include "radio.h" + +// -------------------------------------------------------------- +// Real Functions +// -------------------------------------------------------------- + +radio_float_t dabs(radio_float_t x) +{ + if (x < 0) + return -x; + + return x; +} + +radio_float_t dsign(radio_float_t x) +{ + if (x < 0) + return -1.0; + + return 1.0; +} + +radio_float_t dmod(radio_float_t x, radio_float_t y) +{ + int xy; + + if (y == 0) + return x; + + xy = (int)floor(x/y); + + return dsign(y)*(radio_float_t)fabs(x - y*(radio_float_t)xy); +} + +radio_float_t dmax(radio_float_t x, radio_float_t y) +{ + if (x > y) + return x; + + return y; +} + +radio_float_t dmin(radio_float_t x, radio_float_t y) +{ + if (x < y) + return x; + + return y; +} + +radio_float_t dclamp(radio_float_t x, radio_float_t limit_low, radio_float_t limit_high) +{ + return dmin(dmax(x, limit_low), limit_high); +} + +radio_float_t powerDB(radio_float_t v1, radio_float_t preScale) +{ + return (radio_float_t)(10*log10(RADIO_POWER_EPS + v1*preScale)); +} + +float fsum(float *pSrc, int len) +{ + float sum = 0; + + while(len--) + sum += *(pSrc++); + + return sum; +} + +float fmean(float *pSrc, int len) +{ + return fsum(pSrc, len)/len; +} + +radio_float_t dsum(radio_float_t *pSrc, int len) +{ + radio_float_t sum = 0; + + while(len--) + sum += *(pSrc++); + + return sum; +} + +radio_float_t dmean(radio_float_t *pSrc, int len) +{ + return dsum(pSrc, len)/len; +} + +// -------------------------------------------------------------- +// Complex Functions +// -------------------------------------------------------------- +cpx_t CpxConjS(cpx_t v1) +{ + register cpx_t temp; + + temp.real = v1.real; + temp.imag = -v1.imag; + + return temp; + +} + +cpx_t CpxAddS(cpx_t v1, cpx_t v2) +{ + register cpx_t temp; + + temp.real = v1.real + v2.real; + temp.imag = v1.imag + v2.imag; + + return temp; +} + +cpx_t CpxSubS(cpx_t v1, cpx_t v2) +{ + register cpx_t temp; + + temp.real = v1.real - v2.real; + temp.imag = v1.imag - v2.imag; + + return temp; +} + +cpx_t CpxMulS(cpx_t v1, cpx_t v2) +{ + register cpx_t temp; + + temp.real = v1.real*v2.real - v1.imag*v2.imag; + temp.imag = v1.real*v2.imag + v1.imag*v2.real; + + return temp; +} + +cpx_t CpxScaleRealS(cpx_t v1, radio_float_t v2) +{ + register cpx_t temp; + + temp.real = v1.real*v2; + temp.imag = v1.imag*v2; + + return temp; +} + +cpx_t CpxScaleComplexS(cpx_t x, cpx_t gain) +{ + register cpx_t temp; + + temp.real = x.real*gain.real; + temp.imag = x.imag*gain.imag; + + return temp; +} + +cpx_t CpxFromReal(radio_float_t v1) +{ + cpx_t res = {v1, v1}; + + return res; +} + +cpx_t Cpx(radio_float_t real, radio_float_t imag) +{ + cpx_t res = {real, imag}; + + return res; +} + +radio_float_t CpxMagS(cpx_t v1) +{ + radio_float_t mag; + + mag = (radio_float_t)sqrt(v1.real*v1.real + v1.imag*v1.imag); + + return mag; +} + +radio_float_t CpxPhiS(cpx_t v1) +{ + return (radio_float_t)atan2(v1.real, v1.imag); +} + +cpx_t CpxMinS(cpx_t x1, cpx_t x2) +{ + return Cpx(dmin(x1.real, x2.real), dmin(x1.imag, x2.imag)); +} + +cpx_t CpxMaxS(cpx_t x1, cpx_t x2) +{ + return Cpx(dmax(x1.real, x2.real), dmax(x1.imag, x2.imag)); +} + +radio_float_t cpxPowerDB(cpx_t v1, radio_float_t preScale) +{ + return powerDB(CpxMagS(v1), preScale); +} + +void CpxCopy(cpx_t *pSrc, cpx_t *pDst, uint32_t len) +{ + memcpy(pDst, pSrc, len*sizeof(cpx_t)); +} + +void CpxConj(cpx_t *pSrcDst, uint32_t len) +{ + uint32_t i; + for(i=0; i < len; i++) + pSrcDst[i] = CpxConjS(pSrcDst[i]); +} + +void CpxAdd(cpx_t *pSrc, cpx_t *pSrcDst, uint32_t len) +{ + uint32_t i; + for(i=0; i < len; i++) + pSrcDst[i] = CpxAddS(pSrc[i], pSrcDst[i]); +} + +void CpxSub(cpx_t *pSrc, cpx_t *pSrcDst, uint32_t len) +{ + uint32_t i; + for(i=0; i < len; i++) + pSrcDst[i] = CpxSubS(pSrc[i], pSrcDst[i]); +} + +void CpxMul(cpx_t *pSrc, cpx_t *pSrcDst, uint32_t len) +{ + + uint32_t i; + for(i=0; i < len; i++) + pSrcDst[i] = CpxMulS(pSrc[i], pSrcDst[i]); +} + + +cpx_t csum(cpx_t *pSrc, int len) +{ + cpx_t sum = {0}; + + while(len--) + { + sum.real += (*(pSrc)).real; + sum.imag += (*(pSrc++)).imag; + } + + return sum; +} + +cpx_t cmean(cpx_t *pSrc, int len) +{ + cpx_t y; + + y = csum(pSrc, len); + y.real /= len; + y.imag /= len; + + return y; +} + +// -------------------------------------------------------------- +// NCO +// -------------------------------------------------------------- +void NCO_Init(nco_t *pObj, radio_float_t omega, radio_float_t phi, uint32_t tbl_size) +{ + uint32_t i; + radio_float_t dphi_tbl, phi_tbl; + + pObj->dOmega = 0.0; + pObj->dPhi = 0.0; + pObj->omega = omega; + pObj->phi = phi; + pObj->tbl_index = 0; + pObj->tbl_size = tbl_size; + pObj->pTbl = NULL; + memset(&pObj->state,0,sizeof(cpx_t)); + + if (tbl_size > 0) + { + dphi_tbl = (radio_float_t)(2.0*PI/tbl_size); + pObj->pTbl = (cpx_t*)malloc(tbl_size*sizeof(cpx_t)); + + phi_tbl = 0; + for (i=0; i < tbl_size; i++) + { + pObj->pTbl[i].real = (radio_float_t)cos(phi_tbl); + pObj->pTbl[i].imag = (radio_float_t)sin(phi_tbl); + phi_tbl += dphi_tbl; + } + } +} + +void NCO_Free(nco_t *pObj) +{ + if (pObj->pTbl) + free(pObj->pTbl); +} + +void NCO_ModPhi(nco_t *pObj, radio_float_t dPhi) +{ + pObj->dPhi += dPhi; + pObj->phi += dPhi; + + if (pObj->phi < -(radio_float_t)0.5) pObj->phi += (radio_float_t)1.0; + if (pObj->phi >= +(radio_float_t)0.5) pObj->phi -= (radio_float_t)1.0; +} + +void NCO_ModOmega(nco_t *pObj, radio_float_t dOmega) +{ + pObj->dOmega = dOmega; +} + +radio_float_t NCO_GetOmega(nco_t *pObj) +{ + return pObj->omega + pObj->dOmega; +} + +void NCO_Process(nco_t *pObj) +{ + uint32_t i; + + pObj->phi += (pObj->omega + pObj->dOmega); + + if (pObj->phi < -(radio_float_t)0.5) pObj->phi += (radio_float_t)1.0; + if (pObj->phi >= +(radio_float_t)0.5) pObj->phi -= (radio_float_t)1.0; + + if (pObj->pTbl == NULL) + { + pObj->state.real = +(radio_float_t)cos(2.0*PI*pObj->phi); + pObj->state.imag = -(radio_float_t)sin(2.0*PI*pObj->phi); + } + else + { + i = (int)(0.5 + pObj->phi*pObj->tbl_size)%pObj->tbl_size; + pObj->state.real = +pObj->pTbl[i].real; + pObj->state.imag = -pObj->pTbl[i].imag; + } +} + +// -------------------------------------------------------------- +// Mixer +// Scalar version +// -------------------------------------------------------------- +cpx_t NCO_MixComplexS(nco_t *pObj, cpx_t *pSrc, cpx_t gain) +{ + return CpxMulS(pObj->state, CpxScaleComplexS(*pSrc, gain)); +} + +cpx_t NCO_MixRealS(nco_t *pObj, radio_float_t src, radio_float_t gain) +{ + cpx_t dst; + + dst.real = gain*src; + dst.imag = 0; + + return CpxMulS(pObj->state, dst); +} + +radio_float_t NCO_MixComplexRealS(nco_t *pObj, cpx_t *pSrc, cpx_t gain) +{ + return gain.real*pSrc->real*pObj->state.real + gain.imag*pSrc->imag*pObj->state.imag; +} +// -------------------------------------------------------------- +// Mixer +// Vector version +// -------------------------------------------------------------- +void NCO_MixComplexV(nco_t *pObj, cpx_t *pSrc, cpx_t *pDst, cpx_t gain, uint32_t len) +{ + + while (len--) + { + + *pDst++ = NCO_MixComplexS(pObj, pSrc++, gain); + + // NCO update + NCO_Process(pObj); + } + +} + +void NCO_MixRealV(nco_t *pObj, radio_float_t *pSrc, cpx_t *pDst, radio_float_t gain, uint32_t len) +{ + + while (len--) + { + + *pDst++ = NCO_MixRealS(pObj, *pSrc++, gain); + + // NCO update + NCO_Process(pObj); + } +} + +void NCO_MixComplexRealV(nco_t *pObj, cpx_t *pSrc, radio_float_t *pDst, cpx_t gain, uint32_t len) +{ + + while (len--) + { + + *pDst++ = NCO_MixComplexRealS(pObj, pSrc++, gain); + + // NCO update + NCO_Process(pObj); + } +} + +// -------------------------------------------------------------- +// Synchronization +// -------------------------------------------------------------- +#if 0 +void SamplerInit(sampler_t *pObj, int divide) +{ + pObj->reload = divide; + pObj->count = divide -1;; +} + +int SamplerIsSample(sampler_t *pObj) +{ + return (pObj->count == 0); +} + +void SamplerUpdate(sampler_t *pObj) +{ + if (pObj->count == 0) + pObj->count = pObj->reload -1; + else + pObj->count--; +} + +// -------------------------------------------------------------- +// Phase detector for QPSK +// -------------------------------------------------------------- +radio_float_t PhaseErrQPSK(cpx_t x) +{ + radio_float_t perr; + perr = x.imag*dsign(x.real) - x.real*dsign(x.imag); + + return perr; +} + +radio_float_t PhaseErr(cpx_t x, radio_float_t pstep, radio_float_t poffset) +{ + radio_float_t perr, phi, m; + + phi = (radio_float_t)CpxPhiS(x) + poffset; + + m = dmod(phi/(radio_float_t)PI,(radio_float_t)2.0/pstep); + perr = (radio_float_t)1.0/pstep - m; + + return (radio_float_t)(PI*perr); +} + +// -------------------------------------------------------------- +// Clock generator +// -------------------------------------------------------------- +void Clkgen_Init(clkgen_t *pObj) +{ + pObj->lastPhi = 0; +} + +int Clkgen_GetPulse(clkgen_t *pObj, nco_t *pNCO) +{ + int pulse = 0; + radio_float_t tmp1, tmp2; + + tmp1 = (radio_float_t)fmod(pNCO->phi, (radio_float_t)PI); + tmp2 = (radio_float_t)fmod(pObj->lastPhi, (radio_float_t)PI); + +// if ((pObj->pNCO->phi <= 0) && (pObj->lastPhi > 0)/* && (pObj->pNCO->phi <= 0)*/) +// pulse = 1; + + pulse = tmp1 < tmp2; + + pObj->lastPhi = pNCO->phi; + + return pulse; +} + +void LeadLagInit(lead_lag_filter_t *pObj, radio_float_t lead_gain, radio_float_t lag_gain, radio_float_t ic_lag) +{ + pObj->term_lag = ic_lag; + pObj->term_lead = 0; + pObj->gain_lag = lag_gain; + pObj->gain_lead = lead_gain; +}; + +void LeadLagSetGainLead(lead_lag_filter_t *pObj, radio_float_t gain) +{ + pObj->gain_lead = gain; +} + +void LeadLagSetGainLag(lead_lag_filter_t *pObj, radio_float_t gain) +{ + pObj->gain_lag = gain; +} + +radio_float_t LeadLagProcess(lead_lag_filter_t *pObj, radio_float_t x) +{ + radio_float_t y; + + pObj->term_lag += x * pObj->gain_lag; + pObj->term_lead = x * pObj->gain_lead; + + y = pObj->term_lag + pObj->term_lead; + + return y; +} + +// -------------------------------------------------------------- +// Gardner Timing Error Detector +// -------------------------------------------------------------- +void STRGardnerInit(str_t *pObj) +{ + memset(pObj->d, 0, sizeof(pObj->d)); +} + +radio_float_t STRGardnerProcess(str_t *pObj, cpx_t x) +{ + radio_float_t Vd; + cpx_t t, *pD; + + pD = pObj->d; + + t.real = (pD[1].real - x.real) * pD[0].real; + t.imag = (pD[1].imag - x.imag) * pD[0].imag; + Vd = (t.real + t.imag); + + // Adjust delay line + pD[1] = pD[0]; + pD[0] = x; + + return Vd; +} +#endif +// -------------------------------------------------------------- +// Sliding Statistics +// -------------------------------------------------------------- +void SlidingMeanInit(sl_mean_t *pObj, int N) +{ + RBufInit(&pObj->buf, N); + pObj->Nr = (radio_float_t)1.0/N; + pObj->mean = 0.0; + pObj->sum = 0.0; + pObj->normalize_count = N; +} + +void SlidingMeanFree(sl_mean_t *pObj) +{ + RBufFree(&pObj->buf); +} + +radio_float_t SlidingMeanProcess(sl_mean_t *pObj, radio_float_t x) +{ + uint32_t i; + radio_float_t last; + + last = RBufGetAfter(&pObj->buf, pObj->buf.size-1); + RBufPut(&pObj->buf, x); + pObj->sum += (x - last); + pObj->mean = pObj->sum*pObj->Nr; + + if (--pObj->normalize_count == 0) + { + pObj->normalize_count = pObj->buf.size; + pObj->sum = 0; + for (i=0; i < pObj->buf.size; i++) + { + pObj->sum += pObj->buf.pData[i]; + } + } + return pObj->mean; +} + +void SlidingMeanProcessV(sl_mean_t *pObj, radio_float_t *pX, uint32_t len) +{ + uint32_t i; + + for (i=0; i < len; i++) + SlidingMeanProcess(pObj, *(pX++)); +} + +radio_float_t SlidingMeanGet(sl_mean_t *pObj) +{ + return pObj->mean; +} + +void SlidingVarInit(sl_var_t *pObj, int Npwr, int Nmean) +{ + RBufInit(&pObj->buf, Npwr); + SlidingMeanInit(&pObj->sl_mean, Nmean); + pObj->Nr = (radio_float_t)1.0/Npwr; + pObj->var = 0.0; + pObj->sum = 0.0; + pObj->normalize_count = Npwr; +} + +void SlidingVarFree(sl_var_t *pObj) +{ + RBufFree(&pObj->buf); + SlidingMeanFree(&pObj->sl_mean); +} + +radio_float_t SlidingVarProcess(sl_var_t *pObj, radio_float_t x) +{ + uint32_t i; + radio_float_t last, xm, mean, var; + + last = RBufGetAfter(&pObj->buf, pObj->buf.size-1); + mean = SlidingMeanProcess(&pObj->sl_mean, x); + xm = x - mean; + xm *= xm; + RBufPut(&pObj->buf, xm); + pObj->sum += (xm - last); + + var = pObj->sum*pObj->Nr; + if (var >= 0) + pObj->var = var; + + if (--pObj->normalize_count == 0) + { + pObj->normalize_count = pObj->buf.size; + pObj->sum = 0; + for (i=0; i < pObj->buf.size; i++) + { + pObj->sum += pObj->buf.pData[i]; + } + } + return pObj->var; +} + +void SlidingVarProcessV(sl_var_t *pObj, radio_float_t *pX, uint32_t len) +{ + uint32_t i; + + for (i=0; i < len; i++) + SlidingVarProcess(pObj, *(pX++)); +} + +radio_float_t SlidingVarGet(sl_var_t *pObj) +{ + return pObj->var; +} + +radio_float_t SlidingVarGetPowerDB(sl_var_t *pObj, radio_float_t preScale) +{ + return powerDB(pObj->var, preScale); +} + +void SlidingMinMaxInit(sl_minmax_t *pObj, uint32_t L, radio_float_t P, radio_float_t mode) +{ + pObj->L = L; + pObj->P = P; + pObj->N = 0; + pObj->max = 0; + pObj->mode = mode; + pObj->pP = (uint32_t*)malloc(L*sizeof(uint32_t)); + pObj->pU = (radio_float_t*)malloc(L*sizeof(radio_float_t)); + pObj->pP_last = (uint32_t*)malloc(L*sizeof(uint32_t)); + pObj->pU_last = (radio_float_t*)malloc(L*sizeof(radio_float_t)); + memset(pObj->pP, 0, L*sizeof(uint32_t)); + memset(pObj->pU, 0, L*sizeof(radio_float_t)); + memset(pObj->pP_last, 0, L*sizeof(uint32_t)); + memset(pObj->pU_last, 0, L*sizeof(radio_float_t)); + pObj->pU_last[1] = P; +} + +void SlidingMinMaxFree(sl_minmax_t *pObj) +{ + if (pObj->pP) + free(pObj->pP); + + if (pObj->pU) + free(pObj->pU); + + if (pObj->pP_last) + free(pObj->pP_last); + + if (pObj->pU_last) + free(pObj->pU_last); + + pObj->pP = (uint32_t*)0; + pObj->pU = (radio_float_t*)0; + pObj->pP_last = (uint32_t*)0; + pObj->pU_last = (radio_float_t*)0; +} + +// Sliding Min/Max based on MAXLIST-Algorithm +// "AN EFFICIENT ALGORITHM FOR RUNNING MAX MIN CALCULATION", 1996, S.C. Douglas, University of Utah +// Dependeding on 'mode' this algorithm calculates either minimum (mode = -1) or maximum (mode = +1) +radio_float_t SlidingMinMaxProcess(sl_minmax_t *pObj, radio_float_t x) +{ + uint32_t m; + uint32_t i; + uint32_t j; + + x *= pObj->mode; + + m = 1; + if (pObj->pP_last[pObj->N] == pObj->L) + { + m = 0; + pObj->pU_last[pObj->N] = pObj->P; + } + + i = 0; + while (x >= pObj->pU_last[i+1]) + { + i++; + } + pObj->N = pObj->N - i + m; + + for (j=1; j < pObj->N; j++) + { + pObj->pU[j+1] = pObj->pU_last[j+i]; + pObj->pP[j+1] = pObj->pP_last[j+i] + 1; + } + pObj->pU[pObj->N+1] = pObj->P; + pObj->pU[1] = x; + pObj->pP[1] = 1; + pObj->max = pObj->pU[pObj->N]; + + i=0; + while(pObj->pU[i] != pObj->P) + { + pObj->pU_last[i] = pObj->pU[i]; + pObj->pP_last[i] = pObj->pP[i]; + i++; + } + pObj->pU_last[i] = pObj->pU[i]; + pObj->pP_last[i] = pObj->pP[i]; + + return pObj->mode*pObj->max; +} + +radio_float_t SlidingMinMaxGet(sl_minmax_t *pObj) +{ + return pObj->mode*pObj->max; +} + +void SlidingMinMaxProcessV(sl_minmax_t *pObj, radio_float_t *pX, uint32_t len) +{ + uint32_t i; + + for (i=0; i < len; i++) + { + SlidingMinMaxProcess(pObj, pX[i]); + } +} + +// -------------------------------------------------------------- +// RingBuffer and Fifo +// -------------------------------------------------------------- +void RBufInit(rbuf_t *pObj, int size) +{ + pObj->ir = 0; + pObj->iw = 0; + pObj->dist = 0; + + pObj->size = size; + pObj->pData = (radio_float_t*)malloc(size*sizeof(radio_float_t)); + memset(pObj->pData, 0, size*sizeof(radio_float_t)); +} + +void RBufFree(rbuf_t *pObj) +{ + if (pObj->pData) + free(pObj->pData); + + pObj->pData = NULL; + pObj->size = 0; +} + +void RBufPut(rbuf_t *pObj, radio_float_t x) +{ + (pObj->iw)++; + if (pObj->iw >= pObj->size) + pObj->iw = 0; + + pObj->pData[pObj->iw] = x; + pObj->dist++; + +} + +radio_float_t RBufGet(rbuf_t *pObj) +{ + radio_float_t y; + y = pObj->pData[(pObj->ir)++]; + + if (pObj->ir >= pObj->size) + pObj->ir = 0; + + pObj->dist--; + return y; +} + +radio_float_t RBufGetAfter(rbuf_t *pObj, int delay) +{ + pObj->ir = (pObj->iw-delay)%pObj->size; + if (pObj->ir < 0) + pObj->ir += pObj->size; + + pObj->dist = delay; + return pObj->pData[pObj->ir]; +} + +radio_float_t RBufGetAt(rbuf_t *pObj, int index) +{ + if (index < 0) + index = 0; + pObj->ir = (index)%pObj->size; + pObj->dist = pObj->iw-pObj->ir; + if (pObj->dist < 0) + pObj->dist += pObj->size; + + return pObj->pData[pObj->ir]; +} + +void FifoInit(fifo_t *pObj, uint32_t max_size) +{ + pObj->size_max = max_size; + pObj->size = 0; + pObj->iw = (uint32_t)0; + pObj->ir = (uint32_t)0; + + pObj->pData = (uint32_t*)malloc(max_size*sizeof(uint32_t)); + memset(pObj->pData, 0, max_size*sizeof(uint32_t)); +} + +void FifoFree(fifo_t *pObj) +{ + if (pObj->pData) + free(pObj->pData); + + pObj->pData = NULL; + pObj->size_max = 0; + pObj->size = 0; +} + +uint32_t FifoSize(fifo_t *pObj) +{ + return pObj->size; +} + +uint32_t FifoSizeMax(fifo_t *pObj) +{ + return pObj->size_max; +} + +uint32_t FifoFront(fifo_t *pObj) +{ + return pObj->pData[pObj->ir]; +} + +uint32_t FifoBack(fifo_t *pObj) +{ + return pObj->pData[pObj->iw]; +} + +void FifoPushBack(fifo_t *pObj, uint32_t item) +{ + pObj->pData[pObj->iw++] = item; + if (pObj->iw >= pObj->size_max) + pObj->iw = 0; + + if (pObj->size < pObj->size_max) + { + pObj->size++; + } + else + { + if (++pObj->ir >= pObj->size_max) + pObj->ir = 0; + } +} + +void FifoPushFront(fifo_t *pObj, uint32_t item) +{ + pObj->ir--; + if (pObj->ir >= pObj->size_max) + pObj->ir = 0; + + pObj->pData[pObj->ir] = item; + if (pObj->size < pObj->size_max) + { + pObj->size++; + } + else + { + if (--pObj->iw >= pObj->size_max) + pObj->iw = 0; + } +} + +void FifoPopBack(fifo_t *pObj) +{ + pObj->iw--; + if (pObj->iw >= pObj->size_max) + pObj->iw = 0; + + if (pObj->size > 0) + pObj->size--; +} + +void FifoPopFront(fifo_t *pObj) +{ + pObj->ir++; + if (pObj->ir >= pObj->size_max) + pObj->ir = 0; + + if (pObj->size > 0) + pObj->size--; +} + +// -------------------------------------------------------------- +// Interpolation +// -------------------------------------------------------------- +#if 0 +void FDly_Init(fdly_t *pObj, int order) +{ + pObj->Nf = order + 1; + + pObj->hf = (radio_float_t*)malloc(pObj->Nf*sizeof(radio_float_t)); + pObj->statef = (radio_float_t*)malloc(pObj->Nf*sizeof(radio_float_t)); + memset(pObj->hf, 0, pObj->Nf*sizeof(radio_float_t)); + memset(pObj->statef, 0, pObj->Nf*sizeof(radio_float_t)); +} + +void FDly_Free(fdly_t *pObj) +{ + if (pObj->hf) + free(pObj->hf); + + pObj->hf = NULL; + + if (pObj->statef) + free(pObj->statef); + + pObj->statef = NULL; + +} + +radio_float_t FDly_Process(fdly_t *pObj, radio_float_t x) +{ + radio_float_t y; + + FIR(pObj->hf, pObj->statef, pObj->Nf, &x, &y, 1); + + return y; +} + +void FDly_CalcCoeff(fdly_t *pObj, radio_float_t delay) +{ + int n, k; + radio_float_t hn; + + for (n=0; n < pObj->Nf; n++) + { + hn = 1.0; + for (k=0; k < pObj->Nf; k++) + { + if (k == n) + continue; + + hn *= ((delay - (radio_float_t)k) / (radio_float_t)(n-k)); + } + pObj->hf[n] = hn; + } +} + +void LGIpInit(lgip_t *pObj, int order, int bufsize) +{ + pObj->N = order + 1; + pObj->bufsize = bufsize; + RBufInit(&pObj->rbuf, bufsize); +} + +void LGIpFree(lgip_t *pObj) +{ + RBufFree(&pObj->rbuf); + pObj->N = 0; +} + +radio_float_t LGIpProcess(lgip_t *pObj, radio_float_t x, int m, radio_float_t mu) +{ + int n, k; + radio_float_t hn, y, delay; + + RBufPut(&pObj->rbuf, x); + y = 0; + delay = 1-mu; + for (n=0; n < pObj->N; n++) + { + hn = 1.0; + for (k=0; k < pObj->N; k++) + { + if (k == n) + continue; + + hn *= ((delay - (radio_float_t)k) / (radio_float_t)(n-k)); + } + y += hn*RBufGetAt(&pObj->rbuf, pObj->bufsize/2 + m-n); + } + return y; +} + +void LGCpxIpInit(lgip_cpx_t *pObj, int order) +{ + // FIFO + pObj->N = order + 1; + pObj->w = 0; + pObj->r = 0; + pObj->L = 64*pObj->N; // Influences STR-Loop delay + + pObj->pFifo = (cpx_t*)malloc(pObj->L*sizeof(cpx_t)); + memset(pObj->pFifo, 0, pObj->L*sizeof(cpx_t)); + +} + +void LGCpxIpFree(lgip_cpx_t *pObj) +{ + free(pObj->pFifo); + pObj->pFifo = NULL; + pObj->N = 0; +} + +cpx_t LGCpxIpProcess(lgip_cpx_t *pObj, cpx_t x, int m, radio_float_t mu) +{ + uint32_t i, j, k, N, L, r; + radio_float_t h; + cpx_t y; + + L = pObj->L; + N = pObj->N; + + pObj->pFifo[pObj->w++] = x; + if (pObj->w == L) + pObj->w = 0; + + r = (m-N) % L; + + k = 0; + + y.real = 0.0; + y.imag = 0.0; + for (i=0; i < pObj->N; i++) + { + h = 1.0; + for (j=0; j < pObj->N; j++) + { + if (i == j) + continue; + + h *= (((radio_float_t)pObj->N/2 + mu - (radio_float_t)j - (radio_float_t)0.5) / (radio_float_t)(i-j)); + } + y.real += pObj->pFifo[r].real * h; + y.imag += pObj->pFifo[r].imag * h; + r = (r+1) % L; + } + return y; +} + +radio_float_t PolyPhaseSRRCInit(fir_pp_t *pObj, radio_float_t fa, radio_float_t tsym, radio_float_t alpha, uint32_t N, uint32_t M) +{ + uint32_t i, j; + fir_float_t *pCoeff; + radio_float_t k; + + pCoeff = (fir_float_t*)malloc((N+1)*M*sizeof(fir_float_t)); + memset(pCoeff, 0, M*(N+1)*sizeof(fir_float_t)); + + k = CalcFirSRRC(pCoeff, M*fa, tsym, alpha, M*N); + + pObj->ppCoeff = (fir_float_t**)malloc(M*sizeof(fir_float_t*)); + for(i=0; i < M; i++) + { + pObj->ppCoeff[i] = (fir_float_t*)malloc(N*sizeof(fir_float_t)); + memset(pObj->ppCoeff[i], 0, N*sizeof(fir_float_t)); + } + pObj->pState = (fir_float_t*)malloc(N*sizeof(fir_float_t)); + memset(pObj->pState, 0, N*sizeof(fir_float_t)); + + for(i=0; i < M; i++) + { + for(j=0; j < N; j++) + { + pObj->ppCoeff[i][j] = M*pCoeff[M*j+M/2+i]; + } + } + + pObj->M = M; + pObj->N = N; + + free(pCoeff); + + return k/M; +} + +void PolyPhaseSRRCFree(fir_pp_t *pObj) +{ + uint32_t i; + + for(i=0; i < pObj->M; i++) + { + free(pObj->ppCoeff[i]); + } + free(pObj->ppCoeff); + pObj->ppCoeff = NULL; + + free(pObj->pState); + pObj->pState = NULL; + +} + +uint32_t PolyPhaseSRRCProcess(fir_pp_t *pObj, radio_float_t mu, radio_float_t *pX, radio_float_t *pY, uint32_t len) +{ + uint32_t m; + +// m = (pObj->M/2 + (int)(mu * pObj->M/2)) % pObj->M; + m = (int)dmod(mu*pObj->M, (radio_float_t)pObj->M); + + FIR(pObj->ppCoeff[m], pObj->pState, pObj->N, pX, pY, len); + + return len; +} + +// -------------------------------------------------------------- +radio_float_t PolyPhaseIpInit(ppip_t *pObj, radio_float_t fa, radio_float_t tsym, radio_float_t alpha, uint32_t N, uint32_t M) +{ + uint32_t i, j; + fir_float_t *pCoeff; + radio_float_t k; + + pCoeff = (fir_float_t*)malloc((N+1)*M*sizeof(fir_float_t)); + memset(pCoeff, 0, (N+1)*M*sizeof(fir_float_t)); + + k = CalcFirSRRC(pCoeff, M*fa, tsym, alpha, N*M); + + pObj->ppCoeff = (fir_float_t**)malloc(M*sizeof(fir_float_t*)); + for(i=0; i < M; i++) + { + pObj->ppCoeff[i] = (fir_float_t*)malloc(N*sizeof(fir_float_t)); + memset(pObj->ppCoeff[i], 0, N*sizeof(fir_float_t)); + } + for(i=0; i < M; i++) + { + for(j=0; j < N; j++) + { + pObj->ppCoeff[i][j] = M*pCoeff[M*j+M/2+i]; + } + } + pObj->pState = (fir_float_t*)malloc(N*sizeof(fir_float_t)); + memset(pObj->pState, 0, N*sizeof(fir_float_t)); + + pObj->M = M; + pObj->N = N; + + RBufInit(&pObj->rbuf, 2*N); // Influences STR-Loop delay + + free(pCoeff); + + return k/M; + +} + +void PolyPhaseIpFree(ppip_t *pObj) +{ + uint32_t i; + + for(i=0; i < pObj->M; i++) + { + free(pObj->ppCoeff[i]); + } + free(pObj->ppCoeff); + pObj->ppCoeff = NULL; + + free(pObj->pState); + pObj->pState = NULL; + + RBufFree(&pObj->rbuf); + +} + +radio_float_t PolyPhaseIpProcess(ppip_t *pObj, radio_float_t x, int m, radio_float_t mu) +{ + uint32_t index, i; + radio_float_t y; + + index = (int)dmod(mu*pObj->M, (radio_float_t)pObj->M); + + for(i=0; i < pObj->N; i++) + { + pObj->pState[i] = RBufGetAt(&pObj->rbuf, m-i); + } + + FIR(pObj->ppCoeff[index], pObj->pState, pObj->N, &x, &y, 1); + RBufPut(&pObj->rbuf, x); + + return y; +} + +void FirCpxInit(fir_cpx_t *pObj, uint32_t N) +{ + pObj->pX = (cpx_t*)malloc(N*sizeof(cpx_t)); + memset(pObj->pX, 0, N*sizeof(cpx_t)); + pObj->N = N; + pObj->r = 0; + pObj->w = 0; +} + +void FirCpxFree(fir_cpx_t *pObj) +{ + free(pObj->pX); +} + +void FirCpxProcessReal(fir_cpx_t *pObj, radio_float_t *pW, cpx_t *pSrc, cpx_t *pDst, uint32_t downSampleFactor, uint32_t len) +{ + + uint32_t i, j, w, r, N, k; + + w = pObj->w; + r = pObj->r; + N = pObj->N; + + for (i=0; i < len/downSampleFactor; i++) + { + + for (k=0; k < downSampleFactor; k++) + { + pObj->pX[w++] = pSrc[i*downSampleFactor + k]; + if (w >= N) + w = 0; + } + pDst[i].real = pDst[i].imag = 0; + for (j=0; j < N; j++) + { + + pDst[i].real += pObj->pX[r].real * pW[j]; + pDst[i].imag += pObj->pX[r].imag * pW[j]; + + r--; + if (r >= N) + r = N-1; + + } + for (k=0; k < downSampleFactor; k++) + { + r++; + if (r >= N) + r = 0; + } + } + pObj->r = r; + pObj->w = w; +} + +void FirCpxProcessComplex(fir_cpx_t *pObj, cpx_t *pW, cpx_t *pSrc, cpx_t *pDst, uint32_t len) +{ + (void)pObj; + (void)pW; + (void)pSrc; + (void)pDst; + (void)len; +} + +// -------------------------------------------------------------- +radio_float_t PolyPhaseCpxIpInit(ppip_cpx_t *pObj, radio_float_t fa, radio_float_t tsym, radio_float_t alpha, uint32_t N, uint32_t M) +{ + uint32_t i, j; + fir_float_t *pCoeff; + radio_float_t k; + + // Calculate polyphase filter + pCoeff = (fir_float_t*)malloc((N+1)*M*sizeof(fir_float_t)); + memset(pCoeff, 0, (N+1)*M*sizeof(fir_float_t)); + + k = CalcFirSRRC(pCoeff, M*fa, tsym, alpha, N*M); + CalcKaiser(pCoeff, pCoeff, (radio_float_t)2.4, N*M); + + pObj->ppCoeff = (fir_float_t**)malloc(M*sizeof(fir_float_t*)); + for(i=0; i < M; i++) + { + pObj->ppCoeff[i] = (fir_float_t*)malloc(N*sizeof(fir_float_t)); + memset(pObj->ppCoeff[i], 0, N*sizeof(fir_float_t)); + } + for(i=0; i < M; i++) + { + for(j=0; j < N; j++) + { + pObj->ppCoeff[i][j] = M*pCoeff[M*j+M/2+i]; + } + } + + // FIFO + pObj->w = 0; + pObj->r = 0; + pObj->L = 2*N; // Influences STR-Loop delay + + pObj->pFifo = (cpx_t*)malloc(pObj->L*sizeof(cpx_t)); + memset(pObj->pFifo, 0, pObj->L*sizeof(cpx_t)); + + pObj->M = M; + pObj->N = N; + + free(pCoeff); + + return k/M; + +} + +void PolyPhaseCpxIpFree(ppip_cpx_t *pObj) +{ + uint32_t i; + + for(i=0; i < pObj->M; i++) + { + free(pObj->ppCoeff[i]); + } + free(pObj->ppCoeff); + pObj->ppCoeff = NULL; + + free(pObj->pFifo); + pObj->pFifo = NULL; + +} + +cpx_t PolyPhaseCpxIpProcess(ppip_cpx_t *pObj, cpx_t x, INT32 m, radio_float_t mu) +{ + uint32_t index, j, N, L, r; + radio_float_t *pW; + cpx_t y; + int i; + + index = (uint32_t)dmod(mu*pObj->M, (radio_float_t)pObj->M); + + pW = pObj->ppCoeff[index]; + + L = pObj->L; + N = pObj->N; + + r = m % L; + + pObj->pFifo[pObj->w++] = x; + if (pObj->w == L) + pObj->w = 0; + + + y.real = pObj->pFifo[r].real * pW[0]; + y.imag = pObj->pFifo[r].imag * pW[0]; + + for (j=1; j < N; j++) + { + + i = (int)m - j; + if (i < 0) + { + i = 0; + } + + r = i % L; + + y.real += pObj->pFifo[r].real * pW[j]; + y.imag += pObj->pFifo[r].imag * pW[j]; + + } + + return y; +} + +void FarrowPPIPCpxInit(ppip_farrow_cpx_t *pObj, uint32_t M, uint32_t N) +{ + uint32_t i; + + pObj->ppCoeff = (fir_float_t**)malloc(M*sizeof(fir_float_t*)); + for(i=0; i < M; i++) + { + pObj->ppCoeff[i] = (fir_float_t*)malloc(N*sizeof(fir_float_t)); + memset(pObj->ppCoeff[i], 0, N*sizeof(fir_float_t)); + } + pObj->M = M; + pObj->N = N; + pObj->pH = (cpx_t*)malloc(M*sizeof(cpx_t)); + pObj->pB = (cpx_t*)malloc(M*sizeof(cpx_t)); + + pObj->w = 0; + pObj->r = 0; + pObj->L = 2*N; // Influences STR-Loop delay + + pObj->pFifo = (cpx_t*)malloc(pObj->L*sizeof(cpx_t)); + memset(pObj->pFifo, 0, pObj->L*sizeof(cpx_t)); + + +} + +void FarrowPPIPCpxFree(ppip_farrow_cpx_t *pObj) +{ + uint32_t i; + + for(i=0; i < pObj->M; i++) + { + free(pObj->ppCoeff[i]); + } + free(pObj->ppCoeff); + pObj->ppCoeff = NULL; + + free(pObj->pH); + + free(pObj->pFifo); + pObj->pFifo = NULL; + +} + +cpx_t horner(cpx_t *a, cpx_t *b, uint32_t M, radio_float_t mu) +{ + uint32_t i; + + b[0] = a[0]; + for (i=1; i < M; i++) + { + b[i].real = a[i].real+mu*b[i-1].real; + b[i].imag = a[i].imag+mu*b[i-1].imag; + } + + return b[M-1]; +} + +cpx_t FarrowPPIPCpxProcess(ppip_farrow_cpx_t *pObj, cpx_t x, INT32 m, radio_float_t mu) +{ + INT32 i; + uint32_t n, j, N, L, r; + cpx_t y; + + L = pObj->L; + N = pObj->N; + + pObj->pFifo[pObj->w++] = x; + if (pObj->w == L) + pObj->w = 0; + + + // Partial filter responses + for (n=0; n < pObj->M; n++) + { + r = (uint32_t)m % L; + + j=0; + pObj->pH[n].real = pObj->pFifo[r].real * pObj->ppCoeff[n][j]; + pObj->pH[n].imag = pObj->pFifo[r].imag * pObj->ppCoeff[n][j]; + j++; + for (; j < N; j++) + { + + i = (INT32)m - j; + if (i < 0) + i = 0; + + r = i % L; + + pObj->pH[n].real += pObj->pFifo[r].real * pObj->ppCoeff[n][j]; + pObj->pH[n].imag += pObj->pFifo[r].imag * pObj->ppCoeff[n][j]; + + } + } + + // Combine + y = horner(pObj->pH, pObj->pB, pObj->M, mu); + + return y; +} + +#endif + +// -------------------------------------------------------------- +// Data functions +// -------------------------------------------------------------- +uint32_t Scramble(uint8_t *pSrcDst, uint32_t state, uint32_t poly, uint32_t len) +{ + int i; + + while(len) + { + *pSrcDst ^= (uint8_t)state; + pSrcDst++; + len--; + + for (i=0; i < 8; i++) + { + if (state & 0x0001) + state = (state >> 1) ^ poly; + else + state = (state >> 1); + } + + } + return state; +} + +// -------------------------------------------------------------- +uint32_t FrameCalcNumStreamBytes(uint32_t len_raw) +{ + uint32_t len, num_frames; + num_frames = (int)ceil((float)len_raw / FRAME_NUM_BYTES_PER_FRAME); + len = num_frames*sizeof(frame_t); + + if (len < sizeof(frame_t)) + len = sizeof(frame_t); + + return len; +} + +// -------------------------------------------------------------- +uint32_t FrameFormat(uint8_t *pRaw, uint8_t *pFormatted, uint32_t len_raw, uint32_t *pPrn_state, uint16_t frame_type) +{ + frame_t frame; + + uint32_t bytes_remain, len_formatted, len; + uint32_t prn_state; + + if (len_raw == 0) + return 0; + + prn_state = *pPrn_state; + + // Set preamble + frame.hdr.preamble[0] = FRAME_PREAMBLE_IV; + frame.hdr.preamble[1] = ~(frame.hdr.preamble[0]); + + bytes_remain = len_raw; + len_formatted = 0; + while(bytes_remain) + { + len = FRAME_NUM_BYTES_PER_FRAME; + if (bytes_remain < FRAME_NUM_BYTES_PER_FRAME) + len = bytes_remain; + + memset(frame.data, 0, FRAME_NUM_BYTES_PER_FRAME); + memcpy(frame.data, pRaw, len); + frame.hdr.crc16 = Crc16(FRAME_CRC16_POLY, FRAME_CRC16_IV, frame.data, FRAME_NUM_BYTES_PER_FRAME); + frame.hdr.type = frame_type; + frame.hdr.prn_state = prn_state; + frame.hdr.length = (uint16_t)len; + prn_state = Scramble(frame.data, prn_state, FRAME_SCRAMBLER_POLY, FRAME_NUM_BYTES_PER_FRAME); + prn_state = Scramble((uint8_t*)&frame.hdr.crc16, prn_state, FRAME_SCRAMBLER_POLY, sizeof(frame.hdr.crc16)); + prn_state = Scramble((uint8_t*)&frame.hdr.type, prn_state, FRAME_SCRAMBLER_POLY, sizeof(frame.hdr.type)); + prn_state = Scramble((uint8_t*)&frame.hdr.length, prn_state, FRAME_SCRAMBLER_POLY, sizeof(frame.hdr.length)); + + pRaw += len; + bytes_remain -= len; + + memcpy(pFormatted, &frame, sizeof(frame_t)); + pFormatted += sizeof(frame_t); + len_formatted += sizeof(frame_t); + + } + *pPrn_state = prn_state; + return len_formatted; +} + +// -------------------------------------------------------------- +uint32_t FrameDeformat(uint8_t *pFormatted, uint8_t *pRaw, uint32_t len_formatted, uint16_t frame_type_mask) +{ + frame_hdr_t hdr; + uint32_t bytes_remain, len_raw, sync_state, frame_sync, i; + uint16_t crc16_ist; + uint8_t temp[FRAME_NUM_BYTES_PER_FRAME]; + uint32_t prn_state; + + if (len_formatted == 0) + return 0; + + i = 0; + bytes_remain = len_formatted; + len_raw = 0; + while(bytes_remain) + { + + sync_state = 0; + do + { + // Find frame boundaries + switch(sync_state) + { + case 0: + if (pFormatted[i] == FRAME_PREAMBLE_IV) + { + sync_state = 1; + } + break; + + case 1: + if ((uint8_t)(~pFormatted[i]) == pFormatted[i-1]) + { + sync_state = 2; + } + else + { + sync_state = 0; + } + break; + } + i++; + bytes_remain--; + frame_sync = (sync_state == 2); + + } while(bytes_remain && !frame_sync); + + memcpy(&hdr, &pFormatted[i-2], sizeof(frame_hdr_t)); + memcpy(temp, &pFormatted[i-2+sizeof(frame_hdr_t)], FRAME_NUM_BYTES_PER_FRAME); + + prn_state = Scramble(temp, hdr.prn_state, FRAME_SCRAMBLER_POLY, FRAME_NUM_BYTES_PER_FRAME); + prn_state = Scramble((uint8_t*)&hdr.crc16, prn_state, FRAME_SCRAMBLER_POLY, sizeof(hdr.crc16)); + prn_state = Scramble((uint8_t*)&hdr.type, prn_state, FRAME_SCRAMBLER_POLY, sizeof(hdr.type)); + Scramble((uint8_t*)&hdr.length, prn_state, FRAME_SCRAMBLER_POLY, sizeof(hdr.length)); + + crc16_ist = Crc16(FRAME_CRC16_POLY, FRAME_CRC16_IV, temp, FRAME_NUM_BYTES_PER_FRAME); + + if (crc16_ist == hdr.crc16) + { + + if ((hdr.type & frame_type_mask) == frame_type_mask) + { + memcpy(&pRaw[len_raw], temp, hdr.length); + len_raw += hdr.length; + } + i += FRAME_NUM_BYTES_PER_FRAME + sizeof(frame_hdr_t) - 2; + bytes_remain -= (FRAME_NUM_BYTES_PER_FRAME + sizeof(frame_hdr_t) - 2); + } + + if ((int)bytes_remain < sizeof(frame_t)) + bytes_remain = 0; + } + return len_raw; +} + +// -------------------------------------------------------------- +// Transmission order MSB first +uint32_t FrameSerialize(uint8_t *pSrc, uint8_t *pDst, uint32_t nBitsPerSym, uint32_t srclen) +{ + + uint32_t bits_remain, i, j; + uint8_t src, dst; + + if (srclen == 0) + return 0; + + if (nBitsPerSym > 8) + return (uint32_t)-1; + + j = 0; + src = *pSrc; + bits_remain = 8; + while(srclen) + { + dst = 0; + for (i=0; i < nBitsPerSym; i++) + { + dst <<= 1; + dst |= (0x01 & (src >> 7)); + src <<= 1; + + bits_remain--; + if (bits_remain == 0) + { + pSrc++; + bits_remain = 8; + src = *pSrc; + srclen--; + } + + } + pDst[j++] = dst; + } + return j; +} + +// -------------------------------------------------------------- +uint32_t FrameDeSerialize(uint8_t *pSrc, uint8_t *pDst, uint32_t nBitsPerSym, uint32_t srclen, uint16_t frame_type_mask) +{ + + uint32_t size, err, bits_remain, i, j, byte_sync, srcRemain, bitStart, numCorrupt; + uint8_t src, dst, *pBitStart; + uint16_t dst16, t; + uint8_t frame[sizeof(frame_t)], data[FRAME_NUM_BYTES_PER_FRAME]; + + if (srclen == 0) + return 0; + + if (nBitsPerSym > 8) + return (uint32_t)-1; + + src = *pSrc; + + bits_remain = nBitsPerSym; + bitStart = bits_remain; + pBitStart = pSrc; + numCorrupt = 0; + + t = (FRAME_PREAMBLE_IV << 8) | (0xFF & ~FRAME_PREAMBLE_IV); + size = 0; + do + { + j = 0; + dst16 = 0; + byte_sync = 0; + do + { + bits_remain--; + dst16 <<= 1; + dst16 |= (0x01 & (src >> (bits_remain))); + + if (bits_remain == 0) + { + pSrc++; + bits_remain = nBitsPerSym; + src = *pSrc; + srclen--; + if (!srclen) + break; + } + + // Find frame boundaries + if (dst16 == t) + { + pBitStart = pSrc; + bitStart = bits_remain; + srcRemain = srclen; + byte_sync = 1; + frame[j++] = 0xFF & (t >> 8); + frame[j++] = 0xFF & t; + + } + + } while(srclen && !byte_sync); + if (!srclen) + break; + + for(j; j < sizeof(frame_t); j++) + { + dst = 0; + for (i=0; i < 8; i++) + { + bits_remain--; + dst <<= 1; + dst |= (0x01 & (src >> (bits_remain))); + + if (bits_remain == 0) + { + pSrc++; + bits_remain = nBitsPerSym; + src = *pSrc; + srclen--; + if (!srclen) + break; + } + + } + frame[j] = dst; + if (!srclen) + break; + + } + if (!srclen) + break; + + err = FrameDeformat(frame, data, sizeof(frame_t), frame_type_mask); + if (err > 0) + { + memcpy(&pDst[size], frame, sizeof(frame_t)); + size += sizeof(frame_t); + + } + else + { + if (size > 0) + numCorrupt++; + bits_remain = bitStart; + pSrc = pBitStart; + srclen = srcRemain; + } + + } while(srclen); + + printf("Number of corrupted frames = %d\n", numCorrupt); + return size; +} + +// -------------------------------------------------------------- +// Differential M-PSK symbol mapping +uint32_t FrameSymbolsMap(uint8_t *pBits, cpx_t *pSym, uint32_t nBitsPerSym, uint32_t num_syms, uint32_t type) +{ + uint32_t i; + sym_map_t sym_mapper; + + if (num_syms == 0) + return 0; + + SymMapInit(&sym_mapper, nBitsPerSym, type); + + for(i=0; i < num_syms; i++) + { + pSym[i] = SymMapEncode(&sym_mapper, pBits[i]); + } + + return num_syms; +} + +// -------------------------------------------------------------- +// Differential M-PSK symbol de-mapping +uint32_t FrameSymbolsDemap(cpx_t *pSym, uint8_t *pBits, uint32_t nBitsPerSym, uint32_t num_syms, uint32_t type) +{ + uint32_t i; + sym_map_t sym_demapper; + sym_err_t sym_err; + + if (num_syms == 0) + return 0; + + memset(&sym_err, 0, sizeof(sym_err_t)); + + SymMapInit(&sym_demapper, nBitsPerSym, type); + + for(i=0; i < num_syms; i++) + { + pBits[i] = SymMapDecode(&sym_demapper, pSym[i], &sym_err); + } + + return num_syms; +} + +// -------------------------------------------------------------- +// Symbol +// -------------------------------------------------------------- +void SymErrInit(sym_err_t *pObj) +{ + memset(pObj, 0, sizeof(sym_err_t)); +} + +// -------------------------------------------------------------- +void SymStatInit(sym_stat_t *pObj, uint32_t nBitsPerSym) +{ + uint32_t i; + + memset(pObj, 0, sizeof(sym_stat_t)); + + pObj->num_const = 1; + for(i=0; i < nBitsPerSym; i++) + { + pObj->num_const *= 2; + } + + pObj->pPerSymStat = (per_sym_stat_t*)malloc(pObj->num_const*sizeof(per_sym_stat_t)); + + for(i=0; i < pObj->num_const; i++) + { + pObj->pPerSymStat[i].count = 0; + pObj->pPerSymStat[i].var_err_mag = 0; + pObj->pPerSymStat[i].var_err_phi = 0; + SlidingVarInit(&pObj->pPerSymStat[i].sl_err_mag, 1000, 1000); + SlidingVarInit(&pObj->pPerSymStat[i].sl_err_phi, 1000, 1000); + } + +} + +void SymStatFree(sym_stat_t *pObj) +{ + if(pObj->pPerSymStat) + free(pObj->pPerSymStat); +} + +void SymStatUpDate(sym_stat_t *pObj, uint8_t sym, sym_err_t *pSym_err) +{ + // Statistics + pObj->sym_cnt++; + pObj->pPerSymStat[sym].count++; + pObj->pPerSymStat[sym].p = (radio_float_t)pObj->pPerSymStat[sym].count/pObj->sym_cnt; + pObj->pPerSymStat[sym].var_err_mag = SlidingVarProcess(&pObj->pPerSymStat[sym].sl_err_mag, pSym_err->err_mag); + pObj->pPerSymStat[sym].var_err_phi = SlidingVarProcess(&pObj->pPerSymStat[sym].sl_err_phi, pSym_err->err_phi); + +} + +void SymStatPrint(sym_stat_t *pObj) +{ + uint32_t i; + + printf("Number of constellations : %d\n", pObj->num_const); + printf("Number of total symbols : %d\n", pObj->sym_cnt); + printf("Sym#\tOccur.\t\tProb.\t\tVar(MagErr)[dB]\tVar(PhiErr/PI)[dB]\n"); + for(i=0; i < pObj->num_const; i++) + { + printf("%4.1d\t%6.d\t\t%1.2g\t\t%.2f\t\t%.2f\n", + i, + pObj->pPerSymStat[i].count, + pObj->pPerSymStat[i].p, + 10*log10(pObj->pPerSymStat[i].var_err_mag), + 10*log10(pObj->pPerSymStat[i].var_err_phi/(PI*PI))); + } +} +// -------------------------------------------------------------- +// Symbol demapper for receiver works on each symbol +// -------------------------------------------------------------- +void SymMapInit(sym_map_t *pObj, uint32_t nBitsPerSym, uint32_t type) +{ + cpx_t iq; + uint32_t i, j, k, m, n, u, Ns, Nq, Nsq, map_idx_i, map_idx_q; + radio_float_t phi, dphi, ii, qq, iii, qqq, temp, stepIQ; + radio_float_t mag, sum2, sum4; + int signI[4] = {+1, -1, -1, +1}; + int signQ[4] = {+1, +1, -1, -1}; + int even; + pObj->mask = 0; + pObj->nBitsPerSym = nBitsPerSym; + pObj->num_const = 1; + pObj->type = type; + pObj->iq_step = 0; + pObj->iq_max = 0; + pObj->Pref = 0; + + for(k=0; k < nBitsPerSym; k++) + { + pObj->num_const *= 2; + pObj->mask <<= 1; + pObj->mask |= 1; + } + pObj->pMapTbl = (map_t*)malloc(pObj->num_const*sizeof(map_t)); + pObj->ppMapTbl = NULL; + + Ns = (uint32_t)sqrt(pObj->num_const); + Nq = pObj->num_const/4; + Nsq = (uint32_t)sqrt(Nq); + stepIQ = (radio_float_t)sqrt(2.0)/(Ns-1); + sum2 = sum4 = 0; + switch(type) + { + + case MAP_MODE_PSK: + + pObj->Es = 1.0; // Symbol transmit power + pObj->Eb = pObj->Es/nBitsPerSym; + pObj->Pref = (radio_float_t)(1.0/sqrt(2.0)); + + dphi = 2*(radio_float_t)PI/pObj->num_const; + phi = (radio_float_t)PI/pObj->num_const; + + for (k=0; k < pObj->num_const; k++) + { + iq.real = (radio_float_t)cos(phi); + iq.imag = (radio_float_t)sin(phi); + pObj->pMapTbl[k].phi = (radio_float_t)CpxPhiS(iq); + pObj->pMapTbl[k].mag = (radio_float_t)CpxMagS(iq); + pObj->pMapTbl[k].rect = iq; + phi += dphi; + } + break; + + case MAP_MODE_QAM: + pObj->Es = (radio_float_t)0.5*stepIQ*stepIQ; + pObj->Eb = pObj->Es/nBitsPerSym; + pObj->ppMapTbl = (map_t**)malloc(Ns*sizeof(map_t*)); + for (i=0; i< Ns; i++) + pObj->ppMapTbl[i] = (map_t*)malloc(Ns*sizeof(map_t)); + + ii = (radio_float_t)(1.0/sqrt(2.0)); + pObj->iq_max = ii; + qq = ii; + even = 1; + + k = 0; + for (m=0; m < Nsq; m++) + { + for (n=0; n < Nsq; n++) + { + iii = ii; + qqq = qq; + for (j=0; j < 4; j++) + { + u = Nq*j+k; + iq.real = iii*signI[j]; + iq.imag = qqq*signQ[j]; + mag = (radio_float_t)CpxMagS(iq); + phi = (radio_float_t)CpxPhiS(iq); + pObj->pMapTbl[u].mag = mag; + pObj->pMapTbl[u].phi = phi; + pObj->pMapTbl[u].rect = iq; + sum2 += mag*mag; + sum4 += mag*mag*mag*mag; + temp = iii; + iii = qqq; + qqq = temp; + map_idx_i = (int)(0.5 +(0.5*iq.real/pObj->iq_max + 0.5)*(Ns-1)); + map_idx_q = (int)(0.5 +(0.5*iq.imag/pObj->iq_max + 0.5)*(Ns-1)); + pObj->ppMapTbl[map_idx_i][map_idx_q].mag = mag; + pObj->ppMapTbl[map_idx_i][map_idx_q].phi = phi; + pObj->ppMapTbl[map_idx_i][map_idx_q].rect = iq; + pObj->ppMapTbl[map_idx_i][map_idx_q].sym = u; + } + ii = ii - even*stepIQ; + k++; + } + qq = qq - stepIQ; + ii = ii + even*stepIQ; + even = -even; + } + + switch(pObj->num_const) + { + // QPSK + case 4: + pObj->Pref = (radio_float_t)0.707; + break; + // 16-QAM + case 16: + pObj->Pref = (radio_float_t)0.385; + break; + // 64-QAM + case 64: + pObj->Pref = (radio_float_t)0.31; + break; + // 256-QAM + case 256: + pObj->Pref = (radio_float_t)0.27; + break; + default: + break; + } + break; + + default: + break; + } + pObj->iq_step = stepIQ; + pObj->iq_side_len = Ns; + sum2 /= pObj->num_const; + sum4 /= pObj->num_const; + + pObj->R2 = sum4/sum2; + pObj->R4 = sum4/(sum2*sum2); + + pObj->sym_last = 0; + +} + +// -------------------------------------------------------------- +void SymMapFree(sym_map_t *pObj) +{ + uint32_t i; + + if (pObj->pMapTbl) + { + free(pObj->pMapTbl); + pObj->pMapTbl = NULL; + } + + if (pObj->ppMapTbl) + { + for (i=0; i< (uint32_t)sqrt(pObj->num_const); i++) + free(pObj->ppMapTbl[i]); + + free(pObj->ppMapTbl); + pObj->ppMapTbl = NULL; + } +} + +// -------------------------------------------------------------- +cpx_t SymMapEncode(sym_map_t *pObj, uint8_t bit) +{ + uint32_t sym; + cpx_t iq; + + // Differential encode + sym = pObj->mask & ((uint32_t)bit + pObj->sym_last); + pObj->sym_last = sym; + + iq = pObj->pMapTbl[sym].rect; + + return iq; +} + +// -------------------------------------------------------------- +uint8_t SymMapDecode2(sym_map_t *pObj, cpx_t x, sym_err_t *pSymErr) +{ + + cpx_t err; + uint32_t k; + uint32_t sym, bit; + radio_float_t dist, best_dist, min_err_mag, err_mag, mag, phi; + + mag = (radio_float_t)CpxMagS(x); + phi = (radio_float_t)CpxPhiS(x); + + best_dist = 1000; + min_err_mag = 1000; + for(k=0; k < pObj->num_const; k++) + { + err = CpxSubS(pObj->pMapTbl[k].rect, x); + err_mag = pObj->pMapTbl[k].mag - mag; + dist = err.real*err.real + err.imag*err.imag; + if (dist < best_dist) + { + best_dist = dist; +// pSymErr->err_mag = err_mag; + pSymErr->err_phi = pObj->pMapTbl[k].phi - phi; + pSymErr->err = err; + pSymErr->mag = mag; + pSymErr->phi = phi; + pSymErr->hard_sym = pObj->pMapTbl[k].rect; + sym = k; + + } + if ((radio_float_t)fabs(err_mag) < min_err_mag) + { + pSymErr->err_mag = err_mag; + pSymErr->hard_mag = pObj->pMapTbl[k].mag; + min_err_mag = (radio_float_t)fabs(err_mag); + } + + } + + // Differential decode + bit = (uint8_t)(pObj->mask & (sym - pObj->sym_last)); + pObj->sym_last = sym; + + return bit; +} + +map_t SymMapGetSymbol(sym_map_t *pObj, cpx_t x) +{ + map_t map; + uint32_t map_idx_i, map_idx_q; + radio_float_t rx_i, rx_q; + + rx_i = dclamp(x.real, -pObj->iq_max, pObj->iq_max); + rx_q = dclamp(x.imag, -pObj->iq_max, pObj->iq_max); + + map_idx_i = (int)(0.5 +(0.5*rx_i/pObj->iq_max + 0.5)*(pObj->iq_side_len-1)); + map_idx_q = (int)(0.5 +(0.5*rx_q/pObj->iq_max + 0.5)*(pObj->iq_side_len-1)); + + map = pObj->ppMapTbl[map_idx_i][map_idx_q]; + + return map; +} + +uint8_t SymMapDecode(sym_map_t *pObj, cpx_t x, sym_err_t *pSymErr) +{ + + map_t map; + uint32_t bit; + + map = SymMapGetSymbol(pObj, x); + + pSymErr->err_phi = map.phi - (radio_float_t)CpxPhiS(x); + pSymErr->err_mag = map.mag - (radio_float_t)CpxMagS(x); + pSymErr->err = CpxSubS(map.rect, x); + pSymErr->mag = CpxMagS(x); + pSymErr->phi = CpxPhiS(x); + pSymErr->soft_sym = x; + pSymErr->hard_sym = map.rect; + pSymErr->hard_mag = map.mag; + + // Differential decode + bit = (uint8_t)(pObj->mask & (map.sym - pObj->sym_last)); + pObj->sym_last = map.sym; + + return bit; +} + +// -------------------------------------------------------------- +radio_float_t SymMapGetModulus(sym_map_t *pObj, cpx_t x) +{ + + uint32_t k; + radio_float_t best_mod, min_err_mag, err_mag, mag; + + mag = (radio_float_t)CpxMagS(x); + + min_err_mag = 1000; + for(k=0; k < pObj->num_const; k++) + { + err_mag = pObj->pMapTbl[k].mag - mag; + if ((radio_float_t)fabs(err_mag) < min_err_mag) + { + best_mod = pObj->pMapTbl[k].mag; + min_err_mag = (radio_float_t)fabs(err_mag); + } + + } + return best_mod; +} +// -------------------------------------------------------------- +// Equalizer +// -------------------------------------------------------------- +#if 0 +void EQComplexInit(eq_cpx_t *pObj, uint32_t N) +{ + pObj->N = N; + pObj->pX = (cpx_t*)malloc(pObj->N*sizeof(cpx_t)); + pObj->pW = (cpx_t*)malloc(pObj->N*sizeof(cpx_t)); + memset(pObj->pX, 0, pObj->N*sizeof(cpx_t)); + memset(pObj->pW, 0, pObj->N*sizeof(cpx_t)); +} + +void EQComplexFree(eq_cpx_t *pObj) +{ + free(pObj->pX); + free(pObj->pW); +} + +cpx_t EQComplexProcess(eq_cpx_t *pObj, cpx_t x) +{ + uint32_t i; + cpx_t y, t; + + for(i=pObj->N-1; (int)i > 0; i--) + { + pObj->pX[i] = pObj->pX[i-1]; + } + + // fill M top positions with M new data + pObj->pX[i] = x; + + y.real = 0; + y.imag = 0; + for(i=0; i < pObj->N; i++) + { + t = CpxMulS(pObj->pX[i], CpxConjS(pObj->pW[i])); + y = CpxAddS(y, t); + } + return y; +} + +// -------------------------------------------------------------- +void CMAInit(cma_t *pObj, uint32_t ntaps, uint32_t nSamplesPerSym) +{ + pObj->M = nSamplesPerSym; + pObj->N = ntaps; + pObj->Px = 0; + pObj->Px_last = 0; + + EQComplexInit(&pObj->eq, pObj->N); +} + +void CMAFree(cma_t *pObj) +{ + EQComplexFree(&pObj->eq); +} + +cpx_t CMAProcess(cma_t *pObj, cpx_t x) +{ + cpx_t y; + radio_float_t x2, x1; + + y = EQComplexProcess(&pObj->eq, x); + x1 = CpxMagS(x); + x2 = CpxMagS(pObj->eq.pX[pObj->eq.N-1]); + + pObj->Px += (x1*x1 - pObj->Px_last); + pObj->Px_last = x2*x2; + + return y; +} + +// Proakis: page 698 +cpx_t CMAGodard(cpx_t sym_s_eq, radio_float_t mag_h, radio_float_t R2) +{ + cpx_t d; + radio_float_t mag_s, t; + + mag_s = CpxMagS(sym_s_eq); + + t = (radio_float_t)((mag_h + R2*mag_s - mag_s*mag_s*mag_s)/(1E-4+mag_h)); + d = CpxScaleRealS(sym_s_eq, t); + + return d; +} + +radio_float_t CMATrain(cma_t *pObj, cpx_t y, cpx_t d, radio_float_t mu) +{ + + cpx_t e; + + e = CpxSubS(d, y); + + LMSUpdateWeigths(&pObj->eq, e, mu/(1.f+pObj->Px)); + + return CpxMagS(e); +} + +// -------------------------------------------------------------- +void DFEComplexInit(dfe_cpx_t *pObj, uint32_t K) +{ + pObj->N = 2*K+1; + pObj->N_ff = K+1; + pObj->N_fb = K; + + EQComplexInit(&pObj->eq, pObj->N); + +} + +void DFEComplexFree(dfe_cpx_t *pObj) +{ + EQComplexFree(&pObj->eq); +} + +cpx_t DFEComplexProcess(dfe_cpx_t *pObj, cpx_t xs, cpx_t xh) +{ + INT32 i; + cpx_t y, t, *pW, *pX; + + pX = pObj->eq.pX; + pW = pObj->eq.pW; + + // Shift Feedback part + for(i=pObj->N-1; i > (INT32)pObj->N_ff; i--) + { + pX[i] = pX[i-1]; + } + + // put last x into buffer + pX[i] = xh; + + // Shift Feed forward part + for(i=pObj->N_ff-1; i > 0; i--) + { + pX[i] = pX[i-1]; + } + + // put current x into buffer + pX[i] = xs; + + y.real = 0; + y.imag = 0; + for(i=0; i < (INT32)pObj->N; i++) + { + t = CpxMulS(pX[i], CpxConjS(pW[i])); + y = CpxAddS(y, t); + } + return y; + +} + +void DFEAdaptLMS(dfe_cpx_t *pObj, cpx_t e, radio_float_t mu) +{ + LMSUpdateWeigths(&pObj->eq, e, mu); +} + +// -------------------------------------------------------------- +void LMSUpdateWeigths(eq_cpx_t *pObj, cpx_t e, radio_float_t mu) +{ + uint32_t i; + + for(i=0; i < pObj->N; i++) + { + pObj->pW[i] = CpxAddS(pObj->pW[i], CpxMulS(CpxScaleRealS(CpxConjS(e), mu), pObj->pX[i])); + } +} + +// -------------------------------------------------------------- +void CoeffComplexUnitAt(cpx_t *pW, uint32_t N, uint32_t dly) +{ + if (dly >= N) + dly = 0; + + memset(pW, 0, N*sizeof(cpx_t)); + pW[dly].real = 1.0; + pW[dly].imag = 0.0; +} + +void CoeffComplexConv(cpx_t *pSrc, cpx_t *pSrcDst, uint32_t N, uint32_t dly) +{ + uint32_t i, j, N2; + cpx_t *pX, *pW, t, energy = {0}; + radio_float_t energy_correct; + + N2 = N+dly; + + pX = (cpx_t*)malloc(N2*sizeof(cpx_t)); + memset(pX, 0, N2*sizeof(cpx_t)); + pW = (cpx_t*)malloc(N2*sizeof(cpx_t)); + memset(pW, 0, N2*sizeof(cpx_t)); + + CpxCopy(pSrc, pX, N); + + for(j=0; j < N; j++) + energy = CpxAddS(energy, pSrcDst[j]); + + energy_correct = (radio_float_t)(1.0/CpxMagS(energy)); + + for(i=0; i < N2; i++) + { + for(j=0; j < N; j++) + { + t = CpxMulS(pX[N-j+i-1], pSrcDst[j]); + pW[i] = CpxScaleRealS(CpxAddS(pW[i], t), energy_correct); + } + } + CpxCopy(&pW[N/2], pSrcDst, N); +} + +// -------------------------------------------------------------- +void RLSInit(rls_t *pObj, uint32_t N, uint32_t M) +{ + uint32_t i, j; + radio_float_t *pR; + + pObj->w = (radio_float_t*)malloc(N*sizeof(radio_float_t)); + memset(pObj->w, 0, N*sizeof(radio_float_t)); + pObj->w[0] = 1.0f; + + pObj->pW = (cpx_t*)malloc(N*sizeof(cpx_t)); + memset(pObj->pW, 0, N*sizeof(cpx_t)); + + pObj->z = (radio_float_t*)malloc(N*sizeof(radio_float_t)); + memset(pObj->z, 0, N*sizeof(radio_float_t)); + + pObj->x = (radio_float_t*)malloc(N*sizeof(radio_float_t)); + memset(pObj->x, 0, N*sizeof(radio_float_t)); + + pObj->pX = (cpx_t*)malloc(N*M*sizeof(cpx_t)); + memset(pObj->pX, 0, N*M*sizeof(cpx_t)); + + pObj->R = (radio_float_t*)malloc(N*N*sizeof(radio_float_t)); + memset(pObj->R, 0, N*N*sizeof(radio_float_t)); + + pObj->T = (radio_float_t*)malloc(N*N*sizeof(radio_float_t)); + memset(pObj->T, 0, N*N*sizeof(radio_float_t)); + + pObj->T2 = (radio_float_t*)malloc(N*N*sizeof(radio_float_t)); + memset(pObj->T2, 0, N*N*sizeof(radio_float_t)); + + pR = pObj->R; + for(i=0; i < N; i++) + for(j=0; j < N; j++) + pR[i+j*N] = (radio_float_t)1E6*(i==j); + + pObj->N = N; + pObj->M = M; +} + +void RLSFree(rls_t *pObj) +{ + if(pObj->w) + free(pObj->w); + + if(pObj->z) + free(pObj->z); + + if(pObj->x) + free(pObj->x); + + if(pObj->R) + free(pObj->R); + + if(pObj->T) + free(pObj->T); + + if(pObj->T2) + free(pObj->T2); +} +/* +void RLSProcess(rls_t *pObj, radio_float_t rho, radio_float_t mu, radio_float_t x, radio_float_t d, radio_float_t *pE, radio_float_t *pDD) +{ + int i, j, k, N; + radio_float_t *pR, *pX, *pZ, *pT, *pT2, v, t, rho_i; + + N = pObj->N; + + FIR(pObj->w, pObj->x, N, &x, pDD, 1); + + *pE = d - *pDD; + + // Whitening + pR = pObj->R; + pX = pObj->x; + for(i=0; i < N; i++) + { + t = 0; + for(j=0; j < N; j++) + t += pR[j*N+i] * pX[j]; + + pObj->z[i] = t; + } + + // Berechnunng der Normierungskonstante + v = rho; + for(i=0; i < N; i++) + v += pObj->x[i] * pObj->z[i]; + + v = (radio_float_t)1.0/v; + + // Normierung + for(i=0; i < N; i++) + pObj->z[i] *= v; + + + // Filter update + for(i=0; i < N; i++) + pObj->w[i] += (mu * (*pE)*pObj->z[i]); + + + // Matrix update + pZ = pObj->z; + pX = pObj->x; + pT = pObj->T; + for(i=0; i < N; i++) + { + for(j=0; j < N; j++) + pT[j*N+i] = pZ[i] * pX[j]; + } + + pT = pObj->T; + pT2 = pObj->T2; + pR = pObj->R; + + for (i=0;iN-1; j != 0; j--) + { + pObj->pX[j] = pObj->pX[j-1]; + } + pObj->pX[j].real = i; + pObj->pX[j].imag = q; + + for(j=0; j < pObj->N; j++) + { + pObj->pW[j].real = pObj->w[j]; + pObj->pW[j].imag = pObj->w[j]; + } + +/// for(j=0; j < pObj->N; j++) +// { +// t = CpxMuls(pObj->pX[M*j], CpxConjs(pObj->pW[j])); +// y = CpxAdds(y, t); +// } + + for(j=0; j < pObj->N; j++) + { + t.real = pObj->pX[j].real * pObj->pW[j].real; + t.imag = pObj->pX[j].imag * pObj->pW[j].imag; + + y = CpxAddS(y, t); + } + + for(j=0; j < pObj->N; j++) + { + pObj->x[j] = pObj->pX[j].real; + } + + return y; + +} + +radio_float_t RLSUpdate(rls_t *pObj, radio_float_t rho, radio_float_t mu, radio_float_t y, radio_float_t d) +{ + int i, j, k, N; + radio_float_t *pR, *pX, *pZ, *pT, *pT2, v, t, rho_i, e; + + N = pObj->N; + + e = d - y; + + pR = pObj->R; + pX = pObj->x; + +// for(j=0; j < pObj->N; j++) +// { +// pObj->x[j] = pObj->pX[j*pObj->M].real; +// } + + // Whitening + for(i=0; i < N; i++) + { + t = 0; + for(j=0; j < N; j++) + t += pR[j*N+i] * pX[j]; + + pObj->z[i] = t; + } + + // Berechnunng der Normierungskonstante + v = rho; + for(i=0; i < N; i++) + v += pObj->x[i] * pObj->z[i]; + + v = (radio_float_t)1.0/v; + + // Normierung + for(i=0; i < N; i++) + pObj->z[i] *= v; + + + // Filter update + for(i=0; i < N; i++) + pObj->w[i] += (mu * e * pObj->z[i]); + + + // Matrix update + pZ = pObj->z; + pX = pObj->x; + pT = pObj->T; + for(i=0; i < N; i++) + { + for(j=0; j < N; j++) + pT[j*N+i] = pZ[i] * pX[j]; + } + + pT = pObj->T; + pT2 = pObj->T2; + pR = pObj->R; + + for (i=0;i +// -------------------------------------------------------------- +// RF Types +// -------------------------------------------------------------- +#ifndef PI +#define PI 3.1415926535897932384626433832795 +#endif + +#define RADIO_POWER_EPS (1E-12) + +#define MAP_MODE_PSK 0 +#define MAP_MODE_QAM 1 +#define MAP_MODE_PIN 2 + +#ifndef radio_float_t +#define radio_float_t float +#endif + +typedef uint32_t symbol_t; +typedef uint8_t data_t; + + +// -------------------------------------------------------------- +#endif // RADIO_TYPES_H diff --git a/real.c b/real.c new file mode 100755 index 0000000..ea75a9b --- /dev/null +++ b/real.c @@ -0,0 +1,83 @@ +// -------------------------------------------------------------- +#include +#include +#include "radio_types.h" + +// -------------------------------------------------------------- +// Real Functions +// -------------------------------------------------------------- +radio_float_t dabs(radio_float_t x) +{ + if (x < 0) + return -x; + + return x; +} + +radio_float_t dsign(radio_float_t x) +{ + if (x < 0) + return -1.0; + + return 1.0; +} + +radio_float_t dmod(radio_float_t x, radio_float_t y) +{ + int xy; + + if (y == 0) + return x; + + xy = (int)floor(x/y); + + return dsign(y)*(radio_float_t)fabs(x - y*(radio_float_t)xy); +} + +radio_float_t dmax(radio_float_t x, radio_float_t y) +{ + if (x > y) + return x; + + return y; +} + +radio_float_t dmin(radio_float_t x, radio_float_t y) +{ + if (x < y) + return x; + + return y; +} + +radio_float_t dclamp(radio_float_t x, radio_float_t limit_low, radio_float_t limit_high) +{ + return dmin(dmax(x, limit_low), limit_high); +} + +radio_float_t powerDB(radio_float_t v1, radio_float_t preScale) +{ + return (radio_float_t)(10*log10(RADIO_POWER_EPS + v1*preScale)); +} + +radio_float_t dsum(radio_float_t *pSrc, int len) +{ + radio_float_t sum = 0; + + while(len--) + sum += *(pSrc++); + + return sum; +} + +radio_float_t dmean(radio_float_t *pSrc, int len) +{ + return dsum(pSrc, len)/len; +} + +radio_float_t dpow(radio_float_t base, radio_float_t exp) +{ + return (radio_float_t)pow(base, exp); +} + +// -------------------------------------------------------------- diff --git a/real.h b/real.h new file mode 100755 index 0000000..66449af --- /dev/null +++ b/real.h @@ -0,0 +1,31 @@ +// -------------------------------------------------------------- +#ifndef REAL_H +#define REAL_H + +#include "radio_types.h" + +#ifdef __cplusplus +extern "C" { +#endif +// -------------------------------------------------------------- +// Real Functions +// -------------------------------------------------------------- +// Scalar +radio_float_t dabs(radio_float_t x); +radio_float_t dsign(radio_float_t x); +radio_float_t dmod(radio_float_t x, radio_float_t y); +radio_float_t dmax(radio_float_t x, radio_float_t y); +radio_float_t dmin(radio_float_t x, radio_float_t y); +radio_float_t dclamp(radio_float_t x, radio_float_t limit_low, radio_float_t limit_high); +radio_float_t powerDB(radio_float_t v1, radio_float_t preScale); +radio_float_t dsum(radio_float_t *pSrc, int len); +radio_float_t dmean(radio_float_t *pSrc, int len); +radio_float_t dpow(radio_float_t base, radio_float_t exp); + +// -------------------------------------------------------------- +#ifdef __cplusplus +} +#endif // __cplusplus + +// -------------------------------------------------------------- +#endif // REAL_H diff --git a/ringbuf.c b/ringbuf.c new file mode 100755 index 0000000..cfb869b --- /dev/null +++ b/ringbuf.c @@ -0,0 +1,168 @@ +// -------------------------------------------------------------- +#include +#include +#include "ringbuf.h" + +// -------------------------------------------------------------- +void RBufInit(rbuf_t *pObj, uint32_t size) +{ + pObj->ir = 0; + pObj->iw = 0; + pObj->dist = 0; + + pObj->size = size; + pObj->pData = (radio_float_t*)malloc(size*sizeof(radio_float_t)); + memset(pObj->pData, 0, size*sizeof(radio_float_t)); +} + +void RBufFree(rbuf_t *pObj) +{ + if (pObj->pData) + free(pObj->pData); + + pObj->pData = NULL; + pObj->size = 0; +} + +void RBufPut(rbuf_t *pObj, radio_float_t x) +{ + (pObj->iw)++; + if (pObj->iw >= pObj->size) + pObj->iw = 0; + + pObj->pData[pObj->iw] = x; + pObj->dist++; + +} + +radio_float_t RBufGet(rbuf_t *pObj) +{ + radio_float_t y; + y = pObj->pData[(pObj->ir)++]; + + if (pObj->ir >= pObj->size) + pObj->ir = 0; + + pObj->dist--; + return y; +} + +radio_float_t RBufGetAfter(rbuf_t *pObj, int32_t delay) +{ + pObj->ir = (pObj->iw-delay)%pObj->size; + if (pObj->ir < 0) + pObj->ir += pObj->size; + + pObj->dist = delay; + return pObj->pData[pObj->ir]; +} + +radio_float_t RBufGetAt(rbuf_t *pObj, uint32_t index) +{ + if (index < 0) + index = 0; + pObj->ir = (index)%pObj->size; + pObj->dist = pObj->iw-pObj->ir; + if (pObj->dist < 0) + pObj->dist += pObj->size; + + return pObj->pData[pObj->ir]; +} + +void FifoInit(fifo_t *pObj, uint32_t max_size) +{ + pObj->size_max = max_size; + pObj->size = 0; + pObj->iw = (uint32_t)0; + pObj->ir = (uint32_t)0; + + pObj->pData = (uint32_t*)malloc(max_size*sizeof(uint32_t)); + memset(pObj->pData, 0, max_size*sizeof(uint32_t)); +} + +void FifoFree(fifo_t *pObj) +{ + if (pObj->pData) + free(pObj->pData); + + pObj->pData = NULL; + pObj->size_max = 0; + pObj->size = 0; +} + +uint32_t FifoSize(fifo_t *pObj) +{ + return pObj->size; +} + +uint32_t FifoSizeMax(fifo_t *pObj) +{ + return pObj->size_max; +} + +uint32_t FifoFront(fifo_t *pObj) +{ + return pObj->pData[pObj->ir]; +} + +uint32_t FifoBack(fifo_t *pObj) +{ + return pObj->pData[pObj->iw]; +} + +void FifoPushBack(fifo_t *pObj, uint32_t item) +{ + pObj->pData[pObj->iw++] = item; + if (pObj->iw >= pObj->size_max) + pObj->iw = 0; + + if (pObj->size < pObj->size_max) + { + pObj->size++; + } + else + { + if (++pObj->ir >= pObj->size_max) + pObj->ir = 0; + } +} + +void FifoPushFront(fifo_t *pObj, uint32_t item) +{ + pObj->ir--; + if (pObj->ir >= pObj->size_max) + pObj->ir = 0; + + pObj->pData[pObj->ir] = item; + if (pObj->size < pObj->size_max) + { + pObj->size++; + } + else + { + if (--pObj->iw >= pObj->size_max) + pObj->iw = 0; + } +} + +void FifoPopBack(fifo_t *pObj) +{ + pObj->iw--; + if (pObj->iw >= pObj->size_max) + pObj->iw = 0; + + if (pObj->size > 0) + pObj->size--; +} + +void FifoPopFront(fifo_t *pObj) +{ + pObj->ir++; + if (pObj->ir >= pObj->size_max) + pObj->ir = 0; + + if (pObj->size > 0) + pObj->size--; +} + +// -------------------------------------------------------------- diff --git a/ringbuf.h b/ringbuf.h new file mode 100755 index 0000000..f662130 --- /dev/null +++ b/ringbuf.h @@ -0,0 +1,62 @@ +// -------------------------------------------------------------- +#ifndef RINGBUF_H +#define RINGBUF_H + +#include +#include "radio_types.h" + +// -------------------------------------------------------------- +// Types +// -------------------------------------------------------------- +typedef struct _rbuf_t +{ + uint32_t size, iw, ir, dist; + radio_float_t *pData; + +} rbuf_t; + +typedef struct _fifo_t +{ + uint32_t size_max; + uint32_t size; + uint32_t ir; + uint32_t iw; + uint32_t *pData; + +} fifo_t; + +// -------------------------------------------------------------- +#ifdef __cplusplus +extern "C" { +#endif + +// -------------------------------------------------------------- +// Functions +// -------------------------------------------------------------- +// RingBuffer +void RBufInit(rbuf_t *pObj, uint32_t size); +void RBufFree(rbuf_t *pObj); +void RBufPut(rbuf_t *pObj, radio_float_t x); +radio_float_t RBufGet(rbuf_t *pObj); +radio_float_t RBufGetAfter(rbuf_t *pObj, int32_t delay); +radio_float_t RBufGetAt(rbuf_t *pObj, uint32_t index); + +// Fifo +void FifoInit(fifo_t *pObj, uint32_t max_size); +void FifoFree(fifo_t *pObj); +uint32_t FifoSize(fifo_t *pObj); +uint32_t FifoSizeMax(fifo_t *pObj); +uint32_t FifoFront(fifo_t *pObj); +uint32_t FifoBack(fifo_t *pObj); +void FifoPushBack(fifo_t *pObj, uint32_t item); +void FifoPushFront(fifo_t *pObj, uint32_t item); +void FifoPopBack(fifo_t *pObj); +void FifoPopFront(fifo_t *pObj); + +// -------------------------------------------------------------- +#ifdef __cplusplus +} +#endif // __cplusplus + +// -------------------------------------------------------------- +#endif // RINGBUF_H diff --git a/statistics.c b/statistics.c new file mode 100755 index 0000000..738cf38 --- /dev/null +++ b/statistics.c @@ -0,0 +1,245 @@ +// -------------------------------------------------------------- +#include +#include +#include "statistics.h" + +// -------------------------------------------------------------- +// Sliding Mean +// -------------------------------------------------------------- +void SlidingMeanInit(sl_mean_t *pObj, int N) +{ + RBufInit(&pObj->buf, N); + pObj->Nr = (radio_float_t)1.0/N; + pObj->mean = 0.0; + pObj->sum = 0.0; + pObj->normalize_count = N; +} + +void SlidingMeanFree(sl_mean_t *pObj) +{ + RBufFree(&pObj->buf); +} + +radio_float_t SlidingMeanProcess(sl_mean_t *pObj, radio_float_t x) +{ + uint32_t i; + radio_float_t last; + + last = RBufGetAfter(&pObj->buf, pObj->buf.size-1); + RBufPut(&pObj->buf, x); + pObj->sum += (x - last); + pObj->mean = pObj->sum*pObj->Nr; + + if (--pObj->normalize_count == 0) + { + pObj->normalize_count = pObj->buf.size; + pObj->sum = 0; + for (i=0; i < pObj->buf.size; i++) + { + pObj->sum += pObj->buf.pData[i]; + } + } + return pObj->mean; +} + +void SlidingMeanProcessV(sl_mean_t *pObj, radio_float_t *pX, uint32_t len) +{ + uint32_t i; + + for (i=0; i < len; i++) + SlidingMeanProcess(pObj, *(pX++)); +} + +radio_float_t SlidingMeanGet(sl_mean_t *pObj) +{ + return pObj->mean; +} + +// -------------------------------------------------------------- +// Sliding Variance +// -------------------------------------------------------------- +void SlidingVarInit(sl_var_t *pObj, int Npwr, int Nmean) +{ + RBufInit(&pObj->buf, Npwr); + SlidingMeanInit(&pObj->sl_mean, Nmean); + pObj->Nr = (radio_float_t)1.0/Npwr; + pObj->var = 0.0; + pObj->sum = 0.0; + pObj->normalize_count = Npwr; +} + +void SlidingVarFree(sl_var_t *pObj) +{ + RBufFree(&pObj->buf); + SlidingMeanFree(&pObj->sl_mean); +} + +radio_float_t SlidingVarProcess(sl_var_t *pObj, radio_float_t x) +{ + uint32_t i; + radio_float_t last, xm, mean, var; + + last = RBufGetAfter(&pObj->buf, pObj->buf.size-1); + mean = SlidingMeanProcess(&pObj->sl_mean, x); + xm = x - mean; + xm *= xm; + RBufPut(&pObj->buf, xm); + pObj->sum += (xm - last); + + var = pObj->sum*pObj->Nr; + if (var >= 0) + pObj->var = var; + + if (--pObj->normalize_count == 0) + { + pObj->normalize_count = pObj->buf.size; + pObj->sum = 0; + for (i=0; i < pObj->buf.size; i++) + { + pObj->sum += pObj->buf.pData[i]; + } + } + return pObj->var; +} + +void SlidingVarProcessV(sl_var_t *pObj, radio_float_t *pX, uint32_t len) +{ + uint32_t i; + + for (i=0; i < len; i++) + SlidingVarProcess(pObj, *(pX++)); +} + +radio_float_t SlidingVarGet(sl_var_t *pObj) +{ + return pObj->var; +} + +// -------------------------------------------------------------- +// Sliding Min/Max +// -------------------------------------------------------------- +void SlidingMinMaxInit(sl_minmax_t *pObj, uint32_t L, radio_float_t P, radio_float_t mode) +{ + pObj->L = L; + pObj->P = P; + pObj->N = 0; + pObj->max = 0; + pObj->mode = mode; + pObj->pP = (uint32_t*)malloc(L*sizeof(uint32_t)); + pObj->pU = (radio_float_t*)malloc(L*sizeof(radio_float_t)); + pObj->pP_last = (uint32_t*)malloc(L*sizeof(uint32_t)); + pObj->pU_last = (radio_float_t*)malloc(L*sizeof(radio_float_t)); + memset(pObj->pP, 0, L*sizeof(uint32_t)); + memset(pObj->pU, 0, L*sizeof(radio_float_t)); + memset(pObj->pP_last, 0, L*sizeof(uint32_t)); + memset(pObj->pU_last, 0, L*sizeof(radio_float_t)); + pObj->pU_last[1] = P; +} + +void SlidingMinMaxFree(sl_minmax_t *pObj) +{ + if (pObj->pP) + free(pObj->pP); + + if (pObj->pU) + free(pObj->pU); + + if (pObj->pP_last) + free(pObj->pP_last); + + if (pObj->pU_last) + free(pObj->pU_last); + + pObj->pP = (uint32_t*)0; + pObj->pU = (radio_float_t*)0; + pObj->pP_last = (uint32_t*)0; + pObj->pU_last = (radio_float_t*)0; +} + +// Sliding Min/Max based on MAXLIST-Algorithm, based on: +// "AN EFFICIENT ALGORITHM FOR RUNNING MAX MIN CALCULATION", 1996, S.C. Douglas, University of Utah +// Dependeding on 'mode' this algorithm calculates either minimum (mode = -1) or maximum (mode = +1) +radio_float_t SlidingMinMaxProcess(sl_minmax_t *pObj, radio_float_t x) +{ + uint32_t m; + uint32_t i; + uint32_t j; + + x *= pObj->mode; + + m = 1; + if (pObj->pP_last[pObj->N] == pObj->L) + { + m = 0; + pObj->pU_last[pObj->N] = pObj->P; + } + + i = 0; + while (x >= pObj->pU_last[i+1]) + { + i++; + } + pObj->N = pObj->N - i + m; + + for (j=1; j < pObj->N; j++) + { + pObj->pU[j+1] = pObj->pU_last[j+i]; + pObj->pP[j+1] = pObj->pP_last[j+i] + 1; + } + pObj->pU[pObj->N+1] = pObj->P; + pObj->pU[1] = x; + pObj->pP[1] = 1; + pObj->max = pObj->pU[pObj->N]; + + i=0; + while(pObj->pU[i] != pObj->P) + { + pObj->pU_last[i] = pObj->pU[i]; + pObj->pP_last[i] = pObj->pP[i]; + i++; + } + pObj->pU_last[i] = pObj->pU[i]; + pObj->pP_last[i] = pObj->pP[i]; + + return pObj->mode*pObj->max; +} + +radio_float_t SlidingMinMaxGet(sl_minmax_t *pObj) +{ + return pObj->mode*pObj->max; +} + +void SlidingMinMaxProcessV(sl_minmax_t *pObj, radio_float_t *pX, uint32_t len) +{ + uint32_t i; + + for (i=0; i < len; i++) + { + SlidingMinMaxProcess(pObj, pX[i]); + } +} + +// -------------------------------------------------------------- +void TraceOpen(trace_t *pObj, char *pFilename) +{ + pObj->pFile = fopen(pFilename, "w"); +} + +void TraceClose(trace_t *pObj) +{ + if (pObj->pFile) + fclose(pObj->pFile); +} + +void TracePrint(trace_t *pObj, char *fmt, ... ) +{ + + va_list a_list; + + if (!pObj->pFile) + return; + + va_start( a_list, fmt ); + + vfprintf(pObj->pFile, fmt, a_list); +} diff --git a/statistics.h b/statistics.h new file mode 100755 index 0000000..29fc290 --- /dev/null +++ b/statistics.h @@ -0,0 +1,94 @@ +// -------------------------------------------------------------- +#ifndef STATISTICS_H +#define STATISTICS_H + +#include // Trace() +#include // Trace() + +#include "radio_types.h" +#include "real.h" +#include "ringbuf.h" + +// -------------------------------------------------------------- +// Types +// -------------------------------------------------------------- +typedef struct _sl_mean_t +{ + rbuf_t buf; + uint32_t normalize_count; + radio_float_t Nr; + radio_float_t sum; + radio_float_t element_max; + radio_float_t mean; + +} sl_mean_t; + +typedef struct _sl_var_t +{ + rbuf_t buf; + uint32_t normalize_count; + radio_float_t Nr; + radio_float_t sum; + radio_float_t var; + sl_mean_t sl_mean; + +} sl_var_t; + +typedef struct _sl_minmax_t +{ + uint32_t L; + uint32_t N; + radio_float_t P; + radio_float_t *pU; + radio_float_t *pU_last; + uint32_t *pP; + uint32_t *pP_last; + radio_float_t max; + radio_float_t mode; + +} sl_minmax_t; + +#ifdef __cplusplus +extern "C" { +#endif + +// -------------------------------------------------------------- +// Functions +// -------------------------------------------------------------- +// Sliding Mean +void SlidingMeanInit(sl_mean_t *pObj, int N); +void SlidingMeanFree(sl_mean_t *pObj); +radio_float_t SlidingMeanProcess(sl_mean_t *pObj, radio_float_t x); +void SlidingMeanProcessV(sl_mean_t *pObj, radio_float_t *pX, uint32_t len); +radio_float_t SlidingMeanGet(sl_mean_t *pObj); + +// Sliding Variance +void SlidingVarInit(sl_var_t *pObj, int Npwr, int Nmean); +void SlidingVarFree(sl_var_t *pObj); +radio_float_t SlidingVarProcess(sl_var_t *pObj, radio_float_t x); +void SlidingVarProcessV(sl_var_t *pObj, radio_float_t *pX, uint32_t len); +radio_float_t SlidingVarGet(sl_var_t *pObj); + +// Sliding Min/Max +void SlidingMinMaxInit(sl_minmax_t *pObj, uint32_t L, radio_float_t P, radio_float_t mode); +void SlidingMinMaxFree(sl_minmax_t *pObj); +radio_float_t SlidingMinMaxProcess(sl_minmax_t *pObj, radio_float_t x); +void SlidingMinMaxProcessV(sl_minmax_t *pObj, radio_float_t *pX, uint32_t len); +radio_float_t SlidingMinMaxGet(sl_minmax_t *pObj); + +typedef struct _trace_t +{ + FILE *pFile; +} trace_t; + +void TraceOpen(trace_t *pObj, char *pFilename); +void TraceClose(trace_t *pObj); +void TracePrint(trace_t *pObj, char *fmt, ... ); + +// -------------------------------------------------------------- +#ifdef __cplusplus +} +#endif // __cplusplus + +// -------------------------------------------------------------- +#endif // STATISTICS_H diff --git a/symbol.c b/symbol.c new file mode 100755 index 0000000..07bfceb --- /dev/null +++ b/symbol.c @@ -0,0 +1,298 @@ +// -------------------------------------------------------------- +#include // for SymStatPrint() remove later +#include +#include +#include +#include "radio_types.h" +#include "symbol.h" + +// -------------------------------------------------------------- +// Symbol demapper for receiver works on each symbol +// -------------------------------------------------------------- +void SymMapInit(sym_map_t *pObj, uint32_t nBitsPerSym, uint32_t type) +{ + cpx_t iq; + uint32_t i, j, k, m, n, u, Ns, Nq, Nsq, map_idx_i, map_idx_q; + radio_float_t phi, dphi, ii, qq, iii, qqq, temp, stepIQ; + radio_float_t mag, E_m2, E_m2_c, E_m4; + radio_float_t c_smma; + cpx_t E_a4; + int signI[4] = {+1, -1, -1, +1}; + int signQ[4] = {+1, +1, -1, -1}; + int even; + pObj->nBitsPerSym = nBitsPerSym; + pObj->num_const = 1; + pObj->type = type; + pObj->iq_step = 0; + pObj->iq_max = 0; + pObj->Pref = 0; + E_a4 = Cpx(0,0); + c_smma = (radio_float_t)1; // Tuning constant S-MMA + for(k=0; k < nBitsPerSym; k++) + { + pObj->num_const *= 2; + } + pObj->pMapTbl = (map_t*)malloc(pObj->num_const*sizeof(map_t)); + pObj->ppMapTbl = NULL; + + Ns = (uint32_t)sqrt((radio_float_t)pObj->num_const); + Nq = pObj->num_const/4; + Nsq = (uint32_t)sqrt((radio_float_t)Nq); + stepIQ = (radio_float_t)sqrt(2.0)/(Ns-1); + E_m2_c = E_m2 = E_m4 = 0; + switch(type) + { + + case MAP_MODE_PSK: + + pObj->Es = 1.0; // Symbol transmit power + pObj->Eb = pObj->Es/nBitsPerSym; + pObj->Pref = (radio_float_t)(1.0/sqrt(2.0)); + + dphi = 2*(radio_float_t)PI/pObj->num_const; + phi = (radio_float_t)PI/pObj->num_const; + + for (k=0; k < pObj->num_const; k++) + { + iq.real = (radio_float_t)cos(phi); + iq.imag = (radio_float_t)sin(phi); + pObj->pMapTbl[k].phi = (radio_float_t)CpxPhiS(iq); + pObj->pMapTbl[k].mag = (radio_float_t)CpxMagS(iq); + pObj->pMapTbl[k].rect = iq; + phi += dphi; + } + break; + + case MAP_MODE_QAM: + pObj->Es = (radio_float_t)0.5*stepIQ*stepIQ; + pObj->Eb = pObj->Es/nBitsPerSym; + pObj->ppMapTbl = (map_t**)malloc(Ns*sizeof(map_t*)); + for (i=0; i< Ns; i++) + pObj->ppMapTbl[i] = (map_t*)malloc(Ns*sizeof(map_t)); + + ii = (radio_float_t)(1.0/sqrt(2.0)); + pObj->iq_max = ii; + qq = ii; + even = 1; + + k = 0; + for (m=0; m < Nsq; m++) + { + for (n=0; n < Nsq; n++) + { + iii = ii; + qqq = qq; + for (j=0; j < 4; j++) + { + u = Nq*j+k; + iq.real = iii*signI[j]; + iq.imag = qqq*signQ[j]; + mag = (radio_float_t)CpxMagS(iq); + phi = (radio_float_t)CpxPhiS(iq); + pObj->pMapTbl[u].mag = mag; + pObj->pMapTbl[u].phi = phi; + pObj->pMapTbl[u].rect = iq; + E_m2_c += (radio_float_t)pow(mag, 2+c_smma); + E_m2 += (radio_float_t)pow(mag, 2); + E_m4 += (radio_float_t)pow(mag, 4); + E_a4.real += (radio_float_t)pow(iq.real, 4); + E_a4.imag += (radio_float_t)pow(iq.imag, 4); + temp = iii; + iii = qqq; + qqq = temp; + map_idx_i = (int)(0.5 +(0.5*iq.real/pObj->iq_max + 0.5)*(Ns-1)); + map_idx_q = (int)(0.5 +(0.5*iq.imag/pObj->iq_max + 0.5)*(Ns-1)); + pObj->ppMapTbl[map_idx_i][map_idx_q].mag = mag; + pObj->ppMapTbl[map_idx_i][map_idx_q].phi = phi; + pObj->ppMapTbl[map_idx_i][map_idx_q].rect = iq; + pObj->ppMapTbl[map_idx_i][map_idx_q].sym = (symbol_t)u; + } + ii = ii - even*stepIQ; + k++; + } + qq = qq - stepIQ; + ii = ii + even*stepIQ; + even = -even; + } + + switch(pObj->num_const) + { + // QPSK + case 4: + pObj->Pref = (radio_float_t)0.707; + break; + // 16-QAM + case 16: + pObj->Pref = (radio_float_t)0.385; + break; + // 64-QAM + case 64: + pObj->Pref = (radio_float_t)0.31; + break; + // 256-QAM + case 256: + pObj->Pref = (radio_float_t)0.27; + break; + default: + break; + } + break; + + default: + break; + } + pObj->iq_step = stepIQ; + pObj->iq_side_len = Ns; + pObj->R2_cma = E_m4/E_m2; + pObj->R_mma.real = 2*E_a4.real/E_m2; + pObj->R_mma.imag = 2*E_a4.imag/E_m2; + pObj->R_smma.real = 2*E_a4.real/E_m2_c; + pObj->R_smma.imag = 2*E_a4.imag/E_m2_c; +} + +void SymMapFree(sym_map_t *pObj) +{ + uint32_t i; + + if (pObj->pMapTbl) + { + free(pObj->pMapTbl); + pObj->pMapTbl = NULL; + } + + if (pObj->ppMapTbl) + { + for (i=0; i< (uint32_t)sqrt((float)pObj->num_const); i++) + free(pObj->ppMapTbl[i]); + + free(pObj->ppMapTbl); + pObj->ppMapTbl = NULL; + } +} + +void SymMapReinit(sym_map_t *pObj, uint32_t nBitsPerSym, uint32_t type) +{ + SymMapFree(pObj); + SymMapInit(pObj, nBitsPerSym, type); +} + +cpx_t SymMapMap(sym_map_t *pObj, symbol_t symbol) +{ + if (symbol >= pObj->num_const) + return Cpx(0,0); + + return pObj->pMapTbl[(uint32_t)symbol].rect; +} + +symbol_t SymMapDemap(sym_map_t *pObj, cpx_t x) +{ + uint32_t map_idx_i, map_idx_q; + radio_float_t rx_i, rx_q; + + rx_i = dclamp(x.real, -pObj->iq_max, pObj->iq_max); + rx_q = dclamp(x.imag, -pObj->iq_max, pObj->iq_max); + + map_idx_i = (int)(0.5 +(0.5*rx_i/pObj->iq_max + 0.5)*(pObj->iq_side_len-1)); + map_idx_q = (int)(0.5 +(0.5*rx_q/pObj->iq_max + 0.5)*(pObj->iq_side_len-1)); + + return pObj->ppMapTbl[map_idx_i][map_idx_q].sym; +} + +map_t SymMapGetSymbolInfo(sym_map_t *pObj, symbol_t symbol) +{ + return pObj->pMapTbl[(uint32_t)symbol]; +} + +sym_err_t SymMapGetError(sym_map_t *pObj, cpx_t x, symbol_t symbol) +{ + map_t map; + sym_err_t res; + + map = SymMapGetSymbolInfo(pObj, symbol); + + res.err_mag = map.mag - (radio_float_t)CpxMagS(x); + res.err_phi = map.phi - (radio_float_t)CpxPhiS(x); + res.err = CpxSubS(map.rect, x); + res.mag = CpxMagS(x); + res.phi = CpxPhiS(x); + res.soft_sym = x; + res.hard_sym = map.rect; + res.hard_mag = map.mag; + res.hard_phi = map.phi; + + return res; + +} + +// -------------------------------------------------------------- +void SymStatInit(sym_stat_t *pObj, uint32_t nBitsPerSym) +{ + uint32_t i; + + memset(pObj, 0, sizeof(sym_stat_t)); + + pObj->num_const = 1; + for(i=0; i < nBitsPerSym; i++) + { + pObj->num_const *= 2; + } + + pObj->pPerSymStat = (per_sym_stat_t*)malloc(pObj->num_const*sizeof(per_sym_stat_t)); + + for(i=0; i < pObj->num_const; i++) + { + pObj->pPerSymStat[i].count = 0; + pObj->pPerSymStat[i].var_err_mag = 0; + pObj->pPerSymStat[i].var_err_phi = 0; + SlidingVarInit(&pObj->pPerSymStat[i].sl_err_mag, 1000, 1000); + SlidingVarInit(&pObj->pPerSymStat[i].sl_err_phi, 1000, 1000); + } + +} + +void SymStatFree(sym_stat_t *pObj) +{ + if(pObj->pPerSymStat) + free(pObj->pPerSymStat); + + pObj->pPerSymStat = 0; +} + +void SymStatReset(sym_stat_t *pObj) +{ + uint32_t i; + pObj->sym_cnt = 0; + for(i=0; i < pObj->num_const; i++) + { + pObj->pPerSymStat[i].count = 0; + } +} + +void SymStatUpDate(sym_stat_t *pObj, symbol_t sym, sym_err_t *pSym_err) +{ + // Statistics + pObj->sym_cnt++; + pObj->pPerSymStat[sym].count++; + pObj->pPerSymStat[sym].p = (radio_float_t)pObj->pPerSymStat[sym].count/pObj->sym_cnt; + pObj->pPerSymStat[sym].var_err_mag = SlidingVarProcess(&pObj->pPerSymStat[sym].sl_err_mag, pSym_err->err_mag); + pObj->pPerSymStat[sym].var_err_phi = SlidingVarProcess(&pObj->pPerSymStat[sym].sl_err_phi, pSym_err->err_phi); + +} + +void SymStatPrint(sym_stat_t *pObj) +{ + uint32_t i; + + printf("Number of constellations : %d\n", pObj->num_const); + printf("Number of total symbols : %d\n", pObj->sym_cnt); + printf("Sym#\tOccur.\t\tProb.\t\tVar(MagErr)[dB]\tVar(PhiErr/PI)[dB]\n"); + for(i=0; i < pObj->num_const; i++) + { + printf("%4.1d\t%6.d\t\t%1.2g\t\t%.2f\t\t%.2f\n", + i, + pObj->pPerSymStat[i].count, + pObj->pPerSymStat[i].p, + 10*log10(pObj->pPerSymStat[i].var_err_mag), + 10*log10(pObj->pPerSymStat[i].var_err_phi/(PI*PI))); + } +} \ No newline at end of file diff --git a/symbol.h b/symbol.h new file mode 100755 index 0000000..4a63e14 --- /dev/null +++ b/symbol.h @@ -0,0 +1,83 @@ +// -------------------------------------------------------------- +#ifndef SYMBOL_H +#define SYMBOL_H + +#include "radio_types.h" +#include "statistics.h" +#include "cpx.h" + +// -------------------------------------------------------------- +// Types +// -------------------------------------------------------------- +typedef struct _map_t +{ + radio_float_t mag, phi; + cpx_t rect; + symbol_t sym; + +} map_t; + +typedef struct _sym_map_t +{ + uint32_t nBitsPerSym, num_const, type; + radio_float_t Es, Eb, Pref; + map_t **ppMapTbl, *pMapTbl; + radio_float_t iq_step, iq_max; + uint32_t iq_side_len; + radio_float_t R2_cma; // For CMA + cpx_t R_mma; // for MMA + cpx_t R_smma; // for S-MMA + +} sym_map_t; + +typedef struct _sym_err_t +{ + radio_float_t err_mag, err_phi; + radio_float_t err_mag_norm, err_phi_norm; + radio_float_t mag, phi, hard_mag, hard_phi; + cpx_t err, hard_sym, soft_sym; + +} sym_err_t; + +typedef struct _per_sym_stat_t +{ + uint32_t count; + radio_float_t p, var_err_mag, var_err_phi; + sl_var_t sl_err_mag, sl_err_phi; + +} per_sym_stat_t; + +typedef struct _sym_stat_t +{ + uint32_t sym_cnt, num_const; + per_sym_stat_t *pPerSymStat; + + +} sym_stat_t; + +// -------------------------------------------------------------- +// Functions +// -------------------------------------------------------------- +#ifdef __cplusplus +extern "C" { +#endif + +void SymStatInit(sym_stat_t *pObj, uint32_t nBitsPerSym); +void SymStatFree(sym_stat_t *pObj); +void SymStatReset(sym_stat_t *pObj); +void SymStatUpDate(sym_stat_t *pObj, symbol_t sym, sym_err_t *pSym_err); +void SymStatPrint(sym_stat_t *pObj); + +void SymMapInit(sym_map_t *pObj, uint32_t nBitsPerSym, uint32_t type); +void SymMapFree(sym_map_t *pObj); +void SymMapReinit(sym_map_t *pObj, uint32_t nBitsPerSym, uint32_t type); +cpx_t SymMapMap(sym_map_t *pObj, symbol_t symbol); +symbol_t SymMapDemap(sym_map_t *pObj, cpx_t x); +map_t SymMapGetSymbolInfo(sym_map_t *pObj, symbol_t symbol); +sym_err_t SymMapGetError(sym_map_t *pObj, cpx_t x, symbol_t symbol); +#ifdef __cplusplus +} +#endif // __cplusplus + +// -------------------------------------------------------------- +#endif // SYMBOL_H diff --git a/synchronization.c b/synchronization.c new file mode 100755 index 0000000..970089a --- /dev/null +++ b/synchronization.c @@ -0,0 +1,224 @@ +// -------------------------------------------------------------- +#include +#include +#include "synchronization.h" + +// -------------------------------------------------------------- +// Clock generator +// -------------------------------------------------------------- +void ClockInit(clock_t *pObj, uint32_t divide) +{ + if (divide == 0) + divide = 1; + + pObj->reload = divide; + pObj->count = (int32_t)divide; +} + +uint32_t ClockIsTick(clock_t *pObj, uint32_t do_advance) +{ + uint32_t isTick; + + isTick = pObj->count == 0; + + if (do_advance) + { + if (isTick) + { + pObj->count = pObj->reload; + } + pObj->count--; + } + return isTick; +} + +void ClockAdvance(clock_t *pObj) +{ + if (pObj->count == 0) + { + pObj->count = pObj->reload; + } + pObj->count--; +} + +void ClockSetPhase(clock_t *pObj, int32_t phase) +{ + pObj->count = pObj->count - phase; + if (pObj->count <= 0) + { + pObj->count += pObj->reload; + } + else if (pObj->count > (int32_t)pObj->reload) + { + pObj->count -= pObj->reload; + } +} + +// -------------------------------------------------------------- +// Second-order Loop Filter +// -------------------------------------------------------------- +void LeadLagInit(lead_lag_filter_t *pObj, radio_float_t state) +{ + pObj->lag_state = LEAD_LAG_SCALING*state; +}; + +void LeadLagSetCoeff(lead_lag_coeff_t *pCoeff, radio_float_t lead, radio_float_t lag) +{ + pCoeff->lead = lead; + pCoeff->lag = lag; +} + +radio_float_t LeadLagProcess(lead_lag_filter_t *pObj, lead_lag_coeff_t *pCoeff, radio_float_t x) +{ + pObj->lag_state += LEAD_LAG_SCALING*pCoeff->lag * x; + + return pObj->lag_state/LEAD_LAG_SCALING + pCoeff->lead * x; +} + +radio_float_t LeadLagGetState(lead_lag_filter_t *pObj) +{ + return pObj->lag_state/LEAD_LAG_SCALING; +} + +void LeadLagSetState(lead_lag_filter_t *pObj, radio_float_t state) +{ + pObj->lag_state = LEAD_LAG_SCALING*state; +} + +// -------------------------------------------------------------- +// Gardner Timing Error Detector +// -------------------------------------------------------------- +void STRGardnerInit(str_t *pObj) +{ + memset(pObj->d, 0, sizeof(pObj->d)); +} + +radio_float_t STRGardnerProcess(str_t *pObj, cpx_t x) +{ + radio_float_t Vd; + cpx_t t, *pD; + + pD = pObj->d; + + t.real = (pD[1].real - x.real) * pD[0].real; + t.imag = (pD[1].imag - x.imag) * pD[0].imag; + Vd = (t.real + t.imag); + + // Adjust delay line + pD[1] = pD[0]; + pD[0] = x; + + return Vd; +} + +// -------------------------------------------------------------- +// Simple Phase detector for QPSK +// -------------------------------------------------------------- +radio_float_t PhaseErrQPSK(cpx_t x) +{ + radio_float_t perr; + perr = x.imag*dsign(x.real) - x.real*dsign(x.imag); + + return perr; +} + +radio_float_t PhaseErr(cpx_t x, radio_float_t pstep, radio_float_t poffset) +{ + radio_float_t perr, phi, m; + + phi = (radio_float_t)CpxPhiS(x) + poffset; + + m = dmod(phi/(radio_float_t)PI,(radio_float_t)2.0/pstep); + perr = (radio_float_t)1.0/pstep - m; + + return (radio_float_t)(PI*perr); +} + +// -------------------------------------------------------------- +void PfdInit(pfd_t *pObj) +{ + pObj->state_up = 0; + pObj->state_down = 0; +} + +radio_float_t PfdProcess(pfd_t *pObj, radio_float_t x, radio_float_t k) +{ + radio_float_t result; + + result = 0; + if (x < 0) + { + if (pObj->state_down == 0) + { + pObj->state_up = 0; + pObj->state_down = 1; + } + else + { + result = -k; + } + } + else + { + if (pObj->state_up == 0) + { + pObj->state_down = 0; + pObj->state_up = 1; + } + else + { + result = k; + } + } + + return result; +} + +// -------------------------------------------------------------- +void TimingCorrectorInit(timing_corrector_t *pObj, radio_float_t wrap_alpha) +{ + pObj->mu = 0; + pObj->mu_filtered = 0; + pObj->wrap_alpha = wrap_alpha; + pObj->wrap_beta = (radio_float_t)1.0 - wrap_alpha; + memset(pObj->skip, 0, sizeof(pObj->skip)); + memset(pObj->stuff, 0, sizeof(pObj->stuff)); +} + +radio_float_t TimingCorrectorProcess(timing_corrector_t *pObj, radio_float_t dMu) +{ + pObj->mu += dMu; + pObj->skip[1] = pObj->skip[0]; + pObj->stuff[1] = pObj->stuff[0]; + pObj->skip[0] = 0; + pObj->stuff[0] = 0; + pObj->mu_filtered = pObj->wrap_beta*pObj->mu_filtered + pObj->wrap_alpha*pObj->mu; + + if (pObj->mu_filtered < 0) + { + pObj->mu += (radio_float_t)1.0; + pObj->stuff[0] = 1; + } + else if (pObj->mu_filtered >= (radio_float_t)1.0) + { + pObj->mu -= (radio_float_t)1.0; + pObj->skip[0] = 1; + } + + return pObj->mu; +} + +radio_float_t TimingCorrectorGetMu(timing_corrector_t *pObj) +{ + return pObj->mu; +} + +uint32_t TimingCorrectorIsSkip(timing_corrector_t *pObj) +{ + return pObj->skip[0]; +} + +uint32_t TimingCorrectorIsStuff(timing_corrector_t *pObj) +{ + return pObj->stuff[0]; +} diff --git a/synchronization.h b/synchronization.h new file mode 100755 index 0000000..1aa9319 --- /dev/null +++ b/synchronization.h @@ -0,0 +1,93 @@ +// -------------------------------------------------------------- +#ifndef SYNCHRONIZATION_H +#define SYNCHRONIZATION_H + +#include "radio_types.h" +#include "nco.h" + +#define LEAD_LAG_SCALING ((radio_float_t)1024*1024) +// -------------------------------------------------------------- +// Types +// -------------------------------------------------------------- +typedef struct _clock_t +{ + uint32_t reload; + int32_t count; + +} clock_t; + +typedef struct _lead_lag_filter_t +{ + radio_float_t lag_state; + +} lead_lag_filter_t; + +typedef struct _lead_lag_coeff_t +{ + radio_float_t lead; + radio_float_t lag; + +} lead_lag_coeff_t; + +typedef struct _str_t +{ + cpx_t d[2]; + +} str_t; + +typedef struct _pfd_t +{ + uint32_t state_up; + uint32_t state_down; +} pfd_t; + +typedef struct _timing_corrector_t +{ + radio_float_t mu; + radio_float_t mu_filtered; + radio_float_t wrap_alpha; + radio_float_t wrap_beta; + uint32_t skip[2]; + uint32_t stuff[2]; + +} timing_corrector_t; + +// -------------------------------------------------------------- +// Functions +// -------------------------------------------------------------- +#ifdef __cplusplus +extern "C" { +#endif + +void ClockInit(clock_t *pObj, uint32_t divide); +uint32_t ClockIsTick(clock_t *pObj, uint32_t do_advance); +void ClockAdvance(clock_t *pObj); +void ClockSetPhase(clock_t *pObj, int32_t phase); + +void STRGardnerInit(str_t *pObj); +radio_float_t STRGardnerProcess(str_t *pObj, cpx_t x); + +radio_float_t PhaseErrQPSK(cpx_t x); +radio_float_t PhaseErr(cpx_t x, radio_float_t pstep, radio_float_t poffset); + +void PfdInit(pfd_t *pObj); +radio_float_t PfdProcess(pfd_t *pObj, radio_float_t x, radio_float_t k); + +void LeadLagInit(lead_lag_filter_t *pObj, radio_float_t state); +void LeadLagSetCoeff(lead_lag_coeff_t *pCoeff, radio_float_t lead, radio_float_t lag); +radio_float_t LeadLagProcess(lead_lag_filter_t *pObj, lead_lag_coeff_t *pCoeff, radio_float_t x); +radio_float_t LeadLagGetState(lead_lag_filter_t *pObj); +void LeadLagSetState(lead_lag_filter_t *pObj, radio_float_t state); + +void TimingCorrectorInit(timing_corrector_t *pObj, radio_float_t wrap_alpha); +radio_float_t TimingCorrectorProcess(timing_corrector_t *pObj, radio_float_t dMu); +radio_float_t TimingCorrectorGetMu(timing_corrector_t *pObj); +uint32_t TimingCorrectorIsSkip(timing_corrector_t *pObj); +uint32_t TimingCorrectorIsStuff(timing_corrector_t *pObj); + +#ifdef __cplusplus +} +#endif // __cplusplus + +// -------------------------------------------------------------- +#endif // SYNCHRONIZATION_H