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