• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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