Vector Optimized Library of Kernels  3.1.2
Architecture-tuned implementations of math kernels
volk_32fc_s32f_power_spectrum_32f.h
Go to the documentation of this file.
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2012, 2014 Free Software Foundation, Inc.
4  *
5  * This file is part of VOLK
6  *
7  * SPDX-License-Identifier: LGPL-3.0-or-later
8  */
9 
40 #ifndef INCLUDED_volk_32fc_s32f_power_spectrum_32f_a_H
41 #define INCLUDED_volk_32fc_s32f_power_spectrum_32f_a_H
42 
43 #include <inttypes.h>
44 #include <math.h>
45 #include <stdio.h>
46 
47 #ifdef LV_HAVE_GENERIC
48 
49 static inline void
51  const lv_32fc_t* complexFFTInput,
52  const float normalizationFactor,
53  unsigned int num_points)
54 {
55  // Calculate the Power of the complex point
56  const float normFactSq = 1.0 / (normalizationFactor * normalizationFactor);
57 
58  // Calculate dBm
59  // 50 ohm load assumption
60  // 10 * log10 (v^2 / (2 * 50.0 * .001)) = 10 * log10( v^2 * 10)
61  // 75 ohm load assumption
62  // 10 * log10 (v^2 / (2 * 75.0 * .001)) = 10 * log10( v^2 * 15)
63 
64  /*
65  * For generic reference, the code below is a volk-optimized
66  * approach that also leverages a faster log2 calculation
67  * to calculate the log10:
68  * n*log10(x) = n*log2(x)/log2(10) = (n/log2(10)) * log2(x)
69  *
70  * Generic code:
71  *
72  * const float real = *inputPtr++ * iNormalizationFactor;
73  * const float imag = *inputPtr++ * iNormalizationFactor;
74  * realFFTDataPointsPtr = 10.0*log10f(((real * real) + (imag * imag)) + 1e-20);
75  * realFFTDataPointsPtr++;
76  *
77  */
78 
79  // Calc mag^2
80  volk_32fc_magnitude_squared_32f(logPowerOutput, complexFFTInput, num_points);
81 
82  // Finish ((real * real) + (imag * imag)) calculation:
83  volk_32f_s32f_multiply_32f(logPowerOutput, logPowerOutput, normFactSq, num_points);
84 
85  // The following calculates 10*log10(x) = 10*log2(x)/log2(10) = (10/log2(10))
86  // * log2(x)
87  volk_32f_log2_32f(logPowerOutput, logPowerOutput, num_points);
88  volk_32f_s32f_multiply_32f(
89  logPowerOutput, logPowerOutput, volk_log2to10factor, num_points);
90 }
91 #endif /* LV_HAVE_GENERIC */
92 
93 #ifdef LV_HAVE_NEON
94 #include <arm_neon.h>
96 
97 static inline void
99  const lv_32fc_t* complexFFTInput,
100  const float normalizationFactor,
101  unsigned int num_points)
102 {
103  float* logPowerOutputPtr = logPowerOutput;
104  const lv_32fc_t* complexFFTInputPtr = complexFFTInput;
105  const float iNormalizationFactor = 1.0 / normalizationFactor;
106  unsigned int number;
107  unsigned int quarter_points = num_points / 4;
108  float32x4x2_t fft_vec;
109  float32x4_t log_pwr_vec;
110  float32x4_t mag_squared_vec;
111 
112  const float inv_ln10_10 = 4.34294481903f; // 10.0/ln(10.)
113 
114  for (number = 0; number < quarter_points; number++) {
115  // Load
116  fft_vec = vld2q_f32((float*)complexFFTInputPtr);
117  // Prefetch next 4
118  __VOLK_PREFETCH(complexFFTInputPtr + 4);
119  // Normalize
120  fft_vec.val[0] = vmulq_n_f32(fft_vec.val[0], iNormalizationFactor);
121  fft_vec.val[1] = vmulq_n_f32(fft_vec.val[1], iNormalizationFactor);
122  mag_squared_vec = _vmagnitudesquaredq_f32(fft_vec);
123  log_pwr_vec = vmulq_n_f32(_vlogq_f32(mag_squared_vec), inv_ln10_10);
124  // Store
125  vst1q_f32(logPowerOutputPtr, log_pwr_vec);
126  // Move pointers ahead
127  complexFFTInputPtr += 4;
128  logPowerOutputPtr += 4;
129  }
130 
131  // deal with the rest
132  for (number = quarter_points * 4; number < num_points; number++) {
133  const float real = lv_creal(*complexFFTInputPtr) * iNormalizationFactor;
134  const float imag = lv_cimag(*complexFFTInputPtr) * iNormalizationFactor;
135 
136  *logPowerOutputPtr =
137  volk_log2to10factor * log2f_non_ieee(((real * real) + (imag * imag)));
138  complexFFTInputPtr++;
139  logPowerOutputPtr++;
140  }
141 }
142 
143 #endif /* LV_HAVE_NEON */
144 
145 #endif /* INCLUDED_volk_32fc_s32f_power_spectrum_32f_a_H */
static void volk_32fc_s32f_power_spectrum_32f_generic(float *logPowerOutput, const lv_32fc_t *complexFFTInput, const float normalizationFactor, unsigned int num_points)
Definition: volk_32fc_s32f_power_spectrum_32f.h:50
static void volk_32fc_s32f_power_spectrum_32f_neon(float *logPowerOutput, const lv_32fc_t *complexFFTInput, const float normalizationFactor, unsigned int num_points)
Definition: volk_32fc_s32f_power_spectrum_32f.h:98
#define volk_log2to10factor
Definition: volk_common.h:165
static float log2f_non_ieee(float f)
Definition: volk_common.h:155
#define __VOLK_PREFETCH(addr)
Definition: volk_common.h:68
#define lv_cimag(x)
Definition: volk_complex.h:98
#define lv_creal(x)
Definition: volk_complex.h:96
float complex lv_32fc_t
Definition: volk_complex.h:74
static float32x4_t _vlogq_f32(float32x4_t x)
Definition: volk_neon_intrinsics.h:143
static float32x4_t _vmagnitudesquaredq_f32(float32x4x2_t cmplxValue)
Definition: volk_neon_intrinsics.h:73