poulpy_core/layouts/
glwe_pt.rs

1use std::fmt;
2
3use poulpy_hal::layouts::{Data, DataMut, DataRef, VecZnx, VecZnxToMut, VecZnxToRef, ZnxInfos};
4
5use crate::layouts::{
6    Base2K, BuildError, Degree, GLWECiphertext, GLWECiphertextToMut, GLWECiphertextToRef, GLWEInfos, GLWELayoutSet, LWEInfos,
7    Rank, TorusPrecision,
8};
9
10#[derive(PartialEq, Eq, Copy, Clone, Debug)]
11pub struct GLWEPlaintextLayout {
12    pub n: Degree,
13    pub base2k: Base2K,
14    pub k: TorusPrecision,
15}
16
17impl LWEInfos for GLWEPlaintextLayout {
18    fn base2k(&self) -> Base2K {
19        self.base2k
20    }
21
22    fn k(&self) -> TorusPrecision {
23        self.k
24    }
25
26    fn n(&self) -> Degree {
27        self.n
28    }
29}
30
31impl GLWEInfos for GLWEPlaintextLayout {
32    fn rank(&self) -> Rank {
33        Rank(0)
34    }
35}
36
37pub struct GLWEPlaintext<D: Data> {
38    pub data: VecZnx<D>,
39    pub base2k: Base2K,
40    pub k: TorusPrecision,
41}
42
43impl<D: DataMut> GLWELayoutSet for GLWEPlaintext<D> {
44    fn set_basek(&mut self, base2k: Base2K) {
45        self.base2k = base2k
46    }
47
48    fn set_k(&mut self, k: TorusPrecision) {
49        self.k = k
50    }
51}
52
53impl<D: Data> LWEInfos for GLWEPlaintext<D> {
54    fn base2k(&self) -> Base2K {
55        self.base2k
56    }
57
58    fn k(&self) -> TorusPrecision {
59        self.k
60    }
61
62    fn size(&self) -> usize {
63        self.data.size()
64    }
65
66    fn n(&self) -> Degree {
67        Degree(self.data.n() as u32)
68    }
69}
70
71impl<D: Data> GLWEInfos for GLWEPlaintext<D> {
72    fn rank(&self) -> Rank {
73        Rank(self.data.cols() as u32 - 1)
74    }
75}
76
77pub struct GLWEPlaintextBuilder<D: Data> {
78    data: Option<VecZnx<D>>,
79    base2k: Option<Base2K>,
80    k: Option<TorusPrecision>,
81}
82
83impl<D: Data> GLWEPlaintext<D> {
84    #[inline]
85    pub fn builder() -> GLWEPlaintextBuilder<D> {
86        GLWEPlaintextBuilder {
87            data: None,
88            base2k: None,
89            k: None,
90        }
91    }
92}
93
94impl<D: Data> GLWEPlaintextBuilder<D> {
95    #[inline]
96    pub fn data(mut self, data: VecZnx<D>) -> Self {
97        self.data = Some(data);
98        self
99    }
100    #[inline]
101    pub fn base2k(mut self, base2k: Base2K) -> Self {
102        self.base2k = Some(base2k);
103        self
104    }
105    #[inline]
106    pub fn k(mut self, k: TorusPrecision) -> Self {
107        self.k = Some(k);
108        self
109    }
110
111    pub fn build(self) -> Result<GLWEPlaintext<D>, BuildError> {
112        let data: VecZnx<D> = self.data.ok_or(BuildError::MissingData)?;
113        let base2k: Base2K = self.base2k.ok_or(BuildError::MissingBase2K)?;
114        let k: TorusPrecision = self.k.ok_or(BuildError::MissingK)?;
115
116        if base2k.0 == 0 {
117            return Err(BuildError::ZeroBase2K);
118        }
119
120        if k.0 == 0 {
121            return Err(BuildError::ZeroTorusPrecision);
122        }
123
124        if data.n() == 0 {
125            return Err(BuildError::ZeroDegree);
126        }
127
128        if data.cols() != 1 {
129            return Err(BuildError::ZeroCols);
130        }
131
132        if data.size() == 0 {
133            return Err(BuildError::ZeroLimbs);
134        }
135
136        Ok(GLWEPlaintext { data, base2k, k })
137    }
138}
139
140impl<D: DataRef> fmt::Display for GLWEPlaintext<D> {
141    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
142        write!(
143            f,
144            "GLWEPlaintext: base2k={} k={}: {}",
145            self.base2k().0,
146            self.k().0,
147            self.data
148        )
149    }
150}
151
152impl GLWEPlaintext<Vec<u8>> {
153    pub fn alloc<A>(infos: &A) -> Self
154    where
155        A: GLWEInfos,
156    {
157        Self::alloc_with(infos.n(), infos.base2k(), infos.k(), Rank(0))
158    }
159
160    pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank) -> Self {
161        debug_assert!(rank.0 == 0);
162        Self {
163            data: VecZnx::alloc(n.into(), (rank + 1).into(), k.0.div_ceil(base2k.0) as usize),
164            base2k,
165            k,
166        }
167    }
168
169    pub fn alloc_bytes<A>(infos: &A) -> usize
170    where
171        A: GLWEInfos,
172    {
173        Self::alloc_bytes_with(infos.n(), infos.base2k(), infos.k(), Rank(0))
174    }
175
176    pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank) -> usize {
177        debug_assert!(rank.0 == 0);
178        VecZnx::alloc_bytes(n.into(), (rank + 1).into(), k.0.div_ceil(base2k.0) as usize)
179    }
180}
181
182impl<D: DataRef> GLWECiphertextToRef for GLWEPlaintext<D> {
183    fn to_ref(&self) -> GLWECiphertext<&[u8]> {
184        GLWECiphertext::builder()
185            .data(self.data.to_ref())
186            .k(self.k())
187            .base2k(self.base2k())
188            .build()
189            .unwrap()
190    }
191}
192
193impl<D: DataMut> GLWECiphertextToMut for GLWEPlaintext<D> {
194    fn to_mut(&mut self) -> GLWECiphertext<&mut [u8]> {
195        GLWECiphertext::builder()
196            .k(self.k())
197            .base2k(self.base2k())
198            .data(self.data.to_mut())
199            .build()
200            .unwrap()
201    }
202}