From 414856259d0873546eb0225157d85a12fa18cee5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Edelbo?= Date: Fri, 13 Dec 2019 11:16:38 +0100 Subject: [PATCH] Fix the float sorting algorithm Change-Id: Ia90174fbc838dbe0fe367508309ad3412e28658d --- src/realm/column.hpp | 25 ++++++++++++++----------- test/test_table.cpp | 2 +- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/realm/column.hpp b/src/realm/column.hpp index bbc6f7341c3..eda8ca2e716 100644 --- a/src/realm/column.hpp +++ b/src/realm/column.hpp @@ -895,20 +895,23 @@ template <> struct IntTypeForSize<8> { using type = uint64_t; }; template int compare_float(Float a_raw, Float b_raw) { - // nans (and by extension nulls) are treated as being less than all non-nan values bool a_nan = std::isnan(a_raw); bool b_nan = std::isnan(b_raw); - if (a_nan != b_nan) { - return a_nan ? 1 : -1; + if (!a_nan && !b_nan) { + // Just compare as IEEE floats + return a_raw == b_raw ? 0 : a_raw < b_raw ? 1 : -1; } - - // Compare the values as ints, which gives correct results for IEEE floats - // and bypasses the usual behavior of nans not being comparable to each other - using IntType = typename _impl::IntTypeForSize::type; - IntType a = 0, b = 0; - memcpy(&a, &a_raw, sizeof(Float)); - memcpy(&b, &b_raw, sizeof(Float)); - return a == b ? 0 : a < b ? 1 : -1; + if (a_nan && b_nan) { + // Compare the nan values (including nulls) as unsigned + using IntType = typename _impl::IntTypeForSize::type; + IntType a = 0, b = 0; + memcpy(&a, &a_raw, sizeof(Float)); + memcpy(&b, &b_raw, sizeof(Float)); + return a == b ? 0 : a < b ? 1 : -1; + } + // One is nan, the other is not + // nans are treated as being less than all non-nan values + return a_nan ? 1 : -1; } } // namespace _impl diff --git a/test/test_table.cpp b/test/test_table.cpp index 507f43f33cd..fdf24b73c58 100644 --- a/test/test_table.cpp +++ b/test/test_table.cpp @@ -1877,7 +1877,7 @@ TEST_TYPES(Table_SortFloat, float, double) for (size_t i = 300; i < 600; ++i) { CHECK(sorted.get(i).is_null(col)); } - for (size_t i = 600; i + i < 900; ++i) { + for (size_t i = 600; i + 1 < 900; ++i) { CHECK_GREATER(sorted.get(i + 1).get(col), sorted.get(i).get(col)); } }