use {
crate::SCell,
num_traits::{
CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedSub, Num, One, Signed,
Zero,
},
std::{
ops::{Add, Div, Mul, Not, Rem, Sub},
str::FromStr,
},
};
impl<T> SCell<T> {
pub fn new(data: T) -> Self {
SCell { data }
}
pub fn get_data(&self) -> &T {
&self.data
}
}
impl<T: Zero> SCell<T> {
pub fn zero() -> Self {
SCell::new(T::zero())
}
pub fn is_zero(&self) -> bool {
self.data.is_zero()
}
}
impl<T: One + PartialEq> SCell<T> {
pub fn one() -> Self {
SCell::new(T::one())
}
pub fn is_one(&self) -> bool {
self.data.is_one()
}
}
ops!(+=, add, Add);
ops!(-=, sub, Sub);
ops!(*=, mul, Mul);
ops!(/=, div, Div);
ops!(%=, rem, Rem);
ops!(neg);
impl<T: Num + CheckedAdd + CheckedSub + CheckedMul + CheckedDiv + CheckedRem> SCell<T> {
pub fn from_str_radix(str: &str, radix: u32) -> Result<Self, T::FromStrRadixErr> {
let data = T::from_str_radix(str, radix)?;
Ok(SCell { data })
}
}
impl<
T: Signed
+ CheckedAdd
+ CheckedSub
+ CheckedMul
+ CheckedDiv
+ CheckedRem
+ CheckedNeg
+ Ord
+ Copy,
> SCell<T>
{
pub fn abs(&self) -> Option<Self> {
if *self < Self::zero() {
-*self
} else {
Some(*self)
}
}
pub fn abs_sub(&self, other: &Self) -> Option<Self> {
if *self <= *other {
Some(Self::zero())
} else {
*self - *other
}
}
pub fn signum(&self) -> Self {
SCell {
data: self.data.signum(),
}
}
pub fn is_positive(&self) -> bool {
self.data.is_positive()
}
pub fn is_negative(&self) -> bool {
self.data.is_negative()
}
}
impl<T: FromStr> FromStr for SCell<T> {
type Err = T::Err;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(SCell::new(T::from_str(s)?))
}
}
impl<T: Not> Not for SCell<T> {
type Output = SCell<T::Output>;
fn not(self) -> Self::Output {
SCell::new(!self.data)
}
}