Revision c7e0510c
Added by David Sorber over 4 years ago
| software/fixed/int128.h | ||
|---|---|---|
|
std::numeric_limits<uint128_t>::max() / 7,
|
||
|
std::numeric_limits<uint128_t>::max() / 8,
|
||
|
std::numeric_limits<uint128_t>::max() / 9,
|
||
|
std::numeric_limits<uint128_t>::max() / 10,
|
||
|
std::numeric_limits<uint128_t>::max() / 11,
|
||
|
std::numeric_limits<uint128_t>::max() / 12,
|
||
|
std::numeric_limits<uint128_t>::max() / 13,
|
||
| ... | ... | |
|
std::numeric_limits<uint128_t>::max() % 7,
|
||
|
std::numeric_limits<uint128_t>::max() % 8,
|
||
|
std::numeric_limits<uint128_t>::max() % 9,
|
||
|
std::numeric_limits<uint128_t>::max() % 10,
|
||
|
std::numeric_limits<uint128_t>::max() % 11,
|
||
|
std::numeric_limits<uint128_t>::max() % 12,
|
||
|
std::numeric_limits<uint128_t>::max() % 13,
|
||
| ... | ... | |
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
int128_t strtoll_128_b10opt(const char* nptr, char** endptr, int base=10)
|
||
|
{
|
||
|
bool negative = false;
|
||
|
uint128_t cutoff = 0;
|
||
|
uint32_t cutlim = 0;
|
||
|
int128_t value = 0;
|
||
|
const char* ptr;
|
||
|
unsigned char chr;
|
||
|
const char *save, *end;
|
||
|
bool overflow = false;
|
||
|
|
||
|
// Validate the base parameter
|
||
|
#if 0
|
||
|
if (base < 0 || base == 1 || base > 36)
|
||
|
{
|
||
|
std::ostringstream msg;
|
||
|
msg << "Base value \"" << base << "\" is invalid; base must be "
|
||
|
<< "between 2-36 (inclusive).";
|
||
|
throw std::out_of_range(msg.str());
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
save = ptr = nptr;
|
||
|
|
||
|
// Skip any leading whitespace
|
||
|
while (std::isspace(*ptr))
|
||
|
{
|
||
|
++ptr;
|
||
|
}
|
||
|
|
||
|
// Check for end of string
|
||
|
if (__builtin_expect((*ptr == '\0'), 0))
|
||
|
{
|
||
|
goto noconv;
|
||
|
}
|
||
|
|
||
|
// Parse -/+
|
||
|
if (*ptr == '-')
|
||
|
{
|
||
|
negative = true;
|
||
|
++ptr;
|
||
|
}
|
||
|
else if (*ptr == '+')
|
||
|
{
|
||
|
++ptr;
|
||
|
}
|
||
|
|
||
|
// Save start of digits
|
||
|
save = ptr;
|
||
|
end = nullptr;
|
||
|
|
||
|
cutoff = max_tab[8]; // base 10
|
||
|
cutlim = rem_tab[8];
|
||
|
|
||
|
// Iterate over the characters
|
||
|
chr = *ptr;
|
||
|
for (; chr != '\0'; chr = *++ptr)
|
||
|
{
|
||
|
if (ptr == end)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (chr >= '0' && chr <= '9')
|
||
|
{
|
||
|
chr -= '0';
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (value > cutoff || (value == cutoff && chr > cutlim))
|
||
|
{
|
||
|
overflow = true;
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
value *= static_cast<uint128_t>(10);
|
||
|
value += (int)chr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Check if no conversion was done
|
||
|
if (ptr == save)
|
||
|
{
|
||
|
goto noconv;
|
||
|
}
|
||
|
|
||
|
// Store end if requested
|
||
|
if (endptr != nullptr)
|
||
|
{
|
||
|
*endptr = const_cast<char*>(ptr);
|
||
|
}
|
||
|
|
||
|
// Check for overflow
|
||
|
if (__builtin_expect((overflow), 0))
|
||
|
{
|
||
|
std::ostringstream msg;
|
||
|
msg << "Overflow detected at input offset " << (ptr - nptr);
|
||
|
throw std::overflow_error(msg.str());
|
||
|
}
|
||
|
|
||
|
// Regular return path
|
||
|
return negative ? -value : value;
|
||
|
|
||
|
noconv:
|
||
|
|
||
|
if (endptr != nullptr)
|
||
|
{
|
||
|
*endptr = const_cast<char*>(nptr);
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
uint128_t strtoull_128_b10opt(const char* nptr, char** endptr, int base=10)
|
||
|
{
|
||
|
uint128_t cutoff = 0;
|
||
|
uint32_t cutlim = 0;
|
||
|
uint128_t value = 0;
|
||
|
const char* ptr;
|
||
|
unsigned char chr;
|
||
|
const char *save, *end;
|
||
|
bool overflow = false;
|
||
|
|
||
|
// Validate the base parameter
|
||
|
#if 0
|
||
|
if (base < 0 || base == 1 || base > 36)
|
||
|
{
|
||
|
std::ostringstream msg;
|
||
|
msg << "Base value \"" << base << "\" is invalid; base must be "
|
||
|
<< "between 2-36 (inclusive).";
|
||
|
throw std::out_of_range(msg.str());
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
save = ptr = nptr;
|
||
|
|
||
|
// Skip any leading whitespace
|
||
|
while (std::isspace(*ptr))
|
||
|
{
|
||
|
++ptr;
|
||
|
}
|
||
|
|
||
|
// Check for end of string
|
||
|
if (__builtin_expect((*ptr == '\0'), 0))
|
||
|
{
|
||
|
goto noconv;
|
||
|
}
|
||
|
|
||
|
// Parse -/+
|
||
|
if (*ptr == '-' || *ptr == '+')
|
||
|
{
|
||
|
++ptr;
|
||
|
}
|
||
|
|
||
|
// Save start of digits
|
||
|
save = ptr;
|
||
|
end = nullptr;
|
||
|
|
||
|
cutoff = max_tab[8]; // base 10
|
||
|
cutlim = rem_tab[8];
|
||
|
|
||
|
// Iterate over the characters
|
||
|
chr = *ptr;
|
||
|
for (; chr != '\0'; chr = *++ptr)
|
||
|
{
|
||
|
if (ptr == end)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (chr >= '0' && chr <= '9')
|
||
|
{
|
||
|
chr -= '0';
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (value > cutoff || (value == cutoff && chr > cutlim))
|
||
|
{
|
||
|
overflow = true;
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
value *= static_cast<uint128_t>(10);
|
||
|
value += (int)chr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Check if no conversion was done
|
||
|
if (ptr == save)
|
||
|
{
|
||
|
goto noconv;
|
||
|
}
|
||
|
|
||
|
// Store end if requested
|
||
|
if (endptr != nullptr)
|
||
|
{
|
||
|
*endptr = const_cast<char*>(ptr);
|
||
|
}
|
||
|
|
||
|
// Check for overflow
|
||
|
if (__builtin_expect((overflow), 0))
|
||
|
{
|
||
|
std::ostringstream msg;
|
||
|
msg << "Overflow detected at input offset " << (ptr - nptr);
|
||
|
throw std::overflow_error(msg.str());
|
||
|
}
|
||
|
|
||
|
// Regular return path
|
||
|
return value;
|
||
|
|
||
|
noconv:
|
||
|
|
||
|
if (endptr != nullptr)
|
||
|
{
|
||
|
*endptr = const_cast<char*>(nptr);
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
#endif
|
||
Fix minor bug in int128.h. Also add initial unit tests.