From 49a83c4174f648219ffccb1fc4a71a1bce648110 Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Wed, 24 Oct 2018 13:30:21 +0200 Subject: [PATCH] simplify fallback widening multiplication --- src/arith.rs | 51 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/src/arith.rs b/src/arith.rs index 665347f..07453d4 100644 --- a/src/arith.rs +++ b/src/arith.rs @@ -778,15 +778,14 @@ macro_rules! mul_div_fallback { let lh_rl = lh.wrapping_mul(rl); let ll_rh = ll.wrapping_mul(rh); let lh_rh = lh.wrapping_mul(rh); - let col01 = ll_rl as <$Single as FallbackHelper>::Unsigned; - let (col12, carry_col3) = lh_rl.carrying_add(ll_rh); - let col23 = lh_rh; - let (col12_hi, col12_lo) = col12.hi_lo(); - let col12_lo_up = col12_lo.shift_lo_up_unsigned(); - let (ans01, carry_col2) = col01.carrying_add(col12_lo_up); - let carries = carry_col2 as $Single + carry_col3.shift_lo_up(); - let ans23 = col23.wrapping_add(carries).wrapping_add(col12_hi); + let col01 = ll_rl as <$Single as FallbackHelper>::Unsigned; + let (col01_hi, col01_lo) = col01.hi_lo(); + let partial_col12 = lh_rl + col01_hi as $Single; + let (col12, carry_col3) = partial_col12.carrying_add(ll_rh); + let (col12_hi, col12_lo) = col12.hi_lo(); + let ans01 = col12_lo.shift_lo_up_unsigned() + col01_lo; + let ans23 = lh_rh + col12_hi + carry_col3.shift_lo_up(); ans23.combine_lo_then_shl(ans01, frac_bits) } } @@ -885,16 +884,20 @@ mod tests { let frac = Frac::to_u32(); let a = 0x0003456789abcdef_0123456789abcdef_u128; let b = 5; - let af = FixedU128::::from_bits(a << frac); - let bf = FixedU128::::from_bits(b << frac); - assert_eq!((af + bf).to_bits(), (a << frac) + (b << frac)); - assert_eq!((af - bf).to_bits(), (a << frac) - (b << frac)); - assert_eq!((af * bf).to_bits(), (a << frac) * b); - // assert_eq!((af / bf).to_bits(), (a << frac) / b); - assert_eq!((af & bf).to_bits(), (a << frac) & (b << frac)); - assert_eq!((af | bf).to_bits(), (a << frac) | (b << frac)); - assert_eq!((af ^ bf).to_bits(), (a << frac) ^ (b << frac)); - assert_eq!((!af).to_bits(), !(a << frac)); + for &(a, b) in &[(a, b), (b, a)] { + let af = FixedU128::::from_bits(a << frac); + let bf = FixedU128::::from_bits(b << frac); + assert_eq!((af + bf).to_bits(), (a << frac) + (b << frac)); + if a > b { + assert_eq!((af - bf).to_bits(), (a << frac) - (b << frac)); + } + assert_eq!((af * bf).to_bits(), (a << frac) * b); + // assert_eq!((af / bf).to_bits(), (a << frac) / b); + assert_eq!((af & bf).to_bits(), (a << frac) & (b << frac)); + assert_eq!((af | bf).to_bits(), (a << frac) | (b << frac)); + assert_eq!((af ^ bf).to_bits(), (a << frac) ^ (b << frac)); + assert_eq!((!af).to_bits(), !(a << frac)); + } } #[test] @@ -903,8 +906,16 @@ mod tests { let frac = Frac::to_u32(); let a = 0x0003456789abcdef_0123456789abcdef_i128; let b = 5; - for &pair in &[(a, b), (a, -b), (-a, b), (-a, -b)] { - let (a, b) = pair; + for &(a, b) in &[ + (a, b), + (a, -b), + (-a, b), + (-a, -b), + (b, a), + (b, -a), + (-b, a), + (-b, -a), + ] { let af = FixedI128::::from_bits(a << frac); let bf = FixedI128::::from_bits(b << frac); assert_eq!((af + bf).to_bits(), (a << frac) + (b << frac));