GNU Radio 3.6.5 C++ API

volk_32fc_x2_dot_prod_32fc_u.h

Go to the documentation of this file.
00001 #ifndef INCLUDED_volk_32fc_x2_dot_prod_32fc_u_H
00002 #define INCLUDED_volk_32fc_x2_dot_prod_32fc_u_H
00003 
00004 #include <volk/volk_common.h>
00005 #include <volk/volk_complex.h>
00006 #include <stdio.h>
00007 #include <string.h>
00008 
00009 
00010 #ifdef LV_HAVE_GENERIC
00011 
00012 
00013 static inline void volk_32fc_x2_dot_prod_32fc_u_generic(lv_32fc_t* result, const lv_32fc_t* input, const lv_32fc_t* taps, unsigned int num_points) {
00014 
00015   float * res = (float*) result;
00016   float * in = (float*) input;
00017   float * tp = (float*) taps;
00018   unsigned int n_2_ccomplex_blocks = num_points/2;
00019   unsigned int isodd = num_points &1;
00020 
00021 
00022 
00023   float sum0[2] = {0,0};
00024   float sum1[2] = {0,0};
00025   unsigned int i = 0;
00026 
00027 
00028   for(i = 0; i < n_2_ccomplex_blocks; ++i) {
00029 
00030 
00031     sum0[0] += in[0] * tp[0] - in[1] * tp[1];
00032     sum0[1] += in[0] * tp[1] + in[1] * tp[0];
00033     sum1[0] += in[2] * tp[2] - in[3] * tp[3];
00034     sum1[1] += in[2] * tp[3] + in[3] * tp[2];
00035 
00036 
00037     in += 4;
00038     tp += 4;
00039 
00040   }
00041 
00042 
00043   res[0] = sum0[0] + sum1[0];
00044   res[1] = sum0[1] + sum1[1];
00045 
00046 
00047 
00048   for(i = 0; i < isodd; ++i) {
00049 
00050 
00051     *result += input[num_points - 1] * taps[num_points - 1];
00052 
00053   }
00054 
00055 }
00056 
00057 #endif /*LV_HAVE_GENERIC*/
00058 
00059 #ifdef LV_HAVE_SSE3
00060 
00061 #include <pmmintrin.h>
00062 
00063 static inline void volk_32fc_x2_dot_prod_32fc_u_sse3(lv_32fc_t* result, const lv_32fc_t* input, const lv_32fc_t* taps, unsigned int num_points) {
00064 
00065 
00066   lv_32fc_t dotProduct;
00067   memset(&dotProduct, 0x0, 2*sizeof(float));
00068 
00069   unsigned int number = 0;
00070   const unsigned int halfPoints = num_points/2;
00071 
00072   __m128 x, y, yl, yh, z, tmp1, tmp2, dotProdVal;
00073 
00074   const lv_32fc_t* a = input;
00075   const lv_32fc_t* b = taps;
00076 
00077   dotProdVal = _mm_setzero_ps();
00078 
00079   for(;number < halfPoints; number++){
00080 
00081     x = _mm_loadu_ps((float*)a); // Load the ar + ai, br + bi as ar,ai,br,bi
00082     y = _mm_loadu_ps((float*)b); // Load the cr + ci, dr + di as cr,ci,dr,di
00083 
00084     yl = _mm_moveldup_ps(y); // Load yl with cr,cr,dr,dr
00085     yh = _mm_movehdup_ps(y); // Load yh with ci,ci,di,di
00086 
00087     tmp1 = _mm_mul_ps(x,yl); // tmp1 = ar*cr,ai*cr,br*dr,bi*dr
00088 
00089     x = _mm_shuffle_ps(x,x,0xB1); // Re-arrange x to be ai,ar,bi,br
00090 
00091     tmp2 = _mm_mul_ps(x,yh); // tmp2 = ai*ci,ar*ci,bi*di,br*di
00092 
00093     z = _mm_addsub_ps(tmp1,tmp2); // ar*cr-ai*ci, ai*cr+ar*ci, br*dr-bi*di, bi*dr+br*di
00094 
00095     dotProdVal = _mm_add_ps(dotProdVal, z); // Add the complex multiplication results together
00096 
00097     a += 2;
00098     b += 2;
00099   }
00100 
00101   __VOLK_ATTR_ALIGNED(16) lv_32fc_t dotProductVector[2];
00102 
00103   _mm_storeu_ps((float*)dotProductVector,dotProdVal); // Store the results back into the dot product vector
00104 
00105   dotProduct += ( dotProductVector[0] + dotProductVector[1] );
00106 
00107   if(num_points % 1 != 0) {
00108     dotProduct += (*a) * (*b);
00109   }
00110 
00111   *result = dotProduct;
00112 }
00113 
00114 #endif /*LV_HAVE_SSE3*/
00115 
00116 #endif /*INCLUDED_volk_32fc_x2_dot_prod_32fc_u_H*/