GNU Radio 3.6.1 C++ API
volk_32f_s32f_convert_16i_u.h
Go to the documentation of this file.
1 #ifndef INCLUDED_volk_32f_s32f_convert_16i_u_H
2 #define INCLUDED_volk_32f_s32f_convert_16i_u_H
3 
4 #include <inttypes.h>
5 #include <stdio.h>
6 #include <math.h>
7 
8 #ifdef LV_HAVE_SSE2
9 #include <emmintrin.h>
10  /*!
11  \brief Multiplies each point in the input buffer by the scalar value, then converts the result into a 16 bit integer value
12  \param inputVector The floating point input data buffer
13  \param outputVector The 16 bit output data buffer
14  \param scalar The value multiplied against each point in the input buffer
15  \param num_points The number of data values to be converted
16  \note Input buffer does NOT need to be properly aligned
17  */
18 static inline void volk_32f_s32f_convert_16i_u_sse2(int16_t* outputVector, const float* inputVector, const float scalar, unsigned int num_points){
19  unsigned int number = 0;
20 
21  const unsigned int eighthPoints = num_points / 8;
22 
23  const float* inputVectorPtr = (const float*)inputVector;
24  int16_t* outputVectorPtr = outputVector;
25 
26  float min_val = -32768;
27  float max_val = 32767;
28  float r;
29 
30  __m128 vScalar = _mm_set_ps1(scalar);
31  __m128 inputVal1, inputVal2;
32  __m128i intInputVal1, intInputVal2;
33  __m128 ret1, ret2;
34  __m128 vmin_val = _mm_set_ps1(min_val);
35  __m128 vmax_val = _mm_set_ps1(max_val);
36 
37  for(;number < eighthPoints; number++){
38  inputVal1 = _mm_loadu_ps(inputVectorPtr); inputVectorPtr += 4;
39  inputVal2 = _mm_loadu_ps(inputVectorPtr); inputVectorPtr += 4;
40 
41  // Scale and clip
42  ret1 = _mm_max_ps(_mm_min_ps(_mm_mul_ps(inputVal1, vScalar), vmax_val), vmin_val);
43  ret2 = _mm_max_ps(_mm_min_ps(_mm_mul_ps(inputVal2, vScalar), vmax_val), vmin_val);
44 
45  intInputVal1 = _mm_cvtps_epi32(ret1);
46  intInputVal2 = _mm_cvtps_epi32(ret2);
47 
48  intInputVal1 = _mm_packs_epi32(intInputVal1, intInputVal2);
49 
50  _mm_storeu_si128((__m128i*)outputVectorPtr, intInputVal1);
51  outputVectorPtr += 8;
52  }
53 
54  number = eighthPoints * 8;
55  for(; number < num_points; number++){
56  r = inputVector[number] * scalar;
57  if(r > max_val)
58  r = max_val;
59  else if(r < min_val)
60  r = min_val;
61  outputVector[number] = (int16_t)rintf(r);
62  }
63 }
64 #endif /* LV_HAVE_SSE2 */
65 
66 #ifdef LV_HAVE_SSE
67 #include <xmmintrin.h>
68  /*!
69  \brief Multiplies each point in the input buffer by the scalar value, then converts the result into a 16 bit integer value
70  \param inputVector The floating point input data buffer
71  \param outputVector The 16 bit output data buffer
72  \param scalar The value multiplied against each point in the input buffer
73  \param num_points The number of data values to be converted
74  \note Input buffer does NOT need to be properly aligned
75  */
76 static inline void volk_32f_s32f_convert_16i_u_sse(int16_t* outputVector, const float* inputVector, const float scalar, unsigned int num_points){
77  unsigned int number = 0;
78 
79  const unsigned int quarterPoints = num_points / 4;
80 
81  const float* inputVectorPtr = (const float*)inputVector;
82  int16_t* outputVectorPtr = outputVector;
83 
84  float min_val = -32768;
85  float max_val = 32767;
86  float r;
87 
88  __m128 vScalar = _mm_set_ps1(scalar);
89  __m128 ret;
90  __m128 vmin_val = _mm_set_ps1(min_val);
91  __m128 vmax_val = _mm_set_ps1(max_val);
92 
93  __VOLK_ATTR_ALIGNED(16) float outputFloatBuffer[4];
94 
95  for(;number < quarterPoints; number++){
96  ret = _mm_loadu_ps(inputVectorPtr);
97  inputVectorPtr += 4;
98 
99  // Scale and clip
100  ret = _mm_max_ps(_mm_min_ps(_mm_mul_ps(ret, vScalar), vmax_val), vmin_val);
101 
102  _mm_store_ps(outputFloatBuffer, ret);
103  *outputVectorPtr++ = (int16_t)rintf(outputFloatBuffer[0]);
104  *outputVectorPtr++ = (int16_t)rintf(outputFloatBuffer[1]);
105  *outputVectorPtr++ = (int16_t)rintf(outputFloatBuffer[2]);
106  *outputVectorPtr++ = (int16_t)rintf(outputFloatBuffer[3]);
107  }
108 
109  number = quarterPoints * 4;
110  for(; number < num_points; number++){
111  r = inputVector[number] * scalar;
112  if(r > max_val)
113  r = max_val;
114  else if(r < min_val)
115  r = min_val;
116  outputVector[number] = (int16_t)rintf(r);
117  }
118 }
119 #endif /* LV_HAVE_SSE */
120 
121 #ifdef LV_HAVE_GENERIC
122  /*!
123  \brief Multiplies each point in the input buffer by the scalar value, then converts the result into a 16 bit integer value
124  \param inputVector The floating point input data buffer
125  \param outputVector The 16 bit output data buffer
126  \param scalar The value multiplied against each point in the input buffer
127  \param num_points The number of data values to be converted
128  \note Input buffer does NOT need to be properly aligned
129  */
130 static inline void volk_32f_s32f_convert_16i_u_generic(int16_t* outputVector, const float* inputVector, const float scalar, unsigned int num_points){
131  int16_t* outputVectorPtr = outputVector;
132  const float* inputVectorPtr = inputVector;
133  unsigned int number = 0;
134  float min_val = -32768;
135  float max_val = 32767;
136  float r;
137 
138  for(number = 0; number < num_points; number++){
139  r = *inputVectorPtr++ * scalar;
140  if(r > max_val)
141  r = max_val;
142  else if(r < min_val)
143  r = min_val;
144  *outputVectorPtr++ = (int16_t)rintf(r);
145  }
146 }
147 #endif /* LV_HAVE_GENERIC */
148 
149 
150 
151 
152 #endif /* INCLUDED_volk_32f_s32f_convert_16i_u_H */