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_8ic_s32f_deinterleave_32f_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_8ic_s32f_deinterleave_32f_x2
25  *
26  * \b Overview
27  *
28  * Deinterleaves the complex 8-bit char vector into I & Q vector data,
29  * converts them to floats, and divides the results by the scalar
30  * factor.
31  *
32  * <b>Dispatcher Prototype</b>
33  * \code
34  * void volk_8ic_s32f_deinterleave_32f_x2(float* iBuffer, float* qBuffer, const lv_8sc_t* complexVector, const float scalar, unsigned int num_points)
35  * \endcode
36  *
37  * \b Inputs
38  * \li complexVector: The complex input vector.
39  * \li scalar: The scalar value used to divide the floating point results.
40  * \li num_points: The number of complex data values to be deinterleaved.
41  *
42  * \b Outputs
43  * \li iBuffer: The I buffer output data.
44  * \li qBuffer: The Q buffer output data.
45  *
46  * \b Example
47  * \code
48  * int N = 10000;
49  *
50  * volk_8ic_s32f_deinterleave_32f_x2();
51  *
52  * volk_free(x);
53  * \endcode
54  */
55 
56 #ifndef INCLUDED_volk_8ic_s32f_deinterleave_32f_x2_a_H
57 #define INCLUDED_volk_8ic_s32f_deinterleave_32f_x2_a_H
58 
59 #include <volk/volk_common.h>
60 #include <inttypes.h>
61 #include <stdio.h>
62 
63 #ifdef LV_HAVE_SSE4_1
64 #include <smmintrin.h>
65 
66 static inline void
67 volk_8ic_s32f_deinterleave_32f_x2_a_sse4_1(float* iBuffer, float* qBuffer, const lv_8sc_t* complexVector,
68  const float scalar, unsigned int num_points)
69 {
70  float* iBufferPtr = iBuffer;
71  float* qBufferPtr = qBuffer;
72 
73  unsigned int number = 0;
74  const unsigned int eighthPoints = num_points / 8;
75  __m128 iFloatValue, qFloatValue;
76 
77  const float iScalar= 1.0 / scalar;
78  __m128 invScalar = _mm_set_ps1(iScalar);
79  __m128i complexVal, iIntVal, qIntVal, iComplexVal, qComplexVal;
80  int8_t* complexVectorPtr = (int8_t*)complexVector;
81 
82  __m128i iMoveMask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 14, 12, 10, 8, 6, 4, 2, 0);
83  __m128i qMoveMask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 15, 13, 11, 9, 7, 5, 3, 1);
84 
85  for(;number < eighthPoints; number++){
86  complexVal = _mm_load_si128((__m128i*)complexVectorPtr); complexVectorPtr += 16;
87  iComplexVal = _mm_shuffle_epi8(complexVal, iMoveMask);
88  qComplexVal = _mm_shuffle_epi8(complexVal, qMoveMask);
89 
90  iIntVal = _mm_cvtepi8_epi32(iComplexVal);
91  iFloatValue = _mm_cvtepi32_ps(iIntVal);
92  iFloatValue = _mm_mul_ps(iFloatValue, invScalar);
93  _mm_store_ps(iBufferPtr, iFloatValue);
94  iBufferPtr += 4;
95 
96  iComplexVal = _mm_srli_si128(iComplexVal, 4);
97 
98  iIntVal = _mm_cvtepi8_epi32(iComplexVal);
99  iFloatValue = _mm_cvtepi32_ps(iIntVal);
100  iFloatValue = _mm_mul_ps(iFloatValue, invScalar);
101  _mm_store_ps(iBufferPtr, iFloatValue);
102  iBufferPtr += 4;
103 
104  qIntVal = _mm_cvtepi8_epi32(qComplexVal);
105  qFloatValue = _mm_cvtepi32_ps(qIntVal);
106  qFloatValue = _mm_mul_ps(qFloatValue, invScalar);
107  _mm_store_ps(qBufferPtr, qFloatValue);
108  qBufferPtr += 4;
109 
110  qComplexVal = _mm_srli_si128(qComplexVal, 4);
111 
112  qIntVal = _mm_cvtepi8_epi32(qComplexVal);
113  qFloatValue = _mm_cvtepi32_ps(qIntVal);
114  qFloatValue = _mm_mul_ps(qFloatValue, invScalar);
115  _mm_store_ps(qBufferPtr, qFloatValue);
116 
117  qBufferPtr += 4;
118  }
119 
120  number = eighthPoints * 8;
121  for(; number < num_points; number++){
122  *iBufferPtr++ = (float)(*complexVectorPtr++) * iScalar;
123  *qBufferPtr++ = (float)(*complexVectorPtr++) * iScalar;
124  }
125 
126 }
127 #endif /* LV_HAVE_SSE4_1 */
128 
129 
130 #ifdef LV_HAVE_SSE
131 #include <xmmintrin.h>
132 
133 static inline void
134 volk_8ic_s32f_deinterleave_32f_x2_a_sse(float* iBuffer, float* qBuffer,
135  const lv_8sc_t* complexVector,
136  const float scalar, unsigned int num_points)
137 {
138  float* iBufferPtr = iBuffer;
139  float* qBufferPtr = qBuffer;
140 
141  unsigned int number = 0;
142  const unsigned int quarterPoints = num_points / 4;
143  __m128 cplxValue1, cplxValue2, iValue, qValue;
144 
145  __m128 invScalar = _mm_set_ps1(1.0/scalar);
146  int8_t* complexVectorPtr = (int8_t*)complexVector;
147 
148  __VOLK_ATTR_ALIGNED(16) float floatBuffer[8];
149 
150  for(;number < quarterPoints; number++){
151  floatBuffer[0] = (float)(complexVectorPtr[0]);
152  floatBuffer[1] = (float)(complexVectorPtr[1]);
153  floatBuffer[2] = (float)(complexVectorPtr[2]);
154  floatBuffer[3] = (float)(complexVectorPtr[3]);
155 
156  floatBuffer[4] = (float)(complexVectorPtr[4]);
157  floatBuffer[5] = (float)(complexVectorPtr[5]);
158  floatBuffer[6] = (float)(complexVectorPtr[6]);
159  floatBuffer[7] = (float)(complexVectorPtr[7]);
160 
161  cplxValue1 = _mm_load_ps(&floatBuffer[0]);
162  cplxValue2 = _mm_load_ps(&floatBuffer[4]);
163 
164  complexVectorPtr += 8;
165 
166  cplxValue1 = _mm_mul_ps(cplxValue1, invScalar);
167  cplxValue2 = _mm_mul_ps(cplxValue2, invScalar);
168 
169  // Arrange in i1i2i3i4 format
170  iValue = _mm_shuffle_ps(cplxValue1, cplxValue2, _MM_SHUFFLE(2,0,2,0));
171  qValue = _mm_shuffle_ps(cplxValue1, cplxValue2, _MM_SHUFFLE(3,1,3,1));
172 
173  _mm_store_ps(iBufferPtr, iValue);
174  _mm_store_ps(qBufferPtr, qValue);
175 
176  iBufferPtr += 4;
177  qBufferPtr += 4;
178  }
179 
180  number = quarterPoints * 4;
181  complexVectorPtr = (int8_t*)&complexVector[number];
182  for(; number < num_points; number++){
183  *iBufferPtr++ = (float)(*complexVectorPtr++) / scalar;
184  *qBufferPtr++ = (float)(*complexVectorPtr++) / scalar;
185  }
186 }
187 #endif /* LV_HAVE_SSE */
188 
189 
190 #ifdef LV_HAVE_GENERIC
191 
192 static inline void
193 volk_8ic_s32f_deinterleave_32f_x2_generic(float* iBuffer, float* qBuffer,
194  const lv_8sc_t* complexVector,
195  const float scalar, unsigned int num_points)
196 {
197  const int8_t* complexVectorPtr = (const int8_t*)complexVector;
198  float* iBufferPtr = iBuffer;
199  float* qBufferPtr = qBuffer;
200  unsigned int number;
201  const float invScalar = 1.0 / scalar;
202  for(number = 0; number < num_points; number++){
203  *iBufferPtr++ = (float)(*complexVectorPtr++)*invScalar;
204  *qBufferPtr++ = (float)(*complexVectorPtr++)*invScalar;
205  }
206 }
207 #endif /* LV_HAVE_GENERIC */
208 
209 
210 
211 
212 #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