switch from writing two separate digits to writing the digits as a uint16

This commit is contained in:
Viper Bailey 2015-11-04 12:51:24 -08:00
parent 9beb01d8e5
commit 11e5d8a8b4
2 changed files with 14 additions and 12 deletions

View File

@ -582,6 +582,9 @@ const char fmt::internal::BasicData<T>::DIGITS[] =
"6061626364656667686970717273747576777879" "6061626364656667686970717273747576777879"
"8081828384858687888990919293949596979899"; "8081828384858687888990919293949596979899";
template <typename T>
const uint16_t *fmt::internal::BasicData<T>::U16_DIGITS = (const uint16_t*)DIGITS;
#define FMT_POWERS_OF_10(factor) \ #define FMT_POWERS_OF_10(factor) \
factor * 10, \ factor * 10, \
factor * 100, \ factor * 100, \

View File

@ -726,6 +726,7 @@ struct BasicData {
static const uint32_t POWERS_OF_10_32[]; static const uint32_t POWERS_OF_10_32[];
static const uint64_t POWERS_OF_10_64[]; static const uint64_t POWERS_OF_10_64[];
static const char DIGITS[]; static const char DIGITS[];
static const uint16_t* U16_DIGITS;
}; };
typedef BasicData<> Data; typedef BasicData<> Data;
@ -2802,30 +2803,28 @@ class FormatInt {
private: private:
// Buffer should be large enough to hold all digits (digits10 + 1), // Buffer should be large enough to hold all digits (digits10 + 1),
// a sign and a null character. // a sign and a null character.
enum {BUFFER_SIZE = std::numeric_limits<ULongLong>::digits10 + 3}; enum {BUFFER_SIZE = std::numeric_limits<ULongLong>::digits10 + 4};
mutable char buffer_[BUFFER_SIZE]; mutable char buffer_[BUFFER_SIZE];
char *str_; char *str_;
// Formats value in reverse and returns the number of digits. // Formats value in reverse and returns the number of digits.
char *format_decimal(ULongLong value) { char *format_decimal(ULongLong value) {
char *buffer_end = buffer_ + BUFFER_SIZE - 1; uint16_t* buffer_end = (uint16_t*)(buffer_ + BUFFER_SIZE - 1);
while (value >= 100) { while (value >= 100) {
// Integer division is slow so do it for a group of two digits instead // Integer division is slow so do it for a group of two digits instead
// of for every digit. The idea comes from the talk by Alexandrescu // of for every digit. The idea comes from the talk by Alexandrescu
// "Three Optimization Tips for C++". See speed-test for a comparison. // "Three Optimization Tips for C++". See speed-test for a comparison.
unsigned index = static_cast<unsigned>((value % 100) * 2); unsigned index = value%100;
value /= 100; value /= 100;
*--buffer_end = internal::Data::DIGITS[index + 1]; *--buffer_end = internal::Data::U16_DIGITS[index];
*--buffer_end = internal::Data::DIGITS[index];
} }
*--buffer_end = internal::Data::U16_DIGITS[value];
if ( value < 10 ) { if ( value < 10 ) {
*--buffer_end = static_cast<char>('0' + value); return ((char*)buffer_end)+1;
return buffer_end; } else {
return ((char*)buffer_end);
} }
unsigned index = static_cast<unsigned>(value * 2);
*--buffer_end = internal::Data::DIGITS[index + 1];
*--buffer_end = internal::Data::DIGITS[index];
return buffer_end;
} }
void FormatSigned(LongLong value) { void FormatSigned(LongLong value) {