// File: /workspace/github_c_makefile_star2_O3/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 0x4091
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 0x40b7
movq %rbx, %rdi
callq 0x4797
movq %rax, 0x30(%rsp)
jmp 0x40c0
movq $0x0, 0x30(%rsp)
cmpl $0x0, 0x50(%rbx)
sete %al
orb %r13b, %al
jne 0x40db
movq %rbx, %rdi
callq 0x480b
movq %rax, 0x28(%rsp)
jmp 0x40e4
movq $0x0, 0x28(%rsp)
cmpl $0x0, 0x44(%rbx)
sete %al
orb %r13b, %al
jne 0x40ff
movq %rbx, %rdi
callq 0x3fea
movq %rax, 0x20(%rsp)
jmp 0x4108
movq $0x0, 0x20(%rsp)
movl 0x48(%rbx), %r8d
testl %r8d, %r8d
sete %al
orb %r13b, %al
jne 0x417e
cmpl $0x2, 0x94(%rbx)
jl 0x4130
leaq 0xb34f(%rip), %rdi      # 0xf476
callq 0x2090
movl 0x48(%rbx), %r8d
movq 0x80(%rbx), %rcx
leaq 0xaa36(%rip), %rdx      # 0xeb74
leaq 0xb351(%rip), %r9       # 0xf496
leaq 0x40(%rsp), %r15
movl $0x1000, %esi           # imm = 0x1000
movq %r15, %rdi
xorl %eax, %eax
callq 0x2140
leaq 0xa7ce(%rip), %rsi      # 0xe92e
movq %r15, %rdi
callq 0x21e0
movq %rax, 0x18(%rsp)
testq %rax, %rax
jne 0x4187
leaq 0xb321(%rip), %rdi      # 0xf49a
callq 0x39fc
movq $0x0, 0x18(%rsp)
cmpl $0x0, 0x54(%rbx)
sete %al
orb %r13b, %al
jne 0x41a2
movq %rbx, %rdi
callq 0x487f
movq %rax, 0x10(%rsp)
jmp 0x41ab
movq $0x0, 0x10(%rsp)
movq %rbx, %rdi
callq 0x57ec
movq %rbx, %rdi
callq 0x5883
movl 0x4c(%rbx), %r8d
testl %r8d, %r8d
sete %al
orb %r13b, %al
jne 0x4202
leaq 0x20a0(%rbx), %rdi
movq 0x80(%rbx), %rcx
leaq 0xa995(%rip), %rdx      # 0xeb74
leaq 0xa997(%rip), %r9       # 0xeb7d
movl $0x1000, %esi           # imm = 0x1000
xorl %eax, %eax
callq 0x2140
movq %rbx, %rdi
callq 0x592a
movq %rbx, %rdi
callq 0x59c1
movl 0x50(%rbx), %r8d
testl %r8d, %r8d
sete %al
orb %r13b, %al
jne 0x4249
leaq 0x30a0(%rbx), %rdi
movq 0x80(%rbx), %rcx
leaq 0xa94e(%rip), %rdx      # 0xeb74
leaq 0xa9a8(%rip), %r9       # 0xebd5
movl $0x1000, %esi           # imm = 0x1000
xorl %eax, %eax
callq 0x2140
movq %rbx, %rdi
callq 0x5a70
movq %rbx, %rdi
callq 0x5b07
movl 0x44(%rbx), %r8d
testl %r8d, %r8d
sete %al
orb %r13b, %al
jne 0x4290
leaq 0x10a0(%rbx), %rdi
movq 0x80(%rbx), %rcx
leaq 0xa907(%rip), %rdx      # 0xeb74
leaq 0xa925(%rip), %r9       # 0xeb99
movl $0x1000, %esi           # imm = 0x1000
xorl %eax, %eax
callq 0x2140
movq %rbx, %rdi
callq 0x5cf4
movq %rbx, %rdi
callq 0x5d8b
cmpl $0x0, 0x54(%rbx)
sete %al
orb %r13b, %al
jne 0x42d4
leaq 0x40a0(%rbx), %rdi
movq 0x80(%rbx), %rcx
leaq 0xa66d(%rip), %rdx      # 0xe91e
leaq 0xa8fd(%rip), %r8       # 0xebb5
movl $0x1000, %esi           # imm = 0x1000
xorl %eax, %eax
callq 0x2140
movq %rbx, %rdi
callq 0x5bb6
movq %rbx, %rdi
callq 0x5c4d
movq 0x50d8(%rbx), %rdi
movl $0x2, %esi
xorl %eax, %eax
callq 0x22f0
cmpl $-0x1, %eax
je 0x471f
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 0x471f
movq 0x28(%rbx), %rsi
movq %rax, %rdi
movl $0x2, %edx
callq 0x22e0
movl %r15d, %edi
callq 0x2160
testl %eax, %eax
jne 0x471f
movq 0x50e8(%rbx), %rax
movq %rax, 0x38(%rsp)
cmpq $0x0, 0x28(%rbx)
je 0x4575
xorl %r15d, %r15d
leaq 0x40(%rsp), %r12
movq 0x50e8(%rbx), %rax
movzbl (%rax,%r15), %ebp
andl $0x7f, %ebp
movslq 0x4c(%rbx), %rsi
testq %rsi, %rsi
sete %al
orb %r13b, %al
jne 0x43c6
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 0x471f
movslq 0x4c(%rbx), %rsi
movl $0x1, %edx
movq %r12, %rdi
movq 0x30(%rsp), %rcx
callq 0x2390
cmpq $-0x1, %rax
je 0x472b
movslq 0x50(%rbx), %rsi
testq %rsi, %rsi
sete %al
orb %r13b, %al
jne 0x4422
movl $0x0, 0x40(%rsp)
movq 0x50b8(%rbx), %rax
movzbl %bpl, %ecx
movq (%rax,%rcx,8), %rcx
movl $0x1, %edx
movq %r12, %rdi
callq 0x20a0
cmpl $0x1, %eax
jne 0x471f
movslq 0x50(%rbx), %rsi
movl $0x1, %edx
movq %r12, %rdi
movq 0x28(%rsp), %rcx
callq 0x2390
cmpq $-0x1, %rax
je 0x472b
movslq 0x44(%rbx), %rsi
testq %rsi, %rsi
sete %al
orb %r13b, %al
jne 0x448a
movl $0x0, 0x40(%rsp)
movq 0x50a8(%rbx), %rax
movzbl %bpl, %r14d
movq (%rax,%r14,8), %rcx
movl $0x1, %edx
movq %r12, %rdi
callq 0x20a0
cmpl $0x1, %eax
jne 0x471f
movq 0x10(%rbx), %rax
movl (%rax,%r14,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 0x4737
movslq 0x48(%rbx), %rsi
testq %rsi, %rsi
sete %al
orb %r13b, %al
jne 0x44b9
movl %ebp, 0x40(%rsp)
movl $0x1, %edx
movq %r12, %rdi
movq 0x18(%rsp), %rcx
callq 0x2390
cmpq $-0x1, %rax
je 0x474f
cmpl $0x0, 0x54(%rbx)
setne %al
testb %al, 0xc(%rsp)
je 0x4517
movb $0x0, 0x40(%rsp)
movq 0x50c0(%rbx), %rax
movzbl %bpl, %r14d
movq (%rax,%r14,8), %rcx
movl $0x1, %esi
movl $0x1, %edx
movq %r12, %rdi
callq 0x20a0
cmpl $0x1, %eax
jne 0x471f
movl $0x1, %esi
movl $0x1, %edx
movq %r12, %rdi
movq 0x10(%rsp), %rcx
callq 0x2390
cmpq $-0x1, %rax
jne 0x451b
jmp 0x4743
movzbl %bpl, %r14d
movq 0x38(%rsp), %rax
leaq (%rax,%r15), %rbp
movq 0x50a0(%rbx), %rax
movq (%rax,%r14,8), %rcx
movl $0x1, %esi
movl $0x1, %edx
movq %rbp, %rdi
callq 0x20a0
cmpl $0x1, %eax
jne 0x471f
cmpb $0x0, 0xc(%rsp)
je 0x455d
movzbl (%rbp), %edi
callq 0xc5af
movb %al, (%rbp)
movq 0x5118(%rbx), %rax
incq (%rax,%r14,8)
incq %r15
cmpq 0x28(%rbx), %r15
jb 0x435f
movq %rbx, %rdi
callq 0x58d9
cmpl $0x0, 0x4c(%rbx)
setne %al
testb %al, 0xc(%rsp)
je 0x4592
movq %rbx, %rdi
callq 0x5a1f
cmpl $0x0, 0x50(%rbx)
sete %al
orb %r13b, %al
jne 0x45a6
movq %rbx, %rdi
callq 0x5b65
cmpl $0x0, 0x44(%rbx)
sete %al
orb %r13b, %al
jne 0x45ba
movq %rbx, %rdi
callq 0x5de9
cmpl $0x0, 0x54(%rbx)
sete %al
orb %r13b, %al
jne 0x45ce
movq %rbx, %rdi
callq 0x5ca3
leaq 0xa0(%rbx), %rdi
movl $0x1, %esi
xorl %eax, %eax
callq 0x22f0
cmpl $-0x1, %eax
je 0x471f
movl %eax, %ebp
movq 0x28(%rbx), %rdx
movq 0x30(%rbx), %rcx
movl %eax, %edi
movq 0x38(%rsp), %rsi
callq 0x5ed1
movl %ebp, %edi
callq 0x2160
testl %eax, %eax
jne 0x471f
movq 0x50e8(%rbx), %rdi
movq 0x28(%rbx), %rsi
callq 0x2290
cmpl $-0x1, %eax
je 0x471f
movq $0x0, 0x50e8(%rbx)
cmpl $0x0, 0x4c(%rbx)
sete %al
orb %r13b, %al
jne 0x465d
movq 0x30(%rsp), %rdi
callq 0x20e0
testl %eax, %eax
jne 0x475b
leaq 0x20a0(%rbx), %rdi
callq 0x2070
cmpl $0x0, 0x50(%rbx)
sete %al
orb %r13b, %al
jne 0x4687
movq 0x28(%rsp), %rdi
callq 0x20e0
testl %eax, %eax
jne 0x4767
leaq 0x30a0(%rbx), %rdi
callq 0x2070
cmpl $0x0, 0x44(%rbx)
sete %al
orb %r13b, %al
jne 0x46b1
movq 0x20(%rsp), %rdi
callq 0x20e0
testl %eax, %eax
jne 0x4773
leaq 0x10a0(%rbx), %rdi
callq 0x2070
cmpl $0x0, 0x48(%rbx)
sete %al
orb %r13b, %al
jne 0x46cf
movq 0x18(%rsp), %rdi
callq 0x20e0
testl %eax, %eax
jne 0x477f
cmpl $0x0, 0x54(%rbx)
sete %al
orb %r13b, %al
jne 0x470d
movq 0x10(%rsp), %rdi
callq 0x20e0
testl %eax, %eax
jne 0x478b
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 0xa61b(%rip), %rdi      # 0xed41
callq 0x39fc
leaq 0xa61e(%rip), %rdi      # 0xed50
callq 0x39fc
leaq 0xa645(%rip), %rdi      # 0xed83
callq 0x39fc
leaq 0xa6ab(%rip), %rdi      # 0xedf5
callq 0x39fc
leaq 0xa662(%rip), %rdi      # 0xedb8
callq 0x39fc
leaq 0xa6bc(%rip), %rdi      # 0xee1e
callq 0x39fc
leaq 0xa6e0(%rip), %rdi      # 0xee4e
callq 0x39fc
leaq 0xa709(%rip), %rdi      # 0xee83
callq 0x39fc
leaq 0xa72f(%rip), %rdi      # 0xeeb5
callq 0x39fc
leaq 0xa75d(%rip), %rdi      # 0xeeef
callq 0x39fc