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