Replace FindFirstBit/FindFirstBit64 with a single template function
This commit is contained in:
@@ -25,18 +25,7 @@ const uint8 _ffb_64[64] = {
|
|||||||
3, 0, 1, 0, 2, 0, 1, 0,
|
3, 0, 1, 0, 2, 0, 1, 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
uint8 FindFirstBit32(uint32 x)
|
||||||
* 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)
|
|
||||||
{
|
{
|
||||||
if (x == 0) return 0;
|
if (x == 0) return 0;
|
||||||
/* The macro FIND_FIRST_BIT is better to use when your x is
|
/* 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
|
#ifdef WITH_BITMATH_BUILTINS
|
||||||
|
|
||||||
#define FIND_FIRST_BIT(x) FindFirstBit(x)
|
#define FIND_FIRST_BIT(x) FindFirstBit<uint>(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);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@@ -220,11 +206,39 @@ extern const uint8 _ffb_64[64];
|
|||||||
*/
|
*/
|
||||||
#define FIND_FIRST_BIT(x) _ffb_64[(x)]
|
#define FIND_FIRST_BIT(x) _ffb_64[(x)]
|
||||||
|
|
||||||
uint8 FindFirstBit(uint32 x);
|
|
||||||
uint8 FindFirstBit64(uint64 x);
|
|
||||||
|
|
||||||
#endif
|
#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);
|
uint8 FindLastBit(uint64 x);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -275,6 +289,7 @@ static inline T KillFirstBit(T value)
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
static inline uint CountBits(T value)
|
static inline uint CountBits(T value)
|
||||||
{
|
{
|
||||||
|
static_assert(sizeof(T) <= sizeof(unsigned long long));
|
||||||
#ifdef WITH_BITMATH_BUILTINS
|
#ifdef WITH_BITMATH_BUILTINS
|
||||||
typename std::make_unsigned<T>::type unsigned_value = value;
|
typename std::make_unsigned<T>::type unsigned_value = value;
|
||||||
if (sizeof(T) <= sizeof(unsigned int)) {
|
if (sizeof(T) <= sizeof(unsigned int)) {
|
||||||
|
@@ -81,7 +81,7 @@ DEFINE_POOL_METHOD(inline size_t)::FindFirstFree()
|
|||||||
for (; bitmap_index < bitmap_end; bitmap_index++) {
|
for (; bitmap_index < bitmap_end; bitmap_index++) {
|
||||||
uint64 available = ~this->free_bitmap[bitmap_index];
|
uint64 available = ~this->free_bitmap[bitmap_index];
|
||||||
if (available == 0) continue;
|
if (available == 0) continue;
|
||||||
return (bitmap_index * 64) + FindFirstBit64(available);
|
return (bitmap_index * 64) + FindFirstBit(available);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->first_unused < this->size) {
|
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->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);
|
SetBit(flags, HAS_CARGO);
|
||||||
this->RefreshStats(cur, next);
|
this->RefreshStats(cur, next);
|
||||||
} else {
|
} 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)
|
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);
|
T value = filter_func(first_cargo_id);
|
||||||
CargoTypes other_cargo_mask = cargo_mask;
|
CargoTypes other_cargo_mask = cargo_mask;
|
||||||
ClrBit(other_cargo_mask, first_cargo_id);
|
ClrBit(other_cargo_mask, first_cargo_id);
|
||||||
|
@@ -220,7 +220,7 @@ void InitRailTypes()
|
|||||||
RailTypes compatible = _railtypes[rt].all_compatible_railtypes;
|
RailTypes compatible = _railtypes[rt].all_compatible_railtypes;
|
||||||
RailTypes to_check = compatible;
|
RailTypes to_check = compatible;
|
||||||
while (to_check) {
|
while (to_check) {
|
||||||
RailType i = (RailType)FindFirstBit64(to_check);
|
RailType i = (RailType)FindFirstBit(to_check);
|
||||||
to_check = KillFirstBit(to_check);
|
to_check = KillFirstBit(to_check);
|
||||||
RailTypes new_types = _railtypes[i].compatible_railtypes & (~compatible);
|
RailTypes new_types = _railtypes[i].compatible_railtypes & (~compatible);
|
||||||
to_check |= new_types;
|
to_check |= new_types;
|
||||||
@@ -228,7 +228,7 @@ void InitRailTypes()
|
|||||||
}
|
}
|
||||||
RailTypes to_update = compatible;
|
RailTypes to_update = compatible;
|
||||||
while (to_update) {
|
while (to_update) {
|
||||||
RailType i = (RailType)FindFirstBit64(to_update);
|
RailType i = (RailType)FindFirstBit(to_update);
|
||||||
to_update = KillFirstBit(to_update);
|
to_update = KillFirstBit(to_update);
|
||||||
_railtypes[i].all_compatible_railtypes = compatible;
|
_railtypes[i].all_compatible_railtypes = compatible;
|
||||||
}
|
}
|
||||||
|
@@ -340,7 +340,7 @@ class NIHVehicle : public NIHelper {
|
|||||||
if (cb36_properties != UINT64_MAX) {
|
if (cb36_properties != UINT64_MAX) {
|
||||||
uint64 props = cb36_properties;
|
uint64 props = cb36_properties;
|
||||||
while (props) {
|
while (props) {
|
||||||
PropertyID prop = (PropertyID)FindFirstBit64(props);
|
PropertyID prop = (PropertyID)FindFirstBit(props);
|
||||||
props = KillFirstBit(props);
|
props = KillFirstBit(props);
|
||||||
uint16 res = GetVehicleProperty(v, prop, CALLBACK_FAILED);
|
uint16 res = GetVehicleProperty(v, prop, CALLBACK_FAILED);
|
||||||
if (res == CALLBACK_FAILED) {
|
if (res == CALLBACK_FAILED) {
|
||||||
|
@@ -1037,7 +1037,7 @@ void SetTraceRestrictValueDefault(TraceRestrictItem &item, TraceRestrictValueTyp
|
|||||||
|
|
||||||
case TRVT_CARGO_ID:
|
case TRVT_CARGO_ID:
|
||||||
assert(_standard_cargo_mask != 0);
|
assert(_standard_cargo_mask != 0);
|
||||||
SetTraceRestrictValue(item, FindFirstBit64(_standard_cargo_mask));
|
SetTraceRestrictValue(item, FindFirstBit(_standard_cargo_mask));
|
||||||
SetTraceRestrictAuxField(item, 0);
|
SetTraceRestrictAuxField(item, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user