// File: ushitora-anqou[P]aqtfhe2/./aqtfhe2.hpp
// Function: aqtfhe2::detail::fft_processor<1024ul>::ifft(aqtfhe2::detail::array_slice<double, 1024ul>)
void ifft(array_slice<double, N> out)
    {
        constexpr size_t n = N * 2, ns4 = n / 4;
        double tmp0[4], tmp1[4], tmp2[4], tmp3[4];
        auto itre = out.begin(), itim = out.begin() + ns4;

        // multiply by omb^j
        for (size_t j = 0; j < ns4; j += 4) {
            auto r0 = tables_reverse_.cbegin() + 2 * j;
            auto r1 = r0 + 4;
            //(re*cos-im*sin) + i (im*cos+re*sin)
            auto d0 = itre + j;
            auto d1 = itim + j;

            dotp4(tmp0, d0, r0);  // re*cos
            dotp4(tmp1, d1, r0);  // im*cos
            dotp4(tmp2, d0, r1);  // re*sin
            dotp4(tmp3, d1, r1);  // im*sin
            sub4(d0, tmp0, tmp3);
            add4(d1, tmp1, tmp2);
        }

        // at the beginning of iteration nn
        // a_{j,i} has P_{i%nn}(omega^j)
        // where j between [rev(1) and rev(3)[
        // and i between [0 and nn[
        auto cur_tt = tables_reverse_.cbegin();
        for (size_t nn = ns4; nn >= 8; nn /= 2) {
            size_t halfnn = nn / 2;
            cur_tt += 2 * nn;
            for (size_t block = 0; block < ns4; block += nn) {
                for (size_t off = 0; off < halfnn; off += 4) {
                    auto d00 = itre + block + off;
                    auto d01 = itim + block + off;
                    auto d10 = itre + block + halfnn + off;
                    auto d11 = itim + block + halfnn + off;
                    add4(tmp0, d00, d10);  // re + re
                    add4(tmp1, d01, d11);  // im + im
                    sub4(tmp2, d00, d10);  // re - re
                    sub4(tmp3, d01, d11);  // im - im
                    copy4(d00, tmp0);
                    copy4(d01, tmp1);
                    auto r0 = cur_tt + 2 * off;
                    auto r1 = r0 + 4;
                    dotp4(tmp0, tmp2, r0);  // re*cos
                    dotp4(tmp1, tmp3, r1);  // im*sin
                    sub4(d10, tmp0, tmp1);
                    dotp4(tmp0, tmp2, r1);  // re*sin
                    dotp4(tmp1, tmp3, r0);  // im*cos
                    add4(d11, tmp0, tmp1);
                }
            }
        }

        // size 4
        for (size_t block = 0; block < ns4; block += 4) {
            auto re = itre + block;
            auto im = itim + block;

            tmp0[0] = re[0] + re[2];
            tmp0[1] = re[1] + re[3];
            tmp0[2] = re[0] - re[2];
            tmp0[3] = im[3] - im[1];

            tmp1[0] = im[0] + im[2];
            tmp1[1] = im[1] + im[3];
            tmp1[2] = im[0] + -im[2];
            tmp1[3] = re[1] + -re[3];

            copy4(re, tmp0);
            copy4(im, tmp1);
        }

        // size 2
        for (size_t block = 0; block < ns4; block += 4) {
            auto re = itre + block;
            auto im = itim + block;

            tmp0[0] = re[0] + re[1];
            tmp0[1] = re[0] - re[1];
            tmp0[2] = re[2] + re[3];
            tmp0[3] = re[2] - re[3];
            copy4(re, tmp0);

            tmp1[0] = im[0] + im[1];
            tmp1[1] = im[0] - im[1];
            tmp1[2] = im[2] + im[3];
            tmp1[3] = im[2] - im[3];
            copy4(im, tmp1);
        }
    }

// Assembly:
subq $0x178, %rsp            # imm = 0x178
movq %rsi, 0x170(%rsp)
movq %rdi, 0x168(%rsp)
movq 0x168(%rsp), %rax
movq %rax, 0x8(%rsp)
movq $0x800, 0x160(%rsp) # imm = 0x800
movq $0x200, 0x158(%rsp) # imm = 0x200
leaq 0x170(%rsp), %rdi
callq 0x9900
movq %rax, 0xc8(%rsp)
leaq 0x170(%rsp), %rdi
callq 0x9900
addq $0x1000, %rax           # imm = 0x1000
movq %rax, 0xc0(%rsp)
movq $0x0, 0xb8(%rsp)
cmpq $0x200, 0xb8(%rsp) # imm = 0x200
jae 0xa09e
movq 0x8(%rsp), %rdi
addq $0x4000, %rdi           # imm = 0x4000
callq 0x9960
movq 0xb8(%rsp), %rcx
shlq %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, 0xb0(%rsp)
movq 0xb0(%rsp), %rax
addq $0x20, %rax
movq %rax, 0xa8(%rsp)
movq 0xc8(%rsp), %rax
movq 0xb8(%rsp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, 0xa0(%rsp)
movq 0xc0(%rsp), %rax
movq 0xb8(%rsp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, 0x98(%rsp)
leaq 0x130(%rsp), %rdi
movq 0xa0(%rsp), %rsi
movq 0xb0(%rsp), %rdx
callq 0x9970
leaq 0x110(%rsp), %rdi
movq 0x98(%rsp), %rsi
movq 0xb0(%rsp), %rdx
callq 0x9970
leaq 0xf0(%rsp), %rdi
movq 0xa0(%rsp), %rsi
movq 0xa8(%rsp), %rdx
callq 0x9970
leaq 0xd0(%rsp), %rdi
movq 0x98(%rsp), %rsi
movq 0xa8(%rsp), %rdx
callq 0x9970
movq 0xa0(%rsp), %rdi
leaq 0x130(%rsp), %rsi
leaq 0xd0(%rsp), %rdx
callq 0x99d0
movq 0x98(%rsp), %rdi
leaq 0x110(%rsp), %rsi
leaq 0xf0(%rsp), %rdx
callq 0x9a30
movq 0xb8(%rsp), %rax
addq $0x4, %rax
movq %rax, 0xb8(%rsp)
jmp 0x9f48
movq 0x8(%rsp), %rdi
addq $0x4000, %rdi           # imm = 0x4000
callq 0x9960
movq %rax, 0x90(%rsp)
movq $0x200, 0x88(%rsp) # imm = 0x200
cmpq $0x8, 0x88(%rsp)
jb 0xa376
movq 0x88(%rsp), %rax
shrq %rax
movq %rax, 0x80(%rsp)
movq 0x88(%rsp), %rax
shlq %rax
shlq $0x3, %rax
addq 0x90(%rsp), %rax
movq %rax, 0x90(%rsp)
movq $0x0, 0x78(%rsp)
cmpq $0x200, 0x78(%rsp)      # imm = 0x200
jae 0xa35c
movq $0x0, 0x70(%rsp)
movq 0x70(%rsp), %rax
cmpq 0x80(%rsp), %rax
jae 0xa343
movq 0xc8(%rsp), %rax
movq 0x78(%rsp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq 0x70(%rsp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, 0x68(%rsp)
movq 0xc0(%rsp), %rax
movq 0x78(%rsp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq 0x70(%rsp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, 0x60(%rsp)
movq 0xc8(%rsp), %rax
movq 0x78(%rsp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq 0x80(%rsp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq 0x70(%rsp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, 0x58(%rsp)
movq 0xc0(%rsp), %rax
movq 0x78(%rsp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq 0x80(%rsp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq 0x70(%rsp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, 0x50(%rsp)
leaq 0x130(%rsp), %rdi
movq 0x68(%rsp), %rsi
movq 0x58(%rsp), %rdx
callq 0x9a30
leaq 0x110(%rsp), %rdi
movq 0x60(%rsp), %rsi
movq 0x50(%rsp), %rdx
callq 0x9a30
leaq 0xf0(%rsp), %rdi
movq 0x68(%rsp), %rsi
movq 0x58(%rsp), %rdx
callq 0x99d0
leaq 0xd0(%rsp), %rdi
movq 0x60(%rsp), %rsi
movq 0x50(%rsp), %rdx
callq 0x99d0
movq 0x68(%rsp), %rdi
leaq 0x130(%rsp), %rsi
callq 0x9910
movq 0x60(%rsp), %rdi
leaq 0x110(%rsp), %rsi
callq 0x9910
movq 0x90(%rsp), %rax
movq 0x70(%rsp), %rcx
shlq %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, 0x48(%rsp)
movq 0x48(%rsp), %rax
addq $0x20, %rax
movq %rax, 0x40(%rsp)
leaq 0x130(%rsp), %rdi
leaq 0xf0(%rsp), %rsi
movq 0x48(%rsp), %rdx
callq 0x9970
leaq 0x110(%rsp), %rdi
leaq 0xd0(%rsp), %rsi
movq 0x40(%rsp), %rdx
callq 0x9970
movq 0x58(%rsp), %rdi
leaq 0x130(%rsp), %rsi
leaq 0x110(%rsp), %rdx
callq 0x99d0
leaq 0x130(%rsp), %rdi
leaq 0xf0(%rsp), %rsi
movq 0x40(%rsp), %rdx
callq 0x9970
leaq 0x110(%rsp), %rdi
leaq 0xd0(%rsp), %rsi
movq 0x48(%rsp), %rdx
callq 0x9970
movq 0x50(%rsp), %rdi
leaq 0x130(%rsp), %rsi
leaq 0x110(%rsp), %rdx
callq 0x9a30
movq 0x70(%rsp), %rax
addq $0x4, %rax
movq %rax, 0x70(%rsp)
jmp 0xa125
jmp 0xa345
movq 0x88(%rsp), %rax
addq 0x78(%rsp), %rax
movq %rax, 0x78(%rsp)
jmp 0xa10d
jmp 0xa35e
movq 0x88(%rsp), %rax
shrq %rax
movq %rax, 0x88(%rsp)
jmp 0xa0c3
movq $0x0, 0x38(%rsp)
cmpq $0x200, 0x38(%rsp)      # imm = 0x200
jae 0xa511
movq 0xc8(%rsp), %rax
movq 0x38(%rsp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, 0x30(%rsp)
movq 0xc0(%rsp), %rax
movq 0x38(%rsp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, 0x28(%rsp)
movq 0x30(%rsp), %rax
vmovsd (%rax), %xmm0
movq 0x30(%rsp), %rax
vaddsd 0x10(%rax), %xmm0, %xmm0
vmovsd %xmm0, 0x130(%rsp)
movq 0x30(%rsp), %rax
vmovsd 0x8(%rax), %xmm0
movq 0x30(%rsp), %rax
vaddsd 0x18(%rax), %xmm0, %xmm0
vmovsd %xmm0, 0x138(%rsp)
movq 0x30(%rsp), %rax
vmovsd (%rax), %xmm0
movq 0x30(%rsp), %rax
vsubsd 0x10(%rax), %xmm0, %xmm0
vmovsd %xmm0, 0x140(%rsp)
movq 0x28(%rsp), %rax
vmovsd 0x18(%rax), %xmm0
movq 0x28(%rsp), %rax
vsubsd 0x8(%rax), %xmm0, %xmm0
vmovsd %xmm0, 0x148(%rsp)
movq 0x28(%rsp), %rax
vmovsd (%rax), %xmm0
movq 0x28(%rsp), %rax
vaddsd 0x10(%rax), %xmm0, %xmm0
vmovsd %xmm0, 0x110(%rsp)
movq 0x28(%rsp), %rax
vmovsd 0x8(%rax), %xmm0
movq 0x28(%rsp), %rax
vaddsd 0x18(%rax), %xmm0, %xmm0
vmovsd %xmm0, 0x118(%rsp)
movq 0x28(%rsp), %rax
vmovsd (%rax), %xmm0
movq 0x28(%rsp), %rax
vmovsd 0x10(%rax), %xmm1
vmovq %xmm1, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
vmovq %rax, %xmm1
vaddsd %xmm1, %xmm0, %xmm0
vmovsd %xmm0, 0x120(%rsp)
movq 0x30(%rsp), %rax
vmovsd 0x8(%rax), %xmm0
movq 0x30(%rsp), %rax
vmovsd 0x18(%rax), %xmm1
vmovq %xmm1, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
vmovq %rax, %xmm1
vaddsd %xmm1, %xmm0, %xmm0
vmovsd %xmm0, 0x128(%rsp)
movq 0x30(%rsp), %rdi
leaq 0x130(%rsp), %rsi
callq 0x9910
movq 0x28(%rsp), %rdi
leaq 0x110(%rsp), %rsi
callq 0x9910
movq 0x38(%rsp), %rax
addq $0x4, %rax
movq %rax, 0x38(%rsp)
jmp 0xa37f
movq $0x0, 0x20(%rsp)
cmpq $0x200, 0x20(%rsp)      # imm = 0x200
jae 0xa676
movq 0xc8(%rsp), %rax
movq 0x20(%rsp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, 0x18(%rsp)
movq 0xc0(%rsp), %rax
movq 0x20(%rsp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, 0x10(%rsp)
movq 0x18(%rsp), %rax
vmovsd (%rax), %xmm0
movq 0x18(%rsp), %rax
vaddsd 0x8(%rax), %xmm0, %xmm0
vmovsd %xmm0, 0x130(%rsp)
movq 0x18(%rsp), %rax
vmovsd (%rax), %xmm0
movq 0x18(%rsp), %rax
vsubsd 0x8(%rax), %xmm0, %xmm0
vmovsd %xmm0, 0x138(%rsp)
movq 0x18(%rsp), %rax
vmovsd 0x10(%rax), %xmm0
movq 0x18(%rsp), %rax
vaddsd 0x18(%rax), %xmm0, %xmm0
vmovsd %xmm0, 0x140(%rsp)
movq 0x18(%rsp), %rax
vmovsd 0x10(%rax), %xmm0
movq 0x18(%rsp), %rax
vsubsd 0x18(%rax), %xmm0, %xmm0
vmovsd %xmm0, 0x148(%rsp)
movq 0x18(%rsp), %rdi
leaq 0x130(%rsp), %rsi
callq 0x9910
movq 0x10(%rsp), %rax
vmovsd (%rax), %xmm0
movq 0x10(%rsp), %rax
vaddsd 0x8(%rax), %xmm0, %xmm0
vmovsd %xmm0, 0x110(%rsp)
movq 0x10(%rsp), %rax
vmovsd (%rax), %xmm0
movq 0x10(%rsp), %rax
vsubsd 0x8(%rax), %xmm0, %xmm0
vmovsd %xmm0, 0x118(%rsp)
movq 0x10(%rsp), %rax
vmovsd 0x10(%rax), %xmm0
movq 0x10(%rsp), %rax
vaddsd 0x18(%rax), %xmm0, %xmm0
vmovsd %xmm0, 0x120(%rsp)
movq 0x10(%rsp), %rax
vmovsd 0x10(%rax), %xmm0
movq 0x10(%rsp), %rax
vsubsd 0x18(%rax), %xmm0, %xmm0
vmovsd %xmm0, 0x128(%rsp)
movq 0x10(%rsp), %rdi
leaq 0x110(%rsp), %rsi
callq 0x9910
movq 0x20(%rsp), %rax
addq $0x4, %rax
movq %rax, 0x20(%rsp)
jmp 0xa51a
addq $0x178, %rsp            # imm = 0x178
retq
nop