11use float:: Float ;
2- use int:: { CastInto , Int , WideInt } ;
2+ use int:: { CastInto , DInt , HInt , Int } ;
33
44fn mul < F : Float > ( a : F , b : F ) -> F
55where
66 u32 : CastInto < F :: Int > ,
77 F :: Int : CastInto < u32 > ,
88 i32 : CastInto < F :: Int > ,
99 F :: Int : CastInto < i32 > ,
10- F :: Int : WideInt ,
10+ F :: Int : HInt ,
1111{
1212 let one = F :: Int :: ONE ;
1313 let zero = F :: Int :: ZERO ;
@@ -112,8 +112,9 @@ where
112112 // have (exponentBits + 2) integral digits, all but two of which must be
113113 // zero. Normalizing this result is just a conditional left-shift by one
114114 // and bumping the exponent accordingly.
115- let ( mut product_high, mut product_low) =
116- <F :: Int as WideInt >:: wide_mul ( a_significand, b_significand << exponent_bits) ;
115+ let ( mut product_low, mut product_high) = a_significand
116+ . widen_mul ( b_significand << exponent_bits)
117+ . lo_hi ( ) ;
117118
118119 let a_exponent_i32: i32 = a_exponent. cast ( ) ;
119120 let b_exponent_i32: i32 = b_exponent. cast ( ) ;
@@ -126,7 +127,8 @@ where
126127 if ( product_high & implicit_bit) != zero {
127128 product_exponent = product_exponent. wrapping_add ( 1 ) ;
128129 } else {
129- <F :: Int as WideInt >:: wide_shift_left ( & mut product_high, & mut product_low, 1 ) ;
130+ product_high = ( product_high << 1 ) | ( product_low >> ( bits - 1 ) ) ;
131+ product_low <<= 1 ;
130132 }
131133
132134 // If we have overflowed the type, return +/- infinity.
@@ -142,17 +144,23 @@ where
142144 // handle this case separately, but we make it a special case to
143145 // simplify the shift logic.
144146 let shift = one. wrapping_sub ( product_exponent. cast ( ) ) . cast ( ) ;
145- if shift >= bits as i32 {
147+ if shift >= bits {
146148 return F :: from_repr ( product_sign) ;
147149 }
148150
149151 // Otherwise, shift the significand of the result so that the round
150152 // bit is the high bit of productLo.
151- <F :: Int as WideInt >:: wide_shift_right_with_sticky (
152- & mut product_high,
153- & mut product_low,
154- shift,
155- )
153+ if shift < bits {
154+ let sticky = product_low << ( bits - shift) ;
155+ product_low = product_high << ( bits - shift) | product_low >> shift | sticky;
156+ product_high >>= shift;
157+ } else if shift < ( 2 * bits) {
158+ let sticky = product_high << ( 2 * bits - shift) | product_low;
159+ product_low = product_high >> ( shift - bits) | sticky;
160+ product_high = zero;
161+ } else {
162+ product_high = zero;
163+ }
156164 } else {
157165 // Result is normal before rounding; insert the exponent.
158166 product_high &= significand_mask;
0 commit comments