1
2 /* ----------------------------------------------------------------------
3 * Project: CMSIS DSP Library
4 * Title: arm_canberra_distance_f16.c
5 * Description: Canberra 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 FloatDist
39 */
40
41 /**
42 @defgroup Canberra Canberra distance
43
44 Canberra distance
45 */
46
47
48 /**
49 @addtogroup Canberra
50 @{
51 */
52
53
54 /**
55 * @brief Canberra distance between two vectors
56 *
57 * This function may divide by zero when samples pA[i] and pB[i] are both zero.
58 * The result of the computation will be correct. So the division per zero may be
59 * ignored.
60 *
61 * @param[in] pA First vector
62 * @param[in] pB Second vector
63 * @param[in] blockSize vector length
64 * @return distance
65 *
66 */
67
68 #if defined(ARM_MATH_MVE_FLOAT16) && !defined(ARM_MATH_AUTOVECTORIZE)
69
70 #include "arm_helium_utils.h"
71 #include "arm_vec_math_f16.h"
72
arm_canberra_distance_f16(const float16_t * pA,const float16_t * pB,uint32_t blockSize)73 float16_t arm_canberra_distance_f16(const float16_t *pA,const float16_t *pB, uint32_t blockSize)
74 {
75 _Float16 accum = 0.0f16;
76 uint32_t blkCnt;
77 f16x8_t a, b, c, accumV;
78
79 accumV = vdupq_n_f16(0.0f);
80
81 blkCnt = blockSize >> 3;
82 while (blkCnt > 0) {
83 a = vld1q(pA);
84 b = vld1q(pB);
85
86 c = vabdq(a, b);
87
88 a = vabsq(a);
89 b = vabsq(b);
90 a = vaddq(a, b);
91
92 /*
93 * May divide by zero when a and b have both the same lane at zero.
94 */
95 a = vrecip_hiprec_f16(a);
96
97 /*
98 * Force result of a division by 0 to 0. It the behavior of the
99 * sklearn canberra function.
100 */
101 a = vdupq_m_n_f16(a, 0.0f, vcmpeqq(a, 0.0f));
102 c = vmulq(c, a);
103 accumV = vaddq(accumV, c);
104
105 pA += 8;
106 pB += 8;
107 blkCnt--;
108 }
109
110 blkCnt = blockSize & 7;
111 if (blkCnt > 0U) {
112 mve_pred16_t p0 = vctp16q(blkCnt);
113
114 a = vldrhq_z_f16(pA, p0);
115 b = vldrhq_z_f16(pB, p0);
116
117 c = vabdq(a, b);
118
119 a = vabsq(a);
120 b = vabsq(b);
121 a = vaddq(a, b);
122
123 /*
124 * May divide by zero when a and b have both the same lane at zero.
125 */
126 a = vrecip_hiprec_f16(a);
127
128 /*
129 * Force result of a division by 0 to 0. It the behavior of the
130 * sklearn canberra function.
131 */
132 a = vdupq_m_n_f16(a, 0.0f, vcmpeqq(a, 0.0f));
133 c = vmulq(c, a);
134 accumV = vaddq_m(accumV, accumV, c, p0);
135 }
136
137 accum = vecAddAcrossF16Mve(accumV);
138
139 return (accum);
140 }
141
142
143 #else
arm_canberra_distance_f16(const float16_t * pA,const float16_t * pB,uint32_t blockSize)144 float16_t arm_canberra_distance_f16(const float16_t *pA,const float16_t *pB, uint32_t blockSize)
145 {
146 _Float16 accum=0.0f, tmpA, tmpB,diff,sum;
147
148 while(blockSize > 0)
149 {
150 tmpA = *pA++;
151 tmpB = *pB++;
152
153 diff = fabsf(tmpA - tmpB);
154 sum = fabsf(tmpA) + fabsf(tmpB);
155 if ((tmpA != 0.0f16) || (tmpB != 0.0f16))
156 {
157 accum += (diff / sum);
158 }
159 blockSize --;
160 }
161 return(accum);
162 }
163 #endif /* defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE) */
164
165
166 /**
167 * @} end of Canberra group
168 */
169
170 #endif /* #if defined(ARM_FLOAT16_SUPPORTED) */
171
172