<commit_before>#include "Manager.h"
#include <RuntimeObjectSystem.h>
#include "StdioLogSystem.h"
#include <boost/filesystem.hpp>
#include "nodes/Node.h"
#include <stdarg.h>
#include <assert.h>
#include <iostream>
#include <boost/property_tree/xml_parser.hpp>
//#include <IObjectUtils.h>
using namespace EagleLib;

#ifdef _WIN32
    #include "Windows.h"
    #pragma warning( disable : 4996 4800 )
#endif

void CompileLogger::log(int level, const char *format, va_list args)
{
    int result = vsnprintf(m_buff, LOGSYSTEM_MAX_BUFFER-1, format, args);
    // Make sure there's a limit to the amount of rubbish we can output
    m_buff[LOGSYSTEM_MAX_BUFFER-1] = '\0';
    if(callback)
        callback(std::string(m_buff), level);
    std::cout << m_buff;
#ifdef _WIN32
    OutputDebugStringA( m_buff );
#endif
}

void CompileLogger::LogError(const char * format, ...)
{
    va_list args;
    va_start(args, format);
    log(2, format, args);
}

void CompileLogger::LogWarning(const char * format, ...)
{
    va_list args;
    va_start(args, format);
    log(1, format, args);
}

void CompileLogger::LogInfo(const char * format, ...)
{
    va_list args;
    va_start(args, format);
    log(0, format, args);
}
bool TestCallback::TestBuildCallback(const char* file, TestBuildResult type)
{
    bool success = true;
    switch(type)
    {
        case TESTBUILDRRESULT_SUCCESS:
            std::cout << "TESTBUILDRRESULT_SUCCESS - ";
            break;
        case TESTBUILDRRESULT_NO_FILES_TO_BUILD:
            std::cout << "TESTBUILDRRESULT_NO_FILES_TO_BUILD - ";
            success = false;
            break;
        case TESTBUILDRRESULT_BUILD_FILE_GONE:
            std::cout << "TESTBUILDRRESULT_BUILD_FILE_GONE - ";
            success = false;
            break;
        case TESTBUILDRRESULT_BUILD_NOT_STARTED:
            std::cout << "TESTBUILDRRESULT_BUILD_NOT_STARTED - ";
            success = false;
            break;
        case TESTBUILDRRESULT_BUILD_FAILED:
            std::cout << "TESTBUILDRRESULT_BUILD_FAILED - ";
            success = false;
            break;
        case TESTBUILDRRESULT_OBJECT_SWAP_FAIL:
            std::cout << "TESTBUILDRRESULT_OBJECT_SWAP_FAIL - ";
            success = false;
            break;
    }
    std::cout << file << std::endl;
    return success;
}

bool TestCallback::TestBuildWaitAndUpdate()
{
    boost::this_thread::sleep_for(boost::chrono::milliseconds(10));
    return true;
}

NodeManager& NodeManager::getInstance()
{
	static NodeManager instance;
	return instance;
}

NodeManager::NodeManager()
{
    Init();

}

NodeManager::~NodeManager()
{

}

bool
NodeManager::Init()
{
    testCallback = nullptr;
    m_pRuntimeObjectSystem.reset(new RuntimeObjectSystem);
    m_pCompileLogger.reset(new CompileLogger());
    m_pRuntimeObjectSystem->Initialise(m_pCompileLogger.get(), nullptr);
    m_pRuntimeObjectSystem->GetObjectFactorySystem()->AddListener(this);
    boost::filesystem::path workingDir(__FILE__);
    std::string includePath = workingDir.parent_path().parent_path().string();
#ifdef _MSC_VER

#else
    m_pRuntimeObjectSystem->SetAdditionalCompileOptions("-std=c++11");
#endif
    includePath += "/include";
    m_pRuntimeObjectSystem->AddIncludeDir(includePath.c_str());
	m_pRuntimeObjectSystem->AddIncludeDir(BOOST_INCLUDES);
	m_pRuntimeObjectSystem->AddIncludeDir(OPENCV_INCLUDES);
    m_pRuntimeObjectSystem->AddIncludeDir(CUDA_INCLUDES);

	m_pRuntimeObjectSystem->AddLibraryDir(BOOST_LIB_DIR);
	m_pRuntimeObjectSystem->AddLibraryDir(OPENCV_LIB_DIR);
    m_pRuntimeObjectSystem->AddLibraryDir(CUDA_LIB_DIR);
#ifdef BINARY_DIR
	m_pRuntimeObjectSystem->AddLibraryDir(BINARY_DIR);
#endif
#ifdef HAVE_PCL
    //m_pRuntimeObjectSystem->AddLibraryDir(PCL_LIB_DIR);
    m_pRuntimeObjectSystem->AddIncludeDir(PCL_INCLUDES);
#endif
	return true;
}

bool
NodeManager::MainLoop()
{
	return true;
}

void
NodeManager::OnConstructorsAdded()
{
	AUDynArray<IObjectConstructor*> constructors;
	m_pRuntimeObjectSystem->GetObjectFactorySystem()->GetAll(constructors);
	std::vector<Node*> newNodes;
	for (int i = 0; i < constructors.Size(); ++i)
	{
		int numObjects = constructors[i]->GetNumberConstructedObjects();
		for (int j = 0; j < numObjects; ++j)
		{
			auto ptr = constructors[i]->GetConstructedObject(j);
			ptr = ptr->GetInterface(IID_NodeObject);
			if (ptr)
			{
                auto nodePtr = static_cast<Node*>(ptr);
                //m_nodeTree.put(t_nodeTree::path_type{nodePtr->fullTreeName,'.'}, nodePtr);
				newNodes.push_back(nodePtr);
			}
		}
	}
	for (int i = 0; i < newNodes.size(); ++i)
	{
		for (int j = 0; j < newNodes[i]->parameters.size(); ++j)
		{
			newNodes[i]->parameters[j]->setSource(std::string());
		}
	}
}

shared_ptr<Node> NodeManager::addNode(const std::string &nodeName)
{

    IObjectConstructor* pConstructor = m_pRuntimeObjectSystem->GetObjectFactorySystem()->GetConstructor(nodeName.c_str());

    if(pConstructor)
    {
        IObject* pObj = pConstructor->Construct();
        IObject* interface = pObj->GetInterface(IID_NodeObject);

        if(interface)
        {
            Node* node = static_cast<Node*>(interface);
            node->Init(true);
            nodes.push_back(weak_ptr<Node>(node));
            return Node::Ptr(node);
        }else
        {
            // Input nodename is a compatible object but it is not a node
            return shared_ptr<Node>();
        }
    }else
    {
        // Invalid nodeName
        return shared_ptr<Node>();
    }
    return shared_ptr<Node>();
}
std::vector<shared_ptr<Node>> NodeManager::loadNodes(const std::string& saveFile)
{
    cv::FileStorage fs;
    try
    {
        fs.open(saveFile, cv::FileStorage::READ);
    }catch(cv::Exception &e)
    {
        std::cout << e.what() << std::endl;
    }

    int nodeCount = (int)fs["TopLevelNodeCount"];
    std::vector<shared_ptr<Node>> nodes;
    nodes.reserve(nodeCount);
    for(int i = 0;i < nodeCount; ++i)
    {
        auto nodeFS = fs["Node-" + boost::lexical_cast<std::string>(i)];
        std::string name = (std::string)nodeFS["NodeName"];
        Node::Ptr node = addNode(name);
        node->Init(nodeFS);
        nodes.push_back(node);
    }
    return nodes;
}

void NodeManager::saveNodes(std::vector<shared_ptr<Node>>& topLevelNodes, const std::string& fileName)
{
    cv::FileStorage fs;
    fs.open(fileName, cv::FileStorage::WRITE);
    fs << "TopLevelNodeCount" << (int)topLevelNodes.size();

    for(int i = 0; i < topLevelNodes.size(); ++i)
    {
        fs << "Node-" + boost::lexical_cast<std::string>(i) << "{";
        topLevelNodes[i]->Serialize(fs);
        fs << "}";
    }
    fs.release();
}

bool NodeManager::removeNode(const std::string& nodeName)
{

    return false;
}

bool NodeManager::removeNode(ObjectId oid)
{
 /*   Node* node =getNode(oid);
    if(node == nullptr)
        return false;
    auto path = node->fullTreeName;
    // First we need to get the parent property tree node.
    /////// GRRRRR I've tried everything but I can't get the property tree to delete the node.
    saveTree("test.xml");
    auto idx = path.find_last_of(".");
    auto parentPath = path.substr(0, idx);
    auto parentNode = m_nodeTree.get_child(parentPath);
    for(auto it = parentNode.begin(); it != parentNode.end(); ++it)
    {
        if(it->second.get_value<Node*>() == node)
        {
            parentNode.erase(it);
            break;
        }
    }
    saveTree("test.xml");
    delete m_pRuntimeObjectSystem->GetObjectFactorySystem()->GetConstructor(oid.m_ConstructorId)->GetConstructedObject(oid.m_PerTypeId);
    return true;*/
	return false;
}

void
NodeManager::addConstructors(IAUDynArray<IObjectConstructor*> & constructors)
{
    m_pRuntimeObjectSystem->GetObjectFactorySystem()->AddConstructors(constructors);
}
void
NodeManager::setupModule(IPerModuleInterface* pPerModuleInterface)
{
	m_pRuntimeObjectSystem->SetupObjectConstructors(pPerModuleInterface);
}
bool
NodeManager::CheckRecompile()
{
	static boost::posix_time::ptime prevTime = boost::posix_time::microsec_clock::universal_time();
	boost::posix_time::ptime currentTime = boost::posix_time::microsec_clock::universal_time();
	boost::posix_time::time_duration delta = currentTime - prevTime;
    // Prevent checking too often
    if(delta.total_milliseconds() < 10)
        return false;
    prevTime = currentTime;
    if( m_pRuntimeObjectSystem->GetIsCompiledComplete())
    {
        m_pRuntimeObjectSystem->LoadCompiledModule();
    }
    if(m_pRuntimeObjectSystem->GetIsCompiling())
    {
       return true;
    }else
    {
        m_pRuntimeObjectSystem->GetFileChangeNotifier()->Update(float(delta.total_milliseconds())/1000.0);
    }
    return false;
}

void NodeManager::saveTree(const std::string &fileName)
{

}

bool
NodeManager::CheckRecompile(bool swapAllowed)
{
    static boost::posix_time::ptime prevTime = boost::posix_time::microsec_clock::universal_time();
    boost::posix_time::ptime currentTime = boost::posix_time::microsec_clock::universal_time();
    boost::posix_time::time_duration delta = currentTime - prevTime;
    // Prevent checking too often
    if(delta.total_milliseconds() < 10)
        return false;
    prevTime = currentTime;
    if( m_pRuntimeObjectSystem->GetIsCompiledComplete() && swapAllowed)
    {
        m_pRuntimeObjectSystem->LoadCompiledModule();
    }
    if(m_pRuntimeObjectSystem->GetIsCompiling())
    {
       return true;
    }else
    {
        m_pRuntimeObjectSystem->GetFileChangeNotifier()->Update(float(delta.total_milliseconds())/1000.0);
    }
    return false;
}
bool NodeManager::TestRuntimeCompilation()
{
    if(testCallback == nullptr)
        testCallback = new TestCallback();
    m_pRuntimeObjectSystem->TestBuildAllRuntimeHeaders(testCallback,true);
    m_pRuntimeObjectSystem->TestBuildAllRuntimeSourceFiles(testCallback, true);
}

void
NodeManager::onNodeRecompile(Node *node)
{
    deletedNodes.push_back(node);
    deletedNodeIDs.push_back(node->m_OID);
}

Node*
NodeManager::getNode(const ObjectId& id)
{
    AUDynArray<IObjectConstructor*> constructors;
    m_pRuntimeObjectSystem->GetObjectFactorySystem()->GetAll(constructors);
    if(!id.IsValid())
        return nullptr;
    if(id.m_ConstructorId >= constructors.Size())
        return nullptr;
    if(id.m_PerTypeId >= constructors[id.m_ConstructorId]->GetNumberConstructedObjects())
        return nullptr;
    IObject* pObj = constructors[id.m_ConstructorId]->GetConstructedObject(id.m_PerTypeId);
    if(!pObj)
        return nullptr;
    pObj = pObj->GetInterface(IID_NodeObject);
    if(!pObj)
        return nullptr;
    return static_cast<Node*>(pObj);
}

Node*
NodeManager::getNode(const std::string &treeName)
{
    return nullptr;
}

void
NodeManager::updateTreeName(Node* node, const std::string& prevTreeName)
{
    /*m_nodeTree.put(t_nodeTree::path_type{ node->fullTreeName, '.' }, node);
    m_nodeTree.erase(prevTreeName);*/
}

void
NodeManager::addParameters(Node* node)
{
	for (int i = 0; i < node->parameters.size(); ++i)
	{

	}
}

boost::shared_ptr< Parameter >
NodeManager::getParameter(const std::string& name)
{
	// Strip off the path for the node
	auto idx = name.find(':');
	std::string parameterName = name.substr(idx+1);
	auto node = getNode(name.substr(0, idx));
    if(node == nullptr)
        return Parameter::Ptr();
	return node->getParameter(parameterName);
}

void
NodeManager::getSiblingNodes(const std::string& sourceNode, std::vector<Node*>& output)
{
    /*auto nodePtr = getParent(sourceNode);
	if (!nodePtr)
		return;

	auto node = m_nodeTree.get_child(getParent(sourceNode)->fullTreeName);
	for (auto itr = node.begin(); itr != node.end(); ++itr)
	{
		output.push_back(itr->second.get_value<Node*>());
    }*/
}
void NodeManager::setCompileCallback(boost::function<void (const std::string &, int)> &f)
{
    m_pCompileLogger->callback = f;
}

Node*
NodeManager::getParent(const std::string& sourceNode)
{
    /*auto idx = sourceNode.find_last_of('.');
	if (idx > sourceNode.size())
		return nullptr;
	std::string treeName = sourceNode.substr(0, idx);
    Node* node = nullptr;
    try
    {
        node = m_nodeTree.get<Node*>(treeName);
    }catch(...)
    {
        return nullptr;
    }
    return node;*/
    return nullptr;
}
void NodeManager::getParentNodes(const std::string& sourceNode, std::vector<Node*>& output)
{
    /*Node* parent = getParent(sourceNode);
	if (!parent)
		return;
	output.push_back(parent);
    getParentNodes(parent->fullTreeName, output);*/
}

void NodeManager::getAccessibleNodes(const std::string& sourceNode, std::vector<Node*>& output)
{
	getSiblingNodes(sourceNode, output);
	getParentNodes(sourceNode, output);
}
std::vector<std::string>
NodeManager::getConstructableNodes()
{
    AUDynArray<IObjectConstructor*> constructors;
    m_pRuntimeObjectSystem->GetObjectFactorySystem()->GetAll(constructors);
    std::vector<std::string> output;
    for(int i = 0; i < constructors.Size(); ++i)
    {
        output.push_back(constructors[i]->GetName());
    }
    return output;
}
<commit_msg>Moved to using a weak_ptr to hold all currently created nodes.<commit_after>#include "Manager.h"
#include <RuntimeObjectSystem.h>
#include "StdioLogSystem.h"
#include <boost/filesystem.hpp>
#include "nodes/Node.h"
#include <stdarg.h>
#include <assert.h>
#include <iostream>
#include <boost/property_tree/xml_parser.hpp>
//#include <IObjectUtils.h>
using namespace EagleLib;

#ifdef _WIN32
    #include "Windows.h"
    #pragma warning( disable : 4996 4800 )
#endif

void CompileLogger::log(int level, const char *format, va_list args)
{
    int result = vsnprintf(m_buff, LOGSYSTEM_MAX_BUFFER-1, format, args);
    // Make sure there's a limit to the amount of rubbish we can output
    m_buff[LOGSYSTEM_MAX_BUFFER-1] = '\0';
    if(callback)
        callback(std::string(m_buff), level);
    std::cout << m_buff;
#ifdef _WIN32
    OutputDebugStringA( m_buff );
#endif
}

void CompileLogger::LogError(const char * format, ...)
{
    va_list args;
    va_start(args, format);
    log(2, format, args);
}

void CompileLogger::LogWarning(const char * format, ...)
{
    va_list args;
    va_start(args, format);
    log(1, format, args);
}

void CompileLogger::LogInfo(const char * format, ...)
{
    va_list args;
    va_start(args, format);
    log(0, format, args);
}
bool TestCallback::TestBuildCallback(const char* file, TestBuildResult type)
{
    bool success = true;
    switch(type)
    {
        case TESTBUILDRRESULT_SUCCESS:
            std::cout << "TESTBUILDRRESULT_SUCCESS - ";
            break;
        case TESTBUILDRRESULT_NO_FILES_TO_BUILD:
            std::cout << "TESTBUILDRRESULT_NO_FILES_TO_BUILD - ";
            success = false;
            break;
        case TESTBUILDRRESULT_BUILD_FILE_GONE:
            std::cout << "TESTBUILDRRESULT_BUILD_FILE_GONE - ";
            success = false;
            break;
        case TESTBUILDRRESULT_BUILD_NOT_STARTED:
            std::cout << "TESTBUILDRRESULT_BUILD_NOT_STARTED - ";
            success = false;
            break;
        case TESTBUILDRRESULT_BUILD_FAILED:
            std::cout << "TESTBUILDRRESULT_BUILD_FAILED - ";
            success = false;
            break;
        case TESTBUILDRRESULT_OBJECT_SWAP_FAIL:
            std::cout << "TESTBUILDRRESULT_OBJECT_SWAP_FAIL - ";
            success = false;
            break;
    }
    std::cout << file << std::endl;
    return success;
}

bool TestCallback::TestBuildWaitAndUpdate()
{
    boost::this_thread::sleep_for(boost::chrono::milliseconds(10));
    return true;
}

NodeManager& NodeManager::getInstance()
{
	static NodeManager instance;
	return instance;
}

NodeManager::NodeManager()
{
    Init();

}

NodeManager::~NodeManager()
{

}

bool
NodeManager::Init()
{
    testCallback = nullptr;
    m_pRuntimeObjectSystem.reset(new RuntimeObjectSystem);
    m_pCompileLogger.reset(new CompileLogger());
    m_pRuntimeObjectSystem->Initialise(m_pCompileLogger.get(), nullptr);
    m_pRuntimeObjectSystem->GetObjectFactorySystem()->AddListener(this);
    boost::filesystem::path workingDir(__FILE__);
    std::string includePath = workingDir.parent_path().parent_path().string();
#ifdef _MSC_VER

#else
    m_pRuntimeObjectSystem->SetAdditionalCompileOptions("-std=c++11");
#endif
    includePath += "/include";
    m_pRuntimeObjectSystem->AddIncludeDir(includePath.c_str());
	m_pRuntimeObjectSystem->AddIncludeDir(BOOST_INCLUDES);
	m_pRuntimeObjectSystem->AddIncludeDir(OPENCV_INCLUDES);
    m_pRuntimeObjectSystem->AddIncludeDir(CUDA_INCLUDES);

	m_pRuntimeObjectSystem->AddLibraryDir(BOOST_LIB_DIR);
	m_pRuntimeObjectSystem->AddLibraryDir(OPENCV_LIB_DIR);
    m_pRuntimeObjectSystem->AddLibraryDir(CUDA_LIB_DIR);
#ifdef BINARY_DIR
	m_pRuntimeObjectSystem->AddLibraryDir(BINARY_DIR);
#endif
#ifdef HAVE_PCL
    //m_pRuntimeObjectSystem->AddLibraryDir(PCL_LIB_DIR);
    m_pRuntimeObjectSystem->AddIncludeDir(PCL_INCLUDES);
#endif
	return true;
}

bool
NodeManager::MainLoop()
{
	return true;
}

void
NodeManager::OnConstructorsAdded()
{
	AUDynArray<IObjectConstructor*> constructors;
	m_pRuntimeObjectSystem->GetObjectFactorySystem()->GetAll(constructors);
	std::vector<Node*> newNodes;
	for (int i = 0; i < constructors.Size(); ++i)
	{
		int numObjects = constructors[i]->GetNumberConstructedObjects();
		for (int j = 0; j < numObjects; ++j)
		{
			auto ptr = constructors[i]->GetConstructedObject(j);
			ptr = ptr->GetInterface(IID_NodeObject);
			if (ptr)
			{
                auto nodePtr = static_cast<Node*>(ptr);
                //m_nodeTree.put(t_nodeTree::path_type{nodePtr->fullTreeName,'.'}, nodePtr);
				newNodes.push_back(nodePtr);
			}
		}
	}
	for (int i = 0; i < newNodes.size(); ++i)
	{
		for (int j = 0; j < newNodes[i]->parameters.size(); ++j)
		{
			newNodes[i]->parameters[j]->setSource(std::string());
		}
	}
}

shared_ptr<Node> NodeManager::addNode(const std::string &nodeName)
{

    IObjectConstructor* pConstructor = m_pRuntimeObjectSystem->GetObjectFactorySystem()->GetConstructor(nodeName.c_str());

    if(pConstructor)
    {
        IObject* pObj = pConstructor->Construct();
        IObject* interface = pObj->GetInterface(IID_NodeObject);

        if(interface)
        {
            Node* node = static_cast<Node*>(interface);
            node->Init(true);
            nodes.push_back(weak_ptr<Node>(node));
            return Node::Ptr(node);
        }else
        {
            // Input nodename is a compatible object but it is not a node
            return shared_ptr<Node>();
        }
    }else
    {
        // Invalid nodeName
        return shared_ptr<Node>();
    }
    return shared_ptr<Node>();
}
std::vector<shared_ptr<Node>> NodeManager::loadNodes(const std::string& saveFile)
{
    cv::FileStorage fs;
    try
    {
        fs.open(saveFile, cv::FileStorage::READ);
    }catch(cv::Exception &e)
    {
        std::cout << e.what() << std::endl;
    }

    int nodeCount = (int)fs["TopLevelNodeCount"];
    std::vector<shared_ptr<Node>> nodes;
    nodes.reserve(nodeCount);
    for(int i = 0;i < nodeCount; ++i)
    {
        auto nodeFS = fs["Node-" + boost::lexical_cast<std::string>(i)];
        std::string name = (std::string)nodeFS["NodeName"];
        Node::Ptr node = addNode(name);
        node->Init(nodeFS);
        nodes.push_back(node);
    }
    return nodes;
}

void NodeManager::saveNodes(std::vector<shared_ptr<Node>>& topLevelNodes, const std::string& fileName)
{
    cv::FileStorage fs;
    fs.open(fileName, cv::FileStorage::WRITE);
    fs << "TopLevelNodeCount" << (int)topLevelNodes.size();

    for(int i = 0; i < topLevelNodes.size(); ++i)
    {
        fs << "Node-" + boost::lexical_cast<std::string>(i) << "{";
        topLevelNodes[i]->Serialize(fs);
        fs << "}";
    }
    fs.release();
}

bool NodeManager::removeNode(const std::string& nodeName)
{

    return false;
}

bool NodeManager::removeNode(ObjectId oid)
{
 /*   Node* node =getNode(oid);
    if(node == nullptr)
        return false;
    auto path = node->fullTreeName;
    // First we need to get the parent property tree node.
    /////// GRRRRR I've tried everything but I can't get the property tree to delete the node.
    saveTree("test.xml");
    auto idx = path.find_last_of(".");
    auto parentPath = path.substr(0, idx);
    auto parentNode = m_nodeTree.get_child(parentPath);
    for(auto it = parentNode.begin(); it != parentNode.end(); ++it)
    {
        if(it->second.get_value<Node*>() == node)
        {
            parentNode.erase(it);
            break;
        }
    }
    saveTree("test.xml");
    delete m_pRuntimeObjectSystem->GetObjectFactorySystem()->GetConstructor(oid.m_ConstructorId)->GetConstructedObject(oid.m_PerTypeId);
    return true;*/
	return false;
}

void
NodeManager::addConstructors(IAUDynArray<IObjectConstructor*> & constructors)
{
    m_pRuntimeObjectSystem->GetObjectFactorySystem()->AddConstructors(constructors);
}
void
NodeManager::setupModule(IPerModuleInterface* pPerModuleInterface)
{
	m_pRuntimeObjectSystem->SetupObjectConstructors(pPerModuleInterface);
}
bool
NodeManager::CheckRecompile()
{
	static boost::posix_time::ptime prevTime = boost::posix_time::microsec_clock::universal_time();
	boost::posix_time::ptime currentTime = boost::posix_time::microsec_clock::universal_time();
	boost::posix_time::time_duration delta = currentTime - prevTime;
    // Prevent checking too often
    if(delta.total_milliseconds() < 10)
        return false;
    prevTime = currentTime;
    if( m_pRuntimeObjectSystem->GetIsCompiledComplete())
    {
        m_pRuntimeObjectSystem->LoadCompiledModule();
    }
    if(m_pRuntimeObjectSystem->GetIsCompiling())
    {
       return true;
    }else
    {
        m_pRuntimeObjectSystem->GetFileChangeNotifier()->Update(float(delta.total_milliseconds())/1000.0);
    }
    return false;
}

void NodeManager::saveTree(const std::string &fileName)
{

}

bool
NodeManager::CheckRecompile(bool swapAllowed)
{
    static boost::posix_time::ptime prevTime = boost::posix_time::microsec_clock::universal_time();
    boost::posix_time::ptime currentTime = boost::posix_time::microsec_clock::universal_time();
    boost::posix_time::time_duration delta = currentTime - prevTime;
    // Prevent checking too often
    if(delta.total_milliseconds() < 10)
        return false;
    prevTime = currentTime;
    if( m_pRuntimeObjectSystem->GetIsCompiledComplete() && swapAllowed)
    {
        m_pRuntimeObjectSystem->LoadCompiledModule();
    }
    if(m_pRuntimeObjectSystem->GetIsCompiling())
    {
       return true;
    }else
    {
        m_pRuntimeObjectSystem->GetFileChangeNotifier()->Update(float(delta.total_milliseconds())/1000.0);
    }
    return false;
}
bool NodeManager::TestRuntimeCompilation()
{
    if(testCallback == nullptr)
        testCallback = new TestCallback();
    m_pRuntimeObjectSystem->TestBuildAllRuntimeHeaders(testCallback,true);
    m_pRuntimeObjectSystem->TestBuildAllRuntimeSourceFiles(testCallback, true);
}

void
NodeManager::onNodeRecompile(Node *node)
{
    deletedNodes.push_back(node);
    deletedNodeIDs.push_back(node->m_OID);
}

Node*
NodeManager::getNode(const ObjectId& id)
{
    AUDynArray<IObjectConstructor*> constructors;
    m_pRuntimeObjectSystem->GetObjectFactorySystem()->GetAll(constructors);
    if(!id.IsValid())
        return nullptr;
    if(id.m_ConstructorId >= constructors.Size())
        return nullptr;
    if(id.m_PerTypeId >= constructors[id.m_ConstructorId]->GetNumberConstructedObjects())
        return nullptr;
    IObject* pObj = constructors[id.m_ConstructorId]->GetConstructedObject(id.m_PerTypeId);
    if(!pObj)
        return nullptr;
    pObj = pObj->GetInterface(IID_NodeObject);
    if(!pObj)
        return nullptr;
    return static_cast<Node*>(pObj);
}

Node*
NodeManager::getNode(const std::string &treeName)
{
    for(int i = 0; i < nodes.size(); ++i)
    {
        if(nodes[i]->fullTreeName == treeName)
        {
            return nodes[i].get();
        }
    }
    return nullptr;
}

void
NodeManager::updateTreeName(Node* node, const std::string& prevTreeName)
{
    /*m_nodeTree.put(t_nodeTree::path_type{ node->fullTreeName, '.' }, node);
    m_nodeTree.erase(prevTreeName);*/
}

void
NodeManager::addParameters(Node* node)
{
	for (int i = 0; i < node->parameters.size(); ++i)
	{

	}
}

boost::shared_ptr< Parameter >
NodeManager::getParameter(const std::string& name)
{
	// Strip off the path for the node
	auto idx = name.find(':');
	std::string parameterName = name.substr(idx+1);
	auto node = getNode(name.substr(0, idx));
    if(node == nullptr)
        return Parameter::Ptr();
	return node->getParameter(parameterName);
}

void
NodeManager::getSiblingNodes(const std::string& sourceNode, std::vector<Node*>& output)
{

}
void NodeManager::setCompileCallback(boost::function<void (const std::string &, int)> &f)
{
    m_pCompileLogger->callback = f;
}

Node*
NodeManager::getParent(const std::string& sourceNode)
{

    return nullptr;
}
void NodeManager::getParentNodes(const std::string& sourceNode, std::vector<Node*>& output)
{

}

void NodeManager::getAccessibleNodes(const std::string& sourceNode, std::vector<Node*>& output)
{
	getSiblingNodes(sourceNode, output);
	getParentNodes(sourceNode, output);
}
std::vector<std::string>
NodeManager::getConstructableNodes()
{
    AUDynArray<IObjectConstructor*> constructors;
    m_pRuntimeObjectSystem->GetObjectFactorySystem()->GetAll(constructors);
    std::vector<std::string> output;
    for(int i = 0; i < constructors.Size(); ++i)
    {
        output.push_back(constructors[i]->GetName());
    }
    return output;
}
<|endoftext|>


<commit_before>#include <ctrcommon/common.hpp>

#include <sstream>
#include <iomanip>
#include <stdio.h>

typedef enum {
    INSTALL,
    DELETE
} Mode;

int main(int argc, char **argv) {
    if(!platform_init()) {
        return 0;
    }

    std::vector<std::string> extensions;
    extensions.push_back("cia");

    MediaType destination = SD;
    Mode mode = INSTALL;
    bool netInstall = false;
    u64 freeSpace = fs_get_free_space(destination);
    auto onLoop = [&]() {
        bool breakLoop = false;
        if(input_is_pressed(BUTTON_L)) {
            if(destination == SD) {
                destination = NAND;
            } else {
                destination = SD;
            }

            freeSpace = fs_get_free_space(destination);
            if(mode == DELETE) {
                breakLoop = true;
            }
        }

        if(input_is_pressed(BUTTON_R)) {
            if(mode == INSTALL) {
                mode = DELETE;
            } else {
                mode = INSTALL;
            }

            breakLoop = true;
        }

        if(input_is_pressed(BUTTON_Y)) {
            netInstall = true;
            breakLoop = true;
        }

        std::stringstream stream;
        stream << "Free Space: " << freeSpace << " bytes (" << std::fixed << std::setprecision(2) << freeSpace / 1024.0f / 1024.0f << "MB)" << "\n";
        stream << "Destination: " << (destination == NAND ? "NAND" : "SD") << ", Mode: " << (mode == INSTALL ? "Install" : "Delete") << "\n";
        stream << "L - Switch Destination, R - Switch Mode" << "\n";
        stream << "Y - Receive an app over the network" << "\n";

        std::string str = stream.str();
        screen_draw_string(str, (screen_get_width() - screen_get_str_width(str)) / 2, screen_get_height() - 4 - screen_get_str_height(str), 255, 255, 255);

        return breakLoop;
    };

    auto onProgress = [&](int progress) {
        ui_display_progress(TOP_SCREEN, "Installing", "Press B to cancel.", true, progress);
        input_poll();
        return !input_is_pressed(BUTTON_B);
    };

    while(platform_is_running()) {
        std::string targetInstall;
        App targetDelete;
        bool obtained = false;
        if(mode == INSTALL) {
            obtained = ui_select_file(&targetInstall, "sdmc:", extensions, [&](bool inRoot) {
                return onLoop();
            });
        } else if(mode == DELETE) {
            obtained = ui_select_app(&targetDelete, destination, onLoop);
        }

        if(netInstall) {
            netInstall = false;

            screen_clear_buffers(BOTTOM_SCREEN, 0, 0, 0);

            RemoteFile file = ui_accept_remote_file(TOP_SCREEN);
            if(file.fd == NULL) {
                continue;
            }

            std::stringstream confirmStream;
            confirmStream << "Install the received application?" << "\n";
            confirmStream << "Size: " << file.fileSize << " bytes (" << std::fixed << std::setprecision(2) << file.fileSize / 1024.0f / 1024.0f << "MB)" << "\n";
            if(ui_prompt(TOP_SCREEN, confirmStream.str(), true)) {
                AppResult ret = app_install(destination, file.fd, file.fileSize, onProgress);
                std::stringstream resultMsg;
                if(mode == INSTALL) {
                    resultMsg << "Install ";
                } else if(mode == DELETE) {
                    resultMsg << "Delete ";
                }

                if(ret == APP_SUCCESS) {
                    resultMsg << "succeeded!";
                } else {
                    resultMsg << "failed!" << "\n";
                    resultMsg << app_get_result_string(ret) << "\n";
                }

                ui_prompt(TOP_SCREEN, resultMsg.str(), false);
            }

            fclose(file.fd);
            continue;
        }

        if(obtained) {
            std::stringstream prompt;
            if(mode == INSTALL) {
                prompt << "Install ";
            } else if(mode == DELETE) {
                prompt << "Delete ";
            }

            prompt << "the selected title?";
            if(ui_prompt(TOP_SCREEN, prompt.str(), true)) {
                AppResult ret = APP_SUCCESS;
                if(mode == INSTALL) {
                    ret = app_install_file(destination, targetInstall, onProgress);
                } else if(mode == DELETE) {
                    ui_display_message(TOP_SCREEN, "Deleting title...");
                    ret = app_delete(targetDelete);
                }

                std::stringstream resultMsg;
                if(mode == INSTALL) {
                    resultMsg << "Install ";
                } else if(mode == DELETE) {
                    resultMsg << "Delete ";
                }

                if(ret == APP_SUCCESS) {
                    resultMsg << "succeeded!";
                } else {
                    resultMsg << "failed!" << "\n";
                    resultMsg << app_get_result_string(ret) << "\n";
                }

                ui_prompt(TOP_SCREEN, resultMsg.str(), false);

                freeSpace = fs_get_free_space(destination);
            }
        }
    }

    platform_cleanup();
    return 0;
}
<commit_msg>Update for ctrcommon changes.<commit_after>#include <ctrcommon/input.hpp>
#include <ctrcommon/platform.hpp>
#include <ctrcommon/ui.hpp>

#include <sstream>
#include <iomanip>
#include <stdio.h>

typedef enum {
    INSTALL,
    DELETE
} Mode;

int main(int argc, char **argv) {
    if(!platform_init()) {
        return 0;
    }

    std::vector<std::string> extensions;
    extensions.push_back("cia");

    MediaType destination = SD;
    Mode mode = INSTALL;
    bool netInstall = false;
    u64 freeSpace = fs_get_free_space(destination);
    auto onLoop = [&]() {
        bool breakLoop = false;
        if(input_is_pressed(BUTTON_L)) {
            if(destination == SD) {
                destination = NAND;
            } else {
                destination = SD;
            }

            freeSpace = fs_get_free_space(destination);
            if(mode == DELETE) {
                breakLoop = true;
            }
        }

        if(input_is_pressed(BUTTON_R)) {
            if(mode == INSTALL) {
                mode = DELETE;
            } else {
                mode = INSTALL;
            }

            breakLoop = true;
        }

        if(input_is_pressed(BUTTON_Y)) {
            netInstall = true;
            breakLoop = true;
        }

        std::stringstream stream;
        stream << "Free Space: " << freeSpace << " bytes (" << std::fixed << std::setprecision(2) << freeSpace / 1024.0f / 1024.0f << "MB)" << "\n";
        stream << "Destination: " << (destination == NAND ? "NAND" : "SD") << ", Mode: " << (mode == INSTALL ? "Install" : "Delete") << "\n";
        stream << "L - Switch Destination, R - Switch Mode" << "\n";
        stream << "Y - Receive an app over the network" << "\n";

        std::string str = stream.str();
        screen_draw_string(str, (screen_get_width() - screen_get_str_width(str)) / 2, screen_get_height() - 4 - screen_get_str_height(str), 255, 255, 255);

        return breakLoop;
    };

    auto onProgress = [&](int progress) {
        ui_display_progress(TOP_SCREEN, "Installing", "Press B to cancel.", true, progress);
        input_poll();
        return !input_is_pressed(BUTTON_B);
    };

    while(platform_is_running()) {
        std::string targetInstall;
        App targetDelete;
        bool obtained = false;
        if(mode == INSTALL) {
            obtained = ui_select_file(&targetInstall, "sdmc:", extensions, [&](bool inRoot) {
                return onLoop();
            });
        } else if(mode == DELETE) {
            obtained = ui_select_app(&targetDelete, destination, onLoop);
        }

        if(netInstall) {
            netInstall = false;

            screen_clear_buffers(BOTTOM_SCREEN, 0, 0, 0);

            RemoteFile file = ui_accept_remote_file(TOP_SCREEN);
            if(file.fd == NULL) {
                continue;
            }

            std::stringstream confirmStream;
            confirmStream << "Install the received application?" << "\n";
            confirmStream << "Size: " << file.fileSize << " bytes (" << std::fixed << std::setprecision(2) << file.fileSize / 1024.0f / 1024.0f << "MB)" << "\n";
            if(ui_prompt(TOP_SCREEN, confirmStream.str(), true)) {
                AppResult ret = app_install(destination, file.fd, file.fileSize, onProgress);
                std::stringstream resultMsg;
                if(mode == INSTALL) {
                    resultMsg << "Install ";
                } else if(mode == DELETE) {
                    resultMsg << "Delete ";
                }

                if(ret == APP_SUCCESS) {
                    resultMsg << "succeeded!";
                } else {
                    resultMsg << "failed!" << "\n";
                    resultMsg << app_get_result_string(ret) << "\n";
                }

                ui_prompt(TOP_SCREEN, resultMsg.str(), false);
            }

            fclose(file.fd);
            continue;
        }

        if(obtained) {
            std::stringstream prompt;
            if(mode == INSTALL) {
                prompt << "Install ";
            } else if(mode == DELETE) {
                prompt << "Delete ";
            }

            prompt << "the selected title?";
            if(ui_prompt(TOP_SCREEN, prompt.str(), true)) {
                AppResult ret = APP_SUCCESS;
                if(mode == INSTALL) {
                    ret = app_install_file(destination, targetInstall, onProgress);
                } else if(mode == DELETE) {
                    ui_display_message(TOP_SCREEN, "Deleting title...");
                    ret = app_delete(targetDelete);
                }

                std::stringstream resultMsg;
                if(mode == INSTALL) {
                    resultMsg << "Install ";
                } else if(mode == DELETE) {
                    resultMsg << "Delete ";
                }

                if(ret == APP_SUCCESS) {
                    resultMsg << "succeeded!";
                } else {
                    resultMsg << "failed!" << "\n";
                    resultMsg << app_get_result_string(ret) << "\n";
                }

                ui_prompt(TOP_SCREEN, resultMsg.str(), false);

                freeSpace = fs_get_free_space(destination);
            }
        }
    }

    platform_cleanup();
    return 0;
}
<|endoftext|>


<commit_before>// *****************************************************************************
//
// This file is part of a MASA library or program.
// Refer to the included end-user license agreement for restrictions.
//
// Copyright (c) 2008 Mathmatiques Appliques SA (MASA)
//
// *****************************************************************************

#include "xeumeuleu_test_pch.h"
#include "xeumeuleu/xml.h"

namespace
{
    void Read()
    {
        xml::xistringstream xis( "<element>"
                                    "<sub-node/>"
                                    "<another-sub-node/>"
                                 "</element>" );
        xis >> xml::start( "element" )
                >> xml::start( "another-sub-node" ) >> xml::end();
    }
    void Write()
    {
        xml::xostringstream xos;
        xos << xml::start( "element" )
                << xml::start( "another-sub-node" ) << xml::end()
            << xml::end();
    }
    void Run()
    {
        int count = 1000;
        while( count-- )
        {
            if( std::rand() % 2 != 0 )
                Read();
            else
                Write();
        }
    }
}

// -----------------------------------------------------------------------------
// Name: creating_a_document_is_thread_safe
// Created: AGE 2008-05-20
// -----------------------------------------------------------------------------
BOOST_AUTO_TEST_CASE( creating_a_document_is_thread_safe )
{
    static const int THREADS = 4;
    boost::thread_group group;
    for( int i = 0; i < THREADS; ++i )
        group.create_thread( &Run );
    group.join_all();
}
<commit_msg>Cleanup<commit_after>// *****************************************************************************
//
// This file is part of a MASA library or program.
// Refer to the included end-user license agreement for restrictions.
//
// Copyright (c) 2008 Mathmatiques Appliques SA (MASA)
//
// *****************************************************************************

#include "xeumeuleu_test_pch.h"
#include "xeumeuleu/xml.h"

namespace
{
    void read()
    {
        xml::xistringstream xis( "<element>"
                                    "<sub-node/>"
                                    "<another-sub-node/>"
                                 "</element>" );
        xis >> xml::start( "element" )
                >> xml::start( "another-sub-node" ) >> xml::end();
    }
    void write()
    {
        xml::xostringstream xos;
        xos << xml::start( "element" )
                << xml::start( "another-sub-node" ) << xml::end()
            << xml::end();
    }
    void run()
    {
        int count = 1000;
        while( count-- )
        {
            if( std::rand() % 2 != 0 )
                read();
            else
                write();
        }
    }
}

// -----------------------------------------------------------------------------
// Name: creating_a_document_is_thread_safe
// Created: AGE 2008-05-20
// -----------------------------------------------------------------------------
BOOST_AUTO_TEST_CASE( creating_a_document_is_thread_safe )
{
    static const int THREADS = 4;
    boost::thread_group group;
    for( int i = 0; i < THREADS; ++i )
        group.create_thread( &run );
    group.join_all();
}
<|endoftext|>


<commit_before>#include <matrix.hpp>
#include <catch.hpp>

SCENARIO("copy constructor")

{

	Matrix matrix;

	Matrix copy(matrix);

	REQUIRE(copy.strings() == 2);

	REQUIRE(copy.columns() == 2);

}

SCENARIO("operator +")

{
	Matrix matrix (2, 2);

	Matrix matrix1 = Matrix (2, 2);

	REQUIRE(matrix1 + matrix == matrix + matrix );

}

SCENARIO("operator *")

{

	Matrix matrix (2,2);

	Matrix matrix3  = Matrix (2,2);

	REQUIRE(matrix * matrix == matrix3);

}

SCENARIO("operator =")

{

	Matrix matrix (2,2);

	Matrix matrix2 = matrix;

	REQUIRE(matrix == matrix2);

}

SCENARIO("operator ==")
{

	Matrix matrix (2,2);

	Matrix matrix2 = Matrix (2,2);

	REQUIRE(matrix == matrix2);

}

<commit_msg>Update init.cpp<commit_after>#include <matrix.hpp>
#include <catch.hpp>

SCENARIO("copy constructor")

{

	Matrix matrix;

	Matrix copy(matrix);

	REQUIRE(copy.strings() == 2);

	REQUIRE(copy.columns() == 2);

}

SCENARIO("operator +")

{
	Matrix matrix (2, 2);

	Matrix matrix1 = Matrix (2, 2);

	REQUIRE(matrix + matrix == matrix1);

}

SCENARIO("operator *")

{

	Matrix matrix (2,2);

	Matrix matrix3  = Matrix (2,2);

	REQUIRE(matrix * matrix == matrix3);

}

SCENARIO("operator =")

{

	Matrix matrix (2,2);

	Matrix matrix2 = matrix;

	REQUIRE(matrix == matrix2);

}

SCENARIO("operator ==")
{

	Matrix matrix (2,2);

	Matrix matrix2 = Matrix (2,2);

	REQUIRE(matrix == matrix2);

}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017 Tmplt <tmplt@dragons.rocks>
 *
 * 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>   // std::cout, std::endl
#include <algorithm>  // std::max(), std::set_intersection()
#include <iomanip>    // std::setw()
#include <utility>    // std::make_unique<T>(), std::forward<T>()

#include "components/command_line.hpp"
#include "utils.hpp"

enum {
    /*
     * Same order as they are initialized
     * in main(). Perhaps we should have a
     * getter funtion instead?
     *
     * These (or well, only main) are used in
     * validate_arguments() to get the group of
     * main arguments so that we can find if any of
     * those are passed.
     *
     * I'm a bit unsure if it's worth the time to
     * implement a better way to do this. This will work
     * as long as they are in the same order as they are
     * initialized in in main().
     */
    main,
    excl,
    exact,
    misc
};

enum { /* magic padding numbers */
    padding_margin = 4,
    desc_align_magic = 7
};

cliparser::cli_type cliparser::make(const string &&progname, const groups &&groups)
{
    return std::make_unique<cliparser>(
        "Usage: " + progname + " OPTION...", std::forward<decltype(groups)>(groups)
    );
}

auto cliparser::values_to_str(const choices &values)
{
    string retstring = "";
    for (const auto &v : values)
        retstring += v + (v != values.back() ? ", " : "");

    return retstring;
}

void cliparser::usage() const
{
    std::cout << synopsis_ << "\n\n";

    size_t maxlen = 0;

    /*
     * Get the length of the longest string in the flag column
     * which is used to align the description fields.
     */
    for (const auto &group : valid_groups_) {
        for (const auto &opt : group.options) {
            size_t len = opt.flag_long.length() + opt.flag.length() +
                         opt.token.length() + padding_margin;

            maxlen = std::max(len, maxlen);
        }
    }

    /*
     * Print each option group, its options, the options'
     * descriptions, token and possible values for said token (if any).
     */
    for (const auto &group : valid_groups_) {
        std::cout << group.name << " arguments"
                  << (group.synopsis.empty() ? ":" : " - " + group.synopsis + ":")
                  << '\n';

        for (const auto &opt : group.options) {
            /* Padding between flags and description. */
            size_t pad = maxlen - opt.flag_long.length() - opt.token.length();

            std::cout << "  " << opt.flag << ", " << opt.flag_long;

            if (!opt.token.empty()) {
                std::cout << ' ' << opt.token;
                pad--;
            }

            /*
             * Print the list with accepted values.
             * This line is printed below the description.
             */
            if (!opt.values.empty()) {
                std::cout << std::setw(pad + opt.desc.length())
                          << opt.desc << '\n';

                pad += opt.flag_long.length() + opt.token.length() + desc_align_magic;

                std::cout << string(pad, ' ') << opt.token << " is one of: "
                          << values_to_str(opt.values);
            } else {
                std::cout << std::setw(pad + opt.desc.length()) << opt.desc;
            }

            std::cout << '\n';
        }

        std::cout << std::endl;
    }
}

bool cliparser::has(const string &option) const
{
    return passed_opts_.find(option) != passed_opts_.end();
}

string cliparser::get(string opt) const
{
    if (has(std::forward<string>(opt)))
        return passed_opts_.find(opt)->second;

    return "";
}

auto cliparser::is_short(const string_view &option, const string_view &opt_short)
{
    return option.compare(0, opt_short.length(), opt_short) == 0;
}

auto cliparser::is_long(const string_view &option, const string_view &opt_long)
{
    return option.compare(0, opt_long.length(), opt_long) == 0;
}

auto cliparser::is(const string_view &option, string opt_short, string opt_long)
{
    return is_short(option, std::move(opt_short)) || is_long(option, std::move(opt_long));
}

void cliparser::process_arguments(const vector<string> &args)
{
    for (size_t i = 0; i < args.size(); i++) {
        const string_view &arg = args[i];
        const string_view &next_arg = args.size() > i + 1 ? args[i + 1] : "";

        parse(arg, next_arg);
    }
}

void cliparser::validate_arguments() const
{
    vector<string> passed_opts, required_opts;

    for (const auto &opt : passed_opts_) {
        /* We don't want the value, only the flag. */
        passed_opts.emplace_back(opt.first);
    }

    for (const auto &opt : valid_groups_[main].options)
        required_opts.emplace_back(opt.flag_long.substr(2));

    /* Has any required arguments been passed? */
    const bool req_match = utils::any_intersection(passed_opts, required_opts);
    const bool ident_passed = std::find(passed_opts.cbegin(), passed_opts.cend(), "ident")
        != passed_opts.cend();

    if (ident_passed && passed_opts.size() > 1)
        throw argument_error("ident flag is exclusive and may not be passed with another flag");

    if (!req_match && !passed_opts.empty())
        throw argument_error("at least one main argument must be specified");
}

auto cliparser::check_value(const string_view &flag, const string_view &value, const choices &values)
{

    if (value.empty())
        throw value_error("missing value for " + string(flag.data()));

    if (!values.empty() && std::find(values.begin(), values.end(), value) == values.end()) {
        throw value_error(
            "invalid value '" + string(value.data()) + "' for argument " + string(flag.data()) +
            "; valid options are: " + values_to_str(values)
        );
    }

    return value;
}

void cliparser::parse(const string_view &input, const string_view &input_next)
{
    if (skipnext_) {
        skipnext_ = false;
        return;
    }

    for (const auto &group : valid_groups_) {
        for (const auto &opt : group.options) {
            if (is(input, opt.flag, opt.flag_long)) {
                if (opt.token.empty()) {
                    /* The option is only a flag. */
                    passed_opts_.emplace(std::make_pair(opt.flag_long.substr(2), ""));
                } else {
                    /*
                     * The option should have an accompanied value.
                     * And may be that it must be an element in opt.values.
                     */
                    const auto value = check_value(input, input_next, opt.values);
                    skipnext_ = (value == input_next);
                    passed_opts_.emplace(make_pair(opt.flag_long.substr(2), value));
                }

                return;
            }
        }
    }

    if (input[0] == '-')
        throw argument_error("unrecognized option " + string(input.data()));

    throw argument_error("the bookwyrm takes no positional arguments");
}
<commit_msg>command_line: use more constant references<commit_after>/*
 * Copyright (C) 2017 Tmplt <tmplt@dragons.rocks>
 *
 * 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>   // std::cout, std::endl
#include <algorithm>  // std::max(), std::set_intersection()
#include <iomanip>    // std::setw()
#include <utility>    // std::make_unique<T>(), std::forward<T>()

#include "components/command_line.hpp"
#include "utils.hpp"

enum {
    /*
     * Same order as they are initialized
     * in main(). Perhaps we should have a
     * getter funtion instead?
     *
     * These (or well, only main) are used in
     * validate_arguments() to get the group of
     * main arguments so that we can find if any of
     * those are passed.
     *
     * I'm a bit unsure if it's worth the time to
     * implement a better way to do this. This will work
     * as long as they are in the same order as they are
     * initialized in in main().
     */
    main,
    excl,
    exact,
    misc
};

enum { /* magic padding numbers */
    padding_margin = 4,
    desc_align_magic = 7
};

cliparser::cli_type cliparser::make(const string &&progname, const groups &&groups)
{
    return std::make_unique<cliparser>(
        "Usage: " + progname + " OPTION...", std::forward<decltype(groups)>(groups)
    );
}

auto cliparser::values_to_str(const choices &values)
{
    string retstring = "";
    for (const auto &v : values)
        retstring += v + (v != values.back() ? ", " : "");

    return retstring;
}

void cliparser::usage() const
{
    std::cout << synopsis_ << "\n\n";

    size_t maxlen = 0;

    /*
     * Get the length of the longest string in the flag column
     * which is used to align the description fields.
     */
    for (const auto &group : valid_groups_) {
        for (const auto &opt : group.options) {
            size_t len = opt.flag_long.length() + opt.flag.length() +
                         opt.token.length() + padding_margin;

            maxlen = std::max(len, maxlen);
        }
    }

    /*
     * Print each option group, its options, the options'
     * descriptions, token and possible values for said token (if any).
     */
    for (const auto &group : valid_groups_) {
        std::cout << group.name << " arguments"
                  << (group.synopsis.empty() ? ":" : " - " + group.synopsis + ":")
                  << '\n';

        for (const auto &opt : group.options) {
            /* Padding between flags and description. */
            size_t pad = maxlen - opt.flag_long.length() - opt.token.length();

            std::cout << "  " << opt.flag << ", " << opt.flag_long;

            if (!opt.token.empty()) {
                std::cout << ' ' << opt.token;
                pad--;
            }

            /*
             * Print the list with accepted values.
             * This line is printed below the description.
             */
            if (!opt.values.empty()) {
                std::cout << std::setw(pad + opt.desc.length())
                          << opt.desc << '\n';

                pad += opt.flag_long.length() + opt.token.length() + desc_align_magic;

                std::cout << string(pad, ' ') << opt.token << " is one of: "
                          << values_to_str(opt.values);
            } else {
                std::cout << std::setw(pad + opt.desc.length()) << opt.desc;
            }

            std::cout << '\n';
        }

        std::cout << std::endl;
    }
}

bool cliparser::has(const string &option) const
{
    return passed_opts_.find(option) != passed_opts_.cend();
}

string cliparser::get(string opt) const
{
    if (has(std::forward<string>(opt)))
        return passed_opts_.find(opt)->second;

    return "";
}

auto cliparser::is_short(const string_view &option, const string_view &opt_short)
{
    return option.compare(0, opt_short.length(), opt_short) == 0;
}

auto cliparser::is_long(const string_view &option, const string_view &opt_long)
{
    return option.compare(0, opt_long.length(), opt_long) == 0;
}

auto cliparser::is(const string_view &option, string opt_short, string opt_long)
{
    return is_short(option, std::move(opt_short)) || is_long(option, std::move(opt_long));
}

void cliparser::process_arguments(const vector<string> &args)
{
    for (size_t i = 0; i < args.size(); i++) {
        const string_view &arg = args[i];
        const string_view &next_arg = args.size() > i + 1 ? args[i + 1] : "";

        parse(arg, next_arg);
    }
}

void cliparser::validate_arguments() const
{
    vector<string> passed_opts, required_opts;

    for (const auto &opt : passed_opts_) {
        /* We don't want the value, only the flag. */
        passed_opts.emplace_back(opt.first);
    }

    for (const auto &opt : valid_groups_[main].options)
        required_opts.emplace_back(opt.flag_long.substr(2));

    /* Has any required arguments been passed? */
    const bool req_match = utils::any_intersection(passed_opts, required_opts);
    const bool ident_passed = std::find(passed_opts.cbegin(), passed_opts.cend(), "ident")
        != passed_opts.cend();

    if (ident_passed && passed_opts.size() > 1)
        throw argument_error("ident flag is exclusive and may not be passed with another flag");

    if (!req_match && !passed_opts.empty())
        throw argument_error("at least one main argument must be specified");
}

auto cliparser::check_value(const string_view &flag, const string_view &value, const choices &values)
{

    if (value.empty())
        throw value_error("missing value for " + string(flag.data()));

    if (!values.empty() && std::find(values.cbegin(), values.cend(), value) == values.cend()) {
        throw value_error(
            "invalid value '" + string(value.data()) + "' for argument " + string(flag.data()) +
            "; valid options are: " + values_to_str(values)
        );
    }

    return value;
}

void cliparser::parse(const string_view &input, const string_view &input_next)
{
    if (skipnext_) {
        skipnext_ = false;
        return;
    }

    for (const auto &group : valid_groups_) {
        for (const auto &opt : group.options) {
            if (is(input, opt.flag, opt.flag_long)) {
                if (opt.token.empty()) {
                    /* The option is only a flag. */
                    passed_opts_.emplace(std::make_pair(opt.flag_long.substr(2), ""));
                } else {
                    /*
                     * The option should have an accompanied value.
                     * And may be that it must be an element in opt.values.
                     */
                    const auto value = check_value(input, input_next, opt.values);
                    skipnext_ = (value == input_next);
                    passed_opts_.emplace(make_pair(opt.flag_long.substr(2), value));
                }

                return;
            }
        }
    }

    if (input[0] == '-')
        throw argument_error("unrecognized option " + string(input.data()));

    throw argument_error("the bookwyrm takes no positional arguments");
}
<|endoftext|>


<commit_before>//===-- SIMCCodeEmitter.cpp - SI Code Emitter -------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// The SI code emitter produces machine code that can be executed directly on
// the GPU device.
//
//===----------------------------------------------------------------------===//

#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
#include "MCTargetDesc/AMDGPUMCCodeEmitter.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/raw_ostream.h"

#define VGPR_BIT(src_idx) (1ULL << (9 * src_idx - 1))
#define SI_INSTR_FLAGS_ENCODING_MASK 0xf

// These must be kept in sync with SIInstructions.td and also the
// InstrEncodingInfo array in SIInstrInfo.cpp.
//
// NOTE: This enum is only used to identify the encoding type within LLVM,
// the actual encoding type that is part of the instruction format is different
namespace SIInstrEncodingType {
  enum Encoding {
    EXP = 0,
    LDS = 1,
    MIMG = 2,
    MTBUF = 3,
    MUBUF = 4,
    SMRD = 5,
    SOP1 = 6,
    SOP2 = 7,
    SOPC = 8,
    SOPK = 9,
    SOPP = 10,
    VINTRP = 11,
    VOP1 = 12,
    VOP2 = 13,
    VOP3 = 14,
    VOPC = 15
  };
}

using namespace llvm;

namespace {
class SIMCCodeEmitter : public  AMDGPUMCCodeEmitter {
  SIMCCodeEmitter(const SIMCCodeEmitter &); // DO NOT IMPLEMENT
  void operator=(const SIMCCodeEmitter &); // DO NOT IMPLEMENT
  const MCInstrInfo &MCII;
  const MCSubtargetInfo &STI;
  MCContext &Ctx;

public:
  SIMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti,
                  MCContext &ctx)
    : MCII(mcii), STI(sti), Ctx(ctx) { }

  ~SIMCCodeEmitter() { }

  /// EncodeInstruction - Encode the instruction and write it to the OS.
  virtual void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
                         SmallVectorImpl<MCFixup> &Fixups) const;

  /// getMachineOpValue - Reutrn the encoding for an MCOperand.
  virtual uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
                                     SmallVectorImpl<MCFixup> &Fixups) const;

public:

  /// GPRAlign - Encode a sequence of registers with the correct alignment.
  unsigned GPRAlign(const MCInst &MI, unsigned OpNo, unsigned shift) const;

  /// GPR2AlignEncode - Encoding for when 2 consecutive registers are used
  virtual unsigned GPR2AlignEncode(const MCInst &MI, unsigned OpNo,
                                   SmallVectorImpl<MCFixup> &Fixup) const;

  /// GPR4AlignEncode - Encoding for when 4 consectuive registers are used
  virtual unsigned GPR4AlignEncode(const MCInst &MI, unsigned OpNo,
                                   SmallVectorImpl<MCFixup> &Fixup) const;

  /// SMRDmemriEncode - Encoding for SMRD indexed loads
  virtual uint32_t SMRDmemriEncode(const MCInst &MI, unsigned OpNo,
                                   SmallVectorImpl<MCFixup> &Fixup) const;

  /// VOPPostEncode - Post-Encoder method for VOP instructions
  virtual uint64_t VOPPostEncode(const MCInst &MI, uint64_t Value) const;

private:

  ///getEncodingType =  Return this SIInstrEncodingType for this instruction.
  unsigned getEncodingType(const MCInst &MI) const;

  ///getEncodingBytes - Get then size in bytes of this instructions encoding.
  unsigned getEncodingBytes(const MCInst &MI) const;

  /// getRegBinaryCode - Returns the hardware encoding for a register
  unsigned getRegBinaryCode(unsigned reg) const;

  /// getHWRegNum - Generated function that returns the hardware encoding for
  /// a register
  unsigned getHWRegNum(unsigned reg) const;

};

} // End anonymous namespace

MCCodeEmitter *llvm::createSIMCCodeEmitter(const MCInstrInfo &MCII,
                                           const MCSubtargetInfo &STI,
                                           MCContext &Ctx) {
  return new SIMCCodeEmitter(MCII, STI, Ctx);
}

void SIMCCodeEmitter::EncodeInstruction(const MCInst &MI, raw_ostream &OS,
                                       SmallVectorImpl<MCFixup> &Fixups) const {
  uint64_t Encoding = getBinaryCodeForInstr(MI, Fixups);
  unsigned bytes = getEncodingBytes(MI);
  for (unsigned i = 0; i < bytes; i++) {
    OS.write((uint8_t) ((Encoding >> (8 * i)) & 0xff));
  }
}

uint64_t SIMCCodeEmitter::getMachineOpValue(const MCInst &MI,
                                            const MCOperand &MO,
                                       SmallVectorImpl<MCFixup> &Fixups) const {
  if (MO.isReg()) {
    return getRegBinaryCode(MO.getReg());
  } else if (MO.isImm()) {
    return MO.getImm();
  } else if (MO.isFPImm()) {
    // XXX: Not all instructions can use inline literals
    // XXX: We should make sure this is a 32-bit constant
    union {
      float F;
      uint32_t I;
    } Imm;
    Imm.F = MO.getFPImm();
    return Imm.I;
  } else{
    llvm_unreachable("Encoding of this operand type is not supported yet.");
  }
  return 0;
}

//===----------------------------------------------------------------------===//
// Custom Operand Encodings
//===----------------------------------------------------------------------===//

unsigned SIMCCodeEmitter::GPRAlign(const MCInst &MI, unsigned OpNo,
                                   unsigned shift) const {
  unsigned regCode = getRegBinaryCode(MI.getOperand(OpNo).getReg());
  return regCode >> shift;
  return 0;
}
unsigned SIMCCodeEmitter::GPR2AlignEncode(const MCInst &MI,
                                          unsigned OpNo ,
                                        SmallVectorImpl<MCFixup> &Fixup) const {
  return GPRAlign(MI, OpNo, 1);
}

unsigned SIMCCodeEmitter::GPR4AlignEncode(const MCInst &MI,
                                          unsigned OpNo,
                                        SmallVectorImpl<MCFixup> &Fixup) const {
  return GPRAlign(MI, OpNo, 2);
}

#define SMRD_OFFSET_MASK 0xff
#define SMRD_IMM_SHIFT 8
#define SMRD_SBASE_MASK 0x3f
#define SMRD_SBASE_SHIFT 9
/// SMRDmemriEncode - This function is responsibe for encoding the offset
/// and the base ptr for SMRD instructions it should return a bit string in
/// this format:
///
/// OFFSET = bits{7-0}
/// IMM    = bits{8}
/// SBASE  = bits{14-9}
///
uint32_t SIMCCodeEmitter::SMRDmemriEncode(const MCInst &MI, unsigned OpNo,
                                        SmallVectorImpl<MCFixup> &Fixup) const {
  uint32_t Encoding;

  const MCOperand &OffsetOp = MI.getOperand(OpNo + 1);

  //XXX: Use this function for SMRD loads with register offsets
  assert(OffsetOp.isImm());

  Encoding =
      (getMachineOpValue(MI, OffsetOp, Fixup) & SMRD_OFFSET_MASK)
    | (1 << SMRD_IMM_SHIFT) //XXX If the Offset is a register we shouldn't set this bit
    | ((GPR2AlignEncode(MI, OpNo, Fixup) & SMRD_SBASE_MASK) << SMRD_SBASE_SHIFT)
    ;

  return Encoding;
}

//===----------------------------------------------------------------------===//
// Post Encoder Callbacks
//===----------------------------------------------------------------------===//

uint64_t SIMCCodeEmitter::VOPPostEncode(const MCInst &MI, uint64_t Value) const{
  unsigned encodingType = getEncodingType(MI);
  unsigned numSrcOps;
  unsigned vgprBitOffset;

  if (encodingType == SIInstrEncodingType::VOP3) {
    numSrcOps = 3;
    vgprBitOffset = 32;
  } else {
    numSrcOps = 1;
    vgprBitOffset = 0;
  }

  // Add one to skip over the destination reg operand.
  for (unsigned opIdx = 1; opIdx < numSrcOps + 1; opIdx++) {
    const MCOperand &MO = MI.getOperand(opIdx);
    if (MO.isReg()) {
      unsigned reg = MI.getOperand(opIdx).getReg();
      if (AMDGPUMCRegisterClasses[AMDGPU::VReg_32RegClassID].contains(reg) ||
          AMDGPUMCRegisterClasses[AMDGPU::VReg_64RegClassID].contains(reg)) {
        Value |= (VGPR_BIT(opIdx)) << vgprBitOffset;
      }
    } else if (MO.isFPImm()) {
      union {
        float f;
        uint32_t i;
      } Imm;
      // XXX: Not all instructions can use inline literals
      // XXX: We should make sure this is a 32-bit constant
      Imm.f = MO.getFPImm();
      Value |= ((uint64_t)Imm.i) << 32;
    }
  }
  return Value;
}

//===----------------------------------------------------------------------===//
// Encoding helper functions
//===----------------------------------------------------------------------===//

unsigned SIMCCodeEmitter::getEncodingType(const MCInst &MI) const {
  return MCII.get(MI.getOpcode()).TSFlags & SI_INSTR_FLAGS_ENCODING_MASK;
}

unsigned SIMCCodeEmitter::getEncodingBytes(const MCInst &MI) const {

  // These instructions aren't real instructions with an encoding type, so
  // we need to manually specify their size.
  switch (MI.getOpcode()) {
  default: break;
  case AMDGPU::SI_LOAD_LITERAL_I32:
  case AMDGPU::SI_LOAD_LITERAL_F32:
    return 4;
  }

  unsigned encoding_type = getEncodingType(MI);
  switch (encoding_type) {
    case SIInstrEncodingType::EXP:
    case SIInstrEncodingType::LDS:
    case SIInstrEncodingType::MUBUF:
    case SIInstrEncodingType::MTBUF:
    case SIInstrEncodingType::MIMG:
    case SIInstrEncodingType::VOP3:
      return 8;
    default:
      return 4;
  }
}

unsigned SIMCCodeEmitter::getRegBinaryCode(unsigned reg) const {
  switch (reg) {
    case AMDGPU::M0: return 124;
    case AMDGPU::EXEC: return 126;
    case AMDGPU::EXEC_LO: return 126;
    case AMDGPU::EXEC_HI: return 127;
    case AMDGPU::SREG_LIT_0: return 128;
    case AMDGPU::SI_LITERAL_CONSTANT: return 255;
    default: return getHWRegNum(reg);
  }
}

#define SIRegisterInfo SIMCCodeEmitter
#include "SIRegisterGetHWRegNum.inc"
#undef SIRegisterInfo
<commit_msg>radeon/llvm: Add register encoding for VCC<commit_after>//===-- SIMCCodeEmitter.cpp - SI Code Emitter -------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// The SI code emitter produces machine code that can be executed directly on
// the GPU device.
//
//===----------------------------------------------------------------------===//

#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
#include "MCTargetDesc/AMDGPUMCCodeEmitter.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/raw_ostream.h"

#define VGPR_BIT(src_idx) (1ULL << (9 * src_idx - 1))
#define SI_INSTR_FLAGS_ENCODING_MASK 0xf

// These must be kept in sync with SIInstructions.td and also the
// InstrEncodingInfo array in SIInstrInfo.cpp.
//
// NOTE: This enum is only used to identify the encoding type within LLVM,
// the actual encoding type that is part of the instruction format is different
namespace SIInstrEncodingType {
  enum Encoding {
    EXP = 0,
    LDS = 1,
    MIMG = 2,
    MTBUF = 3,
    MUBUF = 4,
    SMRD = 5,
    SOP1 = 6,
    SOP2 = 7,
    SOPC = 8,
    SOPK = 9,
    SOPP = 10,
    VINTRP = 11,
    VOP1 = 12,
    VOP2 = 13,
    VOP3 = 14,
    VOPC = 15
  };
}

using namespace llvm;

namespace {
class SIMCCodeEmitter : public  AMDGPUMCCodeEmitter {
  SIMCCodeEmitter(const SIMCCodeEmitter &); // DO NOT IMPLEMENT
  void operator=(const SIMCCodeEmitter &); // DO NOT IMPLEMENT
  const MCInstrInfo &MCII;
  const MCSubtargetInfo &STI;
  MCContext &Ctx;

public:
  SIMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti,
                  MCContext &ctx)
    : MCII(mcii), STI(sti), Ctx(ctx) { }

  ~SIMCCodeEmitter() { }

  /// EncodeInstruction - Encode the instruction and write it to the OS.
  virtual void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
                         SmallVectorImpl<MCFixup> &Fixups) const;

  /// getMachineOpValue - Reutrn the encoding for an MCOperand.
  virtual uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
                                     SmallVectorImpl<MCFixup> &Fixups) const;

public:

  /// GPRAlign - Encode a sequence of registers with the correct alignment.
  unsigned GPRAlign(const MCInst &MI, unsigned OpNo, unsigned shift) const;

  /// GPR2AlignEncode - Encoding for when 2 consecutive registers are used
  virtual unsigned GPR2AlignEncode(const MCInst &MI, unsigned OpNo,
                                   SmallVectorImpl<MCFixup> &Fixup) const;

  /// GPR4AlignEncode - Encoding for when 4 consectuive registers are used
  virtual unsigned GPR4AlignEncode(const MCInst &MI, unsigned OpNo,
                                   SmallVectorImpl<MCFixup> &Fixup) const;

  /// SMRDmemriEncode - Encoding for SMRD indexed loads
  virtual uint32_t SMRDmemriEncode(const MCInst &MI, unsigned OpNo,
                                   SmallVectorImpl<MCFixup> &Fixup) const;

  /// VOPPostEncode - Post-Encoder method for VOP instructions
  virtual uint64_t VOPPostEncode(const MCInst &MI, uint64_t Value) const;

private:

  ///getEncodingType =  Return this SIInstrEncodingType for this instruction.
  unsigned getEncodingType(const MCInst &MI) const;

  ///getEncodingBytes - Get then size in bytes of this instructions encoding.
  unsigned getEncodingBytes(const MCInst &MI) const;

  /// getRegBinaryCode - Returns the hardware encoding for a register
  unsigned getRegBinaryCode(unsigned reg) const;

  /// getHWRegNum - Generated function that returns the hardware encoding for
  /// a register
  unsigned getHWRegNum(unsigned reg) const;

};

} // End anonymous namespace

MCCodeEmitter *llvm::createSIMCCodeEmitter(const MCInstrInfo &MCII,
                                           const MCSubtargetInfo &STI,
                                           MCContext &Ctx) {
  return new SIMCCodeEmitter(MCII, STI, Ctx);
}

void SIMCCodeEmitter::EncodeInstruction(const MCInst &MI, raw_ostream &OS,
                                       SmallVectorImpl<MCFixup> &Fixups) const {
  uint64_t Encoding = getBinaryCodeForInstr(MI, Fixups);
  unsigned bytes = getEncodingBytes(MI);
  for (unsigned i = 0; i < bytes; i++) {
    OS.write((uint8_t) ((Encoding >> (8 * i)) & 0xff));
  }
}

uint64_t SIMCCodeEmitter::getMachineOpValue(const MCInst &MI,
                                            const MCOperand &MO,
                                       SmallVectorImpl<MCFixup> &Fixups) const {
  if (MO.isReg()) {
    return getRegBinaryCode(MO.getReg());
  } else if (MO.isImm()) {
    return MO.getImm();
  } else if (MO.isFPImm()) {
    // XXX: Not all instructions can use inline literals
    // XXX: We should make sure this is a 32-bit constant
    union {
      float F;
      uint32_t I;
    } Imm;
    Imm.F = MO.getFPImm();
    return Imm.I;
  } else{
    llvm_unreachable("Encoding of this operand type is not supported yet.");
  }
  return 0;
}

//===----------------------------------------------------------------------===//
// Custom Operand Encodings
//===----------------------------------------------------------------------===//

unsigned SIMCCodeEmitter::GPRAlign(const MCInst &MI, unsigned OpNo,
                                   unsigned shift) const {
  unsigned regCode = getRegBinaryCode(MI.getOperand(OpNo).getReg());
  return regCode >> shift;
  return 0;
}
unsigned SIMCCodeEmitter::GPR2AlignEncode(const MCInst &MI,
                                          unsigned OpNo ,
                                        SmallVectorImpl<MCFixup> &Fixup) const {
  return GPRAlign(MI, OpNo, 1);
}

unsigned SIMCCodeEmitter::GPR4AlignEncode(const MCInst &MI,
                                          unsigned OpNo,
                                        SmallVectorImpl<MCFixup> &Fixup) const {
  return GPRAlign(MI, OpNo, 2);
}

#define SMRD_OFFSET_MASK 0xff
#define SMRD_IMM_SHIFT 8
#define SMRD_SBASE_MASK 0x3f
#define SMRD_SBASE_SHIFT 9
/// SMRDmemriEncode - This function is responsibe for encoding the offset
/// and the base ptr for SMRD instructions it should return a bit string in
/// this format:
///
/// OFFSET = bits{7-0}
/// IMM    = bits{8}
/// SBASE  = bits{14-9}
///
uint32_t SIMCCodeEmitter::SMRDmemriEncode(const MCInst &MI, unsigned OpNo,
                                        SmallVectorImpl<MCFixup> &Fixup) const {
  uint32_t Encoding;

  const MCOperand &OffsetOp = MI.getOperand(OpNo + 1);

  //XXX: Use this function for SMRD loads with register offsets
  assert(OffsetOp.isImm());

  Encoding =
      (getMachineOpValue(MI, OffsetOp, Fixup) & SMRD_OFFSET_MASK)
    | (1 << SMRD_IMM_SHIFT) //XXX If the Offset is a register we shouldn't set this bit
    | ((GPR2AlignEncode(MI, OpNo, Fixup) & SMRD_SBASE_MASK) << SMRD_SBASE_SHIFT)
    ;

  return Encoding;
}

//===----------------------------------------------------------------------===//
// Post Encoder Callbacks
//===----------------------------------------------------------------------===//

uint64_t SIMCCodeEmitter::VOPPostEncode(const MCInst &MI, uint64_t Value) const{
  unsigned encodingType = getEncodingType(MI);
  unsigned numSrcOps;
  unsigned vgprBitOffset;

  if (encodingType == SIInstrEncodingType::VOP3) {
    numSrcOps = 3;
    vgprBitOffset = 32;
  } else {
    numSrcOps = 1;
    vgprBitOffset = 0;
  }

  // Add one to skip over the destination reg operand.
  for (unsigned opIdx = 1; opIdx < numSrcOps + 1; opIdx++) {
    const MCOperand &MO = MI.getOperand(opIdx);
    if (MO.isReg()) {
      unsigned reg = MI.getOperand(opIdx).getReg();
      if (AMDGPUMCRegisterClasses[AMDGPU::VReg_32RegClassID].contains(reg) ||
          AMDGPUMCRegisterClasses[AMDGPU::VReg_64RegClassID].contains(reg)) {
        Value |= (VGPR_BIT(opIdx)) << vgprBitOffset;
      }
    } else if (MO.isFPImm()) {
      union {
        float f;
        uint32_t i;
      } Imm;
      // XXX: Not all instructions can use inline literals
      // XXX: We should make sure this is a 32-bit constant
      Imm.f = MO.getFPImm();
      Value |= ((uint64_t)Imm.i) << 32;
    }
  }
  return Value;
}

//===----------------------------------------------------------------------===//
// Encoding helper functions
//===----------------------------------------------------------------------===//

unsigned SIMCCodeEmitter::getEncodingType(const MCInst &MI) const {
  return MCII.get(MI.getOpcode()).TSFlags & SI_INSTR_FLAGS_ENCODING_MASK;
}

unsigned SIMCCodeEmitter::getEncodingBytes(const MCInst &MI) const {

  // These instructions aren't real instructions with an encoding type, so
  // we need to manually specify their size.
  switch (MI.getOpcode()) {
  default: break;
  case AMDGPU::SI_LOAD_LITERAL_I32:
  case AMDGPU::SI_LOAD_LITERAL_F32:
    return 4;
  }

  unsigned encoding_type = getEncodingType(MI);
  switch (encoding_type) {
    case SIInstrEncodingType::EXP:
    case SIInstrEncodingType::LDS:
    case SIInstrEncodingType::MUBUF:
    case SIInstrEncodingType::MTBUF:
    case SIInstrEncodingType::MIMG:
    case SIInstrEncodingType::VOP3:
      return 8;
    default:
      return 4;
  }
}

unsigned SIMCCodeEmitter::getRegBinaryCode(unsigned reg) const {
  switch (reg) {
    case AMDGPU::VCC: return 106;
    case AMDGPU::M0: return 124;
    case AMDGPU::EXEC: return 126;
    case AMDGPU::EXEC_LO: return 126;
    case AMDGPU::EXEC_HI: return 127;
    case AMDGPU::SREG_LIT_0: return 128;
    case AMDGPU::SI_LITERAL_CONSTANT: return 255;
    default: return getHWRegNum(reg);
  }
}

#define SIRegisterInfo SIMCCodeEmitter
#include "SIRegisterGetHWRegNum.inc"
#undef SIRegisterInfo
<|endoftext|>


<commit_before>#include "catch.hpp"
#include <iostream>
//#include "Database_Creator.hpp"
#include "Database_Sorter.hpp"

person readPerson(std::string file_name, size_t index) {
	person result;
	std::ifstream file(file_name);
	for (size_t i = 0; i < index + 1; i++) {
		file >> result;
	}
	file.close();
	return result;
}
bool isANotMoreThanB(person A, person B) {
        char * A_name = A.getName();
        char * B_name = B.getName();
	for (size_t i = 0; i < A.name_length; i++) {
		char A_char = name[i];
		char B_char = (i < B.name_length) ? B_name[i] : ' ';
		if (letterI(A_name[i], i == 0) < letterI(B_name[i], i == 0)) {
			return true;
		}
		else {
			if (A_name[i] != B_name[i]) {
				return false;
			}
		}
	}
        delete []A_char;
        delete []B_char;
	return true;
}

SCENARIO("Sort", "[s]") {
	size_t n_persons = 200;
	//system("start www.cyberforum.ru/cpp-beginners/thread82643.html#post458604");
	size_t RAM_amount = 1;
	std::string names_file_name = "F:\\1\\names.txt";
	std::string surnames_file_name = "F:\\1\\surnames.txt";
	std::string database_file_name = "8.txt";
	std::string output_file_name = "F:\\1\\sorted_database.txt";

	//Database_Creator database_creator(database_file_name, names_file_name, surnames_file_name, n_persons);
	Database_Sorter database_sorter(database_file_name, output_file_name, RAM_amount);
	size_t start = clock();
	database_sorter.sortDatabase();
	size_t result = clock() - start;
	database_sorter.closeDatabase();
	std::cout << result << std::endl;

	for (size_t i = 0; i < 0; i++) {
		size_t person1_i = rand() % n_persons;
		size_t person2_i = person1_i + rand() % (n_persons - person1_i);
		person person1 = readPerson(output_file_name, person1_i);
		person person2 = readPerson(output_file_name, person2_i);
		REQUIRE(isANotMoreThanB(person1, person2));
	}
}
<commit_msg>Update init.cpp<commit_after>#include "catch.hpp"
#include <iostream>
//#include "Database_Creator.hpp"
#include "Database_Sorter.hpp"

person readPerson(std::string file_name, size_t index) {
	person result;
	std::ifstream file(file_name);
	for (size_t i = 0; i < index + 1; i++) {
		file >> result;
	}
	file.close();
	return result;
}
bool isANotMoreThanB(person A, person B) {
        char * A_name = A.getName();
        char * B_name = B.getName();
	for (size_t i = 0; i < A.name_length; i++) {
		char A_char = A_name[i];
		char B_char = (i < B.name_length) ? B_name[i] : ' ';
		if (letterI(A_name[i], i == 0) < letterI(B_name[i], i == 0)) {
			return true;
		}
		else {
			if (A_name[i] != B_name[i]) {
				return false;
			}
		}
	}
        delete []A_name;
        delete []B_name;
	return true;
}

SCENARIO("Sort", "[s]") {
	size_t n_persons = 200;
	//system("start www.cyberforum.ru/cpp-beginners/thread82643.html#post458604");
	size_t RAM_amount = 1;
	std::string names_file_name = "F:\\1\\names.txt";
	std::string surnames_file_name = "F:\\1\\surnames.txt";
	std::string database_file_name = "8.txt";
	std::string output_file_name = "F:\\1\\sorted_database.txt";

	//Database_Creator database_creator(database_file_name, names_file_name, surnames_file_name, n_persons);
	Database_Sorter database_sorter(database_file_name, output_file_name, RAM_amount);
	size_t start = clock();
	database_sorter.sortDatabase();
	size_t result = clock() - start;
	database_sorter.closeDatabase();
	std::cout << result << std::endl;

	for (size_t i = 0; i < 0; i++) {
		size_t person1_i = rand() % n_persons;
		size_t person2_i = person1_i + rand() % (n_persons - person1_i);
		person person1 = readPerson(output_file_name, person1_i);
		person person2 = readPerson(output_file_name, person2_i);
		REQUIRE(isANotMoreThanB(person1, person2));
	}
}
<|endoftext|>


<commit_before>#line 2 "togo/tool_build/package_compiler.hpp"
/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.

@file
@brief PackageCompiler interface.
@ingroup tool_build_package_compiler
*/

#pragma once

#include <togo/tool_build/config.hpp>
#include <togo/string_types.hpp>
#include <togo/string.hpp>
#include <togo/tool_build/types.hpp>

namespace togo {
namespace tool_build {
namespace package_compiler {

/**
	@addtogroup tool_build_package_compiler
	@{
*/

/// Create a package stub.
///
/// This will fail if the path already exists or if any part of the
/// package couldn't be created.
bool create_stub(
	StringRef const& path,
	StringRef const& name
);

/// Get name hash.
inline ResourcePackageNameHash name_hash(
	PackageCompiler const& pkg
) {
	return pkg._name_hash;
}

/// Get name.
inline StringRef name(
	PackageCompiler const& pkg
) {
	return {pkg._name};
}

/// Get path.
inline StringRef path(
	PackageCompiler const& pkg
) {
	return {pkg._path};
}

/// Check if the package is marked as modified.
inline bool modified(
	PackageCompiler const& pkg
) {
	return pkg._modified;
}

/// Mark the package as modified or unmodified.
inline void set_modified(
	PackageCompiler& pkg,
	bool const value
) {
	pkg._modified = value;
}

/// Find lookup node by resource name.
PackageCompiler::LookupNode* get_node(
	PackageCompiler& pkg,
	ResourceNameHash name_hash
);

/// Read package data.
void read(
	PackageCompiler& pkg
);

/// Write package data.
bool write(
	PackageCompiler& pkg
);

/** @} */ // end of doc-group tool_build_package_compiler

} // namespace package_compiler
} // namespace tool_build
} // namespace togo
<commit_msg>tool_build/package_compiler: added metadata accessor.<commit_after>#line 2 "togo/tool_build/package_compiler.hpp"
/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.

@file
@brief PackageCompiler interface.
@ingroup tool_build_package_compiler
*/

#pragma once

#include <togo/tool_build/config.hpp>
#include <togo/string_types.hpp>
#include <togo/string.hpp>
#include <togo/tool_build/types.hpp>

namespace togo {
namespace tool_build {
namespace package_compiler {

/**
	@addtogroup tool_build_package_compiler
	@{
*/

/// Create a package stub.
///
/// This will fail if the path already exists or if any part of the
/// package couldn't be created.
bool create_stub(
	StringRef const& path,
	StringRef const& name
);

/// Get name hash.
inline ResourcePackageNameHash name_hash(
	PackageCompiler const& pkg
) {
	return pkg._name_hash;
}

/// Get name.
inline StringRef name(
	PackageCompiler const& pkg
) {
	return {pkg._name};
}

/// Get path.
inline StringRef path(
	PackageCompiler const& pkg
) {
	return {pkg._path};
}

/// Get resource metadata.
inline Array<ResourceMetadata> const& metadata(
	PackageCompiler const& pkg
) {
	return pkg._metadata;
}

/// Check if the package is marked as modified.
inline bool modified(
	PackageCompiler const& pkg
) {
	return pkg._modified;
}

/// Mark the package as modified or unmodified.
inline void set_modified(
	PackageCompiler& pkg,
	bool const value
) {
	pkg._modified = value;
}

/// Find lookup node by resource name.
PackageCompiler::LookupNode* get_node(
	PackageCompiler& pkg,
	ResourceNameHash name_hash
);

/// Read package data.
void read(
	PackageCompiler& pkg
);

/// Write package data.
bool write(
	PackageCompiler& pkg
);

/** @} */ // end of doc-group tool_build_package_compiler

} // namespace package_compiler
} // namespace tool_build
} // namespace togo
<|endoftext|>


<commit_before>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow/lite/delegates/gpu/common/tasks/softmax1x1.h"

#include <string>

#include "tensorflow/lite/delegates/gpu/common/status.h"
#include "tensorflow/lite/delegates/gpu/common/task/util.h"

namespace tflite {
namespace gpu {

Softmax1x1::Softmax1x1(const OperationDef& definition)
    : GPUOperation(definition) {
  work_group_size_ = int3(32, 1, 1);
  code_ = GetSoftmaxKernelCode(definition_);
}

Softmax1x1::Softmax1x1(Softmax1x1&& kernel) : GPUOperation(std::move(kernel)) {}

Softmax1x1& Softmax1x1::operator=(Softmax1x1&& kernel) {
  if (this != &kernel) {
    GPUOperation::operator=(std::move(kernel));
  }
  return *this;
}

std::string Softmax1x1::GetSoftmaxKernelCode(const OperationDef& op_def) {
  AddSrcTensor("src_tensor", op_def.src_tensors[0]);
  AddDstTensor("dst_tensor", op_def.dst_tensors[0]);
  args_.AddFloat("mask_x");
  args_.AddFloat("mask_y");
  args_.AddFloat("mask_z");
  args_.AddFloat("mask_w");

  std::string c;
  c += "MAIN_FUNCTION($0) {\n";
  if (op_def.IsBatchSupported()) {
    c += "  int batch_id = GLOBAL_ID_1;\n";
    c += "  if (batch_id >= args.dst_tensor.Batch()) return;\n";
    c += "  args.dst_tensor.SetBatchRef(batch_id);\n";
    c += "  args.src_tensor.SetBatchRef(batch_id);\n";
  }
  c += "  float4 mask = INIT_FLOAT4v4(args.mask_x, args.mask_y, args.mask_z, "
       "args.mask_w);\n";
  c +=
      "  float4 maxx4 = INIT_FLOAT4(args.src_tensor.Read<float>(0, 0, 0).x);\n";
  c += "  int tid = LOCAL_ID_0;\n";
  c += "  for (int s = tid; s < args.src_tensor.Slices(); s += 32) {\n";
  c += "    float4 mask_a = s == args.src_tensor.Slices() - 1 ? mask : "
       "INIT_FLOAT4(1.0f);\n";
  c += "    float4 mask_b = INIT_FLOAT4(1.0f) - mask_a;\n";
  c += "    float4 src = args.src_tensor.Read<float>(0, 0, s);\n";
  c += "    src = src * mask_a + mask_b * src.x;\n";
  c += "    maxx4 = max(maxx4, src);\n";
  c += "  }\n";
  c += "  float maximum = max(maxx4.x, maxx4.y);\n";
  c += "  maximum = max(maximum, maxx4.z);\n";
  c += "  maximum = max(maximum, maxx4.w);\n";
  c += "  __local float4 tmp[8];\n";
  c += "  __local float* tmpx1 = (__local float*)tmp;\n";
  c += "  tmpx1[tid] = maximum;\n";
  c += "  LOCAL_MEM_BARRIER;\n";
  c += "  if (tid == 0) {\n";
  c += "    maxx4 = max(tmp[0], tmp[1]);\n";
  c += "    maxx4 = max(maxx4, tmp[2]);\n";
  c += "    maxx4 = max(maxx4, tmp[3]);\n";
  c += "    maxx4 = max(maxx4, tmp[4]);\n";
  c += "    maxx4 = max(maxx4, tmp[5]);\n";
  c += "    maxx4 = max(maxx4, tmp[6]);\n";
  c += "    maxx4 = max(maxx4, tmp[7]);\n";
  c += "    maximum = max(maxx4.x, maxx4.y);\n";
  c += "    maximum = max(maximum, maxx4.z);\n";
  c += "    maximum = max(maximum, maxx4.w);\n";
  c += "    tmpx1[0] = maximum;\n";
  c += "  }\n";
  c += "  LOCAL_MEM_BARRIER;\n";
  c += "  maximum = tmpx1[0];\n";
  c += "  float sum = 0.0f;\n";
  c += "  for (int s = tid; s < args.src_tensor.Slices(); s += 32) {\n";
  c += "    float4 mask_temp = s == args.src_tensor.Slices() - 1 ? mask : "
       "INIT_FLOAT4(1.0f);\n";
  c += "    float4 src = args.src_tensor.Read<float>(0, 0, s) - "
       "INIT_FLOAT4(maximum);\n";
  c += "    sum += dot(mask_temp, exp(src));\n";
  c += "  }\n";
  c += "  LOCAL_MEM_BARRIER;\n";
  c += "  tmpx1[tid] = sum;\n";
  c += "  LOCAL_MEM_BARRIER;\n";
  c += "  if (tid == 0) {\n";
  c += "    sum = dot((float4)(1.0f), tmp[0]);\n";
  c += "    sum += dot((float4)(1.0f), tmp[1]);\n";
  c += "    sum += dot((float4)(1.0f), tmp[2]);\n";
  c += "    sum += dot((float4)(1.0f), tmp[3]);\n";
  c += "    sum += dot((float4)(1.0f), tmp[4]);\n";
  c += "    sum += dot((float4)(1.0f), tmp[5]);\n";
  c += "    sum += dot((float4)(1.0f), tmp[6]);\n";
  c += "    sum += dot((float4)(1.0f), tmp[7]);\n";
  c += "    tmpx1[0] = 1.0f / sum;\n";
  c += "  }\n";
  c += "  LOCAL_MEM_BARRIER;\n";
  c += "  sum = tmpx1[0];\n";
  c += "\n";
  c += "  int dst_s = GLOBAL_ID_0;\n";
  c += "  if (dst_s < args.dst_tensor.Slices()) {\n";
  c += "    float4 src = args.src_tensor.Read<float>(0, 0, dst_s) - "
       "INIT_FLOAT4(maximum);\n";
  c += "    FLT4 res = TO_FLT4(exp(src) * sum);\n";
  c += "    args.dst_tensor.Write(res, 0, 0, dst_s);\n";
  c += "  }\n";
  c += "}\n";
  return c;
}

absl::Status Softmax1x1::BindArguments(ArgumentsBinder* args) {
  float4 mask = GetMaskForLastPlane(src_[0]->Channels());
  RETURN_IF_ERROR(args->SetFloat("mask_x", mask.x));
  RETURN_IF_ERROR(args->SetFloat("mask_y", mask.y));
  RETURN_IF_ERROR(args->SetFloat("mask_z", mask.z));
  RETURN_IF_ERROR(args->SetFloat("mask_w", mask.w));
  return absl::OkStatus();
}

int3 Softmax1x1::GetGridSize() const {
  return int3(dst_[0]->Slices(), dst_[0]->Batch(), 1);
}

Softmax1x1 CreateSoftmax1x1(const OperationDef& definition) {
  return Softmax1x1(definition);
}

}  // namespace gpu
}  // namespace tflite
<commit_msg>Softmax1x1 rewritten to exclude pointers casting.<commit_after>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow/lite/delegates/gpu/common/tasks/softmax1x1.h"

#include <string>
#include <utility>

#include "tensorflow/lite/delegates/gpu/common/status.h"
#include "tensorflow/lite/delegates/gpu/common/task/util.h"

namespace tflite {
namespace gpu {

Softmax1x1::Softmax1x1(const OperationDef& definition)
    : GPUOperation(definition) {
  work_group_size_ = int3(32, 1, 1);
  code_ = GetSoftmaxKernelCode(definition_);
}

Softmax1x1::Softmax1x1(Softmax1x1&& kernel) : GPUOperation(std::move(kernel)) {}

Softmax1x1& Softmax1x1::operator=(Softmax1x1&& kernel) {
  if (this != &kernel) {
    GPUOperation::operator=(std::move(kernel));
  }
  return *this;
}

std::string Softmax1x1::GetSoftmaxKernelCode(const OperationDef& op_def) {
  AddSrcTensor("src_tensor", op_def.src_tensors[0]);
  AddDstTensor("dst_tensor", op_def.dst_tensors[0]);
  args_.AddFloat("mask_x");
  args_.AddFloat("mask_y");
  args_.AddFloat("mask_z");
  args_.AddFloat("mask_w");

  std::string c;
  c += "MAIN_FUNCTION($0) {\n";
  if (op_def.IsBatchSupported()) {
    c += "  int batch_id = GLOBAL_ID_1;\n";
    c += "  if (batch_id >= args.dst_tensor.Batch()) return;\n";
    c += "  args.dst_tensor.SetBatchRef(batch_id);\n";
    c += "  args.src_tensor.SetBatchRef(batch_id);\n";
  }
  c += "  float4 mask = INIT_FLOAT4v4(args.mask_x, args.mask_y, args.mask_z, "
       "args.mask_w);\n";
  c +=
      "  float4 maxx4 = INIT_FLOAT4(args.src_tensor.Read<float>(0, 0, 0).x);\n";
  c += "  int tid = LOCAL_ID_0;\n";
  c += "  for (int s = tid; s < args.src_tensor.Slices(); s += 32) {\n";
  c += "    float4 mask_a = s == args.src_tensor.Slices() - 1 ? mask : "
       "INIT_FLOAT4(1.0f);\n";
  c += "    float4 mask_b = INIT_FLOAT4(1.0f) - mask_a;\n";
  c += "    float4 src = args.src_tensor.Read<float>(0, 0, s);\n";
  c += "    src = src * mask_a + mask_b * src.x;\n";
  c += "    maxx4 = max(maxx4, src);\n";
  c += "  }\n";
  c += "  float maximum = max(maxx4.x, maxx4.y);\n";
  c += "  maximum = max(maximum, maxx4.z);\n";
  c += "  maximum = max(maximum, maxx4.w);\n";
  c += "  __local float loc_mem[32];\n";
  c += "  loc_mem[tid] = maximum;\n";
  c += "  LOCAL_MEM_BARRIER;\n";
  c += "  if (tid % 8 == 0) {\n";
  c += "    maximum = max(loc_mem[tid], loc_mem[tid + 1]);\n";
  c += "    maximum = max(maximum, loc_mem[tid + 2]);\n";
  c += "    maximum = max(maximum, loc_mem[tid + 3]);\n";
  c += "    maximum = max(maximum, loc_mem[tid + 4]);\n";
  c += "    maximum = max(maximum, loc_mem[tid + 5]);\n";
  c += "    maximum = max(maximum, loc_mem[tid + 6]);\n";
  c += "    maximum = max(maximum, loc_mem[tid + 7]);\n";
  c += "    loc_mem[tid] = maximum;\n";
  c += "  }\n";
  c += "  LOCAL_MEM_BARRIER;\n";
  c += "  if (tid == 0) {\n";
  c += "    maximum = max(loc_mem[0], loc_mem[8]);\n";
  c += "    maximum = max(maximum, loc_mem[16]);\n";
  c += "    maximum = max(maximum, loc_mem[24]);\n";
  c += "    loc_mem[0] = maximum;\n";
  c += "  }\n";
  c += "  LOCAL_MEM_BARRIER;\n";
  c += "  maximum = loc_mem[0];\n";
  c += "  float sum = 0.0f;\n";
  c += "  for (int s = tid; s < args.src_tensor.Slices(); s += 32) {\n";
  c += "    float4 mask_temp = s == args.src_tensor.Slices() - 1 ? mask : "
       "INIT_FLOAT4(1.0f);\n";
  c += "    float4 src = args.src_tensor.Read<float>(0, 0, s) - "
       "INIT_FLOAT4(maximum);\n";
  c += "    sum += dot(mask_temp, exp(src));\n";
  c += "  }\n";
  c += "  LOCAL_MEM_BARRIER;\n";
  c += "  loc_mem[tid] = sum;\n";
  c += "  LOCAL_MEM_BARRIER;\n";
  c += "  if (tid % 8 == 0) {\n";
  c += "    sum = loc_mem[tid] + loc_mem[tid + 1];\n";
  c += "    sum += loc_mem[tid + 2];\n";
  c += "    sum += loc_mem[tid + 3];\n";
  c += "    sum += loc_mem[tid + 4];\n";
  c += "    sum += loc_mem[tid + 5];\n";
  c += "    sum += loc_mem[tid + 6];\n";
  c += "    sum += loc_mem[tid + 7];\n";
  c += "    loc_mem[tid] = sum;\n";
  c += "  }\n";
  c += "  LOCAL_MEM_BARRIER;\n";
  c += "  if (tid == 0) {\n";
  c += "    sum = loc_mem[0] + loc_mem[8] + loc_mem[16] + loc_mem[24];\n";
  c += "    loc_mem[0] = 1.0f / sum;\n";
  c += "  }\n";
  c += "  LOCAL_MEM_BARRIER;\n";
  c += "  sum = loc_mem[0];\n";
  c += "\n";
  c += "  int dst_s = GLOBAL_ID_0;\n";
  c += "  if (dst_s < args.dst_tensor.Slices()) {\n";
  c += "    float4 src = args.src_tensor.Read<float>(0, 0, dst_s) - "
       "INIT_FLOAT4(maximum);\n";
  c += "    FLT4 res = TO_FLT4(exp(src) * sum);\n";
  c += "    args.dst_tensor.Write(res, 0, 0, dst_s);\n";
  c += "  }\n";
  c += "}\n";
  return c;
}

absl::Status Softmax1x1::BindArguments(ArgumentsBinder* args) {
  float4 mask = GetMaskForLastPlane(src_[0]->Channels());
  RETURN_IF_ERROR(args->SetFloat("mask_x", mask.x));
  RETURN_IF_ERROR(args->SetFloat("mask_y", mask.y));
  RETURN_IF_ERROR(args->SetFloat("mask_z", mask.z));
  RETURN_IF_ERROR(args->SetFloat("mask_w", mask.w));
  return absl::OkStatus();
}

int3 Softmax1x1::GetGridSize() const {
  return int3(dst_[0]->Slices(), dst_[0]->Batch(), 1);
}

Softmax1x1 CreateSoftmax1x1(const OperationDef& definition) {
  return Softmax1x1(definition);
}

}  // namespace gpu
}  // namespace tflite
<|endoftext|>