#include "params.h"
#include "poly.h"
#include "reduce.h"
#include "rounding.h"
#include "symmetric.h"
#include <stdint.h>
#include "fips202x2.h"
#include "NTT_params.h"
#include "ntt.h"
static const int32_t montgomery_const[4] = {
DILITHIUM_Q, DILITHIUM_QINV
};
#define DBENCH_START()
#define DBENCH_STOP(t)
extern void PQCLEAN_DILITHIUM2_AARCH64__asm_poly_reduce(int32_t *, const int32_t *);
void poly_reduce(poly *a) {
DBENCH_START();
PQCLEAN_DILITHIUM2_AARCH64__asm_poly_reduce(a->coeffs, montgomery_const);
DBENCH_STOP(*tred);
}
extern void PQCLEAN_DILITHIUM2_AARCH64__asm_poly_caddq(int32_t *, const int32_t *);
void poly_caddq(poly *a) {
DBENCH_START();
PQCLEAN_DILITHIUM2_AARCH64__asm_poly_caddq(a->coeffs, montgomery_const);
DBENCH_STOP(*tred);
}
extern void PQCLEAN_DILITHIUM2_AARCH64__asm_poly_freeze(int32_t *, const int32_t *);
void poly_freeze(poly *a) {
DBENCH_START();
PQCLEAN_DILITHIUM2_AARCH64__asm_poly_freeze(a->coeffs, montgomery_const);
DBENCH_STOP(*tred);
}
void poly_add(poly *c, const poly *a, const poly *b) {
unsigned int i;
DBENCH_START();
for (i = 0; i < N; ++i) {
c->coeffs[i] = a->coeffs[i] + b->coeffs[i];
}
DBENCH_STOP(*tadd);
}
void poly_sub(poly *c, const poly *a, const poly *b) {
unsigned int i;
DBENCH_START();
for (i = 0; i < N; ++i) {
c->coeffs[i] = a->coeffs[i] - b->coeffs[i];
}
DBENCH_STOP(*tadd);
}
void poly_shiftl(poly *a) {
unsigned int i;
DBENCH_START();
for (i = 0; i < N; ++i) {
a->coeffs[i] <<= D;
}
DBENCH_STOP(*tmul);
}
void poly_ntt(poly *a) {
DBENCH_START();
ntt(a->coeffs);
DBENCH_STOP(*tmul);
}
void poly_invntt_tomont(poly *a) {
DBENCH_START();
invntt_tomont(a->coeffs);
DBENCH_STOP(*tmul);
}
extern void PQCLEAN_DILITHIUM2_AARCH64__asm_poly_pointwise_montgomery(int32_t *des, const int32_t *src1, const int32_t *src2, const int32_t *table);
void poly_pointwise_montgomery(poly *c, const poly *a, const poly *b) {
DBENCH_START();
PQCLEAN_DILITHIUM2_AARCH64__asm_poly_pointwise_montgomery(c->coeffs, a->coeffs, b->coeffs, montgomery_const);
DBENCH_STOP(*tmul);
}
extern void PQCLEAN_DILITHIUM2_AARCH64__asm_poly_power2round(int32_t *, int32_t *, const int32_t *);
void poly_power2round(poly *a1, poly *a0, const poly *a) {
DBENCH_START();
PQCLEAN_DILITHIUM2_AARCH64__asm_poly_power2round(a1->coeffs, a0->coeffs, a->coeffs);
DBENCH_STOP(*tround);
}
void poly_decompose(poly *a1, poly *a0, const poly *a) {
unsigned int i;
DBENCH_START();
for (i = 0; i < N; ++i) {
a1->coeffs[i] = decompose(&a0->coeffs[i], a->coeffs[i]);
}
DBENCH_STOP(*tround);
}
unsigned int poly_make_hint(poly *h, const poly *a0, const poly *a1) {
unsigned int i, s = 0;
DBENCH_START();
for (i = 0; i < N; ++i) {
h->coeffs[i] = make_hint(a0->coeffs[i], a1->coeffs[i]);
s += h->coeffs[i];
}
DBENCH_STOP(*tround);
return s;
}
void poly_use_hint(poly *b, const poly *a, const poly *h) {
unsigned int i;
DBENCH_START();
for (i = 0; i < N; ++i) {
b->coeffs[i] = use_hint(a->coeffs[i], h->coeffs[i]);
}
DBENCH_STOP(*tround);
}
int poly_chknorm(const poly *a, int32_t B) {
unsigned int i;
int32_t t;
DBENCH_START();
if (B > (DILITHIUM_Q - 1) / 8) {
return 1;
}
for (i = 0; i < N; ++i) {
t = a->coeffs[i] >> 31;
t = a->coeffs[i] - (t & 2 * a->coeffs[i]);
if (t >= B) {
DBENCH_STOP(*tsample);
return 1;
}
}
DBENCH_STOP(*tsample);
return 0;
}
static unsigned int rej_uniform(int32_t *a,
unsigned int len,
const uint8_t *buf,
unsigned int buflen) {
unsigned int ctr, pos;
uint32_t t;
DBENCH_START();
ctr = pos = 0;
while (ctr < len && pos + 3 <= buflen) {
t = buf[pos++];
t |= (uint32_t)buf[pos++] << 8;
t |= (uint32_t)buf[pos++] << 16;
t &= 0x7FFFFF;
if (t < DILITHIUM_Q) {
a[ctr++] = t;
}
}
DBENCH_STOP(*tsample);
return ctr;
}
#define POLY_UNIFORM_NBLOCKS ((768 + STREAM128_BLOCKBYTES - 1)/STREAM128_BLOCKBYTES)
void poly_uniform(poly *a,
const uint8_t seed[SEEDBYTES],
uint16_t nonce) {
unsigned int i, ctr, off;
unsigned int buflen = POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES;
uint8_t buf[POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES + 2];
stream128_state state;
stream128_init(&state, seed, nonce);
stream128_squeezeblocks(buf, POLY_UNIFORM_NBLOCKS, &state);
ctr = rej_uniform(a->coeffs, N, buf, buflen);
while (ctr < N) {
off = buflen % 3;
for (i = 0; i < off; ++i) {
buf[i] = buf[buflen - off + i];
}
stream128_squeezeblocks(buf + off, 1, &state);
buflen = STREAM128_BLOCKBYTES + off;
ctr += rej_uniform(a->coeffs + ctr, N - ctr, buf, buflen);
}
stream128_release(&state);
}
void poly_uniformx2(poly *a0, poly *a1,
const uint8_t seed[SEEDBYTES],
uint16_t nonce0, uint16_t nonce1) {
unsigned int ctr0, ctr1;
unsigned int buflen = POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES;
uint8_t buf0[POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES + 2];
uint8_t buf1[POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES + 2];
keccakx2_state statex2;
dilithium_shake128x2_stream_init(&statex2, seed, nonce0, nonce1);
shake128x2_squeezeblocks(buf0, buf1, POLY_UNIFORM_NBLOCKS, &statex2);
ctr0 = rej_uniform(a0->coeffs, N, buf0, buflen);
ctr1 = rej_uniform(a1->coeffs, N, buf1, buflen);
while (ctr0 < N || ctr1 < N) {
shake128x2_squeezeblocks(buf0, buf1, 1, &statex2);
ctr0 += rej_uniform(a0->coeffs + ctr0, N - ctr0, buf0, buflen);
ctr1 += rej_uniform(a1->coeffs + ctr1, N - ctr1, buf1, buflen);
}
}
static unsigned int rej_eta(int32_t *a,
unsigned int len,
const uint8_t *buf,
unsigned int buflen) {
unsigned int ctr, pos;
uint32_t t0, t1;
DBENCH_START();
ctr = pos = 0;
while (ctr < len && pos < buflen) {
t0 = buf[pos] & 0x0F;
t1 = buf[pos++] >> 4;
if (t0 < 15) {
t0 = t0 - (205 * t0 >> 10) * 5;
a[ctr++] = 2 - t0;
}
if (t1 < 15 && ctr < len) {
t1 = t1 - (205 * t1 >> 10) * 5;
a[ctr++] = 2 - t1;
}
}
DBENCH_STOP(*tsample);
return ctr;
}
#define POLY_UNIFORM_ETA_NBLOCKS ((136 + STREAM256_BLOCKBYTES - 1)/STREAM256_BLOCKBYTES)
void poly_uniform_eta(poly *a,
const uint8_t seed[CRHBYTES],
uint16_t nonce) {
unsigned int ctr;
unsigned int buflen = POLY_UNIFORM_ETA_NBLOCKS * STREAM256_BLOCKBYTES;
uint8_t buf[POLY_UNIFORM_ETA_NBLOCKS * STREAM256_BLOCKBYTES];
stream256_state state;
stream256_init(&state, seed, nonce);
stream256_squeezeblocks(buf, POLY_UNIFORM_ETA_NBLOCKS, &state);
ctr = rej_eta(a->coeffs, N, buf, buflen);
while (ctr < N) {
stream256_squeezeblocks(buf, 1, &state);
ctr += rej_eta(a->coeffs + ctr, N - ctr, buf, STREAM256_BLOCKBYTES);
}
stream256_release(&state);
}
void poly_uniform_etax2(poly *a0, poly *a1,
const uint8_t seed[CRHBYTES],
uint16_t nonce0, uint16_t nonce1) {
unsigned int ctr0, ctr1;
unsigned int buflen = POLY_UNIFORM_ETA_NBLOCKS * STREAM256_BLOCKBYTES;
uint8_t buf0[POLY_UNIFORM_ETA_NBLOCKS * STREAM256_BLOCKBYTES];
uint8_t buf1[POLY_UNIFORM_ETA_NBLOCKS * STREAM256_BLOCKBYTES];
keccakx2_state statex2;
dilithium_shake256x2_stream_init(&statex2, seed, nonce0, nonce1);
shake256x2_squeezeblocks(buf0, buf1, POLY_UNIFORM_ETA_NBLOCKS, &statex2);
ctr0 = rej_eta(a0->coeffs, N, buf0, buflen);
ctr1 = rej_eta(a1->coeffs, N, buf1, buflen);
while (ctr0 < N || ctr1 < N) {
shake256x2_squeezeblocks(buf0, buf1, 1, &statex2);
ctr0 += rej_eta(a0->coeffs + ctr0, N - ctr0, buf0, STREAM256_BLOCKBYTES);
ctr1 += rej_eta(a1->coeffs + ctr1, N - ctr1, buf1, STREAM256_BLOCKBYTES);
}
}
#define POLY_UNIFORM_GAMMA1_NBLOCKS ((POLYZ_PACKEDBYTES + STREAM256_BLOCKBYTES - 1)/STREAM256_BLOCKBYTES)
void poly_uniform_gamma1(poly *a,
const uint8_t seed[CRHBYTES],
uint16_t nonce) {
uint8_t buf[POLY_UNIFORM_GAMMA1_NBLOCKS * STREAM256_BLOCKBYTES];
stream256_state state;
stream256_init(&state, seed, nonce);
stream256_squeezeblocks(buf, POLY_UNIFORM_GAMMA1_NBLOCKS, &state);
stream256_release(&state);
polyz_unpack(a, buf);
}
void poly_uniform_gamma1x2(poly *a0, poly *a1,
const uint8_t seed[CRHBYTES],
uint16_t nonce0, uint16_t nonce1) {
uint8_t buf0[POLY_UNIFORM_GAMMA1_NBLOCKS * STREAM256_BLOCKBYTES];
uint8_t buf1[POLY_UNIFORM_GAMMA1_NBLOCKS * STREAM256_BLOCKBYTES];
keccakx2_state statex2;
dilithium_shake256x2_stream_init(&statex2, seed, nonce0, nonce1);
shake256x2_squeezeblocks(buf0, buf1, POLY_UNIFORM_GAMMA1_NBLOCKS, &statex2);
polyz_unpack(a0, buf0);
polyz_unpack(a1, buf1);
}
void poly_challenge(poly *c, const uint8_t seed[SEEDBYTES]) {
unsigned int i, b, pos;
uint64_t signs;
uint8_t buf[SHAKE256_RATE];
shake256incctx state;
shake256_inc_init(&state);
shake256_inc_absorb(&state, seed, SEEDBYTES);
shake256_inc_finalize(&state);
shake256_inc_squeeze(buf, sizeof buf, &state);
signs = 0;
for (i = 0; i < 8; ++i) {
signs |= (uint64_t)buf[i] << 8 * i;
}
pos = 8;
for (i = 0; i < N; ++i) {
c->coeffs[i] = 0;
}
for (i = N - TAU; i < N; ++i) {
do {
if (pos >= SHAKE256_RATE) {
shake256_inc_squeeze(buf, sizeof buf, &state);
pos = 0;
}
b = buf[pos++];
} while (b > i);
c->coeffs[i] = c->coeffs[b];
c->coeffs[b] = 1 - 2 * (signs & 1);
signs >>= 1;
}
shake256_inc_ctx_release(&state);
}
void polyeta_pack(uint8_t *r, const poly *a) {
unsigned int i;
uint8_t t[8];
DBENCH_START();
for (i = 0; i < N / 8; ++i) {
t[0] = ETA - a->coeffs[8 * i + 0];
t[1] = ETA - a->coeffs[8 * i + 1];
t[2] = ETA - a->coeffs[8 * i + 2];
t[3] = ETA - a->coeffs[8 * i + 3];
t[4] = ETA - a->coeffs[8 * i + 4];
t[5] = ETA - a->coeffs[8 * i + 5];
t[6] = ETA - a->coeffs[8 * i + 6];
t[7] = ETA - a->coeffs[8 * i + 7];
r[3 * i + 0] = (t[0] >> 0) | (t[1] << 3) | (t[2] << 6);
r[3 * i + 1] = (t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7);
r[3 * i + 2] = (t[5] >> 1) | (t[6] << 2) | (t[7] << 5);
}
DBENCH_STOP(*tpack);
}
void polyeta_unpack(poly *r, const uint8_t *a) {
unsigned int i;
DBENCH_START();
for (i = 0; i < N / 8; ++i) {
r->coeffs[8 * i + 0] = (a[3 * i + 0] >> 0) & 7;
r->coeffs[8 * i + 1] = (a[3 * i + 0] >> 3) & 7;
r->coeffs[8 * i + 2] = ((a[3 * i + 0] >> 6) | (a[3 * i + 1] << 2)) & 7;
r->coeffs[8 * i + 3] = (a[3 * i + 1] >> 1) & 7;
r->coeffs[8 * i + 4] = (a[3 * i + 1] >> 4) & 7;
r->coeffs[8 * i + 5] = ((a[3 * i + 1] >> 7) | (a[3 * i + 2] << 1)) & 7;
r->coeffs[8 * i + 6] = (a[3 * i + 2] >> 2) & 7;
r->coeffs[8 * i + 7] = (a[3 * i + 2] >> 5) & 7;
r->coeffs[8 * i + 0] = ETA - r->coeffs[8 * i + 0];
r->coeffs[8 * i + 1] = ETA - r->coeffs[8 * i + 1];
r->coeffs[8 * i + 2] = ETA - r->coeffs[8 * i + 2];
r->coeffs[8 * i + 3] = ETA - r->coeffs[8 * i + 3];
r->coeffs[8 * i + 4] = ETA - r->coeffs[8 * i + 4];
r->coeffs[8 * i + 5] = ETA - r->coeffs[8 * i + 5];
r->coeffs[8 * i + 6] = ETA - r->coeffs[8 * i + 6];
r->coeffs[8 * i + 7] = ETA - r->coeffs[8 * i + 7];
}
DBENCH_STOP(*tpack);
}
void polyt1_pack(uint8_t *r, const poly *a) {
unsigned int i;
DBENCH_START();
for (i = 0; i < N / 4; ++i) {
r[5 * i + 0] = (uint8_t) (a->coeffs[4 * i + 0] >> 0);
r[5 * i + 1] = (uint8_t) ((a->coeffs[4 * i + 0] >> 8) | (a->coeffs[4 * i + 1] << 2));
r[5 * i + 2] = (uint8_t) ((a->coeffs[4 * i + 1] >> 6) | (a->coeffs[4 * i + 2] << 4));
r[5 * i + 3] = (uint8_t) ((a->coeffs[4 * i + 2] >> 4) | (a->coeffs[4 * i + 3] << 6));
r[5 * i + 4] = (uint8_t) (a->coeffs[4 * i + 3] >> 2);
}
DBENCH_STOP(*tpack);
}
extern void PQCLEAN_DILITHIUM2_AARCH64__asm_10_to_32(int32_t *, const uint8_t *);
void polyt1_unpack(poly *r, const uint8_t *a) {
DBENCH_START();
PQCLEAN_DILITHIUM2_AARCH64__asm_10_to_32(r->coeffs, a);
DBENCH_STOP(*tpack);
}
void polyt0_pack(uint8_t *r, const poly *a) {
unsigned int i;
uint32_t t[8];
DBENCH_START();
for (i = 0; i < N / 8; ++i) {
t[0] = (1 << (D - 1)) - a->coeffs[8 * i + 0];
t[1] = (1 << (D - 1)) - a->coeffs[8 * i + 1];
t[2] = (1 << (D - 1)) - a->coeffs[8 * i + 2];
t[3] = (1 << (D - 1)) - a->coeffs[8 * i + 3];
t[4] = (1 << (D - 1)) - a->coeffs[8 * i + 4];
t[5] = (1 << (D - 1)) - a->coeffs[8 * i + 5];
t[6] = (1 << (D - 1)) - a->coeffs[8 * i + 6];
t[7] = (1 << (D - 1)) - a->coeffs[8 * i + 7];
r[13 * i + 0] = (uint8_t) t[0];
r[13 * i + 1] = (uint8_t) (t[0] >> 8);
r[13 * i + 1] |= (uint8_t) (t[1] << 5);
r[13 * i + 2] = (uint8_t) (t[1] >> 3);
r[13 * i + 3] = (uint8_t) (t[1] >> 11);
r[13 * i + 3] |= (uint8_t) (t[2] << 2);
r[13 * i + 4] = (uint8_t) (t[2] >> 6);
r[13 * i + 4] |= (uint8_t) (t[3] << 7);
r[13 * i + 5] = (uint8_t) (t[3] >> 1);
r[13 * i + 6] = (uint8_t) (t[3] >> 9);
r[13 * i + 6] |= (uint8_t) (t[4] << 4);
r[13 * i + 7] = (uint8_t) (t[4] >> 4);
r[13 * i + 8] = (uint8_t) (t[4] >> 12);
r[13 * i + 8] |= (uint8_t) (t[5] << 1);
r[13 * i + 9] = (uint8_t) (t[5] >> 7);
r[13 * i + 9] |= (uint8_t) (t[6] << 6);
r[13 * i + 10] = (uint8_t) (t[6] >> 2);
r[13 * i + 11] = (uint8_t) (t[6] >> 10);
r[13 * i + 11] |= (uint8_t) (t[7] << 3);
r[13 * i + 12] = (uint8_t) (t[7] >> 5);
}
DBENCH_STOP(*tpack);
}
void polyt0_unpack(poly *r, const uint8_t *a) {
unsigned int i;
DBENCH_START();
for (i = 0; i < N / 8; ++i) {
r->coeffs[8 * i + 0] = a[13 * i + 0];
r->coeffs[8 * i + 0] |= (uint32_t)a[13 * i + 1] << 8;
r->coeffs[8 * i + 0] &= 0x1FFF;
r->coeffs[8 * i + 1] = a[13 * i + 1] >> 5;
r->coeffs[8 * i + 1] |= (uint32_t)a[13 * i + 2] << 3;
r->coeffs[8 * i + 1] |= (uint32_t)a[13 * i + 3] << 11;
r->coeffs[8 * i + 1] &= 0x1FFF;
r->coeffs[8 * i + 2] = a[13 * i + 3] >> 2;
r->coeffs[8 * i + 2] |= (uint32_t)a[13 * i + 4] << 6;
r->coeffs[8 * i + 2] &= 0x1FFF;
r->coeffs[8 * i + 3] = a[13 * i + 4] >> 7;
r->coeffs[8 * i + 3] |= (uint32_t)a[13 * i + 5] << 1;
r->coeffs[8 * i + 3] |= (uint32_t)a[13 * i + 6] << 9;
r->coeffs[8 * i + 3] &= 0x1FFF;
r->coeffs[8 * i + 4] = a[13 * i + 6] >> 4;
r->coeffs[8 * i + 4] |= (uint32_t)a[13 * i + 7] << 4;
r->coeffs[8 * i + 4] |= (uint32_t)a[13 * i + 8] << 12;
r->coeffs[8 * i + 4] &= 0x1FFF;
r->coeffs[8 * i + 5] = a[13 * i + 8] >> 1;
r->coeffs[8 * i + 5] |= (uint32_t)a[13 * i + 9] << 7;
r->coeffs[8 * i + 5] &= 0x1FFF;
r->coeffs[8 * i + 6] = a[13 * i + 9] >> 6;
r->coeffs[8 * i + 6] |= (uint32_t)a[13 * i + 10] << 2;
r->coeffs[8 * i + 6] |= (uint32_t)a[13 * i + 11] << 10;
r->coeffs[8 * i + 6] &= 0x1FFF;
r->coeffs[8 * i + 7] = a[13 * i + 11] >> 3;
r->coeffs[8 * i + 7] |= (uint32_t)a[13 * i + 12] << 5;
r->coeffs[8 * i + 7] &= 0x1FFF;
r->coeffs[8 * i + 0] = (1 << (D - 1)) - r->coeffs[8 * i + 0];
r->coeffs[8 * i + 1] = (1 << (D - 1)) - r->coeffs[8 * i + 1];
r->coeffs[8 * i + 2] = (1 << (D - 1)) - r->coeffs[8 * i + 2];
r->coeffs[8 * i + 3] = (1 << (D - 1)) - r->coeffs[8 * i + 3];
r->coeffs[8 * i + 4] = (1 << (D - 1)) - r->coeffs[8 * i + 4];
r->coeffs[8 * i + 5] = (1 << (D - 1)) - r->coeffs[8 * i + 5];
r->coeffs[8 * i + 6] = (1 << (D - 1)) - r->coeffs[8 * i + 6];
r->coeffs[8 * i + 7] = (1 << (D - 1)) - r->coeffs[8 * i + 7];
}
DBENCH_STOP(*tpack);
}
void polyz_pack(uint8_t *r, const poly *a) {
unsigned int i;
uint32_t t[4];
DBENCH_START();
#if GAMMA1 == (1 << 17)
for (i = 0; i < N / 4; ++i) {
t[0] = GAMMA1 - a->coeffs[4 * i + 0];
t[1] = GAMMA1 - a->coeffs[4 * i + 1];
t[2] = GAMMA1 - a->coeffs[4 * i + 2];
t[3] = GAMMA1 - a->coeffs[4 * i + 3];
r[9 * i + 0] = t[0];
r[9 * i + 1] = t[0] >> 8;
r[9 * i + 2] = t[0] >> 16;
r[9 * i + 2] |= t[1] << 2;
r[9 * i + 3] = t[1] >> 6;
r[9 * i + 4] = t[1] >> 14;
r[9 * i + 4] |= t[2] << 4;
r[9 * i + 5] = t[2] >> 4;
r[9 * i + 6] = t[2] >> 12;
r[9 * i + 6] |= t[3] << 6;
r[9 * i + 7] = t[3] >> 2;
r[9 * i + 8] = t[3] >> 10;
}
#elif GAMMA1 == (1 << 19)
for (i = 0; i < N / 2; ++i) {
t[0] = GAMMA1 - a->coeffs[2 * i + 0];
t[1] = GAMMA1 - a->coeffs[2 * i + 1];
r[5 * i + 0] = t[0];
r[5 * i + 1] = t[0] >> 8;
r[5 * i + 2] = t[0] >> 16;
r[5 * i + 2] |= t[1] << 4;
r[5 * i + 3] = t[1] >> 4;
r[5 * i + 4] = t[1] >> 12;
}
#else
#error "No parameter specified!"
#endif
DBENCH_STOP(*tpack);
}
void polyz_unpack(poly *r, const uint8_t *a) {
unsigned int i;
DBENCH_START();
#if GAMMA1 == (1 << 17)
for (i = 0; i < N / 4; ++i) {
r->coeffs[4 * i + 0] = a[9 * i + 0];
r->coeffs[4 * i + 0] |= (uint32_t)a[9 * i + 1] << 8;
r->coeffs[4 * i + 0] |= (uint32_t)a[9 * i + 2] << 16;
r->coeffs[4 * i + 0] &= 0x3FFFF;
r->coeffs[4 * i + 1] = a[9 * i + 2] >> 2;
r->coeffs[4 * i + 1] |= (uint32_t)a[9 * i + 3] << 6;
r->coeffs[4 * i + 1] |= (uint32_t)a[9 * i + 4] << 14;
r->coeffs[4 * i + 1] &= 0x3FFFF;
r->coeffs[4 * i + 2] = a[9 * i + 4] >> 4;
r->coeffs[4 * i + 2] |= (uint32_t)a[9 * i + 5] << 4;
r->coeffs[4 * i + 2] |= (uint32_t)a[9 * i + 6] << 12;
r->coeffs[4 * i + 2] &= 0x3FFFF;
r->coeffs[4 * i + 3] = a[9 * i + 6] >> 6;
r->coeffs[4 * i + 3] |= (uint32_t)a[9 * i + 7] << 2;
r->coeffs[4 * i + 3] |= (uint32_t)a[9 * i + 8] << 10;
r->coeffs[4 * i + 3] &= 0x3FFFF;
r->coeffs[4 * i + 0] = GAMMA1 - r->coeffs[4 * i + 0];
r->coeffs[4 * i + 1] = GAMMA1 - r->coeffs[4 * i + 1];
r->coeffs[4 * i + 2] = GAMMA1 - r->coeffs[4 * i + 2];
r->coeffs[4 * i + 3] = GAMMA1 - r->coeffs[4 * i + 3];
}
#elif GAMMA1 == (1 << 19)
for (i = 0; i < N / 2; ++i) {
r->coeffs[2 * i + 0] = a[5 * i + 0];
r->coeffs[2 * i + 0] |= (uint32_t)a[5 * i + 1] << 8;
r->coeffs[2 * i + 0] |= (uint32_t)a[5 * i + 2] << 16;
r->coeffs[2 * i + 0] &= 0xFFFFF;
r->coeffs[2 * i + 1] = a[5 * i + 2] >> 4;
r->coeffs[2 * i + 1] |= (uint32_t)a[5 * i + 3] << 4;
r->coeffs[2 * i + 1] |= (uint32_t)a[5 * i + 4] << 12;
r->coeffs[2 * i + 0] &= 0xFFFFF;
r->coeffs[2 * i + 0] = GAMMA1 - r->coeffs[2 * i + 0];
r->coeffs[2 * i + 1] = GAMMA1 - r->coeffs[2 * i + 1];
}
#else
#error "No parameter specified!"
#endif
DBENCH_STOP(*tpack);
}
void polyw1_pack(uint8_t *r, const poly *a) {
unsigned int i;
DBENCH_START();
#if GAMMA2 == (DILITHIUM_Q-1)/88
for (i = 0; i < N / 4; ++i) {
r[3 * i + 0] = a->coeffs[4 * i + 0];
r[3 * i + 0] |= a->coeffs[4 * i + 1] << 6;
r[3 * i + 1] = a->coeffs[4 * i + 1] >> 2;
r[3 * i + 1] |= a->coeffs[4 * i + 2] << 4;
r[3 * i + 2] = a->coeffs[4 * i + 2] >> 4;
r[3 * i + 2] |= a->coeffs[4 * i + 3] << 2;
}
#elif GAMMA2 == (DILITHIUM_Q-1)/32
for (i = 0; i < N / 2; ++i) {
r[i] = a->coeffs[2 * i + 0] | (a->coeffs[2 * i + 1] << 4);
}
#else
#error "No parameter specified!"
#endif
DBENCH_STOP(*tpack);
}