poulpy_core/layouts/
ggsw_ct.rs

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