/ Drivers / CMSIS / DSP / Source / StatisticsFunctions / arm_absmin_f32.c
arm_absmin_f32.c
  1  /* ----------------------------------------------------------------------
  2   * Project:      CMSIS DSP Library
  3   * Title:        arm_absmin_f32.c
  4   * Description:  Minimum value of absolute values of a floating-point 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  #if (defined(ARM_MATH_NEON) || defined(ARM_MATH_MVEF)) && !defined(ARM_MATH_AUTOVECTORIZE)
 32  #include <limits.h>
 33  #endif
 34  
 35  
 36  /**
 37    @ingroup groupStats
 38   */
 39  
 40  /**
 41    @defgroup AbsMin Absolute Minimum
 42  
 43    Computes the minimum value of absolute values of an array of data.
 44    The function returns both the minimum value and its position within the array.
 45    There are separate functions for floating-point, Q31, Q15, and Q7 data types.
 46   */
 47  
 48  /**
 49    @addtogroup AbsMin
 50    @{
 51   */
 52  
 53  /**
 54    @brief         Minimum value of absolute values of a floating-point vector.
 55    @param[in]     pSrc       points to the input vector
 56    @param[in]     blockSize  number of samples in input vector
 57    @param[out]    pResult    minimum value returned here
 58    @param[out]    pIndex     index of minimum value returned here
 59    @return        none
 60   */
 61  
 62  #if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE)
 63  
 64  #include "arm_helium_utils.h"
 65  void arm_absmin_f32(
 66    const float32_t * pSrc,
 67          uint32_t blockSize,
 68          float32_t * pResult,
 69          uint32_t * pIndex)
 70  {
 71      int32_t  blkCnt;           /* loop counters */
 72      f32x4_t vecSrc;
 73      float32_t const *pSrcVec;
 74      f32x4_t curExtremValVec = vdupq_n_f32(F32_ABSMAX);
 75      float32_t minValue = F32_ABSMAX;
 76      uint32_t  idx = blockSize;
 77      uint32x4_t indexVec;
 78      uint32x4_t curExtremIdxVec;
 79      mve_pred16_t p0;
 80  
 81  
 82      indexVec = vidupq_u32((uint32_t)0, 1);
 83      curExtremIdxVec = vdupq_n_u32(0);
 84  
 85      pSrcVec = (float32_t const *) pSrc;
 86      blkCnt = blockSize >> 2;
 87      while (blkCnt > 0)
 88      {
 89          vecSrc = vldrwq_f32(pSrcVec);  
 90          pSrcVec += 4;
 91          vecSrc = vabsq(vecSrc);
 92          /*
 93           * Get current max per lane and current index per lane
 94           * when a max is selected
 95           */
 96          p0 = vcmpleq(vecSrc, curExtremValVec);
 97          curExtremValVec = vpselq(vecSrc, curExtremValVec, p0);
 98          curExtremIdxVec = vpselq(indexVec, curExtremIdxVec, p0);
 99  
100          indexVec = indexVec +  4;
101          /*
102           * Decrement the blockSize loop counter
103           */
104          blkCnt--;
105      }
106      /*
107       * tail
108       * (will be merged thru tail predication)
109       */
110      blkCnt = blockSize & 3;
111      if (blkCnt > 0)
112      {
113          p0 = vctp32q(blkCnt);
114  
115          vecSrc = vldrwq_f32(pSrcVec);  
116          pSrcVec += 4;
117          vecSrc = vabsq(vecSrc);
118          /*
119           * Get current max per lane and current index per lane
120           * when a max is selected
121           */
122          p0 = vcmpleq_m(vecSrc, curExtremValVec, p0);
123          curExtremValVec = vpselq(vecSrc, curExtremValVec, p0);
124          curExtremIdxVec = vpselq(indexVec, curExtremIdxVec, p0);
125      }
126      /*
127       * Get min value across the vector
128       */
129      minValue = vminnmvq(minValue, curExtremValVec);
130      /*
131       * set index for lower values to max possible index
132       */
133      p0 = vcmpleq(curExtremValVec, minValue);
134      indexVec = vpselq(curExtremIdxVec, vdupq_n_u32(blockSize), p0);
135      /*
136       * Get min index which is thus for a max value
137       */
138      idx = vminvq(idx, indexVec);
139      /*
140       * Save result
141       */
142      *pIndex = idx;
143      *pResult = minValue;
144  }
145  
146  #else
147  #if defined(ARM_MATH_LOOPUNROLL)
148  void arm_absmin_f32(
149    const float32_t * pSrc,
150          uint32_t blockSize,
151          float32_t * pResult,
152          uint32_t * pIndex)
153  {
154          float32_t cur_absmin, out;                     /* Temporary variables to store the output value. */\
155          uint32_t blkCnt, outIndex;                     /* Loop counter */                                   \
156          uint32_t index;                                /* index of maximum value */                         \
157                                                                                                              \
158    /* Initialize index value to zero. */                                                                     \
159    outIndex = 0U;                                                                                            \
160    /* Load first input value that act as reference value for comparision */                                  \
161    out = *pSrc++;                                                                                            \
162    out = (out > 0.0f) ? out : -out;                                                                             \
163    /* Initialize index of extrema value. */                                                                  \
164    index = 0U;                                                                                               \
165                                                                                                              \
166    /* Loop unrolling: Compute 4 outputs at a time */                                                         \
167    blkCnt = (blockSize - 1U) >> 2U;                                                                          \
168                                                                                                              \
169    while (blkCnt > 0U)                                                                                       \
170    {                                                                                                         \
171      /* Initialize cur_absmin to next consecutive values one by one */                                         \
172      cur_absmin = *pSrc++;                                                                                     \
173      cur_absmin = (cur_absmin > 0.0f) ? cur_absmin : -cur_absmin;                                                                 \
174      /* compare for the extrema value */                                                                     \
175      if (cur_absmin < out)                                                                         \
176      {                                                                                                       \
177        /* Update the extrema value and it's index */                                                         \
178        out = cur_absmin;                                                                                       \
179        outIndex = index + 1U;                                                                                \
180      }                                                                                                       \
181                                                                                                              \
182      cur_absmin = *pSrc++;                                                                                     \
183      cur_absmin = (cur_absmin > 0.0f) ? cur_absmin : -cur_absmin;                                                                 \
184      if (cur_absmin < out)                                                                         \
185      {                                                                                                       \
186        out = cur_absmin;                                                                                       \
187        outIndex = index + 2U;                                                                                \
188      }                                                                                                       \
189                                                                                                              \
190      cur_absmin = *pSrc++;                                                                                     \
191      cur_absmin = (cur_absmin > 0.0f) ? cur_absmin : -cur_absmin;                                                                 \
192      if (cur_absmin < out)                                                                          \
193      {                                                                                                       \
194        out = cur_absmin;                                                                                       \
195        outIndex = index + 3U;                                                                                \
196      }                                                                                                       \
197                                                                                                              \
198      cur_absmin = *pSrc++;                                                                                     \
199      cur_absmin = (cur_absmin > 0.0f) ? cur_absmin : -cur_absmin;                                                                 \
200      if (cur_absmin < out)                                                                          \
201      {                                                                                                       \
202        out = cur_absmin;                                                                                       \
203        outIndex = index + 4U;                                                                                \
204      }                                                                                                       \
205                                                                                                              \
206      index += 4U;                                                                                            \
207                                                                                                              \
208      /* Decrement loop counter */                                                                            \
209      blkCnt--;                                                                                               \
210    }                                                                                                         \
211                                                                                                              \
212    /* Loop unrolling: Compute remaining outputs */                                                           \
213    blkCnt = (blockSize - 1U) % 4U;                                                                           \
214                                                                                                              \
215                                                                                                              \
216    while (blkCnt > 0U)                                                                                       \
217    {                                                                                                         \
218      cur_absmin = *pSrc++;                                                                                     \
219      cur_absmin = (cur_absmin > 0.0f) ? cur_absmin : -cur_absmin;                                                                 \
220      if (cur_absmin < out)                                                                         \
221      {                                                                                                       \
222        out = cur_absmin;                                                                                       \
223        outIndex = blockSize - blkCnt;                                                                        \
224      }                                                                                                       \
225                                                                                                              \
226      /* Decrement loop counter */                                                                            \
227      blkCnt--;                                                                                               \
228    }                                                                                                         \
229                                                                                                              \
230    /* Store the extrema value and it's index into destination pointers */                                    \
231    *pResult = out;                                                                                           \
232    *pIndex = outIndex;  
233  }
234  #else
235  void arm_absmin_f32(
236    const float32_t * pSrc,
237          uint32_t blockSize,
238          float32_t * pResult,
239          uint32_t * pIndex)
240  {
241         float32_t minVal, out;                         /* Temporary variables to store the output value. */
242         uint32_t blkCnt, outIndex;                     /* Loop counter */
243  
244    /* Initialise index value to zero. */
245    outIndex = 0U;
246  
247    /* Load first input value that act as reference value for comparision */
248    out = fabsf(*pSrc++);
249  
250    /* Initialize blkCnt with number of samples */
251    blkCnt = (blockSize - 1U);
252  
253    while (blkCnt > 0U)
254    {
255      /* Initialize minVal to the next consecutive values one by one */
256      minVal = fabsf(*pSrc++);
257  
258      /* compare for the minimum value */
259      if (out > minVal)
260      {
261        /* Update the minimum value and it's index */
262        out = minVal;
263        outIndex = blockSize - blkCnt;
264      }
265  
266      /* Decrement loop counter */
267      blkCnt--;
268    }
269  
270    /* Store the minimum value and it's index into destination pointers */
271    *pResult = out;
272    *pIndex = outIndex;
273  }
274  
275  #endif /* defined(ARM_MATH_LOOPUNROLL) */
276  #endif /* defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE) */
277  /**
278    @} end of AbsMin group
279   */