poulpy_core/layouts/
glwe_tensor.rs

1use poulpy_hal::{
2    layouts::{Data, DataMut, DataRef, FillUniform, VecZnx, VecZnxToMut, VecZnxToRef, ZnxInfos},
3    source::Source,
4};
5
6use crate::layouts::{Base2K, Degree, GLWEInfos, LWEInfos, Rank, SetGLWEInfos, TorusPrecision};
7use std::fmt;
8
9#[derive(PartialEq, Eq, Clone)]
10pub struct GLWETensor<D: Data> {
11    pub(crate) data: VecZnx<D>,
12    pub(crate) base2k: Base2K,
13    pub(crate) rank: Rank,
14    pub(crate) k: TorusPrecision,
15}
16
17impl<D: DataMut> SetGLWEInfos for GLWETensor<D> {
18    fn set_base2k(&mut self, base2k: Base2K) {
19        self.base2k = base2k
20    }
21
22    fn set_k(&mut self, k: TorusPrecision) {
23        self.k = k
24    }
25}
26
27impl<D: DataRef> GLWETensor<D> {
28    pub fn data(&self) -> &VecZnx<D> {
29        &self.data
30    }
31}
32
33impl<D: DataMut> GLWETensor<D> {
34    pub fn data_mut(&mut self) -> &mut VecZnx<D> {
35        &mut self.data
36    }
37}
38
39impl<D: Data> LWEInfos for GLWETensor<D> {
40    fn base2k(&self) -> Base2K {
41        self.base2k
42    }
43
44    fn k(&self) -> TorusPrecision {
45        self.k
46    }
47
48    fn n(&self) -> Degree {
49        Degree(self.data.n() as u32)
50    }
51
52    fn size(&self) -> usize {
53        self.data.size()
54    }
55}
56
57impl<D: Data> GLWEInfos for GLWETensor<D> {
58    fn rank(&self) -> Rank {
59        self.rank
60    }
61}
62
63impl<D: DataRef> fmt::Debug for GLWETensor<D> {
64    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
65        write!(f, "{self}")
66    }
67}
68
69impl<D: DataRef> fmt::Display for GLWETensor<D> {
70    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71        write!(
72            f,
73            "GLWETensor: base2k={} k={}: {}",
74            self.base2k().0,
75            self.k().0,
76            self.data
77        )
78    }
79}
80
81impl<D: DataMut> FillUniform for GLWETensor<D> {
82    fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
83        self.data.fill_uniform(log_bound, source);
84    }
85}
86
87impl GLWETensor<Vec<u8>> {
88    pub fn alloc_from_infos<A>(infos: &A) -> Self
89    where
90        A: GLWEInfos,
91    {
92        Self::alloc(infos.n(), infos.base2k(), infos.k(), infos.rank())
93    }
94
95    pub fn alloc(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank) -> Self {
96        let pairs: usize = (((rank + 1) * rank).as_usize() >> 1).max(1);
97        GLWETensor {
98            data: VecZnx::alloc(n.into(), pairs + 1, k.0.div_ceil(base2k.0) as usize),
99            base2k,
100            k,
101            rank,
102        }
103    }
104
105    pub fn bytes_of_from_infos<A>(infos: &A) -> usize
106    where
107        A: GLWEInfos,
108    {
109        Self::bytes_of(infos.n(), infos.base2k(), infos.k(), infos.rank())
110    }
111
112    pub fn bytes_of(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank) -> usize {
113        let pairs: usize = (((rank + 1) * rank).as_usize() >> 1).max(1);
114        VecZnx::bytes_of(n.into(), pairs + 1, k.0.div_ceil(base2k.0) as usize)
115    }
116}
117
118pub trait GLWETensorToRef {
119    fn to_ref(&self) -> GLWETensor<&[u8]>;
120}
121
122impl<D: DataRef> GLWETensorToRef for GLWETensor<D> {
123    fn to_ref(&self) -> GLWETensor<&[u8]> {
124        GLWETensor {
125            k: self.k,
126            base2k: self.base2k,
127            data: self.data.to_ref(),
128            rank: self.rank,
129        }
130    }
131}
132
133pub trait GLWETensorToMut {
134    fn to_mut(&mut self) -> GLWETensor<&mut [u8]>;
135}
136
137impl<D: DataMut> GLWETensorToMut for GLWETensor<D> {
138    fn to_mut(&mut self) -> GLWETensor<&mut [u8]> {
139        GLWETensor {
140            k: self.k,
141            base2k: self.base2k,
142            rank: self.rank,
143            data: self.data.to_mut(),
144        }
145    }
146}