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 */