From 8faaedeff9445b78841c145dc8cef24b5d30e2f7 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Thu, 18 Jan 2024 18:40:52 +0100 Subject: [PATCH] Codechange: replace hand written function to find first/last bit with C++ variant --- src/core/bitmath_func.cpp | 56 --------------------------------------- src/core/bitmath_func.hpp | 31 ++++++++++++++++++++-- src/graph_gui.cpp | 2 +- src/signal.cpp | 2 +- 4 files changed, 31 insertions(+), 60 deletions(-) diff --git a/src/core/bitmath_func.cpp b/src/core/bitmath_func.cpp index 09f2a9cb43..e108d96794 100644 --- a/src/core/bitmath_func.cpp +++ b/src/core/bitmath_func.cpp @@ -22,59 +22,3 @@ const uint8_t _ffb_64[64] = { 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, }; - -/** - * Search the first set bit in a 64 bit variable. - * - * This algorithm is a static implementation of a log - * congruence search algorithm. It checks the first half - * if there is a bit set search there further. And this - * way further. If no bit is set return 0. - * - * @param x The value to search - * @return The position of the first bit set - */ -uint8_t FindFirstBit(uint64_t x) -{ - if (x == 0) return 0; - /* The macro FIND_FIRST_BIT is better to use when your x is - not more than 128. */ - - uint8_t pos = 0; - - if ((x & 0xffffffffULL) == 0) { x >>= 32; pos += 32; } - if ((x & 0x0000ffffULL) == 0) { x >>= 16; pos += 16; } - if ((x & 0x000000ffULL) == 0) { x >>= 8; pos += 8; } - if ((x & 0x0000000fULL) == 0) { x >>= 4; pos += 4; } - if ((x & 0x00000003ULL) == 0) { x >>= 2; pos += 2; } - if ((x & 0x00000001ULL) == 0) { pos += 1; } - - return pos; -} - -/** - * Search the last set bit in a 64 bit variable. - * - * This algorithm is a static implementation of a log - * congruence search algorithm. It checks the second half - * if there is a bit set search there further. And this - * way further. If no bit is set return 0. - * - * @param x The value to search - * @return The position of the last bit set - */ -uint8_t FindLastBit(uint64_t x) -{ - if (x == 0) return 0; - - uint8_t pos = 0; - - if ((x & 0xffffffff00000000ULL) != 0) { x >>= 32; pos += 32; } - if ((x & 0x00000000ffff0000ULL) != 0) { x >>= 16; pos += 16; } - if ((x & 0x000000000000ff00ULL) != 0) { x >>= 8; pos += 8; } - if ((x & 0x00000000000000f0ULL) != 0) { x >>= 4; pos += 4; } - if ((x & 0x000000000000000cULL) != 0) { x >>= 2; pos += 2; } - if ((x & 0x0000000000000002ULL) != 0) { pos += 1; } - - return pos; -} diff --git a/src/core/bitmath_func.hpp b/src/core/bitmath_func.hpp index fdd3dfa437..31eda23845 100644 --- a/src/core/bitmath_func.hpp +++ b/src/core/bitmath_func.hpp @@ -222,8 +222,35 @@ inline uint8_t FindFirstBit2x64(const int value) } } -uint8_t FindFirstBit(uint64_t x); -uint8_t FindLastBit(uint64_t x); +/** + * Search the first set bit in a value. + * When no bit is set, it returns 0. + * + * @param x The value to search. + * @return The position of the first bit set. + */ +template +constexpr uint8_t FindFirstBit(T x) +{ + if (x == 0) return 0; + + return std::countr_zero(x); +} + +/** + * Search the last set bit in a value. + * When no bit is set, it returns 0. + * + * @param x The value to search. + * @return The position of the last bit set. + */ +template +constexpr uint8_t FindLastBit(T x) +{ + if (x == 0) return 0; + + return std::numeric_limits::digits - std::countl_zero(x) - 1; +} /** * Clear the first bit in an integer. diff --git a/src/graph_gui.cpp b/src/graph_gui.cpp index 934522208e..070ad8754c 100644 --- a/src/graph_gui.cpp +++ b/src/graph_gui.cpp @@ -440,7 +440,7 @@ protected: * integer, so at about 31 bits because of the sign bit, the * least significant bits are removed. */ - int mult_range = FindLastBit(x_axis_offset) + FindLastBit(abs(datapoint)); + int mult_range = FindLastBit(x_axis_offset) + FindLastBit(abs(datapoint)); int reduce_range = std::max(mult_range - 31, 0); /* Handle negative values differently (don't shift sign) */ diff --git a/src/signal.cpp b/src/signal.cpp index 329b1b05d9..2326ad78fb 100644 --- a/src/signal.cpp +++ b/src/signal.cpp @@ -309,7 +309,7 @@ static SigFlags ExploreSegment(Owner owner) Track track = TrackBitsToTrack(tracks_masked); // mask TRACK_BIT_X and Y too if (HasSignalOnTrack(tile, track)) { // now check whole track, not trackdir SignalType sig = GetSignalType(tile, track); - Trackdir trackdir = (Trackdir)FindFirstBit((tracks * 0x101) & _enterdir_to_trackdirbits[enterdir]); + Trackdir trackdir = (Trackdir)FindFirstBit((tracks * 0x101U) & _enterdir_to_trackdirbits[enterdir]); Trackdir reversedir = ReverseTrackdir(trackdir); /* add (tile, reversetrackdir) to 'to-be-updated' set when there is * ANY conventional signal in REVERSE direction