feature. See also
. The project being documented here (as the example) is the Zig library itself.
ml_kem.PolyVec
fn PolyVec(comptime k: u8) type
File
Code
fn PolyVec(comptime k: u8) type {
return struct {
ps: [k]Poly,
const Self = @This();
const encoded_length = k * Poly.encoded_length;
fn compressedSize(comptime d: u8) usize {
return Poly.compressedSize(d) * k;
}
fn map(v: Self, comptime op: fn (Poly) Poly) Self {
var ret: Self = undefined;
inline for (0..k) |i| {
ret.ps[i] = op(v.ps[i]);
}
return ret;
}
fn mapBinary(a: Self, b: Self, comptime op: fn (Poly, Poly) Poly) Self {
var ret: Self = undefined;
inline for (0..k) |i| {
ret.ps[i] = op(a.ps[i], b.ps[i]);
}
return ret;
}
fn ntt(v: Self) Self {
return map(v, Poly.ntt);
}
fn invNTT(v: Self) Self {
return map(v, Poly.invNTT);
}
fn normalize(v: Self) Self {
return map(v, Poly.normalize);
}
fn barrettReduce(v: Self) Self {
return map(v, Poly.barrettReduce);
}
fn add(a: Self, b: Self) Self {
return mapBinary(a, b, Poly.add);
}
fn sub(a: Self, b: Self) Self {
return mapBinary(a, b, Poly.sub);
}
// seed and nonce+i.
fn noise(comptime eta: u8, nonce: u8, seed: *const [32]u8) Self {
var ret: Self = undefined;
for (0..k) |i| {
ret.ps[i] = Poly.noise(eta, nonce + @as(u8, @intCast(i)), seed);
}
return ret;
}
//
// See MulHat() and NTT() for a description of the multiplication.
// Assumes a and b are in Montgomery form. p will be in Montgomery form,
// and its coefficients will be bounded in absolute value by 2kq.
// If a and b are not in Montgomery form, then the action is the same
// as "pointwise" multiplication followed by multiplying by R⁻¹, the inverse
// of the Montgomery factor.
fn dotHat(a: Self, b: Self) Poly {
var ret: Poly = Poly.zero;
for (0..k) |i| {
ret = ret.add(a.ps[i].mulHat(b.ps[i]));
}
return ret;
}
fn compress(v: Self, comptime d: u8) [compressedSize(d)]u8 {
const cs = comptime Poly.compressedSize(d);
var ret: [compressedSize(d)]u8 = undefined;
inline for (0..k) |i| {
ret[i * cs .. (i + 1) * cs].* = v.ps[i].compress(d);
}
return ret;
}
fn decompress(comptime d: u8, buf: *const [compressedSize(d)]u8) Self {
const cs = comptime Poly.compressedSize(d);
var ret: Self = undefined;
inline for (0..k) |i| {
ret.ps[i] = Poly.decompress(d, buf[i * cs .. (i + 1) * cs]);
}
return ret;
}
fn toBytes(v: Self) [encoded_length]u8 {
var ret: [encoded_length]u8 = undefined;
inline for (0..k) |i| {
ret[i * Poly.encoded_length .. (i + 1) * Poly.encoded_length].* = v.ps[i].toBytes();
}
return ret;
}
fn fromBytes(buf: *const [encoded_length]u8) Self {
var ret: Self = undefined;
inline for (0..k) |i| {
ret.ps[i] = Poly.fromBytes(
buf[i * Poly.encoded_length .. (i + 1) * Poly.encoded_length],
);
}
return ret;
}
};
}