summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--volk/include/volk/volk_32fc_s32f_power_32fc_a16.h18
-rw-r--r--volk/include/volk/volk_32fc_x2_conjugate_dot_prod_32fc_u.h2
-rw-r--r--volk/include/volk/volk_8ic_x2_multiply_conjugate_16ic_a16.h8
-rw-r--r--volk/include/volk/volk_8ic_x2_s32f_multiply_conjugate_32fc_a16.h8
-rw-r--r--volk/include/volk/volk_complex.h79
5 files changed, 66 insertions, 49 deletions
diff --git a/volk/include/volk/volk_32fc_s32f_power_32fc_a16.h b/volk/include/volk/volk_32fc_s32f_power_32fc_a16.h
index 90cc4f5e7..155b93ca2 100644
--- a/volk/include/volk/volk_32fc_s32f_power_32fc_a16.h
+++ b/volk/include/volk/volk_32fc_s32f_power_32fc_a16.h
@@ -3,6 +3,14 @@
#include <inttypes.h>
#include <stdio.h>
+#include <math.h>
+
+//! raise a complex float to a real float power
+static inline lv_32fc_t __volk_s32fc_s32f_power_s32fc_a16(const lv_32fc_t exp, const float power){
+ const float arg = power*atan2f(lv_creal(exp), lv_cimag(exp));
+ const float mag = powf(lv_creal(exp)*lv_creal(exp) + lv_cimag(exp)*lv_cimag(exp), power/2);
+ return mag*lv_cmake(cosf(arg), sinf(arg));
+}
#ifdef LV_HAVE_SSE
#include <xmmintrin.h>
@@ -72,11 +80,8 @@ static inline void volk_32fc_s32f_power_32fc_a16_sse(lv_32fc_t* cVector, const l
number = quarterPoints * 4;
#endif /* LV_HAVE_LIB_SIMDMATH */
- lv_32fc_t complexPower;
- ((float*)&complexPower)[0] = power;
- ((float*)&complexPower)[1] = 0;
for(;number < num_points; number++){
- *cPtr++ = lv_cpow((*aPtr++), complexPower);
+ *cPtr++ = __volk_s32fc_s32f_power_s32fc_a16((*aPtr++), power);
}
}
#endif /* LV_HAVE_SSE */
@@ -93,12 +98,9 @@ static inline void volk_32fc_s32f_power_32fc_a16_generic(lv_32fc_t* cVector, con
lv_32fc_t* cPtr = cVector;
const lv_32fc_t* aPtr = aVector;
unsigned int number = 0;
- lv_32fc_t complexPower;
- ((float*)&complexPower)[0] = power;
- ((float*)&complexPower)[1] = 0.0;
for(number = 0; number < num_points; number++){
- *cPtr++ = lv_cpow((*aPtr++), complexPower);
+ *cPtr++ = __volk_s32fc_s32f_power_s32fc_a16((*aPtr++), power);
}
}
#endif /* LV_HAVE_GENERIC */
diff --git a/volk/include/volk/volk_32fc_x2_conjugate_dot_prod_32fc_u.h b/volk/include/volk/volk_32fc_x2_conjugate_dot_prod_32fc_u.h
index 73576a766..6b22d9f81 100644
--- a/volk/include/volk/volk_32fc_x2_conjugate_dot_prod_32fc_u.h
+++ b/volk/include/volk/volk_32fc_x2_conjugate_dot_prod_32fc_u.h
@@ -131,7 +131,7 @@ static inline void volk_32fc_x2_conjugate_dot_prod_32fc_u_sse3(lv_32fc_t* result
Isum += Im;
}
- result[0] = lv_32fc_init(Rsum,Isum);
+ result[0] = lv_cmake(Rsum,Isum);
return;
}
diff --git a/volk/include/volk/volk_8ic_x2_multiply_conjugate_16ic_a16.h b/volk/include/volk/volk_8ic_x2_multiply_conjugate_16ic_a16.h
index 9e8982e9b..7307ae484 100644
--- a/volk/include/volk/volk_8ic_x2_multiply_conjugate_16ic_a16.h
+++ b/volk/include/volk/volk_8ic_x2_multiply_conjugate_16ic_a16.h
@@ -55,10 +55,10 @@ static inline void volk_8ic_x2_multiply_conjugate_16ic_a16_sse4_1(lv_16sc_t* cVe
for(; number < num_points; number++){
float aReal = (float)*a8Ptr++;
float aImag = (float)*a8Ptr++;
- lv_32fc_t aVal = lv_32fc_init(aReal, aImag );
+ lv_32fc_t aVal = lv_cmake(aReal, aImag );
float bReal = (float)*b8Ptr++;
float bImag = (float)*b8Ptr++;
- lv_32fc_t bVal = lv_32fc_init( bReal, -bImag );
+ lv_32fc_t bVal = lv_cmake( bReal, -bImag );
lv_32fc_t temp = aVal * bVal;
*c16Ptr++ = (int16_t)lv_creal(temp);
@@ -83,10 +83,10 @@ static inline void volk_8ic_x2_multiply_conjugate_16ic_a16_generic(lv_16sc_t* cV
for(number =0; number < num_points; number++){
float aReal = (float)*a8Ptr++;
float aImag = (float)*a8Ptr++;
- lv_32fc_t aVal = lv_32fc_init(aReal, aImag );
+ lv_32fc_t aVal = lv_cmake(aReal, aImag );
float bReal = (float)*b8Ptr++;
float bImag = (float)*b8Ptr++;
- lv_32fc_t bVal = lv_32fc_init( bReal, -bImag );
+ lv_32fc_t bVal = lv_cmake( bReal, -bImag );
lv_32fc_t temp = aVal * bVal;
*c16Ptr++ = (int16_t)lv_creal(temp);
diff --git a/volk/include/volk/volk_8ic_x2_s32f_multiply_conjugate_32fc_a16.h b/volk/include/volk/volk_8ic_x2_s32f_multiply_conjugate_32fc_a16.h
index fa58ff058..adc7c0599 100644
--- a/volk/include/volk/volk_8ic_x2_s32f_multiply_conjugate_32fc_a16.h
+++ b/volk/include/volk/volk_8ic_x2_s32f_multiply_conjugate_32fc_a16.h
@@ -75,10 +75,10 @@ static inline void volk_8ic_x2_s32f_multiply_conjugate_32fc_a16_sse4_1(lv_32fc_t
for(; number < num_points; number++){
float aReal = (float)*a8Ptr++;
float aImag = (float)*a8Ptr++;
- lv_32fc_t aVal = lv_32fc_init(aReal, aImag );
+ lv_32fc_t aVal = lv_cmake(aReal, aImag );
float bReal = (float)*b8Ptr++;
float bImag = (float)*b8Ptr++;
- lv_32fc_t bVal = lv_32fc_init( bReal, -bImag );
+ lv_32fc_t bVal = lv_cmake( bReal, -bImag );
lv_32fc_t temp = aVal * bVal;
*cFloatPtr++ = lv_creal(temp) / scalar;
@@ -104,10 +104,10 @@ static inline void volk_8ic_x2_s32f_multiply_conjugate_32fc_a16_generic(lv_32fc_
for(number = 0; number < num_points; number++){
float aReal = (float)*a8Ptr++;
float aImag = (float)*a8Ptr++;
- lv_32fc_t aVal = lv_32fc_init(aReal, aImag );
+ lv_32fc_t aVal = lv_cmake(aReal, aImag );
float bReal = (float)*b8Ptr++;
float bImag = (float)*b8Ptr++;
- lv_32fc_t bVal = lv_32fc_init( bReal, -bImag );
+ lv_32fc_t bVal = lv_cmake( bReal, -bImag );
lv_32fc_t temp = aVal * bVal;
*cPtr++ = (lv_creal(temp) * invScalar);
diff --git a/volk/include/volk/volk_complex.h b/volk/include/volk/volk_complex.h
index b20b5cf47..5bd925044 100644
--- a/volk/include/volk/volk_complex.h
+++ b/volk/include/volk/volk_complex.h
@@ -2,8 +2,21 @@
#define INCLUDE_VOLK_COMPLEX_H
/*!
- \brief This header file is to prevent issues with having <complex> and <complex.h> variables in the same code as the gcc compiler does not allow that
-*/
+ * \brief Provide typedefs and operators for all complex types in C and C++.
+ *
+ * The typedefs encompass all signed integer and floating point types.
+ * Each operator function is intended to work across all data types.
+ * Under C++, these operators are defined as inline templates.
+ * Under C, these operators are defined as preprocessor macros.
+ * The use of macros makes the operators agnostic to the type.
+ *
+ * The following operator functions are defined:
+ * - lv_cmake - make a complex type from components
+ * - lv_creal - get the real part of the complex number
+ * - lv_cimag - get the imaginary part of the complex number
+ * - lv_conj - take the conjugate of the complex number
+ */
+
#ifdef __cplusplus
#include <complex>
@@ -12,60 +25,62 @@
typedef std::complex<int8_t> lv_8sc_t;
typedef std::complex<int16_t> lv_16sc_t;
typedef std::complex<int32_t> lv_32sc_t;
+typedef std::complex<int64_t> lv_64sc_t;
typedef std::complex<float> lv_32fc_t;
typedef std::complex<double> lv_64fc_t;
-static inline float lv_creal(const lv_32fc_t x){
- return x.real();
-}
-
-static inline float lv_cimag(const lv_32fc_t x){
- return x.imag();
+template <typename T> inline std::complex<T> lv_cmake(const T &r, const T &i){
+ return std::complex<T>(r, i);
}
-static inline lv_32fc_t lv_conj(const lv_32fc_t x){
- return std::conj(x);
+template <typename T> inline typename T::value_type lv_creal(const T &x){
+ return x.real();
}
-static inline lv_32fc_t lv_cpow(const lv_32fc_t x, const lv_32fc_t y){
- return std::pow(x, y);
+template <typename T> inline typename T::value_type lv_cimag(const T &x){
+ return x.imag();
}
-static inline lv_32fc_t lv_32fc_init(const float x, const float y){
- return std::complex<float>(x,y);
+template <typename T> inline T lv_conj(const T &x){
+ return std::conj(x);
}
-#else
+#else /* __cplusplus */
#include <complex.h>
typedef char complex lv_8sc_t;
typedef short complex lv_16sc_t;
-typedef int complex lv_32sc_t;
+typedef long complex lv_32sc_t;
+typedef long long complex lv_64sc_t;
typedef float complex lv_32fc_t;
typedef double complex lv_64fc_t;
-static inline float lv_creal(const lv_32fc_t x){
- return creal(x);
-}
+#define lv_cmake(r, i) ((r) + _Complex_I*(i))
-static inline float lv_cimag(const lv_32fc_t x){
- return cimag(x);
-}
+// When GNUC is available, use the complex extensions.
+// The extensions always return the correct value type.
+// http://gcc.gnu.org/onlinedocs/gcc/Complex.html
+#ifdef __GNUC__
-static inline lv_32fc_t lv_conj(const lv_32fc_t x){
- return conj(x);
-}
+#define lv_creal(x) (__real__(x))
-static inline lv_32fc_t lv_cpow(const lv_32fc_t x, const lv_32fc_t y){
- return cpow(x, y);
-}
+#define lv_cimag(x) (__imag__(x))
-static inline lv_32fc_t lv_32fc_init(const float x, const float y){
- return x + I*y;
-}
+#define lv_conj(x) (~(x))
+
+// When not available, use the c99 complex function family,
+// which always returns double regardless of the input type.
+#else /* __GNUC__ */
+
+#define lv_creal(x) (creal(x))
+
+#define lv_cimag(x) (cimag(x))
+
+#define lv_conj(x) (conj(x))
-#endif
+#endif /* __GNUC__ */
+#endif /* __cplusplus */
#endif /* INCLUDE_VOLK_COMPLEX_H */