use num::{One, Zero};
use std::{
fmt::{Display, Error, Formatter},
ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign},
};
use super::{
super::{
calc::{safe_calc, Operator},
traits::CheckedCalc,
},
Cell,
};
impl<U: One + Zero + CheckedCalc> Zero for Cell<U> {
fn zero() -> Self {
Cell {
error_tag: false,
data: U::zero(),
}
}
fn is_zero(&self) -> bool {
self.data.is_zero()
}
}
impl<U: One + Zero + CheckedCalc + PartialEq> One for Cell<U> {
fn one() -> Self {
Cell {
error_tag: false,
data: U::one(),
}
}
fn is_one(&self) -> bool {
self.data.is_one()
}
}
impl<U: One + CheckedCalc> AddAssign for Cell<U> {
fn add_assign(&mut self, rhs: Self) {
self.data = match safe_calc(&self.data, &rhs.data, &Operator::Add) {
Ok(s) => s,
Err(_) => {
self.error_tag = true;
U::one()
}
};
self.error_tag |= rhs.error_tag;
}
}
impl<U: One + CheckedCalc> SubAssign for Cell<U> {
fn sub_assign(&mut self, rhs: Self) {
self.data = match safe_calc(&self.data, &rhs.data, &Operator::Sub) {
Ok(s) => s,
Err(_) => {
self.error_tag = true;
U::one()
}
};
self.error_tag |= rhs.error_tag;
}
}
impl<U: One + CheckedCalc> MulAssign for Cell<U> {
fn mul_assign(&mut self, rhs: Self) {
self.data = match safe_calc(&self.data, &rhs.data, &Operator::Mul) {
Ok(s) => s,
Err(_) => {
self.error_tag = true;
U::one()
}
};
self.error_tag |= rhs.error_tag;
}
}
impl<U: One + CheckedCalc> DivAssign for Cell<U> {
fn div_assign(&mut self, rhs: Self) {
self.data = match safe_calc(&self.data, &rhs.data, &Operator::Div) {
Ok(s) => s,
Err(_) => {
self.error_tag = true;
U::one()
}
};
self.error_tag |= rhs.error_tag;
}
}
impl<U: One + CheckedCalc> RemAssign for Cell<U> {
fn rem_assign(&mut self, rhs: Self) {
self.data = match safe_calc(&self.data, &rhs.data, &Operator::Rem) {
Ok(s) => s,
Err(_) => {
self.error_tag = true;
U::one()
}
};
self.error_tag |= rhs.error_tag;
}
}
impl<U: One + CheckedCalc> Add for Cell<U> {
type Output = Self;
fn add(mut self, rhs: Self) -> Self::Output {
self += rhs;
self
}
}
impl<U: One + CheckedCalc> Sub for Cell<U> {
type Output = Self;
fn sub(mut self, rhs: Self) -> Self::Output {
self -= rhs;
self
}
}
impl<U: One + CheckedCalc> Mul for Cell<U> {
type Output = Self;
fn mul(mut self, rhs: Self) -> Self::Output {
self *= rhs;
self
}
}
impl<U: One + CheckedCalc> Div for Cell<U> {
type Output = Self;
fn div(mut self, rhs: Self) -> Self::Output {
self /= rhs;
self
}
}
impl<U: One + CheckedCalc> Rem for Cell<U> {
type Output = Self;
fn rem(mut self, rhs: Self) -> Self::Output {
self %= rhs;
self
}
}
impl<U: One + CheckedCalc> Neg for Cell<U> {
type Output = Self;
fn neg(mut self) -> Self::Output {
self.data = match safe_calc(&self.data, &U::one(), &Operator::Neg) {
Ok(s) => s,
Err(_) => {
self.error_tag = true;
U::one()
}
};
Cell {
error_tag: self.error_tag,
data: self.data,
}
}
}
impl<U: Display> Display for Cell<U> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
std::fmt::Display::fmt(&self.data, f)?;
Ok(())
}
}