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
f6d75c53
Commit
f6d75c53
authored
Oct 09, 2020
by
Victor Zverovich
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor write_float
parent
e9c0b2d6
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
91 additions
and
46 deletions
+91
-46
include/fmt/format.h
include/fmt/format.h
+91
-46
No files found.
include/fmt/format.h
View file @
f6d75c53
...
@@ -1067,11 +1067,10 @@ inline format_decimal_result<Char*> format_decimal(Char* out, UInt value,
...
@@ -1067,11 +1067,10 @@ inline format_decimal_result<Char*> format_decimal(Char* out, UInt value,
template
<
typename
Char
,
typename
UInt
,
typename
Iterator
,
template
<
typename
Char
,
typename
UInt
,
typename
Iterator
,
FMT_ENABLE_IF
(
!
std
::
is_pointer
<
remove_cvref_t
<
Iterator
>
>::
value
)
>
FMT_ENABLE_IF
(
!
std
::
is_pointer
<
remove_cvref_t
<
Iterator
>
>::
value
)
>
inline
format_decimal_result
<
Iterator
>
format_decimal
(
Iterator
out
,
UInt
value
,
inline
format_decimal_result
<
Iterator
>
format_decimal
(
Iterator
out
,
UInt
value
,
int
num_digits
)
{
int
size
)
{
// Buffer should be large enough to hold all digits (<= digits10 + 1).
// Buffer is large enough to hold all digits (digits10 + 1).
enum
{
max_size
=
digits10
<
UInt
>
()
+
1
};
Char
buffer
[
digits10
<
UInt
>
()
+
1
];
Char
buffer
[
2
*
max_size
];
auto
end
=
format_decimal
(
buffer
,
value
,
size
).
end
;
auto
end
=
format_decimal
(
buffer
,
value
,
num_digits
).
end
;
return
{
out
,
detail
::
copy_str
<
Char
>
(
buffer
,
end
,
out
)};
return
{
out
,
detail
::
copy_str
<
Char
>
(
buffer
,
end
,
out
)};
}
}
...
@@ -1488,7 +1487,7 @@ template <align::type align = align::left, typename OutputIt, typename Char,
...
@@ -1488,7 +1487,7 @@ template <align::type align = align::left, typename OutputIt, typename Char,
typename
F
>
typename
F
>
inline
OutputIt
write_padded
(
OutputIt
out
,
inline
OutputIt
write_padded
(
OutputIt
out
,
const
basic_format_specs
<
Char
>&
specs
,
size_t
size
,
const
basic_format_specs
<
Char
>&
specs
,
size_t
size
,
size_t
width
,
const
F
&
f
)
{
size_t
width
,
F
&
&
f
)
{
static_assert
(
align
==
align
::
left
||
align
==
align
::
right
,
""
);
static_assert
(
align
==
align
::
left
||
align
==
align
::
right
,
""
);
unsigned
spec_width
=
to_unsigned
(
specs
.
width
);
unsigned
spec_width
=
to_unsigned
(
specs
.
width
);
size_t
padding
=
spec_width
>
width
?
spec_width
-
width
:
0
;
size_t
padding
=
spec_width
>
width
?
spec_width
-
width
:
0
;
...
@@ -1506,7 +1505,7 @@ template <align::type align = align::left, typename OutputIt, typename Char,
...
@@ -1506,7 +1505,7 @@ template <align::type align = align::left, typename OutputIt, typename Char,
typename
F
>
typename
F
>
inline
OutputIt
write_padded
(
OutputIt
out
,
inline
OutputIt
write_padded
(
OutputIt
out
,
const
basic_format_specs
<
Char
>&
specs
,
size_t
size
,
const
basic_format_specs
<
Char
>&
specs
,
size_t
size
,
const
F
&
f
)
{
F
&
&
f
)
{
return
write_padded
<
align
>
(
out
,
specs
,
size
,
size
,
f
);
return
write_padded
<
align
>
(
out
,
specs
,
size
,
size
,
f
);
}
}
...
@@ -1728,23 +1727,76 @@ OutputIt write_nonfinite(OutputIt out, bool isinf,
...
@@ -1728,23 +1727,76 @@ OutputIt write_nonfinite(OutputIt out, bool isinf,
struct
big_decimal_fp
{
struct
big_decimal_fp
{
const
char
*
significand
;
const
char
*
significand
;
int
significand_size
;
int
significand_size
;
int
exp
;
int
exp
onent
;
};
};
// The number is given as v = significand * pow(10, exp).
inline
int
get_significand_size
(
const
big_decimal_fp
&
fp
)
{
return
fp
.
significand_size
;
}
template
<
typename
T
>
inline
int
get_significand_size
(
const
dragonbox
::
decimal_fp
<
T
>&
fp
)
{
return
count_digits
(
fp
.
significand
);
}
template
<
typename
Char
,
typename
OutputIt
>
inline
OutputIt
write_significand
(
OutputIt
out
,
const
char
*
significand
,
int
&
significand_size
)
{
return
copy_str
<
Char
>
(
significand
,
significand
+
significand_size
,
out
);
}
template
<
typename
Char
,
typename
OutputIt
,
typename
UInt
>
inline
OutputIt
write_significand
(
OutputIt
out
,
UInt
significand
,
int
significand_size
)
{
return
format_decimal
<
Char
>
(
out
,
significand
,
significand_size
).
end
;
}
template
<
typename
Char
,
typename
UInt
,
FMT_ENABLE_IF
(
std
::
is_integral
<
UInt
>
::
value
)
>
inline
Char
*
write_significand
(
Char
*
out
,
UInt
significand
,
int
significand_size
,
int
integral_size
,
Char
decimal_point
)
{
if
(
!
decimal_point
)
return
format_decimal
(
out
,
significand
,
significand_size
).
end
;
auto
end
=
format_decimal
(
out
+
1
,
significand
,
significand_size
).
end
;
std
::
copy_n
(
out
+
1
,
integral_size
,
out
);
out
[
integral_size
]
=
decimal_point
;
return
end
;
}
template
<
typename
OutputIt
,
typename
UInt
,
typename
Char
,
FMT_ENABLE_IF
(
!
std
::
is_pointer
<
remove_cvref_t
<
OutputIt
>
>::
value
)
>
inline
OutputIt
write_significand
(
OutputIt
out
,
UInt
significand
,
int
significand_size
,
int
integral_size
,
Char
decimal_point
)
{
// Buffer is large enough to hold digits (digits10 + 1) and a decimal point.
Char
buffer
[
digits10
<
UInt
>
()
+
2
];
auto
end
=
write_significand
(
buffer
,
significand
,
significand_size
,
integral_size
,
decimal_point
);
return
detail
::
copy_str
<
Char
>
(
buffer
,
end
,
out
);
}
template
<
typename
OutputIt
,
typename
Char
>
template
<
typename
OutputIt
,
typename
Char
>
OutputIt
write_float
(
OutputIt
out
,
const
buffer
<
char
>&
significand
,
int
fpexp
,
inline
OutputIt
write_significand
(
OutputIt
out
,
const
char
*
significand
,
int
significand_size
,
int
integral_size
,
Char
decimal_point
)
{
out
=
detail
::
copy_str
<
Char
>
(
significand
,
significand
+
integral_size
,
out
);
if
(
!
decimal_point
)
return
out
;
*
out
++
=
decimal_point
;
return
detail
::
copy_str
<
Char
>
(
significand
+
integral_size
,
significand
+
significand_size
,
out
);
}
template
<
typename
OutputIt
,
typename
DecimalFP
,
typename
Char
>
OutputIt
write_float
(
OutputIt
out
,
const
DecimalFP
&
fp
,
const
basic_format_specs
<
Char
>&
specs
,
float_specs
fspecs
,
const
basic_format_specs
<
Char
>&
specs
,
float_specs
fspecs
,
Char
decimal_point
)
{
Char
decimal_point
)
{
auto
fp
=
big_decimal_fp
{
significand
.
data
(),
auto
significand
=
fp
.
significand
;
static_cast
<
int
>
(
significand
.
size
()),
fpexp
};
int
significand_size
=
get_significand_size
(
fp
);
const
char
*
digits
=
fp
.
significand
;
const
Char
zero
=
static_cast
<
Char
>
(
'0'
);
const
Char
zero
=
static_cast
<
Char
>
(
'0'
);
char
sign
=
data
::
signs
[
fspecs
.
sign
];
char
sign
=
data
::
signs
[
fspecs
.
sign
];
int
size
=
fp
.
significand_size
+
(
fspecs
.
sign
?
1
:
0
);
int
size
=
significand_size
+
(
fspecs
.
sign
?
1
:
0
);
using
iterator
=
remove_reference_t
<
decltype
(
reserve
(
out
,
0
))
>
;
using
iterator
=
remove_reference_t
<
decltype
(
reserve
(
out
,
0
))
>
;
int
output_exp
=
fp
.
exp
+
fp
.
significand_size
-
1
;
int
output_exp
=
fp
.
exp
onent
+
significand_size
-
1
;
auto
use_exp_format
=
[
=
]()
{
auto
use_exp_format
=
[
=
]()
{
if
(
fspecs
.
format
==
float_format
::
exp
)
return
true
;
if
(
fspecs
.
format
==
float_format
::
exp
)
return
true
;
if
(
fspecs
.
format
!=
float_format
::
general
)
return
false
;
if
(
fspecs
.
format
!=
float_format
::
general
)
return
false
;
...
@@ -1757,9 +1809,9 @@ OutputIt write_float(OutputIt out, const buffer<char>& significand, int fpexp,
...
@@ -1757,9 +1809,9 @@ OutputIt write_float(OutputIt out, const buffer<char>& significand, int fpexp,
if
(
use_exp_format
())
{
if
(
use_exp_format
())
{
int
num_zeros
=
0
;
int
num_zeros
=
0
;
if
(
fspecs
.
showpoint
)
{
if
(
fspecs
.
showpoint
)
{
num_zeros
=
fspecs
.
precision
-
fp
.
significand_size
;
num_zeros
=
fspecs
.
precision
-
significand_size
;
if
(
num_zeros
<
0
)
num_zeros
=
0
;
if
(
num_zeros
<
0
)
num_zeros
=
0
;
}
else
if
(
fp
.
significand_size
==
1
)
{
}
else
if
(
significand_size
==
1
)
{
decimal_point
=
Char
();
decimal_point
=
Char
();
}
}
...
@@ -1771,22 +1823,21 @@ OutputIt write_float(OutputIt out, const buffer<char>& significand, int fpexp,
...
@@ -1771,22 +1823,21 @@ OutputIt write_float(OutputIt out, const buffer<char>& significand, int fpexp,
size
+=
(
decimal_point
?
1
:
0
)
+
num_zeros
+
2
+
exp_digits
;
size
+=
(
decimal_point
?
1
:
0
)
+
num_zeros
+
2
+
exp_digits
;
char
exp_char
=
fspecs
.
upper
?
'E'
:
'e'
;
char
exp_char
=
fspecs
.
upper
?
'E'
:
'e'
;
return
write_padded
<
align
::
right
>
(
return
write_padded
<
align
::
right
>
(
out
,
specs
,
to_unsigned
(
size
),
[
=
](
iterator
it
)
{
out
,
specs
,
to_unsigned
(
size
),
[
=
](
iterator
it
)
mutable
{
if
(
sign
)
*
it
++
=
static_cast
<
Char
>
(
sign
);
if
(
sign
)
*
it
++
=
static_cast
<
Char
>
(
sign
);
// 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
=
write_significand
(
it
,
significand
,
significand_size
,
1
,
if
(
decimal_point
)
*
it
++
=
decimal_point
;
decimal_point
);
it
=
copy_str
<
Char
>
(
digits
+
1
,
digits
+
fp
.
significand_size
,
it
);
if
(
num_zeros
>
0
)
it
=
std
::
fill_n
(
it
,
num_zeros
,
zero
);
if
(
num_zeros
>
0
)
it
=
std
::
fill_n
(
it
,
num_zeros
,
zero
);
*
it
++
=
static_cast
<
Char
>
(
exp_char
);
*
it
++
=
static_cast
<
Char
>
(
exp_char
);
return
write_exponent
<
Char
>
(
output_exp
,
it
);
return
write_exponent
<
Char
>
(
output_exp
,
it
);
});
});
}
}
int
exp
=
fp
.
exp
+
fp
.
significand_size
;
int
exp
=
fp
.
exp
onent
+
significand_size
;
if
(
fp
.
exp
>=
0
)
{
if
(
fp
.
exp
onent
>=
0
)
{
// 1234e5 -> 123400000[.0+]
// 1234e5 -> 123400000[.0+]
size
+=
fp
.
exp
;
size
+=
fp
.
exp
onent
;
int
num_zeros
=
fspecs
.
precision
-
exp
;
int
num_zeros
=
fspecs
.
precision
-
exp
;
#ifdef FMT_FUZZ
#ifdef FMT_FUZZ
if
(
num_zeros
>
5000
)
if
(
num_zeros
>
5000
)
...
@@ -1797,45 +1848,42 @@ OutputIt write_float(OutputIt out, const buffer<char>& significand, int fpexp,
...
@@ -1797,45 +1848,42 @@ OutputIt write_float(OutputIt out, const buffer<char>& significand, int fpexp,
if
(
num_zeros
>
0
)
size
+=
num_zeros
;
if
(
num_zeros
>
0
)
size
+=
num_zeros
;
}
}
return
write_padded
<
align
::
right
>
(
return
write_padded
<
align
::
right
>
(
out
,
specs
,
to_unsigned
(
size
),
[
&
](
iterator
it
)
{
out
,
specs
,
to_unsigned
(
size
),
[
&
](
iterator
it
)
mutable
{
if
(
sign
)
*
it
++
=
static_cast
<
Char
>
(
sign
);
if
(
sign
)
*
it
++
=
static_cast
<
Char
>
(
sign
);
it
=
copy_str
<
Char
>
(
digits
,
digits
+
fp
.
significand_size
,
it
);
it
=
write_significand
<
Char
>
(
it
,
significand
,
significand_size
);
it
=
std
::
fill_n
(
it
,
fp
.
exp
,
zero
);
it
=
std
::
fill_n
(
it
,
fp
.
exp
onent
,
zero
);
if
(
!
fspecs
.
showpoint
)
return
it
;
if
(
!
fspecs
.
showpoint
)
return
it
;
*
it
++
=
decimal_point
;
*
it
++
=
decimal_point
;
return
num_zeros
>
0
?
std
::
fill_n
(
it
,
num_zeros
,
zero
)
:
it
;
return
num_zeros
>
0
?
std
::
fill_n
(
it
,
num_zeros
,
zero
)
:
it
;
});
});
}
else
if
(
exp
>
0
)
{
}
else
if
(
exp
>
0
)
{
// 1234e-2 -> 12.34[0+]
// 1234e-2 -> 12.34[0+]
int
num_zeros
=
int
num_zeros
=
fspecs
.
showpoint
?
fspecs
.
precision
-
significand_size
:
0
;
fspecs
.
showpoint
?
fspecs
.
precision
-
fp
.
significand_size
:
0
;
size
+=
1
+
(
num_zeros
>
0
?
num_zeros
:
0
);
size
+=
1
+
(
num_zeros
>
0
?
num_zeros
:
0
);
return
write_padded
<
align
::
right
>
(
return
write_padded
<
align
::
right
>
(
out
,
specs
,
to_unsigned
(
size
),
[
&
](
iterator
it
)
{
out
,
specs
,
to_unsigned
(
size
),
[
&
](
iterator
it
)
mutable
{
if
(
sign
)
*
it
++
=
static_cast
<
Char
>
(
sign
);
if
(
sign
)
*
it
++
=
static_cast
<
Char
>
(
sign
);
it
=
copy_str
<
Char
>
(
digits
,
digits
+
exp
,
it
);
it
=
write_significand
(
it
,
significand
,
significand_size
,
exp
,
*
it
++
=
decimal_point
;
decimal_point
);
it
=
copy_str
<
Char
>
(
digits
+
exp
,
digits
+
fp
.
significand_size
,
it
);
// Add trailing zeros.
return
num_zeros
>
0
?
std
::
fill_n
(
it
,
num_zeros
,
zero
)
:
it
;
return
num_zeros
>
0
?
std
::
fill_n
(
it
,
num_zeros
,
zero
)
:
it
;
});
});
}
}
// 1234e-6 -> 0.001234
// 1234e-6 -> 0.001234
int
num_zeros
=
-
exp
;
int
num_zeros
=
-
exp
;
if
(
fp
.
significand_size
==
0
&&
fspecs
.
precision
>=
0
&&
if
(
significand_size
==
0
&&
fspecs
.
precision
>=
0
&&
fspecs
.
precision
<
num_zeros
)
{
fspecs
.
precision
<
num_zeros
)
{
num_zeros
=
fspecs
.
precision
;
num_zeros
=
fspecs
.
precision
;
}
}
size
+=
2
+
num_zeros
;
size
+=
2
+
num_zeros
;
return
write_padded
<
align
::
right
>
(
return
write_padded
<
align
::
right
>
(
out
,
specs
,
to_unsigned
(
size
),
[
&
](
iterator
it
)
{
out
,
specs
,
to_unsigned
(
size
),
[
&
](
iterator
it
)
mutable
{
if
(
sign
)
*
it
++
=
static_cast
<
Char
>
(
sign
);
if
(
sign
)
*
it
++
=
static_cast
<
Char
>
(
sign
);
*
it
++
=
zero
;
*
it
++
=
zero
;
if
(
num_zeros
==
0
&&
fp
.
significand_size
==
0
&&
!
fspecs
.
showpoint
)
if
(
num_zeros
==
0
&&
significand_size
==
0
&&
!
fspecs
.
showpoint
)
return
it
;
return
it
;
*
it
++
=
decimal_point
;
*
it
++
=
decimal_point
;
it
=
std
::
fill_n
(
it
,
num_zeros
,
zero
);
it
=
std
::
fill_n
(
it
,
num_zeros
,
zero
);
return
copy_str
<
Char
>
(
digits
,
digits
+
fp
.
significand_size
,
it
);
return
write_significand
<
Char
>
(
it
,
significand
,
significand_size
);
});
});
}
}
...
@@ -1883,12 +1931,12 @@ OutputIt write(OutputIt out, T value, basic_format_specs<Char> specs,
...
@@ -1883,12 +1931,12 @@ OutputIt write(OutputIt out, T value, basic_format_specs<Char> specs,
fspecs
.
precision
=
precision
;
fspecs
.
precision
=
precision
;
Char
point
=
Char
point
=
fspecs
.
locale
?
decimal_point
<
Char
>
(
loc
)
:
static_cast
<
Char
>
(
'.'
);
fspecs
.
locale
?
decimal_point
<
Char
>
(
loc
)
:
static_cast
<
Char
>
(
'.'
);
return
write_float
(
out
,
buffer
,
exp
,
specs
,
fspecs
,
point
);
auto
fp
=
big_decimal_fp
{
buffer
.
data
(),
static_cast
<
int
>
(
buffer
.
size
()),
exp
};
return
write_float
(
out
,
fp
,
specs
,
fspecs
,
point
);
}
}
template
<
template
<
typename
Char
,
typename
OutputIt
,
typename
T
,
typename
Char
,
typename
OutputIt
,
typename
T
,
FMT_ENABLE_IF
(
is_fast_float
<
T
>
::
value
)
>
FMT_ENABLE_IF
(
std
::
is_floating_point
<
T
>
::
value
&&
is_fast_float
<
T
>::
value
)
>
OutputIt
write
(
OutputIt
out
,
T
value
)
{
OutputIt
write
(
OutputIt
out
,
T
value
)
{
if
(
const_check
(
!
is_supported_floating_point
(
value
)))
return
out
;
if
(
const_check
(
!
is_supported_floating_point
(
value
)))
return
out
;
auto
fspecs
=
float_specs
();
auto
fspecs
=
float_specs
();
...
@@ -1903,10 +1951,7 @@ OutputIt write(OutputIt out, T value) {
...
@@ -1903,10 +1951,7 @@ OutputIt write(OutputIt out, T value) {
using
type
=
conditional_t
<
std
::
is_same
<
T
,
long
double
>::
value
,
double
,
T
>
;
using
type
=
conditional_t
<
std
::
is_same
<
T
,
long
double
>::
value
,
double
,
T
>
;
auto
dec
=
dragonbox
::
to_decimal
(
static_cast
<
type
>
(
value
));
auto
dec
=
dragonbox
::
to_decimal
(
static_cast
<
type
>
(
value
));
memory_buffer
buf
;
return
write_float
(
out
,
dec
,
specs
,
fspecs
,
static_cast
<
Char
>
(
'.'
));
write
<
char
>
(
buffer_appender
<
char
>
(
buf
),
dec
.
significand
);
return
write_float
(
out
,
buf
,
dec
.
exponent
,
specs
,
fspecs
,
static_cast
<
Char
>
(
'.'
));
}
}
template
<
typename
Char
,
typename
OutputIt
,
typename
T
,
template
<
typename
Char
,
typename
OutputIt
,
typename
T
,
...
...
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