Unpack polynomial with coefficients in (-gamma1, gamma1] from bytes. Output coefficients will be normalized.
fn polyUnpackLeGamma1(comptime gamma1_bits: u8, buf: []const u8) Poly
fn polyUnpackLeGamma1(comptime gamma1_bits: u8, buf: []const u8) Poly {
const gamma1: u32 = @as(u32, 1) << gamma1_bits;
var p = Poly.zero;
if (gamma1_bits == 17) {
// Unpack 4 coefficients from 9 bytes (18 bits each)
var j: usize = 0;
var i: usize = 0;
while (i < buf.len) : (i += 9) {
var p0 = @as(u32, buf[i]) | (@as(u32, buf[i + 1]) << 8) | ((@as(u32, buf[i + 2]) & 0x3) << 16);
var p1 = (@as(u32, buf[i + 2]) >> 2) | (@as(u32, buf[i + 3]) << 6) | ((@as(u32, buf[i + 4]) & 0xf) << 14);
var p2 = (@as(u32, buf[i + 4]) >> 4) | (@as(u32, buf[i + 5]) << 4) | ((@as(u32, buf[i + 6]) & 0x3f) << 12);
var p3 = (@as(u32, buf[i + 6]) >> 6) | (@as(u32, buf[i + 7]) << 2) | (@as(u32, buf[i + 8]) << 10);
// Convert from [0, 2γ₁) to (-γ₁, γ₁]
p0 = centeredToPositive(p0, gamma1);
p1 = centeredToPositive(p1, gamma1);
p2 = centeredToPositive(p2, gamma1);
p3 = centeredToPositive(p3, gamma1);
p.cs[j] = p0;
p.cs[j + 1] = p1;
p.cs[j + 2] = p2;
p.cs[j + 3] = p3;
j += 4;
}
} else if (gamma1_bits == 19) {
// Unpack 2 coefficients from 5 bytes (20 bits each)
var j: usize = 0;
var i: usize = 0;
while (i < buf.len) : (i += 5) {
var p0 = @as(u32, buf[i]) | (@as(u32, buf[i + 1]) << 8) | ((@as(u32, buf[i + 2]) & 0xf) << 16);
var p1 = (@as(u32, buf[i + 2]) >> 4) | (@as(u32, buf[i + 3]) << 4) | (@as(u32, buf[i + 4]) << 12);
p0 = centeredToPositive(p0, gamma1);
p1 = centeredToPositive(p1, gamma1);
p.cs[j] = p0;
p.cs[j + 1] = p1;
j += 2;
}
} else {
@compileError("gamma1_bits must be 17 or 19");
}
return p;
}