1use poulpy_hal::{
2 layouts::{Backend, Data, FillUniform, HostDataMut, HostDataRef, ReaderFrom, WriterTo},
3 source::Source,
4};
5
6use crate::{
7 DeclaredK,
8 layouts::{
9 Base2K, Degree, Dnum, Dsize, GGLWE, GGLWEAtViewMut, GGLWEAtViewRef, GGLWEBackendMut, GGLWEBackendRef, GGLWEInfos,
10 GGLWEToBackendMut, GGLWEToBackendRef, GLWEInfos, GLWEViewMut, GLWEViewRef, LWEInfos, Rank, TorusPrecision,
11 },
12};
13
14use std::fmt;
15
16#[derive(PartialEq, Eq, Copy, Clone, Debug)]
23pub struct GLWETensorKeyLayout {
24 pub n: Degree,
25 pub base2k: Base2K,
26 pub k: TorusPrecision,
27 pub rank: Rank,
28 pub dnum: Dnum,
29 pub dsize: Dsize,
30}
31
32impl DeclaredK for GLWETensorKeyLayout {
33 fn k(&self) -> TorusPrecision {
34 self.k
35 }
36}
37
38#[derive(PartialEq, Eq, Clone)]
46pub struct GLWETensorKey<D: Data>(pub(crate) GGLWE<D>);
47
48impl<D: Data> LWEInfos for GLWETensorKey<D> {
49 fn n(&self) -> Degree {
50 self.0.n()
51 }
52
53 fn base2k(&self) -> Base2K {
54 self.0.base2k()
55 }
56
57 fn size(&self) -> usize {
58 self.0.size()
59 }
60}
61
62impl<D: Data> GLWEInfos for GLWETensorKey<D> {
63 fn rank(&self) -> Rank {
64 self.0.rank_out()
65 }
66}
67
68impl<D: Data> GGLWEInfos for GLWETensorKey<D> {
69 fn rank_in(&self) -> Rank {
70 let rank_out: usize = self.rank_out().as_usize();
71 let pairs: usize = (((rank_out + 1) * rank_out) >> 1).max(1);
72 pairs.into()
73 }
74
75 fn rank_out(&self) -> Rank {
76 self.0.rank_out()
77 }
78
79 fn dsize(&self) -> Dsize {
80 self.0.dsize()
81 }
82
83 fn dnum(&self) -> Dnum {
84 self.0.dnum()
85 }
86}
87
88impl LWEInfos for GLWETensorKeyLayout {
89 fn n(&self) -> Degree {
90 self.n
91 }
92
93 fn base2k(&self) -> Base2K {
94 self.base2k
95 }
96
97 fn size(&self) -> usize {
98 self.k.as_usize().div_ceil(self.base2k.as_usize())
99 }
100}
101
102impl GLWEInfos for GLWETensorKeyLayout {
103 fn rank(&self) -> Rank {
104 self.rank_out()
105 }
106}
107
108impl GGLWEInfos for GLWETensorKeyLayout {
109 fn rank_in(&self) -> Rank {
110 let rank_out: usize = self.rank_out().as_usize();
111 let pairs: usize = (((rank_out + 1) * rank_out) >> 1).max(1);
112 pairs.into()
113 }
114
115 fn dsize(&self) -> Dsize {
116 self.dsize
117 }
118
119 fn rank_out(&self) -> Rank {
120 self.rank
121 }
122
123 fn dnum(&self) -> Dnum {
124 self.dnum
125 }
126}
127
128impl<D: HostDataRef> fmt::Debug for GLWETensorKey<D> {
129 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
130 write!(f, "{self}")
131 }
132}
133
134impl<D: HostDataMut> FillUniform for GLWETensorKey<D> {
135 fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
136 self.0.fill_uniform(log_bound, source)
137 }
138}
139
140impl<D: HostDataRef> fmt::Display for GLWETensorKey<D> {
141 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
142 writeln!(f, "(GLWETensorKey)",)?;
143 write!(f, "{}", self.0)?;
144 Ok(())
145 }
146}
147
148#[expect(
149 dead_code,
150 reason = "host-owned constructors are kept for serialization and host-only staging"
151)]
152impl GLWETensorKey<Vec<u8>> {
153 pub(crate) fn alloc_from_infos<A>(infos: &A) -> Self
155 where
156 A: GGLWEInfos,
157 {
158 Self::alloc(
159 infos.n(),
160 infos.base2k(),
161 infos.max_k(),
162 infos.rank(),
163 infos.dnum(),
164 infos.dsize(),
165 )
166 }
167
168 pub(crate) fn alloc(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self {
170 let pairs: u32 = (((rank.0 + 1) * rank.0) >> 1).max(1);
171 GLWETensorKey(GGLWE::alloc(n, base2k, k, Rank(pairs), rank, dnum, dsize))
172 }
173
174 pub fn bytes_of_from_infos<A>(infos: &A) -> usize
176 where
177 A: GGLWEInfos,
178 {
179 Self::bytes_of(
180 infos.n(),
181 infos.base2k(),
182 infos.max_k(),
183 infos.rank(),
184 infos.dnum(),
185 infos.dsize(),
186 )
187 }
188
189 pub fn bytes_of(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize {
191 let pairs: u32 = (((rank.0 + 1) * rank.0) >> 1).max(1);
192 GGLWE::bytes_of(n, base2k, k, Rank(pairs), rank, dnum, dsize)
193 }
194}
195
196impl<D: HostDataMut> ReaderFrom for GLWETensorKey<D> {
197 fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
198 self.0.read_from(reader)?;
199 Ok(())
200 }
201}
202
203impl<D: HostDataRef> WriterTo for GLWETensorKey<D> {
204 fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
205 self.0.write_to(writer)?;
206 Ok(())
207 }
208}
209
210impl_gglwe_to_backend_for_field!(GLWETensorKey<D>, 0, GGLWE<D>);
211
212impl_gglwe_at_view_for_field!(GLWETensorKey<BE::OwnedBuf>; 0);