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
5fd89d50
Commit
5fd89d50
authored
Sep 23, 2020
by
Victor Zverovich
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Minor simplifications
parent
605ce5e4
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
38 additions
and
73 deletions
+38
-73
include/fmt/format-inl.h
include/fmt/format-inl.h
+38
-73
No files found.
include/fmt/format-inl.h
View file @
5fd89d50
...
@@ -1718,21 +1718,7 @@ FMT_SAFEBUFFERS inline uint64_t umul128_upper64(uint64_t x,
...
@@ -1718,21 +1718,7 @@ FMT_SAFEBUFFERS inline uint64_t umul128_upper64(uint64_t x,
#elif defined(_MSC_VER) && defined(_M_X64)
#elif defined(_MSC_VER) && defined(_M_X64)
return
__umulh
(
x
,
y
);
return
__umulh
(
x
,
y
);
#else
#else
const
uint64_t
mask
=
(
1ull
<<
32
)
-
1ull
;
return
umul128
(
x
,
y
).
high
();
uint64_t
a
=
x
>>
32
;
uint64_t
b
=
x
&
mask
;
uint64_t
c
=
y
>>
32
;
uint64_t
d
=
y
&
mask
;
uint64_t
ac
=
a
*
c
;
uint64_t
bc
=
b
*
c
;
uint64_t
ad
=
a
*
d
;
uint64_t
bd
=
b
*
d
;
uint64_t
intermediate
=
(
bd
>>
32
)
+
(
ad
&
mask
)
+
(
bc
&
mask
);
return
ac
+
(
intermediate
>>
32
)
+
(
ad
>>
32
)
+
(
bc
>>
32
);
#endif
#endif
}
}
...
@@ -1878,53 +1864,35 @@ inline bool divisible_by_power_of_2(uint64_t x, int exp) FMT_NOEXCEPT {
...
@@ -1878,53 +1864,35 @@ inline bool divisible_by_power_of_2(uint64_t x, int exp) FMT_NOEXCEPT {
#endif
#endif
}
}
//
Fast divisibility test for powers of 5 (float
).
//
Returns true iff x is divisible by pow(5, exp
).
inline
bool
divisible_by_power_of_5
(
uint32_t
x
,
int
exp
)
FMT_NOEXCEPT
{
inline
bool
divisible_by_power_of_5
(
uint32_t
x
,
int
exp
)
FMT_NOEXCEPT
{
FMT_ASSERT
(
exp
<=
10
,
"too large exponent"
);
FMT_ASSERT
(
exp
<=
10
,
"too large exponent"
);
return
(
x
*
data
::
divtest_table_for_pow5_32
[
exp
].
mod_inv
)
<=
return
x
*
data
::
divtest_table_for_pow5_32
[
exp
].
mod_inv
<=
data
::
divtest_table_for_pow5_32
[
exp
].
max_quotient
;
data
::
divtest_table_for_pow5_32
[
exp
].
max_quotient
;
}
}
// Fast divisibility test for powers of 5 (double).
inline
bool
divisible_by_power_of_5
(
uint64_t
x
,
int
exp
)
FMT_NOEXCEPT
{
inline
bool
divisible_by_power_of_5
(
uint64_t
x
,
int
exp
)
FMT_NOEXCEPT
{
FMT_ASSERT
(
exp
<=
23
,
"too large exponent"
);
FMT_ASSERT
(
exp
<=
23
,
"too large exponent"
);
return
(
x
*
data
::
divtest_table_for_pow5_64
[
exp
].
mod_inv
)
<=
return
x
*
data
::
divtest_table_for_pow5_64
[
exp
].
mod_inv
<=
data
::
divtest_table_for_pow5_64
[
exp
].
max_quotient
;
data
::
divtest_table_for_pow5_64
[
exp
].
max_quotient
;
}
}
// Replaces n by floor(n / 5^N)
// Replaces n by floor(n / pow(5, N)) returning true if and only if n is
// Returns true if and only if n is divisible by 5^N
// divisible by pow(5, N).
// Precondition: n <= 2 * 5^(N+1)
// Precondition: n <= 2 * pow(5, N + 1).
template
<
int
N
>
struct
check_divisibility_and_divide_by_pow5_info
;
template
<
>
struct
check_divisibility_and_divide_by_pow5_info
<
1
>
{
static
const
uint32_t
magic_number
=
0xcccd
;
static
const
int
bits_for_comparison
=
16
;
static
const
uint32_t
threshold
=
0x3333
;
static
const
int
shift_amount
=
18
;
};
template
<
>
struct
check_divisibility_and_divide_by_pow5_info
<
2
>
{
static
const
uint32_t
magic_number
=
0xa429
;
static
const
int
bits_for_comparison
=
8
;
static
const
uint32_t
threshold
=
0x0a
;
static
const
int
shift_amount
=
20
;
};
template
<
int
N
>
template
<
int
N
>
bool
check_divisibility_and_divide_by_pow5
(
uint32_t
&
n
)
FMT_NOEXCEPT
{
bool
check_divisibility_and_divide_by_pow5
(
uint32_t
&
n
)
FMT_NOEXCEPT
{
using
info
=
check_divisibility_and_divide_by_pow5_info
<
N
>
;
static
constexpr
struct
{
n
*=
info
::
magic_number
;
uint32_t
magic_number
;
const
uint32_t
comparison_mask
=
int
bits_for_comparison
;
info
::
bits_for_comparison
>=
32
?
std
::
numeric_limits
<
uint32_t
>::
max
()
uint32_t
threshold
;
:
((
1u
<<
info
::
bits_for_comparison
)
-
1
);
int
shift_amount
;
}
infos
[]
=
{{
0xcccd
,
16
,
0x3333
,
18
},
{
0xa429
,
8
,
0x0a
,
20
}};
if
((
n
&
comparison_mask
)
<=
info
::
threshold
)
{
constexpr
auto
info
=
infos
[
N
-
1
];
n
>>=
info
::
shift_amount
;
n
*=
info
.
magic_number
;
return
true
;
const
uint32_t
comparison_mask
=
(
1u
<<
info
.
bits_for_comparison
)
-
1
;
}
else
{
bool
result
=
(
n
&
comparison_mask
)
<=
info
.
threshold
;
n
>>=
info
::
shift_amount
;
n
>>=
info
.
shift_amount
;
return
false
;
return
result
;
}
}
}
// Computes floor(n / 10^N) for small n and N
// Computes floor(n / 10^N) for small n and N
...
@@ -1944,7 +1912,8 @@ template <> struct small_division_by_pow10_info<2> {
...
@@ -1944,7 +1912,8 @@ template <> struct small_division_by_pow10_info<2> {
};
};
template
<
int
N
>
uint32_t
small_division_by_pow10
(
uint32_t
n
)
FMT_NOEXCEPT
{
template
<
int
N
>
uint32_t
small_division_by_pow10
(
uint32_t
n
)
FMT_NOEXCEPT
{
FMT_ASSERT
(
n
<=
small_division_by_pow10_info
<
N
>::
divisor_times_10
,
"n is too large"
);
FMT_ASSERT
(
n
<=
small_division_by_pow10_info
<
N
>::
divisor_times_10
,
"n is too large"
);
return
(
n
*
small_division_by_pow10_info
<
N
>::
magic_number
)
>>
return
(
n
*
small_division_by_pow10_info
<
N
>::
magic_number
)
>>
small_division_by_pow10_info
<
N
>::
shift_amount
;
small_division_by_pow10_info
<
N
>::
shift_amount
;
}
}
...
@@ -2285,8 +2254,9 @@ FMT_ALWAYS_INLINE int remove_trailing_zeros(uint64_t& n) FMT_NOEXCEPT {
...
@@ -2285,8 +2254,9 @@ FMT_ALWAYS_INLINE int remove_trailing_zeros(uint64_t& n) FMT_NOEXCEPT {
// The main algorithm for shorter interval case
// The main algorithm for shorter interval case
template
<
class
T
>
template
<
class
T
>
FMT_ALWAYS_INLINE
FMT_SAFEBUFFERS
void
shorter_interval_case
(
FMT_ALWAYS_INLINE
FMT_SAFEBUFFERS
decimal_fp
<
T
>
shorter_interval_case
(
decimal_fp
<
T
>&
ret_value
,
int
exponent
)
FMT_NOEXCEPT
{
int
exponent
)
FMT_NOEXCEPT
{
decimal_fp
<
T
>
ret_value
;
// Compute k and beta
// Compute k and beta
const
int
minus_k
=
floor_log10_pow2_minus_log10_4_over_3
(
exponent
);
const
int
minus_k
=
floor_log10_pow2_minus_log10_4_over_3
(
exponent
);
const
int
beta_minus_1
=
exponent
+
floor_log2_pow10
(
-
minus_k
);
const
int
beta_minus_1
=
exponent
+
floor_log2_pow10
(
-
minus_k
);
...
@@ -2312,7 +2282,7 @@ FMT_ALWAYS_INLINE FMT_SAFEBUFFERS void shorter_interval_case(
...
@@ -2312,7 +2282,7 @@ FMT_ALWAYS_INLINE FMT_SAFEBUFFERS void shorter_interval_case(
if
(
ret_value
.
significand
*
10
>=
xi
)
{
if
(
ret_value
.
significand
*
10
>=
xi
)
{
ret_value
.
exponent
=
minus_k
+
1
;
ret_value
.
exponent
=
minus_k
+
1
;
ret_value
.
exponent
+=
remove_trailing_zeros
(
ret_value
.
significand
);
ret_value
.
exponent
+=
remove_trailing_zeros
(
ret_value
.
significand
);
return
;
return
ret_value
;
}
}
// Otherwise, compute the round-up of y
// Otherwise, compute the round-up of y
...
@@ -2330,19 +2300,17 @@ FMT_ALWAYS_INLINE FMT_SAFEBUFFERS void shorter_interval_case(
...
@@ -2330,19 +2300,17 @@ FMT_ALWAYS_INLINE FMT_SAFEBUFFERS void shorter_interval_case(
}
else
if
(
ret_value
.
significand
<
xi
)
{
}
else
if
(
ret_value
.
significand
<
xi
)
{
++
ret_value
.
significand
;
++
ret_value
.
significand
;
}
}
return
ret_value
;
}
}
// The main algorithm for the normal case
template
<
class
T
>
FMT_SAFEBUFFERS
decimal_fp
<
T
>
to_decimal
(
T
x
)
FMT_NOEXCEPT
{
template
<
class
T
>
FMT_SAFEBUFFERS
decimal_fp
<
T
>
to_decimal
(
T
x
)
FMT_NOEXCEPT
{
// Step 1: integer promotion & Schubfach multiplier calculation
// Step 1: integer promotion & Schubfach multiplier calculation
.
using
carrier_uint
=
typename
float_info
<
T
>::
carrier_uint
;
using
carrier_uint
=
typename
float_info
<
T
>::
carrier_uint
;
using
cache_entry_type
=
typename
cache_accessor
<
T
>::
cache_entry_type
;
using
cache_entry_type
=
typename
cache_accessor
<
T
>::
cache_entry_type
;
auto
br
=
bit_cast
<
carrier_uint
>
(
x
);
carrier_uint
br
=
bit_cast
<
carrier_uint
>
(
x
);
// Extract significand bits and exponent bits.
decimal_fp
<
T
>
ret_value
;
// Extract significand bits and exponent bits
const
carrier_uint
significand_mask
=
const
carrier_uint
significand_mask
=
(
static_cast
<
carrier_uint
>
(
1
)
<<
float_info
<
T
>::
significand_bits
)
-
1
;
(
static_cast
<
carrier_uint
>
(
1
)
<<
float_info
<
T
>::
significand_bits
)
-
1
;
carrier_uint
significand
=
(
br
&
significand_mask
);
carrier_uint
significand
=
(
br
&
significand_mask
);
...
@@ -2352,28 +2320,24 @@ template <class T> FMT_SAFEBUFFERS decimal_fp<T> to_decimal(T x) FMT_NOEXCEPT {
...
@@ -2352,28 +2320,24 @@ template <class T> FMT_SAFEBUFFERS decimal_fp<T> to_decimal(T x) FMT_NOEXCEPT {
int
exponent
=
int
exponent
=
static_cast
<
int
>
((
br
&
exponent_mask
)
>>
float_info
<
T
>::
significand_bits
);
static_cast
<
int
>
((
br
&
exponent_mask
)
>>
float_info
<
T
>::
significand_bits
);
// Deal with normal/subnormal dichotomy
if
(
exponent
!=
0
)
{
// Check if normal.
if
(
exponent
!=
0
)
{
exponent
+=
float_info
<
T
>::
exponent_bias
-
float_info
<
T
>::
significand_bits
;
exponent
+=
float_info
<
T
>::
exponent_bias
-
float_info
<
T
>::
significand_bits
;
// Shorter interval case; proceed like Schubfach
// Shorter interval case; proceed like Schubfach.
if
(
significand
==
0
)
{
if
(
significand
==
0
)
shorter_interval_case
<
T
>
(
ret_value
,
exponent
);
return
shorter_interval_case
<
T
>
(
exponent
);
return
ret_value
;
}
significand
|=
significand
|=
(
static_cast
<
carrier_uint
>
(
1
)
<<
float_info
<
T
>::
significand_bits
);
(
static_cast
<
carrier_uint
>
(
1
)
<<
float_info
<
T
>::
significand_bits
);
}
}
else
{
// Subnormal case; interval is always regular
// Subnormal case; the interval is always regular.
else
{
exponent
=
float_info
<
T
>::
min_exponent
-
float_info
<
T
>::
significand_bits
;
exponent
=
float_info
<
T
>::
min_exponent
-
float_info
<
T
>::
significand_bits
;
}
}
const
bool
include_left_endpoint
=
(
significand
%
2
==
0
);
const
bool
include_left_endpoint
=
(
significand
%
2
==
0
);
const
bool
include_right_endpoint
=
(
significand
%
2
==
0
)
;
const
bool
include_right_endpoint
=
include_left_endpoint
;
// Compute k and beta
// Compute k and beta
.
const
int
minus_k
=
floor_log10_pow2
(
exponent
)
-
float_info
<
T
>::
kappa
;
const
int
minus_k
=
floor_log10_pow2
(
exponent
)
-
float_info
<
T
>::
kappa
;
const
cache_entry_type
cache
=
cache_accessor
<
T
>::
get_cached_power
(
-
minus_k
);
const
cache_entry_type
cache
=
cache_accessor
<
T
>::
get_cached_power
(
-
minus_k
);
const
int
beta_minus_1
=
exponent
+
floor_log2_pow10
(
-
minus_k
);
const
int
beta_minus_1
=
exponent
+
floor_log2_pow10
(
-
minus_k
);
...
@@ -2390,6 +2354,7 @@ template <class T> FMT_SAFEBUFFERS decimal_fp<T> to_decimal(T x) FMT_NOEXCEPT {
...
@@ -2390,6 +2354,7 @@ template <class T> FMT_SAFEBUFFERS decimal_fp<T> to_decimal(T x) FMT_NOEXCEPT {
// Using an upper bound on zi, we might be able to optimize the division
// Using an upper bound on zi, we might be able to optimize the division
// better than the compiler; we are computing zi / big_divisor here
// better than the compiler; we are computing zi / big_divisor here
decimal_fp
<
T
>
ret_value
;
ret_value
.
significand
=
divide_by_10_to_kappa_plus_1
(
zi
);
ret_value
.
significand
=
divide_by_10_to_kappa_plus_1
(
zi
);
uint32_t
r
=
static_cast
<
uint32_t
>
(
zi
-
float_info
<
T
>::
big_divisor
*
uint32_t
r
=
static_cast
<
uint32_t
>
(
zi
-
float_info
<
T
>::
big_divisor
*
ret_value
.
significand
);
ret_value
.
significand
);
...
...
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