GNU Radio Manual and C++ API Reference  3.7.6.1
The Free & Open Software Radio Ecosystem
volk_32fc_s32f_x2_power_spectral_density_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_32fc_s32f_x2_power_spectral_density_32f_a_H
24 #define INCLUDED_volk_32fc_s32f_x2_power_spectral_density_32f_a_H
25 
26 #include <inttypes.h>
27 #include <stdio.h>
28 #include <math.h>
29 
30 #ifdef LV_HAVE_AVX
31 #include <immintrin.h>
32 
33 #ifdef LV_HAVE_LIB_SIMDMATH
34 #include <simdmath.h>
35 #endif /* LV_HAVE_LIB_SIMDMATH */
36 
37 /*!
38  \brief Calculates the log10 power value divided by the RBW for each input point
39  \param logPowerOutput The 10.0 * log10((r*r + i*i)/RBW) for each data point
40  \param complexFFTInput The complex data output from the FFT point
41  \param normalizationFactor This value is divided against all the input values before the power is calculated
42  \param rbw The resolution bandwith of the fft spectrum
43  \param num_points The number of fft data points
44 */
45 static inline void volk_32fc_s32f_x2_power_spectral_density_32f_a_avx(float* logPowerOutput, const lv_32fc_t* complexFFTInput, const float normalizationFactor, const float rbw, unsigned int num_points){
46  const float* inputPtr = (const float*)complexFFTInput;
47  float* destPtr = logPowerOutput;
48  uint64_t number = 0;
49  const float iRBW = 1.0 / rbw;
50  const float iNormalizationFactor = 1.0 / normalizationFactor;
51 
52 #ifdef LV_HAVE_LIB_SIMDMATH
53  __m256 magScalar = _mm256_set1_ps(10.0);
54  magScalar = _mm256_div_ps(magScalar, logf4(magScalar));
55 
56  __m256 invRBW = _mm256_set1_ps(iRBW);
57 
58  __m256 invNormalizationFactor = _mm256_set1_ps(iNormalizationFactor);
59 
60  __m256 power;
61  __m256 input1, input2;
62  const uint64_t eighthPoints = num_points / 8;
63  for(;number < eighthPoints; number++){
64  // Load the complex values
65  input1 =_mm256_load_ps(inputPtr);
66  inputPtr += 8;
67  input2 =_mm256_load_ps(inputPtr);
68  inputPtr += 8;
69 
70  // Apply the normalization factor
71  input1 = _mm256_mul_ps(input1, invNormalizationFactor);
72  input2 = _mm256_mul_ps(input2, invNormalizationFactor);
73 
74  // Multiply each value by itself
75  // (r1*r1), (i1*i1), (r2*r2), (i2*i2)
76  input1 = _mm256_mul_ps(input1, input1);
77  // (r3*r3), (i3*i3), (r4*r4), (i4*i4)
78  input2 = _mm256_mul_ps(input2, input2);
79 
80  // Horizontal add, to add (r*r) + (i*i) for each complex value
81  // (r1*r1)+(i1*i1), (r2*r2) + (i2*i2), (r3*r3)+(i3*i3), (r4*r4)+(i4*i4)
82  inputVal1 = _mm256_permute2f128_ps(input1, input2, 0x20);
83  inputVal2 = _mm256_permute2f128_ps(input1, input2, 0x31);
84 
85  power = _mm256_hadd_ps(inputVal1, inputVal2);
86 
87  // Divide by the rbw
88  power = _mm256_mul_ps(power, invRBW);
89 
90  // Calculate the natural log power
91  power = logf4(power);
92 
93  // Convert to log10 and multiply by 10.0
94  power = _mm256_mul_ps(power, magScalar);
95 
96  // Store the floating point results
97  _mm256_store_ps(destPtr, power);
98 
99  destPtr += 8;
100  }
101 
102  number = eighthPoints*8;
103 #endif /* LV_HAVE_LIB_SIMDMATH */
104  // Calculate the FFT for any remaining points
105  for(; number < num_points; number++){
106  // Calculate dBm
107  // 50 ohm load assumption
108  // 10 * log10 (v^2 / (2 * 50.0 * .001)) = 10 * log10( v^2 * 10)
109  // 75 ohm load assumption
110  // 10 * log10 (v^2 / (2 * 75.0 * .001)) = 10 * log10( v^2 * 15)
111 
112  const float real = *inputPtr++ * iNormalizationFactor;
113  const float imag = *inputPtr++ * iNormalizationFactor;
114 
115  *destPtr = 10.0*log10f((((real * real) + (imag * imag)) + 1e-20) * iRBW);
116  destPtr++;
117  }
118 
119 }
120 #endif /* LV_HAVE_AVX */
121 
122 #ifdef LV_HAVE_SSE3
123 #include <pmmintrin.h>
124 
125 #ifdef LV_HAVE_LIB_SIMDMATH
126 #include <simdmath.h>
127 #endif /* LV_HAVE_LIB_SIMDMATH */
128 
129 /*!
130  \brief Calculates the log10 power value divided by the RBW for each input point
131  \param logPowerOutput The 10.0 * log10((r*r + i*i)/RBW) for each data point
132  \param complexFFTInput The complex data output from the FFT point
133  \param normalizationFactor This value is divided against all the input values before the power is calculated
134  \param rbw The resolution bandwith of the fft spectrum
135  \param num_points The number of fft data points
136 */
137 static inline void volk_32fc_s32f_x2_power_spectral_density_32f_a_sse3(float* logPowerOutput, const lv_32fc_t* complexFFTInput, const float normalizationFactor, const float rbw, unsigned int num_points){
138  const float* inputPtr = (const float*)complexFFTInput;
139  float* destPtr = logPowerOutput;
140  uint64_t number = 0;
141  const float iRBW = 1.0 / rbw;
142  const float iNormalizationFactor = 1.0 / normalizationFactor;
143 
144 #ifdef LV_HAVE_LIB_SIMDMATH
145  __m128 magScalar = _mm_set_ps1(10.0);
146  magScalar = _mm_div_ps(magScalar, logf4(magScalar));
147 
148  __m128 invRBW = _mm_set_ps1(iRBW);
149 
150  __m128 invNormalizationFactor = _mm_set_ps1(iNormalizationFactor);
151 
152  __m128 power;
153  __m128 input1, input2;
154  const uint64_t quarterPoints = num_points / 4;
155  for(;number < quarterPoints; number++){
156  // Load the complex values
157  input1 =_mm_load_ps(inputPtr);
158  inputPtr += 4;
159  input2 =_mm_load_ps(inputPtr);
160  inputPtr += 4;
161 
162  // Apply the normalization factor
163  input1 = _mm_mul_ps(input1, invNormalizationFactor);
164  input2 = _mm_mul_ps(input2, invNormalizationFactor);
165 
166  // Multiply each value by itself
167  // (r1*r1), (i1*i1), (r2*r2), (i2*i2)
168  input1 = _mm_mul_ps(input1, input1);
169  // (r3*r3), (i3*i3), (r4*r4), (i4*i4)
170  input2 = _mm_mul_ps(input2, input2);
171 
172  // Horizontal add, to add (r*r) + (i*i) for each complex value
173  // (r1*r1)+(i1*i1), (r2*r2) + (i2*i2), (r3*r3)+(i3*i3), (r4*r4)+(i4*i4)
174  power = _mm_hadd_ps(input1, input2);
175 
176  // Divide by the rbw
177  power = _mm_mul_ps(power, invRBW);
178 
179  // Calculate the natural log power
180  power = logf4(power);
181 
182  // Convert to log10 and multiply by 10.0
183  power = _mm_mul_ps(power, magScalar);
184 
185  // Store the floating point results
186  _mm_store_ps(destPtr, power);
187 
188  destPtr += 4;
189  }
190 
191  number = quarterPoints*4;
192 #endif /* LV_HAVE_LIB_SIMDMATH */
193  // Calculate the FFT for any remaining points
194  for(; number < num_points; number++){
195  // Calculate dBm
196  // 50 ohm load assumption
197  // 10 * log10 (v^2 / (2 * 50.0 * .001)) = 10 * log10( v^2 * 10)
198  // 75 ohm load assumption
199  // 10 * log10 (v^2 / (2 * 75.0 * .001)) = 10 * log10( v^2 * 15)
200 
201  const float real = *inputPtr++ * iNormalizationFactor;
202  const float imag = *inputPtr++ * iNormalizationFactor;
203 
204  *destPtr = 10.0*log10f((((real * real) + (imag * imag)) + 1e-20) * iRBW);
205  destPtr++;
206  }
207 
208 }
209 #endif /* LV_HAVE_SSE3 */
210 
211 #ifdef LV_HAVE_GENERIC
212 /*!
213  \brief Calculates the log10 power value divided by the RBW for each input point
214  \param logPowerOutput The 10.0 * log10((r*r + i*i)/RBW) for each data point
215  \param complexFFTInput The complex data output from the FFT point
216  \param normalizationFactor This value is divided against all the input values before the power is calculated
217  \param rbw The resolution bandwith of the fft spectrum
218  \param num_points The number of fft data points
219 */
220 static inline void volk_32fc_s32f_x2_power_spectral_density_32f_generic(float* logPowerOutput, const lv_32fc_t* complexFFTInput, const float normalizationFactor, const float rbw, unsigned int num_points){
221  // Calculate the Power of the complex point
222  const float* inputPtr = (float*)complexFFTInput;
223  float* realFFTDataPointsPtr = logPowerOutput;
224  unsigned int point;
225  const float invRBW = 1.0 / rbw;
226  const float iNormalizationFactor = 1.0 / normalizationFactor;
227 
228  for(point = 0; point < num_points; point++){
229  // Calculate dBm
230  // 50 ohm load assumption
231  // 10 * log10 (v^2 / (2 * 50.0 * .001)) = 10 * log10( v^2 * 10)
232  // 75 ohm load assumption
233  // 10 * log10 (v^2 / (2 * 75.0 * .001)) = 10 * log10( v^2 * 15)
234 
235  const float real = *inputPtr++ * iNormalizationFactor;
236  const float imag = *inputPtr++ * iNormalizationFactor;
237 
238  *realFFTDataPointsPtr = 10.0*log10f((((real * real) + (imag * imag)) + 1e-20) * invRBW);
239 
240  realFFTDataPointsPtr++;
241  }
242 }
243 #endif /* LV_HAVE_GENERIC */
244 
245 
246 
247 
248 #endif /* INCLUDED_volk_32fc_s32f_x2_power_spectral_density_32f_a_H */
unsigned __int64 uint64_t
Definition: stdint.h:90
float complex lv_32fc_t
Definition: volk_complex.h:56