// File: /workspace/github_c_makefile_star2_O2/sheneman[P]clearcut/clearcut.c
// Function: main
int
main(int argc,
     char *argv[]) {

  DMAT *dmat;         /* The working distance matrix */
  DMAT *dmat_backup = NULL;/* A backup distance matrix    */
  NJ_TREE *tree;      /* The phylogenetic tree       */
  NJ_ARGS *nj_args;   /* Structure for holding command-line arguments */
  long int i;

  /* some variables for tracking time */
  struct timeval tv;
  unsigned long long startUs, endUs;
  

  /* check and parse supplied command-line arguments */
  nj_args = NJ_handle_args(argc, argv);
  if(!nj_args) {
    fprintf(stderr, "Clearcut: Error processing command-line arguments.\n");
    exit(-1);
  }

  /* for verbose reporting, print the random number seed to stdout */
  if(nj_args->verbose_flag) {
    printf("PRNG SEED: %d\n", nj_args->seed);
  }

  /* Initialize Mersenne Twister PRNG */
  init_genrand(nj_args->seed);


  switch(nj_args->input_mode) {

    /* If the input type is a distance matrix */
  case NJ_INPUT_MODE_DISTANCE:

    /* parse the distance matrix */
    dmat = NJ_parse_distance_matrix(nj_args);
    if(!dmat) {
      exit(-1);
    }

    break;

    /* If the input type is a multiple sequence alignment */
  case NJ_INPUT_MODE_ALIGNED_SEQUENCES:

    /* build a distance matrix from a multiple sequence alignment */
    dmat = NJ_build_distance_matrix(nj_args);
    if(!dmat) {
      fprintf(stderr, "Clearcut: Failed to build distance matrix from alignment.\n");
      exit(-1);
    }
    
    break;

  default:

    fprintf(stderr, "Clearcut: Could not determine how to process input\n");
    exit(-1);
  }

  /*
   * Output the computed distance matrix,
   *  if the user specified one.
   */
  if(nj_args->matrixout) {
    NJ_output_matrix(nj_args, dmat);
  }
  
  /* 
   * If we are going to generate multiple trees from
   * the same distance matrix, we need to make a backup 
   * of the original distance matrix.
   */
  if(nj_args->ntrees > 1) {
    dmat_backup = NJ_dup_dmat(dmat);
  }
  
  /* process n trees */
  for(i=0;i<nj_args->ntrees;i++) {
    
    /* 
     * If the user has specified matrix shuffling, we need 
     * to randomize the distance matrix
     */
    if(nj_args->shuffle) {
      NJ_shuffle_distance_matrix(dmat);
    }

    /* RECORD THE PRECISE TIME OF THE START OF THE NEIGHBOR-JOINING */
    gettimeofday(&tv, NULL);
    startUs = ((unsigned long long) tv.tv_sec * 1000000ULL)
      + ((unsigned long long) tv.tv_usec);

    
    /* 
     * Invoke either the Relaxed Neighbor-Joining algorithm (default)
     * or the "traditional" Neighbor-Joining algorithm 
     */
    if(nj_args->neighbor) {
      tree = NJ_neighbor_joining(nj_args, dmat);
    } else {
      tree = NJ_relaxed_nj(nj_args, dmat);
    }
  
    if(!tree) {
      fprintf(stderr, "Clearcut: Failed to construct tree.\n");
      exit(0);
    }

    /* RECORD THE PRECISE TIME OF THE END OF THE NEIGHBOR-JOINING */
    gettimeofday(&tv, NULL);
    endUs = ((unsigned long long) tv.tv_sec * 1000000ULL)
      + ((unsigned long long) tv.tv_usec);

    /* print the time taken to perform the neighbor join */
    if(nj_args->verbose_flag) {
      if(nj_args->neighbor) {
	fprintf(stderr, "NJ tree built in %llu.%06llu secs\n",
		(endUs - startUs) / 1000000ULL,
		(endUs - startUs) % 1000000ULL);
      } else { 
	fprintf(stderr, "RNJ tree built in %llu.%06llu secs\n",
		(endUs - startUs) / 1000000ULL,
		(endUs - startUs) % 1000000ULL);
      }
    }

    /* Output the neighbor joining tree here */
    NJ_output_tree(nj_args, tree, dmat, i);
    
    NJ_free_tree(tree);  /* Free the tree */
    NJ_free_dmat(dmat);  /* Free the working distance matrix */

    /* 
     * If we need to do another iteration, lets re-initialize 
     * our working distance matrix.
     */
    if(nj_args->ntrees > 1 && i<(nj_args->ntrees-1) ) {
      dmat = NJ_dup_dmat(dmat_backup);
    }
  }
  
  /* Free the backup distance matrix */
  if(nj_args->ntrees > 1) {
    NJ_free_dmat(dmat_backup);
  }

  /* If verbosity, describe where the tree output is */
  if(nj_args->verbose_flag) {
    if(nj_args->neighbor) {
      printf("NJ tree(s) in %s\n", nj_args->outfilename);
    } else {
      printf("Relaxed NJ tree(s) in %s\n", nj_args->outfilename);
    }
  }

  exit(0);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
callq 0x5a50
testq %rax, %rax
jne 0x236a
movq 0x9c9d(%rip), %rax      # 0xbff8
movq (%rax), %rcx
leaq 0x4cdb(%rip), %rdi      # 0x7040
jmp 0x2405
movq %rax, %rbx
cmpl $0x0, 0x20(%rax)
je 0x2384
movl 0x48(%rbx), %esi
leaq 0x4cf7(%rip), %rdi      # 0x7074
xorl %eax, %eax
callq 0x2100
movslq 0x48(%rbx), %rdi
callq 0x6324
movl 0x18(%rbx), %eax
cmpl $0x66, %eax
je 0x23a9
cmpl $0x64, %eax
jne 0x23f4
movq %rbx, %rdi
callq 0x4878
testq %rax, %rax
je 0x2410
jmp 0x23cb
movq %rbx, %rdi
callq 0x3d00
testq %rax, %rax
jne 0x23cb
movq 0x9c3b(%rip), %rax      # 0xbff8
movq (%rax), %rcx
leaq 0x4cbc(%rip), %rdi      # 0x7083
pushq $0x3a
jmp 0x2407
movq %rax, %r14
cmpq $0x0, 0x10(%rbx)
je 0x23e0
movq %rbx, %rdi
movq %r14, %rsi
callq 0x5168
cmpl $0x2, 0x5c(%rbx)
jl 0x2418
movq %r14, %rdi
callq 0x2585
movq %rax, (%rsp)
jmp 0x2420
movq 0x9bfd(%rip), %rax      # 0xbff8
movq (%rax), %rcx
leaq 0x4cb9(%rip), %rdi      # 0x70be
pushq $0x33
popq %rsi
pushq $0x1
popq %rdx
callq 0x2230
pushq $-0x1
popq %rdi
callq 0x2220
movq $0x0, (%rsp)
leaq 0x8(%rsp), %r12
xorl %r13d, %r13d
movslq 0x5c(%rbx), %rax
cmpq %rax, %r13
jge 0x252b
cmpl $0x0, 0x3c(%rbx)
je 0x2443
movq %r14, %rdi
callq 0x272d
movq %r12, %rdi
xorl %esi, %esi
callq 0x2110
imulq $0xf4240, 0x8(%rsp), %r15 # imm = 0xF4240
addq 0x10(%rsp), %r15
cmpl $0x0, 0x58(%rbx)
je 0x246b
movq %r14, %rsi
callq 0x2893
jmp 0x2476
movq %rbx, %rdi
movq %r14, %rsi
callq 0x296a
movq %rax, %rbp
testq %rax, %rax
je 0x2562
movq %r12, %rdi
xorl %esi, %esi
callq 0x2110
cmpl $0x0, 0x20(%rbx)
jne 0x24de
movq %rbx, %rdi
movq %rbp, %rsi
movq %r14, %rdx
movq %r13, %rcx
callq 0x2dd6
movq %rbp, %rdi
callq 0x2e91
movq %r14, %rdi
callq 0x2ebf
movl 0x5c(%rbx), %eax
cmpl $0x2, %eax
setge %cl
decl %eax
cmpq %rax, %r13
setb %al
andb %cl, %al
cmpb $0x1, %al
jne 0x24d6
movq (%rsp), %rdi
callq 0x2585
movq %rax, %r14
incq %r13
jmp 0x2428
imulq $0xf4240, 0x8(%rsp), %rax # imm = 0xF4240
addq 0x10(%rsp), %rax
subq %r15, %rax
xorl %edx, %edx
movl $0xf4240, %ecx          # imm = 0xF4240
divq %rcx
movq %rdx, %rcx
cmpl $0x0, 0x58(%rbx)
movq 0x9af1(%rip), %rdx      # 0xbff8
movq (%rdx), %rdi
leaq 0x4c07(%rip), %rsi      # 0x7118
leaq 0x4bff(%rip), %rdx      # 0x7117
cmoveq %rdx, %rsi
movq %rax, %rdx
xorl %eax, %eax
callq 0x2180
jmp 0x2492
cmpl $0x2, %eax
jl 0x2539
movq (%rsp), %rdi
callq 0x2ebf
cmpl $0x0, 0x20(%rbx)
je 0x257e
cmpl $0x0, 0x58(%rbx)
movq 0x8(%rbx), %rsi
leaq 0x4bed(%rip), %rax      # 0x713b
leaq 0x4bee(%rip), %rdi      # 0x7143
cmoveq %rax, %rdi
xorl %eax, %eax
callq 0x2100
jmp 0x257e
movq 0x9a8f(%rip), %rax      # 0xbff8
movq (%rax), %rcx
leaq 0x4b7f(%rip), %rdi      # 0x70f2
pushq $0x24
popq %rsi
pushq $0x1
popq %rdx
callq 0x2230
xorl %edi, %edi
callq 0x2220