/ Drivers / CMSIS / DSP / Source / StatisticsFunctions / arm_min_q7.c
arm_min_q7.c
  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  
 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  
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
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   */