qfall_math/integer/mat_z/
tensor.rs1use super::MatZ;
12use crate::traits::{MatrixDimensions, Tensor};
13use flint_sys::fmpz_mat::fmpz_mat_kronecker_product;
14
15impl Tensor for MatZ {
16 fn tensor_product(&self, other: &Self) -> Self {
41 let mut out = MatZ::new(
42 self.get_num_rows() * other.get_num_rows(),
43 self.get_num_columns() * other.get_num_columns(),
44 );
45
46 unsafe { fmpz_mat_kronecker_product(&mut out.matrix, &self.matrix, &other.matrix) };
47
48 out
49 }
50}
51#[cfg(test)]
52mod test_tensor {
53 use crate::{
54 integer::MatZ,
55 traits::{MatrixDimensions, Tensor},
56 };
57 use std::str::FromStr;
58
59 #[test]
61 fn dimensions_fit() {
62 let mat_1 = MatZ::new(17, 13);
63 let mat_2 = MatZ::new(3, 4);
64
65 let mat_3 = mat_1.tensor_product(&mat_2);
66
67 assert_eq!(51, mat_3.get_num_rows());
68 assert_eq!(52, mat_3.get_num_columns());
69 }
70
71 #[test]
73 fn identity() {
74 let identity = MatZ::identity(2, 2);
75 let mat_1 =
76 MatZ::from_str(&format!("[[1, {}, 1],[0, {}, -1]]", u64::MAX, i64::MIN)).unwrap();
77
78 let mat_2 = identity.tensor_product(&mat_1);
79 let mat_3 = mat_1.tensor_product(&identity);
80
81 let cmp_mat_2 = MatZ::from_str(&format!(
82 "[[1, {}, 1, 0, 0, 0],[0, {}, -1, 0, 0, 0],[0, 0, 0, 1, {}, 1],[0, 0, 0, 0, {}, -1]]",
83 u64::MAX,
84 i64::MIN,
85 u64::MAX,
86 i64::MIN
87 ))
88 .unwrap();
89 let cmp_mat_3 = MatZ::from_str(&format!(
90 "[[1, 0, {}, 0, 1, 0],[0, 1, 0, {}, 0, 1],[0, 0, {}, 0, -1, 0],[0, 0, 0, {}, 0, -1]]",
91 u64::MAX,
92 u64::MAX,
93 i64::MIN,
94 i64::MIN
95 ))
96 .unwrap();
97
98 assert_eq!(cmp_mat_2, mat_2);
99 assert_eq!(cmp_mat_3, mat_3);
100 }
101
102 #[test]
104 fn vector_matrix() {
105 let vector = MatZ::from_str("[[1],[-1]]").unwrap();
106 let mat_1 =
107 MatZ::from_str(&format!("[[1, {}, 1],[0, {}, -1]]", u64::MAX, i64::MAX)).unwrap();
108
109 let mat_2 = vector.tensor_product(&mat_1);
110 let mat_3 = mat_1.tensor_product(&vector);
111
112 let cmp_mat_2 = MatZ::from_str(&format!(
113 "[[1, {}, 1],[0, {}, -1],[-1, -{}, -1],[0, -{}, 1]]",
114 u64::MAX,
115 i64::MAX,
116 u64::MAX,
117 i64::MAX
118 ))
119 .unwrap();
120 let cmp_mat_3 = MatZ::from_str(&format!(
121 "[[1, {}, 1],[-1, -{}, -1],[0, {}, -1],[0, -{}, 1]]",
122 u64::MAX,
123 u64::MAX,
124 i64::MAX,
125 i64::MAX
126 ))
127 .unwrap();
128
129 assert_eq!(cmp_mat_2, mat_2);
130 assert_eq!(cmp_mat_3, mat_3);
131 }
132
133 #[test]
135 fn vector_vector() {
136 let vec_1 = MatZ::from_str("[[2],[1]]").unwrap();
137 let vec_2 =
138 MatZ::from_str(&format!("[[{}],[{}]]", (u64::MAX - 1) / 2, i64::MIN / 2)).unwrap();
139
140 let vec_3 = vec_1.tensor_product(&vec_2);
141 let vec_4 = vec_2.tensor_product(&vec_1);
142
143 let cmp_vec_3 = MatZ::from_str(&format!(
144 "[[{}],[{}],[{}],[{}]]",
145 u64::MAX - 1,
146 i64::MIN,
147 (u64::MAX - 1) / 2,
148 i64::MIN / 2
149 ))
150 .unwrap();
151 let cmp_vec_4 = MatZ::from_str(&format!(
152 "[[{}],[{}],[{}],[{}]]",
153 u64::MAX - 1,
154 (u64::MAX - 1) / 2,
155 i64::MIN,
156 i64::MIN / 2
157 ))
158 .unwrap();
159
160 assert_eq!(cmp_vec_3, vec_3);
161 assert_eq!(cmp_vec_4, vec_4);
162 }
163}