GNU Radio 3.6.5 C++ API

volk_32fc_s32f_x2_power_spectral_density_32f_a.h

Go to the documentation of this file.
00001 #ifndef INCLUDED_volk_32fc_s32f_x2_power_spectral_density_32f_a_H
00002 #define INCLUDED_volk_32fc_s32f_x2_power_spectral_density_32f_a_H
00003 
00004 #include <inttypes.h>
00005 #include <stdio.h>
00006 #include <math.h>
00007 
00008 #ifdef LV_HAVE_SSE3
00009 #include <pmmintrin.h>
00010 
00011 #ifdef LV_HAVE_LIB_SIMDMATH
00012 #include <simdmath.h>
00013 #endif /* LV_HAVE_LIB_SIMDMATH */
00014 
00015 /*!
00016   \brief Calculates the log10 power value divided by the RBW for each input point
00017   \param logPowerOutput The 10.0 * log10((r*r + i*i)/RBW) for each data point
00018   \param complexFFTInput The complex data output from the FFT point
00019   \param normalizationFactor This value is divided against all the input values before the power is calculated
00020   \param rbw The resolution bandwith of the fft spectrum
00021   \param num_points The number of fft data points
00022 */
00023 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){
00024   const float* inputPtr = (const float*)complexFFTInput;
00025   float* destPtr = logPowerOutput;
00026   uint64_t number = 0;
00027   const float iRBW = 1.0 / rbw;
00028   const float iNormalizationFactor = 1.0 / normalizationFactor;
00029 
00030 #ifdef LV_HAVE_LIB_SIMDMATH
00031   __m128 magScalar = _mm_set_ps1(10.0);
00032   magScalar = _mm_div_ps(magScalar, logf4(magScalar));
00033 
00034   __m128 invRBW = _mm_set_ps1(iRBW);
00035 
00036   __m128 invNormalizationFactor = _mm_set_ps1(iNormalizationFactor);
00037 
00038   __m128 power;
00039   __m128 input1, input2;
00040   const uint64_t quarterPoints = num_points / 4;
00041   for(;number < quarterPoints; number++){
00042     // Load the complex values
00043     input1 =_mm_load_ps(inputPtr);
00044     inputPtr += 4;
00045     input2 =_mm_load_ps(inputPtr);
00046     inputPtr += 4;
00047 
00048     // Apply the normalization factor
00049     input1 = _mm_mul_ps(input1, invNormalizationFactor);
00050     input2 = _mm_mul_ps(input2, invNormalizationFactor);
00051 
00052     // Multiply each value by itself
00053     // (r1*r1), (i1*i1), (r2*r2), (i2*i2)
00054     input1 = _mm_mul_ps(input1, input1);
00055     // (r3*r3), (i3*i3), (r4*r4), (i4*i4)
00056     input2 = _mm_mul_ps(input2, input2);
00057 
00058     // Horizontal add, to add (r*r) + (i*i) for each complex value
00059     // (r1*r1)+(i1*i1), (r2*r2) + (i2*i2), (r3*r3)+(i3*i3), (r4*r4)+(i4*i4)
00060     power = _mm_hadd_ps(input1, input2);
00061 
00062     // Divide by the rbw
00063     power = _mm_mul_ps(power, invRBW);
00064 
00065     // Calculate the natural log power
00066     power = logf4(power);
00067 
00068     // Convert to log10 and multiply by 10.0
00069     power = _mm_mul_ps(power, magScalar);
00070 
00071     // Store the floating point results
00072     _mm_store_ps(destPtr, power);
00073 
00074     destPtr += 4;
00075   }
00076 
00077   number = quarterPoints*4;
00078 #endif /* LV_HAVE_LIB_SIMDMATH */
00079   // Calculate the FFT for any remaining points
00080   for(; number < num_points; number++){
00081     // Calculate dBm
00082     // 50 ohm load assumption
00083     // 10 * log10 (v^2 / (2 * 50.0 * .001)) = 10 * log10( v^2 * 10)
00084     // 75 ohm load assumption
00085     // 10 * log10 (v^2 / (2 * 75.0 * .001)) = 10 * log10( v^2 * 15)
00086 
00087     const float real = *inputPtr++ * iNormalizationFactor;
00088     const float imag = *inputPtr++ * iNormalizationFactor;
00089 
00090     *destPtr = 10.0*log10f((((real * real) + (imag * imag)) + 1e-20) * iRBW);
00091     destPtr++;
00092   }
00093 
00094 }
00095 #endif /* LV_HAVE_SSE3 */
00096 
00097 #ifdef LV_HAVE_GENERIC
00098 /*!
00099   \brief Calculates the log10 power value divided by the RBW for each input point
00100   \param logPowerOutput The 10.0 * log10((r*r + i*i)/RBW) for each data point
00101   \param complexFFTInput The complex data output from the FFT point
00102   \param normalizationFactor This value is divided against all the input values before the power is calculated
00103   \param rbw The resolution bandwith of the fft spectrum
00104   \param num_points The number of fft data points
00105 */
00106 static inline void volk_32fc_s32f_x2_power_spectral_density_32f_a_generic(float* logPowerOutput, const lv_32fc_t* complexFFTInput, const float normalizationFactor, const float rbw, unsigned int num_points){
00107   // Calculate the Power of the complex point
00108   const float* inputPtr = (float*)complexFFTInput;
00109   float* realFFTDataPointsPtr = logPowerOutput;
00110   unsigned int point;
00111   const float invRBW = 1.0 / rbw;
00112   const float iNormalizationFactor = 1.0 / normalizationFactor;
00113 
00114   for(point = 0; point < num_points; point++){
00115     // Calculate dBm
00116     // 50 ohm load assumption
00117     // 10 * log10 (v^2 / (2 * 50.0 * .001)) = 10 * log10( v^2 * 10)
00118     // 75 ohm load assumption
00119     // 10 * log10 (v^2 / (2 * 75.0 * .001)) = 10 * log10( v^2 * 15)
00120 
00121     const float real = *inputPtr++ * iNormalizationFactor;
00122     const float imag = *inputPtr++ * iNormalizationFactor;
00123 
00124     *realFFTDataPointsPtr = 10.0*log10f((((real * real) + (imag * imag)) + 1e-20) * invRBW);
00125 
00126     realFFTDataPointsPtr++;
00127   }
00128 }
00129 #endif /* LV_HAVE_GENERIC */
00130 
00131 
00132 
00133 
00134 #endif /* INCLUDED_volk_32fc_s32f_x2_power_spectral_density_32f_a_H */