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_16ic_s32f_deinterleave_real_32f.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_16ic_s32f_deinterleave_real_32f
25  *
26  * \b Overview
27  *
28  * Deinterleaves the complex 16 bit vector and returns just the real
29  * part (inphase) of the data as a vector of floats that have been
30  * scaled.
31  *
32  * <b>Dispatcher Prototype</b>
33  * \code
34  * void volk_16ic_s32f_deinterleave_real_32f(float* iBuffer, const lv_16sc_t* complexVector, const float scalar, unsigned int num_points){
35  * \endcode
36  *
37  * \b Inputs
38  * \li complexVector: The complex input vector of 16-bit shorts.
39  * \li scalar: The value to be divided against each sample of the input complex vector.
40  * \li num_points: The number of complex data values to be deinterleaved.
41  *
42  * \b Outputs
43  * \li iBuffer: The floating point I buffer output data.
44  *
45  * \b Example
46  * \code
47  * int N = 10000;
48  *
49  * volk_16ic_s32f_deinterleave_real_32f();
50  *
51  * volk_free(x);
52  * volk_free(t);
53  * \endcode
54  */
55 
56 #ifndef INCLUDED_volk_16ic_s32f_deinterleave_real_32f_a_H
57 #define INCLUDED_volk_16ic_s32f_deinterleave_real_32f_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_16ic_s32f_deinterleave_real_32f_a_sse4_1(float* iBuffer, const lv_16sc_t* complexVector,
68  const float scalar, unsigned int num_points)
69 {
70  float* iBufferPtr = iBuffer;
71 
72  unsigned int number = 0;
73  const unsigned int quarterPoints = num_points / 4;
74 
75  __m128 iFloatValue;
76 
77  const float iScalar= 1.0 / scalar;
78  __m128 invScalar = _mm_set_ps1(iScalar);
79  __m128i complexVal, iIntVal;
80  int8_t* complexVectorPtr = (int8_t*)complexVector;
81 
82  __m128i moveMask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 13, 12, 9, 8, 5, 4, 1, 0);
83 
84  for(;number < quarterPoints; number++){
85  complexVal = _mm_load_si128((__m128i*)complexVectorPtr); complexVectorPtr += 16;
86  complexVal = _mm_shuffle_epi8(complexVal, moveMask);
87 
88  iIntVal = _mm_cvtepi16_epi32(complexVal);
89  iFloatValue = _mm_cvtepi32_ps(iIntVal);
90 
91  iFloatValue = _mm_mul_ps(iFloatValue, invScalar);
92 
93  _mm_store_ps(iBufferPtr, iFloatValue);
94 
95  iBufferPtr += 4;
96  }
97 
98  number = quarterPoints * 4;
99  int16_t* sixteenTComplexVectorPtr = (int16_t*)&complexVector[number];
100  for(; number < num_points; number++){
101  *iBufferPtr++ = ((float)(*sixteenTComplexVectorPtr++)) * iScalar;
102  sixteenTComplexVectorPtr++;
103  }
104 
105 }
106 #endif /* LV_HAVE_SSE4_1 */
107 
108 #ifdef LV_HAVE_SSE
109 #include <xmmintrin.h>
110 
111 static inline void
112 volk_16ic_s32f_deinterleave_real_32f_a_sse(float* iBuffer, const lv_16sc_t* complexVector,
113  const float scalar, unsigned int num_points)
114 {
115  float* iBufferPtr = iBuffer;
116 
117  unsigned int number = 0;
118  const unsigned int quarterPoints = num_points / 4;
119  __m128 iValue;
120 
121  const float iScalar = 1.0/scalar;
122  __m128 invScalar = _mm_set_ps1(iScalar);
123  int16_t* complexVectorPtr = (int16_t*)complexVector;
124 
125  __VOLK_ATTR_ALIGNED(16) float floatBuffer[4];
126 
127  for(;number < quarterPoints; number++){
128  floatBuffer[0] = (float)(*complexVectorPtr); complexVectorPtr += 2;
129  floatBuffer[1] = (float)(*complexVectorPtr); complexVectorPtr += 2;
130  floatBuffer[2] = (float)(*complexVectorPtr); complexVectorPtr += 2;
131  floatBuffer[3] = (float)(*complexVectorPtr); complexVectorPtr += 2;
132 
133  iValue = _mm_load_ps(floatBuffer);
134 
135  iValue = _mm_mul_ps(iValue, invScalar);
136 
137  _mm_store_ps(iBufferPtr, iValue);
138 
139  iBufferPtr += 4;
140  }
141 
142  number = quarterPoints * 4;
143  complexVectorPtr = (int16_t*)&complexVector[number];
144  for(; number < num_points; number++){
145  *iBufferPtr++ = ((float)(*complexVectorPtr++)) * iScalar;
146  complexVectorPtr++;
147  }
148 
149 }
150 #endif /* LV_HAVE_SSE */
151 
152 #ifdef LV_HAVE_GENERIC
153 static inline void
154 volk_16ic_s32f_deinterleave_real_32f_generic(float* iBuffer, const lv_16sc_t* complexVector,
155  const float scalar, unsigned int num_points)
156 {
157  unsigned int number = 0;
158  const int16_t* complexVectorPtr = (const int16_t*)complexVector;
159  float* iBufferPtr = iBuffer;
160  const float invScalar = 1.0 / scalar;
161  for(number = 0; number < num_points; number++){
162  *iBufferPtr++ = ((float)(*complexVectorPtr++)) * invScalar;
163  complexVectorPtr++;
164  }
165 }
166 #endif /* LV_HAVE_GENERIC */
167 
168 
169 #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