poulpy_ckks/default/
rotate.rs1use anyhow::Result;
2use poulpy_core::{
3 GLWEAutomorphism, GLWEShift,
4 layouts::{GGLWEInfos, GGLWEPreparedToBackendRef, GLWEInfos, GLWEToBackendMut, GLWEToBackendRef, GetGaloisElement, LWEInfos},
5};
6use poulpy_hal::layouts::{Backend, ScratchArena};
7
8use crate::{CKKSInfos, SetCKKSInfos, checked_log_budget_sub, ckks_offset_unary};
9
10pub trait CKKSRotateDefault<BE: Backend> {
11 fn ckks_rotate_tmp_bytes_default<C, K>(&self, ct_infos: &C, key_infos: &K) -> usize
12 where
13 C: GLWEInfos,
14 K: GGLWEInfos,
15 Self: GLWEAutomorphism<BE>,
16 {
17 self.glwe_automorphism_tmp_bytes(ct_infos, ct_infos, key_infos)
18 }
19
20 fn ckks_rotate_into_default<Dst, Src, K>(
21 &self,
22 dst: &mut Dst,
23 src: &Src,
24 key: &K,
25 scratch: &mut ScratchArena<'_, BE>,
26 ) -> Result<()>
27 where
28 Self: GLWEAutomorphism<BE> + GLWEShift<BE>,
29 Dst: GLWEToBackendMut<BE> + GLWEInfos + LWEInfos + CKKSInfos + SetCKKSInfos,
30 Src: GLWEToBackendRef<BE> + GLWEInfos + LWEInfos + CKKSInfos,
31 K: GetGaloisElement + GGLWEPreparedToBackendRef<BE> + GGLWEInfos,
32 {
33 let offset = ckks_offset_unary(dst, src);
34
35 if offset != 0 {
36 self.glwe_lsh(dst, src, offset, scratch);
37 self.glwe_automorphism_assign(dst, key, dst.size() + key.dsize().as_usize(), scratch);
38 } else {
39 self.glwe_automorphism(dst, src, key, src.size() + key.dsize().as_usize(), scratch);
40 }
41
42 dst.set_meta(src.meta());
43 dst.set_log_budget(checked_log_budget_sub("rotate", dst.log_budget(), offset)?);
44 Ok(())
45 }
46
47 fn ckks_rotate_assign_default<Dst, K>(&self, dst: &mut Dst, key: &K, scratch: &mut ScratchArena<'_, BE>) -> Result<()>
48 where
49 Self: GLWEAutomorphism<BE>,
50 Dst: GLWEToBackendMut<BE> + GLWEInfos + LWEInfos + CKKSInfos + SetCKKSInfos,
51 K: GetGaloisElement + GGLWEPreparedToBackendRef<BE> + GGLWEInfos,
52 {
53 self.glwe_automorphism_assign(dst, key, dst.size() + key.dsize().as_usize(), scratch);
54 Ok(())
55 }
56}