Merge branch 'master' into jgrpp
# Conflicts: # src/core/bitmath_func.cpp # src/core/bitmath_func.hpp # src/core/geometry_type.hpp # src/game/game_text.hpp # src/graph_gui.cpp # src/pathfinder/npf/npf.cpp # src/script/api/script_text.cpp # src/spritecache.cpp # src/track_func.h
This commit is contained in:
@@ -3,7 +3,6 @@ add_files(
|
||||
alloc_func.hpp
|
||||
alloc_type.hpp
|
||||
backup_type.hpp
|
||||
bitmath_func.cpp
|
||||
bitmath_func.hpp
|
||||
checksum_func.hpp
|
||||
container_func.hpp
|
||||
|
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file bitmath_func.cpp Functions related to bit mathematics. */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "bitmath_func.hpp"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
#ifndef WITH_BITMATH_BUILTINS
|
||||
|
||||
const uint8_t _ffb_64[64] = {
|
||||
0, 0, 1, 0, 2, 0, 1, 0,
|
||||
3, 0, 1, 0, 2, 0, 1, 0,
|
||||
4, 0, 1, 0, 2, 0, 1, 0,
|
||||
3, 0, 1, 0, 2, 0, 1, 0,
|
||||
5, 0, 1, 0, 2, 0, 1, 0,
|
||||
3, 0, 1, 0, 2, 0, 1, 0,
|
||||
4, 0, 1, 0, 2, 0, 1, 0,
|
||||
3, 0, 1, 0, 2, 0, 1, 0,
|
||||
};
|
||||
|
||||
uint8_t FindFirstBit32(uint32_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 & 0x0000ffff) == 0) { x >>= 16; pos += 16; }
|
||||
if ((x & 0x000000ff) == 0) { x >>= 8; pos += 8; }
|
||||
if ((x & 0x0000000f) == 0) { x >>= 4; pos += 4; }
|
||||
if ((x & 0x00000003) == 0) { x >>= 2; pos += 2; }
|
||||
if ((x & 0x00000001) == 0) { pos += 1; }
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
uint8_t FindFirstBit64(uint64_t x)
|
||||
{
|
||||
if (x == 0) return 0;
|
||||
if ((x & 0x00000000ffffffffULL) != 0) return FindFirstBit32(static_cast<uint32_t>(x));
|
||||
return FindFirstBit32(static_cast<uint32_t>(x >> 32)) + 32;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* 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 FindLastBit64(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;
|
||||
}
|
@@ -10,6 +10,7 @@
|
||||
#ifndef BITMATH_FUNC_HPP
|
||||
#define BITMATH_FUNC_HPP
|
||||
|
||||
#include <bit>
|
||||
#include <type_traits>
|
||||
|
||||
/**
|
||||
@@ -186,110 +187,38 @@ inline T ToggleBit(T &x, const uint8_t y)
|
||||
return x = (T)(x ^ ((T)1U << y));
|
||||
}
|
||||
|
||||
#ifdef WITH_BITMATH_BUILTINS
|
||||
|
||||
#define FIND_FIRST_BIT(x) FindFirstBit<uint>(x)
|
||||
|
||||
#else
|
||||
|
||||
/** Lookup table to check which bit is set in a 6 bit variable */
|
||||
extern const uint8_t _ffb_64[64];
|
||||
|
||||
/**
|
||||
* Returns the first non-zero bit in a 6-bit value (from right).
|
||||
* Search the first set bit in a value.
|
||||
* When no bit is set, it returns 0.
|
||||
*
|
||||
* Returns the position of the first bit that is not zero, counted from the
|
||||
* LSB. Ie, 110100 returns 2, 000001 returns 0, etc. When x == 0 returns
|
||||
* 0.
|
||||
*
|
||||
* @param x The 6-bit value to check the first zero-bit
|
||||
* @return The first position of a bit started from the LSB or 0 if x is 0.
|
||||
*/
|
||||
#define FIND_FIRST_BIT(x) _ffb_64[(x) & 0x3F]
|
||||
|
||||
#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
|
||||
* @param x The value to search.
|
||||
* @return The position of the first bit set.
|
||||
*/
|
||||
template <typename T>
|
||||
inline uint8_t FindFirstBit(T value)
|
||||
constexpr uint8_t FindFirstBit(T x)
|
||||
{
|
||||
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);
|
||||
if (x == 0) return 0;
|
||||
|
||||
if constexpr (std::is_enum_v<T>) {
|
||||
return std::countr_zero<std::underlying_type_t<T>>(x);
|
||||
} else {
|
||||
return __builtin_ctzll(unsigned_value);
|
||||
return std::countr_zero(x);
|
||||
}
|
||||
#else
|
||||
if (sizeof(T) <= sizeof(uint32_t)) {
|
||||
extern uint8_t FindFirstBit32(uint32_t x);
|
||||
return FindFirstBit32(value);
|
||||
} else {
|
||||
extern uint8_t FindFirstBit64(uint64_t x);
|
||||
return FindFirstBit64(value);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the last set bit in an integer variable.
|
||||
* Search the last set bit in a value.
|
||||
* When no bit is set, it returns 0.
|
||||
*
|
||||
* @param value The value to search
|
||||
* @return The position of the last bit set, or 0 when value is 0
|
||||
* @param x The value to search.
|
||||
* @return The position of the last bit set.
|
||||
*/
|
||||
template <typename T>
|
||||
inline uint8_t FindLastBit(T value)
|
||||
constexpr uint8_t FindLastBit(T x)
|
||||
{
|
||||
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_clz(1) - __builtin_clz(unsigned_value);
|
||||
} else if (sizeof(T) == sizeof(unsigned long)) {
|
||||
return __builtin_clzl(1) - __builtin_clzl(unsigned_value);
|
||||
} else {
|
||||
return __builtin_clzll(1) - __builtin_clzll(unsigned_value);
|
||||
}
|
||||
#else
|
||||
extern uint8_t FindLastBit64(uint64_t x);
|
||||
return FindLastBit64(value);
|
||||
#endif
|
||||
}
|
||||
if (x == 0) return 0;
|
||||
|
||||
|
||||
/**
|
||||
* Finds the position of the first non-zero bit in an integer.
|
||||
*
|
||||
* This function returns the position of the first bit set in the
|
||||
* integer. It does only check the bits of the bitmask
|
||||
* 0x3F3F (0011111100111111).
|
||||
*
|
||||
* @param value The value to check the first bits
|
||||
* @return The position of the first bit which is set
|
||||
* @see FIND_FIRST_BIT
|
||||
*/
|
||||
inline uint8_t FindFirstBit2x64(const int value)
|
||||
{
|
||||
#ifdef WITH_BITMATH_BUILTINS
|
||||
return FindFirstBit(value & 0x3F3F);
|
||||
#else
|
||||
if (value == 0) return 0;
|
||||
if ((value & 0x3F) == 0) {
|
||||
return FIND_FIRST_BIT((value >> 8) & 0x3F) + 8;
|
||||
} else {
|
||||
return FIND_FIRST_BIT(value & 0x3F);
|
||||
}
|
||||
#endif
|
||||
return std::countl_zero<T>(1) - std::countl_zero<T>(x);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -315,32 +244,13 @@ inline T KillFirstBit(T value)
|
||||
* @return the number of bits.
|
||||
*/
|
||||
template <typename T>
|
||||
inline uint CountBits(T value)
|
||||
constexpr 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)) {
|
||||
return __builtin_popcount(unsigned_value);
|
||||
} else if (sizeof(T) == sizeof(unsigned long)) {
|
||||
return __builtin_popcountl(unsigned_value);
|
||||
if constexpr (std::is_enum_v<T>) {
|
||||
return std::popcount<std::underlying_type_t<T>>(value);
|
||||
} else {
|
||||
return __builtin_popcountll(unsigned_value);
|
||||
return std::popcount(value);
|
||||
}
|
||||
#else
|
||||
uint num;
|
||||
|
||||
/* This loop is only called once for every bit set by clearing the lowest
|
||||
* bit in each loop. The number of bits is therefore equal to the number of
|
||||
* times the loop was called. It was found at the following website:
|
||||
* http://graphics.stanford.edu/~seander/bithacks.html */
|
||||
|
||||
for (num = 0; value != 0; num++) {
|
||||
value &= (T)(value - 1);
|
||||
}
|
||||
|
||||
return num;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -353,8 +263,8 @@ template <typename T>
|
||||
inline bool IsOddParity(T value)
|
||||
{
|
||||
static_assert(sizeof(T) <= sizeof(unsigned long long));
|
||||
#ifdef WITH_BITMATH_BUILTINS
|
||||
typename std::make_unsigned<T>::type unsigned_value = value;
|
||||
#ifdef WITH_BITMATH_BUILTINS
|
||||
if (sizeof(T) <= sizeof(unsigned int)) {
|
||||
return __builtin_parity(unsigned_value);
|
||||
} else if (sizeof(T) == sizeof(unsigned long)) {
|
||||
@@ -363,7 +273,7 @@ inline bool IsOddParity(T value)
|
||||
return __builtin_parityll(unsigned_value);
|
||||
}
|
||||
#else
|
||||
return CountBits<T>(value) & 1;
|
||||
return CountBits(unsigned_value) & 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@@ -46,18 +46,4 @@
|
||||
#define TO_LE64(x) (x)
|
||||
#endif /* TTD_ENDIAN == TTD_BIG_ENDIAN */
|
||||
|
||||
inline uint16_t ReadLE16Aligned(const void *x)
|
||||
{
|
||||
return FROM_LE16(*(const uint16_t*)x);
|
||||
}
|
||||
|
||||
inline uint16_t ReadLE16Unaligned(const void *x)
|
||||
{
|
||||
#if OTTD_ALIGNMENT == 1
|
||||
return ((const byte*)x)[0] | ((const byte*)x)[1] << 8;
|
||||
#else
|
||||
return FROM_LE16(*(const uint16_t*)x);
|
||||
#endif /* OTTD_ALIGNMENT == 1 */
|
||||
}
|
||||
|
||||
#endif /* ENDIAN_FUNC_HPP */
|
||||
|
@@ -22,6 +22,9 @@ struct Point {
|
||||
int x;
|
||||
int y;
|
||||
|
||||
constexpr Point() : x(0), y(0) {}
|
||||
constexpr Point(int x, int y) : x(x), y(y) {}
|
||||
|
||||
bool operator==(const Point&) const = default;
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user