GNU Radio 3.7.3 C++ API
volk_32fc_s32f_power_32fc.h
Go to the documentation of this file.
1 #ifndef INCLUDED_volk_32fc_s32f_power_32fc_a_H
2 #define INCLUDED_volk_32fc_s32f_power_32fc_a_H
3 
4 #include <inttypes.h>
5 #include <stdio.h>
6 #include <math.h>
7 
8 //! raise a complex float to a real float power
9 static inline lv_32fc_t __volk_s32fc_s32f_power_s32fc_a(const lv_32fc_t exp, const float power){
10  const float arg = power*atan2f(lv_creal(exp), lv_cimag(exp));
11  const float mag = powf(lv_creal(exp)*lv_creal(exp) + lv_cimag(exp)*lv_cimag(exp), power/2);
12  return mag*lv_cmake(-cosf(arg), sinf(arg));
13 }
14 
15 #ifdef LV_HAVE_SSE
16 #include <xmmintrin.h>
17 
18 #ifdef LV_HAVE_LIB_SIMDMATH
19 #include <simdmath.h>
20 #endif /* LV_HAVE_LIB_SIMDMATH */
21 
22 /*!
23  \brief Takes each the input complex vector value to the specified power and stores the results in the return vector
24  \param cVector The vector where the results will be stored
25  \param aVector The complex vector of values to be taken to a power
26  \param power The power value to be applied to each data point
27  \param num_points The number of values in aVector to be taken to the specified power level and stored into cVector
28 */
29 static inline void volk_32fc_s32f_power_32fc_a_sse(lv_32fc_t* cVector, const lv_32fc_t* aVector, const float power, unsigned int num_points){
30  unsigned int number = 0;
31 
32  lv_32fc_t* cPtr = cVector;
33  const lv_32fc_t* aPtr = aVector;
34 
35 #ifdef LV_HAVE_LIB_SIMDMATH
36  const unsigned int quarterPoints = num_points / 4;
37  __m128 vPower = _mm_set_ps1(power);
38 
39  __m128 cplxValue1, cplxValue2, magnitude, phase, iValue, qValue;
40  for(;number < quarterPoints; number++){
41 
42  cplxValue1 = _mm_load_ps((float*)aPtr);
43  aPtr += 2;
44 
45  cplxValue2 = _mm_load_ps((float*)aPtr);
46  aPtr += 2;
47 
48  // Convert to polar coordinates
49 
50  // Arrange in i1i2i3i4 format
51  iValue = _mm_shuffle_ps(cplxValue1, cplxValue2, _MM_SHUFFLE(2,0,2,0));
52  // Arrange in q1q2q3q4 format
53  qValue = _mm_shuffle_ps(cplxValue1, cplxValue2, _MM_SHUFFLE(3,1,3,1));
54 
55  phase = atan2f4(qValue, iValue); // Calculate the Phase
56 
57  magnitude = _mm_sqrt_ps(_mm_add_ps(_mm_mul_ps(iValue, iValue), _mm_mul_ps(qValue, qValue))); // Calculate the magnitude by square rooting the added I2 and Q2 values
58 
59  // Now calculate the power of the polar coordinate data
60  magnitude = powf4(magnitude, vPower); // Take the magnitude to the specified power
61 
62  phase = _mm_mul_ps(phase, vPower); // Multiply the phase by the specified power
63 
64  // Convert back to cartesian coordinates
65  iValue = _mm_mul_ps( cosf4(phase), magnitude); // Multiply the cos of the phase by the magnitude
66  qValue = _mm_mul_ps( sinf4(phase), magnitude); // Multiply the sin of the phase by the magnitude
67 
68  cplxValue1 = _mm_unpacklo_ps(iValue, qValue); // Interleave the lower two i & q values
69  cplxValue2 = _mm_unpackhi_ps(iValue, qValue); // Interleave the upper two i & q values
70 
71  _mm_store_ps((float*)cPtr,cplxValue1); // Store the results back into the C container
72 
73  cPtr += 2;
74 
75  _mm_store_ps((float*)cPtr,cplxValue2); // Store the results back into the C container
76 
77  cPtr += 2;
78  }
79 
80  number = quarterPoints * 4;
81 #endif /* LV_HAVE_LIB_SIMDMATH */
82 
83  for(;number < num_points; number++){
84  *cPtr++ = __volk_s32fc_s32f_power_s32fc_a((*aPtr++), power);
85  }
86 }
87 #endif /* LV_HAVE_SSE */
88 
89 #ifdef LV_HAVE_GENERIC
90  /*!
91  \brief Takes each the input complex vector value to the specified power and stores the results in the return vector
92  \param cVector The vector where the results will be stored
93  \param aVector The complex vector of values to be taken to a power
94  \param power The power value to be applied to each data point
95  \param num_points The number of values in aVector to be taken to the specified power level and stored into cVector
96  */
97 static inline void volk_32fc_s32f_power_32fc_generic(lv_32fc_t* cVector, const lv_32fc_t* aVector, const float power, unsigned int num_points){
98  lv_32fc_t* cPtr = cVector;
99  const lv_32fc_t* aPtr = aVector;
100  unsigned int number = 0;
101 
102  for(number = 0; number < num_points; number++){
103  *cPtr++ = __volk_s32fc_s32f_power_s32fc_a((*aPtr++), power);
104  }
105 }
106 #endif /* LV_HAVE_GENERIC */
107 
108 
109 
110 
111 #endif /* INCLUDED_volk_32fc_s32f_power_32fc_a_H */
static lv_32fc_t __volk_s32fc_s32f_power_s32fc_a(const lv_32fc_t exp, const float power)
raise a complex float to a real float power
Definition: volk_32fc_s32f_power_32fc.h:9
#define lv_cmake(r, i)
Definition: volk_complex.h:59
float complex lv_32fc_t
Definition: volk_complex.h:56
#define lv_creal(x)
Definition: volk_complex.h:76
#define lv_cimag(x)
Definition: volk_complex.h:78