mirror of
https://github.com/fastfloat/fast_float.git
synced 2025-12-07 01:06:48 +08:00
Merge pull request #294 from dalle/dalle/equiv_uint_t
* introduce equiv_uint_t helper * harmonize ifdef checks * formatted code
This commit is contained in:
commit
49aed7782e
@ -1,2 +1,4 @@
|
|||||||
BasedOnStyle: LLVM
|
BasedOnStyle: LLVM
|
||||||
SortIncludes: false
|
SortIncludes: false
|
||||||
|
SeparateDefinitionBlocks: Always
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
|||||||
@ -52,10 +52,13 @@ struct performance_counters {
|
|||||||
double branches;
|
double branches;
|
||||||
double missed_branches;
|
double missed_branches;
|
||||||
double instructions;
|
double instructions;
|
||||||
|
|
||||||
performance_counters(uint64_t c, uint64_t b, uint64_t m, uint64_t i)
|
performance_counters(uint64_t c, uint64_t b, uint64_t m, uint64_t i)
|
||||||
: cycles(c), branches(b), missed_branches(m), instructions(i) {}
|
: cycles(c), branches(b), missed_branches(m), instructions(i) {}
|
||||||
|
|
||||||
performance_counters(double c, double b, double m, double i)
|
performance_counters(double c, double b, double m, double i)
|
||||||
: cycles(c), branches(b), missed_branches(m), instructions(i) {}
|
: cycles(c), branches(b), missed_branches(m), instructions(i) {}
|
||||||
|
|
||||||
performance_counters(double init)
|
performance_counters(double init)
|
||||||
: cycles(init), branches(init), missed_branches(init),
|
: cycles(init), branches(init), missed_branches(init),
|
||||||
instructions(init) {}
|
instructions(init) {}
|
||||||
@ -67,6 +70,7 @@ struct performance_counters {
|
|||||||
instructions -= other.instructions;
|
instructions -= other.instructions;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline performance_counters &min(const performance_counters &other) {
|
inline performance_counters &min(const performance_counters &other) {
|
||||||
cycles = other.cycles < cycles ? other.cycles : cycles;
|
cycles = other.cycles < cycles ? other.cycles : cycles;
|
||||||
branches = other.branches < branches ? other.branches : branches;
|
branches = other.branches < branches ? other.branches : branches;
|
||||||
@ -77,6 +81,7 @@ struct performance_counters {
|
|||||||
other.instructions < instructions ? other.instructions : instructions;
|
other.instructions < instructions ? other.instructions : instructions;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline performance_counters &operator+=(const performance_counters &other) {
|
inline performance_counters &operator+=(const performance_counters &other) {
|
||||||
cycles += other.cycles;
|
cycles += other.cycles;
|
||||||
branches += other.branches;
|
branches += other.branches;
|
||||||
@ -920,6 +925,7 @@ static int kdebug_wait(usize timeout_ms, bool *suc) {
|
|||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
#define EVENT_NAME_MAX 8
|
#define EVENT_NAME_MAX 8
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *alias; /// name for print
|
const char *alias; /// name for print
|
||||||
const char *names[EVENT_NAME_MAX]; /// name from pmc db
|
const char *names[EVENT_NAME_MAX]; /// name from pmc db
|
||||||
|
|||||||
@ -24,10 +24,13 @@
|
|||||||
struct event_count {
|
struct event_count {
|
||||||
std::chrono::duration<double> elapsed;
|
std::chrono::duration<double> elapsed;
|
||||||
std::vector<unsigned long long> event_counts;
|
std::vector<unsigned long long> event_counts;
|
||||||
|
|
||||||
event_count() : elapsed(0), event_counts{0, 0, 0, 0, 0} {}
|
event_count() : elapsed(0), event_counts{0, 0, 0, 0, 0} {}
|
||||||
|
|
||||||
event_count(const std::chrono::duration<double> _elapsed,
|
event_count(const std::chrono::duration<double> _elapsed,
|
||||||
const std::vector<unsigned long long> _event_counts)
|
const std::vector<unsigned long long> _event_counts)
|
||||||
: elapsed(_elapsed), event_counts(_event_counts) {}
|
: elapsed(_elapsed), event_counts(_event_counts) {}
|
||||||
|
|
||||||
event_count(const event_count &other)
|
event_count(const event_count &other)
|
||||||
: elapsed(other.elapsed), event_counts(other.event_counts) {}
|
: elapsed(other.elapsed), event_counts(other.event_counts) {}
|
||||||
|
|
||||||
@ -42,18 +45,23 @@ struct event_count {
|
|||||||
double elapsed_sec() const {
|
double elapsed_sec() const {
|
||||||
return std::chrono::duration<double>(elapsed).count();
|
return std::chrono::duration<double>(elapsed).count();
|
||||||
}
|
}
|
||||||
|
|
||||||
double elapsed_ns() const {
|
double elapsed_ns() const {
|
||||||
return std::chrono::duration<double, std::nano>(elapsed).count();
|
return std::chrono::duration<double, std::nano>(elapsed).count();
|
||||||
}
|
}
|
||||||
|
|
||||||
double cycles() const {
|
double cycles() const {
|
||||||
return static_cast<double>(event_counts[CPU_CYCLES]);
|
return static_cast<double>(event_counts[CPU_CYCLES]);
|
||||||
}
|
}
|
||||||
|
|
||||||
double instructions() const {
|
double instructions() const {
|
||||||
return static_cast<double>(event_counts[INSTRUCTIONS]);
|
return static_cast<double>(event_counts[INSTRUCTIONS]);
|
||||||
}
|
}
|
||||||
|
|
||||||
double branches() const {
|
double branches() const {
|
||||||
return static_cast<double>(event_counts[BRANCHES]);
|
return static_cast<double>(event_counts[BRANCHES]);
|
||||||
}
|
}
|
||||||
|
|
||||||
double missed_branches() const {
|
double missed_branches() const {
|
||||||
return static_cast<double>(event_counts[MISSED_BRANCHES]);
|
return static_cast<double>(event_counts[MISSED_BRANCHES]);
|
||||||
}
|
}
|
||||||
@ -63,6 +71,7 @@ struct event_count {
|
|||||||
this->event_counts = other.event_counts;
|
this->event_counts = other.event_counts;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
event_count operator+(const event_count &other) const {
|
event_count operator+(const event_count &other) const {
|
||||||
return event_count(elapsed + other.elapsed,
|
return event_count(elapsed + other.elapsed,
|
||||||
{
|
{
|
||||||
@ -98,10 +107,15 @@ struct event_aggregate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
double elapsed_sec() const { return total.elapsed_sec() / iterations; }
|
double elapsed_sec() const { return total.elapsed_sec() / iterations; }
|
||||||
|
|
||||||
double elapsed_ns() const { return total.elapsed_ns() / iterations; }
|
double elapsed_ns() const { return total.elapsed_ns() / iterations; }
|
||||||
|
|
||||||
double cycles() const { return total.cycles() / iterations; }
|
double cycles() const { return total.cycles() / iterations; }
|
||||||
|
|
||||||
double instructions() const { return total.instructions() / iterations; }
|
double instructions() const { return total.instructions() / iterations; }
|
||||||
|
|
||||||
double branches() const { return total.branches() / iterations; }
|
double branches() const { return total.branches() / iterations; }
|
||||||
|
|
||||||
double missed_branches() const {
|
double missed_branches() const {
|
||||||
return total.missed_branches() / iterations;
|
return total.missed_branches() / iterations;
|
||||||
}
|
}
|
||||||
@ -113,18 +127,23 @@ struct event_collector {
|
|||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
LinuxEvents<PERF_TYPE_HARDWARE> linux_events;
|
LinuxEvents<PERF_TYPE_HARDWARE> linux_events;
|
||||||
|
|
||||||
event_collector()
|
event_collector()
|
||||||
: linux_events(std::vector<int>{
|
: linux_events(std::vector<int>{
|
||||||
PERF_COUNT_HW_CPU_CYCLES, PERF_COUNT_HW_INSTRUCTIONS,
|
PERF_COUNT_HW_CPU_CYCLES, PERF_COUNT_HW_INSTRUCTIONS,
|
||||||
PERF_COUNT_HW_BRANCH_INSTRUCTIONS, // Retired branch instructions
|
PERF_COUNT_HW_BRANCH_INSTRUCTIONS, // Retired branch instructions
|
||||||
PERF_COUNT_HW_BRANCH_MISSES}) {}
|
PERF_COUNT_HW_BRANCH_MISSES}) {}
|
||||||
|
|
||||||
bool has_events() { return linux_events.is_working(); }
|
bool has_events() { return linux_events.is_working(); }
|
||||||
#elif __APPLE__ && __aarch64__
|
#elif __APPLE__ && __aarch64__
|
||||||
performance_counters diff;
|
performance_counters diff;
|
||||||
|
|
||||||
event_collector() : diff(0) { setup_performance_counters(); }
|
event_collector() : diff(0) { setup_performance_counters(); }
|
||||||
|
|
||||||
bool has_events() { return setup_performance_counters(); }
|
bool has_events() { return setup_performance_counters(); }
|
||||||
#else
|
#else
|
||||||
event_collector() {}
|
event_collector() {}
|
||||||
|
|
||||||
bool has_events() { return false; }
|
bool has_events() { return false; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -138,6 +157,7 @@ struct event_collector {
|
|||||||
#endif
|
#endif
|
||||||
start_clock = std::chrono::steady_clock::now();
|
start_clock = std::chrono::steady_clock::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline event_count &end() {
|
inline event_count &end() {
|
||||||
const auto end_clock = std::chrono::steady_clock::now();
|
const auto end_clock = std::chrono::steady_clock::now();
|
||||||
#if defined(__linux)
|
#if defined(__linux)
|
||||||
|
|||||||
@ -57,10 +57,12 @@ template <uint16_t size> struct stackvec {
|
|||||||
FASTFLOAT_DEBUG_ASSERT(index < length);
|
FASTFLOAT_DEBUG_ASSERT(index < length);
|
||||||
return data[index];
|
return data[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
FASTFLOAT_CONSTEXPR14 const limb &operator[](size_t index) const noexcept {
|
FASTFLOAT_CONSTEXPR14 const limb &operator[](size_t index) const noexcept {
|
||||||
FASTFLOAT_DEBUG_ASSERT(index < length);
|
FASTFLOAT_DEBUG_ASSERT(index < length);
|
||||||
return data[index];
|
return data[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
// index from the end of the container
|
// index from the end of the container
|
||||||
FASTFLOAT_CONSTEXPR14 const limb &rindex(size_t index) const noexcept {
|
FASTFLOAT_CONSTEXPR14 const limb &rindex(size_t index) const noexcept {
|
||||||
FASTFLOAT_DEBUG_ASSERT(index < length);
|
FASTFLOAT_DEBUG_ASSERT(index < length);
|
||||||
@ -72,14 +74,19 @@ template <uint16_t size> struct stackvec {
|
|||||||
FASTFLOAT_CONSTEXPR14 void set_len(size_t len) noexcept {
|
FASTFLOAT_CONSTEXPR14 void set_len(size_t len) noexcept {
|
||||||
length = uint16_t(len);
|
length = uint16_t(len);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr size_t len() const noexcept { return length; }
|
constexpr size_t len() const noexcept { return length; }
|
||||||
|
|
||||||
constexpr bool is_empty() const noexcept { return length == 0; }
|
constexpr bool is_empty() const noexcept { return length == 0; }
|
||||||
|
|
||||||
constexpr size_t capacity() const noexcept { return size; }
|
constexpr size_t capacity() const noexcept { return size; }
|
||||||
|
|
||||||
// append item to vector, without bounds checking
|
// append item to vector, without bounds checking
|
||||||
FASTFLOAT_CONSTEXPR14 void push_unchecked(limb value) noexcept {
|
FASTFLOAT_CONSTEXPR14 void push_unchecked(limb value) noexcept {
|
||||||
data[length] = value;
|
data[length] = value;
|
||||||
length++;
|
length++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// append item to vector, returning if item was added
|
// append item to vector, returning if item was added
|
||||||
FASTFLOAT_CONSTEXPR14 bool try_push(limb value) noexcept {
|
FASTFLOAT_CONSTEXPR14 bool try_push(limb value) noexcept {
|
||||||
if (len() < capacity()) {
|
if (len() < capacity()) {
|
||||||
@ -89,12 +96,14 @@ template <uint16_t size> struct stackvec {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add items to the vector, from a span, without bounds checking
|
// add items to the vector, from a span, without bounds checking
|
||||||
FASTFLOAT_CONSTEXPR20 void extend_unchecked(limb_span s) noexcept {
|
FASTFLOAT_CONSTEXPR20 void extend_unchecked(limb_span s) noexcept {
|
||||||
limb *ptr = data + length;
|
limb *ptr = data + length;
|
||||||
std::copy_n(s.ptr, s.len(), ptr);
|
std::copy_n(s.ptr, s.len(), ptr);
|
||||||
set_len(len() + s.len());
|
set_len(len() + s.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to add items to the vector, returning if items were added
|
// try to add items to the vector, returning if items were added
|
||||||
FASTFLOAT_CONSTEXPR20 bool try_extend(limb_span s) noexcept {
|
FASTFLOAT_CONSTEXPR20 bool try_extend(limb_span s) noexcept {
|
||||||
if (len() + s.len() <= capacity()) {
|
if (len() + s.len() <= capacity()) {
|
||||||
@ -104,6 +113,7 @@ template <uint16_t size> struct stackvec {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// resize the vector, without bounds checking
|
// resize the vector, without bounds checking
|
||||||
// if the new size is longer than the vector, assign value to each
|
// if the new size is longer than the vector, assign value to each
|
||||||
// appended item.
|
// appended item.
|
||||||
@ -119,6 +129,7 @@ template <uint16_t size> struct stackvec {
|
|||||||
set_len(new_len);
|
set_len(new_len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to resize the vector, returning if the vector was resized.
|
// try to resize the vector, returning if the vector was resized.
|
||||||
FASTFLOAT_CONSTEXPR20 bool try_resize(size_t new_len, limb value) noexcept {
|
FASTFLOAT_CONSTEXPR20 bool try_resize(size_t new_len, limb value) noexcept {
|
||||||
if (new_len > capacity()) {
|
if (new_len > capacity()) {
|
||||||
@ -128,6 +139,7 @@ template <uint16_t size> struct stackvec {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if any limbs are non-zero after the given index.
|
// check if any limbs are non-zero after the given index.
|
||||||
// this needs to be done in reverse order, since the index
|
// this needs to be done in reverse order, since the index
|
||||||
// is relative to the most significant limbs.
|
// is relative to the most significant limbs.
|
||||||
@ -140,6 +152,7 @@ template <uint16_t size> struct stackvec {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// normalize the big integer, so most-significant zero limbs are removed.
|
// normalize the big integer, so most-significant zero limbs are removed.
|
||||||
FASTFLOAT_CONSTEXPR14 void normalize() noexcept {
|
FASTFLOAT_CONSTEXPR14 void normalize() noexcept {
|
||||||
while (len() > 0 && rindex(0) == 0) {
|
while (len() > 0 && rindex(0) == 0) {
|
||||||
@ -423,6 +436,7 @@ struct bigint : pow5_tables<> {
|
|||||||
stackvec<bigint_limbs> vec;
|
stackvec<bigint_limbs> vec;
|
||||||
|
|
||||||
FASTFLOAT_CONSTEXPR20 bigint() : vec() {}
|
FASTFLOAT_CONSTEXPR20 bigint() : vec() {}
|
||||||
|
|
||||||
bigint(bigint const &) = delete;
|
bigint(bigint const &) = delete;
|
||||||
bigint &operator=(bigint const &) = delete;
|
bigint &operator=(bigint const &) = delete;
|
||||||
bigint(bigint &&) = delete;
|
bigint(bigint &&) = delete;
|
||||||
|
|||||||
@ -62,7 +62,7 @@ scientific_exponent(parsed_number_string_t<UC> &num) noexcept {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa
|
||||||
to_extended(T value) noexcept {
|
to_extended(T value) noexcept {
|
||||||
using equiv_uint = typename binary_format<T>::equiv_uint;
|
using equiv_uint = equiv_uint_t<T>;
|
||||||
constexpr equiv_uint exponent_mask = binary_format<T>::exponent_mask();
|
constexpr equiv_uint exponent_mask = binary_format<T>::exponent_mask();
|
||||||
constexpr equiv_uint mantissa_mask = binary_format<T>::mantissa_mask();
|
constexpr equiv_uint mantissa_mask = binary_format<T>::mantissa_mask();
|
||||||
constexpr equiv_uint hidden_bit_mask = binary_format<T>::hidden_bit_mask();
|
constexpr equiv_uint hidden_bit_mask = binary_format<T>::hidden_bit_mask();
|
||||||
@ -170,6 +170,7 @@ round_down(adjusted_mantissa &am, int32_t shift) noexcept {
|
|||||||
}
|
}
|
||||||
am.power2 += shift;
|
am.power2 += shift;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename UC>
|
template <typename UC>
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void
|
||||||
skip_zeros(UC const *&first, UC const *last) noexcept {
|
skip_zeros(UC const *&first, UC const *last) noexcept {
|
||||||
@ -213,6 +214,7 @@ is_truncated(UC const *first, UC const *last) noexcept {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename UC>
|
template <typename UC>
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool
|
||||||
is_truncated(span<UC const> s) noexcept {
|
is_truncated(span<UC const> s) noexcept {
|
||||||
|
|||||||
@ -54,5 +54,6 @@ FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
|||||||
from_chars(UC const *first, UC const *last, T &value, int base = 10) noexcept;
|
from_chars(UC const *first, UC const *last, T &value, int base = 10) noexcept;
|
||||||
|
|
||||||
} // namespace fast_float
|
} // namespace fast_float
|
||||||
|
|
||||||
#include "parse_number.h"
|
#include "parse_number.h"
|
||||||
#endif // FASTFLOAT_FAST_FLOAT_H
|
#endif // FASTFLOAT_FAST_FLOAT_H
|
||||||
|
|||||||
@ -58,6 +58,7 @@ template <typename UC> struct from_chars_result_t {
|
|||||||
UC const *ptr;
|
UC const *ptr;
|
||||||
std::errc ec;
|
std::errc ec;
|
||||||
};
|
};
|
||||||
|
|
||||||
using from_chars_result = from_chars_result_t<char>;
|
using from_chars_result = from_chars_result_t<char>;
|
||||||
|
|
||||||
template <typename UC> struct parse_options_t {
|
template <typename UC> struct parse_options_t {
|
||||||
@ -72,6 +73,7 @@ template <typename UC> struct parse_options_t {
|
|||||||
/** The base used for integers */
|
/** The base used for integers */
|
||||||
int base;
|
int base;
|
||||||
};
|
};
|
||||||
|
|
||||||
using parse_options = parse_options_t<char>;
|
using parse_options = parse_options_t<char>;
|
||||||
|
|
||||||
} // namespace fast_float
|
} // namespace fast_float
|
||||||
@ -221,15 +223,23 @@ template <typename T>
|
|||||||
struct is_supported_float_type
|
struct is_supported_float_type
|
||||||
: std::integral_constant<bool, std::is_same<T, float>::value ||
|
: std::integral_constant<bool, std::is_same<T, float>::value ||
|
||||||
std::is_same<T, double>::value
|
std::is_same<T, double>::value
|
||||||
#if __STDCPP_FLOAT32_T__
|
#ifdef __STDCPP_FLOAT32_T__
|
||||||
|| std::is_same<T, std::float32_t>::value
|
|| std::is_same<T, std::float32_t>::value
|
||||||
#endif
|
#endif
|
||||||
#if __STDCPP_FLOAT64_T__
|
#ifdef __STDCPP_FLOAT64_T__
|
||||||
|| std::is_same<T, std::float64_t>::value
|
|| std::is_same<T, std::float64_t>::value
|
||||||
#endif
|
#endif
|
||||||
> {
|
> {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using equiv_uint_t = typename std::conditional<
|
||||||
|
sizeof(T) == 1, uint8_t,
|
||||||
|
typename std::conditional<
|
||||||
|
sizeof(T) == 2, uint16_t,
|
||||||
|
typename std::conditional<sizeof(T) == 4, uint32_t,
|
||||||
|
uint64_t>::type>::type>::type;
|
||||||
|
|
||||||
template <typename T> struct is_supported_integer_type : std::is_integral<T> {};
|
template <typename T> struct is_supported_integer_type : std::is_integral<T> {};
|
||||||
|
|
||||||
template <typename UC>
|
template <typename UC>
|
||||||
@ -266,7 +276,9 @@ fastfloat_strncasecmp(UC const *actual_mixedcase, UC const *expected_lowercase,
|
|||||||
template <typename T> struct span {
|
template <typename T> struct span {
|
||||||
T const *ptr;
|
T const *ptr;
|
||||||
size_t length;
|
size_t length;
|
||||||
|
|
||||||
constexpr span(T const *_ptr, size_t _length) : ptr(_ptr), length(_length) {}
|
constexpr span(T const *_ptr, size_t _length) : ptr(_ptr), length(_length) {}
|
||||||
|
|
||||||
constexpr span() : ptr(nullptr), length(0) {}
|
constexpr span() : ptr(nullptr), length(0) {}
|
||||||
|
|
||||||
constexpr size_t len() const noexcept { return length; }
|
constexpr size_t len() const noexcept { return length; }
|
||||||
@ -280,7 +292,9 @@ template <typename T> struct span {
|
|||||||
struct value128 {
|
struct value128 {
|
||||||
uint64_t low;
|
uint64_t low;
|
||||||
uint64_t high;
|
uint64_t high;
|
||||||
|
|
||||||
constexpr value128(uint64_t _low, uint64_t _high) : low(_low), high(_high) {}
|
constexpr value128(uint64_t _low, uint64_t _high) : low(_low), high(_high) {}
|
||||||
|
|
||||||
constexpr value128() : low(0), high(0) {}
|
constexpr value128() : low(0), high(0) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -396,9 +410,11 @@ struct adjusted_mantissa {
|
|||||||
uint64_t mantissa{0};
|
uint64_t mantissa{0};
|
||||||
int32_t power2{0}; // a negative value indicates an invalid result
|
int32_t power2{0}; // a negative value indicates an invalid result
|
||||||
adjusted_mantissa() = default;
|
adjusted_mantissa() = default;
|
||||||
|
|
||||||
constexpr bool operator==(adjusted_mantissa const &o) const {
|
constexpr bool operator==(adjusted_mantissa const &o) const {
|
||||||
return mantissa == o.mantissa && power2 == o.power2;
|
return mantissa == o.mantissa && power2 == o.power2;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bool operator!=(adjusted_mantissa const &o) const {
|
constexpr bool operator!=(adjusted_mantissa const &o) const {
|
||||||
return mantissa != o.mantissa || power2 != o.power2;
|
return mantissa != o.mantissa || power2 != o.power2;
|
||||||
}
|
}
|
||||||
@ -413,8 +429,7 @@ constexpr uint64_t constant_55555 = 5 * 5 * 5 * 5 * 5;
|
|||||||
template <typename T, typename U = void> struct binary_format_lookup_tables;
|
template <typename T, typename U = void> struct binary_format_lookup_tables;
|
||||||
|
|
||||||
template <typename T> struct binary_format : binary_format_lookup_tables<T> {
|
template <typename T> struct binary_format : binary_format_lookup_tables<T> {
|
||||||
using equiv_uint =
|
using equiv_uint = equiv_uint_t<T>;
|
||||||
typename std::conditional<sizeof(T) == 4, uint32_t, uint64_t>::type;
|
|
||||||
|
|
||||||
static inline constexpr int mantissa_explicit_bits();
|
static inline constexpr int mantissa_explicit_bits();
|
||||||
static inline constexpr int minimum_exponent();
|
static inline constexpr int minimum_exponent();
|
||||||
@ -542,6 +557,7 @@ template <>
|
|||||||
inline constexpr int binary_format<double>::mantissa_explicit_bits() {
|
inline constexpr int binary_format<double>::mantissa_explicit_bits() {
|
||||||
return 52;
|
return 52;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline constexpr int binary_format<float>::mantissa_explicit_bits() {
|
inline constexpr int binary_format<float>::mantissa_explicit_bits() {
|
||||||
return 23;
|
return 23;
|
||||||
@ -570,6 +586,7 @@ inline constexpr int binary_format<float>::min_exponent_round_to_even() {
|
|||||||
template <> inline constexpr int binary_format<double>::minimum_exponent() {
|
template <> inline constexpr int binary_format<double>::minimum_exponent() {
|
||||||
return -1023;
|
return -1023;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <> inline constexpr int binary_format<float>::minimum_exponent() {
|
template <> inline constexpr int binary_format<float>::minimum_exponent() {
|
||||||
return -127;
|
return -127;
|
||||||
}
|
}
|
||||||
@ -577,6 +594,7 @@ template <> inline constexpr int binary_format<float>::minimum_exponent() {
|
|||||||
template <> inline constexpr int binary_format<double>::infinite_power() {
|
template <> inline constexpr int binary_format<double>::infinite_power() {
|
||||||
return 0x7FF;
|
return 0x7FF;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <> inline constexpr int binary_format<float>::infinite_power() {
|
template <> inline constexpr int binary_format<float>::infinite_power() {
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
}
|
}
|
||||||
@ -584,6 +602,7 @@ template <> inline constexpr int binary_format<float>::infinite_power() {
|
|||||||
template <> inline constexpr int binary_format<double>::sign_index() {
|
template <> inline constexpr int binary_format<double>::sign_index() {
|
||||||
return 63;
|
return 63;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <> inline constexpr int binary_format<float>::sign_index() {
|
template <> inline constexpr int binary_format<float>::sign_index() {
|
||||||
return 31;
|
return 31;
|
||||||
}
|
}
|
||||||
@ -592,6 +611,7 @@ template <>
|
|||||||
inline constexpr int binary_format<double>::max_exponent_fast_path() {
|
inline constexpr int binary_format<double>::max_exponent_fast_path() {
|
||||||
return 22;
|
return 22;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline constexpr int binary_format<float>::max_exponent_fast_path() {
|
inline constexpr int binary_format<float>::max_exponent_fast_path() {
|
||||||
return 10;
|
return 10;
|
||||||
@ -601,6 +621,7 @@ template <>
|
|||||||
inline constexpr uint64_t binary_format<double>::max_mantissa_fast_path() {
|
inline constexpr uint64_t binary_format<double>::max_mantissa_fast_path() {
|
||||||
return uint64_t(2) << mantissa_explicit_bits();
|
return uint64_t(2) << mantissa_explicit_bits();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline constexpr uint64_t
|
inline constexpr uint64_t
|
||||||
binary_format<double>::max_mantissa_fast_path(int64_t power) {
|
binary_format<double>::max_mantissa_fast_path(int64_t power) {
|
||||||
@ -610,10 +631,12 @@ binary_format<double>::max_mantissa_fast_path(int64_t power) {
|
|||||||
// Work around clang bug https://godbolt.org/z/zedh7rrhc
|
// Work around clang bug https://godbolt.org/z/zedh7rrhc
|
||||||
return (void)max_mantissa[0], max_mantissa[power];
|
return (void)max_mantissa[0], max_mantissa[power];
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline constexpr uint64_t binary_format<float>::max_mantissa_fast_path() {
|
inline constexpr uint64_t binary_format<float>::max_mantissa_fast_path() {
|
||||||
return uint64_t(2) << mantissa_explicit_bits();
|
return uint64_t(2) << mantissa_explicit_bits();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline constexpr uint64_t
|
inline constexpr uint64_t
|
||||||
binary_format<float>::max_mantissa_fast_path(int64_t power) {
|
binary_format<float>::max_mantissa_fast_path(int64_t power) {
|
||||||
@ -630,6 +653,7 @@ binary_format<double>::exact_power_of_ten(int64_t power) {
|
|||||||
// Work around clang bug https://godbolt.org/z/zedh7rrhc
|
// Work around clang bug https://godbolt.org/z/zedh7rrhc
|
||||||
return (void)powers_of_ten[0], powers_of_ten[power];
|
return (void)powers_of_ten[0], powers_of_ten[power];
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline constexpr float binary_format<float>::exact_power_of_ten(int64_t power) {
|
inline constexpr float binary_format<float>::exact_power_of_ten(int64_t power) {
|
||||||
// Work around clang bug https://godbolt.org/z/zedh7rrhc
|
// Work around clang bug https://godbolt.org/z/zedh7rrhc
|
||||||
@ -639,6 +663,7 @@ inline constexpr float binary_format<float>::exact_power_of_ten(int64_t power) {
|
|||||||
template <> inline constexpr int binary_format<double>::largest_power_of_ten() {
|
template <> inline constexpr int binary_format<double>::largest_power_of_ten() {
|
||||||
return 308;
|
return 308;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <> inline constexpr int binary_format<float>::largest_power_of_ten() {
|
template <> inline constexpr int binary_format<float>::largest_power_of_ten() {
|
||||||
return 38;
|
return 38;
|
||||||
}
|
}
|
||||||
@ -647,6 +672,7 @@ template <>
|
|||||||
inline constexpr int binary_format<double>::smallest_power_of_ten() {
|
inline constexpr int binary_format<double>::smallest_power_of_ten() {
|
||||||
return -342;
|
return -342;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <> inline constexpr int binary_format<float>::smallest_power_of_ten() {
|
template <> inline constexpr int binary_format<float>::smallest_power_of_ten() {
|
||||||
return -64;
|
return -64;
|
||||||
}
|
}
|
||||||
@ -654,6 +680,7 @@ template <> inline constexpr int binary_format<float>::smallest_power_of_ten() {
|
|||||||
template <> inline constexpr size_t binary_format<double>::max_digits() {
|
template <> inline constexpr size_t binary_format<double>::max_digits() {
|
||||||
return 769;
|
return 769;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <> inline constexpr size_t binary_format<float>::max_digits() {
|
template <> inline constexpr size_t binary_format<float>::max_digits() {
|
||||||
return 114;
|
return 114;
|
||||||
}
|
}
|
||||||
@ -663,6 +690,7 @@ inline constexpr binary_format<float>::equiv_uint
|
|||||||
binary_format<float>::exponent_mask() {
|
binary_format<float>::exponent_mask() {
|
||||||
return 0x7F800000;
|
return 0x7F800000;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline constexpr binary_format<double>::equiv_uint
|
inline constexpr binary_format<double>::equiv_uint
|
||||||
binary_format<double>::exponent_mask() {
|
binary_format<double>::exponent_mask() {
|
||||||
@ -674,6 +702,7 @@ inline constexpr binary_format<float>::equiv_uint
|
|||||||
binary_format<float>::mantissa_mask() {
|
binary_format<float>::mantissa_mask() {
|
||||||
return 0x007FFFFF;
|
return 0x007FFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline constexpr binary_format<double>::equiv_uint
|
inline constexpr binary_format<double>::equiv_uint
|
||||||
binary_format<double>::mantissa_mask() {
|
binary_format<double>::mantissa_mask() {
|
||||||
@ -685,6 +714,7 @@ inline constexpr binary_format<float>::equiv_uint
|
|||||||
binary_format<float>::hidden_bit_mask() {
|
binary_format<float>::hidden_bit_mask() {
|
||||||
return 0x00800000;
|
return 0x00800000;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline constexpr binary_format<double>::equiv_uint
|
inline constexpr binary_format<double>::equiv_uint
|
||||||
binary_format<double>::hidden_bit_mask() {
|
binary_format<double>::hidden_bit_mask() {
|
||||||
@ -694,11 +724,10 @@ binary_format<double>::hidden_bit_mask() {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void
|
||||||
to_float(bool negative, adjusted_mantissa am, T &value) {
|
to_float(bool negative, adjusted_mantissa am, T &value) {
|
||||||
using fastfloat_uint = typename binary_format<T>::equiv_uint;
|
using equiv_uint = equiv_uint_t<T>;
|
||||||
fastfloat_uint word = (fastfloat_uint)am.mantissa;
|
equiv_uint word = equiv_uint(am.mantissa);
|
||||||
word |= fastfloat_uint(am.power2)
|
word |= equiv_uint(am.power2) << binary_format<T>::mantissa_explicit_bits();
|
||||||
<< binary_format<T>::mantissa_explicit_bits();
|
word |= equiv_uint(negative) << binary_format<T>::sign_index();
|
||||||
word |= fastfloat_uint(negative) << binary_format<T>::sign_index();
|
|
||||||
#if FASTFLOAT_HAS_BIT_CAST
|
#if FASTFLOAT_HAS_BIT_CAST
|
||||||
value = std::bit_cast<T>(word);
|
value = std::bit_cast<T>(word);
|
||||||
#else
|
#else
|
||||||
@ -740,16 +769,21 @@ template <typename UC> static constexpr uint64_t int_cmp_zeros() {
|
|||||||
uint64_t(UC('0')) << 16 | UC('0'))
|
uint64_t(UC('0')) << 16 | UC('0'))
|
||||||
: (uint64_t(UC('0')) << 32 | UC('0'));
|
: (uint64_t(UC('0')) << 32 | UC('0'));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename UC> static constexpr int int_cmp_len() {
|
template <typename UC> static constexpr int int_cmp_len() {
|
||||||
return sizeof(uint64_t) / sizeof(UC);
|
return sizeof(uint64_t) / sizeof(UC);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename UC> constexpr UC const *str_const_nan();
|
template <typename UC> constexpr UC const *str_const_nan();
|
||||||
|
|
||||||
template <> constexpr char const *str_const_nan<char>() { return "nan"; }
|
template <> constexpr char const *str_const_nan<char>() { return "nan"; }
|
||||||
|
|
||||||
template <> constexpr wchar_t const *str_const_nan<wchar_t>() { return L"nan"; }
|
template <> constexpr wchar_t const *str_const_nan<wchar_t>() { return L"nan"; }
|
||||||
|
|
||||||
template <> constexpr char16_t const *str_const_nan<char16_t>() {
|
template <> constexpr char16_t const *str_const_nan<char16_t>() {
|
||||||
return u"nan";
|
return u"nan";
|
||||||
}
|
}
|
||||||
|
|
||||||
template <> constexpr char32_t const *str_const_nan<char32_t>() {
|
template <> constexpr char32_t const *str_const_nan<char32_t>() {
|
||||||
return U"nan";
|
return U"nan";
|
||||||
}
|
}
|
||||||
@ -760,13 +794,17 @@ template <> constexpr char8_t const *str_const_nan<char8_t>() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename UC> constexpr UC const *str_const_inf();
|
template <typename UC> constexpr UC const *str_const_inf();
|
||||||
|
|
||||||
template <> constexpr char const *str_const_inf<char>() { return "infinity"; }
|
template <> constexpr char const *str_const_inf<char>() { return "infinity"; }
|
||||||
|
|
||||||
template <> constexpr wchar_t const *str_const_inf<wchar_t>() {
|
template <> constexpr wchar_t const *str_const_inf<wchar_t>() {
|
||||||
return L"infinity";
|
return L"infinity";
|
||||||
}
|
}
|
||||||
|
|
||||||
template <> constexpr char16_t const *str_const_inf<char16_t>() {
|
template <> constexpr char16_t const *str_const_inf<char16_t>() {
|
||||||
return u"infinity";
|
return u"infinity";
|
||||||
}
|
}
|
||||||
|
|
||||||
template <> constexpr char32_t const *str_const_inf<char32_t>() {
|
template <> constexpr char32_t const *str_const_inf<char32_t>() {
|
||||||
return U"infinity";
|
return U"infinity";
|
||||||
}
|
}
|
||||||
@ -841,6 +879,21 @@ fastfloat_really_inline constexpr uint64_t min_safe_u64(int base) {
|
|||||||
return int_luts<>::min_safe_u64[base - 2];
|
return int_luts<>::min_safe_u64[base - 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static_assert(std::is_same<equiv_uint_t<double>, uint64_t>::value,
|
||||||
|
"equiv_uint should be uint64_t for double");
|
||||||
|
static_assert(std::is_same<equiv_uint_t<float>, uint32_t>::value,
|
||||||
|
"equiv_uint should be uint32_t for float");
|
||||||
|
|
||||||
|
#ifdef __STDCPP_FLOAT64_T__
|
||||||
|
static_assert(std::is_same<equiv_uint_t<std::float64_t>, uint64_t>::value,
|
||||||
|
"equiv_uint should be uint64_t for std::float64_t");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __STDCPP_FLOAT32_T__
|
||||||
|
static_assert(std::is_same<equiv_uint_t<std::float32_t>, uint32_t>::value,
|
||||||
|
"equiv_uint should be uint32_t for std::float32_t");
|
||||||
|
#endif
|
||||||
|
|
||||||
constexpr chars_format operator~(chars_format rhs) noexcept {
|
constexpr chars_format operator~(chars_format rhs) noexcept {
|
||||||
using int_type = std::underlying_type<chars_format>::type;
|
using int_type = std::underlying_type<chars_format>::type;
|
||||||
return static_cast<chars_format>(~static_cast<int_type>(rhs));
|
return static_cast<chars_format>(~static_cast<int_type>(rhs));
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
|
|
||||||
namespace fast_float {
|
namespace fast_float {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@ -145,7 +146,7 @@ template <typename T> struct from_chars_caller {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#if __STDCPP_FLOAT32_T__ == 1
|
#ifdef __STDCPP_FLOAT32_T__
|
||||||
template <> struct from_chars_caller<std::float32_t> {
|
template <> struct from_chars_caller<std::float32_t> {
|
||||||
template <typename UC>
|
template <typename UC>
|
||||||
FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC>
|
FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC>
|
||||||
@ -162,7 +163,7 @@ template <> struct from_chars_caller<std::float32_t> {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if __STDCPP_FLOAT64_T__ == 1
|
#ifdef __STDCPP_FLOAT64_T__
|
||||||
template <> struct from_chars_caller<std::float64_t> {
|
template <> struct from_chars_caller<std::float64_t> {
|
||||||
template <typename UC>
|
template <typename UC>
|
||||||
FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC>
|
FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC>
|
||||||
|
|||||||
@ -729,8 +729,7 @@ constexpr void check_basic_test_result(stringtype str, result_type result,
|
|||||||
auto copysign = [](double x, double y) -> double {
|
auto copysign = [](double x, double y) -> double {
|
||||||
#if FASTFLOAT_HAS_BIT_CAST
|
#if FASTFLOAT_HAS_BIT_CAST
|
||||||
if (fast_float::cpp20_and_in_constexpr()) {
|
if (fast_float::cpp20_and_in_constexpr()) {
|
||||||
using equiv_int = std::make_signed_t<
|
using equiv_int = std::make_signed_t<fast_float::equiv_uint_t<double>>;
|
||||||
typename fast_float::binary_format<double>::equiv_uint>;
|
|
||||||
auto const i = std::bit_cast<equiv_int>(y);
|
auto const i = std::bit_cast<equiv_int>(y);
|
||||||
if (i < 0) {
|
if (i < 0) {
|
||||||
return -x;
|
return -x;
|
||||||
|
|||||||
@ -1,2 +1,3 @@
|
|||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
void foo() {}
|
void foo() {}
|
||||||
@ -1,2 +1,3 @@
|
|||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
int main() { return 0; }
|
int main() { return 0; }
|
||||||
@ -14,6 +14,7 @@
|
|||||||
// gcc.
|
// gcc.
|
||||||
#include <locale>
|
#include <locale>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
// workaround for CYGWIN
|
// workaround for CYGWIN
|
||||||
double cygwin_strtod_l(char const *start, char **end) {
|
double cygwin_strtod_l(char const *start, char **end) {
|
||||||
double d;
|
double d;
|
||||||
@ -31,6 +32,7 @@ double cygwin_strtod_l(char const *start, char **end) {
|
|||||||
*end = const_cast<char *>(start) + nread;
|
*end = const_cast<char *>(start) + nread;
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
float cygwin_strtof_l(char const *start, char **end) {
|
float cygwin_strtof_l(char const *start, char **end) {
|
||||||
float d;
|
float d;
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
@ -164,6 +166,7 @@ inline void Assert(bool Assertion) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || \
|
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || \
|
||||||
defined(sun) || defined(__sun)
|
defined(sun) || defined(__sun)
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
int main() {
|
int main() {
|
||||||
// Write some testcases for the parsing of floating point numbers in the
|
// Write some testcases for the parsing of floating point numbers in the
|
||||||
// float32_t type. We use the from_chars function defined in this library.
|
// float32_t type. We use the from_chars function defined in this library.
|
||||||
#if __STDCPP_FLOAT32_T__
|
#ifdef __STDCPP_FLOAT32_T__
|
||||||
std::vector<std::float32_t> const float32_test_expected{
|
std::vector<std::float32_t> const float32_test_expected{
|
||||||
123.456f, -78.9f, 0.0001f, 3.40282e+038f};
|
123.456f, -78.9f, 0.0001f, 3.40282e+038f};
|
||||||
std::vector<std::string_view> const float32_test{"123.456", "-78.9", "0.0001",
|
std::vector<std::string_view> const float32_test{"123.456", "-78.9", "0.0001",
|
||||||
@ -37,7 +37,7 @@ int main() {
|
|||||||
std::cout << "No std::float32_t type available." << std::endl;
|
std::cout << "No std::float32_t type available." << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if __STDCPP_FLOAT64_T__
|
#ifdef __STDCPP_FLOAT64_T__
|
||||||
// Test cases for std::float64_t
|
// Test cases for std::float64_t
|
||||||
std::vector<std::float64_t> const float64_test_expected{
|
std::vector<std::float64_t> const float64_test_expected{
|
||||||
1.23e4, -5.67e-8, 1.7976931348623157e+308, -1.7976931348623157e+308};
|
1.23e4, -5.67e-8, 1.7976931348623157e+308, -1.7976931348623157e+308};
|
||||||
|
|||||||
@ -54,6 +54,7 @@ struct ExpectedResult {
|
|||||||
double value;
|
double value;
|
||||||
std::string junk_chars;
|
std::string junk_chars;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AcceptedValue {
|
struct AcceptedValue {
|
||||||
std::string input;
|
std::string input;
|
||||||
ExpectedResult expected;
|
ExpectedResult expected;
|
||||||
@ -63,6 +64,7 @@ struct RejectReason {
|
|||||||
fast_float::parse_error error;
|
fast_float::parse_error error;
|
||||||
intptr_t location_offset;
|
intptr_t location_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RejectedValue {
|
struct RejectedValue {
|
||||||
std::string input;
|
std::string input;
|
||||||
RejectReason reason;
|
RejectReason reason;
|
||||||
|
|||||||
@ -15,6 +15,7 @@
|
|||||||
// always use this fallback because we cannot rely on it behaving as normal
|
// always use this fallback because we cannot rely on it behaving as normal
|
||||||
// gcc.
|
// gcc.
|
||||||
#include <locale>
|
#include <locale>
|
||||||
|
|
||||||
// workaround for CYGWIN
|
// workaround for CYGWIN
|
||||||
double cygwin_strtod_l(char const *start, char **end) {
|
double cygwin_strtod_l(char const *start, char **end) {
|
||||||
double d;
|
double d;
|
||||||
@ -32,6 +33,7 @@ double cygwin_strtod_l(char const *start, char **end) {
|
|||||||
*end = const_cast<char *>(start) + nread;
|
*end = const_cast<char *>(start) + nread;
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
float cygwin_strtof_l(char const *start, char **end) {
|
float cygwin_strtof_l(char const *start, char **end) {
|
||||||
float d;
|
float d;
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|||||||
@ -14,6 +14,7 @@
|
|||||||
// gcc.
|
// gcc.
|
||||||
#include <locale>
|
#include <locale>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
// workaround for CYGWIN
|
// workaround for CYGWIN
|
||||||
double cygwin_strtod_l(char const *start, char **end) {
|
double cygwin_strtod_l(char const *start, char **end) {
|
||||||
double d;
|
double d;
|
||||||
@ -31,6 +32,7 @@ double cygwin_strtod_l(char const *start, char **end) {
|
|||||||
*end = const_cast<char *>(start) + nread;
|
*end = const_cast<char *>(start) + nread;
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
float cygwin_strtof_l(char const *start, char **end) {
|
float cygwin_strtof_l(char const *start, char **end) {
|
||||||
float d;
|
float d;
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
@ -53,6 +55,7 @@ class RandomEngine {
|
|||||||
public:
|
public:
|
||||||
RandomEngine() = delete;
|
RandomEngine() = delete;
|
||||||
RandomEngine(uint64_t new_seed) : wyhash64_x_(new_seed){};
|
RandomEngine(uint64_t new_seed) : wyhash64_x_(new_seed){};
|
||||||
|
|
||||||
uint64_t next() {
|
uint64_t next() {
|
||||||
// Adapted from https://github.com/wangyi-fudan/wyhash/blob/master/wyhash.h
|
// Adapted from https://github.com/wangyi-fudan/wyhash/blob/master/wyhash.h
|
||||||
// Inspired from
|
// Inspired from
|
||||||
@ -65,9 +68,13 @@ public:
|
|||||||
uint64_t m2 = (tmp.high) ^ tmp.low;
|
uint64_t m2 = (tmp.high) ^ tmp.low;
|
||||||
return m2;
|
return m2;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool next_bool() { return (next() & 1) == 1; }
|
bool next_bool() { return (next() & 1) == 1; }
|
||||||
|
|
||||||
int next_int() { return static_cast<int>(next()); }
|
int next_int() { return static_cast<int>(next()); }
|
||||||
|
|
||||||
char next_char() { return static_cast<char>(next()); }
|
char next_char() { return static_cast<char>(next()); }
|
||||||
|
|
||||||
double next_double() { return static_cast<double>(next()); }
|
double next_double() { return static_cast<double>(next()); }
|
||||||
|
|
||||||
int next_ranged_int(int min, int max) { // min and max are included
|
int next_ranged_int(int min, int max) { // min and max are included
|
||||||
@ -90,6 +97,7 @@ public:
|
|||||||
}
|
}
|
||||||
return int(m.high) + min;
|
return int(m.high) + min;
|
||||||
}
|
}
|
||||||
|
|
||||||
int next_digit() { return next_ranged_int(0, 9); }
|
int next_digit() { return next_ranged_int(0, 9); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@ -14,6 +14,7 @@
|
|||||||
// gcc.
|
// gcc.
|
||||||
#include <locale>
|
#include <locale>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
// workaround for CYGWIN
|
// workaround for CYGWIN
|
||||||
double cygwin_strtod_l(char const *start, char **end) {
|
double cygwin_strtod_l(char const *start, char **end) {
|
||||||
double d;
|
double d;
|
||||||
@ -31,6 +32,7 @@ double cygwin_strtod_l(char const *start, char **end) {
|
|||||||
*end = const_cast<char *>(start) + nread;
|
*end = const_cast<char *>(start) + nread;
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
float cygwin_strtof_l(char const *start, char **end) {
|
float cygwin_strtof_l(char const *start, char **end) {
|
||||||
float d;
|
float d;
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
@ -53,6 +55,7 @@ class RandomEngine {
|
|||||||
public:
|
public:
|
||||||
RandomEngine() = delete;
|
RandomEngine() = delete;
|
||||||
RandomEngine(uint64_t new_seed) : wyhash64_x_(new_seed){};
|
RandomEngine(uint64_t new_seed) : wyhash64_x_(new_seed){};
|
||||||
|
|
||||||
uint64_t next() {
|
uint64_t next() {
|
||||||
// Adapted from https://github.com/wangyi-fudan/wyhash/blob/master/wyhash.h
|
// Adapted from https://github.com/wangyi-fudan/wyhash/blob/master/wyhash.h
|
||||||
// Inspired from
|
// Inspired from
|
||||||
@ -65,9 +68,13 @@ public:
|
|||||||
uint64_t m2 = (tmp.high) ^ tmp.low;
|
uint64_t m2 = (tmp.high) ^ tmp.low;
|
||||||
return m2;
|
return m2;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool next_bool() { return (next() & 1) == 1; }
|
bool next_bool() { return (next() & 1) == 1; }
|
||||||
|
|
||||||
int next_int() { return static_cast<int>(next()); }
|
int next_int() { return static_cast<int>(next()); }
|
||||||
|
|
||||||
char next_char() { return static_cast<char>(next()); }
|
char next_char() { return static_cast<char>(next()); }
|
||||||
|
|
||||||
double next_double() { return static_cast<double>(next()); }
|
double next_double() { return static_cast<double>(next()); }
|
||||||
|
|
||||||
int next_ranged_int(int min, int max) { // min and max are included
|
int next_ranged_int(int min, int max) { // min and max are included
|
||||||
@ -90,6 +97,7 @@ public:
|
|||||||
}
|
}
|
||||||
return int(m.high) + min;
|
return int(m.high) + min;
|
||||||
}
|
}
|
||||||
|
|
||||||
int next_digit() { return next_ranged_int(0, 9); }
|
int next_digit() { return next_ranged_int(0, 9); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@ -16,6 +16,7 @@
|
|||||||
// gcc.
|
// gcc.
|
||||||
#include <locale>
|
#include <locale>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
// workaround for CYGWIN
|
// workaround for CYGWIN
|
||||||
double cygwin_strtod_l(char const *start, char **end) {
|
double cygwin_strtod_l(char const *start, char **end) {
|
||||||
double d;
|
double d;
|
||||||
@ -33,6 +34,7 @@ double cygwin_strtod_l(char const *start, char **end) {
|
|||||||
*end = const_cast<char *>(start) + nread;
|
*end = const_cast<char *>(start) + nread;
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
float cygwin_strtof_l(char const *start, char **end) {
|
float cygwin_strtof_l(char const *start, char **end) {
|
||||||
float d;
|
float d;
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user