<commit_before>///////////////////////////////////////////////////////////////////////////////
//
// CoinQ_blocks.cpp
//
// Copyright (c) 2013 Eric Lombrozo
//
// All Rights Reserved.

#include "CoinQ_blocks.h"

#include <logger/logger.h>

using namespace CoinQ;

bool CoinQBlockTreeMem::setBestChain(ChainHeader& header)
{
    if (header.inBestChain) return false;

    // Retrace back to earliest best block
    std::stack<ChainHeader*> newBestChain;
    ChainHeader* pParent = &header;
    while (!pParent->inBestChain)
    {
        newBestChain.push(pParent);
        pParent = &mHeaderHashMap.at(pParent->prevBlockHash());
    }

    for (auto it = pParent->childHashes.begin(); it != pParent->childHashes.end(); ++it)
    {
        ChainHeader& child = mHeaderHashMap.at(*it);
        if (child.inBestChain)
        {
            unsetBestChain(child);
            break;
        }
    }

    // First set these so we have the most current info.
    mBestHeight = header.height;
    mTotalWork = header.chainWork;

    // Pop back up stack and make this the best chain
    int count = 0;
    while (!newBestChain.empty())
    {
        ChainHeader* pChild = newBestChain.top();
        pChild->inBestChain = true;
        mHeaderHeightMap[pChild->height] = pChild;
        if (count == 0) notifyReorg(*pChild);
        notifyAddBestChain(*pChild);
        newBestChain.pop();
        count++;
    }

    pHead = &header;

    return true;
}

bool CoinQBlockTreeMem::unsetBestChain(ChainHeader& header)
{
    if (!header.inBestChain) return false;

    if (header.height == 0) throw std::runtime_error("Cannot remove genesis block from best chain.");

    ChainHeader* pParent = &mHeaderHashMap.at(header.prevBlockHash());
    if (pParent->inBestChain)
    {
        mBestHeight = pParent->height;
        mTotalWork = pParent->chainWork;
    }
    header.inBestChain = false;
    notifyRemoveBestChain(header);

    pParent = &header;
    while (pParent->childHashes.size() != 0)
    {
        for (auto it = pParent->childHashes.begin(); it != pParent->childHashes.end(); ++it)
        {
            ChainHeader* pChild = &mHeaderHashMap.at(*it);
            if (pChild->inBestChain)
            {
                pParent = pChild;
                mHeaderHeightMap.erase(pChild->height);
                pChild->inBestChain = false;
                notifyRemoveBestChain(*pChild);
                break;
            }
        }
    }
    return true;
}

void CoinQBlockTreeMem::setGenesisBlock(const Coin::CoinBlockHeader& header)
{
    if (mHeaderHashMap.size() != 0) throw std::runtime_error("Tree is not empty.");

    bFlushed = false;
    uchar_vector hash = header.hash();
    ChainHeader& genesisHeader = mHeaderHashMap[hash] = header;
    mHeaderHeightMap[0] = &genesisHeader;
    genesisHeader.height = 0;
    genesisHeader.inBestChain = true;
    genesisHeader.chainWork = genesisHeader.getWork();
    mBestHeight = 0;
    mTotalWork = genesisHeader.chainWork;
    pHead = &genesisHeader;
    notifyInsert(header);
    notifyAddBestChain(header);
}

bool CoinQBlockTreeMem::insertHeader(const Coin::CoinBlockHeader& header, bool bCheckProofOfWork, bool bReplaceTip)
{
    if (mHeaderHashMap.size() == 0) throw std::runtime_error("No genesis block.");

    uchar_vector headerHash = header.hash();
    if (hasHeader(headerHash)) return false;

    header_hash_map_t::iterator it = mHeaderHashMap.find(header.prevBlockHash());
    if (it == mHeaderHashMap.end()) throw std::runtime_error("Parent not found.");

    ChainHeader& parent = it->second;

    // TODO: Check version, compute work required.

    // Check timestamp
/*    if (bCheckTimestamp && header.timestamp > time(NULL) + 2 * 60 * 60) {
        throw std::runtime_error("Timestamp too far in the future.");
    }*/

    // Check proof of work
    if (bCheckProofOfWork && BigInt(header.getPOWHashLittleEndian()) > header.getTarget()) throw std::runtime_error("Header hash is too big.");

    ChainHeader& chainHeader = mHeaderHashMap[headerHash] = header;
    chainHeader.height = parent.height + 1;
    chainHeader.chainWork = parent.chainWork + chainHeader.getWork();
    parent.childHashes.insert(headerHash);
    notifyInsert(chainHeader);

    if ((bReplaceTip && chainHeader.chainWork >= mTotalWork) || chainHeader.chainWork > mTotalWork)
    {
        setBestChain(chainHeader);
    }

    bFlushed = false;
    return true;
}

bool CoinQBlockTreeMem::deleteHeader(const uchar_vector& hash)
{
    header_hash_map_t::iterator it = mHeaderHashMap.find(hash);
    if (it == mHeaderHashMap.end()) return false;

    ChainHeader& header = it->second;
    unsetBestChain(header);
    header_hash_map_t::iterator itParent = mHeaderHashMap.find(header.hash());
    if (itParent == mHeaderHashMap.end()) throw std::runtime_error("Critical error: parent for block not found.");

    // Recurse through children
    for (auto itChild = header.childHashes.begin(); itChild != header.childHashes.end(); ++itChild) { deleteHeader(*itChild); }

    // TODO: Find new best chain if this header was in best chain.

    // Remove header
    ChainHeader& parent = itParent->second;
    unsigned int nErased = parent.childHashes.erase(hash);
    assert(nErased == 1);
    notifyDelete(header);
    mHeaderHashMap.erase(hash);
    bFlushed = false;
    return true;
}

bool CoinQBlockTreeMem::hasHeader(const uchar_vector& hash) const
{
    return (mHeaderHashMap.find(hash) != mHeaderHashMap.end());
}

const ChainHeader& CoinQBlockTreeMem::getHeader(const uchar_vector& hash) const
{
    header_hash_map_t::const_iterator it = mHeaderHashMap.find(hash);
    if (it == mHeaderHashMap.end()) throw std::runtime_error("Not found.");

    return it->second;
}

const ChainHeader& CoinQBlockTreeMem::getHeader(int height) const
{
    if (mHeaderHeightMap.size() > 0)
    {
        if (height < 0) height += mBestHeight + 1;
        if (height >= 0)
        {
            header_height_map_t::const_iterator it = mHeaderHeightMap.find((unsigned int)height);
            if (it != mHeaderHeightMap.end()) return *it->second;
        }
    }

    throw std::runtime_error("Not found.");
}

const ChainHeader& CoinQBlockTreeMem::getTip() const
{
    if (!pHead) throw std::runtime_error("Tree is empty.");

    return *pHead;
}

int CoinQBlockTreeMem::getTipHeight() const
{
    if (!pHead) throw std::runtime_error("Tree is empty.");

    return pHead->height;
}

const ChainHeader& CoinQBlockTreeMem::getHeaderBefore(uint32_t timestamp) const
{
    if (mBestHeight == -1) throw std::runtime_error("Tree is empty.");

    int i;
    for (i = 1; i <= mBestHeight; i++)
    {
        ChainHeader* header = mHeaderHeightMap.at(i);
        if (header->timestamp() > timestamp) break;
    }

    return *mHeaderHeightMap.at(i - 1);
}

std::vector<uchar_vector> CoinQBlockTreeMem::getLocatorHashes(int maxSize = -1) const
{
    std::vector<uchar_vector> locatorHashes;

    if (mBestHeight == -1)
    {
        locatorHashes.push_back(g_zero32bytes);
        return locatorHashes;
    }

    if (maxSize < 0) maxSize = mBestHeight + 1;

    int i = mBestHeight;
    int n = 0;
    int step = 1;
    while ((i >= 0) && (n < maxSize))
    {
        locatorHashes.push_back(mHeaderHeightMap.at(i)->hash());
        i -= step;
        n++;
        if (n > 10) step *= 2;
    }
    return locatorHashes;
}

int CoinQBlockTreeMem::getConfirmations(const uchar_vector& hash) const
{
    header_hash_map_t::const_iterator it = mHeaderHashMap.find(hash);
    if (it == mHeaderHashMap.end() || !it->second.inBestChain) return 0;

    return mBestHeight - it->second.height + 1;
}

void CoinQBlockTreeMem::loadFromFile(const std::string& filename, bool bCheckProofOfWork, CoinQBlockTreeMem::callback_t callback)
{
    boost::filesystem::path p(filename);
    if (!boost::filesystem::exists(p)) throw BlockTreeFileNotFoundException();

    if (!boost::filesystem::is_regular_file(p)) throw BlockTreeInvalidFileTypeException();

    const unsigned int RECORD_SIZE = MIN_COIN_BLOCK_HEADER_SIZE + 4;
    if (boost::filesystem::file_size(p) % RECORD_SIZE != 0) throw BlockTreeInvalidFileLengthException();

#ifndef _WIN32
    std::ifstream fs(p.native(), std::ios::binary);
#else
    std::ifstream fs(filename, std::ios::binary);
#endif
    if (!fs.good()) throw BlockTreeFailedToOpenFileForReadException();

    clear();
    uchar_vector headerBytes;
    uchar_vector hash;
    Coin::CoinBlockHeader header;

    unsigned int count = 0;

    char buf[RECORD_SIZE * 64];
    while (fs)
    {
        fs.read(buf, RECORD_SIZE * 64);
        if (fs.bad()) throw BlockTreeFileReadFailureException();

        unsigned int nbytesread = fs.gcount();
        unsigned int pos = 0;
        for (; pos <= nbytesread - RECORD_SIZE; pos += RECORD_SIZE)
        {
            headerBytes.assign((unsigned char*)&buf[pos], (unsigned char*)&buf[pos + MIN_COIN_BLOCK_HEADER_SIZE]);
            header.setSerialized(headerBytes);
            hash = header.hash();
            if (memcmp(&buf[pos + MIN_COIN_BLOCK_HEADER_SIZE], &hash[0], 4)) throw BlockTreeChecksumErrorException();

            try
            {
                if (mBestHeight >= 0)
                {
                    insertHeader(header, bCheckProofOfWork);
                    if (count % 10000 == 0)
                    {
                        if (callback && !callback(*this)) throw BlockTreeLoadInterruptedException();
                        LOGGER(debug) << "CoinQBlockTreeMem::loadFromFile() - header hash: " << header.hash().getHex() << " height: " << count << std::endl;
                    }
                    count++;
                }
                else
                {
                    setGenesisBlock(header);
                    if (callback && !callback(*this)) throw BlockTreeLoadInterruptedException();
                    LOGGER(debug) << "CoinQBlockTreeMem::loadFromFile() - genesis hash: " << header.hash().getHex() << std::endl;
                    count++;
                }
            }
            catch (const BlockTreeException& e)
            {
                throw e;
            }
            catch (const std::exception& e)
            {
                throw std::runtime_error(std::string("Block ") + hash.getHex() + ": " + e.what());
            }
        }

        if (pos != nbytesread) throw BlockTreeUnexpectedEndOfFileException();
    }

    if (callback) callback(*this); // No need to interrupt since we're done.
}

void CoinQBlockTreeMem::flushToFile(const std::string& filename)
{
    if (mBestHeight == -1) throw std::runtime_error("Tree is empty.");

    boost::filesystem::path swapfile(filename + ".swp");
    //if (boost::filesystem::exists(swapfile)) throw BlockTreeSwapfileAlreadyExistsException();

    {
#ifndef _WIN32
        std::ofstream fs(swapfile.native(), std::ios::binary | std::ios::trunc);
#else
        std::ofstream fs(filename + ".swp", std::ios::binary | std::ios::trunc);
#endif

        uchar_vector headerBytes, hash;

        for (int i = 0; i <= mBestHeight; i++)
        {
            ChainHeader* pHeader = mHeaderHeightMap.at(i);

            headerBytes = pHeader->getSerialized();
            hash = pHeader->hash();

            fs.write((const char*)&headerBytes[0], MIN_COIN_BLOCK_HEADER_SIZE);
            if (fs.bad()) throw BlockTreeFileWriteFailureException();

            fs.write((const char*)&hash[0], 4);
            if (fs.bad()) throw BlockTreeFileWriteFailureException();
        }
    }

    boost::system::error_code ec;
    boost::filesystem::path p(filename);
    boost::filesystem::rename(swapfile, p, ec);
    if (!!ec) throw std::runtime_error(ec.message());

    bFlushed = true;
}

<commit_msg>Log genesis block hash when initializing.<commit_after>///////////////////////////////////////////////////////////////////////////////
//
// CoinQ_blocks.cpp
//
// Copyright (c) 2013 Eric Lombrozo
//
// All Rights Reserved.

#include "CoinQ_blocks.h"

#include <logger/logger.h>

using namespace CoinQ;

bool CoinQBlockTreeMem::setBestChain(ChainHeader& header)
{
    if (header.inBestChain) return false;

    // Retrace back to earliest best block
    std::stack<ChainHeader*> newBestChain;
    ChainHeader* pParent = &header;
    while (!pParent->inBestChain)
    {
        newBestChain.push(pParent);
        pParent = &mHeaderHashMap.at(pParent->prevBlockHash());
    }

    for (auto it = pParent->childHashes.begin(); it != pParent->childHashes.end(); ++it)
    {
        ChainHeader& child = mHeaderHashMap.at(*it);
        if (child.inBestChain)
        {
            unsetBestChain(child);
            break;
        }
    }

    // First set these so we have the most current info.
    mBestHeight = header.height;
    mTotalWork = header.chainWork;

    // Pop back up stack and make this the best chain
    int count = 0;
    while (!newBestChain.empty())
    {
        ChainHeader* pChild = newBestChain.top();
        pChild->inBestChain = true;
        mHeaderHeightMap[pChild->height] = pChild;
        if (count == 0) notifyReorg(*pChild);
        notifyAddBestChain(*pChild);
        newBestChain.pop();
        count++;
    }

    pHead = &header;

    return true;
}

bool CoinQBlockTreeMem::unsetBestChain(ChainHeader& header)
{
    if (!header.inBestChain) return false;

    if (header.height == 0) throw std::runtime_error("Cannot remove genesis block from best chain.");

    ChainHeader* pParent = &mHeaderHashMap.at(header.prevBlockHash());
    if (pParent->inBestChain)
    {
        mBestHeight = pParent->height;
        mTotalWork = pParent->chainWork;
    }
    header.inBestChain = false;
    notifyRemoveBestChain(header);

    pParent = &header;
    while (pParent->childHashes.size() != 0)
    {
        for (auto it = pParent->childHashes.begin(); it != pParent->childHashes.end(); ++it)
        {
            ChainHeader* pChild = &mHeaderHashMap.at(*it);
            if (pChild->inBestChain)
            {
                pParent = pChild;
                mHeaderHeightMap.erase(pChild->height);
                pChild->inBestChain = false;
                notifyRemoveBestChain(*pChild);
                break;
            }
        }
    }
    return true;
}

void CoinQBlockTreeMem::setGenesisBlock(const Coin::CoinBlockHeader& header)
{
    LOGGER(trace) << "setGenesisBlock - hash: " << header.getPOWHashLittleEndian().getHex() << std::endl;
    if (mHeaderHashMap.size() != 0) throw std::runtime_error("Tree is not empty.");

    bFlushed = false;
    uchar_vector hash = header.hash();
    ChainHeader& genesisHeader = mHeaderHashMap[hash] = header;
    mHeaderHeightMap[0] = &genesisHeader;
    genesisHeader.height = 0;
    genesisHeader.inBestChain = true;
    genesisHeader.chainWork = genesisHeader.getWork();
    mBestHeight = 0;
    mTotalWork = genesisHeader.chainWork;
    pHead = &genesisHeader;
    notifyInsert(header);
    notifyAddBestChain(header);
}

bool CoinQBlockTreeMem::insertHeader(const Coin::CoinBlockHeader& header, bool bCheckProofOfWork, bool bReplaceTip)
{
    if (mHeaderHashMap.size() == 0) throw std::runtime_error("No genesis block.");

    uchar_vector headerHash = header.hash();
    if (hasHeader(headerHash)) return false;

    header_hash_map_t::iterator it = mHeaderHashMap.find(header.prevBlockHash());
    if (it == mHeaderHashMap.end()) throw std::runtime_error("Parent not found.");

    ChainHeader& parent = it->second;

    // TODO: Check version, compute work required.

    // Check timestamp
/*    if (bCheckTimestamp && header.timestamp > time(NULL) + 2 * 60 * 60) {
        throw std::runtime_error("Timestamp too far in the future.");
    }*/

    // Check proof of work
    if (bCheckProofOfWork && BigInt(header.getPOWHashLittleEndian()) > header.getTarget()) throw std::runtime_error("Header hash is too big.");

    ChainHeader& chainHeader = mHeaderHashMap[headerHash] = header;
    chainHeader.height = parent.height + 1;
    chainHeader.chainWork = parent.chainWork + chainHeader.getWork();
    parent.childHashes.insert(headerHash);
    notifyInsert(chainHeader);

    if ((bReplaceTip && chainHeader.chainWork >= mTotalWork) || chainHeader.chainWork > mTotalWork)
    {
        setBestChain(chainHeader);
    }

    bFlushed = false;
    return true;
}

bool CoinQBlockTreeMem::deleteHeader(const uchar_vector& hash)
{
    header_hash_map_t::iterator it = mHeaderHashMap.find(hash);
    if (it == mHeaderHashMap.end()) return false;

    ChainHeader& header = it->second;
    unsetBestChain(header);
    header_hash_map_t::iterator itParent = mHeaderHashMap.find(header.hash());
    if (itParent == mHeaderHashMap.end()) throw std::runtime_error("Critical error: parent for block not found.");

    // Recurse through children
    for (auto itChild = header.childHashes.begin(); itChild != header.childHashes.end(); ++itChild) { deleteHeader(*itChild); }

    // TODO: Find new best chain if this header was in best chain.

    // Remove header
    ChainHeader& parent = itParent->second;
    unsigned int nErased = parent.childHashes.erase(hash);
    assert(nErased == 1);
    notifyDelete(header);
    mHeaderHashMap.erase(hash);
    bFlushed = false;
    return true;
}

bool CoinQBlockTreeMem::hasHeader(const uchar_vector& hash) const
{
    return (mHeaderHashMap.find(hash) != mHeaderHashMap.end());
}

const ChainHeader& CoinQBlockTreeMem::getHeader(const uchar_vector& hash) const
{
    header_hash_map_t::const_iterator it = mHeaderHashMap.find(hash);
    if (it == mHeaderHashMap.end()) throw std::runtime_error("Not found.");

    return it->second;
}

const ChainHeader& CoinQBlockTreeMem::getHeader(int height) const
{
    if (mHeaderHeightMap.size() > 0)
    {
        if (height < 0) height += mBestHeight + 1;
        if (height >= 0)
        {
            header_height_map_t::const_iterator it = mHeaderHeightMap.find((unsigned int)height);
            if (it != mHeaderHeightMap.end()) return *it->second;
        }
    }

    throw std::runtime_error("Not found.");
}

const ChainHeader& CoinQBlockTreeMem::getTip() const
{
    if (!pHead) throw std::runtime_error("Tree is empty.");

    return *pHead;
}

int CoinQBlockTreeMem::getTipHeight() const
{
    if (!pHead) throw std::runtime_error("Tree is empty.");

    return pHead->height;
}

const ChainHeader& CoinQBlockTreeMem::getHeaderBefore(uint32_t timestamp) const
{
    if (mBestHeight == -1) throw std::runtime_error("Tree is empty.");

    int i;
    for (i = 1; i <= mBestHeight; i++)
    {
        ChainHeader* header = mHeaderHeightMap.at(i);
        if (header->timestamp() > timestamp) break;
    }

    return *mHeaderHeightMap.at(i - 1);
}

std::vector<uchar_vector> CoinQBlockTreeMem::getLocatorHashes(int maxSize = -1) const
{
    std::vector<uchar_vector> locatorHashes;

    if (mBestHeight == -1)
    {
        locatorHashes.push_back(g_zero32bytes);
        return locatorHashes;
    }

    if (maxSize < 0) maxSize = mBestHeight + 1;

    int i = mBestHeight;
    int n = 0;
    int step = 1;
    while ((i >= 0) && (n < maxSize))
    {
        locatorHashes.push_back(mHeaderHeightMap.at(i)->hash());
        i -= step;
        n++;
        if (n > 10) step *= 2;
    }
    return locatorHashes;
}

int CoinQBlockTreeMem::getConfirmations(const uchar_vector& hash) const
{
    header_hash_map_t::const_iterator it = mHeaderHashMap.find(hash);
    if (it == mHeaderHashMap.end() || !it->second.inBestChain) return 0;

    return mBestHeight - it->second.height + 1;
}

void CoinQBlockTreeMem::loadFromFile(const std::string& filename, bool bCheckProofOfWork, CoinQBlockTreeMem::callback_t callback)
{
    boost::filesystem::path p(filename);
    if (!boost::filesystem::exists(p)) throw BlockTreeFileNotFoundException();

    if (!boost::filesystem::is_regular_file(p)) throw BlockTreeInvalidFileTypeException();

    const unsigned int RECORD_SIZE = MIN_COIN_BLOCK_HEADER_SIZE + 4;
    if (boost::filesystem::file_size(p) % RECORD_SIZE != 0) throw BlockTreeInvalidFileLengthException();

#ifndef _WIN32
    std::ifstream fs(p.native(), std::ios::binary);
#else
    std::ifstream fs(filename, std::ios::binary);
#endif
    if (!fs.good()) throw BlockTreeFailedToOpenFileForReadException();

    clear();
    uchar_vector headerBytes;
    uchar_vector hash;
    Coin::CoinBlockHeader header;

    unsigned int count = 0;

    char buf[RECORD_SIZE * 64];
    while (fs)
    {
        fs.read(buf, RECORD_SIZE * 64);
        if (fs.bad()) throw BlockTreeFileReadFailureException();

        unsigned int nbytesread = fs.gcount();
        unsigned int pos = 0;
        for (; pos <= nbytesread - RECORD_SIZE; pos += RECORD_SIZE)
        {
            headerBytes.assign((unsigned char*)&buf[pos], (unsigned char*)&buf[pos + MIN_COIN_BLOCK_HEADER_SIZE]);
            header.setSerialized(headerBytes);
            hash = header.hash();
            if (memcmp(&buf[pos + MIN_COIN_BLOCK_HEADER_SIZE], &hash[0], 4)) throw BlockTreeChecksumErrorException();

            try
            {
                if (mBestHeight >= 0)
                {
                    insertHeader(header, bCheckProofOfWork);
                    if (count % 10000 == 0)
                    {
                        if (callback && !callback(*this)) throw BlockTreeLoadInterruptedException();
                        LOGGER(debug) << "CoinQBlockTreeMem::loadFromFile() - header hash: " << header.hash().getHex() << " height: " << count << std::endl;
                    }
                    count++;
                }
                else
                {
                    setGenesisBlock(header);
                    if (callback && !callback(*this)) throw BlockTreeLoadInterruptedException();
                    LOGGER(debug) << "CoinQBlockTreeMem::loadFromFile() - genesis hash: " << header.hash().getHex() << std::endl;
                    count++;
                }
            }
            catch (const BlockTreeException& e)
            {
                throw e;
            }
            catch (const std::exception& e)
            {
                throw std::runtime_error(std::string("Block ") + hash.getHex() + ": " + e.what());
            }
        }

        if (pos != nbytesread) throw BlockTreeUnexpectedEndOfFileException();
    }

    if (callback) callback(*this); // No need to interrupt since we're done.
}

void CoinQBlockTreeMem::flushToFile(const std::string& filename)
{
    if (mBestHeight == -1) throw std::runtime_error("Tree is empty.");

    boost::filesystem::path swapfile(filename + ".swp");
    //if (boost::filesystem::exists(swapfile)) throw BlockTreeSwapfileAlreadyExistsException();

    {
#ifndef _WIN32
        std::ofstream fs(swapfile.native(), std::ios::binary | std::ios::trunc);
#else
        std::ofstream fs(filename + ".swp", std::ios::binary | std::ios::trunc);
#endif

        uchar_vector headerBytes, hash;

        for (int i = 0; i <= mBestHeight; i++)
        {
            ChainHeader* pHeader = mHeaderHeightMap.at(i);

            headerBytes = pHeader->getSerialized();
            hash = pHeader->hash();

            fs.write((const char*)&headerBytes[0], MIN_COIN_BLOCK_HEADER_SIZE);
            if (fs.bad()) throw BlockTreeFileWriteFailureException();

            fs.write((const char*)&hash[0], 4);
            if (fs.bad()) throw BlockTreeFileWriteFailureException();
        }
    }

    boost::system::error_code ec;
    boost::filesystem::path p(filename);
    boost::filesystem::rename(swapfile, p, ec);
    if (!!ec) throw std::runtime_error(ec.message());

    bFlushed = true;
}

<|endoftext|>


<commit_before>#include "occaParser.hpp"

namespace occa {
  namespace parserNamespace {
    namespace expType {
      const int root        = (1 << 0);

      const int L           = (1 << 1);
      const int C           = (1 << 2);
      const int R           = (1 << 3);

      const int notOperator = (32 << 4);
      const int type        = (1  << 4);
      const int presetValue = (1  << 5);
      const int variable    = (1  << 6);
      const int function    = (1  << 7);
      const int pFunction   = (1  << 8);
    };

    class expNode {
    public:
      std::string value;
      int info;

      expNode *up;

      int leafCount;
      expNode **leaves;
      varInfo *var;
      typeDef *type;

      expNode() :
        value(""),
        info(expType::root),

        up(NULL),

        leafCount(0),
        leaves(NULL),
        var(NULL),
        type(NULL) {}

      void loadFromNode(strNode *n){
        strNode *nodeRoot = (!(info & expType::root) ? n : n->clone());
        strNode *nodePos  = nodeRoot;

        while(nodePos){
          leafCount += (1 + nodePos->down.size());
          nodePos = nodePos->right;
        }

        if(leafCount == 0)
          return;

        nodePos = nodeRoot;

        leaves = new expNode*[leafCount];
        leafCount = 0;

        while(nodePos){
          expNode *&leaf = leaves[leafCount++];

          leaf        = new expNode;
          leaf->up    = this;
          leaf->value = nodePos->value;

          if(nodePos->type & unknownVariable)
            leaf->info = expType::variable;
          else if(nodePos->type & presetValue)
            leaf->info = expType::presetValue;

          const int downCount = nodePos->down.size();

          for(int i = 0; i < downCount; ++i){
            strNode *downNode = nodePos->down[i];
            strNode *lastDown = lastNode(downNode);

            std::string sValue = downNode->value;

            // Get rid of ()'s and stuff
            popAndGoRight(downNode);
            popAndGoLeft(lastDown);

            expNode *&sLeaf = leaves[leafCount++];

            sLeaf        = new expNode;
            sLeaf->value = sValue;
            sLeaf->info  = expType::C;

            // Case: ()
            if(lastDown != NULL)
              sLeaf->loadFromNode(downNode);
          }

          nodePos = nodePos->right;
        }

        organizeLeaves();

        // [-] Need to free clone();
      }

      class int2 {
        int x, y;

        friend bool operator < (const int2 &a, const int2 &b){
          if(a.x != b.x)
            return (a.x < b.x);

          return (a.y < b.y);
        }
      };

      void organizeLeaves(){
        //---[ Level 0 ]------
        // [a][::][b]
        mergeNamespaces();
        //====================

        //---[ Level 1 ]------
        // class(...), class{1,2,3}
        markClassConstructs();

        // static_cast<>()
        markCasts();

        // func()
        markFunctionCalls();

        organizeLeaves(1);
        //====================

        //---[ Level 2 ]------
        // (class) x
        markClassCasts();

        // sizeof x
        mergeSizeOf();

        // new, new [], delete, delete []
        mergeNewsAndDeletes();

        organizeLeaves(2);
        //====================

        //---[ Level 3-14 ]---
        for(int i = 3; i <= 14; ++i)
          organizeLeaves(i);
        //====================

        //---[ Level 15 ]-----
        // throw x
        mergeThrows();
        //====================

        //---[ Level 16 ]-----
        organizeLeaves(16);
        //====================
      }

      void organizeLeaves(const int level){
        int leafPos = 0;

        while(leafPos < leafCount){
          if(leaves[leafPos]->leafCount){
            ++leafPos;
            continue;
          }

          opLevelMapIterator it = opLevelMap[level].find(leaves[leafPos]->value);

          if(it == opLevelMap[level].end()){
            ++leafPos;
            continue;
          }

          const int levelType = it->second;

          if(levelType & unitaryOperatorType){
            bool updateNow = true;

            // Cases:  1 + [-]1
            //         (+1)
            if((leaves[leafPos]->value.size() == 1) &&
               ((leaves[leafPos]->value[0] == '+') ||
                (leaves[leafPos]->value[0] == '-'))){

              if(leafPos &&
                 !(leaves[leafPos - 1]->info & expType::notOperator))
                updateNow = false;
            }

            if(updateNow){
              if(levelType & lUnitaryOperatorType)
                leafPos = mergeLeftUnary(leafPos);
              else
                leafPos = mergeRightUnary(leafPos);
            }
            else
              ++leafPos;
          }
          else if(levelType & binaryOperatorType)
            leafPos = mergeBinary(leafPos);
          else if(levelType & ternaryOperatorType)
            leafPos = mergeTernary(leafPos);
          else
            ++leafPos;
        }
      }

      void mergeNamespaces(){
      }

      // class(...), class{1,2,3}
      void markClassConstructs(){
      }

      // static_cast<>()
      void markCasts(){
      }

      // func()
      void markFunctionCalls(){
      }

      // (class) x
      void markClassCasts(){
      }

      // sizeof x
      void mergeSizeOf(){
      }

      // new, new [], delete, delete []
      void mergeNewsAndDeletes(){
      }

      // throw x
      void mergeThrows(){
      }

      // [++]i
      int mergeLeftUnary(const int leafPos){
        expNode *leaf  = leaves[leafPos];
        expNode *sLeaf = leaves[leafPos + 1];

        for(int i = (leafPos + 1); i < leafCount; ++i)
          leaves[i - 1] = leaves[i];

        --leafCount;

        leaf->leafCount = 1;
        leaf->info      = expType::L;

        leaf->leaves    = new expNode*[1];
        leaf->leaves[0] = sLeaf;

        return (leafPos + 1);
      }

      // i[++]
      int mergeRightUnary(const int leafPos){
        expNode *leaf  = leaves[leafPos];
        expNode *sLeaf = leaves[leafPos - 1];

        leaves[leafPos - 1] = leaf;

        --leafCount;

        for(int i = leafPos; i < leafCount; ++i)
          leaves[i] = leaves[i + 1];

        leaf->leafCount = 1;
        leaf->info      = expType::R;

        leaf->leaves    = new expNode*[1];
        leaf->leaves[0] = sLeaf;

        sLeaf->up = leaf;

        return (leafPos + 1);
      }

      // a [+] b
      int mergeBinary(const int leafPos){
        expNode *leaf   = leaves[leafPos];
        expNode *sLeafL = leaves[leafPos - 1];
        expNode *sLeafR = leaves[leafPos + 1];

        leaves[leafPos - 1] = leaf;

        leafCount -= 2;

        for(int i = leafPos; i < leafCount; ++i)
          leaves[i] = leaves[i + 2];

        leaf->leafCount = 2;
        leaf->info      = (expType::L | expType::R);

        leaf->leaves    = new expNode*[2];
        leaf->leaves[0] = sLeafL;
        leaf->leaves[1] = sLeafR;

        sLeafL->up = leaf;
        sLeafR->up = leaf;

        return leafPos;
      }

      // a [?] b : c
      int mergeTernary(const int leafPos){
        expNode *leaf   = leaves[leafPos];
        expNode *sLeafL = leaves[leafPos - 1];
        expNode *sLeafC = leaves[leafPos + 1];
        expNode *sLeafR = leaves[leafPos + 3];

        leaves[leafPos - 1] = leaf;

        leafCount -= 4;

        for(int i = leafPos; i < leafCount; ++i)
          leaves[i] = leaves[i + 4];

        leaf->leafCount = 3;
        leaf->info      = (expType::L | expType::C | expType::R);

        leaf->leaves    = new expNode*[3];
        leaf->leaves[0] = sLeafL;
        leaf->leaves[1] = sLeafC;
        leaf->leaves[2] = sLeafR;

        sLeafL->up = leaf;
        sLeafC->up = leaf;
        sLeafR->up = leaf;

        return leafPos;
      }

      void print(const std::string &tab = ""){
        std::cout << tab << value << '\n';

        for(int i = 0; i < leafCount; ++i)
          leaves[i]->print(tab + "  ");
      }

      friend std::ostream& operator << (std::ostream &out, const expNode &n){

        switch(n.info){
        case (expType::root):{
          for(int i = 0; i < n.leafCount; ++i)
            out << *(n.leaves[i]);

          break;
        }

        case (expType::L):{
          out << n.value << *(n.leaves[0]);

          break;
        }
        case (expType::R):{
          out << *(n.leaves[0]) << n.value;

          break;
        }
        case (expType::L | expType::R):{
          out << *(n.leaves[0]) << n.value << *(n.leaves[1]);

          break;
        }
        case (expType::L | expType::C | expType::R):{
          out << *(n.leaves[0]) << '?' << *(n.leaves[1]) << ':' << *(n.leaves[2]);

          break;
        }
        case expType::C:{
          const char startChar = n.value[0];

          out << startChar;

          for(int i = 0; i < n.leafCount; ++i)
            out << *(n.leaves[i]);

          out << (char) ((')' * (startChar == '(')) +
                         (']' * (startChar == '[')) +
                         ('}' * (startChar == '{')));

          break;
        }

        case expType::type:{
        }
        case expType::presetValue:{
          out << n.value;
          break;
        }
        case expType::variable:{
          out << n.value;
          break;
        }
        case expType::function:{
        }
        case expType::pFunction:{
        }
        }

        return out;
      }
    };

    void test(){
      strNode *n = labelCode( splitContent("(1+2*3%2|1+10&3^1)") );

      expNode expRoot;
      expRoot.loadFromNode(n);

      std::cout
        << "expRoot = " << expRoot << '\n';

      expRoot.print();

      throw 1;
    }
  };
};

int main(int argc, char **argv){
  occa::parserNamespace::test();

  // {
  //   occa::parser parser;
  //   std::string parsedContent = parser.parseFile("tests/test.cpp");
  //   std::cout << parsedContent << '\n';
  // }

  // {
  //   occa::parser parser;
  //   std::string parsedContent = parser.parseFile("tests/openclTest.cpp");
  //   std::cout << parsedContent << '\n';
  // }

  // {
  //   occa::parser parser;
  //   std::string parsedContent = parser.parseFile("tests/cudaTest.cpp");
  //   std::cout << parsedContent << '\n';
  // }

  // {
  //   occa::parser parser;
  //   std::string parsedContent = parser.parseFile("tests/midg.okl");
  //   std::cout << parsedContent << '\n';
  // }

  {
    occa::parser parser;
    std::string parsedContent = parser.parseFile("tests/cleanTest.c");
    std::cout << parsedContent << '\n';
  }

  // {
  //   occa::parser parser;
  //   std::string parsedContent = parser.parseFile("tests/clangTest.c");
  //   std::cout << parsedContent << '\n';
  // }

  // {
  //   occa::parser parser;
  //   std::string parsedContent = parser.parseFile("tests/addVectors.okl");
  //   std::cout << parsedContent << '\n';
  // }

  // {
  //   occa::parser parser;
  //   std::string parsedContent = parser.parseFile("tests/PCGpart1.cl");
  //   std::cout << parsedContent << '\n';
  // }
}
<commit_msg>[Parser] Added qualifier and type merging<commit_after>#include "occaParser.hpp"

namespace occa {
  namespace parserNamespace {
    namespace expType {
      const int root        = (1 << 0);

      const int LCR         = (7 << 1);
      const int L           = (1 << 1);
      const int C           = (1 << 2);
      const int R           = (1 << 3);

      const int qualifier   = (1 << 4);
      const int type        = (1 << 5);
      const int presetValue = (1 << 6);
      const int variable    = (1 << 7);
      const int function    = (1 << 8);
      const int pFunction   = (1 << 9);
    };

    class expNode {
    public:
      std::string value;
      int info;

      expNode *up;

      int leafCount;
      expNode **leaves;
      varInfo *var;
      typeDef *type;

      expNode() :
        value(""),
        info(expType::root),

        up(NULL),

        leafCount(0),
        leaves(NULL),
        var(NULL),
        type(NULL) {}

      void loadFromNode(strNode *n){
        strNode *nClone = n->clone();
        initLoadFromNode(nClone);

        initOrganization();
        organizeLeaves();

        // [-] Need to free nClone;
      }

      void initLoadFromNode(strNode *n){
        strNode *nodeRoot = n;
        strNode *nodePos  = nodeRoot;

        while(nodePos){
          leafCount += (1 + nodePos->down.size());
          nodePos = nodePos->right;
        }

        if(leafCount == 0)
          return;

        nodePos = nodeRoot;

        leaves = new expNode*[leafCount];
        leafCount = 0;

        while(nodePos){
          expNode *&leaf = leaves[leafCount++];

          leaf        = new expNode;
          leaf->up    = this;
          leaf->value = nodePos->value;

          if(nodePos->type & unknownVariable){
            leaf->info = expType::variable;
          }

          else if(nodePos->type & presetValue){
            leaf->info = expType::presetValue;
          }

          else if(nodePos->type & descriptorType){
            // Case const int [*] const [*] a;
            if(nodePos->type & operatorType){
              // [--] Check for custom variable-type when
              //        putting this in parser
              if(nodePos->left &&
                 (nodePos->left->type & qualifierType)){

                leaf->info = expType::qualifier;
              }
            }
            else{
              if(nodePos->type & qualifierType)
                leaf->info = expType::qualifier;
              else
                leaf->info = expType::type;
            }
          }

          else{
            const int downCount = nodePos->down.size();

            for(int i = 0; i < downCount; ++i){
              strNode *downNode = nodePos->down[i];
              strNode *lastDown = lastNode(downNode);

              std::string sValue = downNode->value;

              // Get rid of ()'s and stuff
              popAndGoRight(downNode);
              popAndGoLeft(lastDown);

              expNode *&sLeaf = leaves[leafCount++];

              sLeaf        = new expNode;
              sLeaf->value = sValue;
              sLeaf->info  = expType::C;

              // Case: ()
              if(lastDown != NULL)
                sLeaf->initLoadFromNode(downNode);
            }
          }

          nodePos = nodePos->right;
        }
      }

      void initOrganization(){
        // Init ()'s bottom -> up
        for(int i = 0; i < leafCount; ++i){
          if(leaves[i]->leafCount)
            leaves[i]->initOrganization();
        }

        //---[ Level 0 ]------
        // [a][::][b]
        mergeNamespaces();

        // [const] int [*] x
        mergeQualifiers();

        // [[const] [int] [*]] x
        mergeTypes();

        // [qualifiers] [type] (*[name]) ([args])
        mergeFunctionPointers();
        //====================
      }

      void organizeLeaves(){
        // Organize leaves bottom -> up
        for(int i = 0; i < leafCount; ++i){
          if(leaves[i]->leafCount)
            leaves[i]->organizeLeaves();
        }

        //---[ Level 1 ]------
        // class(...), class{1,2,3}
        mergeClassConstructs();

        // static_cast<>()
        mergeCasts();

        // func()
        mergeFunctionCalls();

        organizeLeaves(1);
        //====================

        //---[ Level 2 ]------
        // (class) x
        mergeClassCasts();

        // sizeof x
        mergeSizeOf();

        // new, new [], delete, delete []
        mergeNewsAndDeletes();

        organizeLeaves(2);
        //====================

        //---[ Level 3-14 ]---
        for(int i = 3; i <= 14; ++i)
          organizeLeaves(i);
        //====================

        //---[ Level 15 ]-----
        // throw x
        mergeThrows();
        //====================

        //---[ Level 16 ]-----
        organizeLeaves(16);
        //====================
      }

      void organizeLeaves(const int level){
        int leafPos = 0;

        while(leafPos < leafCount){
          if(leaves[leafPos]->leafCount){
            ++leafPos;
            continue;
          }

          opLevelMapIterator it = opLevelMap[level].find(leaves[leafPos]->value);

          if(it == opLevelMap[level].end()){
            ++leafPos;
            continue;
          }

          const int levelType = it->second;

          if(levelType & unitaryOperatorType){
            bool updateNow = true;

            // Cases:  1 + [-]1
            //         (+1)
            if((leaves[leafPos]->value.size() == 1) &&
               ((leaves[leafPos]->value[0] == '+') ||
                (leaves[leafPos]->value[0] == '-'))){

              if(leafPos &&
                 !(leaves[leafPos - 1]->info & expType::LCR))
                updateNow = false;
            }

            if(updateNow){
              if(levelType & lUnitaryOperatorType)
                leafPos = mergeLeftUnary(leafPos);
              else
                leafPos = mergeRightUnary(leafPos);
            }
            else
              ++leafPos;
          }
          else if(levelType & binaryOperatorType)
            leafPos = mergeBinary(leafPos);
          else if(levelType & ternaryOperatorType)
            leafPos = mergeTernary(leafPos);
          else
            ++leafPos;
        }
      }

      int mergeRange(const int newLeafType,
                     const int leafPosStart,
                     const int leafPosEnd){
        expNode *newLeaf = new expNode;

        newLeaf->up        = this;
        newLeaf->info      = newLeafType;
        newLeaf->leafCount = (leafPosEnd - leafPosStart + 1);
        newLeaf->leaves    = new expNode*[newLeaf->leafCount];

        for(int i = 0; i < newLeaf->leafCount; ++i)
          newLeaf->leaves[i] = leaves[leafPosStart + i];

        leaves[leafPosStart] = newLeaf;

        for(int i = (leafPosEnd + 1); i < leafCount; ++i)
          leaves[leafPosStart + i - leafPosEnd] = leaves[i];

        leafCount -= (newLeaf->leafCount - 1);

        return (leafPosStart + 1);
      }

      // [a][::][b]
      void mergeNamespaces(){
      }

      int mergeNamespace(const int leafPos){
        return 0;
      }

      // [const] int x
      void mergeQualifiers(){
        int leafPos = 0;

        while(leafPos < leafCount){
          if(leaves[leafPos]->info & expType::qualifier){
            int leafPosStart = leafPos;
            int leafPosEnd   = leafPos;

            while((leafPosEnd < leafCount) &&
                  (leaves[leafPosEnd]->info & expType::qualifier))
              ++leafPosEnd;

            --leafPosEnd;

            leafPos = mergeRange(expType::qualifier,
                                 leafPosStart, leafPosEnd);
          }
          else
            ++leafPos;
        }
      }

      // [[const] [int] [*]] x
      void mergeTypes(){
        int leafPos = 0;

        while(leafPos < leafCount){
          if(leaves[leafPos]->info & expType::type){
            int leafPosStart = leafPos;
            int leafPosEnd   = leafPos;

            if(leafPos &&
               (leaves[leafPos - 1]->info & expType::qualifier)){

              --leafPosStart;
            }

            if(((leafPos + 1) < leafCount) &&
               (leaves[leafPos + 1]->info & expType::qualifier)){

              ++leafPosEnd;
            }

            leafPos = mergeRange(expType::type,
                                 leafPosStart, leafPosEnd);
          }
          else
            ++leafPos;
        }
      }

      // [qualifiers] [type] (*[name]) ([args])
      void mergeFunctionPointers(){
        // int leafPos = 0;

        // while(leafPos < leafCount){
        //   if(leaves[leafPos]->leafCount){
        //     ++leafPos;
        //     continue;
        //   }
        // }
      }

      int mergeFunctionPointer(const int leafPos){
        return 0;
      }

      // class(...), class{1,2,3}
      void mergeClassConstructs(){
      }

      // static_cast<>()
      void mergeCasts(){
      }

      // func()
      void mergeFunctionCalls(){
      }

      // (class) x
      void mergeClassCasts(){
      }

      // sizeof x
      void mergeSizeOf(){
      }

      // new, new [], delete, delete []
      void mergeNewsAndDeletes(){
      }

      // throw x
      void mergeThrows(){
      }

      // [++]i
      int mergeLeftUnary(const int leafPos){
        expNode *leaf  = leaves[leafPos];
        expNode *sLeaf = leaves[leafPos + 1];

        for(int i = (leafPos + 1); i < leafCount; ++i)
          leaves[i - 1] = leaves[i];

        --leafCount;

        leaf->info      = expType::L;
        leaf->leafCount = 1;
        leaf->leaves    = new expNode*[1];
        leaf->leaves[0] = sLeaf;

        sLeaf->up = leaf;

        return (leafPos + 1);
      }

      // i[++]
      int mergeRightUnary(const int leafPos){
        expNode *leaf  = leaves[leafPos];
        expNode *sLeaf = leaves[leafPos - 1];

        leaves[leafPos - 1] = leaf;

        --leafCount;

        for(int i = leafPos; i < leafCount; ++i)
          leaves[i] = leaves[i + 1];

        leaf->info      = expType::R;
        leaf->leafCount = 1;
        leaf->leaves    = new expNode*[1];
        leaf->leaves[0] = sLeaf;

        sLeaf->up = leaf;

        return (leafPos + 1);
      }

      // a [+] b
      int mergeBinary(const int leafPos){
        expNode *leaf   = leaves[leafPos];
        expNode *sLeafL = leaves[leafPos - 1];
        expNode *sLeafR = leaves[leafPos + 1];

        leaves[leafPos - 1] = leaf;

        leafCount -= 2;

        for(int i = leafPos; i < leafCount; ++i)
          leaves[i] = leaves[i + 2];

        leaf->info      = (expType::L | expType::R);
        leaf->leafCount = 2;
        leaf->leaves    = new expNode*[2];
        leaf->leaves[0] = sLeafL;
        leaf->leaves[1] = sLeafR;

        sLeafL->up = leaf;
        sLeafR->up = leaf;

        return leafPos;
      }

      // a [?] b : c
      int mergeTernary(const int leafPos){
        expNode *leaf   = leaves[leafPos];
        expNode *sLeafL = leaves[leafPos - 1];
        expNode *sLeafC = leaves[leafPos + 1];
        expNode *sLeafR = leaves[leafPos + 3];

        leaves[leafPos - 1] = leaf;

        leafCount -= 4;

        for(int i = leafPos; i < leafCount; ++i)
          leaves[i] = leaves[i + 4];

        leaf->info      = (expType::L | expType::C | expType::R);
        leaf->leafCount = 3;
        leaf->leaves    = new expNode*[3];
        leaf->leaves[0] = sLeafL;
        leaf->leaves[1] = sLeafC;
        leaf->leaves[2] = sLeafR;

        sLeafL->up = leaf;
        sLeafC->up = leaf;
        sLeafR->up = leaf;

        return leafPos;
      }

      void print(const std::string &tab = ""){
        std::cout << tab << "| " << value << '\n';

        for(int i = 0; i < leafCount; ++i)
          leaves[i]->print(tab + "  ");
      }

      friend std::ostream& operator << (std::ostream &out, const expNode &n){

        switch(n.info){
        case (expType::root):{
          for(int i = 0; i < n.leafCount; ++i)
            out << *(n.leaves[i]);

          break;
        }

        case (expType::L):{
          out << n.value << *(n.leaves[0]);

          break;
        }
        case (expType::R):{
          out << *(n.leaves[0]) << n.value;

          break;
        }
        case (expType::L | expType::R):{
          out << *(n.leaves[0]) << n.value << *(n.leaves[1]);

          break;
        }
        case (expType::L | expType::C | expType::R):{
          out << *(n.leaves[0]) << '?' << *(n.leaves[1]) << ':' << *(n.leaves[2]);

          break;
        }
        case expType::C:{
          const char startChar = n.value[0];

          out << startChar;

          for(int i = 0; i < n.leafCount; ++i)
            out << *(n.leaves[i]);

          out << (char) ((')' * (startChar == '(')) +
                         (']' * (startChar == '[')) +
                         ('}' * (startChar == '{')));

          break;
        }

        case expType::qualifier:{
          if(n.leafCount){
            for(int i = 0; i < (n.leafCount - 1); ++i)
              out << *(n.leaves[i]) << ' ';

            out << *(n.leaves[n.leafCount - 1]);
          }
          else
            out << n.value;

          break;
        }
        case expType::type:{
          // [const] [int] [*]
          if(n.leafCount){
            for(int i = 0; i < (n.leafCount - 1); ++i)
              out << *(n.leaves[i]) << ' ';

            out << *(n.leaves[n.leafCount - 1]);
          }
          // [int]
          else
            out << n.value;

          break;
        }
        case expType::presetValue:{
          out << n.value;

          break;
        }
        case expType::variable:{
          out << n.value;

          break;
        }
        case expType::function:{

          break;
        }
        case expType::pFunction:{

          break;
        }
        };

        return out;
      }
    };

    void test(){
      strNode *n = labelCode( splitContent("const int") );
      // strNode *n = labelCode( splitContent("(1+2*3%2|1+10&3^1)") );

      expNode expRoot;
      expRoot.loadFromNode(n);

      std::cout
        << "expRoot = " << expRoot << '\n';

      expRoot.print();

      throw 1;
    }
  };
};

int main(int argc, char **argv){
  occa::parserNamespace::test();

  // {
  //   occa::parser parser;
  //   std::string parsedContent = parser.parseFile("tests/test.cpp");
  //   std::cout << parsedContent << '\n';
  // }

  // {
  //   occa::parser parser;
  //   std::string parsedContent = parser.parseFile("tests/openclTest.cpp");
  //   std::cout << parsedContent << '\n';
  // }

  // {
  //   occa::parser parser;
  //   std::string parsedContent = parser.parseFile("tests/cudaTest.cpp");
  //   std::cout << parsedContent << '\n';
  // }

  // {
  //   occa::parser parser;
  //   std::string parsedContent = parser.parseFile("tests/midg.okl");
  //   std::cout << parsedContent << '\n';
  // }

  {
    occa::parser parser;
    std::string parsedContent = parser.parseFile("tests/cleanTest.c");
    std::cout << parsedContent << '\n';
  }

  // {
  //   occa::parser parser;
  //   std::string parsedContent = parser.parseFile("tests/clangTest.c");
  //   std::cout << parsedContent << '\n';
  // }

  // {
  //   occa::parser parser;
  //   std::string parsedContent = parser.parseFile("tests/addVectors.okl");
  //   std::cout << parsedContent << '\n';
  // }

  // {
  //   occa::parser parser;
  //   std::string parsedContent = parser.parseFile("tests/PCGpart1.cl");
  //   std::cout << parsedContent << '\n';
  // }
}
<|endoftext|>


<commit_before>#include <QtCore>
#include "token.h"
#include "scanner.h"
#include "myexception.h"
#include "command_line.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    try {

        if (argc < 2)
            throw MyException("Wrong argument count");
        QString targetFile = argv[1];

        for (int i = 1; i < argc; ++i)
            tokenizeFile(argv[i]);

    }
    catch (MyException& e) {
        qDebug() << "Exception occured : " << e.msg;
    }

    return 0;
}
<commit_msg>Unused line<commit_after>#include <QtCore>
#include "token.h"
#include "scanner.h"
#include "myexception.h"
#include "command_line.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    try {

        if (argc < 2)
            throw MyException("Wrong argument count");

        for (int i = 1; i < argc; ++i)
            tokenizeFile(argv[i]);

    }
    catch (MyException& e) {
        qDebug() << "Exception occured : " << e.msg;
    }

    return 0;
}
<|endoftext|>


<commit_before>#include "range_iterator.hpp"
#include "print_automaton.hpp"
#include "redfa.hpp"

#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cassert>

namespace {
  constexpr char const * colors[]{
    "\033[31;02m",
    "\033[32;02m",
    "\033[33;02m",
    "\033[34;02m",
    "\033[35;02m",
    "\033[36;02m",
  };
  constexpr std::size_t nb_colors = sizeof(colors)/sizeof(colors[0]);
  constexpr char const * reset_color = "\033[0m";

  template<class T>
  struct SetColor { T const & x; unsigned i; };

  template<class T>
  SetColor<T> setcolor(T const & x, unsigned i)
  {
    assert(i < nb_colors);
    return {x, i};
  }

  template<class T>
  std::ostream & operator<<(std::ostream & os, SetColor<T> x)
  { return os << colors[x.i] << x.x << reset_color; }
}

namespace falcon { namespace regex_dfa {

std::ostream & operator<<(std::ostream & os, Transition const & t)
{
  return os
    << colors[1]
    << " [" << t.e.l << "-" << t.e.r << "]"
       " ['" << char(t.e.l) << "'-'" << char(t.e.r) << "']"
    << reset_color
    << " → " << t.next
  ;
}

std::ostream & operator<<(std::ostream & os, Transitions const & ts)
{
  for (auto & t : ts) {
    os << t << "\n";
  }
  return os << "\n";
}

std::ostream & operator<<(std::ostream & os, Range::State const & states)
{
  return os
    << (states & Range::Final ? " @" : "  ")
    << (states & Range::Begin ? " ^" : "  ")
    << (states & Range::End ? " $" : "  ")
    << (states & Range::Normal ? " =" : "  ")
    << (states & Range::Invalid ? " x" : "  ")
    //<< (rng.states & Range::Epsilon ? "E " : "  ")
  ;
}

std::ostream & operator<<(std::ostream & os, Capture const & capstate) {
  constexpr char const * c[]{
    "",
    "(",
    ")", "()",
    "+", "(+", "+)", "(+)",
    ".", ".(", ".)", ".()", ".+", ".(+", ".+)", ".(+)",
    "-", "-(", "-)", "-()", "-+", "-(+", "-+)", "-(+)",
      "-.", "-.(", "-.)", "-.()", "-.+", "-.(+", "-.+)", "-.(+)",
  };
  static_assert(sizeof(c)/sizeof(c[0]) == Capture::State::MAX, "");
  return os << c[capstate.e] << capstate.n << " ";
}

void print_head_rng(const Range& rng, int num)
{
  std::cout
    << std::setw(4) << num
    << colors[4]
    << rng.states
    << colors[3]
  ;
  for (auto & capstate : rng.capstates) {
    std::cout << capstate;
  }
  std::cout << reset_color;
}

void print_automaton(const Range& rng, int num)
{
  print_head_rng(rng, num);
  std::cout << "\n" << rng.transitions;
}

void print_table(std::vector<unsigned> const & capture_table)
{
  for (auto & caps : capture_table) {
    constexpr char c[]{'(',')'};
    std::cout << caps << " " << c[capture_table[caps] > caps] << "\n";
  }
}

// void print_automaton(const Ranges& rngs)
// {
//   for (auto & rng : rngs) {
//     print_automaton(rng, int(&rng-&rngs[0]));
//   }
//
//   for (auto & caps : rngs.capture_table) {
//     constexpr char c[]{'(',')'};
//     std::cout << caps << " " << c[rngs.capture_table[caps] > caps] << "\n";
//   }
// }

void print_automaton(const Ranges& rngs)
{
  auto sz = rngs.size() * 2u;
  for (auto & rng : rngs) {
    sz += rng.transitions.size();
  }

  struct L { std::size_t n; enum { None, Start, Plug, Stop, Cont } e; };
  using Graph = std::vector<std::vector<L>>;

  auto process_graph = [sz, &rngs](Graph & graph, auto next_filter_op, auto f_ok, auto process_line){
    auto add_column = [sz, &graph](){
      graph.emplace_back();
      graph.back().resize(sz, L{~std::size_t{}, L::None});
    };
    add_column();

    unsigned i = 1;
    auto first_rng = begin(rngs);
    auto last_rng = end(rngs);
    for (; first_rng != last_rng; ++first_rng) {
      auto rng_num = std::size_t(first_rng - begin(rngs));

      auto first_trs = begin(first_rng->transitions);
      auto last_trs = end(first_rng->transitions);
      for (; first_trs != last_trs; ++first_trs, ++i) {
        auto next = first_trs->next;
        if (next_filter_op(rng_num, next)) {
          continue;
        }
        auto pgraph = std::find_if(begin(graph), end(graph), [i, next](auto & v){
          return v[i].n == next;
        });
        if (end(graph) == pgraph) {
          auto p = begin(graph);
          do {
            p = std::find_if(p, end(graph), [i](auto & v){
              return v[i].e == L::None;
            });
          } while (p != end(graph) && !f_ok(&(*p)[i], first_rng, first_trs) && (++p, 1));
          if (end(graph) == p) {
            add_column();
            p = end(graph)-1;
          }

          process_line(&(*p)[i], first_rng, first_trs);
        }
        else {
          (*pgraph)[i].e = L::Plug;
        }
      }
      i += 2;
    }
  };

  Graph graph;
  process_graph(
    graph, std::greater_equal<>{},
    [](auto, auto, auto){ return std::true_type{}; },
    [&rngs](auto p, auto it_rng, auto it_trs){
      auto next = it_trs->next;
      std::size_t n = end(it_rng->transitions) - it_trs;
      auto first_rng2 = it_rng;
      auto last_rng2 = begin(rngs) + next;
      while (++first_rng2 != last_rng2) {
        n += first_rng2->transitions.size() + 2;
      }

      *p = L{next, L::Start};
      *std::fill_n(++p, n, L{next, L::Cont}) = L{next, L::Stop};
    }
  );
  Graph graph2;
  bool empty_graph2 = true;
  process_graph(
    graph2, std::less<>{},
    [&rngs](auto p, auto it_rng, auto it_trs){
      p -= it_trs - begin(it_rng->transitions) + 1;
      auto first_rng2 = begin(rngs) + it_trs->next;
      for (; first_rng2 != it_rng; ++first_rng2) {
        if (p->e != L::None) {
          return false;
        }
        p -= first_rng2->transitions.size() + 2;
      }
      return true;
    },
    [&rngs, &empty_graph2](auto p, auto it_rng, auto it_trs){
      auto next = it_trs->next;
      std::size_t n = it_trs - begin(it_rng->transitions) + 1;
      auto first_rng2 = begin(rngs) + next;
      for (; first_rng2 != it_rng; ++first_rng2) {
        n += first_rng2->transitions.size() + 2;
      }

      *p = L{next, L::Stop};
      p -= n;
      *p = L{next, L::Start};
      std::fill_n(++p, n-1, L{next, L::Cont});
      empty_graph2 = false;
    }
  );

  auto igraph = 0;
  auto print_tree =[&igraph, &graph, &graph2, empty_graph2]{
    auto print_graph = [&igraph](Graph const & graph, auto ecmp) {
      constexpr char const * borders[]{"  ", "┌─", "├─", "└─", "│ "};

      unsigned i = 0;
      unsigned pluged_color = nb_colors;
      bool is_stop = false;
      auto first = rbegin(graph);
      auto last = rend(graph);
      std::cout << " ";

      for (; first != last; ++first) {
        auto const e = (*first)[igraph].e;
        if (e) {
          std::cout << colors[i % nb_colors];
        }
        std::cout << borders[e];
        if (L::Start <= e && L::Stop >= e) {
          pluged_color = i % nb_colors;
          is_stop = (ecmp == e);
          ++first;
          break;
        }
        ++i;
      }

      constexpr char const * borders2[]{"", "│", "│", "┴", "│"};

      for (; first != last; ++first) {
        ++i;
        auto const e = (*first)[igraph].e;
        if (e) {
          std::cout << colors[i % nb_colors] << borders2[e] << colors[pluged_color] << "─";
        }
        else {
          std::cout << colors[pluged_color] << "──";
        }
      }

      if (pluged_color == nb_colors) {
        std::cout << " " << reset_color;
      }
      else {
        std::cout << (is_stop ? "▸" : "─");
      }
    };

    if (!empty_graph2) {
      print_graph(graph2, L::Start);
      std::cout << reset_color << "┆";
    }
    print_graph(graph, L::Stop);

    ++igraph;
  };

  for (auto & rng : rngs) {
    print_tree();
    print_head_rng(rng, int(&rng-&rngs[0]));
    std::cout << "\n";
    for (auto & t : rng.transitions) {
      print_tree();
      std::cout << t << "\n";
    }
    print_tree();
    std::cout << "\n";
  }

  print_table(rngs.capture_table);
}

} }<commit_msg>fixes print_automaton with backwards transitions<commit_after>#include "range_iterator.hpp"
#include "print_automaton.hpp"
#include "redfa.hpp"

#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cassert>

namespace {
  constexpr char const * colors[]{
    "\033[31;02m",
    "\033[32;02m",
    "\033[33;02m",
    "\033[34;02m",
    "\033[35;02m",
    "\033[36;02m",
  };
  constexpr std::size_t nb_colors = sizeof(colors)/sizeof(colors[0]);
  constexpr char const * reset_color = "\033[0m";

  template<class T>
  struct SetColor { T const & x; unsigned i; };

  template<class T>
  SetColor<T> setcolor(T const & x, unsigned i)
  {
    assert(i < nb_colors);
    return {x, i};
  }

  template<class T>
  std::ostream & operator<<(std::ostream & os, SetColor<T> x)
  { return os << colors[x.i] << x.x << reset_color; }
}

namespace falcon { namespace regex_dfa {

std::ostream & operator<<(std::ostream & os, Transition const & t)
{
  return os
    << colors[1]
    << "[" << t.e.l << "-" << t.e.r << "]"
       " ['" << char(t.e.l) << "'-'" << char(t.e.r) << "']"
    << reset_color
    << " → " << t.next
  ;
}

std::ostream & operator<<(std::ostream & os, Transitions const & ts)
{
  for (auto & t : ts) {
    os << t << "\n";
  }
  return os << "\n";
}

std::ostream & operator<<(std::ostream & os, Range::State const & states)
{
  return os
    << (states & Range::Final ? " @" : "  ")
    << (states & Range::Begin ? " ^" : "  ")
    << (states & Range::End ? " $" : "  ")
    << (states & Range::Normal ? " =" : "  ")
    << (states & Range::Invalid ? " x" : "  ")
    //<< (rng.states & Range::Epsilon ? "E " : "  ")
  ;
}

std::ostream & operator<<(std::ostream & os, Capture const & capstate) {
  constexpr char const * c[]{
    "",
    "(",
    ")", "()",
    "+", "(+", "+)", "(+)",
    ".", ".(", ".)", ".()", ".+", ".(+", ".+)", ".(+)",
    "-", "-(", "-)", "-()", "-+", "-(+", "-+)", "-(+)",
      "-.", "-.(", "-.)", "-.()", "-.+", "-.(+", "-.+)", "-.(+)",
  };
  static_assert(sizeof(c)/sizeof(c[0]) == Capture::State::MAX, "");
  return os << c[capstate.e] << capstate.n << " ";
}

void print_head_rng(const Range& rng, int num)
{
  std::cout
    << std::setw(4) << num
    << colors[4]
    << rng.states
    << colors[3]
  ;
  for (auto & capstate : rng.capstates) {
    std::cout << capstate;
  }
  std::cout << reset_color;
}

void print_automaton(const Range& rng, int num)
{
  print_head_rng(rng, num);
  std::cout << "\n" << rng.transitions;
}

void print_table(std::vector<unsigned> const & capture_table)
{
  for (auto & caps : capture_table) {
    constexpr char c[]{'(',')'};
    std::cout << caps << " " << c[capture_table[caps] > caps] << "\n";
  }
}

// void print_automaton(const Ranges& rngs)
// {
//   for (auto & rng : rngs) {
//     print_automaton(rng, int(&rng-&rngs[0]));
//   }
//
//   for (auto & caps : rngs.capture_table) {
//     constexpr char c[]{'(',')'};
//     std::cout << caps << " " << c[rngs.capture_table[caps] > caps] << "\n";
//   }
// }

struct Begin {
  template<class Cont> static auto begin(Cont & cont) { using std::begin; return begin(cont); }
  template<class Cont> static auto end(Cont & cont) { using std::end; return end(cont); }
};

struct RBegin {
  template<class Cont> static auto begin(Cont & cont) { using std::rbegin; return rbegin(cont); }
  template<class Cont> static auto end(Cont & cont) { using std::rend; return rend(cont); }
};

void print_automaton(const Ranges& rngs)
{
  auto sz = rngs.size() * 2u;
  for (auto & rng : rngs) {
    sz += rng.transitions.size();
  }

  struct L { std::size_t n; enum { None, Start, Plug, Stop, Cont } e; };
  using Graph = std::vector<std::vector<L>>;

  auto process_graph = [sz, &rngs](Graph & graph, auto is_next_op2, auto distance_next, auto a){
    auto egraph = end(graph);
    auto add_column = [sz, &graph, &egraph, a](){
      graph.emplace_back();
      graph.back().resize(sz, L{~std::size_t{}, L::None});
      egraph = end(graph);
      return egraph-1;
    };

    unsigned i = 1;
    unsigned rng_num = 0;
    auto first_rng = a.begin(rngs);
    auto last_rng = a.end(rngs);
    for (; first_rng != last_rng; ++first_rng, ++rng_num) {
      auto first_trs = a.begin(first_rng->transitions);
      auto last_trs = a.end(first_rng->transitions);
      for (; first_trs != last_trs; ++first_trs, ++i) {
        auto next = first_trs->next;
        if (is_next_op2(rng_num, next)) {
          continue;
        }
        auto pgraph = std::find_if(begin(graph), egraph, [i, next](auto & v){
          return v[i].n == next;
        });
        if (egraph == pgraph) {
          auto dist = distance_next(first_rng, first_trs);
          assert(i + dist >= 0);
          assert(decltype(sz)(i + dist) < sz);
          pgraph = std::find_if(begin(graph), egraph, [i](auto & v){
            return v[i].e == L::None;
          });

          if (pgraph == egraph) {
            pgraph = add_column();
          }

          auto first = &(*pgraph)[i];
          auto last = first + dist;
          *first = {next, L::Start};
          *last = {next, L::Stop};
          assert(first != last);
          std::fill(++first, last, L{next, L::Cont});
        }
        else {
          (*pgraph)[i].e = L::Plug;
        }
      }
      i += 2;
    }
  };

  Graph graph;
  process_graph(
    graph,
    std::greater_equal<>{},
    [&rngs](auto it_rng, auto it_trs){
      return std::accumulate(
        it_rng+1,
        begin(rngs) + it_trs->next,
        end(it_rng->transitions) - it_trs + 1u,
        [](auto n, auto & rng) { return n + rng.transitions.size() + 2; }
      );
    },
    Begin()
  );
  Graph graph2;
  process_graph(
    graph2,
    [&rngs](unsigned rev_rng_num, auto next) {
      return rngs.size() - rev_rng_num <= next;
    },
    [&rngs](auto rit_rng, auto it_trs){
      return std::accumulate(
        begin(rngs) + it_trs->next,
        rit_rng.base() - 1,
        rend(rit_rng->transitions) - it_trs,
        [](auto n, auto & rng) { return n + rng.transitions.size() + 2; }
      );
    },
    RBegin()
  );

  auto igraph = 0;
  auto print_tree =[sz, &igraph, &graph, &graph2]{
    auto print_graph = [](Graph const & graph, auto rev, auto igraph) {
      constexpr char const * borders_nor[]{"  ", "┌─", "├─", "└─", "│ "};
      constexpr char const * borders_rev[]{"  ", "└─", "├─", "┌─", "│ "};
      auto & borders = rev ? borders_rev : borders_nor;

      auto i = graph.size() - 1u;
      auto pluged_color = nb_colors;
      auto is_stop = false;
      auto first = rbegin(graph);
      auto last = rend(graph);
      std::cout << " ";

      for (; first != last; ++first) {
        auto const e = (*first)[igraph].e;
        if (e) {
          std::cout << colors[i % nb_colors];
        }
        std::cout << borders[e];
        if (L::Start <= e && L::Stop >= e) {
          pluged_color = i % nb_colors;
          is_stop = (L::Stop == e);
          ++first;
          break;
        }
        --i;
      }

      for (; first != last; ++first) {
        --i;
        auto const e = (*first)[igraph].e;
        if (e) {
          std::cout << colors[i % nb_colors] << "│" << colors[pluged_color] << "─";
        }
        else {
          std::cout << colors[pluged_color] << "──";
        }
      }

      if (pluged_color == nb_colors) {
        std::cout << " " << reset_color;
      }
      else {
        std::cout << (is_stop ? "▸" : "─");
      }
    };

    if (!graph2.empty()) {
      print_graph(graph2, true, sz - igraph - 1);
      std::cout << reset_color << "┆";
    }
    print_graph(graph, false, igraph);

    ++igraph;
  };

  for (auto & rng : rngs) {
    print_tree();
    std::cout << " ";
    print_head_rng(rng, int(&rng-&rngs[0]));
    std::cout << "\n";
    for (auto & t : rng.transitions) {
      print_tree();
      std::cout << " " << t << "\n";
    }
    print_tree();
    std::cout << "\n";
  }

  print_table(rngs.capture_table);
}

} }<|endoftext|>


<commit_before>/* -------------------------------------------------------------------------- *
 *                      OpenSim:  testAssemblySolver.cpp                      *
 * -------------------------------------------------------------------------- *
 * The OpenSim API is a toolkit for musculoskeletal modeling and simulation.  *
 * See http://opensim.stanford.edu and the NOTICE file for more information.  *
 * OpenSim is developed at Stanford University and supported by the US        *
 * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA    *
 * through the Warrior Web program.                                           *
 *                                                                            *
 * Copyright (c) 2005-2012 Stanford University and the Authors                *
 * Author(s): Ajay Seth                                                       *
 *                                                                            *
 * 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.                                             *
 * -------------------------------------------------------------------------- */

//==========================================================================================================
//	testAssemblySolver loads models with constraints to verify that constraints are
//  adequately satified or that an appropriate exception is thrown.
//
//==========================================================================================================
#include <OpenSim/Simulation/osimSimulation.h>
#include <OpenSim/Auxiliary/auxiliaryTestFunctions.h>

using namespace OpenSim;
using namespace std;

void testAssembleModelWithConstraints(string modelFile);
void testAssemblySatisfiesConstraints(string modelFile);
double calcLigamentLengthError(const SimTK::State &s, const Model &model);

int main()
{
	try {
		LoadOpenSimLibrary("osimActuators");
		testAssemblySatisfiesConstraints("knee_patella_ligament.osim");
		testAssembleModelWithConstraints("PushUpToesOnGroundExactConstraints.osim");
		testAssembleModelWithConstraints("PushUpToesOnGroundLessPreciseConstraints.osim");
		testAssembleModelWithConstraints("PushUpToesOnGroundWithMuscles.osim");
	}
	catch (const std::exception& e) {
		cout << "\ntestAssemblySolver FAILED " << e.what() <<endl;
        return 1;
    }
    cout << "\ntestAssemblySolver PASSED" << endl;
    return 0;
}

//==========================================================================================================
// Test Cases
//==========================================================================================================
void testAssembleModelWithConstraints(string modelFile)
{
	using namespace SimTK;

	cout << "\n****************************************************************************" << endl;
	cout << " testAssembleModelWithConstraints with "<< modelFile << endl;
	cout << "****************************************************************************\n" << endl;

	//==========================================================================================================
	// Setup OpenSim model
	Model oldmodel(modelFile);
	string newModelFile = "clone_" + modelFile;
	oldmodel.print(newModelFile);

	Model model(newModelFile);

	const CoordinateSet &coords = model.getCoordinateSet();

	cout << "*********** Coordinates before initSystem ******************** " << endl;
	for(int i=0; i< coords.getSize(); i++) {
		cout << "Coordinate " << coords[i].getName() << " default value = " << coords[i].getDefaultValue() << endl;
	}

	//model.setUseVisualizer(true);

    State state = model.initSystem();
	model.equilibrateMuscles(state);

	cout << "*********** Coordinates after initSystem ******************** "  << endl;
	for(int i=0; i< coords.getSize(); i++) {
		cout << "Coordinate " << coords[i].getName() << " get value = " << coords[i].getValue(state) << endl;
	}

	//For debugging the assembled pose
	if (model.hasVisualizer()){
		SimTK::Visualizer& viz = model.updVisualizer().updSimbodyVisualizer();
		const JointSet& js = model.getJointSet();
		for (int i = 0; i < js.getSize(); ++i){
			const Joint& j = js[i];
			viz.addDecoration(j.getParentBody().getIndex(),
				j.getParentTransform(),
				SimTK::DecorativeFrame(0.05));
			viz.addDecoration(j.getChildBody().getIndex(),
				j.getChildTransform(),
				SimTK::DecorativeFrame(0.033));
			viz.addDecoration(j.getChildBody().getIndex(),
				Transform(),
				SimTK::DecorativeSphere(0.033));
			if (j.getChildBody().getName() == "pelvis"){
				SimTK::DecorativeBrick geom(Vec3(0.10, 0.05, 0.20));
				geom.setColor(Vec3(0.1, 1.0, 0.1));
				viz.addDecoration(j.getChildBody().getIndex(),
					Transform(), geom);
			}
		}

		model.getVisualizer().show(state);
	}

	// Verify that the reaction forces at the constraints are not rediculously large
	// They should sum to body-weight (more or less)
	model.getMultibodySystem().realize(state, Stage::Acceleration);

	Vec3 comVel = model.calcMassCenterVelocity(state);
	Vec3 comAcc = model.calcMassCenterAcceleration(state);
	SpatialVec momentum = model.getMatterSubsystem().calcSystemCentralMomentum(state);

	const ConstraintSet &constraints = model.getConstraintSet();

	Vector_<SpatialVec> constraintBodyForces(constraints.getSize());
	Vector mobilityForces(0);
	double totalYforce = 0;

	for(int i=0; i< constraints.getSize(); i++) {
		constraints[i].calcConstraintForces(state, constraintBodyForces, mobilityForces);
		cout << "Constraint " << i << ":  " << constraints[i].getName();
		cout << " Force = " << constraintBodyForces(1)(1)(1) << endl;
		//constraintBodyForces.dump("Constraint Body Forces");
		totalYforce += constraintBodyForces(1)(1)(1);
	}

	cout << "Total Vertical Constraint Force:" << totalYforce << " N " << endl;

	double mass = model.getTotalMass(state);
	double bw = -mass*(model.getGravity()[1]);

	double inertial = mass*comAcc[1];

	ASSERT_EQUAL((totalYforce - bw - inertial) / bw, 0.0, SimTK::SqrtEps,
		__FILE__, __LINE__,
		"Contraint force does not match body-weight plus inertial force (mg+ma).");

	//const CoordinateSet &coords = model.getCoordinateSet();
	double q_error = 0;
	for(int i=0; i< coords.getSize(); i++) {
		q_error += fabs(coords[i].getValue(state)-coords[i].getDefaultValue());
	}

	cout << "Average Change in  Default Configuration:" << q_error/coords.getSize() << endl;

	//==========================================================================================================
	// Integrate forward and init the state and update defaults to make sure
	// assembler is not effecting anything more than the pose.
    RungeKuttaMersonIntegrator integrator(model.getMultibodySystem());
	integrator.setAccuracy(1.0e-8);
    Manager manager(model, integrator);
    manager.setInitialTime(0.0);
    manager.setFinalTime(0.01);

	// Configuration at the inital state
	Vector y1 = state.getY();

	// set default (properties) which capture an accurate snapshot of the model
	model.setPropertiesFromState(state);

	// Simulate forward in time
    manager.integrate(state);

	// get the configuration at the end of the simulaton
    Vector y2 = state.getY();

	// recreate system with states from initial defaults
    State state2 = model.initSystem();
	// get the configuration after getting a new state from initial defaults
    Vector y3 = state2.getY();

	// set properties to  capture model state after the simulation
	model.setPropertiesFromState(state);
	model.print("test_" + modelFile + "_post.osim");
	model.assemble(state);
	model.setPropertiesFromState(state);
	model.print("test_"+modelFile+"_post_reassemble.osim");

	// recreate system with states from post simulation defaults
    state2 = model.initSystem();
	// get the configuration from post simulation defaults (properties)
    Vector y4 = state2.getY();

	//cout << "******************* Init System Inital State *******************" << endl;
	for (int i = 0; i < y1.size(); i++) {
		//cout << "Pre-simulation:" << i << " y1 = " << y1[i] << ", y3 = " << y3[i] << endl;
		ASSERT_EQUAL(y1[i], y3[i], 2e-4, __FILE__, __LINE__, "Initial state changed after 2nd call to initSystem");
	}

	cout << "******************* Init System Final State *******************" << endl;
	for (int i = 0; i < y1.size(); i++) {
		cout << "Post-simulation:"<<i<< " y2 = " << y2[i] << ", y4 = " << y4[i] << endl;
		ASSERT_EQUAL(y2[i], y4[i], 2e-4, __FILE__, __LINE__, "State differed after a simulation from same init state.");
    }
    ASSERT(max(abs(y1-y2)) > 1e-3, __FILE__, __LINE__, "Check that state changed after simulation FAILED");
}

void testAssemblySatisfiesConstraints(string modelFile)
{
	using namespace SimTK;

	cout << "****************************************************************************" << endl;
	cout << " testAssemblySatisfiesConstraints :: "<< modelFile << endl;
	cout << "****************************************************************************\n" << endl;
	//==========================================================================================================
	// Setup OpenSim model
	Model model(modelFile);
    // In Simbody 3.4, rod constraints are handled differently than in Simbody
    // 3.4. This leads to a decrease in the accuracy that the assembly solver
    // achieves, even though the constraints are achieved to the same extent.
    // Therefore, it is reasonable to reduce the accuracy (increase the value
    // of assembly_accuracy) for assembly.
    model.set_assembly_accuracy(1e-8);

	const CoordinateSet &modelcoords = model.getCoordinateSet();
	cout << "*********** Coordinate defaults (before initSystem) ******************** " << endl;
	for(int i=0; i< modelcoords.getSize(); i++) {
		cout << "Coordinate " << modelcoords[i].getName()
			<< " default value = " << modelcoords[i].getDefaultValue() << endl
			<< " is_free to_satisfy_constraints = " << modelcoords[i].get_is_free_to_satisfy_constraints()
			<< endl;
	}

	//model.setUseVisualizer(true);
    State& state = model.initSystem();

	const CoordinateSet &coords = model.getCoordinateSet();
	cout << "***** Coordinate values (after initSystem including Assembly ********* " << endl;
	for(int i=0; i< coords.getSize(); i++) {
		cout << "Coordinate " << coords[i].getName() << " value = "
			<< coords[i].getValue(state) << endl;
	}

	double cerr = SimTK::Infinity;
	double kneeAngle = -Pi/3;

	int N = 100;
	double lower = -2*Pi/3, upper = Pi/18;
	double delta = (upper-lower)/N;

	double qerr = 0;

	for(int i=0; i<N; ++i){
		kneeAngle = upper-i*delta;
		coords[0].setValue(state, kneeAngle, true);
		//model.getVisualizer().show(state);
		cerr = calcLigamentLengthError(state, model);
		qerr = coords[0].getValue(state)-kneeAngle;
		//cout << "Assembly errors:: cerr = " << cerr << " m,  qerr = "
		//	<< convertRadiansToDegrees(qerr) << " degrees" << endl;
		ASSERT_EQUAL(cerr, 0.0, model.get_assembly_accuracy(),
			__FILE__, __LINE__, "Constraints NOT satisfied to within assembly accuracy");
	}
}

double calcLigamentLengthError(const SimTK::State &s, const Model &model)
{
	using namespace SimTK;
	double error = 0;

	ConstantDistanceConstraint* constraint = dynamic_cast<ConstantDistanceConstraint*>(&model.getConstraintSet()[0]);
	const BodySet& bodies = model.getBodySet();

	if(constraint){
		Vec3 p1inB1, p2inB2, p1inG, p2inG;
		p1inB1 = constraint->get_location_body_1();
		p2inB2 = constraint->get_location_body_2();

		const OpenSim::Body& b1 = bodies.get(constraint->get_body_1());
		const OpenSim::Body& b2 = bodies.get(constraint->get_body_2());

		model.getSimbodyEngine().getPosition(s, b1, p1inB1, p1inG);
		model.getSimbodyEngine().getPosition(s, b2, p2inB2, p2inG);

		double length = (p2inG-p1inG).norm();
		error = length - constraint->get_constant_distance();
	}

	return error;
}
<commit_msg>Put reference value before actual value for ASSERT_EQUAL()<commit_after>/* -------------------------------------------------------------------------- *
 *                      OpenSim:  testAssemblySolver.cpp                      *
 * -------------------------------------------------------------------------- *
 * The OpenSim API is a toolkit for musculoskeletal modeling and simulation.  *
 * See http://opensim.stanford.edu and the NOTICE file for more information.  *
 * OpenSim is developed at Stanford University and supported by the US        *
 * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA    *
 * through the Warrior Web program.                                           *
 *                                                                            *
 * Copyright (c) 2005-2012 Stanford University and the Authors                *
 * Author(s): Ajay Seth                                                       *
 *                                                                            *
 * 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.                                             *
 * -------------------------------------------------------------------------- */

//==========================================================================================================
//	testAssemblySolver loads models with constraints to verify that constraints are
//  adequately satified or that an appropriate exception is thrown.
//
//==========================================================================================================
#include <OpenSim/Simulation/osimSimulation.h>
#include <OpenSim/Auxiliary/auxiliaryTestFunctions.h>

using namespace OpenSim;
using namespace std;

void testAssembleModelWithConstraints(string modelFile);
void testAssemblySatisfiesConstraints(string modelFile);
double calcLigamentLengthError(const SimTK::State &s, const Model &model);

int main()
{
	try {
		LoadOpenSimLibrary("osimActuators");
		testAssemblySatisfiesConstraints("knee_patella_ligament.osim");
		testAssembleModelWithConstraints("PushUpToesOnGroundExactConstraints.osim");
		testAssembleModelWithConstraints("PushUpToesOnGroundLessPreciseConstraints.osim");
		testAssembleModelWithConstraints("PushUpToesOnGroundWithMuscles.osim");
	}
	catch (const std::exception& e) {
		cout << "\ntestAssemblySolver FAILED " << e.what() <<endl;
        return 1;
    }
    cout << "\ntestAssemblySolver PASSED" << endl;
    return 0;
}

//==========================================================================================================
// Test Cases
//==========================================================================================================
void testAssembleModelWithConstraints(string modelFile)
{
	using namespace SimTK;

	cout << "\n****************************************************************************" << endl;
	cout << " testAssembleModelWithConstraints with "<< modelFile << endl;
	cout << "****************************************************************************\n" << endl;

	//==========================================================================================================
	// Setup OpenSim model
	Model oldmodel(modelFile);
	string newModelFile = "clone_" + modelFile;
	oldmodel.print(newModelFile);

	Model model(newModelFile);

	const CoordinateSet &coords = model.getCoordinateSet();

	cout << "*********** Coordinates before initSystem ******************** " << endl;
	for(int i=0; i< coords.getSize(); i++) {
		cout << "Coordinate " << coords[i].getName() << " default value = " << coords[i].getDefaultValue() << endl;
	}

	//model.setUseVisualizer(true);

    State state = model.initSystem();
	model.equilibrateMuscles(state);

	cout << "*********** Coordinates after initSystem ******************** "  << endl;
	for(int i=0; i< coords.getSize(); i++) {
		cout << "Coordinate " << coords[i].getName() << " get value = " << coords[i].getValue(state) << endl;
	}

	//For debugging the assembled pose
	if (model.hasVisualizer()){
		SimTK::Visualizer& viz = model.updVisualizer().updSimbodyVisualizer();
		const JointSet& js = model.getJointSet();
		for (int i = 0; i < js.getSize(); ++i){
			const Joint& j = js[i];
			viz.addDecoration(j.getParentBody().getIndex(),
				j.getParentTransform(),
				SimTK::DecorativeFrame(0.05));
			viz.addDecoration(j.getChildBody().getIndex(),
				j.getChildTransform(),
				SimTK::DecorativeFrame(0.033));
			viz.addDecoration(j.getChildBody().getIndex(),
				Transform(),
				SimTK::DecorativeSphere(0.033));
			if (j.getChildBody().getName() == "pelvis"){
				SimTK::DecorativeBrick geom(Vec3(0.10, 0.05, 0.20));
				geom.setColor(Vec3(0.1, 1.0, 0.1));
				viz.addDecoration(j.getChildBody().getIndex(),
					Transform(), geom);
			}
		}

		model.getVisualizer().show(state);
	}

	// Verify that the reaction forces at the constraints are not rediculously large
	// They should sum to body-weight (more or less)
	model.getMultibodySystem().realize(state, Stage::Acceleration);

	Vec3 comVel = model.calcMassCenterVelocity(state);
	Vec3 comAcc = model.calcMassCenterAcceleration(state);
	SpatialVec momentum = model.getMatterSubsystem().calcSystemCentralMomentum(state);

	const ConstraintSet &constraints = model.getConstraintSet();

	Vector_<SpatialVec> constraintBodyForces(constraints.getSize());
	Vector mobilityForces(0);
	double totalYforce = 0;

	for(int i=0; i< constraints.getSize(); i++) {
		constraints[i].calcConstraintForces(state, constraintBodyForces, mobilityForces);
		cout << "Constraint " << i << ":  " << constraints[i].getName();
		cout << " Force = " << constraintBodyForces(1)(1)(1) << endl;
		//constraintBodyForces.dump("Constraint Body Forces");
		totalYforce += constraintBodyForces(1)(1)(1);
	}

	cout << "Total Vertical Constraint Force:" << totalYforce << " N " << endl;

	double mass = model.getTotalMass(state);
	double bw = -mass*(model.getGravity()[1]);

	double inertial = mass*comAcc[1];

	ASSERT_EQUAL((totalYforce - bw - inertial) / bw, 0.0, SimTK::SqrtEps,
		__FILE__, __LINE__,
		"Contraint force does not match body-weight plus inertial force (mg+ma).");

	//const CoordinateSet &coords = model.getCoordinateSet();
	double q_error = 0;
	for(int i=0; i< coords.getSize(); i++) {
		q_error += fabs(coords[i].getValue(state)-coords[i].getDefaultValue());
	}

	cout << "Average Change in  Default Configuration:" << q_error/coords.getSize() << endl;

	//==========================================================================================================
	// Integrate forward and init the state and update defaults to make sure
	// assembler is not effecting anything more than the pose.
    RungeKuttaMersonIntegrator integrator(model.getMultibodySystem());
	integrator.setAccuracy(1.0e-8);
    Manager manager(model, integrator);
    manager.setInitialTime(0.0);
    manager.setFinalTime(0.01);

	// Configuration at the inital state
	Vector y1 = state.getY();

	// set default (properties) which capture an accurate snapshot of the model
	model.setPropertiesFromState(state);

	// Simulate forward in time
    manager.integrate(state);

	// get the configuration at the end of the simulaton
    Vector y2 = state.getY();

	// recreate system with states from initial defaults
    State state2 = model.initSystem();
	// get the configuration after getting a new state from initial defaults
    Vector y3 = state2.getY();

	// set properties to  capture model state after the simulation
	model.setPropertiesFromState(state);
	model.print("test_" + modelFile + "_post.osim");
	model.assemble(state);
	model.setPropertiesFromState(state);
	model.print("test_"+modelFile+"_post_reassemble.osim");

	// recreate system with states from post simulation defaults
    state2 = model.initSystem();
	// get the configuration from post simulation defaults (properties)
    Vector y4 = state2.getY();

	//cout << "******************* Init System Inital State *******************" << endl;
	for (int i = 0; i < y1.size(); i++) {
		//cout << "Pre-simulation:" << i << " y1 = " << y1[i] << ", y3 = " << y3[i] << endl;
		ASSERT_EQUAL(y1[i], y3[i], 2e-4, __FILE__, __LINE__, "Initial state changed after 2nd call to initSystem");
	}

	cout << "******************* Init System Final State *******************" << endl;
	for (int i = 0; i < y1.size(); i++) {
		cout << "Post-simulation:"<<i<< " y2 = " << y2[i] << ", y4 = " << y4[i] << endl;
		ASSERT_EQUAL(y2[i], y4[i], 2e-4, __FILE__, __LINE__, "State differed after a simulation from same init state.");
    }
    ASSERT(max(abs(y1-y2)) > 1e-3, __FILE__, __LINE__, "Check that state changed after simulation FAILED");
}

void testAssemblySatisfiesConstraints(string modelFile)
{
	using namespace SimTK;

	cout << "****************************************************************************" << endl;
	cout << " testAssemblySatisfiesConstraints :: "<< modelFile << endl;
	cout << "****************************************************************************\n" << endl;
	//==========================================================================================================
	// Setup OpenSim model
	Model model(modelFile);
    // In Simbody 3.4, rod constraints are handled differently than in Simbody
    // 3.4. This leads to a decrease in the accuracy that the assembly solver
    // achieves, even though the constraints are achieved to the same extent.
    // Therefore, it is reasonable to reduce the accuracy (increase the value
    // of assembly_accuracy) for assembly.
    model.set_assembly_accuracy(1e-8);

	const CoordinateSet &modelcoords = model.getCoordinateSet();
	cout << "*********** Coordinate defaults (before initSystem) ******************** " << endl;
	for(int i=0; i< modelcoords.getSize(); i++) {
		cout << "Coordinate " << modelcoords[i].getName()
			<< " default value = " << modelcoords[i].getDefaultValue() << endl
			<< " is_free to_satisfy_constraints = " << modelcoords[i].get_is_free_to_satisfy_constraints()
			<< endl;
	}

	//model.setUseVisualizer(true);
    State& state = model.initSystem();

	const CoordinateSet &coords = model.getCoordinateSet();
	cout << "***** Coordinate values (after initSystem including Assembly ********* " << endl;
	for(int i=0; i< coords.getSize(); i++) {
		cout << "Coordinate " << coords[i].getName() << " value = "
			<< coords[i].getValue(state) << endl;
	}

	double cerr = SimTK::Infinity;
	double kneeAngle = -Pi/3;

	int N = 100;
	double lower = -2*Pi/3, upper = Pi/18;
	double delta = (upper-lower)/N;

	double qerr = 0;

	for(int i=0; i<N; ++i){
		kneeAngle = upper-i*delta;
		coords[0].setValue(state, kneeAngle, true);
		//model.getVisualizer().show(state);
		cerr = calcLigamentLengthError(state, model);
		qerr = coords[0].getValue(state)-kneeAngle;
		//cout << "Assembly errors:: cerr = " << cerr << " m,  qerr = "
		//	<< convertRadiansToDegrees(qerr) << " degrees" << endl;
		ASSERT_EQUAL(0.0, cerr, model.get_assembly_accuracy(),
			__FILE__, __LINE__, "Constraints NOT satisfied to within assembly accuracy");
	}
}

double calcLigamentLengthError(const SimTK::State &s, const Model &model)
{
	using namespace SimTK;
	double error = 0;

	ConstantDistanceConstraint* constraint = dynamic_cast<ConstantDistanceConstraint*>(&model.getConstraintSet()[0]);
	const BodySet& bodies = model.getBodySet();

	if(constraint){
		Vec3 p1inB1, p2inB2, p1inG, p2inG;
		p1inB1 = constraint->get_location_body_1();
		p2inB2 = constraint->get_location_body_2();

		const OpenSim::Body& b1 = bodies.get(constraint->get_body_1());
		const OpenSim::Body& b2 = bodies.get(constraint->get_body_2());

		model.getSimbodyEngine().getPosition(s, b1, p1inB1, p1inG);
		model.getSimbodyEngine().getPosition(s, b2, p2inB2, p2inG);

		double length = (p2inG-p1inG).norm();
		error = length - constraint->get_constant_distance();
	}

	return error;
}
<|endoftext|>


<commit_before>#include "AliFMDAnalysisTaskSE.h"
#include "AliESDEvent.h"
#include "iostream"
#include "AliESDFMD.h"
#include "AliMCEventHandler.h"
#include "AliAnalysisManager.h"
#include "AliFMDAnaParameters.h"
#include "AliLog.h"

ClassImp(AliFMDAnalysisTaskSE)

//_____________________________________________________________________
AliFMDAnalysisTaskSE::AliFMDAnalysisTaskSE():
AliAnalysisTaskSE(),
  fListOfHistos(0),
  fSharing("Sharing",kFALSE),
  fDensity("Density",kFALSE),
  fBackground("BackgroundCorrected",kFALSE),
  fDndeta("dNdeta",kFALSE),
  fParams(0)
{
  // Default constructor
}
//_____________________________________________________________________
AliFMDAnalysisTaskSE::AliFMDAnalysisTaskSE(const char* name):
  AliAnalysisTaskSE(name),
  fListOfHistos(0),
  fSharing("Sharing",kFALSE),
  fDensity("Density",kFALSE),
  fBackground("BackgroundCorrected",kFALSE),
  fDndeta("dNdeta",kFALSE),
  fParams(0)
{
  SetParams(AliFMDAnaParameters::Instance());
  DefineOutput(1, TList::Class());
}
//_____________________________________________________________________
void AliFMDAnalysisTaskSE::UserCreateOutputObjects()
{
// Create the output containers
//
  fListOfHistos = new TList();

  AliESDFMD* fmd = new AliESDFMD();
  AliESDVertex* vertex = new AliESDVertex();

  TList* densitylist = new TList();

  TList* bgcorlist = new TList();

  fSharing.SetFMDData(fmd);
  fSharing.SetVertex(vertex);
  fSharing.SetOutputList(fListOfHistos);

  fDensity.SetOutputList(densitylist);
  fDensity.SetInputESDFMD(fmd) ;
  fDensity.SetInputVertex(vertex);

  fBackground.SetInputList(densitylist);
  fBackground.SetOutputList(bgcorlist);
  fBackground.SetHitList(fListOfHistos);

  fDndeta.SetInputList(bgcorlist);
  fDndeta.SetOutputList(fListOfHistos);

  fSharing.CreateOutputObjects();
  fDensity.CreateOutputObjects();
  fBackground.CreateOutputObjects();
  fDndeta.CreateOutputObjects();

}
//_____________________________________________________________________
void AliFMDAnalysisTaskSE::Init()
{
  std::cout<<"Init"<<std::endl;
}
//_____________________________________________________________________
void AliFMDAnalysisTaskSE::UserExec(Option_t */*option*/)
{
  // Execute analysis for current event
  //
  //  AliFMDAnaParameters* pars = AliFMDAnaParameters::Instance();
  AliESDEvent* fESD = (AliESDEvent*)InputEvent();
  fSharing.SetInputESD(fESD);

  fSharing.Exec("");
  if(fSharing.GetEventStatus()) {
    fDensity.Exec("");
    if(fDensity.GetEventStatus()) {
      fBackground.Exec("");
      fDndeta.Exec("");

    }
  }
  else
    return;

  //fListOfHistos = fBackground.GetOutputList();

  PostData(1, fListOfHistos);
}
//_____________________________________________________________________
void AliFMDAnalysisTaskSE::Terminate(Option_t */*option*/)
{
  fBackground.Terminate("");
  fDndeta.Terminate("");

}

//_____________________________________________________________________
void AliFMDAnalysisTaskSE::Print(Option_t* option) const
{
  AliInfo(Form("FMD Single Event Analysis Task\n"
	       "Parameters set to %p", fParams));
  TString opt(option);
  opt.ToLower();
  if (opt.Contains("s")) {
    fSharing.Print(option);
    fDensity.Print(option);
    fBackground.Print(option);
    fDndeta.Print(option);
  }
  if (opt.Contains("p") && fParams)
    fParams->Print(option);
}

//_____________________________________________________________________
//
// EOF
//
<commit_msg>Technical fix: Call PostData in any case.<commit_after>#include "AliFMDAnalysisTaskSE.h"
#include "AliESDEvent.h"
#include "iostream"
#include "AliESDFMD.h"
#include "AliMCEventHandler.h"
#include "AliAnalysisManager.h"
#include "AliFMDAnaParameters.h"
#include "AliLog.h"

ClassImp(AliFMDAnalysisTaskSE)

//_____________________________________________________________________
AliFMDAnalysisTaskSE::AliFMDAnalysisTaskSE():
AliAnalysisTaskSE(),
  fListOfHistos(0),
  fSharing("Sharing",kFALSE),
  fDensity("Density",kFALSE),
  fBackground("BackgroundCorrected",kFALSE),
  fDndeta("dNdeta",kFALSE),
  fParams(0)
{
  // Default constructor
}
//_____________________________________________________________________
AliFMDAnalysisTaskSE::AliFMDAnalysisTaskSE(const char* name):
  AliAnalysisTaskSE(name),
  fListOfHistos(0),
  fSharing("Sharing",kFALSE),
  fDensity("Density",kFALSE),
  fBackground("BackgroundCorrected",kFALSE),
  fDndeta("dNdeta",kFALSE),
  fParams(0)
{
  SetParams(AliFMDAnaParameters::Instance());
  DefineOutput(1, TList::Class());
}
//_____________________________________________________________________
void AliFMDAnalysisTaskSE::UserCreateOutputObjects()
{
// Create the output containers
//
  fListOfHistos = new TList();

  AliESDFMD* fmd = new AliESDFMD();
  AliESDVertex* vertex = new AliESDVertex();

  TList* densitylist = new TList();

  TList* bgcorlist = new TList();

  fSharing.SetFMDData(fmd);
  fSharing.SetVertex(vertex);
  fSharing.SetOutputList(fListOfHistos);

  fDensity.SetOutputList(densitylist);
  fDensity.SetInputESDFMD(fmd) ;
  fDensity.SetInputVertex(vertex);

  fBackground.SetInputList(densitylist);
  fBackground.SetOutputList(bgcorlist);
  fBackground.SetHitList(fListOfHistos);

  fDndeta.SetInputList(bgcorlist);
  fDndeta.SetOutputList(fListOfHistos);

  fSharing.CreateOutputObjects();
  fDensity.CreateOutputObjects();
  fBackground.CreateOutputObjects();
  fDndeta.CreateOutputObjects();

}
//_____________________________________________________________________
void AliFMDAnalysisTaskSE::Init()
{
  std::cout<<"Init"<<std::endl;
}
//_____________________________________________________________________
void AliFMDAnalysisTaskSE::UserExec(Option_t */*option*/)
{
  // Execute analysis for current event
  //
  //  AliFMDAnaParameters* pars = AliFMDAnaParameters::Instance();
    PostData(1, fListOfHistos);
  AliESDEvent* fESD = (AliESDEvent*)InputEvent();
  fSharing.SetInputESD(fESD);

  fSharing.Exec("");
  if(fSharing.GetEventStatus()) {
    fDensity.Exec("");
    if(fDensity.GetEventStatus()) {
      fBackground.Exec("");
      fDndeta.Exec("");

    }
  }
  else
    return;

  //fListOfHistos = fBackground.GetOutputList();

}
//_____________________________________________________________________
void AliFMDAnalysisTaskSE::Terminate(Option_t */*option*/)
{
  fBackground.Terminate("");
  fDndeta.Terminate("");

}

//_____________________________________________________________________
void AliFMDAnalysisTaskSE::Print(Option_t* option) const
{
  AliInfo(Form("FMD Single Event Analysis Task\n"
	       "Parameters set to %p", fParams));
  TString opt(option);
  opt.ToLower();
  if (opt.Contains("s")) {
    fSharing.Print(option);
    fDensity.Print(option);
    fBackground.Print(option);
    fDndeta.Print(option);
  }
  if (opt.Contains("p") && fParams)
    fParams->Print(option);
}

//_____________________________________________________________________
//
// EOF
//
<|endoftext|>