// File: /workspace/github_c_makefile_star2_O1/felipelouza[P]egap/util.c
// Function: mergeBWT128ext
void mergeBWT128ext(g_data *g, bool lastRound)
{
  if(sizeof(symbol)>sizeof(palette)) die("Sorry, alphabet is too large (mergeBWT128ext");
  assert(!g->lcpMerge && g->extMem && g->numBwt<=128);
  FILE *daOutFile=NULL;
  FILE *colorsOutFile=NULL;
  FILE *saOutFile=NULL;
  FILE *slOutFile=NULL;
  FILE *qsOutFile=NULL;

  check_g_data(g);
  array_clear(g->inCnt,g->numBwt,0);

  if(g->outputSA && lastRound)
    saOutFile = openSAFile(g);
  if(g->outputSL && lastRound)
    slOutFile = openSLFile(g);
  if(g->outputDA && lastRound)
    daOutFile = openDAFile(g);  
  if(g->outputColors && lastRound)
    colorsOutFile = openColorFile(g);  
  if(g->outputQS && lastRound)
    qsOutFile = openQSFile(g);

  open_bw_files(g);     // open files in read mode
  rewind_bw_files(g);   // set file pointers at the beginning of each BWT

  if(g->outputSA && lastRound){
    snprintf(g->safname,Filename_size,"%s.%d.%s",g->outPath,g->outputSA, SA_BL_EXT);
    open_sa_files(g);
    rewind_sa_files(g);   // set file pointers at the beginning of each SA
  }
  if(g->outputSL && lastRound){
    snprintf(g->slfname,Filename_size,"%s.%d.%s",g->outPath,g->outputSL, SL_BL_EXT);
    open_sl_files(g);
    rewind_sl_files(g);   // set file pointers at the beginning of each SL
  }
  if(g->outputDA && lastRound){
    snprintf(g->dafname,Filename_size,"%s.%d.%s",g->outPath,g->outputDA, DA_BL_EXT);
    open_da_files(g);
    rewind_da_files(g);   // set file pointers at the beginning of each DA
  }
  if(g->outputQS && lastRound){
    snprintf(g->qsfname,Filename_size,"%s.%s",g->outPath, QS_BL_EXT);
    open_qs_files(g);
    rewind_qs_files(g);   // set file pointers at the beginning of each DA
  }

  // mmap merge values so we can read/write simultaneously 
  int fd = open(g->merge_fname,O_RDWR);
  if(fd == -1) die(__func__);
  g->mergeColor = mmap(NULL,g->mergeLen*sizeof(palette),PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
  if(g->mergeColor == MAP_FAILED) die(__func__);
  #ifdef USE_MMAP_ADVISE
  madvise(g->mergeColor, g->mergeLen*sizeof(palette), MADV_SEQUENTIAL);
  #endif
  if(close(fd)!=0) die(__func__);

  symbol *bwtout = (symbol *) g->mergeColor;   // merged BWT stored in mergeColor
  for (customInt i = 0; i < g->mergeLen; ++i) {
    int currentColor = g->mergeColor[i] & 0x7F; // delete additional bit
    assert(currentColor < g->numBwt);
    // if requested output merge array
    if(g->outputSA && lastRound){ 
      int sa_value=0;
      int e = fread(&sa_value, g->outputSA, 1, g->saf[currentColor]);
      if(e!=1) die(__func__);
      if(fwrite(&sa_value, g->outputSA, 1, saOutFile)==EOF)
        die("mergeBWT128ext: Error writing to Suffix Array file");   
    } 
    if(g->outputSL && lastRound){ 
      int sl_value=0;
      int e = fread(&sl_value, g->outputSL, 1, g->slf[currentColor]);
      if(e!=1) die(__func__);
      if(fwrite(&sl_value, g->outputSL, 1, slOutFile)==EOF)
        die("mergeBWT128ext: Error writing to Suffix Array file");   
    } 
    if(g->outputDA && lastRound){ 
      int da_value=0;
      int e = fread(&da_value, g->outputDA, 1, g->daf[currentColor]);
      if(e!=1) die(__func__);
      da_value+=g->bwtDocs[currentColor];
      //printf("%d (%d)\n", da_value, currentColor);
      //if(fputc(currentColor, daOutFile)==EOF)
      if(fwrite(&da_value, g->outputDA, 1, daOutFile)==EOF)
        die("mergeBWT128ext: Error writing to Document Array file");   
      //printf("%d ==> %d\n", currentColor, da_value);
    } 
    if(g->outputColors && lastRound){ 
      int da_value=currentColor;
      if(fwrite(&da_value, g->outputColors, 1, colorsOutFile)==EOF)
        die("mergeBWT128ext: Error writing to Document Array (Color) file");   
    } 
    if(g->outputQS && lastRound){ 
      symbol qs_value=0;
      int e = fread(&qs_value, sizeof(symbol), 1, g->qsf[currentColor]);
      if(e!=1) die(__func__);
      if(fwrite(&qs_value, sizeof(symbol), 1, qsOutFile)==EOF)
        die("mergeBWT128ext: Error writing to QS file");   
    } 
    // save new BWT char overwriting mergeColor[i]
    int e = fread(bwtout+i,sizeof(symbol),1,g->bwf[currentColor]);
    if(e!=1) die(__func__);
    if(lastRound) bwtout[i] = alpha_enlarge(bwtout[i]);     
    g->inCnt[currentColor]++; // one more char read from currentColor BWT
  }  
  close_bw_files(g);
  if(g->outputSA  && lastRound) close_sa_files(g);
  if(g->outputSL  && lastRound) close_sl_files(g);
  if(g->outputDA  && lastRound) close_da_files(g);
  if(g->outputQS  && lastRound) close_qs_files(g);
  // final check on the merging 
  for(int i=0;i<g->numBwt;i++) assert(g->inCnt[i]==g->bwtLen[i]);

  // merging done: copy back to file
  fd = open(g->bwfname,O_WRONLY);
  if(fd == -1) die(__func__);
  huge_pwrite(fd, bwtout,sizeof(symbol)*g->mergeLen,sizeof(symbol)*g->symb_offset);
  if(close(fd)!=0) die(__func__);
  // unmap mergeColor
  fd = munmap(g->mergeColor,g->mergeLen*sizeof(palette));
  if(fd == -1) die(__func__);
  g->mergeColor=NULL;  
  // close suffix array file 
  if(g->outputSA && lastRound){
    if(fclose(saOutFile)!=0) die("mergeBWT128ext: Error closing Suffix Array file");   
    remove(g->safname);
  }
  // close suffixes's length file 
  if(g->outputSL && lastRound){
    if(fclose(slOutFile)!=0) die("mergeBWT128ext: Error closing Suffixes' Lengths file");   
    remove(g->slfname);
  }
  // close document array file 
  if(g->outputDA && lastRound){
    if(fclose(daOutFile)!=0) die("mergeBWT128ext: Error closing Document Array file");   
    remove(g->dafname);
  }
  //close DA (color) file
  if(g->outputColors && lastRound){
    if(fclose(colorsOutFile)!=0) die("mergeBWT128ext: Error closing Document Array (Color) file");   
  }
  // close QS file 
  if(g->outputQS && lastRound){
    if(fclose(qsOutFile)!=0) die("mergeBWT128ext: Error closing QS file");   
    remove(g->qsfname);
  }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x1048, %rsp           # imm = 0x1048
movl %esi, 0xc(%rsp)
movq %rdi, %rbx
movslq 0x20(%rdi), %rdx
testq %rdx, %rdx
je 0x4016
movq 0x5118(%rbx), %rdi
shlq $0x3, %rdx
xorl %esi, %esi
callq 0x2150
cmpl $0x0, 0x4c(%rbx)
sete %al
movl 0xc(%rsp), %ecx
movl %ecx, %r13d
xorb $0x1, %r13b
orb %r13b, %al
jne 0x403c
movq %rbx, %rdi
callq 0x470f
movq %rax, 0x30(%rsp)
jmp 0x4045
movq $0x0, 0x30(%rsp)
cmpl $0x0, 0x50(%rbx)
sete %al
orb %r13b, %al
jne 0x4060
movq %rbx, %rdi
callq 0x4783
movq %rax, 0x28(%rsp)
jmp 0x4069
movq $0x0, 0x28(%rsp)
cmpl $0x0, 0x44(%rbx)
sete %al
orb %r13b, %al
jne 0x4084
movq %rbx, %rdi
callq 0x3f6f
movq %rax, 0x20(%rsp)
jmp 0x408d
movq $0x0, 0x20(%rsp)
cmpl $0x0, 0x48(%rbx)
sete %al
orb %r13b, %al
jne 0x4100
cmpl $0x2, 0x94(%rbx)
jl 0x40ae
leaq 0xb3cd(%rip), %rdi      # 0xf476
callq 0x2090
movq 0x80(%rbx), %rcx
movl 0x48(%rbx), %r8d
leaq 0xaab4(%rip), %rdx      # 0xeb74
leaq 0xb3cf(%rip), %r9       # 0xf496
leaq 0x40(%rsp), %r15
movl $0x1000, %esi           # imm = 0x1000
movq %r15, %rdi
xorl %eax, %eax
callq 0x2140
leaq 0xa84c(%rip), %rsi      # 0xe92e
movq %r15, %rdi
callq 0x21e0
movq %rax, 0x18(%rsp)
testq %rax, %rax
jne 0x4109
leaq 0xb39f(%rip), %rdi      # 0xf49a
callq 0x3973
movq $0x0, 0x18(%rsp)
cmpl $0x0, 0x54(%rbx)
sete %al
orb %r13b, %al
jne 0x4124
movq %rbx, %rdi
callq 0x47f7
movq %rax, 0x10(%rsp)
jmp 0x412d
movq $0x0, 0x10(%rsp)
movq %rbx, %rdi
callq 0x5748
movq %rbx, %rdi
callq 0x57d9
movl 0x4c(%rbx), %r8d
testl %r8d, %r8d
sete %al
orb %r13b, %al
jne 0x4184
leaq 0x20a0(%rbx), %rdi
movq 0x80(%rbx), %rcx
leaq 0xaa13(%rip), %rdx      # 0xeb74
leaq 0xaa15(%rip), %r9       # 0xeb7d
movl $0x1000, %esi           # imm = 0x1000
xorl %eax, %eax
callq 0x2140
movq %rbx, %rdi
callq 0x5880
movq %rbx, %rdi
callq 0x5911
movl 0x50(%rbx), %r8d
testl %r8d, %r8d
sete %al
orb %r13b, %al
jne 0x41cb
leaq 0x30a0(%rbx), %rdi
movq 0x80(%rbx), %rcx
leaq 0xa9cc(%rip), %rdx      # 0xeb74
leaq 0xaa26(%rip), %r9       # 0xebd5
movl $0x1000, %esi           # imm = 0x1000
xorl %eax, %eax
callq 0x2140
movq %rbx, %rdi
callq 0x59c0
movq %rbx, %rdi
callq 0x5a51
movl 0x44(%rbx), %r8d
testl %r8d, %r8d
sete %al
orb %r13b, %al
jne 0x4212
leaq 0x10a0(%rbx), %rdi
movq 0x80(%rbx), %rcx
leaq 0xa985(%rip), %rdx      # 0xeb74
leaq 0xa9a3(%rip), %r9       # 0xeb99
movl $0x1000, %esi           # imm = 0x1000
xorl %eax, %eax
callq 0x2140
movq %rbx, %rdi
callq 0x5c38
movq %rbx, %rdi
callq 0x5cc9
cmpl $0x0, 0x54(%rbx)
sete %al
orb %r13b, %al
jne 0x4256
leaq 0x40a0(%rbx), %rdi
movq 0x80(%rbx), %rcx
leaq 0xa6eb(%rip), %rdx      # 0xe91e
leaq 0xa97b(%rip), %r8       # 0xebb5
movl $0x1000, %esi           # imm = 0x1000
xorl %eax, %eax
callq 0x2140
movq %rbx, %rdi
callq 0x5b00
movq %rbx, %rdi
callq 0x5b91
movq 0x50d8(%rbx), %rdi
movl $0x2, %esi
xorl %eax, %eax
callq 0x22f0
cmpl $-0x1, %eax
je 0x4697
movl %eax, %r15d
movq 0x28(%rbx), %rsi
xorl %edi, %edi
movl $0x3, %edx
movl $0x1, %ecx
movl %eax, %r8d
xorl %r9d, %r9d
callq 0x2230
movq %rax, 0x50e8(%rbx)
cmpq $-0x1, %rax
je 0x4697
movq 0x50e8(%rbx), %rdi
movq 0x28(%rbx), %rsi
movl $0x2, %edx
callq 0x22e0
movl %r15d, %edi
callq 0x2160
testl %eax, %eax
jne 0x4697
movq 0x50e8(%rbx), %rax
movq %rax, 0x38(%rsp)
cmpq $0x0, 0x28(%rbx)
je 0x44ed
xorl %r14d, %r14d
leaq 0x40(%rsp), %r12
movq 0x50e8(%rbx), %rax
movzbl (%rax,%r14), %ebp
andl $0x7f, %ebp
movslq 0x4c(%rbx), %rsi
testq %rsi, %rsi
sete %al
orb %r13b, %al
jne 0x434c
movl $0x0, 0x40(%rsp)
movq 0x50b0(%rbx), %rax
movq (%rax,%rbp,8), %rcx
movl $0x1, %edx
movq %r12, %rdi
callq 0x20a0
cmpl $0x1, %eax
jne 0x4697
movslq 0x4c(%rbx), %rsi
movl $0x1, %edx
movq %r12, %rdi
movq 0x30(%rsp), %rcx
callq 0x2390
cmpq $-0x1, %rax
je 0x46a3
movslq 0x50(%rbx), %rsi
testq %rsi, %rsi
sete %al
orb %r13b, %al
movzbl %bpl, %r15d
jne 0x43a8
movl $0x0, 0x40(%rsp)
movq 0x50b8(%rbx), %rax
movq (%rax,%r15,8), %rcx
movl $0x1, %edx
movq %r12, %rdi
callq 0x20a0
cmpl $0x1, %eax
jne 0x4697
movslq 0x50(%rbx), %rsi
movl $0x1, %edx
movq %r12, %rdi
movq 0x28(%rsp), %rcx
callq 0x2390
cmpq $-0x1, %rax
je 0x46a3
movslq 0x44(%rbx), %rsi
testq %rsi, %rsi
sete %al
orb %r13b, %al
jne 0x440c
movl $0x0, 0x40(%rsp)
movq 0x50a8(%rbx), %rax
movq (%rax,%r15,8), %rcx
movl $0x1, %edx
movq %r12, %rdi
callq 0x20a0
cmpl $0x1, %eax
jne 0x4697
movq 0x10(%rbx), %rax
movl (%rax,%r15,8), %eax
addl %eax, 0x40(%rsp)
movslq 0x44(%rbx), %rsi
movl $0x1, %edx
movq %r12, %rdi
movq 0x20(%rsp), %rcx
callq 0x2390
cmpq $-0x1, %rax
je 0x46af
movslq 0x48(%rbx), %rsi
testq %rsi, %rsi
sete %al
orb %r13b, %al
jne 0x443b
movl %ebp, 0x40(%rsp)
movl $0x1, %edx
movq %r12, %rdi
movq 0x18(%rsp), %rcx
callq 0x2390
cmpq $-0x1, %rax
je 0x46c7
cmpl $0x0, 0x54(%rbx)
sete %al
orb %r13b, %al
jne 0x4493
movb $0x0, 0x40(%rsp)
movq 0x50c0(%rbx), %rax
movq (%rax,%r15,8), %rcx
movl $0x1, %esi
movl $0x1, %edx
movq %r12, %rdi
callq 0x20a0
cmpl $0x1, %eax
jne 0x4697
movl $0x1, %esi
movl $0x1, %edx
movq %r12, %rdi
movq 0x10(%rsp), %rcx
callq 0x2390
cmpq $-0x1, %rax
je 0x46bb
movq 0x38(%rsp), %rax
leaq (%rax,%r14), %rbp
movq 0x50a0(%rbx), %rax
movq (%rax,%r15,8), %rcx
movl $0x1, %esi
movl $0x1, %edx
movq %rbp, %rdi
callq 0x20a0
cmpl $0x1, %eax
jne 0x4697
cmpb $0x0, 0xc(%rsp)
je 0x44d5
movzbl (%rbp), %edi
callq 0xc4f3
movb %al, (%rbp)
movq 0x5118(%rbx), %rax
incq (%rax,%r15,8)
incq %r14
cmpq 0x28(%rbx), %r14
jb 0x42e5
movq %rbx, %rdi
callq 0x582f
cmpl $0x0, 0x4c(%rbx)
setne %al
testb %al, 0xc(%rsp)
je 0x450a
movq %rbx, %rdi
callq 0x596f
cmpl $0x0, 0x50(%rbx)
sete %al
orb %r13b, %al
jne 0x451e
movq %rbx, %rdi
callq 0x5aaf
cmpl $0x0, 0x44(%rbx)
sete %al
orb %r13b, %al
jne 0x4532
movq %rbx, %rdi
callq 0x5d27
cmpl $0x0, 0x54(%rbx)
sete %al
orb %r13b, %al
jne 0x4546
movq %rbx, %rdi
callq 0x5be7
leaq 0xa0(%rbx), %rdi
movl $0x1, %esi
xorl %eax, %eax
callq 0x22f0
cmpl $-0x1, %eax
je 0x4697
movl %eax, %ebp
movq 0x28(%rbx), %rdx
movq 0x30(%rbx), %rcx
movl %eax, %edi
movq 0x38(%rsp), %rsi
callq 0x5e0f
movl %ebp, %edi
callq 0x2160
testl %eax, %eax
jne 0x4697
movq 0x50e8(%rbx), %rdi
movq 0x28(%rbx), %rsi
callq 0x2290
cmpl $-0x1, %eax
je 0x4697
movq $0x0, 0x50e8(%rbx)
cmpl $0x0, 0x4c(%rbx)
sete %al
orb %r13b, %al
jne 0x45d5
movq 0x30(%rsp), %rdi
callq 0x20e0
testl %eax, %eax
jne 0x46d3
leaq 0x20a0(%rbx), %rdi
callq 0x2070
cmpl $0x0, 0x50(%rbx)
sete %al
orb %r13b, %al
jne 0x45ff
movq 0x28(%rsp), %rdi
callq 0x20e0
testl %eax, %eax
jne 0x46df
leaq 0x30a0(%rbx), %rdi
callq 0x2070
cmpl $0x0, 0x44(%rbx)
sete %al
orb %r13b, %al
jne 0x4629
movq 0x20(%rsp), %rdi
callq 0x20e0
testl %eax, %eax
jne 0x46eb
leaq 0x10a0(%rbx), %rdi
callq 0x2070
cmpl $0x0, 0x48(%rbx)
sete %al
orb %r13b, %al
jne 0x4647
movq 0x18(%rsp), %rdi
callq 0x20e0
testl %eax, %eax
jne 0x46f7
cmpl $0x0, 0x54(%rbx)
sete %al
orb %r13b, %al
jne 0x4685
movq 0x10(%rsp), %rdi
callq 0x20e0
testl %eax, %eax
jne 0x4703
addq $0x40a0, %rbx           # imm = 0x40A0
movq %rbx, %rdi
addq $0x1048, %rsp           # imm = 0x1048
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x2070
addq $0x1048, %rsp           # imm = 0x1048
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0xa6a3(%rip), %rdi      # 0xed41
callq 0x3973
leaq 0xa6a6(%rip), %rdi      # 0xed50
callq 0x3973
leaq 0xa6cd(%rip), %rdi      # 0xed83
callq 0x3973
leaq 0xa733(%rip), %rdi      # 0xedf5
callq 0x3973
leaq 0xa6ea(%rip), %rdi      # 0xedb8
callq 0x3973
leaq 0xa744(%rip), %rdi      # 0xee1e
callq 0x3973
leaq 0xa768(%rip), %rdi      # 0xee4e
callq 0x3973
leaq 0xa791(%rip), %rdi      # 0xee83
callq 0x3973
leaq 0xa7b7(%rip), %rdi      # 0xeeb5
callq 0x3973
leaq 0xa7e5(%rip), %rdi      # 0xeeef
callq 0x3973