<commit_before>#include "ngraph.h"
#include <PCU.h>
namespace agi {

  bool checkValidity(Ngraph* g) {
    lid_t i =0;
    VertexIterator* vitr = g->begin();
    GraphVertex* vtx;
    while ((vtx = g->iterate(vitr))) {
      i++;
    }
    assert(g->numLocalVtxs()==i);
    lid_t ig = PCU_Add_Long(i);
    assert(g->numGlobalVtxs()==ig);
    vitr = g->begin();
    while ((vtx = g->iterate(vitr))) {
      for (etype t = 0;t<g->numEdgeTypes();t++) {
        GraphEdge* edge;
        EdgeIterator* eitr = g->edges(vtx,t);
        lid_t j=0;
        while ((edge = g->iterate(eitr))) {
          j++;
        }
        g->destroy(eitr);
        assert(g->degree(vtx,t)==j);
      }
    }

    vitr = g->begin();
    while ((vtx = g->iterate(vitr))) {
      for (etype t = 0;t<g->numEdgeTypes();t++) {
        GraphEdge* edge;
        EdgeIterator* eitr = g->edges(vtx,t);
        while ((edge = g->iterate(eitr))) {
          PinIterator* pitr = g->pins(edge);
          GraphVertex* other;
          while ((other = g->iterate(pitr))) {
            if (g->isEqual(other,vtx))
              break;
          }
          assert(other);
          g->destroy(pitr);
        }
        g->destroy(eitr);
      }
    }

    for (etype t=0;t<g->numEdgeTypes();t++) {
      EdgeIterator* eitr = g->begin(t);
      GraphEdge* edge;
      i=0;
      lid_t j=0;
      lid_t k=0;
      lid_t l=0;
      while ((edge = g->iterate(eitr))) {
        i++;
        l+=g->degree(edge);
        Peers res;
        g->getResidence(edge,res);
        Peers::iterator itr;
        part_t owner=PCU_Comm_Self();
        for (itr=res.begin();itr!=res.end();itr++) {
          if (*itr<owner)
            break;
        }
        if (itr==res.end()||!g->isHyper()){
          j++;
          k+=g->degree(edge);
        }
      }
      g->destroy(eitr);
      assert(i==g->numLocalEdges(t));
      j = PCU_Add_Long(j);
      assert(j==g->numGlobalEdges(t));
      k = PCU_Add_Long(k);
      assert(k==g->numGlobalPins(t));
      assert(l==g->numLocalPins(t));
      eitr = g->begin(t);
      while ((edge = g->iterate(eitr))) {
        GraphVertex* other;
        PinIterator* pitr = g->pins(edge);
        j=0;
        while ((other = g->iterate(pitr))) {
          j++;
        }
        g->destroy(pitr);
        assert(g->degree(edge)==j);
      }
      g->destroy(eitr);
    }
    //Ensure all ghost vertices have valid owners
    GhostIterator* g_itr = g->beginGhosts();
    GraphVertex* gv;
    while ((gv = g->iterate(g_itr))) {
      assert(g->owner(gv)!=PCU_Comm_Self());
      assert(g->owner(gv)<PCU_Comm_Peers());
    }

    return true;
  }

}
<commit_msg>Change asserts in validity check to return false, this should be made more precise at a future point<commit_after>#include "ngraph.h"
#include <PCU.h>
namespace agi {

  bool checkValidity(Ngraph* g) {
    lid_t i =0;
    VertexIterator* vitr = g->begin();
    GraphVertex* vtx;
    while ((vtx = g->iterate(vitr))) {
      i++;
    }
    if(g->numLocalVtxs()!=i) return false;
    lid_t ig = PCU_Add_Long(i);
    if(g->numGlobalVtxs()!=ig) return false;
    vitr = g->begin();
    while ((vtx = g->iterate(vitr))) {
      for (etype t = 0;t<g->numEdgeTypes();t++) {
        GraphEdge* edge;
        EdgeIterator* eitr = g->edges(vtx,t);
        lid_t j=0;
        while ((edge = g->iterate(eitr))) {
          j++;
        }
        g->destroy(eitr);
        if(g->degree(vtx,t)!=j) return false;
      }
    }

    vitr = g->begin();
    while ((vtx = g->iterate(vitr))) {
      for (etype t = 0;t<g->numEdgeTypes();t++) {
        GraphEdge* edge;
        EdgeIterator* eitr = g->edges(vtx,t);
        while ((edge = g->iterate(eitr))) {
          PinIterator* pitr = g->pins(edge);
          GraphVertex* other;
          while ((other = g->iterate(pitr))) {
            if (g->isEqual(other,vtx))
              break;
          }
          if(!other) return false;
          g->destroy(pitr);
        }
        g->destroy(eitr);
      }
    }

    for (etype t=0;t<g->numEdgeTypes();t++) {
      EdgeIterator* eitr = g->begin(t);
      GraphEdge* edge;
      i=0;
      lid_t j=0;
      lid_t k=0;
      lid_t l=0;
      while ((edge = g->iterate(eitr))) {
        i++;
        l+=g->degree(edge);
        Peers res;
        g->getResidence(edge,res);
        Peers::iterator itr;
        part_t owner=PCU_Comm_Self();
        for (itr=res.begin();itr!=res.end();itr++) {
          if (*itr<owner)
            break;
        }
        if (itr==res.end()||!g->isHyper()){
          j++;
          k+=g->degree(edge);
        }
      }
      g->destroy(eitr);
      if(i!=g->numLocalEdges(t)) return false;
      j = PCU_Add_Long(j);
      if(j!=g->numGlobalEdges(t)) return false;
      k = PCU_Add_Long(k);
      if(k!=g->numGlobalPins(t)) return false;
      if(l!=g->numLocalPins(t)) return false;
      eitr = g->begin(t);
      while ((edge = g->iterate(eitr))) {
        GraphVertex* other;
        PinIterator* pitr = g->pins(edge);
        j=0;
        while ((other = g->iterate(pitr))) {
          j++;
        }
        g->destroy(pitr);
        if(g->degree(edge)!=j) return false;
      }
      g->destroy(eitr);
    }
    //Ensure all ghost vertices have valid owners
    GhostIterator* g_itr = g->beginGhosts();
    GraphVertex* gv;
    while ((gv = g->iterate(g_itr))) {
      if(g->owner(gv)==PCU_Comm_Self()) return false;
      if(g->owner(gv)>=PCU_Comm_Peers()) return false;
    }

    return true;
  }

}
<|endoftext|>


<commit_before>// Copyright (c) 2017-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <chainparams.h>
#include <index/base.h>
#include <node/blockstorage.h>
#include <node/ui_interface.h>
#include <shutdown.h>
#include <tinyformat.h>
#include <util/thread.h>
#include <util/translation.h>
#include <validation.h> // For g_chainman
#include <warnings.h>

constexpr uint8_t DB_BEST_BLOCK{'B'};

constexpr int64_t SYNC_LOG_INTERVAL = 30; // seconds
constexpr int64_t SYNC_LOCATOR_WRITE_INTERVAL = 30; // seconds

template <typename... Args>
static void FatalError(const char* fmt, const Args&... args)
{
    std::string strMessage = tfm::format(fmt, args...);
    SetMiscWarning(Untranslated(strMessage));
    LogPrintf("*** %s\n", strMessage);
    AbortError(_("A fatal internal error occurred, see debug.log for details"));
    StartShutdown();
}

BaseIndex::DB::DB(const fs::path& path, size_t n_cache_size, bool f_memory, bool f_wipe, bool f_obfuscate) :
    CDBWrapper(path, n_cache_size, f_memory, f_wipe, f_obfuscate)
{}

bool BaseIndex::DB::ReadBestBlock(CBlockLocator& locator) const
{
    bool success = Read(DB_BEST_BLOCK, locator);
    if (!success) {
        locator.SetNull();
    }
    return success;
}

void BaseIndex::DB::WriteBestBlock(CDBBatch& batch, const CBlockLocator& locator)
{
    batch.Write(DB_BEST_BLOCK, locator);
}

BaseIndex::~BaseIndex()
{
    Interrupt();
    Stop();
}

bool BaseIndex::Init()
{
    CBlockLocator locator;
    if (!GetDB().ReadBestBlock(locator)) {
        locator.SetNull();
    }

    LOCK(cs_main);
    if (locator.IsNull()) {
        m_best_block_index = nullptr;
    } else {
        m_best_block_index = m_chainstate->m_blockman.FindForkInGlobalIndex(m_chainstate->m_chain, locator);
    }
    CChain& active_chain = m_chainstate->m_chain;
    m_synced = m_best_block_index.load() == active_chain.Tip();
    if (!m_synced) {
        bool prune_violation = false;
        if (!m_best_block_index) {
            // index is not built yet
            // make sure we have all block data back to the genesis
            const CBlockIndex* block = active_chain.Tip();
            while (block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) {
                block = block->pprev;
            }
            prune_violation = block != active_chain.Genesis();
        }
        // in case the index has a best block set and is not fully synced
        // check if we have the required blocks to continue building the index
        else {
            const CBlockIndex* block_to_test = m_best_block_index.load();
            if (!active_chain.Contains(block_to_test)) {
                // if the bestblock is not part of the mainchain, find the fork
                // and make sure we have all data down to the fork
                block_to_test = active_chain.FindFork(block_to_test);
            }
            const CBlockIndex* block = active_chain.Tip();
            prune_violation = true;
            // check backwards from the tip if we have all block data until we reach the indexes bestblock
            while (block_to_test && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) {
                if (block_to_test == block) {
                    prune_violation = false;
                    break;
                }
                block = block->pprev;
            }
        }
        if (prune_violation) {
            return InitError(strprintf(Untranslated("%s best block of the index goes beyond pruned data. Please disable the index or reindex (which will download the whole blockchain again)"), GetName()));
        }
    }
    return true;
}

static const CBlockIndex* NextSyncBlock(const CBlockIndex* pindex_prev, CChain& chain) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
    AssertLockHeld(cs_main);

    if (!pindex_prev) {
        return chain.Genesis();
    }

    const CBlockIndex* pindex = chain.Next(pindex_prev);
    if (pindex) {
        return pindex;
    }

    return chain.Next(chain.FindFork(pindex_prev));
}

void BaseIndex::ThreadSync()
{
    const CBlockIndex* pindex = m_best_block_index.load();
    if (!m_synced) {
        auto& consensus_params = Params().GetConsensus();

        int64_t last_log_time = 0;
        int64_t last_locator_write_time = 0;
        while (true) {
            if (m_interrupt) {
                m_best_block_index = pindex;
                // No need to handle errors in Commit. If it fails, the error will be already be
                // logged. The best way to recover is to continue, as index cannot be corrupted by
                // a missed commit to disk for an advanced index state.
                Commit();
                return;
            }

            {
                LOCK(cs_main);
                const CBlockIndex* pindex_next = NextSyncBlock(pindex, m_chainstate->m_chain);
                if (!pindex_next) {
                    m_best_block_index = pindex;
                    m_synced = true;
                    // No need to handle errors in Commit. See rationale above.
                    Commit();
                    break;
                }
                if (pindex_next->pprev != pindex && !Rewind(pindex, pindex_next->pprev)) {
                    FatalError("%s: Failed to rewind index %s to a previous chain tip",
                               __func__, GetName());
                    return;
                }
                pindex = pindex_next;
            }

            int64_t current_time = GetTime();
            if (last_log_time + SYNC_LOG_INTERVAL < current_time) {
                LogPrintf("Syncing %s with block chain from height %d\n",
                          GetName(), pindex->nHeight);
                last_log_time = current_time;
            }

            if (last_locator_write_time + SYNC_LOCATOR_WRITE_INTERVAL < current_time) {
                m_best_block_index = pindex;
                last_locator_write_time = current_time;
                // No need to handle errors in Commit. See rationale above.
                Commit();
            }

            CBlock block;
            if (!ReadBlockFromDisk(block, pindex, consensus_params)) {
                FatalError("%s: Failed to read block %s from disk",
                           __func__, pindex->GetBlockHash().ToString());
                return;
            }
            if (!WriteBlock(block, pindex)) {
                FatalError("%s: Failed to write block %s to index database",
                           __func__, pindex->GetBlockHash().ToString());
                return;
            }
        }
    }

    if (pindex) {
        LogPrintf("%s is enabled at height %d\n", GetName(), pindex->nHeight);
    } else {
        LogPrintf("%s is enabled\n", GetName());
    }
}

bool BaseIndex::Commit()
{
    CDBBatch batch(GetDB());
    if (!CommitInternal(batch) || !GetDB().WriteBatch(batch)) {
        return error("%s: Failed to commit latest %s state", __func__, GetName());
    }
    return true;
}

bool BaseIndex::CommitInternal(CDBBatch& batch)
{
    LOCK(cs_main);
    GetDB().WriteBestBlock(batch, m_chainstate->m_chain.GetLocator(m_best_block_index));
    return true;
}

bool BaseIndex::Rewind(const CBlockIndex* current_tip, const CBlockIndex* new_tip)
{
    assert(current_tip == m_best_block_index);
    assert(current_tip->GetAncestor(new_tip->nHeight) == new_tip);

    // In the case of a reorg, ensure persisted block locator is not stale.
    // Pruning has a minimum of 288 blocks-to-keep and getting the index
    // out of sync may be possible but a users fault.
    // In case we reorg beyond the pruned depth, ReadBlockFromDisk would
    // throw and lead to a graceful shutdown
    m_best_block_index = new_tip;
    if (!Commit()) {
        // If commit fails, revert the best block index to avoid corruption.
        m_best_block_index = current_tip;
        return false;
    }

    return true;
}

void BaseIndex::BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex)
{
    if (!m_synced) {
        return;
    }

    const CBlockIndex* best_block_index = m_best_block_index.load();
    if (!best_block_index) {
        if (pindex->nHeight != 0) {
            FatalError("%s: First block connected is not the genesis block (height=%d)",
                       __func__, pindex->nHeight);
            return;
        }
    } else {
        // Ensure block connects to an ancestor of the current best block. This should be the case
        // most of the time, but may not be immediately after the sync thread catches up and sets
        // m_synced. Consider the case where there is a reorg and the blocks on the stale branch are
        // in the ValidationInterface queue backlog even after the sync thread has caught up to the
        // new chain tip. In this unlikely event, log a warning and let the queue clear.
        if (best_block_index->GetAncestor(pindex->nHeight - 1) != pindex->pprev) {
            LogPrintf("%s: WARNING: Block %s does not connect to an ancestor of " /* Continued */
                      "known best chain (tip=%s); not updating index\n",
                      __func__, pindex->GetBlockHash().ToString(),
                      best_block_index->GetBlockHash().ToString());
            return;
        }
        if (best_block_index != pindex->pprev && !Rewind(best_block_index, pindex->pprev)) {
            FatalError("%s: Failed to rewind index %s to a previous chain tip",
                       __func__, GetName());
            return;
        }
    }

    if (WriteBlock(*block, pindex)) {
        m_best_block_index = pindex;
    } else {
        FatalError("%s: Failed to write block %s to index",
                   __func__, pindex->GetBlockHash().ToString());
        return;
    }
}

void BaseIndex::ChainStateFlushed(const CBlockLocator& locator)
{
    if (!m_synced) {
        return;
    }

    const uint256& locator_tip_hash = locator.vHave.front();
    const CBlockIndex* locator_tip_index;
    {
        LOCK(cs_main);
        locator_tip_index = m_chainstate->m_blockman.LookupBlockIndex(locator_tip_hash);
    }

    if (!locator_tip_index) {
        FatalError("%s: First block (hash=%s) in locator was not found",
                   __func__, locator_tip_hash.ToString());
        return;
    }

    // This checks that ChainStateFlushed callbacks are received after BlockConnected. The check may fail
    // immediately after the sync thread catches up and sets m_synced. Consider the case where
    // there is a reorg and the blocks on the stale branch are in the ValidationInterface queue
    // backlog even after the sync thread has caught up to the new chain tip. In this unlikely
    // event, log a warning and let the queue clear.
    const CBlockIndex* best_block_index = m_best_block_index.load();
    if (best_block_index->GetAncestor(locator_tip_index->nHeight) != locator_tip_index) {
        LogPrintf("%s: WARNING: Locator contains block (hash=%s) not on known best " /* Continued */
                  "chain (tip=%s); not writing index locator\n",
                  __func__, locator_tip_hash.ToString(),
                  best_block_index->GetBlockHash().ToString());
        return;
    }

    // No need to handle errors in Commit. If it fails, the error will be already be logged. The
    // best way to recover is to continue, as index cannot be corrupted by a missed commit to disk
    // for an advanced index state.
    Commit();
}

bool BaseIndex::BlockUntilSyncedToCurrentChain() const
{
    AssertLockNotHeld(cs_main);

    if (!m_synced) {
        return false;
    }

    {
        // Skip the queue-draining stuff if we know we're caught up with
        // ::ChainActive().Tip().
        LOCK(cs_main);
        const CBlockIndex* chain_tip = m_chainstate->m_chain.Tip();
        const CBlockIndex* best_block_index = m_best_block_index.load();
        if (best_block_index->GetAncestor(chain_tip->nHeight) == chain_tip) {
            return true;
        }
    }

    LogPrintf("%s: %s is catching up on block notifications\n", __func__, GetName());
    SyncWithValidationInterfaceQueue();
    return true;
}

void BaseIndex::Interrupt()
{
    m_interrupt();
}

bool BaseIndex::Start(CChainState& active_chainstate)
{
    assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate));
    m_chainstate = &active_chainstate;
    // Need to register this ValidationInterface before running Init(), so that
    // callbacks are not missed if Init sets m_synced to true.
    RegisterValidationInterface(this);
    if (!Init()) {
        return false;
    }

    m_thread_sync = std::thread(&util::TraceThread, GetName(), [this] { ThreadSync(); });
    return true;
}

void BaseIndex::Stop()
{
    UnregisterValidationInterface(this);

    if (m_thread_sync.joinable()) {
        m_thread_sync.join();
    }
}

IndexSummary BaseIndex::GetSummary() const
{
    IndexSummary summary{};
    summary.name = GetName();
    summary.synced = m_synced;
    summary.best_block_height = m_best_block_index ? m_best_block_index.load()->nHeight : 0;
    return summary;
}
<commit_msg>index: refactor-only: Reuse CChain ref<commit_after>// Copyright (c) 2017-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <chainparams.h>
#include <index/base.h>
#include <node/blockstorage.h>
#include <node/ui_interface.h>
#include <shutdown.h>
#include <tinyformat.h>
#include <util/thread.h>
#include <util/translation.h>
#include <validation.h> // For g_chainman
#include <warnings.h>

constexpr uint8_t DB_BEST_BLOCK{'B'};

constexpr int64_t SYNC_LOG_INTERVAL = 30; // seconds
constexpr int64_t SYNC_LOCATOR_WRITE_INTERVAL = 30; // seconds

template <typename... Args>
static void FatalError(const char* fmt, const Args&... args)
{
    std::string strMessage = tfm::format(fmt, args...);
    SetMiscWarning(Untranslated(strMessage));
    LogPrintf("*** %s\n", strMessage);
    AbortError(_("A fatal internal error occurred, see debug.log for details"));
    StartShutdown();
}

BaseIndex::DB::DB(const fs::path& path, size_t n_cache_size, bool f_memory, bool f_wipe, bool f_obfuscate) :
    CDBWrapper(path, n_cache_size, f_memory, f_wipe, f_obfuscate)
{}

bool BaseIndex::DB::ReadBestBlock(CBlockLocator& locator) const
{
    bool success = Read(DB_BEST_BLOCK, locator);
    if (!success) {
        locator.SetNull();
    }
    return success;
}

void BaseIndex::DB::WriteBestBlock(CDBBatch& batch, const CBlockLocator& locator)
{
    batch.Write(DB_BEST_BLOCK, locator);
}

BaseIndex::~BaseIndex()
{
    Interrupt();
    Stop();
}

bool BaseIndex::Init()
{
    CBlockLocator locator;
    if (!GetDB().ReadBestBlock(locator)) {
        locator.SetNull();
    }

    LOCK(cs_main);
    CChain& active_chain = m_chainstate->m_chain;
    if (locator.IsNull()) {
        m_best_block_index = nullptr;
    } else {
        m_best_block_index = m_chainstate->m_blockman.FindForkInGlobalIndex(active_chain, locator);
    }
    m_synced = m_best_block_index.load() == active_chain.Tip();
    if (!m_synced) {
        bool prune_violation = false;
        if (!m_best_block_index) {
            // index is not built yet
            // make sure we have all block data back to the genesis
            const CBlockIndex* block = active_chain.Tip();
            while (block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) {
                block = block->pprev;
            }
            prune_violation = block != active_chain.Genesis();
        }
        // in case the index has a best block set and is not fully synced
        // check if we have the required blocks to continue building the index
        else {
            const CBlockIndex* block_to_test = m_best_block_index.load();
            if (!active_chain.Contains(block_to_test)) {
                // if the bestblock is not part of the mainchain, find the fork
                // and make sure we have all data down to the fork
                block_to_test = active_chain.FindFork(block_to_test);
            }
            const CBlockIndex* block = active_chain.Tip();
            prune_violation = true;
            // check backwards from the tip if we have all block data until we reach the indexes bestblock
            while (block_to_test && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) {
                if (block_to_test == block) {
                    prune_violation = false;
                    break;
                }
                block = block->pprev;
            }
        }
        if (prune_violation) {
            return InitError(strprintf(Untranslated("%s best block of the index goes beyond pruned data. Please disable the index or reindex (which will download the whole blockchain again)"), GetName()));
        }
    }
    return true;
}

static const CBlockIndex* NextSyncBlock(const CBlockIndex* pindex_prev, CChain& chain) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
    AssertLockHeld(cs_main);

    if (!pindex_prev) {
        return chain.Genesis();
    }

    const CBlockIndex* pindex = chain.Next(pindex_prev);
    if (pindex) {
        return pindex;
    }

    return chain.Next(chain.FindFork(pindex_prev));
}

void BaseIndex::ThreadSync()
{
    const CBlockIndex* pindex = m_best_block_index.load();
    if (!m_synced) {
        auto& consensus_params = Params().GetConsensus();

        int64_t last_log_time = 0;
        int64_t last_locator_write_time = 0;
        while (true) {
            if (m_interrupt) {
                m_best_block_index = pindex;
                // No need to handle errors in Commit. If it fails, the error will be already be
                // logged. The best way to recover is to continue, as index cannot be corrupted by
                // a missed commit to disk for an advanced index state.
                Commit();
                return;
            }

            {
                LOCK(cs_main);
                const CBlockIndex* pindex_next = NextSyncBlock(pindex, m_chainstate->m_chain);
                if (!pindex_next) {
                    m_best_block_index = pindex;
                    m_synced = true;
                    // No need to handle errors in Commit. See rationale above.
                    Commit();
                    break;
                }
                if (pindex_next->pprev != pindex && !Rewind(pindex, pindex_next->pprev)) {
                    FatalError("%s: Failed to rewind index %s to a previous chain tip",
                               __func__, GetName());
                    return;
                }
                pindex = pindex_next;
            }

            int64_t current_time = GetTime();
            if (last_log_time + SYNC_LOG_INTERVAL < current_time) {
                LogPrintf("Syncing %s with block chain from height %d\n",
                          GetName(), pindex->nHeight);
                last_log_time = current_time;
            }

            if (last_locator_write_time + SYNC_LOCATOR_WRITE_INTERVAL < current_time) {
                m_best_block_index = pindex;
                last_locator_write_time = current_time;
                // No need to handle errors in Commit. See rationale above.
                Commit();
            }

            CBlock block;
            if (!ReadBlockFromDisk(block, pindex, consensus_params)) {
                FatalError("%s: Failed to read block %s from disk",
                           __func__, pindex->GetBlockHash().ToString());
                return;
            }
            if (!WriteBlock(block, pindex)) {
                FatalError("%s: Failed to write block %s to index database",
                           __func__, pindex->GetBlockHash().ToString());
                return;
            }
        }
    }

    if (pindex) {
        LogPrintf("%s is enabled at height %d\n", GetName(), pindex->nHeight);
    } else {
        LogPrintf("%s is enabled\n", GetName());
    }
}

bool BaseIndex::Commit()
{
    CDBBatch batch(GetDB());
    if (!CommitInternal(batch) || !GetDB().WriteBatch(batch)) {
        return error("%s: Failed to commit latest %s state", __func__, GetName());
    }
    return true;
}

bool BaseIndex::CommitInternal(CDBBatch& batch)
{
    LOCK(cs_main);
    GetDB().WriteBestBlock(batch, m_chainstate->m_chain.GetLocator(m_best_block_index));
    return true;
}

bool BaseIndex::Rewind(const CBlockIndex* current_tip, const CBlockIndex* new_tip)
{
    assert(current_tip == m_best_block_index);
    assert(current_tip->GetAncestor(new_tip->nHeight) == new_tip);

    // In the case of a reorg, ensure persisted block locator is not stale.
    // Pruning has a minimum of 288 blocks-to-keep and getting the index
    // out of sync may be possible but a users fault.
    // In case we reorg beyond the pruned depth, ReadBlockFromDisk would
    // throw and lead to a graceful shutdown
    m_best_block_index = new_tip;
    if (!Commit()) {
        // If commit fails, revert the best block index to avoid corruption.
        m_best_block_index = current_tip;
        return false;
    }

    return true;
}

void BaseIndex::BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex)
{
    if (!m_synced) {
        return;
    }

    const CBlockIndex* best_block_index = m_best_block_index.load();
    if (!best_block_index) {
        if (pindex->nHeight != 0) {
            FatalError("%s: First block connected is not the genesis block (height=%d)",
                       __func__, pindex->nHeight);
            return;
        }
    } else {
        // Ensure block connects to an ancestor of the current best block. This should be the case
        // most of the time, but may not be immediately after the sync thread catches up and sets
        // m_synced. Consider the case where there is a reorg and the blocks on the stale branch are
        // in the ValidationInterface queue backlog even after the sync thread has caught up to the
        // new chain tip. In this unlikely event, log a warning and let the queue clear.
        if (best_block_index->GetAncestor(pindex->nHeight - 1) != pindex->pprev) {
            LogPrintf("%s: WARNING: Block %s does not connect to an ancestor of " /* Continued */
                      "known best chain (tip=%s); not updating index\n",
                      __func__, pindex->GetBlockHash().ToString(),
                      best_block_index->GetBlockHash().ToString());
            return;
        }
        if (best_block_index != pindex->pprev && !Rewind(best_block_index, pindex->pprev)) {
            FatalError("%s: Failed to rewind index %s to a previous chain tip",
                       __func__, GetName());
            return;
        }
    }

    if (WriteBlock(*block, pindex)) {
        m_best_block_index = pindex;
    } else {
        FatalError("%s: Failed to write block %s to index",
                   __func__, pindex->GetBlockHash().ToString());
        return;
    }
}

void BaseIndex::ChainStateFlushed(const CBlockLocator& locator)
{
    if (!m_synced) {
        return;
    }

    const uint256& locator_tip_hash = locator.vHave.front();
    const CBlockIndex* locator_tip_index;
    {
        LOCK(cs_main);
        locator_tip_index = m_chainstate->m_blockman.LookupBlockIndex(locator_tip_hash);
    }

    if (!locator_tip_index) {
        FatalError("%s: First block (hash=%s) in locator was not found",
                   __func__, locator_tip_hash.ToString());
        return;
    }

    // This checks that ChainStateFlushed callbacks are received after BlockConnected. The check may fail
    // immediately after the sync thread catches up and sets m_synced. Consider the case where
    // there is a reorg and the blocks on the stale branch are in the ValidationInterface queue
    // backlog even after the sync thread has caught up to the new chain tip. In this unlikely
    // event, log a warning and let the queue clear.
    const CBlockIndex* best_block_index = m_best_block_index.load();
    if (best_block_index->GetAncestor(locator_tip_index->nHeight) != locator_tip_index) {
        LogPrintf("%s: WARNING: Locator contains block (hash=%s) not on known best " /* Continued */
                  "chain (tip=%s); not writing index locator\n",
                  __func__, locator_tip_hash.ToString(),
                  best_block_index->GetBlockHash().ToString());
        return;
    }

    // No need to handle errors in Commit. If it fails, the error will be already be logged. The
    // best way to recover is to continue, as index cannot be corrupted by a missed commit to disk
    // for an advanced index state.
    Commit();
}

bool BaseIndex::BlockUntilSyncedToCurrentChain() const
{
    AssertLockNotHeld(cs_main);

    if (!m_synced) {
        return false;
    }

    {
        // Skip the queue-draining stuff if we know we're caught up with
        // ::ChainActive().Tip().
        LOCK(cs_main);
        const CBlockIndex* chain_tip = m_chainstate->m_chain.Tip();
        const CBlockIndex* best_block_index = m_best_block_index.load();
        if (best_block_index->GetAncestor(chain_tip->nHeight) == chain_tip) {
            return true;
        }
    }

    LogPrintf("%s: %s is catching up on block notifications\n", __func__, GetName());
    SyncWithValidationInterfaceQueue();
    return true;
}

void BaseIndex::Interrupt()
{
    m_interrupt();
}

bool BaseIndex::Start(CChainState& active_chainstate)
{
    assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate));
    m_chainstate = &active_chainstate;
    // Need to register this ValidationInterface before running Init(), so that
    // callbacks are not missed if Init sets m_synced to true.
    RegisterValidationInterface(this);
    if (!Init()) {
        return false;
    }

    m_thread_sync = std::thread(&util::TraceThread, GetName(), [this] { ThreadSync(); });
    return true;
}

void BaseIndex::Stop()
{
    UnregisterValidationInterface(this);

    if (m_thread_sync.joinable()) {
        m_thread_sync.join();
    }
}

IndexSummary BaseIndex::GetSummary() const
{
    IndexSummary summary{};
    summary.name = GetName();
    summary.synced = m_synced;
    summary.best_block_height = m_best_block_index ? m_best_block_index.load()->nHeight : 0;
    return summary;
}
<|endoftext|>


<commit_before>// -*- c++ -*-
/* $Id$ */

/* timer.cc
 *
 * Copyright (C) 2002 The gtkmm Development Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <glib.h>
#include <glibmm.h>

namespace Glib
{

Timer::Timer()
:
  gobject_ (g_timer_new())
{}

Timer::~Timer() noexcept
{
  g_timer_destroy(gobject_);
}

void Timer::start()
{
  g_timer_start(gobject_);
}

void Timer::stop()
{
  g_timer_stop(gobject_);
}

void Timer::reset()
{
  g_timer_reset(gobject_);
}

double Timer::elapsed() const
{
  return g_timer_elapsed(gobject_, 0);
}

double Timer::elapsed(unsigned long& microseconds) const
{
  return g_timer_elapsed(gobject_, &microseconds);
}

void usleep(unsigned long microseconds)
{
  g_usleep(microseconds);
}

} // namespace Glib

<commit_msg>Fix the build after modification of timer.cc<commit_after>/* timer.cc
 *
 * Copyright (C) 2002 The gtkmm Development Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <glibmm.h>
#include <glib.h>

namespace Glib
{

Timer::Timer()
:
  gobject_ (g_timer_new())
{}

Timer::~Timer() noexcept
{
  g_timer_destroy(gobject_);
}

void Timer::start()
{
  g_timer_start(gobject_);
}

void Timer::stop()
{
  g_timer_stop(gobject_);
}

void Timer::reset()
{
  g_timer_reset(gobject_);
}

double Timer::elapsed() const
{
  return g_timer_elapsed(gobject_, 0);
}

double Timer::elapsed(unsigned long& microseconds) const
{
  return g_timer_elapsed(gobject_, &microseconds);
}

void usleep(unsigned long microseconds)
{
  g_usleep(microseconds);
}

} // namespace Glib

<|endoftext|>


<commit_before>#include "ros/ros.h"
#include "ras_arduino_msgs/ADConverter.h"
#include "nord_messages/IRSensors.h"
#include <cmath>

template<class T>

float front_inverse(int x){
		return (-40.19*exp(x*(-0.004891))+41.03*exp(x*(-0.004897)));
}
float back_inverse(int x){
		return (0.05347*exp(x*(0.0004147))+1.9*exp(x*(-0.008829)));
}

float lfront_inverse(int x){
		return (0.04444*exp(x*(0.001731))+3.319*exp(x*(-0.01844)));
}

float lback_inverse(int x){
		return (77.26*exp(x*(-0.04616))+0.5006*exp(x*(-0.005953)));
}

float rback_inverse(int x){
		return (0.3986*exp(x*(-0.04507))+0.515*exp(x*(-0.00663)));
}

float rfront_inverse(int x){
		return (0.4628*exp(x*(-0.1022))+0.515*exp(x*(-0.00663)));
}

int main(int argc, char** argv)
{
    using nord_messages::IRSensors;
    using ras_arduino_msgs::ADConverter;
    ros::init(argc, argv, "nord_sensors");
    ros::NodeHandle n;

    ros::Publisher ir_pub = n.advertise<IRSensors>("/nord/sensors/ir", 10);

    ros::Subscriber adc_sub = n.subscribe<ADConverter>("/arduino/adc", 10,
        [&](const ADConverter::ConstPtr& msg) {
             IRSensors ir;

			ir.back = back_inverse(msg->ch5);

			ir.front = front_inverse(msg->ch6);

			if(msg->ch1>320){
				ir.left_front = lfront_inverse(0);
			}else{
				ir.left_front = lfront_inverse(msg->ch1);
			}

			if(msg->ch3>320){
				ir.left_back = lback_inverse(0);
			}else{
				ir.left_back = lback_inverse(msg->ch3);
			}

			if(msg->ch7>400){
				ir.right_back = rback_inverse(0);
			}else{
				ir.right_back = rback_inverse(msg->ch7);
			}

			if(msg->ch8>320){
				ir.right_front = rfront_inverse(0);
			}else{
				ir.right_front = rfront_inverse(msg->ch8);
			}
            ir_pub.publish(ir);
        });

    ros::spin();

    return 0;
}<commit_msg>back left sensor changed<commit_after>#include "ros/ros.h"
#include "ras_arduino_msgs/ADConverter.h"
#include "nord_messages/IRSensors.h"
#include <cmath>

float front_inverse(int x){
		return (-40.19*std::exp(x*(-0.004891))+41.03*std::exp(x*(-0.004897)));
}
float back_inverse(int x){
		return (0.05347*std::exp(x*(0.0004147))+1.9*std::exp(x*(-0.008829)));
}

float lfront_inverse(int x){
		return (28.73*std::exp(x*(-0.04203))+0.4839*std::exp(x*(-0.006104)));
}

float lback_inverse(int x){
		return (25.57*std::exp(x*(-0.03562))+0.2736*std::exp(x*(-0.003856)));
}

float rback_inverse(int x){
		return (0.3986*std::exp(x*(-0.04507))+0.515*std::exp(x*(-0.00663)));
}

float rfront_inverse(int x){
		return (0.4628*std::exp(x*(-0.1022))+0.515*std::exp(x*(-0.00663)));
}

int main(int argc, char** argv)
{
    using nord_messages::IRSensors;
    using ras_arduino_msgs::ADConverter;
    ros::init(argc, argv, "nord_sensors");
    ros::NodeHandle n;

    ros::Publisher ir_pub = n.advertise<IRSensors>("/nord/sensors/ir", 10);

    ros::Subscriber adc_sub = n.subscribe<ADConverter>("/arduino/adc", 10,
        [&](const ADConverter::ConstPtr& msg) {
             IRSensors ir;

			ir.back = back_inverse(msg->ch5);

			ir.front = front_inverse(msg->ch6);
/*ir.back = back_inverse(0);

			ir.front = front_inverse(0);*/

			if(msg->ch1>320){
				ir.left_front = lfront_inverse(0);
			}else{
				ir.left_front = lfront_inverse(msg->ch1);
			}
			//ir.left_front = lfront_inverse(0);
			if(msg->ch3>320){
				ir.left_back = lback_inverse(0);
			}else{
				ir.left_back = lback_inverse(msg->ch3);
			}
			//ir.left_back = lback_inverse(0);
			if(msg->ch7>400){
				ir.right_back = rback_inverse(0);
			}else{
				ir.right_back = rback_inverse(msg->ch7);
			}
			//ir.right_back = rback_inverse(0);
			if(msg->ch8>320){
				ir.right_front = rfront_inverse(0);
			}else{
				ir.right_front = rfront_inverse(msg->ch8);
			}
			//ir.right_front = rfront_inverse(0);
            ir_pub.publish(ir);
        });

    ros::spin();

    return 0;
}
<|endoftext|>


<commit_before>#include "Image.hpp"

#include "StringEx.hpp"
#include "TargaImage.hpp"
#include "PNGImage.hpp"

using namespace std;
using namespace MPACK::Core;

namespace MPACK
{
	namespace Graphics
	{
		Image::Image()
			: m_width(0), m_height(0), m_GLFormatType(0), m_bytesPerPixel(0),
			  m_imageBuffer(NULL), m_internalFormatType(Image::InternalFormatType::NONE)
		{
		}

		Image::~Image()
		{
			Unload();
		}

		void Image::Init(const int &width, const int &height)
		{
			Unload();

			if (width < 0)
			{
				LOGW("PNGImage::Init() invalid width!");
				m_width = 1;
			}
			else
			{
				m_width = width;
			}

			if (height < 0)
			{
				LOGW("PNGImage::Init() invalid height!");
				m_height = 1;
			}
			else
			{
				m_height = height;
			}

			m_bytesPerPixel = 4;
			m_GLFormatType = GL_RGBA;

			m_imageBuffer = new BYTE[m_width * m_height * m_bytesPerPixel];
		}

		ReturnValue Image::Load(const std::string& path, bool flipForOpenGL, FileFormatType fileFormatType)
		{
			Unload();

			if (fileFormatType == FileFormatType::AUTO)
			{
				string ext;
				Core::StringEx::GetExtension(path.c_str(), ext);
				Core::StringEx::Upper(ext);
				if(ext == "TGA")
				{
					fileFormatType = FileFormatType::TGA;
				}
				else if(ext == "PNG")
				{
					fileFormatType = FileFormatType::PNG;
				}
				else if(ext == "PPM")
				{
					fileFormatType = FileFormatType::PPM;
				}
				else
				{
					LOGE("Image::Load() format auto-detect fail: invalid extension: %s", path.c_str());
					return RETURN_VALUE_KO;
				}
			}

			switch(fileFormatType)
			{
				case FileFormatType::TGA:
					if (LoadTGA(this, path, flipForOpenGL) == RETURN_VALUE_KO)
					{
						LOGE("Image::Load() fail to load TGA image: %s", path.c_str());
						return RETURN_VALUE_KO;
					}
				break;
				case FileFormatType::PNG:
					if (LoadPNG(this, path, flipForOpenGL) == RETURN_VALUE_KO)
					{
						LOGE("Image::Load() fail to load PNG image: %s", path.c_str());
						return RETURN_VALUE_KO;
					}
				break;
				case FileFormatType::PPM:
					if (LoadPPM(this, path, flipForOpenGL) == RETURN_VALUE_KO)
					{
						LOGE("Image::Load() fail to load PPM image: %s", path.c_str());
						return RETURN_VALUE_KO;
					}
				break;
			}

			return RETURN_VALUE_OK;
		}

		ReturnValue Image::Save(const std::string& path, FileFormatType fileFormatType)
		{
			if (fileFormatType == FileFormatType::AUTO)
			{
				fileFormatType = FileFormatType::PNG;
			}

			switch(fileFormatType)
			{
				case FileFormatType::TGA:
					if (SaveTGA(this, path) == RETURN_VALUE_KO)
					{
						LOGE("Image::Save() fail to save image as TGA");
						return RETURN_VALUE_KO;
					}
				break;
				case FileFormatType::PNG:
					if (SavePNG(this, path) == RETURN_VALUE_KO)
					{
						LOGE("Image::Save() fail to save image as PNG");
						return RETURN_VALUE_KO;
					}
				break;
				case FileFormatType::PPM:
					if (SavePPM(this, path) == RETURN_VALUE_KO)
					{
						LOGE("Image::Save() fail to save image as PPM");
						return RETURN_VALUE_KO;
					}
				break;
			}
			return RETURN_VALUE_OK;
		}

		void Image::Unload()
		{
			if (m_imageBuffer)
			{
				m_width = 0;
				m_height = 0;
				m_internalFormatType = InternalFormatType::NONE;
				m_GLFormatType = 0;
				m_bytesPerPixel = 0;
				delete[] m_imageBuffer;
				m_imageBuffer = 0;
			}
		}

		void Image::InitColor(const int &width, const int &height, const Color &c)
		{
			Init(width, height);
			FillColor(Rect(0, 0, m_width, m_height), c);
		}

		void Image::FillColor(const Rect &rect, const Color &c)
		{
			for(int i = 0; i < m_width; ++i)
			{
				for(int j = 0; j < m_height; ++j)
				{
					SetPixel(rect.x + i, rect.y + j, c);
				}
			}
		}

		void Image::Blit(Image *image, const GLushort &x, const GLushort &y)
		{
			BlitSafe(image, Point(x,y), Rect(0,0,image->GetWidth(),image->GetHeight()));
		}

		void Image::Blit(Image *image, const Point &point)
		{
			BlitSafe(image, point, Rect(0,0,image->GetWidth(),image->GetHeight()));
		}

		void Image::Blit(Image *image, const Point &point, const Rect &rect)
		{
			BlitSafe(image, point, rect);
		}

		void Image::FlipVertical()
		{
			for(int i = 0; i < (m_width >> 1); ++i)
			{
				for(int j = 0; j < m_height; ++j)
				{
					int offset1 = i * m_width + j;
					offset1 *= m_bytesPerPixel;

					int vi = m_width - i - 1;
					int vj = j;

					int offset2 = vi * m_width + vj;
					offset2 *= m_bytesPerPixel;

					StringEx::MemSwap((char*)(m_imageBuffer + offset1),(char*)(m_imageBuffer + offset2),m_bytesPerPixel);
				}
			}
		}

		void Image::FlipHorizontal()
		{
			for(int i = 0; i < m_width; ++i)
			{
				for(int j = 0; j < (m_height >> 1); ++j)
				{
					int offset1 = i * m_width + j;
					offset1 *= m_bytesPerPixel;

					int vi = i;
					int vj = m_height - j + 1;

					int offset2 = vi * m_width + vj;
					offset2 *= m_bytesPerPixel;

					StringEx::MemSwap((char*)(m_imageBuffer + offset1),(char*)(m_imageBuffer + offset2),m_bytesPerPixel);
				}
			}
		}

		GLushort Image::GetWidth() const
		{
			return m_width;
		}

		GLushort Image::GetHeight() const
		{
			return m_height;
		}

		GLushort Image::GetBytesPerPixel() const
		{
			return m_bytesPerPixel;
		}

		GLint Image::GetGLFormat() const
		{
			return m_GLFormatType;
		}

		Image::InternalFormatType Image::GetFormat() const
		{
			return m_internalFormatType;
		}

		bool Image::HaveAlphaChannel() const
		{
			return m_internalFormatType == Image::InternalFormatType::GRAY_ALPHA ||
				   m_internalFormatType == Image::InternalFormatType::RGBA;
		}

		const BYTE* Image::GetImageData() const
		{
			return m_imageBuffer;
		}

		const BYTE* Image::GetPixelPointer(const GLushort &x, const GLushort &y) const
		{
			int index = y * m_width + x;
			index *= m_bytesPerPixel;
			return m_imageBuffer + index;
		}

		Color Image::GetPixel(const GLushort &x, const GLushort &y) const
		{
			int index =  y * m_width + x;
			index *= m_bytesPerPixel;
			if (m_bytesPerPixel == 4)
			{
				return Color(m_imageBuffer[index], m_imageBuffer[index+1],
							 m_imageBuffer[index+2], m_imageBuffer[index+3]);
			}
			else if(m_bytesPerPixel == 3)
			{
				return Color(m_imageBuffer[index], m_imageBuffer[index+1],
							 m_imageBuffer[index+2], 255);
			}
			else if(m_bytesPerPixel == 2)
			{
				return Color(m_imageBuffer[index], m_imageBuffer[index],
							 m_imageBuffer[index], m_imageBuffer[index+1]);
			}
			else
			{
				return Color(m_imageBuffer[index], m_imageBuffer[index],
							 m_imageBuffer[index], 255);
			}
		}

		void Image::SetPixel(const GLushort &x, const GLushort &y, const Color &c)
		{
			int index = y * m_width + x;
			index *= m_bytesPerPixel;
			if (m_bytesPerPixel == 4)
			{
				m_imageBuffer[index] = c.r;
				m_imageBuffer[index+1] = c.g;
				m_imageBuffer[index+2] = c.b;
				m_imageBuffer[index+3] = c.a;
			}
			else if(m_bytesPerPixel == 3)
			{
				m_imageBuffer[index] = c.r;
				m_imageBuffer[index+1] = c.g;
				m_imageBuffer[index+2] = c.b;
			}
			else if(m_bytesPerPixel == 2)
			{
				unsigned char gray = (c.r + c.g + c.b) / 3;
				m_imageBuffer[index] = gray;
				m_imageBuffer[index+1] = c.a;
			}
			else
			{
				unsigned char gray = (c.r + c.g + c.b) / 3;
				m_imageBuffer[index] = gray;
			}
		}

		void Image::BlitSafe(Image *image, Point point, Rect rect)
		{
			GLushort width = image->GetWidth();
			GLushort height = image->GetHeight();

			if (point.x >= m_width || point.y >= m_height)
			{
				return;
			}

			if (rect.width <= 0 || rect.height <= 0)
			{
				return;
			}

			if (rect.x >= width || rect.y >= height)
			{
				return;
			}

			if (point.x < 0)
			{
				point.x = 0;
			}

			if (point.y < 0)
			{
				point.y = 0;
			}

			GLushort maxWidth = m_width - point.x;
			if (rect.width > maxWidth)
			{
				rect.width = maxWidth;
			}

			GLushort maxHeight = m_height - point.y;
			if (rect.height > maxHeight)
			{
				rect.height = maxHeight - point.y;
			}

			for (int i = 0; i < rect.width; ++i)
			{
				for (int j = 0; j < rect.height; ++j)
				{
					SetPixel(point.x + i,point.y + j, image->GetPixel(rect.x + i, rect.y + j));
				}
			}
		}

		GLushort GetBPP(GLint format)
		{
			switch(format)
			{
				case GL_RGB:
					return 3;
				break;
				case GL_RGBA:
					return 4;
				break;
				case GL_LUMINANCE:
					return 1;
				break;
				case GL_LUMINANCE_ALPHA:
					return 2;
				break;
			}
			return 0;
		}
	}
}
<commit_msg>Fix: change horizontal flip with vertical flip<commit_after>#include "Image.hpp"

#include "StringEx.hpp"
#include "TargaImage.hpp"
#include "PNGImage.hpp"

using namespace std;
using namespace MPACK::Core;

namespace MPACK
{
	namespace Graphics
	{
		Image::Image()
			: m_width(0), m_height(0), m_GLFormatType(0), m_bytesPerPixel(0),
			  m_imageBuffer(NULL), m_internalFormatType(Image::InternalFormatType::NONE)
		{
		}

		Image::~Image()
		{
			Unload();
		}

		void Image::Init(const int &width, const int &height)
		{
			Unload();

			if (width < 0)
			{
				LOGW("PNGImage::Init() invalid width!");
				m_width = 1;
			}
			else
			{
				m_width = width;
			}

			if (height < 0)
			{
				LOGW("PNGImage::Init() invalid height!");
				m_height = 1;
			}
			else
			{
				m_height = height;
			}

			m_bytesPerPixel = 4;
			m_GLFormatType = GL_RGBA;

			m_imageBuffer = new BYTE[m_width * m_height * m_bytesPerPixel];
		}

		ReturnValue Image::Load(const std::string& path, bool flipForOpenGL, FileFormatType fileFormatType)
		{
			Unload();

			if (fileFormatType == FileFormatType::AUTO)
			{
				string ext;
				Core::StringEx::GetExtension(path.c_str(), ext);
				Core::StringEx::Upper(ext);
				if(ext == "TGA")
				{
					fileFormatType = FileFormatType::TGA;
				}
				else if(ext == "PNG")
				{
					fileFormatType = FileFormatType::PNG;
				}
				else if(ext == "PPM")
				{
					fileFormatType = FileFormatType::PPM;
				}
				else
				{
					LOGE("Image::Load() format auto-detect fail: invalid extension: %s", path.c_str());
					return RETURN_VALUE_KO;
				}
			}

			switch(fileFormatType)
			{
				case FileFormatType::TGA:
					if (LoadTGA(this, path, flipForOpenGL) == RETURN_VALUE_KO)
					{
						LOGE("Image::Load() fail to load TGA image: %s", path.c_str());
						return RETURN_VALUE_KO;
					}
				break;
				case FileFormatType::PNG:
					if (LoadPNG(this, path, flipForOpenGL) == RETURN_VALUE_KO)
					{
						LOGE("Image::Load() fail to load PNG image: %s", path.c_str());
						return RETURN_VALUE_KO;
					}
				break;
				case FileFormatType::PPM:
					if (LoadPPM(this, path, flipForOpenGL) == RETURN_VALUE_KO)
					{
						LOGE("Image::Load() fail to load PPM image: %s", path.c_str());
						return RETURN_VALUE_KO;
					}
				break;
			}

			return RETURN_VALUE_OK;
		}

		ReturnValue Image::Save(const std::string& path, FileFormatType fileFormatType)
		{
			if (fileFormatType == FileFormatType::AUTO)
			{
				fileFormatType = FileFormatType::PNG;
			}

			switch(fileFormatType)
			{
				case FileFormatType::TGA:
					if (SaveTGA(this, path) == RETURN_VALUE_KO)
					{
						LOGE("Image::Save() fail to save image as TGA");
						return RETURN_VALUE_KO;
					}
				break;
				case FileFormatType::PNG:
					if (SavePNG(this, path) == RETURN_VALUE_KO)
					{
						LOGE("Image::Save() fail to save image as PNG");
						return RETURN_VALUE_KO;
					}
				break;
				case FileFormatType::PPM:
					if (SavePPM(this, path) == RETURN_VALUE_KO)
					{
						LOGE("Image::Save() fail to save image as PPM");
						return RETURN_VALUE_KO;
					}
				break;
			}
			return RETURN_VALUE_OK;
		}

		void Image::Unload()
		{
			if (m_imageBuffer)
			{
				m_width = 0;
				m_height = 0;
				m_internalFormatType = InternalFormatType::NONE;
				m_GLFormatType = 0;
				m_bytesPerPixel = 0;
				delete[] m_imageBuffer;
				m_imageBuffer = 0;
			}
		}

		void Image::InitColor(const int &width, const int &height, const Color &c)
		{
			Init(width, height);
			FillColor(Rect(0, 0, m_width, m_height), c);
		}

		void Image::FillColor(const Rect &rect, const Color &c)
		{
			for(int i = 0; i < m_width; ++i)
			{
				for(int j = 0; j < m_height; ++j)
				{
					SetPixel(rect.x + i, rect.y + j, c);
				}
			}
		}

		void Image::Blit(Image *image, const GLushort &x, const GLushort &y)
		{
			BlitSafe(image, Point(x,y), Rect(0,0,image->GetWidth(),image->GetHeight()));
		}

		void Image::Blit(Image *image, const Point &point)
		{
			BlitSafe(image, point, Rect(0,0,image->GetWidth(),image->GetHeight()));
		}

		void Image::Blit(Image *image, const Point &point, const Rect &rect)
		{
			BlitSafe(image, point, rect);
		}

		void Image::FlipVertical()
		{
			for(int i = 0; i < m_width; ++i)
			{
				for(int j = 0; j < (m_height >> 1); ++j)
				{
					int offset1 = j * m_width + i;
					offset1 *= m_bytesPerPixel;

					int vi = i;
					int vj = m_height - j - 1;

					int offset2 = vj * m_width + vi;
					offset2 *= m_bytesPerPixel;

					StringEx::MemSwap((char*)(m_imageBuffer + offset1),(char*)(m_imageBuffer + offset2),m_bytesPerPixel);
				}
			}
		}

		void Image::FlipHorizontal()
		{
			for(int i = 0; i < (m_width >> 1); ++i)
			{
				for(int j = 0; j < m_height; ++j)
				{
					int offset1 = j * m_width + i;
					offset1 *= m_bytesPerPixel;

					int vi = m_width - i - 1;
					int vj = j;

					int offset2 = vj * m_width + vi;
					offset2 *= m_bytesPerPixel;

					StringEx::MemSwap((char*)(m_imageBuffer + offset1),(char*)(m_imageBuffer + offset2),m_bytesPerPixel);
				}
			}
		}

		GLushort Image::GetWidth() const
		{
			return m_width;
		}

		GLushort Image::GetHeight() const
		{
			return m_height;
		}

		GLushort Image::GetBytesPerPixel() const
		{
			return m_bytesPerPixel;
		}

		GLint Image::GetGLFormat() const
		{
			return m_GLFormatType;
		}

		Image::InternalFormatType Image::GetFormat() const
		{
			return m_internalFormatType;
		}

		bool Image::HaveAlphaChannel() const
		{
			return m_internalFormatType == Image::InternalFormatType::GRAY_ALPHA ||
				   m_internalFormatType == Image::InternalFormatType::RGBA;
		}

		const BYTE* Image::GetImageData() const
		{
			return m_imageBuffer;
		}

		const BYTE* Image::GetPixelPointer(const GLushort &x, const GLushort &y) const
		{
			int index = y * m_width + x;
			index *= m_bytesPerPixel;
			return m_imageBuffer + index;
		}

		Color Image::GetPixel(const GLushort &x, const GLushort &y) const
		{
			int index =  y * m_width + x;
			index *= m_bytesPerPixel;
			if (m_bytesPerPixel == 4)
			{
				return Color(m_imageBuffer[index], m_imageBuffer[index+1],
							 m_imageBuffer[index+2], m_imageBuffer[index+3]);
			}
			else if(m_bytesPerPixel == 3)
			{
				return Color(m_imageBuffer[index], m_imageBuffer[index+1],
							 m_imageBuffer[index+2], 255);
			}
			else if(m_bytesPerPixel == 2)
			{
				return Color(m_imageBuffer[index], m_imageBuffer[index],
							 m_imageBuffer[index], m_imageBuffer[index+1]);
			}
			else
			{
				return Color(m_imageBuffer[index], m_imageBuffer[index],
							 m_imageBuffer[index], 255);
			}
		}

		void Image::SetPixel(const GLushort &x, const GLushort &y, const Color &c)
		{
			int index = y * m_width + x;
			index *= m_bytesPerPixel;
			if (m_bytesPerPixel == 4)
			{
				m_imageBuffer[index] = c.r;
				m_imageBuffer[index+1] = c.g;
				m_imageBuffer[index+2] = c.b;
				m_imageBuffer[index+3] = c.a;
			}
			else if(m_bytesPerPixel == 3)
			{
				m_imageBuffer[index] = c.r;
				m_imageBuffer[index+1] = c.g;
				m_imageBuffer[index+2] = c.b;
			}
			else if(m_bytesPerPixel == 2)
			{
				unsigned char gray = (c.r + c.g + c.b) / 3;
				m_imageBuffer[index] = gray;
				m_imageBuffer[index+1] = c.a;
			}
			else
			{
				unsigned char gray = (c.r + c.g + c.b) / 3;
				m_imageBuffer[index] = gray;
			}
		}

		void Image::BlitSafe(Image *image, Point point, Rect rect)
		{
			GLushort width = image->GetWidth();
			GLushort height = image->GetHeight();

			if (point.x >= m_width || point.y >= m_height)
			{
				return;
			}

			if (rect.width <= 0 || rect.height <= 0)
			{
				return;
			}

			if (rect.x >= width || rect.y >= height)
			{
				return;
			}

			if (point.x < 0)
			{
				point.x = 0;
			}

			if (point.y < 0)
			{
				point.y = 0;
			}

			GLushort maxWidth = m_width - point.x;
			if (rect.width > maxWidth)
			{
				rect.width = maxWidth;
			}

			GLushort maxHeight = m_height - point.y;
			if (rect.height > maxHeight)
			{
				rect.height = maxHeight - point.y;
			}

			for (int i = 0; i < rect.width; ++i)
			{
				for (int j = 0; j < rect.height; ++j)
				{
					SetPixel(point.x + i,point.y + j, image->GetPixel(rect.x + i, rect.y + j));
				}
			}
		}

		GLushort GetBPP(GLint format)
		{
			switch(format)
			{
				case GL_RGB:
					return 3;
				break;
				case GL_RGBA:
					return 4;
				break;
				case GL_LUMINANCE:
					return 1;
				break;
				case GL_LUMINANCE_ALPHA:
					return 2;
				break;
			}
			return 0;
		}
	}
}
<|endoftext|>


<commit_before>/*************************************************************************
 *   Copyright (C) 2011-2012 by Paul-Louis Ageneau                       *
 *   paul-louis (at) ageneau (dot) org                                   *
 *                                                                       *
 *   This file is part of Arcanet.                                       *
 *                                                                       *
 *   Arcanet is free software: you can redistribute it and/or modify     *
 *   it under the terms of the GNU Affero General Public License as      *
 *   published by the Free Software Foundation, either version 3 of      *
 *   the License, or (at your option) any later version.                 *
 *                                                                       *
 *   Arcanet is distributed in the hope that it will be useful, but      *
 *   WITHOUT ANY WARRANTY; without even the implied warranty of          *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the        *
 *   GNU Affero General Public License for more details.                 *
 *                                                                       *
 *   You should have received a copy of the GNU Affero General Public    *
 *   License along with Arcanet.                                         *
 *   If not, see <http://www.gnu.org/licenses/>.                         *
 *************************************************************************/

#include "bytearray.h"
#include "exception.h"

namespace arc
{

ByteArray::ByteArray(size_t size) :
		mArray(new char[size]),
		mLength(size),
		mLeft(0),
		mReadPos(0),
		mWritePos(0),
		mMustDelete(true)
{

}

ByteArray::ByteArray(char *array, size_t length) :
		mArray(array),
		mLength(length),
		mLeft(length),
		mReadPos(0),
		mWritePos(0),
		mMustDelete(false)
{

}

ByteArray::ByteArray(const ByteArray &array) :
	mArray(array.mArray),
	mLength(array.mLength),
	mLeft(array.mLeft),
	mReadPos(array.mReadPos),
	mWritePos(array.mWritePos),
	mMustDelete(false)
{

}

ByteArray::~ByteArray(void)
{
	if(mMustDelete) delete mArray;
}

char *ByteArray::array(void)
{
	return mArray;
}

const char *ByteArray::array(void) const
{
	return mArray;
}

size_t ByteArray::length(void) const
{
	return mLength;
}

const char *ByteArray::data(void) const
{
	return mArray+mReadPos;
}

size_t ByteArray::size(void) const
{
	return mLeft;
}

void ByteArray::clear(void)
{
	mReadPos = 0;
	mWritePos = 0;
	mLeft = 0;
}

size_t ByteArray::readData(char *buffer, size_t size)
{
	if(mLeft <= 0) return 0;
	size = std::min(size,mLeft);
	std::copy(mArray+mReadPos, mArray+mReadPos+size, buffer);
	mReadPos+= size;
	mLeft-= size;
	return size;
}

void ByteArray::writeData(const char *data, size_t size)
{
	if(mWritePos+size > mLength) throw IOException();
	std::copy(data, data+size, mArray+mWritePos+size);
	mWritePos+= size;
	mLeft+= size;
}

}
<commit_msg>Corrected bad offset in writeData()<commit_after>/*************************************************************************
 *   Copyright (C) 2011-2012 by Paul-Louis Ageneau                       *
 *   paul-louis (at) ageneau (dot) org                                   *
 *                                                                       *
 *   This file is part of Arcanet.                                       *
 *                                                                       *
 *   Arcanet is free software: you can redistribute it and/or modify     *
 *   it under the terms of the GNU Affero General Public License as      *
 *   published by the Free Software Foundation, either version 3 of      *
 *   the License, or (at your option) any later version.                 *
 *                                                                       *
 *   Arcanet is distributed in the hope that it will be useful, but      *
 *   WITHOUT ANY WARRANTY; without even the implied warranty of          *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the        *
 *   GNU Affero General Public License for more details.                 *
 *                                                                       *
 *   You should have received a copy of the GNU Affero General Public    *
 *   License along with Arcanet.                                         *
 *   If not, see <http://www.gnu.org/licenses/>.                         *
 *************************************************************************/

#include "bytearray.h"
#include "exception.h"

namespace arc
{

ByteArray::ByteArray(size_t size) :
		mArray(new char[size]),
		mLength(size),
		mLeft(0),
		mReadPos(0),
		mWritePos(0),
		mMustDelete(true)
{

}

ByteArray::ByteArray(char *array, size_t length) :
		mArray(array),
		mLength(length),
		mLeft(length),
		mReadPos(0),
		mWritePos(0),
		mMustDelete(false)
{

}

ByteArray::ByteArray(const ByteArray &array) :
	mArray(array.mArray),
	mLength(array.mLength),
	mLeft(array.mLeft),
	mReadPos(array.mReadPos),
	mWritePos(array.mWritePos),
	mMustDelete(false)
{

}

ByteArray::~ByteArray(void)
{
	if(mMustDelete) delete mArray;
}

char *ByteArray::array(void)
{
	return mArray;
}

const char *ByteArray::array(void) const
{
	return mArray;
}

size_t ByteArray::length(void) const
{
	return mLength;
}

const char *ByteArray::data(void) const
{
	return mArray+mReadPos;
}

size_t ByteArray::size(void) const
{
	return mLeft;
}

void ByteArray::clear(void)
{
	mReadPos = 0;
	mWritePos = 0;
	mLeft = 0;
}

size_t ByteArray::readData(char *buffer, size_t size)
{
	if(mLeft <= 0) return 0;
	size = std::min(size,mLeft);
	std::copy(mArray+mReadPos, mArray+mReadPos+size, buffer);
	mReadPos+= size;
	mLeft-= size;
	return size;
}

void ByteArray::writeData(const char *data, size_t size)
{
	if(mWritePos+size > mLength) throw IOException();
	std::copy(data, data+size, mArray+mWritePos);
	mWritePos+= size;
	mLeft+= size;
}

}
<|endoftext|>


<commit_before>#include "gtfcuff.h"
#include "genome.h"
#include <iostream>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <cassert>

using namespace std;

gtfcuff::gtfcuff(const string &cufffile)
{
	read_cuff(cufffile);
	build_cuff_index();
}

int gtfcuff::assign_pred(const string &file)
{
	genome gm(file);
	vpred = gm.collect_transcripts();
	build_pred_index();
	return 0;
}

int gtfcuff::assign_ref(const string &file)
{
	genome gm(file);
	vref = gm.collect_transcripts();
	build_ref_index();
	return 0;
}

int gtfcuff::read_cuff(const string &file)
{
	ifstream fin(file.c_str());
	if(fin.fail()) return -1;

	char line[10240];
	while(fin.getline(line, 10240, '\n'))
	{
		cuffitem x(line);
		if(x.code == '@') continue;
		items.push_back(x);
	}

	fin.close();
	return 0;
}

int gtfcuff::build_cuff_index()
{
	t2i.clear();
	for(int i = 0; i < items.size(); i++)
	{
		string s = items[i].transcript_id;
		t2i.insert(pair<string, int>(s, i));
	}
	return 0;
}

int gtfcuff::build_pred_index()
{
	t2p.clear();
	for(int i = 0; i < vpred.size(); i++)
	{
		transcript &t = vpred[i];
		string s = t.transcript_id;
		t2p.insert(pair<string, int>(s, i));
	}
	return 0;
}

int gtfcuff::build_ref_index()
{
	t2r.clear();
	for(int i = 0; i < vref.size(); i++)
	{
		transcript &t = vref[i];
		string s = t.transcript_id;
		t2r.insert(pair<string, int>(s, i));
	}
	return 0;
}

int gtfcuff::classify(const string &fn1, const string &fn2)
{
	ofstream f1(fn1.c_str());
	ofstream f2(fn2.c_str());

	for(int k = 0; k < vpred.size(); k++)
	{
		string s = vpred[k].transcript_id;
		bool b = false;
		if(t2i.find(s) != t2i.end())
		{
			if(items[t2i[s]].code == '=') b = true;
			else b = false;
		}
		if(b == true) vpred[k].write(f1);
		else vpred[k].write(f2);
	}

	f1.close();
	f2.close();
	return 0;
}

int gtfcuff::roc(int refsize)
{
	if(items.size() == 0) return 0;

	sort(items.begin(), items.end(), cuffitem_cmp_coverage);

	int correct = 0;
	for(int i = 0; i < items.size(); i++) if(items[i].code == '=') correct++;

	double max_sen = 0;
	double max_pre = 0;
	double max_cov = 0;
	int max_len = 0;
	int max_correct = 0;
	int max_size = 0;
	double sen0 = correct * 100.0 / refsize;
	for(int i = 0; i < items.size(); i++)
	{
		double sen = correct * 100.0 / refsize;
		double pre = correct * 100.0 / (items.size() - i);

		if(sen * 2.0 < sen0) break;

		if(i % 100 == 0)
		{
			printf("ROC: reference = %d prediction = %lu correct = %d sensitivity = %.2lf precision = %.2lf | coverage = %.3lf, length = %d\n",
				refsize, items.size() - i, correct, sen, pre, items[i].coverage, items[i].length);
		}

		if(items[i].code == '=') correct--;
	}

	return 0;
}

int gtfcuff::quant()
{
	vector<double> qpred;
	vector<double> qref;

	int pcnt = 0;
	int rcnt = 0;
	int prcnt = 0;

	set<string> rr;
	for(int i = 0; i < vpred.size(); i++)
	{
		transcript &t = vpred[i];
		double ptpm = t.TPM;
		double rtpm = 0;
		string s = t.transcript_id;
		bool b = false;
		if(t2i.find(s) != t2i.end())
		{
			int j = t2i[s];
			if(items[j].code == '=')
			{
				string r = items[j].ref_transcript_id;
				if(t2r.find(r) != t2r.end())
				{
					int k = t2r[r];
					rtpm = vref[k].TPM;
					rr.insert(r);
					b = true;
					prcnt++;
				}
			}
		}
		if(b == false) pcnt++;
		qpred.push_back(ptpm);
		qref.push_back(rtpm);
	}

	for(int i = 0; i < vref.size(); i++)
	{
		transcript &t = vref[i];
		string s = t.transcript_id;
		if(rr.find(s) != rr.end()) continue;
		double ptpm = 0;
		double rtpm = t.TPM;
		qpred.push_back(ptpm);
		qref.push_back(rtpm);
		rcnt++;
	}

	// compute pearson
	vector<double> vx;
	vector<double> vy;

	for(int i = 0; i < qpred.size(); i++)
	{
		double x = log(qpred[i] + 1.0);
		double y = log(qref[i] + 1.0);
		vx.push_back(x);
		vy.push_back(y);
	}

	// compute average
	double ax = 0;
	double ay = 0;
	for(int i = 0; i < vx.size(); i++)
	{
		ax += vx[i];
		ay += vy[i];
	}
	ax /= vx.size();
	ay /= vy.size();

	// compute covariance
	double cov = 0;
	double devx = 0;
	double devy = 0;
	for(int i = 0;i < vx.size(); i++)
	{
		cov += (vx[i] - ax) * (vy[i] - ay);
		devx += (vx[i] - ax) * (vx[i] - ax);
		devy += (vy[i] - ay) * (vy[i] - ay);
	}
	cov /= vx.size();
	devx = sqrt(devx / vx.size());
	devy = sqrt(devy / vy.size());

	double pearson = cov / devx / devy;

	printf("pearson = %.3lf, counts of (prediction, common, reference) = (%d, %d, %d)\n", pearson, pcnt, prcnt, rcnt);

	return 0;
}
<commit_msg>update gtfcuff<commit_after>#include "gtfcuff.h"
#include "genome.h"
#include <iostream>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <cassert>

using namespace std;

gtfcuff::gtfcuff(const string &cufffile)
{
	read_cuff(cufffile);
	build_cuff_index();
}

int gtfcuff::assign_pred(const string &file)
{
	genome gm(file);
	vpred = gm.collect_transcripts();
	build_pred_index();
	return 0;
}

int gtfcuff::assign_ref(const string &file)
{
	genome gm(file);
	vref = gm.collect_transcripts();
	build_ref_index();
	return 0;
}

int gtfcuff::read_cuff(const string &file)
{
	ifstream fin(file.c_str());
	if(fin.fail()) return -1;

	char line[10240];
	while(fin.getline(line, 10240, '\n'))
	{
		cuffitem x(line);
		if(x.code == '@') continue;
		items.push_back(x);
	}

	fin.close();
	return 0;
}

int gtfcuff::build_cuff_index()
{
	t2i.clear();
	for(int i = 0; i < items.size(); i++)
	{
		string s = items[i].transcript_id;
		t2i.insert(pair<string, int>(s, i));
	}
	return 0;
}

int gtfcuff::build_pred_index()
{
	t2p.clear();
	for(int i = 0; i < vpred.size(); i++)
	{
		transcript &t = vpred[i];
		string s = t.transcript_id;
		t2p.insert(pair<string, int>(s, i));
	}
	return 0;
}

int gtfcuff::build_ref_index()
{
	t2r.clear();
	for(int i = 0; i < vref.size(); i++)
	{
		transcript &t = vref[i];
		string s = t.transcript_id;
		t2r.insert(pair<string, int>(s, i));
	}
	return 0;
}

int gtfcuff::classify(const string &fn1, const string &fn2)
{
	ofstream f1(fn1.c_str());
	ofstream f2(fn2.c_str());

	for(int k = 0; k < vpred.size(); k++)
	{
		string s = vpred[k].transcript_id;
		bool b = false;
		if(t2i.find(s) != t2i.end())
		{
			if(items[t2i[s]].code == '=') b = true;
			else b = false;
		}
		if(b == true) vpred[k].write(f1);
		else vpred[k].write(f2);
	}

	f1.close();
	f2.close();
	return 0;
}

int gtfcuff::roc(int refsize)
{
	if(items.size() == 0) return 0;

	sort(items.begin(), items.end(), cuffitem_cmp_coverage);

	int correct = 0;
	for(int i = 0; i < items.size(); i++) if(items[i].code == '=') correct++;

	double max_sen = 0;
	double max_pre = 0;
	double max_cov = 0;
	int max_len = 0;
	int max_correct = 0;
	int max_size = 0;
	double sen0 = correct * 100.0 / refsize;
	for(int i = 0; i < items.size(); i++)
	{
		double sen = correct * 100.0 / refsize;
		double pre = correct * 100.0 / (items.size() - i);

		if(sen * 2.0 < sen0) break;

		if(i % 100 == 0)
		{
			printf("ROC: reference = %d prediction = %lu correct = %d sensitivity = %.2lf precision = %.2lf | coverage = %.3lf, length = %d\n",
				refsize, items.size() - i, correct, sen, pre, items[i].coverage, items[i].length);
		}

		if(items[i].code == '=') correct--;
	}

	return 0;
}

int gtfcuff::quant()
{
	vector<double> qpred;
	vector<double> qref;

	int pcnt = 0;
	int rcnt = 0;
	int prcnt = 0;

	set<string> rr;
	for(int i = 0; i < vpred.size(); i++)
	{
		transcript &t = vpred[i];
		double ptpm = t.TPM;
		double rtpm = 0;
		string s = t.transcript_id;
		bool b = false;
		if(t2i.find(s) != t2i.end())
		{
			int j = t2i[s];
			if(items[j].code == '=')
			{
				string r = items[j].ref_transcript_id;
				if(t2r.find(r) != t2r.end())
				{
					int k = t2r[r];
					rtpm = vref[k].TPM;
					rr.insert(r);
					b = true;
					prcnt++;

					printf("pred = %s, ref = %s, pred-quant = %.3lf, ref-quant = %.3lf\n",
							s.c_str(), r.c_str(), ptpm, rtpm);
				}
			}
		}
		if(b == false)
		{
			printf("pred = %s, ref = %s, pred-quant = %.3lf, ref-quant = %.3lf\n", s.c_str(), "N/A", ptpm, rtpm);
			pcnt++;
		}

		qpred.push_back(ptpm);
		qref.push_back(rtpm);
	}

	for(int i = 0; i < vref.size(); i++)
	{
		transcript &t = vref[i];
		string s = t.transcript_id;
		if(rr.find(s) != rr.end()) continue;
		double ptpm = 0;
		double rtpm = t.TPM;
		qpred.push_back(ptpm);
		qref.push_back(rtpm);
		printf("pred = %s, ref = %s, pred-quant = %.3lf, ref-quant = %.3lf\n", "N/A", s.c_str(), ptpm, rtpm);
		rcnt++;
	}

	// compute pearson
	double sumx = 0;
	double sumy = 0;
	for(int i = 0; i < qpred.size(); i++)
	{
		sumx += qpred[i];
		sumy += qref[i];
	}

	vector<double> vx;
	vector<double> vy;

	for(int i = 0; i < qpred.size(); i++)
	{
		double x = log(qpred[i] * 1e6 / sumx + 1.0);
		double y = log(qref[i] * 1e6 / sumy + 1.0);
		vx.push_back(x);
		vy.push_back(y);
	}

	// compute average
	double ax = 0;
	double ay = 0;
	for(int i = 0; i < vx.size(); i++)
	{
		ax += vx[i];
		ay += vy[i];
	}
	ax /= vx.size();
	ay /= vy.size();

	// compute covariance
	double cov = 0;
	double devx = 0;
	double devy = 0;
	for(int i = 0;i < vx.size(); i++)
	{
		cov += (vx[i] - ax) * (vy[i] - ay);
		devx += (vx[i] - ax) * (vx[i] - ax);
		devy += (vy[i] - ay) * (vy[i] - ay);
	}
	cov /= vx.size();
	devx = sqrt(devx / vx.size());
	devy = sqrt(devy / vy.size());

	double pearson = cov / devx / devy;

	printf("pearson = %.3lf, counts of (prediction, common, reference) = (%d, %d, %d)\n", pearson, pcnt, prcnt, rcnt);

	return 0;
}
<|endoftext|>


<commit_before>//===-- VSCode.cpp ----------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include <stdarg.h>
#include <fstream>
#include <mutex>

#include "LLDBUtils.h"
#include "VSCode.h"
#include "llvm/Support/FormatVariadic.h"

#if defined(_WIN32)
#ifndef __MINGW32__
#define NOMINMAX
#include <Windows.h>
#endif // __MINGW32__
#include <fcntl.h>
#include <io.h>
#endif

using namespace lldb_vscode;

namespace lldb_vscode {

VSCode g_vsc;

VSCode::VSCode()
    : launch_info(nullptr), variables(), broadcaster("lldb-vscode"),
      num_regs(0), num_locals(0), num_globals(0), log(),
      exception_breakpoints(
          {{"cpp_catch", "C++ Catch", lldb::eLanguageTypeC_plus_plus},
           {"cpp_throw", "C++ Throw", lldb::eLanguageTypeC_plus_plus},
           {"objc_catch", "Objective C Catch", lldb::eLanguageTypeObjC},
           {"objc_throw", "Objective C Throw", lldb::eLanguageTypeObjC},
           {"swift_catch", "Swift Catch", lldb::eLanguageTypeSwift},
           {"swift_throw", "Swift Throw", lldb::eLanguageTypeSwift}}),
      focus_tid(LLDB_INVALID_THREAD_ID), sent_terminated_event(false),
      stop_at_entry(false) {
  const char *log_file_path = getenv("LLDBVSCODE_LOG");
#if defined(_WIN32)
// Windows opens stdout and stdin in text mode which converts \n to 13,10
// while the value is just 10 on Darwin/Linux. Setting the file mode to binary
// fixes this.
  assert(_setmode(fileno(stdout), _O_BINARY));
  assert(_setmode(fileno(stdin), _O_BINARY));
#endif
  if (log_file_path)
    log.reset(new std::ofstream(log_file_path));
}

VSCode::~VSCode() {
}

int64_t VSCode::GetLineForPC(int64_t sourceReference, lldb::addr_t pc) const {
  auto pos = source_map.find(sourceReference);
  if (pos != source_map.end())
    return pos->second.GetLineForPC(pc);
  return 0;
}

ExceptionBreakpoint *VSCode::GetExceptionBreakpoint(const std::string &filter) {
  for (auto &bp : exception_breakpoints) {
    if (bp.filter == filter)
      return &bp;
  }
  return nullptr;
}

ExceptionBreakpoint *
VSCode::GetExceptionBreakpoint(const lldb::break_id_t bp_id) {
  for (auto &bp : exception_breakpoints) {
    if (bp.bp.GetID() == bp_id)
      return &bp;
  }
  return nullptr;
}

// Send the JSON in "json_str" to the "out" stream. Correctly send the
// "Content-Length:" field followed by the length, followed by the raw
// JSON bytes.
void VSCode::SendJSON(const std::string &json_str) {
  output.write_full("Content-Length: ");
  output.write_full(llvm::utostr(json_str.size()));
  output.write_full("\r\n\r\n");
  output.write_full(json_str);

  if (log) {
    *log << "<-- " << std::endl
         << "Content-Length: " << json_str.size() << "\r\n\r\n"
         << json_str << std::endl;
  }
}

// Serialize the JSON value into a string and send the JSON packet to
// the "out" stream.
void VSCode::SendJSON(const llvm::json::Value &json) {
  std::string s;
  llvm::raw_string_ostream strm(s);
  strm << json;
  static std::mutex mutex;
  std::lock_guard<std::mutex> locker(mutex);
  SendJSON(strm.str());
}

// Read a JSON packet from the "in" stream.
std::string VSCode::ReadJSON() {
  std::string length_str;
  std::string json_str;
  int length;

  if (!input.read_expected(log.get(), "Content-Length: "))
    return json_str;

  if (!input.read_line(log.get(), length_str))
    return json_str;

  if (!llvm::to_integer(length_str, length))
    return json_str;

  if (!input.read_expected(log.get(), "\r\n"))
    return json_str;

  if (!input.read_full(log.get(), length, json_str))
    return json_str;

  return json_str;
}

// "OutputEvent": {
//   "allOf": [ { "$ref": "#/definitions/Event" }, {
//     "type": "object",
//     "description": "Event message for 'output' event type. The event
//                     indicates that the target has produced some output.",
//     "properties": {
//       "event": {
//         "type": "string",
//         "enum": [ "output" ]
//       },
//       "body": {
//         "type": "object",
//         "properties": {
//           "category": {
//             "type": "string",
//             "description": "The output category. If not specified,
//                             'console' is assumed.",
//             "_enum": [ "console", "stdout", "stderr", "telemetry" ]
//           },
//           "output": {
//             "type": "string",
//             "description": "The output to report."
//           },
//           "variablesReference": {
//             "type": "number",
//             "description": "If an attribute 'variablesReference' exists
//                             and its value is > 0, the output contains
//                             objects which can be retrieved by passing
//                             variablesReference to the VariablesRequest."
//           },
//           "source": {
//             "$ref": "#/definitions/Source",
//             "description": "An optional source location where the output
//                             was produced."
//           },
//           "line": {
//             "type": "integer",
//             "description": "An optional source location line where the
//                             output was produced."
//           },
//           "column": {
//             "type": "integer",
//             "description": "An optional source location column where the
//                             output was produced."
//           },
//           "data": {
//             "type":["array","boolean","integer","null","number","object",
//                     "string"],
//             "description": "Optional data to report. For the 'telemetry'
//                             category the data will be sent to telemetry, for
//                             the other categories the data is shown in JSON
//                             format."
//           }
//         },
//         "required": ["output"]
//       }
//     },
//     "required": [ "event", "body" ]
//   }]
// }
void VSCode::SendOutput(OutputType o, const llvm::StringRef output) {
  if (output.empty())
    return;

  llvm::json::Object event(CreateEventObject("output"));
  llvm::json::Object body;
  const char *category = nullptr;
  switch (o) {
  case OutputType::Console:
    category = "console";
    break;
  case OutputType::Stdout:
    category = "stdout";
    break;
  case OutputType::Stderr:
    category = "stderr";
    break;
  case OutputType::Telemetry:
    category = "telemetry";
    break;
  }
  body.try_emplace("category", category);
  EmplaceSafeString(body, "output", output.str());
  event.try_emplace("body", std::move(body));
  SendJSON(llvm::json::Value(std::move(event)));
}

void __attribute__((format(printf, 3, 4)))
VSCode::SendFormattedOutput(OutputType o, const char *format, ...) {
  char buffer[1024];
  va_list args;
  va_start(args, format);
  int actual_length = vsnprintf(buffer, sizeof(buffer), format, args);
  va_end(args);
  SendOutput(o, llvm::StringRef(buffer,
                                std::min<int>(actual_length, sizeof(buffer))));
}

int64_t VSCode::GetNextSourceReference() {
  static int64_t ref = 0;
  return ++ref;
}

ExceptionBreakpoint *
VSCode::GetExceptionBPFromStopReason(lldb::SBThread &thread) {
  const auto num = thread.GetStopReasonDataCount();
  // Check to see if have hit an exception breakpoint and change the
  // reason to "exception", but only do so if all breakpoints that were
  // hit are exception breakpoints.
  ExceptionBreakpoint *exc_bp = nullptr;
  for (size_t i = 0; i < num; i += 2) {
    // thread.GetStopReasonDataAtIndex(i) will return the bp ID and
    // thread.GetStopReasonDataAtIndex(i+1) will return the location
    // within that breakpoint. We only care about the bp ID so we can
    // see if this is an exception breakpoint that is getting hit.
    lldb::break_id_t bp_id = thread.GetStopReasonDataAtIndex(i);
    exc_bp = GetExceptionBreakpoint(bp_id);
    // If any breakpoint is not an exception breakpoint, then stop and
    // report this as a normal breakpoint
    if (exc_bp == nullptr)
      return nullptr;
  }
  return exc_bp;
}

lldb::SBThread VSCode::GetLLDBThread(const llvm::json::Object &arguments) {
  auto tid = GetSigned(arguments, "threadId", LLDB_INVALID_THREAD_ID);
  return target.GetProcess().GetThreadByID(tid);
}

lldb::SBFrame VSCode::GetLLDBFrame(const llvm::json::Object &arguments) {
  const uint64_t frame_id = GetUnsigned(arguments, "frameId", UINT64_MAX);
  lldb::SBProcess process = target.GetProcess();
  // Upper 32 bits is the thread index ID
  lldb::SBThread thread =
      process.GetThreadByIndexID(GetLLDBThreadIndexID(frame_id));
  // Lower 32 bits is the frame index
  return thread.GetFrameAtIndex(GetLLDBFrameID(frame_id));
}

llvm::json::Value VSCode::CreateTopLevelScopes() {
  llvm::json::Array scopes;
  scopes.emplace_back(CreateScope("Locals", VARREF_LOCALS, num_locals, false));
  scopes.emplace_back(
      CreateScope("Globals", VARREF_GLOBALS, num_globals, false));
  scopes.emplace_back(CreateScope("Registers", VARREF_REGS, num_regs, false));
  return llvm::json::Value(std::move(scopes));
}

void VSCode::RunLLDBCommands(llvm::StringRef prefix,
                             const std::vector<std::string> &commands) {
  SendOutput(OutputType::Console,
             llvm::StringRef(::RunLLDBCommands(prefix, commands)));
}

void VSCode::RunInitCommands() {
  RunLLDBCommands("Running initCommands:", init_commands);
}

void VSCode::RunPreRunCommands() {
  RunLLDBCommands("Running preRunCommands:", pre_run_commands);
}

void VSCode::RunStopCommands() {
  RunLLDBCommands("Running stopCommands:", stop_commands);
}

void VSCode::RunExitCommands() {
  RunLLDBCommands("Running exitCommands:", exit_commands);
}

} // namespace lldb_vscode

<commit_msg>[LLDB] Rework a MinGW build fix from D65691<commit_after>//===-- VSCode.cpp ----------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include <stdarg.h>
#include <fstream>
#include <mutex>

#include "LLDBUtils.h"
#include "VSCode.h"
#include "llvm/Support/FormatVariadic.h"

#if defined(_WIN32)
#define NOMINMAX
#include <windows.h>
#include <fcntl.h>
#include <io.h>
#endif

using namespace lldb_vscode;

namespace lldb_vscode {

VSCode g_vsc;

VSCode::VSCode()
    : launch_info(nullptr), variables(), broadcaster("lldb-vscode"),
      num_regs(0), num_locals(0), num_globals(0), log(),
      exception_breakpoints(
          {{"cpp_catch", "C++ Catch", lldb::eLanguageTypeC_plus_plus},
           {"cpp_throw", "C++ Throw", lldb::eLanguageTypeC_plus_plus},
           {"objc_catch", "Objective C Catch", lldb::eLanguageTypeObjC},
           {"objc_throw", "Objective C Throw", lldb::eLanguageTypeObjC},
           {"swift_catch", "Swift Catch", lldb::eLanguageTypeSwift},
           {"swift_throw", "Swift Throw", lldb::eLanguageTypeSwift}}),
      focus_tid(LLDB_INVALID_THREAD_ID), sent_terminated_event(false),
      stop_at_entry(false) {
  const char *log_file_path = getenv("LLDBVSCODE_LOG");
#if defined(_WIN32)
// Windows opens stdout and stdin in text mode which converts \n to 13,10
// while the value is just 10 on Darwin/Linux. Setting the file mode to binary
// fixes this.
  assert(_setmode(fileno(stdout), _O_BINARY));
  assert(_setmode(fileno(stdin), _O_BINARY));
#endif
  if (log_file_path)
    log.reset(new std::ofstream(log_file_path));
}

VSCode::~VSCode() {
}

int64_t VSCode::GetLineForPC(int64_t sourceReference, lldb::addr_t pc) const {
  auto pos = source_map.find(sourceReference);
  if (pos != source_map.end())
    return pos->second.GetLineForPC(pc);
  return 0;
}

ExceptionBreakpoint *VSCode::GetExceptionBreakpoint(const std::string &filter) {
  for (auto &bp : exception_breakpoints) {
    if (bp.filter == filter)
      return &bp;
  }
  return nullptr;
}

ExceptionBreakpoint *
VSCode::GetExceptionBreakpoint(const lldb::break_id_t bp_id) {
  for (auto &bp : exception_breakpoints) {
    if (bp.bp.GetID() == bp_id)
      return &bp;
  }
  return nullptr;
}

// Send the JSON in "json_str" to the "out" stream. Correctly send the
// "Content-Length:" field followed by the length, followed by the raw
// JSON bytes.
void VSCode::SendJSON(const std::string &json_str) {
  output.write_full("Content-Length: ");
  output.write_full(llvm::utostr(json_str.size()));
  output.write_full("\r\n\r\n");
  output.write_full(json_str);

  if (log) {
    *log << "<-- " << std::endl
         << "Content-Length: " << json_str.size() << "\r\n\r\n"
         << json_str << std::endl;
  }
}

// Serialize the JSON value into a string and send the JSON packet to
// the "out" stream.
void VSCode::SendJSON(const llvm::json::Value &json) {
  std::string s;
  llvm::raw_string_ostream strm(s);
  strm << json;
  static std::mutex mutex;
  std::lock_guard<std::mutex> locker(mutex);
  SendJSON(strm.str());
}

// Read a JSON packet from the "in" stream.
std::string VSCode::ReadJSON() {
  std::string length_str;
  std::string json_str;
  int length;

  if (!input.read_expected(log.get(), "Content-Length: "))
    return json_str;

  if (!input.read_line(log.get(), length_str))
    return json_str;

  if (!llvm::to_integer(length_str, length))
    return json_str;

  if (!input.read_expected(log.get(), "\r\n"))
    return json_str;

  if (!input.read_full(log.get(), length, json_str))
    return json_str;

  return json_str;
}

// "OutputEvent": {
//   "allOf": [ { "$ref": "#/definitions/Event" }, {
//     "type": "object",
//     "description": "Event message for 'output' event type. The event
//                     indicates that the target has produced some output.",
//     "properties": {
//       "event": {
//         "type": "string",
//         "enum": [ "output" ]
//       },
//       "body": {
//         "type": "object",
//         "properties": {
//           "category": {
//             "type": "string",
//             "description": "The output category. If not specified,
//                             'console' is assumed.",
//             "_enum": [ "console", "stdout", "stderr", "telemetry" ]
//           },
//           "output": {
//             "type": "string",
//             "description": "The output to report."
//           },
//           "variablesReference": {
//             "type": "number",
//             "description": "If an attribute 'variablesReference' exists
//                             and its value is > 0, the output contains
//                             objects which can be retrieved by passing
//                             variablesReference to the VariablesRequest."
//           },
//           "source": {
//             "$ref": "#/definitions/Source",
//             "description": "An optional source location where the output
//                             was produced."
//           },
//           "line": {
//             "type": "integer",
//             "description": "An optional source location line where the
//                             output was produced."
//           },
//           "column": {
//             "type": "integer",
//             "description": "An optional source location column where the
//                             output was produced."
//           },
//           "data": {
//             "type":["array","boolean","integer","null","number","object",
//                     "string"],
//             "description": "Optional data to report. For the 'telemetry'
//                             category the data will be sent to telemetry, for
//                             the other categories the data is shown in JSON
//                             format."
//           }
//         },
//         "required": ["output"]
//       }
//     },
//     "required": [ "event", "body" ]
//   }]
// }
void VSCode::SendOutput(OutputType o, const llvm::StringRef output) {
  if (output.empty())
    return;

  llvm::json::Object event(CreateEventObject("output"));
  llvm::json::Object body;
  const char *category = nullptr;
  switch (o) {
  case OutputType::Console:
    category = "console";
    break;
  case OutputType::Stdout:
    category = "stdout";
    break;
  case OutputType::Stderr:
    category = "stderr";
    break;
  case OutputType::Telemetry:
    category = "telemetry";
    break;
  }
  body.try_emplace("category", category);
  EmplaceSafeString(body, "output", output.str());
  event.try_emplace("body", std::move(body));
  SendJSON(llvm::json::Value(std::move(event)));
}

void __attribute__((format(printf, 3, 4)))
VSCode::SendFormattedOutput(OutputType o, const char *format, ...) {
  char buffer[1024];
  va_list args;
  va_start(args, format);
  int actual_length = vsnprintf(buffer, sizeof(buffer), format, args);
  va_end(args);
  SendOutput(o, llvm::StringRef(buffer,
                                std::min<int>(actual_length, sizeof(buffer))));
}

int64_t VSCode::GetNextSourceReference() {
  static int64_t ref = 0;
  return ++ref;
}

ExceptionBreakpoint *
VSCode::GetExceptionBPFromStopReason(lldb::SBThread &thread) {
  const auto num = thread.GetStopReasonDataCount();
  // Check to see if have hit an exception breakpoint and change the
  // reason to "exception", but only do so if all breakpoints that were
  // hit are exception breakpoints.
  ExceptionBreakpoint *exc_bp = nullptr;
  for (size_t i = 0; i < num; i += 2) {
    // thread.GetStopReasonDataAtIndex(i) will return the bp ID and
    // thread.GetStopReasonDataAtIndex(i+1) will return the location
    // within that breakpoint. We only care about the bp ID so we can
    // see if this is an exception breakpoint that is getting hit.
    lldb::break_id_t bp_id = thread.GetStopReasonDataAtIndex(i);
    exc_bp = GetExceptionBreakpoint(bp_id);
    // If any breakpoint is not an exception breakpoint, then stop and
    // report this as a normal breakpoint
    if (exc_bp == nullptr)
      return nullptr;
  }
  return exc_bp;
}

lldb::SBThread VSCode::GetLLDBThread(const llvm::json::Object &arguments) {
  auto tid = GetSigned(arguments, "threadId", LLDB_INVALID_THREAD_ID);
  return target.GetProcess().GetThreadByID(tid);
}

lldb::SBFrame VSCode::GetLLDBFrame(const llvm::json::Object &arguments) {
  const uint64_t frame_id = GetUnsigned(arguments, "frameId", UINT64_MAX);
  lldb::SBProcess process = target.GetProcess();
  // Upper 32 bits is the thread index ID
  lldb::SBThread thread =
      process.GetThreadByIndexID(GetLLDBThreadIndexID(frame_id));
  // Lower 32 bits is the frame index
  return thread.GetFrameAtIndex(GetLLDBFrameID(frame_id));
}

llvm::json::Value VSCode::CreateTopLevelScopes() {
  llvm::json::Array scopes;
  scopes.emplace_back(CreateScope("Locals", VARREF_LOCALS, num_locals, false));
  scopes.emplace_back(
      CreateScope("Globals", VARREF_GLOBALS, num_globals, false));
  scopes.emplace_back(CreateScope("Registers", VARREF_REGS, num_regs, false));
  return llvm::json::Value(std::move(scopes));
}

void VSCode::RunLLDBCommands(llvm::StringRef prefix,
                             const std::vector<std::string> &commands) {
  SendOutput(OutputType::Console,
             llvm::StringRef(::RunLLDBCommands(prefix, commands)));
}

void VSCode::RunInitCommands() {
  RunLLDBCommands("Running initCommands:", init_commands);
}

void VSCode::RunPreRunCommands() {
  RunLLDBCommands("Running preRunCommands:", pre_run_commands);
}

void VSCode::RunStopCommands() {
  RunLLDBCommands("Running stopCommands:", stop_commands);
}

void VSCode::RunExitCommands() {
  RunLLDBCommands("Running exitCommands:", exit_commands);
}

} // namespace lldb_vscode

<|endoftext|>