@@ -220,18 +220,23 @@ macro_rules! impl_to_primitive_float_to_signed_int {
220
220
( $f: ident : $( fn $method: ident -> $i: ident ; ) * ) => { $(
221
221
#[ inline]
222
222
fn $method( & self ) -> Option <$i> {
223
- let t = self . trunc( ) ; // round toward zero.
224
- // MIN is a power of two, which we can cast and compare directly.
225
- if t >= $i:: MIN as $f {
226
- // The mantissa might not be able to represent all digits of MAX.
227
- let sig_bits = size_of:: <$i>( ) as u32 * 8 - 1 ;
228
- let max = if sig_bits > $f:: MANTISSA_DIGITS {
229
- let lost_bits = sig_bits - $f:: MANTISSA_DIGITS ;
230
- $i:: MAX & !( ( 1 << lost_bits) - 1 )
231
- } else {
232
- $i:: MAX
233
- } ;
234
- if t <= max as $f {
223
+ // Float as int truncates toward zero, so we want to allow values
224
+ // in the exclusive range `(MIN-1, MAX+1)`.
225
+ if size_of:: <$f>( ) > size_of:: <$i>( ) {
226
+ // With a larger size, we can represent the range exactly.
227
+ const MIN_M1 : $f = $i:: MIN as $f - 1.0 ;
228
+ const MAX_P1 : $f = $i:: MAX as $f + 1.0 ;
229
+ if * self > MIN_M1 && * self < MAX_P1 {
230
+ return Some ( * self as $i) ;
231
+ }
232
+ } else {
233
+ // We can't represent `MIN-1` exactly, but there's no fractional part
234
+ // at this magnitude, so we can just use a `MIN` inclusive boundary.
235
+ const MIN : $f = $i:: MIN as $f;
236
+ // We can't represent `MAX` exactly, but it will round up to exactly
237
+ // `MAX+1` (a power of two) when we cast it.
238
+ const MAX_P1 : $f = $i:: MAX as $f;
239
+ if * self >= MIN && * self < MAX_P1 {
235
240
return Some ( * self as $i) ;
236
241
}
237
242
}
@@ -244,17 +249,19 @@ macro_rules! impl_to_primitive_float_to_unsigned_int {
244
249
( $f: ident : $( fn $method: ident -> $u: ident ; ) * ) => { $(
245
250
#[ inline]
246
251
fn $method( & self ) -> Option <$u> {
247
- let t = self . trunc( ) ; // round toward zero.
248
- if t >= 0.0 {
249
- // The mantissa might not be able to represent all digits of MAX.
250
- let sig_bits = size_of:: <$u>( ) as u32 * 8 ;
251
- let max = if sig_bits > $f:: MANTISSA_DIGITS {
252
- let lost_bits = sig_bits - $f:: MANTISSA_DIGITS ;
253
- $u:: MAX & !( ( 1 << lost_bits) - 1 )
254
- } else {
255
- $u:: MAX
256
- } ;
257
- if t <= max as $f {
252
+ // Float as int truncates toward zero, so we want to allow values
253
+ // in the exclusive range `(-1, MAX+1)`.
254
+ if size_of:: <$f>( ) > size_of:: <$u>( ) {
255
+ // With a larger size, we can represent the range exactly.
256
+ const MAX_P1 : $f = $u:: MAX as $f + 1.0 ;
257
+ if * self > -1.0 && * self < MAX_P1 {
258
+ return Some ( * self as $u) ;
259
+ }
260
+ } else {
261
+ // We can't represent `MAX` exactly, but it will round up to exactly
262
+ // `MAX+1` (a power of two) when we cast it.
263
+ const MAX_P1 : $f = $u:: MAX as $f;
264
+ if * self > -1.0 && * self < MAX_P1 {
258
265
return Some ( * self as $u) ;
259
266
}
260
267
}
0 commit comments