arm_braycurtis_distance_f16.c
1 2 /* ---------------------------------------------------------------------- 3 * Project: CMSIS DSP Library 4 * Title: arm_braycurtis_distance_f16.c 5 * Description: Bray-Curtis distance between two vectors 6 * 7 * $Date: 23 April 2021 8 * $Revision: V1.9.0 9 * 10 * Target Processor: Cortex-M and Cortex-A cores 11 * -------------------------------------------------------------------- */ 12 /* 13 * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. 14 * 15 * SPDX-License-Identifier: Apache-2.0 16 * 17 * Licensed under the Apache License, Version 2.0 (the License); you may 18 * not use this file except in compliance with the License. 19 * You may obtain a copy of the License at 20 * 21 * www.apache.org/licenses/LICENSE-2.0 22 * 23 * Unless required by applicable law or agreed to in writing, software 24 * distributed under the License is distributed on an AS IS BASIS, WITHOUT 25 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 26 * See the License for the specific language governing permissions and 27 * limitations under the License. 28 */ 29 30 #include "dsp/distance_functions_f16.h" 31 32 #if defined(ARM_FLOAT16_SUPPORTED) 33 34 #include <limits.h> 35 #include <math.h> 36 37 /** 38 * @ingroup groupDistance 39 */ 40 41 /** 42 * @defgroup FloatDist Float Distances 43 * 44 * Distances between two vectors of float values. 45 */ 46 47 /** 48 @ingroup FloatDist 49 */ 50 51 /** 52 @defgroup braycurtis Bray-Curtis distance 53 54 Bray-Curtis distance between two vectors 55 */ 56 57 /** 58 @addtogroup braycurtis 59 @{ 60 */ 61 62 63 /** 64 * @brief Bray-Curtis distance between two vectors 65 * @param[in] pA First vector 66 * @param[in] pB Second vector 67 * @param[in] blockSize vector length 68 * @return distance 69 * 70 */ 71 #if defined(ARM_MATH_MVE_FLOAT16) && !defined(ARM_MATH_AUTOVECTORIZE) 72 73 #include "arm_helium_utils.h" 74 75 float16_t arm_braycurtis_distance_f16(const float16_t *pA,const float16_t *pB, uint32_t blockSize) 76 { 77 _Float16 accumDiff = 0.0f, accumSum = 0.0f; 78 uint32_t blkCnt; 79 f16x8_t a, b, c, accumDiffV, accumSumV; 80 81 82 accumDiffV = vdupq_n_f16(0.0f); 83 accumSumV = vdupq_n_f16(0.0f); 84 85 blkCnt = blockSize >> 3; 86 while (blkCnt > 0) { 87 a = vld1q(pA); 88 b = vld1q(pB); 89 90 c = vabdq(a, b); 91 accumDiffV = vaddq(accumDiffV, c); 92 93 c = vaddq_f16(a, b); 94 c = vabsq_f16(c); 95 accumSumV = vaddq(accumSumV, c); 96 97 pA += 8; 98 pB += 8; 99 blkCnt--; 100 } 101 102 blkCnt = blockSize & 7; 103 if (blkCnt > 0U) { 104 mve_pred16_t p0 = vctp16q(blkCnt); 105 106 a = vldrhq_z_f16(pA, p0); 107 b = vldrhq_z_f16(pB, p0); 108 109 c = vabdq(a, b); 110 accumDiffV = vaddq_m(accumDiffV, accumDiffV, c, p0); 111 112 c = vaddq_f16(a, b); 113 c = vabsq_f16(c); 114 accumSumV = vaddq_m(accumSumV, accumSumV, c, p0); 115 } 116 117 accumDiff = vecAddAcrossF16Mve(accumDiffV); 118 accumSum = vecAddAcrossF16Mve(accumSumV); 119 120 /* 121 It is assumed that accumSum is not zero. Since it is the sum of several absolute 122 values it would imply that all of them are zero. It is very unlikely for long vectors. 123 */ 124 return (accumDiff / accumSum); 125 } 126 #else 127 128 float16_t arm_braycurtis_distance_f16(const float16_t *pA,const float16_t *pB, uint32_t blockSize) 129 { 130 _Float16 accumDiff=0.0f16, accumSum=0.0f16, tmpA, tmpB; 131 132 while(blockSize > 0) 133 { 134 tmpA = *pA++; 135 tmpB = *pB++; 136 accumDiff += (_Float16)fabsf((float32_t)((_Float16)tmpA - (_Float16)tmpB)); 137 accumSum += (_Float16)fabsf((float32_t)((_Float16)tmpA + (_Float16)tmpB)); 138 blockSize --; 139 } 140 /* 141 142 It is assumed that accumSum is not zero. Since it is the sum of several absolute 143 values it would imply that all of them are zero. It is very unlikely for long vectors. 144 145 */ 146 return(accumDiff / accumSum); 147 } 148 #endif /* defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE) */ 149 150 151 /** 152 * @} end of braycurtis group 153 */ 154 155 156 157 #endif /* #if defined(ARM_FLOAT16_SUPPORTED) */ 158