Vector Optimized Library of Kernels  2.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 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 
55 #ifndef INCLUDED_volk_32fc_s32f_power_32fc_a_H
56 #define INCLUDED_volk_32fc_s32f_power_32fc_a_H
57 
58 #include <inttypes.h>
59 #include <stdio.h>
60 #include <math.h>
61 
63 static inline lv_32fc_t __volk_s32fc_s32f_power_s32fc_a(const lv_32fc_t exp, const float power)
64 {
65  const float arg = power*atan2f(lv_creal(exp), lv_cimag(exp));
66  const float mag = powf(lv_creal(exp)*lv_creal(exp) + lv_cimag(exp)*lv_cimag(exp), power/2);
67  return mag*lv_cmake(-cosf(arg), sinf(arg));
68 }
69 
70 #ifdef LV_HAVE_SSE
71 #include <xmmintrin.h>
72 
73 #ifdef LV_HAVE_LIB_SIMDMATH
74 #include <simdmath.h>
75 #endif /* LV_HAVE_LIB_SIMDMATH */
76 
77 static inline void
79  const float power, unsigned int num_points)
80 {
81  unsigned int number = 0;
82 
83  lv_32fc_t* cPtr = cVector;
84  const lv_32fc_t* aPtr = aVector;
85 
86 #ifdef LV_HAVE_LIB_SIMDMATH
87  const unsigned int quarterPoints = num_points / 4;
88  __m128 vPower = _mm_set_ps1(power);
89 
90  __m128 cplxValue1, cplxValue2, magnitude, phase, iValue, qValue;
91  for(;number < quarterPoints; number++){
92 
93  cplxValue1 = _mm_load_ps((float*)aPtr);
94  aPtr += 2;
95 
96  cplxValue2 = _mm_load_ps((float*)aPtr);
97  aPtr += 2;
98 
99  // Convert to polar coordinates
100 
101  // Arrange in i1i2i3i4 format
102  iValue = _mm_shuffle_ps(cplxValue1, cplxValue2, _MM_SHUFFLE(2,0,2,0));
103  // Arrange in q1q2q3q4 format
104  qValue = _mm_shuffle_ps(cplxValue1, cplxValue2, _MM_SHUFFLE(3,1,3,1));
105 
106  phase = atan2f4(qValue, iValue); // Calculate the Phase
107 
108  magnitude = _mm_sqrt_ps(_mm_add_ps(_mm_mul_ps(iValue, iValue), _mm_mul_ps(qValue, qValue))); // Calculate the magnitude by square rooting the added I2 and Q2 values
109 
110  // Now calculate the power of the polar coordinate data
111  magnitude = powf4(magnitude, vPower); // Take the magnitude to the specified power
112 
113  phase = _mm_mul_ps(phase, vPower); // Multiply the phase by the specified power
114 
115  // Convert back to cartesian coordinates
116  iValue = _mm_mul_ps( cosf4(phase), magnitude); // Multiply the cos of the phase by the magnitude
117  qValue = _mm_mul_ps( sinf4(phase), magnitude); // Multiply the sin of the phase by the magnitude
118 
119  cplxValue1 = _mm_unpacklo_ps(iValue, qValue); // Interleave the lower two i & q values
120  cplxValue2 = _mm_unpackhi_ps(iValue, qValue); // Interleave the upper two i & q values
121 
122  _mm_store_ps((float*)cPtr,cplxValue1); // Store the results back into the C container
123 
124  cPtr += 2;
125 
126  _mm_store_ps((float*)cPtr,cplxValue2); // Store the results back into the C container
127 
128  cPtr += 2;
129  }
130 
131  number = quarterPoints * 4;
132 #endif /* LV_HAVE_LIB_SIMDMATH */
133 
134  for(;number < num_points; number++){
135  *cPtr++ = __volk_s32fc_s32f_power_s32fc_a((*aPtr++), power);
136  }
137 }
138 #endif /* LV_HAVE_SSE */
139 
140 
141 #ifdef LV_HAVE_GENERIC
142 
143 static inline void
145  const float power, 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 */
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:78
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:63
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:144
#define lv_cmake(r, i)
Definition: volk_complex.h:64
float complex lv_32fc_t
Definition: volk_complex.h:61
#define lv_creal(x)
Definition: volk_complex.h:83
#define lv_cimag(x)
Definition: volk_complex.h:85