use super::CheckedUnsignedAbs::{Negative, Positive}; use super::Sign::NoSign; use super::{BigInt, UnsignedAbs}; use crate::{IsizePromotion, UsizePromotion}; use core::ops::{Div, DivAssign, Rem, RemAssign}; use num_integer::Integer; use num_traits::{CheckedDiv, CheckedEuclid, Euclid, Signed, ToPrimitive, Zero}; forward_all_binop_to_ref_ref!(impl Div for BigInt, div); impl Div<&BigInt> for &BigInt { type Output = BigInt; #[inline] fn div(self, other: &BigInt) -> BigInt { let (q, _) = self.div_rem(other); q } } impl DivAssign<&BigInt> for BigInt { #[inline] fn div_assign(&mut self, other: &BigInt) { *self = &*self / other; } } forward_val_assign!(impl DivAssign for BigInt, div_assign); promote_all_scalars!(impl Div for BigInt, div); promote_all_scalars_assign!(impl DivAssign for BigInt, div_assign); forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); impl Div for BigInt { type Output = BigInt; #[inline] fn div(self, other: u32) -> BigInt { BigInt::from_biguint(self.sign, self.data / other) } } impl DivAssign for BigInt { #[inline] fn div_assign(&mut self, other: u32) { self.data /= other; if self.data.is_zero() { self.sign = NoSign; } } } impl Div for u32 { type Output = BigInt; #[inline] fn div(self, other: BigInt) -> BigInt { BigInt::from_biguint(other.sign, self / other.data) } } impl Div for BigInt { type Output = BigInt; #[inline] fn div(self, other: u64) -> BigInt { BigInt::from_biguint(self.sign, self.data / other) } } impl DivAssign for BigInt { #[inline] fn div_assign(&mut self, other: u64) { self.data /= other; if self.data.is_zero() { self.sign = NoSign; } } } impl Div for u64 { type Output = BigInt; #[inline] fn div(self, other: BigInt) -> BigInt { BigInt::from_biguint(other.sign, self / other.data) } } impl Div for BigInt { type Output = BigInt; #[inline] fn div(self, other: u128) -> BigInt { BigInt::from_biguint(self.sign, self.data / other) } } impl DivAssign for BigInt { #[inline] fn div_assign(&mut self, other: u128) { self.data /= other; if self.data.is_zero() { self.sign = NoSign; } } } impl Div for u128 { type Output = BigInt; #[inline] fn div(self, other: BigInt) -> BigInt { BigInt::from_biguint(other.sign, self / other.data) } } forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); impl Div for BigInt { type Output = BigInt; #[inline] fn div(self, other: i32) -> BigInt { match other.checked_uabs() { Positive(u) => self / u, Negative(u) => -self / u, } } } impl DivAssign for BigInt { #[inline] fn div_assign(&mut self, other: i32) { match other.checked_uabs() { Positive(u) => *self /= u, Negative(u) => { self.sign = -self.sign; *self /= u; } } } } impl Div for i32 { type Output = BigInt; #[inline] fn div(self, other: BigInt) -> BigInt { match self.checked_uabs() { Positive(u) => u / other, Negative(u) => u / -other, } } } impl Div for BigInt { type Output = BigInt; #[inline] fn div(self, other: i64) -> BigInt { match other.checked_uabs() { Positive(u) => self / u, Negative(u) => -self / u, } } } impl DivAssign for BigInt { #[inline] fn div_assign(&mut self, other: i64) { match other.checked_uabs() { Positive(u) => *self /= u, Negative(u) => { self.sign = -self.sign; *self /= u; } } } } impl Div for i64 { type Output = BigInt; #[inline] fn div(self, other: BigInt) -> BigInt { match self.checked_uabs() { Positive(u) => u / other, Negative(u) => u / -other, } } } impl Div for BigInt { type Output = BigInt; #[inline] fn div(self, other: i128) -> BigInt { match other.checked_uabs() { Positive(u) => self / u, Negative(u) => -self / u, } } } impl DivAssign for BigInt { #[inline] fn div_assign(&mut self, other: i128) { match other.checked_uabs() { Positive(u) => *self /= u, Negative(u) => { self.sign = -self.sign; *self /= u; } } } } impl Div for i128 { type Output = BigInt; #[inline] fn div(self, other: BigInt) -> BigInt { match self.checked_uabs() { Positive(u) => u / other, Negative(u) => u / -other, } } } forward_all_binop_to_ref_ref!(impl Rem for BigInt, rem); impl Rem<&BigInt> for &BigInt { type Output = BigInt; #[inline] fn rem(self, other: &BigInt) -> BigInt { if let Some(other) = other.to_u32() { self % other } else if let Some(other) = other.to_i32() { self % other } else { let (_, r) = self.div_rem(other); r } } } impl RemAssign<&BigInt> for BigInt { #[inline] fn rem_assign(&mut self, other: &BigInt) { *self = &*self % other; } } forward_val_assign!(impl RemAssign for BigInt, rem_assign); promote_all_scalars!(impl Rem for BigInt, rem); promote_all_scalars_assign!(impl RemAssign for BigInt, rem_assign); forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); impl Rem for BigInt { type Output = BigInt; #[inline] fn rem(self, other: u32) -> BigInt { BigInt::from_biguint(self.sign, self.data % other) } } impl RemAssign for BigInt { #[inline] fn rem_assign(&mut self, other: u32) { self.data %= other; if self.data.is_zero() { self.sign = NoSign; } } } impl Rem for u32 { type Output = BigInt; #[inline] fn rem(self, other: BigInt) -> BigInt { BigInt::from(self % other.data) } } impl Rem for BigInt { type Output = BigInt; #[inline] fn rem(self, other: u64) -> BigInt { BigInt::from_biguint(self.sign, self.data % other) } } impl RemAssign for BigInt { #[inline] fn rem_assign(&mut self, other: u64) { self.data %= other; if self.data.is_zero() { self.sign = NoSign; } } } impl Rem for u64 { type Output = BigInt; #[inline] fn rem(self, other: BigInt) -> BigInt { BigInt::from(self % other.data) } } impl Rem for BigInt { type Output = BigInt; #[inline] fn rem(self, other: u128) -> BigInt { BigInt::from_biguint(self.sign, self.data % other) } } impl RemAssign for BigInt { #[inline] fn rem_assign(&mut self, other: u128) { self.data %= other; if self.data.is_zero() { self.sign = NoSign; } } } impl Rem for u128 { type Output = BigInt; #[inline] fn rem(self, other: BigInt) -> BigInt { BigInt::from(self % other.data) } } forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); impl Rem for BigInt { type Output = BigInt; #[inline] fn rem(self, other: i32) -> BigInt { self % other.uabs() } } impl RemAssign for BigInt { #[inline] fn rem_assign(&mut self, other: i32) { *self %= other.uabs(); } } impl Rem for i32 { type Output = BigInt; #[inline] fn rem(self, other: BigInt) -> BigInt { match self.checked_uabs() { Positive(u) => u % other, Negative(u) => -(u % other), } } } impl Rem for BigInt { type Output = BigInt; #[inline] fn rem(self, other: i64) -> BigInt { self % other.uabs() } } impl RemAssign for BigInt { #[inline] fn rem_assign(&mut self, other: i64) { *self %= other.uabs(); } } impl Rem for i64 { type Output = BigInt; #[inline] fn rem(self, other: BigInt) -> BigInt { match self.checked_uabs() { Positive(u) => u % other, Negative(u) => -(u % other), } } } impl Rem for BigInt { type Output = BigInt; #[inline] fn rem(self, other: i128) -> BigInt { self % other.uabs() } } impl RemAssign for BigInt { #[inline] fn rem_assign(&mut self, other: i128) { *self %= other.uabs(); } } impl Rem for i128 { type Output = BigInt; #[inline] fn rem(self, other: BigInt) -> BigInt { match self.checked_uabs() { Positive(u) => u % other, Negative(u) => -(u % other), } } } impl CheckedDiv for BigInt { #[inline] fn checked_div(&self, v: &BigInt) -> Option { if v.is_zero() { return None; } Some(self.div(v)) } } impl CheckedEuclid for BigInt { #[inline] fn checked_div_euclid(&self, v: &BigInt) -> Option { if v.is_zero() { return None; } Some(self.div_euclid(v)) } #[inline] fn checked_rem_euclid(&self, v: &BigInt) -> Option { if v.is_zero() { return None; } Some(self.rem_euclid(v)) } } impl Euclid for BigInt { #[inline] fn div_euclid(&self, v: &BigInt) -> BigInt { let (q, r) = self.div_rem(v); if r.is_negative() { if v.is_positive() { q - 1 } else { q + 1 } } else { q } } #[inline] fn rem_euclid(&self, v: &BigInt) -> BigInt { let r = self % v; if r.is_negative() { if v.is_positive() { r + v } else { r - v } } else { r } } }