1#![allow(non_snake_case)]
2#![allow(non_upper_case_globals)]
3
4pub fn mqpoly_small_is_invertible(logn: u32,
41 f: &[i8], tmp: &mut [u16]) -> bool
42{
43 let n = 1usize << logn;
44 mqpoly_small_to_int(logn, f, tmp);
45 mqpoly_int_to_NTT(logn, tmp);
46 let mut r = 0xFFFFFFFF;
47 for i in 0..n {
48 r &= (tmp[i] as u32).wrapping_sub(Q);
49 }
50 (r >> 16) != 0
51}
52
53pub fn mqpoly_div_small(logn: u32,
58 f: &[i8], g: &[i8], h: &mut [u16], tmp: &mut [u16])
59{
60 let n = 1usize << logn;
61 mqpoly_small_to_int(logn, f, tmp);
62 mqpoly_small_to_int(logn, g, h);
63 mqpoly_int_to_NTT(logn, tmp);
64 mqpoly_int_to_NTT(logn, h);
65 for i in 0..n {
66 h[i] = mq_div(h[i] as u32, tmp[i] as u32) as u16;
67 }
68 mqpoly_NTT_to_int(logn, h);
69 mqpoly_int_to_ext(logn, h);
70}
71
72pub const SQBETA: [u32; 11] = [
74 0, 101498,
76 208714,
77 428865,
78 892039,
79 1852696,
80 3842630,
81 7959734,
82 16468416,
83 34034726,
84 70265242,
85];
86
87const Q: u32 = 12289;
88
89const Q1I: u32 = 4143984639;
91
92const R2: u32 = 5664;
94
95pub fn mqpoly_signed_to_ext(logn: u32, v: &[i16], d: &mut [u16]) {
100 for i in 0..(1usize << logn) {
101 let x = (v[i] as i32) as u32;
102 d[i] = x.wrapping_add((x >> 16) & Q) as u16;
103 }
104}
105
106#[inline(always)]
108fn mq_add(x: u32, y: u32) -> u32 {
109 let a = Q.wrapping_sub(x + y);
112
113 let b = a.wrapping_add(Q & (a >> 16));
117
118 Q - b
121}
122
123#[inline(always)]
125fn mq_sub(x: u32, y: u32) -> u32 {
126 let a = y.wrapping_sub(x);
128 let b = a.wrapping_add(Q & (a >> 16));
130 Q - b
131}
132
133#[inline(always)]
135fn mq_half(x: u32) -> u32 {
136 (x + ((x & 1).wrapping_neg() & Q)) >> 1
137}
138
139#[inline(always)]
144fn mq_mred(x: u32) -> u32 {
145 let b = x.wrapping_mul(Q1I);
146 let c = (b >> 16) * Q;
147 (c >> 16) + 1
148}
149
150#[inline(always)]
152fn mq_mmul(x: u32, y: u32) -> u32 {
153 mq_mred(x * y)
154}
155
156fn mq_div(x: u32, y: u32) -> u32 {
159 let y = mq_mmul(y, R2);
161
162 let y2 = mq_mmul(y, y);
164 let y3 = mq_mmul(y2, y);
165 let y5 = mq_mmul(y3, y2);
166 let y10 = mq_mmul(y5, y5);
167 let y20 = mq_mmul(y10, y10);
168 let y40 = mq_mmul(y20, y20);
169 let y80 = mq_mmul(y40, y40);
170 let y160 = mq_mmul(y80, y80);
171 let y163 = mq_mmul(y160, y3);
172 let y323 = mq_mmul(y163, y160);
173 let y646 = mq_mmul(y323, y323);
174 let y1292 = mq_mmul(y646, y646);
175 let y1455 = mq_mmul(y1292, y163);
176 let y2910 = mq_mmul(y1455, y1455);
177 let y5820 = mq_mmul(y2910, y2910);
178 let y6143 = mq_mmul(y5820, y323);
179 let y12286 = mq_mmul(y6143, y6143);
180 let iy = mq_mmul(y12286, y);
181
182 mq_mmul(x, iy)
185}
186
187pub fn mqpoly_small_to_int(logn: u32, f: &[i8], d: &mut [u16]) {
192 for i in 0..(1usize << logn) {
193 let x = (-(f[i] as i32)) as u32;
194 d[i] = (Q - x.wrapping_add((x >> 16) & Q)) as u16;
195 }
196}
197
198pub fn mqpoly_int_to_small(logn: u32, d: &[u16], f: &mut [i8]) -> bool {
207 let mut ov = 0;
211 for i in 0..(1usize << logn) {
212 let x = mq_add(d[i] as u32, 128);
213 ov |= x >> 8;
214 f[i] = x.wrapping_sub(128) as i8;
215 }
216 ov == 0
217}
218
219pub fn mqpoly_ext_to_int(logn: u32, a: &mut [u16]) {
222 for i in 0..(1usize << logn) {
223 let x = a[i] as u32;
226 a[i] = (x + (Q & (x.wrapping_sub(1) >> 16))) as u16;
227 }
228}
229
230pub fn mqpoly_int_to_ext(logn: u32, a: &mut [u16]) {
233 for i in 0..(1usize << logn) {
234 let x = (a[i] as u32).wrapping_sub(Q);
237 a[i] = x.wrapping_add(Q & (x >> 16)) as u16;
238 }
239}
240
241pub fn mqpoly_int_to_NTT(logn: u32, a: &mut [u16]) {
243 if logn == 0 {
244 return;
245 }
246 let mut t = 1usize << logn;
247 for lm in 0..logn {
248 let m = 1 << lm;
249 let ht = t >> 1;
250 let mut j0 = 0;
251 for i in 0..m {
252 let s = GM[i + m] as u32;
253 for j in 0..ht {
254 let j1 = j0 + j;
255 let j2 = j1 + ht;
256 let x1 = a[j1] as u32;
257 let x2 = mq_mmul(a[j2] as u32, s);
258 a[j1] = mq_add(x1, x2) as u16;
259 a[j2] = mq_sub(x1, x2) as u16;
260 }
261 j0 += t;
262 }
263 t = ht;
264 }
265}
266
267pub fn mqpoly_NTT_to_int(logn: u32, a: &mut [u16]) {
269 if logn == 0 {
270 return;
271 }
272 let mut t = 1;
273 for lm in 0..logn {
274 let hm = 1 << (logn - 1 - lm);
275 let dt = t << 1;
276 let mut j0 = 0;
277 for i in 0..hm {
278 let s = iGM[i + hm] as u32;
279 for j in 0..t {
280 let j1 = j0 + j;
281 let j2 = j1 + t;
282 let x1 = a[j1] as u32;
283 let x2 = a[j2] as u32;
284 a[j1] = mq_half(mq_add(x1, x2)) as u16;
285 a[j2] = mq_mmul(mq_sub(x1, x2), s) as u16;
286 }
287 j0 += dt;
288 }
289 t = dt;
290 }
291}
292
293pub fn mqpoly_mul_ntt(logn: u32, a: &mut [u16], b: &[u16]) {
296 for i in 0..(1usize << logn) {
297 a[i] = mq_mmul(mq_mmul(a[i] as u32, b[i] as u32), R2) as u16;
298 }
299}
300
301pub fn mqpoly_div_ntt(logn: u32, a: &mut [u16], b: &[u16]) -> bool {
308 let mut r = 0xFFFFFFFF;
309 for i in 0..(1usize << logn) {
310 let x = b[i] as u32;
311 r &= x.wrapping_sub(Q);
312 a[i] = mq_div(a[i] as u32, x) as u16;
313 }
314 (r >> 16) != 0
315}
316
317pub fn mqpoly_sub_int(logn: u32, a: &mut [u16], b: &[u16]) {
320 for i in 0..(1usize << logn) {
321 a[i] = mq_sub(a[i] as u32, b[i] as u32) as u16;
322 }
323}
324
325pub fn mqpoly_sqnorm(logn: u32, a: &[u16]) -> u32 {
331 let mut s = 0u32;
332 let mut sat = 0;
333 for i in 0..(1usize << logn) {
334 let x = a[i] as u32;
335 let m = ((Q - 1) >> 1).wrapping_sub(x) >> 16;
336 let y = x.wrapping_sub(m & Q) as i32;
337 s = s.wrapping_add((y * y) as u32);
338 sat |= s;
339 }
340 s | (sat >> 31).wrapping_neg()
341}
342
343pub fn signed_poly_sqnorm(logn: u32, a: &[i16]) -> u32 {
348 let mut s = 0;
349 for i in 0..(1usize << logn) {
350 let x = a[i] as i32;
351 s += (x * x) as u32;
352 }
353 s
354}
355
356pub(crate) const GM: [u16; 1024] = [
366 10952, 11183, 10651, 1669, 12036, 5517, 11593, 9397, 7900, 2739,
367 10901, 589, 971, 1704, 4857, 5562, 6241, 10889, 7260, 3046,
368 3102, 8228, 519, 6606, 10000, 5956, 6332, 11479, 918, 6357,
369 7237, 196, 8614, 3587, 11068, 11665, 3165, 1074, 8124, 3246,
370 9490, 10617, 946, 1812, 2862, 6807, 6659, 7117, 8726, 9985,
371 10, 9788, 4473, 8204, 11528, 7220, 657, 11417, 10842, 1827,
372 2845, 7372, 8118, 12120, 11262, 7386, 672, 1521, 734, 8135,
373 7848, 5913, 12199, 10220, 8447, 4800, 6849, 8754, 12187, 3390,
374 10989, 5616, 4584, 3792, 618, 7653, 2623, 3907, 3775, 8270,
375 2759, 11676, 1514, 9681, 182, 1180, 2453, 9557, 9954, 256,
376 6264, 1450, 11792, 10012, 203, 6988, 12216, 9655, 5443, 11387,
377 9242, 8739, 8394, 9453, 311, 7013, 7618, 1991, 11971, 3340,
378 4457, 7290, 7841, 3977, 8601, 10525, 4232, 8262, 9581, 11207,
379 11931, 1055, 6997, 11064, 208, 11882, 5973, 1724, 10020, 954,
380 8750, 11356, 11685, 8508, 4350, 5786, 5458, 1491, 768, 7005,
381 4930, 8196, 9583, 8249, 1639, 9141, 4387, 219, 11680, 3614,
382 12116, 10087, 5450, 1034, 4563, 10273, 3081, 2420, 1684, 4031,
383 10170, 306, 2111, 11526, 270, 6207, 10670, 10435, 11721, 4420,
384 11376, 10826, 3900, 7730, 4465, 7747, 3540, 11743, 10450, 4012,
385 964, 12057, 4262, 759, 3613, 2088, 5007, 4914, 4011, 3318,
386 5112, 9376, 4397, 10007, 1767, 4164, 878, 4072, 106, 2983,
387 7529, 10732, 9138, 2798, 5855, 4200, 6782, 9535, 588, 2867,
388 9859, 5582, 6867, 6710, 3222, 2794, 9738, 206, 10417, 3663,
389 11025, 1528, 8132, 3703, 9062, 4601, 5436, 9451, 8397, 5016,
390 34, 11159, 9371, 2283, 4786, 12259, 10689, 6912, 9827, 3754,
391 11782, 224, 5481, 4341, 10318, 2616, 8221, 7251, 5761, 8047,
392 12181, 12264, 2763, 5760, 6141, 11321, 5722, 4283, 10712, 9762,
393 4502, 2180, 10873, 5134, 11648, 1786, 4530, 9924, 853, 4180,
394 10729, 9197, 3043, 9466, 8115, 4268, 10521, 9604, 4260, 3717,
395 1616, 6291, 7617, 3470, 4828, 11586, 10317, 4095, 9487, 2765,
396 5059, 1740, 6777, 4641, 9748, 9994, 490, 341, 10264, 8748,
397 11867, 9688, 7615, 6428, 2831, 3500, 4226, 4847, 4534, 4008,
398 11122, 5533, 8350, 795, 11388, 5367, 3593, 7090, 7879, 9220,
399 8366, 1709, 3798, 11120, 7291, 6353, 10034, 4826, 3414, 1473,
400 5704, 6327, 5637, 7108, 640, 11982, 12, 6830, 452, 7387,
401 8918, 8664, 9596, 1311, 8475, 255, 12000, 9605, 225, 11317,
402 9947, 10609, 8712, 6113, 8638, 4958, 10454, 10385, 5769, 8504,
403 2950, 11834, 4612, 11536, 8996, 3903, 9480, 829, 3250, 10538,
404 3623, 11876, 10744, 11590, 2487, 8427, 7036, 2539, 11050, 1420,
405 10192, 4635, 10030, 10742, 11709, 9879, 10924, 3439, 7271, 11355,
406 4237, 867, 9373, 11614, 765, 11442, 8079, 8356, 2585, 10953,
407 6577, 5505, 6050, 10731, 7026, 5040, 3812, 2703, 8981, 1510,
408 2385, 11817, 3501, 7979, 8782, 895, 6770, 2705, 5127, 11769,
409 941, 9207, 6692, 7466, 9035, 7667, 4419, 2047, 6765, 10100,
410 9872, 10933, 1414, 10113, 8201, 12253, 10369, 921, 12214, 324,
411 4991, 4000, 11852, 7295, 12204, 2825, 4708, 4731, 6540, 11072,
412 560, 7412, 6155, 2904, 5194, 10988, 251, 9730, 5358, 1923,
413 4248, 9176, 515, 233, 4234, 5304, 3820, 3160, 4680, 9276,
414 10410, 1727, 10180, 10094, 6584, 7441, 11798, 1138, 5220, 9401,
415 1634, 4247, 8295, 8406, 5916, 4, 1666, 6075, 4486, 1266,
416 1023, 10819, 7623, 6885, 2252, 11900, 12024, 10976, 10500, 3796,
417 1733, 5294, 2930, 4547, 823, 11683, 10518, 1752, 7417, 4334,
418 6144, 6884, 2573, 4123, 6797, 11928, 9421, 2067, 6820, 2489,
419 1664, 9033, 9425, 8440, 3633, 9375, 8555, 4825, 7457, 6619,
420 6426, 7632, 1503, 1372, 11142, 531, 3742, 7921, 9866, 7518,
421 7712, 10433, 4985, 585, 6622, 395, 7745, 10782, 9746, 663,
422 11926, 8450, 70, 7071, 6733, 8272, 6962, 1384, 4599, 6185,
423 2160, 500, 7626, 2448, 7670, 11106, 5100, 2546, 4704, 10647,
424 5138, 7789, 5780, 4524, 11659, 10095, 9973, 9022, 11076, 12122,
425 11575, 11441, 3189, 2445, 7510, 1966, 4326, 4415, 6072, 2771,
426 1847, 8734, 7024, 7998, 10598, 6322, 1274, 8260, 4882, 5454,
427 8233, 1792, 6981, 10150, 8810, 8639, 1421, 12049, 11778, 6140,
428 1234, 5975, 3249, 12017, 9602, 4726, 2177, 12224, 4170, 1648,
429 10063, 11091, 6621, 1874, 5731, 3261, 11051, 12230, 5046, 8678,
430 5622, 4715, 9783, 7385, 12112, 3714, 1456, 9440, 4944, 12068,
431 8695, 6678, 12094, 5758, 8061, 10400, 5872, 3635, 1339, 10437,
432 5376, 12168, 9932, 8216, 5636, 8587, 11473, 2542, 6131, 1533,
433 8026, 720, 11078, 9164, 1283, 7238, 7363, 10466, 9278, 4651,
434 11788, 3639, 9745, 2142, 2488, 6948, 1890, 6582, 956, 11600,
435 8313, 6362, 5898, 2048, 2722, 4954, 6677, 5073, 202, 8467,
436 11705, 3506, 6748, 10665, 5256, 5313, 713, 2327, 10471, 9820,
437 3499, 10937, 11206, 4187, 6201, 8604, 80, 4570, 6146, 3926,
438 742, 8592, 3547, 1390, 2521, 7297, 4118, 4822, 10607, 5300,
439 4116, 7780, 7568, 2207, 11202, 10103, 10265, 7269, 6721, 1442,
440 11474, 1063, 3441, 10696, 7768, 1343, 1989, 7629, 1185, 4712,
441 9623, 10534, 238, 4379, 4152, 3692, 8924, 12079, 1089, 11517,
442 7344, 1700, 8740, 1568, 1500, 5809, 10781, 6023, 8391, 1601,
443 3460, 7173, 11533, 12114, 7052, 3453, 6120, 5513, 3187, 5403,
444 1250, 6889, 6936, 2971, 2377, 11360, 7802, 213, 7132, 8023,
445 5971, 4682, 1369, 2934, 9012, 4817, 7649, 5298, 12202, 5783,
446 5242, 1441, 11312, 7170, 4163, 12001, 9218, 7368, 10774, 4087,
447 4964, 7066, 10835, 12180, 10572, 7909, 6791, 8513, 3430, 2387,
448 10403, 12080, 9335, 6371, 4149, 8129, 7528, 12211, 5004, 9351,
449 7160, 3478, 4120, 1864, 9294, 5565, 5982, 702, 573, 474,
450 5997, 3095, 9406, 11963, 2008, 4106, 1881, 7604, 8793, 9204,
451 11609, 10311, 3061, 7422, 2592, 600, 4480, 10140, 84, 10943,
452 3164, 2553, 981, 11492, 5727, 9177, 10169, 1785, 10266, 5790,
453 1575, 5485, 8184, 529, 11828, 5924, 11310, 10128, 11733, 11250,
454 3516, 10372, 8361, 9104, 7706, 7018, 1527, 2743, 4915, 5803,
455 10461, 32, 783, 9398, 1474, 7396, 5120, 9833, 96, 5484,
456 3616, 9940, 9899, 7867, 8765, 1460, 8229, 7708, 2734, 11784,
457 1741, 5751, 5081, 6069, 4166, 7564, 5355, 6360, 7397, 9336,
458 5806, 2937, 9172, 1668, 5483, 1383, 26, 10702, 2106, 6632,
459 1422, 10570, 4406, 8985, 12218, 6697, 29, 6265, 10523, 6646,
460 11311, 8649, 6587, 3004, 9977, 3106, 1800, 4513, 6355, 2040,
461 10488, 9255, 7659, 2797, 9898, 9346, 8251, 12037, 11138, 6447,
462 11764, 2268, 10359, 3422, 9230, 1909, 11694, 7486, 8378, 8539,
463 8913, 3770, 3920, 2728, 6218, 8039, 11780, 3182, 1757, 6665,
464 639, 1172, 5158, 2787, 3605, 1631, 5060, 261, 2162, 9831,
465 8182, 3487, 11425, 12089, 9815, 9213, 9221, 2931, 8852, 7966,
466 11962, 4362, 11438, 5151, 8909, 9686, 4545, 28, 11662, 5658,
467 6824, 8862, 7161, 1999, 4205, 11328, 3475, 9566, 10434, 3098,
468 12055, 1994, 12131, 191,
469];
470
471pub(crate) const iGM: [u16; 1024] = [
472 5476, 553, 5310, 819, 1446, 348, 3386, 6271, 9508, 3716,
473 11437, 5659, 5850, 694, 4775, 8339, 12191, 2526, 2966, 11830,
474 405, 9123, 9311, 7289, 8986, 5885, 8175, 10738, 10766, 8659,
475 700, 3024, 6229, 8230, 8603, 4722, 5231, 6868, 436, 5816,
476 8679, 6525, 8187, 3908, 7395, 12284, 1152, 7926, 2586, 2815,
477 2741, 10858, 11383, 11816, 836, 7544, 10666, 8227, 11752, 4562,
478 312, 6755, 4351, 7982, 8158, 10173, 882, 1844, 4156, 2224,
479 8644, 3916, 10619, 159, 5149, 8480, 2638, 5989, 1418, 8092,
480 1775, 7668, 451, 3423, 1317, 6181, 8795, 6043, 7283, 6393,
481 11564, 9157, 12161, 7312, 1366, 4918, 11699, 12198, 1304, 11532,
482 6451, 4765, 8154, 4257, 4191, 4833, 2318, 11980, 10393, 9997,
483 9481, 650, 10594, 51, 7912, 2720, 9889, 1921, 7179, 45,
484 3188, 8365, 2077, 11922, 5384, 11953, 8596, 6658, 10981, 7130,
485 3974, 3404, 12177, 6398, 10412, 1231, 8833, 800, 15, 9896,
486 5003, 1459, 565, 12272, 9781, 1946, 1419, 9571, 3844, 7758,
487 4293, 8223, 11525, 632, 4313, 936, 12186, 7420, 10892, 10678,
488 8934, 2711, 9498, 1215, 4711, 11995, 1377, 8898, 10189, 3217,
489 10890, 7720, 6923, 2380, 4653, 12236, 10253, 11850, 10207, 5261,
490 1141, 3946, 7601, 9733, 10630, 4139, 9832, 3641, 11245, 4338,
491 5765, 10158, 116, 11807, 10283, 7064, 273, 10519, 2271, 3912,
492 8424, 10339, 6876, 6601, 10079, 284, 927, 6954, 3041, 12154,
493 6526, 5089, 12136, 7204, 4129, 11447, 11079, 4604, 1008, 3863,
494 11772, 9564, 1101, 6231, 10482, 6449, 6035, 3951, 1574, 5325,
495 2020, 1353, 8191, 9824, 2642, 11905, 5399, 9560, 9396, 10114,
496 8035, 302, 6611, 7914, 11812, 7279, 11427, 3158, 6348, 12185,
497 6757, 2646, 5617, 179, 541, 1354, 9642, 5278, 10391, 7039,
498 6801, 6277, 6339, 11163, 2702, 2333, 735, 5633, 11656, 10046,
499 3107, 11456, 12287, 9331, 8086, 1997, 4021, 11472, 1444, 9679,
500 11720, 6390, 2424, 8997, 7242, 7199, 5281, 7084, 7651, 9949,
501 10709, 10379, 9637, 10172, 6028, 5887, 7701, 10165, 5183, 9610,
502 7424, 6019, 6795, 9692, 10837, 3067, 8583, 12009, 6753, 9019,
503 3779, 9935, 4732, 6187, 2497, 6363, 10289, 3649, 12127, 6182,
504 5684, 960, 18, 2044, 1088, 11582, 678, 7353, 7239, 2762,
505 5121, 3935, 2311, 1627, 8556, 8943, 1541, 5674, 260, 3581,
506 4792, 8904, 5697, 7898, 2155, 4394, 236, 4952, 11534, 1654,
507 4793, 10383, 9769, 8776, 779, 9264, 3392, 2856, 668, 4852,
508 8111, 2105, 6568, 5762, 6482, 1458, 5711, 4026, 467, 2509,
509 4425, 6827, 1205, 290, 6918, 7274, 3827, 7193, 11579, 6764,
510 4875, 8771, 1931, 4901, 6494, 6917, 6351, 4333, 7020, 10664,
511 5730, 7549, 4193, 7791, 6521, 9983, 6372, 10814, 8037, 3260,
512 952, 7062, 9810, 7970, 3088, 7933, 840, 1171, 486, 6032,
513 1342, 6289, 6017, 1907, 5489, 7491, 7957, 7830, 2451, 12063,
514 8874, 12283, 6298, 11969, 8735, 3326, 2981, 9437, 5408, 10582,
515 9876, 7272, 2968, 2499, 6729, 10390, 5290, 8106, 7679, 2205,
516 8744, 4348, 3461, 6595, 5747, 8114, 3378, 6728, 10285, 10022,
517 3721, 10176, 10539, 4729, 9075, 2337, 7445, 211, 7915, 7157,
518 5974, 12044, 7292, 7415, 3824, 2756, 11419, 3615, 4762, 1401,
519 4097, 986, 6496, 9875, 10554, 2336, 2999, 11481, 4286, 10159,
520 7487, 884, 10155, 2087, 7556, 4623, 1546, 780, 10199, 5718,
521 7327, 10024, 11396, 6465, 9722, 708, 11199, 10038, 7408, 6933,
522 4003, 9428, 484, 3074, 9409, 4763, 6157, 54, 2121, 3264,
523 2519, 2034, 6049, 79, 11292, 117, 10740, 7072, 7506, 4407,
524 6625, 4042, 5145, 2564, 7858, 8877, 9460, 6458, 12275, 3872,
525 7446, 1690, 3569, 6570, 10108, 6308, 8306, 7863, 4679, 1534,
526 1538, 1237, 100, 432, 4401, 8198, 1229, 11208, 6014, 9759,
527 5329, 4342, 4751, 9710, 11703, 5825, 2812, 5266, 10698, 6399,
528 2125, 9180, 10925, 10329, 10404, 1688, 1875, 8100, 8546, 6442,
529 5190, 7674, 10578, 965, 11155, 6407, 2921, 6720, 126, 2019,
530 7616, 7340, 4746, 2315, 1517, 7045, 11269, 2967, 3888, 11389,
531 10736, 1156, 10787, 2851, 1820, 489, 8966, 883, 3012, 6130,
532 2796, 6180, 1652, 10086, 7004, 11578, 8973, 11236, 6938, 12276,
533 5453, 3403, 11455, 7703, 4676, 9386, 7621, 2446, 9109, 3467,
534 8507, 10206, 3110, 3604, 3269, 5274, 6397, 10922, 8435, 2030,
535 11559, 1762, 2211, 1195, 7319, 10481, 9547, 12241, 1228, 9729,
536 8591, 11552, 7590, 5753, 12273, 914, 3243, 3687, 4773, 5381,
537 8780, 8436, 7737, 1964, 7103, 10531, 6664, 278, 7225, 6634,
538 9327, 6375, 5880, 8197, 3402, 5357, 9394, 7156, 5252, 1060,
539 1556, 3281, 6543, 5654, 4868, 10707, 673, 12247, 7219, 10049,
540 11989, 10993, 8578, 4614, 989, 340, 7687, 1748, 8487, 5204,
541 10236, 11285, 163, 7586, 4597, 3146, 12052, 5858, 11938, 9298,
542 3362, 7642, 11357, 10229, 10550, 8709, 1469, 9787, 39, 8525,
543 2080, 4070, 2959, 1477, 6249, 943, 4951, 10574, 1888, 2749,
544 2190, 7003, 6199, 727, 8756, 9807, 4101, 6902, 8605, 7680,
545 144, 4063, 8704, 6633, 5424, 9668, 3253, 6188, 9640, 2320,
546 3736, 7783, 10822, 5460, 9948, 3159, 2133, 8723, 6038, 8388,
547 6609, 4956, 4659, 8821, 2700, 11664, 3443, 4551, 3388, 9229,
548 4418, 8763, 6232, 378, 2558, 10559, 5344, 1949, 3133, 754,
549 3240, 11539, 11505, 7919, 11439, 8617, 386, 5600, 105, 7827,
550 10443, 10213, 3955, 12170, 7022, 1333, 9933, 5552, 2330, 5150,
551 5473, 8405, 6941, 4424, 5613, 6552, 11568, 2784, 2510, 1012,
552 1093, 6688, 5041, 8505, 8399, 10231, 9639, 841, 9878, 10230,
553 2496, 4884, 11594, 4371, 7993, 11918, 10326, 9216, 10004, 12249,
554 7987, 3044, 4051, 6686, 676, 4395, 7379, 909, 4981, 5788,
555 3488, 9661, 812, 8915, 10536, 292, 1911, 12188, 3608, 2806,
556 9812, 10928, 11265, 9340, 9108, 1988, 6489, 11811, 8998, 11344,
557 8815, 11045, 11218, 1272, 4325, 6395, 3819, 7650, 7056, 2463,
558 8670, 5503, 7707, 6750, 11929, 8276, 5378, 3079, 11018, 408,
559 1851, 9471, 8181, 7323, 6205, 9601, 926, 5475, 4327, 9353,
560 7089, 2114, 9410, 6242, 8950, 1797, 6255, 9817, 7569, 11561,
561 10432, 6233, 2452, 1253, 3787, 9478, 7950, 9766, 6174, 619,
562 4514, 3279, 11352, 2834, 599, 1113, 11465, 10204, 6177, 5056,
563 9926, 7488, 136, 4520, 3157, 11672, 9219, 6400, 120, 5434,
564 1825, 7884, 7214, 2654, 11393, 2028, 9562, 9848, 8159, 11652,
565 9128, 6990, 8290, 8777, 7922, 5221, 4759, 9253, 3937, 10126,
566 11306, 8534, 4922, 4550, 424, 357, 6228, 6751, 7778, 1158,
567 1097, 315, 10027, 9399, 2250, 9720, 821, 9937, 11016, 9739,
568 6736, 8454, 11065, 8476, 12039, 11209, 3052, 3845, 11597, 8808,
569 8153, 2778, 2609, 12254, 8064, 6326, 5813, 7416, 6898, 2272,
570 5947, 8978, 5852, 3652, 928, 8433, 8530, 7356, 2184, 10418,
571 5879, 6718, 11603, 5393, 8473, 9076, 2835, 2416, 3732, 1867,
572 1457, 4328, 8069, 1432, 1628, 11457, 4900, 8879, 5111, 1434,
573 6325, 2746, 4083, 4858, 8847, 9217, 10122, 2436, 11413, 7030,
574 303, 5733, 3871, 10824,
575];
576
577#[cfg(test)]
578mod tests {
579 use super::*;
580
581 #[inline]
582 fn qadd(a: u32, b: u32) -> u32 {
583 let c = a + b;
584 if c >= 12289 { c - 12289 } else { c }
585 }
586
587 #[inline]
588 fn qsub(a: u32, b: u32) -> u32 {
589 if a >= b { a - b } else { (a + 12289) - b }
590 }
591
592 #[inline]
593 fn qmul(a: u32, b: u32) -> u32 {
594 (a * b) % 12289
595 }
596
597 fn inner_NTT(logn: u32, seed: u32) {
598 let mut tmp = [0u16; 5 * 1024];
599 let n = 1 << logn;
600 let (t1, tx) = tmp.split_at_mut(n);
601 let (t2, tx) = tx.split_at_mut(n);
602 let (w3, tx) = tx.split_at_mut(2 * n);
603 let (t5, _) = tx.split_at_mut(n);
604
605 let mut sh = crate::shake::SHAKE256::new();
607 for i in 0..n {
608 sh.reset();
609 sh.inject(&seed.to_le_bytes());
610 sh.inject(&(i as u16).to_le_bytes());
611 sh.flip();
612 let mut hv = [0u8; 16];
613 sh.extract(&mut hv);
614 t1[i] = (u64::from_le_bytes(*<&[u8; 8]>::try_from(&hv[0..8]).unwrap()) % 12289) as u16;
615 t2[i] = (u64::from_le_bytes(*<&[u8; 8]>::try_from(&hv[8..16]).unwrap()) % 12289) as u16;
616 }
617
618 for i in 0..(2 * n) {
621 w3[i] = 0;
622 }
623 for i in 0..n {
624 for j in 0..n {
625 let z = qmul(t1[i] as u32, t2[j] as u32);
626 let z = qadd(z, w3[i + j] as u32);
627 w3[i + j] = z as u16;
628 }
629 }
630 for i in 0..n {
631 let x = w3[i] as u32;
632 let y = w3[i + n] as u32;
633 t5[i] = qsub(x, y) as u16;
634 }
635
636 mqpoly_ext_to_int(logn, t1);
640 mqpoly_ext_to_int(logn, t2);
641 mqpoly_int_to_NTT(logn, t1);
642 mqpoly_int_to_NTT(logn, t2);
643 for i in 0..n {
644 t1[i] = mq_mmul(mq_mmul(t1[i] as u32, t2[i] as u32), R2) as u16;
645 }
646 mqpoly_NTT_to_int(logn, t1);
647 mqpoly_int_to_ext(logn, t1);
648 assert!(t1 == t5);
649 }
650
651 #[test]
652 fn NTT() {
653 for logn in 1..11 {
654 for j in 0..10 {
655 inner_NTT(logn, j);
656 }
657 }
658 }
659
660 #[test]
661 fn div() {
662 for x in 1..10 {
663 for y in 1..12289 {
664 let z = mq_div(x, y);
665 assert!((y * z) % 12289 == x);
666 }
667 assert!(mq_div(x, 12289) == 12289);
668 }
669 }
670}