use std::{ cmp::min, iter::zip, ops::{Sub, SubAssign}, }; use super::{Number, Sign}; impl Sub for Number { type Output = Self; fn sub(self, rhs: Self) -> Self::Output { let self_len = self.digits.len(); let rhs_len = rhs.digits.len(); let mut self_digits = self.digits.clone(); let mut rhs_digits = rhs.digits.clone(); if self_len != rhs_len { let difference = (self_len).abs_diff(rhs_len); let pad = vec![0i8; difference]; if min(self_len, rhs_len) == self_len { self_digits = [self.digits, pad].concat(); } else { rhs_digits = [rhs.digits, pad].concat(); } } let zipped = zip(self_digits.iter(), rhs_digits.iter()); let mut carry = 0; let mut digits = Vec::new(); let mut sign = match (self.sign, rhs.sign) { (Sign::Positif, Sign::Negatif) => Sign::Positif, (Sign::Negatif, Sign::Positif) => Sign::Negatif, (Sign::Positif, Sign::Positif) | (Sign::Negatif, Sign::Negatif) => Sign::Positif, }; for (a, b) in zipped { let comb = match (self.sign, rhs.sign) { (Sign::Positif, Sign::Positif) => { let comb = a - b - carry; if comb < 0 { carry = 1; } else { carry = 0; } if b > a { sign = Sign::Negatif; } else { sign = Sign::Positif; } (comb % 10).abs() } (Sign::Positif, Sign::Negatif) => { let comb = a + b + carry; if comb > 9 { carry = 1; } else { carry = 0; } comb % 10 } (Sign::Negatif, Sign::Positif) => { let comb = -a - b - carry; if comb < -9 { carry = 1; } else { carry = 0; } (comb % 10).abs() } (Sign::Negatif, Sign::Negatif) => { let comb = -a + b + carry; if comb > 10 { carry = 1; } else { carry = 0; } if a > b { sign = Sign::Negatif; } else { sign = Sign::Positif; } comb % 10 } }; digits.push(comb); } if carry != 0 { digits.push(carry); } Self { digits, sign } } } impl SubAssign for Number { fn sub_assign(&mut self, rhs: Self) { let new = self.clone() - rhs; self.digits = new.digits; self.sign = new.sign; } } #[cfg(test)] mod test_number_sub { use crate::number::Number; #[test] fn sub_positif() { let a = Number::from(1); let b = 1.into(); let res = Number::from(0); assert_eq!(res, a - b); } #[test] fn sub_negatif() { let a = Number::from(-1); let b = (-1).into(); let res = Number::from(0); assert_eq!(res, a - b); } #[test] fn sub_negatif_from_positif() { let a = Number::from(1); let b = (-1).into(); let res = Number::from(2); assert_eq!(res, a - b); } #[test] fn sub_positif_from_negatif() { let a = Number::from(-1); let b = (1).into(); let res = Number::from(-2); assert_eq!(res, a - b); } #[test] fn sub_larger_positif_from_negatif() { let a = Number::from(-1); let b = (11).into(); let res = Number::from(-12); assert_eq!(res, a - b); } #[test] fn sub_larger_negatif_from_positif() { let a = Number::from(1); let b = (-11).into(); let res = Number::from(12); assert_eq!(res, a - b); } #[test] fn sub_positif_from_larger_negatif() { let a = Number::from(-99); let b = (11).into(); let res = Number::from(-110); assert_eq!(res, a - b); } #[test] fn sub_negatif_from_larger_positif() { let a = Number::from(99); let b = (-11).into(); let res = Number::from(110); assert_eq!(res, a - b); } }