arm_absmin_q15.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /* ----------------------------------------------------------------------
  2. * Project: CMSIS DSP Library
  3. * Title: arm_absmin_q15.c
  4. * Description: Minimum value of absolute values of a Q15 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 AbsMin
  34. @{
  35. */
  36. /**
  37. @brief Minimum value of absolute values of a Q15 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. void arm_absmin_q15(
  46. const q15_t * pSrc,
  47. uint32_t blockSize,
  48. q15_t * pResult,
  49. uint32_t * pIndex)
  50. {
  51. uint16_t blkCnt; /* loop counters */
  52. q15x8_t vecSrc;
  53. q15_t const *pSrcVec;
  54. q15x8_t curExtremValVec = vdupq_n_s16(Q15_ABSMAX);
  55. q15_t minValue = Q15_ABSMAX;
  56. uint16_t idx = blockSize;
  57. uint16x8_t indexVec;
  58. uint16x8_t curExtremIdxVec;
  59. uint32_t startIdx = 0;
  60. mve_pred16_t p0;
  61. indexVec = vidupq_wb_u16(&startIdx, 1);
  62. curExtremIdxVec = vdupq_n_u16(0);
  63. pSrcVec = (q15_t const *) pSrc;
  64. blkCnt = blockSize >> 3;
  65. while (blkCnt > 0U)
  66. {
  67. vecSrc = vld1q(pSrcVec);
  68. pSrcVec += 8;
  69. vecSrc = vabsq(vecSrc);
  70. /*
  71. * Get current min per lane and current index per lane
  72. * when a min is selected
  73. */
  74. p0 = vcmpleq(vecSrc, curExtremValVec);
  75. curExtremValVec = vpselq(vecSrc, curExtremValVec, p0);
  76. curExtremIdxVec = vpselq(indexVec, curExtremIdxVec, p0);
  77. indexVec = vidupq_wb_u16(&startIdx, 1);
  78. /*
  79. * Decrement the blockSize loop counter
  80. */
  81. blkCnt--;
  82. }
  83. /*
  84. * tail
  85. * (will be merged thru tail predication)
  86. */
  87. blkCnt = blockSize & 7;
  88. if (blkCnt > 0U)
  89. {
  90. vecSrc = vld1q(pSrcVec);
  91. pSrcVec += 8;
  92. vecSrc = vabsq(vecSrc);
  93. p0 = vctp16q(blkCnt);
  94. /*
  95. * Get current min per lane and current index per lane
  96. * when a min is selected
  97. */
  98. p0 = vcmpleq_m(vecSrc, curExtremValVec, p0);
  99. curExtremValVec = vpselq(vecSrc, curExtremValVec, p0);
  100. curExtremIdxVec = vpselq(indexVec, curExtremIdxVec, p0);
  101. }
  102. /*
  103. * Get min value across the vector
  104. */
  105. minValue = vminvq(minValue, curExtremValVec);
  106. /*
  107. * set index for lower values to min possible index
  108. */
  109. p0 = vcmpleq(curExtremValVec, minValue);
  110. indexVec = vpselq(curExtremIdxVec, vdupq_n_u16(blockSize), p0);
  111. /*
  112. * Get min index which is thus for a min value
  113. */
  114. idx = vminvq(idx, indexVec);
  115. /*
  116. * Save result
  117. */
  118. *pIndex = idx;
  119. *pResult = minValue;
  120. }
  121. #else
  122. #if defined(ARM_MATH_DSP)
  123. void arm_absmin_q15(
  124. const q15_t * pSrc,
  125. uint32_t blockSize,
  126. q15_t * pResult,
  127. uint32_t * pIndex)
  128. {
  129. q15_t cur_absmin, out; /* Temporary variables to store the output value. */\
  130. uint32_t blkCnt, outIndex; /* Loop counter */ \
  131. uint32_t index; /* index of maximum value */ \
  132. \
  133. /* Initialize index value to zero. */ \
  134. outIndex = 0U; \
  135. /* Load first input value that act as reference value for comparision */ \
  136. out = *pSrc++; \
  137. out = (out > 0) ? out : (q15_t)__QSUB16(0, out); \
  138. /* Initialize index of extrema value. */ \
  139. index = 0U; \
  140. \
  141. /* Loop unrolling: Compute 4 outputs at a time */ \
  142. blkCnt = (blockSize - 1U) >> 2U; \
  143. \
  144. while (blkCnt > 0U) \
  145. { \
  146. /* Initialize cur_absmin to next consecutive values one by one */ \
  147. cur_absmin = *pSrc++; \
  148. cur_absmin = (cur_absmin > 0) ? cur_absmin : (q15_t)__QSUB16(0, cur_absmin); \
  149. /* compare for the extrema value */ \
  150. if (cur_absmin < out) \
  151. { \
  152. /* Update the extrema value and it's index */ \
  153. out = cur_absmin; \
  154. outIndex = index + 1U; \
  155. } \
  156. \
  157. cur_absmin = *pSrc++; \
  158. cur_absmin = (cur_absmin > 0) ? cur_absmin : (q15_t)__QSUB16(0, cur_absmin); \
  159. if (cur_absmin < out) \
  160. { \
  161. out = cur_absmin; \
  162. outIndex = index + 2U; \
  163. } \
  164. \
  165. cur_absmin = *pSrc++; \
  166. cur_absmin = (cur_absmin > 0) ? cur_absmin : (q15_t)__QSUB16(0, cur_absmin); \
  167. if (cur_absmin < out) \
  168. { \
  169. out = cur_absmin; \
  170. outIndex = index + 3U; \
  171. } \
  172. \
  173. cur_absmin = *pSrc++; \
  174. cur_absmin = (cur_absmin > 0) ? cur_absmin : (q15_t)__QSUB16(0, cur_absmin); \
  175. if (cur_absmin < out) \
  176. { \
  177. out = cur_absmin; \
  178. outIndex = index + 4U; \
  179. } \
  180. \
  181. index += 4U; \
  182. \
  183. /* Decrement loop counter */ \
  184. blkCnt--; \
  185. } \
  186. \
  187. /* Loop unrolling: Compute remaining outputs */ \
  188. blkCnt = (blockSize - 1U) % 4U; \
  189. \
  190. \
  191. while (blkCnt > 0U) \
  192. { \
  193. cur_absmin = *pSrc++; \
  194. cur_absmin = (cur_absmin > 0) ? cur_absmin : (q15_t)__QSUB16(0, cur_absmin); \
  195. if (cur_absmin < out) \
  196. { \
  197. out = cur_absmin; \
  198. outIndex = blockSize - blkCnt; \
  199. } \
  200. \
  201. /* Decrement loop counter */ \
  202. blkCnt--; \
  203. } \
  204. \
  205. /* Store the extrema value and it's index into destination pointers */ \
  206. *pResult = out; \
  207. *pIndex = outIndex;
  208. }
  209. #else
  210. void arm_absmin_q15(
  211. const q15_t * pSrc,
  212. uint32_t blockSize,
  213. q15_t * pResult,
  214. uint32_t * pIndex)
  215. {
  216. q15_t minVal, out; /* Temporary variables to store the output value. */
  217. uint32_t blkCnt, outIndex; /* Loop counter */
  218. /* Initialise index value to zero. */
  219. outIndex = 0U;
  220. /* Load first input value that act as reference value for comparision */
  221. out = (*pSrc > 0) ? *pSrc : ((*pSrc == (q15_t) 0x8000) ? 0x7fff : -*pSrc);
  222. pSrc++;
  223. /* Initialize blkCnt with number of samples */
  224. blkCnt = (blockSize - 1U);
  225. while (blkCnt > 0U)
  226. {
  227. /* Initialize minVal to the next consecutive values one by one */
  228. minVal = (*pSrc > 0) ? *pSrc : ((*pSrc == (q15_t) 0x8000) ? 0x7fff : -*pSrc);
  229. pSrc++;
  230. /* compare for the minimum value */
  231. if (out > minVal)
  232. {
  233. /* Update the minimum value and it's index */
  234. out = minVal;
  235. outIndex = blockSize - blkCnt;
  236. }
  237. /* Decrement loop counter */
  238. blkCnt--;
  239. }
  240. /* Store the minimum value and it's index into destination pointers */
  241. *pResult = out;
  242. *pIndex = outIndex;
  243. }
  244. #endif /* defined(ARM_MATH_DSP) */
  245. #endif /* defined(ARM_MATH_MVEI) && !defined(ARM_MATH_AUTOVECTORIZE) */
  246. /**
  247. @} end of AbsMin group
  248. */