// File: NinjaDevelper[P]ReedSolomon/cxx/ReedSolomon.cpp
// Function: ReedSolomon::decodeFile(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, int, int, long, std::vector<long, std::allocator<long>>&)
int ReedSolomon::decodeFile(string inFile,string outFile,int K,int N,
                            long size,vector<long>&errLoc){
    int i=0;
    int k=0;

    int fin=open(inFile.c_str(),O_RDWR);
    if(fin<0){
        return 1;
    }
    long inSize=getSize(fin);

    //use MAP_PRIVATE not to copy mem to file.
    unsigned char *buf = 
        (unsigned char*)mmap(NULL, inSize, PROT_READ|PROT_WRITE, 
                               MAP_PRIVATE, fin, 0);

    int interleave=ceil((double)size/K);
    map<int, vector<int> > errors;

    //translate location in file to column/row number of 
    //K x interleave length matrix.
    for(unsigned int i=0;i<errLoc.size();i++){
        long loc=errLoc.at(i);
        errors[loc%interleave].push_back(loc/interleave);
    }
    //it error does not exist in data area but in parity area, ignore it.
    for(i=0;i<interleave;i++){
        bool existData=false;
        for(unsigned int k=0;k<errors[i].size();k++){
            if(errors[i].at(k)<K) existData=true;
        }
        if(!existData) errors[i].clear();
    }
    POLY msgIn={(unsigned char*)malloc(N),N}; 

    //collect data in row , and execute correction.
    unsigned char c=0;
    long loc=0;
    int e=0;
    for(k=0;k<interleave;k++){
        if(errors[k].size()==0) continue;
        for(i=0;i<K;i++){
            loc=(long)i*interleave+k;
            if(loc<size){
                c=buf[loc];
            }else{
                c=0;
            }
            msgIn.data[i]=c;
        }
        for(i=0;i<N-K;i++){
            loc=size+(long)i*interleave+k;
            c=buf[loc];
            msgIn.data[K+i]=c;
        }
        correct(msgIn,N-K,errors[k]);
        for(unsigned int i=0;i<errors[k].size();i++){
            e=errors[k].at(i);
            if(e<K)
                buf[e*interleave+k]=msgIn.data[e];
        }
    }

    //copy only data area to destination file.
    FILE *fp=fopen(outFile.c_str(),"wb");
    fwrite(buf,1,size,fp);
    fclose(fp);

    close(fin);
    munmap(buf,inSize);
    free(msgIn.data);

    return 0;
}

// Assembly:
subq $0x188, %rsp            # imm = 0x188
movq %rdx, 0x88(%rsp)
movq %rsi, 0x90(%rsp)
movq %rdi, %rax
movq 0x90(%rsp), %rdi
movq 0x190(%rsp), %rsi
movq %rax, 0x178(%rsp)
movq %rdi, 0x170(%rsp)
movq %rdx, 0x168(%rsp)
movl %ecx, 0x164(%rsp)
movl %r8d, 0x160(%rsp)
movq %r9, 0x158(%rsp)
movq 0x178(%rsp), %rax
movq %rax, 0x98(%rsp)
movl $0x0, 0x154(%rsp)
movl $0x0, 0x150(%rsp)
callq 0x20a0
movq %rax, %rdi
movl $0x2, %esi
movb $0x0, %al
callq 0x2140
movl %eax, 0x14c(%rsp)
cmpl $0x0, 0x14c(%rsp)
jge 0x30e4
movl $0x1, 0x184(%rsp)
jmp 0x3777
movl 0x14c(%rsp), %edi
callq 0x2ff0
movq %rax, 0x140(%rsp)
movq 0x140(%rsp), %rsi
movl 0x14c(%rsp), %r8d
xorl %eax, %eax
movl %eax, %r9d
movl $0x3, %edx
movl $0x2, %ecx
movq %r9, %rdi
callq 0x22a0
movq %rax, 0x138(%rsp)
cvtsi2sdq 0x158(%rsp), %xmm0
cvtsi2sdl 0x164(%rsp), %xmm1
divsd %xmm1, %xmm0
callq 0x2040
cvttsd2si %xmm0, %eax
movl %eax, 0x134(%rsp)
leaq 0x100(%rsp), %rdi
callq 0x3be0
movl $0x0, 0xfc(%rsp)
movl 0xfc(%rsp), %eax
movq %rax, 0x80(%rsp)
movq 0x190(%rsp), %rdi
callq 0x3bf0
movq %rax, %rcx
movq 0x80(%rsp), %rax
cmpq %rcx, %rax
jae 0x326b
movq 0x190(%rsp), %rdi
movl 0xfc(%rsp), %eax
movl %eax, %esi
callq 0x3c10
movq %rax, 0x78(%rsp)
jmp 0x31b3
movq 0x78(%rsp), %rax
movq (%rax), %rax
movq %rax, 0xf0(%rsp)
movq 0xf0(%rsp), %rax
movslq 0x134(%rsp), %rcx
cqto
idivq %rcx
movl %edx, %eax
movl %eax, 0xe0(%rsp)
leaq 0x100(%rsp), %rdi
leaq 0xe0(%rsp), %rsi
callq 0x3c50
movq %rax, 0x70(%rsp)
jmp 0x31fd
movq 0x70(%rsp), %rdi
movq 0xf0(%rsp), %rax
movslq 0x134(%rsp), %rcx
cqto
idivq %rcx
movl %eax, 0xdc(%rsp)
leaq 0xdc(%rsp), %rsi
callq 0x3d40
jmp 0x322d
jmp 0x322f
movl 0xfc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xfc(%rsp)
jmp 0x3166
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe8(%rsp)
movl %eax, 0xe4(%rsp)
leaq 0x100(%rsp), %rdi
callq 0x3ec0
jmp 0x3786
movl $0x0, 0x154(%rsp)
movl 0x154(%rsp), %eax
cmpl 0x134(%rsp), %eax
jge 0x338a
movb $0x0, 0xdb(%rsp)
movl $0x0, 0xd4(%rsp)
movl 0xd4(%rsp), %eax
movq %rax, 0x60(%rsp)
leaq 0x100(%rsp), %rdi
leaq 0x154(%rsp), %rsi
callq 0x3d70
movq %rax, 0x68(%rsp)
jmp 0x32c5
movq 0x68(%rsp), %rdi
callq 0x3ba0
movq %rax, %rcx
movq 0x60(%rsp), %rax
cmpq %rcx, %rax
jae 0x3342
leaq 0x100(%rsp), %rdi
leaq 0x154(%rsp), %rsi
callq 0x3d70
movq %rax, 0x58(%rsp)
jmp 0x32f8
movq 0x58(%rsp), %rdi
movl 0xd4(%rsp), %eax
movl %eax, %esi
callq 0x3e60
movq %rax, 0x50(%rsp)
jmp 0x3312
movq 0x50(%rsp), %rax
movl (%rax), %eax
cmpl 0x164(%rsp), %eax
jge 0x332a
movb $0x1, 0xdb(%rsp)
jmp 0x332c
movl 0xd4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xd4(%rsp)
jmp 0x329d
testb $0x1, 0xdb(%rsp)
jne 0x3372
leaq 0x100(%rsp), %rdi
leaq 0x154(%rsp), %rsi
callq 0x3d70
movq %rax, 0x48(%rsp)
jmp 0x3368
movq 0x48(%rsp), %rdi
callq 0x3ea0
jmp 0x3374
movl 0x154(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x154(%rsp)
jmp 0x3276
movslq 0x160(%rsp), %rdi
callq 0x2230
movq %rax, 0xc0(%rsp)
movl 0x160(%rsp), %eax
movl %eax, 0xc8(%rsp)
movb $0x0, 0xbf(%rsp)
movq $0x0, 0xb0(%rsp)
movl $0x0, 0xac(%rsp)
movl $0x0, 0x150(%rsp)
movl 0x150(%rsp), %eax
cmpl 0x134(%rsp), %eax
jge 0x36cc
leaq 0x100(%rsp), %rdi
leaq 0x150(%rsp), %rsi
callq 0x3d70
movq %rax, 0x40(%rsp)
jmp 0x3407
movq 0x40(%rsp), %rdi
callq 0x3ba0
cmpq $0x0, %rax
jne 0x341c
jmp 0x36b6
movl $0x0, 0x154(%rsp)
movl 0x154(%rsp), %eax
cmpl 0x164(%rsp), %eax
jge 0x34c8
movslq 0x154(%rsp), %rax
movslq 0x134(%rsp), %rcx
imulq %rcx, %rax
movslq 0x150(%rsp), %rcx
addq %rcx, %rax
movq %rax, 0xb0(%rsp)
movq 0xb0(%rsp), %rax
cmpq 0x158(%rsp), %rax
jge 0x3490
movq 0x138(%rsp), %rax
movq 0xb0(%rsp), %rcx
movb (%rax,%rcx), %al
movb %al, 0xbf(%rsp)
jmp 0x3498
movb $0x0, 0xbf(%rsp)
movb 0xbf(%rsp), %dl
movq 0xc0(%rsp), %rax
movslq 0x154(%rsp), %rcx
movb %dl, (%rax,%rcx)
movl 0x154(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x154(%rsp)
jmp 0x3427
movl $0x0, 0x154(%rsp)
movl 0x154(%rsp), %eax
movl 0x160(%rsp), %ecx
subl 0x164(%rsp), %ecx
cmpl %ecx, %eax
jge 0x3575
movq 0x158(%rsp), %rax
movslq 0x154(%rsp), %rcx
movslq 0x134(%rsp), %rdx
imulq %rdx, %rcx
addq %rcx, %rax
movslq 0x150(%rsp), %rcx
addq %rcx, %rax
movq %rax, 0xb0(%rsp)
movq 0x138(%rsp), %rax
movq 0xb0(%rsp), %rcx
movb (%rax,%rcx), %al
movb %al, 0xbf(%rsp)
movb 0xbf(%rsp), %dl
movq 0xc0(%rsp), %rax
movl 0x164(%rsp), %ecx
addl 0x154(%rsp), %ecx
movslq %ecx, %rcx
movb %dl, (%rax,%rcx)
movl 0x154(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x154(%rsp)
jmp 0x34d3
movl 0x160(%rsp), %eax
movl 0x164(%rsp), %ecx
subl %ecx, %eax
movl %eax, 0x34(%rsp)
leaq 0x100(%rsp), %rdi
leaq 0x150(%rsp), %rsi
callq 0x3d70
movq %rax, 0x38(%rsp)
jmp 0x35a5
movq 0x38(%rsp), %rcx
movl 0x34(%rsp), %edx
movq 0x98(%rsp), %rdi
leaq 0xc0(%rsp), %rsi
callq 0x2a00
movl $0x0, 0xa8(%rsp)
movl 0xa8(%rsp), %eax
movq %rax, 0x20(%rsp)
leaq 0x100(%rsp), %rdi
leaq 0x150(%rsp), %rsi
callq 0x3d70
movq %rax, 0x28(%rsp)
jmp 0x35f6
movq 0x28(%rsp), %rdi
callq 0x3ba0
movq %rax, %rcx
movq 0x20(%rsp), %rax
cmpq %rcx, %rax
jae 0x36b4
leaq 0x100(%rsp), %rdi
leaq 0x150(%rsp), %rsi
callq 0x3d70
movq %rax, 0x18(%rsp)
jmp 0x362d
movq 0x18(%rsp), %rdi
movl 0xa8(%rsp), %eax
movl %eax, %esi
callq 0x3e60
movq %rax, 0x10(%rsp)
jmp 0x3647
movq 0x10(%rsp), %rax
movl (%rax), %eax
movl %eax, 0xac(%rsp)
movl 0xac(%rsp), %eax
cmpl 0x164(%rsp), %eax
jge 0x369c
movq 0xc0(%rsp), %rax
movslq 0xac(%rsp), %rcx
movb (%rax,%rcx), %dl
movq 0x138(%rsp), %rax
movl 0xac(%rsp), %ecx
imull 0x134(%rsp), %ecx
addl 0x150(%rsp), %ecx
movslq %ecx, %rcx
movb %dl, (%rax,%rcx)
jmp 0x369e
movl 0xa8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa8(%rsp)
jmp 0x35ce
jmp 0x36b6
movl 0x150(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x150(%rsp)
jmp 0x33d7
movq 0x88(%rsp), %rdi
callq 0x20a0
movq %rax, %rdi
leaq 0x4923(%rip), %rsi      # 0x8006
callq 0x2200
movq %rax, 0x8(%rsp)
jmp 0x36ef
movq 0x8(%rsp), %rax
movq %rax, 0xa0(%rsp)
movq 0x138(%rsp), %rdi
movq 0x158(%rsp), %rdx
movq 0xa0(%rsp), %rcx
movl $0x1, %esi
callq 0x22d0
jmp 0x3720
movq 0xa0(%rsp), %rdi
callq 0x2180
jmp 0x372f
movl 0x14c(%rsp), %edi
callq 0x22e0
jmp 0x373d
movq 0x138(%rsp), %rdi
movq 0x140(%rsp), %rsi
callq 0x20e0
movq 0xc0(%rsp), %rdi
callq 0x2210
movl $0x0, 0x184(%rsp)
leaq 0x100(%rsp), %rdi
callq 0x3ec0
movl 0x184(%rsp), %eax
addq $0x188, %rsp            # imm = 0x188
retq
movq 0xe8(%rsp), %rdi
callq 0x2280
nopw %cs:(%rax,%rax)