diff --git a/src/realm/array.cpp b/src/realm/array.cpp index 3b4c5f32db1..e3c981049fb 100644 --- a/src/realm/array.cpp +++ b/src/realm/array.cpp @@ -550,92 +550,6 @@ void Array::do_ensure_minimum_width(int_fast64_t value) } } -namespace { - -template <size_t width> -inline int64_t lower_bits() -{ - if (width == 1) - return 0xFFFFFFFFFFFFFFFFULL; - else if (width == 2) - return 0x5555555555555555ULL; - else if (width == 4) - return 0x1111111111111111ULL; - else if (width == 8) - return 0x0101010101010101ULL; - else if (width == 16) - return 0x0001000100010001ULL; - else if (width == 32) - return 0x0000000100000001ULL; - else if (width == 64) - return 0x0000000000000001ULL; - else { - REALM_ASSERT_DEBUG(false); - return int64_t(-1); - } -} - -// Return true if 'value' has an element (of bit-width 'width') which is 0 -template <size_t width> -inline bool has_zero_element(uint64_t value) -{ - uint64_t hasZeroByte; - uint64_t lower = lower_bits<width>(); - uint64_t upper = lower_bits<width>() * 1ULL << (width == 0 ? 0 : (width - 1ULL)); - hasZeroByte = (value - lower) & ~value & upper; - return hasZeroByte != 0; -} - - -// Finds zero element of bit width 'width' -template <bool eq, size_t width> -size_t find_zero(uint64_t v) -{ - size_t start = 0; - uint64_t hasZeroByte; - - // Bisection optimization, speeds up small bitwidths with high match frequency. More partions than 2 do NOT pay - // off because the work done by test_zero() is wasted for the cases where the value exists in first half, but - // useful if it exists in last half. Sweet spot turns out to be the widths and partitions below. - if (width <= 8) { - hasZeroByte = has_zero_element<width>(v | 0xffffffff00000000ULL); - if (eq ? !hasZeroByte : (v & 0x00000000ffffffffULL) == 0) { - // 00?? -> increasing - start += 64 / no0(width) / 2; - if (width <= 4) { - hasZeroByte = has_zero_element<width>(v | 0xffff000000000000ULL); - if (eq ? !hasZeroByte : (v & 0x0000ffffffffffffULL) == 0) { - // 000? - start += 64 / no0(width) / 4; - } - } - } - else { - if (width <= 4) { - // ??00 - hasZeroByte = has_zero_element<width>(v | 0xffffffffffff0000ULL); - if (eq ? !hasZeroByte : (v & 0x000000000000ffffULL) == 0) { - // 0?00 - start += 64 / no0(width) / 4; - } - } - } - } - - uint64_t mask = - (width == 64 - ? ~0ULL - : ((1ULL << (width == 64 ? 0 : width)) - 1ULL)); // Warning free way of computing (1ULL << width) - 1 - while (eq == (((v >> (width * start)) & mask) != 0)) { - start++; - } - - return start; -} - -} // namespace - - int64_t Array::sum(size_t start, size_t end) const { REALM_TEMPEX(return sum, m_width, (start, end)); diff --git a/src/realm/array_with_find.hpp b/src/realm/array_with_find.hpp index e94519ce0a0..ec811a7b977 100644 --- a/src/realm/array_with_find.hpp +++ b/src/realm/array_with_find.hpp @@ -58,12 +58,36 @@ Searching: The main finding function is: namespace realm { +namespace { template <class T> -inline T no0(T v) +inline constexpr T no0(T v) { return v == 0 ? 1 : v; } +template <size_t width> +inline constexpr uint64_t lower_bits() +{ + if (width == 1) + return 0xFFFFFFFFFFFFFFFFULL; + else if (width == 2) + return 0x5555555555555555ULL; + else if (width == 4) + return 0x1111111111111111ULL; + else if (width == 8) + return 0x0101010101010101ULL; + else if (width == 16) + return 0x0001000100010001ULL; + else if (width == 32) + return 0x0000000100000001ULL; + else if (width == 64) + return 0x0000000000000001ULL; + else { + return uint64_t(-1); + } +} +} // namespace + class ArrayWithFind { public: ArrayWithFind(const Array& array) noexcept @@ -133,9 +157,6 @@ class ArrayWithFind { int64_t find_gtlt_magic(int64_t v) const; // Compute magic constant needed for searching for value 'v' using bit hacks - template <size_t width> - inline int64_t lower_bits() const; // Return chunk with lower bit set in each element - size_t first_set_bit(uint32_t v) const; size_t first_set_bit64(int64_t v) const; @@ -419,36 +440,13 @@ bool ArrayWithFind::find_optimized(int64_t value, size_t start, size_t end, size #endif } -template <size_t width> -inline int64_t ArrayWithFind::lower_bits() const -{ - if (width == 1) - return 0xFFFFFFFFFFFFFFFFULL; - else if (width == 2) - return 0x5555555555555555ULL; - else if (width == 4) - return 0x1111111111111111ULL; - else if (width == 8) - return 0x0101010101010101ULL; - else if (width == 16) - return 0x0001000100010001ULL; - else if (width == 32) - return 0x0000000100000001ULL; - else if (width == 64) - return 0x0000000000000001ULL; - else { - REALM_ASSERT_DEBUG(false); - return int64_t(-1); - } -} - // Tests if any chunk in 'value' is 0 template <size_t width> inline bool ArrayWithFind::test_zero(uint64_t value) const { uint64_t hasZeroByte; - uint64_t lower = lower_bits<width>(); - uint64_t upper = lower_bits<width>() * 1ULL << (width == 0 ? 0 : (width - 1ULL)); + constexpr uint64_t lower = lower_bits<width>(); + constexpr uint64_t upper = lower_bits<width>() * 1ULL << (width == 0 ? 0 : (width - 1ULL)); hasZeroByte = (value - lower) & ~value & upper; return hasZeroByte != 0; } @@ -804,7 +802,7 @@ REALM_FORCEINLINE bool ArrayWithFind::find_sse_intern(__m128i* action_data, __m1 size_t s = i * sizeof(__m128i) * 8 / no0(width); while (resmask != 0) { - uint64_t upper = lower_bits<width / 8>() << (no0(width / 8) - 1); + constexpr uint64_t upper = lower_bits<width / 8>() << (no0(width / 8) - 1); uint64_t pattern = resmask & upper; // fixme, bits at wrong offsets. Only OK because we only use them in 'count' aggregate diff --git a/src/realm/query_engine.hpp b/src/realm/query_engine.hpp index 998132eeea5..0bf2fe4d5c2 100644 --- a/src/realm/query_engine.hpp +++ b/src/realm/query_engine.hpp @@ -76,7 +76,6 @@ TConditionValue: Type of values in condition column. That is, int64_t, float, #include <realm/array_key.hpp> #include <realm/array_string.hpp> #include <realm/array_binary.hpp> -#include <realm/array_integer_tpl.hpp> #include <realm/array_timestamp.hpp> #include <realm/array_decimal128.hpp> #include <realm/array_fixed_bytes.hpp>