/ Drivers / CMSIS / DSP / Source / DistanceFunctions / arm_braycurtis_distance_f16.c
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