1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// Copyright © 2023 Marcel Luca Schmidt
//
// 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 <https://mozilla.org/en-US/MPL/2.0/>.
//! This module contains the implementation of the `transpose` function.
use super::MatPolynomialRingZq;
use crate::traits::MatrixDimensions;
use flint_sys::fmpz_poly_mat::fmpz_poly_mat_transpose;
impl MatPolynomialRingZq {
/// Returns the transposed form of the given matrix, i.e. rows get transformed to columns
/// and vice versa.
///
/// # Examples
/// ```
/// use qfall_math::integer_mod_q::{MatPolynomialRingZq, ModulusPolynomialRingZq};
/// use qfall_math::integer::MatPolyOverZ;
/// use std::str::FromStr;
///
/// let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap();
/// let poly_mat = MatPolyOverZ::from_str("[[1 42],[2 1 2],[1 17]]").unwrap();
/// let poly_ring_mat = MatPolynomialRingZq::from((&poly_mat, &modulus));
///
/// let transpose = poly_ring_mat.transpose();
/// ```
pub fn transpose(&self) -> Self {
let mut out = Self::new(self.get_num_columns(), self.get_num_rows(), &self.modulus);
unsafe { fmpz_poly_mat_transpose(&mut out.matrix.matrix, &self.matrix.matrix) };
out
}
}
#[cfg(test)]
mod test_transpose {
use crate::{
integer::MatPolyOverZ,
integer_mod_q::{MatPolynomialRingZq, ModulusPolynomialRingZq},
};
use std::str::FromStr;
const LARGE_PRIME: u64 = u64::MAX - 58;
/// Checks if a row is correctly converted to a column
#[test]
fn row_to_column() {
let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap();
let poly_mat = MatPolyOverZ::from_str("[[1 42],[2 1 2],[1 17]]").unwrap();
let poly_ring_mat = MatPolynomialRingZq::from((&poly_mat, &modulus));
let cmp = MatPolyOverZ::from_str("[[1 8, 2 1 2, 1 0]]").unwrap();
assert_eq!(cmp, poly_ring_mat.transpose().matrix);
}
/// Checks if a column is correctly converted to a row
#[test]
fn column_to_row() {
let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap();
let poly_mat = MatPolyOverZ::from_str("[[1 42, 2 1 2, 1 17]]").unwrap();
let poly_ring_mat = MatPolynomialRingZq::from((&poly_mat, &modulus));
let cmp = MatPolyOverZ::from_str("[[1 8],[2 1 2],[1 0]]").unwrap();
assert_eq!(cmp, poly_ring_mat.transpose().matrix);
}
/// Checks if large, negative, and zero values are transposed correctly
#[test]
fn different_entry_values() {
let modulus =
ModulusPolynomialRingZq::from_str(&format!("4 1 0 0 1 mod {LARGE_PRIME}")).unwrap();
let poly_mat =
MatPolyOverZ::from_str(&format!("[[1 {}, 1 -42, 1 0]]", i64::MAX)).unwrap();
let poly_ring_mat = MatPolynomialRingZq::from((&poly_mat, &modulus));
let cmp = MatPolyOverZ::from_str(&format!(
"[[1 {}],[1 {}],[1 0]]",
i64::MAX,
LARGE_PRIME - 42
))
.unwrap();
assert_eq!(cmp, poly_ring_mat.transpose().matrix);
}
}