GNU Radio Manual and C++ API Reference  3.7.6.1
The Free & Open Software Radio Ecosystem
volk_32fc_s32f_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_32fc_s32f_magnitude_16i_a_H
24 #define INCLUDED_volk_32fc_s32f_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, scales the resulting value and stores the results in the magnitudeVector
35  \param complexVector The vector containing the complex input values
36  \param scalar The scale value multiplied to the magnitude of each complex vector
37  \param magnitudeVector The vector containing the real output values
38  \param num_points The number of complex values in complexVector to be calculated and stored into cVector
39 */
40 static inline void volk_32fc_s32f_magnitude_16i_a_sse3(int16_t* magnitudeVector, const lv_32fc_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 float* complexVectorPtr = (const float*)complexVector;
45  int16_t* magnitudeVectorPtr = magnitudeVector;
46 
47  __m128 vScalar = _mm_set_ps1(scalar);
48 
49  __m128 cplxValue1, cplxValue2, result;
50 
51  __VOLK_ATTR_ALIGNED(16) float floatBuffer[4];
52 
53  for(;number < quarterPoints; number++){
54  cplxValue1 = _mm_load_ps(complexVectorPtr);
55  complexVectorPtr += 4;
56 
57  cplxValue2 = _mm_load_ps(complexVectorPtr);
58  complexVectorPtr += 4;
59 
60  cplxValue1 = _mm_mul_ps(cplxValue1, cplxValue1); // Square the values
61  cplxValue2 = _mm_mul_ps(cplxValue2, cplxValue2); // Square the Values
62 
63  result = _mm_hadd_ps(cplxValue1, cplxValue2); // Add the I2 and Q2 values
64 
65  result = _mm_sqrt_ps(result);
66 
67  result = _mm_mul_ps(result, vScalar);
68 
69  _mm_store_ps(floatBuffer, result);
70  *magnitudeVectorPtr++ = (int16_t)(floatBuffer[0]);
71  *magnitudeVectorPtr++ = (int16_t)(floatBuffer[1]);
72  *magnitudeVectorPtr++ = (int16_t)(floatBuffer[2]);
73  *magnitudeVectorPtr++ = (int16_t)(floatBuffer[3]);
74  }
75 
76  number = quarterPoints * 4;
77  magnitudeVectorPtr = &magnitudeVector[number];
78  for(; number < num_points; number++){
79  float val1Real = *complexVectorPtr++;
80  float val1Imag = *complexVectorPtr++;
81  *magnitudeVectorPtr++ = (int16_t)(sqrtf((val1Real * val1Real) + (val1Imag * val1Imag)) * scalar);
82  }
83 }
84 #endif /* LV_HAVE_SSE3 */
85 
86 #ifdef LV_HAVE_SSE
87 #include <xmmintrin.h>
88 /*!
89  \brief Calculates the magnitude of the complexVector, scales the resulting value and stores the results in the magnitudeVector
90  \param complexVector The vector containing the complex input values
91  \param scalar The scale value multiplied to the magnitude of each complex vector
92  \param magnitudeVector The vector containing the real output values
93  \param num_points The number of complex values in complexVector to be calculated and stored into cVector
94 */
95 static inline void volk_32fc_s32f_magnitude_16i_a_sse(int16_t* magnitudeVector, const lv_32fc_t* complexVector, const float scalar, unsigned int num_points){
96  unsigned int number = 0;
97  const unsigned int quarterPoints = num_points / 4;
98 
99  const float* complexVectorPtr = (const float*)complexVector;
100  int16_t* magnitudeVectorPtr = magnitudeVector;
101 
102  __m128 vScalar = _mm_set_ps1(scalar);
103 
104  __m128 cplxValue1, cplxValue2, iValue, qValue, result;
105 
106  __VOLK_ATTR_ALIGNED(16) float floatBuffer[4];
107 
108  for(;number < quarterPoints; number++){
109  cplxValue1 = _mm_load_ps(complexVectorPtr);
110  complexVectorPtr += 4;
111 
112  cplxValue2 = _mm_load_ps(complexVectorPtr);
113  complexVectorPtr += 4;
114 
115  // Arrange in i1i2i3i4 format
116  iValue = _mm_shuffle_ps(cplxValue1, cplxValue2, _MM_SHUFFLE(2,0,2,0));
117  // Arrange in q1q2q3q4 format
118  qValue = _mm_shuffle_ps(cplxValue1, cplxValue2, _MM_SHUFFLE(3,1,3,1));
119 
120  iValue = _mm_mul_ps(iValue, iValue); // Square the I values
121  qValue = _mm_mul_ps(qValue, qValue); // Square the Q Values
122 
123  result = _mm_add_ps(iValue, qValue); // Add the I2 and Q2 values
124 
125  result = _mm_sqrt_ps(result);
126 
127  result = _mm_mul_ps(result, vScalar);
128 
129  _mm_store_ps(floatBuffer, result);
130  *magnitudeVectorPtr++ = (int16_t)(floatBuffer[0]);
131  *magnitudeVectorPtr++ = (int16_t)(floatBuffer[1]);
132  *magnitudeVectorPtr++ = (int16_t)(floatBuffer[2]);
133  *magnitudeVectorPtr++ = (int16_t)(floatBuffer[3]);
134  }
135 
136  number = quarterPoints * 4;
137  magnitudeVectorPtr = &magnitudeVector[number];
138  for(; number < num_points; number++){
139  float val1Real = *complexVectorPtr++;
140  float val1Imag = *complexVectorPtr++;
141  *magnitudeVectorPtr++ = (int16_t)(sqrtf((val1Real * val1Real) + (val1Imag * val1Imag)) * scalar);
142  }
143 }
144 #endif /* LV_HAVE_SSE */
145 
146 #ifdef LV_HAVE_GENERIC
147 /*!
148  \brief Calculates the magnitude of the complexVector, scales the resulting value and stores the results in the magnitudeVector
149  \param complexVector The vector containing the complex input values
150  \param scalar The scale value multiplied to the magnitude of each complex vector
151  \param magnitudeVector The vector containing the real output values
152  \param num_points The number of complex values in complexVector to be calculated and stored into cVector
153 */
154 static inline void volk_32fc_s32f_magnitude_16i_generic(int16_t* magnitudeVector, const lv_32fc_t* complexVector, const float scalar, unsigned int num_points){
155  const float* complexVectorPtr = (float*)complexVector;
156  int16_t* magnitudeVectorPtr = magnitudeVector;
157  unsigned int number = 0;
158  for(number = 0; number < num_points; number++){
159  const float real = *complexVectorPtr++;
160  const float imag = *complexVectorPtr++;
161  *magnitudeVectorPtr++ = (int16_t)(sqrtf((real*real) + (imag*imag)) * scalar);
162  }
163 }
164 #endif /* LV_HAVE_GENERIC */
165 
166 #ifdef LV_HAVE_ORC
167 /*!
168  \brief Calculates the magnitude of the complexVector, scales the resulting value and stores the results in the magnitudeVector
169  \param complexVector The vector containing the complex input values
170  \param scalar The scale value multiplied to the magnitude of each complex vector
171  \param magnitudeVector The vector containing the real output values
172  \param num_points The number of complex values in complexVector to be calculated and stored into cVector
173 */
174 extern void volk_32fc_s32f_magnitude_16i_a_orc_impl(int16_t* magnitudeVector, const lv_32fc_t* complexVector, const float scalar, unsigned int num_points);
175 static inline void volk_32fc_s32f_magnitude_16i_u_orc(int16_t* magnitudeVector, const lv_32fc_t* complexVector, const float scalar, unsigned int num_points){
176  volk_32fc_s32f_magnitude_16i_a_orc_impl(magnitudeVector, complexVector, scalar, num_points);
177 }
178 #endif /* LV_HAVE_ORC */
179 
180 
181 #endif /* INCLUDED_volk_32fc_s32f_magnitude_16i_a_H */
signed short int16_t
Definition: stdint.h:76
#define __VOLK_ATTR_ALIGNED(x)
Definition: volk_common.h:27
float complex lv_32fc_t
Definition: volk_complex.h:56