use core::cmp::Ordering::{Equal, Greater, Less}; use core::ops::{Sub, SubAssign}; use num_traits::CheckedSub;
#[cfg(target_arch = "x86_64")] use core::arch::x86_64 as arch;
#[cfg(target_arch = "x86")] use core::arch::x86 as arch;
// Subtract with borrow: #[cfg(target_arch = "x86_64")]
cfg_64!( #[inline] fn sbb(borrow: u8, a: u64, b: u64, out: &mut u64) -> u8 { // Safety: There are absolutely no safety concerns with calling `_subborrow_u64`. // It's just unsafe for API consistency with other intrinsics. unsafe { arch::_subborrow_u64(borrow, a, b, out) }
}
);
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
cfg_32!( #[inline] fn sbb(borrow: u8, a: u32, b: u32, out: &mut u32) -> u8 { // Safety: There are absolutely no safety concerns with calling `_subborrow_u32`. // It's just unsafe for API consistency with other intrinsics. unsafe { arch::_subborrow_u32(borrow, a, b, out) }
}
);
// fallback for environments where we don't have a subborrow intrinsic // (copied from the standard library's `borrowing_sub`) #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] #[inline] fn sbb(borrow: u8, lhs: BigDigit, rhs: BigDigit, out: &mut BigDigit) -> u8 { let (a, b) = lhs.overflowing_sub(rhs); let (c, d) = a.overflowing_sub(borrow as BigDigit);
*out = c;
u8::from(b || d)
}
let len = Ord::min(a.len(), b.len()); let (a_lo, a_hi) = a.split_at_mut(len); let (b_lo, b_hi) = b.split_at(len);
for (a, b) in a_lo.iter_mut().zip(b_lo) {
borrow = sbb(borrow, *a, *b, a);
}
if borrow != 0 { for a in a_hi {
borrow = sbb(borrow, *a, 0, a); if borrow == 0 { break;
}
}
}
// note: we're _required_ to fail on underflow
assert!(
borrow == 0 && b_hi.iter().all(|x| *x == 0), "Cannot subtract b from a because b is larger than a."
);
}
// Only for the Sub impl. `a` and `b` must have same length. #[inline] fn __sub2rev(a: &[BigDigit], b: &mut [BigDigit]) -> u8 {
debug_assert!(b.len() == a.len());
letmut borrow = 0;
for (ai, bi) in a.iter().zip(b) {
borrow = sbb(borrow, *ai, *bi, bi);
}
let len = Ord::min(a.len(), b.len()); let (a_lo, a_hi) = a.split_at(len); let (b_lo, b_hi) = b.split_at_mut(len);
let borrow = __sub2rev(a_lo, b_lo);
assert!(a_hi.is_empty());
// note: we're _required_ to fail on underflow
assert!(
borrow == 0 && b_hi.iter().all(|x| *x == 0), "Cannot subtract b from a because b is larger than a."
);
}
forward_val_val_binop!(impl Sub for BigUint, sub);
forward_ref_ref_binop!(impl Sub for BigUint, sub);
forward_val_assign!(impl SubAssign for BigUint, sub_assign);
impl Sub<&BigUint> for BigUint { type Output = BigUint;
promote_unsigned_scalars!(impl Sub for BigUint, sub);
promote_unsigned_scalars_assign!(impl SubAssign for BigUint, sub_assign);
forward_all_scalar_binop_to_val_val!(impl Sub<u32> for BigUint, sub);
forward_all_scalar_binop_to_val_val!(impl Sub<u64> for BigUint, sub);
forward_all_scalar_binop_to_val_val!(impl Sub<u128> for BigUint, sub);
impl Sub<u32> for BigUint { type Output = BigUint;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.