Coverage Report

Created: 2026-07-25 08:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/exprs/function/fmod_fast.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/fmod_fast.h"
19
20
#include <string.h>
21
22
#include <cmath>
23
24
#include "common/compiler_util.h"
25
26
namespace doris::fmod_fast {
27
namespace {
28
29
#if defined(__x86_64__) && (defined(__GNUC__) || defined(__clang__))
30
0
#define DORIS_HAS_X87_FMOD_FAST 1
31
32
1.14M
ALWAYS_INLINE inline double fmod_x87_fprem(double a, double b) {
33
1.14M
    double r;
34
1.14M
    asm volatile(
35
1.14M
            "fldl %[b]\n\t"
36
1.14M
            "fldl %[a]\n\t"
37
1.14M
            "1:\n\t"
38
1.14M
            "fprem\n\t"
39
1.14M
            "fnstsw %%ax\n\t"
40
1.14M
            "testb $4, %%ah\n\t"
41
1.14M
            "jne 1b\n\t"
42
1.14M
            "fstp %%st(1)\n\t"
43
1.14M
            "fstpl %[r]\n\t"
44
1.14M
            : [r] "=m"(r)
45
1.14M
            : [a] "m"(a), [b] "m"(b)
46
1.14M
            : "ax", "cc", "st");
47
1.14M
    return r;
48
1.14M
}
49
#else
50
#define DORIS_HAS_X87_FMOD_FAST 0
51
#endif
52
53
2.93M
ALWAYS_INLINE inline double fmod_double(double a, double b) {
54
2.93M
#if DORIS_HAS_X87_FMOD_FAST
55
2.93M
    if (b != 0.0 && std::isfinite(a) && std::isfinite(b)) {
56
2.93M
        double abs_a = std::fabs(a);
57
2.93M
        double abs_b = std::fabs(b);
58
2.93M
        if (abs_a < abs_b) {
59
1.63M
            return a;
60
1.63M
        }
61
1.29M
        if (abs_a == abs_b) {
62
150k
            return std::copysign(0.0, a);
63
150k
        }
64
1.14M
        return fmod_x87_fprem(a, b);
65
1.29M
    }
66
1.65k
#endif
67
1.65k
    return std::fmod(a, b);
68
2.93M
}
69
70
941k
ALWAYS_INLINE inline float fmod_float(float a, float b) {
71
941k
    return static_cast<float>(fmod_double(static_cast<double>(a), static_cast<double>(b)));
72
941k
}
73
74
1.83M
ALWAYS_INLINE inline double fmod_value(double a, double b) {
75
1.83M
    return fmod_double(a, b);
76
1.83M
}
77
78
780k
ALWAYS_INLINE inline float fmod_value(float a, float b) {
79
780k
    return fmod_float(a, b);
80
780k
}
81
82
template <typename T>
83
ALWAYS_INLINE inline void vector_vector_impl(const T* lhs, const T* rhs, T* result,
84
1.15k
                                             uint8_t* null_map, size_t size) {
85
528k
    for (size_t i = 0; i < size; ++i) {
86
527k
        uint8_t is_null = rhs[i] == T(0);
87
527k
        null_map[i] = is_null;
88
527k
        T adjusted_rhs = rhs[i] + static_cast<T>(is_null);
89
527k
        result[i] = fmod_value(lhs[i], adjusted_rhs);
90
527k
    }
91
1.15k
}
fmod_fast.cpp:_ZN5doris9fmod_fast12_GLOBAL__N_118vector_vector_implIdEEvPKT_S5_PS3_Phm
Line
Count
Source
84
1.11k
                                             uint8_t* null_map, size_t size) {
85
267k
    for (size_t i = 0; i < size; ++i) {
86
266k
        uint8_t is_null = rhs[i] == T(0);
87
266k
        null_map[i] = is_null;
88
266k
        T adjusted_rhs = rhs[i] + static_cast<T>(is_null);
89
266k
        result[i] = fmod_value(lhs[i], adjusted_rhs);
90
266k
    }
91
1.11k
}
fmod_fast.cpp:_ZN5doris9fmod_fast12_GLOBAL__N_118vector_vector_implIfEEvPKT_S5_PS3_Phm
Line
Count
Source
84
38
                                             uint8_t* null_map, size_t size) {
85
260k
    for (size_t i = 0; i < size; ++i) {
86
260k
        uint8_t is_null = rhs[i] == T(0);
87
260k
        null_map[i] = is_null;
88
260k
        T adjusted_rhs = rhs[i] + static_cast<T>(is_null);
89
260k
        result[i] = fmod_value(lhs[i], adjusted_rhs);
90
260k
    }
91
38
}
92
93
template <typename T>
94
ALWAYS_INLINE inline void vector_constant_impl(const T* lhs, T rhs, T* result, uint8_t* null_map,
95
41
                                               size_t size) {
96
41
    uint8_t is_null = rhs == T(0);
97
41
    memset(null_map, is_null, size);
98
41
    if (is_null) {
99
12
        return;
100
12
    }
101
102
1.56M
    for (size_t i = 0; i < size; ++i) {
103
1.56M
        result[i] = fmod_value(lhs[i], rhs);
104
1.56M
    }
105
29
}
fmod_fast.cpp:_ZN5doris9fmod_fast12_GLOBAL__N_120vector_constant_implIdEEvPKT_S3_PS3_Phm
Line
Count
Source
95
37
                                               size_t size) {
96
37
    uint8_t is_null = rhs == T(0);
97
37
    memset(null_map, is_null, size);
98
37
    if (is_null) {
99
10
        return;
100
10
    }
101
102
1.30M
    for (size_t i = 0; i < size; ++i) {
103
1.30M
        result[i] = fmod_value(lhs[i], rhs);
104
1.30M
    }
105
27
}
fmod_fast.cpp:_ZN5doris9fmod_fast12_GLOBAL__N_120vector_constant_implIfEEvPKT_S3_PS3_Phm
Line
Count
Source
95
4
                                               size_t size) {
96
4
    uint8_t is_null = rhs == T(0);
97
4
    memset(null_map, is_null, size);
98
4
    if (is_null) {
99
2
        return;
100
2
    }
101
102
260k
    for (size_t i = 0; i < size; ++i) {
103
260k
        result[i] = fmod_value(lhs[i], rhs);
104
260k
    }
105
2
}
106
107
template <typename T>
108
ALWAYS_INLINE inline void constant_vector_impl(T lhs, const T* rhs, T* result, uint8_t* null_map,
109
4
                                               size_t size) {
110
520k
    for (size_t i = 0; i < size; ++i) {
111
520k
        uint8_t is_null = rhs[i] == T(0);
112
520k
        null_map[i] = is_null;
113
520k
        T adjusted_rhs = rhs[i] + static_cast<T>(is_null);
114
520k
        result[i] = fmod_value(lhs, adjusted_rhs);
115
520k
    }
116
4
}
fmod_fast.cpp:_ZN5doris9fmod_fast12_GLOBAL__N_120constant_vector_implIdEEvT_PKS3_PS3_Phm
Line
Count
Source
109
2
                                               size_t size) {
110
260k
    for (size_t i = 0; i < size; ++i) {
111
260k
        uint8_t is_null = rhs[i] == T(0);
112
260k
        null_map[i] = is_null;
113
260k
        T adjusted_rhs = rhs[i] + static_cast<T>(is_null);
114
260k
        result[i] = fmod_value(lhs, adjusted_rhs);
115
260k
    }
116
2
}
fmod_fast.cpp:_ZN5doris9fmod_fast12_GLOBAL__N_120constant_vector_implIfEEvT_PKS3_PS3_Phm
Line
Count
Source
109
2
                                               size_t size) {
110
260k
    for (size_t i = 0; i < size; ++i) {
111
260k
        uint8_t is_null = rhs[i] == T(0);
112
260k
        null_map[i] = is_null;
113
260k
        T adjusted_rhs = rhs[i] + static_cast<T>(is_null);
114
260k
        result[i] = fmod_value(lhs, adjusted_rhs);
115
260k
    }
116
2
}
117
118
} // namespace
119
120
0
bool is_x87_fast_path_enabled() {
121
0
    return DORIS_HAS_X87_FMOD_FAST;
122
0
}
123
124
161k
double scalar(double a, double b) {
125
161k
    return fmod_double(a, b);
126
161k
}
127
128
161k
float scalar(float a, float b) {
129
161k
    return fmod_float(a, b);
130
161k
}
131
132
void vector_vector(const double* lhs, const double* rhs, double* result, uint8_t* null_map,
133
1.11k
                   size_t size) {
134
1.11k
    vector_vector_impl(lhs, rhs, result, null_map, size);
135
1.11k
}
136
137
void vector_vector(const float* lhs, const float* rhs, float* result, uint8_t* null_map,
138
38
                   size_t size) {
139
38
    vector_vector_impl(lhs, rhs, result, null_map, size);
140
38
}
141
142
void vector_constant(const double* lhs, double rhs, double* result, uint8_t* null_map,
143
37
                     size_t size) {
144
37
    vector_constant_impl(lhs, rhs, result, null_map, size);
145
37
}
146
147
4
void vector_constant(const float* lhs, float rhs, float* result, uint8_t* null_map, size_t size) {
148
4
    vector_constant_impl(lhs, rhs, result, null_map, size);
149
4
}
150
151
void constant_vector(double lhs, const double* rhs, double* result, uint8_t* null_map,
152
2
                     size_t size) {
153
2
    constant_vector_impl(lhs, rhs, result, null_map, size);
154
2
}
155
156
2
void constant_vector(float lhs, const float* rhs, float* result, uint8_t* null_map, size_t size) {
157
2
    constant_vector_impl(lhs, rhs, result, null_map, size);
158
2
}
159
160
} // namespace doris::fmod_fast