Skip to content

Commit 94e64f0

Browse files
degasuscopybara-github
authored andcommitted
PR #1777: Avoid std::ldexp in operator double(int128).
Imported from GitHub PR #1777 This patch replaces all instances of std::ldexp(msb, 64) with msb * (2**64) as it turns out that this optimization is not done by MSVC. Worse, it emited a function call with error checking, even if the int128 cannot hit the inf limitation. Sadly even the constant `std::ldexp(1.0, 64)` is not inlined: https://gcc.godbolt.org/z/oGhGz77sx Merge a21b1c9 into 8783136 Merging this change closes #1777 COPYBARA_INTEGRATE_REVIEW=#1777 from degasus:int128_t a21b1c9 PiperOrigin-RevId: 688968524 Change-Id: Id88cf38e241553f88bf4d97e7b001247dcd5599b
1 parent 8783136 commit 94e64f0

File tree

3 files changed

+19
-10
lines changed

3 files changed

+19
-10
lines changed

absl/numeric/int128.h

+7-3
Original file line numberDiff line numberDiff line change
@@ -789,16 +789,20 @@ constexpr uint128::operator unsigned __int128() const {
789789
// Conversion operators to floating point types.
790790

791791
inline uint128::operator float() const {
792-
return static_cast<float>(lo_) + std::ldexp(static_cast<float>(hi_), 64);
792+
// Note: This method might return Inf.
793+
constexpr float pow_2_64 = 18446744073709551616.0f;
794+
return static_cast<float>(lo_) + static_cast<float>(hi_) * pow_2_64;
793795
}
794796

795797
inline uint128::operator double() const {
796-
return static_cast<double>(lo_) + std::ldexp(static_cast<double>(hi_), 64);
798+
constexpr double pow_2_64 = 18446744073709551616.0;
799+
return static_cast<double>(lo_) + static_cast<double>(hi_) * pow_2_64;
797800
}
798801

799802
inline uint128::operator long double() const {
803+
constexpr long double pow_2_64 = 18446744073709551616.0L;
800804
return static_cast<long double>(lo_) +
801-
std::ldexp(static_cast<long double>(hi_), 64);
805+
static_cast<long double>(hi_) * pow_2_64;
802806
}
803807

804808
// Comparison operators.

absl/numeric/int128_have_intrinsic.inc

+6-4
Original file line numberDiff line numberDiff line change
@@ -170,27 +170,29 @@ inline int128::operator float() const {
170170
// complement overwhelms the precision of the mantissa.
171171
//
172172
// Also check to make sure we don't negate Int128Min()
173+
constexpr float pow_2_64 = 18446744073709551616.0f;
173174
return v_ < 0 && *this != Int128Min()
174175
? -static_cast<float>(-*this)
175176
: static_cast<float>(Int128Low64(*this)) +
176-
std::ldexp(static_cast<float>(Int128High64(*this)), 64);
177+
static_cast<float>(Int128High64(*this)) * pow_2_64;
177178
}
178179

179180
inline int128::operator double() const {
180181
// See comment in int128::operator float() above.
182+
constexpr double pow_2_64 = 18446744073709551616.0;
181183
return v_ < 0 && *this != Int128Min()
182184
? -static_cast<double>(-*this)
183185
: static_cast<double>(Int128Low64(*this)) +
184-
std::ldexp(static_cast<double>(Int128High64(*this)), 64);
186+
static_cast<double>(Int128High64(*this)) * pow_2_64;
185187
}
186188

187189
inline int128::operator long double() const {
188190
// See comment in int128::operator float() above.
191+
constexpr long double pow_2_64 = 18446744073709551616.0L;
189192
return v_ < 0 && *this != Int128Min()
190193
? -static_cast<long double>(-*this)
191194
: static_cast<long double>(Int128Low64(*this)) +
192-
std::ldexp(static_cast<long double>(Int128High64(*this)),
193-
64);
195+
static_cast<long double>(Int128High64(*this)) * pow_2_64;
194196
}
195197
#endif // Clang on PowerPC
196198

absl/numeric/int128_no_intrinsic.inc

+6-3
Original file line numberDiff line numberDiff line change
@@ -139,26 +139,29 @@ inline int128::operator float() const {
139139
// complement overwhelms the precision of the mantissa.
140140
//
141141
// Also check to make sure we don't negate Int128Min()
142+
constexpr float pow_2_64 = 18446744073709551616.0f;
142143
return hi_ < 0 && *this != Int128Min()
143144
? -static_cast<float>(-*this)
144145
: static_cast<float>(lo_) +
145-
std::ldexp(static_cast<float>(hi_), 64);
146+
static_cast<float>(hi_) * pow_2_64;
146147
}
147148

148149
inline int128::operator double() const {
149150
// See comment in int128::operator float() above.
151+
constexpr double pow_2_64 = 18446744073709551616.0;
150152
return hi_ < 0 && *this != Int128Min()
151153
? -static_cast<double>(-*this)
152154
: static_cast<double>(lo_) +
153-
std::ldexp(static_cast<double>(hi_), 64);
155+
static_cast<double>(hi_) * pow_2_64;
154156
}
155157

156158
inline int128::operator long double() const {
157159
// See comment in int128::operator float() above.
160+
constexpr long double pow_2_64 = 18446744073709551616.0L;
158161
return hi_ < 0 && *this != Int128Min()
159162
? -static_cast<long double>(-*this)
160163
: static_cast<long double>(lo_) +
161-
std::ldexp(static_cast<long double>(hi_), 64);
164+
static_cast<long double>(hi_) * pow_2_64;
162165
}
163166

164167
// Comparison operators.

0 commit comments

Comments
 (0)