Statistics
| Branch: | Tag: | Revision:

root / volk / include / volk / volk_32fc_power_spectral_density_32f_aligned16.h @ 23914465

History | View | Annotate | Download (4.6 kB)

1
#ifndef INCLUDED_VOLK_32fc_POWER_SPECTRAL_DENSITY_32F_ALIGNED16_H
2
#define INCLUDED_VOLK_32fc_POWER_SPECTRAL_DENSITY_32F_ALIGNED16_H
3
4
#include <inttypes.h>
5
#include <stdio.h>
6
#include <math.h>
7
8
#if LV_HAVE_SSE3
9
#include <pmmintrin.h>
10
11
#if 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_power_spectral_density_32f_aligned16_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
#if 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
#if 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_power_spectral_density_32f_aligned16_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_POWER_SPECTRAL_DENSITY_32F_ALIGNED16_H */