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
1aee4bc9
Commit
1aee4bc9
authored
Sep 26, 2021
by
Victor Zverovich
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor FP formatting
parent
e1bd6cc9
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
20 additions
and
26 deletions
+20
-26
include/fmt/format-inl.h
include/fmt/format-inl.h
+20
-26
No files found.
include/fmt/format-inl.h
View file @
1aee4bc9
...
@@ -226,46 +226,39 @@ template <typename T> struct bits {
...
@@ -226,46 +226,39 @@ template <typename T> struct bits {
static_cast
<
int
>
(
sizeof
(
T
)
*
std
::
numeric_limits
<
unsigned
char
>::
digits
);
static_cast
<
int
>
(
sizeof
(
T
)
*
std
::
numeric_limits
<
unsigned
char
>::
digits
);
};
};
// Returns the number of significand bits in Float excluding implicit bit.
// Returns the number of significand bits in Float excluding
the
implicit bit.
template
<
typename
Float
>
constexpr
int
num_significand_bits
()
{
template
<
typename
Float
>
constexpr
int
num_significand_bits
()
{
// Subtract 1 to account for an implicit most significant bit in the
// Subtract 1 to account for an implicit most significant bit in the
// normalized form.
// normalized form.
return
std
::
numeric_limits
<
Float
>::
digits
-
1
;
return
std
::
numeric_limits
<
Float
>::
digits
-
1
;
}
}
// A handmade floating-point number f * pow(2, e).
// A floating-point number f * pow(2, e).
class
fp
{
struct
fp
{
private:
uint64_t
f
;
using
significand_type
=
uint64_t
;
template
<
typename
Float
>
using
is_supported_float
=
bool_constant
<
sizeof
(
Float
)
==
sizeof
(
uint64_t
)
||
sizeof
(
Float
)
==
sizeof
(
uint32_t
)
>
;
public:
significand_type
f
;
int
e
;
int
e
;
static
FMT_CONSTEXPR_DECL
const
uint64_t
implicit_bit
=
static
constexpr
const
int
num_significand_bits
=
bits
<
decltype
(
f
)
>::
value
;
1ULL
<<
num_significand_bits
<
double
>
();
static
FMT_CONSTEXPR_DECL
const
int
num_significand_bits
=
bits
<
significand_type
>::
value
;
constexpr
fp
()
:
f
(
0
),
e
(
0
)
{}
constexpr
fp
()
:
f
(
0
),
e
(
0
)
{}
constexpr
fp
(
uint64_t
f_val
,
int
e_val
)
:
f
(
f_val
),
e
(
e_val
)
{}
constexpr
fp
(
uint64_t
f_val
,
int
e_val
)
:
f
(
f_val
),
e
(
e_val
)
{}
// Constructs fp from an IEEE754 double. It is a template to prevent compile
// Constructs fp from an IEEE754 floating-point number. It is a template to
// errors on platforms where double is not IEEE754.
// prevent compile errors on systems where n is not IEEE754.
template
<
typename
Double
>
explicit
FMT_CONSTEXPR
fp
(
Double
d
)
{
assign
(
d
);
}
template
<
typename
Float
>
explicit
FMT_CONSTEXPR
fp
(
Float
n
)
{
assign
(
n
);
}
template
<
typename
Float
>
using
is_supported
=
bool_constant
<
sizeof
(
Float
)
==
sizeof
(
uint64_t
)
||
sizeof
(
Float
)
==
sizeof
(
uint32_t
)
>
;
// Assigns d to this and return true iff predecessor is closer than successor.
// Assigns d to this and return true iff predecessor is closer than successor.
template
<
typename
Float
,
FMT_ENABLE_IF
(
is_supported
_float
<
Float
>
::
value
)
>
template
<
typename
Float
,
FMT_ENABLE_IF
(
is_supported
<
Float
>
::
value
)
>
FMT_CONSTEXPR
bool
assign
(
Float
n
)
{
FMT_CONSTEXPR
bool
assign
(
Float
n
)
{
// Assume float is in the format [sign][exponent][significand].
// Assume float is in the format [sign][exponent][significand].
const
int
num_float_significand_bits
=
const
int
num_float_significand_bits
=
detail
::
num_significand_bits
<
Float
>
();
detail
::
num_significand_bits
<
Float
>
();
const
uint64_t
float_
implicit_bit
=
1ULL
<<
num_float_significand_bits
;
const
uint64_t
implicit_bit
=
1ULL
<<
num_float_significand_bits
;
const
uint64_t
significand_mask
=
float_
implicit_bit
-
1
;
const
uint64_t
significand_mask
=
implicit_bit
-
1
;
constexpr
bool
is_double
=
sizeof
(
Float
)
==
sizeof
(
uint64_t
);
constexpr
bool
is_double
=
sizeof
(
Float
)
==
sizeof
(
uint64_t
);
auto
u
=
bit_cast
<
conditional_t
<
is_double
,
uint64_t
,
uint32_t
>>
(
n
);
auto
u
=
bit_cast
<
conditional_t
<
is_double
,
uint64_t
,
uint32_t
>>
(
n
);
f
=
u
&
significand_mask
;
f
=
u
&
significand_mask
;
...
@@ -276,7 +269,7 @@ class fp {
...
@@ -276,7 +269,7 @@ class fp {
// than the smallest normalized number (biased_e > 1).
// than the smallest normalized number (biased_e > 1).
bool
is_predecessor_closer
=
f
==
0
&&
biased_e
>
1
;
bool
is_predecessor_closer
=
f
==
0
&&
biased_e
>
1
;
if
(
biased_e
!=
0
)
if
(
biased_e
!=
0
)
f
+=
float_
implicit_bit
;
f
+=
implicit_bit
;
else
else
biased_e
=
1
;
// Subnormals use biased exponent 1 (min exponent).
biased_e
=
1
;
// Subnormals use biased exponent 1 (min exponent).
const
int
exponent_bias
=
std
::
numeric_limits
<
Float
>::
max_exponent
-
1
;
const
int
exponent_bias
=
std
::
numeric_limits
<
Float
>::
max_exponent
-
1
;
...
@@ -284,9 +277,9 @@ class fp {
...
@@ -284,9 +277,9 @@ class fp {
return
is_predecessor_closer
;
return
is_predecessor_closer
;
}
}
template
<
typename
Float
,
FMT_ENABLE_IF
(
!
is_supported
_float
<
Float
>
::
value
)
>
template
<
typename
Float
,
FMT_ENABLE_IF
(
!
is_supported
<
Float
>
::
value
)
>
bool
assign
(
Float
)
{
bool
assign
(
Float
)
{
*
this
=
fp
(
);
FMT_ASSERT
(
false
,
""
);
return
false
;
return
false
;
}
}
};
};
...
@@ -294,7 +287,8 @@ class fp {
...
@@ -294,7 +287,8 @@ class fp {
// Normalizes the value converted from double and multiplied by (1 << SHIFT).
// Normalizes the value converted from double and multiplied by (1 << SHIFT).
template
<
int
SHIFT
=
0
>
FMT_CONSTEXPR
fp
normalize
(
fp
value
)
{
template
<
int
SHIFT
=
0
>
FMT_CONSTEXPR
fp
normalize
(
fp
value
)
{
// Handle subnormals.
// Handle subnormals.
const
auto
shifted_implicit_bit
=
fp
::
implicit_bit
<<
SHIFT
;
const
uint64_t
implicit_bit
=
1ULL
<<
num_significand_bits
<
double
>
();
const
auto
shifted_implicit_bit
=
implicit_bit
<<
SHIFT
;
while
((
value
.
f
&
shifted_implicit_bit
)
==
0
)
{
while
((
value
.
f
&
shifted_implicit_bit
)
==
0
)
{
value
.
f
<<=
1
;
value
.
f
<<=
1
;
--
value
.
e
;
--
value
.
e
;
...
...
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