GNU Radio Manual and C++ API Reference  3.7.6.1
The Free & Open Software Radio Ecosystem
volk_32f_x2_s32f_interleave_16ic.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_32f_x2_s32f_interleave_16ic_a_H
24 #define INCLUDED_volk_32f_x2_s32f_interleave_16ic_a_H
25 
26 #include <volk/volk_common.h>
27 #include <inttypes.h>
28 #include <stdio.h>
29 
30 #ifdef LV_HAVE_SSE2
31 #include <emmintrin.h>
32  /*!
33  \brief Interleaves the I & Q vector data into the complex vector, scales the output values by the scalar, and converts to 16 bit data.
34  \param iBuffer The I buffer data to be interleaved
35  \param qBuffer The Q buffer data to be interleaved
36  \param complexVector The complex output vector
37  \param scalar The scaling value being multiplied against each data point
38  \param num_points The number of complex data values to be interleaved
39  */
40 static inline void volk_32f_x2_s32f_interleave_16ic_a_sse2(lv_16sc_t* complexVector, const float* iBuffer, const float* qBuffer, const float scalar, unsigned int num_points){
41  unsigned int number = 0;
42  const float* iBufferPtr = iBuffer;
43  const float* qBufferPtr = qBuffer;
44 
45  __m128 vScalar = _mm_set_ps1(scalar);
46 
47  const unsigned int quarterPoints = num_points / 4;
48 
49  __m128 iValue, qValue, cplxValue1, cplxValue2;
50  __m128i intValue1, intValue2;
51 
52  int16_t* complexVectorPtr = (int16_t*)complexVector;
53 
54  for(;number < quarterPoints; number++){
55  iValue = _mm_load_ps(iBufferPtr);
56  qValue = _mm_load_ps(qBufferPtr);
57 
58  // Interleaves the lower two values in the i and q variables into one buffer
59  cplxValue1 = _mm_unpacklo_ps(iValue, qValue);
60  cplxValue1 = _mm_mul_ps(cplxValue1, vScalar);
61 
62  // Interleaves the upper two values in the i and q variables into one buffer
63  cplxValue2 = _mm_unpackhi_ps(iValue, qValue);
64  cplxValue2 = _mm_mul_ps(cplxValue2, vScalar);
65 
66  intValue1 = _mm_cvtps_epi32(cplxValue1);
67  intValue2 = _mm_cvtps_epi32(cplxValue2);
68 
69  intValue1 = _mm_packs_epi32(intValue1, intValue2);
70 
71  _mm_store_si128((__m128i*)complexVectorPtr, intValue1);
72  complexVectorPtr += 8;
73 
74  iBufferPtr += 4;
75  qBufferPtr += 4;
76  }
77 
78  number = quarterPoints * 4;
79  complexVectorPtr = (int16_t*)(&complexVector[number]);
80  for(; number < num_points; number++){
81  *complexVectorPtr++ = (int16_t)(*iBufferPtr++ * scalar);
82  *complexVectorPtr++ = (int16_t)(*qBufferPtr++ * scalar);
83  }
84 
85 }
86 #endif /* LV_HAVE_SSE2 */
87 
88 #ifdef LV_HAVE_SSE
89 #include <xmmintrin.h>
90  /*!
91  \brief Interleaves the I & Q vector data into the complex vector, scales the output values by the scalar, and converts to 16 bit data.
92  \param iBuffer The I buffer data to be interleaved
93  \param qBuffer The Q buffer data to be interleaved
94  \param complexVector The complex output vector
95  \param scalar The scaling value being multiplied against each data point
96  \param num_points The number of complex data values to be interleaved
97  */
98 static inline void volk_32f_x2_s32f_interleave_16ic_a_sse(lv_16sc_t* complexVector, const float* iBuffer, const float* qBuffer, const float scalar, unsigned int num_points){
99  unsigned int number = 0;
100  const float* iBufferPtr = iBuffer;
101  const float* qBufferPtr = qBuffer;
102 
103  __m128 vScalar = _mm_set_ps1(scalar);
104 
105  const unsigned int quarterPoints = num_points / 4;
106 
107  __m128 iValue, qValue, cplxValue;
108 
109  int16_t* complexVectorPtr = (int16_t*)complexVector;
110 
111  __VOLK_ATTR_ALIGNED(16) float floatBuffer[4];
112 
113  for(;number < quarterPoints; number++){
114  iValue = _mm_load_ps(iBufferPtr);
115  qValue = _mm_load_ps(qBufferPtr);
116 
117  // Interleaves the lower two values in the i and q variables into one buffer
118  cplxValue = _mm_unpacklo_ps(iValue, qValue);
119  cplxValue = _mm_mul_ps(cplxValue, vScalar);
120 
121  _mm_store_ps(floatBuffer, cplxValue);
122 
123  *complexVectorPtr++ = (int16_t)(floatBuffer[0]);
124  *complexVectorPtr++ = (int16_t)(floatBuffer[1]);
125  *complexVectorPtr++ = (int16_t)(floatBuffer[2]);
126  *complexVectorPtr++ = (int16_t)(floatBuffer[3]);
127 
128  // Interleaves the upper two values in the i and q variables into one buffer
129  cplxValue = _mm_unpackhi_ps(iValue, qValue);
130  cplxValue = _mm_mul_ps(cplxValue, vScalar);
131 
132  _mm_store_ps(floatBuffer, cplxValue);
133 
134  *complexVectorPtr++ = (int16_t)(floatBuffer[0]);
135  *complexVectorPtr++ = (int16_t)(floatBuffer[1]);
136  *complexVectorPtr++ = (int16_t)(floatBuffer[2]);
137  *complexVectorPtr++ = (int16_t)(floatBuffer[3]);
138 
139  iBufferPtr += 4;
140  qBufferPtr += 4;
141  }
142 
143  number = quarterPoints * 4;
144  complexVectorPtr = (int16_t*)(&complexVector[number]);
145  for(; number < num_points; number++){
146  *complexVectorPtr++ = (int16_t)(*iBufferPtr++ * scalar);
147  *complexVectorPtr++ = (int16_t)(*qBufferPtr++ * scalar);
148  }
149 
150 }
151 #endif /* LV_HAVE_SSE */
152 
153 #ifdef LV_HAVE_GENERIC
154  /*!
155  \brief Interleaves the I & Q vector data into the complex vector, scales the output values by the scalar, and converts to 16 bit data.
156  \param iBuffer The I buffer data to be interleaved
157  \param qBuffer The Q buffer data to be interleaved
158  \param complexVector The complex output vector
159  \param scalar The scaling value being multiplied against each data point
160  \param num_points The number of complex data values to be interleaved
161  */
162 static inline void volk_32f_x2_s32f_interleave_16ic_generic(lv_16sc_t* complexVector, const float* iBuffer, const float* qBuffer, const float scalar, unsigned int num_points){
163  int16_t* complexVectorPtr = (int16_t*)complexVector;
164  const float* iBufferPtr = iBuffer;
165  const float* qBufferPtr = qBuffer;
166  unsigned int number = 0;
167 
168  for(number = 0; number < num_points; number++){
169  *complexVectorPtr++ = (int16_t)(*iBufferPtr++ * scalar);
170  *complexVectorPtr++ = (int16_t)(*qBufferPtr++ * scalar);
171  }
172 }
173 #endif /* LV_HAVE_GENERIC */
174 
175 
176 
177 
178 #endif /* INCLUDED_volk_32f_x2_s32f_interleave_16ic_a_H */
short complex lv_16sc_t
Definition: volk_complex.h:53
signed short int16_t
Definition: stdint.h:76
#define __VOLK_ATTR_ALIGNED(x)
Definition: volk_common.h:27