// File: /workspace/github_c_makefile_star2_O0/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
movq %rsp, %rbp
subq $0xa0, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq -0x18(%rbp), %rax
cmpq -0x20(%rbp), %rax
jl 0x3c74
movq 0xb39c(%rip), %rax      # 0xeff8
movq (%rax), %rdi
leaq 0x76e1(%rip), %rsi      # 0xb347
movb $0x0, %al
callq 0x2150
xorl %edi, %edi
callq 0x2200
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x60(%rbp)
movq -0x8(%rbp), %rax
movq 0x28(%rax), %rax
movq %rax, -0x68(%rbp)
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movq %rax, -0x70(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x60(%rbp), %rax
movq %rax, -0x90(%rbp)
movq -0x18(%rbp), %rdi
movq -0x20(%rbp), %rsi
movq -0x30(%rbp), %rdx
callq 0x4b70
movq %rax, %rcx
movq -0x90(%rbp), %rax
movss (%rax,%rcx,4), %xmm0
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movq -0x18(%rbp), %rcx
movss (%rax,%rcx,4), %xmm1
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movq -0x20(%rbp), %rcx
subss (%rax,%rcx,4), %xmm1
addss %xmm1, %xmm0
cvtss2sd %xmm0, %xmm0
movsd 0x730f(%rip), %xmm1     # 0xb010
divsd %xmm1, %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, -0x34(%rbp)
movq -0x60(%rbp), %rax
movq %rax, -0x88(%rbp)
movq -0x18(%rbp), %rdi
movq -0x20(%rbp), %rsi
movq -0x30(%rbp), %rdx
callq 0x4b70
movq %rax, %rcx
movq -0x88(%rbp), %rax
movss (%rax,%rcx,4), %xmm0
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movq -0x20(%rbp), %rcx
movss (%rax,%rcx,4), %xmm1
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movq -0x18(%rbp), %rcx
subss (%rax,%rcx,4), %xmm1
addss %xmm1, %xmm0
cvtss2sd %xmm0, %xmm0
movsd 0x72a5(%rip), %xmm1     # 0xb010
divsd %xmm1, %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, -0x38(%rbp)
movq -0x68(%rbp), %rax
movq -0x18(%rbp), %rcx
xorps %xmm0, %xmm0
movss %xmm0, (%rax,%rcx,4)
movq -0x60(%rbp), %rax
movq %rax, -0x80(%rbp)
movq -0x18(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0x1, %rsi
movq -0x30(%rbp), %rdx
callq 0x4b70
movq %rax, %rcx
movq -0x80(%rbp), %rax
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, -0x50(%rbp)
movq -0x60(%rbp), %rax
movq %rax, -0x78(%rbp)
movq -0x18(%rbp), %rdi
addq $0x1, %rdi
movq -0x20(%rbp), %rsi
movq -0x30(%rbp), %rdx
callq 0x4b70
movq %rax, %rcx
movq -0x78(%rbp), %rax
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, -0x58(%rbp)
movq -0x18(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rax
cmpq -0x30(%rbp), %rax
jge 0x3ee9
movq -0x50(%rbp), %rax
movss (%rax), %xmm0
subss -0x34(%rbp), %xmm0
movq -0x58(%rbp), %rax
movss (%rax), %xmm1
subss -0x38(%rbp), %xmm1
addss %xmm1, %xmm0
cvtss2sd %xmm0, %xmm0
movsd 0x71e6(%rip), %xmm1     # 0xb010
divsd %xmm1, %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, -0x3c(%rbp)
movq -0x28(%rbp), %rax
cmpq -0x20(%rbp), %rax
jge 0x3e5b
movq -0x30(%rbp), %rax
subq -0x28(%rbp), %rax
subq $0x1, %rax
shlq $0x2, %rax
addq -0x58(%rbp), %rax
movq %rax, -0x58(%rbp)
jmp 0x3e67
movq -0x58(%rbp), %rax
addq $0x4, %rax
movq %rax, -0x58(%rbp)
movss -0x3c(%rbp), %xmm0
movq -0x50(%rbp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, -0x50(%rbp)
movss %xmm0, (%rax)
movss -0x3c(%rbp), %xmm0
movq -0x68(%rbp), %rax
movq -0x18(%rbp), %rcx
addss (%rax,%rcx,4), %xmm0
movss %xmm0, (%rax,%rcx,4)
movss -0x3c(%rbp), %xmm0
movq -0x68(%rbp), %rax
movq -0x28(%rbp), %rcx
addss (%rax,%rcx,4), %xmm0
movss %xmm0, (%rax,%rcx,4)
movq -0x68(%rbp), %rax
movq -0x28(%rbp), %rcx
movss (%rax,%rcx,4), %xmm0
movq -0x30(%rbp), %rax
subq $0x3, %rax
cvtsi2ss %rax, %xmm1
divss %xmm1, %xmm0
movq -0x70(%rbp), %rax
movq -0x28(%rbp), %rcx
movss %xmm0, (%rax,%rcx,4)
movq -0x28(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x28(%rbp)
jmp 0x3df2
movq -0x60(%rbp), %rax
movq -0x18(%rbp), %rcx
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, -0x50(%rbp)
movq -0x60(%rbp), %rax
movq -0x20(%rbp), %rcx
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, -0x58(%rbp)
movq $0x0, -0x28(%rbp)
movq -0x28(%rbp), %rax
cmpq -0x18(%rbp), %rax
jge 0x4003
movq -0x50(%rbp), %rax
movss (%rax), %xmm0
subss -0x34(%rbp), %xmm0
movq -0x58(%rbp), %rax
movss (%rax), %xmm1
subss -0x38(%rbp), %xmm1
addss %xmm1, %xmm0
cvtss2sd %xmm0, %xmm0
movsd 0x70c1(%rip), %xmm1     # 0xb010
divsd %xmm1, %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, -0x3c(%rbp)
movss -0x3c(%rbp), %xmm0
movq -0x50(%rbp), %rax
movss %xmm0, (%rax)
movss -0x3c(%rbp), %xmm0
movq -0x68(%rbp), %rax
movq -0x18(%rbp), %rcx
addss (%rax,%rcx,4), %xmm0
movss %xmm0, (%rax,%rcx,4)
movss -0x3c(%rbp), %xmm0
movq -0x68(%rbp), %rax
movq -0x28(%rbp), %rcx
addss (%rax,%rcx,4), %xmm0
movss %xmm0, (%rax,%rcx,4)
movq -0x68(%rbp), %rax
movq -0x28(%rbp), %rcx
movss (%rax,%rcx,4), %xmm0
movq -0x30(%rbp), %rax
subq $0x3, %rax
cvtsi2ss %rax, %xmm1
divss %xmm1, %xmm0
movq -0x70(%rbp), %rax
movq -0x28(%rbp), %rcx
movss %xmm0, (%rax,%rcx,4)
movq -0x30(%rbp), %rax
subq -0x28(%rbp), %rax
subq $0x1, %rax
shlq $0x2, %rax
addq -0x50(%rbp), %rax
movq %rax, -0x50(%rbp)
movq -0x30(%rbp), %rax
subq -0x28(%rbp), %rax
subq $0x1, %rax
shlq $0x2, %rax
addq -0x58(%rbp), %rax
movq %rax, -0x58(%rbp)
movq -0x28(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x28(%rbp)
jmp 0x3f17
movq -0x68(%rbp), %rax
movq -0x18(%rbp), %rcx
movss (%rax,%rcx,4), %xmm0
movq -0x30(%rbp), %rax
subq $0x3, %rax
cvtsi2ss %rax, %xmm1
divss %xmm1, %xmm0
movq -0x70(%rbp), %rax
movq -0x18(%rbp), %rcx
movss %xmm0, (%rax,%rcx,4)
movq -0x60(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x60(%rbp), %rax
movq -0x20(%rbp), %rcx
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, -0x58(%rbp)
movq $0x0, -0x28(%rbp)
movq -0x28(%rbp), %rax
cmpq -0x20(%rbp), %rax
jge 0x409c
movq -0x48(%rbp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, -0x48(%rbp)
movss (%rax), %xmm0
movq -0x58(%rbp), %rax
movss %xmm0, (%rax)
movq -0x30(%rbp), %rax
subq -0x28(%rbp), %rax
subq $0x1, %rax
shlq $0x2, %rax
addq -0x58(%rbp), %rax
movq %rax, -0x58(%rbp)
movq -0x28(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x28(%rbp)
jmp 0x4051
movq -0x48(%rbp), %rax
addq $0x4, %rax
movq %rax, -0x48(%rbp)
movq -0x60(%rbp), %rax
movq %rax, -0x98(%rbp)
movq -0x20(%rbp), %rdi
movq -0x20(%rbp), %rsi
addq $0x1, %rsi
movq -0x30(%rbp), %rdx
callq 0x4b70
movq %rax, %rcx
movq -0x98(%rbp), %rax
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, -0x58(%rbp)
movq -0x20(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rax
cmpq -0x30(%rbp), %rax
jge 0x4127
movq -0x48(%rbp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, -0x48(%rbp)
movss (%rax), %xmm0
movq -0x58(%rbp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, -0x58(%rbp)
movss %xmm0, (%rax)
movq -0x28(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x28(%rbp)
jmp 0x40e9
movq -0x68(%rbp), %rax
movss (%rax), %xmm0
movq -0x68(%rbp), %rax
movq -0x20(%rbp), %rcx
movss %xmm0, (%rax,%rcx,4)
movq -0x68(%rbp), %rcx
addq $0x4, %rcx
movq -0x8(%rbp), %rax
movq %rcx, 0x28(%rax)
movq -0x70(%rbp), %rax
movss (%rax), %xmm0
movq -0x70(%rbp), %rax
movq -0x20(%rbp), %rcx
movss %xmm0, (%rax,%rcx,4)
movq -0x70(%rbp), %rcx
addq $0x4, %rcx
movq -0x8(%rbp), %rax
movq %rcx, 0x30(%rax)
movq -0x30(%rbp), %rcx
movq -0x8(%rbp), %rax
shlq $0x2, %rcx
addq 0x18(%rax), %rcx
movq %rcx, 0x18(%rax)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rcx
addq $-0x1, %rcx
movq %rcx, 0x8(%rax)
addq $0xa0, %rsp
popq %rbp
retq
nop