Coverage Report

Created: 2026-05-29 03:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/exprs/function/array/function_array_distance.cpp
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
#include "exprs/function/array/function_array_distance.h"
19
20
#include <algorithm>
21
22
#include "exprs/function/simple_function_factory.h"
23
24
namespace doris {
25
26
FAISS_PRAGMA_IMPRECISE_FUNCTION_BEGIN
27
7
float CosineDistance::distance(const float* x, const float* y, size_t d) {
28
7
    if (d == 0) {
29
1
        return 2.0f;
30
1
    }
31
32
7
    DCHECK(x != nullptr && y != nullptr);
33
34
6
    float dot_prod = 0;
35
6
    float squared_x = 0;
36
6
    float squared_y = 0;
37
22
    for (size_t i = 0; i < d; ++i) {
38
16
        dot_prod += x[i] * y[i];
39
16
        squared_x += x[i] * x[i];
40
16
        squared_y += y[i] * y[i];
41
16
    }
42
43
6
    if (squared_x == 0 || squared_y == 0) {
44
1
        return 2.0f;
45
1
    }
46
47
    // Accumulate the norm in double and take a single square root. Computing
48
    // (double)squared_x * (double)squared_y cannot overflow for finite float inputs,
49
    // whereas the float expression sqrt(squared_x * squared_y) overflows to +inf for
50
    // large-magnitude vectors and would silently yield a distance of 1.0.
51
5
    const double norm = std::sqrt(static_cast<double>(squared_x) * static_cast<double>(squared_y));
52
    // Clamp the cosine to [-1, 1] before mapping to a distance. Floating-point rounding
53
    // can push the ratio slightly outside [-1, 1] (e.g. 1.0000001 for identical vectors),
54
    // which would otherwise produce a tiny negative distance.
55
5
    const float cosine = std::clamp(static_cast<float>(dot_prod / norm), -1.0f, 1.0f);
56
5
    return 1.0f - cosine;
57
6
}
58
FAISS_PRAGMA_IMPRECISE_FUNCTION_END
59
60
FAISS_PRAGMA_IMPRECISE_FUNCTION_BEGIN
61
13
float CosineSimilarity::distance(const float* x, const float* y, size_t d) {
62
13
    if (d == 0) {
63
1
        return 0.0f;
64
1
    }
65
66
13
    DCHECK(x != nullptr && y != nullptr);
67
68
12
    float dot_prod = 0;
69
12
    float squared_x = 0;
70
12
    float squared_y = 0;
71
41
    for (size_t i = 0; i < d; ++i) {
72
29
        dot_prod += x[i] * y[i];
73
29
        squared_x += x[i] * x[i];
74
29
        squared_y += y[i] * y[i];
75
29
    }
76
77
12
    if (squared_x == 0 || squared_y == 0) {
78
3
        return 0.0f;
79
3
    }
80
81
    // See CosineDistance::distance: the double-precision norm avoids float overflow,
82
    // and clamping keeps the result within the mathematically valid [-1, 1] range.
83
9
    const double norm = std::sqrt(static_cast<double>(squared_x) * static_cast<double>(squared_y));
84
9
    return std::clamp(static_cast<float>(dot_prod / norm), -1.0f, 1.0f);
85
12
}
86
FAISS_PRAGMA_IMPRECISE_FUNCTION_END
87
88
1
void register_function_array_distance(SimpleFunctionFactory& factory) {
89
1
    factory.register_function<FunctionArrayDistance<L1Distance>>();
90
1
    factory.register_function<FunctionArrayDistance<L2Distance>>();
91
1
    factory.register_function<FunctionArrayDistance<CosineDistance>>();
92
1
    factory.register_function<FunctionArrayDistance<CosineSimilarity>>();
93
1
    factory.register_function<FunctionArrayDistance<InnerProduct>>();
94
1
    factory.register_function<FunctionArrayDistance<L2DistanceApproximate>>();
95
1
    factory.register_function<FunctionArrayDistance<InnerProductApproximate>>();
96
1
}
97
98
} // namespace doris