use super::super::PolyOverQ;
use crate::{
integer::PolyOverZ,
macros::arithmetics::{
arithmetic_assign_trait_borrowed_to_owned, arithmetic_trait_borrowed_to_owned,
arithmetic_trait_mixed_borrowed_owned, arithmetic_trait_reverse,
},
};
use flint_sys::fmpq_poly::fmpq_poly_mul;
use std::ops::{Mul, MulAssign};
impl MulAssign<&PolyOverQ> for PolyOverQ {
fn mul_assign(&mut self, other: &Self) {
unsafe { fmpq_poly_mul(&mut self.poly, &self.poly, &other.poly) };
}
}
impl MulAssign<&PolyOverZ> for PolyOverQ {
fn mul_assign(&mut self, other: &PolyOverZ) {
let other = PolyOverQ::from(other);
self.mul_assign(other);
}
}
arithmetic_assign_trait_borrowed_to_owned!(MulAssign, mul_assign, PolyOverQ, PolyOverQ);
arithmetic_assign_trait_borrowed_to_owned!(MulAssign, mul_assign, PolyOverQ, PolyOverZ);
impl Mul for &PolyOverQ {
type Output = PolyOverQ;
fn mul(self, other: Self) -> Self::Output {
let mut out = PolyOverQ::default();
unsafe {
fmpq_poly_mul(&mut out.poly, &self.poly, &other.poly);
}
out
}
}
arithmetic_trait_borrowed_to_owned!(Mul, mul, PolyOverQ, PolyOverQ, PolyOverQ);
arithmetic_trait_mixed_borrowed_owned!(Mul, mul, PolyOverQ, PolyOverQ, PolyOverQ);
impl Mul<&PolyOverZ> for &PolyOverQ {
type Output = PolyOverQ;
fn mul(self, other: &PolyOverZ) -> Self::Output {
let mut out = PolyOverQ::default();
unsafe {
fmpq_poly_mul(&mut out.poly, &self.poly, &PolyOverQ::from(other).poly);
}
out
}
}
arithmetic_trait_reverse!(Mul, mul, PolyOverZ, PolyOverQ, PolyOverQ);
arithmetic_trait_borrowed_to_owned!(Mul, mul, PolyOverQ, PolyOverZ, PolyOverQ);
arithmetic_trait_borrowed_to_owned!(Mul, mul, PolyOverZ, PolyOverQ, PolyOverQ);
arithmetic_trait_mixed_borrowed_owned!(Mul, mul, PolyOverQ, PolyOverZ, PolyOverQ);
arithmetic_trait_mixed_borrowed_owned!(Mul, mul, PolyOverZ, PolyOverQ, PolyOverQ);
#[cfg(test)]
mod test_mul_assign {
use super::PolyOverQ;
use crate::integer::PolyOverZ;
use std::str::FromStr;
#[test]
fn correct_small() {
let mut a = PolyOverQ::from_str("3 1/7 2/7 -3/7").unwrap();
let b = PolyOverQ::from_str("5 1/11 2/11 5/11 1/11 2/11").unwrap();
a *= b;
assert_eq!(
a,
PolyOverQ::from_str("7 1/77 4/77 6/77 5/77 -11/77 1/77 -6/77").unwrap()
);
}
#[test]
fn correct_large() {
let mut a = PolyOverQ::from_str(&format!("2 {} {}", 2, i64::MIN)).unwrap();
let b = PolyOverQ::from_str(&format!(
"2 {}/{} {}/{}",
u32::MAX,
u128::MAX,
i64::MAX,
u128::MAX
))
.unwrap();
a *= b;
assert_eq!(
a,
PolyOverQ::from_str(&format!(
"3 {}/{} {}/{} {}/{}",
2_u128 * u128::from(u32::MAX),
u128::MAX,
2_i128 * i128::from(i64::MAX) + i128::from(u32::MAX) * i128::from(i64::MIN),
u128::MAX,
i128::from(i64::MAX) * i128::from(i64::MIN),
u128::MAX
))
.unwrap()
);
}
#[test]
fn availability() {
let mut a = PolyOverQ::from_str("3 1 2 -3").unwrap();
let b = PolyOverQ::from_str("3 -1 -2 3").unwrap();
let c = PolyOverZ::from_str("4 2 -1 2 3").unwrap();
a *= &b;
a *= b;
a *= &c;
a *= c;
}
}
#[cfg(test)]
mod test_mul {
use super::PolyOverQ;
use std::str::FromStr;
#[test]
fn mul() {
let a: PolyOverQ = PolyOverQ::from_str("3 1/7 2/7 -3/7").unwrap();
let b: PolyOverQ = PolyOverQ::from_str("5 1/11 2/11 5/11 1/11 2/11").unwrap();
let c: PolyOverQ = a * b;
assert_eq!(
c,
PolyOverQ::from_str("7 1/77 4/77 6/77 5/77 -11/77 1/77 -6/77").unwrap()
);
}
#[test]
fn mul_borrow() {
let a: PolyOverQ = PolyOverQ::from_str("3 1/7 2/7 -3/7").unwrap();
let b: PolyOverQ = PolyOverQ::from_str("5 1/11 2/11 5/11 1/11 2/11").unwrap();
let c: PolyOverQ = &a * &b;
assert_eq!(
c,
PolyOverQ::from_str("7 1/77 4/77 6/77 5/77 -11/77 1/77 -6/77").unwrap()
);
}
#[test]
fn mul_first_borrowed() {
let a: PolyOverQ = PolyOverQ::from_str("3 1/7 2/7 -3/7").unwrap();
let b: PolyOverQ = PolyOverQ::from_str("5 1/11 2/11 5/11 1/11 2/11").unwrap();
let c: PolyOverQ = &a * b;
assert_eq!(
c,
PolyOverQ::from_str("7 1/77 4/77 6/77 5/77 -11/77 1/77 -6/77").unwrap()
);
}
#[test]
fn mul_second_borrowed() {
let a: PolyOverQ = PolyOverQ::from_str("3 1/7 2/7 -3/7").unwrap();
let b: PolyOverQ = PolyOverQ::from_str("5 1/11 2/11 5/11 1/11 2/11").unwrap();
let c: PolyOverQ = a * &b;
assert_eq!(
c,
PolyOverQ::from_str("7 1/77 4/77 6/77 5/77 -11/77 1/77 -6/77").unwrap()
);
}
#[test]
fn mul_constant() {
let a: PolyOverQ = PolyOverQ::from_str("3 1/11 1/2 -7/3").unwrap();
let b: PolyOverQ = PolyOverQ::from_str("1 4/7").unwrap();
let c: PolyOverQ = a * b;
assert_eq!(c, PolyOverQ::from_str("3 4/77 2/7 -4/3").unwrap());
}
#[test]
fn mul_zero() {
let a: PolyOverQ = PolyOverQ::from_str("3 1/18 2/7 -3/10").unwrap();
let b: PolyOverQ = PolyOverQ::default();
let c: PolyOverQ = a * b;
assert_eq!(c, PolyOverQ::default());
}
#[test]
fn mul_large_numbers() {
let a: PolyOverQ = PolyOverQ::from_str(&format!("2 {} {}", 2, i64::MIN)).unwrap();
let b: PolyOverQ = PolyOverQ::from_str(&format!(
"2 {}/{} {}/{}",
u32::MAX,
u128::MAX,
i64::MAX,
u128::MAX
))
.unwrap();
let c: PolyOverQ = a * b;
assert_eq!(
c,
PolyOverQ::from_str(&format!(
"3 {}/{} {}/{} {}/{}",
2_u128 * u128::from(u32::MAX),
u128::MAX,
2_i128 * i128::from(i64::MAX) + i128::from(u32::MAX) * i128::from(i64::MIN),
u128::MAX,
i128::from(i64::MAX) * i128::from(i64::MIN),
u128::MAX
))
.unwrap()
);
}
}
#[cfg(test)]
mod test_mul_poly_over_z {
use super::PolyOverQ;
use crate::integer::PolyOverZ;
use std::str::FromStr;
#[test]
fn borrowed_correctness() {
let poly_1 = PolyOverQ::from_str(&format!("1 1/{}", i64::MAX)).unwrap();
let poly_2 = PolyOverZ::from_str("2 1 2").unwrap();
let poly_cmp = PolyOverQ::from_str(&format!("2 1/{} 2/{}", i64::MAX, i64::MAX)).unwrap();
let poly_1 = &poly_1 * &poly_2;
assert_eq!(poly_cmp, poly_1);
}
#[test]
fn availability() {
let poly = PolyOverQ::from_str("3 1/2 2 3/7").unwrap();
let z = PolyOverZ::from(2);
_ = poly.clone() * z.clone();
_ = z.clone() * poly.clone();
_ = &poly * &z;
_ = &z * &poly;
_ = &poly * z.clone();
_ = z.clone() * &poly;
_ = &z * poly.clone();
_ = poly.clone() * &z;
}
}