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