<commit_before>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/

#include "condor_common.h"
#include "condor_config.h"
#include "condor_debug.h"
#include "condor_attributes.h"
#include "domain_tools.h"

#include "jic_local_config.h"

JICLocalConfig::JICLocalConfig( const char* keyword, int cluster,
								int proc, int subproc ) : JICLocal()
{
	if( keyword ) {
		key = strdup( keyword );
	} else {
		EXCEPT( "Can't instantiate a JICLocalConfig object without "
				"a keyword" );
	}
	job_cluster = cluster;
	job_proc = proc;
	job_subproc = subproc;
	job_ad = new ClassAd();
	mach_ad = new ClassAd();
}

JICLocalConfig::JICLocalConfig( int cluster, int proc, int subproc )
	: JICLocal()
{
		// this is the protected version that doesn't care if there's
		// no key...
	key = NULL;
	job_cluster = cluster;
	job_proc = proc;
	job_subproc = subproc;
	job_ad = new ClassAd();
	mach_ad = new ClassAd();
}

JICLocalConfig::~JICLocalConfig()
{
	if( key ) {
		free( key );
	}
}

bool
JICLocalConfig::getLocalJobAd( void )
{
	if( ! key ) {
		dprintf( D_ALWAYS, "ERROR: Cannot get job ClassAd from config file "
				 "without a keyword, aborting\n" );
		return false;
	}

	dprintf( D_ALWAYS, "Getting job ClassAd from config file "
			 "with keyword: \"%s\"\n", key );

		// first, things we absolutely need
	if( ! getUniverse() ) {
		return false;
	}
	if( ! getString( 1, ATTR_JOB_CMD, "executable") ) {
		return false;
	}
	if( ! getString( 1, ATTR_JOB_IWD, "initialdir") ) {
		return false;
	}

#if defined ( WIN32 )
		// Windows "owners" may be of the form domain\user,
		// so we'll need to parse it...
	MyString buffer;
	buffer.formatstr( "%s_%s", key, ATTR_OWNER );
	char *owner_defined = param( buffer.Value () );
	if ( owner_defined ) {
			// On Windows we need to set RunAsOwner for it to
			// respect the owner attribute (but only when the
			// starter allows it).
		bool run_as_owner = param_boolean(
			"STARTER_ALLOW_RUNAS_OWNER", false, true, NULL, job_ad );
		if ( run_as_owner ) {
				// Add the RunAsOwner attribute:
			job_ad->Assign( ATTR_JOB_RUNAS_OWNER, true );
				// Parse the OWNER attribute and add the new
				// OWNER and NTDOMAIN attributes:
			char const *local_domain = ".";
			char *name = NULL, *domain = NULL;
			getDomainAndName ( owner_defined, domain, name );
			job_ad->Assign( OWNER, name );
			job_ad->Assign( ATTR_NT_DOMAIN, domain ? domain : local_domain );
		} else {
			dprintf( D_ALWAYS, "Local job \"Owner\" defined, "
				"but will not be used: please set "
				"STARTER_ALLOW_RUNAS_OWNER to True to "
				"enable this.\n" );
		}
		free( owner_defined );
	}
#else
		// ATTR_OWNER only matters if we're running as root, and we'll
		// catch it later if we need it and it's not defined.  so,
		// just treat it as optional at this point.
	getString( 0, ATTR_OWNER, NULL );
#endif

		// now, optional things
	getString( 0, ATTR_JOB_INPUT, "input" );
	getString( 0, ATTR_JOB_OUTPUT, "output" );
	getString( 0, ATTR_JOB_ERROR, "error" );
	getString( 0, ATTR_JOB_ARGUMENTS1, "arguments" );
	getString( 0, ATTR_JOB_ARGUMENTS2, "arguments2" );
	getString( 0, ATTR_JOB_ENVIRONMENT1, "environment" );
	getString( 0, ATTR_JOB_ENVIRONMENT2, "environment2" );
	getString( 0, ATTR_JAR_FILES, "jar_files" );
	getInt( 0, ATTR_KILL_SIG, "kill_sig" );
	getBool( 0, ATTR_STARTER_WAIT_FOR_DEBUG, "starter_wait_for_debug" );
	getString( 0, ATTR_STARTER_ULOG_FILE, "log" );
	getBool( 0, ATTR_STARTER_ULOG_USE_XML, "log_use_xml" );

		// only check for cluster and proc in the config file if we
		// didn't get them on the command-line
	if( job_cluster < 0 ) {
		getInt( 0, ATTR_CLUSTER_ID, "cluster" );
	} else {
		job_ad->Assign( ATTR_CLUSTER_ID, job_cluster );
	}
	if( job_proc < 0 ) {
		getInt( 1, ATTR_PROC_ID, "proc" );
	} else {
		job_ad->Assign( ATTR_PROC_ID, job_proc );
	}
	return true;
}

bool
JICLocalConfig::getString( bool warn, const char* attr,
						   const char* alt_name )
{
	return getAttr( warn, true, attr, alt_name );
}

bool
JICLocalConfig::getBool( bool warn, const char* attr,
						 const char* alt_name )
{
	return getAttr( warn, false, attr, alt_name );
}

bool
JICLocalConfig::getInt( bool warn, const char* attr,
						const char* alt_name )
{
	return getAttr( warn, false, attr, alt_name );
}

bool
JICLocalConfig::getAttr( bool warn, bool is_string, const char* attr,
						 const char* alt_name )
{
	char* tmp;
	char param_name[256];
	MyString expr;
	bool needs_quotes = false;

	if( job_ad->LookupExpr(attr) ) {
			// we've already got this attribute in our ClassAd, we're
			// done.
		return true;
	}

	sprintf( param_name, "%s_%s", key, attr );
	tmp = param( param_name );
	if( ! tmp && alt_name ) {
		sprintf( param_name, "%s_%s", key, alt_name );
		tmp = param( param_name );
	}
	if( ! tmp ) {
		if( warn ) {
			dprintf( D_ALWAYS,
					 "\"%s\" not found in config file\n",
					 param_name );
		}
		return false;
	}
	if( is_string && tmp[0] != '"' ) {
		needs_quotes = true;
	}

	expr = attr;
	expr += " = ";
	if( needs_quotes ) {
		expr += "\"";
	}
	expr += tmp;
	if( needs_quotes ) {
		expr += "\"";
	}
	free( tmp );

	if( job_ad->Insert(expr.Value()) ) {
		return true;
	}
	dprintf( D_ALWAYS, "ERROR: Failed to insert into job ad: %s\n",
			 expr.Value() );
	return false;
}

bool
JICLocalConfig::getUniverse( void )
{
	char* tmp;
	char param_name[256];
	int univ = 0;

		// first try the ClassAd attr name:
	sprintf( param_name, "%s_%s", key, ATTR_JOB_UNIVERSE );
	tmp = param( param_name );
	if( ! tmp ) {
			// now, try just "key_universe"
		sprintf( param_name, "%s_universe", key );
		tmp = param( param_name );
		if( ! tmp ) {
			dprintf( D_ALWAYS, "\"%s\" not found in config file\n",
					 param_name );
			return false;
		}
	}

		// tmp now holds whatever they told us the universe should be.
		// however, it might be a string universe name, or the integer
		// of the universe we eventually want.  first, see if it's
		// just an integer already...
	univ = atoi( tmp );
	if( ! univ ) {
			// it's not already an int, try to convert from a string.
		univ = CondorUniverseNumber( tmp );
	}

		// Make sure the universe we job got is valid.  If the user
		// gave a string which wasn't valid, we'll get back a 0, which
		// is the same as CONDOR_UNIVERSE_MIN, so we'll catch it.
	if( univ >= CONDOR_UNIVERSE_MAX || univ <= CONDOR_UNIVERSE_MIN ) {
		dprintf( D_ALWAYS,
				 "ERROR: Unrecognized %s \"%s\", aborting\n",
				 param_name, tmp );
		free( tmp );
		return false;
	}
		// we're done with this, so avoid leaking by free'ing now.
	free( tmp );
	tmp = NULL;

	if( ! checkUniverse(univ) ) {
		return false;
	}

	if( job_ad->Assign( ATTR_JOB_UNIVERSE, univ ) ) {
		return true;
	}
	dprintf( D_ALWAYS, "ERROR: Failed to insert into job ad: %s = %d\n",
			 ATTR_JOB_UNIVERSE, univ );
	return false;
}

<commit_msg>Fix typo in attribute name in previous commit.<commit_after>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/

#include "condor_common.h"
#include "condor_config.h"
#include "condor_debug.h"
#include "condor_attributes.h"
#include "domain_tools.h"

#include "jic_local_config.h"

JICLocalConfig::JICLocalConfig( const char* keyword, int cluster,
								int proc, int subproc ) : JICLocal()
{
	if( keyword ) {
		key = strdup( keyword );
	} else {
		EXCEPT( "Can't instantiate a JICLocalConfig object without "
				"a keyword" );
	}
	job_cluster = cluster;
	job_proc = proc;
	job_subproc = subproc;
	job_ad = new ClassAd();
	mach_ad = new ClassAd();
}

JICLocalConfig::JICLocalConfig( int cluster, int proc, int subproc )
	: JICLocal()
{
		// this is the protected version that doesn't care if there's
		// no key...
	key = NULL;
	job_cluster = cluster;
	job_proc = proc;
	job_subproc = subproc;
	job_ad = new ClassAd();
	mach_ad = new ClassAd();
}

JICLocalConfig::~JICLocalConfig()
{
	if( key ) {
		free( key );
	}
}

bool
JICLocalConfig::getLocalJobAd( void )
{
	if( ! key ) {
		dprintf( D_ALWAYS, "ERROR: Cannot get job ClassAd from config file "
				 "without a keyword, aborting\n" );
		return false;
	}

	dprintf( D_ALWAYS, "Getting job ClassAd from config file "
			 "with keyword: \"%s\"\n", key );

		// first, things we absolutely need
	if( ! getUniverse() ) {
		return false;
	}
	if( ! getString( 1, ATTR_JOB_CMD, "executable") ) {
		return false;
	}
	if( ! getString( 1, ATTR_JOB_IWD, "initialdir") ) {
		return false;
	}

#if defined ( WIN32 )
		// Windows "owners" may be of the form domain\user,
		// so we'll need to parse it...
	MyString buffer;
	buffer.formatstr( "%s_%s", key, ATTR_OWNER );
	char *owner_defined = param( buffer.Value () );
	if ( owner_defined ) {
			// On Windows we need to set RunAsOwner for it to
			// respect the owner attribute (but only when the
			// starter allows it).
		bool run_as_owner = param_boolean(
			"STARTER_ALLOW_RUNAS_OWNER", false, true, NULL, job_ad );
		if ( run_as_owner ) {
				// Add the RunAsOwner attribute:
			job_ad->Assign( ATTR_JOB_RUNAS_OWNER, true );
				// Parse the OWNER attribute and add the new
				// OWNER and NTDOMAIN attributes:
			char const *local_domain = ".";
			char *name = NULL, *domain = NULL;
			getDomainAndName ( owner_defined, domain, name );
			job_ad->Assign( ATTR_OWNER, name );
			job_ad->Assign( ATTR_NT_DOMAIN, domain ? domain : local_domain );
		} else {
			dprintf( D_ALWAYS, "Local job \"Owner\" defined, "
				"but will not be used: please set "
				"STARTER_ALLOW_RUNAS_OWNER to True to "
				"enable this.\n" );
		}
		free( owner_defined );
	}
#else
		// ATTR_OWNER only matters if we're running as root, and we'll
		// catch it later if we need it and it's not defined.  so,
		// just treat it as optional at this point.
	getString( 0, ATTR_OWNER, NULL );
#endif

		// now, optional things
	getString( 0, ATTR_JOB_INPUT, "input" );
	getString( 0, ATTR_JOB_OUTPUT, "output" );
	getString( 0, ATTR_JOB_ERROR, "error" );
	getString( 0, ATTR_JOB_ARGUMENTS1, "arguments" );
	getString( 0, ATTR_JOB_ARGUMENTS2, "arguments2" );
	getString( 0, ATTR_JOB_ENVIRONMENT1, "environment" );
	getString( 0, ATTR_JOB_ENVIRONMENT2, "environment2" );
	getString( 0, ATTR_JAR_FILES, "jar_files" );
	getInt( 0, ATTR_KILL_SIG, "kill_sig" );
	getBool( 0, ATTR_STARTER_WAIT_FOR_DEBUG, "starter_wait_for_debug" );
	getString( 0, ATTR_STARTER_ULOG_FILE, "log" );
	getBool( 0, ATTR_STARTER_ULOG_USE_XML, "log_use_xml" );

		// only check for cluster and proc in the config file if we
		// didn't get them on the command-line
	if( job_cluster < 0 ) {
		getInt( 0, ATTR_CLUSTER_ID, "cluster" );
	} else {
		job_ad->Assign( ATTR_CLUSTER_ID, job_cluster );
	}
	if( job_proc < 0 ) {
		getInt( 1, ATTR_PROC_ID, "proc" );
	} else {
		job_ad->Assign( ATTR_PROC_ID, job_proc );
	}
	return true;
}

bool
JICLocalConfig::getString( bool warn, const char* attr,
						   const char* alt_name )
{
	return getAttr( warn, true, attr, alt_name );
}

bool
JICLocalConfig::getBool( bool warn, const char* attr,
						 const char* alt_name )
{
	return getAttr( warn, false, attr, alt_name );
}

bool
JICLocalConfig::getInt( bool warn, const char* attr,
						const char* alt_name )
{
	return getAttr( warn, false, attr, alt_name );
}

bool
JICLocalConfig::getAttr( bool warn, bool is_string, const char* attr,
						 const char* alt_name )
{
	char* tmp;
	char param_name[256];
	MyString expr;
	bool needs_quotes = false;

	if( job_ad->LookupExpr(attr) ) {
			// we've already got this attribute in our ClassAd, we're
			// done.
		return true;
	}

	sprintf( param_name, "%s_%s", key, attr );
	tmp = param( param_name );
	if( ! tmp && alt_name ) {
		sprintf( param_name, "%s_%s", key, alt_name );
		tmp = param( param_name );
	}
	if( ! tmp ) {
		if( warn ) {
			dprintf( D_ALWAYS,
					 "\"%s\" not found in config file\n",
					 param_name );
		}
		return false;
	}
	if( is_string && tmp[0] != '"' ) {
		needs_quotes = true;
	}

	expr = attr;
	expr += " = ";
	if( needs_quotes ) {
		expr += "\"";
	}
	expr += tmp;
	if( needs_quotes ) {
		expr += "\"";
	}
	free( tmp );

	if( job_ad->Insert(expr.Value()) ) {
		return true;
	}
	dprintf( D_ALWAYS, "ERROR: Failed to insert into job ad: %s\n",
			 expr.Value() );
	return false;
}

bool
JICLocalConfig::getUniverse( void )
{
	char* tmp;
	char param_name[256];
	int univ = 0;

		// first try the ClassAd attr name:
	sprintf( param_name, "%s_%s", key, ATTR_JOB_UNIVERSE );
	tmp = param( param_name );
	if( ! tmp ) {
			// now, try just "key_universe"
		sprintf( param_name, "%s_universe", key );
		tmp = param( param_name );
		if( ! tmp ) {
			dprintf( D_ALWAYS, "\"%s\" not found in config file\n",
					 param_name );
			return false;
		}
	}

		// tmp now holds whatever they told us the universe should be.
		// however, it might be a string universe name, or the integer
		// of the universe we eventually want.  first, see if it's
		// just an integer already...
	univ = atoi( tmp );
	if( ! univ ) {
			// it's not already an int, try to convert from a string.
		univ = CondorUniverseNumber( tmp );
	}

		// Make sure the universe we job got is valid.  If the user
		// gave a string which wasn't valid, we'll get back a 0, which
		// is the same as CONDOR_UNIVERSE_MIN, so we'll catch it.
	if( univ >= CONDOR_UNIVERSE_MAX || univ <= CONDOR_UNIVERSE_MIN ) {
		dprintf( D_ALWAYS,
				 "ERROR: Unrecognized %s \"%s\", aborting\n",
				 param_name, tmp );
		free( tmp );
		return false;
	}
		// we're done with this, so avoid leaking by free'ing now.
	free( tmp );
	tmp = NULL;

	if( ! checkUniverse(univ) ) {
		return false;
	}

	if( job_ad->Assign( ATTR_JOB_UNIVERSE, univ ) ) {
		return true;
	}
	dprintf( D_ALWAYS, "ERROR: Failed to insert into job ad: %s = %d\n",
			 ATTR_JOB_UNIVERSE, univ );
	return false;
}

<|endoftext|>


<commit_before><commit_msg>null-check of pointer added<commit_after><|endoftext|>


<commit_before><commit_msg>Fixed/Completed buffer copy range checks.<commit_after><|endoftext|>


<commit_before><commit_msg>fix mn payment method<commit_after><|endoftext|>


<commit_before><commit_msg>tweak<commit_after><|endoftext|>


<commit_before>#include "db_construction.h"
#include "fastafile_reader.h"
#include "encoder.h"
#include "sais.h"
#include "raccess.h"
#include <math.h>
#include <time.h>

void DbConstruction::Run(const DbConstructionParameters parameters){
  vector<string> sequences; sequences.reserve(10);
  vector<unsigned char> encoded_sequences;
  vector<int> suffix_array;
  vector<vector <int> > start_hash; start_hash.reserve(parameters.GetHashSize());
  vector<vector <int> > end_hash; start_hash.reserve(parameters.GetHashSize());

  ReadFastaFile(parameters, sequences);
  CalculateAccessibility(parameters,sequences);
  ConstructSuffixArray(parameters, sequences,encoded_sequences,suffix_array);
  ConstructHashForShortSubstring(parameters, encoded_sequences, suffix_array, start_hash, end_hash);

  SaveIndexData(parameters.GetDbFilename(), suffix_array, start_hash, end_hash);
  SaveSequenceData(parameters.GetDbFilename(), sequences, encoded_sequences);

}

void DbConstruction::ReadFastaFile(const DbConstructionParameters parameters,  vector<string> &sequences){
  vector<string> names; names.reserve(10);
  FastafileReader fastafile_reader;
  fastafile_reader.ReadFastafile(parameters.GetInputFilename(), sequences, names);
  SaveBasicInformation(parameters, names);
}

void DbConstruction::CalculateAccessibility(const DbConstructionParameters parameters, vector<string> &sequences){
  Raccess raccess(parameters.GetDbFilename(), parameters.GetMaximalSpan(), parameters.GetMinAccessibleLength());
  for (int i = 0; i < sequences.size() ; i++){
    raccess.Run(sequences[i]);
  }
}

void DbConstruction::ConstructSuffixArray(const DbConstructionParameters parameters, vector<string> &sequences,  vector<unsigned char> &encoded_sequences, vector<int> &suffix_array){
  Encoder encoder(parameters.GetRepeatFlag());
  encoder.Encode(sequences, encoded_sequences, 1);
  suffix_array.resize(encoded_sequences.size());
  sais(&encoded_sequences[0], &suffix_array[0], encoded_sequences.size());
};

void DbConstruction::ConstructHashForShortSubstring(const DbConstructionParameters parameters,  vector<unsigned char> &encoded_sequences, vector<int> &suffix_array, vector<vector <int> > &start_hash, vector<vector <int> > &end_hash){
  int nucleotide_size = 4;

  for(int i = 0; i < parameters.GetHashSize(); i++){
    vector<int> temp_vector; temp_vector.reserve((int)pow(nucleotide_size,i+1));
    start_hash.push_back(temp_vector);
    vector<int> temp_vector2; temp_vector2.reserve((int)pow(nucleotide_size,i+1));
    end_hash.push_back(temp_vector2);
  }

  int start = 0;  int end = 0;
  for(int i = 0; i < parameters.GetHashSize(); i++){
    for(int j  =0; j < (int)pow(nucleotide_size,i+1); j++){
      unsigned char c = (j%4)+2;
      if(i == 0){
	start = 0;
	end = suffix_array.size()-1;
      }else{
	start = start_hash[i-1][j/4];
	end = end_hash[i-1][j/4];
      }
      Search(encoded_sequences, suffix_array, &start, &end, c, i);
      start_hash[i].push_back(start);
      end_hash[i].push_back(end);
    }
  }
}

void DbConstruction::SaveSequenceData(string file_name, vector<string> &sequences, vector<unsigned char> &encoded_sequences){
  ofstream of((file_name+".seq").c_str(), ios::out | ios::binary);
  int number_of_seq = sequences.size();
  of.write(reinterpret_cast<const char*>(&number_of_seq), sizeof(int));
  for(int i = 0; i < number_of_seq; i++){
    int seq_size = sequences[i].size();
    of.write(reinterpret_cast<const char*>(&seq_size), sizeof(int));
  }
  int count = encoded_sequences.size();
  vector<unsigned char>::iterator it;
  of.write(reinterpret_cast<const char*>(&count), sizeof(int));
  for(it = encoded_sequences.begin(); it != encoded_sequences.end(); it++){
    of.write(reinterpret_cast<const char*>(&*it), sizeof(unsigned char));
  }
  of.close();
}

void  DbConstruction::SaveIndexData(string file_name, vector<int> &suffix_array, vector<vector <int> > &start_hash, vector<vector <int> > &end_hash){
  ofstream of((file_name+".ind").c_str(), ios::out | ios::binary);
  int count = suffix_array.size();
  vector<int>::iterator it;
  of.write(reinterpret_cast<const char*>(&count), sizeof(int));
  for(it = suffix_array.begin(); it != suffix_array.end(); it++){
    of.write(reinterpret_cast<const char*>(&*it), sizeof(int));
  }
  for(int i = 0; i< start_hash.size();i++){
    for(it = start_hash[i].begin(); it != start_hash[i].end(); it++){
      of.write(reinterpret_cast<const char*>(&*it), sizeof(int));
    }
  }
  for(int i = 0; i< end_hash.size();i++){
    for(it = end_hash[i].begin(); it != end_hash[i].end(); it++){
      of.write(reinterpret_cast<const char*>(&*it), sizeof(int));
    }
  }
  of.close();
}

void DbConstruction::SaveBasicInformation(DbConstructionParameters parameters, vector<string> &names){
  ofstream of((parameters.GetDbFilename()+".bas").c_str(), ios::out | ios::binary);
  int hash_size = parameters.GetHashSize();
  int repeat_flag = parameters.GetRepeatFlag();
  int maximal_span = parameters.GetMaximalSpan();
  int min_accessible_length = parameters.GetMinAccessibleLength();
  of.write(reinterpret_cast<const char*>(&hash_size), sizeof(int));
  of.write(reinterpret_cast<const char*>(&repeat_flag), sizeof(int));
  of.write(reinterpret_cast<const char*>(&maximal_span), sizeof(int));
  of.write(reinterpret_cast<const char*>(&min_accessible_length), sizeof(int));

  of.close();
  of.open((parameters.GetDbFilename()+".nam").c_str(), ios::out);
  for(int i = 0; i < names.size(); i++){
    of << names[i] << endl;
  }

  of.close();
}

void DbConstruction::Search(vector<unsigned char> &encoded_sequences, vector<int> &suffix_array, int* start, int* end, unsigned char c, int offset){
  int s = *start;
  int e = *end;
  int m;

  if (suffix_array[s] + offset >= encoded_sequences.size()) {
    ++(*start);
  }

  if(s>e){
    *start = 1;
    *end = 0;
    return;
  }else if (s == e) {
    if (encoded_sequences[suffix_array[s]+offset] == c) {
      return;
    } else {
      *start = 1;
      *end = 0;
      return;
    }
  }

  if (encoded_sequences[suffix_array[s]+offset] != c) {
    while (s < e - 1) {
      m = (s + e) / 2;
      if (encoded_sequences[suffix_array[m]+offset] < c) {
        s = m;
      } else {
        e = m;
      }
    }
    if (encoded_sequences[suffix_array[e]+offset] != c) {
      *start = 1;
      *end = 0;
      return;
    }
    *start = e;
    s = e;
    e = *end;
  }

  if (encoded_sequences[suffix_array[e]+offset] != c) {
    while (s < e - 1) {
      m = (s + e) / 2;
      if (encoded_sequences[suffix_array[m]+offset] > c) {
        e = m;
      } else {
        s = m;
      }
    }
    if (encoded_sequences[suffix_array[s]+offset] != c) {
      *start = 1;
      *end = 0;
      return;
    }
    *end = s;
  }
  return;
}
<commit_msg>Delete db_construction.cpp<commit_after><|endoftext|>


<commit_before>
#include "io/idemowriter.h"
#include "io/demoreader.h"
#include <cstdio>
#include <string>
#include <cassert>

std::string GetExtension(const std::string& filename)
{
    size_t index = filename.find_last_of(".");
    if (index != std::string::npos)
    {
        return filename.substr(index + 1);
    }
    return std::string();
}

enum class FileType
{
    None,
    Dem,
    Json,
    ConLog
};

FileType GetFileType(const std::string& filename)
{
    std::string ext = GetExtension(filename);
    if (ext == "dem")
    {
        return FileType::Dem;
    }
    if (ext == "json")
    {
        return FileType::Json;
    }
    if (ext == "con")
    {
        return FileType::ConLog;
    }
    return FileType::None;
}

int main(const int argc, const char* argv[])
{
    if (argc != 3)
    {
        fprintf(stderr, "Usage: %s <in>.dem/json <out>.dem/json/con\n", argv[0]);
        return -1;
    }

    std::string inputFile(argv[1]);
    std::string outputFile(argv[2]);

    FileType inputType = GetFileType(inputFile);
    FileType outputType = GetFileType(outputFile);
    if (inputType == FileType::None)
    {
        fprintf(stderr, "Error: Bad type for input file\n");
        return -1;
    }
    if (outputType == FileType::None)
    {
        fprintf(stderr, "Error: Bad type for output file\n");
        return -1;
    }

    FILE* inputFp = fopen(inputFile.c_str(), "rb");
    if (!inputFp)
    {
        fprintf(stderr, "Error: Could not open input file\n");
        return -1;
    }

    FILE* outputFp = fopen(outputFile.c_str(), "wb");
    if (!outputFp)
    {
        fprintf(stderr, "Error: Could not open input file\n");
        fclose(inputFp);
        return -1;
    }

    IDemoWriter* writer = nullptr;
    if (outputType == FileType::Dem)
    {
        writer = IDemoWriter::CreateDemoWriter(outputFp);
    }
    else if (outputType == FileType::Json)
    {
        writer = IDemoWriter::CreateJsonWriter(outputFp);
    }
    else if (outputType == FileType::ConLog)
    {
        writer = IDemoWriter::CreateConLogWriter(outputFp);
    }
    else
    {
        assert(false);
    }

    if (inputType == FileType::Dem)
    {
        DemoReader::ProcessDem(inputFp, writer);
    }
    else if (inputType == FileType::Json)
    {
        DemoReader::ProcessJson(inputFp, writer);
    }
    else
    {
        assert(false);
    }
    fclose(inputFp);
    fclose(outputFp);

    IDemoWriter::FreeDemoWriter(writer);
    return 0;
}
<commit_msg>Destruct writer before closing files so writer can flush buffers<commit_after>
#include "io/idemowriter.h"
#include "io/demoreader.h"
#include <cstdio>
#include <string>
#include <cassert>

std::string GetExtension(const std::string& filename)
{
    size_t index = filename.find_last_of(".");
    if (index != std::string::npos)
    {
        return filename.substr(index + 1);
    }
    return std::string();
}

enum class FileType
{
    None,
    Dem,
    Json,
    ConLog
};

FileType GetFileType(const std::string& filename)
{
    std::string ext = GetExtension(filename);
    if (ext == "dem")
    {
        return FileType::Dem;
    }
    if (ext == "json")
    {
        return FileType::Json;
    }
    if (ext == "con")
    {
        return FileType::ConLog;
    }
    return FileType::None;
}

int main(const int argc, const char* argv[])
{
    if (argc != 3)
    {
        fprintf(stderr, "Usage: %s <in>.dem/json <out>.dem/json/con\n", argv[0]);
        return -1;
    }

    std::string inputFile(argv[1]);
    std::string outputFile(argv[2]);

    FileType inputType = GetFileType(inputFile);
    FileType outputType = GetFileType(outputFile);
    if (inputType == FileType::None)
    {
        fprintf(stderr, "Error: Bad type for input file\n");
        return -1;
    }
    if (outputType == FileType::None)
    {
        fprintf(stderr, "Error: Bad type for output file\n");
        return -1;
    }

    FILE* inputFp = fopen(inputFile.c_str(), "rb");
    if (!inputFp)
    {
        fprintf(stderr, "Error: Could not open input file\n");
        return -1;
    }

    FILE* outputFp = fopen(outputFile.c_str(), "wb");
    if (!outputFp)
    {
        fprintf(stderr, "Error: Could not open input file\n");
        fclose(inputFp);
        return -1;
    }

    IDemoWriter* writer = nullptr;
    if (outputType == FileType::Dem)
    {
        writer = IDemoWriter::CreateDemoWriter(outputFp);
    }
    else if (outputType == FileType::Json)
    {
        writer = IDemoWriter::CreateJsonWriter(outputFp);
    }
    else if (outputType == FileType::ConLog)
    {
        writer = IDemoWriter::CreateConLogWriter(outputFp);
    }
    else
    {
        assert(false);
    }

    if (inputType == FileType::Dem)
    {
        DemoReader::ProcessDem(inputFp, writer);
    }
    else if (inputType == FileType::Json)
    {
        DemoReader::ProcessJson(inputFp, writer);
    }
    else
    {
        assert(false);
    }
    IDemoWriter::FreeDemoWriter(writer);

    fclose(inputFp);
    fclose(outputFp);
    return 0;
}
<|endoftext|>


<commit_before>// This example demonstrates how classes can be extended / modified using
// mixins and templates
// Contruction problem is solved using variadic templates and perfect forwarding

#include <array>
#include <iostream>
#include <string>
#include <typeinfo>
#include <utility>
#include <vector>

#include "cpp_magic.h"
#include "timing.h"

using std::ostream;

template <typename Type, typename EnclosingClass, int id>
struct SelectAllMembers {
  typedef Type type;
};

/// Type for removed data members - which can be optimized out by the compiler
struct Nulltype {
  int empty[0] = {};
  Nulltype() {}
  template <typename T>
  Nulltype(T&& d) {}  // NOLINT(runtime/explicit)
  template <typename T>
  Nulltype& operator=(const T& other) {
    return *this;
  }
  friend ostream& operator<<(ostream& out, const Nulltype& value) {
    return out;
  }
};

/// loops over variadic macro arguments and calls the specified operation
/// removes the first three parameters in each iteration, but adds the first one
/// again for the next call
/// e.g. LOOP(OP, a, b, c, d, e) will lead to:
/// OP(a, b, c)
/// OP(a, d, e)
/// For a more detailed explanation see `MAP` macro in `third_party/cpp_magic.h`
// clang-format off
#define LOOP(operation, first, second, third, ...)           \
  operation(first, second, third)                            \
  IF(HAS_ARGS(__VA_ARGS__))(                                 \
    DEFER2(_LOOP)()(operation, first, __VA_ARGS__))
#define _LOOP() LOOP
// clang-format on

/// adds the partial template specialization to select one clazz-member pair
/// only for internal usage - will be called inside LOOP
/// @param name:    selector name
/// @param clazz:   clazz of the data member
/// @param member:  data member name
#define INTERNAL_SELECT_MEMBER(name, clazz, member)             \
  template <typename Type>                                      \
  struct name<Type, clazz, clazz::getDataMemberUid##member()> { \
    typedef Type type;                                          \
  };

/// creates a new selector type
/// it only enables the specified data members if applied to a simulation object
/// others will be removed
#define NEW_MEMBER_SELECTOR(name, ...)                      \
  template <typename Type, typename EnclosingClass, int id> \
  struct name {                                             \
    typedef Nulltype type;                                  \
  };                                                        \
  EVAL(LOOP(INTERNAL_SELECT_MEMBER, name, __VA_ARGS__))

/// adds the partial template specialization to remove one clazz-member pair
/// only for internal usage - will be called inside LOOP
/// @param name:    selector name
/// @param clazz:   clazz of the data member
/// @param member:  data member name
#define INTERNAL_MEMBER_REMOVER(name, clazz, member)            \
  template <typename Type>                                      \
  struct name<Type, clazz, clazz::getDataMemberUid##member()> { \
    typedef Nulltype type;                                      \
  };

/// creates a new selector type
/// it removes the specified data members if applied to a simulation object
/// others will be kept -> inverse of NEW_MEMBER_SELECTOR
#define NEW_MEMBER_REMOVER(name, ...)                       \
  template <typename Type, typename EnclosingClass, int id> \
  struct name {                                             \
    typedef Type type;                                      \
  };                                                        \
  EVAL(LOOP(INTERNAL_MEMBER_REMOVER, name, __VA_ARGS__))

#define BDM_DEFAULT_TEMPLATE                                           \
  template <template <typename, typename, int> class TMemberSelector = \
                SelectAllMembers>

/// Macro to define data member for a simulation object
/// Hides complexity needed to conditionally remove the data member
#define BDM_DATA_MEMBER(access_modifier, type_name, var_name)               \
 public:                                                                    \
  static constexpr int getDataMemberUid##var_name() { return __COUNTER__; } \
 access_modifier:                                                           \
  typename TMemberSelector<type_name, self,                                 \
                           getDataMemberUid##var_name()>::type var_name

#define BDM_PUBLIC_MEMBER(type_name, var_name) \
 BDM_DATA_MEMBER(public, REMOVE_TRAILING_COMMAS(type_name), var_name)

#define BDM_PROTECTED_MEMBER(type_name, var_name) \
 BDM_DATA_MEMBER(protected, REMOVE_TRAILING_COMMAS(type_name), var_name)

#define BDM_PRIVATE_MEMBER(type_name, var_name) \
 BDM_DATA_MEMBER(private, REMOVE_TRAILING_COMMAS(type_name), var_name)

class NullBaseClass {};

// -----------------------------------------------------------------------------
// core library only defines minimal cell
BDM_DEFAULT_TEMPLATE
class BaseCell {
 public:
  using self = BaseCell<>;
  explicit BaseCell(const std::array<double, 3>& pos) : position_(pos) {}
  BaseCell() : position_{0, 0, 0} {}
  const std::array<double, 3>& GetPosition() const { return position_; }

 protected:
  BDM_PROTECTED_MEMBER(std::array<double COMMA() 3>, position_);
  BDM_PROTECTED_MEMBER(double, unused_) = 6.28;
};

template <typename Cell>
void CoreOp(Cell* cell) {
  std::cout << cell->GetPosition()[2] << std::endl;
}

// -----------------------------------------------------------------------------
// libraries for specific specialities add functionality - e.g. Neuroscience
class Neurite {};

// adds Neurites to BaseCell
// typename TNeurite = Neurite,
template <typename Base, template <typename, typename, int>
                         class TMemberSelector = SelectAllMembers>
class Neuron : public Base {
 public:
  using self = Neuron<Base>;
  template <class... A>
  explicit Neuron(const std::vector<Neurite>& neurites, const A&... a)
      : Base(a...), neurites_{neurites} {}
  Neuron() = default;
  const std::vector<Neurite>& GetNeurites() const { return neurites_; }

 private:
  BDM_PRIVATE_MEMBER(std::vector<Neurite>, neurites_);
};

// -----------------------------------------------------------------------------
// code written by life scientists using package core and Neuroscience extension
template <typename Base, template <typename, typename, int>
                         class TMemberSelector = SelectAllMembers>
class NeuronExtension : public Base {
 public:
  using self = NeuronExtension<Base>;
  template <class... A>
  explicit NeuronExtension(double foo, const A&... a)
      : Base(a...), foo_{foo} {}
  NeuronExtension() = default;
  double GetFoo() const {
    volatile auto& foo = Base::position_;
    return foo_;
  }

 private:
  BDM_PRIVATE_MEMBER(double, foo_) = 3.14;
};

template <typename Cell>
void CustomOp(const Cell& cell) {
  std::cout << cell->GetNeurites().size() << " - " << cell->GetFoo()
            << std::endl;
}

NEW_MEMBER_REMOVER(RemoveUnused, BaseCell<>, unused_);

BDM_DEFAULT_TEMPLATE
using MyNeuron = Neuron<BaseCell<TMemberSelector>, TMemberSelector>;

BDM_DEFAULT_TEMPLATE
using MyExtendedNeuron =
    NeuronExtension<Neuron<BaseCell<TMemberSelector>, TMemberSelector>,
                    TMemberSelector>;

int main() {
  BaseCell<> base;
  CoreOp(&base);

  Neuron<BaseCell<> > neuron;
  CoreOp(&base);
  std::cout << neuron.GetNeurites().size() << std::endl;

  MyNeuron<> my_neuron;
  MyNeuron<RemoveUnused> my_neuron_wo_unused;

  std::cout << sizeof(my_neuron) << " - " << sizeof(my_neuron_wo_unused)
            << std::endl;

  NeuronExtension<Neuron<BaseCell<> > > extended_neuron;
  CustomOp(&extended_neuron);

  MyExtendedNeuron<> my_extended_neuron(1.2, std::vector<Neurite>{Neurite()},
                                        std::array<double, 3>{1, 2, 3});
  MyExtendedNeuron<RemoveUnused> my_extended_neuron_wo_unused;
  std::cout << sizeof(my_extended_neuron) << " - "
            << sizeof(my_extended_neuron_wo_unused) << std::endl;
  CoreOp(&my_extended_neuron);
  CustomOp(&my_extended_neuron);

  return 0;
}
<commit_msg>Integrate data member selectors in flexibility prototype<commit_after>// This example demonstrates how classes can be extended / modified using
// mixins and templates
// Contruction problem is solved using variadic templates and perfect forwarding

#include <array>
#include <iostream>
#include <string>
#include <typeinfo>
#include <utility>
#include <vector>
#include <stdexcept>

#include "cpp_magic.h"
#include "timing.h"

using std::ostream;

/// default data member selector which does not remove any data members
template <typename Type, typename EnclosingClass, int id>
struct SelectAllMembers {
  typedef Type type;
};

/// Type for removed data members - which can be optimized out by the compiler
struct Nulltype {
  int empty[0] = {};
  Nulltype() {}
  template <typename T>
  Nulltype(T&& d) {}  // NOLINT(runtime/explicit)
  template <typename T>
  Nulltype& operator=(const T& other) {
    return *this;
  }

  template <typename T>
  Nulltype(std::initializer_list<T>) {}

  friend ostream& operator<<(ostream& out, const Nulltype& value) {
    return out;
  }
};

/// loops over variadic macro arguments and calls the specified operation
/// removes the first three parameters in each iteration, but adds the first one
/// again for the next call
/// e.g. LOOP(OP, a, b, c, d, e) will lead to:
/// OP(a, b, c)
/// OP(a, d, e)
/// For a more detailed explanation see `MAP` macro in `third_party/cpp_magic.h`
// clang-format off
#define LOOP(operation, first, second, third, ...)           \
  operation(first, second, third)                            \
  IF(HAS_ARGS(__VA_ARGS__))(                                 \
    DEFER2(_LOOP)()(operation, first, __VA_ARGS__))
#define _LOOP() LOOP
// clang-format on

/// adds the partial template specialization to select one clazz-member pair
/// only for internal usage - will be called inside LOOP
/// @param name:    selector name
/// @param clazz:   clazz of the data member
/// @param member:  data member name
#define INTERNAL_SELECT_MEMBER(name, clazz, member)             \
  template <typename Type>                                      \
  struct name<Type, clazz, clazz::getDataMemberUid##member()> { \
    typedef Type type;                                          \
  };

/// creates a new selector type
/// it only enables the specified data members if applied to a simulation object
/// others will be removed
#define NEW_MEMBER_SELECTOR(name, ...)                      \
  template <typename Type, typename EnclosingClass, int id> \
  struct name {                                             \
    typedef Nulltype type;                                  \
  };                                                        \
  EVAL(LOOP(INTERNAL_SELECT_MEMBER, name, __VA_ARGS__))

/// adds the partial template specialization to remove one clazz-member pair
/// only for internal usage - will be called inside LOOP
/// @param name:    selector name
/// @param clazz:   clazz of the data member
/// @param member:  data member name
#define INTERNAL_MEMBER_REMOVER(name, clazz, member)            \
  template <typename Type>                                      \
  struct name<Type, clazz, clazz::getDataMemberUid##member()> { \
    typedef Nulltype type;                                      \
  };

/// creates a new selector type
/// it removes the specified data members if applied to a simulation object
/// others will be kept -> inverse of NEW_MEMBER_SELECTOR
#define NEW_MEMBER_REMOVER(name, ...)                       \
  template <typename Type, typename EnclosingClass, int id> \
  struct name {                                             \
    typedef Type type;                                      \
  };                                                        \
  EVAL(LOOP(INTERNAL_MEMBER_REMOVER, name, __VA_ARGS__))

#define BDM_DEFAULT_TEMPLATE(template_param_name)                          \
  template <template <typename, typename, int> class template_param_name = \
                SelectAllMembers>

/// Macro to define data member for a simulation object
/// Hides complexity needed to conditionally remove the data member
#define BDM_DATA_MEMBER(access_modifier, type_name, var_name)               \
 public:                                                                    \
  static constexpr int getDataMemberUid##var_name() { return __COUNTER__; } \
  access_modifier:                                                          \
  typename TMemberSelector<type_name, self,                                 \
                           getDataMemberUid##var_name()>::type var_name

#define BDM_PUBLIC_MEMBER(type_name, var_name) \
  BDM_DATA_MEMBER(public, REMOVE_TRAILING_COMMAS(type_name), var_name)

#define BDM_PROTECTED_MEMBER(type_name, var_name) \
  BDM_DATA_MEMBER(protected, REMOVE_TRAILING_COMMAS(type_name), var_name)

#define BDM_PRIVATE_MEMBER(type_name, var_name) \
  BDM_DATA_MEMBER(private, REMOVE_TRAILING_COMMAS(type_name), var_name)

/// Macro to insert required boilerplate code into classes
/// @param: self_specifier: used to point to static members / functions of this
///         class - use PlaceholderType for template parameters without default
///         parameter - e.g.
///         `class A {};`
///           -> self_specifier: A
///         `template<typename T=DefaultValue> class B {};`
///           -> self_specifier: B<>
///         `template<typename T, typename U> class C {};`
///           -> self_specifier: C<PlaceholderType COMMA() PlaceholderType>
#define BDM_CLASS_HEADER(self_specifier)                                 \
 public:                                                                 \
  using self = self_specifier;                                           \
  template <typename Type, typename EnclosingClass, int id>              \
  using TMemberSelector =                                                \
      typename Base::template TMemberSelector<Type, EnclosingClass, id>; \
                                                                         \
 private:

// -----------------------------------------------------------------------------
// core library
BDM_DEFAULT_TEMPLATE(TTMemberSelector)
struct BdmSimObject {
  template <typename Type, typename EnclosingClass, int id>
  using TMemberSelector = TTMemberSelector<Type, EnclosingClass, id>;
};

/// This struct is used to access static functions / members of a class that
/// has template parameter(s) without a default value.
/// e.g.
/// ```
/// template <typename T> class Foo { static const int kBar = 3; };
/// Foo<PlaceholderType>::kBar
/// ```
/// The definition of the static function / member must be invariant of the
/// template parameter(s)
/// e.g. `Foo<PlaceholderType>::kBar == Foo<AnyOtherType>::kBar`
/// Usage solely to create a valid id for the scope operator. It is not allowed
/// to instantiate an object with template parameter PlaceholderType. The
/// following statement is invalid and will throw an exception at runtime:
/// `Foo<PlaceholderType> foo;`
struct PlaceholderType : public BdmSimObject<> {
  PlaceholderType() {
    throw std::logic_error(
        "Creating an instance of type PlaceholderType is not allowed. "
        "PlaceholderType should solely be used for creating a valid id "
        "for the scope operator");
  }
  template <class... A>
  PlaceholderType(const A&... a)
      : PlaceholderType() {}
};

template <typename Base = BdmSimObject<> >
class BaseCell : public Base {
  BDM_CLASS_HEADER(BaseCell<>);

 public:
  explicit BaseCell(const std::array<double, 3>& pos) : position_(pos) {}
  BaseCell() : position_{0, 0, 0} {}
  const std::array<double, 3>& GetPosition() const { return position_; }

 protected:
  BDM_PROTECTED_MEMBER(std::array<double COMMA() 3>, position_);
  BDM_PROTECTED_MEMBER(double, unused_) = 6.28;
};

template <typename Cell>
void CoreOp(Cell* cell) {
  std::cout << "[CoreOp] cell z-position: " << cell->GetPosition()[2]
            << std::endl;
}

// -----------------------------------------------------------------------------
// libraries for specific specialities add functionality - e.g. Neuroscience
class Neurite {};

// add Neurites to BaseCell
template <typename Base = BaseCell<> >
class Neuron : public Base {
  BDM_CLASS_HEADER(Neuron<>);

 public:
  template <class... A>
  explicit Neuron(const std::vector<Neurite>& neurites, const A&... a)
      : Base(a...), neurites_{neurites} {}
  Neuron() = default;
  const std::vector<Neurite>& GetNeurites() const { return neurites_; }

 private:
  BDM_PRIVATE_MEMBER(std::vector<Neurite>, neurites_);
};

// define easy to use templated type alias
BDM_DEFAULT_TEMPLATE(MemberSelector)
using BdmNeuron = Neuron<BaseCell<BdmSimObject<MemberSelector> > >;

// -----------------------------------------------------------------------------
// code written by life scientists using package core and Neuroscience extension
// extend Neuron definition provided by extension
template <typename Base>
class NeuronExtension : public Base {
  BDM_CLASS_HEADER(NeuronExtension<PlaceholderType>);

 public:
  template <class... A>
  explicit NeuronExtension(double foo, const A&... a)
      : Base(a...), foo_{foo} {}
  NeuronExtension() = default;
  double GetFoo() const {
    volatile auto& foo = Base::position_;
    return foo_;
  }

 private:
  BDM_PRIVATE_MEMBER(double, foo_) = 3.14;
};

// define easy to use templated type alias
BDM_DEFAULT_TEMPLATE(MemberSelector)
using MyExtendedNeuron =
    NeuronExtension<Neuron<BaseCell<BdmSimObject<MemberSelector> > > >;

// define some client code that processes extended neurons
template <typename Cell>
void CustomOp(const Cell& cell) {
  std::cout << "[CustomOp] cell #neurites " << cell->GetNeurites().size()
            << std::endl
            << "           cell.foo_      " << cell->GetFoo() << std::endl;
}

// define member selectors to remove data members that won't be used in the
// simulation
NEW_MEMBER_REMOVER(RemoveUnused, BaseCell<>, unused_);
NEW_MEMBER_SELECTOR(FooSelector, NeuronExtension<PlaceholderType>, foo_);

int main() {
  // --------------------------
  // use only classes from core
  BaseCell<> base;
  CoreOp(&base);

  // -------------------------------------
  // use class from neuroscience extension
  Neuron<> neuron;
  CoreOp(&neuron);

  BdmNeuron<> neuron1;
  // following statement is equivalent to:
  // Neuron<BaseCell<BdmSimObject<RemoveUnused> > >
  BdmNeuron<RemoveUnused> neuron_wo_unused;

  std::cout << "sizeof(neuron1)          " << sizeof(neuron1) << std::endl
            << "sizeof(neuron_wo_unused) " << sizeof(neuron_wo_unused)
            << std::endl;

  // ---------------------
  // use customized neuron
  NeuronExtension<Neuron<> > extended_neuron;
  CoreOp(&extended_neuron);
  CustomOp(&extended_neuron);

  // equivalent but with easier interface
  MyExtendedNeuron<> extended_neuron1(1.2, std::vector<Neurite>{Neurite()},
                                      std::array<double, 3>{1, 2, 3});
  CoreOp(&extended_neuron1);
  CustomOp(&extended_neuron1);

  // easier customizeble interface to
  MyExtendedNeuron<RemoveUnused> extended_neuron_wo_unused;
  MyExtendedNeuron<FooSelector> extended_neuron_only_foo;
  std::cout << "sizeof(extended_neuron1)          " << sizeof(extended_neuron1)
            << std::endl
            << "sizeof(extended_neuron_wo_unused) "
            << sizeof(extended_neuron_wo_unused) << std::endl
            << "sizeof(extended_neuron_only_foo)  "
            << sizeof(extended_neuron_only_foo) << std::endl;

  return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2017, James Jackson and Daniel Koch, BYU MAGICC Lab
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * * Neither the name of the copyright holder nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"

#include "revo.h"

namespace rosflight_firmware {

Revo::Revo()
{
}
Revo::~Revo()
{

}

void Revo::init_board(void)
{
  systemInit();
  led2_.init(LED2_GPIO, LED2_PIN);
  led1_.init(LED1_GPIO, LED1_PIN);

  int_i2c_.init(&i2c_config[MAG_I2C]);
  ext_i2c_.init(&i2c_config[EXTERNAL_I2C]);
  spi1_.init(&spi_config[MPU6000_SPI]);
  spi3_.init(&spi_config[FLASH_SPI]);

  serial_interfaces_[0]=&vcp_;
  serial_interfaces_[1]=&uart_;

  this->current_serial_=&uart_;
  //this->current_serial_=&vcp;
}

void Revo::board_reset(bool bootloader)
{
  NVIC_SystemReset();
}

// clock
uint32_t Revo::clock_millis()
{
  return millis();
}

uint64_t Revo::clock_micros()
{
  return micros();
}

void Revo::clock_delay(uint32_t milliseconds)
{
  delay(milliseconds);
}

// serial
void Revo::serial_init(uint32_t baud_rate)
{
  uart_.init(&uart_config[0], baud_rate);
  vcp_.init();
}

void Revo::serial_write(const uint8_t *src, size_t len)
{
  current_serial_->write(src, len);
}

uint16_t Revo::serial_bytes_available(void)
{
  return current_serial_->rx_bytes_waiting();
}

uint8_t Revo::serial_read(void)
{
  return current_serial_->read_byte();
}

void Revo::serial_flush()
{
  current_serial_->flush();
}

Serial** Revo::get_serial_interfaces()
{
    return serial_interfaces_;
}

uint8_t Revo::get_serial_count()
{
    return 2;
}

// sensors
void Revo::sensors_init()
{
  imu_.init(&spi1_);
  mag_.init(&int_i2c_);
  baro_.init(&int_i2c_);
  airspeed_.init(&ext_i2c_);

  while(millis() < 50); // wait for sensors to boot up
}

uint16_t Revo::num_sensor_errors(void)
{
  return int_i2c_.num_errors();
}

bool Revo::new_imu_data()
{
  return imu_.new_data();
}

bool Revo::imu_read(float accel[3], float* temperature, float gyro[3], uint64_t* time_us)
{
  float read_accel[3], read_gyro[3];
  imu_.read(read_accel, read_gyro, temperature, time_us);

  accel[0] = -read_accel[1];
  accel[1] = -read_accel[0];
  accel[2] = -read_accel[2];

  gyro[0] = -read_gyro[1];
  gyro[1] = -read_gyro[0];
  gyro[2] = -read_gyro[2];

  return true;
}

void Revo::imu_not_responding_error(void)
{
  sensors_init();
}

void Revo::mag_read(float mag[3])
{
  mag_.update();
  mag_.read(mag);
}

bool Revo::mag_check(void)
{
  mag_.update();
  return mag_.present();
}

void Revo::baro_read(float *pressure, float *temperature)
{
  baro_.update();
  baro_.read(pressure, temperature);
}

bool Revo::baro_check()
{
  baro_.update();
  return baro_.present();
}

bool Revo::diff_pressure_check(void)
{
  airspeed_.update();
  return airspeed_.present();
}

void Revo::diff_pressure_read(float *diff_pressure, float *temperature)
{
  airspeed_.update();
  airspeed_.read(diff_pressure, temperature);
}

bool Revo::sonar_check(void)
{
  return false;
}

float Revo::sonar_read(void)
{
  return 0.0;
}

// PWM
void Revo::pwm_init(bool cppm, uint32_t refresh_rate, uint16_t idle_pwm)
{
  for (int i = 0; i < PWM_NUM_OUTPUTS; i++)
  {
    esc_out_[i].init(&pwm_config[i], refresh_rate, 2000, 1000);
    esc_out_[i].writeUs(idle_pwm);
  }
  rc_.init(&pwm_config[RC_PPM_PIN]);
}

uint16_t Revo::pwm_read(uint8_t channel)
{
  return rc_.read(channel);
}

void Revo::pwm_write(uint8_t channel, uint16_t value)
{
  esc_out_[channel].writeUs(value);
}

bool Revo::pwm_lost()
{
  return rc_.lost();
}

// non-volatile memory
void Revo::memory_init(void)
{
  return flash_.init(&spi3_);
}

bool Revo::memory_read(void * data, size_t len)
{
  return flash_.read_config((uint8_t*)data, len);
}

bool Revo::memory_write(const void * data, size_t len)
{
  return flash_.write_config((uint8_t*)data, len);
}

// LED
void Revo::led0_on(void) { led1_.on(); }
void Revo::led0_off(void) { led1_.off(); }
void Revo::led0_toggle(void) { led1_.toggle(); }

void Revo::led1_on(void) { led2_.on(); }
void Revo::led1_off(void) { led2_.off(); }
void Revo::led1_toggle(void) { led2_.toggle(); }
}

#pragma GCC diagnostic pop
<commit_msg>Add a small comment<commit_after>/*
 * Copyright (c) 2017, James Jackson and Daniel Koch, BYU MAGICC Lab
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * * Neither the name of the copyright holder nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"

#include "revo.h"

namespace rosflight_firmware {

Revo::Revo()
{
}
Revo::~Revo()
{

}

void Revo::init_board(void)
{
  systemInit();
  led2_.init(LED2_GPIO, LED2_PIN);
  led1_.init(LED1_GPIO, LED1_PIN);

  int_i2c_.init(&i2c_config[MAG_I2C]);
  ext_i2c_.init(&i2c_config[EXTERNAL_I2C]);
  spi1_.init(&spi_config[MPU6000_SPI]);
  spi3_.init(&spi_config[FLASH_SPI]);

  serial_interfaces_[0]=&vcp_;
  serial_interfaces_[1]=&uart_;

  this->current_serial_=&uart_;
  //this->current_serial_=&vcp;    //uncomment this to switch to VCP
}

void Revo::board_reset(bool bootloader)
{
  NVIC_SystemReset();
}

// clock
uint32_t Revo::clock_millis()
{
  return millis();
}

uint64_t Revo::clock_micros()
{
  return micros();
}

void Revo::clock_delay(uint32_t milliseconds)
{
  delay(milliseconds);
}

// serial
void Revo::serial_init(uint32_t baud_rate)
{
  uart_.init(&uart_config[0], baud_rate);
  vcp_.init();
}

void Revo::serial_write(const uint8_t *src, size_t len)
{
  current_serial_->write(src, len);
}

uint16_t Revo::serial_bytes_available(void)
{
  return current_serial_->rx_bytes_waiting();
}

uint8_t Revo::serial_read(void)
{
  return current_serial_->read_byte();
}

void Revo::serial_flush()
{
  current_serial_->flush();
}

Serial** Revo::get_serial_interfaces()
{
    return serial_interfaces_;
}

uint8_t Revo::get_serial_count()
{
    return 2;
}

// sensors
void Revo::sensors_init()
{
  imu_.init(&spi1_);
  mag_.init(&int_i2c_);
  baro_.init(&int_i2c_);
  airspeed_.init(&ext_i2c_);

  while(millis() < 50); // wait for sensors to boot up
}

uint16_t Revo::num_sensor_errors(void)
{
  return int_i2c_.num_errors();
}

bool Revo::new_imu_data()
{
  return imu_.new_data();
}

bool Revo::imu_read(float accel[3], float* temperature, float gyro[3], uint64_t* time_us)
{
  float read_accel[3], read_gyro[3];
  imu_.read(read_accel, read_gyro, temperature, time_us);

  accel[0] = -read_accel[1];
  accel[1] = -read_accel[0];
  accel[2] = -read_accel[2];

  gyro[0] = -read_gyro[1];
  gyro[1] = -read_gyro[0];
  gyro[2] = -read_gyro[2];

  return true;
}

void Revo::imu_not_responding_error(void)
{
  sensors_init();
}

void Revo::mag_read(float mag[3])
{
  mag_.update();
  mag_.read(mag);
}

bool Revo::mag_check(void)
{
  mag_.update();
  return mag_.present();
}

void Revo::baro_read(float *pressure, float *temperature)
{
  baro_.update();
  baro_.read(pressure, temperature);
}

bool Revo::baro_check()
{
  baro_.update();
  return baro_.present();
}

bool Revo::diff_pressure_check(void)
{
  airspeed_.update();
  return airspeed_.present();
}

void Revo::diff_pressure_read(float *diff_pressure, float *temperature)
{
  airspeed_.update();
  airspeed_.read(diff_pressure, temperature);
}

bool Revo::sonar_check(void)
{
  return false;
}

float Revo::sonar_read(void)
{
  return 0.0;
}

// PWM
void Revo::pwm_init(bool cppm, uint32_t refresh_rate, uint16_t idle_pwm)
{
  for (int i = 0; i < PWM_NUM_OUTPUTS; i++)
  {
    esc_out_[i].init(&pwm_config[i], refresh_rate, 2000, 1000);
    esc_out_[i].writeUs(idle_pwm);
  }
  rc_.init(&pwm_config[RC_PPM_PIN]);
}

uint16_t Revo::pwm_read(uint8_t channel)
{
  return rc_.read(channel);
}

void Revo::pwm_write(uint8_t channel, uint16_t value)
{
  esc_out_[channel].writeUs(value);
}

bool Revo::pwm_lost()
{
  return rc_.lost();
}

// non-volatile memory
void Revo::memory_init(void)
{
  return flash_.init(&spi3_);
}

bool Revo::memory_read(void * data, size_t len)
{
  return flash_.read_config((uint8_t*)data, len);
}

bool Revo::memory_write(const void * data, size_t len)
{
  return flash_.write_config((uint8_t*)data, len);
}

// LED
void Revo::led0_on(void) { led1_.on(); }
void Revo::led0_off(void) { led1_.off(); }
void Revo::led0_toggle(void) { led1_.toggle(); }

void Revo::led1_on(void) { led2_.on(); }
void Revo::led1_off(void) { led2_.off(); }
void Revo::led1_toggle(void) { led2_.toggle(); }
}

#pragma GCC diagnostic pop
<|endoftext|>


<commit_before>#include "input/Input.hpp"
#include "Application.hpp"
#include "resources/ResourcesManager.hpp"
#include "graphics/ScreenQuad.hpp"
#include "graphics/Framebuffer.hpp"
#include "graphics/GLUtilities.hpp"
#include "system/Window.hpp"
#include "system/System.hpp"
#include "generation/Random.hpp"
#include "system/Config.hpp"
#include "Common.hpp"

/**
 \defgroup AtmosphericScattering Atmospheric scattering
 \brief Demonstrate real-time approximate atmospheric scattering simulation.
 \see GPU::Frag::Atmosphere
 \ingroup Applications
 */

/** \brief Demo application for the atmospheric scattering shader.
 \ingroup AtmosphericScattering
 */
class AtmosphereApp final : public CameraApp {
public:

	/** Constructor
	 \param config rendering config
	 */
	AtmosphereApp(RenderingConfig & config) : CameraApp(config) {
		_userCamera.projection(config.screenResolution[0] / config.screenResolution[1], 1.34f, 0.1f, 100.0f);
		// Framebuffer to store the rendered atmosphere result before tonemapping and upscaling to the window size.
		const glm::vec2 renderRes = _config.renderingResolution();
		_atmosphereBuffer.reset(new Framebuffer(uint(renderRes[0]), uint(renderRes[1]), {Layout::RGB32F, Filter::LINEAR_NEAREST, Wrap::CLAMP}, false, "Atmosphere"));
		// Lookup table.
		_precomputedScattering = Resources::manager().getTexture("scattering-precomputed", {Layout::RGB32F, Filter::LINEAR_LINEAR, Wrap::CLAMP}, Storage::GPU);
		// Atmosphere screen quad.
		_atmosphere = Resources::manager().getProgram2D("atmosphere_basic");
		// Final tonemapping screen quad.
		_tonemap = Resources::manager().getProgram2D("tonemap");
		// Sun direction.
		_lightDirection = glm::normalize(glm::vec3(0.437f, 0.082f, -0.896f));

		GLUtilities::setDepthState(true);
		checkGLError();
	}

	/** \copydoc CameraApp::draw */
	void draw() override {
		// Render.
		const glm::mat4 camToWorld = glm::inverse(_userCamera.view());
		const glm::mat4 clipToCam  = glm::inverse(_userCamera.projection());

		// Draw the atmosphere.
		GLUtilities::setDepthState(false);
		_atmosphereBuffer->bind();
		_atmosphereBuffer->setViewport();
		GLUtilities::clearColor({0.0f, 0.0f, 0.0f, 1.0f});

		_atmosphere->use();
		const glm::mat4 camToWorldNoT = glm::mat4(glm::mat3(camToWorld));
		const glm::mat4 clipToWorld   = camToWorldNoT * clipToCam;
		_atmosphere->uniform("clipToWorld", clipToWorld);
		_atmosphere->uniform("viewPos", _userCamera.position());
		_atmosphere->uniform("lightDirection", _lightDirection);
		ScreenQuad::draw(_precomputedScattering);
		_atmosphereBuffer->unbind();

		// Tonemapping and final screen.
		GLUtilities::setViewport(0, 0, int(_config.screenResolution[0]), int(_config.screenResolution[1]));
		Framebuffer::backbuffer()->bind(Framebuffer::Mode::SRGB);
		_tonemap->use();
		ScreenQuad::draw(_atmosphereBuffer->texture());
		Framebuffer::backbuffer()->unbind();
	}

	/** \copydoc CameraApp::update */
	void update() override {
		CameraApp::update();

		if(ImGui::Begin("Atmosphere")){
			ImGui::Text("%.1f ms, %.1f fps", frameTime() * 1000.0f, frameRate());
			if(ImGui::DragFloat3("Light dir", &_lightDirection[0], 0.05f, -1.0f, 1.0f)) {
				_lightDirection = glm::normalize(_lightDirection);
			}
		}
		ImGui::End();
	}

	/** \copydoc CameraApp::resize */
	void resize() override {
		_atmosphereBuffer->resize(_config.renderingResolution());
	}

private:
	std::unique_ptr<Framebuffer> _atmosphereBuffer; ///< Scene framebuffer.
	const Program * _atmosphere; ///< Atmospheric scattering shader.
	const Program * _tonemap; ///< Tonemapping shader.
	const Texture * _precomputedScattering; ///< Precomputed lookup table.
	glm::vec3 _lightDirection; ///< Sun light direction.
};

/**
 The main function of the atmospheric scattering demo.
 \param argc the number of input arguments.
 \param argv a pointer to the raw input arguments.
 \return a general error code.
 \ingroup AtmosphericScattering
 */
int main(int argc, char ** argv) {

	// First, init/parse/load configuration.
	RenderingConfig config(std::vector<std::string>(argv, argv + argc));
	if(config.showHelp()) {
		return 0;
	}

	Window window("Atmosphere", config);

	Resources::manager().addResources("../../../resources/common");
	Resources::manager().addResources("../../../resources/atmosphere");
	if(!config.resourcesPath.empty()){
		Resources::manager().addResources(config.resourcesPath);
	}

	// Seed random generator.
	Random::seed();

	AtmosphereApp app(config);

	// Start the display/interaction loop.
	while(window.nextFrame()) {
		app.update();
		app.draw();
	}

	// Cleaning.
	Resources::manager().clean();

	return 0;
}
<commit_msg>Atmosphere: adjust step.<commit_after>#include "input/Input.hpp"
#include "Application.hpp"
#include "resources/ResourcesManager.hpp"
#include "graphics/ScreenQuad.hpp"
#include "graphics/Framebuffer.hpp"
#include "graphics/GLUtilities.hpp"
#include "system/Window.hpp"
#include "system/System.hpp"
#include "generation/Random.hpp"
#include "system/Config.hpp"
#include "Common.hpp"

/**
 \defgroup AtmosphericScattering Atmospheric scattering
 \brief Demonstrate real-time approximate atmospheric scattering simulation.
 \see GPU::Frag::Atmosphere
 \ingroup Applications
 */

/** \brief Demo application for the atmospheric scattering shader.
 \ingroup AtmosphericScattering
 */
class AtmosphereApp final : public CameraApp {
public:

	/** Constructor
	 \param config rendering config
	 */
	AtmosphereApp(RenderingConfig & config) : CameraApp(config) {
		_userCamera.projection(config.screenResolution[0] / config.screenResolution[1], 1.34f, 0.1f, 100.0f);
		// Framebuffer to store the rendered atmosphere result before tonemapping and upscaling to the window size.
		const glm::vec2 renderRes = _config.renderingResolution();
		_atmosphereBuffer.reset(new Framebuffer(uint(renderRes[0]), uint(renderRes[1]), {Layout::RGB32F, Filter::LINEAR_NEAREST, Wrap::CLAMP}, false, "Atmosphere"));
		// Lookup table.
		_precomputedScattering = Resources::manager().getTexture("scattering-precomputed", {Layout::RGB32F, Filter::LINEAR_LINEAR, Wrap::CLAMP}, Storage::GPU);
		// Atmosphere screen quad.
		_atmosphere = Resources::manager().getProgram2D("atmosphere_basic");
		// Final tonemapping screen quad.
		_tonemap = Resources::manager().getProgram2D("tonemap");
		// Sun direction.
		_lightDirection = glm::normalize(glm::vec3(0.437f, 0.082f, -0.896f));

		GLUtilities::setDepthState(true);
		checkGLError();
	}

	/** \copydoc CameraApp::draw */
	void draw() override {
		// Render.
		const glm::mat4 camToWorld = glm::inverse(_userCamera.view());
		const glm::mat4 clipToCam  = glm::inverse(_userCamera.projection());

		// Draw the atmosphere.
		GLUtilities::setDepthState(false);
		_atmosphereBuffer->bind();
		_atmosphereBuffer->setViewport();
		GLUtilities::clearColor({0.0f, 0.0f, 0.0f, 1.0f});

		_atmosphere->use();
		const glm::mat4 camToWorldNoT = glm::mat4(glm::mat3(camToWorld));
		const glm::mat4 clipToWorld   = camToWorldNoT * clipToCam;
		_atmosphere->uniform("clipToWorld", clipToWorld);
		_atmosphere->uniform("viewPos", _userCamera.position());
		_atmosphere->uniform("lightDirection", _lightDirection);
		ScreenQuad::draw(_precomputedScattering);
		_atmosphereBuffer->unbind();

		// Tonemapping and final screen.
		GLUtilities::setViewport(0, 0, int(_config.screenResolution[0]), int(_config.screenResolution[1]));
		Framebuffer::backbuffer()->bind(Framebuffer::Mode::SRGB);
		_tonemap->use();
		ScreenQuad::draw(_atmosphereBuffer->texture());
		Framebuffer::backbuffer()->unbind();
	}

	/** \copydoc CameraApp::update */
	void update() override {
		CameraApp::update();

		if(ImGui::Begin("Atmosphere")){
			ImGui::Text("%.1f ms, %.1f fps", frameTime() * 1000.0f, frameRate());
			if(ImGui::DragFloat3("Light dir", &_lightDirection[0], 0.005f, -1.0f, 1.0f)) {
				_lightDirection = glm::normalize(_lightDirection);
			}
		}
		ImGui::End();
	}

	/** \copydoc CameraApp::resize */
	void resize() override {
		_atmosphereBuffer->resize(_config.renderingResolution());
	}

private:
	std::unique_ptr<Framebuffer> _atmosphereBuffer; ///< Scene framebuffer.
	const Program * _atmosphere; ///< Atmospheric scattering shader.
	const Program * _tonemap; ///< Tonemapping shader.
	const Texture * _precomputedScattering; ///< Precomputed lookup table.
	glm::vec3 _lightDirection; ///< Sun light direction.
};

/**
 The main function of the atmospheric scattering demo.
 \param argc the number of input arguments.
 \param argv a pointer to the raw input arguments.
 \return a general error code.
 \ingroup AtmosphericScattering
 */
int main(int argc, char ** argv) {

	// First, init/parse/load configuration.
	RenderingConfig config(std::vector<std::string>(argv, argv + argc));
	if(config.showHelp()) {
		return 0;
	}

	Window window("Atmosphere", config);

	Resources::manager().addResources("../../../resources/common");
	Resources::manager().addResources("../../../resources/atmosphere");
	if(!config.resourcesPath.empty()){
		Resources::manager().addResources(config.resourcesPath);
	}

	// Seed random generator.
	Random::seed();

	AtmosphereApp app(config);

	// Start the display/interaction loop.
	while(window.nextFrame()) {
		app.update();
		app.draw();
	}

	// Cleaning.
	Resources::manager().clean();

	return 0;
}
<|endoftext|>


<commit_before>//
// Copyright (C) 2013
// Alessio Sclocco <a.sclocco@vu.nl>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

#include <iostream>
#include <string>
#include <vector>
#include <exception>
#include <fstream>
#include <iomanip>
#include <limits>
#include <cmath>
using std::cout;
using std::cerr;
using std::endl;
using std::string;
using std::vector;
using std::exception;
using std::ofstream;
using std::fixed;
using std::setprecision;
using std::numeric_limits;

#include <ArgumentList.hpp>
using isa::utils::ArgumentList;
#include <Observation.hpp>
using AstroData::Observation;
#include <InitializeOpenCL.hpp>
using isa::OpenCL::initializeOpenCL;
#include <CLData.hpp>
using isa::OpenCL::CLData;
#include <utils.hpp>
using isa::utils::toStringValue;
#include <Folding.hpp>
using PulsarSearch::Folding;
#include <Timer.hpp>
using isa::utils::Timer;
#include <Bins.hpp>
using PulsarSearch::getNrSamplesPerBin;

typedef float dataType;
const string typeName("float");

int main(int argc, char * argv[]) {
	unsigned int lowerNrThreads = 0;
	unsigned int maxThreadsPerBlock = 0;
	unsigned int maxItemsPerThread = 16;
	unsigned int nrIterations = 0;
	unsigned int clPlatformID = 0;
	unsigned int clDeviceID = 0;
	Observation< dataType > observation("FoldingTuning", typeName);
	CLData< dataType > * dedispersedData = new CLData< dataType >("DedispersedData", true);
	CLData< dataType > * foldedData = new CLData<dataType >("FoldedData", true);
	CLData< unsigned int > * readCounterData = new CLData< unsigned int >("ReadCounterData", true);
	CLData< unsigned int > * writeCounterData = new CLData< unsigned int >("WriteCounterData", true);
	CLData< unsigned int > * nrSamplesPerBin = new CLData< unsigned int >("SamplesPerBin", true);

	try {
		ArgumentList args(argc, argv);

		clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
		clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
		observation.setPadding(args.getSwitchArgument< unsigned int >("-padding"));
		nrIterations = args.getSwitchArgument< unsigned int >("-iterations");
		observation.setNrDMs(args.getSwitchArgument< unsigned int >("-dms"));
		lowerNrThreads = args.getSwitchArgument< unsigned int >("-lnt");
		maxThreadsPerBlock = args.getSwitchArgument< unsigned int >("-mnt");
		maxItemsPerThread = args.getSwitchArgument< unsigned int >("-mit");
		observation.setNrPeriods(args.getSwitchArgument< unsigned int >("-periods"));
		observation.setFirstPeriod(args.getSwitchArgument< unsigned int >("-first_period"));
		observation.setPeriodStep(args.getSwitchArgument< unsigned int >("-period_step"));
		observation.setNrBins(args.getSwitchArgument< unsigned int >("-bins"));
		observation.setNrSamplesPerSecond(args.getSwitchArgument< unsigned int >("-samples"));
	} catch ( exception & err ) {
		cerr << err.what() << endl;
		return 1;
	}

	cl::Context * clContext = new cl::Context();
	vector< cl::Platform > * clPlatforms = new vector< cl::Platform >();
	vector< cl::Device > * clDevices = new vector< cl::Device >();
	vector< vector< cl::CommandQueue > > * clQueues = new vector< vector < cl::CommandQueue > >();

	initializeOpenCL(clPlatformID, 1, clPlatforms, clContext, clDevices, clQueues);

	cout << fixed << endl;
	cout << "# nrDMs nrPeriods firstPeriod periodStep nrBins nrSamplesPerSecond nrDMsPerBlock nrPeriodsPerBlock nrBinsPerBlock nrDMsPerThread nrPeriodsPerThread nrBinsPerThread GFLOP/s err time err" << endl << endl;

	// Allocate memory
	dedispersedData->allocateHostData(observation.getNrSamplesPerSecond() * observation.getNrPaddedDMs());
	dedispersedData->blankHostData();
	foldedData->allocateHostData(observation.getNrPaddedDMs() * observation.getNrBins() * observation.getNrPeriods());
	foldedData->blankHostData();
	readCounterData->allocateHostData(observation.getNrPeriods() * 2 * observation.getNrPaddedBins());
	readCounterData->blankHostData();
	writeCounterData->allocateHostData(observation.getNrPeriods() * 2 * observation.getNrPaddedBins());
	writeCounterData->blankHostData();
	vector< unsigned int > * nrSamplesPerBinData = getNrSamplesPerBin(observation);
	nrSamplesPerBin->allocateHostData(*nrSamplesPerBinData);

	dedispersedData->setCLContext(clContext);
	dedispersedData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	foldedData->setCLContext(clContext);
	foldedData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	readCounterData->setCLContext(clContext);
	readCounterData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	writeCounterData->setCLContext(clContext);
	writeCounterData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	nrSamplesPerBin->setCLContext(clContext);
	nrSamplesPerBin->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	nrSamplesPerBin->setDeviceReadOnly();

	try {
		dedispersedData->allocateDeviceData();
		dedispersedData->copyHostToDevice();
		foldedData->allocateDeviceData();
		foldedData->copyHostToDevice();
		readCounterData->allocateDeviceData();
		readCounterData->copyHostToDevice();
		writeCounterData->allocateDeviceData();
		writeCounterData->copyHostToDevice();
		nrSamplesPerBin->allocateDeviceData();
		nrSamplesPerBin->copyHostToDevice();
	} catch ( OpenCLError err ) {
		cerr << err.what() << endl;
	}

	// Find the parameters
	vector< vector< unsigned int > > configurations;
	for ( unsigned int DMsPerBlock = lowerNrThreads; DMsPerBlock <= maxThreadsPerBlock; DMsPerBlock += lowerNrThreads ) {
		if ( observation.getNrPaddedDMs() % DMsPerBlock != 0 ) {
			continue;
		}

		for ( unsigned int periodsPerBlock = 1; periodsPerBlock <= maxThreadsPerBlock; periodsPerBlock++ ) {
			if ( observation.getNrPeriods() % periodsPerBlock != 0 ) {
				continue;
			} else if ( DMsPerBlock * periodsPerBlock > maxThreadsPerBlock ) {
				break;
			}

			for ( unsigned int binsPerBlock = 1; binsPerBlock <= maxThreadsPerBlock; binsPerBlock++ ) {
				if ( observation.getNrBins() % binsPerBlock != 0 ) {
					continue;
				} else if ( DMsPerBlock * periodsPerBlock * binsPerBlock > maxThreadsPerBlock ) {
					break;
				}

				for ( unsigned int DMsPerThread = 1; DMsPerThread <= maxItemsPerThread; DMsPerThread++ ) {
					if ( observation.getNrPaddedDMs() % (DMsPerBlock * DMsPerThread) != 0 ) {
						continue;
					}

					for ( unsigned int periodsPerThread = 1; periodsPerThread <= maxItemsPerThread; periodsPerThread++ ) {
						if ( observation.getNrPeriods() % (periodsPerBlock * periodsPerThread) != 0 ) {
							continue;
						} else if ( (DMsPerThread + (2 * periodsPerThread)) > maxItemsPerThread ) {
							break;
						}

						for ( unsigned int binsPerThread = 1; binsPerThread <= maxItemsPerThread; binsPerThread++ ) {
							if ( observation.getNrBins() % (binsPerBlock * binsPerThread) != 0 ) {
								continue;
							} else if ( (DMsPerThread + (2 * periodsPerThread) + binsPerThread) + (3 * periodsPerThread * binsPerThread) + (2 * DMsPerThread * periodsPerThread * binsPerThread) > maxItemsPerThread ) {
								break;
							}

							vector< unsigned int > parameters;

							parameters.push_back(DMsPerBlock);
							parameters.push_back(periodsPerBlock);
							parameters.push_back(binsPerBlock);
							parameters.push_back(DMsPerThread);
							parameters.push_back(periodsPerThread);
							parameters.push_back(binsPerThread);

							configurations.push_back(parameters);
						}
					}
				}
			}
		}
	}

	for ( vector< vector< unsigned int > >::const_iterator parameters = configurations.begin(); parameters != configurations.end(); parameters++ ) {
		try {
			// Generate kernel
			Folding< dataType > clFold("clFold", typeName);
			clFold.bindOpenCL(clContext, &(clDevices->at(clDeviceID)), &((clQueues->at(clDeviceID)).at(0)));
			clFold.setObservation(&observation);
			clFold.setNrSamplesPerBin(nrSamplesPerBin);
			clFold.setNrDMsPerBlock((*parameters)[0]);
			clFold.setNrPeriodsPerBlock((*parameters)[1]);
			clFold.setNrBinsPerBlock((*parameters)[2]);
			clFold.setNrDMsPerThread((*parameters)[3]);
			clFold.setNrPeriodsPerThread((*parameters)[4]);
			clFold.setNrBinsPerThread((*parameters)[5]);
			clFold.generateCode();

			foldedData->copyHostToDevice();
			clFold(0, dedispersedData, foldedData, readCounterData, writeCounterData);
			(clFold.getTimer()).reset();
			clFold.resetStats();

			for ( unsigned int iteration = 0; iteration < nrIterations; iteration++ ) {
				foldedData->copyHostToDevice();
				clFold(0, dedispersedData, foldedData, readCounterData, writeCounterData);
			}

			cout << observation.getNrDMs() << " " << observation.getNrPeriods() << " " << observation.getFirstPeriod() << " " << observation.getPeriodStep() << " " << observation.getNrBins() << " " << observation.getNrSamplesPerSecond() << " " << (*parameters)[0] << " " << (*parameters)[1] << " " << (*parameters)[2] << " " << (*parameters)[3] << " " << (*parameters)[4] << " " << (*parameters)[5] << " " << setprecision(3) << clFold.getGFLOPs() << " " << clFold.getGFLOPsErr() << " " << setprecision(6) << clFold.getTimer().getAverageTime() << " " << clFold.getTimer().getStdDev() << endl;
		} catch ( OpenCLError err ) {
			cerr << err.what() << endl;
			continue;
		}
	}

	cout << endl;

	return 0;
}
<commit_msg>It is possible to limit the maximum number of threads in a row.<commit_after>//
// Copyright (C) 2013
// Alessio Sclocco <a.sclocco@vu.nl>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

#include <iostream>
#include <string>
#include <vector>
#include <exception>
#include <fstream>
#include <iomanip>
#include <limits>
#include <cmath>
using std::cout;
using std::cerr;
using std::endl;
using std::string;
using std::vector;
using std::exception;
using std::ofstream;
using std::fixed;
using std::setprecision;
using std::numeric_limits;

#include <ArgumentList.hpp>
using isa::utils::ArgumentList;
#include <Observation.hpp>
using AstroData::Observation;
#include <InitializeOpenCL.hpp>
using isa::OpenCL::initializeOpenCL;
#include <CLData.hpp>
using isa::OpenCL::CLData;
#include <utils.hpp>
using isa::utils::toStringValue;
#include <Folding.hpp>
using PulsarSearch::Folding;
#include <Timer.hpp>
using isa::utils::Timer;
#include <Bins.hpp>
using PulsarSearch::getNrSamplesPerBin;

typedef float dataType;
const string typeName("float");

int main(int argc, char * argv[]) {
	unsigned int lowerNrThreads = 0;
	unsigned int maxThreadsPerBlock = 0;
	unsigned int maxItemsPerThread = 16;
	unsigned int maxColumns = 0;
	unsigned int maxRows = 0;
	unsigned int nrIterations = 0;
	unsigned int clPlatformID = 0;
	unsigned int clDeviceID = 0;
	Observation< dataType > observation("FoldingTuning", typeName);
	CLData< dataType > * dedispersedData = new CLData< dataType >("DedispersedData", true);
	CLData< dataType > * foldedData = new CLData<dataType >("FoldedData", true);
	CLData< unsigned int > * readCounterData = new CLData< unsigned int >("ReadCounterData", true);
	CLData< unsigned int > * writeCounterData = new CLData< unsigned int >("WriteCounterData", true);
	CLData< unsigned int > * nrSamplesPerBin = new CLData< unsigned int >("SamplesPerBin", true);

	try {
		ArgumentList args(argc, argv);

		clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
		clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
		observation.setPadding(args.getSwitchArgument< unsigned int >("-padding"));
		nrIterations = args.getSwitchArgument< unsigned int >("-iterations");
		observation.setNrDMs(args.getSwitchArgument< unsigned int >("-dms"));
		lowerNrThreads = args.getSwitchArgument< unsigned int >("-lnt");
		maxThreadsPerBlock = args.getSwitchArgument< unsigned int >("-mnt");
		maxItemsPerThread = args.getSwitchArgument< unsigned int >("-mit");
		maxColumns = args.getSwitchArgument< unsigned int >("-max_columns");
		maxRows = args.getSwitchArgument< unsigned int >("-max_rows");
		observation.setNrPeriods(args.getSwitchArgument< unsigned int >("-periods"));
		observation.setFirstPeriod(args.getSwitchArgument< unsigned int >("-first_period"));
		observation.setPeriodStep(args.getSwitchArgument< unsigned int >("-period_step"));
		observation.setNrBins(args.getSwitchArgument< unsigned int >("-bins"));
		observation.setNrSamplesPerSecond(args.getSwitchArgument< unsigned int >("-samples"));
	} catch ( exception & err ) {
		cerr << err.what() << endl;
		return 1;
	}

	cl::Context * clContext = new cl::Context();
	vector< cl::Platform > * clPlatforms = new vector< cl::Platform >();
	vector< cl::Device > * clDevices = new vector< cl::Device >();
	vector< vector< cl::CommandQueue > > * clQueues = new vector< vector < cl::CommandQueue > >();

	initializeOpenCL(clPlatformID, 1, clPlatforms, clContext, clDevices, clQueues);

	cout << fixed << endl;
	cout << "# nrDMs nrPeriods firstPeriod periodStep nrBins nrSamplesPerSecond nrDMsPerBlock nrPeriodsPerBlock nrBinsPerBlock nrDMsPerThread nrPeriodsPerThread nrBinsPerThread GFLOP/s err time err" << endl << endl;

	// Allocate memory
	dedispersedData->allocateHostData(observation.getNrSamplesPerSecond() * observation.getNrPaddedDMs());
	dedispersedData->blankHostData();
	foldedData->allocateHostData(observation.getNrPaddedDMs() * observation.getNrBins() * observation.getNrPeriods());
	foldedData->blankHostData();
	readCounterData->allocateHostData(observation.getNrPeriods() * 2 * observation.getNrPaddedBins());
	readCounterData->blankHostData();
	writeCounterData->allocateHostData(observation.getNrPeriods() * 2 * observation.getNrPaddedBins());
	writeCounterData->blankHostData();
	vector< unsigned int > * nrSamplesPerBinData = getNrSamplesPerBin(observation);
	nrSamplesPerBin->allocateHostData(*nrSamplesPerBinData);

	dedispersedData->setCLContext(clContext);
	dedispersedData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	foldedData->setCLContext(clContext);
	foldedData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	readCounterData->setCLContext(clContext);
	readCounterData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	writeCounterData->setCLContext(clContext);
	writeCounterData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	nrSamplesPerBin->setCLContext(clContext);
	nrSamplesPerBin->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	nrSamplesPerBin->setDeviceReadOnly();

	try {
		dedispersedData->allocateDeviceData();
		dedispersedData->copyHostToDevice();
		foldedData->allocateDeviceData();
		foldedData->copyHostToDevice();
		readCounterData->allocateDeviceData();
		readCounterData->copyHostToDevice();
		writeCounterData->allocateDeviceData();
		writeCounterData->copyHostToDevice();
		nrSamplesPerBin->allocateDeviceData();
		nrSamplesPerBin->copyHostToDevice();
	} catch ( OpenCLError err ) {
		cerr << err.what() << endl;
	}

	// Find the parameters
	vector< vector< unsigned int > > configurations;
	for ( unsigned int DMsPerBlock = lowerNrThreads; DMsPerBlock <= maxColumns; DMsPerBlock += lowerNrThreads ) {
		if ( observation.getNrPaddedDMs() % DMsPerBlock != 0 ) {
			continue;
		}

		for ( unsigned int periodsPerBlock = 1; periodsPerBlock <= maxRows; periodsPerBlock++ ) {
			if ( observation.getNrPeriods() % periodsPerBlock != 0 ) {
				continue;
			} else if ( DMsPerBlock * periodsPerBlock > maxThreadsPerBlock ) {
				break;
			}

			for ( unsigned int binsPerBlock = 1; binsPerBlock <= maxRows; binsPerBlock++ ) {
				if ( observation.getNrBins() % binsPerBlock != 0 ) {
					continue;
				} else if ( DMsPerBlock * periodsPerBlock * binsPerBlock > maxThreadsPerBlock ) {
					break;
				}

				for ( unsigned int DMsPerThread = 1; DMsPerThread <= maxItemsPerThread; DMsPerThread++ ) {
					if ( observation.getNrPaddedDMs() % (DMsPerBlock * DMsPerThread) != 0 ) {
						continue;
					}

					for ( unsigned int periodsPerThread = 1; periodsPerThread <= maxItemsPerThread; periodsPerThread++ ) {
						if ( observation.getNrPeriods() % (periodsPerBlock * periodsPerThread) != 0 ) {
							continue;
						} else if ( (DMsPerThread + (2 * periodsPerThread)) > maxItemsPerThread ) {
							break;
						}

						for ( unsigned int binsPerThread = 1; binsPerThread <= maxItemsPerThread; binsPerThread++ ) {
							if ( observation.getNrBins() % (binsPerBlock * binsPerThread) != 0 ) {
								continue;
							} else if ( (DMsPerThread + (2 * periodsPerThread) + binsPerThread) + (3 * periodsPerThread * binsPerThread) + (2 * DMsPerThread * periodsPerThread * binsPerThread) > maxItemsPerThread ) {
								break;
							}

							vector< unsigned int > parameters;

							parameters.push_back(DMsPerBlock);
							parameters.push_back(periodsPerBlock);
							parameters.push_back(binsPerBlock);
							parameters.push_back(DMsPerThread);
							parameters.push_back(periodsPerThread);
							parameters.push_back(binsPerThread);

							configurations.push_back(parameters);
						}
					}
				}
			}
		}
	}

	for ( vector< vector< unsigned int > >::const_iterator parameters = configurations.begin(); parameters != configurations.end(); parameters++ ) {
		try {
			// Generate kernel
			Folding< dataType > clFold("clFold", typeName);
			clFold.bindOpenCL(clContext, &(clDevices->at(clDeviceID)), &((clQueues->at(clDeviceID)).at(0)));
			clFold.setObservation(&observation);
			clFold.setNrSamplesPerBin(nrSamplesPerBin);
			clFold.setNrDMsPerBlock((*parameters)[0]);
			clFold.setNrPeriodsPerBlock((*parameters)[1]);
			clFold.setNrBinsPerBlock((*parameters)[2]);
			clFold.setNrDMsPerThread((*parameters)[3]);
			clFold.setNrPeriodsPerThread((*parameters)[4]);
			clFold.setNrBinsPerThread((*parameters)[5]);
			clFold.generateCode();

			foldedData->copyHostToDevice();
			clFold(0, dedispersedData, foldedData, readCounterData, writeCounterData);
			(clFold.getTimer()).reset();
			clFold.resetStats();

			for ( unsigned int iteration = 0; iteration < nrIterations; iteration++ ) {
				foldedData->copyHostToDevice();
				clFold(0, dedispersedData, foldedData, readCounterData, writeCounterData);
			}

			cout << observation.getNrDMs() << " " << observation.getNrPeriods() << " " << observation.getFirstPeriod() << " " << observation.getPeriodStep() << " " << observation.getNrBins() << " " << observation.getNrSamplesPerSecond() << " " << (*parameters)[0] << " " << (*parameters)[1] << " " << (*parameters)[2] << " " << (*parameters)[3] << " " << (*parameters)[4] << " " << (*parameters)[5] << " " << setprecision(3) << clFold.getGFLOPs() << " " << clFold.getGFLOPsErr() << " " << setprecision(6) << clFold.getTimer().getAverageTime() << " " << clFold.getTimer().getStdDev() << endl;
		} catch ( OpenCLError err ) {
			cerr << err.what() << endl;
			continue;
		}
	}

	cout << endl;

	return 0;
}
<|endoftext|>


<commit_before>//
//  Track.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 22/09/2017.
//  Copyright 2017 Thomas Harte. All rights reserved.
//

#ifndef Track_h
#define Track_h

#include "../../Storage.hpp"
#include <tuple>

namespace Storage {
namespace Disk {

/*!
	Contains a head position, with some degree of sub-integral precision.
*/
class HeadPosition {
	public:
		/// Creates an instance decribing position @c value at a resolution of @c scale ticks per track.
		HeadPosition(int value, int scale) : position_(value * (4/scale)) {}
		explicit HeadPosition(int value) : HeadPosition(value, 1) {}
		HeadPosition() : HeadPosition(0) {}

		/// @returns the whole number part of the position.
		int as_int() const { return position_ >> 2; }
		/// @returns n where n/2 is the head position.
		int as_half() const { return position_ >> 1; }
		/// @returns n where n/4 is the head position.
		int as_quarter() const { return position_; }

		/// @returns the head position at maximal but unspecified precision.
		int as_largest() const { return as_quarter(); }

		HeadPosition &operator +=(const HeadPosition &rhs) {
			position_ += rhs.position_;
			return *this;
		}
		bool operator ==(const HeadPosition &rhs) const {
			return position_ == rhs.position_;
		}
		bool operator !=(const HeadPosition &rhs) const {
			return position_ != rhs.position_;
		}
		bool operator <(const HeadPosition &rhs) const {
			return position_ < rhs.position_;
		}
		bool operator <=(const HeadPosition &rhs) const {
			return position_ <= rhs.position_;
		}
		bool operator >(const HeadPosition &rhs) const {
			return position_ > rhs.position_;
		}
		bool operator >=(const HeadPosition &rhs) const {
			return position_ >= rhs.position_;
		}

	private:
		int position_ = 0;
};

/*!
	Models a single track on a disk as a series of events, each event being of arbitrary length
	and resulting in either a flux transition or the sensing of an index hole.

	Subclasses should implement @c get_next_event.
*/
class Track {
	public:
		virtual ~Track() {}

		/*!
			Describes the location of a track, implementing < to allow for use as a set key.
		*/
		struct Address {
			int head;
			HeadPosition position;

			bool operator < (const Address &rhs) const {
				int largest_position = position.as_largest();
				int rhs_largest_position = rhs.position.as_largest();
				return std::tie(head, largest_position) < std::tie(rhs.head, rhs_largest_position);
			}
			Address(int head, HeadPosition position) : head(head), position(position) {}
		};

		/*!
			Describes a detectable track event: either a flux transition or the passing of the index hole,
			along with the length of time between the previous event and its occurance.

			The sum of all lengths of time across an entire track should be 1; if an event is said to be
			1/3 away then that means 1/3 of a rotation.
		*/
		struct Event {
			enum Type {
				IndexHole, FluxTransition
			} type;
			Time length;
		};

		/*!
			@returns the next event that will be detected during rotation of this disk.
		*/
		virtual Event get_next_event() = 0;

		/*!
			Jumps to the event latest offset that is less than or equal to the input time.

			@returns the time jumped to.
		*/
		virtual Time seek_to(const Time &time_since_index_hole) = 0;

		/*!
			The virtual copy constructor pattern; returns a copy of the Track.
		*/
		virtual Track *clone() const = 0;
};

}
}

#endif /* Track_h */
<commit_msg>Enhances with `constexpr`.<commit_after>//
//  Track.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 22/09/2017.
//  Copyright 2017 Thomas Harte. All rights reserved.
//

#ifndef Track_h
#define Track_h

#include "../../Storage.hpp"
#include <tuple>

namespace Storage {
namespace Disk {

/*!
	Contains a head position, with some degree of sub-integral precision.
*/
class HeadPosition {
	public:
		/// Creates an instance decribing position @c value at a resolution of @c scale ticks per track.
		constexpr HeadPosition(int value, int scale) : position_(value * (4/scale)) {}
		constexpr explicit HeadPosition(int value) : HeadPosition(value, 1) {}
		constexpr HeadPosition() : HeadPosition(0) {}

		/// @returns the whole number part of the position.
		constexpr int as_int() const { return position_ >> 2; }
		/// @returns n where n/2 is the head position.
		constexpr int as_half() const { return position_ >> 1; }
		/// @returns n where n/4 is the head position.
		constexpr int as_quarter() const { return position_; }

		/// @returns the head position at maximal but unspecified precision.
		constexpr int as_largest() const { return as_quarter(); }

		HeadPosition &operator +=(const HeadPosition &rhs) {
			position_ += rhs.position_;
			return *this;
		}
		constexpr bool operator ==(const HeadPosition &rhs) const {
			return position_ == rhs.position_;
		}
		constexpr bool operator !=(const HeadPosition &rhs) const {
			return position_ != rhs.position_;
		}
		constexpr bool operator <(const HeadPosition &rhs) const {
			return position_ < rhs.position_;
		}
		constexpr bool operator <=(const HeadPosition &rhs) const {
			return position_ <= rhs.position_;
		}
		constexpr bool operator >(const HeadPosition &rhs) const {
			return position_ > rhs.position_;
		}
		constexpr bool operator >=(const HeadPosition &rhs) const {
			return position_ >= rhs.position_;
		}

	private:
		int position_ = 0;
};

/*!
	Models a single track on a disk as a series of events, each event being of arbitrary length
	and resulting in either a flux transition or the sensing of an index hole.

	Subclasses should implement @c get_next_event.
*/
class Track {
	public:
		virtual ~Track() {}

		/*!
			Describes the location of a track, implementing < to allow for use as a set key.
		*/
		struct Address {
			int head;
			HeadPosition position;

			constexpr bool operator < (const Address &rhs) const {
				int largest_position = position.as_largest();
				int rhs_largest_position = rhs.position.as_largest();
				return std::tie(head, largest_position) < std::tie(rhs.head, rhs_largest_position);
			}
			Address(int head, HeadPosition position) : head(head), position(position) {}
		};

		/*!
			Describes a detectable track event: either a flux transition or the passing of the index hole,
			along with the length of time between the previous event and its occurance.

			The sum of all lengths of time across an entire track should be 1; if an event is said to be
			1/3 away then that means 1/3 of a rotation.
		*/
		struct Event {
			enum Type {
				IndexHole, FluxTransition
			} type;
			Time length;
		};

		/*!
			@returns the next event that will be detected during rotation of this disk.
		*/
		virtual Event get_next_event() = 0;

		/*!
			Jumps to the event latest offset that is less than or equal to the input time.

			@returns the time jumped to.
		*/
		virtual Time seek_to(const Time &time_since_index_hole) = 0;

		/*!
			The virtual copy constructor pattern; returns a copy of the Track.
		*/
		virtual Track *clone() const = 0;
};

}
}

#endif /* Track_h */
<|endoftext|>