GNU Radio Manual and C++ API Reference  3.7.6.1
The Free & Open Software Radio Ecosystem
volk_32fc_deinterleave_64f_x2.h
Go to the documentation of this file.
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2014 Free Software Foundation, Inc.
4  *
5  * This file is part of GNU Radio
6  *
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  *
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING. If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #ifndef INCLUDED_volk_32fc_deinterleave_64f_x2_u_H
24 #define INCLUDED_volk_32fc_deinterleave_64f_x2_u_H
25 
26 #include <inttypes.h>
27 #include <stdio.h>
28 
29 #ifdef LV_HAVE_AVX
30 #include <immintrin.h>
31 /*!
32  \brief Deinterleaves the lv_32fc_t vector into double I & Q vector data
33  \param complexVector The complex input vector
34  \param iBuffer The I buffer output data
35  \param qBuffer The Q buffer output data
36  \param num_points The number of complex data values to be deinterleaved
37 */
38 static inline void volk_32fc_deinterleave_64f_x2_u_avx(double* iBuffer, double* qBuffer, const lv_32fc_t* complexVector, unsigned int num_points){
39  unsigned int number = 0;
40 
41  const float* complexVectorPtr = (float*)complexVector;
42  double* iBufferPtr = iBuffer;
43  double* qBufferPtr = qBuffer;
44 
45  const unsigned int quarterPoints = num_points / 4;
46  __m256 cplxValue;
47  __m128 complexH, complexL, fVal;
48  __m256d dVal;
49 
50  for(;number < quarterPoints; number++){
51 
52  cplxValue = _mm256_loadu_ps(complexVectorPtr);
53  complexVectorPtr += 8;
54 
55  complexH = _mm256_extractf128_ps(cplxValue, 1);
56  complexL = _mm256_extractf128_ps(cplxValue, 0);
57 
58  // Arrange in i1i2i1i2 format
59  fVal = _mm_shuffle_ps(complexL, complexH, _MM_SHUFFLE(2,0,2,0));
60  dVal = _mm256_cvtps_pd(fVal);
61  _mm256_storeu_pd(iBufferPtr, dVal);
62 
63  // Arrange in q1q2q1q2 format
64  fVal = _mm_shuffle_ps(complexL, complexH, _MM_SHUFFLE(3,1,3,1));
65  dVal = _mm256_cvtps_pd(fVal);
66  _mm256_storeu_pd(qBufferPtr, dVal);
67 
68  iBufferPtr += 4;
69  qBufferPtr += 4;
70  }
71 
72  number = quarterPoints * 4;
73  for(; number < num_points; number++){
74  *iBufferPtr++ = *complexVectorPtr++;
75  *qBufferPtr++ = *complexVectorPtr++;
76  }
77 }
78 #endif /* LV_HAVE_AVX */
79 
80 #ifdef LV_HAVE_SSE2
81 #include <emmintrin.h>
82 /*!
83  \brief Deinterleaves the lv_32fc_t vector into double I & Q vector data
84  \param complexVector The complex input vector
85  \param iBuffer The I buffer output data
86  \param qBuffer The Q buffer output data
87  \param num_points The number of complex data values to be deinterleaved
88 */
89 static inline void volk_32fc_deinterleave_64f_x2_u_sse2(double* iBuffer, double* qBuffer, const lv_32fc_t* complexVector, unsigned int num_points){
90  unsigned int number = 0;
91 
92  const float* complexVectorPtr = (float*)complexVector;
93  double* iBufferPtr = iBuffer;
94  double* qBufferPtr = qBuffer;
95 
96  const unsigned int halfPoints = num_points / 2;
97  __m128 cplxValue, fVal;
98  __m128d dVal;
99 
100  for(;number < halfPoints; number++){
101 
102  cplxValue = _mm_loadu_ps(complexVectorPtr);
103  complexVectorPtr += 4;
104 
105  // Arrange in i1i2i1i2 format
106  fVal = _mm_shuffle_ps(cplxValue, cplxValue, _MM_SHUFFLE(2,0,2,0));
107  dVal = _mm_cvtps_pd(fVal);
108  _mm_storeu_pd(iBufferPtr, dVal);
109 
110  // Arrange in q1q2q1q2 format
111  fVal = _mm_shuffle_ps(cplxValue, cplxValue, _MM_SHUFFLE(3,1,3,1));
112  dVal = _mm_cvtps_pd(fVal);
113  _mm_storeu_pd(qBufferPtr, dVal);
114 
115  iBufferPtr += 2;
116  qBufferPtr += 2;
117  }
118 
119  number = halfPoints * 2;
120  for(; number < num_points; number++){
121  *iBufferPtr++ = *complexVectorPtr++;
122  *qBufferPtr++ = *complexVectorPtr++;
123  }
124 }
125 #endif /* LV_HAVE_SSE */
126 
127 #ifdef LV_HAVE_GENERIC
128 /*!
129  \brief Deinterleaves the lv_32fc_t vector into double I & Q vector data
130  \param complexVector The complex input vector
131  \param iBuffer The I buffer output data
132  \param qBuffer The Q buffer output data
133  \param num_points The number of complex data values to be deinterleaved
134 */
135 static inline void volk_32fc_deinterleave_64f_x2_generic(double* iBuffer, double* qBuffer, const lv_32fc_t* complexVector, unsigned int num_points){
136  unsigned int number = 0;
137  const float* complexVectorPtr = (float*)complexVector;
138  double* iBufferPtr = iBuffer;
139  double* qBufferPtr = qBuffer;
140 
141  for(number = 0; number < num_points; number++){
142  *iBufferPtr++ = (double)*complexVectorPtr++;
143  *qBufferPtr++ = (double)*complexVectorPtr++;
144  }
145 }
146 #endif /* LV_HAVE_GENERIC */
147 
148 
149 
150 
151 #endif /* INCLUDED_volk_32fc_deinterleave_64f_x2_u_H */
152 #ifndef INCLUDED_volk_32fc_deinterleave_64f_x2_a_H
153 #define INCLUDED_volk_32fc_deinterleave_64f_x2_a_H
154 
155 #include <inttypes.h>
156 #include <stdio.h>
157 
158 #ifdef LV_HAVE_AVX
159 #include <immintrin.h>
160 /*!
161  \brief Deinterleaves the lv_32fc_t vector into double I & Q vector data
162  \param complexVector The complex input vector
163  \param iBuffer The I buffer output data
164  \param qBuffer The Q buffer output data
165  \param num_points The number of complex data values to be deinterleaved
166 */
167 static inline void volk_32fc_deinterleave_64f_x2_a_avx(double* iBuffer, double* qBuffer, const lv_32fc_t* complexVector, unsigned int num_points){
168  unsigned int number = 0;
169 
170  const float* complexVectorPtr = (float*)complexVector;
171  double* iBufferPtr = iBuffer;
172  double* qBufferPtr = qBuffer;
173 
174  const unsigned int quarterPoints = num_points / 4;
175  __m256 cplxValue;
176  __m128 complexH, complexL, fVal;
177  __m256d dVal;
178 
179  for(;number < quarterPoints; number++){
180 
181  cplxValue = _mm256_load_ps(complexVectorPtr);
182  complexVectorPtr += 8;
183 
184  complexH = _mm256_extractf128_ps(cplxValue, 1);
185  complexL = _mm256_extractf128_ps(cplxValue, 0);
186 
187  // Arrange in i1i2i1i2 format
188  fVal = _mm_shuffle_ps(complexL, complexH, _MM_SHUFFLE(2,0,2,0));
189  dVal = _mm256_cvtps_pd(fVal);
190  _mm256_store_pd(iBufferPtr, dVal);
191 
192  // Arrange in q1q2q1q2 format
193  fVal = _mm_shuffle_ps(complexL, complexH, _MM_SHUFFLE(3,1,3,1));
194  dVal = _mm256_cvtps_pd(fVal);
195  _mm256_store_pd(qBufferPtr, dVal);
196 
197  iBufferPtr += 4;
198  qBufferPtr += 4;
199  }
200 
201  number = quarterPoints * 4;
202  for(; number < num_points; number++){
203  *iBufferPtr++ = *complexVectorPtr++;
204  *qBufferPtr++ = *complexVectorPtr++;
205  }
206 }
207 #endif /* LV_HAVE_AVX */
208 
209 #ifdef LV_HAVE_SSE2
210 #include <emmintrin.h>
211 /*!
212  \brief Deinterleaves the lv_32fc_t vector into double I & Q vector data
213  \param complexVector The complex input vector
214  \param iBuffer The I buffer output data
215  \param qBuffer The Q buffer output data
216  \param num_points The number of complex data values to be deinterleaved
217 */
218 static inline void volk_32fc_deinterleave_64f_x2_a_sse2(double* iBuffer, double* qBuffer, const lv_32fc_t* complexVector, unsigned int num_points){
219  unsigned int number = 0;
220 
221  const float* complexVectorPtr = (float*)complexVector;
222  double* iBufferPtr = iBuffer;
223  double* qBufferPtr = qBuffer;
224 
225  const unsigned int halfPoints = num_points / 2;
226  __m128 cplxValue, fVal;
227  __m128d dVal;
228 
229  for(;number < halfPoints; number++){
230 
231  cplxValue = _mm_load_ps(complexVectorPtr);
232  complexVectorPtr += 4;
233 
234  // Arrange in i1i2i1i2 format
235  fVal = _mm_shuffle_ps(cplxValue, cplxValue, _MM_SHUFFLE(2,0,2,0));
236  dVal = _mm_cvtps_pd(fVal);
237  _mm_store_pd(iBufferPtr, dVal);
238 
239  // Arrange in q1q2q1q2 format
240  fVal = _mm_shuffle_ps(cplxValue, cplxValue, _MM_SHUFFLE(3,1,3,1));
241  dVal = _mm_cvtps_pd(fVal);
242  _mm_store_pd(qBufferPtr, dVal);
243 
244  iBufferPtr += 2;
245  qBufferPtr += 2;
246  }
247 
248  number = halfPoints * 2;
249  for(; number < num_points; number++){
250  *iBufferPtr++ = *complexVectorPtr++;
251  *qBufferPtr++ = *complexVectorPtr++;
252  }
253 }
254 #endif /* LV_HAVE_SSE */
255 
256 #ifdef LV_HAVE_GENERIC
257 /*!
258  \brief Deinterleaves the lv_32fc_t vector into double I & Q vector data
259  \param complexVector The complex input vector
260  \param iBuffer The I buffer output data
261  \param qBuffer The Q buffer output data
262  \param num_points The number of complex data values to be deinterleaved
263 */
264 static inline void volk_32fc_deinterleave_64f_x2_a_generic(double* iBuffer, double* qBuffer, const lv_32fc_t* complexVector, unsigned int num_points){
265  unsigned int number = 0;
266  const float* complexVectorPtr = (float*)complexVector;
267  double* iBufferPtr = iBuffer;
268  double* qBufferPtr = qBuffer;
269 
270  for(number = 0; number < num_points; number++){
271  *iBufferPtr++ = (double)*complexVectorPtr++;
272  *qBufferPtr++ = (double)*complexVectorPtr++;
273  }
274 }
275 #endif /* LV_HAVE_GENERIC */
276 
277 
278 
279 
280 #endif /* INCLUDED_volk_32fc_deinterleave_64f_x2_a_H */
float complex lv_32fc_t
Definition: volk_complex.h:56