1 /* ----------------------------------------------------------------------
2  * Project:      CMSIS DSP Library
3  * Title:        arm_q31_to_float.c
4  * Description:  Converts the elements of the Q31 vector to floating-point 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 q31_to_x  Convert 32-bit Integer value
37  */
38 
39 /**
40   @addtogroup q31_to_x
41   @{
42  */
43 
44 /**
45   @brief         Converts the elements of the Q31 vector to floating-point vector.
46   @param[in]     pSrc       points to the Q31 input vector
47   @param[out]    pDst       points to the floating-point 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] = (float32_t) pSrc[n] / 2147483648;   0 <= n < blockSize.
55   </pre>
56  */
57 #if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE)
arm_q31_to_float(const q31_t * pSrc,float32_t * pDst,uint32_t blockSize)58 void arm_q31_to_float(
59   const q31_t * pSrc,
60         float32_t * pDst,
61         uint32_t blockSize)
62 {
63     uint32_t  blkCnt;           /* loop counters */
64     q31x4_t vecDst;
65     q31_t const *pSrcVec;
66 
67     pSrcVec = (q31_t const *) pSrc;
68     blkCnt = blockSize >> 2;
69     while (blkCnt > 0U)
70     {
71         /* C = (float32_t) A / 2147483648 */
72         /* convert from q31 to float and then store the results in the destination buffer */
73         vecDst = vld1q(pSrcVec);
74         pSrcVec += 4;
75         vstrwq(pDst, vcvtq_n_f32_s32(vecDst, 31));
76         pDst += 4;
77         /*
78          * Decrement the blockSize loop counter
79          */
80         blkCnt--;
81     }
82     /*
83      * tail
84      * (will be merged thru tail predication)
85      */
86     blkCnt = blockSize & 3;
87     while (blkCnt > 0U)
88     {
89       /* C = (float32_t) A / 2147483648 */
90 
91       /* Convert from q31 to float and store result in destination buffer */
92       *pDst++ = ((float32_t) *pSrcVec++ / 2147483648.0f);
93 
94       /* Decrement loop counter */
95       blkCnt--;
96     }
97 }
98 
99 #else
100 #if defined(ARM_MATH_NEON_EXPERIMENTAL)
arm_q31_to_float(const q31_t * pSrc,float32_t * pDst,uint32_t blockSize)101 void arm_q31_to_float(
102   const q31_t * pSrc,
103         float32_t * pDst,
104         uint32_t blockSize)
105 {
106   const q31_t *pIn = pSrc;                             /* Src pointer */
107   uint32_t blkCnt;                               /* loop counter */
108 
109   int32x4_t inV;
110   float32x4_t outV;
111 
112   blkCnt = blockSize >> 2U;
113 
114   /* Compute 4 outputs at a time.
115    ** a second loop below computes the remaining 1 to 3 samples. */
116   while (blkCnt > 0U)
117   {
118     /* C = (float32_t) A / 2147483648 */
119     /* Convert from q31 to float and then store the results in the destination buffer */
120     inV = vld1q_s32(pIn);
121     pIn += 4;
122 
123     outV = vcvtq_n_f32_s32(inV,31);
124 
125     vst1q_f32(pDst, outV);
126     pDst += 4;
127 
128     /* Decrement the loop counter */
129     blkCnt--;
130   }
131 
132   /* If the blockSize is not a multiple of 4, compute any remaining output samples here.
133    ** No loop unrolling is used. */
134   blkCnt = blockSize & 3;
135 
136 
137   while (blkCnt > 0U)
138   {
139     /* C = (float32_t) A / 2147483648 */
140     /* Convert from q31 to float and then store the results in the destination buffer */
141     *pDst++ = ((float32_t) * pIn++ / 2147483648.0f);
142 
143     /* Decrement the loop counter */
144     blkCnt--;
145   }
146 }
147 #else
arm_q31_to_float(const q31_t * pSrc,float32_t * pDst,uint32_t blockSize)148 void arm_q31_to_float(
149   const q31_t * pSrc,
150   float32_t * pDst,
151   uint32_t blockSize)
152 {
153   const q31_t *pIn = pSrc;                             /* Src pointer */
154   uint32_t blkCnt;                               /* loop counter */
155 
156 #if defined (ARM_MATH_LOOPUNROLL)
157 
158   /* Loop unrolling */
159   blkCnt = blockSize >> 2U;
160 
161   while (blkCnt > 0U)
162   {
163     /* C = (float32_t) A / 2147483648 */
164 
165     /* Convert from q31 to float and store result in destination buffer */
166     *pDst++ = ((float32_t) *pIn++ / 2147483648.0f);
167     *pDst++ = ((float32_t) *pIn++ / 2147483648.0f);
168     *pDst++ = ((float32_t) *pIn++ / 2147483648.0f);
169     *pDst++ = ((float32_t) *pIn++ / 2147483648.0f);
170 
171     /* Decrement loop counter */
172     blkCnt--;
173   }
174 
175   /* Loop unrolling: Compute remaining outputs */
176   blkCnt = blockSize % 0x4U;
177 
178 #else
179 
180   /* Initialize blkCnt with number of samples */
181   blkCnt = blockSize;
182 
183 #endif /* #if defined (ARM_MATH_LOOPUNROLL) */
184 
185   while (blkCnt > 0U)
186   {
187     /* C = (float32_t) A / 2147483648 */
188 
189     /* Convert from q31 to float and store result in destination buffer */
190     *pDst++ = ((float32_t) *pIn++ / 2147483648.0f);
191 
192     /* Decrement loop counter */
193     blkCnt--;
194   }
195 
196 }
197 #endif /* #if defined(ARM_MATH_NEON) */
198 #endif /* defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE) */
199 
200 /**
201   @} end of q31_to_x group
202  */
203