qfall_math/integer/mat_z/
concat.rs1use super::MatZ;
12use crate::{
13 error::MathError,
14 traits::{Concatenate, MatrixDimensions},
15};
16use flint_sys::fmpz_mat::{fmpz_mat_concat_horizontal, fmpz_mat_concat_vertical};
17
18impl Concatenate for &MatZ {
19 type Output = MatZ;
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 = MatZ::new(
55 self.get_num_rows() + other.get_num_rows(),
56 self.get_num_columns(),
57 );
58 unsafe {
59 fmpz_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 = MatZ::new(
98 self.get_num_rows(),
99 self.get_num_columns() + other.get_num_columns(),
100 );
101 unsafe {
102 fmpz_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::MatZ,
112 traits::{Concatenate, MatrixDimensions},
113 };
114 use std::str::FromStr;
115
116 #[test]
119 fn dimensions_vertical() {
120 let mat_1 = MatZ::new(13, 5);
121 let mat_2 = MatZ::new(17, 5);
122 let mat_3 = MatZ::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 = MatZ::new(13, 5);
136 let mat_2 = MatZ::new(17, 5);
137 let mat_3 = MatZ::new(17, 6);
138
139 let mat_vert = mat_2.concat_horizontal(&mat_3).unwrap();
140
141 assert_eq!(11, mat_vert.get_num_columns());
142 assert_eq!(17, mat_vert.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 =
150 MatZ::from_str(&format!("[[1, 2, {}],[4, 5, {}]]", i64::MIN, u64::MAX)).unwrap();
151 let mat_2 = MatZ::from_str("[[-1, 2, -17]]").unwrap();
152
153 let mat_vertical = mat_1.concat_vertical(&mat_2).unwrap();
154
155 let cmp_mat = MatZ::from_str(&format!(
156 "[[1, 2, {}],[4, 5, {}],[-1, 2, -17]]",
157 i64::MIN,
158 u64::MAX
159 ))
160 .unwrap();
161 assert_eq!(cmp_mat, mat_vertical);
162 }
163
164 #[test]
166 fn horizontally_correct() {
167 let mat_1 =
168 MatZ::from_str(&format!("[[1, 2, {}],[4, 5, {}]]", i64::MIN, u64::MAX)).unwrap();
169 let mat_2 = MatZ::from_str("[[-1, 2],[4, 5]]").unwrap();
170
171 let mat_horizontal = mat_1.concat_horizontal(&mat_2).unwrap();
172
173 let cmp_mat = MatZ::from_str(&format!(
174 "[[1, 2, {}, -1, 2],[4, 5, {}, 4, 5]]",
175 i64::MIN,
176 u64::MAX
177 ))
178 .unwrap();
179 assert_eq!(cmp_mat, mat_horizontal);
180 }
181}