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_16ic_deinterleave_16i_x2.h
Go to the documentation of this file.
1 #ifndef INCLUDED_volk_16ic_deinterleave_16i_x2_a_H
2 #define INCLUDED_volk_16ic_deinterleave_16i_x2_a_H
3 
4 #include <inttypes.h>
5 #include <stdio.h>
6 
7 #ifdef LV_HAVE_SSSE3
8 #include <tmmintrin.h>
9 /*!
10  \brief Deinterleaves the complex 16 bit vector into I & Q vector data
11  \param complexVector The complex input vector
12  \param iBuffer The I buffer output data
13  \param qBuffer The Q buffer output data
14  \param num_points The number of complex data values to be deinterleaved
15 */
16 static inline void volk_16ic_deinterleave_16i_x2_a_ssse3(int16_t* iBuffer, int16_t* qBuffer, const lv_16sc_t* complexVector, unsigned int num_points){
17  unsigned int number = 0;
18  const int8_t* complexVectorPtr = (int8_t*)complexVector;
19  int16_t* iBufferPtr = iBuffer;
20  int16_t* qBufferPtr = qBuffer;
21 
22  __m128i iMoveMask1 = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 13, 12, 9, 8, 5, 4, 1, 0);
23  __m128i iMoveMask2 = _mm_set_epi8(13, 12, 9, 8, 5, 4, 1, 0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80);
24 
25  __m128i qMoveMask1 = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 15, 14, 11, 10, 7, 6, 3, 2);
26  __m128i qMoveMask2 = _mm_set_epi8(15, 14, 11, 10, 7, 6, 3, 2, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80);
27 
28  __m128i complexVal1, complexVal2, iOutputVal, qOutputVal;
29 
30  unsigned int eighthPoints = num_points / 8;
31 
32  for(number = 0; number < eighthPoints; number++){
33  complexVal1 = _mm_load_si128((__m128i*)complexVectorPtr); complexVectorPtr += 16;
34  complexVal2 = _mm_load_si128((__m128i*)complexVectorPtr); complexVectorPtr += 16;
35 
36  iOutputVal = _mm_or_si128( _mm_shuffle_epi8(complexVal1, iMoveMask1) , _mm_shuffle_epi8(complexVal2, iMoveMask2));
37  qOutputVal = _mm_or_si128( _mm_shuffle_epi8(complexVal1, qMoveMask1) , _mm_shuffle_epi8(complexVal2, qMoveMask2));
38 
39  _mm_store_si128((__m128i*)iBufferPtr, iOutputVal);
40  _mm_store_si128((__m128i*)qBufferPtr, qOutputVal);
41 
42  iBufferPtr += 8;
43  qBufferPtr += 8;
44  }
45 
46  number = eighthPoints * 8;
47  int16_t* int16ComplexVectorPtr = (int16_t*)complexVectorPtr;
48  for(; number < num_points; number++){
49  *iBufferPtr++ = *int16ComplexVectorPtr++;
50  *qBufferPtr++ = *int16ComplexVectorPtr++;
51  }
52 }
53 #endif /* LV_HAVE_SSSE3 */
54 
55 #ifdef LV_HAVE_SSE2
56 #include <emmintrin.h>
57 /*!
58  \brief Deinterleaves the complex 16 bit vector into I & Q vector data
59  \param complexVector The complex input vector
60  \param iBuffer The I buffer output data
61  \param qBuffer The Q buffer output data
62  \param num_points The number of complex data values to be deinterleaved
63 */
64 static inline void volk_16ic_deinterleave_16i_x2_a_sse2(int16_t* iBuffer, int16_t* qBuffer, const lv_16sc_t* complexVector, unsigned int num_points){
65  unsigned int number = 0;
66  const int16_t* complexVectorPtr = (int16_t*)complexVector;
67  int16_t* iBufferPtr = iBuffer;
68  int16_t* qBufferPtr = qBuffer;
69  __m128i complexVal1, complexVal2, iComplexVal1, iComplexVal2, qComplexVal1, qComplexVal2, iOutputVal, qOutputVal;
70  __m128i lowMask = _mm_set_epi32(0x0, 0x0, 0xFFFFFFFF, 0xFFFFFFFF);
71  __m128i highMask = _mm_set_epi32(0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0);
72 
73  unsigned int eighthPoints = num_points / 8;
74 
75  for(number = 0; number < eighthPoints; number++){
76  complexVal1 = _mm_load_si128((__m128i*)complexVectorPtr); complexVectorPtr += 8;
77  complexVal2 = _mm_load_si128((__m128i*)complexVectorPtr); complexVectorPtr += 8;
78 
79  iComplexVal1 = _mm_shufflelo_epi16(complexVal1, _MM_SHUFFLE(3,1,2,0));
80 
81  iComplexVal1 = _mm_shufflehi_epi16(iComplexVal1, _MM_SHUFFLE(3,1,2,0));
82 
83  iComplexVal1 = _mm_shuffle_epi32(iComplexVal1, _MM_SHUFFLE(3,1,2,0));
84 
85  iComplexVal2 = _mm_shufflelo_epi16(complexVal2, _MM_SHUFFLE(3,1,2,0));
86 
87  iComplexVal2 = _mm_shufflehi_epi16(iComplexVal2, _MM_SHUFFLE(3,1,2,0));
88 
89  iComplexVal2 = _mm_shuffle_epi32(iComplexVal2, _MM_SHUFFLE(2,0,3,1));
90 
91  iOutputVal = _mm_or_si128(_mm_and_si128(iComplexVal1, lowMask), _mm_and_si128(iComplexVal2, highMask));
92 
93  _mm_store_si128((__m128i*)iBufferPtr, iOutputVal);
94 
95  qComplexVal1 = _mm_shufflelo_epi16(complexVal1, _MM_SHUFFLE(2,0,3,1));
96 
97  qComplexVal1 = _mm_shufflehi_epi16(qComplexVal1, _MM_SHUFFLE(2,0,3,1));
98 
99  qComplexVal1 = _mm_shuffle_epi32(qComplexVal1, _MM_SHUFFLE(3,1,2,0));
100 
101  qComplexVal2 = _mm_shufflelo_epi16(complexVal2, _MM_SHUFFLE(2,0,3,1));
102 
103  qComplexVal2 = _mm_shufflehi_epi16(qComplexVal2, _MM_SHUFFLE(2,0,3,1));
104 
105  qComplexVal2 = _mm_shuffle_epi32(qComplexVal2, _MM_SHUFFLE(2,0,3,1));
106 
107  qOutputVal = _mm_or_si128(_mm_and_si128(qComplexVal1, lowMask), _mm_and_si128(qComplexVal2, highMask));
108 
109  _mm_store_si128((__m128i*)qBufferPtr, qOutputVal);
110 
111  iBufferPtr += 8;
112  qBufferPtr += 8;
113  }
114 
115  number = eighthPoints * 8;
116  for(; number < num_points; number++){
117  *iBufferPtr++ = *complexVectorPtr++;
118  *qBufferPtr++ = *complexVectorPtr++;
119  }
120 }
121 #endif /* LV_HAVE_SSE2 */
122 
123 #ifdef LV_HAVE_GENERIC
124 /*!
125  \brief Deinterleaves the complex 16 bit vector into I & Q vector data
126  \param complexVector The complex input vector
127  \param iBuffer The I buffer output data
128  \param qBuffer The Q buffer output data
129  \param num_points The number of complex data values to be deinterleaved
130 */
131 static inline void volk_16ic_deinterleave_16i_x2_generic(int16_t* iBuffer, int16_t* qBuffer, const lv_16sc_t* complexVector, unsigned int num_points){
132  const int16_t* complexVectorPtr = (const int16_t*)complexVector;
133  int16_t* iBufferPtr = iBuffer;
134  int16_t* qBufferPtr = qBuffer;
135  unsigned int number;
136  for(number = 0; number < num_points; number++){
137  *iBufferPtr++ = *complexVectorPtr++;
138  *qBufferPtr++ = *complexVectorPtr++;
139  }
140 }
141 #endif /* LV_HAVE_GENERIC */
142 
143 #ifdef LV_HAVE_ORC
144 /*!
145  \brief Deinterleaves the complex 16 bit vector into I & Q vector data
146  \param complexVector The complex input vector
147  \param iBuffer The I buffer output data
148  \param qBuffer The Q buffer output data
149  \param num_points The number of complex data values to be deinterleaved
150 */
151 extern void volk_16ic_deinterleave_16i_x2_a_orc_impl(int16_t* iBuffer, int16_t* qBuffer, const lv_16sc_t* complexVector, unsigned int num_points);
152 static inline void volk_16ic_deinterleave_16i_x2_u_orc(int16_t* iBuffer, int16_t* qBuffer, const lv_16sc_t* complexVector, unsigned int num_points){
153  volk_16ic_deinterleave_16i_x2_a_orc_impl(iBuffer, qBuffer, complexVector, num_points);
154 }
155 #endif /* LV_HAVE_ORC */
156 
157 
158 #endif /* INCLUDED_volk_16ic_deinterleave_16i_x2_a_H */
short complex lv_16sc_t
Definition: volk_complex.h:53
signed short int16_t
Definition: stdint.h:76
signed char int8_t
Definition: stdint.h:75