1 /* ----------------------------------------------------------------------
2 * Project: CMSIS DSP Library
3 * Title: arm_min_q7.c
4 * Description: Minimum value of a Q7 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/statistics_functions.h"
30
31 /**
32 @ingroup groupStats
33 */
34
35
36 /**
37 @addtogroup Min
38 @{
39 */
40
41 /**
42 @brief Minimum value of a Q7 vector.
43 @param[in] pSrc points to the input vector
44 @param[in] blockSize number of samples in input vector
45 @param[out] pResult minimum value returned here
46 @param[out] pIndex index of minimum value returned here
47 @return none
48 */
49 #if defined(ARM_MATH_MVEI) && !defined(ARM_MATH_AUTOVECTORIZE)
50
51 #include "arm_helium_utils.h"
52
arm_small_blk_min_q7(const q7_t * pSrc,uint8_t blockSize,q7_t * pResult,uint32_t * pIndex)53 static void arm_small_blk_min_q7(
54 const q7_t * pSrc,
55 uint8_t blockSize,
56 q7_t * pResult,
57 uint32_t * pIndex)
58 {
59 uint32_t blkCnt; /* loop counters */
60 q7x16_t vecSrc;
61 q7x16_t curExtremValVec = vdupq_n_s8(Q7_MAX);
62 q7_t minValue = Q7_MAX,temp;
63 uint32_t idx = blockSize;
64 uint8x16_t indexVec;
65 uint8x16_t curExtremIdxVec;
66 mve_pred16_t p0;
67
68
69 indexVec = vidupq_u8((uint32_t)0, 1);
70 curExtremIdxVec = vdupq_n_u8(0);
71
72 blkCnt = blockSize >> 4;
73 while (blkCnt > 0U)
74 {
75 vecSrc = vldrbq_s8(pSrc);
76 pSrc += 16;
77 /*
78 * Get current min per lane and current index per lane
79 * when a min is selected
80 */
81 p0 = vcmpleq(vecSrc, curExtremValVec);
82 curExtremValVec = vpselq(vecSrc, curExtremValVec, p0);
83 curExtremIdxVec = vpselq(indexVec, curExtremIdxVec, p0);
84
85 indexVec = indexVec + 16;
86 /*
87 * Decrement the blockSize loop counter
88 */
89 blkCnt--;
90 }
91
92 /*
93 * Get min value across the vector
94 */
95 minValue = vminvq(minValue, curExtremValVec);
96 /*
97 * set index for lower values to min possible index
98 */
99 p0 = vcmpleq(curExtremValVec, minValue);
100 indexVec = vpselq(curExtremIdxVec, vdupq_n_u8(blockSize), p0);
101 /*
102 * Get min index which is thus for a min value
103 */
104 idx = vminvq(idx, indexVec);
105
106 blkCnt = blockSize & 0xF;
107 while (blkCnt > 0U)
108 {
109 /* Initialize minVal to the next consecutive values one by one */
110 temp = *pSrc++;
111
112 /* compare for the minimum value */
113 if (minValue > temp)
114 {
115 /* Update the minimum value and it's index */
116 minValue = temp;
117 idx = blockSize - blkCnt;
118 }
119
120 /* Decrement loop counter */
121 blkCnt--;
122 }
123 /*
124 * Save result
125 */
126 *pIndex = idx;
127 *pResult = minValue;
128 }
129
arm_min_q7(const q7_t * pSrc,uint32_t blockSize,q7_t * pResult,uint32_t * pIndex)130 void arm_min_q7(
131 const q7_t * pSrc,
132 uint32_t blockSize,
133 q7_t * pResult,
134 uint32_t * pIndex)
135 {
136 int32_t totalSize = blockSize;
137
138 if (totalSize <= UINT8_MAX)
139 {
140 arm_small_blk_min_q7(pSrc, blockSize, pResult, pIndex);
141 }
142 else
143 {
144 uint32_t curIdx = 0;
145 q7_t curBlkExtr = Q7_MAX;
146 uint32_t curBlkPos = 0;
147 uint32_t curBlkIdx = 0;
148 /*
149 * process blocks of 255 elts
150 */
151 while (totalSize >= UINT8_MAX)
152 {
153 const q7_t *curSrc = pSrc;
154
155 arm_small_blk_min_q7(curSrc, UINT8_MAX, pResult, pIndex);
156 if (*pResult < curBlkExtr)
157 {
158 /*
159 * update partial extrema
160 */
161 curBlkExtr = *pResult;
162 curBlkPos = *pIndex;
163 curBlkIdx = curIdx;
164 }
165 curIdx++;
166 pSrc += UINT8_MAX;
167 totalSize -= UINT8_MAX;
168 }
169 /*
170 * remainder
171 */
172 arm_small_blk_min_q7(pSrc, totalSize, pResult, pIndex);
173 if (*pResult < curBlkExtr)
174 {
175 curBlkExtr = *pResult;
176 curBlkPos = *pIndex;
177 curBlkIdx = curIdx;
178 }
179 *pIndex = curBlkIdx * UINT8_MAX + curBlkPos;
180 *pResult = curBlkExtr;
181 }
182 }
183 #else
arm_min_q7(const q7_t * pSrc,uint32_t blockSize,q7_t * pResult,uint32_t * pIndex)184 void arm_min_q7(
185 const q7_t * pSrc,
186 uint32_t blockSize,
187 q7_t * pResult,
188 uint32_t * pIndex)
189 {
190 q7_t minVal, out; /* Temporary variables to store the output value. */
191 uint32_t blkCnt, outIndex; /* Loop counter */
192
193 #if defined (ARM_MATH_LOOPUNROLL)
194 uint32_t index; /* index of maximum value */
195 #endif
196
197 /* Initialise index value to zero. */
198 outIndex = 0U;
199 /* Load first input value that act as reference value for comparision */
200 out = *pSrc++;
201
202 #if defined (ARM_MATH_LOOPUNROLL)
203 /* Initialise index of maximum value. */
204 index = 0U;
205
206 /* Loop unrolling: Compute 4 outputs at a time */
207 blkCnt = (blockSize - 1U) >> 2U;
208
209 while (blkCnt > 0U)
210 {
211 /* Initialize minVal to next consecutive values one by one */
212 minVal = *pSrc++;
213
214 /* compare for the minimum value */
215 if (out > minVal)
216 {
217 /* Update the minimum value and it's index */
218 out = minVal;
219 outIndex = index + 1U;
220 }
221
222 minVal = *pSrc++;
223 if (out > minVal)
224 {
225 out = minVal;
226 outIndex = index + 2U;
227 }
228
229 minVal = *pSrc++;
230 if (out > minVal)
231 {
232 out = minVal;
233 outIndex = index + 3U;
234 }
235
236 minVal = *pSrc++;
237 if (out > minVal)
238 {
239 out = minVal;
240 outIndex = index + 4U;
241 }
242
243 index += 4U;
244
245 /* Decrement loop counter */
246 blkCnt--;
247 }
248
249 /* Loop unrolling: Compute remaining outputs */
250 blkCnt = (blockSize - 1U) % 4U;
251
252 #else
253
254 /* Initialize blkCnt with number of samples */
255 blkCnt = (blockSize - 1U);
256
257 #endif /* #if defined (ARM_MATH_LOOPUNROLL) */
258
259 while (blkCnt > 0U)
260 {
261 /* Initialize minVal to the next consecutive values one by one */
262 minVal = *pSrc++;
263
264 /* compare for the minimum value */
265 if (out > minVal)
266 {
267 /* Update the minimum value and it's index */
268 out = minVal;
269 outIndex = blockSize - blkCnt;
270 }
271
272 /* Decrement loop counter */
273 blkCnt--;
274 }
275
276 /* Store the minimum value and it's index into destination pointers */
277 *pResult = out;
278 *pIndex = outIndex;
279 }
280 #endif /* defined(ARM_MATH_MVEI) */
281
282 /**
283 @} end of Min group
284 */
285