Replace FindFirstBit/FindFirstBit64 with a single template function

pull/332/head
Jonathan G Rennison 3 years ago
parent d585ce75dd
commit 1e0bea5b8d

@ -25,18 +25,7 @@ const uint8 _ffb_64[64] = {
3, 0, 1, 0, 2, 0, 1, 0,
};
/**
* Search the first set bit in a 32 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 FindFirstBit(uint32 x)
uint8 FindFirstBit32(uint32 x)
{
if (x == 0) return 0;
/* The macro FIND_FIRST_BIT is better to use when your x is

@ -187,21 +187,7 @@ static inline T ToggleBit(T &x, const uint8 y)
#ifdef WITH_BITMATH_BUILTINS
#define FIND_FIRST_BIT(x) FindFirstBit(x)
inline uint8 FindFirstBit(uint32 x)
{
if (x == 0) return 0;
return __builtin_ctz(x);
}
inline uint8 FindFirstBit64(uint64 x)
{
if (x == 0) return 0;
return __builtin_ctzll(x);
}
#define FIND_FIRST_BIT(x) FindFirstBit<uint>(x)
#else
@ -220,10 +206,38 @@ extern const uint8 _ffb_64[64];
*/
#define FIND_FIRST_BIT(x) _ffb_64[(x)]
uint8 FindFirstBit(uint32 x);
uint8 FindFirstBit64(uint64 x);
#endif
/**
* Search the first set bit in an integer variable.
*
* @param value The value to search
* @return The position of the first bit set, or 0 when value is 0
*/
template <typename T>
static inline uint8 FindFirstBit(T value)
{
static_assert(sizeof(T) <= sizeof(unsigned long long));
#ifdef WITH_BITMATH_BUILTINS
if (value == 0) return 0;
typename std::make_unsigned<T>::type unsigned_value = value;
if (sizeof(T) <= sizeof(unsigned int)) {
return __builtin_ctz(unsigned_value);
} else if (sizeof(T) == sizeof(unsigned long)) {
return __builtin_ctzl(unsigned_value);
} else {
return __builtin_ctzll(unsigned_value);
}
#else
if (sizeof(T) <= sizeof(uint32)) {
extern uint8 FindFirstBit32(x);
return FindFirstBit32(value);
} else {
extern uint8 FindFirstBit64(x);
return FindFirstBit64(value);
}
#endif
}
uint8 FindLastBit(uint64 x);
@ -275,6 +289,7 @@ static inline T KillFirstBit(T value)
template <typename T>
static inline uint CountBits(T value)
{
static_assert(sizeof(T) <= sizeof(unsigned long long));
#ifdef WITH_BITMATH_BUILTINS
typename std::make_unsigned<T>::type unsigned_value = value;
if (sizeof(T) <= sizeof(unsigned int)) {

@ -81,7 +81,7 @@ DEFINE_POOL_METHOD(inline size_t)::FindFirstFree()
for (; bitmap_index < bitmap_end; bitmap_index++) {
uint64 available = ~this->free_bitmap[bitmap_index];
if (available == 0) continue;
return (bitmap_index * 64) + FindFirstBit64(available);
return (bitmap_index * 64) + FindFirstBit(available);
}
if (this->first_unused < this->size) {

@ -345,7 +345,7 @@ void LinkRefresher::RefreshLinks(const Order *cur, const Order *next, uint8 flag
}
if (cur->IsType(OT_GOTO_STATION) || cur->IsType(OT_IMPLICIT)) {
if (cur->CanLeaveWithCargo(HasBit(flags, HAS_CARGO), FindFirstBit64(this->cargo_mask))) {
if (cur->CanLeaveWithCargo(HasBit(flags, HAS_CARGO), FindFirstBit(this->cargo_mask))) {
SetBit(flags, HAS_CARGO);
this->RefreshStats(cur, next);
} else {

@ -577,7 +577,7 @@ template <typename F> CargoTypes FilterCargoMask(F filter_func, CargoTypes cargo
template <typename T, typename F> T CargoMaskValueFilter(CargoTypes &cargo_mask, F filter_func)
{
CargoID first_cargo_id = FindFirstBit64(cargo_mask);
CargoID first_cargo_id = FindFirstBit(cargo_mask);
T value = filter_func(first_cargo_id);
CargoTypes other_cargo_mask = cargo_mask;
ClrBit(other_cargo_mask, first_cargo_id);

@ -220,7 +220,7 @@ void InitRailTypes()
RailTypes compatible = _railtypes[rt].all_compatible_railtypes;
RailTypes to_check = compatible;
while (to_check) {
RailType i = (RailType)FindFirstBit64(to_check);
RailType i = (RailType)FindFirstBit(to_check);
to_check = KillFirstBit(to_check);
RailTypes new_types = _railtypes[i].compatible_railtypes & (~compatible);
to_check |= new_types;
@ -228,7 +228,7 @@ void InitRailTypes()
}
RailTypes to_update = compatible;
while (to_update) {
RailType i = (RailType)FindFirstBit64(to_update);
RailType i = (RailType)FindFirstBit(to_update);
to_update = KillFirstBit(to_update);
_railtypes[i].all_compatible_railtypes = compatible;
}

@ -340,7 +340,7 @@ class NIHVehicle : public NIHelper {
if (cb36_properties != UINT64_MAX) {
uint64 props = cb36_properties;
while (props) {
PropertyID prop = (PropertyID)FindFirstBit64(props);
PropertyID prop = (PropertyID)FindFirstBit(props);
props = KillFirstBit(props);
uint16 res = GetVehicleProperty(v, prop, CALLBACK_FAILED);
if (res == CALLBACK_FAILED) {

@ -1037,7 +1037,7 @@ void SetTraceRestrictValueDefault(TraceRestrictItem &item, TraceRestrictValueTyp
case TRVT_CARGO_ID:
assert(_standard_cargo_mask != 0);
SetTraceRestrictValue(item, FindFirstBit64(_standard_cargo_mask));
SetTraceRestrictValue(item, FindFirstBit(_standard_cargo_mask));
SetTraceRestrictAuxField(item, 0);
break;

Loading…
Cancel
Save