qfall_math/integer/mat_poly_over_z/
concat.rs1use super::MatPolyOverZ;
12use crate::{
13 error::MathError,
14 traits::{Concatenate, MatrixDimensions},
15};
16use flint_sys::fmpz_poly_mat::{fmpz_poly_mat_concat_horizontal, fmpz_poly_mat_concat_vertical};
17
18impl Concatenate for &MatPolyOverZ {
19 type Output = MatPolyOverZ;
20
21 fn concat_vertical(self, other: Self) -> Result<Self::Output, crate::error::MathError> {
45 if self.get_num_columns() != other.get_num_columns() {
46 return Err(MathError::MismatchingMatrixDimension(format!(
47 "Tried to concatenate vertically a '{}x{}' matrix and a '{}x{}' matrix.",
48 self.get_num_rows(),
49 self.get_num_columns(),
50 other.get_num_rows(),
51 other.get_num_columns()
52 )));
53 }
54 let mut out = MatPolyOverZ::new(
55 self.get_num_rows() + other.get_num_rows(),
56 self.get_num_columns(),
57 );
58 unsafe {
59 fmpz_poly_mat_concat_vertical(&mut out.matrix, &self.matrix, &other.matrix);
60 }
61 Ok(out)
62 }
63
64 fn concat_horizontal(self, other: Self) -> Result<Self::Output, crate::error::MathError> {
88 if self.get_num_rows() != other.get_num_rows() {
89 return Err(MathError::MismatchingMatrixDimension(format!(
90 "Tried to concatenate horizontally a '{}x{}' matrix and a '{}x{}' matrix.",
91 self.get_num_rows(),
92 self.get_num_columns(),
93 other.get_num_rows(),
94 other.get_num_columns()
95 )));
96 }
97 let mut out = MatPolyOverZ::new(
98 self.get_num_rows(),
99 self.get_num_columns() + other.get_num_columns(),
100 );
101 unsafe {
102 fmpz_poly_mat_concat_horizontal(&mut out.matrix, &self.matrix, &other.matrix);
103 }
104 Ok(out)
105 }
106}
107
108#[cfg(test)]
109mod test_concatenate {
110 use crate::{
111 integer::MatPolyOverZ,
112 traits::{Concatenate, MatrixDimensions},
113 };
114 use std::str::FromStr;
115
116 #[test]
119 fn dimensions_vertical() {
120 let mat_1 = MatPolyOverZ::new(13, 5);
121 let mat_2 = MatPolyOverZ::new(17, 5);
122 let mat_3 = MatPolyOverZ::new(17, 6);
123
124 let mat_vert = mat_1.concat_vertical(&mat_2).unwrap();
125
126 assert_eq!(5, mat_vert.get_num_columns());
127 assert_eq!(30, mat_vert.get_num_rows());
128 assert!(mat_1.concat_vertical(&mat_3).is_err());
129 }
130
131 #[test]
134 fn dimensions_horizontal() {
135 let mat_1 = MatPolyOverZ::new(13, 5);
136 let mat_2 = MatPolyOverZ::new(17, 5);
137 let mat_3 = MatPolyOverZ::new(17, 6);
138
139 let mat_hor = mat_2.concat_horizontal(&mat_3).unwrap();
140
141 assert_eq!(11, mat_hor.get_num_columns());
142 assert_eq!(17, mat_hor.get_num_rows());
143 assert!(mat_1.concat_horizontal(&mat_2).is_err());
144 }
145
146 #[test]
148 fn vertically_correct() {
149 let mat_1 = MatPolyOverZ::from_str(&format!(
150 "[[1 1, 1 2, 1 {}],[0, 1 5, 1 {}]]",
151 i64::MIN,
152 u64::MAX
153 ))
154 .unwrap();
155 let mat_2 = MatPolyOverZ::from_str("[[1 -1, 1 2, 1 -17]]").unwrap();
156
157 let mat_vertical = mat_1.concat_vertical(&mat_2).unwrap();
158
159 let cmp_mat = MatPolyOverZ::from_str(&format!(
160 "[[1 1, 1 2, 1 {}],[0, 1 5, 1 {}],[1 -1, 1 2, 1 -17]]",
161 i64::MIN,
162 u64::MAX
163 ))
164 .unwrap();
165 assert_eq!(cmp_mat, mat_vertical);
166 }
167
168 #[test]
170 fn horizontally_correct() {
171 let mat_1 = MatPolyOverZ::from_str(&format!(
172 "[[1 1, 1 2, 1 {}],[0, 1 5, 1 {}]]",
173 i64::MIN,
174 u64::MAX
175 ))
176 .unwrap();
177 let mat_2 = MatPolyOverZ::from_str("[[1 -1, 1 2],[0, 1 5]]").unwrap();
178
179 let mat_horizontal = mat_1.concat_horizontal(&mat_2).unwrap();
180
181 let cmp_mat = MatPolyOverZ::from_str(&format!(
182 "[[1 1, 1 2, 1 {}, 1 -1, 1 2],[0, 1 5, 1 {}, 0, 1 5]]",
183 i64::MIN,
184 u64::MAX
185 ))
186 .unwrap();
187 assert_eq!(cmp_mat, mat_horizontal);
188 }
189}