use std::fmt;
use std::ops::{Add, AddAssign, Mul, Neg};
use crate::{Sign, Signed, Negateable};
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct Zero;
impl num_traits::Zero for Zero {
fn zero() -> Self {
Self
}
fn is_zero(&self) -> bool {
true
}
}
impl Add for Zero {
type Output = Self;
fn add(self, _: Self) -> Self::Output {
Self
}
}
impl Mul for Zero {
type Output = Self;
fn mul(self, _: Self) -> Self::Output {
Self
}
}
impl Signed for Zero {
#[inline]
fn signum(&self) -> Sign {
Sign::Zero
}
}
impl Negateable for Zero {
#[inline]
fn negate(&mut self) {
}
}
impl Neg for Zero {
type Output = Self;
#[inline]
fn neg(self) -> Self::Output {
self
}
}
impl fmt::Debug for Zero {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<Self as fmt::Display>::fmt(self, f)
}
}
impl fmt::Display for Zero {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("0")
}
}
macro_rules! define_ops {
($primitive:ident) => {
impl From<Zero> for $primitive {
fn from(_: Zero) -> Self {
0
}
}
impl From<&Zero> for $primitive {
fn from(_: &Zero) -> Self {
0
}
}
impl Add<Zero> for $primitive {
type Output = Self;
fn add(self, _: Zero) -> Self::Output {
self
}
}
impl Add<&Zero> for $primitive {
type Output = Self;
fn add(self, _: &Zero) -> Self::Output {
self
}
}
impl AddAssign<&Zero> for $primitive {
fn add_assign(&mut self, _: &Zero) {
}
}
impl Mul<Zero> for $primitive {
type Output = Self;
fn mul(self, _: Zero) -> Self::Output {
0
}
}
impl Mul<&Zero> for $primitive {
type Output = Self;
fn mul(self, _: &Zero) -> Self::Output {
0
}
}
impl Mul<&Zero> for &$primitive {
type Output = $primitive;
fn mul(self, _: &Zero) -> Self::Output {
0
}
}
}
}
define_ops!(i8);
define_ops!(i16);
define_ops!(i32);
define_ops!(i64);
define_ops!(i128);
define_ops!(u8);
define_ops!(u16);
define_ops!(u32);
define_ops!(u64);
define_ops!(u128);
#[cfg(test)]
mod test {
use std::cmp::Ordering;
use crate::{Abs, Negateable, Sign, Signed};
use crate::fixed::Zero;
#[test]
fn test() {
assert_eq!(Zero, num_traits::Zero::zero());
assert!(num_traits::Zero::is_zero(&Zero));
assert_eq!(Zero + Zero, Zero);
assert_eq!(Zero * Zero, Zero);
assert_eq!(Zero.abs(), Zero);
}
#[test]
#[allow(clippy::default_constructed_unit_structs)]
fn test_default() {
assert_eq!(Zero::default(), Zero);
}
#[test]
fn test_signum() {
assert_eq!(Zero.signum(), Sign::Zero);
assert!(!Zero.is_positive());
assert!(!Zero.is_negative());
}
#[test]
fn test_non_zero() {
assert!(num_traits::Zero::is_zero(&Zero));
}
#[test]
fn test_negate() {
let mut value = Zero;
value.negate();
assert_eq!(value, Zero);
assert_eq!(-Zero, Zero);
}
#[test]
fn test_ord() {
assert_eq!(Zero.cmp(&Zero), Ordering::Equal);
assert_eq!(Zero.partial_cmp(&Zero), Some(Ordering::Equal));
assert_eq!(Zero, Zero);
}
#[test]
fn test_display() {
assert_eq!(Zero.to_string(), "0");
assert_eq!(format!("{Zero:?}"), "0");
}
#[test]
fn test_integer() {
assert_eq!(1 + Zero, 1);
assert_eq!(-1 + Zero, -1);
assert_eq!(894 * Zero, 0);
assert_eq!(-894 * &Zero, 0);
assert_eq!(0_u8 * &Zero, 0);
}
}