use crate::reduce::*;
pub const ZETAS: [i16; 128] = [
-1044, -758, -359, -1517, 1493, 1422, 287, 202,
-171, 622, 1577, 182, 962, -1202, -1474, 1468,
573, -1325, 264, 383, -829, 1458, -1602, -130,
-681, 1017, 732, 608, -1542, 411, -205, -1571,
1223, 652, -552, 1015, -1293, 1491, -282, -1544,
516, -8, -320, -666, -1618, -1162, 126, 1469,
-853, -90, -271, 830, 107, -1421, -247, -951,
-398, 961, -1508, -725, 448, -1065, 677, -1275,
-1103, 430, 555, 843, -1251, 871, 1550, 105,
422, 587, 177, -235, -291, -460, 1574, 1653,
-246, 778, 1159, -147, -777, 1483, -602, 1119,
-1590, 644, -872, 349, 418, 329, -156, -75,
817, 1097, 603, 610, 1322, -1285, -1465, 384,
-1215, -136, 1218, -1335, -874, 220, -1187, -1659,
-1185, -1530, -1278, 794, -1510, -854, -870, 478,
-108, -308, 996, 991, 958, -1460, 1522, 1628
];
pub fn fqmul(a: i16, b: i16) -> i16
{
montgomery_reduce(a as i32 * b as i32)
}
pub fn ntt(r: &mut[i16])
{
let mut j;
let mut k = 1usize;
let mut len = 128;
let (mut t, mut zeta);
while len >= 2 {
let mut start = 0;
while start < 256 {
zeta = ZETAS[k];
k += 1;
j = start;
while j < (start + len) {
t = fqmul(zeta, r[j + len]);
r[j + len] = r[j] - t;
r[j] += t;
j += 1;
}
start = j + len;
}
len >>= 1;
}
}
pub fn invntt(r: &mut[i16])
{
let mut j;
let mut k = 127usize;
let mut len = 2;
let (mut t, mut zeta);
const F: i16 = 1441; while len <= 128 {
let mut start = 0;
while start < 256 {
zeta = ZETAS[k];
k -= 1;
j = start;
while j < (start + len) {
t = r[j];
r[j] = barrett_reduce(t + r[j + len]);
r[j + len] = r[j + len] -t;
r[j + len] = fqmul(zeta, r[j + len]);
j += 1
}
start = j + len;
}
len <<= 1;
}
for j in 0..256 {
r[j] = fqmul(r[j], F);
}
}
pub fn basemul(r: &mut[i16], a: &[i16], b: &[i16], zeta: i16)
{
r[0] = fqmul(a[1], b[1]);
r[0] = fqmul(r[0], zeta);
r[0] += fqmul(a[0], b[0]);
r[1] = fqmul(a[0], b[1]);
r[1] += fqmul(a[1], b[0]);
}