use super::PolyOverQ;
use flint3_sys::{fmpq_poly_clear, fmpq_poly_init, fmpq_poly_set};
use std::mem::MaybeUninit;
unsafe impl Send for PolyOverQ {}
unsafe impl Sync for PolyOverQ {}
impl Clone for PolyOverQ {
fn clone(&self) -> Self {
let mut poly = MaybeUninit::uninit();
unsafe {
fmpq_poly_init(poly.as_mut_ptr());
let mut poly = poly.assume_init();
fmpq_poly_set(&mut poly, &self.poly);
Self { poly }
}
}
}
impl Drop for PolyOverQ {
fn drop(&mut self) {
unsafe {
fmpq_poly_clear(&mut self.poly);
}
}
}
#[cfg(test)]
mod test_clone {
use super::PolyOverQ;
use std::str::FromStr;
#[test]
fn same_reference_small() {
let a = PolyOverQ::from_str("4 1/1 -1/-2 -2/2 3/-4").unwrap();
let b = a.clone();
assert_eq!(unsafe { *a.poly.coeffs.offset(0) }, unsafe {
*b.poly.coeffs.offset(0)
});
assert_eq!(unsafe { *a.poly.coeffs.offset(1) }, unsafe {
*b.poly.coeffs.offset(1)
}); assert_eq!(unsafe { *a.poly.coeffs.offset(2) }, unsafe {
*b.poly.coeffs.offset(2)
}); assert_eq!(unsafe { *a.poly.coeffs.offset(3) }, unsafe {
*b.poly.coeffs.offset(3)
});
assert_eq!(a.poly.den[0], b.poly.den[0]);
assert_eq!(a.poly.length, b.poly.length);
}
#[test]
fn same_reference_large() {
let a =
PolyOverQ::from_str(&format!("4 {}/1 1/{} -2/2 3/-4", i64::MAX, i64::MIN)).unwrap();
let b = a.clone();
assert_ne!(unsafe { *a.poly.coeffs.offset(0) }, unsafe {
*b.poly.coeffs.offset(0)
}); assert_eq!(unsafe { *a.poly.coeffs.offset(1) }, unsafe {
*b.poly.coeffs.offset(1)
}); assert_ne!(unsafe { *a.poly.coeffs.offset(2) }, unsafe {
*b.poly.coeffs.offset(2)
}); assert_ne!(unsafe { *a.poly.coeffs.offset(3) }, unsafe {
*b.poly.coeffs.offset(3)
});
assert_ne!(a.poly.den[0], b.poly.den[0]);
assert_eq!(a.poly.length, b.poly.length);
}
}
#[cfg(test)]
mod test_drop {
use super::PolyOverQ;
use std::{collections::HashSet, str::FromStr};
fn create_and_drop_modulus() -> (i64, i64, i64) {
let a = PolyOverQ::from_str(&format!("2 {}/1 -2/-3", i64::MAX)).unwrap();
(
unsafe { *a.poly.coeffs.offset(0) },
unsafe { *a.poly.coeffs.offset(1) },
a.poly.den[0],
)
}
#[test]
fn free_memory() {
let mut storage_addresses = HashSet::new();
for _i in 0..5 {
storage_addresses.insert(create_and_drop_modulus());
}
assert!(storage_addresses.len() < 5);
}
}