arm_float_to_q31.c
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) 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) 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 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 */