// File: cloudinary[P]fuif/transform/permute.h
// Function: fwd_permute(Image&, std::vector<int, std::allocator<int>>&)
bool fwd_permute(Image &input, std::vector<int> &parameters) {
    // TODO: implement this without copying stuff
    Image tmp = input;
    if (parameters.size() < 3) {
        e_printf("Invalid permutation: not enough parameters\n");
        return false;
    }
    bool use_channel = true;
    if (parameters[0] == -1) {
        parameters.erase(parameters.begin(), parameters.begin()+1);
        use_channel = false;
    }
    meta_permute(input, parameters, use_channel);
    if (!use_channel) return true;

    assert(input.channel[0].w == input.channel.size() - input.nb_meta_channels);
    if (parameters.size() != input.channel[0].w) {
        e_printf("Invalid permutation: need to specify %i new channels, gave only %i\n",input.channel[0].w,parameters.size());
        return false;
    }
    v_printf(5,"Permutation: ");
    for (int i=0; i<input.channel[0].w; i++) {
        input.channel[0].value(0,i) = parameters[i];
        int c = input.channel[0].value(0,i);
        if (c < 0 || c >= input.channel[0].w) {
            e_printf("Invalid permutation: %i is not a channel number\n",c);
            return false;
        }
        for (int j=0; j<i; j++) if (input.channel[0].value(0,i) == input.channel[0].value(0,j)) {
            e_printf("Invalid permutation: both %i and %i map to channel number %i\n",i,j,input.channel[0].value(0,i));
            return false;
        }
        input.channel[input.nb_meta_channels+c] = tmp.channel[tmp.nb_meta_channels+i];
        v_printf(5,"[%i -> %i] ",i,c);
    }
    v_printf(5,"\n");
    return true;
}

// Assembly:
subq $0x1a8, %rsp            # imm = 0x1A8
movq %rdi, 0x198(%rsp)
movq %rsi, 0x190(%rsp)
movq 0x198(%rsp), %rsi
leaq 0xe0(%rsp), %rdi
callq 0x12880
movq 0x190(%rsp), %rdi
callq 0x4d50
cmpq $0x3, %rax
jae 0x10e9d
leaq 0x36157(%rip), %rdi     # 0x46fad
xorl %eax, %eax
callq 0x3a670
jmp 0x10e5f
movb $0x0, 0x1a7(%rsp)
movl $0x1, 0xd0(%rsp)
jmp 0x11363
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xd8(%rsp)
movl %eax, 0xd4(%rsp)
leaq 0xe0(%rsp), %rdi
callq 0x12ab0
jmp 0x11381
movb $0x1, 0xcf(%rsp)
movq 0x190(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x12190
cmpl $-0x1, (%rax)
jne 0x10f6e
movq 0x190(%rsp), %rdi
movq %rdi, 0x78(%rsp)
callq 0x13780
movq %rax, 0xb8(%rsp)
leaq 0xc0(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
callq 0x137b0
movq 0x190(%rsp), %rdi
callq 0x13780
movq %rax, 0xa0(%rsp)
leaq 0xa0(%rsp), %rdi
movl $0x1, %esi
callq 0x137f0
movq %rax, 0xa8(%rsp)
leaq 0xb0(%rsp), %rdi
leaq 0xa8(%rsp), %rsi
callq 0x137b0
movq 0x78(%rsp), %rdi
movq 0xc0(%rsp), %rsi
movq 0xb0(%rsp), %rdx
callq 0x136e0
movq %rax, 0x80(%rsp)
jmp 0x10f56
movq 0x80(%rsp), %rax
movq %rax, 0x98(%rsp)
movb $0x0, 0xcf(%rsp)
movq 0x198(%rsp), %rdi
movq 0x190(%rsp), %rsi
movzbl 0xcf(%rsp), %edx
andl $0x1, %edx
callq 0x10a30
jmp 0x10f90
testb $0x1, 0xcf(%rsp)
jne 0x10fb2
movb $0x1, 0x1a7(%rsp)
movl $0x1, 0xd0(%rsp)
jmp 0x11363
movq 0x190(%rsp), %rdi
callq 0x4d50
movq %rax, 0x70(%rsp)
movq 0x198(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x4ba0
movq %rax, %rcx
movq 0x70(%rsp), %rax
movslq 0x18(%rcx), %rcx
cmpq %rcx, %rax
je 0x11040
movq 0x198(%rsp), %rdi
xorl %eax, %eax
movl %eax, 0x6c(%rsp)
movl %eax, %esi
callq 0x4ba0
movl 0x18(%rax), %eax
movl %eax, 0x68(%rsp)
movq 0x190(%rsp), %rdi
callq 0x4d50
movl 0x68(%rsp), %esi
movq %rax, %rdx
movl 0x6c(%rsp), %eax
leaq 0x35fb8(%rip), %rdi     # 0x46fd9
callq 0x3a670
jmp 0x11028
movb $0x0, 0x1a7(%rsp)
movl $0x1, 0xd0(%rsp)
jmp 0x11363
leaq 0x35ea1(%rip), %rsi     # 0x46ee8
xorl %eax, %eax
movl $0x5, %edi
callq 0x3a770
jmp 0x11055
movl $0x0, 0x94(%rsp)
movl 0x94(%rsp), %eax
movl %eax, 0x64(%rsp)
movq 0x198(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x4ba0
movq %rax, %rcx
movl 0x64(%rsp), %eax
cmpl 0x18(%rcx), %eax
jge 0x1133b
movq 0x190(%rsp), %rdi
movslq 0x94(%rsp), %rsi
callq 0x12190
movw (%rax), %ax
movw %ax, 0x52(%rsp)
movq 0x198(%rsp), %rdi
xorl %eax, %eax
movl %eax, 0x54(%rsp)
movl %eax, %esi
callq 0x4ba0
movl 0x54(%rsp), %esi
movq %rax, %rdi
movl 0x94(%rsp), %edx
callq 0x12110
movq %rax, 0x58(%rsp)
jmp 0x110d8
movq 0x58(%rsp), %rax
movw 0x52(%rsp), %cx
movw %cx, (%rax)
movq 0x198(%rsp), %rdi
xorl %eax, %eax
movl %eax, 0x44(%rsp)
movl %eax, %esi
callq 0x4ba0
movl 0x44(%rsp), %esi
movq %rax, %rdi
movl 0x94(%rsp), %edx
callq 0x12110
movq %rax, 0x48(%rsp)
jmp 0x11114
movq 0x48(%rsp), %rax
movswl (%rax), %eax
movl %eax, 0x90(%rsp)
cmpl $0x0, 0x90(%rsp)
jl 0x11155
movl 0x90(%rsp), %eax
movl %eax, 0x40(%rsp)
movq 0x198(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x4ba0
movq %rax, %rcx
movl 0x40(%rsp), %eax
cmpl 0x18(%rcx), %eax
jl 0x11184
movl 0x90(%rsp), %esi
leaq 0x35eba(%rip), %rdi     # 0x4701d
xorl %eax, %eax
callq 0x3a670
jmp 0x1116c
movb $0x0, 0x1a7(%rsp)
movl $0x1, 0xd0(%rsp)
jmp 0x11363
movl $0x0, 0x8c(%rsp)
movl 0x8c(%rsp), %eax
cmpl 0x94(%rsp), %eax
jge 0x112b2
movq 0x198(%rsp), %rdi
xorl %eax, %eax
movl %eax, 0x34(%rsp)
movl %eax, %esi
callq 0x4ba0
movl 0x34(%rsp), %esi
movq %rax, %rdi
movl 0x94(%rsp), %edx
callq 0x12110
movq %rax, 0x38(%rsp)
jmp 0x111d2
movq 0x38(%rsp), %rax
movswl (%rax), %eax
movl %eax, 0x20(%rsp)
movq 0x198(%rsp), %rdi
xorl %eax, %eax
movl %eax, 0x24(%rsp)
movl %eax, %esi
callq 0x4ba0
movl 0x24(%rsp), %esi
movq %rax, %rdi
movl 0x8c(%rsp), %edx
callq 0x12110
movq %rax, 0x28(%rsp)
jmp 0x1120d
movl 0x20(%rsp), %eax
movq 0x28(%rsp), %rcx
movswl (%rcx), %ecx
cmpl %ecx, %eax
jne 0x1129a
movl 0x94(%rsp), %eax
movl %eax, 0xc(%rsp)
movl 0x8c(%rsp), %eax
movl %eax, 0x10(%rsp)
movq 0x198(%rsp), %rdi
xorl %eax, %eax
movl %eax, 0x14(%rsp)
movl %eax, %esi
callq 0x4ba0
movl 0x14(%rsp), %esi
movq %rax, %rdi
movl 0x94(%rsp), %edx
callq 0x12110
movq %rax, 0x18(%rsp)
jmp 0x11262
movl 0x10(%rsp), %edx
movl 0xc(%rsp), %esi
movq 0x18(%rsp), %rax
movswl (%rax), %ecx
leaq 0x35dd5(%rip), %rdi     # 0x4704e
xorl %eax, %eax
callq 0x3a670
jmp 0x11282
movb $0x0, 0x1a7(%rsp)
movl $0x1, 0xd0(%rsp)
jmp 0x11363
jmp 0x1129c
movl 0x8c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x8c(%rsp)
jmp 0x1118f
movl 0x14c(%rsp), %eax
movl 0x94(%rsp), %ecx
addl %ecx, %eax
movslq %eax, %rsi
leaq 0xe0(%rsp), %rdi
callq 0x4ba0
movq %rax, (%rsp)
movq 0x198(%rsp), %rdi
movl 0x6c(%rdi), %eax
movl 0x90(%rsp), %ecx
addl %ecx, %eax
movslq %eax, %rsi
callq 0x4ba0
movq (%rsp), %rsi
movq %rax, %rdi
callq 0x12390
jmp 0x11300
movl 0x94(%rsp), %edx
movl 0x90(%rsp), %ecx
leaq 0x35c56(%rip), %rsi     # 0x46f6b
xorl %eax, %eax
movl $0x5, %edi
callq 0x3a770
jmp 0x11323
jmp 0x11325
movl 0x94(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x94(%rsp)
jmp 0x11060
leaq 0x3756b(%rip), %rsi     # 0x488ad
xorl %eax, %eax
movl $0x5, %edi
callq 0x3a770
jmp 0x11350
movb $0x1, 0x1a7(%rsp)
movl $0x1, 0xd0(%rsp)
leaq 0xe0(%rsp), %rdi
callq 0x12ab0
movb 0x1a7(%rsp), %al
andb $0x1, %al
addq $0x1a8, %rsp            # imm = 0x1A8
retq
movq 0xd8(%rsp), %rdi
callq 0x36a0
nop