GNU Radio Manual and C++ API Reference  3.7.6.1
The Free & Open Software Radio Ecosystem
volk_16ic_s32f_deinterleave_real_32f.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_16ic_s32f_deinterleave_real_32f_a_H
24 #define INCLUDED_volk_16ic_s32f_deinterleave_real_32f_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 16 bit vector into I float vector data
34  \param complexVector The complex input vector
35  \param iBuffer The I buffer output data
36  \param scalar The scaling value being multiplied against each data point
37  \param num_points The number of complex data values to be deinterleaved
38 */
39 static inline void volk_16ic_s32f_deinterleave_real_32f_a_sse4_1(float* iBuffer, const lv_16sc_t* complexVector, const float scalar, unsigned int num_points){
40  float* iBufferPtr = iBuffer;
41 
42  unsigned int number = 0;
43  const unsigned int quarterPoints = num_points / 4;
44 
45  __m128 iFloatValue;
46 
47  const float iScalar= 1.0 / scalar;
48  __m128 invScalar = _mm_set_ps1(iScalar);
49  __m128i complexVal, iIntVal;
50  int8_t* complexVectorPtr = (int8_t*)complexVector;
51 
52  __m128i moveMask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 13, 12, 9, 8, 5, 4, 1, 0);
53 
54  for(;number < quarterPoints; number++){
55  complexVal = _mm_load_si128((__m128i*)complexVectorPtr); complexVectorPtr += 16;
56  complexVal = _mm_shuffle_epi8(complexVal, moveMask);
57 
58  iIntVal = _mm_cvtepi16_epi32(complexVal);
59  iFloatValue = _mm_cvtepi32_ps(iIntVal);
60 
61  iFloatValue = _mm_mul_ps(iFloatValue, invScalar);
62 
63  _mm_store_ps(iBufferPtr, iFloatValue);
64 
65  iBufferPtr += 4;
66  }
67 
68  number = quarterPoints * 4;
69  int16_t* sixteenTComplexVectorPtr = (int16_t*)&complexVector[number];
70  for(; number < num_points; number++){
71  *iBufferPtr++ = ((float)(*sixteenTComplexVectorPtr++)) * iScalar;
72  sixteenTComplexVectorPtr++;
73  }
74 
75 }
76 #endif /* LV_HAVE_SSE4_1 */
77 
78 #ifdef LV_HAVE_SSE
79 #include <xmmintrin.h>
80 /*!
81  \brief Deinterleaves the complex 16 bit vector into I float vector data
82  \param complexVector The complex input vector
83  \param iBuffer The I buffer output data
84  \param scalar The scaling value being multiplied against each data point
85  \param num_points The number of complex data values to be deinterleaved
86 */
87 static inline void volk_16ic_s32f_deinterleave_real_32f_a_sse(float* iBuffer, const lv_16sc_t* complexVector, const float scalar, unsigned int num_points){
88  float* iBufferPtr = iBuffer;
89 
90  unsigned int number = 0;
91  const unsigned int quarterPoints = num_points / 4;
92  __m128 iValue;
93 
94  const float iScalar = 1.0/scalar;
95  __m128 invScalar = _mm_set_ps1(iScalar);
96  int16_t* complexVectorPtr = (int16_t*)complexVector;
97 
98  __VOLK_ATTR_ALIGNED(16) float floatBuffer[4];
99 
100  for(;number < quarterPoints; number++){
101  floatBuffer[0] = (float)(*complexVectorPtr); complexVectorPtr += 2;
102  floatBuffer[1] = (float)(*complexVectorPtr); complexVectorPtr += 2;
103  floatBuffer[2] = (float)(*complexVectorPtr); complexVectorPtr += 2;
104  floatBuffer[3] = (float)(*complexVectorPtr); complexVectorPtr += 2;
105 
106  iValue = _mm_load_ps(floatBuffer);
107 
108  iValue = _mm_mul_ps(iValue, invScalar);
109 
110  _mm_store_ps(iBufferPtr, iValue);
111 
112  iBufferPtr += 4;
113  }
114 
115  number = quarterPoints * 4;
116  complexVectorPtr = (int16_t*)&complexVector[number];
117  for(; number < num_points; number++){
118  *iBufferPtr++ = ((float)(*complexVectorPtr++)) * iScalar;
119  complexVectorPtr++;
120  }
121 
122 }
123 #endif /* LV_HAVE_SSE */
124 
125 #ifdef LV_HAVE_GENERIC
126 /*!
127  \brief Deinterleaves the complex 16 bit vector into I float vector data
128  \param complexVector The complex input vector
129  \param iBuffer The I buffer output data
130  \param scalar The scaling value being multiplied against each data point
131  \param num_points The number of complex data values to be deinterleaved
132 */
133 static inline void volk_16ic_s32f_deinterleave_real_32f_generic(float* iBuffer, const lv_16sc_t* complexVector, const float scalar, unsigned int num_points){
134  unsigned int number = 0;
135  const int16_t* complexVectorPtr = (const int16_t*)complexVector;
136  float* iBufferPtr = iBuffer;
137  const float invScalar = 1.0 / scalar;
138  for(number = 0; number < num_points; number++){
139  *iBufferPtr++ = ((float)(*complexVectorPtr++)) * invScalar;
140  complexVectorPtr++;
141  }
142 }
143 #endif /* LV_HAVE_GENERIC */
144 
145 
146 
147 
148 #endif /* INCLUDED_volk_16ic_s32f_deinterleave_real_32f_a_H */
short complex lv_16sc_t
Definition: volk_complex.h:53
signed short int16_t
Definition: stdint.h:76
signed char int8_t
Definition: stdint.h:75
#define __VOLK_ATTR_ALIGNED(x)
Definition: volk_common.h:27