GNU Radio 3.6.5 C++ API

volk_32fc_s32f_power_spectrum_32f_a.h

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