fp/matrix/
affine.rs

1use super::Subspace;
2use crate::vector::{FpSlice, FpVector};
3
4#[derive(Debug, Clone, PartialEq, Eq)]
5pub struct AffineSubspace {
6    offset: FpVector,
7    linear_part: Subspace,
8}
9
10impl AffineSubspace {
11    pub fn new(mut offset: FpVector, linear_part: Subspace) -> Self {
12        assert_eq!(offset.len(), linear_part.ambient_dimension());
13        linear_part.reduce(offset.as_slice_mut());
14        Self {
15            offset,
16            linear_part,
17        }
18    }
19
20    pub fn offset(&self) -> &FpVector {
21        &self.offset
22    }
23
24    pub fn linear_part(&self) -> &Subspace {
25        &self.linear_part
26    }
27
28    pub fn sum(&self, other: &Self) -> Self {
29        let linear_part = self.linear_part.sum(&other.linear_part);
30
31        let mut offset = self.offset.clone();
32        offset.add(&other.offset, 1);
33
34        Self::new(offset, linear_part)
35    }
36
37    pub fn contains(&self, vector: FpSlice) -> bool {
38        let mut vector = vector.to_owned();
39        vector.add(&self.offset, vector.prime() - 1);
40        self.linear_part.contains(vector.as_slice())
41    }
42
43    pub fn contains_space(&self, other: &Self) -> bool {
44        self.linear_part.contains_space(&other.linear_part)
45            && self.contains(other.offset.as_slice())
46    }
47}
48
49impl From<Subspace> for AffineSubspace {
50    fn from(subspace: Subspace) -> Self {
51        Self::new(
52            FpVector::new(subspace.prime(), subspace.ambient_dimension()),
53            subspace,
54        )
55    }
56}
57
58impl std::fmt::Display for AffineSubspace {
59    /// # Example
60    /// ```
61    /// # use fp::{matrix::{AffineSubspace, Matrix, Subspace}, prime::TWO, vector::FpVector};
62    /// let linear_part = Subspace::from_matrix(Matrix::from_vec(TWO, &[vec![0, 1, 0], vec![0, 0, 1]]));
63    /// let offset = FpVector::from_slice(TWO, &[1, 0, 0]);
64    /// let subspace = AffineSubspace::new(offset, linear_part);
65    ///
66    /// assert_eq!(
67    ///     format!("{}", subspace),
68    ///     "[1, 0, 0] + {[0, 1, 0], [0, 0, 1]}"
69    /// );
70    /// ```
71    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
72        write!(f, "{} + {{{:#}}}", self.offset, self.linear_part)
73    }
74}