use std::cmp::Ordering;
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
use num_traits::Zero;
use crate::{One, Sign};
use crate::integer::big::ops::non_zero::{add_assign, both_not_one_non_zero, is_one_non_zero, subtracting_cmp};
use crate::rational::big::Big;
impl<const S: usize> From<One> for Big<S> {
#[inline]
fn from(_: One) -> Self {
num_traits::One::one()
}
}
impl<const S: usize> From<&One> for Big<S> {
#[inline]
fn from(_: &One) -> Self {
num_traits::One::one()
}
}
impl<const S: usize> Add<One> for Big<S> {
type Output = Self;
#[inline]
fn add(mut self, _: One) -> Self::Output {
<Self as AddAssign<One>>::add_assign(&mut self, One);
self
}
}
impl<const S: usize> Add<&One> for Big<S> {
type Output = Self;
#[inline]
fn add(mut self, _: &One) -> Self::Output {
<Self as AddAssign<&One>>::add_assign(&mut self, &One);
self
}
}
impl<const S: usize> AddAssign<One> for Big<S> {
#[inline]
fn add_assign(&mut self, _: One) {
AddAssign::add_assign(self, &One);
}
}
impl<const S: usize> AddAssign<&One> for Big<S> {
#[inline]
fn add_assign(&mut self, _: &One) {
match self.sign {
Sign::Positive => unsafe {
add_assign(self.numerator.inner_mut(), self.denominator.inner());
},
Sign::Zero => {
self.sign = Sign::Positive;
debug_assert!(self.numerator.is_zero());
num_traits::One::set_one(&mut self.numerator);
debug_assert!(num_traits::One::is_one(&self.denominator));
}
Sign::Negative => {
let both_not_one = unsafe {
both_not_one_non_zero(&self.numerator, &self.denominator)
};
if both_not_one {
unsafe {
let sign_change = subtracting_cmp(
self.numerator.inner_mut(), self.denominator.inner(),
);
if sign_change == Ordering::Less {
self.sign = Sign::Positive;
}
}
} else {
self.set_zero();
}
}
}
}
}
impl<const S: usize> Sub<One> for Big<S> {
type Output = Self;
#[inline]
fn sub(mut self, _: One) -> Self::Output {
SubAssign::sub_assign(&mut self, One);
self
}
}
impl<const S: usize> Sub<&One> for Big<S> {
type Output = Self;
#[inline]
fn sub(mut self, _: &One) -> Self::Output {
SubAssign::sub_assign(&mut self, One);
self
}
}
impl<const S: usize> SubAssign<One> for Big<S> {
#[inline]
fn sub_assign(&mut self, _: One) {
SubAssign::sub_assign(self, &One);
}
}
impl<const S: usize> SubAssign<&One> for Big<S> {
#[inline]
fn sub_assign(&mut self, _: &One) {
match self.sign {
Sign::Positive => {
let numerator_is_one = unsafe { is_one_non_zero(self.numerator.inner()) };
if !numerator_is_one || !num_traits::One::is_one(&self.denominator) {
let direction = unsafe {
subtracting_cmp(self.numerator.inner_mut(), self.denominator.inner())
};
if direction == Ordering::Less {
self.sign = Sign::Negative;
}
} else {
self.set_zero();
}
}
Sign::Zero => {
self.sign = Sign::Negative;
debug_assert!(self.numerator.is_empty());
unsafe {
self.numerator.inner_mut().push(1);
}
debug_assert_eq!(self.denominator[0], 1);
debug_assert_eq!(self.denominator.len(), 1);
}
Sign::Negative => unsafe {
add_assign(self.numerator.inner_mut(), &self.denominator)
},
}
}
}
impl<const S: usize> Mul<One> for Big<S> {
type Output = Self;
#[inline]
fn mul(self, _: One) -> Self::Output {
self
}
}
impl<const S: usize> Mul<&One> for Big<S> {
type Output = Self;
#[inline]
fn mul(self, _: &One) -> Self::Output {
self
}
}
impl<const S: usize> Mul<One> for &Big<S> {
type Output = Big<S>;
#[inline]
fn mul(self, _: One) -> Self::Output {
self.clone()
}
}
impl<const S: usize> Mul<&One> for &Big<S> {
type Output = Big<S>;
#[inline]
fn mul(self, _: &One) -> Self::Output {
self.clone()
}
}
impl<const S: usize> MulAssign<One> for Big<S> {
#[inline]
fn mul_assign(&mut self, _: One) {
}
}
impl<const S: usize> MulAssign<&One> for Big<S> {
#[inline]
fn mul_assign(&mut self, _: &One) {
}
}
impl<const S: usize> Div<One> for Big<S> {
type Output = Self;
#[inline]
fn div(self, _: One) -> Self::Output {
self
}
}
impl<const S: usize> Div<&One> for Big<S> {
type Output = Self;
#[inline]
fn div(self, _: &One) -> Self::Output {
self
}
}
impl<const S: usize> Div<One> for &Big<S> {
type Output = Big<S>;
#[inline]
fn div(self, _: One) -> Self::Output {
self.clone()
}
}
impl<const S: usize> Div<&One> for &Big<S> {
type Output = Big<S>;
#[inline]
fn div(self, _: &One) -> Self::Output {
self.clone()
}
}
impl<const S: usize> DivAssign<One> for Big<S> {
#[inline]
fn div_assign(&mut self, _: One) {
}
}
impl<const S: usize> DivAssign<&One> for Big<S> {
#[inline]
fn div_assign(&mut self, _: &One) {
}
}