#include <stdint.h>
#if !defined(RND) || !defined(SH) || !defined(LAST_ADD)
#error "RND, SH and LAST_ADD are given by the build"
#endif
static inline int64_t fx(int32_t e, int32_t a) {
return ((int64_t)e * (int64_t)a + (int64_t)RND) >> SH;
}
static inline void put(int32_t *o, int64_t v) {
uint64_t u = (uint64_t)v;
o[0] = (int32_t)(uint32_t)u;
o[1] = (int32_t)(uint32_t)(u >> 32);
}
extern "C" void wq_line(const int32_t *in, int32_t *out, int32_t n) {
const int32_t mode = in[0];
const int32_t *m = in + 8;
const int32_t *p = in + 16;
if (mode == 1) {
for (int32_t k = 0; k < n; k++) {
const int32_t a = p[4 * k], b = p[4 * k + 1];
put(out + 8 * k + 0, (int64_t)a * (int64_t)b);
put(out + 8 * k + 2, fx(b, a));
put(out + 8 * k + 4, 0);
put(out + 8 * k + 6, 0);
}
return;
}
const int32_t m0 = m[0], m1 = m[1], m2 = m[2], m3 = m[3], m4 = m[4], m5 = m[5], m6 = m[6], m7 = m[7];
for (int32_t k = 0; k < n; k++) {
const int32_t a0r = p[4 * k], a0i = p[4 * k + 1], a1r = p[4 * k + 2], a1i = p[4 * k + 3];
int64_t r0r = fx(m0, a0r) - fx(m1, a0i) + fx(m2, a1r);
r0r = LAST_ADD ? r0r + fx(m3, a1i) : r0r - fx(m3, a1i);
const int64_t r0i = fx(m0, a0i) + fx(m1, a0r) + fx(m2, a1i) + fx(m3, a1r);
const int64_t r1r = fx(m4, a0r) - fx(m5, a0i) + fx(m6, a1r) - fx(m7, a1i);
const int64_t r1i = fx(m4, a0i) + fx(m5, a0r) + fx(m6, a1i) + fx(m7, a1r);
put(out + 8 * k + 0, r0r);
put(out + 8 * k + 2, r0i);
put(out + 8 * k + 4, r1r);
put(out + 8 * k + 6, r1i);
}
}