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