// File: /workspace/github_c_makefile_star2_O2/sheneman[P]clearcut/dmat.c
// Function: NJ_parse_distance_matrix
DMAT *
NJ_parse_distance_matrix(NJ_ARGS *nj_args) {
  
  DMAT *dmat           = NULL;
  FILE *fp            = NULL;
  NJ_DIST_TOKEN *token = NULL;

  int state, dmat_type;
  int row;
  int fltcnt;
  int x, y, i;
  int numvalread;
  int expectedvalues = -1;
  float val;
  int first_state = 0;


  /* allocate our distance matrix and token structure */
  dmat = (DMAT *)calloc(1, sizeof(DMAT));
  token = (NJ_DIST_TOKEN *)calloc(1, sizeof(NJ_DIST_TOKEN));
  if(token) {
    token->bufsize = NJ_INITIAL_BUFSIZE;
    token->buf     = (char *)calloc(token->bufsize, sizeof(char));
  }
  if(!dmat || !token || !token->buf) {
    fprintf(stderr, "Clearcut: Memory allocation error in NJ_parse_distance_matrix()\n");
    goto XIT_BAD;
  }
  
  /* open distance matrix file here */
  if(nj_args->stdin_flag) {
    fp = stdin;
  } else {
    fp = fopen(nj_args->infilename, "r");
    if(!fp) {
      fprintf(stderr, "Clearcut: Could not open distance matrix: %s\n", nj_args->infilename);
      perror("Clearcut");
      goto XIT_BAD;
    }
  }

  /* get the number of taxa in this file */
  fscanf(fp, "%ld\n", &dmat->ntaxa);
  if(dmat->ntaxa < 2) {
    fprintf(stderr, "Clearcut: Invalid number of taxa in distance matrix\n");

    goto XIT_BAD;
  }

  /* set our initial working size according to the # of taxa */
  dmat->size = dmat->ntaxa;

  /* allocate space for the distance matrix values here */
  dmat->val = 
    (float *)calloc(NJ_NCELLS(dmat->ntaxa), sizeof(float));
  if(!dmat->val) {
    fprintf(stderr, "Clearcut: Memory allocation error in NJ_parse_distance_matrix()\n");
    goto XIT_BAD;
  }

  /*  taxa names */
  dmat->taxaname = (char **)calloc(dmat->ntaxa, sizeof(char *));
  if(!dmat->taxaname) {
    fprintf(stderr, "Clearcut: Memory allocation error in NJ_parse_distance_matrix()\n");
    goto XIT_BAD;
  }

  /* set the initial state of our state machine */
  dmat_type   = NJ_PARSE_UNKNOWN;
  row         = -1;
  fltcnt      = 0;
  numvalread  = 0;


  /* read the input one character at a time to drive simple state machine */
  state = NJ_get_token(fp, token);
  while(state != NJ_EOF_STATE) {
    
    switch(state) {

    case NJ_NAME_STATE:
      
      if(first_state == 0) {
	first_state = 1;
      }

      row++;

      if(row > 0 && dmat_type == NJ_PARSE_UNKNOWN) {

	if(fltcnt == dmat->ntaxa) {

	  dmat_type = NJ_PARSE_SYMMETRIC;
	  expectedvalues = dmat->ntaxa * dmat->ntaxa;

	} else if (fltcnt == dmat->ntaxa-1) {

	  dmat_type = NJ_PARSE_UPPER;
	  expectedvalues = ((dmat->ntaxa) * (dmat->ntaxa-1)) / 2;

	  /* shift everything in first row by one char */
	  for(i=dmat->ntaxa-2;i>=0;i--) {
	    dmat->val[i+1] = dmat->val[i];
	  }

	} else if (fltcnt == 0) {

	  dmat_type = NJ_PARSE_LOWER;
	  expectedvalues = ((dmat->ntaxa) * (dmat->ntaxa-1)) / 2;

	} else {
	  goto XIT_BAD;
	}
      }
      
      if(row >= dmat->ntaxa) {
	goto XIT_BAD;
      }
      
      /* allocate space for this taxon label */
      dmat->taxaname[row] = (char *)calloc(strlen(token->buf)+1, sizeof(char));
      if(!dmat->taxaname[row]) {
	fprintf(stderr, "Clearcut: Memory allocation error in NJ_parse_distance_matrix()\n");
	goto XIT_BAD;
      }
      
      strcpy(dmat->taxaname[row], token->buf); 
      
      fltcnt = 0;

      break;


    case NJ_FLOAT_STATE:

      if(first_state == 0) {
	goto XIT_BAD;
      }

      val = atof(token->buf);
      if(errno) {
	fprintf(stderr, "Clearcut: Distance value out-of-range.\n");
	goto XIT_BAD;
      }
      
      x = row;
      y = fltcnt;

      switch(dmat_type) {

      case NJ_PARSE_UNKNOWN:

	dmat->val[NJ_MAP(x, y, dmat->size)] = val;

	break;

      case NJ_PARSE_SYMMETRIC:
	
	if(fltcnt >= dmat->ntaxa) {
	  fprintf(stderr, "Clearcut: Incorrect number of distance values on row.\n");
	  goto XIT_BAD;
	}

	if(x < y) {
	  dmat->val[NJ_MAP(x, y, dmat->size)] = val;
	} else if(x > y) {
	  if(!NJ_FLT_EQ(val, dmat->val[NJ_MAP(y, x, dmat->size)])) {
	    fprintf(stderr, "Clearcut: Full matrices must be symmetric.\n");
	    goto XIT_BAD;
	  }
	} else {
	  if(!NJ_FLT_EQ(val, 0.0)) {
	    fprintf(stderr, "Clearcut: Values along the diagonal in a symmetric matrix must be zero.\n");
	    goto XIT_BAD;

            }
	}

	break;
	
      case NJ_PARSE_UPPER:

	if(fltcnt > dmat->ntaxa-row) {
	  fprintf(stderr, "Clearcut: Incorrect number of distance values on row.\n");
	  goto XIT_BAD;
	}
	
	dmat->val[NJ_MAP(x, x+y+1, dmat->size)] = val;
	
	break;

      case NJ_PARSE_LOWER:
	
	if(fltcnt > row-1) {
	  fprintf(stderr, "Clearcut: Incorrect number of distance values on row.\n");
	  goto XIT_BAD;
	}

	dmat->val[NJ_MAP(y, x, dmat->size)] = val;
	
	break;
	
      default:
	
	goto XIT_BAD;
	
	break;
      }

      fltcnt++;
      numvalread++;
      
      break;

    case NJ_WS_STATE:

      break;

    case NJ_EOF_STATE:

      if(first_state == 0) {
	goto XIT_BAD;
      }

      break;

    default:

      fprintf(stderr, "Clearcut: Unknown state in distance matrix parser.\n");
      break;

    }

    /* get next token from stream */
    state = NJ_get_token(fp, token);
  }


  /* 
   * At the end, if we have not read the number of values that we predicted
   * we would need, then there was a problem and we need to punt.
   */
  if(numvalread != expectedvalues) {
    fprintf(stderr, "Clearcut: Incorrect number of values in the distance matrix.\n");
    goto XIT_BAD;
  }
  
  /* special check to make sure first value read is 0.0 */
  if(dmat_type == NJ_PARSE_SYMMETRIC) {
    if(!NJ_FLT_EQ(dmat->val[NJ_MAP(0, 0, dmat->size)], 0.0)) {
      fprintf(stderr, "Clearcut: Values along the diagonal in a symmetric matrix must be zero.\n");
      goto XIT_BAD;
    }
  }

  
  /* now lets allocate space for the r and r2 columns */
  dmat->r  = (float *)calloc(dmat->ntaxa, sizeof(float));
  dmat->r2 = (float *)calloc(dmat->ntaxa, sizeof(float));
  if(!dmat->r || !dmat->r2) {
    fprintf(stderr, "Clearcut: Memory allocation error in NJ_parse_distance_matrix()\n");
    goto XIT_BAD;
  }
  
  /* track some memory addresses */
  dmat->rhandle   = dmat->r;
  dmat->r2handle  = dmat->r2;
  dmat->valhandle = dmat->val;

  /* close matrix file here */
  if(!nj_args->stdin_flag) {
    fclose(fp);
  }
  
  if(token) {
    if(token->buf) {
      free(token->buf);
    }
    free(token);
  }

  return(dmat);



  /* clean up our partial progress */
 XIT_BAD:

  if(fp) {
    fprintf(stderr, "Clearcut: Syntax error in distance matrix at offset %ld.\n", ftell(fp));
  }

  /* close matrix file here */
  if(!nj_args->stdin_flag) {
    if(fp) {
      fclose(fp);
    }
  }

  /* if we have a valid dmat (partial or complete), we need to free it */
  if(dmat) {
    NJ_free_dmat(dmat);
  }
  
  if(token) {
    if(token->buf) {
      free(token->buf);
    }
    free(token);
  }
  
  return(NULL);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %rdi, %r15
pushq $0x1
popq %rbx
pushq $0x48
popq %rsi
movq %rbx, %rdi
callq 0x2160
movq %rax, %r14
pushq $0x18
popq %rsi
movq %rbx, %rdi
callq 0x2160
movq %rax, %rbx
testq %rax, %rax
je 0x4d37
movq $0x20, 0x8(%rbx)
pushq $0x20
popq %rdi
pushq $0x1
popq %rsi
callq 0x2160
movq %rax, (%rbx)
testq %r14, %r14
je 0x4d61
testq %rax, %rax
je 0x4d82
cmpl $0x0, 0x28(%r15)
je 0x48ec
movq 0x76f1(%rip), %rax      # 0xbfd8
movq (%rax), %r12
jmp 0x4907
movq (%r15), %rdi
leaq 0x3333(%rip), %rsi      # 0x7c29
callq 0x21f0
movq %rax, %r12
testq %rax, %rax
je 0x4dca
leaq 0x2ee3(%rip), %rsi      # 0x77f1
movq %r12, %rdi
movq %r14, %rdx
xorl %eax, %eax
callq 0x20a0
movq (%r14), %r13
cmpq $0x1, %r13
movq %r14, (%rsp)
movq %r15, 0x30(%rsp)
jle 0x4da0
movq %r13, 0x8(%r14)
leaq 0x1(%r13), %rdi
imulq %r13, %rdi
shrq %rdi
pushq $0x4
popq %rsi
callq 0x2160
movq %rax, 0x18(%r14)
testq %rax, %rax
je 0x4d1f
pushq $0x8
popq %rsi
movq %r13, %rdi
callq 0x2160
movq %rax, 0x10(%r14)
testq %rax, %rax
je 0x4d1f
movb $0x1, %r14b
movl $0x0, 0x14(%rsp)
pushq $-0x1
popq %r15
pushq $0x67
popq %rax
movq %rax, 0x8(%rsp)
leaq 0x2be1(%rip), %rbp      # 0x756c
movl %r15d, %eax
movq %rax, 0x18(%rsp)
movl %r15d, 0x2c(%rsp)
movslq %r15d, %rax
movq %rax, 0x38(%rsp)
notq %rax
movq %rax, 0x20(%rsp)
xorl %r15d, %r15d
movq %r12, %rdi
movq %rbx, %rsi
callq 0x4ecd
addl $-0x64, %eax
cmpl $0x3, %eax
ja 0x4a54
movslq (%rbp,%rax,4), %rax
addq %rbp, %rax
movl %r15d, %r13d
jmpq *%rax
testb $0x1, %r14b
movq 0x38(%rsp), %r14
jne 0x4e0f
movq (%rbx), %rdi
callq 0x20c0
movsd %xmm0, 0x40(%rsp)
callq 0x2060
cmpl $0x0, (%rax)
jne 0x4e85
cvtsd2ss 0x40(%rsp), %xmm0
movq 0x8(%rsp), %rax
addl $-0x64, %eax
leaq 0x2b6d(%rip), %rcx      # 0x757c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq (%rsp), %rsi
cmpq %r13, (%rsi)
jle 0x4e9d
cmpl %r15d, %r14d
jge 0x4b2d
movq 0x8(%rsi), %rax
movq 0x20(%rsp), %rcx
leaq (%rcx,%rax,2), %rax
imulq %r14, %rax
cqto
pushq $0x2
popq %rcx
idivq %rcx
shlq $0x2, %rax
addq 0x18(%rsi), %rax
jmp 0x4adf
movq 0x759d(%rip), %rax      # 0xbff8
movq (%rax), %rcx
leaq 0x2ca8(%rip), %rdi      # 0x770d
pushq $0x33
popq %rsi
pushq $0x1
popq %rdx
callq 0x2230
jmp 0x49ab
movq (%rsp), %rsi
movq (%rsi), %rax
subq %r14, %rax
cmpq %r13, %rax
jl 0x4e9d
leal (%r15,%r14), %ecx
movq 0x8(%rsi), %rax
movq 0x20(%rsp), %rdx
leaq (%rdx,%rax,2), %rax
imulq %r14, %rax
cqto
pushq $0x2
popq %rdi
idivq %rdi
shlq $0x2, %rax
addq 0x18(%rsi), %rax
movslq %ecx, %rcx
leaq (%rax,%rcx,4), %rax
addq $0x4, %rax
jmp 0x4b1a
movq (%rsp), %rcx
movq 0x8(%rcx), %rax
movq 0x20(%rsp), %rdx
leaq (%rdx,%rax,2), %rax
imulq %r14, %rax
cqto
pushq $0x2
popq %rsi
idivq %rsi
shlq $0x2, %rax
addq 0x18(%rcx), %rax
leaq (%rax,%r13,4), %rax
jmp 0x4b1a
cmpl 0x2c(%rsp), %r15d
movq (%rsp), %rsi
jge 0x4e9d
movq 0x8(%rsi), %rax
movq %r13, %rcx
notq %rcx
leaq (%rcx,%rax,2), %rax
imulq %r13, %rax
cqto
pushq $0x2
popq %rcx
idivq %rcx
shlq $0x2, %rax
addq 0x18(%rsi), %rax
leaq (%rax,%r14,4), %rax
movss %xmm0, (%rax)
incl %r15d
incl 0x14(%rsp)
xorl %r14d, %r14d
jmp 0x49ab
cmpl %r15d, %r14d
jle 0x4b73
movq 0x8(%rsi), %rax
movq %r13, %rcx
notq %rcx
leaq (%rcx,%rax,2), %rax
imulq %r13, %rax
cqto
pushq $0x2
popq %rcx
idivq %rcx
shlq $0x2, %rax
addq 0x18(%rsi), %rax
subss (%rax,%r14,4), %xmm0
andps 0x24bf(%rip), %xmm0     # 0x7020
movss 0x249f(%rip), %xmm1     # 0x7008
ucomiss %xmm0, %xmm1
ja 0x4b1e
jmp 0x4eb5
andps 0x24a6(%rip), %xmm0     # 0x7020
movss 0x2486(%rip), %xmm1     # 0x7008
ucomiss %xmm0, %xmm1
ja 0x4b1e
jmp 0x4df3
movq 0x38(%rsp), %r8
testl %r8d, %r8d
setns %al
cmpl $0x67, 0x8(%rsp)
sete %dl
andb %al, %dl
movq (%rsp), %rdi
movq (%rdi), %rcx
cmpb $0x1, %dl
jne 0x4c24
cmpq %r13, %rcx
jne 0x4bc5
imull %r15d, %r15d
pushq $0x64
popq %rax
movq %rax, 0x8(%rsp)
movq %r15, 0x18(%rsp)
jmp 0x4c24
leaq -0x1(%rcx), %rax
cmpq %r13, %rax
jne 0x4bfe
imulq %rcx, %r13
movq %r13, %rax
cqto
pushq $0x2
popq %rsi
idivq %rsi
movq %rax, 0x18(%rsp)
leal -0x2(%rcx), %eax
testl %eax, %eax
js 0x4c1c
movq 0x18(%rdi), %rdx
movl %eax, %esi
movss (%rdx,%rsi,4), %xmm0
movss %xmm0, 0x4(%rdx,%rsi,4)
decl %eax
jmp 0x4be5
testl %r15d, %r15d
jne 0x4e0f
imulq %rcx, %rax
cqto
pushq $0x2
popq %rsi
idivq %rsi
movq %rax, 0x18(%rsp)
pushq $0x65
jmp 0x4c1e
pushq $0x66
popq %rax
movq %rax, 0x8(%rsp)
leal 0x1(%r8), %eax
movslq %eax, %r14
cmpq %r14, %rcx
jle 0x4e0f
movl %eax, %r15d
movq (%rbx), %r13
movq %r13, %rdi
callq 0x20e0
leaq 0x1(%rax), %rdi
pushq $0x1
popq %rsi
callq 0x2160
movq (%rsp), %rdx
movq 0x10(%rdx), %rcx
movq %rax, (%rcx,%r14,8)
movq 0x10(%rdx), %rax
movq (%rax,%r14,8), %rdi
testq %rdi, %rdi
je 0x4d1f
movq %r13, %rsi
callq 0x2090
xorl %r14d, %r14d
jmp 0x4993
movq 0x18(%rsp), %rax
cmpl %eax, 0x14(%rsp)
jne 0x4db5
cmpl $0x64, 0x8(%rsp)
movq (%rsp), %r14
jne 0x4cb5
movq 0x18(%r14), %rax
movss (%rax), %xmm0
andps 0x237c(%rip), %xmm0     # 0x7020
movss 0x235c(%rip), %xmm1     # 0x7008
ucomiss %xmm0, %xmm1
jbe 0x4df3
movq (%r14), %rbp
pushq $0x4
popq %r15
movq %rbp, %rdi
movq %r15, %rsi
callq 0x2160
movq %rax, %r13
movq %rax, 0x28(%r14)
movq %rbp, %rdi
movq %r15, %rsi
callq 0x2160
movq %rax, 0x30(%r14)
testq %r13, %r13
je 0x4d1f
testq %rax, %rax
je 0x4d1f
movq %r13, 0x38(%r14)
movq %rax, 0x40(%r14)
movq 0x18(%r14), %rax
movq %rax, 0x20(%r14)
movq 0x30(%rsp), %rax
cmpl $0x0, 0x28(%rax)
jne 0x4d0a
movq %r12, %rdi
callq 0x20d0
movq (%rbx), %rdi
callq 0x2040
movq %rbx, %rdi
callq 0x2040
jmp 0x4e38
movq 0x72d2(%rip), %rax      # 0xbff8
movq (%rax), %rcx
leaq 0x285c(%rip), %rdi      # 0x758c
pushq $0x40
jmp 0x4e06
movq 0x72ba(%rip), %rax      # 0xbff8
movq (%rax), %rcx
leaq 0x2844(%rip), %rdi      # 0x758c
pushq $0x40
popq %rsi
pushq $0x1
popq %rdx
callq 0x2230
testq %r14, %r14
jne 0x4e18
jmp 0x4e20
movq 0x7290(%rip), %rax      # 0xbff8
movq (%rax), %rcx
leaq 0x281a(%rip), %rdi      # 0x758c
pushq $0x40
popq %rsi
pushq $0x1
popq %rdx
callq 0x2230
jmp 0x4e20
movq 0x726f(%rip), %rax      # 0xbff8
movq (%rax), %rcx
leaq 0x27f9(%rip), %rdi      # 0x758c
pushq $0x40
popq %rsi
pushq $0x1
popq %rdx
callq 0x2230
jmp 0x4e18
movq 0x7251(%rip), %rax      # 0xbff8
movq (%rax), %rcx
leaq 0x2853(%rip), %rdi      # 0x7604
pushq $0x34
jmp 0x4e06
movq 0x723c(%rip), %rax      # 0xbff8
movq (%rax), %rcx
leaq 0x297b(%rip), %rdi      # 0x7741
pushq $0x3d
jmp 0x4e06
movq 0x7227(%rip), %rax      # 0xbff8
movq (%rax), %rdi
movq (%r15), %rdx
leaq 0x27ef(%rip), %rsi      # 0x75cd
xorl %eax, %eax
callq 0x2180
leaq 0x280f(%rip), %rdi      # 0x75fb
callq 0x2200
jmp 0x4e18
movq 0x71fe(%rip), %rax      # 0xbff8
movq (%rax), %rcx
leaq 0x28c0(%rip), %rdi      # 0x76c4
pushq $0x48
popq %rsi
pushq $0x1
popq %rdx
callq 0x2230
testq %r12, %r12
movq (%rsp), %r14
jne 0x4e4a
movq %r14, %rdi
callq 0x2ebf
testq %rbx, %rbx
je 0x4e35
movq (%rbx), %rdi
callq 0x2040
movq %rbx, %rdi
callq 0x2040
xorl %r14d, %r14d
movq %r14, %rax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x71a7(%rip), %rax      # 0xbff8
movq (%rax), %r15
movq %r12, %rdi
callq 0x2190
leaq 0x291c(%rip), %rsi      # 0x777f
movq %r15, %rdi
movq %rax, %rdx
xorl %eax, %eax
callq 0x2180
movq 0x30(%rsp), %rax
cmpl $0x0, 0x28(%rax)
jne 0x4e18
movq %r12, %rdi
callq 0x20d0
jmp 0x4e18
movq 0x716c(%rip), %rax      # 0xbff8
movq (%rax), %rcx
leaq 0x27a3(%rip), %rdi      # 0x7639
pushq $0x27
jmp 0x4e06
movq 0x7154(%rip), %rax      # 0xbff8
movq (%rax), %rcx
leaq 0x27b3(%rip), %rdi      # 0x7661
pushq $0x36
jmp 0x4e06
movq 0x713c(%rip), %rax      # 0xbff8
movq (%rax), %rcx
leaq 0x27d2(%rip), %rdi      # 0x7698
pushq $0x2b
jmp 0x4e06