GNU Radio Manual and C++ API Reference  3.7.6.1
The Free & Open Software Radio Ecosystem
volk_8ic_deinterleave_real_16i.h
Go to the documentation of this file.
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2014 Free Software Foundation, Inc.
4  *
5  * This file is part of GNU Radio
6  *
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  *
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING. If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #ifndef INCLUDED_volk_8ic_deinterleave_real_16i_a_H
24 #define INCLUDED_volk_8ic_deinterleave_real_16i_a_H
25 
26 #include <inttypes.h>
27 #include <stdio.h>
28 
29 #ifdef LV_HAVE_SSE4_1
30 #include <smmintrin.h>
31 /*!
32  \brief Deinterleaves the complex 8 bit vector into I 16 bit vector data
33  \param complexVector The complex input vector
34  \param iBuffer The I buffer output data
35  \param num_points The number of complex data values to be deinterleaved
36 */
37 static inline void volk_8ic_deinterleave_real_16i_a_sse4_1(int16_t* iBuffer, const lv_8sc_t* complexVector, unsigned int num_points){
38  unsigned int number = 0;
39  const int8_t* complexVectorPtr = (int8_t*)complexVector;
40  int16_t* iBufferPtr = iBuffer;
41  __m128i moveMask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 14, 12, 10, 8, 6, 4, 2, 0);
42  __m128i complexVal, outputVal;
43 
44  unsigned int eighthPoints = num_points / 8;
45 
46  for(number = 0; number < eighthPoints; number++){
47  complexVal = _mm_load_si128((__m128i*)complexVectorPtr); complexVectorPtr += 16;
48 
49  complexVal = _mm_shuffle_epi8(complexVal, moveMask);
50 
51  outputVal = _mm_cvtepi8_epi16(complexVal);
52  outputVal = _mm_slli_epi16(outputVal, 7);
53 
54  _mm_store_si128((__m128i*)iBufferPtr, outputVal);
55  iBufferPtr += 8;
56  }
57 
58  number = eighthPoints * 8;
59  for(; number < num_points; number++){
60  *iBufferPtr++ = ((int16_t)*complexVectorPtr++) * 128;
61  complexVectorPtr++;
62  }
63 }
64 #endif /* LV_HAVE_SSE4_1 */
65 
66 #ifdef LV_HAVE_AVX
67 #include <immintrin.h>
68 /*!
69  \brief Deinterleaves the complex 8 bit vector into I 16 bit vector data
70  \param complexVector The complex input vector
71  \param iBuffer The I buffer output data
72  \param num_points The number of complex data values to be deinterleaved
73 */
74 static inline void volk_8ic_deinterleave_real_16i_a_avx(int16_t* iBuffer, const lv_8sc_t* complexVector, unsigned int num_points){
75  unsigned int number = 0;
76  const int8_t* complexVectorPtr = (int8_t*)complexVector;
77  int16_t* iBufferPtr = iBuffer;
78  __m128i moveMask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 14, 12, 10, 8, 6, 4, 2, 0);
79  __m256i complexVal, outputVal;
80  __m128i complexVal1, complexVal0, outputVal1, outputVal0;
81 
82  unsigned int sixteenthPoints = num_points / 16;
83 
84  for(number = 0; number < sixteenthPoints; number++){
85  complexVal = _mm256_load_si256((__m256i*)complexVectorPtr); complexVectorPtr += 32;
86 
87  complexVal1 = _mm256_extractf128_si256(complexVal, 1);
88  complexVal0 = _mm256_extractf128_si256(complexVal, 0);
89 
90  outputVal1 = _mm_shuffle_epi8(complexVal1, moveMask);
91  outputVal0 = _mm_shuffle_epi8(complexVal0, moveMask);
92 
93  outputVal1 = _mm_cvtepi8_epi16(outputVal1);
94  outputVal1 = _mm_slli_epi16(outputVal1, 7);
95  outputVal0 = _mm_cvtepi8_epi16(outputVal0);
96  outputVal0 = _mm_slli_epi16(outputVal0, 7);
97 
98  __m256i dummy = _mm256_setzero_si256();
99  outputVal = _mm256_insertf128_si256(dummy, outputVal0, 0);
100  outputVal = _mm256_insertf128_si256(outputVal, outputVal1, 1);
101  _mm256_store_si256((__m256i*)iBufferPtr, outputVal);
102 
103  iBufferPtr += 16;
104  }
105 
106  number = sixteenthPoints * 16;
107  for(; number < num_points; number++){
108  *iBufferPtr++ = ((int16_t)*complexVectorPtr++) * 128;
109  complexVectorPtr++;
110  }
111 }
112 #endif /* LV_HAVE_AVX */
113 
114 
115 #ifdef LV_HAVE_GENERIC
116 /*!
117  \brief Deinterleaves the complex 8 bit vector into I 16 bit vector data
118  \param complexVector The complex input vector
119  \param iBuffer The I buffer output data
120  \param num_points The number of complex data values to be deinterleaved
121 */
122 static inline void volk_8ic_deinterleave_real_16i_generic(int16_t* iBuffer, const lv_8sc_t* complexVector, unsigned int num_points){
123  unsigned int number = 0;
124  const int8_t* complexVectorPtr = (const int8_t*)complexVector;
125  int16_t* iBufferPtr = iBuffer;
126  for(number = 0; number < num_points; number++){
127  *iBufferPtr++ = ((int16_t)(*complexVectorPtr++)) * 128;
128  complexVectorPtr++;
129  }
130 }
131 #endif /* LV_HAVE_GENERIC */
132 
133 
134 
135 
136 #endif /* INCLUDED_volk_8ic_deinterleave_real_16i_a_H */
signed short int16_t
Definition: stdint.h:76
signed char int8_t
Definition: stdint.h:75
char complex lv_8sc_t
Provide typedefs and operators for all complex types in C and C++.
Definition: volk_complex.h:52