<commit_before>#include "config.h"

Config* Config::getHandle() {
	static Config instance;
	return &instance;
}

void Config::setMainConfigFile(const std::string& configFileName) {
	if (confname.empty())
		confname = configFileName;
}

void Config::readConfig() {
	config = readConfig(confname, std::ifstream(confname));
	for (auto callback : notifyList)
		callback();
}

enum ConfigState { CONFIG_BLOCK, CONFIG_KEY, CONFIG_VALUE, CONFIG_VALUE_NEXT, CONFIG_VALUE_VAR, CONFIG_VALUE_STR, CONFIG_VALUE_STR_ESCAPED };
// This enum is simply an implementation detail for the configuration parser; hence it is placed here instead of the header file.

std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>> Config::readConfig(const std::string& filename, std::istream&& configData) {
	ConfigState state = CONFIG_BLOCK;
	unsigned int lineNum = 1;
	LogManager* logger = LogManager::getHandle();
	std::string blockName, key, value, valueVar;
	std::unordered_map<std::string, std::string> blockValues;
	std::unordered_multimap<std::string, std::string> localConfig;
	while (configData.good()) {
		char nextChar = configData.get();
		if (nextChar == std::istream::traits_type::eof())
			break;
		if (nextChar == '\n')
			lineNum++;
		if (state == CONFIG_BLOCK) {
			if (nextChar == '{') {
				if (blockName.empty())
					throw ConfigError (filename, lineNum, "A block without a name was opened.");
				state = CONFIG_KEY;
			} else if (nextChar == '}')
				throw ConfigError (filename, lineNum, "A closing brace could not be mached to an open block.");
			else if (nextChar == '#') {
				while (configFile.good() && configFile.get() != '\n') {}
				lineNum++;
			} else if (nextChar != ' ' && nextChar != '\t' && nextChar != '\r' && nextChar != '\n')
				blockName += nextChar;
		} else if (state == CONFIG_KEY) {
			if (nextChar == '#') {
				while (configFile.good() && configFile.get() != '\n') {}
				lineNum++;
			} else if (nextChar == '{')
				throw ConfigError (filename, lineNum, "A block was opened inside another block.");
			else if (nextChar == '}') {
				if (blockValues.empty())
					throw ConfigError (filename, lineNum, "An empty block was defined.  What was the point of that?");
				if (!key.empty() || !value.empty())
					throw ConfigError (filename, lineNum, "A key-value pair was unfinished when the block was terminated.");
				localConfig.insert(std::pair<std::string, std::unordered_map<std::string, std::string>> (blockName, blockValues));
				blockName.clear();
				blockValues.clear();
				logger->log(LOG_ALL, "config", "Block " + blockName + " read.");
				state = CONFIG_BLOCK;
			} else if (nextChar == ';')
				throw ConfigError (filename, lineNum, "A key was specified without a value.");
			else if (nextChar == '=')
				state = CONFIG_VALUE_NEXT;
			else if (nextChar != ' ' && nextChar != '\t' && nextChar != '\r' && nextChar != '\n')
				key += nextChar;
		} else if (state == CONFIG_VALUE) {
			if (nextChar == '#') {
				while (configFile.good() && configFile.get() != '\n') {}
				lineNum++;
			} else if (nextChar == ';') {
				blockValues.insert(std::pair<std::string, std::string> (key, value));
				key.clear();
				value.clear();
				state = CONFIG_KEY;
			} else if (nextChar == '+')
				state = CONFIG_VALUE_NEXT;
			else
				throw ConfigError (filename, lineNum, "An unexpected character was encountered; expected ';' or '+' (perhaps you forgot to end or properly concatenate your value?).");
		} else if (state == CONFIG_VALUE_NEXT) {
			if (nextChar == '#') {
				while (configFile.good() && configFile.get() != '\n') {}
				lineNum++;
			} else if (nextChar == '"')
				state = CONFIG_VALUE_STR;
			else if (nextChar != ' ' && nextChar != '\t' && nextChar != '\r' && nextChar != '\n') {
				valueVar += nextChar;
				state = CONFIG_VALUE_VAR;
			}
		} else if (state == CONFIG_VALUE_VAR) {
			if (nextChar == '"')
				throw ConfigError (filename, lineNum, "A string value was specified in the middle of a variable (perhaps you forgot to properly concatenate with '+'?).");
			else if (nextChar == '{')
				throw ConfigError (filename, lineNum, "A block was opened inside another block.");
			else if (nextChar == '}')
				throw ConfigError (filename, lineNum, "A key-value pair was unfinished when the block was terminated.");
			else if (nextChar == ' ' || nextChar == '\t' || nextChar == '\r' || nextChar == '\n' || nextChar == '+' || nextChar == ';') {
				auto keyIter = blockValues.find(valueVar);
				if (keyIter == blockValues.end())
					throw ConfigError (filename, lineNum, "The variable " + valueVar + " was specified, but did not match a variable already specified in the block.");
				value += keyIter->second;
				valueVar.clear();
				if (nextChar == ';') {
					state = CONFIG_KEY;
					blockValues.insert(std::pair<std::string, std::string> (key, value));
					key.clear();
					value.clear();
				} else if (nextChar == '+')
					state = CONFIG_VALUE_NEXT;
				else
					state = CONFIG_VALUE;
			} else
				valueVar += nextChar;
		} else if (state == CONFIG_VALUE_STR) {
			if (nextChar == '\\')
				state = CONFIG_VALUE_STR_ESCAPED;
			else if (nextChar == '"')
				state = CONFIG_VALUE;
			else
				value += nextChar;
		} else if (state == CONFIG_VALUE_STR_ESCAPED) {
			if (nextChar == '\\')
				value += '\\';
			else if (nextChar == 'n')
				value += '\n';
			else if (nextChar == 't')
				value += '\t';
			else if (nextChar == 'r')
				value += '\r';
			else
				value += nextChar;
			state = CONFIG_VALUE_STR;
		}
	}
	if (!blockValues.empty())
		throw ConfigError (filename, lineNum, "A block remained unterminated at the end of the file.");
	std::list<std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>> includedConfigs;
	for (auto block : localConfig) {
		if (block.first == "include") {
			auto inclfIter = block.second.find("file");
			if (inclfIter != block.second.end()) {
				std::string name = inclfIter->second;
				logger->log(LOG_ALL, "config", "Reading included file " + inclfIter->second);
				includedConfigs.push_back(readConfig(inclfIter->second, std::ifstream(name)));
			} else {
				auto incleIter = block.second.find("executable");
				if (incleIter != block.second.end()) {
					std::string cmd = incleIter->second;
					logger->log(LOG_ALL, "config", "Getting configuration data from `" + incleIter->second + "`");
					FILE* pipe = popen(cmd, "r");
					if (!pipe)
						raise ConfigError (cmd, 0, "Could not open pipe to read output.");
					char buffer[256];
					std::stringstream output;
					while (!feof(pipe)) {
						if (fgets(buffer, 256, pipe) != NULL)
							output << buffer;
					}
					pclose(pipe);
					includedConfigs.push_back(readConfig(cmd, output));
				} else
					throw ConfigError (filename, lineNum, "An include block was present that contained neither a file nor an executable.");
			}
		}
	}
	for (auto includes : includedConfigs) {
		for (auto conf : includes.second)
			localConfig.insert(std::pair<std::string, std::unordered_map<std::string, std::string>> (conf));
	}
	return localConfig;
}

void Config::addRehashNotify(std::function<void()> notifyCallback) {
	notifyList.push_back(notifyCallback);
}

size_t Config::blockCount(const std::string& block) const {
	return config.count(block);
}

std::list<std::unordered_map<std::string, std::string>> Config::getBlock(const std::string& block) const {
	std::list<std::unordered_map<std::string, std::string>> blockList;
	std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>::const_iterator startIter, endIter;
	std::tie(startIter, endIter) = config.equal_range(block);
	for (; startIter != endIter; ++startIter)
		blockList.push_back(startIter->second);
	return blockList;
}

std::unordered_map<std::string, std::string> Config::getSingleBlock(const std::string& block, const std::unordered_map<std::string, std::string>& conditions) const {
	std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>::const_iterator startIter, endIter;
	std::tie(startIter, endIter) = config.equal_range(block);
	for (; startIter != endIter; ++startIter) {
		for (auto check : conditions) {
			auto blockIter = startIter->second.find(check.first);
			if (blockIter == startIter->second.end())
				continue;
			if (check.second == blockIter->second)
				return startIter->second;
		}
	}
	return std::unordered_map<std::string, std::string> ();
}

std::string Config::getValue(const std::string& block, const std::string& key) const {
	auto blockIter = config.find(block);
	if (blockIter == config.end())
		return "";
	auto dataIter = blockIter->second.find(key);
	if (dataIter == blockIter->second.end())
		return "";
	return dataIter->second;
}

bool Config::getBoolValue(const std::string& block, const std::string& key) const {
	const std::string& value = getValue(block, key);
	std::string lowerValue;
	std::transform(value.begin(), value.end(), std::back_inserter(lowerValue), ::tolower);
	if (lowerValue == "yes" || lowerValue == "on" || lowerValue == "true")
		return true;
	return false;
}

std::list<std::string> Config::getAllValues(const std::string& block, const std::string& key) const {
	std::list<std::string> valueList;
	std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>::const_iterator startIter, endIter;
	std::tie(startIter, endIter) = config.equal_range(block);
	for (; startIter != endIter; ++startIter) {
		auto dataIter = startIter->second.find(key);
		if (dataIter == startIter->second.end())
			valueList.push_back("");
		else
			valueList.push_back(dataIter->second);
	}
	return valueList;
}

std::list<bool> Config::getAllBoolValues(const std::string& block, const std::string& key) const {
	std::list<bool> valueList;
	std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>::const_iterator startIter, endIter;
	std::tie(startIter, endIter) = config.equal_range(block);
	for (std::string lowerValue; startIter != endIter; ++startIter) {
		auto dataIter = startIter->second.find(key);
		if (dataIter == startIter->second.end())
			valueList.push_back(false);
		else {
			lowerValue.clear();
			std::transform(dataIter->second.begin(), dataIter->second.end(), std::back_inserter(lowerValue), ::tolower);
			if (lowerValue == "yes" || lowerValue == "on" || lowerValue == "true")
				valueList.push_back(true);
			else
				valueList.push_back(false);
		}
	}
	return valueList;
}

static bool Config::makeBool(const std::string& value) {
	std::string lowerValue;
	std::transform(value.begin(), value.end(), std::back_inserter(lowerValue), ::tolower);
	if (lowerValue == "yes" || lowerValue == "on" || lowerValue == "true")
		return true;
	return false;
}

Config::Config() {}

ConfigError::ConfigError(const std::string& filename, unsigned int lineNum, const std::string& description) {
	std::ostringstream descStr;
	descStr << "An error occurred reading the configuration from '" << filename << "' on line " << lineNum << ": " << description;
	desc = descStr.str();
}<commit_msg>Fix remaining uses of configFile<commit_after>#include "config.h"

Config* Config::getHandle() {
	static Config instance;
	return &instance;
}

void Config::setMainConfigFile(const std::string& configFileName) {
	if (confname.empty())
		confname = configFileName;
}

void Config::readConfig() {
	config = readConfig(confname, std::ifstream(confname));
	for (auto callback : notifyList)
		callback();
}

enum ConfigState { CONFIG_BLOCK, CONFIG_KEY, CONFIG_VALUE, CONFIG_VALUE_NEXT, CONFIG_VALUE_VAR, CONFIG_VALUE_STR, CONFIG_VALUE_STR_ESCAPED };
// This enum is simply an implementation detail for the configuration parser; hence it is placed here instead of the header file.

std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>> Config::readConfig(const std::string& filename, std::istream&& configData) {
	ConfigState state = CONFIG_BLOCK;
	unsigned int lineNum = 1;
	LogManager* logger = LogManager::getHandle();
	std::string blockName, key, value, valueVar;
	std::unordered_map<std::string, std::string> blockValues;
	std::unordered_multimap<std::string, std::string> localConfig;
	while (configData.good()) {
		char nextChar = configData.get();
		if (nextChar == std::istream::traits_type::eof())
			break;
		if (nextChar == '\n')
			lineNum++;
		if (state == CONFIG_BLOCK) {
			if (nextChar == '{') {
				if (blockName.empty())
					throw ConfigError (filename, lineNum, "A block without a name was opened.");
				state = CONFIG_KEY;
			} else if (nextChar == '}')
				throw ConfigError (filename, lineNum, "A closing brace could not be mached to an open block.");
			else if (nextChar == '#') {
				while (configData.good() && configData.get() != '\n') {}
				lineNum++;
			} else if (nextChar != ' ' && nextChar != '\t' && nextChar != '\r' && nextChar != '\n')
				blockName += nextChar;
		} else if (state == CONFIG_KEY) {
			if (nextChar == '#') {
				while (configData.good() && configData.get() != '\n') {}
				lineNum++;
			} else if (nextChar == '{')
				throw ConfigError (filename, lineNum, "A block was opened inside another block.");
			else if (nextChar == '}') {
				if (blockValues.empty())
					throw ConfigError (filename, lineNum, "An empty block was defined.  What was the point of that?");
				if (!key.empty() || !value.empty())
					throw ConfigError (filename, lineNum, "A key-value pair was unfinished when the block was terminated.");
				localConfig.insert(std::pair<std::string, std::unordered_map<std::string, std::string>> (blockName, blockValues));
				blockName.clear();
				blockValues.clear();
				logger->log(LOG_ALL, "config", "Block " + blockName + " read.");
				state = CONFIG_BLOCK;
			} else if (nextChar == ';')
				throw ConfigError (filename, lineNum, "A key was specified without a value.");
			else if (nextChar == '=')
				state = CONFIG_VALUE_NEXT;
			else if (nextChar != ' ' && nextChar != '\t' && nextChar != '\r' && nextChar != '\n')
				key += nextChar;
		} else if (state == CONFIG_VALUE) {
			if (nextChar == '#') {
				while (configData.good() && configData.get() != '\n') {}
				lineNum++;
			} else if (nextChar == ';') {
				blockValues.insert(std::pair<std::string, std::string> (key, value));
				key.clear();
				value.clear();
				state = CONFIG_KEY;
			} else if (nextChar == '+')
				state = CONFIG_VALUE_NEXT;
			else
				throw ConfigError (filename, lineNum, "An unexpected character was encountered; expected ';' or '+' (perhaps you forgot to end or properly concatenate your value?).");
		} else if (state == CONFIG_VALUE_NEXT) {
			if (nextChar == '#') {
				while (configData.good() && configData.get() != '\n') {}
				lineNum++;
			} else if (nextChar == '"')
				state = CONFIG_VALUE_STR;
			else if (nextChar != ' ' && nextChar != '\t' && nextChar != '\r' && nextChar != '\n') {
				valueVar += nextChar;
				state = CONFIG_VALUE_VAR;
			}
		} else if (state == CONFIG_VALUE_VAR) {
			if (nextChar == '"')
				throw ConfigError (filename, lineNum, "A string value was specified in the middle of a variable (perhaps you forgot to properly concatenate with '+'?).");
			else if (nextChar == '{')
				throw ConfigError (filename, lineNum, "A block was opened inside another block.");
			else if (nextChar == '}')
				throw ConfigError (filename, lineNum, "A key-value pair was unfinished when the block was terminated.");
			else if (nextChar == ' ' || nextChar == '\t' || nextChar == '\r' || nextChar == '\n' || nextChar == '+' || nextChar == ';') {
				auto keyIter = blockValues.find(valueVar);
				if (keyIter == blockValues.end())
					throw ConfigError (filename, lineNum, "The variable " + valueVar + " was specified, but did not match a variable already specified in the block.");
				value += keyIter->second;
				valueVar.clear();
				if (nextChar == ';') {
					state = CONFIG_KEY;
					blockValues.insert(std::pair<std::string, std::string> (key, value));
					key.clear();
					value.clear();
				} else if (nextChar == '+')
					state = CONFIG_VALUE_NEXT;
				else
					state = CONFIG_VALUE;
			} else
				valueVar += nextChar;
		} else if (state == CONFIG_VALUE_STR) {
			if (nextChar == '\\')
				state = CONFIG_VALUE_STR_ESCAPED;
			else if (nextChar == '"')
				state = CONFIG_VALUE;
			else
				value += nextChar;
		} else if (state == CONFIG_VALUE_STR_ESCAPED) {
			if (nextChar == '\\')
				value += '\\';
			else if (nextChar == 'n')
				value += '\n';
			else if (nextChar == 't')
				value += '\t';
			else if (nextChar == 'r')
				value += '\r';
			else
				value += nextChar;
			state = CONFIG_VALUE_STR;
		}
	}
	if (!blockValues.empty())
		throw ConfigError (filename, lineNum, "A block remained unterminated at the end of the file.");
	std::list<std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>> includedConfigs;
	for (auto block : localConfig) {
		if (block.first == "include") {
			auto inclfIter = block.second.find("file");
			if (inclfIter != block.second.end()) {
				std::string name = inclfIter->second;
				logger->log(LOG_ALL, "config", "Reading included file " + inclfIter->second);
				includedConfigs.push_back(readConfig(inclfIter->second, std::ifstream(name)));
			} else {
				auto incleIter = block.second.find("executable");
				if (incleIter != block.second.end()) {
					std::string cmd = incleIter->second;
					logger->log(LOG_ALL, "config", "Getting configuration data from `" + incleIter->second + "`");
					FILE* pipe = popen(cmd, "r");
					if (!pipe)
						raise ConfigError (cmd, 0, "Could not open pipe to read output.");
					char buffer[256];
					std::stringstream output;
					while (!feof(pipe)) {
						if (fgets(buffer, 256, pipe) != NULL)
							output << buffer;
					}
					pclose(pipe);
					includedConfigs.push_back(readConfig(cmd, output));
				} else
					throw ConfigError (filename, lineNum, "An include block was present that contained neither a file nor an executable.");
			}
		}
	}
	for (auto includes : includedConfigs) {
		for (auto conf : includes.second)
			localConfig.insert(std::pair<std::string, std::unordered_map<std::string, std::string>> (conf));
	}
	return localConfig;
}

void Config::addRehashNotify(std::function<void()> notifyCallback) {
	notifyList.push_back(notifyCallback);
}

size_t Config::blockCount(const std::string& block) const {
	return config.count(block);
}

std::list<std::unordered_map<std::string, std::string>> Config::getBlock(const std::string& block) const {
	std::list<std::unordered_map<std::string, std::string>> blockList;
	std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>::const_iterator startIter, endIter;
	std::tie(startIter, endIter) = config.equal_range(block);
	for (; startIter != endIter; ++startIter)
		blockList.push_back(startIter->second);
	return blockList;
}

std::unordered_map<std::string, std::string> Config::getSingleBlock(const std::string& block, const std::unordered_map<std::string, std::string>& conditions) const {
	std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>::const_iterator startIter, endIter;
	std::tie(startIter, endIter) = config.equal_range(block);
	for (; startIter != endIter; ++startIter) {
		for (auto check : conditions) {
			auto blockIter = startIter->second.find(check.first);
			if (blockIter == startIter->second.end())
				continue;
			if (check.second == blockIter->second)
				return startIter->second;
		}
	}
	return std::unordered_map<std::string, std::string> ();
}

std::string Config::getValue(const std::string& block, const std::string& key) const {
	auto blockIter = config.find(block);
	if (blockIter == config.end())
		return "";
	auto dataIter = blockIter->second.find(key);
	if (dataIter == blockIter->second.end())
		return "";
	return dataIter->second;
}

bool Config::getBoolValue(const std::string& block, const std::string& key) const {
	const std::string& value = getValue(block, key);
	std::string lowerValue;
	std::transform(value.begin(), value.end(), std::back_inserter(lowerValue), ::tolower);
	if (lowerValue == "yes" || lowerValue == "on" || lowerValue == "true")
		return true;
	return false;
}

std::list<std::string> Config::getAllValues(const std::string& block, const std::string& key) const {
	std::list<std::string> valueList;
	std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>::const_iterator startIter, endIter;
	std::tie(startIter, endIter) = config.equal_range(block);
	for (; startIter != endIter; ++startIter) {
		auto dataIter = startIter->second.find(key);
		if (dataIter == startIter->second.end())
			valueList.push_back("");
		else
			valueList.push_back(dataIter->second);
	}
	return valueList;
}

std::list<bool> Config::getAllBoolValues(const std::string& block, const std::string& key) const {
	std::list<bool> valueList;
	std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>::const_iterator startIter, endIter;
	std::tie(startIter, endIter) = config.equal_range(block);
	for (std::string lowerValue; startIter != endIter; ++startIter) {
		auto dataIter = startIter->second.find(key);
		if (dataIter == startIter->second.end())
			valueList.push_back(false);
		else {
			lowerValue.clear();
			std::transform(dataIter->second.begin(), dataIter->second.end(), std::back_inserter(lowerValue), ::tolower);
			if (lowerValue == "yes" || lowerValue == "on" || lowerValue == "true")
				valueList.push_back(true);
			else
				valueList.push_back(false);
		}
	}
	return valueList;
}

static bool Config::makeBool(const std::string& value) {
	std::string lowerValue;
	std::transform(value.begin(), value.end(), std::back_inserter(lowerValue), ::tolower);
	if (lowerValue == "yes" || lowerValue == "on" || lowerValue == "true")
		return true;
	return false;
}

Config::Config() {}

ConfigError::ConfigError(const std::string& filename, unsigned int lineNum, const std::string& description) {
	std::ostringstream descStr;
	descStr << "An error occurred reading the configuration from '" << filename << "' on line " << lineNum << ": " << description;
	desc = descStr.str();
}<|endoftext|>


<commit_before>/*
 * SchemeExec.cc
 *
 * Execute ExecutionLink's
 * Copyright (c) 2009 Linas Vepstas <linasvepstas@gmail.com>
 */

#ifdef HAVE_GUILE

#include <libguile.h>

#include <opencog/atomspace/Link.h>

#include <boost/shared_ptr.hpp>

#include "SchemeEval.h"
#include "SchemeSmob.h"

using namespace opencog;

/**
 * do_apply -- apply named function func to arguments in ListLink
 * It is assumed that varargs is a ListLink, containing a list of
 * atom handles. This list is unpacked, and then the fuction func
 * is applied to them. If the function returns an atom handle, then
 * this is returned.
 */
Handle SchemeEval::do_apply(const std::string &func, Handle varargs)
{
	// Apply the function to the args
	SCM sresult = do_apply_scm (func, varargs);

	// If the result is a handle, return the handle.
	if (!SCM_SMOB_PREDICATE(SchemeSmob::cog_handle_tag, sresult))
	{
		return Handle::UNDEFINED;
	}
	return SchemeSmob::scm_to_handle(sresult);
}

/**
 * do_apply_scm -- apply named function func to arguments in ListLink
 * It is assumed that varargs is a ListLink, containing a list of
 * atom handles. This list is unpacked, and then the fuction func
 * is applied to them. The SCM value returned by the function is returned.
 */
SCM SchemeEval::do_apply_scm( const std::string& func, Handle varargs )
{
	SCM sfunc = scm_from_locale_symbol(func.c_str());
	SCM expr = SCM_EOL;

	// If there were args, pass the args to the function.
    boost::shared_ptr<Link> largs = atomspace->cloneLink(varargs);
	if (largs)
	{
		const std::vector<Handle> &oset = largs->getOutgoingSet();

		size_t sz = oset.size();
		for (int i=sz-1; i>=0; i--)
		{
			Handle h = oset[i];
			SCM sh = SchemeSmob::handle_to_scm(h);
			expr = scm_cons(sh, expr);
		}
	}
	expr = scm_cons(sfunc, expr);
	return do_scm_eval(expr);
}

#endif
/* ===================== END OF FILE ============================ */
<commit_msg>cleanup conversion to new atomspace design; all that smart-pointer complexity wasn't needed.<commit_after>/*
 * SchemeExec.cc
 *
 * Execute ExecutionLink's
 * Copyright (c) 2009 Linas Vepstas <linasvepstas@gmail.com>
 */

#ifdef HAVE_GUILE

#include <libguile.h>

#include <opencog/atomspace/Link.h>
#include "SchemeEval.h"
#include "SchemeSmob.h"

using namespace opencog;

/**
 * do_apply -- apply named function func to arguments in ListLink
 * It is assumed that varargs is a ListLink, containing a list of
 * atom handles. This list is unpacked, and then the fuction func
 * is applied to them. If the function returns an atom handle, then
 * this is returned.
 */
Handle SchemeEval::do_apply(const std::string &func, Handle varargs)
{
	// Apply the function to the args
	SCM sresult = do_apply_scm (func, varargs);

	// If the result is a handle, return the handle.
	if (!SCM_SMOB_PREDICATE(SchemeSmob::cog_handle_tag, sresult))
	{
		return Handle::UNDEFINED;
	}
	return SchemeSmob::scm_to_handle(sresult);
}

/**
 * do_apply_scm -- apply named function func to arguments in ListLink
 * It is assumed that varargs is a ListLink, containing a list of
 * atom handles. This list is unpacked, and then the fuction func
 * is applied to them. The SCM value returned by the function is returned.
 */
SCM SchemeEval::do_apply_scm( const std::string& func, Handle varargs )
{
	SCM sfunc = scm_from_locale_symbol(func.c_str());
	SCM expr = SCM_EOL;

	// If there were args, pass the args to the function.
	const std::vector<Handle> &oset = atomspace->getOutgoing(varargs);

	size_t sz = oset.size();
	for (int i=sz-1; i>=0; i--)
	{
		Handle h = oset[i];
		SCM sh = SchemeSmob::handle_to_scm(h);
		expr = scm_cons(sh, expr);
	}
	expr = scm_cons(sfunc, expr);
	return do_scm_eval(expr);
}

#endif
/* ===================== END OF FILE ============================ */
<|endoftext|>


<commit_before>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "GatherRCDataElementThread.h"
#include "INSFVAttributes.h"
#include "INSFVMomentumResidualObject.h"
#include "FVElementalKernel.h"

GatherRCDataElementThread::GatherRCDataElementThread(FEProblemBase & fe_problem,
                                                     const std::vector<unsigned int> & vars)
  : ThreadedElementLoop<ConstElemRange>(fe_problem), _vars(vars)
{
}

// Splitting Constructor
GatherRCDataElementThread::GatherRCDataElementThread(GatherRCDataElementThread & x,
                                                     Threads::split split)
  : ThreadedElementLoop<ConstElemRange>(x, split), _vars(x._vars)
{
}

void
GatherRCDataElementThread::subdomainChanged()
{
  ThreadedElementLoop<ConstElemRange>::subdomainChanged();

  _insfv_elemental_kernels.clear();

  auto queries = _fe_problem.theWarehouse()
                     .query()
                     .template condition<AttribSystem>("FVElementalKernel")
                     .template condition<AttribThread>(_tid)
                     .template condition<AttribSubdomains>(_subdomain);

  for (const auto var_num : _vars)
  {
    // We don't want to do cascading var num attributes or else the second time around we won't get
    // any results out of the query (e.g. an object cannot have a variable that simultaneously has
    // both var number 0 and 1)
    auto copied_queries = queries;
    std::vector<FVElementalKernel *> var_eks;
    copied_queries.template condition<AttribVar>(static_cast<int>(var_num)).queryInto(var_eks);
    for (auto var_ek : var_eks)
      if (auto insfv_ek = dynamic_cast<INSFVMomentumResidualObject *>(var_ek))
        _insfv_elemental_kernels.push_back(insfv_ek);
  }
}

void
GatherRCDataElementThread::onElement(const Elem * const elem)
{
  mooseAssert(elem && elem->subdomain_id() == _subdomain, "sub ids don't match");

  for (auto * const insfv_ek : _insfv_elemental_kernels)
    insfv_ek->gatherRCData(*elem);
}
<commit_msg>Avoid time kernels when executing RC on initial as they are not initialized refs  #18817<commit_after>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "GatherRCDataElementThread.h"
#include "INSFVAttributes.h"
#include "INSFVMomentumResidualObject.h"
#include "FVElementalKernel.h"
#include "FVTimeKernel.h"

GatherRCDataElementThread::GatherRCDataElementThread(FEProblemBase & fe_problem,
                                                     const std::vector<unsigned int> & vars)
  : ThreadedElementLoop<ConstElemRange>(fe_problem), _vars(vars)
{
}

// Splitting Constructor
GatherRCDataElementThread::GatherRCDataElementThread(GatherRCDataElementThread & x,
                                                     Threads::split split)
  : ThreadedElementLoop<ConstElemRange>(x, split), _vars(x._vars)
{
}

void
GatherRCDataElementThread::subdomainChanged()
{
  ThreadedElementLoop<ConstElemRange>::subdomainChanged();

  _insfv_elemental_kernels.clear();

  auto queries = _fe_problem.theWarehouse()
                     .query()
                     .template condition<AttribSystem>("FVElementalKernel")
                     .template condition<AttribThread>(_tid)
                     .template condition<AttribSubdomains>(_subdomain);

  for (const auto var_num : _vars)
  {
    // We don't want to do cascading var num attributes or else the second time around we won't get
    // any results out of the query (e.g. an object cannot have a variable that simultaneously has
    // both var number 0 and 1)
    auto copied_queries = queries;
    std::vector<FVElementalKernel *> var_eks;
    copied_queries.template condition<AttribVar>(static_cast<int>(var_num)).queryInto(var_eks);
    for (auto var_ek : var_eks)
      if (auto insfv_ek = dynamic_cast<INSFVMomentumResidualObject *>(var_ek))
      {
        // On INITIAL, the time integrator is not ready for these residual objects
        if (this->_fe_problem.getCurrentExecuteOnFlag() == EXEC_INITIAL)
          if (dynamic_cast<FVTimeKernel *>(var_ek))
            continue;

        _insfv_elemental_kernels.push_back(insfv_ek);
      }
  }
}

void
GatherRCDataElementThread::onElement(const Elem * const elem)
{
  mooseAssert(elem && elem->subdomain_id() == _subdomain, "sub ids don't match");

  for (auto * const insfv_ek : _insfv_elemental_kernels)
    insfv_ek->gatherRCData(*elem);
}
<|endoftext|>


<commit_before>//===-- ARMTargetMachine.cpp - Define TargetMachine for ARM ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//

#include "ARMTargetMachine.h"
#include "ARM.h"
#include "ARMFrameLowering.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/PassManager.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Transforms/Scalar.h"
using namespace llvm;

static cl::opt<bool>
EnableGlobalMerge("global-merge", cl::Hidden,
                  cl::desc("Enable global merge pass"),
                  cl::init(true));

static cl::opt<bool>
DisableA15SDOptimization("disable-a15-sd-optimization", cl::Hidden,
                   cl::desc("Inhibit optimization of S->D register accesses on A15"),
                   cl::init(false));

extern "C" void LLVMInitializeARMTarget() {
  // Register the target.
  RegisterTargetMachine<ARMTargetMachine> X(TheARMTarget);
  RegisterTargetMachine<ThumbTargetMachine> Y(TheThumbTarget);
}

/// TargetMachine ctor - Create an ARM architecture model.
///
ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T, StringRef TT,
                                           StringRef CPU, StringRef FS,
                                           const TargetOptions &Options,
                                           Reloc::Model RM, CodeModel::Model CM,
                                           CodeGenOpt::Level OL)
  : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL),
    Subtarget(TT, CPU, FS, Options),
    JITInfo(),
    InstrItins(Subtarget.getInstrItineraryData()) {
  // Default to soft float ABI
  if (Options.FloatABIType == FloatABI::Default)
    this->Options.FloatABIType = FloatABI::Soft;
}

void ARMBaseTargetMachine::addAnalysisPasses(PassManagerBase &PM) {
  // Add first the target-independent BasicTTI pass, then our ARM pass. This
  // allows the ARM pass to delegate to the target independent layer when
  // appropriate.
  PM.add(createBasicTargetTransformInfoPass(this));
  PM.add(createARMTargetTransformInfoPass(this));
}

void ARMTargetMachine::anchor() { }

ARMTargetMachine::ARMTargetMachine(const Target &T, StringRef TT,
                                   StringRef CPU, StringRef FS,
                                   const TargetOptions &Options,
                                   Reloc::Model RM, CodeModel::Model CM,
                                   CodeGenOpt::Level OL)
  : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL),
    InstrInfo(Subtarget),
    DL(Subtarget.isAPCS_ABI() ?
               std::string("e-p:32:32-f64:32:64-i64:32:64-"
                           "v128:32:128-v64:32:64-n32-S32") :
               Subtarget.isAAPCS_ABI() ?
               std::string("e-p:32:32-f64:64:64-i64:64:64-"
                           "v128:64:128-v64:64:64-n32-S64") :
               std::string("e-p:32:32-f64:64:64-i64:64:64-"
                           "v128:64:128-v64:64:64-n32-S32")),
    TLInfo(*this),
    TSInfo(*this),
    FrameLowering(Subtarget) {
  initAsmInfo();
  if (!Subtarget.hasARMOps())
    report_fatal_error("CPU: '" + Subtarget.getCPUString() + "' does not "
                       "support ARM mode execution!");
}

void ThumbTargetMachine::anchor() { }

ThumbTargetMachine::ThumbTargetMachine(const Target &T, StringRef TT,
                                       StringRef CPU, StringRef FS,
                                       const TargetOptions &Options,
                                       Reloc::Model RM, CodeModel::Model CM,
                                       CodeGenOpt::Level OL)
  : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL),
    InstrInfo(Subtarget.hasThumb2()
              ? ((ARMBaseInstrInfo*)new Thumb2InstrInfo(Subtarget))
              : ((ARMBaseInstrInfo*)new Thumb1InstrInfo(Subtarget))),
    DL(Subtarget.isAPCS_ABI() ?
               std::string("e-p:32:32-f64:32:64-i64:32:64-"
                           "i16:16:32-i8:8:32-i1:8:32-"
                           "v128:32:128-v64:32:64-a:0:32-n32-S32") :
               Subtarget.isAAPCS_ABI() ?
               std::string("e-p:32:32-f64:64:64-i64:64:64-"
                           "i16:16:32-i8:8:32-i1:8:32-"
                           "v128:64:128-v64:64:64-a:0:32-n32-S64") :
               std::string("e-p:32:32-f64:64:64-i64:64:64-"
                           "i16:16:32-i8:8:32-i1:8:32-"
                           "v128:64:128-v64:64:64-a:0:32-n32-S32")),
    TLInfo(*this),
    TSInfo(*this),
    FrameLowering(Subtarget.hasThumb2()
              ? new ARMFrameLowering(Subtarget)
              : (ARMFrameLowering*)new Thumb1FrameLowering(Subtarget)) {
  initAsmInfo();
}

namespace {
/// ARM Code Generator Pass Configuration Options.
class ARMPassConfig : public TargetPassConfig {
public:
  ARMPassConfig(ARMBaseTargetMachine *TM, PassManagerBase &PM)
    : TargetPassConfig(TM, PM) {}

  ARMBaseTargetMachine &getARMTargetMachine() const {
    return getTM<ARMBaseTargetMachine>();
  }

  const ARMSubtarget &getARMSubtarget() const {
    return *getARMTargetMachine().getSubtargetImpl();
  }

  virtual bool addPreISel();
  virtual bool addInstSelector();
  virtual bool addPreRegAlloc();
  virtual bool addPreSched2();
  virtual bool addPreEmitPass();
};
} // namespace

TargetPassConfig *ARMBaseTargetMachine::createPassConfig(PassManagerBase &PM) {
  return new ARMPassConfig(this, PM);
}

bool ARMPassConfig::addPreISel() {
  if (TM->getOptLevel() != CodeGenOpt::None && EnableGlobalMerge)
    addPass(createGlobalMergePass(TM));

  return false;
}

bool ARMPassConfig::addInstSelector() {
  addPass(createARMISelDag(getARMTargetMachine(), getOptLevel()));

  const ARMSubtarget *Subtarget = &getARMSubtarget();
  if (Subtarget->isTargetELF() && !Subtarget->isThumb1Only() &&
      TM->Options.EnableFastISel)
    addPass(createARMGlobalBaseRegPass());
  return false;
}

bool ARMPassConfig::addPreRegAlloc() {
  // FIXME: temporarily disabling load / store optimization pass for Thumb1.
  if (getOptLevel() != CodeGenOpt::None && !getARMSubtarget().isThumb1Only())
    addPass(createARMLoadStoreOptimizationPass(true));
  if (getOptLevel() != CodeGenOpt::None && getARMSubtarget().isCortexA9())
    addPass(createMLxExpansionPass());
  // Since the A15SDOptimizer pass can insert VDUP instructions, it can only be
  // enabled when NEON is available.
  if (getOptLevel() != CodeGenOpt::None && getARMSubtarget().isCortexA15() &&
    getARMSubtarget().hasNEON() && !DisableA15SDOptimization) {
    addPass(createA15SDOptimizerPass());
  }
  return true;
}

bool ARMPassConfig::addPreSched2() {
  // FIXME: temporarily disabling load / store optimization pass for Thumb1.
  if (getOptLevel() != CodeGenOpt::None) {
    if (!getARMSubtarget().isThumb1Only()) {
      addPass(createARMLoadStoreOptimizationPass());
      printAndVerify("After ARM load / store optimizer");
    }
    if (getARMSubtarget().hasNEON())
      addPass(createExecutionDependencyFixPass(&ARM::DPRRegClass));
  }

  // Expand some pseudo instructions into multiple instructions to allow
  // proper scheduling.
  addPass(createARMExpandPseudoPass());

  if (getOptLevel() != CodeGenOpt::None) {
    if (!getARMSubtarget().isThumb1Only()) {
      // in v8, IfConversion depends on Thumb instruction widths
      if (getARMSubtarget().restrictIT() &&
          !getARMSubtarget().prefers32BitThumb())
        addPass(createThumb2SizeReductionPass());
      addPass(&IfConverterID);
    }
  }
  if (getARMSubtarget().isThumb2())
    addPass(createThumb2ITBlockPass());

  return true;
}

bool ARMPassConfig::addPreEmitPass() {
  if (getARMSubtarget().isThumb2()) {
    if (!getARMSubtarget().prefers32BitThumb())
      addPass(createThumb2SizeReductionPass());

    // Constant island pass work on unbundled instructions.
    addPass(&UnpackMachineBundlesID);
  }

  addPass(createARMConstantIslandPass());

  return true;
}

bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM,
                                          JITCodeEmitter &JCE) {
  // Machine code emitter pass for ARM.
  PM.add(createARMJITCodeEmitterPass(*this, JCE));
  return false;
}
<commit_msg>Refactor the construction of the DataLayout string on ARM.<commit_after>//===-- ARMTargetMachine.cpp - Define TargetMachine for ARM ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//

#include "ARMTargetMachine.h"
#include "ARM.h"
#include "ARMFrameLowering.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/PassManager.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Transforms/Scalar.h"
using namespace llvm;

static cl::opt<bool>
EnableGlobalMerge("global-merge", cl::Hidden,
                  cl::desc("Enable global merge pass"),
                  cl::init(true));

static cl::opt<bool>
DisableA15SDOptimization("disable-a15-sd-optimization", cl::Hidden,
                   cl::desc("Inhibit optimization of S->D register accesses on A15"),
                   cl::init(false));

extern "C" void LLVMInitializeARMTarget() {
  // Register the target.
  RegisterTargetMachine<ARMTargetMachine> X(TheARMTarget);
  RegisterTargetMachine<ThumbTargetMachine> Y(TheThumbTarget);
}

/// TargetMachine ctor - Create an ARM architecture model.
///
ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T, StringRef TT,
                                           StringRef CPU, StringRef FS,
                                           const TargetOptions &Options,
                                           Reloc::Model RM, CodeModel::Model CM,
                                           CodeGenOpt::Level OL)
  : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL),
    Subtarget(TT, CPU, FS, Options),
    JITInfo(),
    InstrItins(Subtarget.getInstrItineraryData()) {
  // Default to soft float ABI
  if (Options.FloatABIType == FloatABI::Default)
    this->Options.FloatABIType = FloatABI::Soft;
}

void ARMBaseTargetMachine::addAnalysisPasses(PassManagerBase &PM) {
  // Add first the target-independent BasicTTI pass, then our ARM pass. This
  // allows the ARM pass to delegate to the target independent layer when
  // appropriate.
  PM.add(createBasicTargetTransformInfoPass(this));
  PM.add(createARMTargetTransformInfoPass(this));
}

void ARMTargetMachine::anchor() { }

static std::string computeDataLayout(ARMSubtarget &ST) {
  std::string Ret = "e-p:32:32";

  if (ST.isAPCS_ABI())
    Ret += "-f64:32:64-i64:32:64";
  else
    Ret += "-f64:64:64-i64:64:64";

  if (ST.isThumb()) {
    if (ST.isAPCS_ABI())
      Ret += "-i16:16:32-i8:8:32-i1:8:32";
    else
      Ret += "-i16:16:32-i8:8:32-i1:8:32";
  }

  if (ST.isAPCS_ABI())
    Ret += "-v128:32:128-v64:32:64";
  else
    Ret += "-v128:64:128-v64:64:64";

  if (ST.isThumb()) {
    if (ST.isAPCS_ABI())
      Ret += "-a:0:32";
    else
      Ret += "-a:0:32";
  }

  Ret += "-n32";

  if (ST.isAAPCS_ABI())
    Ret += "-S64";
  else
    Ret += "-S32";

  return Ret;
}

ARMTargetMachine::ARMTargetMachine(const Target &T, StringRef TT,
                                   StringRef CPU, StringRef FS,
                                   const TargetOptions &Options,
                                   Reloc::Model RM, CodeModel::Model CM,
                                   CodeGenOpt::Level OL)
  : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL),
    InstrInfo(Subtarget),
    DL(computeDataLayout(Subtarget)),
    TLInfo(*this),
    TSInfo(*this),
    FrameLowering(Subtarget) {
  initAsmInfo();
  if (!Subtarget.hasARMOps())
    report_fatal_error("CPU: '" + Subtarget.getCPUString() + "' does not "
                       "support ARM mode execution!");
}

void ThumbTargetMachine::anchor() { }

ThumbTargetMachine::ThumbTargetMachine(const Target &T, StringRef TT,
                                       StringRef CPU, StringRef FS,
                                       const TargetOptions &Options,
                                       Reloc::Model RM, CodeModel::Model CM,
                                       CodeGenOpt::Level OL)
  : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL),
    InstrInfo(Subtarget.hasThumb2()
              ? ((ARMBaseInstrInfo*)new Thumb2InstrInfo(Subtarget))
              : ((ARMBaseInstrInfo*)new Thumb1InstrInfo(Subtarget))),
    DL(computeDataLayout(Subtarget)),
    TLInfo(*this),
    TSInfo(*this),
    FrameLowering(Subtarget.hasThumb2()
              ? new ARMFrameLowering(Subtarget)
              : (ARMFrameLowering*)new Thumb1FrameLowering(Subtarget)) {
  initAsmInfo();
}

namespace {
/// ARM Code Generator Pass Configuration Options.
class ARMPassConfig : public TargetPassConfig {
public:
  ARMPassConfig(ARMBaseTargetMachine *TM, PassManagerBase &PM)
    : TargetPassConfig(TM, PM) {}

  ARMBaseTargetMachine &getARMTargetMachine() const {
    return getTM<ARMBaseTargetMachine>();
  }

  const ARMSubtarget &getARMSubtarget() const {
    return *getARMTargetMachine().getSubtargetImpl();
  }

  virtual bool addPreISel();
  virtual bool addInstSelector();
  virtual bool addPreRegAlloc();
  virtual bool addPreSched2();
  virtual bool addPreEmitPass();
};
} // namespace

TargetPassConfig *ARMBaseTargetMachine::createPassConfig(PassManagerBase &PM) {
  return new ARMPassConfig(this, PM);
}

bool ARMPassConfig::addPreISel() {
  if (TM->getOptLevel() != CodeGenOpt::None && EnableGlobalMerge)
    addPass(createGlobalMergePass(TM));

  return false;
}

bool ARMPassConfig::addInstSelector() {
  addPass(createARMISelDag(getARMTargetMachine(), getOptLevel()));

  const ARMSubtarget *Subtarget = &getARMSubtarget();
  if (Subtarget->isTargetELF() && !Subtarget->isThumb1Only() &&
      TM->Options.EnableFastISel)
    addPass(createARMGlobalBaseRegPass());
  return false;
}

bool ARMPassConfig::addPreRegAlloc() {
  // FIXME: temporarily disabling load / store optimization pass for Thumb1.
  if (getOptLevel() != CodeGenOpt::None && !getARMSubtarget().isThumb1Only())
    addPass(createARMLoadStoreOptimizationPass(true));
  if (getOptLevel() != CodeGenOpt::None && getARMSubtarget().isCortexA9())
    addPass(createMLxExpansionPass());
  // Since the A15SDOptimizer pass can insert VDUP instructions, it can only be
  // enabled when NEON is available.
  if (getOptLevel() != CodeGenOpt::None && getARMSubtarget().isCortexA15() &&
    getARMSubtarget().hasNEON() && !DisableA15SDOptimization) {
    addPass(createA15SDOptimizerPass());
  }
  return true;
}

bool ARMPassConfig::addPreSched2() {
  // FIXME: temporarily disabling load / store optimization pass for Thumb1.
  if (getOptLevel() != CodeGenOpt::None) {
    if (!getARMSubtarget().isThumb1Only()) {
      addPass(createARMLoadStoreOptimizationPass());
      printAndVerify("After ARM load / store optimizer");
    }
    if (getARMSubtarget().hasNEON())
      addPass(createExecutionDependencyFixPass(&ARM::DPRRegClass));
  }

  // Expand some pseudo instructions into multiple instructions to allow
  // proper scheduling.
  addPass(createARMExpandPseudoPass());

  if (getOptLevel() != CodeGenOpt::None) {
    if (!getARMSubtarget().isThumb1Only()) {
      // in v8, IfConversion depends on Thumb instruction widths
      if (getARMSubtarget().restrictIT() &&
          !getARMSubtarget().prefers32BitThumb())
        addPass(createThumb2SizeReductionPass());
      addPass(&IfConverterID);
    }
  }
  if (getARMSubtarget().isThumb2())
    addPass(createThumb2ITBlockPass());

  return true;
}

bool ARMPassConfig::addPreEmitPass() {
  if (getARMSubtarget().isThumb2()) {
    if (!getARMSubtarget().prefers32BitThumb())
      addPass(createThumb2SizeReductionPass());

    // Constant island pass work on unbundled instructions.
    addPass(&UnpackMachineBundlesID);
  }

  addPass(createARMConstantIslandPass());

  return true;
}

bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM,
                                          JITCodeEmitter &JCE) {
  // Machine code emitter pass for ARM.
  PM.add(createARMJITCodeEmitterPass(*this, JCE));
  return false;
}
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#ifndef _Stroika_Foundation_Traversal_Range_inl_
#define _Stroika_Foundation_Traversal_Range_inl_

#include    "../Debug/Assertions.h"
#include    "../Math/Overlap.h"

namespace   Stroika {
    namespace   Foundation {
        namespace   Traversal {

            /*
             ********************************************************************************
             RangeTraits::ExplicitRangeTraits_Integral<T, MIN, MAX, LOWER_BOUND_OPEN, UPPER_BOUND_OPEN, SIGNED_DIFF_TYPE, UNSIGNED_DIFF_TYPE>
             ********************************************************************************
             */
#if     qCompilerAndStdLib_constexpr_Buggy
            template    <typename T, T MIN, T MAX , Openness LOWER_BOUND_OPEN, Openness UPPER_BOUND_OPEN, typename SIGNED_DIFF_TYPE, typename UNSIGNED_DIFF_TYPE>
            const T RangeTraits::ExplicitRangeTraits_Integral<T, MIN, MAX, LOWER_BOUND_OPEN, UPPER_BOUND_OPEN, SIGNED_DIFF_TYPE, UNSIGNED_DIFF_TYPE>::kLowerBound   =   MIN;
            template    <typename T, T MIN, T MAX , Openness LOWER_BOUND_OPEN, Openness UPPER_BOUND_OPEN, typename SIGNED_DIFF_TYPE, typename UNSIGNED_DIFF_TYPE>
            const T RangeTraits::ExplicitRangeTraits_Integral<T, MIN, MAX, LOWER_BOUND_OPEN, UPPER_BOUND_OPEN, SIGNED_DIFF_TYPE, UNSIGNED_DIFF_TYPE>::kUpperBound   =   MAX;
#else
            template    <typename T, T MIN, T MAX , Openness LOWER_BOUND_OPEN, Openness UPPER_BOUND_OPEN, typename SIGNED_DIFF_TYPE, typename UNSIGNED_DIFF_TYPE>
            const T RangeTraits::ExplicitRangeTraits_Integral<T, MIN, MAX, LOWER_BOUND_OPEN, UPPER_BOUND_OPEN, SIGNED_DIFF_TYPE, UNSIGNED_DIFF_TYPE>::kLowerBound;
            template    <typename T, T MIN, T MAX , Openness LOWER_BOUND_OPEN, Openness UPPER_BOUND_OPEN, typename SIGNED_DIFF_TYPE, typename UNSIGNED_DIFF_TYPE>
            const T RangeTraits::ExplicitRangeTraits_Integral<T, MIN, MAX, LOWER_BOUND_OPEN, UPPER_BOUND_OPEN, SIGNED_DIFF_TYPE, UNSIGNED_DIFF_TYPE>::kUpperBound;
#endif

            /*
             ********************************************************************************
             ****************** RangeTraits::DefaultRangeTraits<T> **************************
             ********************************************************************************
             */
#if     qCompilerAndStdLib_constexpr_Buggy
            template    <typename T>
            const T RangeTraits::DefaultRangeTraits<T>::kLowerBound     =   numeric_limits<T>::lowest ();
            template    <typename T>
            const T RangeTraits::DefaultRangeTraits<T>::kUpperBound     =   numeric_limits<T>::max ();
#else
            template    <typename T>
            const T RangeTraits::DefaultRangeTraits<T>::kLowerBound;
            template    <typename T>
            const T RangeTraits::DefaultRangeTraits<T>::kUpperBound;
#endif

            /*
             ********************************************************************************
             ***************************** Range<T, TRAITS> *********************************
             ********************************************************************************
             */
            template    <typename T, typename TRAITS>
#if     !qCompilerAndStdLib_constexpr_Buggy
            constexpr
#endif
            inline  Range<T, TRAITS>::Range ()
                : Range (TRAITS::kLowerBoundOpenness, TRAITS::kUpperBoundOpenness)
            {
#if     !qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                Ensure (empty ());
#endif
            }
            template    <typename T, typename TRAITS>
            template    <typename T2, typename TRAITS2>
#if     !qCompilerAndStdLib_constexpr_Buggy
            constexpr
#endif
            inline  Range<T, TRAITS>::Range (const Range<T2, TRAITS>& src)
                : Range (src.GetLowerBound (), src.GetUpperBound (), src.GetLowerBoundOpenness (), src.GetUpperBoundOpenness ())
            {
            }
            template    <typename T, typename TRAITS>
#if     !qCompilerAndStdLib_constexpr_Buggy
            constexpr
#endif
            inline  Range<T, TRAITS>::Range (const T& begin, const T& end)
                : Range (begin, end, TRAITS::kLowerBoundOpenness, TRAITS::kUpperBoundOpenness)
            {
            }
            template    <typename T, typename TRAITS>
            inline  Range<T, TRAITS>::Range (const Memory::Optional<T>& begin, const Memory::Optional<T>& end)
                : Range (begin.IsPresent () ? *begin : TRAITS::kLowerBound, end.IsPresent () ? *end : TRAITS::kUpperBound, TRAITS::kLowerBoundOpenness, TRAITS::kUpperBoundOpenness)
            {
            }
            template    <typename T, typename TRAITS>
#if     !qCompilerAndStdLib_constexpr_Buggy
            constexpr
#endif
            inline  Range<T, TRAITS>::Range (Openness lhsOpen, Openness rhsOpen)
                : fBegin_ (TRAITS::kUpperBound)
                , fEnd_ (TRAITS::kLowerBound)
                , fBeginOpenness_ (lhsOpen)
                , fEndOpenness_ (rhsOpen)
            {
#if     !qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                Ensure (empty ());
#endif
            }
            template    <typename T, typename TRAITS>
#if     !qCompilerAndStdLib_constexpr_Buggy
            constexpr
#endif
            inline  Range<T, TRAITS>::Range (const T& begin, const T& end, Openness lhsOpen, Openness rhsOpen)
                : fBegin_ (begin)
                , fEnd_ (end)
                , fBeginOpenness_ (lhsOpen)
                , fEndOpenness_ (rhsOpen)
            {
#if     !qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                Require  (TRAITS::kLowerBound <= TRAITS::kUpperBound);    // always required for class
                Require (TRAITS::kLowerBound <= begin);
                Require (begin <= end);
                Require (end <= TRAITS::kUpperBound);
#endif
            }
            template    <typename T, typename TRAITS>
            inline  Range<T, TRAITS>::Range (const Memory::Optional<T>& begin, const Memory::Optional<T>& end, Openness lhsOpen, Openness rhsOpen)
                : Range (begin.IsPresent () ? *begin : TRAITS::kLowerBound, end.IsPresent () ? *end : TRAITS::kUpperBound, lhsOpen, rhsOpen)
            {
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   Range<T, TRAITS>    Range<T, TRAITS>::FullRange ()
            {
                return Range<T, TRAITS> (
                           TraitsType::kLowerBound, TraitsType::kUpperBound,
                           TraitsType::kLowerBoundOpenness, TraitsType::kUpperBoundOpenness
                       );
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   bool    Range<T, TRAITS>::empty () const
            {
#if     qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                return
                    fBegin_ > fEnd_ ?
                    true :
                    ((fBegin_ == fEnd_) ?
                     (fBeginOpenness_ == Openness::eOpen and fEndOpenness_ == Openness::eOpen) :
                     false
                    )
                    ;
#else
                if (fBegin_ > fEnd_) {
                    // internal hack done in Range<T, TRAITS>::Range() - empty range - otherwise not possible to create this situation
                    return true;
                }
                else if (fBegin_ == fEnd_) {
                    return fBeginOpenness_ == Openness::eOpen and fEndOpenness_ == Openness::eOpen;
                }
                return false;
#endif
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   typename Range<T, TRAITS>::UnsignedDifferenceType    Range<T, TRAITS>::GetDistanceSpanned () const
            {
#if     qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                return
                    empty () ?
                    static_cast<UnsignedDifferenceType> (0) :
                    (fEnd_ - fBegin_)
                    ;
#else
                if (empty ()) {
                    return static_cast<UnsignedDifferenceType> (0);
                }
                return fEnd_ - fBegin_;
#endif
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   T    Range<T, TRAITS>::GetMidpoint () const
            {
#if     !qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                Require (not empty ());
#endif
                return GetLowerBound () + GetDistanceSpanned () / 2;
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   bool    Range<T, TRAITS>::Contains (const T& r) const
            {
#if     qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                return
                    empty () ?
                    false :
                    (
                        (fBegin_ < r and r < fEnd_) or
                        (fBeginOpenness_ == Openness::eClosed and r == fBegin_) or
                        (fEndOpenness_ == Openness::eClosed and r == fEnd_)
                    )
                    ;
#else
                if (empty ()) {
                    return false;
                }
                if (fBegin_ < r and r < fEnd_) {
                    return true;
                }
                if (fBeginOpenness_ == Openness::eClosed and r == fBegin_) {
                    return true;
                }
                if (fEndOpenness_ == Openness::eClosed and r == fEnd_) {
                    return true;
                }
                return false;
#endif
            }
            template    <typename T, typename TRAITS>
            template    <typename T2, typename TRAITS2>
            inline  bool    Range<T, TRAITS>::Equals (const Range<T2, TRAITS2>& rhs) const
            {
                if (empty ()) {
                    return rhs.empty ();
                }
                return fBegin_ == rhs.fBegin_ and fEnd_ == rhs.fEnd_ and fBeginOpenness_ == rhs.fBeginOpenness_ and fBeginOpenness_ == rhs.fBeginOpenness_;
            }
#if 0
            template    <typename T, typename TRAITS>
            bool    Range<T, TRAITS>::Overlaps (const Range<T, TRAITS>& rhs) const
            {
                /*
                 *  @todo   RETHINK - because Range has semantics of exclude end - make sure overlap usuage
                 *          here is correct??? Unsure -- LGP 2013-07-05
                 */
                return Math::Overlaps (
                           pair<T, T> (fBegin_, fEnd_),
                           pair<T, T> (rhs.fBegin_, rhs.fEnd_)
                       );
            }
#endif
            template    <typename T, typename TRAITS>
            template    <typename T2, typename TRAITS2>
            bool    Range<T, TRAITS>::Intersects (const Range<T2, TRAITS2>& rhs) const
            {
                if (empty () or rhs.empty ()) {
                    return false;
                }
                T   l   =   max (fBegin_, rhs.GetLowerBound ());
                T   r   =   min (fEnd_, rhs.GetUpperBound ());
                if (l < r) {
                    return true;
                }
                else if (l == r) {
                    // must check if the end that has 'l' for each Range that that end is closed. Contains()
                    // is a shortcut for that
                    return Contains (l) and rhs.Contains (l);
                }
                else {
                    return false;
                }
            }
            template    <typename T, typename TRAITS>
            Range<T, TRAITS> Range<T, TRAITS>::Intersection (const Range<T, TRAITS>& rhs) const
            {
                if (empty () or rhs.empty ()) {
                    return Range ();
                }
                T   l   =   max (fBegin_, rhs.fBegin_);
                T   r   =   min (fEnd_, rhs.fEnd_);
                if (l <= r) {
                    // lhs/rhs ends are closed iff BOTH lhs/rhs contains that point
                    Openness lhsO = Contains (l) and rhs.Contains (l) ? Openness::eClosed : Openness::eOpen;
                    Openness rhsO = Contains (r) and rhs.Contains (r) ? Openness::eClosed : Openness::eOpen;
                    return Range<T, TRAITS> (l, r, lhsO, rhsO);
                }
                else {
                    return Range ();
                }
            }
            template    <typename T, typename TRAITS>
            Range<T, TRAITS> Range<T, TRAITS>::UnionBounds (const Range<T, TRAITS>& rhs) const
            {
                if (empty ()) {
                    return rhs;
                }
                if (rhs.empty ()) {
                    return *this;
                }
                T   l   =   min (GetLowerBound (), rhs.GetLowerBound ());
                T   r   =   max (GetUpperBound (), rhs.GetUpperBound ());
                Range<T, TRAITS>   result;
                if (l <= r) {
                    // lhs/rhs ends are closed iff BOTH lhs/rhs contains that point
                    Openness lhsO = Contains (l) and rhs.Contains (l) ? Openness::eClosed : Openness::eOpen;
                    Openness rhsO = Contains (r) and rhs.Contains (r) ? Openness::eClosed : Openness::eOpen;
                    result = Range<T, TRAITS> (l, r, lhsO, rhsO);
                }
                Ensure (result.GetLowerBound () <= GetLowerBound ());
                Ensure (result.GetLowerBound () <= GetUpperBound ());
                Ensure (result.GetLowerBound () <= rhs.GetLowerBound ());
                Ensure (result.GetLowerBound () <= rhs.GetUpperBound ());
                Ensure (result.GetUpperBound () >= GetLowerBound ());
                Ensure (result.GetUpperBound () >= GetUpperBound ());
                Ensure (result.GetUpperBound () >= rhs.GetLowerBound ());
                Ensure (result.GetUpperBound () >= rhs.GetUpperBound ());
                return result;
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   T    Range<T, TRAITS>::GetLowerBound () const
            {
#if     !qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                Require (not empty ());
#endif
                return fBegin_;
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   Openness    Range<T, TRAITS>::GetLowerBoundOpenness () const
            {
                return fBeginOpenness_;
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   T    Range<T, TRAITS>::GetUpperBound () const
            {
#if     !qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                Require (not empty ());
#endif
                return fEnd_;
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   Openness    Range<T, TRAITS>::GetUpperBoundOpenness () const
            {
                return fEndOpenness_;
            }
            template    <typename T, typename TRAITS>
            template    <typename... ARGS>
            inline  Characters::String  Range<T, TRAITS>::Format (ARGS&& ... args) const
            {
                if (GetLowerBound () == GetUpperBound ()) {
                    return GetLowerBound ().Format (forward<ARGS> (args)...);
                }
                else {
                    return GetLowerBound ().Format (forward<ARGS> (args)...) + L" - " + GetUpperBound  ().Format (forward<ARGS> (args)...);
                }
            }
            template    <typename T, typename TRAITS>
            inline  bool    Range<T, TRAITS>::operator== (const Range<T, TRAITS>& rhs) const
            {
                return Equals (rhs);
            }
            template    <typename T, typename TRAITS>
            inline  bool    Range<T, TRAITS>::operator!= (const Range<T, TRAITS>& rhs) const
            {
                return not Equals (rhs);
            }

        }
    }
}
#endif /* _Stroika_Foundation_Traversal_Range_inl_ */
<commit_msg>fixed regression in constexpr  code<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#ifndef _Stroika_Foundation_Traversal_Range_inl_
#define _Stroika_Foundation_Traversal_Range_inl_

#include    "../Debug/Assertions.h"
#include    "../Math/Overlap.h"

namespace   Stroika {
    namespace   Foundation {
        namespace   Traversal {

            /*
             ********************************************************************************
             RangeTraits::ExplicitRangeTraits_Integral<T, MIN, MAX, LOWER_BOUND_OPEN, UPPER_BOUND_OPEN, SIGNED_DIFF_TYPE, UNSIGNED_DIFF_TYPE>
             ********************************************************************************
             */
#if     qCompilerAndStdLib_constexpr_Buggy
            template    <typename T, T MIN, T MAX , Openness LOWER_BOUND_OPEN, Openness UPPER_BOUND_OPEN, typename SIGNED_DIFF_TYPE, typename UNSIGNED_DIFF_TYPE>
            const T RangeTraits::ExplicitRangeTraits_Integral<T, MIN, MAX, LOWER_BOUND_OPEN, UPPER_BOUND_OPEN, SIGNED_DIFF_TYPE, UNSIGNED_DIFF_TYPE>::kLowerBound   =   MIN;
            template    <typename T, T MIN, T MAX , Openness LOWER_BOUND_OPEN, Openness UPPER_BOUND_OPEN, typename SIGNED_DIFF_TYPE, typename UNSIGNED_DIFF_TYPE>
            const T RangeTraits::ExplicitRangeTraits_Integral<T, MIN, MAX, LOWER_BOUND_OPEN, UPPER_BOUND_OPEN, SIGNED_DIFF_TYPE, UNSIGNED_DIFF_TYPE>::kUpperBound   =   MAX;
#else
            template    <typename T, T MIN, T MAX , Openness LOWER_BOUND_OPEN, Openness UPPER_BOUND_OPEN, typename SIGNED_DIFF_TYPE, typename UNSIGNED_DIFF_TYPE>
            constexpr T RangeTraits::ExplicitRangeTraits_Integral<T, MIN, MAX, LOWER_BOUND_OPEN, UPPER_BOUND_OPEN, SIGNED_DIFF_TYPE, UNSIGNED_DIFF_TYPE>::kLowerBound;
            template    <typename T, T MIN, T MAX , Openness LOWER_BOUND_OPEN, Openness UPPER_BOUND_OPEN, typename SIGNED_DIFF_TYPE, typename UNSIGNED_DIFF_TYPE>
            constexpr T RangeTraits::ExplicitRangeTraits_Integral<T, MIN, MAX, LOWER_BOUND_OPEN, UPPER_BOUND_OPEN, SIGNED_DIFF_TYPE, UNSIGNED_DIFF_TYPE>::kUpperBound;
#endif

            /*
             ********************************************************************************
             ****************** RangeTraits::DefaultRangeTraits<T> **************************
             ********************************************************************************
             */
#if     qCompilerAndStdLib_constexpr_Buggy
            template    <typename T>
            const T RangeTraits::DefaultRangeTraits<T>::kLowerBound     =   numeric_limits<T>::lowest ();
            template    <typename T>
            const T RangeTraits::DefaultRangeTraits<T>::kUpperBound     =   numeric_limits<T>::max ();
#else
            template    <typename T>
            constexpr T RangeTraits::DefaultRangeTraits<T>::kLowerBound;
            template    <typename T>
            constexpr T RangeTraits::DefaultRangeTraits<T>::kUpperBound;
#endif

            /*
             ********************************************************************************
             ***************************** Range<T, TRAITS> *********************************
             ********************************************************************************
             */
            template    <typename T, typename TRAITS>
#if     !qCompilerAndStdLib_constexpr_Buggy
            constexpr
#endif
            inline  Range<T, TRAITS>::Range ()
                : Range (TRAITS::kLowerBoundOpenness, TRAITS::kUpperBoundOpenness)
            {
#if     !qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                Ensure (empty ());
#endif
            }
            template    <typename T, typename TRAITS>
            template    <typename T2, typename TRAITS2>
#if     !qCompilerAndStdLib_constexpr_Buggy
            constexpr
#endif
            inline  Range<T, TRAITS>::Range (const Range<T2, TRAITS>& src)
                : Range (src.GetLowerBound (), src.GetUpperBound (), src.GetLowerBoundOpenness (), src.GetUpperBoundOpenness ())
            {
            }
            template    <typename T, typename TRAITS>
#if     !qCompilerAndStdLib_constexpr_Buggy
            constexpr
#endif
            inline  Range<T, TRAITS>::Range (const T& begin, const T& end)
                : Range (begin, end, TRAITS::kLowerBoundOpenness, TRAITS::kUpperBoundOpenness)
            {
            }
            template    <typename T, typename TRAITS>
            inline  Range<T, TRAITS>::Range (const Memory::Optional<T>& begin, const Memory::Optional<T>& end)
                : Range (begin.IsPresent () ? *begin : TRAITS::kLowerBound, end.IsPresent () ? *end : TRAITS::kUpperBound, TRAITS::kLowerBoundOpenness, TRAITS::kUpperBoundOpenness)
            {
            }
            template    <typename T, typename TRAITS>
#if     !qCompilerAndStdLib_constexpr_Buggy
            constexpr
#endif
            inline  Range<T, TRAITS>::Range (Openness lhsOpen, Openness rhsOpen)
                : fBegin_ (TRAITS::kUpperBound)
                , fEnd_ (TRAITS::kLowerBound)
                , fBeginOpenness_ (lhsOpen)
                , fEndOpenness_ (rhsOpen)
            {
#if     !qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                Ensure (empty ());
#endif
            }
            template    <typename T, typename TRAITS>
#if     !qCompilerAndStdLib_constexpr_Buggy
            constexpr
#endif
            inline  Range<T, TRAITS>::Range (const T& begin, const T& end, Openness lhsOpen, Openness rhsOpen)
                : fBegin_ (begin)
                , fEnd_ (end)
                , fBeginOpenness_ (lhsOpen)
                , fEndOpenness_ (rhsOpen)
            {
#if     !qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                Require  (TRAITS::kLowerBound <= TRAITS::kUpperBound);    // always required for class
                Require (TRAITS::kLowerBound <= begin);
                Require (begin <= end);
                Require (end <= TRAITS::kUpperBound);
#endif
            }
            template    <typename T, typename TRAITS>
            inline  Range<T, TRAITS>::Range (const Memory::Optional<T>& begin, const Memory::Optional<T>& end, Openness lhsOpen, Openness rhsOpen)
                : Range (begin.IsPresent () ? *begin : TRAITS::kLowerBound, end.IsPresent () ? *end : TRAITS::kUpperBound, lhsOpen, rhsOpen)
            {
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   Range<T, TRAITS>    Range<T, TRAITS>::FullRange ()
            {
                return Range<T, TRAITS> (
                           TraitsType::kLowerBound, TraitsType::kUpperBound,
                           TraitsType::kLowerBoundOpenness, TraitsType::kUpperBoundOpenness
                       );
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   bool    Range<T, TRAITS>::empty () const
            {
#if     qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                return
                    fBegin_ > fEnd_ ?
                    true :
                    ((fBegin_ == fEnd_) ?
                     (fBeginOpenness_ == Openness::eOpen and fEndOpenness_ == Openness::eOpen) :
                     false
                    )
                    ;
#else
                if (fBegin_ > fEnd_) {
                    // internal hack done in Range<T, TRAITS>::Range() - empty range - otherwise not possible to create this situation
                    return true;
                }
                else if (fBegin_ == fEnd_) {
                    return fBeginOpenness_ == Openness::eOpen and fEndOpenness_ == Openness::eOpen;
                }
                return false;
#endif
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   typename Range<T, TRAITS>::UnsignedDifferenceType    Range<T, TRAITS>::GetDistanceSpanned () const
            {
#if     qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                return
                    empty () ?
                    static_cast<UnsignedDifferenceType> (0) :
                    (fEnd_ - fBegin_)
                    ;
#else
                if (empty ()) {
                    return static_cast<UnsignedDifferenceType> (0);
                }
                return fEnd_ - fBegin_;
#endif
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   T    Range<T, TRAITS>::GetMidpoint () const
            {
#if     !qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                Require (not empty ());
#endif
                return GetLowerBound () + GetDistanceSpanned () / 2;
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   bool    Range<T, TRAITS>::Contains (const T& r) const
            {
#if     qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                return
                    empty () ?
                    false :
                    (
                        (fBegin_ < r and r < fEnd_) or
                        (fBeginOpenness_ == Openness::eClosed and r == fBegin_) or
                        (fEndOpenness_ == Openness::eClosed and r == fEnd_)
                    )
                    ;
#else
                if (empty ()) {
                    return false;
                }
                if (fBegin_ < r and r < fEnd_) {
                    return true;
                }
                if (fBeginOpenness_ == Openness::eClosed and r == fBegin_) {
                    return true;
                }
                if (fEndOpenness_ == Openness::eClosed and r == fEnd_) {
                    return true;
                }
                return false;
#endif
            }
            template    <typename T, typename TRAITS>
            template    <typename T2, typename TRAITS2>
            inline  bool    Range<T, TRAITS>::Equals (const Range<T2, TRAITS2>& rhs) const
            {
                if (empty ()) {
                    return rhs.empty ();
                }
                return fBegin_ == rhs.fBegin_ and fEnd_ == rhs.fEnd_ and fBeginOpenness_ == rhs.fBeginOpenness_ and fBeginOpenness_ == rhs.fBeginOpenness_;
            }
#if 0
            template    <typename T, typename TRAITS>
            bool    Range<T, TRAITS>::Overlaps (const Range<T, TRAITS>& rhs) const
            {
                /*
                 *  @todo   RETHINK - because Range has semantics of exclude end - make sure overlap usuage
                 *          here is correct??? Unsure -- LGP 2013-07-05
                 */
                return Math::Overlaps (
                           pair<T, T> (fBegin_, fEnd_),
                           pair<T, T> (rhs.fBegin_, rhs.fEnd_)
                       );
            }
#endif
            template    <typename T, typename TRAITS>
            template    <typename T2, typename TRAITS2>
            bool    Range<T, TRAITS>::Intersects (const Range<T2, TRAITS2>& rhs) const
            {
                if (empty () or rhs.empty ()) {
                    return false;
                }
                T   l   =   max (fBegin_, rhs.GetLowerBound ());
                T   r   =   min (fEnd_, rhs.GetUpperBound ());
                if (l < r) {
                    return true;
                }
                else if (l == r) {
                    // must check if the end that has 'l' for each Range that that end is closed. Contains()
                    // is a shortcut for that
                    return Contains (l) and rhs.Contains (l);
                }
                else {
                    return false;
                }
            }
            template    <typename T, typename TRAITS>
            Range<T, TRAITS> Range<T, TRAITS>::Intersection (const Range<T, TRAITS>& rhs) const
            {
                if (empty () or rhs.empty ()) {
                    return Range ();
                }
                T   l   =   max (fBegin_, rhs.fBegin_);
                T   r   =   min (fEnd_, rhs.fEnd_);
                if (l <= r) {
                    // lhs/rhs ends are closed iff BOTH lhs/rhs contains that point
                    Openness lhsO = Contains (l) and rhs.Contains (l) ? Openness::eClosed : Openness::eOpen;
                    Openness rhsO = Contains (r) and rhs.Contains (r) ? Openness::eClosed : Openness::eOpen;
                    return Range<T, TRAITS> (l, r, lhsO, rhsO);
                }
                else {
                    return Range ();
                }
            }
            template    <typename T, typename TRAITS>
            Range<T, TRAITS> Range<T, TRAITS>::UnionBounds (const Range<T, TRAITS>& rhs) const
            {
                if (empty ()) {
                    return rhs;
                }
                if (rhs.empty ()) {
                    return *this;
                }
                T   l   =   min (GetLowerBound (), rhs.GetLowerBound ());
                T   r   =   max (GetUpperBound (), rhs.GetUpperBound ());
                Range<T, TRAITS>   result;
                if (l <= r) {
                    // lhs/rhs ends are closed iff BOTH lhs/rhs contains that point
                    Openness lhsO = Contains (l) and rhs.Contains (l) ? Openness::eClosed : Openness::eOpen;
                    Openness rhsO = Contains (r) and rhs.Contains (r) ? Openness::eClosed : Openness::eOpen;
                    result = Range<T, TRAITS> (l, r, lhsO, rhsO);
                }
                Ensure (result.GetLowerBound () <= GetLowerBound ());
                Ensure (result.GetLowerBound () <= GetUpperBound ());
                Ensure (result.GetLowerBound () <= rhs.GetLowerBound ());
                Ensure (result.GetLowerBound () <= rhs.GetUpperBound ());
                Ensure (result.GetUpperBound () >= GetLowerBound ());
                Ensure (result.GetUpperBound () >= GetUpperBound ());
                Ensure (result.GetUpperBound () >= rhs.GetLowerBound ());
                Ensure (result.GetUpperBound () >= rhs.GetUpperBound ());
                return result;
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   T    Range<T, TRAITS>::GetLowerBound () const
            {
#if     !qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                Require (not empty ());
#endif
                return fBegin_;
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   Openness    Range<T, TRAITS>::GetLowerBoundOpenness () const
            {
                return fBeginOpenness_;
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   T    Range<T, TRAITS>::GetUpperBound () const
            {
#if     !qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                Require (not empty ());
#endif
                return fEnd_;
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   Openness    Range<T, TRAITS>::GetUpperBoundOpenness () const
            {
                return fEndOpenness_;
            }
            template    <typename T, typename TRAITS>
            template    <typename... ARGS>
            inline  Characters::String  Range<T, TRAITS>::Format (ARGS&& ... args) const
            {
                if (GetLowerBound () == GetUpperBound ()) {
                    return GetLowerBound ().Format (forward<ARGS> (args)...);
                }
                else {
                    return GetLowerBound ().Format (forward<ARGS> (args)...) + L" - " + GetUpperBound  ().Format (forward<ARGS> (args)...);
                }
            }
            template    <typename T, typename TRAITS>
            inline  bool    Range<T, TRAITS>::operator== (const Range<T, TRAITS>& rhs) const
            {
                return Equals (rhs);
            }
            template    <typename T, typename TRAITS>
            inline  bool    Range<T, TRAITS>::operator!= (const Range<T, TRAITS>& rhs) const
            {
                return not Equals (rhs);
            }

        }
    }
}
#endif /* _Stroika_Foundation_Traversal_Range_inl_ */
<|endoftext|>


<commit_before>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Language:  C++
Date:      $Date: 2010-03-15 11:12:36 +0100 (Mo, 15 Mrz 2010) $
Version:   $Revision: 21745 $

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "mitkTestingMacros.h"
#include "mitkPlanarPolygon.h"
#include "mitkPlaneGeometry.h"

class mitkPlanarPolygonTestClass
{

public:

static void TestPlanarPolygonPlacement( mitk::PlanarPolygon::Pointer planarPolygon )
{
  // Test for correct minimum number of control points in cross-mode
  MITK_TEST_CONDITION( planarPolygon->GetMinimumNumberOfControlPoints() == 2, "Minimum number of control points" );

  // Test for correct maximum number of control points in cross-mode
  MITK_TEST_CONDITION( planarPolygon->GetMaximumNumberOfControlPoints() == 1000, "Maximum number of control points" );

  // Initial placement of PlanarPolygon
  mitk::Point2D p0;
  p0[0] = 00.0; p0[1] = 0.0;
  planarPolygon->PlaceFigure( p0 );

  // Add second control point
  mitk::Point2D p1;
  p1[0] = 50.0; p1[1] = 00.0;
  planarPolygon->SetControlPoint(1, p1 );

  // Add third control point
  mitk::Point2D p2;
  p2[0] = 50.0; p2[1] = 50.0;
  planarPolygon->AddControlPoint( p2 );

  // Add fourth control point
  mitk::Point2D p3;
  p3[0] = 0.0; p3[1] = 50.0;
  planarPolygon->AddControlPoint( p3 );

  // Test for number of control points
  MITK_TEST_CONDITION( planarPolygon->GetNumberOfControlPoints() == 4, "Number of control points after placement" );

  // Test if PlanarFigure is closed
  MITK_TEST_CONDITION( planarPolygon->IsClosed(), "planar polygon should not be closed, yet, right?" );

  planarPolygon->SetClosed(true);

  MITK_TEST_CONDITION( planarPolygon->IsClosed(), "planar polygon should be closed after function call, right?" );

  // Test for number of polylines
  const mitk::PlanarFigure::VertexContainerType* polyLine0 = planarPolygon->GetPolyLine( 0 );
  MITK_TEST_CONDITION( planarPolygon->GetPolyLinesSize() == 1, "Number of polylines after placement" );

  // Get polylines and check if the generated coordinates are OK
  const mitk::Point2D& pp0 = polyLine0->ElementAt( 0 );
  const mitk::Point2D& pp1 = polyLine0->ElementAt( 1 );
  MITK_TEST_CONDITION( ((pp0 == p0) && (pp1 == p1))
    || ((pp0 == p1) && (pp1 == p0)), "Correct polyline 1" );

  // Test for number of measurement features
  planarPolygon->EvaluateFeatures();
  MITK_TEST_CONDITION( planarPolygon->GetNumberOfFeatures() == 2, "Number of measurement features" );

  // Test for correct feature evaluation
  double length0 = 4 * 50.0; // circumference
  MITK_TEST_CONDITION( fabs( planarPolygon->GetQuantity( 0 ) - length0) < mitk::eps, "Size of longest diameter" );

  double length1 = 50.0 * 50.0 ; // area
  MITK_TEST_CONDITION( fabs( planarPolygon->GetQuantity( 1 ) - length1) < mitk::eps, "Size of short axis diameter" );
}

/**
 * mitkplanarPolygonTest tests the methods and behavior of mitk::PlanarPolygon with sub-tests:
 *
 * 1. Instantiation and basic tests, including feature evaluation
 *
 */
int mitkPlanarPolygonTest(int /* argc */, char* /*argv*/[])
{
  // always start with this!
  MITK_TEST_BEGIN("planarPolygon")

  // create PlaneGeometry on which to place the planarPolygon
  mitk::PlaneGeometry::Pointer planeGeometry = mitk::PlaneGeometry::New();
  planeGeometry->InitializeStandardPlane( 100.0, 100.0 );

  // **************************************************************************
  // 1. Instantiation and basic tests, including feature evaluation
  mitk::PlanarPolygon::Pointer planarPolygon = mitk::PlanarPolygon::New();
  planarPolygon->SetGeometry2D( planeGeometry );

  // first test: did this work?
  MITK_TEST_CONDITION_REQUIRED( planarPolygon.IsNotNull(), "Testing instantiation" );

  // Test placement of planarPolygon by control points
  mitkPlanarPolygonTestClass::TestPlanarPolygonPlacement( planarPolygon );

  // always end with this!
  MITK_TEST_END()
}
<commit_msg>COMP: typo<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Language:  C++
Date:      $Date: 2010-03-15 11:12:36 +0100 (Mo, 15 Mrz 2010) $
Version:   $Revision: 21745 $

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "mitkTestingMacros.h"
#include "mitkPlanarPolygon.h"
#include "mitkPlaneGeometry.h"

class mitkPlanarPolygonTestClass
{

public:

static void TestPlanarPolygonPlacement( mitk::PlanarPolygon::Pointer planarPolygon )
{
  // Test for correct minimum number of control points in cross-mode
  MITK_TEST_CONDITION( planarPolygon->GetMinimumNumberOfControlPoints() == 2, "Minimum number of control points" );

  // Test for correct maximum number of control points in cross-mode
  MITK_TEST_CONDITION( planarPolygon->GetMaximumNumberOfControlPoints() == 1000, "Maximum number of control points" );

  // Initial placement of PlanarPolygon
  mitk::Point2D p0;
  p0[0] = 00.0; p0[1] = 0.0;
  planarPolygon->PlaceFigure( p0 );

  // Add second control point
  mitk::Point2D p1;
  p1[0] = 50.0; p1[1] = 00.0;
  planarPolygon->SetControlPoint(1, p1 );

  // Add third control point
  mitk::Point2D p2;
  p2[0] = 50.0; p2[1] = 50.0;
  planarPolygon->AddControlPoint( p2 );

  // Add fourth control point
  mitk::Point2D p3;
  p3[0] = 0.0; p3[1] = 50.0;
  planarPolygon->AddControlPoint( p3 );

  // Test for number of control points
  MITK_TEST_CONDITION( planarPolygon->GetNumberOfControlPoints() == 4, "Number of control points after placement" );

  // Test if PlanarFigure is closed
  MITK_TEST_CONDITION( planarPolygon->IsClosed(), "planar polygon should not be closed, yet, right?" );

  planarPolygon->SetClosed(true);

  MITK_TEST_CONDITION( planarPolygon->IsClosed(), "planar polygon should be closed after function call, right?" );

  // Test for number of polylines
  const mitk::PlanarFigure::VertexContainerType* polyLine0 = planarPolygon->GetPolyLine( 0 );
  MITK_TEST_CONDITION( planarPolygon->GetPolyLinesSize() == 1, "Number of polylines after placement" );

  // Get polylines and check if the generated coordinates are OK
  const mitk::Point2D& pp0 = polyLine0->ElementAt( 0 );
  const mitk::Point2D& pp1 = polyLine0->ElementAt( 1 );
  MITK_TEST_CONDITION( ((pp0 == p0) && (pp1 == p1))
    || ((pp0 == p1) && (pp1 == p0)), "Correct polyline 1" );

  // Test for number of measurement features
  planarPolygon->EvaluateFeatures();
  MITK_TEST_CONDITION( planarPolygon->GetNumberOfFeatures() == 2, "Number of measurement features" );

  // Test for correct feature evaluation
  double length0 = 4 * 50.0; // circumference
  MITK_TEST_CONDITION( fabs( planarPolygon->GetQuantity( 0 ) - length0) < mitk::eps, "Size of longest diameter" );

  double length1 = 50.0 * 50.0 ; // area
  MITK_TEST_CONDITION( fabs( planarPolygon->GetQuantity( 1 ) - length1) < mitk::eps, "Size of short axis diameter" );
}
};
/**
 * mitkplanarPolygonTest tests the methods and behavior of mitk::PlanarPolygon with sub-tests:
 *
 * 1. Instantiation and basic tests, including feature evaluation
 *
 */
int mitkPlanarPolygonTest(int /* argc */, char* /*argv*/[])
{
  // always start with this!
  MITK_TEST_BEGIN("planarPolygon")

  // create PlaneGeometry on which to place the planarPolygon
  mitk::PlaneGeometry::Pointer planeGeometry = mitk::PlaneGeometry::New();
  planeGeometry->InitializeStandardPlane( 100.0, 100.0 );

  // **************************************************************************
  // 1. Instantiation and basic tests, including feature evaluation
  mitk::PlanarPolygon::Pointer planarPolygon = mitk::PlanarPolygon::New();
  planarPolygon->SetGeometry2D( planeGeometry );

  // first test: did this work?
  MITK_TEST_CONDITION_REQUIRED( planarPolygon.IsNotNull(), "Testing instantiation" );

  // Test placement of planarPolygon by control points
  mitkPlanarPolygonTestClass::TestPlanarPolygonPlacement( planarPolygon );

  // always end with this!
  MITK_TEST_END();
}
<|endoftext|>