Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
F
fmt
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
fmt
Commits
b60a5c5d
Commit
b60a5c5d
authored
May 28, 2018
by
Victor Zverovich
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improve floating-point formatting
parent
8dc2360b
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
36 additions
and
58 deletions
+36
-58
include/fmt/format-inl.h
include/fmt/format-inl.h
+7
-18
include/fmt/format.h
include/fmt/format.h
+20
-34
src/format.cc
src/format.cc
+6
-6
support/compute-powers.py
support/compute-powers.py
+3
-0
No files found.
include/fmt/format-inl.h
View file @
b60a5c5d
...
...
@@ -232,30 +232,19 @@ FMT_FUNC void system_error::init(
namespace
internal
{
template
<
typename
T
>
int
char_traits
<
char
>::
format_float
(
char
*
buffer
,
std
::
size_t
size
,
const
char
*
format
,
unsigned
width
,
int
precision
,
T
value
)
{
if
(
width
==
0
)
{
return
precision
<
0
?
FMT_SNPRINTF
(
buffer
,
size
,
format
,
value
)
:
FMT_SNPRINTF
(
buffer
,
size
,
format
,
precision
,
value
);
}
char
*
buffer
,
std
::
size_t
size
,
const
char
*
format
,
int
precision
,
T
value
)
{
return
precision
<
0
?
FMT_SNPRINTF
(
buffer
,
size
,
format
,
width
,
value
)
:
FMT_SNPRINTF
(
buffer
,
size
,
format
,
width
,
precision
,
value
);
FMT_SNPRINTF
(
buffer
,
size
,
format
,
value
)
:
FMT_SNPRINTF
(
buffer
,
size
,
format
,
precision
,
value
);
}
template
<
typename
T
>
int
char_traits
<
wchar_t
>::
format_float
(
wchar_t
*
buffer
,
std
::
size_t
size
,
const
wchar_t
*
format
,
unsigned
width
,
int
precision
,
T
value
)
{
if
(
width
==
0
)
{
return
precision
<
0
?
FMT_SWPRINTF
(
buffer
,
size
,
format
,
value
)
:
FMT_SWPRINTF
(
buffer
,
size
,
format
,
precision
,
value
);
}
wchar_t
*
buffer
,
std
::
size_t
size
,
const
wchar_t
*
format
,
int
precision
,
T
value
)
{
return
precision
<
0
?
FMT_SWPRINTF
(
buffer
,
size
,
format
,
width
,
value
)
:
FMT_SWPRINTF
(
buffer
,
size
,
format
,
width
,
precision
,
value
);
FMT_SWPRINTF
(
buffer
,
size
,
format
,
value
)
:
FMT_SWPRINTF
(
buffer
,
size
,
format
,
precision
,
value
);
}
template
<
typename
T
>
...
...
include/fmt/format.h
View file @
b60a5c5d
...
...
@@ -660,30 +660,30 @@ struct char_traits<char> {
// Formats a floating-point number.
template
<
typename
T
>
FMT_API
static
int
format_float
(
char
*
buffer
,
std
::
size_t
size
,
const
char
*
format
,
unsigned
width
,
int
precision
,
T
value
);
const
char
*
format
,
int
precision
,
T
value
);
};
template
<
>
struct
char_traits
<
wchar_t
>
{
template
<
typename
T
>
FMT_API
static
int
format_float
(
wchar_t
*
buffer
,
std
::
size_t
size
,
const
wchar_t
*
format
,
unsigned
width
,
int
precision
,
T
value
);
const
wchar_t
*
format
,
int
precision
,
T
value
);
};
#if FMT_USE_EXTERN_TEMPLATES
extern
template
int
char_traits
<
char
>
::
format_float
<
double
>
(
char
*
buffer
,
std
::
size_t
size
,
const
char
*
format
,
unsigned
width
,
int
precision
,
double
value
);
char
*
buffer
,
std
::
size_t
size
,
const
char
*
format
,
int
precision
,
double
value
);
extern
template
int
char_traits
<
char
>
::
format_float
<
long
double
>
(
char
*
buffer
,
std
::
size_t
size
,
const
char
*
format
,
unsigned
width
,
int
precision
,
long
double
value
);
char
*
buffer
,
std
::
size_t
size
,
const
char
*
format
,
int
precision
,
long
double
value
);
extern
template
int
char_traits
<
wchar_t
>
::
format_float
<
double
>
(
wchar_t
*
buffer
,
std
::
size_t
size
,
const
wchar_t
*
format
,
unsigned
width
,
int
precision
,
double
value
);
wchar_t
*
buffer
,
std
::
size_t
size
,
const
wchar_t
*
format
,
int
precision
,
double
value
);
extern
template
int
char_traits
<
wchar_t
>
::
format_float
<
long
double
>
(
wchar_t
*
buffer
,
std
::
size_t
size
,
const
wchar_t
*
format
,
unsigned
width
,
int
precision
,
long
double
value
);
wchar_t
*
buffer
,
std
::
size_t
size
,
const
wchar_t
*
format
,
int
precision
,
long
double
value
);
#endif
template
<
typename
Container
>
...
...
@@ -2657,8 +2657,7 @@ class basic_writer {
void
write_double
(
T
value
,
const
format_specs
&
spec
);
template
<
typename
T
>
void
write_double_sprintf
(
T
value
,
const
format_specs
&
spec
,
internal
::
basic_buffer
<
char_type
>&
buffer
,
char
sign
);
internal
::
basic_buffer
<
char_type
>&
buffer
);
template
<
typename
Char
>
struct
str_writer
{
...
...
@@ -2887,7 +2886,7 @@ void basic_writer<Range>::write_double(T value, const format_specs &spec) {
fp_value
.
normalize
();
// Find a cached power of 10 close to 1 / fp_value.
int
dec_exp
=
0
;
int
min_exp
=
-
60
;
const
int
min_exp
=
-
60
;
auto
dec_pow
=
internal
::
get_cached_power
(
min_exp
-
(
fp_value
.
e
+
internal
::
fp
::
significand_size
),
dec_exp
);
internal
::
fp
product
=
fp_value
*
dec_pow
;
...
...
@@ -2898,8 +2897,10 @@ void basic_writer<Range>::write_double(T value, const format_specs &spec) {
typedef
back_insert_range
<
internal
::
basic_buffer
<
char_type
>>
range
;
basic_writer
<
range
>
w
{
range
(
buffer
)};
w
.
write
(
hi
);
unsigned
digits
=
buffer
.
size
();
w
.
write
(
'.'
);
for
(
int
i
=
0
;
i
<
18
;
++
i
)
{
const
unsigned
max_digits
=
18
;
while
(
digits
++
<
max_digits
)
{
f
*=
10
;
w
.
write
(
static_cast
<
char
>
(
'0'
+
(
f
>>
-
one
.
e
)));
f
&=
one
.
f
-
1
;
...
...
@@ -2909,7 +2910,7 @@ void basic_writer<Range>::write_double(T value, const format_specs &spec) {
}
else
{
format_specs
normalized_spec
(
spec
);
normalized_spec
.
type_
=
handler
.
type
;
write_double_sprintf
(
value
,
normalized_spec
,
buffer
,
sign
);
write_double_sprintf
(
value
,
normalized_spec
,
buffer
);
}
unsigned
n
=
buffer
.
size
();
align_spec
as
=
spec
;
...
...
@@ -2934,23 +2935,17 @@ template <typename Range>
template
<
typename
T
>
void
basic_writer
<
Range
>::
write_double_sprintf
(
T
value
,
const
format_specs
&
spec
,
internal
::
basic_buffer
<
char_type
>&
buffer
,
char
sign
)
{
unsigned
width
=
spec
.
width
();
if
(
sign
)
{
buffer
.
reserve
(
width
>
1u
?
width
:
1u
);
if
(
width
>
0
)
--
width
;
}
internal
::
basic_buffer
<
char_type
>&
buffer
)
{
// Buffer capacity must be non-zero, otherwise MSVC's vsnprintf_s will fail.
FMT_ASSERT
(
buffer
.
capacity
()
!=
0
,
"empty buffer"
);
// Build format string.
enum
{
MAX_FORMAT_SIZE
=
10
};
// longest format: %#-*.*Lg
char_type
format
[
MAX_FORMAT_SIZE
];
char_type
*
format_ptr
=
format
;
*
format_ptr
++
=
'%'
;
unsigned
width_for_sprintf
=
width
;
if
(
spec
.
flag
(
HASH_FLAG
))
*
format_ptr
++
=
'#'
;
width_for_sprintf
=
0
;
if
(
spec
.
precision
()
>=
0
)
{
*
format_ptr
++
=
'.'
;
*
format_ptr
++
=
'*'
;
...
...
@@ -2964,18 +2959,9 @@ void basic_writer<Range>::write_double_sprintf(
char_type
*
start
=
FMT_NULL
;
for
(;;)
{
std
::
size_t
buffer_size
=
buffer
.
capacity
();
#if FMT_MSC_VER
// MSVC's vsnprintf_s doesn't work with zero size, so reserve
// space for at least one extra character to make the size non-zero.
// Note that the buffer's capacity may increase by more than 1.
if
(
buffer_size
==
0
)
{
buffer
.
reserve
(
1
);
buffer_size
=
buffer
.
capacity
();
}
#endif
start
=
&
buffer
[
0
];
int
result
=
internal
::
char_traits
<
char_type
>::
format_float
(
start
,
buffer_size
,
format
,
width_for_sprintf
,
spec
.
precision
(),
value
);
start
,
buffer_size
,
format
,
spec
.
precision
(),
value
);
if
(
result
>=
0
)
{
unsigned
n
=
internal
::
to_unsigned
(
result
);
if
(
n
<
buffer
.
capacity
())
{
...
...
src/format.cc
View file @
b60a5c5d
...
...
@@ -21,12 +21,12 @@ template void internal::arg_map<format_context>::init(
const
basic_format_args
<
format_context
>
&
args
);
template
FMT_API
int
internal
::
char_traits
<
char
>
::
format_float
(
char
*
buffer
,
std
::
size_t
size
,
const
char
*
format
,
unsigned
width
,
int
precision
,
double
value
);
char
*
buffer
,
std
::
size_t
size
,
const
char
*
format
,
int
precision
,
double
value
);
template
FMT_API
int
internal
::
char_traits
<
char
>
::
format_float
(
char
*
buffer
,
std
::
size_t
size
,
const
char
*
format
,
unsigned
width
,
int
precision
,
long
double
value
);
char
*
buffer
,
std
::
size_t
size
,
const
char
*
format
,
int
precision
,
long
double
value
);
// Explicit instantiations for wchar_t.
...
...
@@ -39,9 +39,9 @@ template void internal::arg_map<wformat_context>::init(
template
FMT_API
int
internal
::
char_traits
<
wchar_t
>
::
format_float
(
wchar_t
*
buffer
,
std
::
size_t
size
,
const
wchar_t
*
format
,
unsigned
width
,
int
precision
,
double
value
);
int
precision
,
double
value
);
template
FMT_API
int
internal
::
char_traits
<
wchar_t
>
::
format_float
(
wchar_t
*
buffer
,
std
::
size_t
size
,
const
wchar_t
*
format
,
unsigned
width
,
int
precision
,
long
double
value
);
int
precision
,
long
double
value
);
FMT_END_NAMESPACE
support/compute-powers.py
View file @
b60a5c5d
...
...
@@ -48,3 +48,6 @@ for i, fp in enumerate(powers):
if
i
%
11
==
0
:
print
(
end
=
'
\n
'
)
print
(
' {:5}'
.
format
(
fp
.
e
),
end
=
','
)
print
(
'
\n\n
Max exponent difference:'
,
max
([
x
.
e
-
powers
[
i
-
1
].
e
for
i
,
x
in
enumerate
(
powers
)][
1
:]))
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