// File: /workspace/github_c_makefile_star2_O2/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
movq 0x5118(%rdi), %rax
movslq 0x20(%rdi), %rcx
xorl %edx, %edx
cmpq %rdx, %rcx
je 0x3c3e
andq $0x0, (%rax,%rdx,8)
incq %rdx
jmp 0x3c2f
cmpl $0x0, 0x4c(%rbx)
sete %al
movl 0xc(%rsp), %ecx
xorb $0x1, %cl
movb %cl, 0xb(%rsp)
orb %cl, %al
jne 0x3c63
movq %rbx, %rdi
callq 0x4319
movq %rax, 0x30(%rsp)
jmp 0x3c6c
movq $0x0, 0x30(%rsp)
cmpl $0x0, 0x50(%rbx)
sete %al
orb 0xb(%rsp), %al
jne 0x3c88
movq %rbx, %rdi
callq 0x438d
movq %rax, 0x28(%rsp)
jmp 0x3c91
movq $0x0, 0x28(%rsp)
cmpl $0x0, 0x44(%rbx)
sete %al
orb 0xb(%rsp), %al
jne 0x3cad
movq %rbx, %rdi
callq 0x3b96
movq %rax, 0x20(%rsp)
jmp 0x3cb6
movq $0x0, 0x20(%rsp)
movl 0x48(%rbx), %r8d
testl %r8d, %r8d
sete %al
orb 0xb(%rsp), %al
jne 0x3d2d
cmpl $0x2, 0x94(%rbx)
jl 0x3cdf
leaq 0xa765(%rip), %rdi      # 0xe43b
callq 0x2090
movl 0x48(%rbx), %r8d
movq 0x80(%rbx), %rcx
leaq 0x9e4c(%rip), %rdx      # 0xdb39
leaq 0xa767(%rip), %r9       # 0xe45b
leaq 0x40(%rsp), %r12
movl $0x1000, %esi           # imm = 0x1000
movq %r12, %rdi
xorl %eax, %eax
callq 0x2140
leaq 0x9c1f(%rip), %rsi      # 0xd92e
movq %r12, %rdi
callq 0x21e0
movq %rax, 0x18(%rsp)
testq %rax, %rax
jne 0x3d36
leaq 0xa737(%rip), %rdi      # 0xe45f
callq 0x35b7
movq $0x0, 0x18(%rsp)
cmpl $0x0, 0x54(%rbx)
sete %al
orb 0xb(%rsp), %al
jne 0x3d52
movq %rbx, %rdi
callq 0x4401
movq %rax, 0x10(%rsp)
jmp 0x3d5b
movq $0x0, 0x10(%rsp)
movq %rbx, %rdi
callq 0x52fc
movq %rbx, %rdi
callq 0x5389
movl 0x4c(%rbx), %r8d
testl %r8d, %r8d
sete %al
orb 0xb(%rsp), %al
jne 0x3db3
leaq 0x20a0(%rbx), %rdi
movq 0x80(%rbx), %rcx
leaq 0x9da9(%rip), %rdx      # 0xdb39
leaq 0x9dab(%rip), %r9       # 0xdb42
movl $0x1000, %esi           # imm = 0x1000
xorl %eax, %eax
callq 0x2140
movq %rbx, %rdi
callq 0x5421
movq %rbx, %rdi
callq 0x54ae
movl 0x50(%rbx), %r8d
testl %r8d, %r8d
sete %al
orb 0xb(%rsp), %al
jne 0x3dfb
leaq 0x30a0(%rbx), %rdi
movq 0x80(%rbx), %rcx
leaq 0x9d61(%rip), %rdx      # 0xdb39
leaq 0x9dbb(%rip), %r9       # 0xdb9a
movl $0x1000, %esi           # imm = 0x1000
xorl %eax, %eax
callq 0x2140
movq %rbx, %rdi
callq 0x554e
movq %rbx, %rdi
callq 0x55db
movl 0x44(%rbx), %r8d
testl %r8d, %r8d
sete %al
orb 0xb(%rsp), %al
jne 0x3e43
leaq 0x10a0(%rbx), %rdi
movq 0x80(%rbx), %rcx
leaq 0x9d19(%rip), %rdx      # 0xdb39
leaq 0x9d37(%rip), %r9       # 0xdb5e
movl $0x1000, %esi           # imm = 0x1000
xorl %eax, %eax
callq 0x2140
movq %rbx, %rdi
callq 0x57a0
movq %rbx, %rdi
callq 0x582d
cmpl $0x0, 0x54(%rbx)
sete %al
orb 0xb(%rsp), %al
jne 0x3e88
leaq 0x40a0(%rbx), %rdi
movq 0x80(%rbx), %rcx
leaq 0x9ab9(%rip), %rdx      # 0xd91e
leaq 0x9d0e(%rip), %r8       # 0xdb7a
movl $0x1000, %esi           # imm = 0x1000
xorl %eax, %eax
callq 0x2140
movq %rbx, %rdi
callq 0x567b
movq %rbx, %rdi
callq 0x5708
movq 0x50d8(%rbx), %rdi
pushq $0x2
popq %rsi
xorl %eax, %eax
callq 0x22f0
cmpl $-0x1, %eax
je 0x42a1
movl %eax, %ebp
movq 0x28(%rbx), %rsi
pushq $0x3
popq %rdx
pushq $0x1
popq %rcx
xorl %edi, %edi
movl %eax, %r8d
xorl %r9d, %r9d
callq 0x2230
movq %rax, 0x50e8(%rbx)
cmpq $-0x1, %rax
je 0x42a1
movq 0x28(%rbx), %rsi
pushq $0x2
popq %rdx
movq %rax, %rdi
callq 0x22e0
movl %ebp, %edi
callq 0x2160
testl %eax, %eax
jne 0x42a1
movq 0x50e8(%rbx), %rax
movq %rax, 0x38(%rsp)
xorl %r14d, %r14d
leaq 0x40(%rsp), %r12
pushq $0x1
popq %rbp
cmpq 0x28(%rbx), %r14
jae 0x40f4
movq 0x50e8(%rbx), %rax
movzbl (%rax,%r14), %r13d
andl $0x7f, %r13d
movslq 0x4c(%rbx), %rsi
testq %rsi, %rsi
sete %al
orb 0xb(%rsp), %al
jne 0x3f6d
andl $0x0, 0x40(%rsp)
movq 0x50b0(%rbx), %rax
movq (%rax,%r13,8), %rcx
movq %r12, %rdi
movq %rbp, %rdx
callq 0x20a0
cmpl $0x1, %eax
jne 0x42a1
movslq 0x4c(%rbx), %rsi
movq %r12, %rdi
movq %rbp, %rdx
movq 0x30(%rsp), %rcx
callq 0x2390
cmpq $-0x1, %rax
je 0x42ad
movslq 0x50(%rbx), %rsi
testq %rsi, %rsi
sete %al
orb 0xb(%rsp), %al
movzbl %r13b, %r15d
jne 0x3fc3
andl $0x0, 0x40(%rsp)
movq 0x50b8(%rbx), %rax
movq (%rax,%r15,8), %rcx
movq %r12, %rdi
movq %rbp, %rdx
callq 0x20a0
cmpl $0x1, %eax
jne 0x42a1
movslq 0x50(%rbx), %rsi
movq %r12, %rdi
movq %rbp, %rdx
movq 0x28(%rsp), %rcx
callq 0x2390
cmpq $-0x1, %rax
je 0x42ad
movslq 0x44(%rbx), %rsi
testq %rsi, %rsi
sete %al
orb 0xb(%rsp), %al
jne 0x4021
andl $0x0, 0x40(%rsp)
movq 0x50a8(%rbx), %rax
movq (%rax,%r15,8), %rcx
movq %r12, %rdi
movq %rbp, %rdx
callq 0x20a0
cmpl $0x1, %eax
jne 0x42a1
movq 0x10(%rbx), %rax
movl (%rax,%r15,8), %eax
addl %eax, 0x40(%rsp)
movslq 0x44(%rbx), %rsi
movq %r12, %rdi
movq %rbp, %rdx
movq 0x20(%rsp), %rcx
callq 0x2390
cmpq $-0x1, %rax
je 0x42c5
movslq 0x48(%rbx), %rsi
testq %rsi, %rsi
sete %al
orb 0xb(%rsp), %al
jne 0x4050
movl %r13d, 0x40(%rsp)
movq %r12, %rdi
movq %rbp, %rdx
movq 0x18(%rsp), %rcx
callq 0x2390
cmpq $-0x1, %rax
je 0x42b9
cmpl $0x0, 0x54(%rbx)
setne %al
testb %al, 0xc(%rsp)
je 0x40a1
movb $0x0, 0x40(%rsp)
movq 0x50c0(%rbx), %rax
movq (%rax,%r15,8), %rcx
movq %r12, %rdi
movq %rbp, %rsi
movq %rbp, %rdx
callq 0x20a0
cmpl $0x1, %eax
jne 0x42a1
movq %r12, %rdi
movq %rbp, %rsi
movq %rbp, %rdx
movq 0x10(%rsp), %rcx
callq 0x2390
cmpq $-0x1, %rax
je 0x42d1
movq 0x38(%rsp), %rax
leaq (%rax,%r14), %r13
movq 0x50a0(%rbx), %rax
movq (%rax,%r15,8), %rcx
movq %r13, %rdi
movq %rbp, %rsi
movq %rbp, %rdx
callq 0x20a0
cmpl $0x1, %eax
jne 0x42a1
cmpb $0x0, 0xc(%rsp)
je 0x40e1
movzbl (%r13), %edi
callq 0xbb6a
movb %al, (%r13)
movq 0x5118(%rbx), %rax
incq (%rax,%r15,8)
incq %r14
jmp 0x3f01
movq %rbx, %rdi
callq 0x53db
cmpl $0x0, 0x4c(%rbx)
setne %al
testb %al, 0xc(%rsp)
je 0x4111
movq %rbx, %rdi
callq 0x5508
cmpl $0x0, 0x50(%rbx)
sete %al
orb 0xb(%rsp), %al
jne 0x4126
movq %rbx, %rdi
callq 0x5635
cmpl $0x0, 0x44(%rbx)
sete %al
orb 0xb(%rsp), %al
jne 0x413b
movq %rbx, %rdi
callq 0x5887
cmpl $0x0, 0x54(%rbx)
sete %al
orb 0xb(%rsp), %al
jne 0x4150
movq %rbx, %rdi
callq 0x575a
leaq 0xa0(%rbx), %rdi
pushq $0x1
popq %rsi
xorl %eax, %eax
callq 0x22f0
cmpl $-0x1, %eax
je 0x42a1
movl %eax, %ebp
movq 0x28(%rbx), %rdx
movq 0x30(%rbx), %rcx
movl %eax, %edi
movq 0x38(%rsp), %rsi
callq 0x5964
movl %ebp, %edi
callq 0x2160
testl %eax, %eax
jne 0x42a1
movq 0x50e8(%rbx), %rdi
movq 0x28(%rbx), %rsi
callq 0x2290
cmpl $-0x1, %eax
je 0x42a1
andq $0x0, 0x50e8(%rbx)
cmpl $0x0, 0x4c(%rbx)
sete %al
orb 0xb(%rsp), %al
jne 0x41db
movq 0x30(%rsp), %rdi
callq 0x20e0
testl %eax, %eax
jne 0x42dd
leaq 0x20a0(%rbx), %rdi
callq 0x2070
cmpl $0x0, 0x50(%rbx)
sete %al
orb 0xb(%rsp), %al
jne 0x4206
movq 0x28(%rsp), %rdi
callq 0x20e0
testl %eax, %eax
jne 0x42e9
leaq 0x30a0(%rbx), %rdi
callq 0x2070
cmpl $0x0, 0x44(%rbx)
sete %al
orb 0xb(%rsp), %al
jne 0x4231
movq 0x20(%rsp), %rdi
callq 0x20e0
testl %eax, %eax
jne 0x42f5
leaq 0x10a0(%rbx), %rdi
callq 0x2070
cmpl $0x0, 0x48(%rbx)
sete %al
orb 0xb(%rsp), %al
jne 0x4250
movq 0x18(%rsp), %rdi
callq 0x20e0
testl %eax, %eax
jne 0x4301
cmpl $0x0, 0x54(%rbx)
sete %al
orb 0xb(%rsp), %al
jne 0x428f
movq 0x10(%rsp), %rdi
callq 0x20e0
testl %eax, %eax
jne 0x430d
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 0x9a5e(%rip), %rdi      # 0xdd06
callq 0x35b7
leaq 0x9a61(%rip), %rdi      # 0xdd15
callq 0x35b7
leaq 0x9abd(%rip), %rdi      # 0xdd7d
callq 0x35b7
leaq 0x9a7c(%rip), %rdi      # 0xdd48
callq 0x35b7
leaq 0x9ae2(%rip), %rdi      # 0xddba
callq 0x35b7
leaq 0x9aff(%rip), %rdi      # 0xdde3
callq 0x35b7
leaq 0x9b23(%rip), %rdi      # 0xde13
callq 0x35b7
leaq 0x9b4c(%rip), %rdi      # 0xde48
callq 0x35b7
leaq 0x9b72(%rip), %rdi      # 0xde7a
callq 0x35b7
leaq 0x9ba0(%rip), %rdi      # 0xdeb4
callq 0x35b7