poulpy/math/tests/automorphism.rs
math/tests/automorphism.rsRaw
1use itertools::izip;
2use math::poly::Poly;
3use math::ring::Ring;
4
5#[test]
6fn automorphism_u64() {
7 let n: usize = 1 << 4;
8 let nth_root: usize = n << 1;
9 let q_base: u64 = 65537u64;
10 let q_power: usize = 1usize;
11 let ring: Ring<u64> = Ring::new(n, q_base, q_power);
12
13 sub_test("test_automorphism_u64::<NTT:false>", || {
14 test_automorphism_u64::<false>(&ring, nth_root)
15 });
16 sub_test("test_automorphism_u64::<NTT:true>", || {
17 test_automorphism_u64::<true>(&ring, nth_root)
18 });
19}
20
21fn sub_test<F: FnOnce()>(name: &str, f: F) {
22 println!("Running {}", name);
23 f();
24}
25
26fn test_automorphism_u64<const NTT: bool>(ring: &Ring<u64>, nth_root: usize) {
27 let n: usize = ring.n();
28 let q: u64 = ring.modulus.q;
29
30 let mut p0: Poly<u64> = ring.new_poly();
31 let mut p1: Poly<u64> = ring.new_poly();
32
33 for i in 0..p0.n() {
34 p0.0[i] = i as u64
35 }
36
37 if NTT {
38 ring.ntt_inplace::<false>(&mut p0);
39 }
40
41 ring.a_apply_automorphism_into_b::<NTT>(&p0, 2 * n - 1, nth_root, &mut p1);
42
43 if NTT {
44 ring.intt_inplace::<false>(&mut p1);
45 }
46
47 p0.0[0] = 0;
48 for i in 1..p0.n() {
49 p0.0[i] = q - (n - i) as u64
50 }
51
52 izip!(p0.0, p1.0).for_each(|(a, b)| assert_eq!(a, b));
53}
54
55#[test]
56fn packing_u64() {
57 let n: usize = 1 << 5;
58 let q_base: u64 = 65537u64;
59 let q_power: usize = 1usize;
60 let ring: Ring<u64> = Ring::new(n, q_base, q_power);
61
62 sub_test("test_packing_u64::<NTT:false>", || {
63 test_packing_full_u64::<false>(&ring)
64 });
65 sub_test("test_packing_u64::<NTT:true>", || {
66 test_packing_full_u64::<true>(&ring)
67 });
68 sub_test("test_packing_sparse_u64::<NTT:false>", || {
69 test_packing_sparse_u64::<false>(&ring)
70 });
71 sub_test("test_packing_sparse_u64::<NTT:true>", || {
72 test_packing_sparse_u64::<true>(&ring)
73 });
74}
75
76fn test_packing_full_u64<const NTT: bool>(ring: &Ring<u64>) {
77 let n: usize = ring.n();
78
79 let mut result: Vec<Option<Poly<u64>>> = vec![None; n];
80
81 for i in 0..n {
82 let mut poly: Poly<u64> = ring.new_poly();
83 poly.fill(&(1 + i as u64));
84 if NTT {
85 ring.ntt_inplace::<false>(&mut poly);
86 }
87
88 result[i] = Some(poly);
89 }
90
91 ring.pack::<true, NTT>(&mut result, ring.log_n());
92
93 if let Some(poly) = result[0].as_mut() {
94 if NTT {
95 ring.intt_inplace::<false>(poly);
96 }
97
98 poly.0
99 .iter()
100 .enumerate()
101 .for_each(|(i, x)| assert_eq!(*x, 1 + i as u64));
102 }
103}
104
105fn test_packing_sparse_u64<const NTT: bool>(ring: &Ring<u64>) {
106 let n: usize = ring.n();
107
108 let mut result: Vec<Option<Poly<u64>>> = vec![None; n];
109
110 let gap: usize = 3;
111
112 for i in (0..n).step_by(gap) {
113 let mut poly: Poly<u64> = ring.new_poly();
114 poly.fill(&(1 + i as u64));
115 if NTT {
116 ring.ntt_inplace::<false>(&mut poly);
117 }
118 result[i] = Some(poly);
119 }
120
121 ring.pack::<true, NTT>(&mut result, ring.log_n());
122
123 if let Some(poly) = result[0].as_mut() {
124 if NTT {
125 ring.intt_inplace::<false>(poly);
126 }
127
128 poly.0.iter().enumerate().for_each(|(i, x)| {
129 if i % gap == 0 {
130 assert_eq!(*x, 1 + i as u64)
131 } else {
132 assert_eq!(*x, 0u64)
133 }
134 });
135 }
136}
137
138
139
140#[test]
141fn trace_u64() {
142 let n: usize = 1 << 5;
143 let q_base: u64 = 65537u64;
144 let q_power: usize = 1usize;
145 let ring: Ring<u64> = Ring::new(n, q_base, q_power);
146
147 sub_test("test_trace::<NTT:false>", || {
148 test_trace_u64::<false>(&ring)
149 });
150 sub_test("test_trace::<NTT:true>", || {
151 test_trace_u64::<true>(&ring)
152 });
153}
154
155fn test_trace_u64<const NTT: bool>(ring: &Ring<u64>) {
156 let n: usize = ring.n();
157
158 let mut poly: Poly<u64> = ring.new_poly();
159
160 poly.0.iter_mut().enumerate().for_each(|(i, x)|{
161 *x = (i+1) as u64
162 });
163
164 if NTT{
165 ring.ntt_inplace::<false>(&mut poly);
166 }
167
168 let step_start: usize = 2;
169
170 ring.trace_inplace::<NTT>(step_start, &mut poly);
171
172 if NTT{
173 ring.intt_inplace::<false>(&mut poly);
174 }
175
176 let gap: usize = 1<<(ring.log_n() - step_start);
177
178 poly.0.iter().enumerate().for_each(|(i, x)| {
179 if i % gap == 0 {
180 assert_eq!(*x, 1 + i as u64)
181 } else {
182 assert_eq!(*x, 0u64)
183 }
184 });
185}