| use core::ops; |
| |
| use int::Int; |
| use int::LargeInt; |
| |
| trait Mul: LargeInt { |
| fn mul(self, other: Self) -> Self { |
| let half_bits = Self::BITS / 4; |
| let lower_mask = !<<Self as LargeInt>::LowHalf>::ZERO >> half_bits; |
| let mut low = (self.low() & lower_mask).wrapping_mul(other.low() & lower_mask); |
| let mut t = low >> half_bits; |
| low &= lower_mask; |
| t += (self.low() >> half_bits).wrapping_mul(other.low() & lower_mask); |
| low += (t & lower_mask) << half_bits; |
| let mut high = Self::low_as_high(t >> half_bits); |
| t = low >> half_bits; |
| low &= lower_mask; |
| t += (other.low() >> half_bits).wrapping_mul(self.low() & lower_mask); |
| low += (t & lower_mask) << half_bits; |
| high += Self::low_as_high(t >> half_bits); |
| high += Self::low_as_high((self.low() >> half_bits).wrapping_mul(other.low() >> half_bits)); |
| high = high |
| .wrapping_add(self.high().wrapping_mul(Self::low_as_high(other.low()))) |
| .wrapping_add(Self::low_as_high(self.low()).wrapping_mul(other.high())); |
| Self::from_parts(low, high) |
| } |
| } |
| |
| impl Mul for u64 {} |
| impl Mul for i128 {} |
| |
| trait Mulo: Int + ops::Neg<Output = Self> { |
| fn mulo(self, other: Self, overflow: &mut i32) -> Self { |
| *overflow = 0; |
| let result = self.wrapping_mul(other); |
| if self == Self::min_value() { |
| if other != Self::ZERO && other != Self::ONE { |
| *overflow = 1; |
| } |
| return result; |
| } |
| if other == Self::min_value() { |
| if self != Self::ZERO && self != Self::ONE { |
| *overflow = 1; |
| } |
| return result; |
| } |
| |
| let sa = self >> (Self::BITS - 1); |
| let abs_a = (self ^ sa) - sa; |
| let sb = other >> (Self::BITS - 1); |
| let abs_b = (other ^ sb) - sb; |
| let two = Self::ONE + Self::ONE; |
| if abs_a < two || abs_b < two { |
| return result; |
| } |
| if sa == sb { |
| if abs_a > Self::max_value().aborting_div(abs_b) { |
| *overflow = 1; |
| } |
| } else { |
| if abs_a > Self::min_value().aborting_div(-abs_b) { |
| *overflow = 1; |
| } |
| } |
| result |
| } |
| } |
| |
| impl Mulo for i32 {} |
| impl Mulo for i64 {} |
| impl Mulo for i128 {} |
| |
| trait UMulo: Int { |
| fn mulo(self, other: Self, overflow: &mut i32) -> Self { |
| *overflow = 0; |
| let result = self.wrapping_mul(other); |
| if self > Self::max_value().aborting_div(other) { |
| *overflow = 1; |
| } |
| result |
| } |
| } |
| impl UMulo for u128 {} |
| |
| intrinsics! { |
| #[maybe_use_optimized_c_shim] |
| #[arm_aeabi_alias = __aeabi_lmul] |
| pub extern "C" fn __muldi3(a: u64, b: u64) -> u64 { |
| a.mul(b) |
| } |
| |
| #[aapcs_on_arm] |
| pub extern "C" fn __multi3(a: i128, b: i128) -> i128 { |
| a.mul(b) |
| } |
| |
| pub extern "C" fn __mulosi4(a: i32, b: i32, oflow: &mut i32) -> i32 { |
| a.mulo(b, oflow) |
| } |
| |
| pub extern "C" fn __mulodi4(a: i64, b: i64, oflow: &mut i32) -> i64 { |
| a.mulo(b, oflow) |
| } |
| |
| #[unadjusted_on_win64] |
| pub extern "C" fn __muloti4(a: i128, b: i128, oflow: &mut i32) -> i128 { |
| a.mulo(b, oflow) |
| } |
| } |
| |
| u128_lang_items! { |
| #[lang = "i128_mul"] |
| pub fn rust_i128_mul(a: i128, b: i128) -> i128 { |
| __multi3(a, b) |
| } |
| #[lang = "i128_mulo"] |
| pub fn rust_i128_mulo(a: i128, b: i128) -> (i128, bool) { |
| let mut oflow = 0; |
| let r = __muloti4(a, b, &mut oflow); |
| (r, oflow != 0) |
| } |
| #[lang = "u128_mul"] |
| pub fn rust_u128_mul(a: u128, b: u128) -> u128 { |
| __multi3(a as _, b as _) as _ |
| } |
| #[lang = "u128_mulo"] |
| pub fn rust_u128_mulo(a: u128, b: u128) -> (u128, bool) { |
| let mut oflow = 0; |
| let r = a.mulo(b, &mut oflow); |
| (r, oflow != 0) |
| } |
| } |