26#ifdef HAVE_MLDSA_OPTIMIZATION
40static const int16_t mldsa_small_zetas[128] = {
41 -1044, -758, -359, -1517, 1493, 1422, 287, 202,
42 -171, 622, 1577, 182, 962, -1202, -1474, 1468,
43 573, -1325, 264, 383, -829, 1458, -1602, -130,
44 -681, 1017, 732, 608, -1542, 411, -205, -1571,
45 1223, 652, -552, 1015, -1293, 1491, -282, -1544,
46 516, -8, -320, -666, -1618, -1162, 126, 1469,
47 -853, -90, -271, 830, 107, -1421, -247, -951,
48 -398, 961, -1508, -725, 448, -1065, 677, -1275,
49 -1103, 430, 555, 843, -1251, 871, 1550, 105,
50 422, 587, 177, -235, -291, -460, 1574, 1653,
51 -246, 778, 1159, -147, -777, 1483, -602, 1119,
52 -1590, 644, -872, 349, 418, 329, -156, -75,
53 817, 1097, 603, 610, 1322, -1285, -1465, 384,
54 -1215, -136, 1218, -1335, -874, 220, -1187, -1659,
55 -1185, -1530, -1278, 794, -1510, -854, -870, 478,
56 -108, -308, 996, 991, 958, -1460, 1522, 1628
67static inline int16_t mldsa_small_montgomery_reduce(int32_t a)
70 t = (int16_t) ((int16_t) a * (int16_t) MLDSA_SMALL_QINV);
71 t = (int16_t) ((a - (int32_t) t * MLDSA_SMALL_Q) >> 16);
78static inline int16_t mldsa_small_barrett_reduce(int16_t a)
81 const int16_t v = ((1 << 26) + MLDSA_SMALL_Q / 2) / MLDSA_SMALL_Q;
82 t = (int16_t) (((int32_t) v * a + (1 << 25)) >> 26);
83 t = (int16_t) (t * MLDSA_SMALL_Q);
84 return (int16_t) (a - t);
90static inline int16_t mldsa_small_fqmul(int16_t a, int16_t b)
92 return mldsa_small_montgomery_reduce((int32_t) a * b);
99void MLDSA_SMALLPOLY_ntt(int16_t r[
MLDSA_N])
101 uint32_t len, start, j, k;
105 for (len = 128U; len >= 2U; len >>= 1U) {
106 for (start = 0U; start <
MLDSA_N; start = j + len) {
107 zeta = mldsa_small_zetas[k++];
108 for (j = start; j < start + len; j++) {
109 t = mldsa_small_fqmul(zeta, r[j + len]);
110 r[j + len] = (int16_t) (r[j] - t);
111 r[j] = (int16_t) (r[j] + t);
117void MLDSA_SMALLPOLY_invntt_tomont(int16_t r[
MLDSA_N])
119 uint32_t start, len, j, k;
121 const int16_t f = 1441;
124 for (len = 2U; len <= 128U; len <<= 1U) {
125 for (start = 0U; start <
MLDSA_N; start = j + len) {
126 zeta = mldsa_small_zetas[k--];
127 for (j = start; j < start + len; j++) {
129 r[j] = mldsa_small_barrett_reduce((int16_t) (t + r[j + len]));
130 r[j + len] = (int16_t) (r[j + len] - t);
131 r[j + len] = mldsa_small_fqmul(zeta, r[j + len]);
136 for (j = 0U; j <
MLDSA_N; j++) {
137 r[j] = mldsa_small_barrett_reduce(mldsa_small_fqmul(r[j], f));
144static inline void mldsa_small_basemul(int16_t r[2],
149 int16_t a0 = a[0], a1 = a[1];
152 r[0] = mldsa_small_fqmul(a1, b[1]);
153 r[0] = mldsa_small_fqmul(r[0], zeta);
154 r[0] = (int16_t) (r[0] + mldsa_small_fqmul(a0, b0));
155 r[1] = mldsa_small_fqmul(a0, b[1]);
156 r[1] = (int16_t) (r[1] + mldsa_small_fqmul(a1, b0));
159void MLDSA_SMALLPOLY_ntt_copy(mldsa_smallpoly *out,
const mldsa_poly *in)
161 for (uint32_t i = 0U; i <
MLDSA_N; i++) {
162 out->coeffs[i] = (int16_t) in->
coeffs[i];
164 MLDSA_SMALLPOLY_ntt(out->coeffs);
167void MLDSA_SMALLPOLY_basemul_invntt(
mldsa_poly *r,
168 const mldsa_smallpoly *a,
169 const mldsa_smallpoly *b)
172 mldsa_smallpoly *tmp = (mldsa_smallpoly *) r;
175 for (uint32_t i = 0U; i <
MLDSA_N / 4U; i++) {
176 mldsa_small_basemul(&tmp->coeffs[4U * i],
179 mldsa_small_zetas[64U + i]);
180 mldsa_small_basemul(&tmp->coeffs[4U * i + 2U],
181 &a->coeffs[4U * i + 2U],
182 &b->coeffs[4U * i + 2U],
183 (int16_t) (-mldsa_small_zetas[64U + i]));
187 MLDSA_SMALLPOLY_invntt_tomont(tmp->coeffs);
190 for (int32_t j = (int32_t)
MLDSA_N - 1; j >= 0; j--) {
191 r->
coeffs[j] = (int32_t) tmp->coeffs[j];
195void MLDSA_SMALLPOLY_unpack_eta(mldsa_smallpoly *r,
const uint8_t *a, uint8_t eta)
198 for (uint32_t i = 0U; i <
MLDSA_N / 8U; i++) {
199 r->coeffs[8U * i + 0U] = (int16_t) ((a[3U * i + 0U] >> 0U) & 7U);
200 r->coeffs[8U * i + 1U] = (int16_t) ((a[3U * i + 0U] >> 3U) & 7U);
201 r->coeffs[8U * i + 2U]
202 = (int16_t) (((a[3U * i + 0U] >> 6U) | (a[3U * i + 1U] << 2U)) & 7U);
203 r->coeffs[8U * i + 3U] = (int16_t) ((a[3U * i + 1U] >> 1U) & 7U);
204 r->coeffs[8U * i + 4U] = (int16_t) ((a[3U * i + 1U] >> 4U) & 7U);
205 r->coeffs[8U * i + 5U]
206 = (int16_t) (((a[3U * i + 1U] >> 7U) | (a[3U * i + 2U] << 1U)) & 7U);
207 r->coeffs[8U * i + 6U] = (int16_t) ((a[3U * i + 2U] >> 2U) & 7U);
208 r->coeffs[8U * i + 7U] = (int16_t) ((a[3U * i + 2U] >> 5U) & 7U);
210 r->coeffs[8U * i + 0U] = (int16_t) eta - r->coeffs[8U * i + 0U];
211 r->coeffs[8U * i + 1U] = (int16_t) eta - r->coeffs[8U * i + 1U];
212 r->coeffs[8U * i + 2U] = (int16_t) eta - r->coeffs[8U * i + 2U];
213 r->coeffs[8U * i + 3U] = (int16_t) eta - r->coeffs[8U * i + 3U];
214 r->coeffs[8U * i + 4U] = (int16_t) eta - r->coeffs[8U * i + 4U];
215 r->coeffs[8U * i + 5U] = (int16_t) eta - r->coeffs[8U * i + 5U];
216 r->coeffs[8U * i + 6U] = (int16_t) eta - r->coeffs[8U * i + 6U];
217 r->coeffs[8U * i + 7U] = (int16_t) eta - r->coeffs[8U * i + 7U];
222 for (uint32_t i = 0U; i <
MLDSA_N / 2U; i++) {
223 r->coeffs[2U * i + 0U] = (int16_t) (a[i] & 0x0FU);
224 r->coeffs[2U * i + 1U] = (int16_t) (a[i] >> 4U);
225 r->coeffs[2U * i + 0U] = (int16_t) eta - r->coeffs[2U * i + 0U];
226 r->coeffs[2U * i + 1U] = (int16_t) eta - r->coeffs[2U * i + 1U];
ML-DSA small polynomial type and NTT mod 3329 (low-RAM optimization).
Polynomial with MLDSA_N int32_t coefficients.