poulpy_core/layouts/
gglwe_ct.rs1use poulpy_hal::{
2 api::{FillUniform, Reset},
3 layouts::{Data, DataMut, DataRef, MatZnx, ReaderFrom, WriterTo},
4 source::Source,
5};
6
7use crate::layouts::{GLWECiphertext, Infos};
8use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
9
10use std::fmt;
11
12#[derive(PartialEq, Eq, Clone)]
13pub struct GGLWECiphertext<D: Data> {
14 pub(crate) data: MatZnx<D>,
15 pub(crate) basek: usize,
16 pub(crate) k: usize,
17 pub(crate) digits: usize,
18}
19
20impl<D: DataRef> fmt::Debug for GGLWECiphertext<D> {
21 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
22 write!(f, "{}", self)
23 }
24}
25
26impl<D: DataMut> FillUniform for GGLWECiphertext<D> {
27 fn fill_uniform(&mut self, source: &mut Source) {
28 self.data.fill_uniform(source);
29 }
30}
31
32impl<D: DataMut> Reset for GGLWECiphertext<D> {
33 fn reset(&mut self) {
34 self.data.reset();
35 self.basek = 0;
36 self.k = 0;
37 self.digits = 0;
38 }
39}
40
41impl<D: DataRef> fmt::Display for GGLWECiphertext<D> {
42 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 write!(
44 f,
45 "(GGLWECiphertext: basek={} k={} digits={}) {}",
46 self.basek, self.k, self.digits, self.data
47 )
48 }
49}
50
51impl<D: DataRef> GGLWECiphertext<D> {
52 pub fn at(&self, row: usize, col: usize) -> GLWECiphertext<&[u8]> {
53 GLWECiphertext {
54 data: self.data.at(row, col),
55 basek: self.basek,
56 k: self.k,
57 }
58 }
59}
60
61impl<D: DataMut> GGLWECiphertext<D> {
62 pub fn at_mut(&mut self, row: usize, col: usize) -> GLWECiphertext<&mut [u8]> {
63 GLWECiphertext {
64 data: self.data.at_mut(row, col),
65 basek: self.basek,
66 k: self.k,
67 }
68 }
69}
70
71impl GGLWECiphertext<Vec<u8>> {
72 pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> Self {
73 let size: usize = k.div_ceil(basek);
74 debug_assert!(
75 size > digits,
76 "invalid gglwe: ceil(k/basek): {} <= digits: {}",
77 size,
78 digits
79 );
80
81 assert!(
82 rows * digits <= size,
83 "invalid gglwe: rows: {} * digits:{} > ceil(k/basek): {}",
84 rows,
85 digits,
86 size
87 );
88
89 Self {
90 data: MatZnx::alloc(n, rows, rank_in, rank_out + 1, size),
91 basek,
92 k,
93 digits,
94 }
95 }
96
97 pub fn bytes_of(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> usize {
98 let size: usize = k.div_ceil(basek);
99 debug_assert!(
100 size > digits,
101 "invalid gglwe: ceil(k/basek): {} <= digits: {}",
102 size,
103 digits
104 );
105
106 assert!(
107 rows * digits <= size,
108 "invalid gglwe: rows: {} * digits:{} > ceil(k/basek): {}",
109 rows,
110 digits,
111 size
112 );
113
114 MatZnx::alloc_bytes(n, rows, rank_in, rank_out + 1, rows)
115 }
116}
117
118impl<D: Data> Infos for GGLWECiphertext<D> {
119 type Inner = MatZnx<D>;
120
121 fn inner(&self) -> &Self::Inner {
122 &self.data
123 }
124
125 fn basek(&self) -> usize {
126 self.basek
127 }
128
129 fn k(&self) -> usize {
130 self.k
131 }
132}
133
134impl<D: Data> GGLWECiphertext<D> {
135 pub fn rank(&self) -> usize {
136 self.data.cols_out() - 1
137 }
138
139 pub fn digits(&self) -> usize {
140 self.digits
141 }
142
143 pub fn rank_in(&self) -> usize {
144 self.data.cols_in()
145 }
146
147 pub fn rank_out(&self) -> usize {
148 self.data.cols_out() - 1
149 }
150}
151
152impl<D: DataMut> ReaderFrom for GGLWECiphertext<D> {
153 fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
154 self.k = reader.read_u64::<LittleEndian>()? as usize;
155 self.basek = reader.read_u64::<LittleEndian>()? as usize;
156 self.digits = reader.read_u64::<LittleEndian>()? as usize;
157 self.data.read_from(reader)
158 }
159}
160
161impl<D: DataRef> WriterTo for GGLWECiphertext<D> {
162 fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
163 writer.write_u64::<LittleEndian>(self.k as u64)?;
164 writer.write_u64::<LittleEndian>(self.basek as u64)?;
165 writer.write_u64::<LittleEndian>(self.digits as u64)?;
166 self.data.write_to(writer)
167 }
168}