<commit_before>/**
 * This file is part of the CernVM File System.
 */

#include "cvmfs_config.h"
#include "fetch.h"

#include <unistd.h>

#include "backoff.h"
#include "cache.h"
#include "clientctx.h"
#include "download.h"
#include "logging.h"
#include "quota.h"
#include "statistics.h"
#include "util/posix.h"

using namespace std;  // NOLINT

namespace cvmfs {

void TLSDestructor(void *data) {
  Fetcher::ThreadLocalStorage *tls =
    static_cast<Fetcher::ThreadLocalStorage *>(data);
  std::vector<Fetcher::ThreadLocalStorage *> *tls_blocks =
    &tls->fetcher->tls_blocks_;

  pthread_mutex_lock(tls->fetcher->lock_tls_blocks_);
  for (vector<Fetcher::ThreadLocalStorage *>::iterator i =
       tls_blocks->begin(), iEnd = tls_blocks->end(); i != iEnd; ++i)
  {
    if ((*i) == tls) {
      tls_blocks->erase(i);
      break;
    }
  }
  pthread_mutex_unlock(tls->fetcher->lock_tls_blocks_);
  tls->fetcher->CleanupTls(tls);
}

/**
 * Called when a thread exists, releases a ThreadLocalStorage object and
 * removes the pointer to it from tls_blocks_.
 */
void Fetcher::CleanupTls(ThreadLocalStorage *tls) {
  ClosePipe(tls->pipe_wait);
  delete tls;
}

/**
 * Initialized thread-local storage if called the first time in a new thread.
 */
Fetcher::ThreadLocalStorage *Fetcher::GetTls() {
  ThreadLocalStorage *tls = static_cast<ThreadLocalStorage *>(
    pthread_getspecific(thread_local_storage_));
  if (tls != NULL)
    return tls;

  tls = new ThreadLocalStorage();
  tls->fetcher = this;
  MakePipe(tls->pipe_wait);
  tls->download_job.destination = download::kDestinationSink;
  tls->download_job.compressed = true;
  tls->download_job.probe_hosts = true;
  int retval = pthread_setspecific(thread_local_storage_, tls);
  assert(retval == 0);
  pthread_mutex_lock(lock_tls_blocks_);
  tls_blocks_.push_back(tls);
  pthread_mutex_unlock(lock_tls_blocks_);
  return tls;
}

int Fetcher::Fetch(
  const shash::Any &id,
  const uint64_t size,
  const std::string &name,
  const zlib::Algorithms compression_algorithm,
  const CacheManager::ObjectType object_type,
  const std::string &alt_url,
  off_t range_offset)
{
  int fd_return;  // Read-only file descriptor that is returned
  int retval;

  // Try to open from local cache
  if ((fd_return = OpenSelect(id, name, object_type)) >= 0) {
    LogCvmfs(kLogCache, kLogDebug, "hit: %s", name.c_str());
    return fd_return;
  }

  ThreadLocalStorage *tls = GetTls();

  // Synchronization point: either act as a master thread for this object or
  // enqueue to the list of waiting threads.
  pthread_mutex_lock(lock_queues_download_);
  ThreadQueues::iterator iDownloadQueue = queues_download_.find(id);
  if (iDownloadQueue != queues_download_.end()) {
    LogCvmfs(kLogCache, kLogDebug, "waiting for download of %s", name.c_str());

    iDownloadQueue->second->push_back(tls->pipe_wait[1]);
    pthread_mutex_unlock(lock_queues_download_);
    ReadPipe(tls->pipe_wait[0], &fd_return, sizeof(int));

    LogCvmfs(kLogCache, kLogDebug, "received from another thread fd %d for %s",
             fd_return, name.c_str());
    return fd_return;
  } else {
    // Seems we are the first one, check again in the cache (race condition)
    fd_return = OpenSelect(id, name, object_type);
    if (fd_return >= 0) {
      pthread_mutex_unlock(lock_queues_download_);
      return fd_return;
    }

    // Create a new queue for this chunk
    queues_download_[id] = &tls->other_pipes_waiting;
    pthread_mutex_unlock(lock_queues_download_);
  }

  perf::Inc(n_downloads);

  // Involve the download manager
  LogCvmfs(kLogCache, kLogDebug, "downloading %s", name.c_str());
  std::string url;
  if (external_) {
    url = !alt_url.empty() ? alt_url : name;
  } else {
    url = "/" + (alt_url.size() ? alt_url : "data/" + id.MakePath());
  }
  void *txn = alloca(cache_mgr_->SizeOfTxn());
  retval = cache_mgr_->StartTxn(id, size, txn);
  if (retval < 0) {
    LogCvmfs(kLogCache, kLogDebug, "could not start transaction on %s",
             name.c_str());
    SignalWaitingThreads(retval, id, tls);
    return retval;
  }
  cache_mgr_->CtrlTxn(CacheManager::ObjectInfo(object_type, name), 0, txn);

  LogCvmfs(kLogCache, kLogDebug, "miss: %s %s", name.c_str(), url.c_str());
  TransactionSink sink(cache_mgr_, txn);
  tls->download_job.url = &url;
  tls->download_job.destination_sink = &sink;
  tls->download_job.expected_hash = &id;
  tls->download_job.extra_info = &name;
  ClientCtx *ctx = ClientCtx::GetInstance();
  if (ctx->IsSet()) {
    ctx->Get(&tls->download_job.uid,
             &tls->download_job.gid,
             &tls->download_job.pid);
  }
  tls->download_job.compressed = (compression_algorithm == zlib::kZlibDefault);
  tls->download_job.range_offset = range_offset;
  tls->download_job.range_size = size;
  download_mgr_->Fetch(&tls->download_job);

  if (tls->download_job.error_code == download::kFailOk) {
    LogCvmfs(kLogCache, kLogDebug, "finished downloading of %s", url.c_str());

    fd_return = cache_mgr_->OpenFromTxn(txn);
    if (fd_return < 0) {
      cache_mgr_->AbortTxn(txn);
      SignalWaitingThreads(fd_return, id, tls);
      return fd_return;
    }

    retval = cache_mgr_->CommitTxn(txn);
    if (retval < 0) {
      cache_mgr_->Close(fd_return);
      SignalWaitingThreads(retval, id, tls);
      return retval;
    }
    SignalWaitingThreads(fd_return, id, tls);
    return fd_return;
  }

  // Download failed
  LogCvmfs(kLogCache, kLogDebug | kLogSyslogErr,
           "failed to fetch %s (hash: %s, error %d [%s])", name.c_str(),
           id.ToString().c_str(), tls->download_job.error_code,
           download::Code2Ascii(tls->download_job.error_code));
  cache_mgr_->AbortTxn(txn);
  backoff_throttle_->Throttle();
  SignalWaitingThreads(-EIO, id, tls);
  return -EIO;
}

Fetcher::Fetcher(
  CacheManager *cache_mgr,
  download::DownloadManager *download_mgr,
  BackoffThrottle *backoff_throttle,
  perf::StatisticsTemplate statistics,
  bool external)
  : external_(external)
  , lock_queues_download_(NULL)
  , lock_tls_blocks_(NULL)
  , cache_mgr_(cache_mgr)
  , download_mgr_(download_mgr)
  , backoff_throttle_(backoff_throttle)
{
  int retval;
  retval = pthread_key_create(&thread_local_storage_, TLSDestructor);
  assert(retval == 0);
  lock_queues_download_ = reinterpret_cast<pthread_mutex_t *>(
    smalloc(sizeof(pthread_mutex_t)));
  retval = pthread_mutex_init(lock_queues_download_, NULL);
  assert(retval == 0);
  lock_tls_blocks_ = reinterpret_cast<pthread_mutex_t *>(
    smalloc(sizeof(pthread_mutex_t)));
  retval = pthread_mutex_init(lock_tls_blocks_, NULL);
  assert(retval == 0);
  n_downloads = statistics.RegisterTemplated("n_downloads",
    "overall number of downloaded files (incl. catalogs, chunks)");
}

Fetcher::~Fetcher() {
  int retval;

  pthread_mutex_lock(lock_tls_blocks_);
  for (unsigned i = 0; i < tls_blocks_.size(); ++i)
    CleanupTls(tls_blocks_[i]);
  pthread_mutex_unlock(lock_tls_blocks_);

  retval = pthread_mutex_destroy(lock_tls_blocks_);
  assert(retval == 0);
  free(lock_tls_blocks_);

  retval = pthread_mutex_destroy(lock_queues_download_);
  assert(retval == 0);
  free(lock_queues_download_);

  retval = pthread_key_delete(thread_local_storage_);
  assert(retval == 0);
}

/**
 * Depending on the object type, uses either Open() or OpenPinned() from the
 * cache manager
 */
int Fetcher::OpenSelect(
  const shash::Any &id,
  const std::string &name,
  const CacheManager::ObjectType object_type)
{
  bool is_catalog = object_type == CacheManager::kTypeCatalog;
  if (is_catalog || (object_type == CacheManager::kTypePinned)) {
    return cache_mgr_->OpenPinned(id, name, is_catalog);
  } else {
    return cache_mgr_->Open(CacheManager::Bless(id, object_type, name));
  }
}

void Fetcher::SignalWaitingThreads(
  const int fd,
  const shash::Any &id,
  ThreadLocalStorage *tls)
{
  pthread_mutex_lock(lock_queues_download_);
  for (unsigned i = 0, s = tls->other_pipes_waiting.size(); i < s; ++i) {
    int fd_dup = (fd >= 0) ? cache_mgr_->Dup(fd) : fd;
    WritePipe(tls->other_pipes_waiting[i], &fd_dup, sizeof(int));
  }
  tls->other_pipes_waiting.clear();
  queues_download_.erase(id);
  pthread_mutex_unlock(lock_queues_download_);
}

}  // namespace cvmfs
<commit_msg>remove raw mutex from fetch.cc<commit_after>/**
 * This file is part of the CernVM File System.
 */

#include "cvmfs_config.h"
#include "fetch.h"

#include <unistd.h>

#include "backoff.h"
#include "cache.h"
#include "clientctx.h"
#include "download.h"
#include "logging.h"
#include "quota.h"
#include "statistics.h"
#include "util/posix.h"
#include "util_concurrency.h"

using namespace std;  // NOLINT

namespace cvmfs {

void TLSDestructor(void *data) {
  Fetcher::ThreadLocalStorage *tls =
    static_cast<Fetcher::ThreadLocalStorage *>(data);
  std::vector<Fetcher::ThreadLocalStorage *> *tls_blocks =
    &tls->fetcher->tls_blocks_;

  {
    MutexLockGuard m(tls->fetcher->lock_tls_blocks_);
    for (vector<Fetcher::ThreadLocalStorage *>::iterator
             i = tls_blocks->begin(),
             iEnd = tls_blocks->end();
         i != iEnd; ++i) {
      if ((*i) == tls) {
        tls_blocks->erase(i);
        break;
      }
    }
  }
  tls->fetcher->CleanupTls(tls);
}

/**
 * Called when a thread exists, releases a ThreadLocalStorage object and
 * removes the pointer to it from tls_blocks_.
 */
void Fetcher::CleanupTls(ThreadLocalStorage *tls) {
  ClosePipe(tls->pipe_wait);
  delete tls;
}

/**
 * Initialized thread-local storage if called the first time in a new thread.
 */
Fetcher::ThreadLocalStorage *Fetcher::GetTls() {
  ThreadLocalStorage *tls = static_cast<ThreadLocalStorage *>(
    pthread_getspecific(thread_local_storage_));
  if (tls != NULL)
    return tls;

  tls = new ThreadLocalStorage();
  tls->fetcher = this;
  MakePipe(tls->pipe_wait);
  tls->download_job.destination = download::kDestinationSink;
  tls->download_job.compressed = true;
  tls->download_job.probe_hosts = true;
  int retval = pthread_setspecific(thread_local_storage_, tls);
  assert(retval == 0);

  MutexLockGuard m(lock_tls_blocks_);
  tls_blocks_.push_back(tls);

  return tls;
}

int Fetcher::Fetch(
  const shash::Any &id,
  const uint64_t size,
  const std::string &name,
  const zlib::Algorithms compression_algorithm,
  const CacheManager::ObjectType object_type,
  const std::string &alt_url,
  off_t range_offset)
{
  int fd_return;  // Read-only file descriptor that is returned
  int retval;

  // Try to open from local cache
  if ((fd_return = OpenSelect(id, name, object_type)) >= 0) {
    LogCvmfs(kLogCache, kLogDebug, "hit: %s", name.c_str());
    return fd_return;
  }

  ThreadLocalStorage *tls = GetTls();

  {
    // Synchronization point: either act as a master thread for this object or
    // enqueue to the list of waiting threads.
    MutexLockGuard m(lock_queues_download_);
    ThreadQueues::iterator iDownloadQueue = queues_download_.find(id);
    if (iDownloadQueue != queues_download_.end()) {
      LogCvmfs(kLogCache, kLogDebug, "waiting for download of %s",
               name.c_str());

      iDownloadQueue->second->push_back(tls->pipe_wait[1]);
      ReadPipe(tls->pipe_wait[0], &fd_return, sizeof(int));

      LogCvmfs(kLogCache, kLogDebug,
               "received from another thread fd %d for %s", fd_return,
               name.c_str());
      return fd_return;
    } else {
      // Seems we are the first one, check again in the cache (race condition)
      fd_return = OpenSelect(id, name, object_type);
      if (fd_return >= 0) {
        return fd_return;
      }

      // Create a new queue for this chunk
      queues_download_[id] = &tls->other_pipes_waiting;
    }
  }

  perf::Inc(n_downloads);

  // Involve the download manager
  LogCvmfs(kLogCache, kLogDebug, "downloading %s", name.c_str());
  std::string url;
  if (external_) {
    url = !alt_url.empty() ? alt_url : name;
  } else {
    url = "/" + (alt_url.size() ? alt_url : "data/" + id.MakePath());
  }
  void *txn = alloca(cache_mgr_->SizeOfTxn());
  retval = cache_mgr_->StartTxn(id, size, txn);
  if (retval < 0) {
    LogCvmfs(kLogCache, kLogDebug, "could not start transaction on %s",
             name.c_str());
    SignalWaitingThreads(retval, id, tls);
    return retval;
  }
  cache_mgr_->CtrlTxn(CacheManager::ObjectInfo(object_type, name), 0, txn);

  LogCvmfs(kLogCache, kLogDebug, "miss: %s %s", name.c_str(), url.c_str());
  TransactionSink sink(cache_mgr_, txn);
  tls->download_job.url = &url;
  tls->download_job.destination_sink = &sink;
  tls->download_job.expected_hash = &id;
  tls->download_job.extra_info = &name;
  ClientCtx *ctx = ClientCtx::GetInstance();
  if (ctx->IsSet()) {
    ctx->Get(&tls->download_job.uid,
             &tls->download_job.gid,
             &tls->download_job.pid);
  }
  tls->download_job.compressed = (compression_algorithm == zlib::kZlibDefault);
  tls->download_job.range_offset = range_offset;
  tls->download_job.range_size = size;
  download_mgr_->Fetch(&tls->download_job);

  if (tls->download_job.error_code == download::kFailOk) {
    LogCvmfs(kLogCache, kLogDebug, "finished downloading of %s", url.c_str());

    fd_return = cache_mgr_->OpenFromTxn(txn);
    if (fd_return < 0) {
      cache_mgr_->AbortTxn(txn);
      SignalWaitingThreads(fd_return, id, tls);
      return fd_return;
    }

    retval = cache_mgr_->CommitTxn(txn);
    if (retval < 0) {
      cache_mgr_->Close(fd_return);
      SignalWaitingThreads(retval, id, tls);
      return retval;
    }
    SignalWaitingThreads(fd_return, id, tls);
    return fd_return;
  }

  // Download failed
  LogCvmfs(kLogCache, kLogDebug | kLogSyslogErr,
           "failed to fetch %s (hash: %s, error %d [%s])", name.c_str(),
           id.ToString().c_str(), tls->download_job.error_code,
           download::Code2Ascii(tls->download_job.error_code));
  cache_mgr_->AbortTxn(txn);
  backoff_throttle_->Throttle();
  SignalWaitingThreads(-EIO, id, tls);
  return -EIO;
}

Fetcher::Fetcher(
  CacheManager *cache_mgr,
  download::DownloadManager *download_mgr,
  BackoffThrottle *backoff_throttle,
  perf::StatisticsTemplate statistics,
  bool external)
  : external_(external)
  , lock_queues_download_(NULL)
  , lock_tls_blocks_(NULL)
  , cache_mgr_(cache_mgr)
  , download_mgr_(download_mgr)
  , backoff_throttle_(backoff_throttle)
{
  int retval;
  retval = pthread_key_create(&thread_local_storage_, TLSDestructor);
  assert(retval == 0);
  lock_queues_download_ = reinterpret_cast<pthread_mutex_t *>(
    smalloc(sizeof(pthread_mutex_t)));
  retval = pthread_mutex_init(lock_queues_download_, NULL);
  assert(retval == 0);
  lock_tls_blocks_ = reinterpret_cast<pthread_mutex_t *>(
    smalloc(sizeof(pthread_mutex_t)));
  retval = pthread_mutex_init(lock_tls_blocks_, NULL);
  assert(retval == 0);
  n_downloads = statistics.RegisterTemplated("n_downloads",
    "overall number of downloaded files (incl. catalogs, chunks)");
}

Fetcher::~Fetcher() {
  int retval;

  {
    MutexLockGuard m(lock_tls_blocks_);
    for (unsigned i = 0; i < tls_blocks_.size(); ++i)
      CleanupTls(tls_blocks_[i]);
  }

  retval = pthread_mutex_destroy(lock_tls_blocks_);
  assert(retval == 0);
  free(lock_tls_blocks_);

  retval = pthread_mutex_destroy(lock_queues_download_);
  assert(retval == 0);
  free(lock_queues_download_);

  retval = pthread_key_delete(thread_local_storage_);
  assert(retval == 0);
}

/**
 * Depending on the object type, uses either Open() or OpenPinned() from the
 * cache manager
 */
int Fetcher::OpenSelect(
  const shash::Any &id,
  const std::string &name,
  const CacheManager::ObjectType object_type)
{
  bool is_catalog = object_type == CacheManager::kTypeCatalog;
  if (is_catalog || (object_type == CacheManager::kTypePinned)) {
    return cache_mgr_->OpenPinned(id, name, is_catalog);
  } else {
    return cache_mgr_->Open(CacheManager::Bless(id, object_type, name));
  }
}

void Fetcher::SignalWaitingThreads(
  const int fd,
  const shash::Any &id,
  ThreadLocalStorage *tls)
{
  MutexLockGuard m(lock_queues_download_);
  for (unsigned i = 0, s = tls->other_pipes_waiting.size(); i < s; ++i) {
    int fd_dup = (fd >= 0) ? cache_mgr_->Dup(fd) : fd;
    WritePipe(tls->other_pipes_waiting[i], &fd_dup, sizeof(int));
  }
  tls->other_pipes_waiting.clear();
  queues_download_.erase(id);
}

}  // namespace cvmfs
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014-2016 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <iostream>
#include <chrono>
#include <random>

#include "etl/etl.hpp"

template<typename I, typename K, typename C>
void locality(const I& input, const K& kernel, C& conv){
    conv = 0;

    const auto n1 = etl::dim<0>(input);
    const auto n2 = etl::dim<1>(input);

    const auto k1 = etl::dim<0>(kernel);
    const auto k2 = etl::dim<1>(kernel);

    const auto c1 = etl::dim<0>(conv);
    const auto c2 = etl::dim<1>(conv);

    const auto R = std::min(k1, c1); // Max number of kernels per line of input

    // Primary steps
    for(size_t i = 0; i < k1 - 1; ++i){
        const auto M = std::min(i + 1, R);

        std::cout << "Primary:" << i << ":" << M << std::endl;

        for(size_t m = 0; m < M; ++m){
            for(size_t j = 0; j < c2;  ++j){
                const auto c_i = m;
                const auto c_j = j;

                for(size_t k = 0; k < k2; ++k){
                    const auto k_i = m;
                    const auto k_j = k;

                    const auto i_i = i;
                    const auto i_j = j + k;

                    std::cout << "c(" << c_i << "," << c_j << ") += i(" << i_i << "," << i_j << ") * k("  << k_i << "," << k_j << ")" << std::endl;
                    conv(c_i, c_j) += input(i_i, i_j) * kernel(k_i, k_j);
                }
            }
        }
    }

    // Main steps
    for(size_t i = k1 - 1; i < n1 - k1 + 1; ++i){
        const auto M = R;

        std::cout << "Main:" << i << ":" << M << std::endl;

        for(size_t m = 0; m < M; ++m){
            for(size_t j = 0; j < c2;  ++j){
                const auto c_i = (c1 - 1) - (m + (i - (k1 - 1)));
                const auto c_j = j;

                for(size_t k = 0; k < k2; ++k){
                    const auto k_i = m;
                    const auto k_j = k;

                    const auto i_i = i;
                    const auto i_j = j + k;

                    std::cout << "c(" << c_i << "," << c_j << ") += i(" << i_i << "," << i_j << ") * k("  << k_i << "," << k_j << ")" << std::endl;
                    conv(c_i, c_j) += input(i_i, i_j) * kernel(k_i, k_j);
                }
            }
        }
    }

    // Secondary steps
    for(size_t i = n1 - k1 + 1; i < n1; ++i){
        auto M = std::min(n1 - i, R);

        std::cout << "Secondary:" << i << ":" << M << std::endl;

        for(size_t m = 0; m < M; ++m){
            for(size_t j = 0; j < c2;  ++j){
                const auto c_i = m + (i - (k1 - 1));
                const auto c_j = j;

                for(size_t k = 0; k < k2; ++k){
                    const auto k_i = M - m;
                    const auto k_j = k;

                    const auto i_i = i;
                    const auto i_j = j + k;

                    std::cout << "c(" << c_i << "," << c_j << ") += i(" << i_i << "," << i_j << ") * k("  << k_i << "," << k_j << ")" << std::endl;
                    conv(c_i, c_j) += input(i_i, i_j) * kernel(k_i, k_j);
                }
            }
        }
    }

    cpp_unused(n2);
    cpp_unused(k2);
    cpp_unused(c2);
}

int main(){
    const size_t i1 = 3;
    const size_t i2 = 3;

    const size_t k1 = 2;
    const size_t k2 = 2;

    const size_t c1 = i1 - k1 + 1;
    const size_t c2 = i2 - k2 + 1;

    std::cout << "Input: [" << i1 << "x" << i2 << "]" << std::endl;
    std::cout << "Kernel: [" << k1 << "x" << k2 << "]" << std::endl;

    using Z = float;

    etl::dyn_matrix<Z, 2> input(i1, i2);
    etl::dyn_matrix<Z, 2> kernel(k1, k2);

    input = etl::sequence_generator(1.0);
    kernel = etl::sequence_generator(1.0);

    etl::dyn_matrix<Z, 2> CA(c1, c2);
    etl::dyn_matrix<Z, 2> CB(c1, c2);

    CA = etl::conv_2d_valid_flipped(input, kernel);
    locality(input, kernel, CB);

    std::cout << etl::to_string(CA) << std::endl;
    std::cout << etl::to_string(CB) << std::endl;

    std::cout << etl::sum(CA - CB) << std::endl;

    return 0;
}
<commit_msg>Improvements<commit_after>//=======================================================================
// Copyright (c) 2014-2016 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <iostream>
#include <chrono>
#include <random>

#include "etl/etl.hpp"

template<typename I, typename K, typename C>
void locality(const I& input, const K& kernel, C& conv){
    conv = 0;

    const auto n1 = etl::dim<0>(input);
    const auto n2 = etl::dim<1>(input);

    const auto k1 = etl::dim<0>(kernel);
    const auto k2 = etl::dim<1>(kernel);

    const auto c1 = etl::dim<0>(conv);
    const auto c2 = etl::dim<1>(conv);

    const auto R = std::min(k1, c1); // Max number of kernels per line of input

    // Primary steps
    for(size_t i = 0; i < k1 - 1; ++i){
        const auto M = std::min(i + 1, R);

        std::cout << "Primary:" << i << ":" << M << std::endl;

        for(size_t m = 0; m < M; ++m){
            for(size_t j = 0; j < c2;  ++j){
                const auto c_i = m;
                const auto c_j = j;

                for(size_t k = 0; k < k2; ++k){
                    const auto k_i = i - m;
                    const auto k_j = k;

                    const auto i_i = i;
                    const auto i_j = j + k;

                    std::cout << "c(" << c_i << "," << c_j << ") += i(" << i_i << "," << i_j << ") * k("  << k_i << "," << k_j << ")" << std::endl;
                    conv(c_i, c_j) += input(i_i, i_j) * kernel(k_i, k_j);
                }
            }
        }
    }

    // Main steps
    for(size_t i = k1 - 1; i < c1; ++i){
        const auto M = R;

        std::cout << "Main:" << i << ":" << M << std::endl;

        for(size_t m = 0; m < M; ++m){
            for(size_t j = 0; j < c2;  ++j){
                const auto c_i = (c1 - 1) - (m + (i - (k1 - 1)));
                const auto c_j = j;

                for(size_t k = 0; k < k2; ++k){
                    const auto k_i = m;
                    const auto k_j = k;

                    const auto i_i = i;
                    const auto i_j = j + k;

                    std::cout << "c(" << c_i << "," << c_j << ") += i(" << i_i << "," << i_j << ") * k("  << k_i << "," << k_j << ")" << std::endl;
                    conv(c_i, c_j) += input(i_i, i_j) * kernel(k_i, k_j);
                }
            }
        }
    }

    // Secondary steps
    for(size_t i = c1; i < n1; ++i){
        auto M = std::min(n1 - i, R);

        std::cout << "Secondary:" << i << ":" << M << std::endl;

        for(size_t m = 0; m < M; ++m){
            for(size_t j = 0; j < c2;  ++j){
                const auto c_i = m + (i - (k1 - 1));
                const auto c_j = j;

                for(size_t k = 0; k < k2; ++k){
                    const auto k_i = M - m - (c1 - i);
                    const auto k_j = k;

                    const auto i_i = i;
                    const auto i_j = j + k;

                    std::cout << "c(" << c_i << "," << c_j << ") += i(" << i_i << "," << i_j << ") * k("  << k_i << "," << k_j << ")" << std::endl;
                    conv(c_i, c_j) += input(i_i, i_j) * kernel(k_i, k_j);
                }
            }
        }
    }

    cpp_unused(n2);
    cpp_unused(k2);
    cpp_unused(c2);
}

int main(){
    const size_t i1 = 28;
    const size_t i2 = 28;

    const size_t k1 = 5;
    const size_t k2 = 5;

    const size_t c1 = i1 - k1 + 1;
    const size_t c2 = i2 - k2 + 1;

    std::cout << "Input: [" << i1 << "x" << i2 << "]" << std::endl;
    std::cout << "Kernel: [" << k1 << "x" << k2 << "]" << std::endl;

    using Z = float;

    etl::dyn_matrix<Z, 2> input(i1, i2);
    etl::dyn_matrix<Z, 2> kernel(k1, k2);

    input = etl::sequence_generator(1.0);
    kernel = etl::sequence_generator(1.0);

    etl::dyn_matrix<Z, 2> CA(c1, c2);
    etl::dyn_matrix<Z, 2> CB(c1, c2);

    CA = etl::conv_2d_valid_flipped(input, kernel);
    locality(input, kernel, CB);

    if(i1 * i2 < 100){
        std::cout << etl::to_string(CA) << std::endl;
        std::cout << etl::to_string(CB) << std::endl;
    }

    std::cout << etl::sum(CA - CB) << std::endl;

    return 0;
}
<|endoftext|>


<commit_before>/*
* Copyright (C) 2008-2011 J-P Nurmi <jpnurmi@gmail.com>
*
* 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 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.
*/

#include <QtDeclarative>
#include <IrcSession>
#include <IrcCommand>
#include <IrcMessage>
#include <IrcPrefix>
#include <Irc>

class DeclarativeIrcPrefix : public QObject
{
    Q_OBJECT

public:
    explicit DeclarativeIrcPrefix(QObject* parent = 0) : QObject(parent) { }

    Q_INVOKABLE static QString nick(const QString& prefix)
    {
        return IrcPrefix(prefix).nick();
    }

    Q_INVOKABLE static QString user(const QString& prefix)
    {
        return IrcPrefix(prefix).user();
    }

    Q_INVOKABLE static QString host(const QString& prefix)
    {
        return IrcPrefix(prefix).host();
    }
};

class DeclarativeIrcSession : public IrcSession
{
    Q_OBJECT
    Q_PROPERTY(int port READ port WRITE setPort)

public:
    explicit DeclarativeIrcSession(QObject* parent = 0) : IrcSession(parent) { }

    // Invalid property assignment: unsupported type "ushort"
    int port() const { return IrcSession::port(); }
    void setPort(int port) { IrcSession::setPort(port); }

    Q_INVOKABLE static IrcCommand* createPasswordCommand(const QString& password) { return IrcCommand::createPassword(password); }
    Q_INVOKABLE static IrcCommand* createNickCommand(const QString& nick) { return IrcCommand::createNick(nick); }
    Q_INVOKABLE static IrcCommand* createUserCommand(const QString& userName, const QString& realName) { return IrcCommand::createUser(userName, realName); }
    Q_INVOKABLE static IrcCommand* createOperatorCommand(const QString& user, const QString& password) { return IrcCommand::createOperator(user, password); }
    Q_INVOKABLE static IrcCommand* createQuitCommand(const QString& reason) { return IrcCommand::createQuit(reason); }
    Q_INVOKABLE static IrcCommand* createJoinCommand(const QString& channel, const QString& key) { return IrcCommand::createJoin(channel, key); }
    Q_INVOKABLE static IrcCommand* createPartCommand(const QString& channel, const QString& reason) { return IrcCommand::createPart(channel, reason); }
    Q_INVOKABLE static IrcCommand* createTopicCommand(const QString& channel, const QString& topic) { return IrcCommand::createTopic(channel, topic); }
    Q_INVOKABLE static IrcCommand* createNamesCommand(const QString& channel) { return IrcCommand::createNames(channel); }
    Q_INVOKABLE static IrcCommand* createListCommand(const QString& channel, const QString& server) { return IrcCommand::createList(channel, server); }
    Q_INVOKABLE static IrcCommand* createInviteCommand(const QString& user, const QString& channel) { return IrcCommand::createInvite(user, channel); }
    Q_INVOKABLE static IrcCommand* createKickCommand(const QString& user, const QString& channel, const QString& reason) { return IrcCommand::createKick(user, channel, reason); }
    Q_INVOKABLE static IrcCommand* createModeCommand(const QString& target, const QString& mode, const QString& arg, const QString& mask) { return IrcCommand::createMode(target, mode, arg, mask); }
    Q_INVOKABLE static IrcCommand* createMessageCommand(const QString& target, const QString& message) { return IrcCommand::createMessage(target, message); }
    Q_INVOKABLE static IrcCommand* createNoticeCommand(const QString& target, const QString& message) { return IrcCommand::createNotice(target, message); }
    Q_INVOKABLE static IrcCommand* createCtcpActionCommand(const QString& target, const QString& action) { return IrcCommand::createCtcpAction(target, action); }
    Q_INVOKABLE static IrcCommand* createCtcpRequestCommand(const QString& target, const QString& request) { return IrcCommand::createCtcpRequest(target, request); }
    Q_INVOKABLE static IrcCommand* createCtcpReplyCommand(const QString& target, const QString& reply) { return IrcCommand::createCtcpReply(target, reply); }
    Q_INVOKABLE static IrcCommand* createWhoCommand(const QString& user) { return IrcCommand::createWho(user); }
    Q_INVOKABLE static IrcCommand* createWhoisCommand(const QString& user) { return IrcCommand::createWhois(user); }
    Q_INVOKABLE static IrcCommand* createWhowasCommand(const QString& user) { return IrcCommand::createWhowas(user); }
    Q_INVOKABLE static IrcCommand* createPingCommand(const QString& target) { return IrcCommand::createPing(target); }
    Q_INVOKABLE static IrcCommand* createPongCommand(const QString& target) { return IrcCommand::createPong(target); }
    Q_INVOKABLE static IrcCommand* createAwayCommand(const QString& reason) { return IrcCommand::createAway(reason); }
};

QML_DECLARE_TYPE(Irc)
QML_DECLARE_TYPE(IrcCommand)
QML_DECLARE_TYPE(IrcMessage)
QML_DECLARE_TYPE(DeclarativeIrcPrefix)
QML_DECLARE_TYPE(DeclarativeIrcSession)

class CommuniPlugin : public QDeclarativeExtensionPlugin
{
    Q_OBJECT

public:
    virtual void initializeEngine(QDeclarativeEngine* engine, const char* uri)
    {
        QDeclarativeExtensionPlugin::initializeEngine(engine, uri);
    }

    void registerTypes(const char *uri)
    {
        qmlRegisterType<DeclarativeIrcSession>(uri, 1, 0, "IrcSession");

        qmlRegisterUncreatableType<Irc>(uri, 1, 0, "Irc", "");
        qmlRegisterUncreatableType<IrcMessage>(uri, 1, 0, "IrcMessage", "");
        qmlRegisterUncreatableType<IrcCommand>(uri, 1, 0, "IrcCommand", "");
        qmlRegisterUncreatableType<DeclarativeIrcPrefix>(uri, 1, 0, "IrcPrefix", "");
    }
};

#include "plugin.moc"

Q_EXPORT_PLUGIN2(communiplugin, CommuniPlugin);
<commit_msg>Removed DeclarativeIrcSession<commit_after>/*
* Copyright (C) 2008-2011 J-P Nurmi <jpnurmi@gmail.com>
*
* 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 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.
*/

#include <QtDeclarative>
#include <IrcSession>
#include <IrcCommand>
#include <IrcMessage>
#include <IrcPrefix>
#include <Irc>

class DeclarativeIrcPrefix : public QObject
{
    Q_OBJECT

public:
    explicit DeclarativeIrcPrefix(QObject* parent = 0) : QObject(parent) { }

    Q_INVOKABLE static QString nick(const QString& prefix)
    {
        return IrcPrefix(prefix).nick();
    }

    Q_INVOKABLE static QString user(const QString& prefix)
    {
        return IrcPrefix(prefix).user();
    }

    Q_INVOKABLE static QString host(const QString& prefix)
    {
        return IrcPrefix(prefix).host();
    }
};

QML_DECLARE_TYPE(Irc)
QML_DECLARE_TYPE(IrcCommand)
QML_DECLARE_TYPE(IrcMessage)
QML_DECLARE_TYPE(IrcSession)
QML_DECLARE_TYPE(DeclarativeIrcPrefix)

class CommuniPlugin : public QDeclarativeExtensionPlugin
{
    Q_OBJECT

public:
    virtual void initializeEngine(QDeclarativeEngine* engine, const char* uri)
    {
        QDeclarativeExtensionPlugin::initializeEngine(engine, uri);
    }

    void registerTypes(const char *uri)
    {
        qmlRegisterType<IrcSession>(uri, 1, 0, "IrcSession");
        qmlRegisterType<IrcCommand>(uri, 1, 0, "IrcCommand");

        qmlRegisterUncreatableType<Irc>(uri, 1, 0, "Irc", "");
        qmlRegisterUncreatableType<IrcMessage>(uri, 1, 0, "IrcMessage", "");
        qmlRegisterUncreatableType<DeclarativeIrcPrefix>(uri, 1, 0, "IrcPrefix", "");
    }
};

#include "plugin.moc"

Q_EXPORT_PLUGIN2(communiplugin, CommuniPlugin);
<|endoftext|>


<commit_before>#include "ExecutionEngine.h"

#include <array>
#include <mutex>
#include <iostream>
#include <unordered_map>
#include <cstdlib>
#include <cstring>

#include "preprocessor/llvm_includes_start.h"
#include <llvm/IR/Module.h>
#include <llvm/ADT/Triple.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/SectionMemoryManager.h>
#include <llvm/ExecutionEngine/MCJIT.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Support/Host.h>
#include <llvm/Support/CommandLine.h>
#include <llvm/Support/ManagedStatic.h>
#include "preprocessor/llvm_includes_end.h"

#include "Runtime.h"
#include "Compiler.h"
#include "Optimizer.h"
#include "Cache.h"
#include "ExecStats.h"
#include "Utils.h"
#include "BuildInfo.gen.h"

namespace dev
{
namespace eth
{
namespace jit
{

namespace
{
using EntryFuncPtr = ReturnCode(*)(Runtime*);

std::string codeHash(i256 const& _hash)
{
	static const auto size = sizeof(_hash);
	static const auto hexChars = "0123456789abcdef";
	std::string str;
	str.resize(size * 2);
	auto outIt = str.rbegin(); // reverse for BE
	auto& arr = *(std::array<byte, size>*)&_hash;
	for (auto b : arr)
	{
		*(outIt++) = hexChars[b & 0xf];
		*(outIt++) = hexChars[b >> 4];
	}
	return str;
}

void printVersion()
{
	std::cout << "Ethereum EVM JIT Compiler (http://github.com/ethereum/evmjit):\n"
			  << "  EVMJIT version " << EVMJIT_VERSION << "\n"
#ifdef NDEBUG
			  << "  Optimized build, " EVMJIT_VERSION_FULL "\n"
#else
			  << "  DEBUG build, " EVMJIT_VERSION_FULL "\n"
#endif
			  << "  Built " << __DATE__ << " (" << __TIME__ << ")\n"
			  << std::endl;
}

namespace cl = llvm::cl;
cl::opt<bool> g_optimize{"O", cl::desc{"Optimize"}};
cl::opt<CacheMode> g_cache{"cache", cl::desc{"Cache compiled EVM code on disk"},
	cl::values(
		clEnumValN(CacheMode::on,    "1", "Enabled"),
		clEnumValN(CacheMode::off,   "0", "Disabled"),
		clEnumValN(CacheMode::read,  "r", "Read only. No new objects are added to cache."),
		clEnumValN(CacheMode::write, "w", "Write only. No objects are loaded from cache."),
		clEnumValN(CacheMode::clear, "c", "Clear the cache storage. Cache is disabled."),
		clEnumValN(CacheMode::preload, "p", "Preload all cached objects."),
		clEnumValEnd)};
cl::opt<bool> g_stats{"st", cl::desc{"Statistics"}};
cl::opt<bool> g_dump{"dump", cl::desc{"Dump LLVM IR module"}};

void parseOptions()
{
	static llvm::llvm_shutdown_obj shutdownObj{};
	cl::AddExtraVersionPrinter(printVersion);
	//cl::ParseEnvironmentOptions("evmjit", "EVMJIT", "Ethereum EVM JIT Compiler");

	// FIXME: LLVM workaround:
	// Manually select instruction scheduler other than "source".
	// "source" scheduler has a bug: http://llvm.org/bugs/show_bug.cgi?id=22304
	auto envLine = std::getenv("EVMJIT");
	auto commandLine = std::string{"evmjit "} + (envLine ? envLine : "") + " -pre-RA-sched=list-burr\0";
	static const auto c_maxArgs = 20;
	char const* argv[c_maxArgs] = {nullptr, };
	auto arg = std::strtok(&*commandLine.begin(), " ");
	auto i = 0;
	for (; i < c_maxArgs && arg; ++i, arg = std::strtok(nullptr, " "))
		argv[i] = arg;
	cl::ParseCommandLineOptions(i, argv, "Ethereum EVM JIT Compiler");
}

}

ReturnCode ExecutionEngine::run(RuntimeData* _data, Env* _env)
{
	static std::once_flag flag;
	std::call_once(flag, parseOptions);

	std::unique_ptr<ExecStats> listener{new ExecStats};
	listener->stateChanged(ExecState::Started);

	bool preloadCache = g_cache == CacheMode::preload;
	if (preloadCache)
		g_cache = CacheMode::on;

	// TODO: Do not pseudo-init the cache every time
	auto objectCache = (g_cache != CacheMode::off && g_cache != CacheMode::clear) ? Cache::getObjectCache(g_cache, listener.get()) : nullptr;

	static std::unordered_map<std::string, uint64_t> funcCache;

	static std::unique_ptr<llvm::ExecutionEngine> ee;
	if (!ee)
	{
		if (g_cache == CacheMode::clear)
			Cache::clear();

		llvm::InitializeNativeTarget();
		llvm::InitializeNativeTargetAsmPrinter();

		auto module = std::unique_ptr<llvm::Module>(new llvm::Module({}, llvm::getGlobalContext()));
		llvm::EngineBuilder builder(module.get());
		builder.setEngineKind(llvm::EngineKind::JIT);
		builder.setUseMCJIT(true);
		builder.setOptLevel(g_optimize ? llvm::CodeGenOpt::Default : llvm::CodeGenOpt::None);

		auto triple = llvm::Triple(llvm::sys::getProcessTriple());
		if (triple.getOS() == llvm::Triple::OSType::Win32)
			triple.setObjectFormat(llvm::Triple::ObjectFormatType::ELF);  // MCJIT does not support COFF format
		module->setTargetTriple(triple.str());

		ee.reset(builder.create());
		if (!CHECK(ee))
			return ReturnCode::LLVMConfigError;
		module.release();  // Successfully created llvm::ExecutionEngine takes ownership of the module
		ee->setObjectCache(objectCache);

		if (preloadCache)
			Cache::preload(*ee, funcCache);
	}

	static StatsCollector statsCollector;

	auto mainFuncName = codeHash(_data->codeHash);
	m_runtime.init(_data, _env);

	EntryFuncPtr entryFuncPtr = nullptr;
	auto it = funcCache.find(mainFuncName);
	if (it != funcCache.end())
		entryFuncPtr = (EntryFuncPtr) it->second;

	if (!entryFuncPtr)
	{
		auto module = objectCache ? Cache::getObject(mainFuncName) : nullptr;
		if (!module)
		{
			listener->stateChanged(ExecState::Compilation);
			assert(_data->code || !_data->codeSize); //TODO: Is it good idea to execute empty code?
			module = Compiler{{}}.compile(_data->code, _data->code + _data->codeSize, mainFuncName);

			if (g_optimize)
			{
				listener->stateChanged(ExecState::Optimization);
				optimize(*module);
			}
		}
		if (g_dump)
			module->dump();

		ee->addModule(module.get());
		module.release();
		listener->stateChanged(ExecState::CodeGen);
		entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName);
	}
	if (!CHECK(entryFuncPtr))
		return ReturnCode::LLVMLinkError;

	if (it == funcCache.end())
		funcCache[mainFuncName] = (uint64_t) entryFuncPtr;

	listener->stateChanged(ExecState::Execution);
	auto returnCode = entryFuncPtr(&m_runtime);
	listener->stateChanged(ExecState::Return);

	if (returnCode == ReturnCode::Return)
		returnData = m_runtime.getReturnData();     // Save reference to return data

	listener->stateChanged(ExecState::Finished);

	if (g_stats)
		statsCollector.stats.push_back(std::move(listener));

	return returnCode;
}

}
}
}
<commit_msg>Change instruction scheduler<commit_after>#include "ExecutionEngine.h"

#include <array>
#include <mutex>
#include <iostream>
#include <unordered_map>
#include <cstdlib>
#include <cstring>

#include "preprocessor/llvm_includes_start.h"
#include <llvm/IR/Module.h>
#include <llvm/ADT/Triple.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/SectionMemoryManager.h>
#include <llvm/ExecutionEngine/MCJIT.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Support/Host.h>
#include <llvm/Support/CommandLine.h>
#include <llvm/Support/ManagedStatic.h>
#include "preprocessor/llvm_includes_end.h"

#include "Runtime.h"
#include "Compiler.h"
#include "Optimizer.h"
#include "Cache.h"
#include "ExecStats.h"
#include "Utils.h"
#include "BuildInfo.gen.h"

namespace dev
{
namespace eth
{
namespace jit
{

namespace
{
using EntryFuncPtr = ReturnCode(*)(Runtime*);

std::string codeHash(i256 const& _hash)
{
	static const auto size = sizeof(_hash);
	static const auto hexChars = "0123456789abcdef";
	std::string str;
	str.resize(size * 2);
	auto outIt = str.rbegin(); // reverse for BE
	auto& arr = *(std::array<byte, size>*)&_hash;
	for (auto b : arr)
	{
		*(outIt++) = hexChars[b & 0xf];
		*(outIt++) = hexChars[b >> 4];
	}
	return str;
}

void printVersion()
{
	std::cout << "Ethereum EVM JIT Compiler (http://github.com/ethereum/evmjit):\n"
			  << "  EVMJIT version " << EVMJIT_VERSION << "\n"
#ifdef NDEBUG
			  << "  Optimized build, " EVMJIT_VERSION_FULL "\n"
#else
			  << "  DEBUG build, " EVMJIT_VERSION_FULL "\n"
#endif
			  << "  Built " << __DATE__ << " (" << __TIME__ << ")\n"
			  << std::endl;
}

namespace cl = llvm::cl;
cl::opt<bool> g_optimize{"O", cl::desc{"Optimize"}};
cl::opt<CacheMode> g_cache{"cache", cl::desc{"Cache compiled EVM code on disk"},
	cl::values(
		clEnumValN(CacheMode::on,    "1", "Enabled"),
		clEnumValN(CacheMode::off,   "0", "Disabled"),
		clEnumValN(CacheMode::read,  "r", "Read only. No new objects are added to cache."),
		clEnumValN(CacheMode::write, "w", "Write only. No objects are loaded from cache."),
		clEnumValN(CacheMode::clear, "c", "Clear the cache storage. Cache is disabled."),
		clEnumValN(CacheMode::preload, "p", "Preload all cached objects."),
		clEnumValEnd)};
cl::opt<bool> g_stats{"st", cl::desc{"Statistics"}};
cl::opt<bool> g_dump{"dump", cl::desc{"Dump LLVM IR module"}};

void parseOptions()
{
	static llvm::llvm_shutdown_obj shutdownObj{};
	cl::AddExtraVersionPrinter(printVersion);
	//cl::ParseEnvironmentOptions("evmjit", "EVMJIT", "Ethereum EVM JIT Compiler");

	// FIXME: LLVM workaround:
	// Manually select instruction scheduler. Confirmed bad schedulers: source, list-burr, list-hybrid.
	// "source" scheduler has a bug: http://llvm.org/bugs/show_bug.cgi?id=22304
	auto envLine = std::getenv("EVMJIT");
	auto commandLine = std::string{"evmjit "} + (envLine ? envLine : "") + " -pre-RA-sched=list-ilp\0";
	static const auto c_maxArgs = 20;
	char const* argv[c_maxArgs] = {nullptr, };
	auto arg = std::strtok(&*commandLine.begin(), " ");
	auto i = 0;
	for (; i < c_maxArgs && arg; ++i, arg = std::strtok(nullptr, " "))
		argv[i] = arg;
	cl::ParseCommandLineOptions(i, argv, "Ethereum EVM JIT Compiler");
}

}

ReturnCode ExecutionEngine::run(RuntimeData* _data, Env* _env)
{
	static std::once_flag flag;
	std::call_once(flag, parseOptions);

	std::unique_ptr<ExecStats> listener{new ExecStats};
	listener->stateChanged(ExecState::Started);

	bool preloadCache = g_cache == CacheMode::preload;
	if (preloadCache)
		g_cache = CacheMode::on;

	// TODO: Do not pseudo-init the cache every time
	auto objectCache = (g_cache != CacheMode::off && g_cache != CacheMode::clear) ? Cache::getObjectCache(g_cache, listener.get()) : nullptr;

	static std::unordered_map<std::string, uint64_t> funcCache;

	static std::unique_ptr<llvm::ExecutionEngine> ee;
	if (!ee)
	{
		if (g_cache == CacheMode::clear)
			Cache::clear();

		llvm::InitializeNativeTarget();
		llvm::InitializeNativeTargetAsmPrinter();

		auto module = std::unique_ptr<llvm::Module>(new llvm::Module({}, llvm::getGlobalContext()));
		llvm::EngineBuilder builder(module.get());
		builder.setEngineKind(llvm::EngineKind::JIT);
		builder.setUseMCJIT(true);
		builder.setOptLevel(g_optimize ? llvm::CodeGenOpt::Default : llvm::CodeGenOpt::None);

		auto triple = llvm::Triple(llvm::sys::getProcessTriple());
		if (triple.getOS() == llvm::Triple::OSType::Win32)
			triple.setObjectFormat(llvm::Triple::ObjectFormatType::ELF);  // MCJIT does not support COFF format
		module->setTargetTriple(triple.str());

		ee.reset(builder.create());
		if (!CHECK(ee))
			return ReturnCode::LLVMConfigError;
		module.release();  // Successfully created llvm::ExecutionEngine takes ownership of the module
		ee->setObjectCache(objectCache);

		if (preloadCache)
			Cache::preload(*ee, funcCache);
	}

	static StatsCollector statsCollector;

	auto mainFuncName = codeHash(_data->codeHash);
	m_runtime.init(_data, _env);

	EntryFuncPtr entryFuncPtr = nullptr;
	auto it = funcCache.find(mainFuncName);
	if (it != funcCache.end())
		entryFuncPtr = (EntryFuncPtr) it->second;

	if (!entryFuncPtr)
	{
		auto module = objectCache ? Cache::getObject(mainFuncName) : nullptr;
		if (!module)
		{
			listener->stateChanged(ExecState::Compilation);
			assert(_data->code || !_data->codeSize); //TODO: Is it good idea to execute empty code?
			module = Compiler{{}}.compile(_data->code, _data->code + _data->codeSize, mainFuncName);

			if (g_optimize)
			{
				listener->stateChanged(ExecState::Optimization);
				optimize(*module);
			}
		}
		if (g_dump)
			module->dump();

		ee->addModule(module.get());
		module.release();
		listener->stateChanged(ExecState::CodeGen);
		entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName);
	}
	if (!CHECK(entryFuncPtr))
		return ReturnCode::LLVMLinkError;

	if (it == funcCache.end())
		funcCache[mainFuncName] = (uint64_t) entryFuncPtr;

	listener->stateChanged(ExecState::Execution);
	auto returnCode = entryFuncPtr(&m_runtime);
	listener->stateChanged(ExecState::Return);

	if (returnCode == ReturnCode::Return)
		returnData = m_runtime.getReturnData();     // Save reference to return data

	listener->stateChanged(ExecState::Finished);

	if (g_stats)
		statsCollector.stats.push_back(std::move(listener));

	return returnCode;
}

}
}
}
<|endoftext|>


<commit_before>#include "ExecutionEngine.h"

#include <chrono>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"

#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/ADT/Triple.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/SectionMemoryManager.h>
#include <llvm/ExecutionEngine/GenericValue.h>
#include <llvm/ExecutionEngine/MCJIT.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Support/Signals.h>
#include <llvm/Support/PrettyStackTrace.h>
#include <llvm/Support/Host.h>

#pragma GCC diagnostic pop

#include "Runtime.h"
#include "Memory.h"
#include "Stack.h"
#include "Type.h"
#include "Compiler.h"
#include "Cache.h"

namespace dev
{
namespace eth
{
namespace jit
{

ReturnCode ExecutionEngine::run(bytes const& _code, RuntimeData* _data, Env* _env)
{
	std::string key{reinterpret_cast<char const*>(_code.data()), _code.size()};
	if (auto cachedExec = Cache::findExec(key))
	{
		return run(*cachedExec, _data, _env);
	}

	auto module = Compiler({}).compile(_code);
	return run(std::move(module), _data, _env, _code);
}

ReturnCode ExecutionEngine::run(std::unique_ptr<llvm::Module> _module, RuntimeData* _data, Env* _env, bytes const& _code)
{
	auto module = _module.get(); // Keep ownership of the module in _module

	llvm::sys::PrintStackTraceOnErrorSignal();
	static const auto program = "EVM JIT";
	llvm::PrettyStackTraceProgram X(1, &program);

	auto&& context = llvm::getGlobalContext();

	llvm::InitializeNativeTarget();
	llvm::InitializeNativeTargetAsmPrinter();
	llvm::InitializeNativeTargetAsmParser();

	std::string errorMsg;
	llvm::EngineBuilder builder(module);
	//builder.setMArch(MArch);
	//builder.setMCPU(MCPU);
	//builder.setMAttrs(MAttrs);
	//builder.setRelocationModel(RelocModel);
	//builder.setCodeModel(CMModel);
	builder.setErrorStr(&errorMsg);
	builder.setEngineKind(llvm::EngineKind::JIT);
	builder.setUseMCJIT(true);
	builder.setMCJITMemoryManager(new llvm::SectionMemoryManager());
	builder.setOptLevel(llvm::CodeGenOpt::None);

	auto triple = llvm::Triple(llvm::sys::getProcessTriple());
	if (triple.getOS() == llvm::Triple::OSType::Win32)
		triple.setObjectFormat(llvm::Triple::ObjectFormatType::ELF);    // MCJIT does not support COFF format
	module->setTargetTriple(triple.str());

	ExecBundle exec;
	exec.engine.reset(builder.create());
	if (!exec.engine)
		return ReturnCode::LLVMConfigError;
	_module.release();  // Successfully created llvm::ExecutionEngine takes ownership of the module

	auto finalizationStartTime = std::chrono::high_resolution_clock::now();
	exec.engine->finalizeObject();
	auto finalizationEndTime = std::chrono::high_resolution_clock::now();
	clog(JIT) << " + " << std::chrono::duration_cast<std::chrono::milliseconds>(finalizationEndTime - finalizationStartTime).count();

	auto executionStartTime = std::chrono::high_resolution_clock::now();

	exec.entryFunc = module->getFunction("main");
	if (!exec.entryFunc)
		return ReturnCode::LLVMLinkError;

	std::string key{reinterpret_cast<char const*>(_code.data()), _code.size()};
	auto& cachedExec = Cache::registerExec(key, std::move(exec));
	auto returnCode = run(cachedExec, _data, _env);

	auto executionEndTime = std::chrono::high_resolution_clock::now();
	clog(JIT) << " + " << std::chrono::duration_cast<std::chrono::milliseconds>(executionEndTime - executionStartTime).count() << " ms ";
	//clog(JIT) << "Max stack size: " << Stack::maxStackSize;

	clog(JIT) << "\n";

	return returnCode;
}

ReturnCode ExecutionEngine::run(ExecBundle const& _exec, RuntimeData* _data, Env* _env)
{
	ReturnCode returnCode;
	Runtime runtime(_data, _env);

	std::vector<llvm::GenericValue> args{{}, llvm::GenericValue(&runtime)};
	llvm::GenericValue result;

	typedef ReturnCode(*EntryFuncPtr)(int, Runtime*);

	auto entryFuncVoidPtr = _exec.engine->getPointerToFunction(_exec.entryFunc);
	auto entryFuncPtr = static_cast<EntryFuncPtr>(entryFuncVoidPtr);

	auto r = setjmp(runtime.getJmpBuf());
	if (r == 0)
	{
		returnCode = entryFuncPtr(0, &runtime);
	}
	else
		returnCode = static_cast<ReturnCode>(r);

	if (returnCode == ReturnCode::Return)
	{
		returnData = runtime.getReturnData();

		auto&& log = clog(JIT);
		log << "RETURN [ ";
		for (auto it = returnData.begin(), end = returnData.end(); it != end; ++it)
			log << std::hex << std::setw(2) << std::setfill('0') << (int)*it << " ";
		log << "]";
	}
	else
		clog(JIT) << "RETURN " << (int)returnCode;

	return returnCode;
}

}
}
}
<commit_msg>Change the way entry function is called.<commit_after>#include "ExecutionEngine.h"

#include <chrono>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"

#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/ADT/Triple.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/SectionMemoryManager.h>
#include <llvm/ExecutionEngine/GenericValue.h>
#include <llvm/ExecutionEngine/MCJIT.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Support/Signals.h>
#include <llvm/Support/PrettyStackTrace.h>
#include <llvm/Support/Host.h>

#pragma GCC diagnostic pop

#include "Runtime.h"
#include "Memory.h"
#include "Stack.h"
#include "Type.h"
#include "Compiler.h"
#include "Cache.h"

namespace dev
{
namespace eth
{
namespace jit
{

ReturnCode ExecutionEngine::run(bytes const& _code, RuntimeData* _data, Env* _env)
{
	std::string key{reinterpret_cast<char const*>(_code.data()), _code.size()};
	if (auto cachedExec = Cache::findExec(key))
	{
		return run(*cachedExec, _data, _env);
	}

	auto module = Compiler({}).compile(_code);
	return run(std::move(module), _data, _env, _code);
}

ReturnCode ExecutionEngine::run(std::unique_ptr<llvm::Module> _module, RuntimeData* _data, Env* _env, bytes const& _code)
{
	auto module = _module.get(); // Keep ownership of the module in _module

	llvm::sys::PrintStackTraceOnErrorSignal();
	static const auto program = "EVM JIT";
	llvm::PrettyStackTraceProgram X(1, &program);

	auto&& context = llvm::getGlobalContext();

	llvm::InitializeNativeTarget();
	llvm::InitializeNativeTargetAsmPrinter();
	llvm::InitializeNativeTargetAsmParser();

	std::string errorMsg;
	llvm::EngineBuilder builder(module);
	//builder.setMArch(MArch);
	//builder.setMCPU(MCPU);
	//builder.setMAttrs(MAttrs);
	//builder.setRelocationModel(RelocModel);
	//builder.setCodeModel(CMModel);
	builder.setErrorStr(&errorMsg);
	builder.setEngineKind(llvm::EngineKind::JIT);
	builder.setUseMCJIT(true);
	builder.setMCJITMemoryManager(new llvm::SectionMemoryManager());
	builder.setOptLevel(llvm::CodeGenOpt::None);

	auto triple = llvm::Triple(llvm::sys::getProcessTriple());
	if (triple.getOS() == llvm::Triple::OSType::Win32)
		triple.setObjectFormat(llvm::Triple::ObjectFormatType::ELF);    // MCJIT does not support COFF format
	module->setTargetTriple(triple.str());

	ExecBundle exec;
	exec.engine.reset(builder.create());
	if (!exec.engine)
		return ReturnCode::LLVMConfigError;
	_module.release();  // Successfully created llvm::ExecutionEngine takes ownership of the module

	auto finalizationStartTime = std::chrono::high_resolution_clock::now();
	exec.engine->finalizeObject();
	auto finalizationEndTime = std::chrono::high_resolution_clock::now();
	clog(JIT) << " + " << std::chrono::duration_cast<std::chrono::milliseconds>(finalizationEndTime - finalizationStartTime).count();

	auto executionStartTime = std::chrono::high_resolution_clock::now();

	exec.entryFunc = module->getFunction("main");
	if (!exec.entryFunc)
		return ReturnCode::LLVMLinkError;

	std::string key{reinterpret_cast<char const*>(_code.data()), _code.size()};
	auto& cachedExec = Cache::registerExec(key, std::move(exec));
	auto returnCode = run(cachedExec, _data, _env);

	auto executionEndTime = std::chrono::high_resolution_clock::now();
	clog(JIT) << " + " << std::chrono::duration_cast<std::chrono::milliseconds>(executionEndTime - executionStartTime).count() << " ms ";
	//clog(JIT) << "Max stack size: " << Stack::maxStackSize;

	clog(JIT) << "\n";

	return returnCode;
}

namespace
{
ReturnCode runEntryFunc(ExecBundle const& _exec, Runtime* _runtime)
{
	typedef ReturnCode(*EntryFuncPtr)(int, Runtime*);
	auto entryFuncVoidPtr = _exec.engine->getPointerToFunction(_exec.entryFunc);
	auto entryFuncPtr = static_cast<EntryFuncPtr>(entryFuncVoidPtr);

	ReturnCode returnCode{};
	auto sj = setjmp(_runtime->getJmpBuf());
	if (sj == 0)
		returnCode = entryFuncPtr(0, _runtime);	// FIXME: Remove int argument
	else
		returnCode = static_cast<ReturnCode>(sj);

	return returnCode;
}
}

ReturnCode ExecutionEngine::run(ExecBundle const& _exec, RuntimeData* _data, Env* _env)
{
	Runtime runtime(_data, _env);
	auto returnCode = runEntryFunc(_exec, &runtime);
	if (returnCode == ReturnCode::Return)
		this->returnData = runtime.getReturnData();
	return returnCode;
}

}
}
}
<|endoftext|>


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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

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

#include "mitkContourModelSetReader.h"
#include "mitkContourModelReader.h"
#include "mitkContourModelWriter.h"
#include "mitkContourModelSetWriter.h"

#include <usModuleActivator.h>
#include <usModuleContext.h>

namespace mitk {

/*
 * This is the module activator for the "ContourModel" module.
 */
class ContourModelActivator : public us::ModuleActivator
{
public:

  void Load(us::ModuleContext* context)
  {
    m_ContourModelReader = new ContourModelReader();
    m_ContourModelSetReader = new ContourModelSetReader();
    m_ContourModelWriter = new ContourModelWriter();
    m_ContourModelSetWriter = new ContourModelSetWriter();
  }

  void Unload(us::ModuleContext* )
  {
    delete m_ContourModelReader;
    delete m_ContourModelSetReader;
    delete m_ContourModelWriter;
    delete m_ContourModelSetWriter;
  }

private:

  mitk::ContourModelReader* m_ContourModelReader;
  mitk::ContourModelSetReader* m_ContourModelSetReader;
  mitk::ContourModelWriter* m_ContourModelWriter;
  mitk::ContourModelSetWriter* m_ContourModelSetWriter;
};
}

US_EXPORT_MODULE_ACTIVATOR(MitkContourModel, mitk::ContourModelActivator)<commit_msg>Adjusted modul export macro call<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

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

#include "mitkContourModelSetReader.h"
#include "mitkContourModelReader.h"
#include "mitkContourModelWriter.h"
#include "mitkContourModelSetWriter.h"

#include <usModuleActivator.h>
#include <usModuleContext.h>

namespace mitk {

/*
 * This is the module activator for the "ContourModel" module.
 */
class ContourModelActivator : public us::ModuleActivator
{
public:

  void Load(us::ModuleContext* context)
  {
    m_ContourModelReader = new ContourModelReader();
    m_ContourModelSetReader = new ContourModelSetReader();
    m_ContourModelWriter = new ContourModelWriter();
    m_ContourModelSetWriter = new ContourModelSetWriter();
  }

  void Unload(us::ModuleContext* )
  {
    delete m_ContourModelReader;
    delete m_ContourModelSetReader;
    delete m_ContourModelWriter;
    delete m_ContourModelSetWriter;
  }

private:

  mitk::ContourModelReader* m_ContourModelReader;
  mitk::ContourModelSetReader* m_ContourModelSetReader;
  mitk::ContourModelWriter* m_ContourModelWriter;
  mitk::ContourModelSetWriter* m_ContourModelSetWriter;
};
}

US_EXPORT_MODULE_ACTIVATOR(mitk::ContourModelActivator)<|endoftext|>


<commit_before>#include <opencv2/opencv.hpp>
#include <opencv2/features2d.hpp>
#include <wiringPi.h>

using namespace cv;

int main(int, char**)
{
    VideoCapture cap(0); // open the default camera

    wiringPiSetup () ;
    pinMode (0, OUTPUT) ;

    // Set FPS to 10
    // cap.set(CV_CAP_PROP_FPS, 10);

    // Constants
    int fWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH); //True frame width
    int fHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT); //True frame height
    int cHeight = floor(fHeight * 0.7); // Cropped height
    int cWidth = fWidth; // Width remains same
    int X = 0; // X of Top left corner of Rectangle
    int Y = fHeight - cHeight; // Y of Top left corner of Rectangle

    // Frame matrix and cropping rectangle initialization
    Mat frame;
    Rect cropper(X, Y, cWidth, cHeight);
    int _delta = 5;
    int _min_area = 800;
    int _max_area = 3000;
    std::vector<std::vector<Point> > contours;
    std::vector<Rect> bboxes;
    Ptr< MSER > mser = MSER::create(_delta, _min_area, _max_area);

    // Iterating over each frame
    for(;;)
    {
        cap >> frame; // Webcam image to an empty frame
        frame = frame(cropper); // Cropping same frame
        cvtColor(frame, frame, CV_BGR2GRAY); // Grayscale conversion of same frame
        threshold(frame, frame, 200, 255, THRESH_TOZERO); // Threshold at 200 value
        mser->detectRegions(frame, contours, bboxes);

	if(bboxes.size()){
		digitalWrite (0,  HIGH) ;
	}
	else
		digitalWrite (0,  LOW);

        if(waitKey(30) >= 0) break;
    }
    // the camera will be deinitialized automatically in VideoCapture destructor
    return 0;
}
<commit_msg>Added two LEDs<commit_after>#include <opencv2/opencv.hpp>
#include <opencv2/features2d.hpp>
#include <wiringPi.h>

using namespace cv;

int main(int, char**)
{
    VideoCapture cap(0); // open the default camera

    wiringPiSetup () ;
    pinMode (0, OUTPUT) ; //High-beam
    pinMode (1, OUTPUT) ; //Low-beam

    digitalWrite(0, HIGH) ; //Set high beam
    digitalWrite(1, LOW) ; //Unset low beam

    // Constants
    int fWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH); //True frame width
    int fHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT); //True frame height
    int cHeight = floor(fHeight * 0.7); // Cropped height
    int cWidth = fWidth; // Width remains same
    int X = 0; // X of Top left corner of Rectangle
    int Y = fHeight - cHeight; // Y of Top left corner of Rectangle

    // Frame matrix and cropping rectangle initialization
    Mat frame;
    Rect cropper(X, Y, cWidth, cHeight);
    int _delta = 5;
    int _min_area = 800;
    int _max_area = 3000;
    std::vector<std::vector<Point> > contours;
    std::vector<Rect> bboxes;
    Ptr< MSER > mser = MSER::create(_delta, _min_area, _max_area);

    // Iterating over each frame
    for(;;)
    {
        cap >> frame; // Webcam image to an empty frame
        frame = frame(cropper); // Cropping same frame
        cvtColor(frame, frame, CV_BGR2GRAY); // Grayscale conversion of same frame
        threshold(frame, frame, 200, 255, THRESH_TOZERO); // Threshold at 200 value
        mser->detectRegions(frame, contours, bboxes);

	if(bboxes.size()){
		//High Beam detected
		digitalWrite (0, LOW) ; // unset high beam
		digitalWrite (1, HIGH); // set low beam
		delay(5000);		// wait for 5 seconds
		digitalWrite (0, HIGH); // set high beam again now
		digitalWrite (1, LOW);  // unset low beam now
	}
	else{
		//No beam detected yet
		digitalWrite (0, HIGH); // High beam is set as usual
		digitalWrite (1, LOW);  // Low beam is unset as usual
	}

        if(waitKey(30) >= 0) break;
    }
    // the camera will be deinitialized automatically in VideoCapture destructor
    return 0;
}
<|endoftext|>


<commit_before>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#pragma once

#include <unordered_map>
#include <vector>

#include <caf/fwd.hpp>

#include "vast/expression.hpp"
#include "vast/fwd.hpp"
#include "vast/meta_index.hpp"
#include "vast/system/indexer_stage_driver.hpp"
#include "vast/system/partition.hpp"
#include "vast/system/query_supervisor.hpp"
#include "vast/system/spawn_indexer.hpp"
#include "vast/uuid.hpp"

#include "vast/detail/flat_lru_cache.hpp"
#include "vast/detail/flat_set.hpp"

namespace vast::system {

/// State of an INDEX actor.
struct index_state {
  // -- member types -----------------------------------------------------------

  /// Function for spawning more INDEXER actors.
  using indexer_factory = decltype(spawn_indexer)*;

  /// Pointer to the stage that multiplexing traffic between our sources and
  /// the INDEXER actors of the current partition.
  using stage_ptr = indexer_stage_driver::stage_ptr_type;

  /// Looks up partitions in the LRU cache by UUID.
  class partition_lookup {
  public:
    auto operator()(const uuid& id) const {
      return [&](const partition_ptr& ptr) {
        return ptr->id() == id;
      };
    }
  };

  /// Loads partitions from disk by UUID.
  class partition_factory {
  public:
    partition_factory(index_state* st) : st_(st) {
      // nop
    }

    partition_ptr operator()(const uuid& id) const;

  private:
    index_state* st_;
  };

  /// Stores partitions sorted by access frequency.
  using partition_cache_type = detail::flat_lru_cache<partition_ptr,
                                                      partition_lookup,
                                                      partition_factory>;

  /// Stores context information for unfinished queries.
  struct lookup_state {
    /// Issued query.
    expression expr;

    /// Unscheduled partitions.
    std::vector<uuid> partitions;
  };

  // -- constructors, destructors, and assignment operators --------------------

  index_state(caf::event_based_actor* self);

  ~index_state();

  /// Initializes the state.
  caf::error init(const path& dir, size_t max_events, size_t max_parts,
                  size_t taste_parts);

  // -- persistence ------------------------------------------------------------

  /// Loads the state from disk.
  caf::error load_from_disk();

  /// Persists the state to disk.
  caf::error flush_to_disk();

  // -- convenience functions --------------------------------------------------

  /// Returns the file name for saving or loading the meta index.
  path meta_index_filename() const;

  /// @returns whether there's an idle worker available.
  bool worker_available();

  /// Takes the next worker from the idle workers stack and returns it.
  /// @pre `has_worker()`
  caf::actor next_worker();

  /// @returns various status metrics.
  caf::dictionary<caf::config_value> status() const;

  /// Creates a new partition owned by the INDEX (stored as `active`).
  void reset_active_partition();

  /// @returns a new partition with random ID.
  partition_ptr make_partition();

  /// @returns a new partition with given ID.
  partition_ptr make_partition(uuid id);

  /// @returns a new INDEXER actor.
  caf::actor make_indexer(path dir, type column_type, size_t column,
                          uuid partition_id);

  /// Decrements the indexer count for a partition.
  caf::error decrement_indexer_count(uuid pid);

  /// @returns the unpersisted partition matching `id` or `nullptr` if no
  ///          partition matches.
  partition* find_unpersisted(const uuid& id);

  /// Locates all INDEXER actors in range [first, last) and spawns one
  /// evaluator per identified INDEXER set.
  /// @returns a query map for passing to INDEX workers over the spawned
  ///          EVALUATOR actors.
  /// @pre num_partitions > 0
  query_map launch_evaluators(lookup_state& lookup, size_t num_partitions);

  // -- member variables -------------------------------------------------------

  /// Pointer to the parent actor.
  caf::event_based_actor* self;

  /// Allows to select partitions with timestamps.
  meta_index meta_idx;

  /// Base directory for all partitions of the index.
  path dir;

  /// Stream manager for ingesting events.
  stage_ptr stage;

  /// The maximum number of events per partition.
  size_t max_partition_size;

  /// The number of partitions to schedule immediately for each query
  size_t taste_partitions;

  /// Allows the index to multiplex between waiting for ready workers and
  /// queries.
  caf::behavior has_worker;

  /// Maps query IDs to pending lookup state.
  std::unordered_map<uuid, lookup_state> pending;

  /// Caches idle workers.
  std::vector<caf::actor> idle_workers;

  /// Spawns an INDEXER actor. Default-initialized to `spawn_indexer`, but
  /// allows users to redirect to other implementations (primarily for unit
  /// testing).
  indexer_factory factory;

  /// Our current partition.
  partition_ptr active;

  /// Our current partition.
  size_t active_partition_indexers;

  /// Recently accessed partitions.
  partition_cache_type lru_partitions;

  /// Stores partitions that are no longer active but have not persisted their
  /// state yet.
  std::vector<std::pair<partition_ptr, size_t>> unpersisted;

  /// Name of the INDEX actor.
  static inline const char* name = "index";
};

/// Indexes events in horizontal partitions.
/// @param dir The directory of the index.
/// @param max_partition_size The maximum number of events per partition.
/// @param in_mem_partitions The maximum number of partitions to hold in memory.
/// @param taste_partitions The number of partitions to schedule immediately
///                         for each query
/// @pre `max_partition_size > 0 && in_mem_partitions > 0`
caf::behavior index(caf::stateful_actor<index_state>* self, const path& dir,
                    size_t max_partition_size, size_t in_mem_partitions,
                    size_t taste_partitions, size_t num_workers);

} // namespace vast::system
<commit_msg>Fix doxygen<commit_after>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#pragma once

#include <unordered_map>
#include <vector>

#include <caf/fwd.hpp>

#include "vast/expression.hpp"
#include "vast/fwd.hpp"
#include "vast/meta_index.hpp"
#include "vast/system/indexer_stage_driver.hpp"
#include "vast/system/partition.hpp"
#include "vast/system/query_supervisor.hpp"
#include "vast/system/spawn_indexer.hpp"
#include "vast/uuid.hpp"

#include "vast/detail/flat_lru_cache.hpp"
#include "vast/detail/flat_set.hpp"

namespace vast::system {

/// State of an INDEX actor.
struct index_state {
  // -- member types -----------------------------------------------------------

  /// Function for spawning more INDEXER actors.
  using indexer_factory = decltype(spawn_indexer)*;

  /// Pointer to the stage that multiplexing traffic between our sources and
  /// the INDEXER actors of the current partition.
  using stage_ptr = indexer_stage_driver::stage_ptr_type;

  /// Looks up partitions in the LRU cache by UUID.
  class partition_lookup {
  public:
    auto operator()(const uuid& id) const {
      return [&](const partition_ptr& ptr) {
        return ptr->id() == id;
      };
    }
  };

  /// Loads partitions from disk by UUID.
  class partition_factory {
  public:
    partition_factory(index_state* st) : st_(st) {
      // nop
    }

    partition_ptr operator()(const uuid& id) const;

  private:
    index_state* st_;
  };

  /// Stores partitions sorted by access frequency.
  using partition_cache_type = detail::flat_lru_cache<partition_ptr,
                                                      partition_lookup,
                                                      partition_factory>;

  /// Stores context information for unfinished queries.
  struct lookup_state {
    /// Issued query.
    expression expr;

    /// Unscheduled partitions.
    std::vector<uuid> partitions;
  };

  // -- constructors, destructors, and assignment operators --------------------

  index_state(caf::event_based_actor* self);

  ~index_state();

  /// Initializes the state.
  caf::error init(const path& dir, size_t max_events, size_t max_parts,
                  size_t taste_parts);

  // -- persistence ------------------------------------------------------------

  /// Loads the state from disk.
  caf::error load_from_disk();

  /// Persists the state to disk.
  caf::error flush_to_disk();

  // -- convenience functions --------------------------------------------------

  /// Returns the file name for saving or loading the meta index.
  path meta_index_filename() const;

  /// @returns whether there's an idle worker available.
  bool worker_available();

  /// Takes the next worker from the idle workers stack and returns it.
  /// @pre `has_worker()`
  caf::actor next_worker();

  /// @returns various status metrics.
  caf::dictionary<caf::config_value> status() const;

  /// Creates a new partition owned by the INDEX (stored as `active`).
  void reset_active_partition();

  /// @returns a new partition with random ID.
  partition_ptr make_partition();

  /// @returns a new partition with given ID.
  partition_ptr make_partition(uuid id);

  /// @returns a new INDEXER actor.
  caf::actor make_indexer(path dir, type column_type, size_t column,
                          uuid partition_id);

  /// Decrements the indexer count for a partition.
  caf::error decrement_indexer_count(uuid pid);

  /// @returns the unpersisted partition matching `id` or `nullptr` if no
  ///          partition matches.
  partition* find_unpersisted(const uuid& id);

  /// Locates all INDEXER actors in range [first, last) and spawns one
  /// evaluator per identified INDEXER set.
  /// @returns a query map for passing to INDEX workers over the spawned
  ///          EVALUATOR actors.
  /// @pre num_partitions > 0
  query_map launch_evaluators(lookup_state& lookup, size_t num_partitions);

  // -- member variables -------------------------------------------------------

  /// Pointer to the parent actor.
  caf::event_based_actor* self;

  /// Allows to select partitions with timestamps.
  meta_index meta_idx;

  /// Base directory for all partitions of the index.
  path dir;

  /// Stream manager for ingesting events.
  stage_ptr stage;

  /// The maximum number of events per partition.
  size_t max_partition_size;

  /// The number of partitions to schedule immediately for each query
  size_t taste_partitions;

  /// Allows the index to multiplex between waiting for ready workers and
  /// queries.
  caf::behavior has_worker;

  /// Maps query IDs to pending lookup state.
  std::unordered_map<uuid, lookup_state> pending;

  /// Caches idle workers.
  std::vector<caf::actor> idle_workers;

  /// Spawns an INDEXER actor. Default-initialized to `spawn_indexer`, but
  /// allows users to redirect to other implementations (primarily for unit
  /// testing).
  indexer_factory factory;

  /// Our current partition.
  partition_ptr active;

  /// Active indexer count for the current partition.
  size_t active_partition_indexers;

  /// Recently accessed partitions.
  partition_cache_type lru_partitions;

  /// Stores partitions that are no longer active but have not persisted their
  /// state yet.
  std::vector<std::pair<partition_ptr, size_t>> unpersisted;

  /// Name of the INDEX actor.
  static inline const char* name = "index";
};

/// Indexes events in horizontal partitions.
/// @param dir The directory of the index.
/// @param max_partition_size The maximum number of events per partition.
/// @param in_mem_partitions The maximum number of partitions to hold in memory.
/// @param taste_partitions The number of partitions to schedule immediately
///                         for each query
/// @pre `max_partition_size > 0 && in_mem_partitions > 0`
caf::behavior index(caf::stateful_actor<index_state>* self, const path& dir,
                    size_t max_partition_size, size_t in_mem_partitions,
                    size_t taste_partitions, size_t num_workers);

} // namespace vast::system
<|endoftext|>


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

// ROS includes
#include <ros/ros.h>
#include <geometry_msgs/TwistStamped.h>
#include <geometry_msgs/PoseStamped.h>
#include <std_msgs/Float32.h>
#include "vehicle_socket/CanInfo.h"

namespace vel_pose_mux
{
inline double kmph2mps(double velocity_kmph)
{
  return (velocity_kmph * 1000) / (60 * 60);
}

inline double mps2kmph(double velocity_mps)
{
  return (velocity_mps * 60 * 60) / 1000;
}

void callbackFromCanInfoAndPublishAsTwistStamped(const vehicle_socket::CanInfoConstPtr &msg,
                                                 ros::Publisher *pub_twist_stamped, ros::Publisher *pub_float)
{
  geometry_msgs::TwistStamped tw;
  tw.header = msg->header;

  // linear velocity
  tw.twist.linear.x = kmph2mps(msg->speed);  // km/h -> m/s

  pub_twist_stamped->publish(tw);

  std_msgs::Float32 fl;
  fl.data = msg->speed;
  pub_float->publish(fl);

}

void callbackFromPoseStampedAndPublish(const geometry_msgs::PoseStampedConstPtr &msg, ros::Publisher *pub_message)
{
  pub_message->publish(*msg);
}

void callbackFromTwistStampedAndPublish(const geometry_msgs::TwistStampedConstPtr &msg, ros::Publisher *pub_twist_stamped, ros::Publisher *pub_float)
{
  pub_twist_stamped->publish(*msg);

  std_msgs::Float32 fl;
  fl.data = mps2kmph(msg->twist.linear.x);
  pub_float->publish(fl);
}

}  // namespace

int main(int argc, char **argv)
{
  // set up ros
  ros::init(argc, argv, "vel_pose_mux");

  ros::NodeHandle nh;
  ros::NodeHandle private_nh("~");

  int32_t pose_mux_select, vel_mux_select;
  bool sim_mode;

  // setting params
  private_nh.param<int32_t>("pose_mux_select", pose_mux_select, int32_t(0));
  // ROS_INFO_STREAM("pose_mux_select : " << pose_mux_select);

  private_nh.param<int32_t>("vel_mux_select", vel_mux_select, int32_t(1));
  // ROS_INFO_STREAM("vel_mux_select : " << vel_mux_select);

  private_nh.param<bool>("sim_mode", sim_mode, false);
  // ROS_INFO_STREAM("sim_mode : " << sim_mode);

  // publish topic
  ros::Publisher vel_publisher = nh.advertise<geometry_msgs::TwistStamped>("current_velocity", 10);
  ros::Publisher pose_publisher = nh.advertise<geometry_msgs::PoseStamped>("current_pose", 10);
  ros::Publisher linear_viz_publisher = nh.advertise<std_msgs::Float32>("linear_velocity_viz",10);

  // subscribe topic
  ros::Subscriber pose_subcscriber;
  ros::Subscriber vel_subcscriber;

  if (sim_mode)
  {
    vel_subcscriber = nh.subscribe<geometry_msgs::TwistStamped>(
        "sim_velocity", 10, boost::bind(vel_pose_mux::callbackFromTwistStampedAndPublish, _1, &vel_publisher, &linear_viz_publisher));
    pose_subcscriber = nh.subscribe<geometry_msgs::PoseStamped>(
        "sim_pose", 10, boost::bind(vel_pose_mux::callbackFromPoseStampedAndPublish, _1, &pose_publisher));
  }
  else
  {
    // pose
    switch (pose_mux_select)
    {
      case 0:  // ndt_localizer
      {
        pose_subcscriber = nh.subscribe<geometry_msgs::PoseStamped>(
            "ndt_pose", 10, boost::bind(vel_pose_mux::callbackFromPoseStampedAndPublish, _1, &pose_publisher));
        break;
      }
      case 1:  // gnss
      {
        pose_subcscriber = nh.subscribe<geometry_msgs::PoseStamped>(
            "gnss_pose", 10, boost::bind(vel_pose_mux::callbackFromPoseStampedAndPublish, _1, &pose_publisher));
        break;
      }
      default:
        break;
    }

    // velocity
    switch (vel_mux_select)
    {
      case 0:  // ndt_localizer
      {
        vel_subcscriber = nh.subscribe<geometry_msgs::TwistStamped>(
            "estimate_twist", 10, boost::bind(vel_pose_mux::callbackFromTwistStampedAndPublish, _1, &vel_publisher, &linear_viz_publisher));
        break;
      }
      case 1:  // CAN
      {
        vel_subcscriber = nh.subscribe<vehicle_socket::CanInfo>(
            "can_info", 10, boost::bind(vel_pose_mux::callbackFromCanInfoAndPublishAsTwistStamped, _1, &vel_publisher, &linear_viz_publisher));
        break;
      }
      default:
        break;
    }
  }

  ros::spin();

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

// ROS includes
#include <ros/ros.h>
#include <geometry_msgs/TwistStamped.h>
#include <geometry_msgs/PoseStamped.h>
#include <std_msgs/Float32.h>
#include "vehicle_socket/CanInfo.h"

namespace vel_pose_mux
{

struct VehicleInfo {
  double wheel_base;
  double minimum_turning_radius;
  double maximum_steering_angle;
};

inline double kmph2mps(double velocity_kmph)
{
  return (velocity_kmph * 1000) / (60 * 60);
}

inline double mps2kmph(double velocity_mps)
{
  return (velocity_mps * 60 * 60) / 1000;
}

// convert degree to radian
inline double deg2rad(double deg)
{
  return deg * M_PI / 180;
}

// convert degree to radian
inline double rad2deg(double rad)
{
  return rad * 180 / M_PI;
}

void callbackFromCanInfoAndPublishAsTwistStamped(const vehicle_socket::CanInfoConstPtr &msg,
                                                 ros::Publisher *pub_twist_stamped, ros::Publisher *pub_float,
                                                 const VehicleInfo &vehicle_info)
{
  geometry_msgs::TwistStamped tw;
  tw.header = msg->header;

  // linear velocity
  tw.twist.linear.x = kmph2mps(msg->speed);  // km/h -> m/s

  // angular velocity
  double maximum_tire_angle = rad2deg(asin(vehicle_info.wheel_base / vehicle_info.minimum_turning_radius));  //[degree]
  double current_tire_angle =
      msg->angle * maximum_tire_angle / vehicle_info.maximum_steering_angle;  // steering [degree] -> tire [degree]
  tw.twist.angular.z = sin(deg2rad(current_tire_angle)) * kmph2mps(msg->speed) / vehicle_info.wheel_base;

  pub_twist_stamped->publish(tw);

  std_msgs::Float32 fl;
  fl.data = msg->speed;
  pub_float->publish(fl);
}

void callbackFromCanInfoAndPublishAsTwistStamped(const vehicle_socket::CanInfoConstPtr &msg,
                                                 ros::Publisher *pub_twist_stamped, ros::Publisher *pub_float)
{
  geometry_msgs::TwistStamped tw;
  tw.header = msg->header;

  // linear velocity
  tw.twist.linear.x = kmph2mps(msg->speed);  // km/h -> m/s

  pub_twist_stamped->publish(tw);

  std_msgs::Float32 fl;
  fl.data = msg->speed;
  pub_float->publish(fl);

}

void callbackFromPoseStampedAndPublish(const geometry_msgs::PoseStampedConstPtr &msg, ros::Publisher *pub_message)
{
  pub_message->publish(*msg);
}

void callbackFromTwistStampedAndPublish(const geometry_msgs::TwistStampedConstPtr &msg, ros::Publisher *pub_twist_stamped, ros::Publisher *pub_float)
{
  pub_twist_stamped->publish(*msg);

  std_msgs::Float32 fl;
  fl.data = mps2kmph(msg->twist.linear.x);
  pub_float->publish(fl);
}

}  // namespace

int main(int argc, char **argv)
{
  // set up ros
  ros::init(argc, argv, "vel_pose_mux");

  ros::NodeHandle nh;
  ros::NodeHandle private_nh("~");

  int32_t pose_mux_select, vel_mux_select;
  bool sim_mode;

  // setting params
  private_nh.param<int32_t>("pose_mux_select", pose_mux_select, int32_t(0));
  // ROS_INFO_STREAM("pose_mux_select : " << pose_mux_select);

  private_nh.param<int32_t>("vel_mux_select", vel_mux_select, int32_t(1));
  // ROS_INFO_STREAM("vel_mux_select : " << vel_mux_select);

  private_nh.param<bool>("sim_mode", sim_mode, false);
  // ROS_INFO_STREAM("sim_mode : " << sim_mode);

  bool vehicle_info_flag = false;
  vel_pose_mux::VehicleInfo vehicle_info;
  if (!nh.hasParam("/vehicle_info/wheel_base") || !nh.hasParam("/vehicle_info/minimum_turning_radius") ||
      !nh.hasParam("/vehicle_info/maximum_steering_angle"))
  {
    ROS_INFO("vehicle_info is not set");
  }
  else
  {
    private_nh.getParam("/vehicle_info/wheel_base", vehicle_info.wheel_base);
    // ROS_INFO_STREAM("wheel_base : " << wheel_base);

    private_nh.getParam("/vehicle_info/minimum_turning_radius", vehicle_info.minimum_turning_radius);
    // ROS_INFO_STREAM("minimum_turning_radius : " << minimum_turning_radius);

    private_nh.getParam("/vehicle_info/maximum_steering_angle", vehicle_info.maximum_steering_angle);  //[degree:
    // ROS_INFO_STREAM("maximum_steering_angle : " << maximum_steering_angle);

    vehicle_info_flag = true;
  }

  // publish topic
  ros::Publisher vel_publisher = nh.advertise<geometry_msgs::TwistStamped>("current_velocity", 10);
  ros::Publisher pose_publisher = nh.advertise<geometry_msgs::PoseStamped>("current_pose", 10);
  ros::Publisher linear_viz_publisher = nh.advertise<std_msgs::Float32>("linear_velocity_viz",10);

  // subscribe topic
  ros::Subscriber pose_subcscriber;
  ros::Subscriber vel_subcscriber;

  if (sim_mode)
  {
    vel_subcscriber = nh.subscribe<geometry_msgs::TwistStamped>(
        "sim_velocity", 10, boost::bind(vel_pose_mux::callbackFromTwistStampedAndPublish, _1, &vel_publisher, &linear_viz_publisher));
    pose_subcscriber = nh.subscribe<geometry_msgs::PoseStamped>(
        "sim_pose", 10, boost::bind(vel_pose_mux::callbackFromPoseStampedAndPublish, _1, &pose_publisher));
  }
  else
  {
    // pose
    switch (pose_mux_select)
    {
      case 0:  // ndt_localizer
      {
        pose_subcscriber = nh.subscribe<geometry_msgs::PoseStamped>(
            "ndt_pose", 10, boost::bind(vel_pose_mux::callbackFromPoseStampedAndPublish, _1, &pose_publisher));
        break;
      }
      case 1:  // gnss
      {
        pose_subcscriber = nh.subscribe<geometry_msgs::PoseStamped>(
            "gnss_pose", 10, boost::bind(vel_pose_mux::callbackFromPoseStampedAndPublish, _1, &pose_publisher));
        break;
      }
      default:
        break;
    }

    // velocity
    switch (vel_mux_select)
    {
      case 0:  // ndt_localizer
      {
        vel_subcscriber = nh.subscribe<geometry_msgs::TwistStamped>(
            "estimate_twist", 10, boost::bind(vel_pose_mux::callbackFromTwistStampedAndPublish, _1, &vel_publisher, &linear_viz_publisher));
        break;
      }
      case 1:  // CAN
      {
        if (vehicle_info_flag)  // has vehicle info
        {
          vel_subcscriber = nh.subscribe<vehicle_socket::CanInfo>(
              "can_info", 10, boost::bind(vel_pose_mux::callbackFromCanInfoAndPublishAsTwistStamped, _1, &vel_publisher,
                                          &linear_viz_publisher, vehicle_info));
        }
        else
        {
          vel_subcscriber = nh.subscribe<vehicle_socket::CanInfo>(
              "can_info", 10, boost::bind(vel_pose_mux::callbackFromCanInfoAndPublishAsTwistStamped, _1, &vel_publisher,
                                          &linear_viz_publisher));
        }

        break;
      }
      default:
        break;
    }
  }

  ros::spin();

  return 0;
}
<|endoftext|>


<commit_before>/**
 * @file opencv_sanity.cpp
 * @brief Sanity test for the OpenCV libraries
 * @author Paolo D'Apice
 */

#define BOOST_TEST_MODULE sanity
#include <boost/test/unit_test.hpp>

#include <opencv2/opencv.hpp>
#include <iostream>

#define argc boost::unit_test::framework::master_test_suite().argc
#define argv boost::unit_test::framework::master_test_suite().argv

using namespace cv;
using namespace std;

BOOST_AUTO_TEST_CASE(lena) {
    Mat image = imread(argv[1]);
    BOOST_WARN_MESSAGE(!image.data, "No image data");

    BOOST_CHECK_EQUAL(Size(512, 512), image.size());
    BOOST_CHECK_EQUAL(512, image.rows);
    BOOST_CHECK_EQUAL(512, image.cols);
    BOOST_CHECK_EQUAL(2, image.dims);
    BOOST_CHECK_EQUAL(3, image.channels());

    if (argc > 2) {
        imshow("Display image", image);

        cout << "Press a key to continue" << endl;
        waitKey(0);
    }
}

#define print(X) cout << #X << ": " << X << endl;

BOOST_AUTO_TEST_CASE(opencv_traits) {
    float data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    Mat mat(3,3, CV_32F, data);

    BOOST_CHECK(CV_32F == DataType<float>::type);
    BOOST_CHECK(mat.depth() == DataType<float>::type);
}

<commit_msg>Added test for Mat::push_back<commit_after>/**
 * @file opencv_sanity.cpp
 * @brief Sanity test for the OpenCV libraries
 * @author Paolo D'Apice
 */

#define BOOST_TEST_MODULE sanity
#include <boost/test/unit_test.hpp>

#include "utils/matrix.hpp"
#include <opencv2/opencv.hpp>
#include <iostream>

#define argc boost::unit_test::framework::master_test_suite().argc
#define argv boost::unit_test::framework::master_test_suite().argv

using namespace cv;
using namespace std;

BOOST_AUTO_TEST_CASE(lena) {
    Mat image = imread(argv[1]);
    BOOST_WARN_MESSAGE(!image.data, "No image data");

    BOOST_CHECK_EQUAL(Size(512, 512), image.size());
    BOOST_CHECK_EQUAL(512, image.rows);
    BOOST_CHECK_EQUAL(512, image.cols);
    BOOST_CHECK_EQUAL(2, image.dims);
    BOOST_CHECK_EQUAL(3, image.channels());

    if (argc > 2) {
        imshow("Display image", image);

        cout << "Press a key to continue" << endl;
        waitKey(0);
    }
}

#define print(X) cout << #X << ": " << X << endl;

BOOST_AUTO_TEST_CASE(opencv_traits) {
    float data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    Mat mat(3,3, CV_32F, data);

    BOOST_CHECK(CV_32F == DataType<float>::type);
    BOOST_CHECK(mat.depth() == DataType<float>::type);
}

BOOST_AUTO_TEST_CASE(matrix_push_back) {
    Mat row = Mat::ones(2, 3, CV_32F);

    Mat mat;
    for (int i = 1; i <= 3; i++) {
        mat.push_back( Mat(row*i) );
    }
    Mat expected = (Mat_<float>(6, 3) << 1, 1, 1,
                                         1, 1, 1,
                                         2, 2, 2,
                                         2, 2, 2,
                                         3, 3, 3,
                                         3, 3, 3);
    BOOST_CHECK(vis::equals(expected, mat));
}

<|endoftext|>


<commit_before>#ifndef STAN_MATH_REV_SCAL_FUNCTOR_PARALLEL_REDUCE_SUM_HPP
#define STAN_MATH_REV_SCAL_FUNCTOR_PARALLEL_REDUCE_SUM_HPP

#include <stan/math/prim/meta/return_type.hpp>
#include <stan/math/rev/mat/fun/typedefs.hpp>

#include <boost/iterator/counting_iterator.hpp>

#include <tbb/task_arena.h>
#include <tbb/parallel_reduce.h>
#include <tbb/blocked_range.h>

#include <iostream>
#include <iterator>
#include <vector>

namespace stan {
namespace math {

namespace internal {

template <class ReduceFunction, class InputIt, class T, class Arg1>
struct parallel_reduce_sum_impl<ReduceFunction, InputIt, T, Arg1, var> {
  using ops_partials_t = operands_and_partials<std::vector<Arg1>>;

  struct recursive_reducer {
    InputIt first_;
    std::vector<Arg1>& varg1_;
    const std::vector<int>& idata1_;
    std::vector<std::vector<double>> terms_adjs_;
    std::vector<double> terms_vals_;
    typedef typename std::iterator_traits<InputIt>::value_type elem_t;

    recursive_reducer(InputIt first, const T& init, std::vector<Arg1>& varg1,
                      const std::vector<int>& idata1)
        : first_(first),
          varg1_(varg1),
          idata1_(idata1),
          terms_adjs_(1, std::vector<double>(varg1.size(), 0.0)),
          terms_vals_(1, init.val()) {}

    recursive_reducer(recursive_reducer& other, tbb::split)
        : first_(other.first_),
          varg1_(other.varg1_),
          idata1_(other.idata1_),
          terms_adjs_(),
          terms_vals_() {}
    // terms_adjs_(other.terms_adjs_), terms_vals_(other.terms_vals_) {}

    void operator()(const tbb::blocked_range<size_t>& r) {
      if (r.empty())
        return;

      auto start = first_;
      std::advance(start, r.begin());
      auto end = first_;
      std::advance(end, r.end());

      try {
        start_nested();

        // elem_t should better be a non-var!!! Otherwise we interfere
        // with the outer AD tree as we mess with the adjoints (and
        // right now we discard that it is a var if it would be)
        std::vector<elem_t> sub_slice(start, end);

        // create a deep copy of arg1 which is not tied to the outer AD tree
        std::vector<Arg1> varg1;
        varg1.reserve(varg1_.size());

        for (Arg1& elem : varg1_)
          varg1.emplace_back(var(new vari(elem.val(), false)));

        T sub_sum_v = ReduceFunction()(r.begin(), r.end() - 1, sub_slice, varg1,
                                       idata1_);

        sub_sum_v.grad();

        terms_vals_.push_back(sub_sum_v.val());

        std::vector<double> varg1_adj;
        for (const Arg1& elem : varg1)
          varg1_adj.push_back(elem.adj());

        terms_adjs_.push_back(varg1_adj);

      } catch (const std::exception& e) {
        recover_memory_nested();
        throw;
      }
      recover_memory_nested();
    }
    void join(const recursive_reducer& child) {
      terms_adjs_.insert(terms_adjs_.end(), child.terms_adjs_.begin(),
                         child.terms_adjs_.end());
      terms_vals_.insert(terms_vals_.end(), child.terms_vals_.begin(),
                         child.terms_vals_.end());
    }
  };

  T operator()(InputIt first, InputIt last, T init, std::size_t grainsize,
               std::vector<Arg1>& varg1, const std::vector<int>& idata) const {
    const std::size_t num_jobs = std::distance(first, last);
    recursive_reducer worker(first, init, varg1, idata);
    tbb::parallel_reduce(
        tbb::blocked_range<std::size_t>(0, num_jobs, grainsize), worker);
    ops_partials_t ops_sum(varg1);
    double sum = 0.0;
    for (std::size_t i = 0; i != worker.terms_adjs_.size(); ++i) {
      sum += worker.terms_vals_[i];
      for (std::size_t j = 0; j != worker.terms_adjs_[i].size(); ++j)
        ops_sum.edge1_.partials_[j] += worker.terms_adjs_[i][j];
    }
    return ops_sum.build(sum);
  }
};
}  // namespace internal

}  // namespace math
}  // namespace stan

#endif
<commit_msg>aggregate more efficiently the partial sums<commit_after>#ifndef STAN_MATH_REV_SCAL_FUNCTOR_PARALLEL_REDUCE_SUM_HPP
#define STAN_MATH_REV_SCAL_FUNCTOR_PARALLEL_REDUCE_SUM_HPP

#include <stan/math/prim/meta/return_type.hpp>
#include <stan/math/rev/mat/fun/typedefs.hpp>

#include <boost/iterator/counting_iterator.hpp>

#include <tbb/task_arena.h>
#include <tbb/parallel_reduce.h>
#include <tbb/blocked_range.h>

#include <iostream>
#include <iterator>
#include <vector>

namespace stan {
namespace math {

namespace internal {

template <class ReduceFunction, class InputIt, class T, class Arg1>
struct parallel_reduce_sum_impl<ReduceFunction, InputIt, T, Arg1, var> {
  using ops_partials_t
      = operands_and_partials<std::vector<Arg1>, const std::vector<int>>;

  struct recursive_reducer {
    InputIt first_;
    std::vector<Arg1>& varg1_;
    const std::vector<int>& idata1_;
    ops_partials_t terms_partials_;
    double terms_sum_;
    typedef typename std::iterator_traits<InputIt>::value_type elem_t;

    recursive_reducer(InputIt first, const T& init, std::vector<Arg1>& varg1,
                      const std::vector<int>& idata1)
        : first_(first),
          varg1_(varg1),
          idata1_(idata1),
          terms_partials_(varg1_, idata1_),
          terms_sum_(init.val()) {}

    recursive_reducer(recursive_reducer& other, tbb::split)
        : first_(other.first_),
          varg1_(other.varg1_),
          idata1_(other.idata1_),
          terms_partials_(varg1_, idata1_),
          terms_sum_(0.0) {}

    void operator()(const tbb::blocked_range<size_t>& r) {
      if (r.empty())
        return;

      auto start = first_;
      std::advance(start, r.begin());
      auto end = first_;
      std::advance(end, r.end());

      try {
        start_nested();

        // elem_t should better be a non-var!!! Otherwise we interfere
        // with the outer AD tree as we mess with the adjoints (and
        // right now we discard that it is a var if it would be)
        std::vector<elem_t> sub_slice(start, end);

        // create a deep copy of arg1 which is not tied to the outer
        // AD tree
        // todo: these copies can be put onto a thread-local storage
        // object such that we only create these once per thread which
        // should significantly boost performance as many copies are
        // avoided... this comes at the cost that the adjoints have to
        // be zeroed "manually"
        std::vector<Arg1> varg1;
        varg1.reserve(varg1_.size());

        for (Arg1& elem : varg1_)
          varg1.emplace_back(var(new vari(elem.val(), false)));

        T sub_sum_v = ReduceFunction()(r.begin(), r.end() - 1, sub_slice, varg1,
                                       idata1_);

        sub_sum_v.grad();

        terms_sum_ += sub_sum_v.val();

        for (std::size_t i = 0; i != varg1.size(); ++i)
          terms_partials_.edge1_.partials_[i] += varg1[i].adj();

      } catch (const std::exception& e) {
        recover_memory_nested();
        throw;
      }
      recover_memory_nested();
    }

    void join(const recursive_reducer& child) {
      terms_sum_ += child.terms_sum_;

      for (std::size_t i = 0; i != varg1_.size(); ++i)
        terms_partials_.edge1_.partials_[i]
            += child.terms_partials_.edge1_.partials_[i];
    }
  };

  T operator()(InputIt first, InputIt last, T init, std::size_t grainsize,
               std::vector<Arg1>& varg1, const std::vector<int>& idata) const {
    const std::size_t num_jobs = std::distance(first, last);
    recursive_reducer worker(first, init, varg1, idata);
    tbb::parallel_reduce(
        tbb::blocked_range<std::size_t>(0, num_jobs, grainsize), worker);
    return worker.terms_partials_.build(worker.terms_sum_);
  }
};
}  // namespace internal

}  // namespace math
}  // namespace stan

#endif
<|endoftext|>