GNU Radio 3.6.5 C++ API

volk_16ic_deinterleave_16i_x2_a.h

Go to the documentation of this file.
00001 #ifndef INCLUDED_volk_16ic_deinterleave_16i_x2_a_H
00002 #define INCLUDED_volk_16ic_deinterleave_16i_x2_a_H
00003 
00004 #include <inttypes.h>
00005 #include <stdio.h>
00006 
00007 #ifdef LV_HAVE_SSSE3
00008 #include <tmmintrin.h>
00009 /*!
00010   \brief Deinterleaves the complex 16 bit vector into I & Q vector data
00011   \param complexVector The complex input vector
00012   \param iBuffer The I buffer output data
00013   \param qBuffer The Q buffer output data
00014   \param num_points The number of complex data values to be deinterleaved
00015 */
00016 static inline void volk_16ic_deinterleave_16i_x2_a_ssse3(int16_t* iBuffer, int16_t* qBuffer, const lv_16sc_t* complexVector, unsigned int num_points){
00017   unsigned int number = 0;
00018   const int8_t* complexVectorPtr = (int8_t*)complexVector;
00019   int16_t* iBufferPtr = iBuffer;
00020   int16_t* qBufferPtr = qBuffer;
00021 
00022   __m128i iMoveMask1 = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 13, 12, 9, 8, 5, 4, 1, 0);
00023   __m128i iMoveMask2 = _mm_set_epi8(13, 12, 9, 8, 5, 4, 1, 0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80);
00024 
00025   __m128i qMoveMask1 = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 15, 14, 11, 10, 7, 6, 3, 2);
00026   __m128i qMoveMask2 = _mm_set_epi8(15, 14, 11, 10, 7, 6, 3, 2, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80);
00027 
00028   __m128i complexVal1, complexVal2, iOutputVal, qOutputVal;
00029 
00030   unsigned int eighthPoints = num_points / 8;
00031 
00032   for(number = 0; number < eighthPoints; number++){
00033     complexVal1 = _mm_load_si128((__m128i*)complexVectorPtr);  complexVectorPtr += 16;
00034     complexVal2 = _mm_load_si128((__m128i*)complexVectorPtr);  complexVectorPtr += 16;
00035 
00036     iOutputVal = _mm_or_si128( _mm_shuffle_epi8(complexVal1, iMoveMask1) , _mm_shuffle_epi8(complexVal2, iMoveMask2));
00037     qOutputVal = _mm_or_si128( _mm_shuffle_epi8(complexVal1, qMoveMask1) , _mm_shuffle_epi8(complexVal2, qMoveMask2));
00038 
00039     _mm_store_si128((__m128i*)iBufferPtr, iOutputVal);
00040     _mm_store_si128((__m128i*)qBufferPtr, qOutputVal);
00041 
00042     iBufferPtr += 8;
00043     qBufferPtr += 8;
00044   }
00045 
00046   number = eighthPoints * 8;
00047   int16_t* int16ComplexVectorPtr = (int16_t*)complexVectorPtr;
00048   for(; number < num_points; number++){
00049     *iBufferPtr++ = *int16ComplexVectorPtr++;
00050     *qBufferPtr++ = *int16ComplexVectorPtr++;
00051   }
00052 }
00053 #endif /* LV_HAVE_SSSE3 */
00054 
00055 #ifdef LV_HAVE_SSE2
00056 #include <emmintrin.h>
00057 /*!
00058   \brief Deinterleaves the complex 16 bit vector into I & Q vector data
00059   \param complexVector The complex input vector
00060   \param iBuffer The I buffer output data
00061   \param qBuffer The Q buffer output data
00062   \param num_points The number of complex data values to be deinterleaved
00063 */
00064 static inline void volk_16ic_deinterleave_16i_x2_a_sse2(int16_t* iBuffer, int16_t* qBuffer, const lv_16sc_t* complexVector, unsigned int num_points){
00065   unsigned int number = 0;
00066   const int16_t* complexVectorPtr = (int16_t*)complexVector;
00067   int16_t* iBufferPtr = iBuffer;
00068   int16_t* qBufferPtr = qBuffer;
00069   __m128i complexVal1, complexVal2, iComplexVal1, iComplexVal2, qComplexVal1, qComplexVal2, iOutputVal, qOutputVal;
00070   __m128i lowMask = _mm_set_epi32(0x0, 0x0, 0xFFFFFFFF, 0xFFFFFFFF);
00071   __m128i highMask = _mm_set_epi32(0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0);
00072 
00073   unsigned int eighthPoints = num_points / 8;
00074 
00075   for(number = 0; number < eighthPoints; number++){
00076     complexVal1 = _mm_load_si128((__m128i*)complexVectorPtr);  complexVectorPtr += 8;
00077     complexVal2 = _mm_load_si128((__m128i*)complexVectorPtr);  complexVectorPtr += 8;
00078 
00079     iComplexVal1 = _mm_shufflelo_epi16(complexVal1, _MM_SHUFFLE(3,1,2,0));
00080 
00081     iComplexVal1 = _mm_shufflehi_epi16(iComplexVal1, _MM_SHUFFLE(3,1,2,0));
00082 
00083     iComplexVal1 = _mm_shuffle_epi32(iComplexVal1, _MM_SHUFFLE(3,1,2,0));
00084 
00085     iComplexVal2 = _mm_shufflelo_epi16(complexVal2, _MM_SHUFFLE(3,1,2,0));
00086 
00087     iComplexVal2 = _mm_shufflehi_epi16(iComplexVal2, _MM_SHUFFLE(3,1,2,0));
00088 
00089     iComplexVal2 = _mm_shuffle_epi32(iComplexVal2, _MM_SHUFFLE(2,0,3,1));
00090 
00091     iOutputVal = _mm_or_si128(_mm_and_si128(iComplexVal1, lowMask), _mm_and_si128(iComplexVal2, highMask));
00092 
00093     _mm_store_si128((__m128i*)iBufferPtr, iOutputVal);
00094 
00095     qComplexVal1 = _mm_shufflelo_epi16(complexVal1, _MM_SHUFFLE(2,0,3,1));
00096 
00097     qComplexVal1 = _mm_shufflehi_epi16(qComplexVal1, _MM_SHUFFLE(2,0,3,1));
00098 
00099     qComplexVal1 = _mm_shuffle_epi32(qComplexVal1, _MM_SHUFFLE(3,1,2,0));
00100 
00101     qComplexVal2 = _mm_shufflelo_epi16(complexVal2, _MM_SHUFFLE(2,0,3,1));
00102 
00103     qComplexVal2 = _mm_shufflehi_epi16(qComplexVal2, _MM_SHUFFLE(2,0,3,1));
00104 
00105     qComplexVal2 = _mm_shuffle_epi32(qComplexVal2, _MM_SHUFFLE(2,0,3,1));
00106 
00107     qOutputVal = _mm_or_si128(_mm_and_si128(qComplexVal1, lowMask), _mm_and_si128(qComplexVal2, highMask));
00108 
00109     _mm_store_si128((__m128i*)qBufferPtr, qOutputVal);
00110 
00111     iBufferPtr += 8;
00112     qBufferPtr += 8;
00113   }
00114 
00115   number = eighthPoints * 8;
00116   for(; number < num_points; number++){
00117     *iBufferPtr++ = *complexVectorPtr++;
00118     *qBufferPtr++ = *complexVectorPtr++;
00119   }
00120 }
00121 #endif /* LV_HAVE_SSE2 */
00122 
00123 #ifdef LV_HAVE_GENERIC
00124 /*!
00125   \brief Deinterleaves the complex 16 bit vector into I & Q vector data
00126   \param complexVector The complex input vector
00127   \param iBuffer The I buffer output data
00128   \param qBuffer The Q buffer output data
00129   \param num_points The number of complex data values to be deinterleaved
00130 */
00131 static inline void volk_16ic_deinterleave_16i_x2_a_generic(int16_t* iBuffer, int16_t* qBuffer, const lv_16sc_t* complexVector, unsigned int num_points){
00132   const int16_t* complexVectorPtr = (const int16_t*)complexVector;
00133   int16_t* iBufferPtr = iBuffer;
00134   int16_t* qBufferPtr = qBuffer;
00135   unsigned int number;
00136   for(number = 0; number < num_points; number++){
00137     *iBufferPtr++ = *complexVectorPtr++;
00138     *qBufferPtr++ = *complexVectorPtr++;
00139   }
00140 }
00141 #endif /* LV_HAVE_GENERIC */
00142 
00143 #ifdef LV_HAVE_ORC
00144 /*!
00145   \brief Deinterleaves the complex 16 bit vector into I & Q vector data
00146   \param complexVector The complex input vector
00147   \param iBuffer The I buffer output data
00148   \param qBuffer The Q buffer output data
00149   \param num_points The number of complex data values to be deinterleaved
00150 */
00151 extern void volk_16ic_deinterleave_16i_x2_a_orc_impl(int16_t* iBuffer, int16_t* qBuffer, const lv_16sc_t* complexVector, unsigned int num_points);
00152 static inline void volk_16ic_deinterleave_16i_x2_a_orc(int16_t* iBuffer, int16_t* qBuffer, const lv_16sc_t* complexVector, unsigned int num_points){
00153     volk_16ic_deinterleave_16i_x2_a_orc_impl(iBuffer, qBuffer, complexVector, num_points);
00154 }
00155 #endif /* LV_HAVE_ORC */
00156 
00157 
00158 #endif /* INCLUDED_volk_16ic_deinterleave_16i_x2_a_H */