GNU Radio 3.4.0 C++ API
|
00001 #ifndef INCLUDED_volk_32fc_s32f_power_32fc_a16_H 00002 #define INCLUDED_volk_32fc_s32f_power_32fc_a16_H 00003 00004 #include <inttypes.h> 00005 #include <stdio.h> 00006 00007 #if LV_HAVE_SSE 00008 #include <xmmintrin.h> 00009 00010 #if LV_HAVE_LIB_SIMDMATH 00011 #include <simdmath.h> 00012 #endif /* LV_HAVE_LIB_SIMDMATH */ 00013 00014 /*! 00015 \brief Takes each the input complex vector value to the specified power and stores the results in the return vector 00016 \param cVector The vector where the results will be stored 00017 \param aVector The complex vector of values to be taken to a power 00018 \param power The power value to be applied to each data point 00019 \param num_points The number of values in aVector to be taken to the specified power level and stored into cVector 00020 */ 00021 static inline void volk_32fc_s32f_power_32fc_a16_sse(lv_32fc_t* cVector, const lv_32fc_t* aVector, const float power, unsigned int num_points){ 00022 unsigned int number = 0; 00023 const unsigned int quarterPoints = num_points / 4; 00024 00025 lv_32fc_t* cPtr = cVector; 00026 const lv_32fc_t* aPtr = aVector; 00027 00028 #if LV_HAVE_LIB_SIMDMATH 00029 __m128 vPower = _mm_set_ps1(power); 00030 00031 __m128 cplxValue1, cplxValue2, magnitude, phase, iValue, qValue; 00032 for(;number < quarterPoints; number++){ 00033 00034 cplxValue1 = _mm_load_ps((float*)aPtr); 00035 aPtr += 2; 00036 00037 cplxValue2 = _mm_load_ps((float*)aPtr); 00038 aPtr += 2; 00039 00040 // Convert to polar coordinates 00041 00042 // Arrange in i1i2i3i4 format 00043 iValue = _mm_shuffle_ps(cplxValue1, cplxValue2, _MM_SHUFFLE(2,0,2,0)); 00044 // Arrange in q1q2q3q4 format 00045 qValue = _mm_shuffle_ps(cplxValue1, cplxValue2, _MM_SHUFFLE(3,1,3,1)); 00046 00047 phase = atan2f4(qValue, iValue); // Calculate the Phase 00048 00049 magnitude = _mm_sqrt_ps(_mm_add_ps(_mm_mul_ps(iValue, iValue), _mm_mul_ps(qValue, qValue))); // Calculate the magnitude by square rooting the added I2 and Q2 values 00050 00051 // Now calculate the power of the polar coordinate data 00052 magnitude = powf4(magnitude, vPower); // Take the magnitude to the specified power 00053 00054 phase = _mm_mul_ps(phase, vPower); // Multiply the phase by the specified power 00055 00056 // Convert back to cartesian coordinates 00057 iValue = _mm_mul_ps( cosf4(phase), magnitude); // Multiply the cos of the phase by the magnitude 00058 qValue = _mm_mul_ps( sinf4(phase), magnitude); // Multiply the sin of the phase by the magnitude 00059 00060 cplxValue1 = _mm_unpacklo_ps(iValue, qValue); // Interleave the lower two i & q values 00061 cplxValue2 = _mm_unpackhi_ps(iValue, qValue); // Interleave the upper two i & q values 00062 00063 _mm_store_ps((float*)cPtr,cplxValue1); // Store the results back into the C container 00064 00065 cPtr += 2; 00066 00067 _mm_store_ps((float*)cPtr,cplxValue2); // Store the results back into the C container 00068 00069 cPtr += 2; 00070 } 00071 00072 number = quarterPoints * 4; 00073 #endif /* LV_HAVE_LIB_SIMDMATH */ 00074 00075 lv_32fc_t complexPower; 00076 ((float*)&complexPower)[0] = power; 00077 ((float*)&complexPower)[1] = 0; 00078 for(;number < num_points; number++){ 00079 *cPtr++ = lv_cpow((*aPtr++), complexPower); 00080 } 00081 } 00082 #endif /* LV_HAVE_SSE */ 00083 00084 #if LV_HAVE_GENERIC 00085 /*! 00086 \brief Takes each the input complex vector value to the specified power and stores the results in the return vector 00087 \param cVector The vector where the results will be stored 00088 \param aVector The complex vector of values to be taken to a power 00089 \param power The power value to be applied to each data point 00090 \param num_points The number of values in aVector to be taken to the specified power level and stored into cVector 00091 */ 00092 static inline void volk_32fc_s32f_power_32fc_a16_generic(lv_32fc_t* cVector, const lv_32fc_t* aVector, const float power, unsigned int num_points){ 00093 lv_32fc_t* cPtr = cVector; 00094 const lv_32fc_t* aPtr = aVector; 00095 unsigned int number = 0; 00096 lv_32fc_t complexPower; 00097 ((float*)&complexPower)[0] = power; 00098 ((float*)&complexPower)[1] = 0.0; 00099 00100 for(number = 0; number < num_points; number++){ 00101 *cPtr++ = lv_cpow((*aPtr++), complexPower); 00102 } 00103 } 00104 #endif /* LV_HAVE_GENERIC */ 00105 00106 00107 00108 00109 #endif /* INCLUDED_volk_32fc_s32f_power_32fc_a16_H */