Skip to content

Commit aad5e48

Browse files
authored
[refine](float) Add NormalizeFloat to handle special values of floating-point numbers. (apache#56937)
### What problem does this PR solve? The previous check was actually a bit complicated; it can simply be compared with 0.0. ### Release note None ### Check List (For Author) - Test <!-- At least one of them must be included. --> - [ ] Regression test - [ ] Unit Test - [ ] Manual test (add detailed scripts or steps below) - [ ] No need to test or manual test. Explain why: - [ ] This is a refactor/code format and no logic has been changed. - [ ] Previous test can cover this change. - [ ] No code files have been changed. - [ ] Other reason <!-- Add your reason? --> - Behavior changed: - [ ] No. - [ ] Yes. <!-- Explain the behavior change --> - Does this need documentation? - [ ] No. - [ ] Yes. <!-- Add document PR link here. eg: apache/doris-website#1214 --> ### Check List (For Reviewer who merge this PR) - [ ] Confirm the release note - [ ] Confirm test cases - [ ] Confirm document - [ ] Add branch pick label <!-- Add branch pick label that this PR should merge into -->
1 parent ce7b17a commit aad5e48

File tree

4 files changed

+65
-19
lines changed

4 files changed

+65
-19
lines changed

be/src/common/compare.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,18 @@ template <>
223223
inline bool EqualTo<float>::operator()(const float& lhs, const float& rhs) const {
224224
return Compare::equal(lhs, rhs);
225225
}
226+
227+
template <typename T>
228+
requires(std::is_floating_point_v<T>)
229+
void NormalizeFloat(T& val) {
230+
if (val == (T)0.0) {
231+
// Turn negative zero into positive zero
232+
val = (T)0.0;
233+
} else if (std::isnan(val)) {
234+
val = std::numeric_limits<T>::quiet_NaN();
235+
}
236+
}
237+
226238
} // namespace doris
227239

228240
#include "common/compile_check_end.h"

be/src/vec/columns/column_vector.cpp

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -489,20 +489,9 @@ void ColumnVector<T>::replace_column_null_data(const uint8_t* __restrict null_ma
489489
template <PrimitiveType T>
490490
void ColumnVector<T>::replace_float_special_values() {
491491
if constexpr (is_float_or_double(T)) {
492-
static constexpr float f_neg_zero = -0.0F;
493-
static constexpr double d_neg_zero = -0.0;
494-
static constexpr size_t byte_size = sizeof(value_type);
495-
static const void* p_neg_zero = (byte_size == 4 ? static_cast<const void*>(&f_neg_zero)
496-
: static_cast<const void*>(&d_neg_zero));
497492
auto s = size();
498-
auto* data_ptr = data.data();
499493
for (size_t i = 0; i < s; ++i) {
500-
// replace negative zero with positive zero
501-
if (0 == std::memcmp(data_ptr + i, p_neg_zero, byte_size)) {
502-
data[i] = 0.0;
503-
} else if (is_nan(data[i])) {
504-
data[i] = std::numeric_limits<value_type>::quiet_NaN();
505-
}
494+
NormalizeFloat(data[i]);
506495
}
507496
}
508497
}

be/src/vec/functions/function_jsonb_transform.cpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,7 @@ void normalize_json_numbers_to_double(JsonbWriter& jsonb_writer, const JsonbValu
8787
CastParameters params;
8888
params.is_strict = false;
8989
JsonbCast::cast_from_json_to_float(jsonb_value, to, params);
90-
if (to == 0.0) {
91-
// to avoid -0.0
92-
to = 0.0;
93-
} else if (std::isnan(to)) {
94-
// to avoid -nan
95-
to = std::numeric_limits<double>::quiet_NaN();
96-
}
90+
NormalizeFloat(to);
9791
jsonb_writer.writeDouble(to);
9892
} else {
9993
jsonb_writer.writeValue(jsonb_value);

be/test/common/compare_test.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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 "common/compare.h"
19+
20+
#include <gtest/gtest.h>
21+
22+
#include <vector>
23+
24+
#include "common/status.h"
25+
26+
namespace doris {
27+
28+
TEST(CompareTest, test) {
29+
{
30+
double x = -0.0;
31+
NormalizeFloat(x);
32+
EXPECT_EQ(x, 0.0);
33+
}
34+
{
35+
float x = -0.0F;
36+
NormalizeFloat(x);
37+
EXPECT_EQ(x, 0.0F);
38+
}
39+
{
40+
double x = std::nan("");
41+
NormalizeFloat(x);
42+
EXPECT_TRUE(std::isnan(x));
43+
}
44+
{
45+
float x = std::nanf("");
46+
NormalizeFloat(x);
47+
EXPECT_TRUE(std::isnan(x));
48+
}
49+
}
50+
51+
} // namespace doris

0 commit comments

Comments
 (0)