GNU Radio Manual and C++ API Reference  3.7.7
The Free & Open Software Radio Ecosystem
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
volk_32fc_deinterleave_64f_x2.h
Go to the documentation of this file.
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2012, 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 /*!
24  * \page volk_32fc_deinterleave_64f_x2
25  *
26  * \b Overview
27  *
28  * Deinterleaves the complex floating point vector into I & Q vector
29  * data. The output vectors are converted to doubles.
30  *
31  * <b>Dispatcher Prototype</b>
32  * \code
33  * void volk_32fc_deinterleave_64f_x2(double* iBuffer, double* qBuffer, const lv_32fc_t* complexVector, unsigned int num_points)
34  * \endcode
35  *
36  * \b Inputs
37  * \li complexVector: The complex input vector.
38  * \li num_points: The number of complex data values to be deinterleaved.
39  *
40  * \b Outputs
41  * \li iBuffer: The I buffer output data.
42  * \li qBuffer: The Q buffer output data.
43  *
44  * \b Example
45  * Generate complex numbers around the top half of the unit circle and
46  * deinterleave in to real and imaginary double buffers.
47  * \code
48  * int N = 10;
49  * unsigned int alignment = volk_get_alignment();
50  * lv_32fc_t* in = (lv_32fc_t*)volk_malloc(sizeof(lv_32fc_t)*N, alignment);
51  * double* re = (double*)volk_malloc(sizeof(double)*N, alignment);
52  * double* im = (double*)volk_malloc(sizeof(double)*N, alignment);
53  *
54  * for(unsigned int ii = 0; ii < N; ++ii){
55  * float real = 2.f * ((float)ii / (float)N) - 1.f;
56  * float imag = std::sqrt(1.f - real * real);
57  * in[ii] = lv_cmake(real, imag);
58  * }
59  *
60  * volk_32fc_deinterleave_64f_x2(re, im, in, N);
61  *
62  * printf(" re | im\n");
63  * for(unsigned int ii = 0; ii < N; ++ii){
64  * printf("out(%i) = %+.1g | %+.1g\n", ii, re[ii], im[ii]);
65  * }
66  *
67  * volk_free(in);
68  * volk_free(re);
69  * volk_free(im);
70  * \endcode
71  */
72 
73 #ifndef INCLUDED_volk_32fc_deinterleave_64f_x2_u_H
74 #define INCLUDED_volk_32fc_deinterleave_64f_x2_u_H
75 
76 #include <inttypes.h>
77 #include <stdio.h>
78 
79 #ifdef LV_HAVE_AVX
80 #include <immintrin.h>
81 
82 static inline void
83 volk_32fc_deinterleave_64f_x2_u_avx(double* iBuffer, double* qBuffer, const lv_32fc_t* complexVector,
84  unsigned int num_points)
85 {
86  unsigned int number = 0;
87 
88  const float* complexVectorPtr = (float*)complexVector;
89  double* iBufferPtr = iBuffer;
90  double* qBufferPtr = qBuffer;
91 
92  const unsigned int quarterPoints = num_points / 4;
93  __m256 cplxValue;
94  __m128 complexH, complexL, fVal;
95  __m256d dVal;
96 
97  for(;number < quarterPoints; number++){
98 
99  cplxValue = _mm256_loadu_ps(complexVectorPtr);
100  complexVectorPtr += 8;
101 
102  complexH = _mm256_extractf128_ps(cplxValue, 1);
103  complexL = _mm256_extractf128_ps(cplxValue, 0);
104 
105  // Arrange in i1i2i1i2 format
106  fVal = _mm_shuffle_ps(complexL, complexH, _MM_SHUFFLE(2,0,2,0));
107  dVal = _mm256_cvtps_pd(fVal);
108  _mm256_storeu_pd(iBufferPtr, dVal);
109 
110  // Arrange in q1q2q1q2 format
111  fVal = _mm_shuffle_ps(complexL, complexH, _MM_SHUFFLE(3,1,3,1));
112  dVal = _mm256_cvtps_pd(fVal);
113  _mm256_storeu_pd(qBufferPtr, dVal);
114 
115  iBufferPtr += 4;
116  qBufferPtr += 4;
117  }
118 
119  number = quarterPoints * 4;
120  for(; number < num_points; number++){
121  *iBufferPtr++ = *complexVectorPtr++;
122  *qBufferPtr++ = *complexVectorPtr++;
123  }
124 }
125 #endif /* LV_HAVE_AVX */
126 
127 #ifdef LV_HAVE_SSE2
128 #include <emmintrin.h>
129 
130 static inline void
131 volk_32fc_deinterleave_64f_x2_u_sse2(double* iBuffer, double* qBuffer, const lv_32fc_t* complexVector,
132  unsigned int num_points)
133 {
134  unsigned int number = 0;
135 
136  const float* complexVectorPtr = (float*)complexVector;
137  double* iBufferPtr = iBuffer;
138  double* qBufferPtr = qBuffer;
139 
140  const unsigned int halfPoints = num_points / 2;
141  __m128 cplxValue, fVal;
142  __m128d dVal;
143 
144  for(;number < halfPoints; number++){
145 
146  cplxValue = _mm_loadu_ps(complexVectorPtr);
147  complexVectorPtr += 4;
148 
149  // Arrange in i1i2i1i2 format
150  fVal = _mm_shuffle_ps(cplxValue, cplxValue, _MM_SHUFFLE(2,0,2,0));
151  dVal = _mm_cvtps_pd(fVal);
152  _mm_storeu_pd(iBufferPtr, dVal);
153 
154  // Arrange in q1q2q1q2 format
155  fVal = _mm_shuffle_ps(cplxValue, cplxValue, _MM_SHUFFLE(3,1,3,1));
156  dVal = _mm_cvtps_pd(fVal);
157  _mm_storeu_pd(qBufferPtr, dVal);
158 
159  iBufferPtr += 2;
160  qBufferPtr += 2;
161  }
162 
163  number = halfPoints * 2;
164  for(; number < num_points; number++){
165  *iBufferPtr++ = *complexVectorPtr++;
166  *qBufferPtr++ = *complexVectorPtr++;
167  }
168 }
169 #endif /* LV_HAVE_SSE */
170 
171 #ifdef LV_HAVE_GENERIC
172 
173 static inline void
174 volk_32fc_deinterleave_64f_x2_generic(double* iBuffer, double* qBuffer, const lv_32fc_t* complexVector,
175  unsigned int num_points)
176 {
177  unsigned int number = 0;
178  const float* complexVectorPtr = (float*)complexVector;
179  double* iBufferPtr = iBuffer;
180  double* qBufferPtr = qBuffer;
181 
182  for(number = 0; number < num_points; number++){
183  *iBufferPtr++ = (double)*complexVectorPtr++;
184  *qBufferPtr++ = (double)*complexVectorPtr++;
185  }
186 }
187 #endif /* LV_HAVE_GENERIC */
188 
189 
190 
191 
192 #endif /* INCLUDED_volk_32fc_deinterleave_64f_x2_u_H */
193 #ifndef INCLUDED_volk_32fc_deinterleave_64f_x2_a_H
194 #define INCLUDED_volk_32fc_deinterleave_64f_x2_a_H
195 
196 #include <inttypes.h>
197 #include <stdio.h>
198 
199 #ifdef LV_HAVE_AVX
200 #include <immintrin.h>
201 
202 static inline void
203 volk_32fc_deinterleave_64f_x2_a_avx(double* iBuffer, double* qBuffer, const lv_32fc_t* complexVector,
204  unsigned int num_points)
205 {
206  unsigned int number = 0;
207 
208  const float* complexVectorPtr = (float*)complexVector;
209  double* iBufferPtr = iBuffer;
210  double* qBufferPtr = qBuffer;
211 
212  const unsigned int quarterPoints = num_points / 4;
213  __m256 cplxValue;
214  __m128 complexH, complexL, fVal;
215  __m256d dVal;
216 
217  for(;number < quarterPoints; number++){
218 
219  cplxValue = _mm256_load_ps(complexVectorPtr);
220  complexVectorPtr += 8;
221 
222  complexH = _mm256_extractf128_ps(cplxValue, 1);
223  complexL = _mm256_extractf128_ps(cplxValue, 0);
224 
225  // Arrange in i1i2i1i2 format
226  fVal = _mm_shuffle_ps(complexL, complexH, _MM_SHUFFLE(2,0,2,0));
227  dVal = _mm256_cvtps_pd(fVal);
228  _mm256_store_pd(iBufferPtr, dVal);
229 
230  // Arrange in q1q2q1q2 format
231  fVal = _mm_shuffle_ps(complexL, complexH, _MM_SHUFFLE(3,1,3,1));
232  dVal = _mm256_cvtps_pd(fVal);
233  _mm256_store_pd(qBufferPtr, dVal);
234 
235  iBufferPtr += 4;
236  qBufferPtr += 4;
237  }
238 
239  number = quarterPoints * 4;
240  for(; number < num_points; number++){
241  *iBufferPtr++ = *complexVectorPtr++;
242  *qBufferPtr++ = *complexVectorPtr++;
243  }
244 }
245 #endif /* LV_HAVE_AVX */
246 
247 #ifdef LV_HAVE_SSE2
248 #include <emmintrin.h>
249 
250 static inline void
251 volk_32fc_deinterleave_64f_x2_a_sse2(double* iBuffer, double* qBuffer, const lv_32fc_t* complexVector,
252  unsigned int num_points)
253 {
254  unsigned int number = 0;
255 
256  const float* complexVectorPtr = (float*)complexVector;
257  double* iBufferPtr = iBuffer;
258  double* qBufferPtr = qBuffer;
259 
260  const unsigned int halfPoints = num_points / 2;
261  __m128 cplxValue, fVal;
262  __m128d dVal;
263 
264  for(;number < halfPoints; number++){
265 
266  cplxValue = _mm_load_ps(complexVectorPtr);
267  complexVectorPtr += 4;
268 
269  // Arrange in i1i2i1i2 format
270  fVal = _mm_shuffle_ps(cplxValue, cplxValue, _MM_SHUFFLE(2,0,2,0));
271  dVal = _mm_cvtps_pd(fVal);
272  _mm_store_pd(iBufferPtr, dVal);
273 
274  // Arrange in q1q2q1q2 format
275  fVal = _mm_shuffle_ps(cplxValue, cplxValue, _MM_SHUFFLE(3,1,3,1));
276  dVal = _mm_cvtps_pd(fVal);
277  _mm_store_pd(qBufferPtr, dVal);
278 
279  iBufferPtr += 2;
280  qBufferPtr += 2;
281  }
282 
283  number = halfPoints * 2;
284  for(; number < num_points; number++){
285  *iBufferPtr++ = *complexVectorPtr++;
286  *qBufferPtr++ = *complexVectorPtr++;
287  }
288 }
289 #endif /* LV_HAVE_SSE */
290 
291 #ifdef LV_HAVE_GENERIC
292 
293 static inline void
294 volk_32fc_deinterleave_64f_x2_a_generic(double* iBuffer, double* qBuffer, const lv_32fc_t* complexVector,
295  unsigned int num_points)
296 {
297  unsigned int number = 0;
298  const float* complexVectorPtr = (float*)complexVector;
299  double* iBufferPtr = iBuffer;
300  double* qBufferPtr = qBuffer;
301 
302  for(number = 0; number < num_points; number++){
303  *iBufferPtr++ = (double)*complexVectorPtr++;
304  *qBufferPtr++ = (double)*complexVectorPtr++;
305  }
306 }
307 #endif /* LV_HAVE_GENERIC */
308 
309 
310 #endif /* INCLUDED_volk_32fc_deinterleave_64f_x2_a_H */
float complex lv_32fc_t
Definition: volk_complex.h:56