1 /* ----------------------------------------------------------------------
2 * Project: CMSIS DSP Library
3 * Title: arm_float_to_q31.c
4 * Description: Converts the elements of the floating-point vector to Q31 vector
5 *
6 * $Date: 23 April 2021
7 * $Revision: V1.9.0
8 *
9 * Target Processor: Cortex-M and Cortex-A cores
10 * -------------------------------------------------------------------- */
11 /*
12 * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved.
13 *
14 * SPDX-License-Identifier: Apache-2.0
15 *
16 * Licensed under the Apache License, Version 2.0 (the License); you may
17 * not use this file except in compliance with the License.
18 * You may obtain a copy of the License at
19 *
20 * www.apache.org/licenses/LICENSE-2.0
21 *
22 * Unless required by applicable law or agreed to in writing, software
23 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
24 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25 * See the License for the specific language governing permissions and
26 * limitations under the License.
27 */
28
29 #include "dsp/support_functions.h"
30
31 /**
32 @ingroup groupSupport
33 */
34
35 /**
36 * @defgroup float_to_x Convert 32-bit floating point value
37 */
38
39 /**
40 @addtogroup float_to_x
41 @{
42 */
43
44 /**
45 @brief Converts the elements of the floating-point vector to Q31 vector.
46 @param[in] pSrc points to the floating-point input vector
47 @param[out] pDst points to the Q31 output vector
48 @param[in] blockSize number of samples in each vector
49 @return none
50
51 @par Details
52 The equation used for the conversion process is:
53 <pre>
54 pDst[n] = (q31_t)(pSrc[n] * 2147483648); 0 <= n < blockSize.
55 </pre>
56
57 @par Scaling and Overflow Behavior
58 The function uses saturating arithmetic.
59 Results outside of the allowable Q31 range[0x80000000 0x7FFFFFFF] are saturated.
60
61 @note
62 In order to apply rounding, the library should be rebuilt with the ROUNDING macro
63 defined in the preprocessor section of project options.
64 */
65
66 #if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE)
arm_float_to_q31(const float32_t * pSrc,q31_t * pDst,uint32_t blockSize)67 void arm_float_to_q31(
68 const float32_t * pSrc,
69 q31_t * pDst,
70 uint32_t blockSize)
71 {
72 uint32_t blkCnt;
73 float32_t maxQ = (float32_t) Q31_MAX;
74 f32x4_t vecDst;
75 #ifdef ARM_MATH_ROUNDING
76 float32_t in;
77 #endif
78
79
80 blkCnt = blockSize >> 2U;
81
82 /* Compute 4 outputs at a time. */
83 while (blkCnt > 0U)
84 {
85
86 vecDst = vldrwq_f32(pSrc);
87 /* C = A * 2147483648 */
88 /* convert from float to Q31 and then store the results in the destination buffer */
89 vecDst = vmulq(vecDst, maxQ);
90
91 vstrwq_s32(pDst, vcvtaq_s32_f32(vecDst));
92 /*
93 * Decrement the blockSize loop counter
94 * Advance vector source and destination pointers
95 */
96 pSrc += 4;
97 pDst += 4;
98 blkCnt --;
99 }
100
101 blkCnt = blockSize & 3;
102
103 while (blkCnt > 0U)
104 {
105 /* C = A * 2147483648 */
106
107 /* convert from float to Q31 and store result in destination buffer */
108 #ifdef ARM_MATH_ROUNDING
109
110 in = (*pSrc++ * 2147483648.0f);
111 in += in > 0.0f ? 0.5f : -0.5f;
112 *pDst++ = clip_q63_to_q31((q63_t) (in));
113
114 #else
115
116 /* C = A * 2147483648 */
117 /* Convert from float to Q31 and then store the results in the destination buffer */
118 *pDst++ = clip_q63_to_q31((q63_t) (*pSrc++ * 2147483648.0f));
119
120 #endif /* #ifdef ARM_MATH_ROUNDING */
121
122 /* Decrement loop counter */
123 blkCnt--;
124 }
125 }
126 #else
127 #if defined(ARM_MATH_NEON)
arm_float_to_q31(const float32_t * pSrc,q31_t * pDst,uint32_t blockSize)128 void arm_float_to_q31(
129 const float32_t * pSrc,
130 q31_t * pDst,
131 uint32_t blockSize)
132 {
133 const float32_t *pIn = pSrc; /* Src pointer */
134 uint32_t blkCnt; /* loop counter */
135
136 float32x4_t inV;
137 #ifdef ARM_MATH_ROUNDING
138 float32_t in;
139 float32x4_t zeroV = vdupq_n_f32(0.0f);
140 float32x4_t pHalf = vdupq_n_f32(0.5f / 2147483648.0f);
141 float32x4_t mHalf = vdupq_n_f32(-0.5f / 2147483648.0f);
142 float32x4_t r;
143 uint32x4_t cmp;
144 #endif
145
146 int32x4_t outV;
147
148 blkCnt = blockSize >> 2U;
149
150 /* Compute 4 outputs at a time.
151 ** a second loop below computes the remaining 1 to 3 samples. */
152 while (blkCnt > 0U)
153 {
154
155 #ifdef ARM_MATH_ROUNDING
156
157 /* C = A * 32768 */
158 /* Convert from float to Q31 and then store the results in the destination buffer */
159 inV = vld1q_f32(pIn);
160 cmp = vcgtq_f32(inV,zeroV);
161 r = vbslq_f32(cmp,pHalf,mHalf);
162 inV = vaddq_f32(inV, r);
163
164 pIn += 4;
165
166 outV = vcvtq_n_s32_f32(inV,31);
167
168 vst1q_s32(pDst, outV);
169 pDst += 4;
170
171 #else
172
173 /* C = A * 2147483648 */
174 /* Convert from float to Q31 and then store the results in the destination buffer */
175 inV = vld1q_f32(pIn);
176
177 outV = vcvtq_n_s32_f32(inV,31);
178
179 vst1q_s32(pDst, outV);
180 pDst += 4;
181 pIn += 4;
182
183 #endif /* #ifdef ARM_MATH_ROUNDING */
184
185 /* Decrement the loop counter */
186 blkCnt--;
187 }
188
189 /* If the blockSize is not a multiple of 4, compute any remaining output samples here.
190 ** No loop unrolling is used. */
191 blkCnt = blockSize & 3;
192
193 while (blkCnt > 0U)
194 {
195
196 #ifdef ARM_MATH_ROUNDING
197
198 /* C = A * 2147483648 */
199 /* Convert from float to Q31 and then store the results in the destination buffer */
200 in = *pIn++;
201 in = (in * 2147483648.0f);
202 in += in > 0.0f ? 0.5f : -0.5f;
203 *pDst++ = clip_q63_to_q31((q63_t) (in));
204
205 #else
206
207 /* C = A * 2147483648 */
208 /* Convert from float to Q31 and then store the results in the destination buffer */
209 *pDst++ = clip_q63_to_q31((q63_t) (*pIn++ * 2147483648.0f));
210
211 #endif /* #ifdef ARM_MATH_ROUNDING */
212
213 /* Decrement the loop counter */
214 blkCnt--;
215 }
216
217
218 }
219 #else
arm_float_to_q31(const float32_t * pSrc,q31_t * pDst,uint32_t blockSize)220 void arm_float_to_q31(
221 const float32_t * pSrc,
222 q31_t * pDst,
223 uint32_t blockSize)
224 {
225 uint32_t blkCnt; /* Loop counter */
226 const float32_t *pIn = pSrc; /* Source pointer */
227
228 #ifdef ARM_MATH_ROUNDING
229 float32_t in;
230 #endif /* #ifdef ARM_MATH_ROUNDING */
231
232 #if defined (ARM_MATH_LOOPUNROLL)
233
234 /* Loop unrolling: Compute 4 outputs at a time */
235 blkCnt = blockSize >> 2U;
236
237 while (blkCnt > 0U)
238 {
239 /* C = A * 2147483648 */
240
241 /* convert from float to Q31 and store result in destination buffer */
242 #ifdef ARM_MATH_ROUNDING
243
244 in = (*pIn++ * 2147483648.0f);
245 in += in > 0.0f ? 0.5f : -0.5f;
246 *pDst++ = clip_q63_to_q31((q63_t) (in));
247
248 in = (*pIn++ * 2147483648.0f);
249 in += in > 0.0f ? 0.5f : -0.5f;
250 *pDst++ = clip_q63_to_q31((q63_t) (in));
251
252 in = (*pIn++ * 2147483648.0f);
253 in += in > 0.0f ? 0.5f : -0.5f;
254 *pDst++ = clip_q63_to_q31((q63_t) (in));
255
256 in = (*pIn++ * 2147483648.0f);
257 in += in > 0.0f ? 0.5f : -0.5f;
258 *pDst++ = clip_q63_to_q31((q63_t) (in));
259
260 #else
261
262 /* C = A * 2147483648 */
263 /* Convert from float to Q31 and then store the results in the destination buffer */
264 *pDst++ = clip_q63_to_q31((q63_t) (*pIn++ * 2147483648.0f));
265 *pDst++ = clip_q63_to_q31((q63_t) (*pIn++ * 2147483648.0f));
266 *pDst++ = clip_q63_to_q31((q63_t) (*pIn++ * 2147483648.0f));
267 *pDst++ = clip_q63_to_q31((q63_t) (*pIn++ * 2147483648.0f));
268
269 #endif /* #ifdef ARM_MATH_ROUNDING */
270
271 /* Decrement loop counter */
272 blkCnt--;
273 }
274
275 /* Loop unrolling: Compute remaining outputs */
276 blkCnt = blockSize % 0x4U;
277
278 #else
279
280 /* Initialize blkCnt with number of samples */
281 blkCnt = blockSize;
282
283 #endif /* #if defined (ARM_MATH_LOOPUNROLL) */
284
285 while (blkCnt > 0U)
286 {
287 /* C = A * 2147483648 */
288
289 /* convert from float to Q31 and store result in destination buffer */
290 #ifdef ARM_MATH_ROUNDING
291
292 in = (*pIn++ * 2147483648.0f);
293 in += in > 0.0f ? 0.5f : -0.5f;
294 *pDst++ = clip_q63_to_q31((q63_t) (in));
295
296 #else
297
298 /* C = A * 2147483648 */
299 /* Convert from float to Q31 and then store the results in the destination buffer */
300 *pDst++ = clip_q63_to_q31((q63_t) (*pIn++ * 2147483648.0f));
301
302 #endif /* #ifdef ARM_MATH_ROUNDING */
303
304 /* Decrement loop counter */
305 blkCnt--;
306 }
307
308 }
309 #endif /* #if defined(ARM_MATH_NEON) */
310 #endif /* defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE) */
311
312 /**
313 @} end of float_to_x group
314 */
315