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_s32f_deinterleave_32f_x2.h
Go to the documentation of this file.
1 #ifndef INCLUDED_volk_8ic_s32f_deinterleave_32f_x2_a_H
2 #define INCLUDED_volk_8ic_s32f_deinterleave_32f_x2_a_H
3 
4 #include <volk/volk_common.h>
5 #include <inttypes.h>
6 #include <stdio.h>
7 
8 #ifdef LV_HAVE_SSE4_1
9 #include <smmintrin.h>
10 /*!
11  \brief Deinterleaves the complex 8 bit vector into I & Q floating point vector data
12  \param complexVector The complex input vector
13  \param iBuffer The I buffer output data
14  \param qBuffer The Q buffer output data
15  \param scalar The scaling value being multiplied against each data point
16  \param num_points The number of complex data values to be deinterleaved
17 */
18 static inline void volk_8ic_s32f_deinterleave_32f_x2_a_sse4_1(float* iBuffer, float* qBuffer, const lv_8sc_t* complexVector, const float scalar, unsigned int num_points){
19  float* iBufferPtr = iBuffer;
20  float* qBufferPtr = qBuffer;
21 
22  unsigned int number = 0;
23  const unsigned int eighthPoints = num_points / 8;
24  __m128 iFloatValue, qFloatValue;
25 
26  const float iScalar= 1.0 / scalar;
27  __m128 invScalar = _mm_set_ps1(iScalar);
28  __m128i complexVal, iIntVal, qIntVal, iComplexVal, qComplexVal;
29  int8_t* complexVectorPtr = (int8_t*)complexVector;
30 
31  __m128i iMoveMask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 14, 12, 10, 8, 6, 4, 2, 0);
32  __m128i qMoveMask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 15, 13, 11, 9, 7, 5, 3, 1);
33 
34  for(;number < eighthPoints; number++){
35  complexVal = _mm_load_si128((__m128i*)complexVectorPtr); complexVectorPtr += 16;
36  iComplexVal = _mm_shuffle_epi8(complexVal, iMoveMask);
37  qComplexVal = _mm_shuffle_epi8(complexVal, qMoveMask);
38 
39  iIntVal = _mm_cvtepi8_epi32(iComplexVal);
40  iFloatValue = _mm_cvtepi32_ps(iIntVal);
41  iFloatValue = _mm_mul_ps(iFloatValue, invScalar);
42  _mm_store_ps(iBufferPtr, iFloatValue);
43  iBufferPtr += 4;
44 
45  iComplexVal = _mm_srli_si128(iComplexVal, 4);
46 
47  iIntVal = _mm_cvtepi8_epi32(iComplexVal);
48  iFloatValue = _mm_cvtepi32_ps(iIntVal);
49  iFloatValue = _mm_mul_ps(iFloatValue, invScalar);
50  _mm_store_ps(iBufferPtr, iFloatValue);
51  iBufferPtr += 4;
52 
53  qIntVal = _mm_cvtepi8_epi32(qComplexVal);
54  qFloatValue = _mm_cvtepi32_ps(qIntVal);
55  qFloatValue = _mm_mul_ps(qFloatValue, invScalar);
56  _mm_store_ps(qBufferPtr, qFloatValue);
57  qBufferPtr += 4;
58 
59  qComplexVal = _mm_srli_si128(qComplexVal, 4);
60 
61  qIntVal = _mm_cvtepi8_epi32(qComplexVal);
62  qFloatValue = _mm_cvtepi32_ps(qIntVal);
63  qFloatValue = _mm_mul_ps(qFloatValue, invScalar);
64  _mm_store_ps(qBufferPtr, qFloatValue);
65 
66  qBufferPtr += 4;
67  }
68 
69  number = eighthPoints * 8;
70  for(; number < num_points; number++){
71  *iBufferPtr++ = (float)(*complexVectorPtr++) * iScalar;
72  *qBufferPtr++ = (float)(*complexVectorPtr++) * iScalar;
73  }
74 
75 }
76 #endif /* LV_HAVE_SSE4_1 */
77 
78 #ifdef LV_HAVE_SSE
79 #include <xmmintrin.h>
80 /*!
81  \brief Deinterleaves the complex 8 bit vector into I & Q floating point vector data
82  \param complexVector The complex input vector
83  \param iBuffer The I buffer output data
84  \param qBuffer The Q buffer output data
85  \param scalar The scaling value being multiplied against each data point
86  \param num_points The number of complex data values to be deinterleaved
87 */
88 static inline void volk_8ic_s32f_deinterleave_32f_x2_a_sse(float* iBuffer, float* qBuffer, const lv_8sc_t* complexVector, const float scalar, unsigned int num_points){
89  float* iBufferPtr = iBuffer;
90  float* qBufferPtr = qBuffer;
91 
92  unsigned int number = 0;
93  const unsigned int quarterPoints = num_points / 4;
94  __m128 cplxValue1, cplxValue2, iValue, qValue;
95 
96  __m128 invScalar = _mm_set_ps1(1.0/scalar);
97  int8_t* complexVectorPtr = (int8_t*)complexVector;
98 
99  __VOLK_ATTR_ALIGNED(16) float floatBuffer[8];
100 
101  for(;number < quarterPoints; number++){
102  floatBuffer[0] = (float)(complexVectorPtr[0]);
103  floatBuffer[1] = (float)(complexVectorPtr[1]);
104  floatBuffer[2] = (float)(complexVectorPtr[2]);
105  floatBuffer[3] = (float)(complexVectorPtr[3]);
106 
107  floatBuffer[4] = (float)(complexVectorPtr[4]);
108  floatBuffer[5] = (float)(complexVectorPtr[5]);
109  floatBuffer[6] = (float)(complexVectorPtr[6]);
110  floatBuffer[7] = (float)(complexVectorPtr[7]);
111 
112  cplxValue1 = _mm_load_ps(&floatBuffer[0]);
113  cplxValue2 = _mm_load_ps(&floatBuffer[4]);
114 
115  complexVectorPtr += 8;
116 
117  cplxValue1 = _mm_mul_ps(cplxValue1, invScalar);
118  cplxValue2 = _mm_mul_ps(cplxValue2, invScalar);
119 
120  // Arrange in i1i2i3i4 format
121  iValue = _mm_shuffle_ps(cplxValue1, cplxValue2, _MM_SHUFFLE(2,0,2,0));
122  qValue = _mm_shuffle_ps(cplxValue1, cplxValue2, _MM_SHUFFLE(3,1,3,1));
123 
124  _mm_store_ps(iBufferPtr, iValue);
125  _mm_store_ps(qBufferPtr, qValue);
126 
127  iBufferPtr += 4;
128  qBufferPtr += 4;
129  }
130 
131  number = quarterPoints * 4;
132  complexVectorPtr = (int8_t*)&complexVector[number];
133  for(; number < num_points; number++){
134  *iBufferPtr++ = (float)(*complexVectorPtr++) / scalar;
135  *qBufferPtr++ = (float)(*complexVectorPtr++) / scalar;
136  }
137 }
138 #endif /* LV_HAVE_SSE */
139 
140 #ifdef LV_HAVE_GENERIC
141 /*!
142  \brief Deinterleaves the complex 8 bit vector into I & Q floating point vector data
143  \param complexVector The complex input vector
144  \param iBuffer The I buffer output data
145  \param qBuffer The Q buffer output data
146  \param scalar The scaling value being multiplied against each data point
147  \param num_points The number of complex data values to be deinterleaved
148 */
149 static inline void volk_8ic_s32f_deinterleave_32f_x2_generic(float* iBuffer, float* qBuffer, const lv_8sc_t* complexVector, const float scalar, unsigned int num_points){
150  const int8_t* complexVectorPtr = (const int8_t*)complexVector;
151  float* iBufferPtr = iBuffer;
152  float* qBufferPtr = qBuffer;
153  unsigned int number;
154  const float invScalar = 1.0 / scalar;
155  for(number = 0; number < num_points; number++){
156  *iBufferPtr++ = (float)(*complexVectorPtr++)*invScalar;
157  *qBufferPtr++ = (float)(*complexVectorPtr++)*invScalar;
158  }
159 }
160 #endif /* LV_HAVE_GENERIC */
161 
162 
163 
164 
165 #endif /* INCLUDED_volk_8ic_s32f_deinterleave_32f_x2_a_H */
signed char int8_t
Definition: stdint.h:75
#define __VOLK_ATTR_ALIGNED(x)
Definition: volk_common.h:27
char complex lv_8sc_t
Provide typedefs and operators for all complex types in C and C++.
Definition: volk_complex.h:52