// File: /workspace/github_c_makefile_star2_O3/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 0x6788
testq %rax, %rax
jne 0x2b6a
movq 0xa49d(%rip), %rax      # 0xcff8
movq (%rax), %rcx
leaq 0x551b(%rip), %rdi      # 0x8080
jmp 0x2c0d
movq %rax, %rbx
cmpl $0x0, 0x20(%rax)
je 0x2b84
movl 0x48(%rbx), %esi
leaq 0x5537(%rip), %rdi      # 0x80b4
xorl %eax, %eax
callq 0x2100
movslq 0x48(%rbx), %rdi
callq 0x6f90
movl 0x18(%rbx), %eax
cmpl $0x66, %eax
je 0x2ba9
cmpl $0x64, %eax
jne 0x2bfc
movq %rbx, %rdi
callq 0x5638
testq %rax, %rax
jne 0x2bce
jmp 0x2c1c
movq %rbx, %rdi
callq 0x4a88
testq %rax, %rax
jne 0x2bce
movq 0xa43b(%rip), %rax      # 0xcff8
movq (%rax), %rcx
leaq 0x54fc(%rip), %rdi      # 0x80c3
movl $0x3a, %esi
jmp 0x2c12
movq %rax, %r14
cmpq $0x0, 0x10(%rbx)
je 0x2be3
movq %rbx, %rdi
movq %r14, %rsi
callq 0x5ee1
movl 0x5c(%rbx), %eax
cmpl $0x2, %eax
jl 0x2c26
movq %r14, %rdi
callq 0x2daf
movq %rax, (%rsp)
movl 0x5c(%rbx), %eax
jmp 0x2c2e
movq 0xa3f5(%rip), %rax      # 0xcff8
movq (%rax), %rcx
leaq 0x54f1(%rip), %rdi      # 0x80fe
movl $0x33, %esi
movl $0x1, %edx
callq 0x2240
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x2230
movq $0x0, (%rsp)
testl %eax, %eax
jle 0x2d81
leaq 0x8(%rsp), %r12
xorl %r13d, %r13d
cmpl $0x0, 0x3c(%rbx)
je 0x2c4c
movq %r14, %rdi
callq 0x2f39
movq %r12, %rdi
xorl %esi, %esi
callq 0x2110
imulq $0xf4240, 0x8(%rsp), %r15 # imm = 0xF4240
addq 0x10(%rsp), %r15
cmpl $0x0, 0x58(%rbx)
je 0x2c74
movq %r14, %rsi
callq 0x3196
jmp 0x2c7f
movq %rbx, %rdi
movq %r14, %rsi
callq 0x3357
movq %rax, %rbp
testq %rax, %rax
je 0x2d51
movq %r12, %rdi
xorl %esi, %esi
callq 0x2110
cmpl $0x0, 0x20(%rbx)
jne 0x2cf6
movq %rbx, %rdi
movq %rbp, %rsi
movq %r14, %rdx
movq %r13, %rcx
callq 0x3d5e
movq %rbp, %rdi
callq 0x3e01
movq %r14, %rdi
callq 0x3e2f
movl 0x5c(%rbx), %eax
cmpl $0x2, %eax
setge %cl
movl %eax, %edx
decl %edx
cmpq %rdx, %r13
setb %dl
andb %cl, %dl
cmpb $0x1, %dl
jne 0x2ce5
movq (%rsp), %rdi
callq 0x2daf
movq %rax, %r14
movl 0x5c(%rbx), %eax
incq %r13
movslq %eax, %rcx
cmpq %rcx, %r13
jl 0x2c3e
jmp 0x2d73
imulq $0xf4240, 0x8(%rsp), %rcx # imm = 0xF4240
addq 0x10(%rsp), %rcx
subq %r15, %rcx
movq %rcx, %rax
movabsq $0x431bde82d7b634db, %rdx # imm = 0x431BDE82D7B634DB
mulq %rdx
shrq $0x12, %rdx
imulq $0xf4240, %rdx, %rax    # imm = 0xF4240
subq %rax, %rcx
cmpl $0x0, 0x58(%rbx)
movq 0xa2c8(%rip), %rax      # 0xcff8
movq (%rax), %rdi
leaq 0x541e(%rip), %rsi      # 0x8158
leaq 0x5416(%rip), %rax      # 0x8157
cmoveq %rax, %rsi
xorl %eax, %eax
callq 0x2180
jmp 0x2c9b
movq 0xa2a0(%rip), %rax      # 0xcff8
movq (%rax), %rcx
leaq 0x53d0(%rip), %rdi      # 0x8132
movl $0x24, %esi
movl $0x1, %edx
callq 0x2240
jmp 0x2da8
cmpl $0x2, %eax
jl 0x2d81
movq (%rsp), %rdi
callq 0x3e2f
cmpl $0x0, 0x20(%rbx)
je 0x2da8
cmpl $0x0, 0x58(%rbx)
movq 0x8(%rbx), %rsi
leaq 0x53e5(%rip), %rax      # 0x817b
leaq 0x53e6(%rip), %rdi      # 0x8183
cmoveq %rax, %rdi
xorl %eax, %eax
callq 0x2100
xorl %edi, %edi
callq 0x2230