GNU Radio 3.5.3.1 C++ API
volk_32f_s32f_convert_16i_a.h
Go to the documentation of this file.
1 #ifndef INCLUDED_volk_32f_s32f_convert_16i_a_H
2 #define INCLUDED_volk_32f_s32f_convert_16i_a_H
3 
4 #include <volk/volk_common.h>
5 #include <inttypes.h>
6 #include <stdio.h>
7 #include <math.h>
8 
9 #ifdef LV_HAVE_SSE2
10 #include <emmintrin.h>
11  /*!
12  \brief Multiplies each point in the input buffer by the scalar value, then converts the result into a 16 bit integer value
13  \param inputVector The floating point input data buffer
14  \param outputVector The 16 bit output data buffer
15  \param scalar The value multiplied against each point in the input buffer
16  \param num_points The number of data values to be converted
17  */
18 static inline void volk_32f_s32f_convert_16i_a_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_load_ps(inputVectorPtr); inputVectorPtr += 4;
39  inputVal2 = _mm_load_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_store_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  */
75 static inline void volk_32f_s32f_convert_16i_a_sse(int16_t* outputVector, const float* inputVector, const float scalar, unsigned int num_points){
76  unsigned int number = 0;
77 
78  const unsigned int quarterPoints = num_points / 4;
79 
80  const float* inputVectorPtr = (const float*)inputVector;
81  int16_t* outputVectorPtr = outputVector;
82 
83  float min_val = -32768;
84  float max_val = 32767;
85  float r;
86 
87  __m128 vScalar = _mm_set_ps1(scalar);
88  __m128 ret;
89  __m128 vmin_val = _mm_set_ps1(min_val);
90  __m128 vmax_val = _mm_set_ps1(max_val);
91 
92  __VOLK_ATTR_ALIGNED(16) float outputFloatBuffer[4];
93 
94  for(;number < quarterPoints; number++){
95  ret = _mm_load_ps(inputVectorPtr);
96  inputVectorPtr += 4;
97 
98  // Scale and clip
99  ret = _mm_max_ps(_mm_min_ps(_mm_mul_ps(ret, vScalar), vmax_val), vmin_val);
100 
101  _mm_store_ps(outputFloatBuffer, ret);
102  *outputVectorPtr++ = (int16_t)rintf(outputFloatBuffer[0]);
103  *outputVectorPtr++ = (int16_t)rintf(outputFloatBuffer[1]);
104  *outputVectorPtr++ = (int16_t)rintf(outputFloatBuffer[2]);
105  *outputVectorPtr++ = (int16_t)rintf(outputFloatBuffer[3]);
106  }
107 
108  number = quarterPoints * 4;
109  for(; number < num_points; number++){
110  r = inputVector[number] * scalar;
111  if(r > max_val)
112  r = max_val;
113  else if(r < min_val)
114  r = min_val;
115  outputVector[number] = (int16_t)rintf(r);
116  }
117 }
118 #endif /* LV_HAVE_SSE */
119 
120 #ifdef LV_HAVE_GENERIC
121  /*!
122  \brief Multiplies each point in the input buffer by the scalar value, then converts the result into a 16 bit integer value
123  \param inputVector The floating point input data buffer
124  \param outputVector The 16 bit output data buffer
125  \param scalar The value multiplied against each point in the input buffer
126  \param num_points The number of data values to be converted
127  */
128 static inline void volk_32f_s32f_convert_16i_a_generic(int16_t* outputVector, const float* inputVector, const float scalar, unsigned int num_points){
129  int16_t* outputVectorPtr = outputVector;
130  const float* inputVectorPtr = inputVector;
131  unsigned int number = 0;
132  float min_val = -32768;
133  float max_val = 32767;
134  float r;
135 
136  for(number = 0; number < num_points; number++){
137  r = *inputVectorPtr++ * scalar;
138  if(r < min_val)
139  r = min_val;
140  else if(r > max_val)
141  r = max_val;
142  *outputVectorPtr++ = (int16_t)rintf(r);
143  }
144 }
145 #endif /* LV_HAVE_GENERIC */
146 
147 
148 
149 
150 #endif /* INCLUDED_volk_32f_s32f_convert_16i_a_H */