GNU Radio Manual and C++ API Reference  3.7.7
The Free & Open Software Radio Ecosystem
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
volk_8ic_deinterleave_real_8i.h
Go to the documentation of this file.
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2012, 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 /*!
24  * \page volk_8ic_deinterleave_real_8i
25  *
26  * \b Overview
27  *
28  * Deinterleaves the complex 8-bit char vector into just the I (real)
29  * vector.
30  *
31  * <b>Dispatcher Prototype</b>
32  * \code
33  * void volk_8ic_deinterleave_real_8i(int8_t* iBuffer, const lv_8sc_t* complexVector, unsigned int num_points)
34  * \endcode
35  *
36  * \b Inputs
37  * \li complexVector: The complex input vector.
38  * \li num_points: The number of complex data values to be deinterleaved.
39  *
40  * \b Outputs
41  * \li iBuffer: The I buffer output data.
42  *
43  * \b Example
44  * \code
45  * int N = 10000;
46  *
47  * volk_8ic_deinterleave_real_8i();
48  *
49  * volk_free(x);
50  * \endcode
51  */
52 
53 #ifndef INCLUDED_VOLK_8sc_DEINTERLEAVE_REAL_8s_ALIGNED8_H
54 #define INCLUDED_VOLK_8sc_DEINTERLEAVE_REAL_8s_ALIGNED8_H
55 
56 #include <inttypes.h>
57 #include <stdio.h>
58 
59 #ifdef LV_HAVE_SSSE3
60 #include <tmmintrin.h>
61 
62 static inline void
63 volk_8ic_deinterleave_real_8i_a_ssse3(int8_t* iBuffer, const lv_8sc_t* complexVector,
64  unsigned int num_points)
65 {
66  unsigned int number = 0;
67  const int8_t* complexVectorPtr = (int8_t*)complexVector;
68  int8_t* iBufferPtr = iBuffer;
69  __m128i moveMask1 = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 14, 12, 10, 8, 6, 4, 2, 0);
70  __m128i moveMask2 = _mm_set_epi8(14, 12, 10, 8, 6, 4, 2, 0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80);
71  __m128i complexVal1, complexVal2, outputVal;
72 
73  unsigned int sixteenthPoints = num_points / 16;
74 
75  for(number = 0; number < sixteenthPoints; number++){
76  complexVal1 = _mm_load_si128((__m128i*)complexVectorPtr); complexVectorPtr += 16;
77  complexVal2 = _mm_load_si128((__m128i*)complexVectorPtr); complexVectorPtr += 16;
78 
79  complexVal1 = _mm_shuffle_epi8(complexVal1, moveMask1);
80  complexVal2 = _mm_shuffle_epi8(complexVal2, moveMask2);
81 
82  outputVal = _mm_or_si128(complexVal1, complexVal2);
83 
84  _mm_store_si128((__m128i*)iBufferPtr, outputVal);
85  iBufferPtr += 16;
86  }
87 
88  number = sixteenthPoints * 16;
89  for(; number < num_points; number++){
90  *iBufferPtr++ = *complexVectorPtr++;
91  complexVectorPtr++;
92  }
93 }
94 #endif /* LV_HAVE_SSSE3 */
95 
96 
97 #ifdef LV_HAVE_AVX
98 #include <immintrin.h>
99 
100 static inline void
101 volk_8ic_deinterleave_real_8i_a_avx(int8_t* iBuffer, const lv_8sc_t* complexVector,
102  unsigned int num_points)
103 {
104  unsigned int number = 0;
105  const int8_t* complexVectorPtr = (int8_t*)complexVector;
106  int8_t* iBufferPtr = iBuffer;
107  __m128i moveMaskL = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 14, 12, 10, 8, 6, 4, 2, 0);
108  __m128i moveMaskH = _mm_set_epi8(14, 12, 10, 8, 6, 4, 2, 0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80);
109  __m256i complexVal1, complexVal2, outputVal;
110  __m128i complexVal1H, complexVal1L, complexVal2H, complexVal2L, outputVal1, outputVal2;
111 
112  unsigned int thirtysecondPoints = num_points / 32;
113 
114  for(number = 0; number < thirtysecondPoints; number++){
115 
116  complexVal1 = _mm256_load_si256((__m256i*)complexVectorPtr);
117  complexVectorPtr += 32;
118  complexVal2 = _mm256_load_si256((__m256i*)complexVectorPtr);
119  complexVectorPtr += 32;
120 
121  complexVal1H = _mm256_extractf128_si256(complexVal1, 1);
122  complexVal1L = _mm256_extractf128_si256(complexVal1, 0);
123  complexVal2H = _mm256_extractf128_si256(complexVal2, 1);
124  complexVal2L = _mm256_extractf128_si256(complexVal2, 0);
125 
126  complexVal1H = _mm_shuffle_epi8(complexVal1H, moveMaskH);
127  complexVal1L = _mm_shuffle_epi8(complexVal1L, moveMaskL);
128  outputVal1 = _mm_or_si128(complexVal1H, complexVal1L);
129 
130 
131  complexVal2H = _mm_shuffle_epi8(complexVal2H, moveMaskH);
132  complexVal2L = _mm_shuffle_epi8(complexVal2L, moveMaskL);
133  outputVal2 = _mm_or_si128(complexVal2H, complexVal2L);
134 
135  __m256i dummy = _mm256_setzero_si256();
136  outputVal = _mm256_insertf128_si256(dummy, outputVal1, 0);
137  outputVal = _mm256_insertf128_si256(outputVal, outputVal2, 1);
138 
139 
140  _mm256_store_si256((__m256i*)iBufferPtr, outputVal);
141  iBufferPtr += 32;
142  }
143 
144  number = thirtysecondPoints * 32;
145  for(; number < num_points; number++){
146  *iBufferPtr++ = *complexVectorPtr++;
147  complexVectorPtr++;
148  }
149 }
150 #endif /* LV_HAVE_AVX */
151 
152 
153 #ifdef LV_HAVE_GENERIC
154 
155 static inline void
156 volk_8ic_deinterleave_real_8i_generic(int8_t* iBuffer, const lv_8sc_t* complexVector,
157  unsigned int num_points)
158 {
159  unsigned int number = 0;
160  const int8_t* complexVectorPtr = (int8_t*)complexVector;
161  int8_t* iBufferPtr = iBuffer;
162  for(number = 0; number < num_points; number++){
163  *iBufferPtr++ = *complexVectorPtr++;
164  complexVectorPtr++;
165  }
166 }
167 #endif /* LV_HAVE_GENERIC */
168 
169 
170 #ifdef LV_HAVE_NEON
171 #include <arm_neon.h>
172 
173 static inline void
174 volk_8ic_deinterleave_real_8i_neon(int8_t* iBuffer, const lv_8sc_t* complexVector, unsigned int num_points)
175 {
176  unsigned int number;
177  unsigned int sixteenth_points = num_points / 16;
178 
179  int8x16x2_t input_vector;
180  for(number=0; number < sixteenth_points; ++number) {
181  input_vector = vld2q_s8((int8_t*) complexVector );
182  vst1q_s8(iBuffer, input_vector.val[0]);
183  iBuffer += 16;
184  complexVector += 16;
185  }
186 
187  const int8_t* complexVectorPtr = (int8_t*)complexVector;
188  int8_t* iBufferPtr = iBuffer;
189  for(number = sixteenth_points*16; number < num_points; number++){
190  *iBufferPtr++ = *complexVectorPtr++;
191  complexVectorPtr++;
192  }
193 }
194 #endif /* LV_HAVE_NEON */
195 
196 
197 #endif /* INCLUDED_VOLK_8sc_DEINTERLEAVE_REAL_8s_ALIGNED8_H */
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