mul.rs 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  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. intrinsics! {
  67. #[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))]
  68. #[arm_aeabi_alias = __aeabi_lmul]
  69. pub extern "C" fn __muldi3(a: u64, b: u64) -> u64 {
  70. a.mul(b)
  71. }
  72. #[aapcs_on_arm]
  73. pub extern "C" fn __multi3(a: i128, b: i128) -> i128 {
  74. a.mul(b)
  75. }
  76. pub extern "C" fn __mulosi4(a: i32, b: i32, oflow: &mut i32) -> i32 {
  77. a.mulo(b, oflow)
  78. }
  79. pub extern "C" fn __mulodi4(a: i64, b: i64, oflow: &mut i32) -> i64 {
  80. a.mulo(b, oflow)
  81. }
  82. #[unadjusted_on_win64]
  83. pub extern "C" fn __muloti4(a: i128, b: i128, oflow: &mut i32) -> i128 {
  84. a.mulo(b, oflow)
  85. }
  86. }