Skip to content

Commit 25fc7a7

Browse files
committed
fix: fp_to_string uses now 2 spaces
1 parent f02069d commit 25fc7a7

File tree

2 files changed

+146
-146
lines changed

2 files changed

+146
-146
lines changed

include/yaml-cpp/fp_to_string.h

Lines changed: 140 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ namespace fp_formatting {
2020
* Converts a integer into its ASCII digits.
2121
*
2222
* @param begin/end - a buffer, must be at least 20bytes long
23-
* @param value - input value
24-
* @param width - minimum number of digits, fill with '0' to the left. Must be equal or smaller than the buffer size.
25-
* @return - number of digits filled into the buffer.
23+
* @param value - input value
24+
* @param width - minimum number of digits, fill with '0' to the left. Must be equal or smaller than the buffer size.
25+
* @return - number of digits filled into the buffer.
2626
*
2727
* Example:
2828
* std::array<char, 20> buffer;
@@ -33,27 +33,27 @@ namespace fp_formatting {
3333
* assert(buffer[2] == '3');
3434
*/
3535
inline auto ConvertToChars(char* begin, char* end, size_t value, int width=1) -> int {
36-
assert(width >= 1);
37-
assert(end >= begin); // end must be after begin
38-
assert(end-begin >= width); // Buffer must be large enough
39-
assert(end-begin >= 20); // 2^64 has 20digits, so at least 20 digits must be available
40-
41-
// count number of digits, and fill digits array accordingly
42-
int digits_ct{};
43-
while (value > 0) {
44-
char c = value % 10 + '0';
45-
value = value / 10;
46-
digits_ct += 1;
47-
*(end-digits_ct) = c;
48-
}
49-
while(digits_ct < width) {
50-
assert(digits_ct < 64);
51-
digits_ct += 1;
52-
*(end-digits_ct) = '0';
53-
}
54-
// move data to the front of the array
55-
std::memmove(begin, end-digits_ct, digits_ct);
56-
return digits_ct;
36+
assert(width >= 1);
37+
assert(end >= begin); // end must be after begin
38+
assert(end-begin >= width); // Buffer must be large enough
39+
assert(end-begin >= 20); // 2^64 has 20digits, so at least 20 digits must be available
40+
41+
// count number of digits, and fill digits array accordingly
42+
int digits_ct{};
43+
while (value > 0) {
44+
char c = value % 10 + '0';
45+
value = value / 10;
46+
digits_ct += 1;
47+
*(end-digits_ct) = c;
48+
}
49+
while(digits_ct < width) {
50+
assert(digits_ct < 64);
51+
digits_ct += 1;
52+
*(end-digits_ct) = '0';
53+
}
54+
// move data to the front of the array
55+
std::memmove(begin, end-digits_ct, digits_ct);
56+
return digits_ct;
5757
}
5858

5959
/**
@@ -63,144 +63,144 @@ inline auto ConvertToChars(char* begin, char* end, size_t value, int width=1) ->
6363
*/
6464
template <typename T>
6565
auto FpToString(T v, int precision = 0) -> std::string {
66-
// assert(precision > 0);
67-
// hardcoded constant, at which exponent should switch to a scientific notation
68-
int const lowerExponentThreshold = -5;
69-
int const upperExponentThreshold = (precision==0)?6:precision;
70-
if (precision == 0) {
71-
precision = 6;
72-
}
73-
74-
// dragonbox/to_decimal does not handle value 0, inf, NaN
75-
if (v == 0 || std::isinf(v) || std::isnan(v)) {
76-
std::stringstream ss;
77-
ss << v;
78-
return ss.str();
79-
}
80-
81-
auto r = jkj::dragonbox::to_decimal(v);
82-
83-
auto digits = std::array<char, 20>{}; // max digits of size_t is 20.
84-
auto digits_ct = ConvertToChars(digits.data(), digits.data() + digits.size(), r.significand);
85-
86-
// check if requested precision is lower than
87-
// required digits for exact representation
88-
if (digits_ct > precision) {
89-
auto diff = digits_ct - precision;
90-
r.exponent += diff;
91-
digits_ct = precision;
92-
93-
// round numbers if required
94-
if (digits[digits_ct] >= '5') {
95-
int i{digits_ct-1};
96-
digits[i] += 1;
97-
while (digits[i] == '9'+1) {
98-
digits_ct -= 1;
99-
r.exponent += 1;
100-
if (i > 0) {
101-
digits[i-1] += 1;
102-
i -= 1;
103-
} else {
104-
digits_ct = 1;
105-
digits[0] = '1';
106-
break;
107-
}
108-
}
66+
// assert(precision > 0);
67+
// hardcoded constant, at which exponent should switch to a scientific notation
68+
int const lowerExponentThreshold = -5;
69+
int const upperExponentThreshold = (precision==0)?6:precision;
70+
if (precision == 0) {
71+
precision = 6;
72+
}
73+
74+
// dragonbox/to_decimal does not handle value 0, inf, NaN
75+
if (v == 0 || std::isinf(v) || std::isnan(v)) {
76+
std::stringstream ss;
77+
ss << v;
78+
return ss.str();
79+
}
80+
81+
auto r = jkj::dragonbox::to_decimal(v);
82+
83+
auto digits = std::array<char, 20>{}; // max digits of size_t is 20.
84+
auto digits_ct = ConvertToChars(digits.data(), digits.data() + digits.size(), r.significand);
85+
86+
// check if requested precision is lower than
87+
// required digits for exact representation
88+
if (digits_ct > precision) {
89+
auto diff = digits_ct - precision;
90+
r.exponent += diff;
91+
digits_ct = precision;
92+
93+
// round numbers if required
94+
if (digits[digits_ct] >= '5') {
95+
int i{digits_ct-1};
96+
digits[i] += 1;
97+
while (digits[i] == '9'+1) {
98+
digits_ct -= 1;
99+
r.exponent += 1;
100+
if (i > 0) {
101+
digits[i-1] += 1;
102+
i -= 1;
103+
} else {
104+
digits_ct = 1;
105+
digits[0] = '1';
106+
break;
109107
}
108+
}
110109
}
111-
112-
std::array<char, 28> output_buffer; // max digits of size_t plus sign, a dot and 2 letters for 'e+' or 'e-' and 4 letters for the exponent
113-
auto output_ptr = &output_buffer[0];
114-
115-
// print '-' symbol for negative numbers
116-
if (r.is_negative) {
117-
*(output_ptr++) = '-';
110+
}
111+
112+
std::array<char, 28> output_buffer; // max digits of size_t plus sign, a dot and 2 letters for 'e+' or 'e-' and 4 letters for the exponent
113+
auto output_ptr = &output_buffer[0];
114+
115+
// print '-' symbol for negative numbers
116+
if (r.is_negative) {
117+
*(output_ptr++) = '-';
118+
}
119+
120+
// exponent if only a single non-zero digit is before the decimal point
121+
int const exponent = r.exponent + digits_ct - 1;
122+
123+
// case 1: scientific notation
124+
if (exponent >= upperExponentThreshold || exponent <= lowerExponentThreshold) {
125+
// print first digit
126+
*(output_ptr++) = digits[0];
127+
128+
// print digits after decimal point
129+
if (digits_ct > 1) {
130+
*(output_ptr++) = '.';
131+
// print significant numbers after decimal point
132+
for (int i{1}; i < digits_ct; ++i) {
133+
*(output_ptr++) = digits[i];
134+
}
135+
}
136+
*(output_ptr++) = 'e';
137+
*(output_ptr++) = (exponent>=0)?'+':'-';
138+
auto exp_digits = std::array<char, 20>{};
139+
auto exp_digits_ct = ConvertToChars(exp_digits.data(), exp_digits.data() + exp_digits.size(), std::abs(exponent), /*.precision=*/ 2);
140+
for (int i{0}; i < exp_digits_ct; ++i) {
141+
*(output_ptr++) = exp_digits[i];
118142
}
119143

120-
// exponent if only a single non-zero digit is before the decimal point
121-
int const exponent = r.exponent + digits_ct - 1;
122-
123-
// case 1: scientific notation
124-
if (exponent >= upperExponentThreshold || exponent <= lowerExponentThreshold) {
125-
// print first digit
126-
*(output_ptr++) = digits[0];
127-
128-
// print digits after decimal point
129-
if (digits_ct > 1) {
130-
*(output_ptr++) = '.';
131-
// print significant numbers after decimal point
132-
for (int i{1}; i < digits_ct; ++i) {
133-
*(output_ptr++) = digits[i];
134-
}
135-
}
136-
*(output_ptr++) = 'e';
137-
*(output_ptr++) = (exponent>=0)?'+':'-';
138-
auto exp_digits = std::array<char, 20>{};
139-
auto exp_digits_ct = ConvertToChars(exp_digits.data(), exp_digits.data() + exp_digits.size(), std::abs(exponent), /*.precision=*/ 2);
140-
for (int i{0}; i < exp_digits_ct; ++i) {
141-
*(output_ptr++) = exp_digits[i];
142-
}
143-
144-
// case 2: default notation
144+
// case 2: default notation
145+
} else {
146+
auto const digits_end = digits.begin() + digits_ct;
147+
auto digits_iter = digits.begin();
148+
149+
// print digits before point
150+
int const before_decimal_digits = digits_ct + r.exponent;
151+
if (before_decimal_digits > 0) {
152+
// print digits before point
153+
for (int i{0}; i < std::min(before_decimal_digits, digits_ct); ++i) {
154+
*(output_ptr++) = *(digits_iter++);
155+
}
156+
// print trailing zeros before point
157+
for (int i{0}; i < before_decimal_digits - digits_ct; ++i) {
158+
*(output_ptr++) = '0';
159+
}
160+
161+
// print 0 before point if none where printed before
145162
} else {
146-
auto const digits_end = digits.begin() + digits_ct;
147-
auto digits_iter = digits.begin();
148-
149-
// print digits before point
150-
int const before_decimal_digits = digits_ct + r.exponent;
151-
if (before_decimal_digits > 0) {
152-
// print digits before point
153-
for (int i{0}; i < std::min(before_decimal_digits, digits_ct); ++i) {
154-
*(output_ptr++) = *(digits_iter++);
155-
}
156-
// print trailing zeros before point
157-
for (int i{0}; i < before_decimal_digits - digits_ct; ++i) {
158-
*(output_ptr++) = '0';
159-
}
160-
161-
// print 0 before point if none where printed before
162-
} else {
163-
*(output_ptr++) = '0';
164-
}
163+
*(output_ptr++) = '0';
164+
}
165165

166-
if (digits_iter != digits_end) {
167-
*(output_ptr++) = '.';
168-
// print 0 afer decimal point, to fill until first digits
169-
int const after_decimal_zeros = -digits_ct - r.exponent;
170-
for (int i{0}; i < after_decimal_zeros; ++i) {
171-
*(output_ptr++) = '0';
172-
}
173-
174-
// print significant numbers after decimal point
175-
for (;digits_iter < digits_end; ++digits_iter) {
176-
*(output_ptr++) = *digits_iter;
177-
}
178-
}
166+
if (digits_iter != digits_end) {
167+
*(output_ptr++) = '.';
168+
// print 0 afer decimal point, to fill until first digits
169+
int const after_decimal_zeros = -digits_ct - r.exponent;
170+
for (int i{0}; i < after_decimal_zeros; ++i) {
171+
*(output_ptr++) = '0';
172+
}
173+
174+
// print significant numbers after decimal point
175+
for (;digits_iter < digits_end; ++digits_iter) {
176+
*(output_ptr++) = *digits_iter;
177+
}
179178
}
180-
*output_ptr = '\0';
181-
return std::string{&output_buffer[0], output_ptr};
179+
}
180+
*output_ptr = '\0';
181+
return std::string{&output_buffer[0], output_ptr};
182182
}
183183

184184
}
185185
}
186186

187187
inline auto FpToString(float v, size_t precision = 0) -> std::string {
188-
return detail::fp_formatting::FpToString(v, precision);
188+
return detail::fp_formatting::FpToString(v, precision);
189189
}
190190

191191
inline auto FpToString(double v, size_t precision = 0) -> std::string {
192-
return detail::fp_formatting::FpToString(v, precision);
192+
return detail::fp_formatting::FpToString(v, precision);
193193
}
194194

195195
/**
196196
* dragonbox only works for floats/doubles not long double
197197
*/
198198
inline auto FpToString(long double v, size_t precision = std::numeric_limits<long double>::max_digits10) -> std::string {
199-
std::stringstream ss;
200-
ss.precision(precision);
201-
ss.imbue(std::locale("C"));
202-
ss << v;
203-
return ss.str();
199+
std::stringstream ss;
200+
ss.imbue(std::locale("C"));
201+
ss.precision(precision);
202+
ss << v;
203+
return ss.str();
204204
}
205205

206206
}

test/fp_to_string_test.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ namespace {
99
*/
1010
template <typename T>
1111
static std::string convert_with_stringstream(T v, size_t precision = 0) {
12-
std::stringstream ss;
13-
if (precision > 0) {
14-
ss << std::setprecision(precision);
15-
}
16-
ss << v;
17-
return ss.str();
12+
std::stringstream ss;
13+
if (precision > 0) {
14+
ss << std::setprecision(precision);
15+
}
16+
ss << v;
17+
return ss.str();
1818
}
1919

2020
// Caution: Test involving 'convert_with_stringstream' are based on std::stringstream

0 commit comments

Comments
 (0)