• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /* ----------------------------------------------------------------------
3  * Project:      CMSIS DSP Library
4  * Title:        arm_braycurtis_distance_f32.c
5  * Description:  Bray-Curtis distance between two vectors
6  *
7  *
8  * Target Processor: Cortex-M cores
9  * -------------------------------------------------------------------- */
10 /*
11  * Copyright (C) 2010-2019 ARM Limited or its affiliates. All rights reserved.
12  *
13  * SPDX-License-Identifier: Apache-2.0
14  *
15  * Licensed under the Apache License, Version 2.0 (the License); you may
16  * not use this file except in compliance with the License.
17  * You may obtain a copy of the License at
18  *
19  * www.apache.org/licenses/LICENSE-2.0
20  *
21  * Unless required by applicable law or agreed to in writing, software
22  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
23  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24  * See the License for the specific language governing permissions and
25  * limitations under the License.
26  */
27 
28 #include "arm_math.h"
29 #include <limits.h>
30 #include <math.h>
31 
32 
33 
34 /**
35  * @ingroup groupDistance
36  * @{
37  */
38 
39 /**
40  * @defgroup FloatDist Float Distances
41  *
42  * Distances between two vectors of float values.
43  */
44 
45 /**
46   @addtogroup FloatDist
47   @{
48  */
49 
50 
51 /**
52  * @brief        Bray-Curtis distance between two vectors
53  * @param[in]    pA         First vector
54  * @param[in]    pB         Second vector
55  * @param[in]    blockSize  vector length
56  * @return distance
57  *
58  */
59 #if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE)
60 
61 #include "arm_helium_utils.h"
62 
arm_braycurtis_distance_f32(const float32_t * pA,const float32_t * pB,uint32_t blockSize)63 float32_t arm_braycurtis_distance_f32(const float32_t *pA,const float32_t *pB, uint32_t blockSize)
64 {
65     float32_t       accumDiff = 0.0f, accumSum = 0.0f;
66     uint32_t        blkCnt;
67     f32x4_t         a, b, c, accumDiffV, accumSumV;
68 
69 
70     accumDiffV = vdupq_n_f32(0.0f);
71     accumSumV = vdupq_n_f32(0.0f);
72 
73     blkCnt = blockSize >> 2;
74     while (blkCnt > 0) {
75         a = vld1q(pA);
76         b = vld1q(pB);
77 
78         c = vabdq(a, b);
79         accumDiffV = vaddq(accumDiffV, c);
80 
81         c = vaddq_f32(a, b);
82         c = vabsq_f32(c);
83         accumSumV = vaddq(accumSumV, c);
84 
85         pA += 4;
86         pB += 4;
87         blkCnt--;
88     }
89 
90     blkCnt = blockSize & 3;
91     if (blkCnt > 0U) {
92         mve_pred16_t    p0 = vctp32q(blkCnt);
93 
94         a = vldrwq_z_f32(pA, p0);
95         b = vldrwq_z_f32(pB, p0);
96 
97         c = vabdq(a, b);
98         accumDiffV = vaddq_m(accumDiffV, accumDiffV, c, p0);
99 
100         c = vaddq_f32(a, b);
101         c = vabsq_f32(c);
102         accumSumV = vaddq_m(accumSumV, accumSumV, c, p0);
103     }
104 
105     accumDiff = vecAddAcrossF32Mve(accumDiffV);
106     accumSum = vecAddAcrossF32Mve(accumSumV);
107 
108     /*
109        It is assumed that accumSum is not zero. Since it is the sum of several absolute
110        values it would imply that all of them are zero. It is very unlikely for long vectors.
111      */
112     return (accumDiff / accumSum);
113 }
114 #else
115 #if defined(ARM_MATH_NEON)
116 
117 #include "NEMath.h"
118 
arm_braycurtis_distance_f32(const float32_t * pA,const float32_t * pB,uint32_t blockSize)119 float32_t arm_braycurtis_distance_f32(const float32_t *pA,const float32_t *pB, uint32_t blockSize)
120 {
121    float32_t accumDiff=0.0f, accumSum=0.0f;
122    uint32_t blkCnt;
123    float32x4_t a,b,c,accumDiffV, accumSumV;
124    float32x2_t accumV2;
125 
126    accumDiffV = vdupq_n_f32(0.0f);
127    accumSumV = vdupq_n_f32(0.0f);
128 
129    blkCnt = blockSize >> 2;
130    while(blkCnt > 0)
131    {
132         a = vld1q_f32(pA);
133         b = vld1q_f32(pB);
134 
135         c = vabdq_f32(a,b);
136         accumDiffV = vaddq_f32(accumDiffV,c);
137 
138         c = vaddq_f32(a,b);
139         c = vabsq_f32(c);
140         accumSumV = vaddq_f32(accumSumV,c);
141 
142         pA += 4;
143         pB += 4;
144         blkCnt --;
145    }
146    accumV2 = vpadd_f32(vget_low_f32(accumDiffV),vget_high_f32(accumDiffV));
147    accumDiff = vget_lane_f32(accumV2, 0) + vget_lane_f32(accumV2, 1);
148 
149    accumV2 = vpadd_f32(vget_low_f32(accumSumV),vget_high_f32(accumSumV));
150    accumSum = vget_lane_f32(accumV2, 0) + vget_lane_f32(accumV2, 1);
151 
152    blkCnt = blockSize & 3;
153    while(blkCnt > 0)
154    {
155       accumDiff += fabsf(*pA - *pB);
156       accumSum += fabsf(*pA++ + *pB++);
157       blkCnt --;
158    }
159    /*
160 
161    It is assumed that accumSum is not zero. Since it is the sum of several absolute
162    values it would imply that all of them are zero. It is very unlikely for long vectors.
163 
164    */
165    return(accumDiff / accumSum);
166 }
167 
168 #else
arm_braycurtis_distance_f32(const float32_t * pA,const float32_t * pB,uint32_t blockSize)169 float32_t arm_braycurtis_distance_f32(const float32_t *pA,const float32_t *pB, uint32_t blockSize)
170 {
171    float32_t accumDiff=0.0f, accumSum=0.0f, tmpA, tmpB;
172 
173    while(blockSize > 0)
174    {
175       tmpA = *pA++;
176       tmpB = *pB++;
177       accumDiff += fabsf(tmpA - tmpB);
178       accumSum += fabsf(tmpA + tmpB);
179       blockSize --;
180    }
181    /*
182 
183    It is assumed that accumSum is not zero. Since it is the sum of several absolute
184    values it would imply that all of them are zero. It is very unlikely for long vectors.
185 
186    */
187    return(accumDiff / accumSum);
188 }
189 #endif
190 #endif /* defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE) */
191 
192 
193 /**
194  * @} end of FloatDist group
195  */
196 
197 /**
198  * @} end of groupDistance group
199  */
200