1 /* ----------------------------------------------------------------------
2 * Project: CMSIS DSP Library
3 * Title: arm_min_q31.c
4 * Description: Minimum value of a Q31 vector
5 *
6 * $Date: 18. March 2019
7 * $Revision: V1.6.0
8 *
9 * Target Processor: Cortex-M cores
10 * -------------------------------------------------------------------- */
11 /*
12 * Copyright (C) 2010-2019 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 "arm_math.h"
30
31 /**
32 @ingroup groupStats
33 */
34
35
36 /**
37 @addtogroup Min
38 @{
39 */
40
41 /**
42 @brief Minimum value of a Q31 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)
50
51 #include "arm_helium_utils.h"
52
arm_min_q31(const q31_t * pSrc,uint32_t blockSize,q31_t * pResult,uint32_t * pIndex)53 void arm_min_q31(
54 const q31_t * pSrc,
55 uint32_t blockSize,
56 q31_t * pResult,
57 uint32_t * pIndex)
58 {
59 uint32_t blkCnt; /* loop counters */
60 q31x4_t vecSrc;
61 q31x4_t curExtremValVec = vdupq_n_s32(Q31_MAX);
62 q31_t minValue = Q31_MAX, temp;
63 uint32_t idx = blockSize;
64 uint32x4_t indexVec;
65 uint32x4_t curExtremIdxVec;
66 mve_pred16_t p0;
67
68
69 indexVec = vidupq_u32((uint32_t)0, 1);
70 curExtremIdxVec = vdupq_n_u32(0);
71
72 /* Compute 4 outputs at a time */
73 blkCnt = blockSize >> 2U;
74 while (blkCnt > 0U)
75 {
76 vecSrc = vldrwq_s32(pSrc);
77 pSrc += 4;
78 /*
79 * Get current min per lane and current index per lane
80 * when a min is selected
81 */
82 p0 = vcmpleq(vecSrc, curExtremValVec);
83 curExtremValVec = vpselq(vecSrc, curExtremValVec, p0);
84 curExtremIdxVec = vpselq(indexVec, curExtremIdxVec, p0);
85
86 indexVec = indexVec + 4;
87 /*
88 * Decrement the blockSize loop counter
89 */
90 blkCnt--;
91 }
92
93 /*
94 * Get min value across the vector
95 */
96 minValue = vminvq(minValue, curExtremValVec);
97 /*
98 * set index for lower values to min possible index
99 */
100 p0 = vcmpleq(curExtremValVec, minValue);
101 indexVec = vpselq(curExtremIdxVec, vdupq_n_u32(blockSize), p0);
102 /*
103 * Get min index which is thus for a min value
104 */
105 idx = vminvq(idx, indexVec);
106
107
108 /* Tail */
109 blkCnt = blockSize & 0x3;
110 while (blkCnt > 0U)
111 {
112 /* Initialize temp to the next consecutive values one by one */
113 temp = *pSrc++;
114
115 /* compare for the minimum value */
116 if (minValue > temp)
117 {
118 /* Update the minimum value and it's index */
119 minValue = temp;
120 idx = blockSize - blkCnt;
121 }
122
123 /* Decrement loop counter */
124 blkCnt--;
125 }
126 /*
127 * Save result
128 */
129 *pIndex = idx;
130 *pResult = minValue;
131 }
132 #else
arm_min_q31(const q31_t * pSrc,uint32_t blockSize,q31_t * pResult,uint32_t * pIndex)133 void arm_min_q31(
134 const q31_t * pSrc,
135 uint32_t blockSize,
136 q31_t * pResult,
137 uint32_t * pIndex)
138 {
139 q31_t minVal, out; /* Temporary variables to store the output value. */
140 uint32_t blkCnt, outIndex; /* Loop counter */
141
142 #if defined (ARM_MATH_LOOPUNROLL)
143 uint32_t index; /* index of maximum value */
144 #endif
145
146 /* Initialise index value to zero. */
147 outIndex = 0U;
148 /* Load first input value that act as reference value for comparision */
149 out = *pSrc++;
150
151 #if defined (ARM_MATH_LOOPUNROLL)
152 /* Initialise index of maximum value. */
153 index = 0U;
154
155 /* Loop unrolling: Compute 4 outputs at a time */
156 blkCnt = (blockSize - 1U) >> 2U;
157
158 while (blkCnt > 0U)
159 {
160 /* Initialize minVal to next consecutive values one by one */
161 minVal = *pSrc++;
162
163 /* compare for the minimum value */
164 if (out > minVal)
165 {
166 /* Update the minimum value and it's index */
167 out = minVal;
168 outIndex = index + 1U;
169 }
170
171 minVal = *pSrc++;
172 if (out > minVal)
173 {
174 out = minVal;
175 outIndex = index + 2U;
176 }
177
178 minVal = *pSrc++;
179 if (out > minVal)
180 {
181 out = minVal;
182 outIndex = index + 3U;
183 }
184
185 minVal = *pSrc++;
186 if (out > minVal)
187 {
188 out = minVal;
189 outIndex = index + 4U;
190 }
191
192 index += 4U;
193
194 /* Decrement loop counter */
195 blkCnt--;
196 }
197
198 /* Loop unrolling: Compute remaining outputs */
199 blkCnt = (blockSize - 1U) % 4U;
200
201 #else
202
203 /* Initialize blkCnt with number of samples */
204 blkCnt = (blockSize - 1U);
205
206 #endif /* #if defined (ARM_MATH_LOOPUNROLL) */
207
208 while (blkCnt > 0U)
209 {
210 /* Initialize minVal to the next consecutive values one by one */
211 minVal = *pSrc++;
212
213 /* compare for the minimum value */
214 if (out > minVal)
215 {
216 /* Update the minimum value and it's index */
217 out = minVal;
218 outIndex = blockSize - blkCnt;
219 }
220
221 /* Decrement loop counter */
222 blkCnt--;
223 }
224
225 /* Store the minimum value and it's index into destination pointers */
226 *pResult = out;
227 *pIndex = outIndex;
228 }
229 #endif /* defined(ARM_MATH_MVEI) */
230
231 /**
232 @} end of Min group
233 */
234