arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-core/src/layouts/glwe_pt.rs
poulpy-core/src/layouts/glwe_pt.rsRaw
  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}