// File: /workspace/github_c_makefile_star2_O3/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, 0xc(%rsp)
movq %rdi, %r14
movq 0x50e8(%rdi), %rbp
movslq 0x20(%rdi), %rdx
testq %rdx, %rdx
je 0x4a80
movq 0x5118(%r14), %rdi
shlq $0x3, %rdx
xorl %esi, %esi
callq 0x2150
cmpl $0x0, 0x4c(%r14)
sete %al
movl 0xc(%rsp), %ecx
movl %ecx, %r13d
xorb $0x1, %r13b
orb %r13b, %al
jne 0x4ae3
movq %r14, %rdi
callq 0x4797
movq %rax, 0x30(%rsp)
leaq 0x20a0(%r14), %rdi
movq 0x80(%r14), %rcx
movl 0x4c(%r14), %r8d
leaq 0xa0b6(%rip), %rdx      # 0xeb74
leaq 0xa0b8(%rip), %r9       # 0xeb7d
movl $0x1000, %esi           # imm = 0x1000
xorl %eax, %eax
callq 0x2140
movq %r14, %rdi
callq 0x592a
movq %r14, %rdi
callq 0x59c1
jmp 0x4aec
movq $0x0, 0x30(%rsp)
cmpl $0x0, 0x50(%r14)
sete %al
orb %r13b, %al
jne 0x4b44
movq %r14, %rdi
callq 0x480b
movq %rax, 0x28(%rsp)
leaq 0x30a0(%r14), %rdi
movq 0x80(%r14), %rcx
movl 0x50(%r14), %r8d
leaq 0xa055(%rip), %rdx      # 0xeb74
leaq 0xa0af(%rip), %r9       # 0xebd5
movl $0x1000, %esi           # imm = 0x1000
xorl %eax, %eax
callq 0x2140
movq %r14, %rdi
callq 0x5a70
movq %r14, %rdi
callq 0x5b07
jmp 0x4b4d
movq $0x0, 0x28(%rsp)
cmpl $0x0, 0x44(%r14)
sete %al
orb %r13b, %al
jne 0x4ba5
movq %r14, %rdi
callq 0x3fea
movq %rax, 0x20(%rsp)
leaq 0x10a0(%r14), %rdi
movq 0x80(%r14), %rcx
movl 0x44(%r14), %r8d
leaq 0x9ff4(%rip), %rdx      # 0xeb74
leaq 0xa012(%rip), %r9       # 0xeb99
movl $0x1000, %esi           # imm = 0x1000
xorl %eax, %eax
callq 0x2140
movq %r14, %rdi
callq 0x5cf4
movq %r14, %rdi
callq 0x5d8b
jmp 0x4bae
movq $0x0, 0x20(%rsp)
cmpl $0x0, 0x54(%r14)
sete %al
orb %r13b, %al
jne 0x4c02
movq %r14, %rdi
callq 0x487f
movq %rax, 0x18(%rsp)
leaq 0x40a0(%r14), %rdi
movq 0x80(%r14), %rcx
leaq 0x9d41(%rip), %rdx      # 0xe91e
leaq 0x9fd1(%rip), %r8       # 0xebb5
movl $0x1000, %esi           # imm = 0x1000
xorl %eax, %eax
callq 0x2140
movq %r14, %rdi
callq 0x5bb6
movq %r14, %rdi
callq 0x5c4d
jmp 0x4c0b
movq $0x0, 0x18(%rsp)
cmpb $0x1, 0x69(%r14)
jne 0x4c22
movq %r14, %rdi
callq 0x57ec
movq %r14, %rdi
callq 0x5883
cmpq $0x0, 0x28(%r14)
movq %rbp, 0x40(%rsp)
je 0x4ea4
xorl %r15d, %r15d
leaq 0x8(%rsp), %rbx
movb %r13b, 0x7(%rsp)
movq 0x50e8(%r14), %rax
movzbl (%rax,%r15), %r12d
andl $0x7, %r12d
movslq 0x4c(%r14), %rsi
testq %rsi, %rsi
sete %al
orb %r13b, %al
jne 0x4cb1
movl $0x0, 0x3c(%rsp)
movq 0x50b0(%r14), %rax
movq (%rax,%r12,8), %rcx
movl $0x1, %edx
leaq 0x3c(%rsp), %rbp
movq %rbp, %rdi
callq 0x20a0
cmpl $0x1, %eax
jne 0x4fee
movslq 0x4c(%r14), %rsi
movl $0x1, %edx
movq %rbp, %rdi
movq 0x30(%rsp), %rcx
callq 0x2390
cmpq $-0x1, %rax
je 0x5012
movq 0x40(%rsp), %rbp
movslq 0x50(%r14), %rsi
testq %rsi, %rsi
sete %al
orb %r13b, %al
movzbl %r12b, %ecx
movq %rcx, 0x10(%rsp)
jne 0x4d33
movl %r13d, %ebx
movq %rbp, %r13
movl $0x0, 0x38(%rsp)
movq 0x50b0(%r14), %rax
movq (%rax,%rcx,8), %rcx
movl $0x1, %edx
leaq 0x38(%rsp), %rbp
movq %rbp, %rdi
callq 0x20a0
cmpl $0x1, %eax
jne 0x4fee
movq %r14, %r12
movslq 0x50(%r14), %rsi
movl $0x1, %edx
movq %rbp, %rdi
movq 0x28(%rsp), %rcx
callq 0x2390
cmpq $-0x1, %rax
je 0x4ffa
movq %r13, %rbp
movl %ebx, %r13d
leaq 0x8(%rsp), %rbx
movq %r12, %r14
movq 0x10(%rsp), %rcx
movslq 0x44(%r14), %rsi
testq %rsi, %rsi
sete %al
orb %r13b, %al
leaq 0x6(%rsp), %r12
jne 0x4dc2
movq %rbx, %r12
movq %rbp, %r13
movl $0x0, 0x8(%rsp)
movq 0x50a8(%r14), %rax
movq %rcx, %rbp
movq (%rax,%rcx,8), %rcx
movl $0x1, %edx
movq %rbx, %rdi
callq 0x20a0
cmpl $0x1, %eax
jne 0x4fee
movq 0x10(%r14), %rax
movl (%rax,%rbp,8), %eax
addl %eax, 0x8(%rsp)
movq %r14, %rbp
movslq 0x44(%r14), %rsi
movl $0x1, %edx
movq %r12, %rbx
movq %r12, %rdi
movq 0x20(%rsp), %rcx
callq 0x2390
cmpq $-0x1, %rax
je 0x501e
movq 0x10(%rsp), %rcx
movq %r13, %rax
movb 0x7(%rsp), %r13b
movq %rbp, %r14
movq %rax, %rbp
leaq 0x6(%rsp), %r12
cmpl $0x0, 0x54(%r14)
sete %al
orb %r13b, %al
jne 0x4e20
movb $0x0, 0x6(%rsp)
movq 0x50c0(%r14), %rax
movq (%rax,%rcx,8), %rcx
movl $0x1, %esi
movl $0x1, %edx
movq %r12, %rdi
callq 0x20a0
cmpl $0x1, %eax
jne 0x4fee
movl $0x1, %esi
movl $0x1, %edx
movq %r12, %rdi
movq 0x18(%rsp), %rcx
callq 0x2390
cmpq $-0x1, %rax
je 0x5006
movq 0x10(%rsp), %rcx
cmpb $0x1, 0x69(%r14)
jne 0x4e4f
leaq (%r15,%rbp), %rdi
movq 0x50a0(%r14), %rax
movq (%rax,%rcx,8), %rcx
movl $0x1, %esi
movl $0x1, %edx
callq 0x20a0
cmpl $0x1, %eax
je 0x4e70
jmp 0x4fee
movq (%r14), %rax
leal (,%rcx,8), %ecx
movq (%rax,%rcx), %rax
movq 0x5118(%r14), %rdx
movq (%rdx,%rcx), %rcx
movb (%rax,%rcx), %al
movb %al, (%rbp,%r15)
cmpb $0x0, 0xc(%rsp)
je 0x4e87
movzbl (%rbp,%r15), %edi
callq 0xc5af
movb %al, (%rbp,%r15)
movq 0x5118(%r14), %rax
movq 0x10(%rsp), %rcx
incq (%rax,%rcx,8)
incq %r15
cmpq 0x28(%r14), %r15
jb 0x4c3f
cmpb $0x0, 0x69(%r14)
je 0x4eb3
movq %r14, %rdi
callq 0x58d9
cmpl $0x0, 0x4c(%r14)
sete %al
orb %r13b, %al
jne 0x4ede
movq 0x30(%rsp), %rdi
callq 0x20e0
testl %eax, %eax
jne 0x502a
leaq 0x20a0(%r14), %rdi
callq 0x2070
cmpl $0x0, 0x50(%r14)
sete %al
orb %r13b, %al
jne 0x4f09
movq 0x28(%rsp), %rdi
callq 0x20e0
testl %eax, %eax
jne 0x5036
leaq 0x30a0(%r14), %rdi
callq 0x2070
cmpl $0x0, 0x44(%r14)
sete %al
orb %r13b, %al
jne 0x4f34
movq 0x20(%rsp), %rdi
callq 0x20e0
testl %eax, %eax
jne 0x5042
leaq 0x10a0(%r14), %rdi
callq 0x2070
cmpl $0x0, 0x54(%r14)
sete %al
orb %r13b, %al
jne 0x4f5f
movq 0x18(%rsp), %rdi
callq 0x20e0
testl %eax, %eax
jne 0x504e
leaq 0x40a0(%r14), %rdi
callq 0x2070
cmpb $0x1, 0x69(%r14)
jne 0x4fce
cmpl $0x2, 0x94(%r14)
jl 0x4f86
movq 0x28(%r14), %rsi
movq 0x30(%r14), %rdx
leaq 0xa113(%rip), %rdi      # 0xf092
xorl %eax, %eax
callq 0x2100
leaq 0xa0(%r14), %rdi
movl $0x1, %esi
xorl %eax, %eax
callq 0x22f0
cmpl $-0x1, %eax
je 0x4fee
movl %eax, %ebp
movq 0x28(%r14), %rdx
movq 0x30(%r14), %rcx
movl %eax, %edi
movq 0x40(%rsp), %rsi
callq 0x5ed1
movl %ebp, %edi
callq 0x2160
testl %eax, %eax
jne 0x4fee
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 %rbp, %rsi
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x21f0
leaq 0x9f81(%rip), %rdi      # 0xef76
callq 0x39fc
leaq 0x9fb1(%rip), %rdi      # 0xefb2
callq 0x39fc
leaq 0x9de8(%rip), %rdi      # 0xedf5
callq 0x39fc
leaq 0x9f67(%rip), %rdi      # 0xef80
callq 0x39fc
leaq 0x9d5e(%rip), %rdi      # 0xed83
callq 0x39fc
leaq 0x9fb8(%rip), %rdi      # 0xefe9
callq 0x39fc
leaq 0x9fd7(%rip), %rdi      # 0xf014
callq 0x39fc
leaq 0x9ffb(%rip), %rdi      # 0xf044
callq 0x39fc
leaq 0xa01c(%rip), %rdi      # 0xf071
callq 0x39fc