use super::Q;
use flint_sys::fmpq::{fmpq_clear, fmpq_set};
impl Clone for Q {
fn clone(&self) -> Self {
let mut clone = Self::default();
unsafe { fmpq_set(&mut clone.value, &self.value) };
clone
}
}
impl Drop for Q {
fn drop(&mut self) {
unsafe { fmpq_clear(&mut self.value) }
}
}
#[cfg(test)]
mod test_clone {
use super::Q;
use crate::integer::Z;
use std::str::FromStr;
#[test]
fn clone_equals_small() {
let values = ["1/2", "-1/2", "0/1"];
for str_value in values {
let val = Q::from_str(str_value).unwrap();
let val_clone = val.clone();
assert_eq!(
Z {
value: val.value.num
},
Z {
value: val_clone.value.num
}
);
assert_eq!(
Z {
value: val.value.den
},
Z {
value: val_clone.value.den
}
);
assert_eq!(val, val_clone);
assert_eq!(val.value.num.0, val_clone.value.num.0);
assert_eq!(val.value.den.0, val_clone.value.den.0);
}
}
#[test]
fn clone_equals_large() {
let large = "1".repeat(65);
let signs = ["", "-"];
for sign in signs {
let val = Q::from_str(&format!("{sign}{large}/2")).unwrap();
let val_clone = val.clone();
assert_eq!(
Z {
value: val.value.num
},
Z {
value: val_clone.value.num
}
);
assert_eq!(
Z {
value: val.value.den
},
Z {
value: val_clone.value.den
}
);
assert_eq!(val, val_clone);
assert_ne!(val.value.num.0, val_clone.value.num.0);
}
}
#[test]
#[allow(clippy::redundant_clone)]
fn keep_alive() {
let a: Q;
{
let b = Q::from(5);
a = b.clone();
}
assert_eq!(a, Q::from(5));
}
}
#[cfg(test)]
mod test_drop {
use super::Q;
use std::str::FromStr;
#[test]
fn free_memory() {
let string = format!("{}/2", "1".repeat(65));
let a = Q::from_str(&string).unwrap();
let num_point_in_memory = a.value.num.0;
let den_point_in_memory = a.value.den.0;
drop(a);
let c = Q::from_str(&string).unwrap();
assert_eq!(num_point_in_memory, c.value.num.0);
assert_eq!(den_point_in_memory, c.value.den.0);
assert_ne!(
num_point_in_memory,
Q::from_str(&"1".repeat(65)).unwrap().value.num.0
);
}
}