Vector Optimized Library of Kernels  3.0.0
Architecture-tuned implementations of math kernels
volk_32fc_s32f_power_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 VOLK
6  *
7  * SPDX-License-Identifier: LGPL-3.0-or-later
8  */
9 
42 #ifndef INCLUDED_volk_32fc_s32f_power_32fc_a_H
43 #define INCLUDED_volk_32fc_s32f_power_32fc_a_H
44 
45 #include <inttypes.h>
46 #include <math.h>
47 #include <stdio.h>
48 
51  const float power)
52 {
53  const float arg = power * atan2f(lv_creal(exp), lv_cimag(exp));
54  const float mag =
55  powf(lv_creal(exp) * lv_creal(exp) + lv_cimag(exp) * lv_cimag(exp), power / 2);
56  return mag * lv_cmake(-cosf(arg), sinf(arg));
57 }
58 
59 #ifdef LV_HAVE_SSE
60 #include <xmmintrin.h>
61 
62 #ifdef LV_HAVE_LIB_SIMDMATH
63 #include <simdmath.h>
64 #endif /* LV_HAVE_LIB_SIMDMATH */
65 
66 static inline void volk_32fc_s32f_power_32fc_a_sse(lv_32fc_t* cVector,
67  const lv_32fc_t* aVector,
68  const float power,
69  unsigned int num_points)
70 {
71  unsigned int number = 0;
72 
73  lv_32fc_t* cPtr = cVector;
74  const lv_32fc_t* aPtr = aVector;
75 
76 #ifdef LV_HAVE_LIB_SIMDMATH
77  const unsigned int quarterPoints = num_points / 4;
78  __m128 vPower = _mm_set_ps1(power);
79 
80  __m128 cplxValue1, cplxValue2, magnitude, phase, iValue, qValue;
81  for (; number < quarterPoints; number++) {
82 
83  cplxValue1 = _mm_load_ps((float*)aPtr);
84  aPtr += 2;
85 
86  cplxValue2 = _mm_load_ps((float*)aPtr);
87  aPtr += 2;
88 
89  // Convert to polar coordinates
90 
91  // Arrange in i1i2i3i4 format
92  iValue = _mm_shuffle_ps(cplxValue1, cplxValue2, _MM_SHUFFLE(2, 0, 2, 0));
93  // Arrange in q1q2q3q4 format
94  qValue = _mm_shuffle_ps(cplxValue1, cplxValue2, _MM_SHUFFLE(3, 1, 3, 1));
95 
96  phase = atan2f4(qValue, iValue); // Calculate the Phase
97 
98  magnitude = _mm_sqrt_ps(
99  _mm_add_ps(_mm_mul_ps(iValue, iValue),
100  _mm_mul_ps(qValue, qValue))); // Calculate the magnitude by square
101  // rooting the added I2 and Q2 values
102 
103  // Now calculate the power of the polar coordinate data
104  magnitude = powf4(magnitude, vPower); // Take the magnitude to the specified power
105 
106  phase = _mm_mul_ps(phase, vPower); // Multiply the phase by the specified power
107 
108  // Convert back to cartesian coordinates
109  iValue = _mm_mul_ps(cosf4(phase),
110  magnitude); // Multiply the cos of the phase by the magnitude
111  qValue = _mm_mul_ps(sinf4(phase),
112  magnitude); // Multiply the sin of the phase by the magnitude
113 
114  cplxValue1 =
115  _mm_unpacklo_ps(iValue, qValue); // Interleave the lower two i & q values
116  cplxValue2 =
117  _mm_unpackhi_ps(iValue, qValue); // Interleave the upper two i & q values
118 
119  _mm_store_ps((float*)cPtr,
120  cplxValue1); // Store the results back into the C container
121 
122  cPtr += 2;
123 
124  _mm_store_ps((float*)cPtr,
125  cplxValue2); // Store the results back into the C container
126 
127  cPtr += 2;
128  }
129 
130  number = quarterPoints * 4;
131 #endif /* LV_HAVE_LIB_SIMDMATH */
132 
133  for (; number < num_points; number++) {
134  *cPtr++ = __volk_s32fc_s32f_power_s32fc_a((*aPtr++), power);
135  }
136 }
137 #endif /* LV_HAVE_SSE */
138 
139 
140 #ifdef LV_HAVE_GENERIC
141 
142 static inline void volk_32fc_s32f_power_32fc_generic(lv_32fc_t* cVector,
143  const lv_32fc_t* aVector,
144  const float power,
145  unsigned int num_points)
146 {
147  lv_32fc_t* cPtr = cVector;
148  const lv_32fc_t* aPtr = aVector;
149  unsigned int number = 0;
150 
151  for (number = 0; number < num_points; number++) {
152  *cPtr++ = __volk_s32fc_s32f_power_s32fc_a((*aPtr++), power);
153  }
154 }
155 
156 #endif /* LV_HAVE_GENERIC */
157 
158 
159 #endif /* INCLUDED_volk_32fc_s32f_power_32fc_a_H */
float32x4_t __m128
Definition: sse2neon.h:235
#define _mm_shuffle_ps(a, b, imm)
Definition: sse2neon.h:2586
FORCE_INLINE __m128 _mm_unpackhi_ps(__m128 a, __m128 b)
Definition: sse2neon.h:2920
FORCE_INLINE __m128 _mm_mul_ps(__m128 a, __m128 b)
Definition: sse2neon.h:2205
FORCE_INLINE __m128 _mm_set_ps1(float)
Definition: sse2neon.h:2437
FORCE_INLINE __m128 _mm_add_ps(__m128 a, __m128 b)
Definition: sse2neon.h:1039
FORCE_INLINE __m128 _mm_unpacklo_ps(__m128 a, __m128 b)
Definition: sse2neon.h:2942
#define _MM_SHUFFLE(fp3, fp2, fp1, fp0)
Definition: sse2neon.h:195
FORCE_INLINE __m128 _mm_load_ps(const float *p)
Definition: sse2neon.h:1858
FORCE_INLINE void _mm_store_ps(float *p, __m128 a)
Definition: sse2neon.h:2704
FORCE_INLINE __m128 _mm_sqrt_ps(__m128 in)
Definition: sse2neon.h:2659
static void volk_32fc_s32f_power_32fc_generic(lv_32fc_t *cVector, const lv_32fc_t *aVector, const float power, unsigned int num_points)
Definition: volk_32fc_s32f_power_32fc.h:142
static lv_32fc_t __volk_s32fc_s32f_power_s32fc_a(const lv_32fc_t exp, const float power)
raise a complex float to a real float power
Definition: volk_32fc_s32f_power_32fc.h:50
static void volk_32fc_s32f_power_32fc_a_sse(lv_32fc_t *cVector, const lv_32fc_t *aVector, const float power, unsigned int num_points)
Definition: volk_32fc_s32f_power_32fc.h:66
#define lv_cimag(x)
Definition: volk_complex.h:98
#define lv_cmake(r, i)
Definition: volk_complex.h:77
#define lv_creal(x)
Definition: volk_complex.h:96
float complex lv_32fc_t
Definition: volk_complex.h:74