GNU Radio Manual and C++ API Reference  3.7.6.1
The Free & Open Software Radio Ecosystem
volk_8ic_s32f_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_8ic_s32f_deinterleave_32f_x2_a_H
24 #define INCLUDED_volk_8ic_s32f_deinterleave_32f_x2_a_H
25 
26 #include <volk/volk_common.h>
27 #include <inttypes.h>
28 #include <stdio.h>
29 
30 #ifdef LV_HAVE_SSE4_1
31 #include <smmintrin.h>
32 /*!
33  \brief Deinterleaves the complex 8 bit vector into I & Q floating point vector data
34  \param complexVector The complex input vector
35  \param iBuffer The I buffer output data
36  \param qBuffer The Q buffer output data
37  \param scalar The scaling value being multiplied against each data point
38  \param num_points The number of complex data values to be deinterleaved
39 */
40 static inline void volk_8ic_s32f_deinterleave_32f_x2_a_sse4_1(float* iBuffer, float* qBuffer, const lv_8sc_t* complexVector, const float scalar, unsigned int num_points){
41  float* iBufferPtr = iBuffer;
42  float* qBufferPtr = qBuffer;
43 
44  unsigned int number = 0;
45  const unsigned int eighthPoints = num_points / 8;
46  __m128 iFloatValue, qFloatValue;
47 
48  const float iScalar= 1.0 / scalar;
49  __m128 invScalar = _mm_set_ps1(iScalar);
50  __m128i complexVal, iIntVal, qIntVal, iComplexVal, qComplexVal;
51  int8_t* complexVectorPtr = (int8_t*)complexVector;
52 
53  __m128i iMoveMask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 14, 12, 10, 8, 6, 4, 2, 0);
54  __m128i qMoveMask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 15, 13, 11, 9, 7, 5, 3, 1);
55 
56  for(;number < eighthPoints; number++){
57  complexVal = _mm_load_si128((__m128i*)complexVectorPtr); complexVectorPtr += 16;
58  iComplexVal = _mm_shuffle_epi8(complexVal, iMoveMask);
59  qComplexVal = _mm_shuffle_epi8(complexVal, qMoveMask);
60 
61  iIntVal = _mm_cvtepi8_epi32(iComplexVal);
62  iFloatValue = _mm_cvtepi32_ps(iIntVal);
63  iFloatValue = _mm_mul_ps(iFloatValue, invScalar);
64  _mm_store_ps(iBufferPtr, iFloatValue);
65  iBufferPtr += 4;
66 
67  iComplexVal = _mm_srli_si128(iComplexVal, 4);
68 
69  iIntVal = _mm_cvtepi8_epi32(iComplexVal);
70  iFloatValue = _mm_cvtepi32_ps(iIntVal);
71  iFloatValue = _mm_mul_ps(iFloatValue, invScalar);
72  _mm_store_ps(iBufferPtr, iFloatValue);
73  iBufferPtr += 4;
74 
75  qIntVal = _mm_cvtepi8_epi32(qComplexVal);
76  qFloatValue = _mm_cvtepi32_ps(qIntVal);
77  qFloatValue = _mm_mul_ps(qFloatValue, invScalar);
78  _mm_store_ps(qBufferPtr, qFloatValue);
79  qBufferPtr += 4;
80 
81  qComplexVal = _mm_srli_si128(qComplexVal, 4);
82 
83  qIntVal = _mm_cvtepi8_epi32(qComplexVal);
84  qFloatValue = _mm_cvtepi32_ps(qIntVal);
85  qFloatValue = _mm_mul_ps(qFloatValue, invScalar);
86  _mm_store_ps(qBufferPtr, qFloatValue);
87 
88  qBufferPtr += 4;
89  }
90 
91  number = eighthPoints * 8;
92  for(; number < num_points; number++){
93  *iBufferPtr++ = (float)(*complexVectorPtr++) * iScalar;
94  *qBufferPtr++ = (float)(*complexVectorPtr++) * iScalar;
95  }
96 
97 }
98 #endif /* LV_HAVE_SSE4_1 */
99 
100 #ifdef LV_HAVE_SSE
101 #include <xmmintrin.h>
102 /*!
103  \brief Deinterleaves the complex 8 bit vector into I & Q floating point vector data
104  \param complexVector The complex input vector
105  \param iBuffer The I buffer output data
106  \param qBuffer The Q buffer output data
107  \param scalar The scaling value being multiplied against each data point
108  \param num_points The number of complex data values to be deinterleaved
109 */
110 static inline void volk_8ic_s32f_deinterleave_32f_x2_a_sse(float* iBuffer, float* qBuffer, const lv_8sc_t* complexVector, const float scalar, unsigned int num_points){
111  float* iBufferPtr = iBuffer;
112  float* qBufferPtr = qBuffer;
113 
114  unsigned int number = 0;
115  const unsigned int quarterPoints = num_points / 4;
116  __m128 cplxValue1, cplxValue2, iValue, qValue;
117 
118  __m128 invScalar = _mm_set_ps1(1.0/scalar);
119  int8_t* complexVectorPtr = (int8_t*)complexVector;
120 
121  __VOLK_ATTR_ALIGNED(16) float floatBuffer[8];
122 
123  for(;number < quarterPoints; number++){
124  floatBuffer[0] = (float)(complexVectorPtr[0]);
125  floatBuffer[1] = (float)(complexVectorPtr[1]);
126  floatBuffer[2] = (float)(complexVectorPtr[2]);
127  floatBuffer[3] = (float)(complexVectorPtr[3]);
128 
129  floatBuffer[4] = (float)(complexVectorPtr[4]);
130  floatBuffer[5] = (float)(complexVectorPtr[5]);
131  floatBuffer[6] = (float)(complexVectorPtr[6]);
132  floatBuffer[7] = (float)(complexVectorPtr[7]);
133 
134  cplxValue1 = _mm_load_ps(&floatBuffer[0]);
135  cplxValue2 = _mm_load_ps(&floatBuffer[4]);
136 
137  complexVectorPtr += 8;
138 
139  cplxValue1 = _mm_mul_ps(cplxValue1, invScalar);
140  cplxValue2 = _mm_mul_ps(cplxValue2, invScalar);
141 
142  // Arrange in i1i2i3i4 format
143  iValue = _mm_shuffle_ps(cplxValue1, cplxValue2, _MM_SHUFFLE(2,0,2,0));
144  qValue = _mm_shuffle_ps(cplxValue1, cplxValue2, _MM_SHUFFLE(3,1,3,1));
145 
146  _mm_store_ps(iBufferPtr, iValue);
147  _mm_store_ps(qBufferPtr, qValue);
148 
149  iBufferPtr += 4;
150  qBufferPtr += 4;
151  }
152 
153  number = quarterPoints * 4;
154  complexVectorPtr = (int8_t*)&complexVector[number];
155  for(; number < num_points; number++){
156  *iBufferPtr++ = (float)(*complexVectorPtr++) / scalar;
157  *qBufferPtr++ = (float)(*complexVectorPtr++) / scalar;
158  }
159 }
160 #endif /* LV_HAVE_SSE */
161 
162 #ifdef LV_HAVE_GENERIC
163 /*!
164  \brief Deinterleaves the complex 8 bit vector into I & Q floating point vector data
165  \param complexVector The complex input vector
166  \param iBuffer The I buffer output data
167  \param qBuffer The Q buffer output data
168  \param scalar The scaling value being multiplied against each data point
169  \param num_points The number of complex data values to be deinterleaved
170 */
171 static inline void volk_8ic_s32f_deinterleave_32f_x2_generic(float* iBuffer, float* qBuffer, const lv_8sc_t* complexVector, const float scalar, unsigned int num_points){
172  const int8_t* complexVectorPtr = (const int8_t*)complexVector;
173  float* iBufferPtr = iBuffer;
174  float* qBufferPtr = qBuffer;
175  unsigned int number;
176  const float invScalar = 1.0 / scalar;
177  for(number = 0; number < num_points; number++){
178  *iBufferPtr++ = (float)(*complexVectorPtr++)*invScalar;
179  *qBufferPtr++ = (float)(*complexVectorPtr++)*invScalar;
180  }
181 }
182 #endif /* LV_HAVE_GENERIC */
183 
184 
185 
186 
187 #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