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}