Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Low-risk C++11 and C++14 constexpr functions #177

Merged
merged 4 commits into from
Feb 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions include/fast_float/ascii_number.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ namespace fast_float {

// Next function can be micro-optimized, but compilers are entirely
// able to optimize it well.
fastfloat_really_inline bool is_integer(char c) noexcept { return c >= '0' && c <= '9'; }
fastfloat_really_inline constexpr bool is_integer(char c) noexcept {
return c >= '0' && c <= '9';
}

fastfloat_really_inline uint64_t byteswap(uint64_t val) {
fastfloat_really_inline constexpr uint64_t byteswap(uint64_t val) {
return (val & 0xFF00000000000000) >> 56
| (val & 0x00FF000000000000) >> 40
| (val & 0x0000FF0000000000) >> 24
Expand Down Expand Up @@ -44,7 +46,8 @@ fastfloat_really_inline void write_u64(uint8_t *chars, uint64_t val) {
}

// credit @aqrit
fastfloat_really_inline uint32_t parse_eight_digits_unrolled(uint64_t val) {
fastfloat_really_inline FASTFLOAT_CONSTEXPR14
uint32_t parse_eight_digits_unrolled(uint64_t val) {
const uint64_t mask = 0x000000FF000000FF;
const uint64_t mul1 = 0x000F424000000064; // 100 + (1000000ULL << 32)
const uint64_t mul2 = 0x0000271000000001; // 1 + (10000ULL << 32)
Expand All @@ -59,7 +62,7 @@ fastfloat_really_inline uint32_t parse_eight_digits_unrolled(const char *chars)
}

// credit @aqrit
fastfloat_really_inline bool is_made_of_eight_digits_fast(uint64_t val) noexcept {
fastfloat_really_inline constexpr bool is_made_of_eight_digits_fast(uint64_t val) noexcept {
return !((((val + 0x4646464646464646) | (val - 0x3030303030303030)) &
0x8080808080808080));
}
Expand Down
18 changes: 9 additions & 9 deletions include/fast_float/bigint.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,23 +54,23 @@ struct stackvec {
FASTFLOAT_ASSERT(try_extend(s));
}

limb& operator[](size_t index) noexcept {
FASTFLOAT_CONSTEXPR14 limb& operator[](size_t index) noexcept {
FASTFLOAT_DEBUG_ASSERT(index < length);
return data[index];
}
const limb& operator[](size_t index) const noexcept {
FASTFLOAT_CONSTEXPR14 const limb& operator[](size_t index) const noexcept {
FASTFLOAT_DEBUG_ASSERT(index < length);
return data[index];
}
// index from the end of the container
const limb& rindex(size_t index) const noexcept {
FASTFLOAT_CONSTEXPR14 const limb& rindex(size_t index) const noexcept {
FASTFLOAT_DEBUG_ASSERT(index < length);
size_t rindex = length - index - 1;
return data[rindex];
}

// set the length, without bounds checking.
void set_len(size_t len) noexcept {
FASTFLOAT_CONSTEXPR14 void set_len(size_t len) noexcept {
length = uint16_t(len);
}
constexpr size_t len() const noexcept {
Expand All @@ -83,12 +83,12 @@ struct stackvec {
return size;
}
// append item to vector, without bounds checking
void push_unchecked(limb value) noexcept {
FASTFLOAT_CONSTEXPR14 void push_unchecked(limb value) noexcept {
data[length] = value;
length++;
}
// append item to vector, returning if item was added
bool try_push(limb value) noexcept {
FASTFLOAT_CONSTEXPR14 bool try_push(limb value) noexcept {
if (len() < capacity()) {
push_unchecked(value);
return true;
Expand Down Expand Up @@ -137,7 +137,7 @@ struct stackvec {
// check if any limbs are non-zero after the given index.
// this needs to be done in reverse order, since the index
// is relative to the most significant limbs.
bool nonzero(size_t index) const noexcept {
FASTFLOAT_CONSTEXPR14 bool nonzero(size_t index) const noexcept {
while (index < len()) {
if (rindex(index) != 0) {
return true;
Expand All @@ -147,14 +147,14 @@ struct stackvec {
return false;
}
// normalize the big integer, so most-significant zero limbs are removed.
void normalize() noexcept {
FASTFLOAT_CONSTEXPR14 void normalize() noexcept {
while (len() > 0 && rindex(0) == 0) {
length--;
}
}
};

fastfloat_really_inline
fastfloat_really_inline FASTFLOAT_CONSTEXPR14
uint64_t empty_hi64(bool& truncated) noexcept {
truncated = false;
return 0;
Expand Down
2 changes: 1 addition & 1 deletion include/fast_float/decimal_to_binary.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ namespace detail {
// create an adjusted mantissa, biased by the invalid power2
// for significant digits already multiplied by 10 ** q.
template <typename binary>
fastfloat_really_inline
fastfloat_really_inline FASTFLOAT_CONSTEXPR14
adjusted_mantissa compute_error_scaled(int64_t q, uint64_t w, int lz) noexcept {
int hilz = int(w >> 63) ^ 1;
adjusted_mantissa answer;
Expand Down
33 changes: 16 additions & 17 deletions include/fast_float/digit_comparison.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ constexpr static uint64_t powers_of_ten_uint64[] = {
// this algorithm is not even close to optimized, but it has no practical
// effect on performance: in order to have a faster algorithm, we'd need
// to slow down performance for faster algorithms, and this is still fast.
fastfloat_really_inline int32_t scientific_exponent(parsed_number_string& num) noexcept {
fastfloat_really_inline FASTFLOAT_CONSTEXPR14
int32_t scientific_exponent(parsed_number_string& num) noexcept {
uint64_t mantissa = num.mantissa;
int32_t exponent = int32_t(num.exponent);
while (mantissa >= 10000) {
Expand Down Expand Up @@ -81,7 +82,8 @@ fastfloat_really_inline adjusted_mantissa to_extended_halfway(T value) noexcept

// round an extended-precision float to the nearest machine float.
template <typename T, typename callback>
fastfloat_really_inline void round(adjusted_mantissa& am, callback cb) noexcept {
fastfloat_really_inline FASTFLOAT_CONSTEXPR14
void round(adjusted_mantissa& am, callback cb) noexcept {
int32_t mantissa_shift = 64 - binary_format<T>::mantissa_explicit_bits() - 1;
if (-am.power2 >= mantissa_shift) {
// have a denormal float
Expand Down Expand Up @@ -110,20 +112,16 @@ fastfloat_really_inline void round(adjusted_mantissa& am, callback cb) noexcept
}

template <typename callback>
fastfloat_really_inline
fastfloat_really_inline FASTFLOAT_CONSTEXPR14
void round_nearest_tie_even(adjusted_mantissa& am, int32_t shift, callback cb) noexcept {
uint64_t mask;
uint64_t halfway;
if (shift == 64) {
mask = UINT64_MAX;
} else {
mask = (uint64_t(1) << shift) - 1;
}
if (shift == 0) {
halfway = 0;
} else {
halfway = uint64_t(1) << (shift - 1);
}
const uint64_t mask
= (shift == 64)
? UINT64_MAX
: (uint64_t(1) << shift) - 1;
const uint64_t halfway
= (shift == 0)
? 0
: uint64_t(1) << (shift - 1);
uint64_t truncated_bits = am.mantissa & mask;
bool is_above = truncated_bits > halfway;
bool is_halfway = truncated_bits == halfway;
Expand All @@ -140,7 +138,8 @@ void round_nearest_tie_even(adjusted_mantissa& am, int32_t shift, callback cb) n
am.mantissa += uint64_t(cb(is_odd, is_halfway, is_above));
}

fastfloat_really_inline void round_down(adjusted_mantissa& am, int32_t shift) noexcept {
fastfloat_really_inline FASTFLOAT_CONSTEXPR14
void round_down(adjusted_mantissa& am, int32_t shift) noexcept {
if (shift == 64) {
am.mantissa = 0;
} else {
Expand Down Expand Up @@ -199,7 +198,7 @@ void parse_eight_digits(const char*& p, limb& value, size_t& counter, size_t& co
count += 8;
}

fastfloat_really_inline
fastfloat_really_inline FASTFLOAT_CONSTEXPR14
void parse_one_digit(const char*& p, limb& value, size_t& counter, size_t& count) noexcept {
value = value * 10 + limb(*p - '0');
p++;
Expand Down
Loading