From 290fd5f5e0107319f7803f6c5910fb3ea9c84559 Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Sat, 19 Jul 2014 07:44:42 +0000 Subject: [PATCH] Initial import git-svn-id: http://moon:8086/svn/software/trunk/libsrc/radio@1 b431acfa-c32f-4a4a-93f1-934dc6c82436 --- Complex.cpp.bak.cpp | 1027 ++++++++++++++++ Complex.hpp | 274 +++++ Complex.hpp.bak.hpp | 550 +++++++++ ComplexVector.cpp | 445 +++++++ ComplexVector.hpp | 192 +++ RealVector.cpp | 1182 ++++++++++++++++++ RealVector.cpp.inherit | 1089 ++++++++++++++++ RealVector.hpp | 234 ++++ RealVector.hpp.inherit | 403 ++++++ RealVector2.cpp | 785 ++++++++++++ RealVector2.hpp | 271 ++++ agc.c | 41 + agc.h | 39 + cpx.c | 591 +++++++++ cpx.h | 80 ++ equalizer.c | 498 ++++++++ equalizer.h | 96 ++ frame.c | 356 ++++++ frame.h | 61 + interpolation.c | 830 +++++++++++++ interpolation.h | 158 +++ nco.c | 118 ++ nco.h | 57 + radio.c | 2660 ++++++++++++++++++++++++++++++++++++++++ radio.h | 530 ++++++++ radio_types.h | 28 + real.c | 83 ++ real.h | 31 + ringbuf.c | 168 +++ ringbuf.h | 62 + statistics.c | 245 ++++ statistics.h | 94 ++ symbol.c | 298 +++++ symbol.h | 83 ++ synchronization.c | 224 ++++ synchronization.h | 93 ++ 36 files changed, 13976 insertions(+) create mode 100755 Complex.cpp.bak.cpp create mode 100755 Complex.hpp create mode 100755 Complex.hpp.bak.hpp create mode 100755 ComplexVector.cpp create mode 100755 ComplexVector.hpp create mode 100755 RealVector.cpp create mode 100755 RealVector.cpp.inherit create mode 100755 RealVector.hpp create mode 100755 RealVector.hpp.inherit create mode 100755 RealVector2.cpp create mode 100755 RealVector2.hpp create mode 100755 agc.c create mode 100755 agc.h create mode 100755 cpx.c create mode 100755 cpx.h create mode 100755 equalizer.c create mode 100755 equalizer.h create mode 100755 frame.c create mode 100755 frame.h create mode 100755 interpolation.c create mode 100755 interpolation.h create mode 100755 nco.c create mode 100755 nco.h create mode 100755 radio.c create mode 100755 radio.h create mode 100755 radio_types.h create mode 100755 real.c create mode 100755 real.h create mode 100755 ringbuf.c create mode 100755 ringbuf.h create mode 100755 statistics.c create mode 100755 statistics.h create mode 100755 symbol.c create mode 100755 symbol.h create mode 100755 synchronization.c create mode 100755 synchronization.h 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