diff --git a/src/integer/mat_z.rs b/src/integer/mat_z.rs
index 3caaf4149..2d54ced7f 100644
--- a/src/integer/mat_z.rs
+++ b/src/integer/mat_z.rs
@@ -11,11 +11,14 @@
use flint_sys::fmpz_mat::fmpz_mat_struct;
+mod cmp;
mod from;
mod get;
+mod mul;
mod ownership;
mod set;
mod to_string;
+mod transpose;
/// [`MatZ`] is a matrix with entries of type [`Z`](crate::integer::Z).
///
diff --git a/src/integer/mat_z/cmp.rs b/src/integer/mat_z/cmp.rs
new file mode 100644
index 000000000..a1898060e
--- /dev/null
+++ b/src/integer/mat_z/cmp.rs
@@ -0,0 +1,105 @@
+// Copyright © 2023 Niklas Siemer
+//
+// This file is part of qFALL-math.
+//
+// qFALL-math is free software: you can redistribute it and/or modify it under
+// the terms of the Mozilla Public License Version 2.0 as published by the
+// Mozilla Foundation. See .
+
+//! This module contains implementations for comparison of [`MatZ`].
+
+use super::MatZ;
+use flint_sys::fmpz_mat::fmpz_mat_equal;
+
+impl PartialEq for MatZ {
+ /// Checks if two [`MatZ`] instances are equal. Used by the `==` and `!=` operators.
+ ///
+ /// Parameters:
+ /// - `other`: the other value that is compare against `self`
+ ///
+ /// Returns `true` if the elements are equal, otherwise `false`.
+ ///
+ /// # Example
+ /// ```
+ /// use math::integer::MatZ;
+ /// use std::str::FromStr;
+ ///
+ /// let a = MatZ::from_str("[[1,2],[3,4]]").unwrap();
+ /// let b = MatZ::from_str("[[1,2],[2,4]]").unwrap();
+ ///
+ /// // These are all equivalent and return false.
+ /// let compared: bool = (a == b);
+ /// # assert!(!compared);
+ /// let compared: bool = (&a == &b);
+ /// # assert!(!compared);
+ /// let compared: bool = (a.eq(&b));
+ /// # assert!(!compared);
+ /// let compared: bool = (MatZ::eq(&a,&b));
+ /// # assert!(!compared);
+ /// ```
+ fn eq(&self, other: &Self) -> bool {
+ unsafe { fmpz_mat_equal(&self.matrix, &other.matrix) != 0 }
+ }
+}
+
+// With the [`Eq`] trait, `a == a` is always true.
+// This is not guaranteed by the [`PartialEq`] trait.
+impl Eq for MatZ {}
+
+/// Test that the [`PartialEq`] trait is correctly implemented.
+#[cfg(test)]
+mod test_partial_eq {
+
+ use super::MatZ;
+ use std::str::FromStr;
+
+ /// Ensures that different instantiations do not break the equality between matrices
+ #[test]
+ fn equality_between_instantiations() {
+ let a = MatZ::from_str("[[0,1],[0,0]]").unwrap();
+ let mut b = MatZ::new(2, 2).unwrap();
+ b.set_entry(0, 1, 1).unwrap();
+
+ assert_eq!(a, b);
+ }
+
+ /// Checks that large and small entries (and different points in storage) do not break equality
+ #[test]
+ fn equality_for_large_and_small_entries() {
+ let a = MatZ::from_str(&format!(
+ "[[{},{}, 1],[-10, 10, 0],[0, 1, -10]]",
+ i64::MIN,
+ i64::MAX
+ ))
+ .unwrap();
+ let b = MatZ::from_str(&format!(
+ "[[{},{}, 1],[-10, 10, 0],[0, 1, -10]]",
+ i64::MIN,
+ i64::MAX
+ ))
+ .unwrap();
+
+ assert_eq!(&a, &b);
+ }
+
+ /// Checks that different unequal matrices are unequal
+ #[test]
+ fn not_equal() {
+ let a = MatZ::from_str(&format!("[[{},{}],[-10, 10]]", i64::MIN, i64::MAX)).unwrap();
+ let b = MatZ::from_str(&format!("[[0,{}],[-10, 10]]", i64::MAX)).unwrap();
+ let c = MatZ::from_str(&format!("[[{},{}],[-10, 10],[0,0]]", i64::MIN, i64::MAX)).unwrap();
+ let d = MatZ::from_str(&format!("[[{},{}]]", i64::MIN, i64::MAX)).unwrap();
+ let e = MatZ::from_str("[[0]]").unwrap();
+
+ assert_ne!(&a, &b);
+ assert_ne!(&a, &c);
+ assert_ne!(&a, &d);
+ assert_ne!(&a, &e);
+ assert_ne!(&b, &c);
+ assert_ne!(&b, &d);
+ assert_ne!(&b, &e);
+ assert_ne!(&c, &d);
+ assert_ne!(&c, &e);
+ assert_ne!(&d, &e);
+ }
+}
diff --git a/src/integer/mat_z/mul.rs b/src/integer/mat_z/mul.rs
new file mode 100644
index 000000000..2d32920f3
--- /dev/null
+++ b/src/integer/mat_z/mul.rs
@@ -0,0 +1,115 @@
+// Copyright © 2023 Niklas Siemer
+//
+// This file is part of qFALL-math.
+//
+// qFALL-math is free software: you can redistribute it and/or modify it under
+// the terms of the Mozilla Public License Version 2.0 as published by the
+// Mozilla Foundation. See .
+
+//! Implementation of the [`Mul`] trait for [`MatZ`] values.
+
+use super::MatZ;
+use crate::{
+ macros::arithmetics::{
+ arithmetic_trait_borrowed_to_owned, arithmetic_trait_mixed_borrowed_owned,
+ },
+ traits::{GetNumColumns, GetNumRows},
+};
+use flint_sys::fmpz_mat::fmpz_mat_mul;
+use std::ops::Mul;
+
+impl Mul for &MatZ {
+ type Output = MatZ;
+
+ /// Implements the [`Mul`] trait for two [`MatZ`] values.
+ ///
+ /// [`Mul`] is implemented for any combination of owned and borrowed [`MatZ`].
+ ///
+ /// Parameters:
+ /// - `other`: specifies the value to multiply with `self`
+ ///
+ /// Returns the product of `self` and `other` as a [`MatZ`].
+ ///
+ /// # Example
+ /// ```
+ /// use math::integer::MatZ;
+ /// use std::str::FromStr;
+ ///
+ /// let a = MatZ::from_str("[[2,1],[1,2]]").unwrap();
+ /// let b = MatZ::from_str("[[1,0],[0,1]]").unwrap();
+ ///
+ /// let c = &a * &b;
+ /// let d = a * b;
+ /// let e = &c * d;
+ /// let f = c * &e;
+ /// ```
+ ///
+ /// # Errors and Failures
+ /// - Panics if the dimensions of `self` and `other` do not match for multiplication.
+ fn mul(self, other: Self) -> Self::Output {
+ // TODO: mul_safe
+ if self.get_num_columns() != other.get_num_rows() {
+ panic!("Matrix dimensions do not match for matrix multiplication!");
+ }
+
+ let mut new = MatZ::new(self.get_num_rows(), other.get_num_columns()).unwrap();
+ unsafe { fmpz_mat_mul(&mut new.matrix, &self.matrix, &other.matrix) };
+ new
+ }
+}
+
+arithmetic_trait_borrowed_to_owned!(Mul, mul, MatZ);
+arithmetic_trait_mixed_borrowed_owned!(Mul, mul, MatZ);
+
+#[cfg(test)]
+mod test_mul {
+
+ use super::MatZ;
+ use crate::integer::Z;
+ use std::str::FromStr;
+
+ /// Checks if matrix multiplication works fine for sqaured matrices
+ #[test]
+ fn square_correctness() {
+ let mat_1 = MatZ::from_str("[[2,1],[1,2]]").unwrap();
+ let mat_2 = MatZ::from_str("[[1,0],[0,1]]").unwrap();
+ let mat_3 = MatZ::from_str("[[1,2],[2,1]]").unwrap();
+ let cmp = MatZ::from_str("[[4,5],[5,4]]").unwrap();
+
+ assert_eq!(mat_1, &mat_1 * &mat_2);
+ assert_eq!(cmp, &mat_1 * &mat_3);
+ }
+
+ /// Checks if matrix multiplication works fine for matrices of different dimensions
+ #[test]
+ fn different_dimensions_correctness() {
+ let mat = MatZ::from_str("[[2,1],[1,2]]").unwrap();
+ let vec = MatZ::from_str("[[1],[0]]").unwrap();
+ let cmp = MatZ::from_str("[[2],[1]]").unwrap();
+
+ assert_eq!(cmp, &mat * &vec);
+ }
+
+ /// Checks if matrix multiplication works fine for large entries
+ #[test]
+ fn large_entries() {
+ let mat = MatZ::from_str(&format!("[[{},1],[0,2]]", i64::MAX)).unwrap();
+ let vec = MatZ::from_str(&format!("[[{}],[0]]", i64::MAX)).unwrap();
+ let mut cmp = MatZ::new(2, 1).unwrap();
+ let max: Z = i64::MAX.into();
+ cmp.set_entry_ref_z(0, 0, &(&max * &max)).unwrap();
+
+ assert_eq!(cmp, mat * vec);
+ }
+
+ /// Checks if matrix multiplication with incompatible matrix dimensions
+ /// results in panic
+ #[test]
+ #[should_panic]
+ fn incompatible_dimensions() {
+ let mat_1 = MatZ::from_str("[[2,1],[1,2]]").unwrap();
+ let mat_2 = MatZ::from_str("[[1,0],[0,1],[0,0]]").unwrap();
+
+ let _ = mat_1 * mat_2;
+ }
+}
diff --git a/src/integer/mat_z/transpose.rs b/src/integer/mat_z/transpose.rs
new file mode 100644
index 000000000..4c0305948
--- /dev/null
+++ b/src/integer/mat_z/transpose.rs
@@ -0,0 +1,69 @@
+// Copyright © 2023 Niklas Siemer
+//
+// This file is part of qFALL-math.
+//
+// qFALL-math is free software: you can redistribute it and/or modify it under
+// the terms of the Mozilla Public License Version 2.0 as published by the
+// Mozilla Foundation. See .
+
+//! This module containts the implementation of the `transpose` function.
+
+use crate::traits::{GetNumColumns, GetNumRows};
+
+use super::MatZ;
+use flint_sys::fmpz_mat::fmpz_mat_transpose;
+
+impl MatZ {
+ /// Returns the transposed form of the given matrix, i.e. rows get transformed to columns
+ /// and vice versa.
+ ///
+ /// # Example
+ /// ```
+ /// use math::integer::MatZ;
+ /// use std::str::FromStr;
+ ///
+ /// let mat = MatZ::from_str("[[2,1],[2,1],[2,1]]").unwrap();
+ /// let cmp = MatZ::from_str("[[2,2,2],[1,1,1]]").unwrap();
+ ///
+ /// assert_eq!(mat.transpose(), cmp);
+ /// ```
+ pub fn transpose(&self) -> Self {
+ let mut out = Self::new(self.get_num_columns(), self.get_num_rows()).unwrap();
+ unsafe { fmpz_mat_transpose(&mut out.matrix, &self.matrix) };
+ out
+ }
+}
+
+#[cfg(test)]
+mod test_transpose {
+
+ use super::MatZ;
+ use std::str::FromStr;
+
+ /// Checks if a row is correctly converted to a column
+ #[test]
+ fn row_to_column() {
+ let mat = MatZ::from_str("[[1],[2],[3]]").unwrap();
+ let cmp = MatZ::from_str("[[1,2,3]]").unwrap();
+
+ assert_eq!(cmp, mat.transpose());
+ }
+
+ /// Checks if a column is correctly converted to a row
+ #[test]
+ fn column_to_row() {
+ let mat = MatZ::from_str("[[1,2,3]]").unwrap();
+ let cmp = MatZ::from_str("[[1],[2],[3]]").unwrap();
+
+ assert_eq!(cmp, mat.transpose());
+ }
+
+ /// Checks if large, negative, and zero values are transposed correctly
+ #[test]
+ fn different_entry_values() {
+ let mat = MatZ::from_str(&format!("[[{},{},0]]", i64::MAX, i64::MIN)).unwrap();
+ let cmp = MatZ::from_str(&format!("[[{}],[{}],[0]]", i64::MAX, i64::MIN)).unwrap();
+
+ assert_eq!(cmp, mat.transpose());
+ }
+}
diff --git a/src/utils/dimensions.rs b/src/utils/dimensions.rs
index 02689a8bd..9795d12de 100644
--- a/src/utils/dimensions.rs
+++ b/src/utils/dimensions.rs
@@ -6,7 +6,7 @@
// the terms of the Mozilla Public License Version 2.0 as published by the
// Mozilla Foundation. See .
-//! Implements methods for finding matrix dimensions.
+//! Implements methods for finding matrix dimensions and enums for detecting vector directions.
use crate::error::MathError;
diff --git a/src/utils/parse.rs b/src/utils/parse.rs
index f6e4a2073..b8b9a75a2 100644
--- a/src/utils/parse.rs
+++ b/src/utils/parse.rs
@@ -8,13 +8,12 @@
//! Implements methods to parse a [`String`] e.g. matrix strings.
-use std::fmt::Display;
-
use crate::{
error::MathError,
traits::{GetEntry, GetNumColumns, GetNumRows},
};
use regex::Regex;
+use std::fmt::Display;
use string_builder::Builder;
/// Takes the string of a matrix as input and parses it for easy use.
@@ -116,6 +115,7 @@ pub(crate) fn matrix_to_string + GetNumRows + GetNumCo
#[cfg(test)]
mod test_parse_matrix_string {
+
use crate::utils::parse::parse_matrix_string;
// Ensure that correct strings of a matrix are accepted.
@@ -125,11 +125,13 @@ mod test_parse_matrix_string {
let matrix_string2 = String::from("[[1/3, -2/7, 3],[3, 4, -5/-2]]");
let matrix_string3 = String::from("[[4 0 1 2 3, 2 0 1],[1 5, 2 7 8]]");
let matrix_string4 = String::from("[[sdclin, =§&%, +57n4],[+dk<, 37 ffew, 8fh2n]]");
+ let matrix_string5 = String::from("[[0],[1]]");
assert!(parse_matrix_string(&matrix_string1).is_ok());
assert!(parse_matrix_string(&matrix_string2).is_ok());
assert!(parse_matrix_string(&matrix_string3).is_ok());
assert!(parse_matrix_string(&matrix_string4).is_ok());
+ assert!(parse_matrix_string(&matrix_string5).is_ok());
}
// Ensure that incorrect strings of a matrix are rejected.