// File: kernel.cpp
#include "loop_106.h"
#include <stdint.h>

static uint32_t popcount106(uint32_t x) {
    x = (x & 0x55555555u) + ((x >> 1) & 0x55555555u);
    x = (x & 0x33333333u) + ((x >> 2) & 0x33333333u);
    x = (x & 0x0F0F0F0Fu) + ((x >> 4) & 0x0F0F0F0Fu);
    x = (x & 0x00FF00FFu) + ((x >> 8) & 0x00FF00FFu);
    x = (x & 0x0000FFFFu) + ((x >> 16) & 0x0000FFFFu);
    return x;
}
static uint32_t compress106(uint32_t x, uint32_t m) {
    uint32_t mk, mp, mv, t;
    x = x & m;
    mk = ~m << 1;
    for (int i = 0; i < 5; i++) {
        mp = mk ^ (mk << 1);
        mp = mp ^ (mp << 2);
        mp = mp ^ (mp << 4);
        mp = mp ^ (mp << 8);
        mp = mp ^ (mp << 16);
        mv = mp & m;
        m = (m ^ mv) | (mv >> (1 << i));
        t = x & mv;
        x = (x ^ t) | (t >> (1 << i));
        mk = mk & ~mp;
    }
    return x;
}
static uint32_t sag106(uint32_t x, uint32_t m) {
    return (compress106(x, m) << popcount106(m)) | compress106(x, ~m);
}
static uint32_t permute106(uint32_t x, uint32_t p[5]) {
    x = sag106(x, p[0]);
    x = sag106(x, p[1]);
    x = sag106(x, p[2]);
    x = sag106(x, p[3]);
    return sag106(x, p[4]);
}
extern "C" void inner_loop_106(struct loop_106_data *data) {
    uint32_t *a = data->a;
    uint32_t *b = data->b;
    int64_t n = data->n;
    uint32_t permutation[5] = {0xaaaaaaaau, 0xccccccccu, 0x0f0f0f0fu, 0x0ff00ff0u, 0x0ffff000u};
    uint32_t p[5];
    p[0] = permutation[0];
    p[1] = sag106(permutation[1], permutation[0]);
    p[2] = sag106(permutation[2], permutation[0]);
    p[3] = sag106(permutation[3], permutation[0]);
    p[4] = sag106(permutation[4], permutation[0]);
    for (int64_t i = 0; i < n; i++) b[i] = permute106(a[i], p);
}