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_32fc_s32f_magnitude_16i.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_32fc_s32f_magnitude_16i
25  *
26  * \b Overview
27  *
28  * Calculates the magnitude of the complexVector and stores the
29  * results in the magnitudeVector. The results are scaled and
30  * converted into 16-bit shorts.
31  *
32  * <b>Dispatcher Prototype</b>
33  * \code
34  * void volk_32fc_s32f_magnitude_16i(int16_t* magnitudeVector, const lv_32fc_t* complexVector, unsigned int num_points)
35  * \endcode
36  *
37  * \b Inputs
38  * \li complexVector: The complex input vector.
39  * \li num_points: The number of samples.
40  *
41  * \b Outputs
42  * \li magnitudeVector: The output value as 16-bit shorts.
43  *
44  * \b Example
45  * Generate points around the unit circle and map them to integers with
46  * magnitude 50 to preserve smallest deltas.
47  * \code
48  * int N = 10;
49  * unsigned int alignment = volk_get_alignment();
50  * lv_32fc_t* in = (lv_32fc_t*)volk_malloc(sizeof(lv_32fc_t)*N, alignment);
51  * int16_t* out = (int16_t*)volk_malloc(sizeof(int16_t)*N, alignment);
52  * float scale = 50.f;
53  *
54  * for(unsigned int ii = 0; ii < N/2; ++ii){
55  * // Generate points around the unit circle
56  * float real = -4.f * ((float)ii / (float)N) + 1.f;
57  * float imag = std::sqrt(1.f - real * real);
58  * in[ii] = lv_cmake(real, imag);
59  * in[ii+N/2] = lv_cmake(-real, -imag);
60  * }
61  *
62  * volk_32fc_s32f_magnitude_16i(out, in, scale, N);
63  *
64  * for(unsigned int ii = 0; ii < N; ++ii){
65  * printf("out[%u] = %i\n", ii, out[ii]);
66  * }
67  *
68  * volk_free(in);
69  * volk_free(out);
70  * \endcode
71  */
72 
73 #ifndef INCLUDED_volk_32fc_s32f_magnitude_16i_a_H
74 #define INCLUDED_volk_32fc_s32f_magnitude_16i_a_H
75 
76 #include <volk/volk_common.h>
77 #include <inttypes.h>
78 #include <stdio.h>
79 #include <math.h>
80 
81 #ifdef LV_HAVE_SSE3
82 #include <pmmintrin.h>
83 
84 static inline void
85 volk_32fc_s32f_magnitude_16i_a_sse3(int16_t* magnitudeVector, const lv_32fc_t* complexVector,
86  const float scalar, unsigned int num_points)
87 {
88  unsigned int number = 0;
89  const unsigned int quarterPoints = num_points / 4;
90 
91  const float* complexVectorPtr = (const float*)complexVector;
92  int16_t* magnitudeVectorPtr = magnitudeVector;
93 
94  __m128 vScalar = _mm_set_ps1(scalar);
95 
96  __m128 cplxValue1, cplxValue2, result;
97 
98  __VOLK_ATTR_ALIGNED(16) float floatBuffer[4];
99 
100  for(;number < quarterPoints; number++){
101  cplxValue1 = _mm_load_ps(complexVectorPtr);
102  complexVectorPtr += 4;
103 
104  cplxValue2 = _mm_load_ps(complexVectorPtr);
105  complexVectorPtr += 4;
106 
107  cplxValue1 = _mm_mul_ps(cplxValue1, cplxValue1); // Square the values
108  cplxValue2 = _mm_mul_ps(cplxValue2, cplxValue2); // Square the Values
109 
110  result = _mm_hadd_ps(cplxValue1, cplxValue2); // Add the I2 and Q2 values
111 
112  result = _mm_sqrt_ps(result);
113 
114  result = _mm_mul_ps(result, vScalar);
115 
116  _mm_store_ps(floatBuffer, result);
117  *magnitudeVectorPtr++ = (int16_t)(floatBuffer[0]);
118  *magnitudeVectorPtr++ = (int16_t)(floatBuffer[1]);
119  *magnitudeVectorPtr++ = (int16_t)(floatBuffer[2]);
120  *magnitudeVectorPtr++ = (int16_t)(floatBuffer[3]);
121  }
122 
123  number = quarterPoints * 4;
124  magnitudeVectorPtr = &magnitudeVector[number];
125  for(; number < num_points; number++){
126  float val1Real = *complexVectorPtr++;
127  float val1Imag = *complexVectorPtr++;
128  *magnitudeVectorPtr++ = (int16_t)(sqrtf((val1Real * val1Real) + (val1Imag * val1Imag)) * scalar);
129  }
130 }
131 #endif /* LV_HAVE_SSE3 */
132 
133 
134 #ifdef LV_HAVE_SSE
135 #include <xmmintrin.h>
136 
137 static inline void
138 volk_32fc_s32f_magnitude_16i_a_sse(int16_t* magnitudeVector, const lv_32fc_t* complexVector,
139  const float scalar, unsigned int num_points)
140 {
141  unsigned int number = 0;
142  const unsigned int quarterPoints = num_points / 4;
143 
144  const float* complexVectorPtr = (const float*)complexVector;
145  int16_t* magnitudeVectorPtr = magnitudeVector;
146 
147  __m128 vScalar = _mm_set_ps1(scalar);
148 
149  __m128 cplxValue1, cplxValue2, iValue, qValue, result;
150 
151  __VOLK_ATTR_ALIGNED(16) float floatBuffer[4];
152 
153  for(;number < quarterPoints; number++){
154  cplxValue1 = _mm_load_ps(complexVectorPtr);
155  complexVectorPtr += 4;
156 
157  cplxValue2 = _mm_load_ps(complexVectorPtr);
158  complexVectorPtr += 4;
159 
160  // Arrange in i1i2i3i4 format
161  iValue = _mm_shuffle_ps(cplxValue1, cplxValue2, _MM_SHUFFLE(2,0,2,0));
162  // Arrange in q1q2q3q4 format
163  qValue = _mm_shuffle_ps(cplxValue1, cplxValue2, _MM_SHUFFLE(3,1,3,1));
164 
165  iValue = _mm_mul_ps(iValue, iValue); // Square the I values
166  qValue = _mm_mul_ps(qValue, qValue); // Square the Q Values
167 
168  result = _mm_add_ps(iValue, qValue); // Add the I2 and Q2 values
169 
170  result = _mm_sqrt_ps(result);
171 
172  result = _mm_mul_ps(result, vScalar);
173 
174  _mm_store_ps(floatBuffer, result);
175  *magnitudeVectorPtr++ = (int16_t)(floatBuffer[0]);
176  *magnitudeVectorPtr++ = (int16_t)(floatBuffer[1]);
177  *magnitudeVectorPtr++ = (int16_t)(floatBuffer[2]);
178  *magnitudeVectorPtr++ = (int16_t)(floatBuffer[3]);
179  }
180 
181  number = quarterPoints * 4;
182  magnitudeVectorPtr = &magnitudeVector[number];
183  for(; number < num_points; number++){
184  float val1Real = *complexVectorPtr++;
185  float val1Imag = *complexVectorPtr++;
186  *magnitudeVectorPtr++ = (int16_t)(sqrtf((val1Real * val1Real) + (val1Imag * val1Imag)) * scalar);
187  }
188 }
189 #endif /* LV_HAVE_SSE */
190 
191 #ifdef LV_HAVE_GENERIC
192 
193 static inline void
194 volk_32fc_s32f_magnitude_16i_generic(int16_t* magnitudeVector, const lv_32fc_t* complexVector,
195  const float scalar, unsigned int num_points)
196 {
197  const float* complexVectorPtr = (float*)complexVector;
198  int16_t* magnitudeVectorPtr = magnitudeVector;
199  unsigned int number = 0;
200  for(number = 0; number < num_points; number++){
201  const float real = *complexVectorPtr++;
202  const float imag = *complexVectorPtr++;
203  *magnitudeVectorPtr++ = (int16_t)(sqrtf((real*real) + (imag*imag)) * scalar);
204  }
205 }
206 #endif /* LV_HAVE_GENERIC */
207 
208 
209 #ifdef LV_HAVE_ORC
210 
211 extern void
212 volk_32fc_s32f_magnitude_16i_a_orc_impl(int16_t* magnitudeVector, const lv_32fc_t* complexVector,
213  const float scalar, unsigned int num_points);
214 
215 static inline void
216 volk_32fc_s32f_magnitude_16i_u_orc(int16_t* magnitudeVector, const lv_32fc_t* complexVector,
217  const float scalar, unsigned int num_points)
218 {
219  volk_32fc_s32f_magnitude_16i_a_orc_impl(magnitudeVector, complexVector, scalar, num_points);
220 }
221 
222 #endif /* LV_HAVE_ORC */
223 
224 
225 #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