qfall_math/integer_mod_q/mat_zq.rs
1// Copyright © 2023 Marcel Luca Schmidt
2//
3// This file is part of qFALL-math.
4//
5// qFALL-math is free software: you can redistribute it and/or modify it under
6// the terms of the Mozilla Public License Version 2.0 as published by the
7// Mozilla Foundation. See <https://mozilla.org/en-US/MPL/2.0/>.
8
9//! [`MatZq`] is a type of matrix with integer entries of arbitrary length modulo `q`.
10//! This implementation uses the [FLINT](https://flintlib.org/) library.
11
12// For **DEVELOPERS**: Many functions assume that the [`MatZq`] instances are reduced.
13// To avoid unnecessary checks and reductions, always return canonical/reduced
14// values. The end-user should be unable to obtain a non-reduced value.
15
16use crate::{integer_mod_q::Modulus, utils::parse::partial_string};
17use flint_sys::fmpz_mod_mat::fmpz_mod_mat_struct;
18use std::fmt;
19
20mod arithmetic;
21mod cmp;
22mod concat;
23mod default;
24mod from;
25mod get;
26mod inverse;
27mod norm;
28mod ownership;
29mod properties;
30mod sample;
31mod serialize;
32mod set;
33mod solve;
34mod sort;
35mod tensor;
36mod to_string;
37mod trace;
38mod transpose;
39mod unsafe_functions;
40mod vector;
41
42/// [`MatZq`] is a matrix with entries of type [`Zq`](crate::integer_mod_q::Zq).
43///
44/// Attributes:
45/// - `matrix`: holds [FLINT](https://flintlib.org/)'s [struct](fmpz_mod_mat_struct)
46/// of the [`Zq`](crate::integer_mod_q::Zq) matrix
47///
48/// # Examples
49/// ## Matrix usage
50/// ```
51/// use qfall_math::{
52/// integer::Z,
53/// integer_mod_q::MatZq,
54/// traits::{MatrixGetEntry, MatrixSetEntry},
55/// };
56/// use std::str::FromStr;
57///
58/// // instantiate new matrix
59/// let id_mat = MatZq::from_str("[[1, 0],[0, 1]] mod 2").unwrap();
60///
61/// // clone object, set and get entry
62/// let mut clone = id_mat.clone();
63/// clone.set_entry(0, 0, 2);
64/// let entry:Z = clone.get_entry(1, 1).unwrap();
65/// assert_eq!(entry, Z::ONE);
66///
67/// // to_string incl. (de-)serialization
68/// assert_eq!("[[1, 0],[0, 1]] mod 2", &id_mat.to_string());
69/// ```
70///
71/// ## Vector usage
72/// ```
73/// use qfall_math::{
74/// integer::Z,
75/// integer_mod_q::MatZq,
76/// };
77/// use std::str::FromStr;
78///
79/// let row_vec = MatZq::from_str("[[1, 1, 1]] mod 2").unwrap();
80/// let col_vec = MatZq::from_str("[[1],[-1],[0]] mod 2").unwrap();
81///
82/// // check if matrix instance is vector
83/// assert!(row_vec.is_row_vector());
84/// assert!(col_vec.is_column_vector());
85/// ```
86pub struct MatZq {
87 pub(crate) matrix: fmpz_mod_mat_struct,
88
89 // Since `get_mod` is needed for many actions with `MatZq` instances
90 // a separate storage of the modulus object guarantees memory safety and
91 // is due to a reference counter in the `Modulus` object memory efficient.
92 // The modulus of a `MatZq` is not able to be modified afterwards. Hence, we
93 // do not need to care about conformity of the modulus stored in the `matrix`
94 // attribute and `modulus` attribute, if they are both initalized from the same value.
95 modulus: Modulus,
96}
97
98impl fmt::Debug for MatZq {
99 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100 write!(
101 f,
102 "MatZq: {{matrix: {}, modulus: {}, storage: {{matrix: {:?}, modulus: {:?}}}}}",
103 // printing the entire matrix is not meaningful for large matrices
104 partial_string(&self.get_representative_least_nonnegative_residue(), 3, 3),
105 self.modulus,
106 self.matrix,
107 self.modulus
108 )
109 }
110}