Coverage Report

Created: 2026-07-02 14:47

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
1.88M
ALWAYS_INLINE inline double fmod_double(double a, double b) {
54
1.88M
#if DORIS_HAS_X87_FMOD_FAST
55
1.88M
    if (b != 0.0 && std::isfinite(a) && std::isfinite(b)) {
56
1.88M
        double abs_a = std::fabs(a);
57
1.88M
        double abs_b = std::fabs(b);
58
1.88M
        if (abs_a < abs_b) {
59
587k
            return a;
60
587k
        }
61
1.29M
        if (abs_a == abs_b) {
62
149k
            return std::copysign(0.0, a);
63
149k
        }
64
1.14M
        return fmod_x87_fprem(a, b);
65
1.29M
    }
66
1.58k
#endif
67
1.58k
    return std::fmod(a, b);
68
1.88M
}
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
780k
ALWAYS_INLINE inline double fmod_value(double a, double b) {
75
780k
    return fmod_double(a, b);
76
780k
}
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
8
                                             uint8_t* null_map, size_t size) {
85
520k
    for (size_t i = 0; i < size; ++i) {
86
520k
        uint8_t is_null = rhs[i] == T(0);
87
520k
        null_map[i] = is_null;
88
520k
        T adjusted_rhs = rhs[i] + static_cast<T>(is_null);
89
520k
        result[i] = fmod_value(lhs[i], adjusted_rhs);
90
520k
    }
91
8
}
fmod_fast.cpp:_ZN5doris9fmod_fast12_GLOBAL__N_118vector_vector_implIdEEvPKT_S5_PS3_Phm
Line
Count
Source
84
6
                                             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
6
}
fmod_fast.cpp:_ZN5doris9fmod_fast12_GLOBAL__N_118vector_vector_implIfEEvPKT_S5_PS3_Phm
Line
Count
Source
84
2
                                             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
2
}
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
8
                                               size_t size) {
96
8
    uint8_t is_null = rhs == T(0);
97
8
    memset(null_map, is_null, size);
98
8
    if (is_null) {
99
4
        return;
100
4
    }
101
102
520k
    for (size_t i = 0; i < size; ++i) {
103
520k
        result[i] = fmod_value(lhs[i], rhs);
104
520k
    }
105
4
}
fmod_fast.cpp:_ZN5doris9fmod_fast12_GLOBAL__N_120vector_constant_implIdEEvPKT_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
}
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
6
                   size_t size) {
134
6
    vector_vector_impl(lhs, rhs, result, null_map, size);
135
6
}
136
137
void vector_vector(const float* lhs, const float* rhs, float* result, uint8_t* null_map,
138
2
                   size_t size) {
139
2
    vector_vector_impl(lhs, rhs, result, null_map, size);
140
2
}
141
142
void vector_constant(const double* lhs, double rhs, double* result, uint8_t* null_map,
143
4
                     size_t size) {
144
4
    vector_constant_impl(lhs, rhs, result, null_map, size);
145
4
}
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