GNU Radio 3.4.0 C++ API
|
00001 #ifndef INCLUDED_volk_16ic_s32f_magnitude_32f_a16_H 00002 #define INCLUDED_volk_16ic_s32f_magnitude_32f_a16_H 00003 00004 #include <inttypes.h> 00005 #include <stdio.h> 00006 #include <math.h> 00007 00008 #if LV_HAVE_SSE3 00009 #include <pmmintrin.h> 00010 /*! 00011 \brief Calculates the magnitude of the complexVector and stores the results in the magnitudeVector 00012 \param complexVector The vector containing the complex input values 00013 \param magnitudeVector The vector containing the real output values 00014 \param scalar The data value to be divided against each input data value of the input complex vector 00015 \param num_points The number of complex values in complexVector to be calculated and stored into cVector 00016 */ 00017 static inline void volk_16ic_s32f_magnitude_32f_a16_sse3(float* magnitudeVector, const lv_16sc_t* complexVector, const float scalar, unsigned int num_points){ 00018 unsigned int number = 0; 00019 const unsigned int quarterPoints = num_points / 4; 00020 00021 const int16_t* complexVectorPtr = (const int16_t*)complexVector; 00022 float* magnitudeVectorPtr = magnitudeVector; 00023 00024 __m128 invScalar = _mm_set_ps1(1.0/scalar); 00025 00026 __m128 cplxValue1, cplxValue2, result; 00027 00028 float inputFloatBuffer[8] __attribute__((aligned(128))); 00029 00030 for(;number < quarterPoints; number++){ 00031 00032 inputFloatBuffer[0] = (float)(complexVectorPtr[0]); 00033 inputFloatBuffer[1] = (float)(complexVectorPtr[1]); 00034 inputFloatBuffer[2] = (float)(complexVectorPtr[2]); 00035 inputFloatBuffer[3] = (float)(complexVectorPtr[3]); 00036 00037 inputFloatBuffer[4] = (float)(complexVectorPtr[4]); 00038 inputFloatBuffer[5] = (float)(complexVectorPtr[5]); 00039 inputFloatBuffer[6] = (float)(complexVectorPtr[6]); 00040 inputFloatBuffer[7] = (float)(complexVectorPtr[7]); 00041 00042 cplxValue1 = _mm_load_ps(&inputFloatBuffer[0]); 00043 cplxValue2 = _mm_load_ps(&inputFloatBuffer[4]); 00044 00045 complexVectorPtr += 8; 00046 00047 cplxValue1 = _mm_mul_ps(cplxValue1, invScalar); 00048 cplxValue2 = _mm_mul_ps(cplxValue2, invScalar); 00049 00050 cplxValue1 = _mm_mul_ps(cplxValue1, cplxValue1); // Square the values 00051 cplxValue2 = _mm_mul_ps(cplxValue2, cplxValue2); // Square the Values 00052 00053 result = _mm_hadd_ps(cplxValue1, cplxValue2); // Add the I2 and Q2 values 00054 00055 result = _mm_sqrt_ps(result); // Square root the values 00056 00057 _mm_store_ps(magnitudeVectorPtr, result); 00058 00059 magnitudeVectorPtr += 4; 00060 } 00061 00062 number = quarterPoints * 4; 00063 magnitudeVectorPtr = &magnitudeVector[number]; 00064 complexVectorPtr = (const int16_t*)&complexVector[number]; 00065 for(; number < num_points; number++){ 00066 float val1Real = (float)(*complexVectorPtr++) / scalar; 00067 float val1Imag = (float)(*complexVectorPtr++) / scalar; 00068 *magnitudeVectorPtr++ = sqrtf((val1Real * val1Real) + (val1Imag * val1Imag)); 00069 } 00070 } 00071 #endif /* LV_HAVE_SSE3 */ 00072 00073 #if LV_HAVE_SSE 00074 #include <xmmintrin.h> 00075 /*! 00076 \brief Calculates the magnitude of the complexVector and stores the results in the magnitudeVector 00077 \param complexVector The vector containing the complex input values 00078 \param magnitudeVector The vector containing the real output values 00079 \param scalar The data value to be divided against each input data value of the input complex vector 00080 \param num_points The number of complex values in complexVector to be calculated and stored into cVector 00081 */ 00082 static inline void volk_16ic_s32f_magnitude_32f_a16_sse(float* magnitudeVector, const lv_16sc_t* complexVector, const float scalar, unsigned int num_points){ 00083 unsigned int number = 0; 00084 const unsigned int quarterPoints = num_points / 4; 00085 00086 const int16_t* complexVectorPtr = (const int16_t*)complexVector; 00087 float* magnitudeVectorPtr = magnitudeVector; 00088 00089 const float iScalar = 1.0 / scalar; 00090 __m128 invScalar = _mm_set_ps1(iScalar); 00091 00092 __m128 cplxValue1, cplxValue2, result, re, im; 00093 00094 float inputFloatBuffer[8] __attribute__((aligned(128))); 00095 00096 for(;number < quarterPoints; number++){ 00097 inputFloatBuffer[0] = (float)(complexVectorPtr[0]); 00098 inputFloatBuffer[1] = (float)(complexVectorPtr[1]); 00099 inputFloatBuffer[2] = (float)(complexVectorPtr[2]); 00100 inputFloatBuffer[3] = (float)(complexVectorPtr[3]); 00101 00102 inputFloatBuffer[4] = (float)(complexVectorPtr[4]); 00103 inputFloatBuffer[5] = (float)(complexVectorPtr[5]); 00104 inputFloatBuffer[6] = (float)(complexVectorPtr[6]); 00105 inputFloatBuffer[7] = (float)(complexVectorPtr[7]); 00106 00107 cplxValue1 = _mm_load_ps(&inputFloatBuffer[0]); 00108 cplxValue2 = _mm_load_ps(&inputFloatBuffer[4]); 00109 00110 re = _mm_shuffle_ps(cplxValue1, cplxValue2, 0x88); 00111 im = _mm_shuffle_ps(cplxValue1, cplxValue2, 0xdd); 00112 00113 complexVectorPtr += 8; 00114 00115 cplxValue1 = _mm_mul_ps(re, invScalar); 00116 cplxValue2 = _mm_mul_ps(im, invScalar); 00117 00118 cplxValue1 = _mm_mul_ps(cplxValue1, cplxValue1); // Square the values 00119 cplxValue2 = _mm_mul_ps(cplxValue2, cplxValue2); // Square the Values 00120 00121 result = _mm_add_ps(cplxValue1, cplxValue2); // Add the I2 and Q2 values 00122 00123 result = _mm_sqrt_ps(result); // Square root the values 00124 00125 _mm_store_ps(magnitudeVectorPtr, result); 00126 00127 magnitudeVectorPtr += 4; 00128 } 00129 00130 number = quarterPoints * 4; 00131 magnitudeVectorPtr = &magnitudeVector[number]; 00132 complexVectorPtr = (const int16_t*)&complexVector[number]; 00133 for(; number < num_points; number++){ 00134 float val1Real = (float)(*complexVectorPtr++) * iScalar; 00135 float val1Imag = (float)(*complexVectorPtr++) * iScalar; 00136 *magnitudeVectorPtr++ = sqrtf((val1Real * val1Real) + (val1Imag * val1Imag)); 00137 } 00138 } 00139 00140 00141 #endif /* LV_HAVE_SSE */ 00142 00143 #if LV_HAVE_GENERIC 00144 /*! 00145 \brief Calculates the magnitude of the complexVector and stores the results in the magnitudeVector 00146 \param complexVector The vector containing the complex input values 00147 \param magnitudeVector The vector containing the real output values 00148 \param scalar The data value to be divided against each input data value of the input complex vector 00149 \param num_points The number of complex values in complexVector to be calculated and stored into cVector 00150 */ 00151 static inline void volk_16ic_s32f_magnitude_32f_a16_generic(float* magnitudeVector, const lv_16sc_t* complexVector, const float scalar, unsigned int num_points){ 00152 const int16_t* complexVectorPtr = (const int16_t*)complexVector; 00153 float* magnitudeVectorPtr = magnitudeVector; 00154 unsigned int number = 0; 00155 const float invScalar = 1.0 / scalar; 00156 for(number = 0; number < num_points; number++){ 00157 float real = ( (float) (*complexVectorPtr++)) * invScalar; 00158 float imag = ( (float) (*complexVectorPtr++)) * invScalar; 00159 *magnitudeVectorPtr++ = sqrtf((real*real) + (imag*imag)); 00160 } 00161 } 00162 #endif /* LV_HAVE_GENERIC */ 00163 00164 #if LV_HAVE_ORC_DISABLED 00165 /*! 00166 \brief Calculates the magnitude of the complexVector and stores the results in the magnitudeVector 00167 \param complexVector The vector containing the complex input values 00168 \param magnitudeVector The vector containing the real output values 00169 \param scalar The data value to be divided against each input data value of the input complex vector 00170 \param num_points The number of complex values in complexVector to be calculated and stored into cVector 00171 */ 00172 extern void volk_16ic_s32f_magnitude_32f_a16_orc_impl(float* magnitudeVector, const lv_16sc_t* complexVector, const float scalar, unsigned int num_points); 00173 static inline void volk_16ic_s32f_magnitude_32f_a16_orc(float* magnitudeVector, const lv_16sc_t* complexVector, const float scalar, unsigned int num_points){ 00174 volk_16ic_s32f_magnitude_32f_a16_orc_impl(magnitudeVector, complexVector, scalar, num_points); 00175 } 00176 #endif /* LV_HAVE_ORC */ 00177 00178 00179 #endif /* INCLUDED_volk_16ic_s32f_magnitude_32f_a16_H */