GNU Radio Manual and C++ API Reference  3.7.6.1
The Free & Open Software Radio Ecosystem
volk_16ic_magnitude_16i.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_magnitude_16i_a_H
24 #define INCLUDED_volk_16ic_magnitude_16i_a_H
25 
26 #include <volk/volk_common.h>
27 #include <inttypes.h>
28 #include <stdio.h>
29 #include <math.h>
30 
31 #ifdef LV_HAVE_SSE3
32 #include <pmmintrin.h>
33 /*!
34  \brief Calculates the magnitude of the complexVector and stores the results in the magnitudeVector
35  \param complexVector The vector containing the complex input values
36  \param magnitudeVector The vector containing the real output values
37  \param num_points The number of complex values in complexVector to be calculated and stored into cVector
38 */
39 static inline void volk_16ic_magnitude_16i_a_sse3(int16_t* magnitudeVector, const lv_16sc_t* complexVector, unsigned int num_points){
40  unsigned int number = 0;
41  const unsigned int quarterPoints = num_points / 4;
42 
43  const int16_t* complexVectorPtr = (const int16_t*)complexVector;
44  int16_t* magnitudeVectorPtr = magnitudeVector;
45 
46  __m128 vScalar = _mm_set_ps1(32768.0);
47  __m128 invScalar = _mm_set_ps1(1.0/32768.0);
48 
49  __m128 cplxValue1, cplxValue2, result;
50 
51  __VOLK_ATTR_ALIGNED(16) float inputFloatBuffer[8];
52  __VOLK_ATTR_ALIGNED(16) float outputFloatBuffer[4];
53 
54  for(;number < quarterPoints; number++){
55 
56  inputFloatBuffer[0] = (float)(complexVectorPtr[0]);
57  inputFloatBuffer[1] = (float)(complexVectorPtr[1]);
58  inputFloatBuffer[2] = (float)(complexVectorPtr[2]);
59  inputFloatBuffer[3] = (float)(complexVectorPtr[3]);
60 
61  inputFloatBuffer[4] = (float)(complexVectorPtr[4]);
62  inputFloatBuffer[5] = (float)(complexVectorPtr[5]);
63  inputFloatBuffer[6] = (float)(complexVectorPtr[6]);
64  inputFloatBuffer[7] = (float)(complexVectorPtr[7]);
65 
66  cplxValue1 = _mm_load_ps(&inputFloatBuffer[0]);
67  cplxValue2 = _mm_load_ps(&inputFloatBuffer[4]);
68 
69  complexVectorPtr += 8;
70 
71  cplxValue1 = _mm_mul_ps(cplxValue1, invScalar);
72  cplxValue2 = _mm_mul_ps(cplxValue2, invScalar);
73 
74  cplxValue1 = _mm_mul_ps(cplxValue1, cplxValue1); // Square the values
75  cplxValue2 = _mm_mul_ps(cplxValue2, cplxValue2); // Square the Values
76 
77  result = _mm_hadd_ps(cplxValue1, cplxValue2); // Add the I2 and Q2 values
78 
79  result = _mm_sqrt_ps(result); // Square root the values
80 
81  result = _mm_mul_ps(result, vScalar); // Scale the results
82 
83  _mm_store_ps(outputFloatBuffer, result);
84  *magnitudeVectorPtr++ = (int16_t)(outputFloatBuffer[0]);
85  *magnitudeVectorPtr++ = (int16_t)(outputFloatBuffer[1]);
86  *magnitudeVectorPtr++ = (int16_t)(outputFloatBuffer[2]);
87  *magnitudeVectorPtr++ = (int16_t)(outputFloatBuffer[3]);
88  }
89 
90  number = quarterPoints * 4;
91  magnitudeVectorPtr = &magnitudeVector[number];
92  complexVectorPtr = (const int16_t*)&complexVector[number];
93  for(; number < num_points; number++){
94  const float val1Real = (float)(*complexVectorPtr++) / 32768.0;
95  const float val1Imag = (float)(*complexVectorPtr++) / 32768.0;
96  const float val1Result = sqrtf((val1Real * val1Real) + (val1Imag * val1Imag)) * 32768.0;
97  *magnitudeVectorPtr++ = (int16_t)(val1Result);
98  }
99 }
100 #endif /* LV_HAVE_SSE3 */
101 
102 #ifdef LV_HAVE_SSE
103 #include <xmmintrin.h>
104 /*!
105  \brief Calculates the magnitude of the complexVector and stores the results in the magnitudeVector
106  \param complexVector The vector containing the complex input values
107  \param magnitudeVector The vector containing the real output values
108  \param num_points The number of complex values in complexVector to be calculated and stored into cVector
109 */
110 static inline void volk_16ic_magnitude_16i_a_sse(int16_t* magnitudeVector, const lv_16sc_t* complexVector, unsigned int num_points){
111  unsigned int number = 0;
112  const unsigned int quarterPoints = num_points / 4;
113 
114  const int16_t* complexVectorPtr = (const int16_t*)complexVector;
115  int16_t* magnitudeVectorPtr = magnitudeVector;
116 
117  __m128 vScalar = _mm_set_ps1(32768.0);
118  __m128 invScalar = _mm_set_ps1(1.0/32768.0);
119 
120  __m128 cplxValue1, cplxValue2, iValue, qValue, result;
121 
122  __VOLK_ATTR_ALIGNED(16) float inputFloatBuffer[4];
123  __VOLK_ATTR_ALIGNED(16) float outputFloatBuffer[4];
124 
125  for(;number < quarterPoints; number++){
126 
127  inputFloatBuffer[0] = (float)(complexVectorPtr[0]);
128  inputFloatBuffer[1] = (float)(complexVectorPtr[1]);
129  inputFloatBuffer[2] = (float)(complexVectorPtr[2]);
130  inputFloatBuffer[3] = (float)(complexVectorPtr[3]);
131 
132  cplxValue1 = _mm_load_ps(inputFloatBuffer);
133  complexVectorPtr += 4;
134 
135  inputFloatBuffer[0] = (float)(complexVectorPtr[0]);
136  inputFloatBuffer[1] = (float)(complexVectorPtr[1]);
137  inputFloatBuffer[2] = (float)(complexVectorPtr[2]);
138  inputFloatBuffer[3] = (float)(complexVectorPtr[3]);
139 
140  cplxValue2 = _mm_load_ps(inputFloatBuffer);
141  complexVectorPtr += 4;
142 
143  cplxValue1 = _mm_mul_ps(cplxValue1, invScalar);
144  cplxValue2 = _mm_mul_ps(cplxValue2, invScalar);
145 
146  // Arrange in i1i2i3i4 format
147  iValue = _mm_shuffle_ps(cplxValue1, cplxValue2, _MM_SHUFFLE(2,0,2,0));
148  // Arrange in q1q2q3q4 format
149  qValue = _mm_shuffle_ps(cplxValue1, cplxValue2, _MM_SHUFFLE(3,1,3,1));
150 
151  iValue = _mm_mul_ps(iValue, iValue); // Square the I values
152  qValue = _mm_mul_ps(qValue, qValue); // Square the Q Values
153 
154  result = _mm_add_ps(iValue, qValue); // Add the I2 and Q2 values
155 
156  result = _mm_sqrt_ps(result); // Square root the values
157 
158  result = _mm_mul_ps(result, vScalar); // Scale the results
159 
160  _mm_store_ps(outputFloatBuffer, result);
161  *magnitudeVectorPtr++ = (int16_t)(outputFloatBuffer[0]);
162  *magnitudeVectorPtr++ = (int16_t)(outputFloatBuffer[1]);
163  *magnitudeVectorPtr++ = (int16_t)(outputFloatBuffer[2]);
164  *magnitudeVectorPtr++ = (int16_t)(outputFloatBuffer[3]);
165  }
166 
167  number = quarterPoints * 4;
168  magnitudeVectorPtr = &magnitudeVector[number];
169  complexVectorPtr = (const int16_t*)&complexVector[number];
170  for(; number < num_points; number++){
171  const float val1Real = (float)(*complexVectorPtr++) / 32768.0;
172  const float val1Imag = (float)(*complexVectorPtr++) / 32768.0;
173  const float val1Result = sqrtf((val1Real * val1Real) + (val1Imag * val1Imag)) * 32768.0;
174  *magnitudeVectorPtr++ = (int16_t)(val1Result);
175  }
176 }
177 #endif /* LV_HAVE_SSE */
178 
179 #ifdef LV_HAVE_GENERIC
180 /*!
181  \brief Calculates the magnitude of the complexVector and stores the results in the magnitudeVector
182  \param complexVector The vector containing the complex input values
183  \param magnitudeVector The vector containing the real output values
184  \param num_points The number of complex values in complexVector to be calculated and stored into cVector
185 */
186 static inline void volk_16ic_magnitude_16i_generic(int16_t* magnitudeVector, const lv_16sc_t* complexVector, unsigned int num_points){
187  const int16_t* complexVectorPtr = (const int16_t*)complexVector;
188  int16_t* magnitudeVectorPtr = magnitudeVector;
189  unsigned int number = 0;
190  const float scalar = 32768.0;
191  for(number = 0; number < num_points; number++){
192  float real = ((float)(*complexVectorPtr++)) / scalar;
193  float imag = ((float)(*complexVectorPtr++)) / scalar;
194  *magnitudeVectorPtr++ = (int16_t)(sqrtf((real*real) + (imag*imag)) * scalar);
195  }
196 }
197 #endif /* LV_HAVE_GENERIC */
198 
199 #ifdef LV_HAVE_ORC_DISABLED
200 /*!
201  \brief Calculates the magnitude of the complexVector and stores the results in the magnitudeVector
202  \param complexVector The vector containing the complex input values
203  \param magnitudeVector The vector containing the real output values
204  \param num_points The number of complex values in complexVector to be calculated and stored into cVector
205 */
206 extern void volk_16ic_magnitude_16i_a_orc_impl(int16_t* magnitudeVector, const lv_16sc_t* complexVector, float scalar, unsigned int num_points);
207 static inline void volk_16ic_magnitude_16i_u_orc(int16_t* magnitudeVector, const lv_16sc_t* complexVector, unsigned int num_points){
208  volk_16ic_magnitude_16i_a_orc_impl(magnitudeVector, complexVector, 32768.0, num_points);
209 }
210 #endif /* LV_HAVE_ORC */
211 
212 
213 #endif /* INCLUDED_volk_16ic_magnitude_16i_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