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_32f_x2_interleave_32fc.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_32f_x2_interleave_32fc
25  *
26  * \b Overview
27  *
28  * Takes input vector iBuffer as the real (inphase) part and input
29  * vector qBuffer as the imag (quadrature) part and combines them into
30  * a complex output vector.
31  *
32  * c[i] = complex(a[i], b[i])
33  *
34  * <b>Dispatcher Prototype</b>
35  * \code
36  * void volk_32f_x2_interleave_32fc(lv_32fc_t* complexVector, const float* iBuffer, const float* qBuffer, unsigned int num_points)
37  * \endcode
38  *
39  * \b Inputs
40  * \li iBuffer: Input vector of samples for the real part.
41  * \li qBuffer: Input vector of samples for the imaginary part.
42  * \li num_points: The number of values in both input vectors.
43  *
44  * \b Outputs
45  * \li complexVector: The output vector of complex numbers.
46  *
47  * \b Example
48  * Generate the top half of the unit circle with real points equally spaced.
49  * \code
50  * int N = 10;
51  * unsigned int alignment = volk_get_alignment();
52  * float* imag = (float*)volk_malloc(sizeof(float)*N, alignment);
53  * float* real = (float*)volk_malloc(sizeof(float)*N, alignment);
54  * lv_32fc_t* out = (lv_32fc_t*)volk_malloc(sizeof(lv_32fc_t)*N, alignment);
55  *
56  * for(unsigned int ii = 0; ii < N; ++ii){
57  * real[ii] = 2.f * ((float)ii / (float)N) - 1.f;
58  * imag[ii] = std::sqrt(1.f - real[ii] * real[ii]);
59  * }
60  *
61  * volk_32f_x2_interleave_32fc(out, imag, real, N);
62  *
63  * for(unsigned int ii = 0; ii < N; ++ii){
64  * printf("out[%u] = %1.2f + %1.2fj\n", ii, std::real(out[ii]), std::imag(out[ii]));
65  * }
66  *
67  * volk_free(imag);
68  * volk_free(real);
69  * volk_free(out);
70  * \endcode
71  */
72 
73 #ifndef INCLUDED_volk_32f_x2_interleave_32fc_a_H
74 #define INCLUDED_volk_32f_x2_interleave_32fc_a_H
75 
76 #include <inttypes.h>
77 #include <stdio.h>
78 
79 #ifdef LV_HAVE_SSE
80 #include <xmmintrin.h>
81 
82 static inline void
83 volk_32f_x2_interleave_32fc_a_sse(lv_32fc_t* complexVector, const float* iBuffer,
84  const float* qBuffer, unsigned int num_points)
85 {
86  unsigned int number = 0;
87  float* complexVectorPtr = (float*)complexVector;
88  const float* iBufferPtr = iBuffer;
89  const float* qBufferPtr = qBuffer;
90 
91  const uint64_t quarterPoints = num_points / 4;
92 
93  __m128 iValue, qValue, cplxValue;
94  for(;number < quarterPoints; number++){
95  iValue = _mm_load_ps(iBufferPtr);
96  qValue = _mm_load_ps(qBufferPtr);
97 
98  // Interleaves the lower two values in the i and q variables into one buffer
99  cplxValue = _mm_unpacklo_ps(iValue, qValue);
100  _mm_store_ps(complexVectorPtr, cplxValue);
101  complexVectorPtr += 4;
102 
103  // Interleaves the upper two values in the i and q variables into one buffer
104  cplxValue = _mm_unpackhi_ps(iValue, qValue);
105  _mm_store_ps(complexVectorPtr, cplxValue);
106  complexVectorPtr += 4;
107 
108  iBufferPtr += 4;
109  qBufferPtr += 4;
110  }
111 
112  number = quarterPoints * 4;
113  for(; number < num_points; number++){
114  *complexVectorPtr++ = *iBufferPtr++;
115  *complexVectorPtr++ = *qBufferPtr++;
116  }
117 }
118 #endif /* LV_HAVE_SSE */
119 
120 
121 #ifdef LV_HAVE_NEON
122 #include <arm_neon.h>
123 
124 static inline void
125 volk_32f_x2_interleave_32fc_neon(lv_32fc_t* complexVector, const float* iBuffer,
126  const float* qBuffer, unsigned int num_points)
127 {
128  unsigned int quarter_points = num_points / 4;
129  unsigned int number;
130  float* complexVectorPtr = (float*) complexVector;
131 
132  float32x4x2_t complex_vec;
133  for(number=0; number < quarter_points; ++number) {
134  complex_vec.val[0] = vld1q_f32(iBuffer);
135  complex_vec.val[1] = vld1q_f32(qBuffer);
136  vst2q_f32(complexVectorPtr, complex_vec);
137  iBuffer += 4;
138  qBuffer += 4;
139  complexVectorPtr += 8;
140  }
141 
142  for(number=quarter_points * 4; number < num_points; ++number) {
143  *complexVectorPtr++ = *iBuffer++;
144  *complexVectorPtr++ = *qBuffer++;
145  }
146 }
147 #endif /* LV_HAVE_NEON */
148 
149 
150 #ifdef LV_HAVE_GENERIC
151 
152 static inline void
153 volk_32f_x2_interleave_32fc_generic(lv_32fc_t* complexVector, const float* iBuffer,
154  const float* qBuffer, unsigned int num_points)
155 {
156  float* complexVectorPtr = (float*)complexVector;
157  const float* iBufferPtr = iBuffer;
158  const float* qBufferPtr = qBuffer;
159  unsigned int number;
160 
161  for(number = 0; number < num_points; number++){
162  *complexVectorPtr++ = *iBufferPtr++;
163  *complexVectorPtr++ = *qBufferPtr++;
164  }
165 }
166 #endif /* LV_HAVE_GENERIC */
167 
168 
169 
170 #endif /* INCLUDED_volk_32f_x2_interleave_32fc_a_H */
unsigned __int64 uint64_t
Definition: stdint.h:90
float complex lv_32fc_t
Definition: volk_complex.h:56