2017-06-23 13:36:37 +08:00
|
|
|
use core::ops;
|
|
|
|
|
2016-10-11 09:21:11 +08:00
|
|
|
use int::LargeInt;
|
|
|
|
use int::Int;
|
2016-08-13 16:51:54 +08:00
|
|
|
|
2017-06-23 13:36:37 +08:00
|
|
|
trait Mul: LargeInt {
|
|
|
|
fn mul(self, other: Self) -> Self {
|
2017-09-14 03:01:40 +08:00
|
|
|
let half_bits = Self::BITS / 4;
|
|
|
|
let lower_mask = !<<Self as LargeInt>::LowHalf>::ZERO >> half_bits;
|
2017-06-23 13:36:37 +08:00
|
|
|
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)
|
2016-08-13 16:51:54 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-23 13:36:37 +08:00
|
|
|
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() {
|
2017-09-14 03:01:40 +08:00
|
|
|
if other != Self::ZERO && other != Self::ONE {
|
2017-06-23 13:36:37 +08:00
|
|
|
*overflow = 1;
|
2016-08-13 16:51:54 +08:00
|
|
|
}
|
2017-06-23 13:36:37 +08:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
if other == Self::min_value() {
|
2017-09-14 03:01:40 +08:00
|
|
|
if self != Self::ZERO && self != Self::ONE {
|
2017-06-23 13:36:37 +08:00
|
|
|
*overflow = 1;
|
2016-08-13 16:51:54 +08:00
|
|
|
}
|
2017-06-23 13:36:37 +08:00
|
|
|
return result;
|
|
|
|
}
|
2016-08-13 16:51:54 +08:00
|
|
|
|
2017-09-14 03:01:40 +08:00
|
|
|
let sa = self >> (Self::BITS - 1);
|
2017-06-23 13:36:37 +08:00
|
|
|
let abs_a = (self ^ sa) - sa;
|
2017-09-14 03:01:40 +08:00
|
|
|
let sb = other >> (Self::BITS - 1);
|
2017-06-23 13:36:37 +08:00
|
|
|
let abs_b = (other ^ sb) - sb;
|
2017-09-14 03:01:40 +08:00
|
|
|
let two = Self::ONE + Self::ONE;
|
2017-06-23 13:36:37 +08:00
|
|
|
if abs_a < two || abs_b < two {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
if sa == sb {
|
2017-06-24 12:31:54 +08:00
|
|
|
if abs_a > Self::max_value().aborting_div(abs_b) {
|
2017-06-23 13:36:37 +08:00
|
|
|
*overflow = 1;
|
2016-08-13 16:51:54 +08:00
|
|
|
}
|
2017-06-23 13:36:37 +08:00
|
|
|
} else {
|
2017-06-24 12:31:54 +08:00
|
|
|
if abs_a > Self::min_value().aborting_div(-abs_b) {
|
2017-06-23 13:36:37 +08:00
|
|
|
*overflow = 1;
|
2016-08-13 16:51:54 +08:00
|
|
|
}
|
|
|
|
}
|
2017-06-23 13:36:37 +08:00
|
|
|
result
|
2016-08-13 16:51:54 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-23 13:36:37 +08:00
|
|
|
impl Mulo for i32 {}
|
|
|
|
impl Mulo for i64 {}
|
|
|
|
impl Mulo for i128 {}
|
2017-02-08 01:51:18 +08:00
|
|
|
|
2017-11-25 20:21:05 +08:00
|
|
|
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 {}
|
|
|
|
|
2017-06-23 13:36:37 +08:00
|
|
|
intrinsics! {
|
2017-06-23 22:52:38 +08:00
|
|
|
#[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))]
|
2017-06-24 06:16:07 +08:00
|
|
|
#[arm_aeabi_alias = __aeabi_lmul]
|
2017-06-23 13:36:37 +08:00
|
|
|
pub extern "C" fn __muldi3(a: u64, b: u64) -> u64 {
|
|
|
|
a.mul(b)
|
|
|
|
}
|
2017-01-04 09:42:03 +08:00
|
|
|
|
2017-06-23 13:36:37 +08:00
|
|
|
#[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)
|
|
|
|
}
|
2016-09-27 04:55:11 +08:00
|
|
|
|
2017-06-23 13:36:37 +08:00
|
|
|
pub extern "C" fn __mulodi4(a: i64, b: i64, oflow: &mut i32) -> i64 {
|
|
|
|
a.mulo(b, oflow)
|
|
|
|
}
|
2016-08-13 16:51:54 +08:00
|
|
|
|
2017-06-23 13:36:37 +08:00
|
|
|
#[unadjusted_on_win64]
|
|
|
|
pub extern "C" fn __muloti4(a: i128, b: i128, oflow: &mut i32) -> i128 {
|
|
|
|
a.mulo(b, oflow)
|
|
|
|
}
|
|
|
|
}
|
2017-11-25 20:21:05 +08:00
|
|
|
|
2017-12-09 00:19:28 +08:00
|
|
|
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)
|
|
|
|
}
|
2017-11-25 20:21:05 +08:00
|
|
|
}
|