poulpy_core/layouts/
gglwe_ksk.rs

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