GNU Radio Manual and C++ API Reference  3.7.4.1
The Free & Open Software Radio Ecosystem
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
volk_8ic_x2_s32f_multiply_conjugate_32fc.h
Go to the documentation of this file.
1 #ifndef INCLUDED_volk_8ic_x2_s32f_multiply_conjugate_32fc_a_H
2 #define INCLUDED_volk_8ic_x2_s32f_multiply_conjugate_32fc_a_H
3 
4 #include <inttypes.h>
5 #include <stdio.h>
6 #include <volk/volk_complex.h>
7 
8 #ifdef LV_HAVE_SSE4_1
9 #include <smmintrin.h>
10 /*!
11  \brief Multiplys the one complex vector with the complex conjugate of the second complex vector and stores their results in the third vector
12  \param cVector The complex vector where the results will be stored
13  \param aVector One of the complex vectors to be multiplied
14  \param bVector The complex vector which will be converted to complex conjugate and multiplied
15  \param num_points The number of complex values in aVector and bVector to be multiplied together and stored into cVector
16 */
17 static inline void volk_8ic_x2_s32f_multiply_conjugate_32fc_a_sse4_1(lv_32fc_t* cVector, const lv_8sc_t* aVector, const lv_8sc_t* bVector, const float scalar, unsigned int num_points){
18  unsigned int number = 0;
19  const unsigned int quarterPoints = num_points / 4;
20 
21  __m128i x, y, realz, imagz;
22  __m128 ret;
23  lv_32fc_t* c = cVector;
24  const lv_8sc_t* a = aVector;
25  const lv_8sc_t* b = bVector;
26  __m128i conjugateSign = _mm_set_epi16(-1, 1, -1, 1, -1, 1, -1, 1);
27 
28  __m128 invScalar = _mm_set_ps1(1.0/scalar);
29 
30  for(;number < quarterPoints; number++){
31  // Convert into 8 bit values into 16 bit values
32  x = _mm_cvtepi8_epi16(_mm_loadl_epi64((__m128i*)a));
33  y = _mm_cvtepi8_epi16(_mm_loadl_epi64((__m128i*)b));
34 
35  // Calculate the ar*cr - ai*(-ci) portions
36  realz = _mm_madd_epi16(x,y);
37 
38  // Calculate the complex conjugate of the cr + ci j values
39  y = _mm_sign_epi16(y, conjugateSign);
40 
41  // Shift the order of the cr and ci values
42  y = _mm_shufflehi_epi16(_mm_shufflelo_epi16(y, _MM_SHUFFLE(2,3,0,1) ), _MM_SHUFFLE(2,3,0,1));
43 
44  // Calculate the ar*(-ci) + cr*(ai)
45  imagz = _mm_madd_epi16(x,y);
46 
47  // Interleave real and imaginary and then convert to float values
48  ret = _mm_cvtepi32_ps(_mm_unpacklo_epi32(realz, imagz));
49 
50  // Normalize the floating point values
51  ret = _mm_mul_ps(ret, invScalar);
52 
53  // Store the floating point values
54  _mm_store_ps((float*)c, ret);
55  c += 2;
56 
57  // Interleave real and imaginary and then convert to float values
58  ret = _mm_cvtepi32_ps(_mm_unpackhi_epi32(realz, imagz));
59 
60  // Normalize the floating point values
61  ret = _mm_mul_ps(ret, invScalar);
62 
63  // Store the floating point values
64  _mm_store_ps((float*)c, ret);
65  c += 2;
66 
67  a += 4;
68  b += 4;
69  }
70 
71  number = quarterPoints * 4;
72  float* cFloatPtr = (float*)&cVector[number];
73  int8_t* a8Ptr = (int8_t*)&aVector[number];
74  int8_t* b8Ptr = (int8_t*)&bVector[number];
75  for(; number < num_points; number++){
76  float aReal = (float)*a8Ptr++;
77  float aImag = (float)*a8Ptr++;
78  lv_32fc_t aVal = lv_cmake(aReal, aImag );
79  float bReal = (float)*b8Ptr++;
80  float bImag = (float)*b8Ptr++;
81  lv_32fc_t bVal = lv_cmake( bReal, -bImag );
82  lv_32fc_t temp = aVal * bVal;
83 
84  *cFloatPtr++ = lv_creal(temp) / scalar;
85  *cFloatPtr++ = lv_cimag(temp) / scalar;
86  }
87 }
88 #endif /* LV_HAVE_SSE4_1 */
89 
90 #ifdef LV_HAVE_GENERIC
91 /*!
92  \brief Multiplys the one complex vector with the complex conjugate of the second complex vector and stores their results in the third vector
93  \param cVector The complex vector where the results will be stored
94  \param aVector One of the complex vectors to be multiplied
95  \param bVector The complex vector which will be converted to complex conjugate and multiplied
96  \param num_points The number of complex values in aVector and bVector to be multiplied together and stored into cVector
97 */
98 static inline void volk_8ic_x2_s32f_multiply_conjugate_32fc_generic(lv_32fc_t* cVector, const lv_8sc_t* aVector, const lv_8sc_t* bVector, const float scalar, unsigned int num_points){
99  unsigned int number = 0;
100  float* cPtr = (float*)cVector;
101  const float invScalar = 1.0 / scalar;
102  int8_t* a8Ptr = (int8_t*)aVector;
103  int8_t* b8Ptr = (int8_t*)bVector;
104  for(number = 0; number < num_points; number++){
105  float aReal = (float)*a8Ptr++;
106  float aImag = (float)*a8Ptr++;
107  lv_32fc_t aVal = lv_cmake(aReal, aImag );
108  float bReal = (float)*b8Ptr++;
109  float bImag = (float)*b8Ptr++;
110  lv_32fc_t bVal = lv_cmake( bReal, -bImag );
111  lv_32fc_t temp = aVal * bVal;
112 
113  *cPtr++ = (lv_creal(temp) * invScalar);
114  *cPtr++ = (lv_cimag(temp) * invScalar);
115  }
116 }
117 #endif /* LV_HAVE_GENERIC */
118 
119 
120 
121 
122 #endif /* INCLUDED_volk_8ic_x2_s32f_multiply_conjugate_32fc_a_H */
#define lv_cmake(r, i)
Definition: volk_complex.h:59
signed char int8_t
Definition: stdint.h:75
float complex lv_32fc_t
Definition: volk_complex.h:56
#define lv_creal(x)
Definition: volk_complex.h:76
char complex lv_8sc_t
Provide typedefs and operators for all complex types in C and C++.
Definition: volk_complex.h:52
#define lv_cimag(x)
Definition: volk_complex.h:78