arm_min_q7.c 6.9 KB

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