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
7395472d
Commit
7395472d
authored
Nov 22, 2019
by
Victor Zverovich
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor floating-point formatting
parent
9108b25d
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
26 additions
and
32 deletions
+26
-32
include/fmt/format-inl.h
include/fmt/format-inl.h
+6
-6
include/fmt/format.h
include/fmt/format.h
+17
-24
src/format.cc
src/format.cc
+2
-1
test/format-impl-test.cc
test/format-impl-test.cc
+1
-1
No files found.
include/fmt/format-inl.h
View file @
7395472d
...
@@ -1029,12 +1029,12 @@ void fallback_format(Double d, buffer<char>& buf, int& exp10) {
...
@@ -1029,12 +1029,12 @@ void fallback_format(Double d, buffer<char>& buf, int& exp10) {
}
}
}
}
template
<
typename
Double
,
template
<
typename
Float
,
enable_if_t
<
(
sizeof
(
Float
)
==
sizeof
(
uint64_t
)),
int
>
>
enable_if_t
<
(
sizeof
(
Double
)
==
sizeof
(
uint64_t
)),
int
>
>
bool
grisu_format
(
Float
value
,
int
precision
,
buffer
<
char
>&
buf
,
bool
grisu_format
(
Double
value
,
buffer
<
char
>&
buf
,
int
precision
,
float_spec
spec
,
int
&
exp
)
{
unsigned
options
,
int
&
exp
)
{
FMT_ASSERT
(
value
>=
0
,
"value is negative"
);
FMT_ASSERT
(
value
>=
0
,
"value is negative"
);
const
bool
fixed
=
(
options
&
grisu_options
::
fixed
)
!=
0
;
const
bool
fixed
=
spec
.
format
==
float_format
::
fixed
;
if
(
value
<=
0
)
{
// <= instead of == to silence a warning.
if
(
value
<=
0
)
{
// <= instead of == to silence a warning.
if
(
precision
<=
0
||
!
fixed
)
{
if
(
precision
<=
0
||
!
fixed
)
{
exp
=
0
;
exp
=
0
;
...
@@ -1071,7 +1071,7 @@ bool grisu_format(Double value, buffer<char>& buf, int precision,
...
@@ -1071,7 +1071,7 @@ bool grisu_format(Double value, buffer<char>& buf, int precision,
}
else
{
}
else
{
fp
fp_value
;
fp
fp_value
;
fp
lower
,
upper
;
// w^- and w^+ in the Grisu paper.
fp
lower
,
upper
;
// w^- and w^+ in the Grisu paper.
if
(
(
options
&
grisu_options
::
binary32
)
!=
0
)
if
(
spec
.
binary32
)
fp_value
.
assign_float_with_boundaries
(
value
,
lower
,
upper
);
fp_value
.
assign_float_with_boundaries
(
value
,
lower
,
upper
);
else
else
fp_value
.
assign_with_boundaries
(
value
,
lower
,
upper
);
fp_value
.
assign_with_boundaries
(
value
,
lower
,
upper
);
...
...
include/fmt/format.h
View file @
7395472d
...
@@ -1075,6 +1075,7 @@ struct float_spec {
...
@@ -1075,6 +1075,7 @@ struct float_spec {
bool
locale
;
bool
locale
;
bool
percent
;
bool
percent
;
bool
alt
;
bool
alt
;
bool
binary32
;
};
};
struct
gen_digits_params
{
struct
gen_digits_params
{
...
@@ -1116,7 +1117,7 @@ template <typename Char> class float_writer {
...
@@ -1116,7 +1117,7 @@ template <typename Char> class float_writer {
gen_digits_params
params_
;
gen_digits_params
params_
;
Char
decimal_point_
;
Char
decimal_point_
;
template
<
typename
It
>
It
grisu_
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
(
params_
.
format
==
float_format
::
exp
)
{
if
(
params_
.
format
==
float_format
::
exp
)
{
...
@@ -1194,7 +1195,7 @@ template <typename Char> class float_writer {
...
@@ -1194,7 +1195,7 @@ template <typename Char> class float_writer {
?
float_format
::
fixed
?
float_format
::
fixed
:
float_format
::
exp
;
:
float_format
::
exp
;
}
}
size_
=
grisu_
prettify
(
counting_iterator
()).
count
();
size_
=
prettify
(
counting_iterator
()).
count
();
size_
+=
params_
.
sign
?
1
:
0
;
size_
+=
params_
.
sign
?
1
:
0
;
}
}
...
@@ -1203,20 +1204,16 @@ template <typename Char> class float_writer {
...
@@ -1203,20 +1204,16 @@ template <typename Char> class float_writer {
template
<
typename
It
>
void
operator
()(
It
&&
it
)
{
template
<
typename
It
>
void
operator
()(
It
&&
it
)
{
if
(
params_
.
sign
)
*
it
++
=
static_cast
<
Char
>
(
data
::
signs
[
params_
.
sign
]);
if
(
params_
.
sign
)
*
it
++
=
static_cast
<
Char
>
(
data
::
signs
[
params_
.
sign
]);
it
=
grisu_
prettify
(
it
);
it
=
prettify
(
it
);
}
}
};
};
namespace
grisu_options
{
enum
{
fixed
=
1
,
binary32
=
2
};
}
// Formats value using the Grisu algorithm:
// Formats value using the Grisu algorithm:
// https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf
// https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf
template
<
typename
Double
,
FMT_ENABLE_IF
(
sizeof
(
Double
)
==
sizeof
(
uint64_t
))>
template
<
typename
Float
,
FMT_ENABLE_IF
(
sizeof
(
Float
)
==
sizeof
(
uint64_t
))>
FMT_API
bool
grisu_format
(
Double
,
buffer
<
char
>&
,
int
,
unsigned
,
int
&
);
FMT_API
bool
grisu_format
(
Float
,
int
,
buffer
<
char
>&
,
float_spec
,
int
&
);
template
<
typename
Double
,
FMT_ENABLE_IF
(
sizeof
(
Double
)
!=
sizeof
(
uint64_t
))>
template
<
typename
Float
,
FMT_ENABLE_IF
(
sizeof
(
Float
)
!=
sizeof
(
uint64_t
))>
inline
bool
grisu_format
(
Double
,
buffer
<
char
>&
,
int
,
unsigned
,
int
&
)
{
inline
bool
grisu_format
(
Float
,
int
,
buffer
<
char
>&
,
float_spec
,
int
&
)
{
return
false
;
return
false
;
}
}
...
@@ -1739,17 +1736,13 @@ template <typename Range> class basic_writer {
...
@@ -1739,17 +1736,13 @@ template <typename Range> class basic_writer {
return
;
return
;
}
}
int
precision
=
specs
.
precision
>=
0
||
!
specs
.
type
?
specs
.
precision
:
6
;
int
precision
=
specs
.
precision
>=
0
||
!
specs
.
type
?
specs
.
precision
:
6
;
int
num_digits
=
if
(
fspec
.
format
==
float_format
::
exp
)
++
precision
;
fspec
.
format
==
float_format
::
exp
?
precision
+
1
:
precision
;
if
(
const_check
(
std
::
is_same
<
T
,
float
>
()))
fspec
.
binary32
=
true
;
unsigned
options
=
0
;
if
(
fspec
.
format
==
float_format
::
fixed
)
options
|=
grisu_options
::
fixed
;
if
(
const_check
(
std
::
is_same
<
T
,
float
>
()))
options
|=
grisu_options
::
binary32
;
if
(
const_check
(
FMT_DEPRECATED_PERCENT
)
&&
fspec
.
percent
)
value
*=
100
;
if
(
const_check
(
FMT_DEPRECATED_PERCENT
)
&&
fspec
.
percent
)
value
*=
100
;
int
exp
=
0
;
int
exp
=
0
;
bool
use_grisu
=
internal
::
use_grisu
<
T
>
()
&&
bool
use_grisu
=
grisu_format
(
static_cast
<
double
>
(
value
),
buffer
,
internal
::
use_grisu
<
T
>
()
&&
num_digits
,
options
,
exp
);
grisu_format
(
static_cast
<
double
>
(
value
),
precision
,
buffer
,
fspec
,
exp
);
if
(
!
use_grisu
)
exp
=
sprintf_format
(
value
,
precision
,
fspec
,
buffer
);
if
(
!
use_grisu
)
exp
=
sprintf_format
(
value
,
precision
,
fspec
,
buffer
);
if
(
const_check
(
FMT_DEPRECATED_PERCENT
)
&&
fspec
.
percent
)
{
if
(
const_check
(
FMT_DEPRECATED_PERCENT
)
&&
fspec
.
percent
)
{
...
@@ -1759,18 +1752,18 @@ template <typename Range> class basic_writer {
...
@@ -1759,18 +1752,18 @@ template <typename Range> class basic_writer {
auto
params
=
gen_digits_params
();
auto
params
=
gen_digits_params
();
params
.
sign
=
sign
;
params
.
sign
=
sign
;
params
.
format
=
fspec
.
format
;
params
.
format
=
fspec
.
format
;
params
.
num_digits
=
num_digits
;
params
.
num_digits
=
precision
;
params
.
trailing_zeros
=
params
.
trailing_zeros
=
(
precision
!=
0
&&
(
precision
!=
0
&&
(
!
specs
.
type
||
fspec
.
format
==
float_format
::
fixed
||
(
!
specs
.
type
||
fspec
.
format
==
float_format
::
fixed
||
fspec
.
format
==
float_format
::
exp
))
||
fspec
.
format
==
float_format
::
exp
))
||
specs
.
alt
;
specs
.
alt
;
params
.
upper
=
fspec
.
upper
;
params
.
upper
=
fspec
.
upper
;
num_digits
=
static_cast
<
int
>
(
buffer
.
size
());
char_type
point
=
fspec
.
locale
?
decimal_point
<
char_type
>
(
locale_
)
char_type
point
=
fspec
.
locale
?
decimal_point
<
char_type
>
(
locale_
)
:
static_cast
<
char_type
>
(
'.'
);
:
static_cast
<
char_type
>
(
'.'
);
write_padded
(
specs
,
float_writer
<
char_type
>
(
buffer
.
data
(),
num_digits
,
exp
,
write_padded
(
specs
,
float_writer
<
char_type
>
(
buffer
.
data
(),
params
,
point
));
static_cast
<
int
>
(
buffer
.
size
()),
exp
,
params
,
point
));
}
}
void
write
(
char
value
)
{
void
write
(
char
value
)
{
...
...
src/format.cc
View file @
7395472d
...
@@ -11,7 +11,8 @@ FMT_BEGIN_NAMESPACE
...
@@ -11,7 +11,8 @@ FMT_BEGIN_NAMESPACE
template
struct
FMT_API
internal
::
basic_data
<
void
>;
template
struct
FMT_API
internal
::
basic_data
<
void
>;
// Workaround a bug in MSVC2013 that prevents instantiation of grisu_format.
// Workaround a bug in MSVC2013 that prevents instantiation of grisu_format.
bool
(
*
instantiate_grisu_format
)(
double
,
internal
::
buffer
<
char
>&
,
int
,
unsigned
,
bool
(
*
instantiate_grisu_format
)(
double
,
int
,
internal
::
buffer
<
char
>&
,
internal
::
float_spec
,
int
&
)
=
internal
::
grisu_format
;
int
&
)
=
internal
::
grisu_format
;
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
...
...
test/format-impl-test.cc
View file @
7395472d
...
@@ -327,7 +327,7 @@ TEST(FPTest, FixedHandler) {
...
@@ -327,7 +327,7 @@ TEST(FPTest, FixedHandler) {
TEST
(
FPTest
,
GrisuFormatCompilesWithNonIEEEDouble
)
{
TEST
(
FPTest
,
GrisuFormatCompilesWithNonIEEEDouble
)
{
fmt
::
memory_buffer
buf
;
fmt
::
memory_buffer
buf
;
int
exp
=
0
;
int
exp
=
0
;
grisu_format
(
4.2
f
,
buf
,
-
1
,
false
,
exp
);
grisu_format
(
4.2
f
,
-
1
,
buf
,
fmt
::
internal
::
float_spec
()
,
exp
);
}
}
template
<
typename
T
>
struct
value_extractor
{
template
<
typename
T
>
struct
value_extractor
{
...
...
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