Vector Optimized Library of Kernels 2.5.1
Architecture-tuned implementations of math kernels
 
Loading...
Searching...
No Matches
volk_32fc_x2_multiply_conjugate_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
71#ifndef INCLUDED_volk_32fc_x2_multiply_conjugate_32fc_u_H
72#define INCLUDED_volk_32fc_x2_multiply_conjugate_32fc_u_H
73
74#include <float.h>
75#include <inttypes.h>
76#include <stdio.h>
77#include <volk/volk_complex.h>
78
79#ifdef LV_HAVE_AVX
80#include <immintrin.h>
82
84 const lv_32fc_t* aVector,
85 const lv_32fc_t* bVector,
86 unsigned int num_points)
87{
88 unsigned int number = 0;
89 const unsigned int quarterPoints = num_points / 4;
90
91 __m256 x, y, z;
92 lv_32fc_t* c = cVector;
93 const lv_32fc_t* a = aVector;
94 const lv_32fc_t* b = bVector;
95
96 for (; number < quarterPoints; number++) {
97 x = _mm256_loadu_ps(
98 (float*)a); // Load the ar + ai, br + bi ... as ar,ai,br,bi ...
99 y = _mm256_loadu_ps(
100 (float*)b); // Load the cr + ci, dr + di ... as cr,ci,dr,di ...
102 _mm256_storeu_ps((float*)c, z); // Store the results back into the C container
103
104 a += 4;
105 b += 4;
106 c += 4;
107 }
108
109 number = quarterPoints * 4;
110
111 for (; number < num_points; number++) {
112 *c++ = (*a++) * lv_conj(*b++);
113 }
114}
115#endif /* LV_HAVE_AVX */
116
117
118#ifdef LV_HAVE_SSE3
119#include <pmmintrin.h>
121
123 const lv_32fc_t* aVector,
124 const lv_32fc_t* bVector,
125 unsigned int num_points)
126{
127 unsigned int number = 0;
128 const unsigned int halfPoints = num_points / 2;
129
130 __m128 x, y, z;
131 lv_32fc_t* c = cVector;
132 const lv_32fc_t* a = aVector;
133 const lv_32fc_t* b = bVector;
134
135 for (; number < halfPoints; number++) {
136 x = _mm_loadu_ps((float*)a); // Load the ar + ai, br + bi as ar,ai,br,bi
137 y = _mm_loadu_ps((float*)b); // Load the cr + ci, dr + di as cr,ci,dr,di
139 _mm_storeu_ps((float*)c, z); // Store the results back into the C container
140
141 a += 2;
142 b += 2;
143 c += 2;
144 }
145
146 if ((num_points % 2) != 0) {
147 *c = (*a) * lv_conj(*b);
148 }
149}
150#endif /* LV_HAVE_SSE */
151
152
153#ifdef LV_HAVE_GENERIC
154
156 const lv_32fc_t* aVector,
157 const lv_32fc_t* bVector,
158 unsigned int num_points)
159{
160 lv_32fc_t* cPtr = cVector;
161 const lv_32fc_t* aPtr = aVector;
162 const lv_32fc_t* bPtr = bVector;
163 unsigned int number = 0;
164
165 for (number = 0; number < num_points; number++) {
166 *cPtr++ = (*aPtr++) * lv_conj(*bPtr++);
167 }
168}
169#endif /* LV_HAVE_GENERIC */
170
171
172#endif /* INCLUDED_volk_32fc_x2_multiply_conjugate_32fc_u_H */
173#ifndef INCLUDED_volk_32fc_x2_multiply_conjugate_32fc_a_H
174#define INCLUDED_volk_32fc_x2_multiply_conjugate_32fc_a_H
175
176#include <float.h>
177#include <inttypes.h>
178#include <stdio.h>
179#include <volk/volk_complex.h>
180
181#ifdef LV_HAVE_AVX
182#include <immintrin.h>
184
186 const lv_32fc_t* aVector,
187 const lv_32fc_t* bVector,
188 unsigned int num_points)
189{
190 unsigned int number = 0;
191 const unsigned int quarterPoints = num_points / 4;
192
193 __m256 x, y, z;
194 lv_32fc_t* c = cVector;
195 const lv_32fc_t* a = aVector;
196 const lv_32fc_t* b = bVector;
197
198 for (; number < quarterPoints; number++) {
199 x = _mm256_load_ps((float*)a); // Load the ar + ai, br + bi ... as ar,ai,br,bi ...
200 y = _mm256_load_ps((float*)b); // Load the cr + ci, dr + di ... as cr,ci,dr,di ...
202 _mm256_store_ps((float*)c, z); // Store the results back into the C container
203
204 a += 4;
205 b += 4;
206 c += 4;
207 }
208
209 number = quarterPoints * 4;
210
211 for (; number < num_points; number++) {
212 *c++ = (*a++) * lv_conj(*b++);
213 }
214}
215#endif /* LV_HAVE_AVX */
216
217
218#ifdef LV_HAVE_SSE3
219#include <pmmintrin.h>
221
223 const lv_32fc_t* aVector,
224 const lv_32fc_t* bVector,
225 unsigned int num_points)
226{
227 unsigned int number = 0;
228 const unsigned int halfPoints = num_points / 2;
229
230 __m128 x, y, z;
231 lv_32fc_t* c = cVector;
232 const lv_32fc_t* a = aVector;
233 const lv_32fc_t* b = bVector;
234
235 for (; number < halfPoints; number++) {
236 x = _mm_load_ps((float*)a); // Load the ar + ai, br + bi as ar,ai,br,bi
237 y = _mm_load_ps((float*)b); // Load the cr + ci, dr + di as cr,ci,dr,di
239 _mm_store_ps((float*)c, z); // Store the results back into the C container
240
241 a += 2;
242 b += 2;
243 c += 2;
244 }
245
246 if ((num_points % 2) != 0) {
247 *c = (*a) * lv_conj(*b);
248 }
249}
250#endif /* LV_HAVE_SSE */
251
252
253#ifdef LV_HAVE_NEON
254#include <arm_neon.h>
255
257 const lv_32fc_t* aVector,
258 const lv_32fc_t* bVector,
259 unsigned int num_points)
260{
261 lv_32fc_t* a_ptr = (lv_32fc_t*)aVector;
262 lv_32fc_t* b_ptr = (lv_32fc_t*)bVector;
263 unsigned int quarter_points = num_points / 4;
264 float32x4x2_t a_val, b_val, c_val;
265 float32x4x2_t tmp_real, tmp_imag;
266 unsigned int number = 0;
267
268 for (number = 0; number < quarter_points; ++number) {
269 a_val = vld2q_f32((float*)a_ptr); // a0r|a1r|a2r|a3r || a0i|a1i|a2i|a3i
270 b_val = vld2q_f32((float*)b_ptr); // b0r|b1r|b2r|b3r || b0i|b1i|b2i|b3i
271 b_val.val[1] = vnegq_f32(b_val.val[1]);
272 __VOLK_PREFETCH(a_ptr + 4);
273 __VOLK_PREFETCH(b_ptr + 4);
274
275 // multiply the real*real and imag*imag to get real result
276 // a0r*b0r|a1r*b1r|a2r*b2r|a3r*b3r
277 tmp_real.val[0] = vmulq_f32(a_val.val[0], b_val.val[0]);
278 // a0i*b0i|a1i*b1i|a2i*b2i|a3i*b3i
279 tmp_real.val[1] = vmulq_f32(a_val.val[1], b_val.val[1]);
280
281 // Multiply cross terms to get the imaginary result
282 // a0r*b0i|a1r*b1i|a2r*b2i|a3r*b3i
283 tmp_imag.val[0] = vmulq_f32(a_val.val[0], b_val.val[1]);
284 // a0i*b0r|a1i*b1r|a2i*b2r|a3i*b3r
285 tmp_imag.val[1] = vmulq_f32(a_val.val[1], b_val.val[0]);
286
287 // store the results
288 c_val.val[0] = vsubq_f32(tmp_real.val[0], tmp_real.val[1]);
289 c_val.val[1] = vaddq_f32(tmp_imag.val[0], tmp_imag.val[1]);
290 vst2q_f32((float*)cVector, c_val);
291
292 a_ptr += 4;
293 b_ptr += 4;
294 cVector += 4;
295 }
296
297 for (number = quarter_points * 4; number < num_points; number++) {
298 *cVector++ = (*a_ptr++) * conj(*b_ptr++);
299 }
300}
301#endif /* LV_HAVE_NEON */
302
303
304#ifdef LV_HAVE_GENERIC
305
306static inline void
308 const lv_32fc_t* aVector,
309 const lv_32fc_t* bVector,
310 unsigned int num_points)
311{
312 lv_32fc_t* cPtr = cVector;
313 const lv_32fc_t* aPtr = aVector;
314 const lv_32fc_t* bPtr = bVector;
315 unsigned int number = 0;
316
317 for (number = 0; number < num_points; number++) {
318 *cPtr++ = (*aPtr++) * lv_conj(*bPtr++);
319 }
320}
321#endif /* LV_HAVE_GENERIC */
322
323
324#endif /* INCLUDED_volk_32fc_x2_multiply_conjugate_32fc_a_H */
static void volk_32fc_x2_multiply_conjugate_32fc_u_sse3(lv_32fc_t *cVector, const lv_32fc_t *aVector, const lv_32fc_t *bVector, unsigned int num_points)
Definition: volk_32fc_x2_multiply_conjugate_32fc.h:122
static void volk_32fc_x2_multiply_conjugate_32fc_a_sse3(lv_32fc_t *cVector, const lv_32fc_t *aVector, const lv_32fc_t *bVector, unsigned int num_points)
Definition: volk_32fc_x2_multiply_conjugate_32fc.h:222
static void volk_32fc_x2_multiply_conjugate_32fc_generic(lv_32fc_t *cVector, const lv_32fc_t *aVector, const lv_32fc_t *bVector, unsigned int num_points)
Definition: volk_32fc_x2_multiply_conjugate_32fc.h:155
static void volk_32fc_x2_multiply_conjugate_32fc_neon(lv_32fc_t *cVector, const lv_32fc_t *aVector, const lv_32fc_t *bVector, unsigned int num_points)
Definition: volk_32fc_x2_multiply_conjugate_32fc.h:256
static void volk_32fc_x2_multiply_conjugate_32fc_u_avx(lv_32fc_t *cVector, const lv_32fc_t *aVector, const lv_32fc_t *bVector, unsigned int num_points)
Definition: volk_32fc_x2_multiply_conjugate_32fc.h:83
static void volk_32fc_x2_multiply_conjugate_32fc_a_generic(lv_32fc_t *cVector, const lv_32fc_t *aVector, const lv_32fc_t *bVector, unsigned int num_points)
Definition: volk_32fc_x2_multiply_conjugate_32fc.h:307
static void volk_32fc_x2_multiply_conjugate_32fc_a_avx(lv_32fc_t *cVector, const lv_32fc_t *aVector, const lv_32fc_t *bVector, unsigned int num_points)
Definition: volk_32fc_x2_multiply_conjugate_32fc.h:185
static __m256 _mm256_complexconjugatemul_ps(const __m256 x, const __m256 y)
Definition: volk_avx_intrinsics.h:51
#define __VOLK_PREFETCH(addr)
Definition: volk_common.h:62
#define lv_conj(x)
Definition: volk_complex.h:91
float complex lv_32fc_t
Definition: volk_complex.h:65
static __m128 _mm_complexconjugatemul_ps(__m128 x, __m128 y)
Definition: volk_sse3_intrinsics.h:44