1 /* ----------------------------------------------------------------------
2 * Project: CMSIS DSP Library
3 * Title: arm_shift_q31.c
4 * Description: Shifts the elements of a Q31 vector by a specified number of bits
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/basic_math_functions.h"
30
31 /**
32 @ingroup groupMath
33 */
34 /**
35 @defgroup BasicShift Vector Shift
36
37 Shifts the elements of a fixed-point vector by a specified number of bits.
38 There are separate functions for Q7, Q15, and Q31 data types.
39 The underlying algorithm used is:
40
41 <pre>
42 pDst[n] = pSrc[n] << shift, 0 <= n < blockSize.
43 </pre>
44
45 If <code>shift</code> is positive then the elements of the vector are shifted to the left.
46 If <code>shift</code> is negative then the elements of the vector are shifted to the right.
47
48 The functions support in-place computation allowing the source and destination
49 pointers to reference the same memory buffer.
50 */
51
52 /**
53 @addtogroup BasicShift
54 @{
55 */
56
57 /**
58 @brief Shifts the elements of a Q31 vector a specified number of bits.
59 @param[in] pSrc points to the input vector
60 @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right.
61 @param[out] pDst points to the output vector
62 @param[in] blockSize number of samples in the vector
63
64 @par Scaling and Overflow Behavior
65 The function uses saturating arithmetic.
66 Results outside of the allowable Q31 range [0x80000000 0x7FFFFFFF] are saturated.
67 */
68
69 #if defined(ARM_MATH_MVEI) && !defined(ARM_MATH_AUTOVECTORIZE)
70
71 #include "arm_helium_utils.h"
72
arm_shift_q31(const q31_t * pSrc,int8_t shiftBits,q31_t * pDst,uint32_t blockSize)73 ARM_DSP_ATTRIBUTE void arm_shift_q31(
74 const q31_t * pSrc,
75 int8_t shiftBits,
76 q31_t * pDst,
77 uint32_t blockSize)
78 {
79 uint32_t blkCnt; /* loop counters */
80 q31x4_t vecSrc;
81 q31x4_t vecDst;
82
83 /* Compute 4 outputs at a time */
84 blkCnt = blockSize >> 2;
85 while (blkCnt > 0U)
86 {
87 /*
88 * C = A (>> or <<) shiftBits
89 * Shift the input and then store the result in the destination buffer.
90 */
91 vecSrc = vld1q((q31_t const *) pSrc);
92 vecDst = vqshlq_r(vecSrc, shiftBits);
93 vst1q(pDst, vecDst);
94 /*
95 * Decrement the blockSize loop counter
96 */
97 blkCnt--;
98 /*
99 * advance vector source and destination pointers
100 */
101 pSrc += 4;
102 pDst += 4;
103 }
104 /*
105 * tail
106 */
107 blkCnt = blockSize & 3;
108 if (blkCnt > 0U)
109 {
110 mve_pred16_t p0 = vctp32q(blkCnt);
111 vecSrc = vld1q((q31_t const *) pSrc);
112 vecDst = vqshlq_r(vecSrc, shiftBits);
113 vstrwq_p(pDst, vecDst, p0);
114 }
115 }
116
117
118 #else
arm_shift_q31(const q31_t * pSrc,int8_t shiftBits,q31_t * pDst,uint32_t blockSize)119 ARM_DSP_ATTRIBUTE void arm_shift_q31(
120 const q31_t * pSrc,
121 int8_t shiftBits,
122 q31_t * pDst,
123 uint32_t blockSize)
124 {
125 uint32_t blkCnt; /* Loop counter */
126 uint8_t sign = (shiftBits & 0x80); /* Sign of shiftBits */
127
128 #if defined (ARM_MATH_LOOPUNROLL)
129
130 q31_t in, out; /* Temporary variables */
131
132 /* Loop unrolling: Compute 4 outputs at a time */
133 blkCnt = blockSize >> 2U;
134
135 /* If the shift value is positive then do right shift else left shift */
136 if (sign == 0U)
137 {
138 while (blkCnt > 0U)
139 {
140 /* C = A << shiftBits */
141
142 /* Shift input and store result in destination buffer. */
143 in = *pSrc++;
144 out = in << shiftBits;
145 if (in != (out >> shiftBits))
146 out = 0x7FFFFFFF ^ (in >> 31);
147 *pDst++ = out;
148
149 in = *pSrc++;
150 out = in << shiftBits;
151 if (in != (out >> shiftBits))
152 out = 0x7FFFFFFF ^ (in >> 31);
153 *pDst++ = out;
154
155 in = *pSrc++;
156 out = in << shiftBits;
157 if (in != (out >> shiftBits))
158 out = 0x7FFFFFFF ^ (in >> 31);
159 *pDst++ = out;
160
161 in = *pSrc++;
162 out = in << shiftBits;
163 if (in != (out >> shiftBits))
164 out = 0x7FFFFFFF ^ (in >> 31);
165 *pDst++ = out;
166
167 /* Decrement loop counter */
168 blkCnt--;
169 }
170 }
171 else
172 {
173 while (blkCnt > 0U)
174 {
175 /* C = A >> shiftBits */
176
177 /* Shift input and store results in destination buffer. */
178 *pDst++ = (*pSrc++ >> -shiftBits);
179 *pDst++ = (*pSrc++ >> -shiftBits);
180 *pDst++ = (*pSrc++ >> -shiftBits);
181 *pDst++ = (*pSrc++ >> -shiftBits);
182
183 /* Decrement loop counter */
184 blkCnt--;
185 }
186 }
187
188 /* Loop unrolling: Compute remaining outputs */
189 blkCnt = blockSize % 0x4U;
190
191 #else
192
193 /* Initialize blkCnt with number of samples */
194 blkCnt = blockSize;
195
196 #endif /* #if defined (ARM_MATH_LOOPUNROLL) */
197
198 /* If the shift value is positive then do right shift else left shift */
199 if (sign == 0U)
200 {
201 while (blkCnt > 0U)
202 {
203 /* C = A << shiftBits */
204
205 /* Shift input and store result in destination buffer. */
206 *pDst++ = clip_q63_to_q31((q63_t) *pSrc++ << shiftBits);
207
208 /* Decrement loop counter */
209 blkCnt--;
210 }
211 }
212 else
213 {
214 while (blkCnt > 0U)
215 {
216 /* C = A >> shiftBits */
217
218 /* Shift input and store result in destination buffer. */
219 *pDst++ = (*pSrc++ >> -shiftBits);
220
221 /* Decrement loop counter */
222 blkCnt--;
223 }
224 }
225
226 }
227 #endif /* defined(ARM_MATH_MVEI) */
228
229 /**
230 @} end of BasicShift group
231 */
232