arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/core/src/glwe/trace.rs
core/src/glwe/trace.rsRaw
  1use std::collections::HashMap;
  2
  3use backend::hal::{
  4    api::{ScratchAvailable, TakeVecZnxDft, VecZnxBigAutomorphismInplace, VecZnxCopy, VecZnxRshInplace},
  5    layouts::{Backend, DataMut, DataRef, Module, Scratch},
  6};
  7
  8use crate::{AutomorphismKeyExec, GLWECiphertext, GLWECiphertextToMut, GLWEKeyswitchFamily, GLWEOps, Infos, SetMetaData};
  9
 10pub trait GLWETraceFamily<B: Backend> = GLWEKeyswitchFamily<B> + VecZnxCopy + VecZnxRshInplace + VecZnxBigAutomorphismInplace<B>;
 11
 12impl GLWECiphertext<Vec<u8>> {
 13    pub fn trace_galois_elements<B: Backend>(module: &Module<B>) -> Vec<i64> {
 14        let mut gal_els: Vec<i64> = Vec::new();
 15        (0..module.log_n()).for_each(|i| {
 16            if i == 0 {
 17                gal_els.push(-1);
 18            } else {
 19                gal_els.push(module.galois_element(1 << (i - 1)));
 20            }
 21        });
 22        gal_els
 23    }
 24
 25    pub fn trace_scratch_space<B: Backend>(
 26        module: &Module<B>,
 27        n: usize,
 28        basek: usize,
 29        out_k: usize,
 30        in_k: usize,
 31        ksk_k: usize,
 32        digits: usize,
 33        rank: usize,
 34    ) -> usize
 35    where
 36        Module<B>: GLWEKeyswitchFamily<B>,
 37    {
 38        Self::automorphism_inplace_scratch_space(module, n, basek, out_k.min(in_k), ksk_k, digits, rank)
 39    }
 40
 41    pub fn trace_inplace_scratch_space<B: Backend>(
 42        module: &Module<B>,
 43        n: usize,
 44        basek: usize,
 45        out_k: usize,
 46        ksk_k: usize,
 47        digits: usize,
 48        rank: usize,
 49    ) -> usize
 50    where
 51        Module<B>: GLWEKeyswitchFamily<B>,
 52    {
 53        Self::automorphism_inplace_scratch_space(module, n, basek, out_k, ksk_k, digits, rank)
 54    }
 55}
 56
 57impl<DataSelf: DataMut> GLWECiphertext<DataSelf>
 58where
 59    GLWECiphertext<DataSelf>: GLWECiphertextToMut + Infos + SetMetaData,
 60{
 61    pub fn trace<DataLhs: DataRef, DataAK: DataRef, B: Backend>(
 62        &mut self,
 63        module: &Module<B>,
 64        start: usize,
 65        end: usize,
 66        lhs: &GLWECiphertext<DataLhs>,
 67        auto_keys: &HashMap<i64, AutomorphismKeyExec<DataAK, B>>,
 68        scratch: &mut Scratch<B>,
 69    ) where
 70        Module<B>: GLWETraceFamily<B>,
 71        Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable,
 72    {
 73        self.copy(module, lhs);
 74        self.trace_inplace(module, start, end, auto_keys, scratch);
 75    }
 76
 77    pub fn trace_inplace<DataAK: DataRef, B: Backend>(
 78        &mut self,
 79        module: &Module<B>,
 80        start: usize,
 81        end: usize,
 82        auto_keys: &HashMap<i64, AutomorphismKeyExec<DataAK, B>>,
 83        scratch: &mut Scratch<B>,
 84    ) where
 85        Module<B>: GLWETraceFamily<B>,
 86        Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable,
 87    {
 88        (start..end).for_each(|i| {
 89            self.rsh(module, 1);
 90
 91            let p: i64;
 92            if i == 0 {
 93                p = -1;
 94            } else {
 95                p = module.galois_element(1 << (i - 1));
 96            }
 97
 98            if let Some(key) = auto_keys.get(&p) {
 99                self.automorphism_add_inplace(module, key, scratch);
100            } else {
101                panic!("auto_keys[{}] is empty", p)
102            }
103        });
104    }
105}