poulpy_core/layouts/prepared/
gglwe_ct.rs1use poulpy_hal::{
2 api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPrepare},
3 layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat},
4};
5
6use crate::layouts::{
7 GGLWECiphertext, Infos,
8 prepared::{Prepare, PrepareAlloc},
9};
10
11#[derive(PartialEq, Eq)]
12pub struct GGLWECiphertextPrepared<D: Data, B: Backend> {
13 pub(crate) data: VmpPMat<D, B>,
14 pub(crate) basek: usize,
15 pub(crate) k: usize,
16 pub(crate) digits: usize,
17}
18
19impl<B: Backend> GGLWECiphertextPrepared<Vec<u8>, B> {
20 #[allow(clippy::too_many_arguments)]
21 pub fn alloc(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> Self
22 where
23 Module<B>: VmpPMatAlloc<B>,
24 {
25 let size: usize = k.div_ceil(basek);
26 debug_assert!(
27 size > digits,
28 "invalid gglwe: ceil(k/basek): {} <= digits: {}",
29 size,
30 digits
31 );
32
33 assert!(
34 rows * digits <= size,
35 "invalid gglwe: rows: {} * digits:{} > ceil(k/basek): {}",
36 rows,
37 digits,
38 size
39 );
40
41 Self {
42 data: module.vmp_pmat_alloc(rows, rank_in, rank_out + 1, size),
43 basek,
44 k,
45 digits,
46 }
47 }
48
49 #[allow(clippy::too_many_arguments)]
50 pub fn bytes_of(
51 module: &Module<B>,
52 basek: usize,
53 k: usize,
54 rows: usize,
55 digits: usize,
56 rank_in: usize,
57 rank_out: usize,
58 ) -> usize
59 where
60 Module<B>: VmpPMatAllocBytes,
61 {
62 let size: usize = k.div_ceil(basek);
63 debug_assert!(
64 size > digits,
65 "invalid gglwe: ceil(k/basek): {} <= digits: {}",
66 size,
67 digits
68 );
69
70 assert!(
71 rows * digits <= size,
72 "invalid gglwe: rows: {} * digits:{} > ceil(k/basek): {}",
73 rows,
74 digits,
75 size
76 );
77
78 module.vmp_pmat_alloc_bytes(rows, rank_in, rank_out + 1, rows)
79 }
80}
81
82impl<D: Data, B: Backend> Infos for GGLWECiphertextPrepared<D, B> {
83 type Inner = VmpPMat<D, B>;
84
85 fn inner(&self) -> &Self::Inner {
86 &self.data
87 }
88
89 fn basek(&self) -> usize {
90 self.basek
91 }
92
93 fn k(&self) -> usize {
94 self.k
95 }
96}
97
98impl<D: Data, B: Backend> GGLWECiphertextPrepared<D, B> {
99 pub fn rank(&self) -> usize {
100 self.data.cols_out() - 1
101 }
102
103 pub fn digits(&self) -> usize {
104 self.digits
105 }
106
107 pub fn rank_in(&self) -> usize {
108 self.data.cols_in()
109 }
110
111 pub fn rank_out(&self) -> usize {
112 self.data.cols_out() - 1
113 }
114}
115
116impl<D: DataMut, DR: DataRef, B: Backend> Prepare<B, GGLWECiphertext<DR>> for GGLWECiphertextPrepared<D, B>
117where
118 Module<B>: VmpPrepare<B>,
119{
120 fn prepare(&mut self, module: &Module<B>, other: &GGLWECiphertext<DR>, scratch: &mut Scratch<B>) {
121 module.vmp_prepare(&mut self.data, &other.data, scratch);
122 self.basek = other.basek;
123 self.k = other.k;
124 self.digits = other.digits;
125 }
126}
127
128impl<D: DataRef, B: Backend> PrepareAlloc<B, GGLWECiphertextPrepared<Vec<u8>, B>> for GGLWECiphertext<D>
129where
130 Module<B>: VmpPMatAlloc<B> + VmpPrepare<B>,
131{
132 fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> GGLWECiphertextPrepared<Vec<u8>, B> {
133 let mut atk_prepared: GGLWECiphertextPrepared<Vec<u8>, B> = GGLWECiphertextPrepared::alloc(
134 module,
135 self.basek(),
136 self.k(),
137 self.rows(),
138 self.digits(),
139 self.rank_in(),
140 self.rank_out(),
141 );
142 atk_prepared.prepare(module, self, scratch);
143 atk_prepared
144 }
145}