Unpack polynomial with coefficients in [Q-eta, Q+eta] from bytes. Output coefficients will not be normalized, but in [q-η, q+η].
fn polyUnpackLeqEta(comptime eta: u8, buf: []const u8) Poly
fn polyUnpackLeqEta(comptime eta: u8, buf: []const u8) Poly {
comptime {
if (eta != 2 and eta != 4) {
@compileError("eta must be 2 or 4");
}
}
var p = Poly.zero;
if (eta == 2) {
// 3 bits per coefficient: unpack 8 coefficients from 3 bytes
var j: usize = 0;
var i: usize = 0;
while (i < buf.len) : (i += 3) {
p.cs[j] = Q + eta - (buf[i] & 7);
p.cs[j + 1] = Q + eta - ((buf[i] >> 3) & 7);
p.cs[j + 2] = Q + eta - ((buf[i] >> 6) | ((buf[i + 1] << 2) & 7));
p.cs[j + 3] = Q + eta - ((buf[i + 1] >> 1) & 7);
p.cs[j + 4] = Q + eta - ((buf[i + 1] >> 4) & 7);
p.cs[j + 5] = Q + eta - ((buf[i + 1] >> 7) | ((buf[i + 2] << 1) & 7));
p.cs[j + 6] = Q + eta - ((buf[i + 2] >> 2) & 7);
p.cs[j + 7] = Q + eta - ((buf[i + 2] >> 5) & 7);
j += 8;
}
} else { // eta == 4
// 4 bits per coefficient: unpack 2 coefficients from 1 byte
var j: usize = 0;
for (0..buf.len) |i| {
p.cs[j] = Q + eta - (buf[i] & 15);
p.cs[j + 1] = Q + eta - (buf[i] >> 4);
j += 2;
}
}
return p;
}