arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/core/src/external_product/ggsw_ct.rs
core/src/external_product/ggsw_ct.rsRaw
  1use backend::hal::{
  2    api::{
  3        ScratchAvailable, TakeVecZnxDft, VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftFromVecZnx,
  4        VecZnxDftToVecZnxBigConsume, VecZnxNormalizeTmpBytes, VmpApply, VmpApplyAdd, VmpApplyTmpBytes, ZnxZero,
  5    },
  6    layouts::{Backend, DataMut, DataRef, Module, Scratch},
  7};
  8
  9use crate::layouts::{GGSWCiphertext, GLWECiphertext, Infos, prepared::GGSWCiphertextPrepared};
 10
 11impl GGSWCiphertext<Vec<u8>> {
 12    pub fn external_product_scratch_space<B: Backend>(
 13        module: &Module<B>,
 14        n: usize,
 15        basek: usize,
 16        k_out: usize,
 17        k_in: usize,
 18        k_ggsw: usize,
 19        digits: usize,
 20        rank: usize,
 21    ) -> usize
 22    where
 23        Module<B>: VecZnxDftAllocBytes + VmpApplyTmpBytes + VecZnxNormalizeTmpBytes,
 24    {
 25        GLWECiphertext::external_product_scratch_space(module, n, basek, k_out, k_in, k_ggsw, digits, rank)
 26    }
 27
 28    pub fn external_product_inplace_scratch_space<B: Backend>(
 29        module: &Module<B>,
 30        n: usize,
 31        basek: usize,
 32        k_out: usize,
 33        k_ggsw: usize,
 34        digits: usize,
 35        rank: usize,
 36    ) -> usize
 37    where
 38        Module<B>: VecZnxDftAllocBytes + VmpApplyTmpBytes + VecZnxNormalizeTmpBytes,
 39    {
 40        GLWECiphertext::external_product_inplace_scratch_space(module, n, basek, k_out, k_ggsw, digits, rank)
 41    }
 42}
 43
 44impl<DataSelf: DataMut> GGSWCiphertext<DataSelf> {
 45    pub fn external_product<DataLhs: DataRef, DataRhs: DataRef, B: Backend>(
 46        &mut self,
 47        module: &Module<B>,
 48        lhs: &GGSWCiphertext<DataLhs>,
 49        rhs: &GGSWCiphertextPrepared<DataRhs, B>,
 50        scratch: &mut Scratch<B>,
 51    ) where
 52        Module<B>: VecZnxDftAllocBytes
 53            + VmpApplyTmpBytes
 54            + VecZnxNormalizeTmpBytes
 55            + VecZnxDftFromVecZnx<B>
 56            + VmpApply<B>
 57            + VmpApplyAdd<B>
 58            + VecZnxDftToVecZnxBigConsume<B>
 59            + VecZnxBigNormalize<B>,
 60        Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable,
 61    {
 62        #[cfg(debug_assertions)]
 63        {
 64            use crate::layouts::Infos;
 65
 66            assert_eq!(lhs.n(), self.n());
 67            assert_eq!(rhs.n(), self.n());
 68
 69            assert_eq!(
 70                self.rank(),
 71                lhs.rank(),
 72                "ggsw_out rank: {} != ggsw_in rank: {}",
 73                self.rank(),
 74                lhs.rank()
 75            );
 76            assert_eq!(
 77                self.rank(),
 78                rhs.rank(),
 79                "ggsw_in rank: {} != ggsw_apply rank: {}",
 80                self.rank(),
 81                rhs.rank()
 82            );
 83
 84            assert!(
 85                scratch.available()
 86                    >= GGSWCiphertext::external_product_scratch_space(
 87                        module,
 88                        self.n(),
 89                        self.basek(),
 90                        self.k(),
 91                        lhs.k(),
 92                        rhs.k(),
 93                        rhs.digits(),
 94                        rhs.rank()
 95                    )
 96            )
 97        }
 98
 99        let min_rows: usize = self.rows().min(lhs.rows());
100
101        (0..self.rank() + 1).for_each(|col_i| {
102            (0..min_rows).for_each(|row_j| {
103                self.at_mut(row_j, col_i)
104                    .external_product(module, &lhs.at(row_j, col_i), rhs, scratch);
105            });
106            (min_rows..self.rows()).for_each(|row_i| {
107                self.at_mut(row_i, col_i).data.zero();
108            });
109        });
110    }
111
112    pub fn external_product_inplace<DataRhs: DataRef, B: Backend>(
113        &mut self,
114        module: &Module<B>,
115        rhs: &GGSWCiphertextPrepared<DataRhs, B>,
116        scratch: &mut Scratch<B>,
117    ) where
118        Module<B>: VecZnxDftAllocBytes
119            + VmpApplyTmpBytes
120            + VecZnxNormalizeTmpBytes
121            + VecZnxDftFromVecZnx<B>
122            + VmpApply<B>
123            + VmpApplyAdd<B>
124            + VecZnxDftToVecZnxBigConsume<B>
125            + VecZnxBigNormalize<B>,
126        Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable,
127    {
128        #[cfg(debug_assertions)]
129        {
130            assert_eq!(rhs.n(), self.n());
131            assert_eq!(
132                self.rank(),
133                rhs.rank(),
134                "ggsw_out rank: {} != ggsw_apply: {}",
135                self.rank(),
136                rhs.rank()
137            );
138        }
139
140        (0..self.rank() + 1).for_each(|col_i| {
141            (0..self.rows()).for_each(|row_j| {
142                self.at_mut(row_j, col_i)
143                    .external_product_inplace(module, rhs, scratch);
144            });
145        });
146    }
147}