use crate::number::integer::*;
use core::{
iter::Sum,
num::*,
ops::{Add, AddAssign},
};
use devela::paste;
macro_rules! impl_integer_add {
( $($t:ident + $p:ident + $b:literal, cast: $bcast:literal);+ ) => {
$( impl_integer_add![add: $t + $p + $b]; )+
};
(add: $t:ident + $p:ident + $b:literal) => { paste! {
impl Add<[<$t$b>]> for [<$t$b>] {
type Output = [<$t$b>];
#[inline]
fn add(self, rhs: [<$t$b>]) -> Self::Output {
self.basic_add(rhs)
}
}
impl AddAssign for [<$t$b>] {
#[inline]
fn add_assign(&mut self, rhs: [<$t$b>]) {
*self = self.basic_add(rhs)
}
}
impl Sum for [<$t$b>] {
fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
iter.reduce(
|a, b| a + b,
).expect("The iterator is empty")
}
}
impl [<$t$b>] {
#[inline]
#[must_use]
pub const fn basic_add(self, rhs: [<$t$b>]) -> [<$t$b>] {
if let Some(result) = [<$p$b>]::new(self.0.get() + rhs.0.get()) {
Self(result)
} else {
panic!["NonZero addition resulted in 0"]
}
}
#[inline]
#[must_use]
pub const fn checked_add(self, rhs: [<$t$b>]) -> Option<[<$t$b>]> {
if let Some(result) = self.0.get().checked_add(rhs.0.get()) {
if let Some(non0_result) = [<$p$b>]::new(result) {
Some(Self(non0_result))
} else {
None
}
} else {
None
}
}
#[inline]
#[must_use]
pub const fn checked_saturating_add(self, rhs: [<$t$b>]) -> Option<[<$t$b>]> {
let result = self.0.get().saturating_add(rhs.0.get());
if let Some(non0_result) = [<$p$b>]::new(result) {
Some(Self(non0_result))
} else {
None
}
}
#[inline]
#[must_use]
pub const fn checked_wrapping_add(self, rhs: [<$t$b>]) -> Option<[<$t$b>]> {
let result = self.0.get().wrapping_add(rhs.0.get());
if let Some(non0_result) = [<$p$b>]::new(result) {
Some(Self(non0_result))
} else {
None
}
}
#[inline]
#[must_use]
pub const fn overflowing_add(self, rhs: [<$t$b>]) -> (Option<[<$t$b>]>, bool) {
let (result, overflown) = self.0.get().overflowing_add(rhs.0.get());
if let Some(non0_result) = [<$p$b>]::new(result) {
(Some(Self(non0_result)), overflown)
} else {
(None, overflown)
}
}
}
}};
}
impl_integer_add![
NonZeroInteger+NonZeroI+8, cast:16;
NonZeroInteger+NonZeroI+16, cast:32;
NonZeroInteger+NonZeroI+32, cast:64;
NonZeroInteger+NonZeroI+64, cast:128;
NonZeroInteger+NonZeroI+128, cast:128
];