mul.rs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. use core::ops;
  2. use int::LargeInt;
  3. use int::Int;
  4. trait Mul: LargeInt {
  5. fn mul(self, other: Self) -> Self {
  6. let half_bits = Self::BITS / 4;
  7. let lower_mask = !<<Self as LargeInt>::LowHalf>::ZERO >> half_bits;
  8. let mut low = (self.low() & lower_mask).wrapping_mul(other.low() & lower_mask);
  9. let mut t = low >> half_bits;
  10. low &= lower_mask;
  11. t += (self.low() >> half_bits).wrapping_mul(other.low() & lower_mask);
  12. low += (t & lower_mask) << half_bits;
  13. let mut high = Self::low_as_high(t >> half_bits);
  14. t = low >> half_bits;
  15. low &= lower_mask;
  16. t += (other.low() >> half_bits).wrapping_mul(self.low() & lower_mask);
  17. low += (t & lower_mask) << half_bits;
  18. high += Self::low_as_high(t >> half_bits);
  19. high += Self::low_as_high((self.low() >> half_bits).wrapping_mul(other.low() >> half_bits));
  20. high = high.wrapping_add(self.high().wrapping_mul(Self::low_as_high(other.low())))
  21. .wrapping_add(Self::low_as_high(self.low()).wrapping_mul(other.high()));
  22. Self::from_parts(low, high)
  23. }
  24. }
  25. impl Mul for u64 {}
  26. impl Mul for i128 {}
  27. trait Mulo: Int + ops::Neg<Output = Self> {
  28. fn mulo(self, other: Self, overflow: &mut i32) -> Self {
  29. *overflow = 0;
  30. let result = self.wrapping_mul(other);
  31. if self == Self::min_value() {
  32. if other != Self::ZERO && other != Self::ONE {
  33. *overflow = 1;
  34. }
  35. return result;
  36. }
  37. if other == Self::min_value() {
  38. if self != Self::ZERO && self != Self::ONE {
  39. *overflow = 1;
  40. }
  41. return result;
  42. }
  43. let sa = self >> (Self::BITS - 1);
  44. let abs_a = (self ^ sa) - sa;
  45. let sb = other >> (Self::BITS - 1);
  46. let abs_b = (other ^ sb) - sb;
  47. let two = Self::ONE + Self::ONE;
  48. if abs_a < two || abs_b < two {
  49. return result;
  50. }
  51. if sa == sb {
  52. if abs_a > Self::max_value().aborting_div(abs_b) {
  53. *overflow = 1;
  54. }
  55. } else {
  56. if abs_a > Self::min_value().aborting_div(-abs_b) {
  57. *overflow = 1;
  58. }
  59. }
  60. result
  61. }
  62. }
  63. impl Mulo for i32 {}
  64. impl Mulo for i64 {}
  65. impl Mulo for i128 {}
  66. trait UMulo : Int {
  67. fn mulo(self, other: Self, overflow: &mut i32) -> Self {
  68. *overflow = 0;
  69. let result = self.wrapping_mul(other);
  70. if self > Self::max_value().aborting_div(other) {
  71. *overflow = 1;
  72. }
  73. result
  74. }
  75. }
  76. impl UMulo for u128 {}
  77. intrinsics! {
  78. #[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))]
  79. #[arm_aeabi_alias = __aeabi_lmul]
  80. pub extern "C" fn __muldi3(a: u64, b: u64) -> u64 {
  81. a.mul(b)
  82. }
  83. #[aapcs_on_arm]
  84. pub extern "C" fn __multi3(a: i128, b: i128) -> i128 {
  85. a.mul(b)
  86. }
  87. pub extern "C" fn __mulosi4(a: i32, b: i32, oflow: &mut i32) -> i32 {
  88. a.mulo(b, oflow)
  89. }
  90. pub extern "C" fn __mulodi4(a: i64, b: i64, oflow: &mut i32) -> i64 {
  91. a.mulo(b, oflow)
  92. }
  93. #[unadjusted_on_win64]
  94. pub extern "C" fn __muloti4(a: i128, b: i128, oflow: &mut i32) -> i128 {
  95. a.mulo(b, oflow)
  96. }
  97. }
  98. #[cfg_attr(not(stage0), lang = "i128_mul")]
  99. pub fn rust_i128_mul(a: i128, b: i128) -> i128 {
  100. __multi3(a, b)
  101. }
  102. #[cfg_attr(not(stage0), lang = "i128_mulo")]
  103. pub fn rust_i128_mulo(a: i128, b: i128) -> (i128, bool) {
  104. let mut oflow = 0;
  105. let r = __muloti4(a, b, &mut oflow);
  106. (r, oflow != 0)
  107. }
  108. #[cfg_attr(not(stage0), lang = "u128_mul")]
  109. pub fn rust_u128_mul(a: u128, b: u128) -> u128 {
  110. __multi3(a as _, b as _) as _
  111. }
  112. #[cfg_attr(not(stage0), lang = "u128_mulo")]
  113. pub fn rust_u128_mulo(a: u128, b: u128) -> (u128, bool) {
  114. let mut oflow = 0;
  115. let r = a.mulo(b, &mut oflow);
  116. (r, oflow != 0)
  117. }