#include "inner.h"
#include "macrof.h"
#include "macrofx4.h"
void PQCLEAN_FALCON1024_AARCH64_poly_add(fpr *c, const fpr *restrict a,
const fpr *restrict b, unsigned logn) {
float64x2x4_t neon_a, neon_b, neon_c;
float64x2x2_t neon_a2, neon_b2, neon_c2;
const unsigned falcon_n = 1 << logn;
switch (logn) {
case 1:
vload(neon_a.val[0], &a[0]);
vload(neon_b.val[0], &b[0]);
vfadd(neon_c.val[0], neon_a.val[0], neon_b.val[0]);
vstore(&c[0], neon_c.val[0]);
break;
case 2:
vloadx2(neon_a2, &a[0]);
vloadx2(neon_b2, &b[0]);
vfadd(neon_c2.val[0], neon_a2.val[0], neon_b2.val[0]);
vfadd(neon_c2.val[1], neon_a2.val[1], neon_b2.val[1]);
vstorex2(&c[0], neon_c2);
break;
default:
for (unsigned i = 0; i < falcon_n; i += 8) {
vloadx4(neon_a, &a[i]);
vloadx4(neon_b, &b[i]);
vfaddx4(neon_c, neon_a, neon_b);
vstorex4(&c[i], neon_c);
}
break;
}
}
void PQCLEAN_FALCON1024_AARCH64_poly_sub(fpr *c, const fpr *restrict a,
const fpr *restrict b, unsigned logn) {
float64x2x4_t neon_a, neon_b, neon_c;
float64x2x2_t neon_a2, neon_b2, neon_c2;
const unsigned falcon_n = 1 << logn;
switch (logn) {
case 1:
vload(neon_a.val[0], &a[0]);
vload(neon_b.val[0], &b[0]);
vfsub(neon_c.val[0], neon_a.val[0], neon_b.val[0]);
vstore(&c[0], neon_c.val[0]);
break;
case 2:
vloadx2(neon_a2, &a[0]);
vloadx2(neon_b2, &b[0]);
vfsub(neon_c2.val[0], neon_a2.val[0], neon_b2.val[0]);
vfsub(neon_c2.val[1], neon_a2.val[1], neon_b2.val[1]);
vstorex2(&c[0], neon_c2);
break;
default:
for (unsigned i = 0; i < falcon_n; i += 8) {
vloadx4(neon_a, &a[i]);
vloadx4(neon_b, &b[i]);
vfsubx4(neon_c, neon_a, neon_b);
vstorex4(&c[i], neon_c);
}
break;
}
}
void PQCLEAN_FALCON1024_AARCH64_poly_neg(fpr *c, const fpr *restrict a,
unsigned logn) {
float64x2x4_t neon_a, neon_c;
float64x2x2_t neon_a2, neon_c2;
const unsigned falcon_n = 1 << logn;
switch (logn) {
case 1:
vload(neon_a.val[0], &a[0]);
vfneg(neon_c.val[0], neon_a.val[0]);
vstore(&c[0], neon_c.val[0]);
break;
case 2:
vloadx2(neon_a2, &a[0]);
vfneg(neon_c2.val[0], neon_a2.val[0]);
vfneg(neon_c2.val[1], neon_a2.val[1]);
vstorex2(&c[0], neon_c2);
break;
default:
for (unsigned i = 0; i < falcon_n; i += 8) {
vloadx4(neon_a, &a[i]);
vfnegx4(neon_c, neon_a);
vstorex4(&c[i], neon_c);
}
break;
}
}
void PQCLEAN_FALCON1024_AARCH64_poly_adj_fft(fpr *c, const fpr *restrict a,
unsigned logn) {
float64x2x4_t neon_a, neon_c;
float64x2x2_t neon_a2, neon_c2;
const unsigned falcon_n = 1 << logn;
const unsigned hn = falcon_n >> 1;
switch (logn) {
case 1:
c[1] = fpr_neg(a[1]);
break;
case 2:
vload(neon_a.val[0], &a[2]);
vfneg(neon_c.val[0], neon_a.val[0]);
vstore(&c[2], neon_c.val[0]);
break;
case 3:
vloadx2(neon_a2, &a[4]);
vfneg(neon_c2.val[0], neon_a2.val[0]);
vfneg(neon_c2.val[1], neon_a2.val[1]);
vstorex2(&c[4], neon_c2);
break;
default:
for (unsigned i = hn; i < falcon_n; i += 8) {
vloadx4(neon_a, &a[i]);
vfnegx4(neon_c, neon_a);
vstorex4(&c[i], neon_c);
}
break;
}
}
static inline void PQCLEAN_FALCON1024_AARCH64_poly_mul_fft_log1(
fpr *restrict c, const fpr *restrict a, const fpr *restrict b) {
fpr a_re, a_im, b_re, b_im, c_re, c_im;
a_re = a[0];
a_im = a[1];
b_re = b[0];
b_im = b[1];
c_re = a_re * b_re - a_im * b_im;
c_im = a_re * b_im + a_im * b_re;
c[0] = c_re;
c[1] = c_im;
}
static inline void PQCLEAN_FALCON1024_AARCH64_poly_mul_fft_log2(
fpr *restrict c, const fpr *restrict a, const fpr *restrict b) {
float64x2x2_t neon_a, neon_b, neon_c;
float64x2_t a_re, a_im, b_re, b_im, c_re, c_im;
vloadx2(neon_a, &a[0]);
vloadx2(neon_b, &b[0]);
a_re = neon_a.val[0];
a_im = neon_a.val[1];
b_re = neon_b.val[0];
b_im = neon_b.val[1];
FPC_MUL(c_re, c_im, a_re, a_im, b_re, b_im);
neon_c.val[0] = c_re;
neon_c.val[1] = c_im;
vstorex2(&c[0], neon_c);
}
static inline void PQCLEAN_FALCON1024_AARCH64_poly_mul_fft_log3(
fpr *restrict c, const fpr *restrict a, const fpr *restrict b) {
float64x2x4_t neon_a, neon_b, neon_c;
float64x2x2_t a_re, a_im, b_re, b_im, c_re, c_im;
vloadx4(neon_a, &a[0]);
vloadx4(neon_b, &b[0]);
a_re.val[0] = neon_a.val[0];
a_re.val[1] = neon_a.val[1];
a_im.val[0] = neon_a.val[2];
a_im.val[1] = neon_a.val[3];
b_re.val[0] = neon_b.val[0];
b_re.val[1] = neon_b.val[1];
b_im.val[0] = neon_b.val[2];
b_im.val[1] = neon_b.val[3];
FPC_MULx2(c_re, c_im, a_re, a_im, b_re, b_im);
neon_c.val[0] = c_re.val[0];
neon_c.val[1] = c_re.val[1];
neon_c.val[2] = c_im.val[0];
neon_c.val[3] = c_im.val[1];
vstorex4(&c[0], neon_c);
}
void PQCLEAN_FALCON1024_AARCH64_poly_mul_fft(fpr *c, const fpr *a,
const fpr *restrict b,
unsigned logn) {
float64x2x4_t a_re, b_re, a_im, b_im; float64x2x4_t c_re, c_im; const unsigned falcon_n = 1 << logn;
const unsigned hn = falcon_n >> 1;
switch (logn) {
case 1:
PQCLEAN_FALCON1024_AARCH64_poly_mul_fft_log1(c, a, b);
break;
case 2:
PQCLEAN_FALCON1024_AARCH64_poly_mul_fft_log2(c, a, b);
break;
case 3:
PQCLEAN_FALCON1024_AARCH64_poly_mul_fft_log3(c, a, b);
break;
default:
for (unsigned i = 0; i < hn; i += 8) {
vloadx4(a_re, &a[i]);
vloadx4(a_im, &a[i + hn]);
vloadx4(b_re, &b[i]);
vloadx4(b_im, &b[i + hn]);
FPC_MULx4(c_re, c_im, a_re, a_im, b_re, b_im);
vstorex4(&c[i], c_re);
vstorex4(&c[i + hn], c_im);
}
break;
}
}
static inline void PQCLEAN_FALCON1024_AARCH64_poly_mul_fft_add_log1(
fpr *restrict c, const fpr *restrict d, const fpr *restrict a,
const fpr *restrict b) {
fpr a_re, a_im, b_re, b_im, c_re, c_im, d_re, d_im;
a_re = a[0];
a_im = a[1];
b_re = b[0];
b_im = b[1];
d_re = d[0];
d_im = d[1];
c_re = a_re * b_re - a_im * b_im;
c_im = a_re * b_im + a_im * b_re;
c[0] = c_re + d_re;
c[1] = c_im + d_im;
}
static inline void PQCLEAN_FALCON1024_AARCH64_poly_mul_fft_add_log2(
fpr *restrict c, const fpr *restrict d, const fpr *restrict a,
const fpr *restrict b) {
float64x2x2_t neon_a, neon_b, neon_d;
float64x2_t a_re, a_im, b_re, b_im, d_re, d_im;
vloadx2(neon_a, &a[0]);
vloadx2(neon_b, &b[0]);
vloadx2(neon_d, &d[0]);
a_re = neon_a.val[0];
a_im = neon_a.val[1];
b_re = neon_b.val[0];
b_im = neon_b.val[1];
d_re = neon_d.val[0];
d_im = neon_d.val[1];
FPC_MLA(d_re, d_im, a_re, a_im, b_re, b_im);
neon_d.val[0] = d_re;
neon_d.val[1] = d_im;
vstorex2(&c[0], neon_d);
}
static inline void PQCLEAN_FALCON1024_AARCH64_poly_mul_fft_add_log3(
fpr *restrict c, const fpr *restrict d, const fpr *restrict a,
const fpr *restrict b) {
float64x2x4_t neon_a, neon_b, neon_d;
float64x2x2_t a_re, a_im, b_re, b_im, d_re, d_im;
vloadx4(neon_a, &a[0]);
vloadx4(neon_b, &b[0]);
vloadx4(neon_d, &d[0]);
a_re.val[0] = neon_a.val[0];
a_re.val[1] = neon_a.val[1];
a_im.val[0] = neon_a.val[2];
a_im.val[1] = neon_a.val[3];
b_re.val[0] = neon_b.val[0];
b_re.val[1] = neon_b.val[1];
b_im.val[0] = neon_b.val[2];
b_im.val[1] = neon_b.val[3];
d_re.val[0] = neon_d.val[0];
d_re.val[1] = neon_d.val[1];
d_im.val[0] = neon_d.val[2];
d_im.val[1] = neon_d.val[3];
FPC_MLAx2(d_re, d_im, a_re, a_im, b_re, b_im);
neon_d.val[0] = d_re.val[0];
neon_d.val[1] = d_re.val[1];
neon_d.val[2] = d_im.val[0];
neon_d.val[3] = d_im.val[1];
vstorex4(&c[0], neon_d);
}
void PQCLEAN_FALCON1024_AARCH64_poly_mul_add_fft(fpr *c, const fpr *restrict d,
const fpr *a,
const fpr *restrict b,
unsigned logn) {
float64x2x4_t a_re, b_re, a_im, b_im, d_re, d_im; const unsigned falcon_n = 1 << logn;
const unsigned hn = falcon_n >> 1;
switch (logn) {
case 1:
PQCLEAN_FALCON1024_AARCH64_poly_mul_fft_add_log1(c, d, a, b);
break;
case 2:
PQCLEAN_FALCON1024_AARCH64_poly_mul_fft_add_log2(c, d, a, b);
break;
case 3:
PQCLEAN_FALCON1024_AARCH64_poly_mul_fft_add_log3(c, d, a, b);
break;
default:
for (unsigned i = 0; i < hn; i += 8) {
vloadx4(a_re, &a[i]);
vloadx4(a_im, &a[i + hn]);
vloadx4(b_re, &b[i]);
vloadx4(b_im, &b[i + hn]);
vloadx4(d_re, &d[i]);
vloadx4(d_im, &d[i + hn]);
FPC_MLAx4(d_re, d_im, a_re, a_im, b_re, b_im);
vstorex4(&c[i], d_re);
vstorex4(&c[i + hn], d_im);
}
break;
}
}
void PQCLEAN_FALCON1024_AARCH64_poly_muladj_fft(fpr *d, fpr *a,
const fpr *restrict b,
unsigned logn) {
float64x2x4_t a_re, b_re, d_re, a_im, b_im, d_im; const unsigned falcon_n = 1 << logn;
const unsigned hn = falcon_n >> 1;
for (unsigned i = 0; i < hn; i += 8) {
vloadx4(a_re, &a[i]);
vloadx4(a_im, &a[i + hn]);
vloadx4(b_re, &b[i]);
vloadx4(b_im, &b[i + hn]);
FPC_MUL_CONJx4(d_re, d_im, a_re, a_im, b_re, b_im);
vstorex4(&d[i], d_re);
vstorex4(&d[i + hn], d_im);
}
}
void PQCLEAN_FALCON1024_AARCH64_poly_muladj_add_fft(fpr *c, fpr *d, const fpr *a,
const fpr *restrict b,
unsigned logn) {
float64x2x4_t a_re, b_re, d_re, a_im, b_im, d_im; const unsigned falcon_n = 1 << logn;
const unsigned hn = falcon_n >> 1;
for (unsigned i = 0; i < hn; i += 8) {
vloadx4(a_re, &a[i]);
vloadx4(a_im, &a[i + hn]);
vloadx4(b_re, &b[i]);
vloadx4(b_im, &b[i + hn]);
vloadx4(d_re, &d[i]);
vloadx4(d_im, &d[i + hn]);
FPC_MLA_CONJx4(d_re, d_im, a_re, a_im, b_re, b_im);
vstorex4(&c[i], d_re);
vstorex4(&c[i + hn], d_im);
}
}
void PQCLEAN_FALCON1024_AARCH64_poly_mulselfadj_fft(fpr *c,
const fpr *restrict a,
unsigned logn) {
float64x2x4_t a_re, a_im, c_re, c_im; const unsigned falcon_n = 1 << logn;
const unsigned hn = falcon_n >> 1;
vfdupx4(c_im, 0);
for (unsigned i = 0; i < hn; i += 8) {
vloadx4(a_re, &a[i]);
vloadx4(a_im, &a[i + hn]);
vfmul(c_re.val[0], a_re.val[0], a_re.val[0]);
vfmla(c_re.val[0], c_re.val[0], a_im.val[0], a_im.val[0]);
vfmul(c_re.val[1], a_re.val[1], a_re.val[1]);
vfmla(c_re.val[1], c_re.val[1], a_im.val[1], a_im.val[1]);
vfmul(c_re.val[2], a_re.val[2], a_re.val[2]);
vfmla(c_re.val[2], c_re.val[2], a_im.val[2], a_im.val[2]);
vfmul(c_re.val[3], a_re.val[3], a_re.val[3]);
vfmla(c_re.val[3], c_re.val[3], a_im.val[3], a_im.val[3]);
vstorex4(&c[i], c_re);
vstorex4(&c[i + hn], c_im);
}
}
void PQCLEAN_FALCON1024_AARCH64_poly_mulselfadj_add_fft(fpr *c,
const fpr *restrict d,
const fpr *restrict a,
unsigned logn) {
float64x2x4_t a_re, a_im, d_re; const unsigned falcon_n = 1 << logn;
const unsigned hn = falcon_n >> 1;
for (unsigned i = 0; i < hn; i += 8) {
vloadx4(a_re, &a[i]);
vloadx4(a_im, &a[i + hn]);
vloadx4(d_re, &d[i]);
vfmla(d_re.val[0], d_re.val[0], a_re.val[0], a_re.val[0]);
vfmla(d_re.val[0], d_re.val[0], a_im.val[0], a_im.val[0]);
vfmla(d_re.val[1], d_re.val[1], a_re.val[1], a_re.val[1]);
vfmla(d_re.val[1], d_re.val[1], a_im.val[1], a_im.val[1]);
vfmla(d_re.val[2], d_re.val[2], a_re.val[2], a_re.val[2]);
vfmla(d_re.val[2], d_re.val[2], a_im.val[2], a_im.val[2]);
vfmla(d_re.val[3], d_re.val[3], a_re.val[3], a_re.val[3]);
vfmla(d_re.val[3], d_re.val[3], a_im.val[3], a_im.val[3]);
vstorex4(&c[i], d_re);
}
}
void PQCLEAN_FALCON1024_AARCH64_poly_mulconst(fpr *c, const fpr *a, const fpr x,
unsigned logn) {
const unsigned falcon_n = 1 << logn;
float64x2x4_t neon_a, neon_c; float64x2_t neon_x; neon_x = vdupq_n_f64(x);
for (unsigned i = 0; i < falcon_n; i += 8) {
vloadx4(neon_a, &a[i]);
vfmulx4_i(neon_c, neon_a, neon_x);
vstorex4(&c[i], neon_c);
}
}
void PQCLEAN_FALCON1024_AARCH64_poly_div_fft(fpr *restrict c,
const fpr *restrict a,
const fpr *restrict b,
unsigned logn) {
const unsigned falcon_n = 1 << logn;
const unsigned hn = falcon_n >> 1;
float64x2x4_t a_re, a_im, b_re, b_im, c_re, c_im, m;
for (unsigned i = 0; i < hn; i += 8) {
vloadx4(a_re, &a[i]);
vloadx4(a_im, &a[i + hn]);
vloadx4(b_re, &b[i]);
vloadx4(b_im, &b[i + hn]);
vfmulx4(m, b_re, b_re);
vfmlax4(m, m, b_im, b_im);
vfmulx4(c_re, a_re, b_re);
vfmlax4(c_re, c_re, a_im, b_im);
vfinvx4(m, m);
vfmulx4(c_im, a_im, b_re);
vfmlsx4(c_im, c_im, a_re, b_im);
vfmulx4(c_re, c_re, m);
vfmulx4(c_im, c_im, m);
vstorex4(&c[i], c_re);
vstorex4(&c[i + hn], c_im);
}
}
void PQCLEAN_FALCON1024_AARCH64_poly_invnorm2_fft(fpr *restrict d,
const fpr *restrict a,
const fpr *restrict b,
unsigned logn) {
const unsigned falcon_n = 1 << logn;
const unsigned hn = falcon_n >> 1;
float64x2x4_t a_re, a_im, b_re, b_im, c_re;
float64x2x2_t x, y;
float64x2_t z;
switch (logn) {
case 1:
vload(a_re.val[0], &a[0]);
vload(b_re.val[0], &b[0]);
vfmul(a_re.val[0], a_re.val[0], a_re.val[0]);
vfmla(c_re.val[0], a_re.val[0], b_re.val[0], b_re.val[0]);
d[0] = 1.0 / vaddvq_f64(c_re.val[0]);
break;
case 2:
vloadx2(x, &a[0]);
vloadx2(y, &b[0]);
vfmul(z, x.val[0], x.val[0]);
vfmla(z, z, x.val[1], x.val[1]);
vfmla(z, z, y.val[0], y.val[0]);
vfmla(z, z, y.val[1], y.val[1]);
vfinv(z, z);
vstore(&d[0], z);
break;
case 3:
vloadx4(a_re, &a[0]);
vloadx4(b_re, &b[0]);
vfmul(x.val[0], a_re.val[0], a_re.val[0]);
vfmla(x.val[0], x.val[0], b_re.val[0], b_re.val[0]);
vfmla(x.val[0], x.val[0], a_re.val[2], a_re.val[2]);
vfmla(x.val[0], x.val[0], b_re.val[2], b_re.val[2]);
vfinv(x.val[0], x.val[0]);
vfmul(x.val[1], a_re.val[1], a_re.val[1]);
vfmla(x.val[1], x.val[1], b_re.val[1], b_re.val[1]);
vfmla(x.val[1], x.val[1], a_re.val[3], a_re.val[3]);
vfmla(x.val[1], x.val[1], b_re.val[3], b_re.val[3]);
vfinv(x.val[1], x.val[1]);
vstorex2(&d[0], x);
break;
default:
for (unsigned i = 0; i < hn; i += 8) {
vloadx4(a_re, &a[i]);
vloadx4(a_im, &a[i + hn]);
vloadx4(b_re, &b[i]);
vloadx4(b_im, &b[i + hn]);
vfmul(c_re.val[0], a_re.val[0], a_re.val[0]);
vfmla(c_re.val[0], c_re.val[0], a_im.val[0], a_im.val[0]);
vfmla(c_re.val[0], c_re.val[0], b_re.val[0], b_re.val[0]);
vfmla(c_re.val[0], c_re.val[0], b_im.val[0], b_im.val[0]);
vfinv(c_re.val[0], c_re.val[0]);
vfmul(c_re.val[1], a_re.val[1], a_re.val[1]);
vfmla(c_re.val[1], c_re.val[1], a_im.val[1], a_im.val[1]);
vfmla(c_re.val[1], c_re.val[1], b_re.val[1], b_re.val[1]);
vfmla(c_re.val[1], c_re.val[1], b_im.val[1], b_im.val[1]);
vfinv(c_re.val[1], c_re.val[1]);
vfmul(c_re.val[2], a_re.val[2], a_re.val[2]);
vfmla(c_re.val[2], c_re.val[2], a_im.val[2], a_im.val[2]);
vfmla(c_re.val[2], c_re.val[2], b_re.val[2], b_re.val[2]);
vfmla(c_re.val[2], c_re.val[2], b_im.val[2], b_im.val[2]);
vfinv(c_re.val[2], c_re.val[2]);
vfmul(c_re.val[3], a_re.val[3], a_re.val[3]);
vfmla(c_re.val[3], c_re.val[3], a_im.val[3], a_im.val[3]);
vfmla(c_re.val[3], c_re.val[3], b_re.val[3], b_re.val[3]);
vfmla(c_re.val[3], c_re.val[3], b_im.val[3], b_im.val[3]);
vfinv(c_re.val[3], c_re.val[3]);
vstorex4(&d[i], c_re);
}
break;
}
}
void PQCLEAN_FALCON1024_AARCH64_poly_add_muladj_fft(
fpr *restrict d, const fpr *restrict F, const fpr *restrict G,
const fpr *restrict f, const fpr *restrict g, unsigned logn) {
const unsigned falcon_n = 1 << logn;
const unsigned hn = falcon_n >> 1;
float64x2x4_t F_re, F_im, G_re, G_im;
float64x2x4_t f_re, f_im, g_re, g_im;
float64x2x4_t a_re, a_im;
for (unsigned i = 0; i < hn; i += 8) {
vloadx4(F_re, &F[i]);
vloadx4(F_im, &F[i + hn]);
vloadx4(f_re, &f[i]);
vloadx4(f_im, &f[i + hn]);
FPC_MUL_CONJx4(a_re, a_im, F_re, F_im, f_re, f_im);
vloadx4(G_re, &G[i]);
vloadx4(g_re, &g[i]);
vloadx4(G_im, &G[i + hn]);
vloadx4(g_im, &g[i + hn]);
FPC_MLA_CONJx4(a_re, a_im, G_re, G_im, g_re, g_im);
vstorex4(&d[i], a_re);
vstorex4(&d[i + hn], a_im);
}
}
void PQCLEAN_FALCON1024_AARCH64_poly_mul_autoadj_fft(fpr *c, const fpr *a,
const fpr *restrict b,
unsigned logn) {
const unsigned falcon_n = 1 << logn;
const unsigned hn = falcon_n >> 1;
float64x2x4_t a_re, a_im, b_re, c_re, c_im;
float64x2x2_t a_re_im, b_re_im, c_re_im;
switch (logn) {
case 1:
vload(a_re.val[0], &a[0]);
vfmuln(a_re.val[0], a_re.val[0], b[0]);
vstore(&c[0], a_re.val[0]);
break;
case 2:
vload2(a_re_im, &a[0]);
vload(b_re_im.val[0], &b[0]);
vfmul_lane(c_re_im.val[0], a_re_im.val[0], b_re_im.val[0], 0);
vfmul_lane(c_re_im.val[1], a_re_im.val[1], b_re_im.val[0], 1);
vstore2(&c[0], c_re_im);
break;
case 3:
vload4(a_re, &a[0]);
vloadx2(b_re_im, &b[0]);
vfmul_lane(c_re.val[0], a_re.val[0], b_re_im.val[0], 0);
vfmul_lane(c_re.val[1], a_re.val[1], b_re_im.val[0], 1);
vfmul_lane(c_re.val[2], a_re.val[2], b_re_im.val[1], 0);
vfmul_lane(c_re.val[3], a_re.val[3], b_re_im.val[1], 1);
vstore4(&c[0], c_re);
break;
default:
for (unsigned i = 0; i < hn; i += 8) {
vloadx4(a_re, &a[i]);
vloadx4(a_im, &a[i + hn]);
vloadx4(b_re, &b[i]);
vfmulx4(c_re, a_re, b_re);
vfmulx4(c_im, a_im, b_re);
vstorex4(&c[i], c_re);
vstorex4(&c[i + hn], c_im);
}
break;
}
}
void PQCLEAN_FALCON1024_AARCH64_poly_div_autoadj_fft(fpr *c, const fpr *a,
const fpr *restrict b,
unsigned logn) {
const unsigned falcon_n = 1 << logn;
const unsigned hn = falcon_n >> 1;
float64x2x4_t a_re, a_im, b_re, binv, c_re, c_im;
for (unsigned i = 0; i < hn; i += 8) {
vloadx4(b_re, &b[i]);
vfinvx4(binv, b_re);
vloadx4(a_re, &a[i]);
vloadx4(a_im, &a[i + hn]);
vfmulx4(c_re, a_re, binv);
vfmulx4(c_im, a_im, binv);
vstorex4(&c[i], c_re);
vstorex4(&c[i + hn], c_im);
}
}
static inline void PQCLEAN_FALCON1024_AARCH64_poly_LDL_fft_log1(
const fpr *restrict g00, fpr *restrict g01, fpr *restrict g11) {
float64x2x4_t g00_re, g01_re, g11_re;
float64x2x4_t mu_re, m;
float64x2_t neon_1i2;
const fpr imagine[2] = {1.0, -1.0};
vload(g00_re.val[0], &g00[0]);
vfmul(m.val[0], g00_re.val[0], g00_re.val[0]);
m.val[0] = vdupq_n_f64(1 / vaddvq_f64(m.val[0]));
vload(g01_re.val[0], &g01[0]);
vload(neon_1i2, &imagine[0]);
vfmul(g01_re.val[2], g01_re.val[0], g00_re.val[0]);
vswap(g01_re.val[1], g01_re.val[0]);
vfmul(g01_re.val[1], g01_re.val[1], neon_1i2);
vfmul(g01_re.val[1], g01_re.val[1], g00_re.val[0]);
mu_re.val[0] = vpaddq_f64(g01_re.val[2], g01_re.val[1]);
vfmul(mu_re.val[0], mu_re.val[0], m.val[0]);
vfmul(g01_re.val[1], mu_re.val[0], g01_re.val[0]);
vfmul(g01_re.val[2], g01_re.val[0], neon_1i2);
vswap(g01_re.val[2], g01_re.val[2]);
vfmul(g01_re.val[2], g01_re.val[2], mu_re.val[0]);
g01_re.val[0] = vpaddq_f64(g01_re.val[1], g01_re.val[2]);
vload(g11_re.val[0], &g11[0]);
vfsub(g11_re.val[0], g11_re.val[0], g01_re.val[0]);
vfmul(mu_re.val[0], mu_re.val[0], neon_1i2);
vstore(&g11[0], g11_re.val[0]);
vstore(&g01[0], mu_re.val[0]);
}
static inline void PQCLEAN_FALCON1024_AARCH64_poly_LDL_fft_log2(
const fpr *restrict g00, fpr *restrict g01, fpr *restrict g11) {
float64x2x4_t g00_re, g00_im, g01_re, g01_im, g11_re, g11_im;
float64x2x4_t mu_re, mu_im, m, d_re, d_im;
float64x2x2_t tmp;
vloadx2(tmp, &g00[0]);
g00_re.val[0] = tmp.val[0];
g00_im.val[0] = tmp.val[1];
vfmul(m.val[0], g00_re.val[0], g00_re.val[0]);
vfmla(m.val[0], m.val[0], g00_im.val[0], g00_im.val[0]);
vfinv(m.val[0], m.val[0]);
vloadx2(tmp, &g01[0]);
g01_re.val[0] = tmp.val[0];
g01_im.val[0] = tmp.val[1];
vfmul(mu_re.val[0], g01_re.val[0], g00_re.val[0]);
vfmla(mu_re.val[0], mu_re.val[0], g01_im.val[0], g00_im.val[0]);
vfmul(mu_im.val[0], g01_im.val[0], g00_re.val[0]);
vfmls(mu_im.val[0], mu_im.val[0], g01_re.val[0], g00_im.val[0]);
vfmul(mu_re.val[0], mu_re.val[0], m.val[0]);
vfmul(mu_im.val[0], mu_im.val[0], m.val[0]);
vloadx2(tmp, &g11[0]);
g11_re.val[0] = tmp.val[0];
g11_im.val[0] = tmp.val[1];
vfmls(d_re.val[0], g11_re.val[0], mu_re.val[0], g01_re.val[0]);
vfmls(d_re.val[0], d_re.val[0], mu_im.val[0], g01_im.val[0]);
vfmls(d_im.val[0], g11_im.val[0], mu_im.val[0], g01_re.val[0]);
vfmla(d_im.val[0], d_im.val[0], mu_re.val[0], g01_im.val[0]);
tmp.val[0] = d_re.val[0];
tmp.val[1] = d_im.val[0];
vstorex2(&g11[0], tmp);
vfneg(mu_im.val[0], mu_im.val[0]);
tmp.val[0] = mu_re.val[0];
tmp.val[1] = mu_im.val[0];
vstorex2(&g01[0], tmp);
}
static inline void PQCLEAN_FALCON1024_AARCH64_poly_LDL_fft_log3(
const fpr *restrict g00, fpr *restrict g01, fpr *restrict g11) {
float64x2x4_t g00_re, g00_im, g01_re, g01_im, g11_re;
float64x2x4_t mu_re, mu_im, m, d_re;
vloadx4(g00_re, &g00[0]);
g00_im.val[0] = g00_re.val[2];
g00_im.val[1] = g00_re.val[3];
vfmul(m.val[0], g00_re.val[0], g00_re.val[0]);
vfmla(m.val[0], m.val[0], g00_im.val[0], g00_im.val[0]);
vfinv(m.val[0], m.val[0]);
vfmul(m.val[1], g00_re.val[1], g00_re.val[1]);
vfmla(m.val[1], m.val[1], g00_im.val[1], g00_im.val[1]);
vfinv(m.val[1], m.val[1]);
vloadx4(g01_re, &g01[0]);
g01_im.val[0] = g01_re.val[2];
g01_im.val[1] = g01_re.val[3];
vfmul(mu_re.val[0], g01_re.val[0], g00_re.val[0]);
vfmla(mu_re.val[0], mu_re.val[0], g01_im.val[0], g00_im.val[0]);
vfmul(mu_re.val[1], g01_re.val[1], g00_re.val[1]);
vfmla(mu_re.val[1], mu_re.val[1], g01_im.val[1], g00_im.val[1]);
vfmul(mu_im.val[0], g01_im.val[0], g00_re.val[0]);
vfmls(mu_im.val[0], mu_im.val[0], g01_re.val[0], g00_im.val[0]);
vfmul(mu_im.val[1], g01_im.val[1], g00_re.val[1]);
vfmls(mu_im.val[1], mu_im.val[1], g01_re.val[1], g00_im.val[1]);
vfmul(mu_re.val[0], mu_re.val[0], m.val[0]);
vfmul(mu_re.val[1], mu_re.val[1], m.val[1]);
vfmul(mu_im.val[0], mu_im.val[0], m.val[0]);
vfmul(mu_im.val[1], mu_im.val[1], m.val[1]);
vloadx4(g11_re, &g11[0]);
vfmls(d_re.val[0], g11_re.val[0], mu_re.val[0], g01_re.val[0]);
vfmls(d_re.val[0], d_re.val[0], mu_im.val[0], g01_im.val[0]);
vfmls(d_re.val[1], g11_re.val[1], mu_re.val[1], g01_re.val[1]);
vfmls(d_re.val[1], d_re.val[1], mu_im.val[1], g01_im.val[1]);
vfmls(d_re.val[2], g11_re.val[2], mu_im.val[0], g01_re.val[0]);
vfmla(d_re.val[2], d_re.val[2], mu_re.val[0], g01_im.val[0]);
vfmls(d_re.val[3], g11_re.val[3], mu_im.val[1], g01_re.val[1]);
vfmla(d_re.val[3], d_re.val[3], mu_re.val[1], g01_im.val[1]);
vstorex4(&g11[0], d_re);
vfneg(mu_re.val[2], mu_im.val[0]);
vfneg(mu_re.val[3], mu_im.val[1]);
vstorex4(&g01[0], mu_re);
}
void PQCLEAN_FALCON1024_AARCH64_poly_LDL_fft(const fpr *restrict g00,
fpr *restrict g01,
fpr *restrict g11, unsigned logn) {
const unsigned falcon_n = 1 << logn;
const unsigned hn = falcon_n >> 1;
float64x2x4_t g00_re, g00_im, g01_re, g01_im, g11_re, g11_im;
float64x2x4_t mu_re, mu_im, m, d_re, d_im;
switch (logn) {
case 1:
PQCLEAN_FALCON1024_AARCH64_poly_LDL_fft_log1(g00, g01, g11);
break;
case 2:
PQCLEAN_FALCON1024_AARCH64_poly_LDL_fft_log2(g00, g01, g11);
break;
case 3:
PQCLEAN_FALCON1024_AARCH64_poly_LDL_fft_log3(g00, g01, g11);
break;
default:
for (unsigned i = 0; i < hn; i += 8) {
vloadx4(g00_re, &g00[i]);
vloadx4(g00_im, &g00[i + hn]);
vfmul(m.val[0], g00_re.val[0], g00_re.val[0]);
vfmla(m.val[0], m.val[0], g00_im.val[0], g00_im.val[0]);
vfinv(m.val[0], m.val[0]);
vfmul(m.val[1], g00_re.val[1], g00_re.val[1]);
vfmla(m.val[1], m.val[1], g00_im.val[1], g00_im.val[1]);
vfinv(m.val[1], m.val[1]);
vfmul(m.val[2], g00_re.val[2], g00_re.val[2]);
vfmla(m.val[2], m.val[2], g00_im.val[2], g00_im.val[2]);
vfinv(m.val[2], m.val[2]);
vfmul(m.val[3], g00_re.val[3], g00_re.val[3]);
vfmla(m.val[3], m.val[3], g00_im.val[3], g00_im.val[3]);
vfinv(m.val[3], m.val[3]);
vloadx4(g01_re, &g01[i]);
vloadx4(g01_im, &g01[i + hn]);
vfmul(mu_re.val[0], g01_re.val[0], g00_re.val[0]);
vfmla(mu_re.val[0], mu_re.val[0], g01_im.val[0], g00_im.val[0]);
vfmul(mu_re.val[1], g01_re.val[1], g00_re.val[1]);
vfmla(mu_re.val[1], mu_re.val[1], g01_im.val[1], g00_im.val[1]);
vfmul(mu_re.val[2], g01_re.val[2], g00_re.val[2]);
vfmla(mu_re.val[2], mu_re.val[2], g01_im.val[2], g00_im.val[2]);
vfmul(mu_re.val[3], g01_re.val[3], g00_re.val[3]);
vfmla(mu_re.val[3], mu_re.val[3], g01_im.val[3], g00_im.val[3]);
vfmul(mu_im.val[0], g01_im.val[0], g00_re.val[0]);
vfmls(mu_im.val[0], mu_im.val[0], g01_re.val[0], g00_im.val[0]);
vfmul(mu_im.val[1], g01_im.val[1], g00_re.val[1]);
vfmls(mu_im.val[1], mu_im.val[1], g01_re.val[1], g00_im.val[1]);
vfmul(mu_im.val[2], g01_im.val[2], g00_re.val[2]);
vfmls(mu_im.val[2], mu_im.val[2], g01_re.val[2], g00_im.val[2]);
vfmul(mu_im.val[3], g01_im.val[3], g00_re.val[3]);
vfmls(mu_im.val[3], mu_im.val[3], g01_re.val[3], g00_im.val[3]);
vfmulx4(mu_re, mu_re, m);
vfmulx4(mu_im, mu_im, m);
vstorex4(&g01[i], mu_re);
vloadx4(g11_re, &g11[i]);
vloadx4(g11_im, &g11[i + hn]);
vfmls(d_re.val[0], g11_re.val[0], mu_re.val[0], g01_re.val[0]);
vfmls(d_re.val[0], d_re.val[0], mu_im.val[0], g01_im.val[0]);
vfmls(d_re.val[1], g11_re.val[1], mu_re.val[1], g01_re.val[1]);
vfmls(d_re.val[1], d_re.val[1], mu_im.val[1], g01_im.val[1]);
vfmls(d_re.val[2], g11_re.val[2], mu_re.val[2], g01_re.val[2]);
vfmls(d_re.val[2], d_re.val[2], mu_im.val[2], g01_im.val[2]);
vfmls(d_re.val[3], g11_re.val[3], mu_re.val[3], g01_re.val[3]);
vfmls(d_re.val[3], d_re.val[3], mu_im.val[3], g01_im.val[3]);
vstorex4(&g11[i], d_re);
vfmls(d_im.val[0], g11_im.val[0], mu_im.val[0], g01_re.val[0]);
vfmla(d_im.val[0], d_im.val[0], mu_re.val[0], g01_im.val[0]);
vfmls(d_im.val[1], g11_im.val[1], mu_im.val[1], g01_re.val[1]);
vfmla(d_im.val[1], d_im.val[1], mu_re.val[1], g01_im.val[1]);
vfmls(d_im.val[2], g11_im.val[2], mu_im.val[2], g01_re.val[2]);
vfmla(d_im.val[2], d_im.val[2], mu_re.val[2], g01_im.val[2]);
vfmls(d_im.val[3], g11_im.val[3], mu_im.val[3], g01_re.val[3]);
vfmla(d_im.val[3], d_im.val[3], mu_re.val[3], g01_im.val[3]);
vstorex4(&g11[i + hn], d_im);
vfnegx4(mu_im, mu_im);
vstorex4(&g01[i + hn], mu_im);
}
break;
}
}
static inline void PQCLEAN_FALCON1024_AARCH64_poly_LDLmv_fft_log1(
fpr *restrict d11, fpr *restrict l10, const fpr *restrict g00,
const fpr *restrict g01, const fpr *restrict g11) {
float64x2x4_t g00_re, g01_re, g11_re;
float64x2x4_t mu_re, m;
float64x2_t neon_1i2;
const fpr imagine[2] = {1.0, -1.0};
vload(g00_re.val[0], &g00[0]);
vfmul(m.val[0], g00_re.val[0], g00_re.val[0]);
m.val[0] = vdupq_n_f64(1 / vaddvq_f64(m.val[0]));
vload(g01_re.val[0], &g01[0]);
vload(neon_1i2, &imagine[0]);
vfmul(g01_re.val[2], g01_re.val[0], g00_re.val[0]);
vswap(g01_re.val[1], g01_re.val[0]);
vfmul(g01_re.val[1], g01_re.val[1], neon_1i2);
vfmul(g01_re.val[1], g01_re.val[1], g00_re.val[0]);
mu_re.val[0] = vpaddq_f64(g01_re.val[2], g01_re.val[1]);
vfmul(mu_re.val[0], mu_re.val[0], m.val[0]);
vfmul(g01_re.val[1], mu_re.val[0], g01_re.val[0]);
vfmul(g01_re.val[2], g01_re.val[0], neon_1i2);
vswap(g01_re.val[2], g01_re.val[2]);
vfmul(g01_re.val[2], g01_re.val[2], mu_re.val[0]);
g01_re.val[0] = vpaddq_f64(g01_re.val[1], g01_re.val[2]);
vload(g11_re.val[0], &g11[0]);
vfsub(g11_re.val[0], g11_re.val[0], g01_re.val[0]);
vfmul(mu_re.val[0], mu_re.val[0], neon_1i2);
vstore(&d11[0], g11_re.val[0]);
vstore(&l10[0], mu_re.val[0]);
}
static inline void PQCLEAN_FALCON1024_AARCH64_poly_LDLmv_fft_log2(
fpr *restrict d11, fpr *restrict l10, const fpr *restrict g00,
const fpr *restrict g01, const fpr *restrict g11) {
float64x2x4_t g00_re, g00_im, g01_re, g01_im, g11_re, g11_im;
float64x2x4_t mu_re, mu_im, m, d_re, d_im;
float64x2x2_t tmp;
vloadx2(tmp, &g00[0]);
g00_re.val[0] = tmp.val[0];
g00_im.val[0] = tmp.val[1];
vfmul(m.val[0], g00_re.val[0], g00_re.val[0]);
vfmla(m.val[0], m.val[0], g00_im.val[0], g00_im.val[0]);
vfinv(m.val[0], m.val[0]);
vloadx2(tmp, &g01[0]);
g01_re.val[0] = tmp.val[0];
g01_im.val[0] = tmp.val[1];
vfmul(mu_re.val[0], g01_re.val[0], g00_re.val[0]);
vfmla(mu_re.val[0], mu_re.val[0], g01_im.val[0], g00_im.val[0]);
vfmul(mu_im.val[0], g01_im.val[0], g00_re.val[0]);
vfmls(mu_im.val[0], mu_im.val[0], g01_re.val[0], g00_im.val[0]);
vfmul(mu_re.val[0], mu_re.val[0], m.val[0]);
vfmul(mu_im.val[0], mu_im.val[0], m.val[0]);
vloadx2(tmp, &g11[0]);
g11_re.val[0] = tmp.val[0];
g11_im.val[0] = tmp.val[1];
vfmls(d_re.val[0], g11_re.val[0], mu_re.val[0], g01_re.val[0]);
vfmls(d_re.val[0], d_re.val[0], mu_im.val[0], g01_im.val[0]);
vfmls(d_im.val[0], g11_im.val[0], mu_im.val[0], g01_re.val[0]);
vfmla(d_im.val[0], d_im.val[0], mu_re.val[0], g01_im.val[0]);
tmp.val[0] = d_re.val[0];
tmp.val[1] = d_im.val[0];
vstorex2(&d11[0], tmp);
vfneg(mu_im.val[0], mu_im.val[0]);
tmp.val[0] = mu_re.val[0];
tmp.val[1] = mu_im.val[0];
vstorex2(&l10[0], tmp);
}
static inline void PQCLEAN_FALCON1024_AARCH64_poly_LDLmv_fft_log3(
fpr *restrict d11, fpr *restrict l10, const fpr *restrict g00,
const fpr *restrict g01, const fpr *restrict g11) {
float64x2x4_t g00_re, g00_im, g01_re, g01_im, g11_re;
float64x2x4_t mu_re, mu_im, m, d_re;
vloadx4(g00_re, &g00[0]);
g00_im.val[0] = g00_re.val[2];
g00_im.val[1] = g00_re.val[3];
vfmul(m.val[0], g00_re.val[0], g00_re.val[0]);
vfmla(m.val[0], m.val[0], g00_im.val[0], g00_im.val[0]);
vfinv(m.val[0], m.val[0]);
vfmul(m.val[1], g00_re.val[1], g00_re.val[1]);
vfmla(m.val[1], m.val[1], g00_im.val[1], g00_im.val[1]);
vfinv(m.val[1], m.val[1]);
vloadx4(g01_re, &g01[0]);
g01_im.val[0] = g01_re.val[2];
g01_im.val[1] = g01_re.val[3];
vfmul(mu_re.val[0], g01_re.val[0], g00_re.val[0]);
vfmla(mu_re.val[0], mu_re.val[0], g01_im.val[0], g00_im.val[0]);
vfmul(mu_re.val[1], g01_re.val[1], g00_re.val[1]);
vfmla(mu_re.val[1], mu_re.val[1], g01_im.val[1], g00_im.val[1]);
vfmul(mu_im.val[0], g01_im.val[0], g00_re.val[0]);
vfmls(mu_im.val[0], mu_im.val[0], g01_re.val[0], g00_im.val[0]);
vfmul(mu_im.val[1], g01_im.val[1], g00_re.val[1]);
vfmls(mu_im.val[1], mu_im.val[1], g01_re.val[1], g00_im.val[1]);
vfmul(mu_re.val[0], mu_re.val[0], m.val[0]);
vfmul(mu_re.val[1], mu_re.val[1], m.val[1]);
vfmul(mu_im.val[0], mu_im.val[0], m.val[0]);
vfmul(mu_im.val[1], mu_im.val[1], m.val[1]);
vloadx4(g11_re, &g11[0]);
vfmls(d_re.val[0], g11_re.val[0], mu_re.val[0], g01_re.val[0]);
vfmls(d_re.val[0], d_re.val[0], mu_im.val[0], g01_im.val[0]);
vfmls(d_re.val[1], g11_re.val[1], mu_re.val[1], g01_re.val[1]);
vfmls(d_re.val[1], d_re.val[1], mu_im.val[1], g01_im.val[1]);
vfmls(d_re.val[2], g11_re.val[2], mu_im.val[0], g01_re.val[0]);
vfmla(d_re.val[2], d_re.val[2], mu_re.val[0], g01_im.val[0]);
vfmls(d_re.val[3], g11_re.val[3], mu_im.val[1], g01_re.val[1]);
vfmla(d_re.val[3], d_re.val[3], mu_re.val[1], g01_im.val[1]);
vstorex4(&d11[0], d_re);
vfneg(mu_re.val[2], mu_im.val[0]);
vfneg(mu_re.val[3], mu_im.val[1]);
vstorex4(&l10[0], mu_re);
}
void PQCLEAN_FALCON1024_AARCH64_poly_LDLmv_fft(
fpr *restrict d11, fpr *restrict l10, const fpr *restrict g00,
const fpr *restrict g01, const fpr *restrict g11, unsigned logn) {
const unsigned falcon_n = 1 << logn;
const unsigned hn = falcon_n >> 1;
float64x2x4_t g00_re, g00_im, g01_re, g01_im, g11_re, g11_im;
float64x2x4_t mu_re, mu_im, m, d_re, d_im;
switch (logn) {
case 1:
PQCLEAN_FALCON1024_AARCH64_poly_LDLmv_fft_log1(d11, l10, g00, g01, g11);
break;
case 2:
PQCLEAN_FALCON1024_AARCH64_poly_LDLmv_fft_log2(d11, l10, g00, g01, g11);
break;
case 3:
PQCLEAN_FALCON1024_AARCH64_poly_LDLmv_fft_log3(d11, l10, g00, g01, g11);
break;
default:
for (unsigned i = 0; i < hn; i += 8) {
vloadx4(g00_re, &g00[i]);
vloadx4(g00_im, &g00[i + hn]);
vfmul(m.val[0], g00_re.val[0], g00_re.val[0]);
vfmla(m.val[0], m.val[0], g00_im.val[0], g00_im.val[0]);
vfinv(m.val[0], m.val[0]);
vfmul(m.val[1], g00_re.val[1], g00_re.val[1]);
vfmla(m.val[1], m.val[1], g00_im.val[1], g00_im.val[1]);
vfinv(m.val[1], m.val[1]);
vfmul(m.val[2], g00_re.val[2], g00_re.val[2]);
vfmla(m.val[2], m.val[2], g00_im.val[2], g00_im.val[2]);
vfinv(m.val[2], m.val[2]);
vfmul(m.val[3], g00_re.val[3], g00_re.val[3]);
vfmla(m.val[3], m.val[3], g00_im.val[3], g00_im.val[3]);
vfinv(m.val[3], m.val[3]);
vloadx4(g01_re, &g01[i]);
vloadx4(g01_im, &g01[i + hn]);
vfmul(mu_re.val[0], g01_re.val[0], g00_re.val[0]);
vfmla(mu_re.val[0], mu_re.val[0], g01_im.val[0], g00_im.val[0]);
vfmul(mu_re.val[1], g01_re.val[1], g00_re.val[1]);
vfmla(mu_re.val[1], mu_re.val[1], g01_im.val[1], g00_im.val[1]);
vfmul(mu_re.val[2], g01_re.val[2], g00_re.val[2]);
vfmla(mu_re.val[2], mu_re.val[2], g01_im.val[2], g00_im.val[2]);
vfmul(mu_re.val[3], g01_re.val[3], g00_re.val[3]);
vfmla(mu_re.val[3], mu_re.val[3], g01_im.val[3], g00_im.val[3]);
vfmul(mu_im.val[0], g01_im.val[0], g00_re.val[0]);
vfmls(mu_im.val[0], mu_im.val[0], g01_re.val[0], g00_im.val[0]);
vfmul(mu_im.val[1], g01_im.val[1], g00_re.val[1]);
vfmls(mu_im.val[1], mu_im.val[1], g01_re.val[1], g00_im.val[1]);
vfmul(mu_im.val[2], g01_im.val[2], g00_re.val[2]);
vfmls(mu_im.val[2], mu_im.val[2], g01_re.val[2], g00_im.val[2]);
vfmul(mu_im.val[3], g01_im.val[3], g00_re.val[3]);
vfmls(mu_im.val[3], mu_im.val[3], g01_re.val[3], g00_im.val[3]);
vfmulx4(mu_re, mu_re, m);
vfmulx4(mu_im, mu_im, m);
vstorex4(&l10[i], mu_re);
vloadx4(g11_re, &g11[i]);
vloadx4(g11_im, &g11[i + hn]);
vfmls(d_re.val[0], g11_re.val[0], mu_re.val[0], g01_re.val[0]);
vfmls(d_re.val[0], d_re.val[0], mu_im.val[0], g01_im.val[0]);
vfmls(d_re.val[1], g11_re.val[1], mu_re.val[1], g01_re.val[1]);
vfmls(d_re.val[1], d_re.val[1], mu_im.val[1], g01_im.val[1]);
vfmls(d_re.val[2], g11_re.val[2], mu_re.val[2], g01_re.val[2]);
vfmls(d_re.val[2], d_re.val[2], mu_im.val[2], g01_im.val[2]);
vfmls(d_re.val[3], g11_re.val[3], mu_re.val[3], g01_re.val[3]);
vfmls(d_re.val[3], d_re.val[3], mu_im.val[3], g01_im.val[3]);
vstorex4(&d11[i], d_re);
vfmls(d_im.val[0], g11_im.val[0], mu_im.val[0], g01_re.val[0]);
vfmla(d_im.val[0], d_im.val[0], mu_re.val[0], g01_im.val[0]);
vfmls(d_im.val[1], g11_im.val[1], mu_im.val[1], g01_re.val[1]);
vfmla(d_im.val[1], d_im.val[1], mu_re.val[1], g01_im.val[1]);
vfmls(d_im.val[2], g11_im.val[2], mu_im.val[2], g01_re.val[2]);
vfmla(d_im.val[2], d_im.val[2], mu_re.val[2], g01_im.val[2]);
vfmls(d_im.val[3], g11_im.val[3], mu_im.val[3], g01_re.val[3]);
vfmla(d_im.val[3], d_im.val[3], mu_re.val[3], g01_im.val[3]);
vstorex4(&d11[i + hn], d_im);
vfnegx4(mu_im, mu_im);
vstorex4(&l10[i + hn], mu_im);
}
break;
}
}
void PQCLEAN_FALCON1024_AARCH64_poly_fpr_of_s16(fpr *t0, const uint16_t *hm,
const unsigned falcon_n) {
float64x2x4_t neon_t0;
uint16x8x4_t neon_hm;
uint16x8_t neon_zero;
uint32x4x4_t neon_hmu32[2];
int64x2x4_t neon_hms64[4];
neon_zero = vdupq_n_u16(0);
for (unsigned u = 0; u < falcon_n; u += 32) {
neon_hm = vld1q_u16_x4(&hm[u]);
neon_hmu32[0].val[0] = (uint32x4_t)vzip1q_u16(neon_hm.val[0], neon_zero);
neon_hmu32[0].val[1] = (uint32x4_t)vzip2q_u16(neon_hm.val[0], neon_zero);
neon_hmu32[0].val[2] = (uint32x4_t)vzip1q_u16(neon_hm.val[1], neon_zero);
neon_hmu32[0].val[3] = (uint32x4_t)vzip2q_u16(neon_hm.val[1], neon_zero);
neon_hmu32[1].val[0] = (uint32x4_t)vzip1q_u16(neon_hm.val[2], neon_zero);
neon_hmu32[1].val[1] = (uint32x4_t)vzip2q_u16(neon_hm.val[2], neon_zero);
neon_hmu32[1].val[2] = (uint32x4_t)vzip1q_u16(neon_hm.val[3], neon_zero);
neon_hmu32[1].val[3] = (uint32x4_t)vzip2q_u16(neon_hm.val[3], neon_zero);
neon_hms64[0].val[0] =
(int64x2_t)vzip1q_u32(neon_hmu32[0].val[0], (uint32x4_t)neon_zero);
neon_hms64[0].val[1] =
(int64x2_t)vzip2q_u32(neon_hmu32[0].val[0], (uint32x4_t)neon_zero);
neon_hms64[0].val[2] =
(int64x2_t)vzip1q_u32(neon_hmu32[0].val[1], (uint32x4_t)neon_zero);
neon_hms64[0].val[3] =
(int64x2_t)vzip2q_u32(neon_hmu32[0].val[1], (uint32x4_t)neon_zero);
neon_hms64[1].val[0] =
(int64x2_t)vzip1q_u32(neon_hmu32[0].val[2], (uint32x4_t)neon_zero);
neon_hms64[1].val[1] =
(int64x2_t)vzip2q_u32(neon_hmu32[0].val[2], (uint32x4_t)neon_zero);
neon_hms64[1].val[2] =
(int64x2_t)vzip1q_u32(neon_hmu32[0].val[3], (uint32x4_t)neon_zero);
neon_hms64[1].val[3] =
(int64x2_t)vzip2q_u32(neon_hmu32[0].val[3], (uint32x4_t)neon_zero);
neon_hms64[2].val[0] =
(int64x2_t)vzip1q_u32(neon_hmu32[1].val[0], (uint32x4_t)neon_zero);
neon_hms64[2].val[1] =
(int64x2_t)vzip2q_u32(neon_hmu32[1].val[0], (uint32x4_t)neon_zero);
neon_hms64[2].val[2] =
(int64x2_t)vzip1q_u32(neon_hmu32[1].val[1], (uint32x4_t)neon_zero);
neon_hms64[2].val[3] =
(int64x2_t)vzip2q_u32(neon_hmu32[1].val[1], (uint32x4_t)neon_zero);
neon_hms64[3].val[0] =
(int64x2_t)vzip1q_u32(neon_hmu32[1].val[2], (uint32x4_t)neon_zero);
neon_hms64[3].val[1] =
(int64x2_t)vzip2q_u32(neon_hmu32[1].val[2], (uint32x4_t)neon_zero);
neon_hms64[3].val[2] =
(int64x2_t)vzip1q_u32(neon_hmu32[1].val[3], (uint32x4_t)neon_zero);
neon_hms64[3].val[3] =
(int64x2_t)vzip2q_u32(neon_hmu32[1].val[3], (uint32x4_t)neon_zero);
vfcvtx4(neon_t0, neon_hms64[0]);
vstorex4(&t0[u], neon_t0);
vfcvtx4(neon_t0, neon_hms64[1]);
vstorex4(&t0[u + 8], neon_t0);
vfcvtx4(neon_t0, neon_hms64[2]);
vstorex4(&t0[u + 16], neon_t0);
vfcvtx4(neon_t0, neon_hms64[3]);
vstorex4(&t0[u + 24], neon_t0);
}
}
fpr PQCLEAN_FALCON1024_AARCH64_compute_bnorm(const fpr *rt1, const fpr *rt2) {
float64x2x4_t r1, r11, r2, r22;
float64x2x4_t bnorm, bnorm2;
vfdupx4(bnorm, 0);
vfdupx4(bnorm2, 0);
for (unsigned i = 0; i < FALCON_N;) {
vloadx4(r1, &rt1[i]);
i += 8;
vfmla(bnorm.val[0], bnorm.val[0], r1.val[0], r1.val[0]);
vfmla(bnorm.val[1], bnorm.val[1], r1.val[1], r1.val[1]);
vfmla(bnorm.val[2], bnorm.val[2], r1.val[2], r1.val[2]);
vfmla(bnorm.val[3], bnorm.val[3], r1.val[3], r1.val[3]);
vloadx4(r11, &rt1[i]);
i += 8;
vfmla(bnorm2.val[0], bnorm2.val[0], r11.val[0], r11.val[0]);
vfmla(bnorm2.val[1], bnorm2.val[1], r11.val[1], r11.val[1]);
vfmla(bnorm2.val[2], bnorm2.val[2], r11.val[2], r11.val[2]);
vfmla(bnorm2.val[3], bnorm2.val[3], r11.val[3], r11.val[3]);
}
for (unsigned i = 0; i < FALCON_N;) {
vloadx4(r2, &rt2[i]);
i += 8;
vfmla(bnorm.val[0], bnorm.val[0], r2.val[0], r2.val[0]);
vfmla(bnorm.val[1], bnorm.val[1], r2.val[1], r2.val[1]);
vfmla(bnorm.val[2], bnorm.val[2], r2.val[2], r2.val[2]);
vfmla(bnorm.val[3], bnorm.val[3], r2.val[3], r2.val[3]);
vloadx4(r22, &rt2[i]);
i += 8;
vfmla(bnorm2.val[0], bnorm2.val[0], r22.val[0], r22.val[0]);
vfmla(bnorm2.val[1], bnorm2.val[1], r22.val[1], r22.val[1]);
vfmla(bnorm2.val[2], bnorm2.val[2], r22.val[2], r22.val[2]);
vfmla(bnorm2.val[3], bnorm2.val[3], r22.val[3], r22.val[3]);
}
vfadd(bnorm.val[0], bnorm.val[0], bnorm.val[1]);
vfadd(bnorm2.val[0], bnorm2.val[0], bnorm2.val[1]);
vfadd(bnorm.val[2], bnorm.val[2], bnorm.val[3]);
vfadd(bnorm2.val[2], bnorm2.val[2], bnorm2.val[3]);
vfadd(bnorm.val[0], bnorm.val[0], bnorm.val[2]);
vfadd(bnorm2.val[0], bnorm2.val[0], bnorm2.val[2]);
vfadd(bnorm.val[0], bnorm.val[0], bnorm2.val[0]);
return vaddvq_f64(bnorm.val[0]);
}