poulpy/poulpy-schemes/src/tfhe/bdd_arithmetic/bdd_2w_to_1w.rs
poulpy-schemes/src/tfhe/bdd_arithmetic/bdd_2w_to_1w.rsRaw
1use std::marker::PhantomData;
2
3use poulpy_core::layouts::GGSWPrepared;
4use poulpy_hal::layouts::{Backend, DataMut, DataRef, Module, Scratch};
5
6use crate::tfhe::bdd_arithmetic::{
7 BitSize, ExecuteBDDCircuit, FheUint, FheUintPrepared, GetBitCircuitInfo, GetGGSWBit, UnsignedInteger, circuits,
8};
9
10impl<T: UnsignedInteger, BE: Backend> ExecuteBDDCircuit2WTo1W<T, BE> for Module<BE> where Self: Sized + ExecuteBDDCircuit<T, BE> {}
11
12pub trait ExecuteBDDCircuit2WTo1W<T: UnsignedInteger, BE: Backend>
13where
14 Self: Sized + ExecuteBDDCircuit<T, BE>,
15{
16 /// Operations Z x Z -> Z
17 fn execute_bdd_circuit_2w_to_1w<R, C, A, B>(
18 &self,
19 out: &mut FheUint<R, T>,
20 circuit: &C,
21 a: &FheUintPrepared<A, T, BE>,
22 b: &FheUintPrepared<B, T, BE>,
23 scratch: &mut Scratch<BE>,
24 ) where
25 C: GetBitCircuitInfo<T>,
26 R: DataMut,
27 A: DataRef,
28 B: DataRef,
29 {
30 assert_eq!(out.bits.len(), T::WORD_SIZE);
31 assert_eq!(b.bits.len(), T::WORD_SIZE);
32 assert_eq!(b.bits.len(), T::WORD_SIZE);
33
34 // Collects inputs into a single array
35 let inputs: Vec<&dyn GetGGSWBit<BE>> = [a as &dyn GetGGSWBit<BE>, b as &dyn GetGGSWBit<BE>].to_vec();
36 let helper: FheUintHelper<'_, T, BE> = FheUintHelper {
37 data: inputs,
38 _phantom: PhantomData,
39 };
40
41 // Evaluates out[i] = circuit[i](a, b)
42 self.execute_bdd_circuit(&mut out.bits, &helper, circuit, scratch);
43 }
44}
45
46struct FheUintHelper<'a, T: UnsignedInteger, BE: Backend> {
47 data: Vec<&'a dyn GetGGSWBit<BE>>,
48 _phantom: PhantomData<T>,
49}
50
51impl<'a, T: UnsignedInteger, BE: Backend> GetGGSWBit<BE> for FheUintHelper<'a, T, BE> {
52 fn get_bit(&self, bit: usize) -> GGSWPrepared<&[u8], BE> {
53 let lo: usize = bit % T::WORD_SIZE;
54 let hi: usize = bit / T::WORD_SIZE;
55 self.data[hi].get_bit(lo)
56 }
57}
58
59impl<'a, T: UnsignedInteger, BE: Backend> BitSize for FheUintHelper<'a, T, BE> {
60 fn bit_size(&self) -> usize {
61 T::WORD_SIZE * self.data.len()
62 }
63}
64
65pub struct JoinedBits<A, B> {
66 pub lo: A,
67 pub hi: B,
68 pub split: usize, // 32 in your example
69}
70
71impl<A, B, BE> GetGGSWBit<BE> for JoinedBits<A, B>
72where
73 BE: Backend,
74 A: GetGGSWBit<BE>,
75 B: GetGGSWBit<BE>,
76{
77 fn get_bit(&self, bit: usize) -> GGSWPrepared<&[u8], BE> {
78 if bit < self.split {
79 self.lo.get_bit(bit)
80 } else {
81 self.hi.get_bit(bit - self.split)
82 }
83 }
84}
85
86#[macro_export]
87macro_rules! define_bdd_2w_to_1w_trait {
88 ($(#[$meta:meta])* $vis:vis $trait_name:ident, $method_name:ident) => {
89 $(#[$meta])*
90 $vis trait $trait_name<T: UnsignedInteger, BE: Backend> {
91 fn $method_name<A, M, B>(
92 &mut self,
93 module: &M,
94 a: &FheUintPrepared<A, T, BE>,
95 b: &FheUintPrepared<B, T, BE>,
96 scratch: &mut Scratch<BE>,
97 ) where
98 M: ExecuteBDDCircuit2WTo1W<T, BE>,
99 A: DataRef,
100 B: DataRef;
101 }
102 };
103}
104
105#[macro_export]
106macro_rules! impl_bdd_2w_to_1w_trait {
107 ($trait_name:ident, $method_name:ident, $ty:ty, $n:literal, $circuit_ty:ty, $output_circuits:path) => {
108 impl<D: DataMut, BE: Backend> $trait_name<$ty, BE> for FheUint<D, $ty> {
109 fn $method_name<A, M, B>(
110 &mut self,
111 module: &M,
112 a: &FheUintPrepared<A, $ty, BE>,
113 b: &FheUintPrepared<B, $ty, BE>,
114 scratch: &mut Scratch<BE>,
115 ) where
116 M: ExecuteBDDCircuit2WTo1W<$ty, BE>,
117 A: DataRef,
118 B: DataRef,
119 {
120 module.execute_bdd_circuit_2w_to_1w(self, &$output_circuits, a, b, scratch)
121 }
122 }
123 };
124}
125
126define_bdd_2w_to_1w_trait!(pub Add, add);
127define_bdd_2w_to_1w_trait!(pub Sub, sub);
128define_bdd_2w_to_1w_trait!(pub Sll, sll);
129define_bdd_2w_to_1w_trait!(pub Sra, sra);
130define_bdd_2w_to_1w_trait!(pub Srl, srl);
131define_bdd_2w_to_1w_trait!(pub Slt, slt);
132define_bdd_2w_to_1w_trait!(pub Sltu, sltu);
133define_bdd_2w_to_1w_trait!(pub Or, or);
134define_bdd_2w_to_1w_trait!(pub And, and);
135define_bdd_2w_to_1w_trait!(pub Xor, xor);
136
137impl_bdd_2w_to_1w_trait!(
138 Add,
139 add,
140 u32,
141 32,
142 circuits::u32::add_codegen::AnyBitCircuit,
143 circuits::u32::add_codegen::OUTPUT_CIRCUITS
144);
145
146impl_bdd_2w_to_1w_trait!(
147 Sub,
148 sub,
149 u32,
150 32,
151 circuits::u32::sub_codegen::AnyBitCircuit,
152 circuits::u32::sub_codegen::OUTPUT_CIRCUITS
153);
154
155impl_bdd_2w_to_1w_trait!(
156 Sll,
157 sll,
158 u32,
159 32,
160 circuits::u32::sll_codegen::AnyBitCircuit,
161 circuits::u32::sll_codegen::OUTPUT_CIRCUITS
162);
163
164impl_bdd_2w_to_1w_trait!(
165 Sra,
166 sra,
167 u32,
168 32,
169 circuits::u32::sra_codegen::AnyBitCircuit,
170 circuits::u32::sra_codegen::OUTPUT_CIRCUITS
171);
172
173impl_bdd_2w_to_1w_trait!(
174 Srl,
175 srl,
176 u32,
177 32,
178 circuits::u32::srl_codegen::AnyBitCircuit,
179 circuits::u32::srl_codegen::OUTPUT_CIRCUITS
180);
181
182impl_bdd_2w_to_1w_trait!(
183 Slt,
184 slt,
185 u32,
186 1,
187 circuits::u32::slt_codegen::AnyBitCircuit,
188 circuits::u32::slt_codegen::OUTPUT_CIRCUITS
189);
190
191impl_bdd_2w_to_1w_trait!(
192 Sltu,
193 sltu,
194 u32,
195 1,
196 circuits::u32::sltu_codegen::AnyBitCircuit,
197 circuits::u32::sltu_codegen::OUTPUT_CIRCUITS
198);
199
200impl_bdd_2w_to_1w_trait!(
201 And,
202 and,
203 u32,
204 32,
205 circuits::u32::and_codegen::AnyBitCircuit,
206 circuits::u32::and_codegen::OUTPUT_CIRCUITS
207);
208
209impl_bdd_2w_to_1w_trait!(
210 Or,
211 or,
212 u32,
213 32,
214 circuits::u32::or_codegen::AnyBitCircuit,
215 circuits::u32::or_codegen::OUTPUT_CIRCUITS
216);
217
218impl_bdd_2w_to_1w_trait!(
219 Xor,
220 xor,
221 u32,
222 32,
223 circuits::u32::xor_codegen::AnyBitCircuit,
224 circuits::u32::xor_codegen::OUTPUT_CIRCUITS
225);