qfall_math/integer_mod_q/modulus_polynomial_ring_zq/
ownership.rs1use super::ModulusPolynomialRingZq;
15use flint_sys::fq::fq_ctx_clear;
16use std::rc::Rc;
17
18impl Clone for ModulusPolynomialRingZq {
19 fn clone(&self) -> Self {
34 Self {
35 modulus: Rc::clone(&self.modulus),
36 ntt_basis: Rc::clone(&self.ntt_basis),
37 }
38 }
39}
40
41impl Drop for ModulusPolynomialRingZq {
42 fn drop(&mut self) {
62 if Rc::strong_count(&self.modulus) <= 1 {
63 let mut a = *self.modulus;
64 unsafe {
65 fq_ctx_clear(&mut a);
66 }
67 }
68 }
69}
70
71#[cfg(test)]
73mod test_clone {
74 use super::ModulusPolynomialRingZq;
75 use std::{rc::Rc, str::FromStr};
76
77 #[test]
79 fn references_increased() {
80 let a = ModulusPolynomialRingZq::from_str("3 1 0 1 mod 17").unwrap();
81 assert_eq!(Rc::strong_count(&a.modulus), 1);
82
83 let b = a.clone();
84
85 assert_eq!(Rc::strong_count(&a.modulus), 2);
86 assert_eq!(Rc::strong_count(&b.modulus), 2);
87
88 let c = b.clone();
89
90 assert_eq!(Rc::strong_count(&a.modulus), 3);
91 assert_eq!(Rc::strong_count(&b.modulus), 3);
92 assert_eq!(Rc::strong_count(&c.modulus), 3);
93 }
94
95 #[test]
97 fn same_reference() {
98 let a = ModulusPolynomialRingZq::from_str(&format!(
99 "3 {} 0 -{} mod {}",
100 u64::MAX,
101 u64::MAX,
102 u64::MAX - 58 ))
104 .unwrap();
105
106 let b = a.clone();
107
108 assert_eq!(
109 unsafe { *a.get_fq_ctx().a }.0,
110 unsafe { *b.get_fq_ctx().a }.0,
111 );
112 assert_eq!(a.get_fq_ctx().ctxp[0].n[0].0, b.get_fq_ctx().ctxp[0].n[0].0,);
113 assert_eq!(
114 unsafe { *a.get_fq_ctx().modulus[0].coeffs.offset(0) }.0,
115 unsafe { *b.get_fq_ctx().modulus[0].coeffs.offset(0) }.0,
116 );
117 }
118}
119
120#[cfg(test)]
122mod test_drop {
123 use super::ModulusPolynomialRingZq;
124 use std::{collections::HashSet, rc::Rc, str::FromStr};
125
126 #[test]
128 fn references_decreased() {
129 let a = ModulusPolynomialRingZq::from_str("3 1 0 1 mod 17").unwrap();
130 assert_eq!(Rc::strong_count(&a.modulus), 1);
131
132 {
133 let b = a.clone();
134
135 assert_eq!(Rc::strong_count(&a.modulus), 2);
136 assert_eq!(Rc::strong_count(&b.modulus), 2);
137 }
138
139 assert_eq!(Rc::strong_count(&a.modulus), 1);
140
141 let b = a.clone();
142 assert_eq!(Rc::strong_count(&a.modulus), 2);
143 assert_eq!(Rc::strong_count(&b.modulus), 2);
144
145 let c = b.clone();
146 assert_eq!(Rc::strong_count(&a.modulus), 3);
147 assert_eq!(Rc::strong_count(&b.modulus), 3);
148 assert_eq!(Rc::strong_count(&c.modulus), 3);
149
150 drop(a);
151 assert_eq!(Rc::strong_count(&b.modulus), 2);
152 }
153
154 fn create_and_drop_modulus() -> (i64, i64, i64) {
157 let a = ModulusPolynomialRingZq::from_str(
158 "3 184467440739018 0 -184467440739018 mod 184467440739019",
159 )
160 .unwrap();
161 (
162 unsafe { *a.get_fq_ctx().a }.0,
163 a.get_fq_ctx().ctxp[0].n[0].0,
164 unsafe { *a.get_fq_ctx().modulus[0].coeffs.offset(0) }.0,
165 )
166 }
167
168 #[test]
170 fn free_memory() {
171 let mut storage_addresses = HashSet::new();
172
173 for _i in 0..5 {
174 storage_addresses.insert(create_and_drop_modulus());
175 }
176
177 assert!(storage_addresses.len() < 5);
178 }
179}