use super::super::PolyOverQ;
use crate::integer::Z;
use crate::macros::arithmetics::{
arithmetic_assign_between_types, arithmetic_assign_trait_borrowed_to_owned,
arithmetic_trait_borrowed_to_owned, arithmetic_trait_mixed_borrowed_owned,
};
use crate::macros::for_others::implement_for_others;
use crate::rational::Q;
use flint_sys::fmpq_poly::{
fmpq_poly_scalar_div_fmpq, fmpq_poly_scalar_div_fmpz, fmpq_poly_scalar_div_si,
fmpq_poly_scalar_div_ui,
};
use std::ops::{Div, DivAssign};
impl Div<&Z> for &PolyOverQ {
type Output = PolyOverQ;
fn div(self, scalar: &Z) -> Self::Output {
assert!(!scalar.is_zero(), "Tried to divide {self} by zero.");
let mut out = PolyOverQ::default();
unsafe {
fmpq_poly_scalar_div_fmpz(&mut out.poly, &self.poly, &scalar.value);
}
out
}
}
arithmetic_trait_borrowed_to_owned!(Div, div, PolyOverQ, Z, PolyOverQ);
arithmetic_trait_mixed_borrowed_owned!(Div, div, PolyOverQ, Z, PolyOverQ);
implement_for_others!(Z, PolyOverQ, PolyOverQ, Div Scalar for i8 i16 i32 i64 u8 u16 u32 u64);
impl Div<&Q> for &PolyOverQ {
type Output = PolyOverQ;
fn div(self, scalar: &Q) -> Self::Output {
assert!(!scalar.is_zero(), "Tried to divide {self} by zero.");
let mut out = PolyOverQ::default();
unsafe {
fmpq_poly_scalar_div_fmpq(&mut out.poly, &self.poly, &scalar.value);
}
out
}
}
arithmetic_trait_borrowed_to_owned!(Div, div, PolyOverQ, Q, PolyOverQ);
arithmetic_trait_mixed_borrowed_owned!(Div, div, PolyOverQ, Q, PolyOverQ);
implement_for_others!(Q, PolyOverQ, PolyOverQ, Div Scalar for f32 f64);
impl DivAssign<&Q> for PolyOverQ {
fn div_assign(&mut self, scalar: &Q) {
assert!(!scalar.is_zero(), "Tried to divide {self} by zero.");
unsafe { fmpq_poly_scalar_div_fmpq(&mut self.poly, &self.poly, &scalar.value) }
}
}
impl DivAssign<&Z> for PolyOverQ {
fn div_assign(&mut self, scalar: &Z) {
assert!(!scalar.is_zero(), "Tried to divide {self} by zero.");
unsafe { fmpq_poly_scalar_div_fmpz(&mut self.poly, &self.poly, &scalar.value) };
}
}
impl DivAssign<u64> for PolyOverQ {
fn div_assign(&mut self, scalar: u64) {
assert!(scalar != 0, "Tried to divide {self} by zero.");
unsafe { fmpq_poly_scalar_div_ui(&mut self.poly, &self.poly, scalar) };
}
}
impl DivAssign<i64> for PolyOverQ {
fn div_assign(&mut self, scalar: i64) {
assert!(scalar != 0, "Tried to divide {self} by zero.");
unsafe { fmpq_poly_scalar_div_si(&mut self.poly, &self.poly, scalar) };
}
}
arithmetic_assign_trait_borrowed_to_owned!(DivAssign, div_assign, PolyOverQ, Q);
arithmetic_assign_trait_borrowed_to_owned!(DivAssign, div_assign, PolyOverQ, Z);
arithmetic_assign_between_types!(DivAssign, div_assign, PolyOverQ, u64, u32 u16 u8);
arithmetic_assign_between_types!(DivAssign, div_assign, PolyOverQ, i64, i32 i16 i8);
arithmetic_assign_between_types!(DivAssign, div_assign, PolyOverQ, Q, f64 f32);
#[cfg(test)]
mod test_mul_z {
use super::PolyOverQ;
use crate::integer::Z;
use std::str::FromStr;
#[test]
fn borrowed_correctness() {
let poly_1 = PolyOverQ::from_str(&format!("3 1 4/5 {}", (i64::MAX as u64) * 2)).unwrap();
let poly_2 = PolyOverQ::from_str(&format!("3 1/2 2/5 {}", i64::MAX)).unwrap();
let integer = Z::from(2);
let poly_1 = &poly_1 / &integer;
assert_eq!(poly_2, poly_1);
}
#[test]
fn availability() {
let poly = PolyOverQ::from_str("3 1/2 2 3/8").unwrap();
let z = Z::from(2);
_ = poly.clone() / z.clone();
_ = poly.clone() / 2i8;
_ = poly.clone() / 2u8;
_ = poly.clone() / 2i16;
_ = poly.clone() / 2u16;
_ = poly.clone() / 2i32;
_ = poly.clone() / 2u32;
_ = poly.clone() / 2i64;
_ = poly.clone() / 2u64;
_ = &poly / &z;
_ = &poly / z.clone();
_ = poly.clone() / &z;
_ = &poly / 2i8;
}
}
#[cfg(test)]
mod test_mul_q {
use crate::{
integer::Z,
rational::{PolyOverQ, Q},
};
use std::str::FromStr;
#[test]
fn borrowed_correctness() {
let poly_1 = PolyOverQ::from_str(&format!("3 1 2 {}", (i64::MAX as u64) * 2)).unwrap();
let poly_2 = poly_1.clone();
let poly_3 = PolyOverQ::from_str(&format!("3 1/2 1 {}", i64::MAX)).unwrap();
let rational = Q::from((1, 2));
let poly_1 = &poly_1 * &rational;
let poly_2 = &rational * &poly_2;
assert_eq!(poly_3, poly_1);
assert_eq!(poly_3, poly_2);
}
#[test]
fn availability() {
let poly = PolyOverQ::from_str("3 1/2 2 3/7").unwrap();
let q = Q::from((1, 2));
_ = poly.clone() / q.clone();
_ = &poly / &q;
_ = &poly / q.clone();
_ = &poly / 2.0_f32;
_ = &poly / 2.0_f64;
}
#[test]
#[should_panic]
fn div_0() {
let poly = PolyOverQ::from_str("3 1/2 2 3/7").unwrap();
let integer = Z::from(0);
let _ = &poly / &integer;
}
}
#[cfg(test)]
mod test_div_assign {
use crate::integer::Z;
use crate::rational::{PolyOverQ, Q};
use std::str::FromStr;
#[test]
fn consistency() {
let mut a = PolyOverQ::from_str("3 1/2 2 3/7").unwrap();
let b = Q::from((1, i32::MAX));
let cmp = &a / &b;
a /= b;
assert_eq!(cmp, a);
}
#[test]
fn availability() {
let mut a = PolyOverQ::from_str("3 1/2 2 3/7").unwrap();
let b = Z::from(2);
let c = Q::from((2, 3));
a /= &b;
a /= b;
a /= &c;
a /= c;
a /= 1_u8;
a /= 1_u16;
a /= 1_u32;
a /= 1_u64;
a /= 1_i8;
a /= 1_i16;
a /= 1_i32;
a /= 1_i64;
a /= 1_f32;
a /= 1_f64;
}
#[test]
#[should_panic]
fn div_0() {
let mut a = PolyOverQ::from_str("3 1/2 2 3/7").unwrap();
let b = Q::from((0, i32::MAX));
a /= b;
}
}