use super::super::PolyOverZ;
use crate::macros::arithmetics::{
arithmetic_assign_trait_borrowed_to_owned, arithmetic_trait_borrowed_to_owned,
arithmetic_trait_mixed_borrowed_owned,
};
use flint_sys::fmpz_poly::fmpz_poly_mul;
use std::ops::{Mul, MulAssign};
impl MulAssign<&PolyOverZ> for PolyOverZ {
fn mul_assign(&mut self, other: &Self) {
unsafe { fmpz_poly_mul(&mut self.poly, &self.poly, &other.poly) };
}
}
arithmetic_assign_trait_borrowed_to_owned!(MulAssign, mul_assign, PolyOverZ, PolyOverZ);
impl Mul for &PolyOverZ {
type Output = PolyOverZ;
fn mul(self, other: Self) -> Self::Output {
let mut out = PolyOverZ::default();
unsafe {
fmpz_poly_mul(&mut out.poly, &self.poly, &other.poly);
}
out
}
}
arithmetic_trait_borrowed_to_owned!(Mul, mul, PolyOverZ, PolyOverZ, PolyOverZ);
arithmetic_trait_mixed_borrowed_owned!(Mul, mul, PolyOverZ, PolyOverZ, PolyOverZ);
#[cfg(test)]
mod test_mul_assign {
use super::PolyOverZ;
use std::str::FromStr;
#[test]
fn correct_small() {
let mut a = PolyOverZ::from_str("3 -1 2 -3").unwrap();
let b = PolyOverZ::from_str("2 5 2").unwrap();
let cmp = PolyOverZ::from_str("4 -5 8 -11 -6").unwrap();
a *= b;
assert_eq!(cmp, a);
}
#[test]
fn correct_large() {
let mut a = PolyOverZ::from_str(&format!("1 {}", i32::MIN)).unwrap();
let b = PolyOverZ::from_str(&format!("2 {} {}", i32::MAX, i32::MIN)).unwrap();
let cmp = PolyOverZ::from_str(&format!(
"2 {} {}",
i32::MIN as i64 * i32::MAX as i64,
i32::MIN as i64 * i32::MIN as i64
))
.unwrap();
a *= b;
assert_eq!(cmp, a);
}
#[test]
fn availability() {
let mut a = PolyOverZ::from_str("3 1 2 -3").unwrap();
let b = PolyOverZ::from_str("3 -1 -2 3").unwrap();
a *= &b;
a *= b;
}
}
#[cfg(test)]
mod test_mul {
use super::PolyOverZ;
use std::str::FromStr;
#[test]
fn mul() {
let a: PolyOverZ = PolyOverZ::from_str("3 1 2 -3").unwrap();
let b: PolyOverZ = PolyOverZ::from_str("5 1 2 5 1 2").unwrap();
let c: PolyOverZ = a * b;
assert_eq!(c, PolyOverZ::from_str("7 1 4 6 5 -11 1 -6").unwrap());
}
#[test]
fn mul_borrow() {
let a: PolyOverZ = PolyOverZ::from_str("3 1 2 -3").unwrap();
let b: PolyOverZ = PolyOverZ::from_str("5 1 2 5 1 2").unwrap();
let c: PolyOverZ = &a * &b;
assert_eq!(c, PolyOverZ::from_str("7 1 4 6 5 -11 1 -6").unwrap());
}
#[test]
fn mul_first_borrowed() {
let a: PolyOverZ = PolyOverZ::from_str("3 1 2 -3").unwrap();
let b: PolyOverZ = PolyOverZ::from_str("5 1 2 5 1 2").unwrap();
let c: PolyOverZ = &a * b;
assert_eq!(c, PolyOverZ::from_str("7 1 4 6 5 -11 1 -6").unwrap());
}
#[test]
fn mul_second_borrowed() {
let a: PolyOverZ = PolyOverZ::from_str("3 1 2 -3").unwrap();
let b: PolyOverZ = PolyOverZ::from_str("5 1 2 5 1 2").unwrap();
let c: PolyOverZ = a * &b;
assert_eq!(c, PolyOverZ::from_str("7 1 4 6 5 -11 1 -6").unwrap());
}
#[test]
fn mul_constant() {
let a: PolyOverZ = PolyOverZ::from_str("3 1 2 -3").unwrap();
let b: PolyOverZ = PolyOverZ::from(4);
let c: PolyOverZ = a * b;
assert_eq!(c, PolyOverZ::from_str("3 4 8 -12").unwrap());
}
#[test]
fn mul_zero() {
let a: PolyOverZ = PolyOverZ::from_str("3 1 2 -3").unwrap();
let b: PolyOverZ = PolyOverZ::default();
let c: PolyOverZ = a * b;
assert_eq!(c, PolyOverZ::default());
}
#[test]
fn mul_large_numbers() {
let a: PolyOverZ = PolyOverZ::from_str(&format!("2 {} {}", u16::MAX, i32::MIN)).unwrap();
let b: PolyOverZ = PolyOverZ::from_str(&format!("2 {} {}", u32::MAX, i32::MAX)).unwrap();
let c: PolyOverZ = a * b;
assert_eq!(
c,
PolyOverZ::from_str(&format!(
"3 {} {} {}",
i64::from(u16::MAX) * i64::from(u32::MAX),
i64::from(u16::MAX) * i64::from(i32::MAX)
+ i64::from(u32::MAX) * i64::from(i32::MIN),
i64::from(i32::MAX) * i64::from(i32::MIN)
))
.unwrap()
);
}
}