1 /* ----------------------------------------------------------------------
2 * Project: CMSIS DSP Library
3 * Title: arm_min_q31.c
4 * Description: Minimum value of a 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/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 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) && !defined(ARM_MATH_AUTOVECTORIZE)
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 int32_t blkCnt; /* loop counters */
60 q31x4_t extremValVec = vdupq_n_s32(Q31_MAX);
61 q31_t minValue = Q31_MAX;
62 uint32x4_t indexVec;
63 uint32x4_t extremIdxVec;
64 mve_pred16_t p0;
65 uint32_t extremIdxArr[4];
66
67 indexVec = vidupq_u32(0U, 1);
68
69 blkCnt = blockSize;
70 do {
71 mve_pred16_t p = vctp32q(blkCnt);
72 q31x4_t extremIdxVal = vld1q_z_s32(pSrc, p);
73 /*
74 * Get current min per lane and current index per lane
75 * when a min is selected
76 */
77 p0 = vcmpleq_m(extremIdxVal, extremValVec, p);
78
79 extremValVec = vorrq_m(extremValVec, extremIdxVal, extremIdxVal, p0);
80 /* store per-lane extrema indexes */
81 vst1q_p_u32(extremIdxArr, indexVec, p0);
82
83 indexVec += 4;
84 pSrc += 4;
85 blkCnt -= 4;
86 }
87 while (blkCnt > 0);
88
89
90 /* Get min value across the vector */
91 minValue = vminvq(minValue, extremValVec);
92
93 /* set index for lower values to min possible index */
94 p0 = vcmpleq(extremValVec, minValue);
95 extremIdxVec = vld1q_u32(extremIdxArr);
96
97 indexVec = vpselq(extremIdxVec, vdupq_n_u32(blockSize - 1), p0);
98 *pIndex = vminvq(blockSize - 1, indexVec);
99 *pResult = minValue;
100 }
101
102 #else
arm_min_q31(const q31_t * pSrc,uint32_t blockSize,q31_t * pResult,uint32_t * pIndex)103 void arm_min_q31(
104 const q31_t * pSrc,
105 uint32_t blockSize,
106 q31_t * pResult,
107 uint32_t * pIndex)
108 {
109 q31_t minVal, out; /* Temporary variables to store the output value. */
110 uint32_t blkCnt, outIndex; /* Loop counter */
111
112 #if defined (ARM_MATH_LOOPUNROLL)
113 uint32_t index; /* index of maximum value */
114 #endif
115
116 /* Initialise index value to zero. */
117 outIndex = 0U;
118 /* Load first input value that act as reference value for comparision */
119 out = *pSrc++;
120
121 #if defined (ARM_MATH_LOOPUNROLL)
122 /* Initialise index of maximum value. */
123 index = 0U;
124
125 /* Loop unrolling: Compute 4 outputs at a time */
126 blkCnt = (blockSize - 1U) >> 2U;
127
128 while (blkCnt > 0U)
129 {
130 /* Initialize minVal to next consecutive values one by one */
131 minVal = *pSrc++;
132
133 /* compare for the minimum value */
134 if (out > minVal)
135 {
136 /* Update the minimum value and it's index */
137 out = minVal;
138 outIndex = index + 1U;
139 }
140
141 minVal = *pSrc++;
142 if (out > minVal)
143 {
144 out = minVal;
145 outIndex = index + 2U;
146 }
147
148 minVal = *pSrc++;
149 if (out > minVal)
150 {
151 out = minVal;
152 outIndex = index + 3U;
153 }
154
155 minVal = *pSrc++;
156 if (out > minVal)
157 {
158 out = minVal;
159 outIndex = index + 4U;
160 }
161
162 index += 4U;
163
164 /* Decrement loop counter */
165 blkCnt--;
166 }
167
168 /* Loop unrolling: Compute remaining outputs */
169 blkCnt = (blockSize - 1U) % 4U;
170
171 #else
172
173 /* Initialize blkCnt with number of samples */
174 blkCnt = (blockSize - 1U);
175
176 #endif /* #if defined (ARM_MATH_LOOPUNROLL) */
177
178 while (blkCnt > 0U)
179 {
180 /* Initialize minVal to the next consecutive values one by one */
181 minVal = *pSrc++;
182
183 /* compare for the minimum value */
184 if (out > minVal)
185 {
186 /* Update the minimum value and it's index */
187 out = minVal;
188 outIndex = blockSize - blkCnt;
189 }
190
191 /* Decrement loop counter */
192 blkCnt--;
193 }
194
195 /* Store the minimum value and it's index into destination pointers */
196 *pResult = out;
197 *pIndex = outIndex;
198 }
199 #endif /* defined(ARM_MATH_MVEI) */
200
201 /**
202 @} end of Min group
203 */
204