Don't use pow and log10 directly because it causes an overflow.

This commit is contained in:
King_DuckZ 2017-04-13 19:21:25 +01:00
parent c20ed80ef4
commit c3dee50e5b
2 changed files with 10 additions and 1 deletions

View file

@ -166,11 +166,15 @@ namespace dhandy {
template <typename T>
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...>) {
static_assert(sizeof...(Digits) == CHAR_BIT * sizeof(T) + 1, "Too many values for Digits");
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 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));
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);
}

View file

@ -78,4 +78,9 @@ TEST_CASE ("Check string to int conversions", "[s2i][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");
}