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 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
72 write!(f, "{} + {{{:#}}}", self.offset, self.linear_part)
73 }
74}