Project

General

Profile

« Previous | Next » 

Revision c7e0510c

Added by David Sorber over 4 years ago

Fix minor bug in int128.h. Also add initial unit tests.

View differences:

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

Also available in: Unified diff