mirror of
https://github.com/boostorg/spirit.git
synced 2026-01-19 04:42:11 +00:00
Karma: fix broken real_generator output for long double
Eliminate Boost 1.90.0 regression introduced in e6fbdf615b.
This commit is contained in:
@@ -257,20 +257,28 @@ namespace boost { namespace spirit { namespace karma
|
|||||||
// generate(sink, right_align(precision, '0')[ulong], n);
|
// generate(sink, right_align(precision, '0')[ulong], n);
|
||||||
// but it's spelled out to avoid inter-modular dependencies.
|
// but it's spelled out to avoid inter-modular dependencies.
|
||||||
|
|
||||||
unsigned int digits=1; //should be number of digits n(truncating any fraction)
|
// should be number of digits n(truncating any fraction)
|
||||||
if(!boost::spirit::traits::test_zero(n)) {
|
typename remove_const<T>::type digits = 1;
|
||||||
static constexpr uint64_t limit = UINT64_MAX / 10;
|
|
||||||
const T num = floor(n);
|
if (!boost::spirit::traits::test_zero(n)) {
|
||||||
for (uint64_t x = 10u, i = 1u;; x *= 10, i++) {
|
BOOST_CONSTEXPR_OR_CONST uint64_t limit =
|
||||||
if (num < x) {
|
std::numeric_limits<uint64_t>::max() / 10;
|
||||||
digits=i;break;
|
// Cannot cast T to uint64_t since the former might be a mocked
|
||||||
}
|
// type that does not support type casting
|
||||||
if (x > limit) {
|
const T num = floor(n);
|
||||||
digits= i + 1;break;
|
|
||||||
}
|
if (num > limit) {
|
||||||
}
|
// uint64_t cannot represent the fractional part of an 80
|
||||||
}
|
// bit floating point type at full precision. Fallback to
|
||||||
|
// convential computation.
|
||||||
|
digits = ceil(log10(n + T(1.)));
|
||||||
|
} else {
|
||||||
|
for (uint64_t x = 10; num >= x; x *= 10) {
|
||||||
|
++digits;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool r = true;
|
bool r = true;
|
||||||
for (/**/; r && digits < precision_; digits = digits + 1)
|
for (/**/; r && digits < precision_; digits = digits + 1)
|
||||||
r = char_inserter<>::call(sink, '0');
|
r = char_inserter<>::call(sink, '0');
|
||||||
|
|||||||
@@ -145,6 +145,7 @@ run regression_iterator.cpp ;
|
|||||||
run regression_optional_double.cpp ;
|
run regression_optional_double.cpp ;
|
||||||
run regression_real_0.cpp ;
|
run regression_real_0.cpp ;
|
||||||
run regression_real_policy_sign.cpp ;
|
run regression_real_policy_sign.cpp ;
|
||||||
|
run regression_real_policy_precision.cpp ;
|
||||||
run regression_real_scientific.cpp ;
|
run regression_real_scientific.cpp ;
|
||||||
run regression_semantic_action_attribute.cpp ;
|
run regression_semantic_action_attribute.cpp ;
|
||||||
run regression_unicode_char.cpp : : : <pch>off ;
|
run regression_unicode_char.cpp : : : <pch>off ;
|
||||||
|
|||||||
35
test/karma/regression_real_policy_precision.cpp
Normal file
35
test/karma/regression_real_policy_precision.cpp
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
|
#include <boost/spirit/home/karma/numeric/real_policies.hpp>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
#include "real.hpp"
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct max_precision_policy : boost::spirit::karma::real_policies<T> {
|
||||||
|
static BOOST_CONSTEXPR unsigned precision(T /*unused*/) BOOST_NOEXCEPT {
|
||||||
|
return std::numeric_limits<T>::max_digits10;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
using namespace boost::spirit;
|
||||||
|
|
||||||
|
boost::spirit::karma::real_generator<long double,
|
||||||
|
max_precision_policy<long double>>
|
||||||
|
real;
|
||||||
|
|
||||||
|
BOOST_TEST(test("1.004999999999999999996", real, 1.005l));
|
||||||
|
BOOST_TEST(test("1.049999999999999999956", real, 1.05l));
|
||||||
|
BOOST_TEST(test("1.549999999999999999968", real, 1.55l));
|
||||||
|
|
||||||
|
// Construct the fractional part as the limit of uint64_t plus one as
|
||||||
|
// 1844674407370955265 = (2^64-1)/10)+1
|
||||||
|
// to ensure the formatting does not break above this internal limit.
|
||||||
|
BOOST_TEST(test("1.001844674407370955251", real, 1.001844674407370955251l));
|
||||||
|
BOOST_TEST(test("1.01844674407370955262", real, 1.01844674407370955262l));
|
||||||
|
BOOST_TEST(test("1.184467440737095526528", real, 1.184467440737095526528l));
|
||||||
|
|
||||||
|
return boost::report_errors();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user