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