mirror of
https://github.com/fastfloat/fast_float.git
synced 2025-12-07 01:06:48 +08:00
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f8c573d741 | ||
|
|
9d78a01ff7 | ||
|
|
409d6215b4 | ||
|
|
7b21183a93 | ||
|
|
8ac72791a9 | ||
|
|
e77e2bca7e | ||
|
|
24fa687d45 | ||
|
|
88f6c5e367 | ||
|
|
83a4f696d7 | ||
|
|
1ea4d2563e | ||
|
|
7262d9454e | ||
|
|
23f16adad4 | ||
|
|
fd98fd6689 | ||
|
|
197c0ffca7 | ||
|
|
e9438e64ba | ||
|
|
7abb574ffc | ||
|
|
04e8e545d8 | ||
|
|
e4b949e55b | ||
|
|
01e505797b | ||
|
|
13345cab65 |
4
.github/workflows/cifuzz.yml
vendored
4
.github/workflows/cifuzz.yml
vendored
@ -20,14 +20,14 @@ jobs:
|
|||||||
fuzz-seconds: 300
|
fuzz-seconds: 300
|
||||||
output-sarif: true
|
output-sarif: true
|
||||||
- name: Upload Crash
|
- name: Upload Crash
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v5
|
||||||
if: failure() && steps.build.outcome == 'success'
|
if: failure() && steps.build.outcome == 'success'
|
||||||
with:
|
with:
|
||||||
name: artifacts
|
name: artifacts
|
||||||
path: ./out/artifacts
|
path: ./out/artifacts
|
||||||
- name: Upload Sarif
|
- name: Upload Sarif
|
||||||
if: always() && steps.build.outcome == 'success'
|
if: always() && steps.build.outcome == 'success'
|
||||||
uses: github/codeql-action/upload-sarif@v3
|
uses: github/codeql-action/upload-sarif@v4
|
||||||
with:
|
with:
|
||||||
# Path to SARIF file relative to the root of the repository
|
# Path to SARIF file relative to the root of the repository
|
||||||
sarif_file: cifuzz-sarif/results.sarif
|
sarif_file: cifuzz-sarif/results.sarif
|
||||||
|
|||||||
2
.github/workflows/emscripten.yml
vendored
2
.github/workflows/emscripten.yml
vendored
@ -5,7 +5,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v4.2.2
|
- uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v4.2.2
|
||||||
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
|
||||||
- uses: mymindstorm/setup-emsdk@6ab9eb1bda2574c4ddb79809fc9247783eaf9021 # v14
|
- uses: mymindstorm/setup-emsdk@6ab9eb1bda2574c4ddb79809fc9247783eaf9021 # v14
|
||||||
- name: Verify
|
- name: Verify
|
||||||
run: emcc -v
|
run: emcc -v
|
||||||
|
|||||||
2
.github/workflows/risc.yml
vendored
2
.github/workflows/risc.yml
vendored
@ -6,7 +6,7 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
- name: Install packages
|
- name: Install packages
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update -q -y
|
sudo apt-get update -q -y
|
||||||
|
|||||||
24
README.md
24
README.md
@ -401,6 +401,23 @@ except `fast_float::integer_times_pow10()` does not report out-of-range errors,
|
|||||||
underflows to zero or overflows to infinity when the resulting value is
|
underflows to zero or overflows to infinity when the resulting value is
|
||||||
out of range.
|
out of range.
|
||||||
|
|
||||||
|
You can use template overloads to get the result converted to different
|
||||||
|
supported floating-point types: `float`, `double`, etc.
|
||||||
|
For example, to get result as `float` use
|
||||||
|
`fast_float::integer_times_pow10<float>()` specialization:
|
||||||
|
```C++
|
||||||
|
const uint64_t W = 12345678;
|
||||||
|
const int Q = 23;
|
||||||
|
const float result = fast_float::integer_times_pow10<float>(W, Q);
|
||||||
|
std::cout.precision(9);
|
||||||
|
std::cout << "float: " << W << " * 10^" << Q << " = " << result << " ("
|
||||||
|
<< (result == 12345678e23f ? "==" : "!=") << "expected)\n";
|
||||||
|
```
|
||||||
|
outputs
|
||||||
|
```
|
||||||
|
float: 12345678 * 10^23 = 1.23456782e+30 (==expected)
|
||||||
|
```
|
||||||
|
|
||||||
Overloads of `fast_float::integer_times_pow10()` are provided for
|
Overloads of `fast_float::integer_times_pow10()` are provided for
|
||||||
signed and unsigned integer types: `int64_t`, `uint64_t`, etc.
|
signed and unsigned integer types: `int64_t`, `uint64_t`, etc.
|
||||||
|
|
||||||
@ -443,7 +460,7 @@ framework](https://github.com/microsoft/LightGBM).
|
|||||||
Packages
|
Packages
|
||||||
------
|
------
|
||||||
|
|
||||||
[](https://repology.org/project/fastfloat/versions)
|
[](https://repology.org/project/fast-float/versions)
|
||||||
|
|
||||||
|
|
||||||
## References
|
## References
|
||||||
@ -598,6 +615,11 @@ long digits.
|
|||||||
The library includes code adapted from Google Wuffs (written by Nigel Tao) which
|
The library includes code adapted from Google Wuffs (written by Nigel Tao) which
|
||||||
was originally published under the Apache 2.0 license.
|
was originally published under the Apache 2.0 license.
|
||||||
|
|
||||||
|
## Stars
|
||||||
|
|
||||||
|
|
||||||
|
[](https://www.star-history.com/#fastfloat/fast_float&Date)
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
<sup>
|
<sup>
|
||||||
|
|||||||
@ -38,11 +38,8 @@ constexpr static uint64_t powers_of_ten_uint64[] = {1UL,
|
|||||||
// this algorithm is not even close to optimized, but it has no practical
|
// 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
|
// 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.
|
// to slow down performance for faster algorithms, and this is still fast.
|
||||||
template <typename UC>
|
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 int32_t
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 int32_t
|
||||||
scientific_exponent(parsed_number_string_t<UC> &num) noexcept {
|
scientific_exponent(uint64_t mantissa, int32_t exponent) noexcept {
|
||||||
uint64_t mantissa = num.mantissa;
|
|
||||||
int32_t exponent = int32_t(num.exponent);
|
|
||||||
while (mantissa >= 10000) {
|
while (mantissa >= 10000) {
|
||||||
mantissa /= 10000;
|
mantissa /= 10000;
|
||||||
exponent += 4;
|
exponent += 4;
|
||||||
@ -398,7 +395,7 @@ inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa negative_digit_comp(
|
|||||||
FASTFLOAT_ASSERT(real_digits.pow2(uint32_t(-pow2_exp)));
|
FASTFLOAT_ASSERT(real_digits.pow2(uint32_t(-pow2_exp)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// compare digits, and use it to director rounding
|
// compare digits, and use it to direct rounding
|
||||||
int ord = real_digits.compare(theor_digits);
|
int ord = real_digits.compare(theor_digits);
|
||||||
adjusted_mantissa answer = am;
|
adjusted_mantissa answer = am;
|
||||||
round<T>(answer, [ord](adjusted_mantissa &a, int32_t shift) {
|
round<T>(answer, [ord](adjusted_mantissa &a, int32_t shift) {
|
||||||
@ -419,7 +416,7 @@ inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa negative_digit_comp(
|
|||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse the significant digits as a big integer to unambiguously round the
|
// parse the significant digits as a big integer to unambiguously round
|
||||||
// the significant digits. here, we are trying to determine how to round
|
// the significant digits. here, we are trying to determine how to round
|
||||||
// an extended float representation close to `b+h`, halfway between `b`
|
// an extended float representation close to `b+h`, halfway between `b`
|
||||||
// (the float rounded-down) and `b+u`, the next positive float. this
|
// (the float rounded-down) and `b+u`, the next positive float. this
|
||||||
@ -438,7 +435,8 @@ digit_comp(parsed_number_string_t<UC> &num, adjusted_mantissa am) noexcept {
|
|||||||
// remove the invalid exponent bias
|
// remove the invalid exponent bias
|
||||||
am.power2 -= invalid_am_bias;
|
am.power2 -= invalid_am_bias;
|
||||||
|
|
||||||
int32_t sci_exp = scientific_exponent(num);
|
int32_t sci_exp =
|
||||||
|
scientific_exponent(num.mantissa, static_cast<int32_t>(num.exponent));
|
||||||
size_t max_digits = binary_format<T>::max_digits();
|
size_t max_digits = binary_format<T>::max_digits();
|
||||||
size_t digits = 0;
|
size_t digits = 0;
|
||||||
bigint bigmant;
|
bigint bigmant;
|
||||||
|
|||||||
@ -63,6 +63,20 @@ integer_times_pow10(uint64_t mantissa, int decimal_exponent) noexcept;
|
|||||||
FASTFLOAT_CONSTEXPR20 inline double
|
FASTFLOAT_CONSTEXPR20 inline double
|
||||||
integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept;
|
integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is a template overload of `integer_times_pow10()`
|
||||||
|
* that returns a floating-point value of type `T` that is one of
|
||||||
|
* supported floating-point types (e.g. `double`, `float`).
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
FASTFLOAT_CONSTEXPR20
|
||||||
|
typename std::enable_if<is_supported_float_type<T>::value, T>::type
|
||||||
|
integer_times_pow10(uint64_t mantissa, int decimal_exponent) noexcept;
|
||||||
|
template <typename T>
|
||||||
|
FASTFLOAT_CONSTEXPR20
|
||||||
|
typename std::enable_if<is_supported_float_type<T>::value, T>::type
|
||||||
|
integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* from_chars for integer types.
|
* from_chars for integer types.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -406,8 +406,8 @@ full_multiplication(uint64_t a, uint64_t b) {
|
|||||||
// But MinGW on ARM64 doesn't have native support for 64-bit multiplications
|
// But MinGW on ARM64 doesn't have native support for 64-bit multiplications
|
||||||
answer.high = __umulh(a, b);
|
answer.high = __umulh(a, b);
|
||||||
answer.low = a * b;
|
answer.low = a * b;
|
||||||
#elif defined(FASTFLOAT_32BIT) || \
|
#elif defined(FASTFLOAT_32BIT) || (defined(_WIN64) && !defined(__clang__) && \
|
||||||
(defined(_WIN64) && !defined(__clang__) && !defined(_M_ARM64))
|
!defined(_M_ARM64) && !defined(__GNUC__))
|
||||||
answer.low = _umul128(a, b, &answer.high); // _umul128 not available on ARM64
|
answer.low = _umul128(a, b, &answer.high); // _umul128 not available on ARM64
|
||||||
#elif defined(FASTFLOAT_64BIT) && defined(__SIZEOF_INT128__)
|
#elif defined(FASTFLOAT_64BIT) && defined(__SIZEOF_INT128__)
|
||||||
__uint128_t r = ((__uint128_t)a) * b;
|
__uint128_t r = ((__uint128_t)a) * b;
|
||||||
@ -1166,6 +1166,9 @@ static_assert(std::is_same<equiv_uint_t<std::float64_t>, uint64_t>::value,
|
|||||||
static_assert(
|
static_assert(
|
||||||
std::numeric_limits<std::float64_t>::is_iec559,
|
std::numeric_limits<std::float64_t>::is_iec559,
|
||||||
"std::float64_t must fulfill the requirements of IEC 559 (IEEE 754)");
|
"std::float64_t must fulfill the requirements of IEC 559 (IEEE 754)");
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct binary_format<std::float64_t> : public binary_format<double> {};
|
||||||
#endif // __STDCPP_FLOAT64_T__
|
#endif // __STDCPP_FLOAT64_T__
|
||||||
|
|
||||||
#ifdef __STDCPP_FLOAT32_T__
|
#ifdef __STDCPP_FLOAT32_T__
|
||||||
@ -1174,6 +1177,9 @@ static_assert(std::is_same<equiv_uint_t<std::float32_t>, uint32_t>::value,
|
|||||||
static_assert(
|
static_assert(
|
||||||
std::numeric_limits<std::float32_t>::is_iec559,
|
std::numeric_limits<std::float32_t>::is_iec559,
|
||||||
"std::float32_t must fulfill the requirements of IEC 559 (IEEE 754)");
|
"std::float32_t must fulfill the requirements of IEC 559 (IEEE 754)");
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct binary_format<std::float32_t> : public binary_format<float> {};
|
||||||
#endif // __STDCPP_FLOAT32_T__
|
#endif // __STDCPP_FLOAT32_T__
|
||||||
|
|
||||||
#ifdef __STDCPP_FLOAT16_T__
|
#ifdef __STDCPP_FLOAT16_T__
|
||||||
@ -1245,7 +1251,6 @@ constexpr chars_format adjust_for_feature_macros(chars_format fmt) {
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
} // namespace fast_float
|
} // namespace fast_float
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -344,44 +344,79 @@ from_chars(UC const *first, UC const *last, T &value, int base) noexcept {
|
|||||||
return from_chars_advanced(first, last, value, options);
|
return from_chars_advanced(first, last, value, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
FASTFLOAT_CONSTEXPR20 inline double
|
template <typename T>
|
||||||
|
FASTFLOAT_CONSTEXPR20
|
||||||
|
typename std::enable_if<is_supported_float_type<T>::value, T>::type
|
||||||
integer_times_pow10(uint64_t mantissa, int decimal_exponent) noexcept {
|
integer_times_pow10(uint64_t mantissa, int decimal_exponent) noexcept {
|
||||||
double value;
|
T value;
|
||||||
if (clinger_fast_path_impl(mantissa, decimal_exponent, false, value))
|
if (clinger_fast_path_impl(mantissa, decimal_exponent, false, value))
|
||||||
return value;
|
return value;
|
||||||
|
|
||||||
adjusted_mantissa am =
|
adjusted_mantissa am =
|
||||||
compute_float<binary_format<double>>(decimal_exponent, mantissa);
|
compute_float<binary_format<T>>(decimal_exponent, mantissa);
|
||||||
to_float(false, am, value);
|
to_float(false, am, value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
FASTFLOAT_CONSTEXPR20 inline double
|
template <typename T>
|
||||||
|
FASTFLOAT_CONSTEXPR20
|
||||||
|
typename std::enable_if<is_supported_float_type<T>::value, T>::type
|
||||||
integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept {
|
integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept {
|
||||||
const bool is_negative = mantissa < 0;
|
const bool is_negative = mantissa < 0;
|
||||||
const uint64_t m = static_cast<uint64_t>(is_negative ? -mantissa : mantissa);
|
const uint64_t m = static_cast<uint64_t>(is_negative ? -mantissa : mantissa);
|
||||||
|
|
||||||
double value;
|
T value;
|
||||||
if (clinger_fast_path_impl(m, decimal_exponent, is_negative, value))
|
if (clinger_fast_path_impl(m, decimal_exponent, is_negative, value))
|
||||||
return value;
|
return value;
|
||||||
|
|
||||||
adjusted_mantissa am =
|
adjusted_mantissa am = compute_float<binary_format<T>>(decimal_exponent, m);
|
||||||
compute_float<binary_format<double>>(decimal_exponent, m);
|
|
||||||
to_float(is_negative, am, value);
|
to_float(is_negative, am, value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FASTFLOAT_CONSTEXPR20 inline double
|
||||||
|
integer_times_pow10(uint64_t mantissa, int decimal_exponent) noexcept {
|
||||||
|
return integer_times_pow10<double>(mantissa, decimal_exponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
FASTFLOAT_CONSTEXPR20 inline double
|
||||||
|
integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept {
|
||||||
|
return integer_times_pow10<double>(mantissa, decimal_exponent);
|
||||||
|
}
|
||||||
|
|
||||||
// the following overloads are here to avoid surprising ambiguity for int,
|
// the following overloads are here to avoid surprising ambiguity for int,
|
||||||
// unsigned, etc.
|
// unsigned, etc.
|
||||||
|
template <typename T, typename Int>
|
||||||
|
FASTFLOAT_CONSTEXPR20
|
||||||
|
typename std::enable_if<is_supported_float_type<T>::value &&
|
||||||
|
std::is_integral<Int>::value &&
|
||||||
|
!std::is_signed<Int>::value,
|
||||||
|
T>::type
|
||||||
|
integer_times_pow10(Int mantissa, int decimal_exponent) noexcept {
|
||||||
|
return integer_times_pow10<T>(static_cast<uint64_t>(mantissa),
|
||||||
|
decimal_exponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename Int>
|
||||||
|
FASTFLOAT_CONSTEXPR20
|
||||||
|
typename std::enable_if<is_supported_float_type<T>::value &&
|
||||||
|
std::is_integral<Int>::value &&
|
||||||
|
std::is_signed<Int>::value,
|
||||||
|
T>::type
|
||||||
|
integer_times_pow10(Int mantissa, int decimal_exponent) noexcept {
|
||||||
|
return integer_times_pow10<T>(static_cast<int64_t>(mantissa),
|
||||||
|
decimal_exponent);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Int>
|
template <typename Int>
|
||||||
FASTFLOAT_CONSTEXPR20 inline typename std::enable_if<
|
FASTFLOAT_CONSTEXPR20 typename std::enable_if<
|
||||||
std::is_integral<Int>::value && !std::is_signed<Int>::value, double>::type
|
std::is_integral<Int>::value && !std::is_signed<Int>::value, double>::type
|
||||||
integer_times_pow10(Int mantissa, int decimal_exponent) noexcept {
|
integer_times_pow10(Int mantissa, int decimal_exponent) noexcept {
|
||||||
return integer_times_pow10(static_cast<uint64_t>(mantissa), decimal_exponent);
|
return integer_times_pow10(static_cast<uint64_t>(mantissa), decimal_exponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Int>
|
template <typename Int>
|
||||||
FASTFLOAT_CONSTEXPR20 inline typename std::enable_if<
|
FASTFLOAT_CONSTEXPR20 typename std::enable_if<
|
||||||
std::is_integral<Int>::value && std::is_signed<Int>::value, double>::type
|
std::is_integral<Int>::value && std::is_signed<Int>::value, double>::type
|
||||||
integer_times_pow10(Int mantissa, int decimal_exponent) noexcept {
|
integer_times_pow10(Int mantissa, int decimal_exponent) noexcept {
|
||||||
return integer_times_pow10(static_cast<int64_t>(mantissa), decimal_exponent);
|
return integer_times_pow10(static_cast<int64_t>(mantissa), decimal_exponent);
|
||||||
|
|||||||
@ -1142,6 +1142,15 @@ TEST_CASE("double.inf") {
|
|||||||
// DBL_MAX + 0.0000000000000001e308
|
// DBL_MAX + 0.0000000000000001e308
|
||||||
verify("1.7976931348623159e308", std::numeric_limits<double>::infinity(),
|
verify("1.7976931348623159e308", std::numeric_limits<double>::infinity(),
|
||||||
std::errc::result_out_of_range);
|
std::errc::result_out_of_range);
|
||||||
|
|
||||||
|
// ( (2 - 0.5*2^(−52)) * 2^1023 ) smallest number that overflows to infinity
|
||||||
|
verify("179769313486231580793728971405303415079934132710037826936173778980444"
|
||||||
|
"968292764750946649017977587207096330286416692887910946555547851940402"
|
||||||
|
"630657488671505820681908902000708383676273854845817711531764475730270"
|
||||||
|
"069855571366959622842914819860834936475292719074168444365510704342711"
|
||||||
|
"559699508093042880177904174497792",
|
||||||
|
std::numeric_limits<double>::infinity(),
|
||||||
|
std::errc::result_out_of_range);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("double.general") {
|
TEST_CASE("double.general") {
|
||||||
@ -1333,6 +1342,15 @@ TEST_CASE("double.general") {
|
|||||||
std::numeric_limits<double>::infinity(), std::errc::result_out_of_range);
|
std::numeric_limits<double>::infinity(), std::errc::result_out_of_range);
|
||||||
verify("-2240084132271013504.131248280843119943687942846658579428",
|
verify("-2240084132271013504.131248280843119943687942846658579428",
|
||||||
-0x1.f1660a65b00bfp+60);
|
-0x1.f1660a65b00bfp+60);
|
||||||
|
|
||||||
|
// ( (2 - 0.5*2^(−52)) * 2^1023 - 1 ) largest 309 decimal digit number
|
||||||
|
// that rounds to DBL_MAX
|
||||||
|
verify("179769313486231580793728971405303415079934132710037826936173778980444"
|
||||||
|
"968292764750946649017977587207096330286416692887910946555547851940402"
|
||||||
|
"630657488671505820681908902000708383676273854845817711531764475730270"
|
||||||
|
"069855571366959622842914819860834936475292719074168444365510704342711"
|
||||||
|
"559699508093042880177904174497791",
|
||||||
|
std::numeric_limits<double>::max());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("double.decimal_point") {
|
TEST_CASE("double.decimal_point") {
|
||||||
@ -1507,14 +1525,35 @@ TEST_CASE("float.inf") {
|
|||||||
std::errc::result_out_of_range);
|
std::errc::result_out_of_range);
|
||||||
verify("3.5028234666e38", std::numeric_limits<float>::infinity(),
|
verify("3.5028234666e38", std::numeric_limits<float>::infinity(),
|
||||||
std::errc::result_out_of_range);
|
std::errc::result_out_of_range);
|
||||||
|
// FLT_MAX + 0.00000007e38
|
||||||
|
verify("3.40282357e38", std::numeric_limits<float>::infinity(),
|
||||||
|
std::errc::result_out_of_range);
|
||||||
|
// FLT_MAX + 0.0000001e38
|
||||||
|
verify("3.4028236e38", std::numeric_limits<float>::infinity(),
|
||||||
|
std::errc::result_out_of_range);
|
||||||
|
|
||||||
|
// ( (2 - 0.5*2^(-23)) * 2^127 ) smallest number that overflows to infinity
|
||||||
|
verify("340282356779733661637539395458142568448",
|
||||||
|
std::numeric_limits<float>::infinity(),
|
||||||
|
std::errc::result_out_of_range);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("float.general") {
|
TEST_CASE("float.general") {
|
||||||
|
// FLT_TRUE_MIN / 2
|
||||||
|
verify("0.7006492e-45", 0.f, std::errc::result_out_of_range);
|
||||||
|
// FLT_TRUE_MIN / 2 + 0.0000001e-45
|
||||||
|
verify("0.7006493e-45", 0x1p-149f);
|
||||||
|
|
||||||
// max
|
// max
|
||||||
verify("340282346638528859811704183484516925440", 0x1.fffffep+127f);
|
verify("340282346638528859811704183484516925440", 0x1.fffffep+127f);
|
||||||
// -max
|
// -max
|
||||||
verify("-340282346638528859811704183484516925440", -0x1.fffffep+127f);
|
verify("-340282346638528859811704183484516925440", -0x1.fffffep+127f);
|
||||||
|
|
||||||
|
// ( (2 - 0.5*2^(-23)) * 2^127 - 1 ) largest 39 decimal digits number
|
||||||
|
// that rounds to FLT_MAX
|
||||||
|
verify("340282356779733661637539395458142568447",
|
||||||
|
std::numeric_limits<float>::max());
|
||||||
|
|
||||||
verify("-1e-999", -0.0f, std::errc::result_out_of_range);
|
verify("-1e-999", -0.0f, std::errc::result_out_of_range);
|
||||||
verify("1."
|
verify("1."
|
||||||
"175494140627517859246175898662808184331245864732796240031385942718174"
|
"175494140627517859246175898662808184331245864732796240031385942718174"
|
||||||
@ -2086,12 +2125,11 @@ TEST_CASE("bfloat16.general") {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename Int>
|
template <typename Int, typename T, typename U>
|
||||||
void verify_integer_multiplication_by_power_of_10(Int mantissa,
|
void verify_integer_times_pow10_result(Int mantissa, int decimal_exponent,
|
||||||
int decimal_exponent,
|
T actual, U expected) {
|
||||||
double expected) {
|
static_assert(std::is_same<T, U>::value,
|
||||||
const double actual =
|
"expected and actual types must match");
|
||||||
fast_float::integer_times_pow10(mantissa, decimal_exponent);
|
|
||||||
|
|
||||||
INFO("m * 10^e=" << mantissa << " * 10^" << decimal_exponent
|
INFO("m * 10^e=" << mantissa << " * 10^" << decimal_exponent
|
||||||
<< "\n"
|
<< "\n"
|
||||||
@ -2105,45 +2143,173 @@ void verify_integer_multiplication_by_power_of_10(Int mantissa,
|
|||||||
CHECK_EQ(actual, expected);
|
CHECK_EQ(actual, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Int>
|
template <typename T, typename Int>
|
||||||
void verify_integer_multiplication_by_power_of_10(Int mantissa,
|
T calculate_integer_times_pow10_expected_result(Int mantissa,
|
||||||
int decimal_exponent) {
|
int decimal_exponent) {
|
||||||
std::string constructed_string =
|
std::string constructed_string =
|
||||||
std::to_string(mantissa) + "e" + std::to_string(decimal_exponent);
|
std::to_string(mantissa) + "e" + std::to_string(decimal_exponent);
|
||||||
double expected_result;
|
T expected_result;
|
||||||
const auto result = fast_float::from_chars(
|
const auto result = fast_float::from_chars(
|
||||||
constructed_string.data(),
|
constructed_string.data(),
|
||||||
constructed_string.data() + constructed_string.size(), expected_result);
|
constructed_string.data() + constructed_string.size(), expected_result);
|
||||||
if (result.ec != std::errc())
|
if (result.ec != std::errc())
|
||||||
INFO("Failed to parse: " << constructed_string);
|
INFO("Failed to parse: " << constructed_string);
|
||||||
verify_integer_multiplication_by_power_of_10(mantissa, decimal_exponent,
|
return expected_result;
|
||||||
expected_result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Int>
|
||||||
|
void verify_integer_times_pow10_dflt(Int mantissa, int decimal_exponent,
|
||||||
|
double expected) {
|
||||||
|
static_assert(std::is_integral<Int>::value);
|
||||||
|
|
||||||
|
// the "default" overload
|
||||||
|
const double actual =
|
||||||
|
fast_float::integer_times_pow10(mantissa, decimal_exponent);
|
||||||
|
|
||||||
|
verify_integer_times_pow10_result(mantissa, decimal_exponent, actual,
|
||||||
|
expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Int>
|
||||||
|
void verify_integer_times_pow10_dflt(Int mantissa, int decimal_exponent) {
|
||||||
|
static_assert(std::is_integral<Int>::value);
|
||||||
|
|
||||||
|
const auto expected_result =
|
||||||
|
calculate_integer_times_pow10_expected_result<double>(mantissa,
|
||||||
|
decimal_exponent);
|
||||||
|
|
||||||
|
verify_integer_times_pow10_dflt(mantissa, decimal_exponent, expected_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename Int>
|
||||||
|
void verify_integer_times_pow10(Int mantissa, int decimal_exponent,
|
||||||
|
T expected) {
|
||||||
|
static_assert(std::is_floating_point<T>::value);
|
||||||
|
static_assert(std::is_integral<Int>::value);
|
||||||
|
|
||||||
|
// explicit specialization
|
||||||
|
const auto actual =
|
||||||
|
fast_float::integer_times_pow10<T>(mantissa, decimal_exponent);
|
||||||
|
|
||||||
|
verify_integer_times_pow10_result(mantissa, decimal_exponent, actual,
|
||||||
|
expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename Int>
|
||||||
|
void verify_integer_times_pow10(Int mantissa, int decimal_exponent) {
|
||||||
|
static_assert(std::is_floating_point<T>::value);
|
||||||
|
static_assert(std::is_integral<Int>::value);
|
||||||
|
|
||||||
|
const auto expected_result = calculate_integer_times_pow10_expected_result<T>(
|
||||||
|
mantissa, decimal_exponent);
|
||||||
|
|
||||||
|
verify_integer_times_pow10(mantissa, decimal_exponent, expected_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace all_supported_types {
|
||||||
|
template <typename Int>
|
||||||
|
void verify_integer_times_pow10(Int mantissa, int decimal_exponent) {
|
||||||
|
static_assert(std::is_integral<Int>::value);
|
||||||
|
|
||||||
|
// verify the "default" overload
|
||||||
|
verify_integer_times_pow10_dflt(mantissa, decimal_exponent);
|
||||||
|
|
||||||
|
// verify explicit specializations
|
||||||
|
::verify_integer_times_pow10<double>(mantissa, decimal_exponent);
|
||||||
|
::verify_integer_times_pow10<float>(mantissa, decimal_exponent);
|
||||||
|
#if defined(__STDCPP_FLOAT64_T__)
|
||||||
|
::verify_integer_times_pow10<std::float64_t>(mantissa, decimal_exponent);
|
||||||
|
#endif
|
||||||
|
#if defined(__STDCPP_FLOAT32_T__)
|
||||||
|
::verify_integer_times_pow10<std::float32_t>(mantissa, decimal_exponent);
|
||||||
|
#endif
|
||||||
|
#if defined(__STDCPP_FLOAT16_T__)
|
||||||
|
::verify_integer_times_pow10<std::float16_t>(mantissa, decimal_exponent);
|
||||||
|
#endif
|
||||||
|
#if defined(__STDCPP_BFLOAT16_T__)
|
||||||
|
::verify_integer_times_pow10<std::bfloat16_t>(mantissa, decimal_exponent);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
} // namespace all_supported_types
|
||||||
|
|
||||||
TEST_CASE("integer_times_pow10") {
|
TEST_CASE("integer_times_pow10") {
|
||||||
// explicitly verifying API with different types of integers
|
/* explicitly verifying API with different types of integers */
|
||||||
verify_integer_multiplication_by_power_of_10<int8_t>(31, -1, 3.1);
|
// double (the "default" overload)
|
||||||
verify_integer_multiplication_by_power_of_10<int8_t>(-31, -1, -3.1);
|
verify_integer_times_pow10_dflt<int8_t>(31, -1, 3.1);
|
||||||
verify_integer_multiplication_by_power_of_10<uint8_t>(31, -1, 3.1);
|
verify_integer_times_pow10_dflt<int8_t>(-31, -1, -3.1);
|
||||||
verify_integer_multiplication_by_power_of_10<int16_t>(31415, -4, 3.1415);
|
verify_integer_times_pow10_dflt<uint8_t>(31, -1, 3.1);
|
||||||
verify_integer_multiplication_by_power_of_10<int16_t>(-31415, -4, -3.1415);
|
verify_integer_times_pow10_dflt<int16_t>(31415, -4, 3.1415);
|
||||||
verify_integer_multiplication_by_power_of_10<uint16_t>(31415, -4, 3.1415);
|
verify_integer_times_pow10_dflt<int16_t>(-31415, -4, -3.1415);
|
||||||
verify_integer_multiplication_by_power_of_10<int32_t>(314159265, -8,
|
verify_integer_times_pow10_dflt<uint16_t>(31415, -4, 3.1415);
|
||||||
3.14159265);
|
verify_integer_times_pow10_dflt<int32_t>(314159265, -8, 3.14159265);
|
||||||
verify_integer_multiplication_by_power_of_10<int32_t>(-314159265, -8,
|
verify_integer_times_pow10_dflt<int32_t>(-314159265, -8, -3.14159265);
|
||||||
-3.14159265);
|
verify_integer_times_pow10_dflt<uint32_t>(3141592653, -9, 3.141592653);
|
||||||
verify_integer_multiplication_by_power_of_10<uint32_t>(3141592653, -9,
|
verify_integer_times_pow10_dflt<long>(314159265, -8, 3.14159265);
|
||||||
|
verify_integer_times_pow10_dflt<long>(-314159265, -8, -3.14159265);
|
||||||
|
verify_integer_times_pow10_dflt<unsigned long>(3141592653, -9, 3.141592653);
|
||||||
|
verify_integer_times_pow10_dflt<int64_t>(3141592653589793238, -18,
|
||||||
|
3.141592653589793238);
|
||||||
|
verify_integer_times_pow10_dflt<int64_t>(-3141592653589793238, -18,
|
||||||
|
-3.141592653589793238);
|
||||||
|
verify_integer_times_pow10_dflt<uint64_t>(3141592653589793238, -18,
|
||||||
|
3.141592653589793238);
|
||||||
|
verify_integer_times_pow10_dflt<long long>(3141592653589793238, -18,
|
||||||
|
3.141592653589793238);
|
||||||
|
verify_integer_times_pow10_dflt<long long>(-3141592653589793238, -18,
|
||||||
|
-3.141592653589793238);
|
||||||
|
verify_integer_times_pow10_dflt<unsigned long long>(3141592653589793238, -18,
|
||||||
|
3.141592653589793238);
|
||||||
|
// double (explicit specialization)
|
||||||
|
verify_integer_times_pow10<double, int8_t>(31, -1, 3.1);
|
||||||
|
verify_integer_times_pow10<double, int8_t>(-31, -1, -3.1);
|
||||||
|
verify_integer_times_pow10<double, uint8_t>(31, -1, 3.1);
|
||||||
|
verify_integer_times_pow10<double, int16_t>(31415, -4, 3.1415);
|
||||||
|
verify_integer_times_pow10<double, int16_t>(-31415, -4, -3.1415);
|
||||||
|
verify_integer_times_pow10<double, uint16_t>(31415, -4, 3.1415);
|
||||||
|
verify_integer_times_pow10<double, int32_t>(314159265, -8, 3.14159265);
|
||||||
|
verify_integer_times_pow10<double, int32_t>(-314159265, -8, -3.14159265);
|
||||||
|
verify_integer_times_pow10<double, uint32_t>(3141592653, -9, 3.141592653);
|
||||||
|
verify_integer_times_pow10<double, long>(314159265, -8, 3.14159265);
|
||||||
|
verify_integer_times_pow10<double, long>(-314159265, -8, -3.14159265);
|
||||||
|
verify_integer_times_pow10<double, unsigned long>(3141592653, -9,
|
||||||
3.141592653);
|
3.141592653);
|
||||||
verify_integer_multiplication_by_power_of_10<int64_t>(
|
verify_integer_times_pow10<double, int64_t>(3141592653589793238, -18,
|
||||||
3141592653589793238, -18, 3.141592653589793238);
|
3.141592653589793238);
|
||||||
verify_integer_multiplication_by_power_of_10<int64_t>(
|
verify_integer_times_pow10<double, int64_t>(-3141592653589793238, -18,
|
||||||
-3141592653589793238, -18, -3.141592653589793238);
|
-3.141592653589793238);
|
||||||
verify_integer_multiplication_by_power_of_10<uint64_t>(
|
verify_integer_times_pow10<double, uint64_t>(3141592653589793238, -18,
|
||||||
3141592653589793238, -18, 3.141592653589793238);
|
3.141592653589793238);
|
||||||
verify_integer_multiplication_by_power_of_10<long long>(
|
verify_integer_times_pow10<double, long long>(3141592653589793238, -18,
|
||||||
-3141592653589793238, -18, -3.141592653589793238);
|
3.141592653589793238);
|
||||||
verify_integer_multiplication_by_power_of_10<unsigned long long>(
|
verify_integer_times_pow10<double, long long>(-3141592653589793238, -18,
|
||||||
|
-3.141592653589793238);
|
||||||
|
verify_integer_times_pow10<double, unsigned long long>(
|
||||||
3141592653589793238, -18, 3.141592653589793238);
|
3141592653589793238, -18, 3.141592653589793238);
|
||||||
|
// float (explicit specialization)
|
||||||
|
verify_integer_times_pow10<float, int8_t>(31, -1, 3.1f);
|
||||||
|
verify_integer_times_pow10<float, int8_t>(-31, -1, -3.1f);
|
||||||
|
verify_integer_times_pow10<float, uint8_t>(31, -1, 3.1f);
|
||||||
|
verify_integer_times_pow10<float, int16_t>(31415, -4, 3.1415f);
|
||||||
|
verify_integer_times_pow10<float, int16_t>(-31415, -4, -3.1415f);
|
||||||
|
verify_integer_times_pow10<float, uint16_t>(31415, -4, 3.1415f);
|
||||||
|
verify_integer_times_pow10<float, int32_t>(314159265, -8, 3.14159265f);
|
||||||
|
verify_integer_times_pow10<float, int32_t>(-314159265, -8, -3.14159265f);
|
||||||
|
verify_integer_times_pow10<float, uint32_t>(3141592653, -9, 3.14159265f);
|
||||||
|
verify_integer_times_pow10<float, long>(314159265, -8, 3.14159265f);
|
||||||
|
verify_integer_times_pow10<float, long>(-314159265, -8, -3.14159265f);
|
||||||
|
verify_integer_times_pow10<float, unsigned long>(3141592653, -9, 3.14159265f);
|
||||||
|
verify_integer_times_pow10<float, int64_t>(3141592653589793238, -18,
|
||||||
|
3.141592653589793238f);
|
||||||
|
verify_integer_times_pow10<float, int64_t>(-3141592653589793238, -18,
|
||||||
|
-3.141592653589793238f);
|
||||||
|
verify_integer_times_pow10<float, uint64_t>(3141592653589793238, -18,
|
||||||
|
3.141592653589793238f);
|
||||||
|
verify_integer_times_pow10<float, long long>(3141592653589793238, -18,
|
||||||
|
3.141592653589793238f);
|
||||||
|
verify_integer_times_pow10<float, long long>(-3141592653589793238, -18,
|
||||||
|
-3.141592653589793238f);
|
||||||
|
verify_integer_times_pow10<float, unsigned long long>(
|
||||||
|
3141592653589793238, -18, 3.141592653589793238f);
|
||||||
|
|
||||||
for (int mode : {FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO, FE_TONEAREST}) {
|
for (int mode : {FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO, FE_TONEAREST}) {
|
||||||
fesetround(mode);
|
fesetround(mode);
|
||||||
@ -2153,87 +2319,122 @@ TEST_CASE("integer_times_pow10") {
|
|||||||
~Guard() { fesetround(FE_TONEAREST); }
|
~Guard() { fesetround(FE_TONEAREST); }
|
||||||
} guard;
|
} guard;
|
||||||
|
|
||||||
verify_integer_multiplication_by_power_of_10(0, 0);
|
namespace all = all_supported_types;
|
||||||
verify_integer_multiplication_by_power_of_10(1, 0);
|
|
||||||
verify_integer_multiplication_by_power_of_10(0, 1);
|
|
||||||
verify_integer_multiplication_by_power_of_10(1, 1);
|
|
||||||
verify_integer_multiplication_by_power_of_10(-1, 0);
|
|
||||||
verify_integer_multiplication_by_power_of_10(0, -1);
|
|
||||||
verify_integer_multiplication_by_power_of_10(-1, -1);
|
|
||||||
verify_integer_multiplication_by_power_of_10(-1, 1);
|
|
||||||
verify_integer_multiplication_by_power_of_10(1, -1);
|
|
||||||
|
|
||||||
verify_integer_multiplication_by_power_of_10(
|
all::verify_integer_times_pow10(0, 0);
|
||||||
|
all::verify_integer_times_pow10(1, 0);
|
||||||
|
all::verify_integer_times_pow10(0, 1);
|
||||||
|
all::verify_integer_times_pow10(1, 1);
|
||||||
|
all::verify_integer_times_pow10(-1, 0);
|
||||||
|
all::verify_integer_times_pow10(0, -1);
|
||||||
|
all::verify_integer_times_pow10(-1, -1);
|
||||||
|
all::verify_integer_times_pow10(-1, 1);
|
||||||
|
all::verify_integer_times_pow10(1, -1);
|
||||||
|
|
||||||
|
/* denormal min */
|
||||||
|
verify_integer_times_pow10_dflt(49406564584124654, -340,
|
||||||
|
std::numeric_limits<double>::denorm_min());
|
||||||
|
verify_integer_times_pow10<double>(
|
||||||
49406564584124654, -340, std::numeric_limits<double>::denorm_min());
|
49406564584124654, -340, std::numeric_limits<double>::denorm_min());
|
||||||
verify_integer_multiplication_by_power_of_10(
|
verify_integer_times_pow10<float>(14012984, -52,
|
||||||
22250738585072014, -324, std::numeric_limits<double>::min());
|
std::numeric_limits<float>::denorm_min());
|
||||||
verify_integer_multiplication_by_power_of_10(
|
|
||||||
17976931348623158, 292, std::numeric_limits<double>::max());
|
|
||||||
|
|
||||||
// DBL_TRUE_MIN / 2 underflows to 0
|
/* normal min */
|
||||||
verify_integer_multiplication_by_power_of_10(49406564584124654 / 2, -340,
|
verify_integer_times_pow10_dflt(22250738585072014, -324,
|
||||||
0.);
|
std::numeric_limits<double>::min());
|
||||||
|
verify_integer_times_pow10<double>(22250738585072014, -324,
|
||||||
|
std::numeric_limits<double>::min());
|
||||||
|
verify_integer_times_pow10<float>(11754944, -45,
|
||||||
|
std::numeric_limits<float>::min());
|
||||||
|
|
||||||
// DBL_TRUE_MIN / 2 + 0.0000000000000001e-324 rounds to DBL_TRUE_MIN
|
/* max */
|
||||||
verify_integer_multiplication_by_power_of_10(
|
verify_integer_times_pow10_dflt(17976931348623158, 292,
|
||||||
|
std::numeric_limits<double>::max());
|
||||||
|
verify_integer_times_pow10<double>(17976931348623158, 292,
|
||||||
|
std::numeric_limits<double>::max());
|
||||||
|
verify_integer_times_pow10<float>(34028235, 31,
|
||||||
|
std::numeric_limits<float>::max());
|
||||||
|
|
||||||
|
/* underflow */
|
||||||
|
// (DBL_TRUE_MIN / 2) underflows to 0
|
||||||
|
verify_integer_times_pow10_dflt(49406564584124654 / 2, -340, 0.);
|
||||||
|
verify_integer_times_pow10<double>(49406564584124654 / 2, -340, 0.);
|
||||||
|
// (FLT_TRUE_MIN / 2) underflows to 0
|
||||||
|
verify_integer_times_pow10<float>(14012984 / 2, -52, 0.f);
|
||||||
|
|
||||||
|
/* rounding to denormal min */
|
||||||
|
// (DBL_TRUE_MIN / 2 + 0.0000000000000001e-324) rounds to DBL_TRUE_MIN
|
||||||
|
verify_integer_times_pow10_dflt(49406564584124654 / 2 + 1, -340,
|
||||||
|
std::numeric_limits<double>::denorm_min());
|
||||||
|
verify_integer_times_pow10<double>(
|
||||||
49406564584124654 / 2 + 1, -340,
|
49406564584124654 / 2 + 1, -340,
|
||||||
std::numeric_limits<double>::denorm_min());
|
std::numeric_limits<double>::denorm_min());
|
||||||
|
// (FLT_TRUE_MIN / 2 + 0.0000001e-45) rounds to FLT_TRUE_MIN
|
||||||
|
verify_integer_times_pow10<float>(14012984 / 2 + 1, -52,
|
||||||
|
std::numeric_limits<float>::denorm_min());
|
||||||
|
|
||||||
// DBL_MAX + 0.0000000000000001e308 overflows to infinity
|
/* overflow */
|
||||||
verify_integer_multiplication_by_power_of_10(
|
// (DBL_MAX + 0.0000000000000001e308) overflows to infinity
|
||||||
17976931348623158 + 1, 292, std::numeric_limits<double>::infinity());
|
verify_integer_times_pow10_dflt(17976931348623158 + 1, 292,
|
||||||
// DBL_MAX + 0.00000000000000001e308 overflows to infinity
|
std::numeric_limits<double>::infinity());
|
||||||
verify_integer_multiplication_by_power_of_10(
|
verify_integer_times_pow10<double>(17976931348623158 + 1, 292,
|
||||||
179769313486231580 + 1, 291, std::numeric_limits<double>::infinity());
|
std::numeric_limits<double>::infinity());
|
||||||
|
// (DBL_MAX + 0.00000000000000001e308) overflows to infinity
|
||||||
|
verify_integer_times_pow10_dflt(179769313486231580 + 1, 291,
|
||||||
|
std::numeric_limits<double>::infinity());
|
||||||
|
verify_integer_times_pow10<double>(179769313486231580 + 1, 291,
|
||||||
|
std::numeric_limits<double>::infinity());
|
||||||
|
// (FLT_MAX + 0.0000001e38) overflows to infinity
|
||||||
|
verify_integer_times_pow10<float>(34028235 + 1, 31,
|
||||||
|
std::numeric_limits<float>::infinity());
|
||||||
|
// (FLT_MAX + 0.00000007e38) overflows to infinity
|
||||||
|
verify_integer_times_pow10<float>(340282350 + 7, 30,
|
||||||
|
std::numeric_limits<float>::infinity());
|
||||||
|
|
||||||
// loosely verifying correct rounding of 1 to 64 bits
|
// loosely verifying correct rounding of 1 to 64 bits
|
||||||
// worth of significant digits
|
// worth of significant digits
|
||||||
verify_integer_multiplication_by_power_of_10(1, 42);
|
all::verify_integer_times_pow10(1, 42);
|
||||||
verify_integer_multiplication_by_power_of_10(1, -42);
|
all::verify_integer_times_pow10(1, -42);
|
||||||
verify_integer_multiplication_by_power_of_10(12, 42);
|
all::verify_integer_times_pow10(12, 42);
|
||||||
verify_integer_multiplication_by_power_of_10(12, -42);
|
all::verify_integer_times_pow10(12, -42);
|
||||||
verify_integer_multiplication_by_power_of_10(123, 42);
|
all::verify_integer_times_pow10(123, 42);
|
||||||
verify_integer_multiplication_by_power_of_10(123, -42);
|
all::verify_integer_times_pow10(123, -42);
|
||||||
verify_integer_multiplication_by_power_of_10(1234, 42);
|
all::verify_integer_times_pow10(1234, 42);
|
||||||
verify_integer_multiplication_by_power_of_10(1234, -42);
|
all::verify_integer_times_pow10(1234, -42);
|
||||||
verify_integer_multiplication_by_power_of_10(12345, 42);
|
all::verify_integer_times_pow10(12345, 42);
|
||||||
verify_integer_multiplication_by_power_of_10(12345, -42);
|
all::verify_integer_times_pow10(12345, -42);
|
||||||
verify_integer_multiplication_by_power_of_10(123456, 42);
|
all::verify_integer_times_pow10(123456, 42);
|
||||||
verify_integer_multiplication_by_power_of_10(123456, -42);
|
all::verify_integer_times_pow10(123456, -42);
|
||||||
verify_integer_multiplication_by_power_of_10(1234567, 42);
|
all::verify_integer_times_pow10(1234567, 42);
|
||||||
verify_integer_multiplication_by_power_of_10(1234567, -42);
|
all::verify_integer_times_pow10(1234567, -42);
|
||||||
verify_integer_multiplication_by_power_of_10(12345678, 42);
|
all::verify_integer_times_pow10(12345678, 42);
|
||||||
verify_integer_multiplication_by_power_of_10(12345678, -42);
|
all::verify_integer_times_pow10(12345678, -42);
|
||||||
verify_integer_multiplication_by_power_of_10(123456789, 42);
|
all::verify_integer_times_pow10(123456789, 42);
|
||||||
verify_integer_multiplication_by_power_of_10(1234567890, 42);
|
all::verify_integer_times_pow10(1234567890, 42);
|
||||||
verify_integer_multiplication_by_power_of_10(1234567890, -42);
|
all::verify_integer_times_pow10(1234567890, -42);
|
||||||
verify_integer_multiplication_by_power_of_10(12345678901, 42);
|
all::verify_integer_times_pow10(12345678901, 42);
|
||||||
verify_integer_multiplication_by_power_of_10(12345678901, -42);
|
all::verify_integer_times_pow10(12345678901, -42);
|
||||||
verify_integer_multiplication_by_power_of_10(123456789012, 42);
|
all::verify_integer_times_pow10(123456789012, 42);
|
||||||
verify_integer_multiplication_by_power_of_10(123456789012, -42);
|
all::verify_integer_times_pow10(123456789012, -42);
|
||||||
verify_integer_multiplication_by_power_of_10(1234567890123, 42);
|
all::verify_integer_times_pow10(1234567890123, 42);
|
||||||
verify_integer_multiplication_by_power_of_10(1234567890123, -42);
|
all::verify_integer_times_pow10(1234567890123, -42);
|
||||||
verify_integer_multiplication_by_power_of_10(12345678901234, 42);
|
all::verify_integer_times_pow10(12345678901234, 42);
|
||||||
verify_integer_multiplication_by_power_of_10(12345678901234, -42);
|
all::verify_integer_times_pow10(12345678901234, -42);
|
||||||
verify_integer_multiplication_by_power_of_10(123456789012345, 42);
|
all::verify_integer_times_pow10(123456789012345, 42);
|
||||||
verify_integer_multiplication_by_power_of_10(123456789012345, -42);
|
all::verify_integer_times_pow10(123456789012345, -42);
|
||||||
verify_integer_multiplication_by_power_of_10(1234567890123456, 42);
|
all::verify_integer_times_pow10(1234567890123456, 42);
|
||||||
verify_integer_multiplication_by_power_of_10(1234567890123456, -42);
|
all::verify_integer_times_pow10(1234567890123456, -42);
|
||||||
verify_integer_multiplication_by_power_of_10(12345678901234567, 42);
|
all::verify_integer_times_pow10(12345678901234567, 42);
|
||||||
verify_integer_multiplication_by_power_of_10(12345678901234567, -42);
|
all::verify_integer_times_pow10(12345678901234567, -42);
|
||||||
verify_integer_multiplication_by_power_of_10(123456789012345678, 42);
|
all::verify_integer_times_pow10(123456789012345678, 42);
|
||||||
verify_integer_multiplication_by_power_of_10(123456789012345678, -42);
|
all::verify_integer_times_pow10(123456789012345678, -42);
|
||||||
verify_integer_multiplication_by_power_of_10(1234567890123456789, 42);
|
all::verify_integer_times_pow10(1234567890123456789, 42);
|
||||||
verify_integer_multiplication_by_power_of_10(1234567890123456789, -42);
|
all::verify_integer_times_pow10(1234567890123456789, -42);
|
||||||
verify_integer_multiplication_by_power_of_10(12345678901234567890ull, 42);
|
all::verify_integer_times_pow10(12345678901234567890ull, 42);
|
||||||
verify_integer_multiplication_by_power_of_10(12345678901234567890ull, -42);
|
all::verify_integer_times_pow10(12345678901234567890ull, -42);
|
||||||
verify_integer_multiplication_by_power_of_10(
|
all::verify_integer_times_pow10(std::numeric_limits<int64_t>::max(), 42);
|
||||||
std::numeric_limits<int64_t>::max(), 42);
|
all::verify_integer_times_pow10(std::numeric_limits<int64_t>::max(), -42);
|
||||||
verify_integer_multiplication_by_power_of_10(
|
all::verify_integer_times_pow10(std::numeric_limits<uint64_t>::max(), 42);
|
||||||
std::numeric_limits<int64_t>::max(), -42);
|
all::verify_integer_times_pow10(std::numeric_limits<uint64_t>::max(), -42);
|
||||||
verify_integer_multiplication_by_power_of_10(
|
|
||||||
std::numeric_limits<uint64_t>::max(), 42);
|
|
||||||
verify_integer_multiplication_by_power_of_10(
|
|
||||||
std::numeric_limits<uint64_t>::max(), -42);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
int main() {
|
void default_overload() {
|
||||||
const uint64_t W = 12345678901234567;
|
const uint64_t W = 12345678901234567;
|
||||||
const int Q = 23;
|
const int Q = 23;
|
||||||
const double result = fast_float::integer_times_pow10(W, Q);
|
const double result = fast_float::integer_times_pow10(W, Q);
|
||||||
@ -10,3 +10,27 @@ int main() {
|
|||||||
std::cout << W << " * 10^" << Q << " = " << result << " ("
|
std::cout << W << " * 10^" << Q << " = " << result << " ("
|
||||||
<< (result == 12345678901234567e23 ? "==" : "!=") << "expected)\n";
|
<< (result == 12345678901234567e23 ? "==" : "!=") << "expected)\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void double_specialization() {
|
||||||
|
const uint64_t W = 12345678901234567;
|
||||||
|
const int Q = 23;
|
||||||
|
const double result = fast_float::integer_times_pow10<double>(W, Q);
|
||||||
|
std::cout.precision(17);
|
||||||
|
std::cout << "double: " << W << " * 10^" << Q << " = " << result << " ("
|
||||||
|
<< (result == 12345678901234567e23 ? "==" : "!=") << "expected)\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void float_specialization() {
|
||||||
|
const uint64_t W = 12345678;
|
||||||
|
const int Q = 23;
|
||||||
|
const float result = fast_float::integer_times_pow10<float>(W, Q);
|
||||||
|
std::cout.precision(9);
|
||||||
|
std::cout << "float: " << W << " * 10^" << Q << " = " << result << " ("
|
||||||
|
<< (result == 12345678e23f ? "==" : "!=") << "expected)\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
default_overload();
|
||||||
|
double_specialization();
|
||||||
|
float_specialization();
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user