GNU Radio Manual and C++ API Reference  3.7.6.1
The Free & Open Software Radio Ecosystem
volk_32fc_deinterleave_32f_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_32f_x2_a_H
24 #define INCLUDED_volk_32fc_deinterleave_32f_x2_a_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 complex vector into 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_32f_x2_a_avx(float* iBuffer, float* qBuffer, const lv_32fc_t* complexVector, unsigned int num_points){
39  const float* complexVectorPtr = (float*)complexVector;
40  float* iBufferPtr = iBuffer;
41  float* qBufferPtr = qBuffer;
42 
43  unsigned int number = 0;
44  // Mask for real and imaginary parts
45  const unsigned int eighthPoints = num_points / 8;
46  __m256 cplxValue1, cplxValue2, complex1, complex2, iValue, qValue;
47  for(;number < eighthPoints; number++){
48 
49  cplxValue1 = _mm256_load_ps(complexVectorPtr);
50  complexVectorPtr += 8;
51 
52  cplxValue2 = _mm256_load_ps(complexVectorPtr);
53  complexVectorPtr += 8;
54 
55  complex1 = _mm256_permute2f128_ps(cplxValue1, cplxValue2, 0x20);
56  complex2 = _mm256_permute2f128_ps(cplxValue1, cplxValue2, 0x31);
57 
58  // Arrange in i1i2i3i4 format
59  iValue = _mm256_shuffle_ps(complex1, complex2, 0x88);
60  // Arrange in q1q2q3q4 format
61  qValue = _mm256_shuffle_ps(complex1, complex2, 0xdd);
62 
63  _mm256_store_ps(iBufferPtr, iValue);
64  _mm256_store_ps(qBufferPtr, qValue);
65 
66  iBufferPtr += 8;
67  qBufferPtr += 8;
68  }
69 
70  number = eighthPoints * 8;
71  for(; number < num_points; number++){
72  *iBufferPtr++ = *complexVectorPtr++;
73  *qBufferPtr++ = *complexVectorPtr++;
74  }
75 }
76 #endif /* LV_HAVE_AVX */
77 
78 #ifdef LV_HAVE_SSE
79 #include <xmmintrin.h>
80 /*!
81  \brief Deinterleaves the complex vector into I & Q 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 num_points The number of complex data values to be deinterleaved
86 */
87 static inline void volk_32fc_deinterleave_32f_x2_a_sse(float* iBuffer, float* qBuffer, const lv_32fc_t* complexVector, unsigned int num_points){
88  const float* complexVectorPtr = (float*)complexVector;
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  for(;number < quarterPoints; number++){
96 
97  cplxValue1 = _mm_load_ps(complexVectorPtr);
98  complexVectorPtr += 4;
99 
100  cplxValue2 = _mm_load_ps(complexVectorPtr);
101  complexVectorPtr += 4;
102 
103  // Arrange in i1i2i3i4 format
104  iValue = _mm_shuffle_ps(cplxValue1, cplxValue2, _MM_SHUFFLE(2,0,2,0));
105  // Arrange in q1q2q3q4 format
106  qValue = _mm_shuffle_ps(cplxValue1, cplxValue2, _MM_SHUFFLE(3,1,3,1));
107 
108  _mm_store_ps(iBufferPtr, iValue);
109  _mm_store_ps(qBufferPtr, qValue);
110 
111  iBufferPtr += 4;
112  qBufferPtr += 4;
113  }
114 
115  number = quarterPoints * 4;
116  for(; number < num_points; number++){
117  *iBufferPtr++ = *complexVectorPtr++;
118  *qBufferPtr++ = *complexVectorPtr++;
119  }
120 }
121 #endif /* LV_HAVE_SSE */
122 
123 #ifdef LV_HAVE_NEON
124 #include <arm_neon.h>
125 /*!
126  \brief Deinterleaves the complex vector into I & Q vector data
127  \param complexVector The complex input vector
128  \param iBuffer The I buffer output data
129  \param qBuffer The Q buffer output data
130  \param num_points The number of complex data values to be deinterleaved
131 */
132 static inline void volk_32fc_deinterleave_32f_x2_neon(float* iBuffer, float* qBuffer, const lv_32fc_t* complexVector, unsigned int num_points){
133  unsigned int number = 0;
134  unsigned int quarter_points = num_points / 4;
135  const float* complexVectorPtr = (float*)complexVector;
136  float* iBufferPtr = iBuffer;
137  float* qBufferPtr = qBuffer;
138  float32x4x2_t complexInput;
139 
140  for(number = 0; number < quarter_points; number++){
141  complexInput = vld2q_f32(complexVectorPtr);
142  vst1q_f32( iBufferPtr, complexInput.val[0] );
143  vst1q_f32( qBufferPtr, complexInput.val[1] );
144  complexVectorPtr += 8;
145  iBufferPtr += 4;
146  qBufferPtr += 4;
147  }
148 
149  for(number = quarter_points*4; number < num_points; number++){
150  *iBufferPtr++ = *complexVectorPtr++;
151  *qBufferPtr++ = *complexVectorPtr++;
152  }
153 }
154 #endif /* LV_HAVE_NEON */
155 
156 #ifdef LV_HAVE_GENERIC
157 /*!
158  \brief Deinterleaves the complex vector into I & Q vector data
159  \param complexVector The complex input vector
160  \param iBuffer The I buffer output data
161  \param qBuffer The Q buffer output data
162  \param num_points The number of complex data values to be deinterleaved
163 */
164 static inline void volk_32fc_deinterleave_32f_x2_generic(float* iBuffer, float* qBuffer, const lv_32fc_t* complexVector, unsigned int num_points){
165  const float* complexVectorPtr = (float*)complexVector;
166  float* iBufferPtr = iBuffer;
167  float* qBufferPtr = qBuffer;
168  unsigned int number;
169  for(number = 0; number < num_points; number++){
170  *iBufferPtr++ = *complexVectorPtr++;
171  *qBufferPtr++ = *complexVectorPtr++;
172  }
173 }
174 #endif /* LV_HAVE_GENERIC */
175 
176 
177 
178 
179 #endif /* INCLUDED_volk_32fc_deinterleave_32f_x2_a_H */
float complex lv_32fc_t
Definition: volk_complex.h:56