// File: /workspace/github_c_makefile_star2_O2/sheneman[P]clearcut/clearcut.c
// Function: NJ_collapse
static inline
void
NJ_collapse(DMAT *dmat,
	    NJ_VERTEX *vertex,
	    long int a,
	    long int b) {


  long int i;     /* index used for looping */
  long int size;  /* size of dmat --> reduce pointer dereferencing */
  float a2clade;  /* distance from a to the new node that joins a and b */
  float b2clade;  /* distance from b to the new node that joins a and b */
  float cval;     /* stores distance information during loop */
  float *vptr;    /* pointer to elements in first row of dist matrix */
  float *ptra;    /* pointer to elements in row a of distance matrix */
  float *ptrb;    /* pointer to elements in row b of distance matrix */

  float *val, *r, *r2;  /* simply used to limit pointer dereferencing */


  /* We must assume that a < b */
  if(a >= b) {
    fprintf(stderr, "Clearcut: (a<b) constraint check failed in NJ_collapse()\n");
    exit(0);
  }

  /* some shortcuts to help limit dereferencing */
  val  = dmat->val;
  r    = dmat->r;
  r2   = dmat->r2;
  size = dmat->size;

  /* compute the distance from the clade components (a, b) to the new node */
  a2clade = 
    ( (val[NJ_MAP(a, b, size)]) + (dmat->r2[a] - dmat->r2[b]) ) / 2.0;  
  b2clade = 
    ( (val[NJ_MAP(a, b, size)]) + (dmat->r2[b] - dmat->r2[a]) ) / 2.0;  


  r[a] = 0.0;  /* we are removing row a, so clear dist. in r */

  /* 
   * Fill the horizontal part of the "a" row and finish computing r and r2 
   * we handle the horizontal component first to maximize cache locality
   */
  ptra = &(val[NJ_MAP(a,   a+1, size)]);   /* start ptra at the horiz. of a  */
  ptrb = &(val[NJ_MAP(a+1, b,   size)]);   /* start ptrb at comparable place */
  for(i=a+1;i<size;i++) {

    /* 
     * Compute distance from new internal node to others in 
     * the distance matrix.
     */
    cval = 
      ( (*ptra - a2clade) +
	(*ptrb - b2clade) ) / 2.0;

    /* incr.  row b pointer differently depending on where i is in loop */
    if(i<b) {
      ptrb += size-i-1;  /* traverse vertically  by incrementing by row */
    } else {
      ptrb++;            /* traverse horiz. by incrementing by column   */
    }

    /* assign the newly computed distance and increment a ptr by a column */
    *(ptra++) = cval;  

    /* accumulate the distance onto the r vector */
    r[a] += cval;
    r[i] += cval;
    
    /* scale r2 on the fly here */
    r2[i] = r[i]/(float)(size-3);
  }

  /* fill the vertical part of the "a" column and finish computing r and r2 */ 
  ptra = val + a;  /* start at the top of the columb for "a" */
  ptrb = val + b;  /* start at the top of the columb for "b" */
  for(i=0;i<a;i++) {

    /* 
     * Compute distance from new internal node to others in 
     * the distance matrix.
     */
    cval = 
      ( (*ptra - a2clade) + 
	(*ptrb - b2clade) ) / 2.0;
    
    /* assign the newly computed distance and increment a ptr by a column */
    *ptra = cval;

    /* accumulate the distance onto the r vector */
    r[a] += cval;
    r[i] += cval;

    /* scale r2 on the fly here */
    r2[i] = r[i]/(float)(size-3);

    /* here, always increment by an entire row */
    ptra += size-i-1;
    ptrb += size-i-1;
  }


  /* scale r2 on the fly here */
  r2[a] = r[a]/(float)(size-3);



  /* 
   * Copy row 0 into row b.  Again, the code is structured into two 
   * loops to maximize cache locality for writes along the horizontal
   * component of row b.
   */
  vptr = val;
  ptrb = val + b;
  for(i=0;i<b;i++) {
    *ptrb = *(vptr++);
    ptrb += size-i-1;
  }
  vptr++;  /* skip over the diagonal */
  ptrb = &(val[NJ_MAP(b, b+1, size)]); 
  for(i=b+1;i<size;i++) {
    *(ptrb++) = *(vptr++);
  }

  /* 
   * Collapse r here by copying contents of r[0] into r[b] and
   * incrementing pointer to the beginning of r by one row
   */
  r[b]    = r[0];
  dmat->r = r+1;


  /* 
   * Collapse r2 here by copying contents of r2[0] into r2[b] and
   * incrementing pointer to the beginning of r2 by one row
   */
  r2[b]    = r2[0];
  dmat->r2 = r2+1;

  /* increment dmat pointer to next row */
  dmat->val += size;
  
  /* decrement the total size of the distance matrix by one row */
  dmat->size--;

  return;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
cmpq %rdx, %rsi
jge 0x34e6
movq %rdx, %rcx
movq 0x8(%rdi), %r9
movq 0x18(%rdi), %r10
movq 0x28(%rdi), %rbx
movq 0x30(%rdi), %r11
movq %rsi, %rax
notq %rax
leaq (%rax,%r9,2), %rax
imulq %rsi, %rax
pushq $0x2
popq %r14
cqto
idivq %r14
leaq (%r10,%rax,4), %r15
movss (%r11,%rcx,4), %xmm0
movss (%r11,%rsi,4), %xmm1
movaps %xmm1, %xmm2
unpcklps %xmm0, %xmm2            # xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1]
unpcklps %xmm1, %xmm0            # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
subps %xmm0, %xmm2
movss (%r15,%rcx,4), %xmm0
shufps $0x0, %xmm0, %xmm0      # xmm0 = xmm0[0,0,0,0]
addps %xmm2, %xmm0
mulps 0x3d36(%rip), %xmm0     # 0x7030
leaq (%r9,%r9), %r8
andl $0x0, (%rbx,%rsi,4)
leaq 0x1(%rsi), %r12
movq %r8, %rax
subq %rsi, %rax
addq $-0x2, %rax
imulq %r12, %rax
cqto
idivq %r14
leaq (%r10,%rax,4), %rax
leaq (%rax,%rcx,4), %rax
leaq -0x3(%r9), %rdx
cvtsi2ss %rdx, %xmm1
movq %r9, %rdx
subq %rsi, %rdx
leaq -0x8(,%rdx,4), %rdx
movss 0x3cd0(%rip), %xmm2     # 0x7010
pushq $0x4
popq %r13
cmpq %r9, %r12
jge 0x33a8
movss (%r15,%r12,4), %xmm3
movss (%rax), %xmm4
unpcklps %xmm4, %xmm3            # xmm3 = xmm3[0],xmm4[0],xmm3[1],xmm4[1]
subps %xmm0, %xmm3
movaps %xmm3, %xmm4
shufps $0x55, %xmm3, %xmm4     # xmm4 = xmm4[1,1],xmm3[1,1]
addss %xmm3, %xmm4
mulss %xmm2, %xmm4
cmpq %rcx, %r12
movq %r13, %rbp
cmovlq %rdx, %rbp
addq %rbp, %rax
movss %xmm4, (%r15,%r12,4)
movss (%rbx,%rsi,4), %xmm3
addss %xmm4, %xmm3
movss %xmm3, (%rbx,%rsi,4)
addss (%rbx,%r12,4), %xmm4
movss %xmm4, (%rbx,%r12,4)
divss %xmm1, %xmm4
movss %xmm4, (%r11,%r12,4)
incq %r12
addq $-0x4, %rdx
jmp 0x3344
leaq (%r10,%rsi,4), %rdx
leaq (%r10,%rcx,4), %rax
xorl %r15d, %r15d
testq %rsi, %rsi
movl $0x0, %r12d
cmovgq %rsi, %r12
leaq -0x1(%r9), %r13
movq %rax, %rbp
cmpq %r15, %r12
je 0x3423
movss (%rbp), %xmm3
movss (%rdx), %xmm4
unpcklps %xmm3, %xmm4            # xmm4 = xmm4[0],xmm3[0],xmm4[1],xmm3[1]
subps %xmm0, %xmm4
movaps %xmm4, %xmm3
shufps $0x55, %xmm4, %xmm3     # xmm3 = xmm3[1,1],xmm4[1,1]
addss %xmm4, %xmm3
mulss %xmm2, %xmm3
movss %xmm3, (%rdx)
movss (%rbx,%rsi,4), %xmm4
addss %xmm3, %xmm4
movss %xmm4, (%rbx,%rsi,4)
addss (%rbx,%r15,4), %xmm3
movss %xmm3, (%rbx,%r15,4)
divss %xmm1, %xmm3
movss %xmm3, (%r11,%r15,4)
leaq (%rdx,%r13,4), %rdx
leaq (%rbp,%r13,4), %rbp
incq %r15
decq %r13
jmp 0x33c7
movss (%rbx,%rsi,4), %xmm0
divss %xmm1, %xmm0
movss %xmm0, (%r11,%rsi,4)
xorl %edx, %edx
testq %rcx, %rcx
cmovgq %rcx, %rdx
pushq $-0x1
popq %r15
movq %r10, %rsi
leaq (%rdx,%r15), %r12
cmpq $-0x1, %r12
je 0x3465
movss (%rsi), %xmm0
addq $0x4, %rsi
movss %xmm0, (%rax)
leaq (%r9,%r15), %r12
leaq (%rax,%r12,4), %rax
decq %r15
jmp 0x3442
movq %rcx, %rax
notq %rax
addq %rax, %r8
imulq %rcx, %r8
movq %r8, %rax
cqto
idivq %r14
leaq (,%rcx,4), %rdx
leaq (%rdx,%rax,4), %rax
addq %r10, %rax
pushq $0x1
popq %rdx
leaq (%rcx,%rdx), %r8
cmpq %r9, %r8
jge 0x34a4
movss (%rsi,%rdx,4), %xmm0
movss %xmm0, (%rax,%rdx,4)
incq %rdx
jmp 0x348c
movss (%rbx), %xmm0
movss %xmm0, (%rbx,%rcx,4)
addq $0x4, %rbx
movq %rbx, 0x28(%rdi)
movss (%r11), %xmm0
movss %xmm0, (%r11,%rcx,4)
addq $0x4, %r11
movq %r11, 0x30(%rdi)
leaq (%r10,%r9,4), %rax
movq %rax, 0x18(%rdi)
decq %r9
movq %r9, 0x8(%rdi)
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x8b0b(%rip), %rax      # 0xbff8
movq (%rax), %rcx
leaq 0x3e23(%rip), %rdi      # 0x731a
pushq $0x39
popq %rsi
pushq $0x1
popq %rdx
callq 0x2230
xorl %edi, %edi
callq 0x2220