PuzzleUtils/src/number/mul.rs

142 lines
3.7 KiB
Rust

use std::ops::{Mul, MulAssign};
use super::{Number, Sign};
impl Mul for Number {
type Output = Self;
#[allow(clippy::suspicious_arithmetic_impl)]
fn mul(self, rhs: Self) -> Self::Output {
let sign = match (self.sign, rhs.sign) {
(Sign::Positif, Sign::Positif) => Sign::Positif,
(Sign::Positif, Sign::Negatif) => Sign::Negatif,
(Sign::Negatif, Sign::Positif) => Sign::Negatif,
(Sign::Negatif, Sign::Negatif) => Sign::Positif,
};
let mut digits = Vec::new();
for (zeroes, rdigit) in rhs.digits.iter().enumerate() {
for (idx, ldigit) in self.digits.iter().enumerate() {
let mult = rdigit * ldigit;
let new = mult % 10;
let mut carry = mult / 10;
if let Some(old) = digits.get(zeroes + idx) {
let add = old + new;
digits[zeroes + idx] = add % 10;
carry += add / 10;
} else {
digits.push(new);
}
let mut carry_idx = 1;
loop {
if carry == 0 {
break;
}
if let Some(old) = digits.get(zeroes + idx + carry_idx) {
let add = old + carry;
digits[zeroes + idx + carry_idx] = add % 10;
carry = add / 10;
} else {
digits.push(carry % 10);
carry /= 10;
}
carry_idx += 1;
}
}
}
Number { digits, sign }
}
}
impl Mul<Number> for isize {
type Output = Number;
fn mul(self, rhs: Number) -> Self::Output {
Number::from(self) * rhs
}
}
impl Mul<isize> for Number {
type Output = Self;
fn mul(self, rhs: isize) -> Self::Output {
self * Number::from(rhs)
}
}
impl MulAssign for Number {
fn mul_assign(&mut self, rhs: Self) {
let new = self.clone() * rhs;
self.digits = new.digits;
self.sign = new.sign;
}
}
#[cfg(test)]
mod test_number_mul {
use crate::number::Number;
#[test]
fn mul_positif() {
let a = Number::from(9);
let b = Number::from(9);
let res = Number::from(81);
assert_eq!(res, a * b);
}
#[test]
fn mul_negatif() {
let a = Number::from(-9);
let b = Number::from(-9);
let res = Number::from(81);
assert_eq!(res, a * b);
}
#[test]
fn mul_positif_with_negatif() {
let a = Number::from(9);
let b = Number::from(-9);
let res = Number::from(-81);
assert_eq!(res, a * b);
}
#[test]
fn mul_negatif_with_positif() {
let a = Number::from(-9);
let b = Number::from(9);
let res = Number::from(-81);
assert_eq!(res, a * b);
}
#[test]
fn mul_eleven_x_ten() {
let a = Number::from(11);
let b = Number::from(10);
let res = Number::from(110);
assert_eq!(res, a * b);
}
#[test]
fn mul_eleven_x_eleven() {
let a = Number::from(11);
let b = Number::from(11);
let res = Number::from(121);
assert_eq!(res, a * b);
}
#[test]
fn mul_big_1() {
let a = Number::from("123");
let b = Number::from("321");
let res = Number::from("39483");
assert_eq!(res, a * b);
}
#[test]
fn mul_big_2() {
let a = Number::from("123456789");
let b = Number::from("987654321");
let res = Number::from("121932631112635269");
assert_eq!(res, a * b);
}
}