// File: /workspace/github_c_makefile_star2_O2/felipelouza[P]egap/util.c
// Function: mergeBWT8
void mergeBWT8(g_data *g, bool lastRound)
{
  if(sizeof(symbol)>sizeof(palette)) die("Sorry, alphabet is too large (mergeBWT8)");
  symbol *bwtout = (symbol *) g->mergeColor;   // merged BWT stored in mergeColor
  assert(!g->lcpMerge);
  FILE *daOutFile=NULL;
  FILE *saOutFile=NULL;
  FILE *slOutFile=NULL;
  FILE *qsOutFile=NULL;

  check_g_data(g);
  array_clear(g->inCnt,g->numBwt,0); // clear counter inside each bwt
  if(g->outputSA && lastRound){
    saOutFile = openSAFile(g);    
    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){
    slOutFile = openSLFile(g);    
    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){
    daOutFile = openDAFile(g);    
    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){
    qsOutFile = openQSFile(g);    
    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 QS
  }
  if(g->extMem) {
    open_bw_files(g);     // open files in read/write mode
    rewind_bw_files(g);   // set file pointers at the beginning of each BWT 
  }
  int shift = 3; (void) shift;  // shift is not used outside assertions
  for (customInt i = 0; i < g->mergeLen; ++i) {
    int currentColor = g->mergeColor[i] & 0x7;
    assert(currentColor == ((g->mergeColor[i]>>shift) & 0x7)); // we must have mergeColor==newMergeColor
    assert(currentColor < g->numBwt);
    // check that all LCP values have been obtained
    if(g->lcpCompute && lastRound)
      assert( ((g->mergeColor[i]>>2*shift) & 3)==3);    
    // 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 Sufix Array file");   
    } 
    if(g->outputSL && lastRound){ 
      int sl_value=0;
      int e = fread(&sl_value, g->outputSL, 1, g->saf[currentColor]);
      if(e!=1) die(__func__);
      if(fwrite(&sl_value, g->outputSL, 1, slOutFile)==EOF)
        die("mergeBWT128ext: Error writing to Sufixes' lengths 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__);
      //if(fputc(currentColor, daOutFile)==EOF)
      da_value+=g->bwtDocs[currentColor];
      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->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]
    if(g->extMem) {
      int e = fread(bwtout+i,sizeof(symbol),1,g->bwf[currentColor]);
      if(e!=1) die(__func__);
    }      
    else bwtout[i] = g->bws[currentColor][g->inCnt[currentColor]];
    if(lastRound) bwtout[i] = alpha_enlarge(bwtout[i]); 
    g->inCnt[currentColor]++; // one more char read from currentColor BWT
  }
  // final check on the merging 
  for(int i=0;i<g->numBwt;i++) assert(g->inCnt[i]==g->bwtLen[i]);
  if(g->extMem) close_bw_files(g);
  // close suffix array file 
  if(g->outputSA && lastRound){
    if(fclose(saOutFile)!=0) die("mergeBWT8: Error closing Suffix Array file");       
    remove(g->safname);
  }
  // close suffixes' lengths file 
  if(g->outputSL && lastRound){
    if(fclose(slOutFile)!=0) die("mergeBWT8: Error closing Suffixes' lengths file");       
    remove(g->slfname);
  }
  // close document array file 
  if(g->outputDA && lastRound){
    if(fclose(daOutFile)!=0) die("mergeBWT8: Error closing Document Array file");       
    remove(g->dafname);
  }
  // close suffix array file 
  if(g->outputQS && lastRound){
    if(fclose(qsOutFile)!=0) die("mergeBWT8: Error closing QS file");       
    remove(g->qsfname);
  }

  // merging done: copy back to g->bws[0] or to file
  if(g->extMem) {
    if(g->verbose>1) printf("Copy back to file. Bytes: %zu, offset %zu\n",g->mergeLen, g->symb_offset);
    int 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__);
  }
  else 
    memcpy(g->bws[0],bwtout,g->mergeLen*sizeof(symbol));
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movl %esi, 0x14(%rsp)
movq %rdi, %r14
movq 0x50e8(%rdi), %rax
movq %rax, 0x8(%rsp)
movq 0x5118(%rdi), %rax
movslq 0x20(%rdi), %rcx
xorl %edx, %edx
cmpq %rdx, %rcx
je 0x45f5
andq $0x0, (%rax,%rdx,8)
incq %rdx
jmp 0x45e6
cmpl $0x0, 0x4c(%r14)
sete %al
movl 0x14(%rsp), %ecx
movl %ecx, %r13d
xorb $0x1, %r13b
orb %r13b, %al
jne 0x4658
movq %r14, %rdi
callq 0x4319
movq %rax, 0x30(%rsp)
leaq 0x20a0(%r14), %rdi
movq 0x80(%r14), %rcx
movl 0x4c(%r14), %r8d
leaq 0x9506(%rip), %rdx      # 0xdb39
leaq 0x9508(%rip), %r9       # 0xdb42
movl $0x1000, %esi           # imm = 0x1000
xorl %eax, %eax
callq 0x2140
movq %r14, %rdi
callq 0x5421
movq %r14, %rdi
callq 0x54ae
jmp 0x4661
movq $0x0, 0x30(%rsp)
cmpl $0x0, 0x50(%r14)
sete %al
orb %r13b, %al
jne 0x46b9
movq %r14, %rdi
callq 0x438d
movq %rax, 0x28(%rsp)
leaq 0x30a0(%r14), %rdi
movq 0x80(%r14), %rcx
movl 0x50(%r14), %r8d
leaq 0x94a5(%rip), %rdx      # 0xdb39
leaq 0x94ff(%rip), %r9       # 0xdb9a
movl $0x1000, %esi           # imm = 0x1000
xorl %eax, %eax
callq 0x2140
movq %r14, %rdi
callq 0x554e
movq %r14, %rdi
callq 0x55db
jmp 0x46c2
movq $0x0, 0x28(%rsp)
cmpl $0x0, 0x44(%r14)
sete %al
orb %r13b, %al
jne 0x471a
movq %r14, %rdi
callq 0x3b96
movq %rax, 0x20(%rsp)
leaq 0x10a0(%r14), %rdi
movq 0x80(%r14), %rcx
movl 0x44(%r14), %r8d
leaq 0x9444(%rip), %rdx      # 0xdb39
leaq 0x9462(%rip), %r9       # 0xdb5e
movl $0x1000, %esi           # imm = 0x1000
xorl %eax, %eax
callq 0x2140
movq %r14, %rdi
callq 0x57a0
movq %r14, %rdi
callq 0x582d
jmp 0x4723
movq $0x0, 0x20(%rsp)
cmpl $0x0, 0x54(%r14)
sete %al
orb %r13b, %al
jne 0x4777
movq %r14, %rdi
callq 0x4401
movq %rax, 0x18(%rsp)
leaq 0x40a0(%r14), %rdi
movq 0x80(%r14), %rcx
leaq 0x91cc(%rip), %rdx      # 0xd91e
leaq 0x9421(%rip), %r8       # 0xdb7a
movl $0x1000, %esi           # imm = 0x1000
xorl %eax, %eax
callq 0x2140
movq %r14, %rdi
callq 0x567b
movq %r14, %rdi
callq 0x5708
jmp 0x4780
movq $0x0, 0x18(%rsp)
cmpb $0x1, 0x69(%r14)
jne 0x4797
movq %r14, %rdi
callq 0x52fc
movq %r14, %rdi
callq 0x5389
xorl %ebx, %ebx
pushq $0x1
popq %r12
leaq 0x4(%rsp), %r15
movb %r13b, 0x2(%rsp)
cmpq 0x28(%r14), %rbx
jae 0x49e0
movq 0x50e8(%r14), %rax
movzbl (%rax,%rbx), %ebp
andl $0x7, %ebp
movslq 0x4c(%r14), %rsi
testq %rsi, %rsi
sete %al
orb %r13b, %al
movq %rbx, 0x40(%rsp)
jne 0x482f
andl $0x0, 0x3c(%rsp)
movq 0x50b0(%r14), %rax
movq (%rax,%rbp,8), %rcx
leaq 0x3c(%rsp), %rbx
movq %rbx, %rdi
movq %r12, %rdx
callq 0x20a0
cmpl $0x1, %eax
jne 0x4b2a
movq %r12, %rdx
movq %r14, %r15
movslq 0x4c(%r14), %rsi
movq %rbx, %rdi
movq 0x30(%rsp), %rcx
callq 0x2390
cmpq $-0x1, %rax
je 0x4b4e
movb 0x2(%rsp), %r13b
movq 0x40(%rsp), %rbx
movq %r15, %r14
leaq 0x4(%rsp), %r15
movslq 0x50(%r14), %rsi
testq %rsi, %rsi
sete %al
orb %r13b, %al
movzbl %bpl, %ebp
jne 0x488e
andl $0x0, 0x38(%rsp)
movq 0x50b0(%r14), %rax
movq (%rax,%rbp,8), %rcx
leaq 0x38(%rsp), %r15
movq %r15, %rdi
movq %r12, %rdx
callq 0x20a0
cmpl $0x1, %eax
jne 0x4b2a
movslq 0x50(%r14), %rsi
movq %r15, %rdi
movq %r12, %rdx
movq 0x28(%rsp), %rcx
callq 0x2390
cmpq $-0x1, %rax
je 0x4b5a
leaq 0x4(%rsp), %r15
movslq 0x44(%r14), %rsi
testq %rsi, %rsi
sete %al
orb %r13b, %al
jne 0x48ea
andl $0x0, 0x4(%rsp)
movq 0x50a8(%r14), %rax
movq (%rax,%rbp,8), %rcx
movq %r15, %rdi
movq %r12, %rdx
callq 0x20a0
cmpl $0x1, %eax
jne 0x4b2a
movq 0x10(%r14), %rax
movl (%rax,%rbp,8), %eax
addl %eax, 0x4(%rsp)
movslq 0x44(%r14), %rsi
movq %r15, %rdi
movq %r12, %rdx
movq 0x20(%rsp), %rcx
callq 0x2390
cmpq $-0x1, %rax
je 0x4b36
cmpl $0x0, 0x54(%r14)
sete %al
orb %r13b, %al
jne 0x495a
movq %r15, %rbx
movl %r13d, %r15d
movb $0x0, 0x3(%rsp)
movq 0x50c0(%r14), %rax
movq (%rax,%rbp,8), %rcx
leaq 0x3(%rsp), %r13
movq %r13, %rdi
movq %r12, %rsi
movq %r12, %rdx
callq 0x20a0
cmpl $0x1, %eax
jne 0x4b2a
movq %r13, %rdi
movq %r12, %rsi
movq %r12, %r13
movq %r12, %rdx
movq 0x18(%rsp), %rcx
callq 0x2390
cmpq $-0x1, %rax
je 0x4b42
movl %r15d, %eax
movq %rbx, %r15
movq %r13, %r12
movl %eax, %r13d
movq 0x40(%rsp), %rbx
cmpb $0x1, 0x69(%r14)
jne 0x498a
movq 0x8(%rsp), %rax
leaq (%rax,%rbx), %rdi
movq 0x50a0(%r14), %rax
movq (%rax,%rbp,8), %rcx
movq %r12, %rsi
movq %r12, %rdx
callq 0x20a0
cmpl $0x1, %eax
je 0x49ae
jmp 0x4b2a
movq (%r14), %rax
leal (,%rbp,8), %ecx
movq (%rax,%rcx), %rax
movq 0x5118(%r14), %rdx
movq (%rdx,%rcx), %rcx
movb (%rax,%rcx), %al
movq 0x8(%rsp), %rcx
movb %al, (%rcx,%rbx)
cmpb $0x0, 0x14(%rsp)
je 0x49cd
movq 0x8(%rsp), %r15
movzbl (%r15,%rbx), %edi
callq 0xbb6a
movb %al, (%r15,%rbx)
leaq 0x4(%rsp), %r15
movq 0x5118(%r14), %rax
incq (%rax,%rbp,8)
incq %rbx
jmp 0x47a7
cmpb $0x0, 0x69(%r14)
je 0x49ef
movq %r14, %rdi
callq 0x53db
cmpl $0x0, 0x4c(%r14)
sete %al
orb %r13b, %al
jne 0x4a1a
movq 0x30(%rsp), %rdi
callq 0x20e0
testl %eax, %eax
jne 0x4b66
leaq 0x20a0(%r14), %rdi
callq 0x2070
cmpl $0x0, 0x50(%r14)
sete %al
orb %r13b, %al
jne 0x4a45
movq 0x28(%rsp), %rdi
callq 0x20e0
testl %eax, %eax
jne 0x4b72
leaq 0x30a0(%r14), %rdi
callq 0x2070
cmpl $0x0, 0x44(%r14)
sete %al
orb %r13b, %al
jne 0x4a70
movq 0x20(%rsp), %rdi
callq 0x20e0
testl %eax, %eax
jne 0x4b7e
leaq 0x10a0(%r14), %rdi
callq 0x2070
cmpl $0x0, 0x54(%r14)
sete %al
orb %r13b, %al
jne 0x4a9b
movq 0x18(%rsp), %rdi
callq 0x20e0
testl %eax, %eax
jne 0x4b8a
leaq 0x40a0(%r14), %rdi
callq 0x2070
cmpb $0x1, 0x69(%r14)
jne 0x4b08
cmpl $0x2, 0x94(%r14)
jl 0x4ac2
movq 0x28(%r14), %rsi
movq 0x30(%r14), %rdx
leaq 0x959c(%rip), %rdi      # 0xe057
xorl %eax, %eax
callq 0x2100
leaq 0xa0(%r14), %rdi
pushq $0x1
popq %rsi
xorl %eax, %eax
callq 0x22f0
cmpl $-0x1, %eax
je 0x4b2a
movl %eax, %ebp
movq 0x28(%r14), %rdx
movq 0x30(%r14), %rcx
movl %eax, %edi
movq 0x8(%rsp), %rsi
callq 0x5964
movl %ebp, %edi
callq 0x2160
testl %eax, %eax
jne 0x4b2a
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq (%r14), %rax
movq 0x28(%r14), %rdx
movq (%rax), %rdi
movq 0x8(%rsp), %rsi
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x21f0
leaq 0x940a(%rip), %rdi      # 0xdf3b
callq 0x35b7
leaq 0x920b(%rip), %rdi      # 0xdd48
callq 0x35b7
leaq 0x9271(%rip), %rdi      # 0xddba
callq 0x35b7
leaq 0x93f0(%rip), %rdi      # 0xdf45
callq 0x35b7
leaq 0x9416(%rip), %rdi      # 0xdf77
callq 0x35b7
leaq 0x9441(%rip), %rdi      # 0xdfae
callq 0x35b7
leaq 0x9460(%rip), %rdi      # 0xdfd9
callq 0x35b7
leaq 0x9484(%rip), %rdi      # 0xe009
callq 0x35b7
leaq 0x94a5(%rip), %rdi      # 0xe036
callq 0x35b7