Пример #1
1
/** Initialize the SSL context.
 * \return pointer to SSL context object.
 */
SSL_CTX *
ssl_init(char *private_key_file, char *ca_file, int req_client_cert)
{
  const SSL_METHOD *meth;       /* If this const gives you a warning, you're
                                   using an old version of OpenSSL. */
  unsigned char context[128];
  DH *dh;
  unsigned int reps = 1;

  if (!bio_err) {
    if (!SSL_library_init())
      return NULL;
    SSL_load_error_strings();
    /* Error write context */
    bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
  }

  do_rawlog(LT_ERR, "Seeding OpenSSL random number pool.");
  while (!RAND_status()) {
    /* At this point, a system with /dev/urandom or a EGD file in the usual
       places will have enough entropy. Otherwise, be lazy and use random numbers
       until it's satisfied. */
    uint32_t gibberish[4];
    int n;

    for (n = 0; n < 4; n++)
      gibberish[n] = gen_rand32();

    RAND_seed(gibberish, sizeof gibberish);

    reps += 1;
  }

  do_rawlog(LT_ERR, "Seeded after %u %s.", reps, reps > 1 ? "cycles" : "cycle");


  /* Set up SIGPIPE handler here? */

  /* Create context */
  meth = SSLv23_server_method();
  ctx = SSL_CTX_new(meth);

  /* Load keys/certs */
  if (private_key_file && *private_key_file) {
    if (!SSL_CTX_use_certificate_chain_file(ctx, private_key_file)) {
      ssl_errordump
        ("Unable to load server certificate - only anonymous ciphers supported.");
    }
    if (!SSL_CTX_use_PrivateKey_file(ctx, private_key_file, SSL_FILETYPE_PEM)) {
      ssl_errordump
        ("Unable to load private key - only anonymous ciphers supported.");
    }
  }

  /* Load trusted CAs */
  if (ca_file && *ca_file) {
    if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
      ssl_errordump("Unable to load CA certificates");
    } else {
      if (req_client_cert)
        SSL_CTX_set_verify(ctx,
                           SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
                           client_verify_callback);
      else
        SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, client_verify_callback);
#if (OPENSSL_VERSION_NUMBER < 0x0090600fL)
      SSL_CTX_set_verify_depth(ctx, 1);
#endif
    }
  }

  SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE | SSL_OP_ALL);
  SSL_CTX_set_mode(ctx,
                   SSL_MODE_ENABLE_PARTIAL_WRITE |
                   SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);

  /* Set up DH callback */
  dh = get_dh1024();
  SSL_CTX_set_tmp_dh(ctx, dh);
  /* The above function makes a private copy of this */
  DH_free(dh);

  /* Set the cipher list to the usual default list, except that
   * we'll allow anonymous diffie-hellman, too.
   */
  SSL_CTX_set_cipher_list(ctx, "ALL:ADH:RC4+RSA:+SSLv2:@STRENGTH");

  /* Set up session cache if we can */
  strncpy((char *) context, MUDNAME, 128);
  SSL_CTX_set_session_id_context(ctx, context, u_strlen(context));

  /* Load hash algorithms */
  OpenSSL_add_all_digests();

  return ctx;
}
Пример #2
0
// NormFloat64 returns a normally distributed float64 in the range
// [-math.MaxFloat64, +math.MaxFloat64] with
// standard normal distribution (mean = 0, stddev = 1).
// To produce a different normal distribution, callers can
// adjust the output using:
//
//  sample = NormFloat64() * desiredStdDev + desiredMean
//
real_t rstdnorm_zig(void) {
        for (;;) {
                int32_t j = gen_rand32(); // Possibly negative
                int32_t i = j & 0x7F;
                real_t x = (real_t)(j) * (real_t)(wn[i]);
                if (absInt32(j) < kn[i]) {
                        // This case should be hit better than 99% of the time.
                        return x;
                }

                if (i == 0) {
                        // This extra work is only required for the base strip.
                        for (;;) {
                                x = -log(runif()) * (1.0 / rn);
                                real_t y = -log(runif());
                                if (y+y >= x*x) {
                                        break;
                                }
                        }
                        if (j > 0) {
                                return rn + x;
                        }
                        return -rn - x;
                }
                if (fn[i]+runif()*(fn[i-1]-fn[i]) < exp(-.5*x*x)) {
                        return x;
                }
        }
        errx(EXIT_FAILURE,"Unreachable: %s (%s:%d)",__func__,__FILE__,__LINE__);
}
Пример #3
0
char get_random_card(char maxv) {
	#ifdef USE_MERSENNE_TWISTER
		#ifdef USE_BUFFER
			if (bp >= BUFFER_SIZE) {
				fill_array32((uint32_t*) buffer, BUFFER_SIZE/4);
				bp = 0;
			}
			return ((buffer[bp++] & 127) >> 1) % maxv;
		#else
			return (char)(gen_rand32() % maxv);
		#endif
	#else
		return (char) (rand() % maxv);
	#endif
}
Пример #4
0
int Book::GetMove( Shogi* pshogi, MOVE& move, TYPE type ){
/************************************************
定跡から指し手を探す。
************************************************/
	unsigned i;
	int flag;
	list<BLIST>::iterator ib;
	list<MLIST>::iterator im;
	int cnt;
	uint64 hash = pshogi->GetHash();
	MOVE mtemp;

	i = (unsigned)( hash & BOOK_HASH_MASK );

	// 局面が既にあるか調べる。
	flag = 0;
	for( ib = blist[i].begin() ; ib != blist[i].end() ; ++ib ){
		if( (*ib).hash == hash ){
			flag = 1;
			break;
		}
	}

	if( flag == 0 )
		return 0;

	// 指し手を決定
	switch( type ){
	// 評価値を用いる場合
	case TYPE_EVAL:
		{
			list<MLIST>* pmlist = &(*ib).mlist;
			int vmax = (*pmlist->begin()).val - 1;
			for( im = pmlist->begin() ; im != pmlist->end() ; ++im ){
				mtemp.Import( (*im).mv );
				if( (*im).val > vmax && pshogi->IsLegalMove( mtemp ) ){
					vmax = (*im).val;
					move = mtemp;
				}
			}
			return 1;
		}
		break;

	// 出現頻度を用いる場合
	case TYPE_FREQ:
	default:
		list<MLIST>* pmlist = &(*ib).mlist;
		cnt = (int)( gen_rand32() % (*ib).cnt );
		for( im = pmlist->begin() ; im != pmlist->end() ; ++im ){
			cnt -= (*im).cnt;
			if( cnt < 0 ){
				mtemp.Import( (*im).mv );
				if( pshogi->IsLegalMove( mtemp ) ){
					move = mtemp;
					return 1;
				}
			}
		}
		break;
	}

	return 0;
}
Пример #5
0
int main(int argcs, char* pArgs[])
{
  // Variable declarations.

  uint64_t i = 0, y = 0, q = 0, k = 0;
  uint64_t line_length = 0;
  uint64_t seq_min_id = 0, seq_max_id = 0;
  uint64_t is_sample_repeat = 0;

  char * line_ptr = NULL;

  const uint64_t MAX_HEADER_LENGTH = 1024;
  const uint64_t ymax = 100;
  const uint64_t SAMPLE_SIZE = 50;

  char ** db_seq = NULL;
  char ** seq_headers = NULL;
  uint64_t * seq_len = NULL;
  uint64_t * seq_alloc = NULL;
  struct node * sequences = NULL;

  //int num_buckets = 0;
  uint64_t current_seq = 0;
  uint64_t num_seq_total = 0;
  uint64_t num_seq_selected = 0;
  uint64_t total_db_length = 0;
  uint64_t local_seq_length = 0;
  uint64_t line_return = 0;
  uint64_t seq_len_i=0, seq_i_bin=0;
  uint64_t seq_min = 0, seq_avg = 0, seq_max = 0;
  double seq_avg_d = 0.0, delta_x = 0.0;
  double variance = 0.0, std_dev = 0.0;
  double s_variance = 0.0, s_std_dev = 0.0;
  double s_mean_d = 0.0;
  uint64_t s_mean = 0;
  uint64_t random_prot = 0, seed = 0;
  uint64_t seq_id = 0, seq_len_remaining = 0;
  uint64_t num_seq_alloc = 0;
  //uint64_t sample_query[SAMPLE_SIZE];
  uint64_t * sample_query = NULL;
  uint64_t sample_size = 0;
  uint64_t got_newline = 0;
  uint64_t current_space = 0;

  char line[MAX_HEADER_LENGTH];

  FILE * fasta_db_in = NULL;
  FILE * fasta_db_out = NULL;

  uint64_t filter_length=0;
  uint64_t has_filter = 0;
  uint64_t sequence_count = 0;
  uint64_t begin_range = 0;
  uint64_t end_range = 0;
  uint64_t has_range = 0;

  uint64_t target_letters = 0;

  const char* const short_options = "hi:o:s:f:b:e:t:";

  const struct option long_options[] = {
    { "help", 0, NULL, 'h' },
    { "input" , 1, NULL, 'i' },
    { "output", 1, NULL, 'o' },
    { "seqs", 1, NULL, 's' },
    { "filter", 0, NULL, 'f' },
    { "begin", 0, NULL, 'b' },
    { "end", 0, NULL, 'e' },
    { "total",0,NULL,'t'},
    { NULL, 0, NULL, 0 }               };

  int next_option = 0;

  int got_in = 0;
  int got_out = 0;
  int got_num_seqs = 0;
  int got_filter = 0;
  int got_begin = 0;
  int got_end = 0;
  int got_total = 0;

  do
    {
      next_option = getopt_long( argcs, pArgs, short_options, long_options, NULL );

      switch( next_option )
	{
	case 'h':
	  print_usage();
	  exit(0);

	case 'i':
	  fasta_db_in = fopen( optarg, "r");
	  got_in = 1;
	  
	  break;

	case 'o':
	  fasta_db_out = fopen( optarg, "w" );
	  got_out = 1;

	  break;

	case 's':
	  sample_size = atoi( optarg );
	  got_num_seqs = 1;
	  if ( sample_size < 1 )
	    {
	      printf("Error: Sample size is non-positive.\n");
	      fflush(stdout);
	      exit(1);
	    }

	  break;

	case 'f':
	  filter_length = atoi(optarg);
	  got_filter = 1;
	  has_filter = 1;
	  printf("Filtering on sequences of length %d\n", filter_length);

	  break;

	case 'b':
	  begin_range = atoi(optarg);
	  got_begin = 1;
	  has_range = 1;
	  break;

	case 'e':
	  end_range = atoi(optarg);
	  got_end = 1;
	  has_range = 1;
	  break;

	case 't':
	  target_letters = atoi(optarg);
	  got_total = 1;
	  printf("Targeting to sample up to %d total letters.\n",target_letters);

	  break;

	case '?':
	  printf("Error: Invalid command line argument!\n");
	  print_usage();
	  exit(1);

	case -1:
	  break;

	default:
	  printf("Error: Something strange happened.\n");
	  fflush(stdout);
	  exit(1);
	}

    }
  while ( next_option != -1 );
  
  if ( !got_in )
    {
      printf("Error: No input specified!\n");
      print_usage();
      exit(1);
    }

  if ( !got_out )
    {
      printf("Error: No output specified!\n");
      print_usage();
      exit(1);
    }

  // Initialize the database array to have 50,000 sequences each with an intial length of 250.
  printf("Initialize the sequence array... ");

  num_seq_alloc = 50000;
  db_seq = (char**) malloc( 50000 * sizeof(char*));

  if ( db_seq == NULL )
    {  printf("\nError: Could not allocate db_seq.\n");  exit(1);  }

  for ( i=0; i < 50000; ++i )
    {
      db_seq[i] = NULL;
      db_seq[i] = (char*) malloc( 250 * sizeof(char) );
      if ( db_seq[i] == NULL )
	{  printf("\nError: Could not allocate db_seq[%llu].\n",i);  exit(1);  }
    }

  printf("Done\n");

  // Initialize the headers for the database sequences.
  printf("Initialize the sequence header array... ");

  seq_headers = (char**) malloc( 50000 * sizeof(char*));

  if ( seq_headers == NULL )
    {  printf("\nError: Could not allocate seq_headers.\n");  exit(1);  }

  for ( i=0; i < 50000; ++i )
    {
      seq_headers[i] = NULL;
      seq_headers[i] = (char*) malloc( MAX_HEADER_LENGTH * sizeof(char) );
      if ( seq_headers[i] == NULL )
	{  printf("\nError: Could not allocate seq_headers[%llu].\n",i);  exit(1);  }
    }

  printf("Done\n");
  
  // Initialize the allocated length of the database sequences.
  printf("Initialize the sequence allocated length array... ");

  seq_alloc = (uint64_t*) malloc( 50000 * sizeof(uint64_t));

  if ( seq_alloc == NULL )
    {  printf("\nError: Could not allocate seq_alloc.\n");  exit(1);  }

  for ( i=0 ; i < 50000; ++i )
    {
      seq_alloc[i] = 250;
    }

  printf("Done\n");

  // Initialize the sequence length of the database sequences.
  printf("Initialize the sequence length array... ");

  seq_len = (uint64_t*) malloc( 50000 * sizeof(uint64_t));

  if ( seq_len == NULL )
    {  printf("\nError: Could not allocate seq_len.\n");  exit(1);  }

  for ( i=0 ; i < 50000; ++i )
    {
      seq_len[i] = 0;
    }

  printf("Done\n");

  // Read in the file one line at a time.

  printf("Reading in the database... ");

  current_seq = -1;

  if ( (line_ptr = fgets( line, MAX_HEADER_LENGTH-1, fasta_db_in )) == NULL )
    {  printf("Error: Could not get the first line of file.\n");  exit(1);  }

  while ( line_ptr != NULL )
    {
      // Check if this is a new sequence.
      if ( line[0] == '>' )  // Start of a new sequence.
	{
	  ++current_seq;

	  // Check that there is enough memory. Allocate more if needed.
	  if ( current_seq >= num_seq_alloc )
	    {
	      num_seq_alloc += (uint64_t)50000;

	      db_seq = (char**) realloc( (void*) db_seq, num_seq_alloc * sizeof(char*) );
	      if ( db_seq == NULL )
		{  printf("Error: Reallocation of db_seq failed.\n");  exit(1);  }

	      for ( i=(num_seq_alloc-50000); i < num_seq_alloc; ++i )
		{
		  db_seq[i] = NULL;
		  db_seq[i] = (char*) malloc( 250 * sizeof(char) );
		  if ( db_seq[i] == NULL )
		    {  printf("\nError: Could not allocate db_seq[%llu].\n",i);  exit(1);  }
		}

	      seq_headers = (char**) realloc( (void*) seq_headers, num_seq_alloc * sizeof(char*) );
	      if ( seq_headers == NULL )
		{  printf("Error: Reallocation of seq_headers failed.\n");  exit(1);  }

	      for ( i=(num_seq_alloc-50000); i < num_seq_alloc; ++i )
		{
		  seq_headers[i] = NULL;
		  seq_headers[i] = (char*) malloc( MAX_HEADER_LENGTH * sizeof(char) );
		  if ( seq_headers[i] == NULL )
		    {  printf("\nError: Could not allocate seq_headers[%llu].\n",i);  exit(1);  }
		}

	      seq_alloc = (uint64_t*) realloc( (void*) seq_alloc, num_seq_alloc * sizeof(uint64_t) );
	      if ( seq_alloc == NULL )
		{  printf("Error: Could not reallocate seq_alloc.\n");  exit(1);  }

	      for ( i=(num_seq_alloc-50000); i < num_seq_alloc; ++i )
		{  seq_alloc[i] = 250; }
	      
	      seq_len = (uint64_t*) realloc( (void*) seq_len, num_seq_alloc * sizeof(uint64_t) );
	      if ( seq_len == NULL )
		{  printf("Error: Could not reallocate seq_len.\n");  exit(1);  }

	      for ( i=(num_seq_alloc-50000); i < num_seq_alloc; ++i )
		{  seq_len[i] = 0; }
	    }

	  // check that we got a new line character.
	  got_newline = 0;
	  for ( i=0; i < MAX_HEADER_LENGTH; ++i )
	    {
	      if ( line[i] == '\n' )
		got_newline = 1;
	    }

	  // Copy the header information.
	  strncpy( seq_headers[current_seq], line, MAX_HEADER_LENGTH-1 );

	  current_space = MAX_HEADER_LENGTH;

	  while ( !got_newline )
	    {
	      // Grab the next line
	      line_ptr = fgets( line, MAX_HEADER_LENGTH-1, fasta_db_in );

	      // Allocate more space
	      seq_headers[current_seq] = (char*)realloc( (void*)seq_headers[current_seq], current_space+MAX_HEADER_LENGTH);

	      // Append the end.
	      strncpy( &(seq_headers[current_seq][current_space]), line, MAX_HEADER_LENGTH-1 );

	      current_space += MAX_HEADER_LENGTH;

	      for ( i=0; i < MAX_HEADER_LENGTH; ++i )
		{
		  if ( line[i] == '\n' )
		    got_newline = 1;
		}
	    }
	}
      else
	{
	  // Any other line should have nucleotides or amino acids on it. Put them into the sequence array.
	  line_length = strlen(line);

	  if ( line_length > (MAX_HEADER_LENGTH-2) )
	    {
	      printf("ERROR: Line length for sequence line is too long: %llu\n",line_length);
	      fflush(stdout);
	      exit(1);
	    }

	  // Check that the current line can be written to the sequence array. Add more memory if not.
	  if ( seq_len[current_seq] + line_length >= seq_alloc[current_seq] )
	    {
	      //printf("current_seq=%llu  seq_alloc= %llu \n",current_seq, seq_alloc[current_seq]);
	      //fflush(stdout);

	      //printf("seq_alloc[current_seq] + 250 = %llu\n", seq_alloc[current_seq] + 250 );
	      //fflush(stdout);

	      // Allocate additional space for the sequence.

	      //printf("  Realloc size requested is seq_alloc[%llu] + 250 = %llu + 250 = %llu\n",current_seq,seq_alloc[current_seq],seq_alloc[current_seq] + 250);
	      //printf("  REALLOC SIZE - (seq_alloc[current_seq] + 250 ) * (uint64_t)(sizeof(char)) = %llu \n",(seq_alloc[current_seq] + 250 ) * (uint64_t)(sizeof(char)));
	      fflush(stdout);

	      db_seq[current_seq] = (char*) realloc( (void*) db_seq[current_seq], (seq_alloc[current_seq] + 250 ) );
	      if ( db_seq[current_seq] == NULL )
		{  printf("Error: Could not reallocate db_seq[%llu].\n",current_seq);  exit(1);  }

	      seq_alloc[current_seq] += 250;
	    }

	  if ( line[line_length-1] == '\n' )
	    {  line[line_length-1] = '\0';  }

	  // Checked length already so assume its safe to pop the current line into the sequence.
	  
	  // Start from the end of the sequence ( squash the terminator already there )
	  strcpy( &(db_seq[current_seq][seq_len[current_seq]]), line );
	  
	  seq_len[current_seq] += (line_length-1);

	}

      // Read in the next line for next iteration.
      line_ptr = fgets( line, MAX_HEADER_LENGTH-1, fasta_db_in );

    }

  num_seq_total = current_seq+1;

  // Close the file.
  fclose(fasta_db_in);

  printf("Done.\n");

  printf("Total number of sequences in the database is %llu.\n", num_seq_total);

  if ( sample_size >= num_seq_total )
    {
      printf("Error: The sample size is too large. <%llu>\n",sample_size);
      fflush(stdout);
      exit(1);
    }

  sample_query = (uint64_t*) malloc(sizeof(uint64_t) * sample_size);

  if ( sample_query == NULL )
    {  printf("\nError: Could not allocate sample_query.\n");  exit(1);  }

  for ( i=0; i < sample_size; i++ )
    sample_query[i] = -1;  // Initialize to a false sequence identity.

  // Fill in the histogram array.
  
  seq_min = (uint64_t)1<<52;
  seq_max = 0;

  for ( i=0; i < num_seq_total; ++i )
    {
      seq_avg += seq_len[i];

      if ( seq_min > seq_len[i] )
	{
	  seq_min = seq_len[i];
	  seq_min_id = i;
	}

      if ( seq_max < seq_len[i] )
	{
	  seq_max = seq_len[i];
	  seq_max_id = i;
	}
    }

  seq_avg_d = ( (double)seq_avg  )/( (double) num_seq_total );

  seq_avg = (uint64_t)seq_avg_d;

  // Compute the standard deviation and variance.
  for ( i=0; i < num_seq_total; i++ )
    {
      variance += ( (double)seq_len[i] - seq_avg_d  ) * ( (double)seq_len[i] - seq_avg_d );
    }

  variance = variance * (1./( (double) (num_seq_total-1) ));

  std_dev = sqrt(variance);

  printf("Average sequence length is %lf ( or %llu ).\n", seq_avg_d, seq_avg );
  printf("Minimum sequence length is %llu.\n", seq_min);
  printf("Maximum sequence length is %llu.\n", seq_max);

  printf("\n");
  printf("Standard deviation is %lf.\n",std_dev);
  printf("Variance is %lf.\n",variance);

  if ( has_range )
    {
      if ( !got_begin )
	{
	  begin_range = seq_min;
	}
      if ( !got_end )
	{
	  end_range = seq_max;
	}
      printf("Filtering on sequences in the range of [%d , %d]\n",begin_range,end_range);
    }

  // Sort the sequences according to lengths.
  printf("Initialize the sequence node array... ");

  sequences = (struct node *) malloc( num_seq_total * sizeof(struct node));

  if ( sequences == NULL )
    {  printf("\nError: Could not allocate sequences node array.\n");  exit(1);  }

  sequence_count = 0;

  double window = 0.0;
  uint64_t lower_bound = 0;
  uint64_t upper_bound = 0;
  uint64_t midpoint = 0;
  uint64_t min_seqs = 5 * sample_size;

  if ( has_range )
    midpoint = ( end_range - begin_range )/2;

  if ( has_filter )
    {
      lower_bound = filter_length - ( (uint64_t) window * filter_length);
      upper_bound = filter_length + ( (uint64_t) window * filter_length);
    }
  else if ( has_range )
    {
      lower_bound = begin_range - ( (uint64_t) window * midpoint);
      upper_bound = end_range   + ( (uint64_t) window * midpoint);
    }
  else
    {
      lower_bound = seq_min;
      upper_bound = seq_max;
    }

  while ( sequence_count < min_seqs )
    {
      sequence_count = 0;

      for ( i=0; i < num_seq_total; ++i )
	{
	  if ( has_filter || has_range )
	    {
	      if ( seq_len[i] >= lower_bound &&
		   seq_len[i] <= upper_bound )
		{
		  sequences[sequence_count].id = i;
		  sequences[sequence_count].length = seq_len[i];
		  ++sequence_count;
		}
	    }
	  else
	    {
	      sequences[sequence_count].id = i;
	      sequences[sequence_count].length = seq_len[i];
	      ++sequence_count;
	    }
	}

      printf("Attempting to sample %llu sequences in the range of [%llu , %llu]. Found %llu in the range.\n",sample_size,lower_bound,upper_bound,sequence_count);

      if ( (has_filter || has_range) && sequence_count < min_seqs )
	{
	  window = window + 0.005;
	  lower_bound = filter_length - ( (uint64_t) (window * filter_length));
	  upper_bound = filter_length + ( (uint64_t) (window * filter_length));

	  if ( window > 0.06 ) // Ok give up.
	    {
	      fprintf(stderr,"Error, window is getting too big so I'm giving up.\n");
	      fflush(stderr);
	      exit(1);
	    }

	  printf("Adding 0.005 to the filter length window, now at %lf : ( %llu , %llu )\n",window,lower_bound,upper_bound);
	}

      if ( !(has_filter || has_range) && sequence_count == 0 )
	{
	  fprintf(stderr,"ERROR: Apparently the database is empty.\n");
	  fflush(stderr);
	  exit(1);
	}
      
    }
  printf("Done\n");

  if ( !(has_filter || has_range) )
    {
      printf("Starting the sort algorithm... ");

      // Sort the nodes by sequence length.
      qsort ( sequences , num_seq_total, sizeof(struct node), compare_length );

      printf("Done\n");
    }
  else if ( has_filter )
    {
      printf("Found %llu sequences of, or around, length %llu in the database.\n",sequence_count, filter_length);
    }
  else
    {
      printf("Found %llu sequences in the range of [%llu , %llu] in the database.\n",sequence_count,lower_bound,upper_bound);
    }

  //for (i=0;i<num_seq_total;i++)
  //  {
  //    printf("%llu     %llu\n",sequences[i].length, sequences[i].id);
  //  }

  // Initialize the psuedo-random number generator.
  //srand48(time(NULL));

  //random number = drand48();

  //mt_seed();

  //srand(time(NULL));
  seed = time(NULL);
  //init_gen_rand(1384375234u);

  //seed = 1384375254u;
  init_gen_rand(seed);

  printf("Seed used = %u\n", seed);

  uint64_t letters_collected = 0;
  uint64_t samples_taken = 0;

  for ( y=0; y < sample_size ; ++y )
    {
      is_sample_repeat = 1;
      
      while ( is_sample_repeat )
	{
	  // Assume that it is not a repeat.
	  is_sample_repeat = 0;
	  
	  // Fill the data sample.
	  random_prot = gen_rand32();
	  
	  //printf("Got random number -> %llu\n",random_prot);
	  
	  random_prot = random_prot % sequence_count;
	  
	  //printf("Modulo number of sequences -> %llu\n", random_prot);
	  
	  if ( random_prot >= sequence_count || random_prot < 0 )
	    {
	      printf("Error : random_prot = %llu\n", random_prot);
	      exit(1);
	    }
	  
	  // check if sample is a repeat.
	  for (k=0; k < y; ++k )
	    {
	      if ( random_prot == sample_query[k] )
		is_sample_repeat = 1;
	    }
	}
      
      sample_query[y] = random_prot;
      ++samples_taken;

      letters_collected += sequences[random_prot].length ;

      if ( got_total )
	{
	  if ( letters_collected > target_letters )
	    y = sample_size;  // exit early
	}
    }
  
  // possibly reset sample size
  sample_size = samples_taken;

  if ( got_total )
    {
      printf("Got a sample with %d letters and %d sequences.\n",letters_collected,sample_size);
    }

  // Compute relevant statistics.
  seq_min = (uint64_t)1<<52;
  seq_max = 0;
  seq_avg = 0;
      
  for ( y=0; y < sample_size; ++y )
    {
      q = sample_query[y];
      
      seq_avg += sequences[q].length;
      
      if ( seq_min > sequences[q].length )
	{
	  seq_min = sequences[q].length;
	  seq_min_id = q;
	}
      
      if ( seq_max < sequences[q].length )
	{
	  seq_max = sequences[q].length;
	  seq_max_id = q;
	}
    }

  seq_avg_d = ( (double)seq_avg  )/( (double) sample_size );
  
  seq_avg = (uint64_t)seq_avg_d;

  // Compute the standard deviation and variance.
  for ( y=0; y < sample_size; y++ )
    {
      q = sample_query[y];
      variance += ( (double)sequences[q].length - seq_avg_d  ) * 
	( (double)sequences[q].length - seq_avg_d );
    }
  
  variance = variance * (1./( (double) (sample_size) ));
  
  std_dev = sqrt(variance);
  
  printf("  Average sequence length is %lf ( or %llu ).\n", seq_avg_d, seq_avg );
  printf("  Minimum sequence length is %llu.\n", seq_min);
  printf("  Maximum sequence length is %llu.\n", seq_max);
  printf("  Standard deviation is %lf.\n",std_dev);
  printf("  Variance is %lf.\n\n",variance);

  for ( i=0; i < sample_size; ++i )
    {
      // Retrieve sequence id.
      seq_id = sample_query[i];
      seq_id = sequences[seq_id].id;

      // Write the sequence header.
      fprintf(fasta_db_out,"%s", seq_headers[seq_id]);

      // Write out the amino acids.
      seq_len_remaining = seq_len[seq_id];

      for ( y=0; y < seq_len[seq_id]; y+=60 , seq_len_remaining-=60 )
	{
	  if ( seq_len_remaining >= 60 )
	    {
	      strncpy( line, &( db_seq[seq_id][y] ), 60 );
	      line[60] = '\0';
	    }
	  else
	    {
	      strncpy( line, &( db_seq[seq_id][y] ), seq_len_remaining );
	      line[seq_len_remaining] = '\0';
	    }

	  fprintf(fasta_db_out,"%s\n", line);
	}

    }

  // Close the file.
  fclose(fasta_db_out);

  // Clean out the memory.
  for ( i=0; i < num_seq_total; ++i )
    {
      free(db_seq[i]);
      free(seq_headers[i]);
    }

  free(db_seq);
  free(seq_headers);
  free(seq_len);
  free(seq_alloc);
  
  free(sequences);
  free(sample_query);

  return 0;
}