use std::collections::HashMap; use backend::{FFT64, MatZnxDft, MatZnxDftToRef, Module, Scratch, VecZnx, VecZnxToMut, VecZnxToRef}; use crate::{automorphism::AutomorphismKey, glwe_ciphertext::GLWECiphertext, glwe_ops::GLWEOps}; impl GLWECiphertext> { pub fn trace_galois_elements(module: &Module) -> Vec { let mut gal_els: Vec = Vec::new(); (0..module.log_n()).for_each(|i| { if i == 0 { gal_els.push(-1); } else { gal_els.push(module.galois_element(1 << (i - 1))); } }); gal_els } pub fn trace_scratch_space( module: &Module, out_size: usize, in_size: usize, autokey_size: usize, rank: usize, ) -> usize { Self::automorphism_inplace_scratch_space(module, out_size.max(in_size), rank, autokey_size) } pub fn trace_inplace_scratch_space(module: &Module, out_size: usize, autokey_size: usize, rank: usize) -> usize { Self::automorphism_inplace_scratch_space(module, out_size, rank, autokey_size) } } impl GLWECiphertext where VecZnx: VecZnxToMut, { pub fn trace( &mut self, module: &Module, start: usize, end: usize, lhs: &GLWECiphertext, auto_keys: &HashMap>, scratch: &mut Scratch, ) where VecZnx: VecZnxToRef, MatZnxDft: MatZnxDftToRef, { self.copy(module, lhs); self.trace_inplace(module, start, end, auto_keys, scratch); } pub fn trace_inplace( &mut self, module: &Module, start: usize, end: usize, auto_keys: &HashMap>, scratch: &mut Scratch, ) where MatZnxDft: MatZnxDftToRef, { (start..end).for_each(|i| { self.rsh(1, scratch); let p: i64; if i == 0 { p = -1; } else { p = module.galois_element(1 << (i - 1)); } if let Some(key) = auto_keys.get(&p) { self.automorphism_add_inplace(module, key, scratch); } else { panic!("auto_keys[{}] is empty", p) } }); } }