GNU Radio 3.6.5 C++ API
|
00001 #ifndef INCLUDED_volk_8ic_s32f_deinterleave_32f_x2_a_H 00002 #define INCLUDED_volk_8ic_s32f_deinterleave_32f_x2_a_H 00003 00004 #include <volk/volk_common.h> 00005 #include <inttypes.h> 00006 #include <stdio.h> 00007 00008 #ifdef LV_HAVE_SSE4_1 00009 #include <smmintrin.h> 00010 /*! 00011 \brief Deinterleaves the complex 8 bit vector into I & Q floating point vector data 00012 \param complexVector The complex input vector 00013 \param iBuffer The I buffer output data 00014 \param qBuffer The Q buffer output data 00015 \param scalar The scaling value being multiplied against each data point 00016 \param num_points The number of complex data values to be deinterleaved 00017 */ 00018 static inline void volk_8ic_s32f_deinterleave_32f_x2_a_sse4_1(float* iBuffer, float* qBuffer, const lv_8sc_t* complexVector, const float scalar, unsigned int num_points){ 00019 float* iBufferPtr = iBuffer; 00020 float* qBufferPtr = qBuffer; 00021 00022 unsigned int number = 0; 00023 const unsigned int eighthPoints = num_points / 8; 00024 __m128 iFloatValue, qFloatValue; 00025 00026 const float iScalar= 1.0 / scalar; 00027 __m128 invScalar = _mm_set_ps1(iScalar); 00028 __m128i complexVal, iIntVal, qIntVal, iComplexVal, qComplexVal; 00029 int8_t* complexVectorPtr = (int8_t*)complexVector; 00030 00031 __m128i iMoveMask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 14, 12, 10, 8, 6, 4, 2, 0); 00032 __m128i qMoveMask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 15, 13, 11, 9, 7, 5, 3, 1); 00033 00034 for(;number < eighthPoints; number++){ 00035 complexVal = _mm_load_si128((__m128i*)complexVectorPtr); complexVectorPtr += 16; 00036 iComplexVal = _mm_shuffle_epi8(complexVal, iMoveMask); 00037 qComplexVal = _mm_shuffle_epi8(complexVal, qMoveMask); 00038 00039 iIntVal = _mm_cvtepi8_epi32(iComplexVal); 00040 iFloatValue = _mm_cvtepi32_ps(iIntVal); 00041 iFloatValue = _mm_mul_ps(iFloatValue, invScalar); 00042 _mm_store_ps(iBufferPtr, iFloatValue); 00043 iBufferPtr += 4; 00044 00045 iComplexVal = _mm_srli_si128(iComplexVal, 4); 00046 00047 iIntVal = _mm_cvtepi8_epi32(iComplexVal); 00048 iFloatValue = _mm_cvtepi32_ps(iIntVal); 00049 iFloatValue = _mm_mul_ps(iFloatValue, invScalar); 00050 _mm_store_ps(iBufferPtr, iFloatValue); 00051 iBufferPtr += 4; 00052 00053 qIntVal = _mm_cvtepi8_epi32(qComplexVal); 00054 qFloatValue = _mm_cvtepi32_ps(qIntVal); 00055 qFloatValue = _mm_mul_ps(qFloatValue, invScalar); 00056 _mm_store_ps(qBufferPtr, qFloatValue); 00057 qBufferPtr += 4; 00058 00059 qComplexVal = _mm_srli_si128(qComplexVal, 4); 00060 00061 qIntVal = _mm_cvtepi8_epi32(qComplexVal); 00062 qFloatValue = _mm_cvtepi32_ps(qIntVal); 00063 qFloatValue = _mm_mul_ps(qFloatValue, invScalar); 00064 _mm_store_ps(qBufferPtr, qFloatValue); 00065 00066 qBufferPtr += 4; 00067 } 00068 00069 number = eighthPoints * 8; 00070 for(; number < num_points; number++){ 00071 *iBufferPtr++ = (float)(*complexVectorPtr++) * iScalar; 00072 *qBufferPtr++ = (float)(*complexVectorPtr++) * iScalar; 00073 } 00074 00075 } 00076 #endif /* LV_HAVE_SSE4_1 */ 00077 00078 #ifdef LV_HAVE_SSE 00079 #include <xmmintrin.h> 00080 /*! 00081 \brief Deinterleaves the complex 8 bit vector into I & Q floating point vector data 00082 \param complexVector The complex input vector 00083 \param iBuffer The I buffer output data 00084 \param qBuffer The Q buffer output data 00085 \param scalar The scaling value being multiplied against each data point 00086 \param num_points The number of complex data values to be deinterleaved 00087 */ 00088 static inline void volk_8ic_s32f_deinterleave_32f_x2_a_sse(float* iBuffer, float* qBuffer, const lv_8sc_t* complexVector, const float scalar, unsigned int num_points){ 00089 float* iBufferPtr = iBuffer; 00090 float* qBufferPtr = qBuffer; 00091 00092 unsigned int number = 0; 00093 const unsigned int quarterPoints = num_points / 4; 00094 __m128 cplxValue1, cplxValue2, iValue, qValue; 00095 00096 __m128 invScalar = _mm_set_ps1(1.0/scalar); 00097 int8_t* complexVectorPtr = (int8_t*)complexVector; 00098 00099 __VOLK_ATTR_ALIGNED(16) float floatBuffer[8]; 00100 00101 for(;number < quarterPoints; number++){ 00102 floatBuffer[0] = (float)(complexVectorPtr[0]); 00103 floatBuffer[1] = (float)(complexVectorPtr[1]); 00104 floatBuffer[2] = (float)(complexVectorPtr[2]); 00105 floatBuffer[3] = (float)(complexVectorPtr[3]); 00106 00107 floatBuffer[4] = (float)(complexVectorPtr[4]); 00108 floatBuffer[5] = (float)(complexVectorPtr[5]); 00109 floatBuffer[6] = (float)(complexVectorPtr[6]); 00110 floatBuffer[7] = (float)(complexVectorPtr[7]); 00111 00112 cplxValue1 = _mm_load_ps(&floatBuffer[0]); 00113 cplxValue2 = _mm_load_ps(&floatBuffer[4]); 00114 00115 complexVectorPtr += 8; 00116 00117 cplxValue1 = _mm_mul_ps(cplxValue1, invScalar); 00118 cplxValue2 = _mm_mul_ps(cplxValue2, invScalar); 00119 00120 // Arrange in i1i2i3i4 format 00121 iValue = _mm_shuffle_ps(cplxValue1, cplxValue2, _MM_SHUFFLE(2,0,2,0)); 00122 qValue = _mm_shuffle_ps(cplxValue1, cplxValue2, _MM_SHUFFLE(3,1,3,1)); 00123 00124 _mm_store_ps(iBufferPtr, iValue); 00125 _mm_store_ps(qBufferPtr, qValue); 00126 00127 iBufferPtr += 4; 00128 qBufferPtr += 4; 00129 } 00130 00131 number = quarterPoints * 4; 00132 complexVectorPtr = (int8_t*)&complexVector[number]; 00133 for(; number < num_points; number++){ 00134 *iBufferPtr++ = (float)(*complexVectorPtr++) / scalar; 00135 *qBufferPtr++ = (float)(*complexVectorPtr++) / scalar; 00136 } 00137 } 00138 #endif /* LV_HAVE_SSE */ 00139 00140 #ifdef LV_HAVE_GENERIC 00141 /*! 00142 \brief Deinterleaves the complex 8 bit vector into I & Q floating point vector data 00143 \param complexVector The complex input vector 00144 \param iBuffer The I buffer output data 00145 \param qBuffer The Q buffer output data 00146 \param scalar The scaling value being multiplied against each data point 00147 \param num_points The number of complex data values to be deinterleaved 00148 */ 00149 static inline void volk_8ic_s32f_deinterleave_32f_x2_a_generic(float* iBuffer, float* qBuffer, const lv_8sc_t* complexVector, const float scalar, unsigned int num_points){ 00150 const int8_t* complexVectorPtr = (const int8_t*)complexVector; 00151 float* iBufferPtr = iBuffer; 00152 float* qBufferPtr = qBuffer; 00153 unsigned int number; 00154 const float invScalar = 1.0 / scalar; 00155 for(number = 0; number < num_points; number++){ 00156 *iBufferPtr++ = (float)(*complexVectorPtr++)*invScalar; 00157 *qBufferPtr++ = (float)(*complexVectorPtr++)*invScalar; 00158 } 00159 } 00160 #endif /* LV_HAVE_GENERIC */ 00161 00162 00163 00164 00165 #endif /* INCLUDED_volk_8ic_s32f_deinterleave_32f_x2_a_H */