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
c3be0f59
Commit
c3be0f59
authored
Nov 27, 2019
by
Victor Zverovich
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor floating-point formatting
parent
c68703c9
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
35 additions
and
37 deletions
+35
-37
include/fmt/format-inl.h
include/fmt/format-inl.h
+1
-1
include/fmt/format.h
include/fmt/format.h
+33
-35
test/format
test/format
+1
-1
No files found.
include/fmt/format-inl.h
View file @
c3be0f59
...
@@ -1128,7 +1128,7 @@ int snprintf_float(T value, int precision, float_specs specs,
...
@@ -1128,7 +1128,7 @@ int snprintf_float(T value, int precision, float_specs specs,
char
format
[
max_format_size
];
char
format
[
max_format_size
];
char
*
format_ptr
=
format
;
char
*
format_ptr
=
format
;
*
format_ptr
++
=
'%'
;
*
format_ptr
++
=
'%'
;
if
(
specs
.
alt
)
*
format_ptr
++
=
'#'
;
if
(
specs
.
trailing_zeros
)
*
format_ptr
++
=
'#'
;
if
(
precision
>=
0
)
{
if
(
precision
>=
0
)
{
*
format_ptr
++
=
'.'
;
*
format_ptr
++
=
'.'
;
*
format_ptr
++
=
'*'
;
*
format_ptr
++
=
'*'
;
...
...
include/fmt/format.h
View file @
c3be0f59
...
@@ -1076,7 +1076,6 @@ struct float_specs {
...
@@ -1076,7 +1076,6 @@ struct float_specs {
bool
upper
:
1
;
bool
upper
:
1
;
bool
locale
:
1
;
bool
locale
:
1
;
bool
percent
:
1
;
bool
percent
:
1
;
bool
alt
:
1
;
bool
binary32
:
1
;
bool
binary32
:
1
;
bool
use_grisu
:
1
;
bool
use_grisu
:
1
;
bool
trailing_zeros
:
1
;
bool
trailing_zeros
:
1
;
...
@@ -1110,32 +1109,32 @@ template <typename Char> class float_writer {
...
@@ -1110,32 +1109,32 @@ template <typename Char> class float_writer {
int
num_digits_
;
int
num_digits_
;
int
exp_
;
int
exp_
;
size_t
size_
;
size_t
size_
;
float_specs
param
s_
;
float_specs
spec
s_
;
Char
decimal_point_
;
Char
decimal_point_
;
template
<
typename
It
>
It
prettify
(
It
it
)
const
{
template
<
typename
It
>
It
prettify
(
It
it
)
const
{
// pow(10, full_exp - 1) <= v <= pow(10, full_exp).
// pow(10, full_exp - 1) <= v <= pow(10, full_exp).
int
full_exp
=
num_digits_
+
exp_
;
int
full_exp
=
num_digits_
+
exp_
;
if
(
param
s_
.
format
==
float_format
::
exp
)
{
if
(
spec
s_
.
format
==
float_format
::
exp
)
{
// Insert a decimal point after the first digit and add an exponent.
// Insert a decimal point after the first digit and add an exponent.
*
it
++
=
static_cast
<
Char
>
(
*
digits_
);
*
it
++
=
static_cast
<
Char
>
(
*
digits_
);
if
(
num_digits_
>
1
)
*
it
++
=
decimal_point_
;
if
(
num_digits_
>
1
)
*
it
++
=
decimal_point_
;
it
=
copy_str
<
Char
>
(
digits_
+
1
,
digits_
+
num_digits_
,
it
);
it
=
copy_str
<
Char
>
(
digits_
+
1
,
digits_
+
num_digits_
,
it
);
int
num_zeros
=
param
s_
.
precision
-
num_digits_
;
int
num_zeros
=
spec
s_
.
precision
-
num_digits_
;
if
(
num_zeros
>
0
&&
param
s_
.
trailing_zeros
)
if
(
num_zeros
>
0
&&
spec
s_
.
trailing_zeros
)
it
=
std
::
fill_n
(
it
,
num_zeros
,
static_cast
<
Char
>
(
'0'
));
it
=
std
::
fill_n
(
it
,
num_zeros
,
static_cast
<
Char
>
(
'0'
));
*
it
++
=
static_cast
<
Char
>
(
param
s_
.
upper
?
'E'
:
'e'
);
*
it
++
=
static_cast
<
Char
>
(
spec
s_
.
upper
?
'E'
:
'e'
);
return
write_exponent
<
Char
>
(
full_exp
-
1
,
it
);
return
write_exponent
<
Char
>
(
full_exp
-
1
,
it
);
}
}
if
(
num_digits_
<=
full_exp
)
{
if
(
num_digits_
<=
full_exp
)
{
// 1234e7 -> 12340000000[.0+]
// 1234e7 -> 12340000000[.0+]
it
=
copy_str
<
Char
>
(
digits_
,
digits_
+
num_digits_
,
it
);
it
=
copy_str
<
Char
>
(
digits_
,
digits_
+
num_digits_
,
it
);
it
=
std
::
fill_n
(
it
,
full_exp
-
num_digits_
,
static_cast
<
Char
>
(
'0'
));
it
=
std
::
fill_n
(
it
,
full_exp
-
num_digits_
,
static_cast
<
Char
>
(
'0'
));
if
(
param
s_
.
trailing_zeros
)
{
if
(
spec
s_
.
trailing_zeros
)
{
*
it
++
=
decimal_point_
;
*
it
++
=
decimal_point_
;
int
num_zeros
=
param
s_
.
precision
-
full_exp
;
int
num_zeros
=
spec
s_
.
precision
-
full_exp
;
if
(
num_zeros
<=
0
)
{
if
(
num_zeros
<=
0
)
{
if
(
param
s_
.
format
!=
float_format
::
fixed
)
if
(
spec
s_
.
format
!=
float_format
::
fixed
)
*
it
++
=
static_cast
<
Char
>
(
'0'
);
*
it
++
=
static_cast
<
Char
>
(
'0'
);
return
it
;
return
it
;
}
}
...
@@ -1148,7 +1147,7 @@ template <typename Char> class float_writer {
...
@@ -1148,7 +1147,7 @@ template <typename Char> class float_writer {
}
else
if
(
full_exp
>
0
)
{
}
else
if
(
full_exp
>
0
)
{
// 1234e-2 -> 12.34[0+]
// 1234e-2 -> 12.34[0+]
it
=
copy_str
<
Char
>
(
digits_
,
digits_
+
full_exp
,
it
);
it
=
copy_str
<
Char
>
(
digits_
,
digits_
+
full_exp
,
it
);
if
(
!
param
s_
.
trailing_zeros
)
{
if
(
!
spec
s_
.
trailing_zeros
)
{
// Remove trailing zeros.
// Remove trailing zeros.
int
num_digits
=
num_digits_
;
int
num_digits
=
num_digits_
;
while
(
num_digits
>
full_exp
&&
digits_
[
num_digits
-
1
]
==
'0'
)
while
(
num_digits
>
full_exp
&&
digits_
[
num_digits
-
1
]
==
'0'
)
...
@@ -1158,19 +1157,19 @@ template <typename Char> class float_writer {
...
@@ -1158,19 +1157,19 @@ template <typename Char> class float_writer {
}
}
*
it
++
=
decimal_point_
;
*
it
++
=
decimal_point_
;
it
=
copy_str
<
Char
>
(
digits_
+
full_exp
,
digits_
+
num_digits_
,
it
);
it
=
copy_str
<
Char
>
(
digits_
+
full_exp
,
digits_
+
num_digits_
,
it
);
if
(
param
s_
.
precision
>
num_digits_
)
{
if
(
spec
s_
.
precision
>
num_digits_
)
{
// Add trailing zeros.
// Add trailing zeros.
int
num_zeros
=
param
s_
.
precision
-
num_digits_
;
int
num_zeros
=
spec
s_
.
precision
-
num_digits_
;
it
=
std
::
fill_n
(
it
,
num_zeros
,
static_cast
<
Char
>
(
'0'
));
it
=
std
::
fill_n
(
it
,
num_zeros
,
static_cast
<
Char
>
(
'0'
));
}
}
}
else
{
}
else
{
// 1234e-6 -> 0.001234
// 1234e-6 -> 0.001234
*
it
++
=
static_cast
<
Char
>
(
'0'
);
*
it
++
=
static_cast
<
Char
>
(
'0'
);
int
num_zeros
=
-
full_exp
;
int
num_zeros
=
-
full_exp
;
if
(
params_
.
precision
>=
0
&&
param
s_
.
precision
<
num_zeros
)
if
(
specs_
.
precision
>=
0
&&
spec
s_
.
precision
<
num_zeros
)
num_zeros
=
param
s_
.
precision
;
num_zeros
=
spec
s_
.
precision
;
int
num_digits
=
num_digits_
;
int
num_digits
=
num_digits_
;
if
(
!
param
s_
.
trailing_zeros
)
if
(
!
spec
s_
.
trailing_zeros
)
while
(
num_digits
>
0
&&
digits_
[
num_digits
-
1
]
==
'0'
)
--
num_digits
;
while
(
num_digits
>
0
&&
digits_
[
num_digits
-
1
]
==
'0'
)
--
num_digits
;
if
(
num_zeros
!=
0
||
num_digits
!=
0
)
{
if
(
num_zeros
!=
0
||
num_digits
!=
0
)
{
*
it
++
=
decimal_point_
;
*
it
++
=
decimal_point_
;
...
@@ -1187,13 +1186,13 @@ template <typename Char> class float_writer {
...
@@ -1187,13 +1186,13 @@ template <typename Char> class float_writer {
:
digits_
(
digits
),
:
digits_
(
digits
),
num_digits_
(
num_digits
),
num_digits_
(
num_digits
),
exp_
(
exp
),
exp_
(
exp
),
param
s_
(
specs
),
spec
s_
(
specs
),
decimal_point_
(
decimal_point
)
{
decimal_point_
(
decimal_point
)
{
int
full_exp
=
num_digits
+
exp
-
1
;
int
full_exp
=
num_digits
+
exp
-
1
;
int
precision
=
specs
.
precision
>
0
?
specs
.
precision
:
16
;
int
precision
=
specs
.
precision
>
0
?
specs
.
precision
:
16
;
if
(
param
s_
.
format
==
float_format
::
general
&&
if
(
spec
s_
.
format
==
float_format
::
general
&&
!
(
full_exp
>=
-
4
&&
full_exp
<
precision
))
{
!
(
full_exp
>=
-
4
&&
full_exp
<
precision
))
{
param
s_
.
format
=
float_format
::
exp
;
spec
s_
.
format
=
float_format
::
exp
;
}
}
size_
=
prettify
(
counting_iterator
()).
count
();
size_
=
prettify
(
counting_iterator
()).
count
();
size_
+=
specs
.
sign
?
1
:
0
;
size_
+=
specs
.
sign
?
1
:
0
;
...
@@ -1203,7 +1202,7 @@ template <typename Char> class float_writer {
...
@@ -1203,7 +1202,7 @@ template <typename Char> class float_writer {
size_t
width
()
const
{
return
size
();
}
size_t
width
()
const
{
return
size
();
}
template
<
typename
It
>
void
operator
()(
It
&&
it
)
{
template
<
typename
It
>
void
operator
()(
It
&&
it
)
{
if
(
params_
.
sign
)
*
it
++
=
static_cast
<
Char
>
(
data
::
signs
[
param
s_
.
sign
]);
if
(
specs_
.
sign
)
*
it
++
=
static_cast
<
Char
>
(
data
::
signs
[
spec
s_
.
sign
]);
it
=
prettify
(
it
);
it
=
prettify
(
it
);
}
}
};
};
...
@@ -1245,15 +1244,19 @@ FMT_CONSTEXPR void handle_int_type_spec(char spec, Handler&& handler) {
...
@@ -1245,15 +1244,19 @@ FMT_CONSTEXPR void handle_int_type_spec(char spec, Handler&& handler) {
}
}
}
}
template
<
typename
ErrorHandler
=
error_handler
>
template
<
typename
ErrorHandler
=
error_handler
,
typename
Char
>
FMT_CONSTEXPR
float_specs
parse_float_type_spec
(
char
spec
,
FMT_CONSTEXPR
float_specs
parse_float_type_spec
(
ErrorHandler
&&
eh
=
{})
{
const
basic_format_specs
<
Char
>&
specs
,
ErrorHandler
&&
eh
=
{})
{
auto
result
=
float_specs
();
auto
result
=
float_specs
();
switch
(
spec
)
{
result
.
trailing_zeros
=
specs
.
alt
;
switch
(
specs
.
type
)
{
case
0
:
result
.
format
=
float_format
::
general
;
result
.
trailing_zeros
|=
specs
.
precision
!=
0
;
break
;
case
'G'
:
case
'G'
:
result
.
upper
=
true
;
result
.
upper
=
true
;
FMT_FALLTHROUGH
;
FMT_FALLTHROUGH
;
case
0
:
case
'g'
:
case
'g'
:
result
.
format
=
float_format
::
general
;
result
.
format
=
float_format
::
general
;
break
;
break
;
...
@@ -1262,12 +1265,14 @@ FMT_CONSTEXPR float_specs parse_float_type_spec(char spec,
...
@@ -1262,12 +1265,14 @@ FMT_CONSTEXPR float_specs parse_float_type_spec(char spec,
FMT_FALLTHROUGH
;
FMT_FALLTHROUGH
;
case
'e'
:
case
'e'
:
result
.
format
=
float_format
::
exp
;
result
.
format
=
float_format
::
exp
;
result
.
trailing_zeros
|=
specs
.
precision
!=
0
;
break
;
break
;
case
'F'
:
case
'F'
:
result
.
upper
=
true
;
result
.
upper
=
true
;
FMT_FALLTHROUGH
;
FMT_FALLTHROUGH
;
case
'f'
:
case
'f'
:
result
.
format
=
float_format
::
fixed
;
result
.
format
=
float_format
::
fixed
;
result
.
trailing_zeros
|=
specs
.
precision
!=
0
;
break
;
break
;
#if FMT_DEPRECATED_PERCENT
#if FMT_DEPRECATED_PERCENT
case
'%'
:
case
'%'
:
...
@@ -1378,7 +1383,7 @@ void arg_map<Context>::init(const basic_format_args<Context>& args) {
...
@@ -1378,7 +1383,7 @@ void arg_map<Context>::init(const basic_format_args<Context>& args) {
}
}
}
}
template
<
typename
Char
>
struct
inf_or_nan
_writer
{
template
<
typename
Char
>
struct
nonfinite
_writer
{
sign_t
sign
;
sign_t
sign
;
const
char
*
str
;
const
char
*
str
;
static
constexpr
size_t
str_size
=
3
;
static
constexpr
size_t
str_size
=
3
;
...
@@ -1691,7 +1696,7 @@ template <typename Range> class basic_writer {
...
@@ -1691,7 +1696,7 @@ template <typename Range> class basic_writer {
template
<
typename
T
,
FMT_ENABLE_IF
(
std
::
is_floating_point
<
T
>
::
value
)
>
template
<
typename
T
,
FMT_ENABLE_IF
(
std
::
is_floating_point
<
T
>
::
value
)
>
void
write
(
T
value
,
format_specs
specs
=
{})
{
void
write
(
T
value
,
format_specs
specs
=
{})
{
float_specs
fspecs
=
parse_float_type_spec
(
specs
.
type
);
float_specs
fspecs
=
parse_float_type_spec
(
specs
);
fspecs
.
sign
=
specs
.
sign
;
fspecs
.
sign
=
specs
.
sign
;
if
(
std
::
signbit
(
value
))
{
// value < 0 is false for NaN so use signbit.
if
(
std
::
signbit
(
value
))
{
// value < 0 is false for NaN so use signbit.
fspecs
.
sign
=
sign
::
minus
;
fspecs
.
sign
=
sign
::
minus
;
...
@@ -1703,8 +1708,7 @@ template <typename Range> class basic_writer {
...
@@ -1703,8 +1708,7 @@ template <typename Range> class basic_writer {
if
(
!
std
::
isfinite
(
value
))
{
if
(
!
std
::
isfinite
(
value
))
{
auto
str
=
std
::
isinf
(
value
)
?
(
fspecs
.
upper
?
"INF"
:
"inf"
)
auto
str
=
std
::
isinf
(
value
)
?
(
fspecs
.
upper
?
"INF"
:
"inf"
)
:
(
fspecs
.
upper
?
"NAN"
:
"nan"
);
:
(
fspecs
.
upper
?
"NAN"
:
"nan"
);
return
write_padded
(
specs
,
return
write_padded
(
specs
,
nonfinite_writer
<
char_type
>
{
fspecs
.
sign
,
str
});
inf_or_nan_writer
<
char_type
>
{
fspecs
.
sign
,
str
});
}
}
if
(
specs
.
align
==
align
::
none
)
{
if
(
specs
.
align
==
align
::
none
)
{
...
@@ -1722,18 +1726,12 @@ template <typename Range> class basic_writer {
...
@@ -1722,18 +1726,12 @@ template <typename Range> class basic_writer {
memory_buffer
buffer
;
memory_buffer
buffer
;
if
(
fspecs
.
format
==
float_format
::
hex
)
{
if
(
fspecs
.
format
==
float_format
::
hex
)
{
if
(
fspecs
.
sign
)
buffer
.
push_back
(
data
::
signs
[
fspecs
.
sign
]);
if
(
fspecs
.
sign
)
buffer
.
push_back
(
data
::
signs
[
fspecs
.
sign
]);
fspecs
.
alt
=
specs
.
alt
;
snprintf_float
(
promote_float
(
value
),
specs
.
precision
,
fspecs
,
buffer
);
snprintf_float
(
promote_float
(
value
),
specs
.
precision
,
fspecs
,
buffer
);
write_padded
(
specs
,
str_writer
<
char
>
{
buffer
.
data
(),
buffer
.
size
()});
write_padded
(
specs
,
str_writer
<
char
>
{
buffer
.
data
(),
buffer
.
size
()});
return
;
return
;
}
}
int
precision
=
specs
.
precision
>=
0
||
!
specs
.
type
?
specs
.
precision
:
6
;
int
precision
=
specs
.
precision
>=
0
||
!
specs
.
type
?
specs
.
precision
:
6
;
if
(
fspecs
.
format
==
float_format
::
exp
)
++
precision
;
if
(
fspecs
.
format
==
float_format
::
exp
)
++
precision
;
fspecs
.
trailing_zeros
=
(
precision
!=
0
&&
(
!
specs
.
type
||
fspecs
.
format
==
float_format
::
fixed
||
fspecs
.
format
==
float_format
::
exp
))
||
specs
.
alt
;
if
(
const_check
(
std
::
is_same
<
T
,
float
>
()))
fspecs
.
binary32
=
true
;
if
(
const_check
(
std
::
is_same
<
T
,
float
>
()))
fspecs
.
binary32
=
true
;
fspecs
.
use_grisu
=
use_grisu
<
T
>
();
fspecs
.
use_grisu
=
use_grisu
<
T
>
();
if
(
const_check
(
FMT_DEPRECATED_PERCENT
)
&&
fspecs
.
percent
)
value
*=
100
;
if
(
const_check
(
FMT_DEPRECATED_PERCENT
)
&&
fspecs
.
percent
)
value
*=
100
;
...
@@ -2956,7 +2954,7 @@ struct formatter<T, Char,
...
@@ -2956,7 +2954,7 @@ struct formatter<T, Char,
case
internal
:
:
float_type
:
case
internal
:
:
float_type
:
case
internal
:
:
double_type
:
case
internal
:
:
double_type
:
case
internal
:
:
long_double_type
:
case
internal
:
:
long_double_type
:
internal
::
parse_float_type_spec
(
specs_
.
type
,
eh
);
internal
::
parse_float_type_spec
(
specs_
,
eh
);
break
;
break
;
case
internal
:
:
cstring_type
:
case
internal
:
:
cstring_type
:
internal
::
handle_cstring_type_spec
(
internal
::
handle_cstring_type_spec
(
...
...
test/format
View file @
c3be0f59
...
@@ -666,7 +666,7 @@ struct formatter {
...
@@ -666,7 +666,7 @@ struct formatter {
break;
break;
case internal::double_type:
case internal::double_type:
case internal::long_double_type:
case internal::long_double_type:
internal::parse_float_type_spec(
type_spec
, eh);
internal::parse_float_type_spec(
specs_
, eh);
break;
break;
case internal::cstring_type:
case internal::cstring_type:
internal::handle_cstring_type_spec(
internal::handle_cstring_type_spec(
...
...
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