use super::PolyOverZq;
use crate::integer::PolyOverZ;
use flint_sys::fmpz_mod_poly::{
fmpz_mod_poly_clear, fmpz_mod_poly_init, fmpz_mod_poly_set_fmpz_poly,
};
use std::{mem::MaybeUninit, str::FromStr};
impl Clone for PolyOverZq {
fn clone(&self) -> Self {
let string = self.to_string();
let poly_over_z = PolyOverZ::from_str(&string).unwrap();
let mut poly_zq = MaybeUninit::uninit();
unsafe {
fmpz_mod_poly_init(poly_zq.as_mut_ptr(), self.modulus.get_fmpz_mod_ctx_struct());
let mut poly_zq = poly_zq.assume_init();
fmpz_mod_poly_set_fmpz_poly(
&mut poly_zq,
&poly_over_z.poly,
self.modulus.get_fmpz_mod_ctx_struct(),
);
Self {
poly: poly_zq,
modulus: self.modulus.clone(),
}
}
}
}
impl Drop for PolyOverZq {
fn drop(&mut self) {
unsafe {
fmpz_mod_poly_clear(&mut self.poly, self.modulus.get_fmpz_mod_ctx_struct());
}
}
}
#[cfg(test)]
mod test_clone {
use super::PolyOverZq;
use std::str::FromStr;
#[test]
fn same_reference() {
let a = PolyOverZq::from_str(&format!("4 {} 1 -2 3 mod {}", i64::MAX, u64::MAX)).unwrap();
let b = a.clone();
assert_eq!(
a.modulus.get_fmpz_mod_ctx_struct().n[0].0,
b.modulus.get_fmpz_mod_ctx_struct().n[0].0
);
assert_ne!(
unsafe { *a.poly.coeffs.offset(0) }.0,
unsafe { *b.poly.coeffs.offset(0) }.0
); assert_eq!(
unsafe { *a.poly.coeffs.offset(1) }.0,
unsafe { *b.poly.coeffs.offset(1) }.0
); assert_ne!(
unsafe { *a.poly.coeffs.offset(2) }.0,
unsafe { *b.poly.coeffs.offset(2) }.0
); assert_eq!(
unsafe { *a.poly.coeffs.offset(3) }.0,
unsafe { *b.poly.coeffs.offset(3) }.0
);
assert_eq!(a.poly.length, b.poly.length);
}
}
#[cfg(test)]
mod test_drop {
use super::PolyOverZq;
use std::{collections::HashSet, str::FromStr};
fn create_and_drop_modulus() -> (i64, i64) {
let a = PolyOverZq::from_str(&format!("2 {} -2 mod {}", i64::MAX, u64::MAX)).unwrap();
(
unsafe { *a.poly.coeffs.offset(0) }.0,
unsafe { *a.poly.coeffs.offset(1) }.0,
)
}
#[test]
fn free_memory() {
let mut storage_addresses = HashSet::new();
for _i in 0..5 {
let (a, b) = create_and_drop_modulus();
storage_addresses.insert(a);
storage_addresses.insert(b);
}
assert!(storage_addresses.len() < 10);
}
}