Don't use pow and log10 directly because it causes an overflow.
This commit is contained in:
parent
c20ed80ef4
commit
c3dee50e5b
2 changed files with 10 additions and 1 deletions
|
@ -166,11 +166,15 @@ namespace dhandy {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
template <std::size_t... Powers, std::size_t... Digits>
|
template <std::size_t... Powers, std::size_t... Digits>
|
||||||
std::size_t dec<T>::count_digits_implem (T parValue, dhandy::bt::index_seq<Powers...>, dhandy::bt::index_seq<Digits...>) {
|
std::size_t dec<T>::count_digits_implem (T parValue, dhandy::bt::index_seq<Powers...>, dhandy::bt::index_seq<Digits...>) {
|
||||||
|
static_assert(sizeof...(Digits) == CHAR_BIT * sizeof(T) + 1, "Too many values for Digits");
|
||||||
typedef typename std::make_unsigned<T>::type UT;
|
typedef typename std::make_unsigned<T>::type UT;
|
||||||
static constexpr UT powers[] = { 0, static_cast<UT>(dhandy::implem::power<10, Powers + 1>::value)... };
|
static constexpr UT powers[] = { 0, static_cast<UT>(dhandy::implem::power<10, Powers + 1>::value)... };
|
||||||
static constexpr std::size_t maxdigits[] = { count_digits_bt(static_cast<T>(sprout::pow(2.0, Digits))) - (std::numeric_limits<T>::is_signed ? 1 : 0)... };
|
//the maxdigits table is [len(str(pow(2,b))) for b in range(0,MAX_BITS)]
|
||||||
|
static constexpr std::size_t maxdigits[] = { static_cast<std::size_t>(static_cast<double>(Digits) / sprout::log2(10.0)) + 1 ... };
|
||||||
|
static_assert(maxdigits[sizeof(maxdigits) / sizeof(maxdigits[0]) - 1] <= std::numeric_limits<T>::max(), "Last item in maxdigits overflows T");
|
||||||
const auto bits = sizeof(parValue) * CHAR_BIT - dhandy::implem::count_leading_zeroes<T>(dhandy::implem::abs(parValue));
|
const auto bits = sizeof(parValue) * CHAR_BIT - dhandy::implem::count_leading_zeroes<T>(dhandy::implem::abs(parValue));
|
||||||
static_assert(std::is_same<UT, decltype(dhandy::implem::abs(parValue))>::value, "Unexpected type");
|
static_assert(std::is_same<UT, decltype(dhandy::implem::abs(parValue))>::value, "Unexpected type");
|
||||||
|
assert(bits < sizeof(maxdigits) / sizeof(maxdigits[0]));
|
||||||
return (dhandy::implem::abs(parValue) < powers[maxdigits[bits] - 1] ? maxdigits[bits] - 1 : maxdigits[bits]) + dhandy::implem::is_negative<T>::check(parValue);
|
return (dhandy::implem::abs(parValue) < powers[maxdigits[bits] - 1] ? maxdigits[bits] - 1 : maxdigits[bits]) + dhandy::implem::is_negative<T>::check(parValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,4 +78,9 @@ TEST_CASE ("Check string to int conversions", "[s2i][lexical_cast]") {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE ("Check int to string conversions", "[i2s][lexical_cast]") {
|
TEST_CASE ("Check int to string conversions", "[i2s][lexical_cast]") {
|
||||||
|
using std::string;
|
||||||
|
using dhandy::lexical_cast;
|
||||||
|
|
||||||
|
CHECK(lexical_cast<string>(1) == "1");
|
||||||
|
CHECK(lexical_cast<string>(static_cast<uint16_t>(0xFFFF)) == "65535");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue