use super::Number;
use super::add::{
Fallback, add_assign_ref, medium, medium_into, medium_new, ref_plus_ref, small, small_add_to,
small_number_of,
};
use core::marker::PhantomData;
use core::mem::ManuallyDrop;
use core::ops::{Deref, Sub, SubAssign};
use core::ptr;
impl Sub<&Number> for &Number {
type Output = Number;
fn sub(self, rhs: &Number) -> Number {
if small(self, rhs) {
return small_number_of(self, rhs, !rhs.negative);
}
if medium(self, rhs) {
return medium_new(self, rhs, !rhs.negative);
}
ref_plus_ref(self, &Negated::new(rhs))
}
}
impl Sub<&Number> for Number {
type Output = Number;
fn sub(mut self, rhs: &Number) -> Number {
self -= rhs;
self
}
}
impl Sub<Number> for &Number {
type Output = Number;
fn sub(self, mut rhs: Number) -> Number {
rhs.negative = !rhs.negative;
self + rhs
}
}
impl Sub<Number> for Number {
type Output = Number;
fn sub(mut self, rhs: Number) -> Number {
self -= rhs;
self
}
}
impl SubAssign<&Number> for Number {
#[inline]
fn sub_assign(&mut self, rhs: &Number) {
if small(self, rhs) {
small_add_to(self, rhs, !rhs.negative);
return;
}
if medium(self, rhs) {
let (a, b) = (ptr::from_mut(self), ptr::from_ref(rhs).cast_mut());
unsafe { medium_into(a, b, !rhs.negative, a, Fallback::New) };
return;
}
self.negative = !self.negative;
let a = add_assign_ref(self, rhs);
let zero = a.value.len() == 1 && a.value[0] == 0;
a.negative = !a.negative & !zero;
}
}
impl SubAssign<Number> for Number {
#[inline]
fn sub_assign(&mut self, mut rhs: Number) {
rhs.negative = !rhs.negative;
*self += rhs;
}
}
pub(super) struct Negated<'a> {
number: ManuallyDrop<Number>,
borrowed: PhantomData<&'a Number>,
}
impl<'a> Negated<'a> {
#[inline(always)]
pub(super) fn new(n: &'a Number) -> Self {
Negated {
number: ManuallyDrop::new(Number {
value: unsafe { ptr::read(&n.value) },
negative: !n.negative,
byte_order: n.byte_order,
}),
borrowed: PhantomData,
}
}
}
impl Deref for Negated<'_> {
type Target = Number;
#[inline(always)]
fn deref(&self) -> &Number {
&self.number
}
}