qfall_math/integer_mod_q/mat_zq/
ownership.rs1use super::MatZq;
15use crate::traits::MatrixDimensions;
16use flint3_sys::{fmpz_mod_mat_clear, fmpz_mod_mat_set};
17
18impl Clone for MatZq {
19 fn clone(&self) -> Self {
31 let mut out = MatZq::new(self.get_num_rows(), self.get_num_columns(), self.get_mod());
32 unsafe {
33 fmpz_mod_mat_set(
34 &mut out.matrix,
35 &self.matrix,
36 self.modulus.get_fmpz_mod_ctx_struct(),
37 );
38 }
39 out
40 }
41}
42
43impl Drop for MatZq {
44 fn drop(&mut self) {
66 unsafe { fmpz_mod_mat_clear(&mut self.matrix, self.modulus.get_fmpz_mod_ctx_struct()) }
67 }
68}
69
70#[cfg(test)]
72mod test_clone {
73 use super::MatZq;
74 use crate::integer::Z;
75 use crate::traits::{MatrixDimensions, MatrixGetEntry};
76 use std::{collections::HashSet, str::FromStr};
77
78 #[test]
80 #[allow(clippy::redundant_clone)]
81 fn keep_alive() {
82 let a: MatZq;
83 let str_1 = "[[1, 2, 3],[3, 4, 5]] mod 6";
84 {
85 let b = MatZq::from_str(str_1).unwrap();
86
87 a = b.clone();
88 }
89
90 assert_eq!(a.get_num_rows(), 2);
91 assert_eq!(a.get_num_columns(), 3);
92
93 assert_eq!(MatrixGetEntry::<Z>::get_entry(&a, 0, 0).unwrap(), 1);
94 assert_eq!(MatrixGetEntry::<Z>::get_entry(&a, 0, 1).unwrap(), 2);
95 assert_eq!(MatrixGetEntry::<Z>::get_entry(&a, 0, 2).unwrap(), 3);
96 assert_eq!(MatrixGetEntry::<Z>::get_entry(&a, 1, 0).unwrap(), 3);
97 assert_eq!(MatrixGetEntry::<Z>::get_entry(&a, 1, 1).unwrap(), 4);
98 assert_eq!(MatrixGetEntry::<Z>::get_entry(&a, 1, 2).unwrap(), 5);
99 }
100
101 #[test]
103 fn entries_stored_separately() {
104 let a: MatZq;
105 let string = format!("[[{}, {}],[-10, 0]] mod {}", i64::MAX, i64::MIN, u64::MAX);
106 let b = MatZq::from_str(&string).unwrap();
107
108 a = b.clone();
109
110 assert_ne!(
111 MatrixGetEntry::<Z>::get_entry(&a, 0, 0).unwrap().value,
112 MatrixGetEntry::<Z>::get_entry(&b, 0, 0).unwrap().value
113 );
114 assert_ne!(
115 MatrixGetEntry::<Z>::get_entry(&a, 0, 1).unwrap().value,
116 MatrixGetEntry::<Z>::get_entry(&b, 0, 1).unwrap().value
117 );
118 assert_ne!(
119 MatrixGetEntry::<Z>::get_entry(&a, 1, 0).unwrap().value,
120 MatrixGetEntry::<Z>::get_entry(&b, 1, 0).unwrap().value
121 );
122 assert_eq!(
123 MatrixGetEntry::<Z>::get_entry(&a, 1, 1).unwrap().value,
124 MatrixGetEntry::<Z>::get_entry(&b, 1, 1).unwrap().value
125 ); }
127
128 #[test]
130 #[allow(clippy::redundant_clone)]
131 fn modulus_applied() {
132 let string = String::from("[[1, 2],[4, 5]] mod 4");
133 let b = MatZq::from_str(&string).unwrap();
134
135 let a = b.clone();
136
137 assert_eq!(MatrixGetEntry::<Z>::get_entry(&a, 1, 1).unwrap(), 1);
138 assert_eq!(MatrixGetEntry::<Z>::get_entry(&a, 1, 0).unwrap(), 0);
139 }
140
141 #[test]
146 fn no_memory_leak() {
147 let a = MatZq::from_str("[[1, 2, 3],[4, 5, 6]] mod 7").unwrap();
148 let mut storage_addresses = HashSet::new();
149
150 for _i in 0..5 {
151 let b = a.clone();
152 storage_addresses.insert(b.matrix.entries as usize);
153 }
154
155 assert!(storage_addresses.len() < 5);
156 }
157}
158
159#[cfg(test)]
161mod test_drop {
162 use super::MatZq;
163 use crate::integer::Z;
164 use crate::traits::{AsInteger, MatrixGetEntry};
165 use std::collections::HashSet;
166 use std::str::FromStr;
167
168 fn create_and_drop_matzq() -> (i64, i64, i64) {
171 let string = format!("[[{}, {}]] mod {}", i64::MAX, i64::MIN, u64::MAX);
172 let a = MatZq::from_str(&string).unwrap();
173
174 let storage_mod = unsafe { a.get_mod().into_fmpz() };
175 let storage_0 = MatrixGetEntry::<Z>::get_entry(&a, 0, 0).unwrap().value;
176 let storage_1 = MatrixGetEntry::<Z>::get_entry(&a, 0, 1).unwrap().value;
177
178 (storage_mod, storage_0, storage_1)
179 }
180
181 #[test]
183 fn free_memory() {
184 let mut set = HashSet::new();
185
186 for _i in 0..5 {
187 let (a, b, c) = create_and_drop_matzq();
188 set.insert(a);
189 set.insert(b);
190 set.insert(c);
191 }
192
193 assert!(set.len() < 15);
194 }
195}