Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yaml-cpp
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
yaml-cpp
Commits
f4bca79d
Commit
f4bca79d
authored
Jul 16, 2024
by
Simon Gene Gottlieb
Committed by
Jesse Beder
Nov 07, 2024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: fp_to_string uses now 2 spaces
parent
d4e00bd4
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
146 additions
and
146 deletions
+146
-146
include/yaml-cpp/fp_to_string.h
+140
-140
test/fp_to_string_test.cpp
+6
-6
No files found.
include/yaml-cpp/fp_to_string.h
View file @
f4bca79d
...
@@ -20,9 +20,9 @@ namespace fp_formatting {
...
@@ -20,9 +20,9 @@ namespace fp_formatting {
* Converts a integer into its ASCII digits.
* Converts a integer into its ASCII digits.
*
*
* @param begin/end - a buffer, must be at least 20bytes long
* @param begin/end - a buffer, must be at least 20bytes long
* @param value
- input value
* @param value - input value
* @param width
- minimum number of digits, fill with '0' to the left. Must be equal or smaller than the buffer size.
* @param width - minimum number of digits, fill with '0' to the left. Must be equal or smaller than the buffer size.
* @return
- number of digits filled into the buffer.
* @return - number of digits filled into the buffer.
*
*
* Example:
* Example:
* std::array<char, 20> buffer;
* std::array<char, 20> buffer;
...
@@ -33,27 +33,27 @@ namespace fp_formatting {
...
@@ -33,27 +33,27 @@ namespace fp_formatting {
* assert(buffer[2] == '3');
* assert(buffer[2] == '3');
*/
*/
inline
auto
ConvertToChars
(
char
*
begin
,
char
*
end
,
size_t
value
,
int
width
=
1
)
->
int
{
inline
auto
ConvertToChars
(
char
*
begin
,
char
*
end
,
size_t
value
,
int
width
=
1
)
->
int
{
assert
(
width
>=
1
);
assert
(
width
>=
1
);
assert
(
end
>=
begin
);
// end must be after begin
assert
(
end
>=
begin
);
// end must be after begin
assert
(
end
-
begin
>=
width
);
// Buffer must be large enough
assert
(
end
-
begin
>=
width
);
// Buffer must be large enough
assert
(
end
-
begin
>=
20
);
// 2^64 has 20digits, so at least 20 digits must be available
assert
(
end
-
begin
>=
20
);
// 2^64 has 20digits, so at least 20 digits must be available
// count number of digits, and fill digits array accordingly
// count number of digits, and fill digits array accordingly
int
digits_ct
{};
int
digits_ct
{};
while
(
value
>
0
)
{
while
(
value
>
0
)
{
char
c
=
value
%
10
+
'0'
;
char
c
=
value
%
10
+
'0'
;
value
=
value
/
10
;
value
=
value
/
10
;
digits_ct
+=
1
;
digits_ct
+=
1
;
*
(
end
-
digits_ct
)
=
c
;
*
(
end
-
digits_ct
)
=
c
;
}
}
while
(
digits_ct
<
width
)
{
while
(
digits_ct
<
width
)
{
assert
(
digits_ct
<
64
);
assert
(
digits_ct
<
64
);
digits_ct
+=
1
;
digits_ct
+=
1
;
*
(
end
-
digits_ct
)
=
'0'
;
*
(
end
-
digits_ct
)
=
'0'
;
}
}
// move data to the front of the array
// move data to the front of the array
std
::
memmove
(
begin
,
end
-
digits_ct
,
digits_ct
);
std
::
memmove
(
begin
,
end
-
digits_ct
,
digits_ct
);
return
digits_ct
;
return
digits_ct
;
}
}
/**
/**
...
@@ -63,144 +63,144 @@ inline auto ConvertToChars(char* begin, char* end, size_t value, int width=1) ->
...
@@ -63,144 +63,144 @@ inline auto ConvertToChars(char* begin, char* end, size_t value, int width=1) ->
*/
*/
template
<
typename
T
>
template
<
typename
T
>
auto
FpToString
(
T
v
,
int
precision
=
0
)
->
std
::
string
{
auto
FpToString
(
T
v
,
int
precision
=
0
)
->
std
::
string
{
// assert(precision > 0);
// assert(precision > 0);
// hardcoded constant, at which exponent should switch to a scientific notation
// hardcoded constant, at which exponent should switch to a scientific notation
int
const
lowerExponentThreshold
=
-
5
;
int
const
lowerExponentThreshold
=
-
5
;
int
const
upperExponentThreshold
=
(
precision
==
0
)
?
6
:
precision
;
int
const
upperExponentThreshold
=
(
precision
==
0
)
?
6
:
precision
;
if
(
precision
==
0
)
{
if
(
precision
==
0
)
{
precision
=
6
;
precision
=
6
;
}
}
// dragonbox/to_decimal does not handle value 0, inf, NaN
// dragonbox/to_decimal does not handle value 0, inf, NaN
if
(
v
==
0
||
std
::
isinf
(
v
)
||
std
::
isnan
(
v
))
{
if
(
v
==
0
||
std
::
isinf
(
v
)
||
std
::
isnan
(
v
))
{
std
::
stringstream
ss
;
std
::
stringstream
ss
;
ss
<<
v
;
ss
<<
v
;
return
ss
.
str
();
return
ss
.
str
();
}
}
auto
r
=
jkj
::
dragonbox
::
to_decimal
(
v
);
auto
r
=
jkj
::
dragonbox
::
to_decimal
(
v
);
auto
digits
=
std
::
array
<
char
,
20
>
{};
// max digits of size_t is 20.
auto
digits
=
std
::
array
<
char
,
20
>
{};
// max digits of size_t is 20.
auto
digits_ct
=
ConvertToChars
(
digits
.
data
(),
digits
.
data
()
+
digits
.
size
(),
r
.
significand
);
auto
digits_ct
=
ConvertToChars
(
digits
.
data
(),
digits
.
data
()
+
digits
.
size
(),
r
.
significand
);
// check if requested precision is lower than
// check if requested precision is lower than
// required digits for exact representation
// required digits for exact representation
if
(
digits_ct
>
precision
)
{
if
(
digits_ct
>
precision
)
{
auto
diff
=
digits_ct
-
precision
;
auto
diff
=
digits_ct
-
precision
;
r
.
exponent
+=
diff
;
r
.
exponent
+=
diff
;
digits_ct
=
precision
;
digits_ct
=
precision
;
// round numbers if required
// round numbers if required
if
(
digits
[
digits_ct
]
>=
'5'
)
{
if
(
digits
[
digits_ct
]
>=
'5'
)
{
int
i
{
digits_ct
-
1
};
int
i
{
digits_ct
-
1
};
digits
[
i
]
+=
1
;
digits
[
i
]
+=
1
;
while
(
digits
[
i
]
==
'9'
+
1
)
{
while
(
digits
[
i
]
==
'9'
+
1
)
{
digits_ct
-=
1
;
digits_ct
-=
1
;
r
.
exponent
+=
1
;
r
.
exponent
+=
1
;
if
(
i
>
0
)
{
if
(
i
>
0
)
{
digits
[
i
-
1
]
+=
1
;
digits
[
i
-
1
]
+=
1
;
i
-=
1
;
i
-=
1
;
}
else
{
}
else
{
digits_ct
=
1
;
digits_ct
=
1
;
digits
[
0
]
=
'1'
;
digits
[
0
]
=
'1'
;
break
;
break
;
}
}
}
}
}
}
}
}
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
auto
output_ptr
=
&
output_buffer
[
0
];
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
auto
output_ptr
=
&
output_buffer
[
0
];
// print '-' symbol for negative numbers
if
(
r
.
is_negative
)
{
// print '-' symbol for negative numbers
*
(
output_ptr
++
)
=
'-'
;
if
(
r
.
is_negative
)
{
*
(
output_ptr
++
)
=
'-'
;
}
// exponent if only a single non-zero digit is before the decimal point
int
const
exponent
=
r
.
exponent
+
digits_ct
-
1
;
// case 1: scientific notation
if
(
exponent
>=
upperExponentThreshold
||
exponent
<=
lowerExponentThreshold
)
{
// print first digit
*
(
output_ptr
++
)
=
digits
[
0
];
// print digits after decimal point
if
(
digits_ct
>
1
)
{
*
(
output_ptr
++
)
=
'.'
;
// print significant numbers after decimal point
for
(
int
i
{
1
};
i
<
digits_ct
;
++
i
)
{
*
(
output_ptr
++
)
=
digits
[
i
];
}
}
*
(
output_ptr
++
)
=
'e'
;
*
(
output_ptr
++
)
=
(
exponent
>=
0
)
?
'+'
:
'-'
;
auto
exp_digits
=
std
::
array
<
char
,
20
>
{};
auto
exp_digits_ct
=
ConvertToChars
(
exp_digits
.
data
(),
exp_digits
.
data
()
+
exp_digits
.
size
(),
std
::
abs
(
exponent
),
/*.precision=*/
2
);
for
(
int
i
{
0
};
i
<
exp_digits_ct
;
++
i
)
{
*
(
output_ptr
++
)
=
exp_digits
[
i
];
}
}
// exponent if only a single non-zero digit is before the decimal point
// case 2: default notation
int
const
exponent
=
r
.
exponent
+
digits_ct
-
1
;
}
else
{
auto
const
digits_end
=
digits
.
begin
()
+
digits_ct
;
// case 1: scientific notation
auto
digits_iter
=
digits
.
begin
();
if
(
exponent
>=
upperExponentThreshold
||
exponent
<=
lowerExponentThreshold
)
{
// print first digit
// print digits before point
*
(
output_ptr
++
)
=
digits
[
0
];
int
const
before_decimal_digits
=
digits_ct
+
r
.
exponent
;
if
(
before_decimal_digits
>
0
)
{
// print digits after decimal point
// print digits before point
if
(
digits_ct
>
1
)
{
for
(
int
i
{
0
};
i
<
std
::
min
(
before_decimal_digits
,
digits_ct
);
++
i
)
{
*
(
output_ptr
++
)
=
'.'
;
*
(
output_ptr
++
)
=
*
(
digits_iter
++
);
// print significant numbers after decimal point
}
for
(
int
i
{
1
};
i
<
digits_ct
;
++
i
)
{
// print trailing zeros before point
*
(
output_ptr
++
)
=
digits
[
i
];
for
(
int
i
{
0
};
i
<
before_decimal_digits
-
digits_ct
;
++
i
)
{
}
*
(
output_ptr
++
)
=
'0'
;
}
}
*
(
output_ptr
++
)
=
'e'
;
*
(
output_ptr
++
)
=
(
exponent
>=
0
)
?
'+'
:
'-'
;
// print 0 before point if none where printed before
auto
exp_digits
=
std
::
array
<
char
,
20
>
{};
auto
exp_digits_ct
=
ConvertToChars
(
exp_digits
.
data
(),
exp_digits
.
data
()
+
exp_digits
.
size
(),
std
::
abs
(
exponent
),
/*.precision=*/
2
);
for
(
int
i
{
0
};
i
<
exp_digits_ct
;
++
i
)
{
*
(
output_ptr
++
)
=
exp_digits
[
i
];
}
// case 2: default notation
}
else
{
}
else
{
auto
const
digits_end
=
digits
.
begin
()
+
digits_ct
;
*
(
output_ptr
++
)
=
'0'
;
auto
digits_iter
=
digits
.
begin
();
}
// print digits before point
int
const
before_decimal_digits
=
digits_ct
+
r
.
exponent
;
if
(
before_decimal_digits
>
0
)
{
// print digits before point
for
(
int
i
{
0
};
i
<
std
::
min
(
before_decimal_digits
,
digits_ct
);
++
i
)
{
*
(
output_ptr
++
)
=
*
(
digits_iter
++
);
}
// print trailing zeros before point
for
(
int
i
{
0
};
i
<
before_decimal_digits
-
digits_ct
;
++
i
)
{
*
(
output_ptr
++
)
=
'0'
;
}
// print 0 before point if none where printed before
}
else
{
*
(
output_ptr
++
)
=
'0'
;
}
if
(
digits_iter
!=
digits_end
)
{
if
(
digits_iter
!=
digits_end
)
{
*
(
output_ptr
++
)
=
'.'
;
*
(
output_ptr
++
)
=
'.'
;
// print 0 afer decimal point, to fill until first digits
// print 0 afer decimal point, to fill until first digits
int
const
after_decimal_zeros
=
-
digits_ct
-
r
.
exponent
;
int
const
after_decimal_zeros
=
-
digits_ct
-
r
.
exponent
;
for
(
int
i
{
0
};
i
<
after_decimal_zeros
;
++
i
)
{
for
(
int
i
{
0
};
i
<
after_decimal_zeros
;
++
i
)
{
*
(
output_ptr
++
)
=
'0'
;
*
(
output_ptr
++
)
=
'0'
;
}
}
// print significant numbers after decimal point
// print significant numbers after decimal point
for
(;
digits_iter
<
digits_end
;
++
digits_iter
)
{
for
(;
digits_iter
<
digits_end
;
++
digits_iter
)
{
*
(
output_ptr
++
)
=
*
digits_iter
;
*
(
output_ptr
++
)
=
*
digits_iter
;
}
}
}
}
}
*
output_ptr
=
'\0'
;
}
return
std
::
string
{
&
output_buffer
[
0
],
output_ptr
};
*
output_ptr
=
'\0'
;
return
std
::
string
{
&
output_buffer
[
0
],
output_ptr
};
}
}
}
}
}
}
inline
auto
FpToString
(
float
v
,
size_t
precision
=
0
)
->
std
::
string
{
inline
auto
FpToString
(
float
v
,
size_t
precision
=
0
)
->
std
::
string
{
return
detail
::
fp_formatting
::
FpToString
(
v
,
precision
);
return
detail
::
fp_formatting
::
FpToString
(
v
,
precision
);
}
}
inline
auto
FpToString
(
double
v
,
size_t
precision
=
0
)
->
std
::
string
{
inline
auto
FpToString
(
double
v
,
size_t
precision
=
0
)
->
std
::
string
{
return
detail
::
fp_formatting
::
FpToString
(
v
,
precision
);
return
detail
::
fp_formatting
::
FpToString
(
v
,
precision
);
}
}
/**
/**
* dragonbox only works for floats/doubles not long double
* dragonbox only works for floats/doubles not long double
*/
*/
inline
auto
FpToString
(
long
double
v
,
size_t
precision
=
std
::
numeric_limits
<
long
double
>::
max_digits10
)
->
std
::
string
{
inline
auto
FpToString
(
long
double
v
,
size_t
precision
=
std
::
numeric_limits
<
long
double
>::
max_digits10
)
->
std
::
string
{
std
::
stringstream
ss
;
std
::
stringstream
ss
;
ss
.
precision
(
precision
);
ss
.
imbue
(
std
::
locale
(
"C"
)
);
ss
.
imbue
(
std
::
locale
(
"C"
)
);
ss
.
precision
(
precision
);
ss
<<
v
;
ss
<<
v
;
return
ss
.
str
();
return
ss
.
str
();
}
}
}
}
...
...
test/fp_to_string_test.cpp
View file @
f4bca79d
...
@@ -9,12 +9,12 @@ namespace {
...
@@ -9,12 +9,12 @@ namespace {
*/
*/
template
<
typename
T
>
template
<
typename
T
>
static
std
::
string
convert_with_stringstream
(
T
v
,
size_t
precision
=
0
)
{
static
std
::
string
convert_with_stringstream
(
T
v
,
size_t
precision
=
0
)
{
std
::
stringstream
ss
;
std
::
stringstream
ss
;
if
(
precision
>
0
)
{
if
(
precision
>
0
)
{
ss
<<
std
::
setprecision
(
precision
);
ss
<<
std
::
setprecision
(
precision
);
}
}
ss
<<
v
;
ss
<<
v
;
return
ss
.
str
();
return
ss
.
str
();
}
}
// Caution: Test involving 'convert_with_stringstream' are based on std::stringstream
// Caution: Test involving 'convert_with_stringstream' are based on std::stringstream
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment