GNU Radio Manual and C++ API Reference  3.7.4
The Free & Open Software Radio Ecosystem
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
volk_32fc_s32f_x2_power_spectral_density_32f.h
Go to the documentation of this file.
1 #ifndef INCLUDED_volk_32fc_s32f_x2_power_spectral_density_32f_a_H
2 #define INCLUDED_volk_32fc_s32f_x2_power_spectral_density_32f_a_H
3 
4 #include <inttypes.h>
5 #include <stdio.h>
6 #include <math.h>
7 
8 #ifdef LV_HAVE_SSE3
9 #include <pmmintrin.h>
10 
11 #ifdef LV_HAVE_LIB_SIMDMATH
12 #include <simdmath.h>
13 #endif /* LV_HAVE_LIB_SIMDMATH */
14 
15 /*!
16  \brief Calculates the log10 power value divided by the RBW for each input point
17  \param logPowerOutput The 10.0 * log10((r*r + i*i)/RBW) for each data point
18  \param complexFFTInput The complex data output from the FFT point
19  \param normalizationFactor This value is divided against all the input values before the power is calculated
20  \param rbw The resolution bandwith of the fft spectrum
21  \param num_points The number of fft data points
22 */
23 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){
24  const float* inputPtr = (const float*)complexFFTInput;
25  float* destPtr = logPowerOutput;
26  uint64_t number = 0;
27  const float iRBW = 1.0 / rbw;
28  const float iNormalizationFactor = 1.0 / normalizationFactor;
29 
30 #ifdef LV_HAVE_LIB_SIMDMATH
31  __m128 magScalar = _mm_set_ps1(10.0);
32  magScalar = _mm_div_ps(magScalar, logf4(magScalar));
33 
34  __m128 invRBW = _mm_set_ps1(iRBW);
35 
36  __m128 invNormalizationFactor = _mm_set_ps1(iNormalizationFactor);
37 
38  __m128 power;
39  __m128 input1, input2;
40  const uint64_t quarterPoints = num_points / 4;
41  for(;number < quarterPoints; number++){
42  // Load the complex values
43  input1 =_mm_load_ps(inputPtr);
44  inputPtr += 4;
45  input2 =_mm_load_ps(inputPtr);
46  inputPtr += 4;
47 
48  // Apply the normalization factor
49  input1 = _mm_mul_ps(input1, invNormalizationFactor);
50  input2 = _mm_mul_ps(input2, invNormalizationFactor);
51 
52  // Multiply each value by itself
53  // (r1*r1), (i1*i1), (r2*r2), (i2*i2)
54  input1 = _mm_mul_ps(input1, input1);
55  // (r3*r3), (i3*i3), (r4*r4), (i4*i4)
56  input2 = _mm_mul_ps(input2, input2);
57 
58  // Horizontal add, to add (r*r) + (i*i) for each complex value
59  // (r1*r1)+(i1*i1), (r2*r2) + (i2*i2), (r3*r3)+(i3*i3), (r4*r4)+(i4*i4)
60  power = _mm_hadd_ps(input1, input2);
61 
62  // Divide by the rbw
63  power = _mm_mul_ps(power, invRBW);
64 
65  // Calculate the natural log power
66  power = logf4(power);
67 
68  // Convert to log10 and multiply by 10.0
69  power = _mm_mul_ps(power, magScalar);
70 
71  // Store the floating point results
72  _mm_store_ps(destPtr, power);
73 
74  destPtr += 4;
75  }
76 
77  number = quarterPoints*4;
78 #endif /* LV_HAVE_LIB_SIMDMATH */
79  // Calculate the FFT for any remaining points
80  for(; number < num_points; number++){
81  // Calculate dBm
82  // 50 ohm load assumption
83  // 10 * log10 (v^2 / (2 * 50.0 * .001)) = 10 * log10( v^2 * 10)
84  // 75 ohm load assumption
85  // 10 * log10 (v^2 / (2 * 75.0 * .001)) = 10 * log10( v^2 * 15)
86 
87  const float real = *inputPtr++ * iNormalizationFactor;
88  const float imag = *inputPtr++ * iNormalizationFactor;
89 
90  *destPtr = 10.0*log10f((((real * real) + (imag * imag)) + 1e-20) * iRBW);
91  destPtr++;
92  }
93 
94 }
95 #endif /* LV_HAVE_SSE3 */
96 
97 #ifdef LV_HAVE_GENERIC
98 /*!
99  \brief Calculates the log10 power value divided by the RBW for each input point
100  \param logPowerOutput The 10.0 * log10((r*r + i*i)/RBW) for each data point
101  \param complexFFTInput The complex data output from the FFT point
102  \param normalizationFactor This value is divided against all the input values before the power is calculated
103  \param rbw The resolution bandwith of the fft spectrum
104  \param num_points The number of fft data points
105 */
106 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){
107  // Calculate the Power of the complex point
108  const float* inputPtr = (float*)complexFFTInput;
109  float* realFFTDataPointsPtr = logPowerOutput;
110  unsigned int point;
111  const float invRBW = 1.0 / rbw;
112  const float iNormalizationFactor = 1.0 / normalizationFactor;
113 
114  for(point = 0; point < num_points; point++){
115  // Calculate dBm
116  // 50 ohm load assumption
117  // 10 * log10 (v^2 / (2 * 50.0 * .001)) = 10 * log10( v^2 * 10)
118  // 75 ohm load assumption
119  // 10 * log10 (v^2 / (2 * 75.0 * .001)) = 10 * log10( v^2 * 15)
120 
121  const float real = *inputPtr++ * iNormalizationFactor;
122  const float imag = *inputPtr++ * iNormalizationFactor;
123 
124  *realFFTDataPointsPtr = 10.0*log10f((((real * real) + (imag * imag)) + 1e-20) * invRBW);
125 
126  realFFTDataPointsPtr++;
127  }
128 }
129 #endif /* LV_HAVE_GENERIC */
130 
131 
132 
133 
134 #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