poulpy_core/layouts/
glwe_tensor.rs1use 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}