Merge branch 'master' into jgrpp
# Conflicts: # src/company_cmd.cpp # src/core/overflowsafe_type.hpp # src/economy.cpp # src/engine_base.h # src/ground_vehicle.cpp # src/group_gui.cpp # src/industry_cmd.cpp # src/industry_gui.cpp # src/newgrf_commons.cpp # src/newgrf_engine.cpp # src/newgrf_industries.cpp # src/newgrf_object.cpp # src/newgrf_roadstop.cpp # src/newgrf_station.cpp # src/rail_gui.cpp # src/road_cmd.h # src/road_gui.cpp # src/saveload/afterload.cpp # src/script/api/script_log.cpp # src/script/api/script_log.hpp # src/settings_gui.cpp # src/settingsgen/settingsgen.cpp # src/station_cmd.cpp # src/station_cmd.h # src/station_gui.cpp # src/strgen/strgen.cpp # src/string_func.h # src/string_type.h # src/table/settings/network_private_settings.ini # src/tests/math_func.cpp # src/textfile_gui.cpp # src/timetable_gui.cpp # src/town_cmd.cpp # src/vehicle.cpp # src/waypoint_cmd.cpp # src/waypoint_cmd.h # src/widgets/dropdown.cpp
This commit is contained in:
@@ -10,6 +10,9 @@
|
||||
#ifndef MATH_FUNC_HPP
|
||||
#define MATH_FUNC_HPP
|
||||
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
/**
|
||||
* Returns the absolute value of (scalar) variable.
|
||||
*
|
||||
@@ -148,38 +151,65 @@ static inline uint ClampU(const uint a, const uint min, const uint max)
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduce a signed 64-bit int to a signed 32-bit one
|
||||
* Clamp the given value down to lie within the requested type.
|
||||
*
|
||||
* This function clamps a 64-bit integer to a 32-bit integer.
|
||||
* If the 64-bit value is smaller than the smallest 32-bit integer
|
||||
* value 0x80000000 this value is returned (the left one bit is the sign bit).
|
||||
* If the 64-bit value is greater than the greatest 32-bit integer value 0x7FFFFFFF
|
||||
* this value is returned. In all other cases the 64-bit value 'fits' in a
|
||||
* 32-bits integer field and so the value is casted to int32 and returned.
|
||||
* For example ClampTo<uint8_t> will return a value clamped to the range of 0
|
||||
* to 255. Anything smaller will become 0, anything larger will become 255.
|
||||
*
|
||||
* @param a The 64-bit value to clamps
|
||||
* @return The 64-bit value reduced to a 32-bit value
|
||||
* @param a The 64-bit value to clamp.
|
||||
* @return The 64-bit value reduced to a value within the given allowed range
|
||||
* for the return type.
|
||||
* @see Clamp(int, int, int)
|
||||
*/
|
||||
static inline int32 ClampToI32(const int64 a)
|
||||
template <typename To, typename From>
|
||||
constexpr To ClampTo(From value)
|
||||
{
|
||||
return static_cast<int32>(Clamp<int64>(a, INT32_MIN, INT32_MAX));
|
||||
}
|
||||
static_assert(std::numeric_limits<To>::is_integer, "Do not clamp from non-integer values");
|
||||
static_assert(std::numeric_limits<From>::is_integer, "Do not clamp to non-integer values");
|
||||
|
||||
/**
|
||||
* Reduce an unsigned 64-bit int to an unsigned 16-bit one
|
||||
*
|
||||
* @param a The 64-bit value to clamp
|
||||
* @return The 64-bit value reduced to a 16-bit value
|
||||
* @see ClampU(uint, uint, uint)
|
||||
*/
|
||||
static inline uint16 ClampToU16(const uint64 a)
|
||||
{
|
||||
/* MSVC thinks, in its infinite wisdom, that int min(int, int) is a better
|
||||
* match for min(uint64, uint) than uint64 min(uint64, uint64). As such we
|
||||
* need to cast the UINT16_MAX to prevent MSVC from displaying its
|
||||
* infinite loads of warnings. */
|
||||
return static_cast<uint16>(std::min(a, static_cast<uint64>(UINT16_MAX)));
|
||||
if (sizeof(To) >= sizeof(From) && std::numeric_limits<To>::is_signed == std::numeric_limits<From>::is_signed) {
|
||||
/* Same signedness and To type is larger or equal than From type, no clamping is required. */
|
||||
return static_cast<To>(value);
|
||||
}
|
||||
|
||||
if (sizeof(To) > sizeof(From) && std::numeric_limits<To>::is_signed) {
|
||||
/* Signed destination and a larger To type, no clamping is required. */
|
||||
return static_cast<To>(value);
|
||||
}
|
||||
|
||||
/* Get the bigger of the two types based on essentially the number of bits. */
|
||||
using BiggerType = typename std::conditional<sizeof(From) >= sizeof(To), From, To>::type;
|
||||
|
||||
if constexpr (std::numeric_limits<To>::is_signed) {
|
||||
/* The output is a signed number. */
|
||||
if constexpr (std::numeric_limits<From>::is_signed) {
|
||||
/* Both input and output are signed. */
|
||||
return static_cast<To>(std::clamp<BiggerType>(value,
|
||||
std::numeric_limits<To>::lowest(), std::numeric_limits<To>::max()));
|
||||
}
|
||||
|
||||
/* The input is unsigned, so skip the minimum check and use unsigned variant of the biggest type as intermediate type. */
|
||||
using BiggerUnsignedType = typename std::make_unsigned<BiggerType>::type;
|
||||
return static_cast<To>(std::min<BiggerUnsignedType>(std::numeric_limits<To>::max(), value));
|
||||
}
|
||||
|
||||
/* The output is unsigned. */
|
||||
|
||||
if constexpr (std::numeric_limits<From>::is_signed) {
|
||||
/* Input is signed; account for the negative numbers in the input. */
|
||||
if constexpr (sizeof(To) >= sizeof(From)) {
|
||||
/* If the output type is larger or equal to the input type, then only clamp the negative numbers. */
|
||||
return static_cast<To>(std::max<From>(value, 0));
|
||||
}
|
||||
|
||||
/* The output type is smaller than the input type. */
|
||||
using BiggerSignedType = typename std::make_signed<BiggerType>::type;
|
||||
return static_cast<To>(std::clamp<BiggerSignedType>(value,
|
||||
std::numeric_limits<To>::lowest(), std::numeric_limits<To>::max()));
|
||||
}
|
||||
|
||||
/* The input and output are unsigned, just clamp at the high side. */
|
||||
return static_cast<To>(std::min<BiggerType>(value, std::numeric_limits<To>::max()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -212,4 +212,8 @@ static_assert(OverflowSafeInt32(INT32_MAX) + 1 == OverflowSafeInt32(INT32_MAX));
|
||||
static_assert(OverflowSafeInt32(INT32_MAX) * 2 == OverflowSafeInt32(INT32_MAX));
|
||||
static_assert(OverflowSafeInt32(INT32_MIN) * 2 == OverflowSafeInt32(INT32_MIN));
|
||||
|
||||
/* Specialisation of the generic ClampTo function for overflow safe integers to normal integers. */
|
||||
template <typename To, typename From>
|
||||
constexpr To ClampTo(OverflowSafeInt<From> value) { return ClampTo<To>(From(value)); }
|
||||
|
||||
#endif /* OVERFLOWSAFE_TYPE_HPP */
|
||||
|
Reference in New Issue
Block a user