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