@@ -466,8 +466,9 @@ pub fn compute_nearest_shorter<F: RawFloat>(float: F) -> ExtendedFloat80 {
466
466
let lower_threshold: i32 = -floor_log5_pow2_minus_log5_3 ( bits + 4 ) - 2 - bits;
467
467
let upper_threshold: i32 = -floor_log5_pow2 ( bits + 2 ) - 2 - bits;
468
468
469
- if exponent >= lower_threshold && exponent <= upper_threshold {
470
- significand = RoundMode :: Round . break_rounding_tie ( significand) ;
469
+ let round_down = RoundMode :: Round . prefer_round_down ( significand) ;
470
+ if round_down && exponent >= lower_threshold && exponent <= upper_threshold {
471
+ significand -= 1 ;
471
472
} else if significand < xi {
472
473
significand += 1 ;
473
474
}
@@ -525,24 +526,27 @@ pub fn compute_nearest_normal<F: RawFloat>(float: F) -> ExtendedFloat80 {
525
526
// Must be Round since we only use compute_round with a round-nearest direction.
526
527
let interval_type = IntervalType :: Symmetric ( is_even) ;
527
528
528
- // Short-circuit case.
529
- let short_circuit = || {
530
- let ( mant, exp) = F :: process_trailing_zeros ( significand, minus_k + F :: KAPPA as i32 + 1 ) ;
531
- extended_float ( mant, exp)
532
- } ;
533
-
534
529
// Check for short-circuit.
530
+ // We use this, since the `goto` statements in dragonbox are unidiomatic
531
+ // in Rust and lead to unmaintainable code. Using a simple closure is much
532
+ // simpler, however, we do store a boolean in some cases to determine
533
+ // if we need to short-circuit.
534
+ let mut should_short_circuit = true ;
535
535
if r < deltai {
536
536
// Exclude the right endpoint if necessary.
537
537
let include_right = interval_type. include_right_endpoint ( ) ;
538
538
if r == 0 && !include_right && is_z_integer {
539
539
significand -= 1 ;
540
540
r = big_divisor;
541
- } else {
542
- return short_circuit ( ) ;
541
+ should_short_circuit = false ;
543
542
}
544
- } else if r == deltai {
543
+ } else if r > deltai {
544
+ should_short_circuit = false ;
545
+ } else {
545
546
// r == deltai; compare fractional parts.
547
+ // Due to the more complex logic in the new dragonbox algorithm,
548
+ // it's much easier logically to store if we should short circuit,
549
+ // the default, and only mark
546
550
let two_fl = two_fc - 1 ;
547
551
let include_left = interval_type. include_left_endpoint ( ) ;
548
552
@@ -553,54 +557,60 @@ pub fn compute_nearest_normal<F: RawFloat>(float: F) -> ExtendedFloat80 {
553
557
// x is not an integer, so if z^(f) >= delta^(f) (even parity), we in fact
554
558
// have strict inequality.
555
559
let parity = F :: compute_mul_parity ( two_fl, & pow5, beta) . 0 ;
556
- if parity {
557
- return short_circuit ( ) ;
560
+ if ! parity {
561
+ should_short_circuit = false ;
558
562
}
559
563
} else {
560
564
let ( xi_parity, x_is_integer) = F :: compute_mul_parity ( two_fl, & pow5, beta) ;
561
- if xi_parity || x_is_integer {
562
- return short_circuit ( ) ;
565
+ if ! xi_parity && ! x_is_integer {
566
+ should_short_circuit = false
563
567
}
564
568
}
565
569
}
566
570
567
- // Step 3: Find the significand with the smaller divisor
568
- significand *= 10 ;
569
-
570
- let dist = r - ( deltai / 2 ) + ( small_divisor / 2 ) ;
571
- let approx_y_parity = ( ( dist ^ ( small_divisor / 2 ) ) & 1 ) != 0 ;
572
-
573
- // Is dist divisible by 10^kappa?
574
- let ( dist, is_dist_div_by_kappa) = F :: check_div_pow10 ( dist) ;
575
-
576
- // Add dist / 10^kappa to the significand.
577
- significand += dist as u64 ;
578
-
579
- if is_dist_div_by_kappa {
580
- // Check z^(f) >= epsilon^(f).
581
- // We have either yi == zi - epsiloni or yi == (zi - epsiloni) - 1,
582
- // where yi == zi - epsiloni if and only if z^(f) >= epsilon^(f).
583
- // Since there are only 2 possibilities, we only need to care about the
584
- // parity. Also, zi and r should have the same parity since the divisor is
585
- // an even number.
586
- let ( yi_parity, is_y_integer) = F :: compute_mul_parity ( two_fc, & pow5, beta) ;
587
-
588
- if yi_parity != approx_y_parity {
589
- significand -= 1 ;
590
- } else if is_y_integer {
591
- // If z^(f) >= epsilon^(f), we might have a tie
592
- // when z^(f) == epsilon^(f), or equivalently, when y is an integer.
593
- // For tie-to-up case, we can just choose the upper one.
594
- significand = RoundMode :: Round . break_rounding_tie ( significand) ;
571
+ if should_short_circuit {
572
+ // Short-circuit case.
573
+ let ( mant, exp) = F :: process_trailing_zeros ( significand, minus_k + F :: KAPPA as i32 + 1 ) ;
574
+ extended_float ( mant, exp)
575
+ } else {
576
+ // Step 3: Find the significand with the smaller divisor
577
+ significand *= 10 ;
578
+
579
+ let dist = r - ( deltai / 2 ) + ( small_divisor / 2 ) ;
580
+ let approx_y_parity = ( ( dist ^ ( small_divisor / 2 ) ) & 1 ) != 0 ;
581
+
582
+ // Is dist divisible by 10^kappa?
583
+ let ( dist, is_dist_div_by_kappa) = F :: check_div_pow10 ( dist) ;
584
+
585
+ // Add dist / 10^kappa to the significand.
586
+ significand += dist as u64 ;
587
+
588
+ if is_dist_div_by_kappa {
589
+ // Check z^(f) >= epsilon^(f).
590
+ // We have either yi == zi - epsiloni or yi == (zi - epsiloni) - 1,
591
+ // where yi == zi - epsiloni if and only if z^(f) >= epsilon^(f).
592
+ // Since there are only 2 possibilities, we only need to care about the
593
+ // parity. Also, zi and r should have the same parity since the divisor is
594
+ // an even number.
595
+ let ( yi_parity, is_y_integer) = F :: compute_mul_parity ( two_fc, & pow5, beta) ;
596
+ let round_down = RoundMode :: Round . prefer_round_down ( significand) ;
597
+
598
+ if yi_parity != approx_y_parity || ( is_y_integer && round_down) {
599
+ // If z^(f) >= epsilon^(f), we might have a tie
600
+ // when z^(f) == epsilon^(f), or equivalently, when y is an integer.
601
+ // For tie-to-up case, we can just choose the upper one.
602
+ //significand -= 1;
603
+ significand -= 1 ;
604
+ }
595
605
}
596
- }
597
606
598
- // Ensure we haven't re-assigned exponent or minus_k, since this
599
- // is a massive potential security vulnerability.
600
- debug_assert ! ( float. exponent( ) == exponent) ;
601
- debug_assert ! ( minus_k == floor_log10_pow2( exponent) - F :: KAPPA as i32 ) ;
607
+ // Ensure we haven't re-assigned exponent or minus_k, since this
608
+ // is a massive potential security vulnerability.
609
+ debug_assert ! ( float. exponent( ) == exponent) ;
610
+ debug_assert ! ( minus_k == floor_log10_pow2( exponent) - F :: KAPPA as i32 ) ;
602
611
603
- extended_float ( significand, minus_k + F :: KAPPA as i32 )
612
+ extended_float ( significand, minus_k + F :: KAPPA as i32 )
613
+ }
604
614
}
605
615
606
616
/// Compute the interval I = [w,w+).
@@ -628,10 +638,8 @@ pub fn compute_left_closed_directed<F: RawFloat>(float: F) -> ExtendedFloat80 {
628
638
// and 29711844 * 2^-81
629
639
// = 1.2288530660000000001731007559513386695471126586198806762695... * 10^-17
630
640
// for binary32.
631
- if F :: BITS == 32 {
632
- if exponent <= -80 {
633
- is_x_integer = false ;
634
- }
641
+ if F :: BITS == 32 && exponent <= -80 {
642
+ is_x_integer = false ;
635
643
}
636
644
637
645
if !is_x_integer {
@@ -653,15 +661,14 @@ pub fn compute_left_closed_directed<F: RawFloat>(float: F) -> ExtendedFloat80 {
653
661
r = big_divisor - r;
654
662
}
655
663
656
- // Short-circuit case.
657
- let short_circuit = || {
658
- let ( mant, exp) = F :: process_trailing_zeros ( significand, minus_k + F :: KAPPA as i32 + 1 ) ;
659
- extended_float ( mant, exp)
660
- } ;
661
-
662
664
// Check for short-circuit.
663
- if r < deltai {
664
- return short_circuit ( ) ;
665
+ // We use this, since the `goto` statements in dragonbox are unidiomatic
666
+ // in Rust and lead to unmaintainable code. Using a simple closure is much
667
+ // simpler, however, we do store a boolean in some cases to determine
668
+ // if we need to short-circuit.
669
+ let mut should_short_circuit = true ;
670
+ if r > deltai {
671
+ should_short_circuit = false ;
665
672
} else if r == deltai {
666
673
// Compare the fractional parts.
667
674
// This branch is never taken for the exceptional cases
@@ -670,21 +677,26 @@ pub fn compute_left_closed_directed<F: RawFloat>(float: F) -> ExtendedFloat80 {
670
677
// and 2f_c = 29711482, e = -80
671
678
// (1.2288529832819387448703332688104694625508273020386695861816... * 10^-17).
672
679
let ( zi_parity, is_z_integer) = F :: compute_mul_parity ( two_fc + 2 , & pow5, beta) ;
673
- if ! ( zi_parity && is_z_integer) {
674
- return short_circuit ( ) ;
680
+ if zi_parity || is_z_integer {
681
+ should_short_circuit = false ;
675
682
}
676
683
}
677
684
678
- // Step 3: Find the significand with the smaller divisor
679
- significand *= 10 ;
680
- significand -= F :: div_pow10 ( r) as u64 ;
685
+ if should_short_circuit {
686
+ let ( mant, exp) = F :: process_trailing_zeros ( significand, minus_k + F :: KAPPA as i32 + 1 ) ;
687
+ extended_float ( mant, exp)
688
+ } else {
689
+ // Step 3: Find the significand with the smaller divisor
690
+ significand *= 10 ;
691
+ significand -= F :: div_pow10 ( r) as u64 ;
681
692
682
- // Ensure we haven't re-assigned exponent or minus_k, since this
683
- // is a massive potential security vulnerability.
684
- debug_assert ! ( float. exponent( ) == exponent) ;
685
- debug_assert ! ( minus_k == floor_log10_pow2( exponent) - F :: KAPPA as i32 ) ;
693
+ // Ensure we haven't re-assigned exponent or minus_k, since this
694
+ // is a massive potential security vulnerability.
695
+ debug_assert ! ( float. exponent( ) == exponent) ;
696
+ debug_assert ! ( minus_k == floor_log10_pow2( exponent) - F :: KAPPA as i32 ) ;
686
697
687
- extended_float ( significand, minus_k + F :: KAPPA as i32 )
698
+ extended_float ( significand, minus_k + F :: KAPPA as i32 )
699
+ }
688
700
}
689
701
690
702
/// Compute the interval I = (w−,w]..
@@ -716,15 +728,14 @@ pub fn compute_right_closed_directed<F: RawFloat>(float: F, shorter: bool) -> Ex
716
728
let mut significand = F :: divide_by_pow10 ( zi, exp, n_max) ;
717
729
let r = ( zi - ( big_divisor as u64 ) . wrapping_mul ( significand) ) as u32 ;
718
730
719
- // Short-circuit case.
720
- let short_circuit = || {
721
- let ( mant, exp) = F :: process_trailing_zeros ( significand, minus_k + F :: KAPPA as i32 + 1 ) ;
722
- extended_float ( mant, exp)
723
- } ;
724
-
725
731
// Check for short-circuit.
726
- if r < deltai {
727
- return short_circuit ( ) ;
732
+ // We use this, since the `goto` statements in dragonbox are unidiomatic
733
+ // in Rust and lead to unmaintainable code. Using a simple closure is much
734
+ // simpler, however, we do store a boolean in some cases to determine
735
+ // if we need to short-circuit.
736
+ let mut should_short_circuit = true ;
737
+ if r > deltai {
738
+ should_short_circuit = false ;
728
739
} else if r == deltai {
729
740
// Compare the fractional parts.
730
741
let two_f = two_fc
@@ -733,21 +744,26 @@ pub fn compute_right_closed_directed<F: RawFloat>(float: F, shorter: bool) -> Ex
733
744
} else {
734
745
2
735
746
} ;
736
- if F :: compute_mul_parity ( two_f, & pow5, beta) . 0 {
737
- return short_circuit ( ) ;
747
+ if ! F :: compute_mul_parity ( two_f, & pow5, beta) . 0 {
748
+ should_short_circuit = false ;
738
749
}
739
750
}
740
751
741
- // Step 3: Find the significand with the smaller divisor
742
- significand *= 10 ;
743
- significand -= F :: div_pow10 ( r) as u64 ;
752
+ if should_short_circuit {
753
+ let ( mant, exp) = F :: process_trailing_zeros ( significand, minus_k + F :: KAPPA as i32 + 1 ) ;
754
+ extended_float ( mant, exp)
755
+ } else {
756
+ // Step 3: Find the significand with the smaller divisor
757
+ significand *= 10 ;
758
+ significand -= F :: div_pow10 ( r) as u64 ;
744
759
745
- // Ensure we haven't re-assigned exponent or minus_k, since this
746
- // is a massive potential security vulnerability.
747
- debug_assert ! ( float. exponent( ) == exponent) ;
748
- debug_assert ! ( minus_k == floor_log10_pow2( exponent - shorter as i32 ) - F :: KAPPA as i32 ) ;
760
+ // Ensure we haven't re-assigned exponent or minus_k, since this
761
+ // is a massive potential security vulnerability.
762
+ debug_assert ! ( float. exponent( ) == exponent) ;
763
+ debug_assert ! ( minus_k == floor_log10_pow2( exponent - shorter as i32 ) - F :: KAPPA as i32 ) ;
749
764
750
- extended_float ( significand, minus_k + F :: KAPPA as i32 )
765
+ extended_float ( significand, minus_k + F :: KAPPA as i32 )
766
+ }
751
767
}
752
768
753
769
// DIGITS
@@ -991,15 +1007,12 @@ pub const fn divide_by_pow10_64(n: u64, exp: u32, n_max: u64) -> u64 {
991
1007
// --------
992
1008
993
1009
impl RoundMode {
994
- /// Zero out the lowest bit.
995
- // NOTE: this is now `prefer_round_down` in dragonbox, but this
996
- // logic is simpler for Rust to handle.
1010
+ /// Determine if we should round down.
997
1011
#[ inline( always) ]
998
- pub const fn break_rounding_tie ( & self , significand : u64 ) -> u64 {
1012
+ pub const fn prefer_round_down ( & self , significand : u64 ) -> bool {
999
1013
match self {
1000
- // r.significand % 2 != 0 ? r.significand : r.significand - 1
1001
- RoundMode :: Round => significand & !1u64 ,
1002
- RoundMode :: Truncate => significand - 1u64 ,
1014
+ RoundMode :: Round => significand % 2 != 0 ,
1015
+ RoundMode :: Truncate => true ,
1003
1016
}
1004
1017
}
1005
1018
}
@@ -1062,23 +1075,19 @@ impl IntervalType {
1062
1075
// ENDPOINTS
1063
1076
// ---------
1064
1077
1065
- /// Compute the left or right endpoint from a 64-bit power-of-5.
1066
- #[ inline( always) ]
1067
- pub fn compute_endpoint_u64 < F : DragonboxFloat , const SHIFT : usize > ( pow5 : u64 , beta : i32 ) -> u64 {
1068
- let zero_carry = pow5 >> ( F :: MANTISSA_SIZE as usize + SHIFT ) ;
1069
- let mantissa_shift = 64 - F :: MANTISSA_SIZE as usize - 1 ;
1070
- ( pow5 - zero_carry) >> ( mantissa_shift as i32 - beta)
1071
- }
1072
-
1073
1078
/// Compute the left endpoint from a 64-bit power-of-5.
1074
1079
#[ inline( always) ]
1075
1080
pub fn compute_left_endpoint_u64 < F : DragonboxFloat > ( pow5 : u64 , beta : i32 ) -> u64 {
1076
- compute_endpoint_u64 :: < F , 2 > ( pow5, beta)
1081
+ let zero_carry = pow5 >> ( F :: MANTISSA_SIZE as usize + 2 ) ;
1082
+ let mantissa_shift = 64 - F :: MANTISSA_SIZE as usize - 1 ;
1083
+ ( pow5 - zero_carry) >> ( mantissa_shift as i32 - beta)
1077
1084
}
1078
1085
1079
1086
#[ inline( always) ]
1080
1087
pub fn compute_right_endpoint_u64 < F : DragonboxFloat > ( pow5 : u64 , beta : i32 ) -> u64 {
1081
- compute_endpoint_u64 :: < F , 1 > ( pow5, beta)
1088
+ let zero_carry = pow5 >> ( F :: MANTISSA_SIZE as usize + 1 ) ;
1089
+ let mantissa_shift = 64 - F :: MANTISSA_SIZE as usize - 1 ;
1090
+ ( pow5 + zero_carry) >> ( mantissa_shift as i32 - beta)
1082
1091
}
1083
1092
1084
1093
/// Determine if we should round up for the short interval case.
@@ -1140,7 +1149,7 @@ const F64_DIV10_INFO: Div10Info = Div10Info {
1140
1149
macro_rules! check_div_pow10 {
1141
1150
( $n: ident, $exp: literal, $float: ident, $info: ident) => { {
1142
1151
// Make sure the computation for max_n does not overflow.
1143
- debug_assert!( $exp + 1 <= floor_log10_pow2( 31 ) ) ;
1152
+ debug_assert!( $exp + 2 < floor_log10_pow2( 31 ) ) ;
1144
1153
debug_assert!( $n as u64 <= pow64( 10 , $exp + 1 ) ) ;
1145
1154
1146
1155
let n = $n. wrapping_mul( $info. magic_number) ;
@@ -1278,17 +1287,17 @@ impl DragonboxFloat for f32 {
1278
1287
#[ inline( always) ]
1279
1288
fn compute_mul ( u : u64 , pow5 : & Self :: Power ) -> ( u64 , bool ) {
1280
1289
let r = umul96_upper64 ( u, * pow5) ;
1281
- ( r >> 32 , r == 0 )
1290
+ ( r >> 32 , ( r as u32 ) == 0 )
1282
1291
}
1283
1292
1284
1293
#[ inline( always) ]
1285
1294
fn compute_mul_parity ( two_f : u64 , pow5 : & Self :: Power , beta : i32 ) -> ( bool , bool ) {
1286
1295
debug_assert ! ( ( 1 ..64 ) . contains( & beta) ) ;
1287
1296
1288
1297
let r = umul96_lower64 ( two_f, * pow5) ;
1289
- let parity = r >> ( ( 64 - beta) & 1 ) ;
1298
+ let parity = ( r >> ( 64 - beta) ) & 1 ;
1290
1299
let is_integer = r >> ( 32 - beta) ;
1291
- ( parity != 0 , is_integer ! = 0 )
1300
+ ( parity != 0 , is_integer = = 0 )
1292
1301
}
1293
1302
1294
1303
#[ inline( always) ]
@@ -1396,9 +1405,9 @@ impl DragonboxFloat for f64 {
1396
1405
debug_assert ! ( ( 1 ..64 ) . contains( & beta) ) ;
1397
1406
1398
1407
let ( rhi, rlo) = umul192_lower128 ( two_f, high ( pow5) , low ( pow5) ) ;
1399
- let parity = rhi >> ( ( 64 - beta) & 1 ) ;
1408
+ let parity = ( rhi >> ( 64 - beta) ) & 1 ;
1400
1409
let is_integer = ( rhi << beta) | ( rlo >> ( 64 - beta) ) ;
1401
- ( parity != 0 , is_integer ! = 0 )
1410
+ ( parity != 0 , is_integer = = 0 )
1402
1411
}
1403
1412
1404
1413
#[ inline( always) ]
0 commit comments