<commit_before>//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Axel Naumann <axel@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "IncrementalExecutor.h"
#include "IncrementalJIT.h"
#include "Threading.h"

#include "cling/Interpreter/Value.h"
#include "cling/Interpreter/Transaction.h"
#include "cling/Utils/AST.h"
#include "cling/Utils/Output.h"
#include "cling/Utils/Platform.h"

#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Frontend/CompilerInstance.h"

#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetMachine.h"

using namespace llvm;

namespace cling {

namespace {

static std::unique_ptr<TargetMachine>
CreateHostTargetMachine(const clang::CompilerInstance& CI) {
  const clang::TargetOptions& TargetOpts = CI.getTargetOpts();
  const clang::CodeGenOptions& CGOpt = CI.getCodeGenOpts();
  const std::string& Triple = TargetOpts.Triple;

  std::string Error;
  const Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error);
  if (!TheTarget) {
    cling::errs() << "cling::IncrementalExecutor: unable to find target:\n"
                  << Error;
    return std::unique_ptr<TargetMachine>();
  }

// We have to use large code model for PowerPC64 because TOC and text sections
// can be more than 2GB apart.
#if defined(__powerpc64__) || defined(__PPC64__)
  CodeModel::Model CMModel = CodeModel::Large;
#else
  CodeModel::Model CMModel = CodeModel::JITDefault;
#endif
  CodeGenOpt::Level OptLevel = CodeGenOpt::Default;
  switch (CGOpt.OptimizationLevel) {
    case 0: OptLevel = CodeGenOpt::None; break;
    case 1: OptLevel = CodeGenOpt::Less; break;
    case 2: OptLevel = CodeGenOpt::Default; break;
    case 3: OptLevel = CodeGenOpt::Aggressive; break;
    default: OptLevel = CodeGenOpt::Default;
  }

  std::string MCPU;
  std::string FeaturesStr;

  auto TM = std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine(Triple,
                                        MCPU, FeaturesStr,
                                        llvm::TargetOptions(),
                                        Optional<Reloc::Model>(), CMModel,
                                        OptLevel));
  TM->Options.EmulatedTLS = true;
  return TM;
}

} // anonymous namespace

IncrementalExecutor::IncrementalExecutor(clang::DiagnosticsEngine& diags,
                                         const clang::CompilerInstance& CI):
  m_Callbacks(nullptr), m_externalIncrementalExecutor(nullptr)
#if 0
  : m_Diags(diags)
#endif
{

  // MSVC doesn't support m_AtExitFuncsSpinLock=ATOMIC_FLAG_INIT; in the class definition
  std::atomic_flag_clear( &m_AtExitFuncsSpinLock );

  std::unique_ptr<TargetMachine> TM(CreateHostTargetMachine(CI));
  m_BackendPasses.reset(new BackendPasses(CI.getCodeGenOpts(),
                                          CI.getTargetOpts(),
                                          CI.getLangOpts(),
                                          *TM));
  m_JIT.reset(new IncrementalJIT(*this, std::move(TM)));
}

// Keep in source: ~unique_ptr<ClingJIT> needs ClingJIT
IncrementalExecutor::~IncrementalExecutor() {}

void IncrementalExecutor::shuttingDown() {
  // It is legal to register an atexit handler from within another atexit
  // handler and furthor-more the standard says they need to run in reverse
  // order, so this function must be recursion safe.
  AtExitFunctions Local;
  {
    cling::internal::SpinLockGuard slg(m_AtExitFuncsSpinLock);
    // Check this case first, to avoid the swap all-together.
    if (m_AtExitFuncs.empty())
      return;
    Local.swap(m_AtExitFuncs);
  }
  for (auto&& Ordered : llvm::reverse(Local.ordered())) {
    for (auto&& AtExit : llvm::reverse(Ordered->second))
      AtExit();
    // The standard says that they need to run in reverse order, which means
    // anything added from 'AtExit()' must now be run!
    shuttingDown();
  }
}

void IncrementalExecutor::AddAtExitFunc(void (*func)(void*), void* arg,
                                       const std::shared_ptr<llvm::Module>& M) {
  // Register a CXAAtExit function
  cling::internal::SpinLockGuard slg(m_AtExitFuncsSpinLock);
  m_AtExitFuncs[M].emplace_back(func, arg);
}

void unresolvedSymbol()
{
  // This might get called recursively, or a billion of times. Do not generate
  // useless output; unresolvedSymbol() is always handed out with an error
  // message - that's enough.
  //cling::errs() << "IncrementalExecutor: calling unresolved symbol, "
  //  "see previous error message!\n";

  // throw exception instead?
}

void* IncrementalExecutor::HandleMissingFunction(const std::string& mangled_name)
{
  // Not found in the map, add the symbol in the list of unresolved symbols
  if (m_unresolvedSymbols.insert(mangled_name).second) {
    //cling::errs() << "IncrementalExecutor: use of undefined symbol '"
    //             << mangled_name << "'!\n";
  }

  return utils::FunctionToVoidPtr(&unresolvedSymbol);
}

void* IncrementalExecutor::NotifyLazyFunctionCreators(const std::string& mangled_name)
{
  for (std::vector<LazyFunctionCreatorFunc_t>::iterator it
         = m_lazyFuncCreator.begin(), et = m_lazyFuncCreator.end();
       it != et; ++it) {
    void* ret = (void*)((LazyFunctionCreatorFunc_t)*it)(mangled_name);
    if (ret)
      return ret;
  }
  void *address = nullptr;
  if (m_externalIncrementalExecutor)
   address = m_externalIncrementalExecutor->getAddressOfGlobal(mangled_name);

  return (address ? address : HandleMissingFunction(mangled_name));
}

#if 0
// FIXME: employ to empty module dependencies *within* the *current* module.
static void
freeCallersOfUnresolvedSymbols(llvm::SmallVectorImpl<llvm::Function*>&
                               funcsToFree, llvm::ExecutionEngine* engine) {
  llvm::SmallPtrSet<llvm::Function*, 40> funcsToFreeUnique;
  for (size_t i = 0; i < funcsToFree.size(); ++i) {
    llvm::Function* func = funcsToFree[i];
    assert(func && "Cannot free NULL function");
    if (funcsToFreeUnique.insert(func).second) {
      for (llvm::Value::use_iterator IU = func->use_begin(),
             EU = func->use_end(); IU != EU; ++IU) {
        llvm::Instruction* instUser = llvm::dyn_cast<llvm::Instruction>(*IU);
        if (!instUser) continue;
        if (!instUser->getParent()) continue;
        if (llvm::Function* userFunc = instUser->getParent()->getParent())
          funcsToFree.push_back(userFunc);
      }
    }
  }
  for (llvm::SmallPtrSet<llvm::Function*, 40>::iterator
         I = funcsToFreeUnique.begin(), E = funcsToFreeUnique.end();
       I != E; ++I) {
    // This should force the JIT to recompile the function. But the stubs stay,
    // and the JIT reuses the stubs now pointing nowhere, i.e. without updating
    // the machine code address. Fix the JIT, or hope that MCJIT helps.
    //engine->freeMachineCodeForFunction(*I);
    engine->updateGlobalMapping(*I, 0);
  }
}
#endif

IncrementalExecutor::ExecutionResult
IncrementalExecutor::runStaticInitializersOnce(const Transaction& T) {
  auto m = T.getModule();
  assert(m.get() && "Module must not be null");

  // We don't care whether something was unresolved before.
  m_unresolvedSymbols.clear();

  // check if there is any unresolved symbol in the list
  if (diagnoseUnresolvedSymbols("static initializers"))
    return kExeUnresolvedSymbols;

  llvm::GlobalVariable* GV
     = m->getGlobalVariable("llvm.global_ctors", true);
  // Nothing to do is good, too.
  if (!GV) return kExeSuccess;

  // Close similarity to
  // m_engine->runStaticConstructorsDestructors(false) aka
  // llvm::ExecutionEngine::runStaticConstructorsDestructors()
  // is intentional; we do an extra pass to check whether the JIT
  // managed to collect all the symbols needed by the niitializers.
  // Should be an array of '{ i32, void ()* }' structs.  The first value is
  // the init priority, which we ignore.
  llvm::ConstantArray *InitList
    = llvm::dyn_cast<llvm::ConstantArray>(GV->getInitializer());

  // We need to delete it here just in case we have recursive inits, otherwise
  // it will call inits multiple times.
  GV->eraseFromParent();

  if (InitList == 0)
    return kExeSuccess;

  //SmallVector<Function*, 2> initFuncs;

  for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
    llvm::ConstantStruct *CS
      = llvm::dyn_cast<llvm::ConstantStruct>(InitList->getOperand(i));
    if (CS == 0) continue;

    llvm::Constant *FP = CS->getOperand(1);
    if (FP->isNullValue())
      continue;  // Found a sentinal value, ignore.

    // Strip off constant expression casts.
    if (llvm::ConstantExpr *CE = llvm::dyn_cast<llvm::ConstantExpr>(FP))
      if (CE->isCast())
        FP = CE->getOperand(0);

    // Execute the ctor/dtor function!
    if (llvm::Function *F = llvm::dyn_cast<llvm::Function>(FP)) {
      const llvm::StringRef fName = F->getName();
      executeInit(fName);
/*
      initFuncs.push_back(F);
      if (fName.startswith("_GLOBAL__sub_I_")) {
        BasicBlock& BB = F->getEntryBlock();
        for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I)
          if (CallInst* call = dyn_cast<CallInst>(I))
            initFuncs.push_back(call->getCalledFunction());
      }
*/
    }
  }

/*
  for (SmallVector<Function*,2>::iterator I = initFuncs.begin(),
         E = initFuncs.end(); I != E; ++I) {
    // Cleanup also the dangling init functions. They are in the form:
    // define internal void @_GLOBAL__I_aN() section "..."{
    // entry:
    //   call void @__cxx_global_var_init(N-1)()
    //   call void @__cxx_global_var_initM()
    //   ret void
    // }
    //
    // define internal void @__cxx_global_var_init(N-1)() section "..." {
    // entry:
    //   call void @_ZN7MyClassC1Ev(%struct.MyClass* @n)
    //   ret void
    // }

    // Erase __cxx_global_var_init(N-1)() first.
    (*I)->removeDeadConstantUsers();
    (*I)->eraseFromParent();
  }
*/

  return kExeSuccess;
}

void IncrementalExecutor::runAndRemoveStaticDestructors(Transaction* T) {
  assert(T && "Must be set");
  // Collect all the dtors bound to this transaction.
  AtExitFunctions::mapped_type Local;
  {
    cling::internal::SpinLockGuard slg(m_AtExitFuncsSpinLock);
    auto Itr = m_AtExitFuncs.find(T->getModule());
    if (Itr == m_AtExitFuncs.end()) return;
    m_AtExitFuncs.erase(Itr, &Local);
  } // end of spin lock lifetime block.

  // 'Unload' the cxa_atexit, atexit entities.
  for (auto&& AtExit : llvm::reverse(Local)) {
    AtExit();
    // Run anything that was just registered in 'AtExit()'
    runAndRemoveStaticDestructors(T);
  }
}

void
IncrementalExecutor::installLazyFunctionCreator(LazyFunctionCreatorFunc_t fp)
{
  m_lazyFuncCreator.push_back(fp);
}

bool
IncrementalExecutor::addSymbol(const char* Name,  void* Addr,
                               bool Jit) {
  return m_JIT->lookupSymbol(Name, Addr, Jit).second;
}

void* IncrementalExecutor::getAddressOfGlobal(llvm::StringRef symbolName,
                                              bool* fromJIT /*=0*/) {
  // Return a symbol's address, and whether it was jitted.
  void* address = m_JIT->lookupSymbol(symbolName).first;

  // It's not from the JIT if it's in a dylib.
  if (fromJIT)
    *fromJIT = !address;

  if (!address)
    return (void*)m_JIT->getSymbolAddress(symbolName, false /*no dlsym*/);

  return address;
}

void*
IncrementalExecutor::getPointerToGlobalFromJIT(const llvm::GlobalValue& GV) {
  // Get the function / variable pointer referenced by GV.

  // We don't care whether something was unresolved before.
  m_unresolvedSymbols.clear();

  void* addr = (void*)m_JIT->getSymbolAddress(GV.getName(),
                                              false /*no dlsym*/);

  if (diagnoseUnresolvedSymbols(GV.getName(), "symbol"))
    return 0;
  return addr;
}

bool IncrementalExecutor::diagnoseUnresolvedSymbols(llvm::StringRef trigger,
                                                    llvm::StringRef title) {
  if (m_unresolvedSymbols.empty())
    return false;

  llvm::SmallVector<llvm::Function*, 128> funcsToFree;
  for (const std::string& sym : m_unresolvedSymbols) {
#if 0
    // FIXME: This causes a lot of test failures, for some reason it causes
    // the call to HandleMissingFunction to be elided.
    unsigned diagID = m_Diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
                                              "%0 unresolved while jitting %1");
    (void)diagID;
    //m_Diags.Report(diagID) << sym << funcname; // TODO: demangle the names.
#endif

    cling::errs() << "IncrementalExecutor::executeFunction: symbol '" << sym
                  << "' unresolved while linking ";
    if (trigger.find(utils::Synthesize::UniquePrefix) != llvm::StringRef::npos)
      cling::errs() << "[cling interface function]";
    else {
      if (!title.empty())
        cling::errs() << title << " '";
      cling::errs() << trigger;
      if (!title.empty())
        cling::errs() << "'";
    }
    cling::errs() << "!\n";

    // Be helpful, demangle!
    std::string demangledName = platform::Demangle(sym);
    if (!demangledName.empty()) {
       cling::errs()
          << "You are probably missing the definition of "
          << demangledName << "\n"
          << "Maybe you need to load the corresponding shared library?\n";
    }

    //llvm::Function *ff = m_engine->FindFunctionNamed(i->c_str());
    // i could also reference a global variable, in which case ff == 0.
    //if (ff)
    //  funcsToFree.push_back(ff);
  }
  //freeCallersOfUnresolvedSymbols(funcsToFree, m_engine.get());
  m_unresolvedSymbols.clear();
  return true;
}

}// end namespace cling
<commit_msg>Fix formatting of the TLS commit<commit_after>//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Axel Naumann <axel@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "IncrementalExecutor.h"
#include "IncrementalJIT.h"
#include "Threading.h"

#include "cling/Interpreter/Value.h"
#include "cling/Interpreter/Transaction.h"
#include "cling/Utils/AST.h"
#include "cling/Utils/Output.h"
#include "cling/Utils/Platform.h"

#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Frontend/CompilerInstance.h"

#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetMachine.h"

using namespace llvm;

namespace cling {

namespace {

static std::unique_ptr<TargetMachine>
CreateHostTargetMachine(const clang::CompilerInstance& CI) {
  const clang::TargetOptions& TargetOpts = CI.getTargetOpts();
  const clang::CodeGenOptions& CGOpt = CI.getCodeGenOpts();
  const std::string& Triple = TargetOpts.Triple;

  std::string Error;
  const Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error);
  if (!TheTarget) {
    cling::errs() << "cling::IncrementalExecutor: unable to find target:\n"
                  << Error;
    return std::unique_ptr<TargetMachine>();
  }

// We have to use large code model for PowerPC64 because TOC and text sections
// can be more than 2GB apart.
#if defined(__powerpc64__) || defined(__PPC64__)
  CodeModel::Model CMModel = CodeModel::Large;
#else
  CodeModel::Model CMModel = CodeModel::JITDefault;
#endif
  CodeGenOpt::Level OptLevel = CodeGenOpt::Default;
  switch (CGOpt.OptimizationLevel) {
    case 0: OptLevel = CodeGenOpt::None; break;
    case 1: OptLevel = CodeGenOpt::Less; break;
    case 2: OptLevel = CodeGenOpt::Default; break;
    case 3: OptLevel = CodeGenOpt::Aggressive; break;
    default: OptLevel = CodeGenOpt::Default;
  }

  std::string MCPU;
  std::string FeaturesStr;

  auto TM = std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine(
      Triple, MCPU, FeaturesStr, llvm::TargetOptions(),
      Optional<Reloc::Model>(), CMModel, OptLevel));
  TM->Options.EmulatedTLS = true;
  return TM;
}

} // anonymous namespace

IncrementalExecutor::IncrementalExecutor(clang::DiagnosticsEngine& diags,
                                         const clang::CompilerInstance& CI):
  m_Callbacks(nullptr), m_externalIncrementalExecutor(nullptr)
#if 0
  : m_Diags(diags)
#endif
{

  // MSVC doesn't support m_AtExitFuncsSpinLock=ATOMIC_FLAG_INIT; in the class definition
  std::atomic_flag_clear( &m_AtExitFuncsSpinLock );

  std::unique_ptr<TargetMachine> TM(CreateHostTargetMachine(CI));
  m_BackendPasses.reset(new BackendPasses(CI.getCodeGenOpts(),
                                          CI.getTargetOpts(),
                                          CI.getLangOpts(),
                                          *TM));
  m_JIT.reset(new IncrementalJIT(*this, std::move(TM)));
}

// Keep in source: ~unique_ptr<ClingJIT> needs ClingJIT
IncrementalExecutor::~IncrementalExecutor() {}

void IncrementalExecutor::shuttingDown() {
  // It is legal to register an atexit handler from within another atexit
  // handler and furthor-more the standard says they need to run in reverse
  // order, so this function must be recursion safe.
  AtExitFunctions Local;
  {
    cling::internal::SpinLockGuard slg(m_AtExitFuncsSpinLock);
    // Check this case first, to avoid the swap all-together.
    if (m_AtExitFuncs.empty())
      return;
    Local.swap(m_AtExitFuncs);
  }
  for (auto&& Ordered : llvm::reverse(Local.ordered())) {
    for (auto&& AtExit : llvm::reverse(Ordered->second))
      AtExit();
    // The standard says that they need to run in reverse order, which means
    // anything added from 'AtExit()' must now be run!
    shuttingDown();
  }
}

void IncrementalExecutor::AddAtExitFunc(void (*func)(void*), void* arg,
                                       const std::shared_ptr<llvm::Module>& M) {
  // Register a CXAAtExit function
  cling::internal::SpinLockGuard slg(m_AtExitFuncsSpinLock);
  m_AtExitFuncs[M].emplace_back(func, arg);
}

void unresolvedSymbol()
{
  // This might get called recursively, or a billion of times. Do not generate
  // useless output; unresolvedSymbol() is always handed out with an error
  // message - that's enough.
  //cling::errs() << "IncrementalExecutor: calling unresolved symbol, "
  //  "see previous error message!\n";

  // throw exception instead?
}

void* IncrementalExecutor::HandleMissingFunction(const std::string& mangled_name)
{
  // Not found in the map, add the symbol in the list of unresolved symbols
  if (m_unresolvedSymbols.insert(mangled_name).second) {
    //cling::errs() << "IncrementalExecutor: use of undefined symbol '"
    //             << mangled_name << "'!\n";
  }

  return utils::FunctionToVoidPtr(&unresolvedSymbol);
}

void* IncrementalExecutor::NotifyLazyFunctionCreators(const std::string& mangled_name)
{
  for (std::vector<LazyFunctionCreatorFunc_t>::iterator it
         = m_lazyFuncCreator.begin(), et = m_lazyFuncCreator.end();
       it != et; ++it) {
    void* ret = (void*)((LazyFunctionCreatorFunc_t)*it)(mangled_name);
    if (ret)
      return ret;
  }
  void *address = nullptr;
  if (m_externalIncrementalExecutor)
   address = m_externalIncrementalExecutor->getAddressOfGlobal(mangled_name);

  return (address ? address : HandleMissingFunction(mangled_name));
}

#if 0
// FIXME: employ to empty module dependencies *within* the *current* module.
static void
freeCallersOfUnresolvedSymbols(llvm::SmallVectorImpl<llvm::Function*>&
                               funcsToFree, llvm::ExecutionEngine* engine) {
  llvm::SmallPtrSet<llvm::Function*, 40> funcsToFreeUnique;
  for (size_t i = 0; i < funcsToFree.size(); ++i) {
    llvm::Function* func = funcsToFree[i];
    assert(func && "Cannot free NULL function");
    if (funcsToFreeUnique.insert(func).second) {
      for (llvm::Value::use_iterator IU = func->use_begin(),
             EU = func->use_end(); IU != EU; ++IU) {
        llvm::Instruction* instUser = llvm::dyn_cast<llvm::Instruction>(*IU);
        if (!instUser) continue;
        if (!instUser->getParent()) continue;
        if (llvm::Function* userFunc = instUser->getParent()->getParent())
          funcsToFree.push_back(userFunc);
      }
    }
  }
  for (llvm::SmallPtrSet<llvm::Function*, 40>::iterator
         I = funcsToFreeUnique.begin(), E = funcsToFreeUnique.end();
       I != E; ++I) {
    // This should force the JIT to recompile the function. But the stubs stay,
    // and the JIT reuses the stubs now pointing nowhere, i.e. without updating
    // the machine code address. Fix the JIT, or hope that MCJIT helps.
    //engine->freeMachineCodeForFunction(*I);
    engine->updateGlobalMapping(*I, 0);
  }
}
#endif

IncrementalExecutor::ExecutionResult
IncrementalExecutor::runStaticInitializersOnce(const Transaction& T) {
  auto m = T.getModule();
  assert(m.get() && "Module must not be null");

  // We don't care whether something was unresolved before.
  m_unresolvedSymbols.clear();

  // check if there is any unresolved symbol in the list
  if (diagnoseUnresolvedSymbols("static initializers"))
    return kExeUnresolvedSymbols;

  llvm::GlobalVariable* GV
     = m->getGlobalVariable("llvm.global_ctors", true);
  // Nothing to do is good, too.
  if (!GV) return kExeSuccess;

  // Close similarity to
  // m_engine->runStaticConstructorsDestructors(false) aka
  // llvm::ExecutionEngine::runStaticConstructorsDestructors()
  // is intentional; we do an extra pass to check whether the JIT
  // managed to collect all the symbols needed by the niitializers.
  // Should be an array of '{ i32, void ()* }' structs.  The first value is
  // the init priority, which we ignore.
  llvm::ConstantArray *InitList
    = llvm::dyn_cast<llvm::ConstantArray>(GV->getInitializer());

  // We need to delete it here just in case we have recursive inits, otherwise
  // it will call inits multiple times.
  GV->eraseFromParent();

  if (InitList == 0)
    return kExeSuccess;

  //SmallVector<Function*, 2> initFuncs;

  for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
    llvm::ConstantStruct *CS
      = llvm::dyn_cast<llvm::ConstantStruct>(InitList->getOperand(i));
    if (CS == 0) continue;

    llvm::Constant *FP = CS->getOperand(1);
    if (FP->isNullValue())
      continue;  // Found a sentinal value, ignore.

    // Strip off constant expression casts.
    if (llvm::ConstantExpr *CE = llvm::dyn_cast<llvm::ConstantExpr>(FP))
      if (CE->isCast())
        FP = CE->getOperand(0);

    // Execute the ctor/dtor function!
    if (llvm::Function *F = llvm::dyn_cast<llvm::Function>(FP)) {
      const llvm::StringRef fName = F->getName();
      executeInit(fName);
/*
      initFuncs.push_back(F);
      if (fName.startswith("_GLOBAL__sub_I_")) {
        BasicBlock& BB = F->getEntryBlock();
        for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I)
          if (CallInst* call = dyn_cast<CallInst>(I))
            initFuncs.push_back(call->getCalledFunction());
      }
*/
    }
  }

/*
  for (SmallVector<Function*,2>::iterator I = initFuncs.begin(),
         E = initFuncs.end(); I != E; ++I) {
    // Cleanup also the dangling init functions. They are in the form:
    // define internal void @_GLOBAL__I_aN() section "..."{
    // entry:
    //   call void @__cxx_global_var_init(N-1)()
    //   call void @__cxx_global_var_initM()
    //   ret void
    // }
    //
    // define internal void @__cxx_global_var_init(N-1)() section "..." {
    // entry:
    //   call void @_ZN7MyClassC1Ev(%struct.MyClass* @n)
    //   ret void
    // }

    // Erase __cxx_global_var_init(N-1)() first.
    (*I)->removeDeadConstantUsers();
    (*I)->eraseFromParent();
  }
*/

  return kExeSuccess;
}

void IncrementalExecutor::runAndRemoveStaticDestructors(Transaction* T) {
  assert(T && "Must be set");
  // Collect all the dtors bound to this transaction.
  AtExitFunctions::mapped_type Local;
  {
    cling::internal::SpinLockGuard slg(m_AtExitFuncsSpinLock);
    auto Itr = m_AtExitFuncs.find(T->getModule());
    if (Itr == m_AtExitFuncs.end()) return;
    m_AtExitFuncs.erase(Itr, &Local);
  } // end of spin lock lifetime block.

  // 'Unload' the cxa_atexit, atexit entities.
  for (auto&& AtExit : llvm::reverse(Local)) {
    AtExit();
    // Run anything that was just registered in 'AtExit()'
    runAndRemoveStaticDestructors(T);
  }
}

void
IncrementalExecutor::installLazyFunctionCreator(LazyFunctionCreatorFunc_t fp)
{
  m_lazyFuncCreator.push_back(fp);
}

bool
IncrementalExecutor::addSymbol(const char* Name,  void* Addr,
                               bool Jit) {
  return m_JIT->lookupSymbol(Name, Addr, Jit).second;
}

void* IncrementalExecutor::getAddressOfGlobal(llvm::StringRef symbolName,
                                              bool* fromJIT /*=0*/) {
  // Return a symbol's address, and whether it was jitted.
  void* address = m_JIT->lookupSymbol(symbolName).first;

  // It's not from the JIT if it's in a dylib.
  if (fromJIT)
    *fromJIT = !address;

  if (!address)
    return (void*)m_JIT->getSymbolAddress(symbolName, false /*no dlsym*/);

  return address;
}

void*
IncrementalExecutor::getPointerToGlobalFromJIT(const llvm::GlobalValue& GV) {
  // Get the function / variable pointer referenced by GV.

  // We don't care whether something was unresolved before.
  m_unresolvedSymbols.clear();

  void* addr = (void*)m_JIT->getSymbolAddress(GV.getName(),
                                              false /*no dlsym*/);

  if (diagnoseUnresolvedSymbols(GV.getName(), "symbol"))
    return 0;
  return addr;
}

bool IncrementalExecutor::diagnoseUnresolvedSymbols(llvm::StringRef trigger,
                                                    llvm::StringRef title) {
  if (m_unresolvedSymbols.empty())
    return false;

  llvm::SmallVector<llvm::Function*, 128> funcsToFree;
  for (const std::string& sym : m_unresolvedSymbols) {
#if 0
    // FIXME: This causes a lot of test failures, for some reason it causes
    // the call to HandleMissingFunction to be elided.
    unsigned diagID = m_Diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
                                              "%0 unresolved while jitting %1");
    (void)diagID;
    //m_Diags.Report(diagID) << sym << funcname; // TODO: demangle the names.
#endif

    cling::errs() << "IncrementalExecutor::executeFunction: symbol '" << sym
                  << "' unresolved while linking ";
    if (trigger.find(utils::Synthesize::UniquePrefix) != llvm::StringRef::npos)
      cling::errs() << "[cling interface function]";
    else {
      if (!title.empty())
        cling::errs() << title << " '";
      cling::errs() << trigger;
      if (!title.empty())
        cling::errs() << "'";
    }
    cling::errs() << "!\n";

    // Be helpful, demangle!
    std::string demangledName = platform::Demangle(sym);
    if (!demangledName.empty()) {
       cling::errs()
          << "You are probably missing the definition of "
          << demangledName << "\n"
          << "Maybe you need to load the corresponding shared library?\n";
    }

    //llvm::Function *ff = m_engine->FindFunctionNamed(i->c_str());
    // i could also reference a global variable, in which case ff == 0.
    //if (ff)
    //  funcsToFree.push_back(ff);
  }
  //freeCallersOfUnresolvedSymbols(funcsToFree, m_engine.get());
  m_unresolvedSymbols.clear();
  return true;
}

}// end namespace cling
<|endoftext|>


<commit_before>/*
 * copyright: (c) RDO-Team, 2011
 * filename : procgui.cpp
 * author   :
 * date     : 22.04.2011
 * bref     :
 * indent   : 4T
 */

// ====================================================================== PCH
// ====================================================================== INCLUDES
// ====================================================================== SYNOPSIS
#include "rdo_lib/rdo_simulator/ProcGUI.h"
#include "rdo_lib/rdo_mbuilder/rdo_resources.h"
// ===============================================================================

// --------------------------------------------------------------------
// ---------- ProcGUIBlock
// --------------------------------------------------------------------
ProcGUIBlock::ProcGUIBlock(PTR(rdoParse::RDOParser) pParser, PTR(rdoRuntime::RDORuntime) pRuntime)
	: m_pParser (pParser )
	, m_pRuntime(pRuntime)
{
	//!
	m_pProcess = F(rdoRuntime::RDOPROCProcess)::create(_T("GuiProcess"), m_pRuntime);
	ASSERT(m_pProcess);
	m_pProcess.query_cast<ILogic>()->init(m_pRuntime);
}

ProcGUIBlock::~ProcGUIBlock()
{}

void ProcGUIBlock::Create()
{
	tstring rtp_name       = _T("");
	tstring rtp_param_name = _T("_");

	//!
	rdoMBuilder::RDOResTypeList rtpList(m_pParser);
	//!   ,   ,
	if (!rtpList[rtp_name].exist())
	{
		//!
		rdoMBuilder::RDOResType rtp(rtp_name);
		//!   _
		rtp.m_params.append(rdoMBuilder::RDOResType::Param(rtp_param_name, rdo::Factory<rdoParse::RDOType__real>::create()));
		//!
		rdoRuntime::RDOPROCTransact::typeID = rtp.id();
	}
	else
	{
		CREF(rdoMBuilder::RDOResType) rtp = rtpList[rtp_name];
		rdoRuntime::RDOPROCTransact::typeID = rtp.id();
	}

	//! GENERATE
	rdoRuntime::LPRDOCalcConst pCalc  = rdo::Factory<rdoRuntime::RDOCalcConst>::create(4);
	LPIPROCBlock pBlock = F(rdoRuntime::RDOPROCGenerate)::create(m_pProcess, pCalc);
	ASSERT(pBlock);

	//! TERMINATE
	pBlock = F(rdoRuntime::RDOPROCTerminate)::create(m_pProcess, 1);
	ASSERT(pBlock);
}
<commit_msg> - форматирование<commit_after>/*
 * copyright: (c) RDO-Team, 2011
 * filename : procgui.cpp
 * author   :
 * date     : 22.04.2011
 * bref     :
 * indent   : 4T
 */

// ====================================================================== PCH
// ====================================================================== INCLUDES
// ====================================================================== SYNOPSIS
#include "rdo_lib/rdo_simulator/ProcGUI.h"
#include "rdo_lib/rdo_mbuilder/rdo_resources.h"
// ===============================================================================

// --------------------------------------------------------------------
// ---------- ProcGUIBlock
// --------------------------------------------------------------------
ProcGUIBlock::ProcGUIBlock(PTR(rdoParse::RDOParser) pParser, PTR(rdoRuntime::RDORuntime) pRuntime)
	: m_pParser (pParser )
	, m_pRuntime(pRuntime)
{
	ASSERT(m_pParser );
	ASSERT(m_pRuntime);

	//!
	m_pProcess = F(rdoRuntime::RDOPROCProcess)::create(_T("GuiProcess"), m_pRuntime);
	ASSERT(m_pProcess);
	m_pProcess.query_cast<ILogic>()->init(m_pRuntime);
}

ProcGUIBlock::~ProcGUIBlock()
{}

void ProcGUIBlock::Create()
{
	tstring rtp_name       = _T("");
	tstring rtp_param_name = _T("_");

	//!
	rdoMBuilder::RDOResTypeList rtpList(m_pParser);
	//!   ,   ,
	if (!rtpList[rtp_name].exist())
	{
		//!
		rdoMBuilder::RDOResType rtp(rtp_name);
		//!   _
		rtp.m_params.append(rdoMBuilder::RDOResType::Param(rtp_param_name, rdo::Factory<rdoParse::RDOType__real>::create()));
		//!
		rdoRuntime::RDOPROCTransact::typeID = rtp.id();
	}
	else
	{
		CREF(rdoMBuilder::RDOResType) rtp = rtpList[rtp_name];
		rdoRuntime::RDOPROCTransact::typeID = rtp.id();
	}

	//! GENERATE
	rdoRuntime::LPRDOCalcConst pCalc  = rdo::Factory<rdoRuntime::RDOCalcConst>::create(4);
	LPIPROCBlock pBlock = F(rdoRuntime::RDOPROCGenerate)::create(m_pProcess, pCalc);
	ASSERT(pBlock);

	//! TERMINATE
	pBlock = F(rdoRuntime::RDOPROCTerminate)::create(m_pProcess, 1);
	ASSERT(pBlock);
}
<|endoftext|>


<commit_before>/* vim: set sw=4 sts=4 et foldmethod=syntax : */

#include <max_clique/mpicco_max_clique.hh>
#include <max_clique/cco_base.hh>

#include <graph/template_voodoo.hh>

#include <boost/mpi.hpp>

#include <algorithm>
#include <thread>
#include <mutex>

using namespace parasols;
namespace mpi = boost::mpi;

namespace
{
    template <CCOPermutations perm_, CCOInference inference_, unsigned size_, typename VertexType_>
    struct MPICCO : CCOBase<perm_, inference_, size_, VertexType_, MPICCO<perm_, inference_, size_, VertexType_> >
    {
        using MyCCOBase = CCOBase<perm_, inference_, size_, VertexType_, MPICCO<perm_, inference_, size_, VertexType_> >;

        using MyCCOBase::graph;
        using MyCCOBase::params;
        using MyCCOBase::expand;
        using MyCCOBase::order;
        using MyCCOBase::colour_class_order;

        mpi::environment & env;
        mpi::communicator & world;
        MaxCliqueResult result;

        MPICCO(const Graph & g, const MaxCliqueParams & p, mpi::environment & e, mpi::communicator & w) :
            MyCCOBase(g, p),
            env(e),
            world(w)
        {
        }

        auto run() -> MaxCliqueResult
        {
            result.size = params.initial_bound;

            if (0 == world.rank())
                return run_master();
            else
                return run_slave();
        }

        auto run_slave() -> MaxCliqueResult
        {
            while (true)
            {
                /* ask for something to do */
                int message = 0;
                world.send(0, 1000, message);

                /* get a subproblem */
                std::vector<int> subproblem;
                world.recv(0, 1001, subproblem);

                if (subproblem.empty())
                    break;

                std::vector<unsigned> c;
                c.reserve(graph.size());

                FixedBitSet<size_> p; // potential additions
                p.resize(graph.size());
                p.set_all();

                std::vector<int> positions;
                positions.reserve(graph.size());
                positions.push_back(0);

                // initial colouring
                std::array<VertexType_, size_ * bits_per_word> initial_p_order;
                std::array<VertexType_, size_ * bits_per_word> initial_colours;
                colour_class_order(SelectColourClassOrderOverload<perm_>(), p, initial_p_order, initial_colours);

                // go!
                expand(c, p, initial_p_order, initial_colours, positions, subproblem);
            }

            /* send result */
            world.send(0, 1002, result.size);
            std::vector<int> result_members{ result.members.begin(), result.members.end() };
            world.send(0, 1003, result_members);
            world.send(0, 1004, result.nodes);

            return result;
        }

        auto run_master() -> MaxCliqueResult
        {
            int s1 = 0, s2 = 0, n_finishes_sent = 0;
            while (n_finishes_sent < world.size() - 1) {
                /* request from anyone */
                int message;
                auto status = world.recv(mpi::any_source, 1000, message);

                if (s1 < graph.size()) {
                    /* send subproblem */
                    std::cerr << "sending subproblem " << s1 << " " << s2 << " to " << status.source() << std::endl;
                    std::vector<int> subproblem_vector = { s1, s2 };
                    world.send(status.source(), 1001, subproblem_vector);
                    if (++s2 == graph.size()) {
                        s2 = 0;
                        ++s1;
                    }
                }
                else {
                    /* send finish */
                    std::cerr << "sending finish to " << status.source() << std::endl;
                    std::vector<int> subproblem_vector;
                    world.send(status.source(), 1001, subproblem_vector);
                    ++n_finishes_sent;

                    /* read result */
                    MaxCliqueResult sub_result;
                    std::vector<int> sub_result_members;
                    world.recv(status.source(), 1002, sub_result.size);
                    world.recv(status.source(), 1003, sub_result_members);
                    sub_result.members = std::set<int>{ sub_result_members.begin(), sub_result_members.end() };
                    world.recv(status.source(), 1004, sub_result.nodes);
                    result.merge(sub_result);
                }
            }

            std::cerr << "all finishes sent" << std::endl;

            return result;
        }

        auto increment_nodes(std::vector<int> &) -> void
        {
            ++result.nodes;
        }

        auto recurse(
                std::vector<unsigned> & c,                       // current candidate clique
                FixedBitSet<size_> & p,
                const std::array<VertexType_, size_ * bits_per_word> & p_order,
                const std::array<VertexType_, size_ * bits_per_word> & colours,
                std::vector<int> & position,
                std::vector<int> & subproblem
                ) -> bool
        {
            expand(c, p, p_order, colours, position, subproblem);
            return true;
        }

        auto potential_new_best(
                const std::vector<unsigned> & c,
                const std::vector<int> &,
                std::vector<int> &) -> void
        {
            // potential new best
            if (c.size() > result.size) {
                result.size = c.size();

                result.members.clear();
                for (auto & v : c)
                    result.members.insert(order[v]);
            }
        }

        auto get_best_anywhere_value() -> unsigned
        {
            return result.size;
        }

        auto get_skip(unsigned c_popcount, std::vector<int> & subproblem, int & skip, bool & keep_going) -> void
        {
            if (c_popcount < subproblem.size()) {
                skip = subproblem.at(c_popcount);
                keep_going = false;
            }
        }
    };
}

template <CCOPermutations perm_, CCOInference inference_>
auto parasols::detail::mpicco_max_clique(
        mpi::environment & env,
        mpi::communicator & world,
        const Graph & graph,
        const MaxCliqueParams & params) -> MaxCliqueResult
{
    return select_graph_size<ApplyPermInference<MPICCO, perm_, inference_>::template Type, MaxCliqueResult>(
            AllGraphSizes(), graph, params, env, world);
}

template auto parasols::detail::mpicco_max_clique<CCOPermutations::None, CCOInference::None>(
        mpi::environment &, mpi::communicator &, const Graph &, const MaxCliqueParams &) -> MaxCliqueResult;

<commit_msg>Record worker runtimes<commit_after>/* vim: set sw=4 sts=4 et foldmethod=syntax : */

#include <max_clique/mpicco_max_clique.hh>
#include <max_clique/cco_base.hh>

#include <graph/template_voodoo.hh>

#include <boost/mpi.hpp>

#include <algorithm>
#include <thread>
#include <mutex>

using namespace parasols;
namespace mpi = boost::mpi;

using std::chrono::steady_clock;
using std::chrono::duration_cast;
using std::chrono::milliseconds;

namespace
{
    template <CCOPermutations perm_, CCOInference inference_, unsigned size_, typename VertexType_>
    struct MPICCO : CCOBase<perm_, inference_, size_, VertexType_, MPICCO<perm_, inference_, size_, VertexType_> >
    {
        using MyCCOBase = CCOBase<perm_, inference_, size_, VertexType_, MPICCO<perm_, inference_, size_, VertexType_> >;

        using MyCCOBase::graph;
        using MyCCOBase::params;
        using MyCCOBase::expand;
        using MyCCOBase::order;
        using MyCCOBase::colour_class_order;

        mpi::environment & env;
        mpi::communicator & world;
        MaxCliqueResult result;

        MPICCO(const Graph & g, const MaxCliqueParams & p, mpi::environment & e, mpi::communicator & w) :
            MyCCOBase(g, p),
            env(e),
            world(w)
        {
        }

        auto run() -> MaxCliqueResult
        {
            result.size = params.initial_bound;

            if (0 == world.rank())
                return run_master();
            else
                return run_slave();
        }

        auto run_slave() -> MaxCliqueResult
        {
            while (true)
            {
                /* ask for something to do */
                int message = 0;
                world.send(0, 1000, message);

                /* get a subproblem */
                std::vector<int> subproblem;
                world.recv(0, 1001, subproblem);

                if (subproblem.empty())
                    break;

                std::vector<unsigned> c;
                c.reserve(graph.size());

                FixedBitSet<size_> p; // potential additions
                p.resize(graph.size());
                p.set_all();

                std::vector<int> positions;
                positions.reserve(graph.size());
                positions.push_back(0);

                // initial colouring
                std::array<VertexType_, size_ * bits_per_word> initial_p_order;
                std::array<VertexType_, size_ * bits_per_word> initial_colours;
                colour_class_order(SelectColourClassOrderOverload<perm_>(), p, initial_p_order, initial_colours);

                // go!
                expand(c, p, initial_p_order, initial_colours, positions, subproblem);
            }

            /* send result */
            world.send(0, 1002, result.size);
            std::vector<int> result_members{ result.members.begin(), result.members.end() };
            world.send(0, 1003, result_members);
            world.send(0, 1004, result.nodes);

            return result;
        }

        auto run_master() -> MaxCliqueResult
        {
            auto start_time = steady_clock::now(); // local start time

            int s1 = 0, s2 = 0, n_finishes_sent = 0;
            while (n_finishes_sent < world.size() - 1) {
                /* request from anyone */
                int message;
                auto status = world.recv(mpi::any_source, 1000, message);

                if (s1 < graph.size()) {
                    /* send subproblem */
                    std::cerr << "sending subproblem " << s1 << " " << s2 << " to " << status.source() << std::endl;
                    std::vector<int> subproblem_vector = { s1, s2 };
                    world.send(status.source(), 1001, subproblem_vector);
                    if (++s2 == graph.size()) {
                        s2 = 0;
                        ++s1;
                    }
                }
                else {
                    /* send finish */
                    std::cerr << "sending finish to " << status.source() << std::endl;
                    std::vector<int> subproblem_vector;
                    world.send(status.source(), 1001, subproblem_vector);
                    ++n_finishes_sent;

                    auto overall_time = duration_cast<milliseconds>(steady_clock::now() - start_time);
                    result.times.push_back(overall_time);

                    /* read result */
                    MaxCliqueResult sub_result;
                    std::vector<int> sub_result_members;
                    world.recv(status.source(), 1002, sub_result.size);
                    world.recv(status.source(), 1003, sub_result_members);
                    sub_result.members = std::set<int>{ sub_result_members.begin(), sub_result_members.end() };
                    world.recv(status.source(), 1004, sub_result.nodes);
                    result.merge(sub_result);
                }
            }

            std::cerr << "all finishes sent" << std::endl;

            return result;
        }

        auto increment_nodes(std::vector<int> &) -> void
        {
            ++result.nodes;
        }

        auto recurse(
                std::vector<unsigned> & c,                       // current candidate clique
                FixedBitSet<size_> & p,
                const std::array<VertexType_, size_ * bits_per_word> & p_order,
                const std::array<VertexType_, size_ * bits_per_word> & colours,
                std::vector<int> & position,
                std::vector<int> & subproblem
                ) -> bool
        {
            expand(c, p, p_order, colours, position, subproblem);
            return true;
        }

        auto potential_new_best(
                const std::vector<unsigned> & c,
                const std::vector<int> &,
                std::vector<int> &) -> void
        {
            // potential new best
            if (c.size() > result.size) {
                result.size = c.size();

                result.members.clear();
                for (auto & v : c)
                    result.members.insert(order[v]);
            }
        }

        auto get_best_anywhere_value() -> unsigned
        {
            return result.size;
        }

        auto get_skip(unsigned c_popcount, std::vector<int> & subproblem, int & skip, bool & keep_going) -> void
        {
            if (c_popcount < subproblem.size()) {
                skip = subproblem.at(c_popcount);
                keep_going = false;
            }
        }
    };
}

template <CCOPermutations perm_, CCOInference inference_>
auto parasols::detail::mpicco_max_clique(
        mpi::environment & env,
        mpi::communicator & world,
        const Graph & graph,
        const MaxCliqueParams & params) -> MaxCliqueResult
{
    return select_graph_size<ApplyPermInference<MPICCO, perm_, inference_>::template Type, MaxCliqueResult>(
            AllGraphSizes(), graph, params, env, world);
}

template auto parasols::detail::mpicco_max_clique<CCOPermutations::None, CCOInference::None>(
        mpi::environment &, mpi::communicator &, const Graph &, const MaxCliqueParams &) -> MaxCliqueResult;

<|endoftext|>


<commit_before>#include <deque>
using namespace std;

#include <gtest/gtest.h>

#include "../src/pulseTrain.hpp"

class defaultPulseTrain : public ::testing::Test {
	protected:
		pulseTrain myTrain;
};

class filledPulseTrain : public ::testing::Test {
	protected:
	virtual void SetUp() {
		firstPulse = freqPulse(10, 20, 30, true, true);
		secondPulse = freqPulse(1, 2, 3, false, true);
		initialQueue.push_back(firstPulse);
		initialQueue.push_back(secondPulse);
		initialShift = 3.14;

		testTrain = pulseTrain(initialShift, initialQueue);
	}
	double initialShift;
	pulseTrain testTrain;
	freqPulse firstPulse, secondPulse;
	std::deque<freqPulse> initialQueue;
};

class pulseTrainOutputs : public ::testing::Test {
	protected:
	pulseTrainOutputs() :
		firstPulse(freqPulse(100, 1.0, 10, true, false)),
		secondPulse(freqPulse(130, 1.0, 10, 1.57079632679, false, true)),
		samplePeriodGHz(1.0),
		samplePeriodFull(1.0/1.024),
		expectPtsGHz(21),
		expectPtsFull(21),
		expectPtsExact(20),
		expectShiftGHz(3),
		expectShiftFull(4),
		shiftSize(3.45) {
			testTrain.pushPulse(firstPulse);
			testTrain.pushPulse(secondPulse);
		};
	pulseTrain testTrain;
	freqPulse firstPulse, secondPulse;
	const double samplePeriodGHz;
	const double samplePeriodFull;
	const unsigned int expectPtsGHz;
	const unsigned int expectPtsFull;
	const unsigned int expectPtsExact;
	const unsigned int expectShiftGHz;
	const unsigned int expectShiftFull;
	const double shiftSize;
};

TEST_F(defaultPulseTrain, CorrectContents) {
	deque<freqPulse> emptyPulseQueue;

	EXPECT_EQ(0, myTrain.getShift());
	EXPECT_EQ(emptyPulseQueue, myTrain.getPulses());
}

TEST_F(filledPulseTrain, size) {
	EXPECT_EQ(initialQueue.size(), testTrain.size());
}

TEST_F(filledPulseTrain, front) {
	EXPECT_EQ(initialQueue.front(), testTrain.front());
}

TEST_F(filledPulseTrain, pop) {
	initialQueue.pop_front();
	testTrain.pop();
	EXPECT_EQ(initialQueue, testTrain.getPulses());
}

TEST_F(filledPulseTrain, push) {
	freqPulse toPush(3.1,4,5,false,true);
	initialQueue.push_back(toPush);
	testTrain.pushPulse(toPush);;
	EXPECT_EQ(initialQueue, testTrain.getPulses());
}

TEST_F(filledPulseTrain, empty) {
	EXPECT_FALSE(testTrain.empty());
	EXPECT_EQ(initialQueue.empty(), testTrain.empty());
	initialQueue.pop_front();
	testTrain.pop();
	initialQueue.pop_front();
	testTrain.pop();
	EXPECT_TRUE(testTrain.empty());
	EXPECT_EQ(initialQueue.empty(), testTrain.empty());
}

TEST(pulseTrainExplicitConstructor, JustDelay) {
	pulseTrain testTrain(1.0);
	deque<freqPulse> emptyPulseQueue;

	EXPECT_EQ(1.0, testTrain.getShift());
	EXPECT_EQ(emptyPulseQueue, testTrain.getPulses());
}

TEST(pulseTrainExplicitConstructor, FullConstructor) {
	deque<freqPulse> pulseQueue;
	pulseQueue.push_back(freqPulse());

	pulseTrain testTrain(1.0, pulseQueue);

	EXPECT_EQ(1.0, testTrain.getShift());
	EXPECT_EQ(pulseQueue, testTrain.getPulses());
}

TEST(pulseTrainShift, SetShift) {
	pulseTrain testTrain;
	double testShift = 3.14;
	testTrain.setShift(testShift);
	EXPECT_EQ(testShift, testTrain.getShift());
}

TEST_F(pulseTrainOutputs, getNumPoints) {
	EXPECT_EQ(expectPtsExact, testTrain.getNumPoints(samplePeriodGHz, false));
	EXPECT_EQ(expectPtsExact, testTrain.getNumPoints(samplePeriodFull, false));
	EXPECT_EQ(expectPtsGHz,   testTrain.getNumPoints(samplePeriodGHz));
	EXPECT_EQ(expectPtsFull,  testTrain.getNumPoints(samplePeriodFull));
}

TEST_F(pulseTrainOutputs, getMarkerChars) {
	unsigned int startLength = 5;
	string expectedMarker  = string(startLength, (char) 0x02) + string(10 - startLength, (char) 0x00) + string(11, (char) 0x01);
	unsigned int testLen = expectedMarker.length();
	string shiftMarkerGHz  = expectedMarker.substr(testLen-expectShiftGHz)  + expectedMarker.substr(0, testLen-expectShiftGHz);
	string shiftMarkerFull = expectedMarker.substr(testLen-expectShiftFull) + expectedMarker.substr(0, testLen-expectShiftFull);
	string negMarkerGHz = expectedMarker.substr(expectShiftGHz ) + expectedMarker.substr(0, expectShiftGHz);
	string negMarkerFull= expectedMarker.substr(expectShiftFull) + expectedMarker.substr(0, expectShiftFull);

	EXPECT_EQ(expectedMarker, testTrain.getMarkerChars(samplePeriodGHz,  expectPtsGHz,  true, startLength));
	EXPECT_EQ(expectedMarker, testTrain.getMarkerChars(samplePeriodFull, expectPtsFull, true, startLength));

	EXPECT_EQ(expectedMarker.substr(0, expectPtsExact), testTrain.getMarkerChars(samplePeriodGHz,  expectPtsExact, false, startLength));
	EXPECT_EQ(expectedMarker.substr(0, expectPtsExact), testTrain.getMarkerChars(samplePeriodFull, expectPtsExact, false, startLength));

	testTrain.setShift(shiftSize);

	EXPECT_EQ(shiftMarkerGHz,  testTrain.getMarkerChars(samplePeriodGHz,  expectPtsGHz,  true, startLength));
	EXPECT_EQ(shiftMarkerFull, testTrain.getMarkerChars(samplePeriodFull, expectPtsFull, true, startLength));

	testTrain.setShift(-shiftSize);

	EXPECT_EQ(negMarkerGHz,  testTrain.getMarkerChars(samplePeriodGHz,  expectPtsGHz,  true, startLength));
	EXPECT_EQ(negMarkerFull, testTrain.getMarkerChars(samplePeriodFull, expectPtsFull, true, startLength));
}

TEST_F(pulseTrainOutputs, getWaveChars) {
	string expectExactGHz  = "\x7F\xCA\xF8\xF8\xCA\x7F\x34\x06\x06\x34\xD9\xFE\xD3\x73\x1B\x02\x38\x9B\xEC\xF9";
	string expectExactFull = "\x7F\xC8\xF7\xF9\xD0\x88\x3E\x0B\x02\x27\xD9\xFE\xD7\x7A\x21\x00\x2C\x8A\xE1\xFD";
	string expectGHz       = "\x7F\xCA\xF8\xF8\xCA\x7F\x34\x06\x06\x34\xD9\xFE\xD3\x73\x1B\x02\x38\x9B\xEC\xF9\xB9";
	string expectFull      = "\x7F\xC8\xF7\xF9\xD0\x88\x3E\x0B\x02\x27\xD9\xFE\xD7\x7A\x21\x00\x2C\x8A\xE1\xFD\xCD";
	string expectShiftGHz  = "\xEC\xF9\xB9\x7F\xCA\xF8\xF8\xCA\x7F\x34\x06\x06\x34\xD9\xFE\xD3\x73\x1B\x02\x38\x9B";
	string expectShiftFull = "\x8A\xE1\xFD\xCD\x7F\xC8\xF7\xF9\xD0\x88\x3E\x0B\x02\x27\xD9\xFE\xD7\x7A\x21\x00\x2C";
	string expectNegGHz    = "\xF8\xCA\x7F\x34\x06\x06\x34\xD9\xFE\xD3\x73\x1B\x02\x38\x9B\xEC\xF9\xB9\x7F\xCA\xF8";
	string expectNegFull   = "\xD0\x88\x3E\x0B\x02\x27\xD9\xFE\xD7\x7A\x21\x00\x2C\x8A\xE1\xFD\xCD\x7F\xC8\xF7\xF9";

	EXPECT_EQ(expectExactGHz,  testTrain.getWaveChars(samplePeriodGHz,  expectPtsExact, false));
	EXPECT_EQ(expectExactFull, testTrain.getWaveChars(samplePeriodFull, expectPtsExact, false));

	EXPECT_EQ(expectGHz,  testTrain.getWaveChars(samplePeriodGHz,  expectPtsGHz,  true));
	EXPECT_EQ(expectFull, testTrain.getWaveChars(samplePeriodFull, expectPtsFull, true));

	testTrain.setShift(shiftSize);
	EXPECT_EQ(expectShiftGHz,  testTrain.getWaveChars(samplePeriodGHz,  expectPtsGHz,  true));
	EXPECT_EQ(expectShiftFull, testTrain.getWaveChars(samplePeriodFull, expectPtsFull, true));

	testTrain.setShift(-shiftSize);
	EXPECT_EQ(expectNegGHz,  testTrain.getWaveChars(samplePeriodGHz,  expectPtsGHz,  true));
	EXPECT_EQ(expectNegFull, testTrain.getWaveChars(samplePeriodFull, expectPtsFull, true));
}

int main(int argc, char * argv[] ) {
	::testing::InitGoogleTest(&argc, argv);
	return RUN_ALL_TESTS();
}
<commit_msg>Add missing phase of 0 to freqPulse constructors.<commit_after>#include <deque>
using namespace std;

#include <gtest/gtest.h>

#include "../src/pulseTrain.hpp"

class defaultPulseTrain : public ::testing::Test {
	protected:
		pulseTrain myTrain;
};

class filledPulseTrain : public ::testing::Test {
	protected:
	virtual void SetUp() {
		firstPulse = freqPulse(10, 20, 30, 0.0, true, true);
		secondPulse = freqPulse(1, 2, 3, 0.0, false, true);
		initialQueue.push_back(firstPulse);
		initialQueue.push_back(secondPulse);
		initialShift = 3.14;

		testTrain = pulseTrain(initialShift, initialQueue);
	}
	double initialShift;
	pulseTrain testTrain;
	freqPulse firstPulse, secondPulse;
	std::deque<freqPulse> initialQueue;
};

class pulseTrainOutputs : public ::testing::Test {
	protected:
	pulseTrainOutputs() :
		firstPulse(freqPulse(100, 1.0, 10, 0.0, true, false)),
		secondPulse(freqPulse(130, 1.0, 10, 1.57079632679, false, true)),
		samplePeriodGHz(1.0),
		samplePeriodFull(1.0/1.024),
		expectPtsGHz(21),
		expectPtsFull(21),
		expectPtsExact(20),
		expectShiftGHz(3),
		expectShiftFull(4),
		shiftSize(3.45) {
			testTrain.pushPulse(firstPulse);
			testTrain.pushPulse(secondPulse);
		};
	pulseTrain testTrain;
	freqPulse firstPulse, secondPulse;
	const double samplePeriodGHz;
	const double samplePeriodFull;
	const unsigned int expectPtsGHz;
	const unsigned int expectPtsFull;
	const unsigned int expectPtsExact;
	const unsigned int expectShiftGHz;
	const unsigned int expectShiftFull;
	const double shiftSize;
};

TEST_F(defaultPulseTrain, CorrectContents) {
	deque<freqPulse> emptyPulseQueue;

	EXPECT_EQ(0, myTrain.getShift());
	EXPECT_EQ(emptyPulseQueue, myTrain.getPulses());
}

TEST_F(filledPulseTrain, size) {
	EXPECT_EQ(initialQueue.size(), testTrain.size());
}

TEST_F(filledPulseTrain, front) {
	EXPECT_EQ(initialQueue.front(), testTrain.front());
}

TEST_F(filledPulseTrain, pop) {
	initialQueue.pop_front();
	testTrain.pop();
	EXPECT_EQ(initialQueue, testTrain.getPulses());
}

TEST_F(filledPulseTrain, push) {
	freqPulse toPush(3.1,4,5,false,true);
	initialQueue.push_back(toPush);
	testTrain.pushPulse(toPush);;
	EXPECT_EQ(initialQueue, testTrain.getPulses());
}

TEST_F(filledPulseTrain, empty) {
	EXPECT_FALSE(testTrain.empty());
	EXPECT_EQ(initialQueue.empty(), testTrain.empty());
	initialQueue.pop_front();
	testTrain.pop();
	initialQueue.pop_front();
	testTrain.pop();
	EXPECT_TRUE(testTrain.empty());
	EXPECT_EQ(initialQueue.empty(), testTrain.empty());
}

TEST(pulseTrainExplicitConstructor, JustDelay) {
	pulseTrain testTrain(1.0);
	deque<freqPulse> emptyPulseQueue;

	EXPECT_EQ(1.0, testTrain.getShift());
	EXPECT_EQ(emptyPulseQueue, testTrain.getPulses());
}

TEST(pulseTrainExplicitConstructor, FullConstructor) {
	deque<freqPulse> pulseQueue;
	pulseQueue.push_back(freqPulse());

	pulseTrain testTrain(1.0, pulseQueue);

	EXPECT_EQ(1.0, testTrain.getShift());
	EXPECT_EQ(pulseQueue, testTrain.getPulses());
}

TEST(pulseTrainShift, SetShift) {
	pulseTrain testTrain;
	double testShift = 3.14;
	testTrain.setShift(testShift);
	EXPECT_EQ(testShift, testTrain.getShift());
}

TEST_F(pulseTrainOutputs, getNumPoints) {
	EXPECT_EQ(expectPtsExact, testTrain.getNumPoints(samplePeriodGHz, false));
	EXPECT_EQ(expectPtsExact, testTrain.getNumPoints(samplePeriodFull, false));
	EXPECT_EQ(expectPtsGHz,   testTrain.getNumPoints(samplePeriodGHz));
	EXPECT_EQ(expectPtsFull,  testTrain.getNumPoints(samplePeriodFull));
}

TEST_F(pulseTrainOutputs, getMarkerChars) {
	unsigned int startLength = 5;
	string expectedMarker  = string(startLength, (char) 0x02) + string(10 - startLength, (char) 0x00) + string(11, (char) 0x01);
	unsigned int testLen = expectedMarker.length();
	string shiftMarkerGHz  = expectedMarker.substr(testLen-expectShiftGHz)  + expectedMarker.substr(0, testLen-expectShiftGHz);
	string shiftMarkerFull = expectedMarker.substr(testLen-expectShiftFull) + expectedMarker.substr(0, testLen-expectShiftFull);
	string negMarkerGHz = expectedMarker.substr(expectShiftGHz ) + expectedMarker.substr(0, expectShiftGHz);
	string negMarkerFull= expectedMarker.substr(expectShiftFull) + expectedMarker.substr(0, expectShiftFull);

	EXPECT_EQ(expectedMarker, testTrain.getMarkerChars(samplePeriodGHz,  expectPtsGHz,  true, startLength));
	EXPECT_EQ(expectedMarker, testTrain.getMarkerChars(samplePeriodFull, expectPtsFull, true, startLength));

	EXPECT_EQ(expectedMarker.substr(0, expectPtsExact), testTrain.getMarkerChars(samplePeriodGHz,  expectPtsExact, false, startLength));
	EXPECT_EQ(expectedMarker.substr(0, expectPtsExact), testTrain.getMarkerChars(samplePeriodFull, expectPtsExact, false, startLength));

	testTrain.setShift(shiftSize);

	EXPECT_EQ(shiftMarkerGHz,  testTrain.getMarkerChars(samplePeriodGHz,  expectPtsGHz,  true, startLength));
	EXPECT_EQ(shiftMarkerFull, testTrain.getMarkerChars(samplePeriodFull, expectPtsFull, true, startLength));

	testTrain.setShift(-shiftSize);

	EXPECT_EQ(negMarkerGHz,  testTrain.getMarkerChars(samplePeriodGHz,  expectPtsGHz,  true, startLength));
	EXPECT_EQ(negMarkerFull, testTrain.getMarkerChars(samplePeriodFull, expectPtsFull, true, startLength));
}

TEST_F(pulseTrainOutputs, getWaveChars) {
	string expectExactGHz  = "\x7F\xCA\xF8\xF8\xCA\x7F\x34\x06\x06\x34\xD9\xFE\xD3\x73\x1B\x02\x38\x9B\xEC\xF9";
	string expectExactFull = "\x7F\xC8\xF7\xF9\xD0\x88\x3E\x0B\x02\x27\xD9\xFE\xD7\x7A\x21\x00\x2C\x8A\xE1\xFD";
	string expectGHz       = "\x7F\xCA\xF8\xF8\xCA\x7F\x34\x06\x06\x34\xD9\xFE\xD3\x73\x1B\x02\x38\x9B\xEC\xF9\xB9";
	string expectFull      = "\x7F\xC8\xF7\xF9\xD0\x88\x3E\x0B\x02\x27\xD9\xFE\xD7\x7A\x21\x00\x2C\x8A\xE1\xFD\xCD";
	string expectShiftGHz  = "\xEC\xF9\xB9\x7F\xCA\xF8\xF8\xCA\x7F\x34\x06\x06\x34\xD9\xFE\xD3\x73\x1B\x02\x38\x9B";
	string expectShiftFull = "\x8A\xE1\xFD\xCD\x7F\xC8\xF7\xF9\xD0\x88\x3E\x0B\x02\x27\xD9\xFE\xD7\x7A\x21\x00\x2C";
	string expectNegGHz    = "\xF8\xCA\x7F\x34\x06\x06\x34\xD9\xFE\xD3\x73\x1B\x02\x38\x9B\xEC\xF9\xB9\x7F\xCA\xF8";
	string expectNegFull   = "\xD0\x88\x3E\x0B\x02\x27\xD9\xFE\xD7\x7A\x21\x00\x2C\x8A\xE1\xFD\xCD\x7F\xC8\xF7\xF9";

	EXPECT_EQ(expectExactGHz,  testTrain.getWaveChars(samplePeriodGHz,  expectPtsExact, false));
	EXPECT_EQ(expectExactFull, testTrain.getWaveChars(samplePeriodFull, expectPtsExact, false));

	EXPECT_EQ(expectGHz,  testTrain.getWaveChars(samplePeriodGHz,  expectPtsGHz,  true));
	EXPECT_EQ(expectFull, testTrain.getWaveChars(samplePeriodFull, expectPtsFull, true));

	testTrain.setShift(shiftSize);
	EXPECT_EQ(expectShiftGHz,  testTrain.getWaveChars(samplePeriodGHz,  expectPtsGHz,  true));
	EXPECT_EQ(expectShiftFull, testTrain.getWaveChars(samplePeriodFull, expectPtsFull, true));

	testTrain.setShift(-shiftSize);
	EXPECT_EQ(expectNegGHz,  testTrain.getWaveChars(samplePeriodGHz,  expectPtsGHz,  true));
	EXPECT_EQ(expectNegFull, testTrain.getWaveChars(samplePeriodFull, expectPtsFull, true));
}

int main(int argc, char * argv[] ) {
	::testing::InitGoogleTest(&argc, argv);
	return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>// Scintilla source code edit control
/** @file LexerModule.cxx
 ** Colourise for particular languages.
 **/
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include <string>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "PropSetSimple.h"
#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "LexerModule.h"
#include "LexerBase.h"
#include "LexerSimple.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

LexerModule::LexerModule(int language_,
	LexerFunction fnLexer_,
	const char *languageName_,
	LexerFunction fnFolder_,
        const char *const wordListDescriptions_[],
	int styleBits_) :
	language(language_),
	fnLexer(fnLexer_),
	fnFolder(fnFolder_),
	fnFactory(0),
	wordListDescriptions(wordListDescriptions_),
	styleBits(styleBits_),
	languageName(languageName_) {
}

LexerModule::LexerModule(int language_,
	LexerFactoryFunction fnFactory_,
	const char *languageName_,
	const char * const wordListDescriptions_[],
	int styleBits_) :
	language(language_),
	fnLexer(0),
	fnFolder(0),
	fnFactory(fnFactory_),
	wordListDescriptions(wordListDescriptions_),
	styleBits(styleBits_),
	languageName(languageName_) {
}

int LexerModule::GetNumWordLists() const {
	if (wordListDescriptions == NULL) {
		return -1;
	} else {
		int numWordLists = 0;

		while (wordListDescriptions[numWordLists]) {
			++numWordLists;
		}

		return numWordLists;
	}
}

const char *LexerModule::GetWordListDescription(int index) const {
	static const char *emptyStr = "";

	assert(index < GetNumWordLists());
	if (index >= GetNumWordLists()) {
		return emptyStr;
	} else {
		return wordListDescriptions[index];
 	}
}

int LexerModule::GetStyleBitsNeeded() const {
	return styleBits;
}

ILexer *LexerModule::Create() const {
	if (fnFactory)
		return fnFactory();
	else
		return new LexerSimple(this);
}

void LexerModule::Lex(unsigned int startPos, int lengthDoc, int initStyle,
	  WordList *keywordlists[], Accessor &styler) const {
	if (fnLexer)
		fnLexer(startPos, lengthDoc, initStyle, keywordlists, styler);
}

void LexerModule::Fold(unsigned int startPos, int lengthDoc, int initStyle,
	  WordList *keywordlists[], Accessor &styler) const {
	if (fnFolder) {
		int lineCurrent = styler.GetLine(startPos);
		// Move back one line in case deletion wrecked current line fold state
		if (lineCurrent > 0) {
			lineCurrent--;
			int newStartPos = styler.LineStart(lineCurrent);
			lengthDoc += startPos - newStartPos;
			startPos = newStartPos;
			initStyle = 0;
			if (startPos > 0) {
				initStyle = styler.StyleAt(startPos - 1);
			}
		}
		fnFolder(startPos, lengthDoc, initStyle, keywordlists, styler);
	}
}
<commit_msg>Variable not needed.<commit_after>// Scintilla source code edit control
/** @file LexerModule.cxx
 ** Colourise for particular languages.
 **/
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include <string>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "PropSetSimple.h"
#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "LexerModule.h"
#include "LexerBase.h"
#include "LexerSimple.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

LexerModule::LexerModule(int language_,
	LexerFunction fnLexer_,
	const char *languageName_,
	LexerFunction fnFolder_,
        const char *const wordListDescriptions_[],
	int styleBits_) :
	language(language_),
	fnLexer(fnLexer_),
	fnFolder(fnFolder_),
	fnFactory(0),
	wordListDescriptions(wordListDescriptions_),
	styleBits(styleBits_),
	languageName(languageName_) {
}

LexerModule::LexerModule(int language_,
	LexerFactoryFunction fnFactory_,
	const char *languageName_,
	const char * const wordListDescriptions_[],
	int styleBits_) :
	language(language_),
	fnLexer(0),
	fnFolder(0),
	fnFactory(fnFactory_),
	wordListDescriptions(wordListDescriptions_),
	styleBits(styleBits_),
	languageName(languageName_) {
}

int LexerModule::GetNumWordLists() const {
	if (wordListDescriptions == NULL) {
		return -1;
	} else {
		int numWordLists = 0;

		while (wordListDescriptions[numWordLists]) {
			++numWordLists;
		}

		return numWordLists;
	}
}

const char *LexerModule::GetWordListDescription(int index) const {
	assert(index < GetNumWordLists());
	if (index >= GetNumWordLists()) {
		return "";
	} else {
		return wordListDescriptions[index];
 	}
}

int LexerModule::GetStyleBitsNeeded() const {
	return styleBits;
}

ILexer *LexerModule::Create() const {
	if (fnFactory)
		return fnFactory();
	else
		return new LexerSimple(this);
}

void LexerModule::Lex(unsigned int startPos, int lengthDoc, int initStyle,
	  WordList *keywordlists[], Accessor &styler) const {
	if (fnLexer)
		fnLexer(startPos, lengthDoc, initStyle, keywordlists, styler);
}

void LexerModule::Fold(unsigned int startPos, int lengthDoc, int initStyle,
	  WordList *keywordlists[], Accessor &styler) const {
	if (fnFolder) {
		int lineCurrent = styler.GetLine(startPos);
		// Move back one line in case deletion wrecked current line fold state
		if (lineCurrent > 0) {
			lineCurrent--;
			int newStartPos = styler.LineStart(lineCurrent);
			lengthDoc += startPos - newStartPos;
			startPos = newStartPos;
			initStyle = 0;
			if (startPos > 0) {
				initStyle = styler.StyleAt(startPos - 1);
			}
		}
		fnFolder(startPos, lengthDoc, initStyle, keywordlists, styler);
	}
}
<|endoftext|>


<commit_before>// Test under-development.  Calls async mem-copy API, experiment with functionality.

#include "hip_runtime.h"
#include "test_common.h"

unsigned p_streams = 2;

void simpleNegTest()
{
    printf ("testing: %s\n",__func__);
    hipError_t e;
    float *A_malloc, *A_pinned, *A_d;

    size_t Nbytes = N*sizeof(float);
    A_malloc = (float*)malloc(Nbytes);
    HIPCHECK(hipMallocHost(&A_pinned, Nbytes));
    HIPCHECK(hipMalloc(&A_d, Nbytes));

    // Can't use default with async copy
    e = hipMemcpyAsync(A_pinned, A_d, Nbytes, hipMemcpyDefault, NULL);
    HIPASSERT (e==hipErrorInvalidMemcpyDirection);

    // Not sure what happens here, the memory must be pinned.
    e = hipMemcpyAsync(A_malloc, A_d, Nbytes, hipMemcpyHostToDevice, NULL);

    printf ("  async memcpy of A_malloc to A_d. Result=%d\n", e);
    //HIPASSERT (e==hipErrorInvalidValue);
}

//---
//Classic example showing how to overlap data transfer with compute.
//We divide the work into "chunks" and create a stream for each chunk.
//Each chunk then runs a H2D copy, followed by kernel execution, followed by D2H copyback.
//Work in separate streams is independent which enables concurrency.

// IN: nStreams : number of streams to use for the test
// IN :useNullStream - use NULL stream.  Synchronizes everything.
// IN: useSyncMemcpyH2D - use sync memcpy (no overlap) for H2D
// IN: useSyncMemcpyD2H - use sync memcpy (no overlap) for D2H
void chunkedAsyncExample(int nStreams, bool useNullStream, bool useSyncMemcpyH2D, bool useSyncMemcpyD2H)
{

    size_t Nbytes = N*sizeof(int);
    printf ("testing: %s(useNullStream=%d, useSyncMemcpyH2D=%d, useSyncMemcpyD2H=%d)  ",__func__, useNullStream, useSyncMemcpyH2D, useSyncMemcpyD2H);
    printf ("Nbytes=%zu (%6.1f MB)\n", Nbytes, (double)(Nbytes)/1024.0/1024.0);

    int *A_d, *B_d, *C_d;
    int *A_h, *B_h, *C_h;

    HipTest::initArrays (&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, N, true);

    unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);

    hipStream_t *stream = (hipStream_t*)malloc(sizeof(hipStream_t) * nStreams);
    if (useNullStream) {
        nStreams = 1;
        stream[0] = NULL;
    } else  {
        for (int i = 0; i < nStreams; ++i) {
            HIPCHECK (hipStreamCreate(&stream[i]));
        }
    }

    size_t workLeft = N;
    size_t workPerStream = N / nStreams;
    for (int i = 0; i < nStreams; ++i) {
        size_t work = (workLeft < workPerStream) ? workLeft : workPerStream;
        size_t workBytes = work * sizeof(int);

        size_t offset = i*workPerStream;

        if (useSyncMemcpyH2D) {
            HIPCHECK ( hipMemcpy(&A_d[offset], &A_h[offset], workBytes, hipMemcpyHostToDevice));
            HIPCHECK ( hipMemcpy(&B_d[offset], &B_h[offset], workBytes, hipMemcpyHostToDevice));
        } else {
            HIPCHECK ( hipMemcpyAsync(&A_d[offset], &A_h[offset], workBytes, hipMemcpyHostToDevice, stream[i]));
            HIPCHECK ( hipMemcpyAsync(&B_d[offset], &B_h[offset], workBytes, hipMemcpyHostToDevice, stream[i]));
        };

        hipLaunchKernel(HipTest::vectorADD, dim3(blocks), dim3(threadsPerBlock), 0, stream[i], &A_d[offset], &B_d[offset], &C_d[offset], work);

        if (useSyncMemcpyD2H) {
            HIPCHECK ( hipMemcpy(&C_h[offset], &C_d[offset], workBytes, hipMemcpyDeviceToHost));
        } else {
            HIPCHECK ( hipMemcpyAsync(&C_h[offset], &C_d[offset], workBytes, hipMemcpyDeviceToHost, stream[i]));
        }
    }

    HIPCHECK (hipDeviceSynchronize());

    HipTest::checkVectorADD(A_h, B_h, C_h, N);

    HipTest::freeArrays (A_d, B_d, C_d, A_h, B_h, C_h, true);
};

//---
//Parse arguments specific to this test.
void parseMyArguments(int argc, char *argv[])
{
    int more_argc = HipTest::parseStandardArguments(argc, argv, false);

    // parse args for this test:
    for (int i = 1; i < more_argc; i++) {
        const char *arg = argv[i];

        if (!strcmp(arg, "--streams")) {
            if (++i >= argc || !HipTest::parseUInt(argv[i], &p_streams)) {
               failed("Bad streams argument");
            }
        } else {
            failed("Bad argument '%s'", arg);
        }
    };
};

int main(int argc, char *argv[])
{
    HipTest::parseStandardArguments(argc, argv, true);
    parseMyArguments(argc, argv);

    printf ("info: set device to %d\n", p_gpuDevice);
    HIPCHECK(hipSetDevice(p_gpuDevice));

    simpleNegTest();

    chunkedAsyncExample(p_streams, true, true, true); // Easy sync version
    chunkedAsyncExample(p_streams, false, true, true); // Easy sync version
    chunkedAsyncExample(p_streams, false, false, true); // Some async
    chunkedAsyncExample(p_streams, false, false, false); // All async

    passed();

}
<commit_msg>Describe how to update HTML docs<commit_after>// Test under-development.  Calls async mem-copy API, experiment with functionality.

#include "hip_runtime.h"
#include "test_common.h"

unsigned p_streams = 2;

void simpleNegTest()
{
    printf ("testing: %s\n",__func__);
    hipError_t e;
    float *A_malloc, *A_pinned, *A_d;

    size_t Nbytes = N*sizeof(float);
    A_malloc = (float*)malloc(Nbytes);
    HIPCHECK(hipMallocHost(&A_pinned, Nbytes));
    HIPCHECK(hipMalloc(&A_d, Nbytes));

    // Can't use default with async copy
    e = hipMemcpyAsync(A_pinned, A_d, Nbytes, hipMemcpyDefault, NULL);
    HIPASSERT (e==hipErrorInvalidMemcpyDirection); // TODO
    HIPASSERT (e!= hipSuccess);

    // Not sure what happens here, the memory must be pinned.
    e = hipMemcpyAsync(A_malloc, A_d, Nbytes, hipMemcpyHostToDevice, NULL);

    printf ("  async memcpy of A_malloc to A_d. Result=%d\n", e);
    //HIPASSERT (e==hipErrorInvalidValue);
}

//---
//Send many async copies to the same stream.
//This requires runtime to keep track of many outstanding commands, and in the case of HCC requires growing/tracking the signal pool:
template<typename T>
void test_manyCopies(int nElements, size_t numCopies, int nStreams)
{
    size_t Nbytes = nElements*sizeof(T);
    printf ("Nbytes=%zu (%6.1f MB)\n", Nbytes, (double)(Nbytes)/1024.0/1024.0);

    int *A_d, *B_d, *C_d;
    int *A_h, *B_h, *C_h;

    HipTest::initArrays (&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, N, true);

    size_t eachCopyBytes = Nbytes / numCopies;

    for (size_t i=0; i<Nbytes; i++)
    {

    }

    HipTest::freeArrays (A_d, B_d, C_d, A_h, B_h, C_h, true);
}

//---
//Classic example showing how to overlap data transfer with compute.
//We divide the work into "chunks" and create a stream for each chunk.
//Each chunk then runs a H2D copy, followed by kernel execution, followed by D2H copyback.
//Work in separate streams is independent which enables concurrency.

// IN: nStreams : number of streams to use for the test
// IN :useNullStream - use NULL stream.  Synchronizes everything.
// IN: useSyncMemcpyH2D - use sync memcpy (no overlap) for H2D
// IN: useSyncMemcpyD2H - use sync memcpy (no overlap) for D2H
void test_chunkedAsyncExample(int nStreams, bool useNullStream, bool useSyncMemcpyH2D, bool useSyncMemcpyD2H)
{

    size_t Nbytes = N*sizeof(int);
    printf ("testing: %s(useNullStream=%d, useSyncMemcpyH2D=%d, useSyncMemcpyD2H=%d)  ",__func__, useNullStream, useSyncMemcpyH2D, useSyncMemcpyD2H);
    printf ("Nbytes=%zu (%6.1f MB)\n", Nbytes, (double)(Nbytes)/1024.0/1024.0);

    int *A_d, *B_d, *C_d;
    int *A_h, *B_h, *C_h;

    HipTest::initArrays (&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, N, true);

    unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);

    hipStream_t *stream = (hipStream_t*)malloc(sizeof(hipStream_t) * nStreams);
    if (useNullStream) {
        nStreams = 1;
        stream[0] = NULL;
    } else  {
        for (int i = 0; i < nStreams; ++i) {
            HIPCHECK (hipStreamCreate(&stream[i]));
        }
    }

    size_t workLeft = N;
    size_t workPerStream = N / nStreams;
    for (int i = 0; i < nStreams; ++i) {
        size_t work = (workLeft < workPerStream) ? workLeft : workPerStream;
        size_t workBytes = work * sizeof(int);

        size_t offset = i*workPerStream;

        if (useSyncMemcpyH2D) {
            HIPCHECK ( hipMemcpy(&A_d[offset], &A_h[offset], workBytes, hipMemcpyHostToDevice));
            HIPCHECK ( hipMemcpy(&B_d[offset], &B_h[offset], workBytes, hipMemcpyHostToDevice));
        } else {
            HIPCHECK ( hipMemcpyAsync(&A_d[offset], &A_h[offset], workBytes, hipMemcpyHostToDevice, stream[i]));
            HIPCHECK ( hipMemcpyAsync(&B_d[offset], &B_h[offset], workBytes, hipMemcpyHostToDevice, stream[i]));
        };

        hipLaunchKernel(HipTest::vectorADD, dim3(blocks), dim3(threadsPerBlock), 0, stream[i], &A_d[offset], &B_d[offset], &C_d[offset], work);

        if (useSyncMemcpyD2H) {
            HIPCHECK ( hipMemcpy(&C_h[offset], &C_d[offset], workBytes, hipMemcpyDeviceToHost));
        } else {
            HIPCHECK ( hipMemcpyAsync(&C_h[offset], &C_d[offset], workBytes, hipMemcpyDeviceToHost, stream[i]));
        }
    }

    HIPCHECK (hipDeviceSynchronize());

    HipTest::checkVectorADD(A_h, B_h, C_h, N);

    HipTest::freeArrays (A_d, B_d, C_d, A_h, B_h, C_h, true);
};

//---
//Parse arguments specific to this test.
void parseMyArguments(int argc, char *argv[])
{
    int more_argc = HipTest::parseStandardArguments(argc, argv, false);

    // parse args for this test:
    for (int i = 1; i < more_argc; i++) {
        const char *arg = argv[i];

        if (!strcmp(arg, "--streams")) {
            if (++i >= argc || !HipTest::parseUInt(argv[i], &p_streams)) {
               failed("Bad streams argument");
            }
        } else {
            failed("Bad argument '%s'", arg);
        }
    };
};

int main(int argc, char *argv[])
{
    HipTest::parseStandardArguments(argc, argv, true);
    parseMyArguments(argc, argv);

    printf ("info: set device to %d\n", p_gpuDevice);
    HIPCHECK(hipSetDevice(p_gpuDevice));

    simpleNegTest();

    test_chunkedAsyncExample(p_streams, true, true, true); // Easy sync version
    test_chunkedAsyncExample(p_streams, false, true, true); // Easy sync version
    test_chunkedAsyncExample(p_streams, false, false, true); // Some async
    test_chunkedAsyncExample(p_streams, false, false, false); // All async

    passed();

}
<|endoftext|>


<commit_before>#include <geometry/camera.h>
#include <geometry/camera_functions.h>
#include <iostream>

Camera Camera::CreatePerspectiveCamera(double focal, double k1, double k2) {
  Camera camera;
  camera.type_ = ProjectionType::PERSPECTIVE;
  camera.parameters_[Camera::Parameters::Focal] = focal;
  camera.parameters_[Camera::Parameters::K1] = k1;
  camera.parameters_[Camera::Parameters::K2] = k2;
  return camera;
};

Camera Camera::CreateBrownCamera(double focal, double aspect_ratio,
                                 const Vec2d& principal_point,
                                 const VecXd& distortion) {
  Camera camera;
  if (distortion.size() != 5) {
    throw std::runtime_error("Invalid distortion coefficients size");
  }
  camera.type_ = ProjectionType::BROWN;
  camera.parameters_[Camera::Parameters::Focal] = focal;
  camera.parameters_[Camera::Parameters::AspectRatio] = aspect_ratio;
  camera.parameters_[Camera::Parameters::K1] = distortion(0);
  camera.parameters_[Camera::Parameters::K2] = distortion(1);
  camera.parameters_[Camera::Parameters::K3] = distortion(2);
  camera.parameters_[Camera::Parameters::P1] = distortion(3);
  camera.parameters_[Camera::Parameters::P2] = distortion(4);
  camera.parameters_[Camera::Parameters::Cx] = principal_point(0);
  camera.parameters_[Camera::Parameters::Cy] = principal_point(1);
};

Camera Camera::CreateFisheyeCamera(double focal, double k1, double k2) {
  Camera camera;
  camera.type_ = ProjectionType::FISHEYE;
  camera.parameters_[Camera::Parameters::Focal] = focal;
  camera.parameters_[Camera::Parameters::K1] = k1;
  camera.parameters_[Camera::Parameters::K2] = k2;
  return camera;
};

Camera Camera::CreateDualCamera(double transition, double focal, double k1,
                                double k2) {
  Camera camera;
  camera.type_ = ProjectionType::DUAL;
  camera.parameters_[Camera::Parameters::Focal] = focal;
  camera.parameters_[Camera::Parameters::K1] = k1;
  camera.parameters_[Camera::Parameters::K2] = k2;
  camera.parameters_[Camera::Parameters::Transition] = transition;
  return camera;
};

Camera Camera::CreateSphericalCamera() {
  Camera camera;
  camera.type_ = ProjectionType::SPHERICAL;
  camera.parameters_[Camera::Parameters::None] = 0.;
  return camera;
};

std::vector<Camera::Parameters> Camera::GetParametersTypes() const {
  std::vector<Camera::Parameters> types;
  for (const auto p : parameters_) {
    types.push_back(p.first);
  }
  return types;
}

VecXd Camera::GetParametersValues() const {
  VecXd values(parameters_.size());
  int count = 0;
  for (const auto p : parameters_) {
    values[count++] = p.second;
  }
  return values;
}

bool Camera::SetParameterValue(const Parameters& parameter, double value) {
  if (parameters_.find(parameter) == parameters_.end()) {
    throw std::runtime_error("Unknown parameter for this camera model");
  }
  parameters_[parameter] = value;
}

ProjectionType Camera::GetProjectionType() const { return type_; }

std::string Camera::GetProjectionString() const {
  switch (type_) {
    case ProjectionType::PERSPECTIVE:
      return "perspective";
    case ProjectionType::BROWN:
      return "brown";
    case ProjectionType::FISHEYE:
      return "fisheye";
    case ProjectionType::DUAL:
      return "dual";
    case ProjectionType::SPHERICAL:
      return "spherical";
    default:
      throw std::runtime_error("Invalid ProjectionType");
  }
}

Mat3d Camera::GetProjectionMatrix() const {
  Mat3d unnormalized = Mat3d::Zero();

  double focal = 1.0;
  const auto find_focal = parameters_.find(Camera::Parameters::Focal);
  if(find_focal != parameters_.end()){
    focal = find_focal->second;
  }

  double aspect_ratio = 1.0;
  const auto find_aspect_ratio = parameters_.find(Camera::Parameters::AspectRatio);
  if(find_aspect_ratio != parameters_.end()){
    aspect_ratio = find_aspect_ratio->second;
  }

  Vec2d principal_point = Vec2d::Zero();
  const auto find_principal_point_x = parameters_.find(Camera::Parameters::Cx);
  if(find_principal_point_x != parameters_.end()){
    principal_point(0) = find_principal_point_x->second;
  }
  const auto find_principal_point_y = parameters_.find(Camera::Parameters::Cy);
  if(find_principal_point_y != parameters_.end()){
    principal_point(1) = find_principal_point_y->second;
  }

  unnormalized(0, 0) = focal;
  unnormalized(1, 1) = focal*aspect_ratio;
  unnormalized.col(2) << principal_point, 1.0;
  return unnormalized;
}

Mat3d Camera::GetProjectionMatrixScaled(int width, int height) const {
  const auto unnormalizer = std::max(width, height);
  Mat3d unnormalized = Mat3d::Zero();

  const auto projection_matrix = GetProjectionMatrix();
  unnormalized.block<2, 2>(0, 0) << unnormalizer * unnormalized.block<2, 2>(0, 0);
  unnormalized.col(2) << projection_matrix(0, 2) * unnormalizer + 0.5 * width,
      projection_matrix(1, 2)  * unnormalizer + 0.5 * height, 1.0;
  return unnormalized;
}

Vec2d Camera::Project(const Vec3d& point) const {
  Vec2d projected;
  const auto parameters = GetParametersValues();
  Dispatch<ProjectFunction>(type_, point.data(), parameters.data(),
                            projected.data());
  return projected;
}

Eigen::MatrixX2d Camera::ProjectMany(const Eigen::MatrixX3d& points) const {
  Eigen::MatrixX2d projected(points.rows(), 2);
  for (int i = 0; i < points.rows(); ++i) {
    projected.row(i) = Project(points.row(i));
  }
  return projected;
}

Vec3d Camera::Bearing(const Vec2d& point) const {
  Vec3d bearing;
  const auto parameters = GetParametersValues();
  Dispatch<BearingFunction>(type_, point.data(), parameters.data(),
                            bearing.data());
  return bearing;
}

Eigen::MatrixX3d Camera::BearingsMany(const Eigen::MatrixX2d& points) const {
  Eigen::MatrixX3d projected(points.rows(), 3);
  for (int i = 0; i < points.rows(); ++i) {
    projected.row(i) = Bearing(points.row(i));
  }
  return projected;
}

Camera::Camera() : type_(ProjectionType::PERSPECTIVE) {
}

std::pair<MatXf, MatXf> ComputeCameraMapping(const Camera& from, const Camera& to, int width, int height){
  const auto normalizer_factor = std::max(width, height);
  const auto inv_normalizer_factor = 1.0/normalizer_factor;

  MatXf u_from(height, width);
  MatXf v_from(height, width);

  const auto half_width = width*0.5;
  const auto half_height = height*0.5;

  for(int v = 0; v < height; ++v){
    for(int u = 0; u < width; ++u){
      const auto uv = Vec2d(u-half_width, v-half_height);
      const Vec2d point_uv_from = normalizer_factor*from.Project(to.Bearing(inv_normalizer_factor*uv));
      u_from(v, u) = point_uv_from(0) + half_width;
      v_from(v, u) = point_uv_from(1) + half_height;
    }
  }
  return std::make_pair(u_from, v_from);
}
<commit_msg>refactor: fixed bug and more accessors<commit_after>#include <geometry/camera.h>
#include <geometry/camera_functions.h>
#include <iostream>

Camera Camera::CreatePerspectiveCamera(double focal, double k1, double k2) {
  Camera camera;
  camera.type_ = ProjectionType::PERSPECTIVE;
  camera.parameters_[Camera::Parameters::Focal] = focal;
  camera.parameters_[Camera::Parameters::K1] = k1;
  camera.parameters_[Camera::Parameters::K2] = k2;
  return camera;
};

Camera Camera::CreateBrownCamera(double focal, double aspect_ratio,
                                 const Vec2d& principal_point,
                                 const VecXd& distortion) {
  Camera camera;
  if (distortion.size() != 5) {
    throw std::runtime_error("Invalid distortion coefficients size");
  }
  camera.type_ = ProjectionType::BROWN;
  camera.parameters_[Camera::Parameters::Focal] = focal;
  camera.parameters_[Camera::Parameters::AspectRatio] = aspect_ratio;
  camera.parameters_[Camera::Parameters::K1] = distortion(0);
  camera.parameters_[Camera::Parameters::K2] = distortion(1);
  camera.parameters_[Camera::Parameters::K3] = distortion(2);
  camera.parameters_[Camera::Parameters::P1] = distortion(3);
  camera.parameters_[Camera::Parameters::P2] = distortion(4);
  camera.parameters_[Camera::Parameters::Cx] = principal_point(0);
  camera.parameters_[Camera::Parameters::Cy] = principal_point(1);
  return camera;
};

Camera Camera::CreateFisheyeCamera(double focal, double k1, double k2) {
  Camera camera;
  camera.type_ = ProjectionType::FISHEYE;
  camera.parameters_[Camera::Parameters::Focal] = focal;
  camera.parameters_[Camera::Parameters::K1] = k1;
  camera.parameters_[Camera::Parameters::K2] = k2;
  return camera;
};

Camera Camera::CreateDualCamera(double transition, double focal, double k1,
                                double k2) {
  Camera camera;
  camera.type_ = ProjectionType::DUAL;
  camera.parameters_[Camera::Parameters::Focal] = focal;
  camera.parameters_[Camera::Parameters::K1] = k1;
  camera.parameters_[Camera::Parameters::K2] = k2;
  camera.parameters_[Camera::Parameters::Transition] = transition;
  return camera;
};

Camera Camera::CreateSphericalCamera() {
  Camera camera;
  camera.type_ = ProjectionType::SPHERICAL;
  camera.parameters_[Camera::Parameters::None] = 0.;
  return camera;
};

std::vector<Camera::Parameters> Camera::GetParametersTypes() const {
  std::vector<Camera::Parameters> types;
  for (const auto p : parameters_) {
    types.push_back(p.first);
  }
  return types;
}

VecXd Camera::GetParametersValues() const {
  VecXd values(parameters_.size());
  int count = 0;
  for (const auto p : parameters_) {
    values[count++] = p.second;
  }
  return values;
}

std::map<Camera::Parameters, double, Camera::CompParameters>
Camera::GetParametersMap() const {
  return parameters_;
}

void Camera::SetParameterValue(const Parameters& parameter, double value) {
  if (parameters_.find(parameter) == parameters_.end()) {
    throw std::runtime_error("Unknown parameter for this camera model");
  }
  parameters_[parameter] = value;
}

double Camera::GetParameterValue(const Parameters& parameter) const {
  if (parameters_.find(parameter) == parameters_.end()) {
    throw std::runtime_error("Unknown parameter for this camera model");
  }
  return parameters_.at(parameter);
}

ProjectionType Camera::GetProjectionType() const { return type_; }

std::string Camera::GetProjectionString() const {
  switch (type_) {
    case ProjectionType::PERSPECTIVE:
      return "perspective";
    case ProjectionType::BROWN:
      return "brown";
    case ProjectionType::FISHEYE:
      return "fisheye";
    case ProjectionType::DUAL:
      return "dual";
    case ProjectionType::SPHERICAL:
      return "spherical";
    default:
      throw std::runtime_error("Invalid ProjectionType");
  }
}

Mat3d Camera::GetProjectionMatrix() const {
  Mat3d unnormalized = Mat3d::Zero();

  double focal = 1.0;
  const auto find_focal = parameters_.find(Camera::Parameters::Focal);
  if(find_focal != parameters_.end()){
    focal = find_focal->second;
  }

  double aspect_ratio = 1.0;
  const auto find_aspect_ratio = parameters_.find(Camera::Parameters::AspectRatio);
  if(find_aspect_ratio != parameters_.end()){
    aspect_ratio = find_aspect_ratio->second;
  }

  Vec2d principal_point = Vec2d::Zero();
  const auto find_principal_point_x = parameters_.find(Camera::Parameters::Cx);
  if(find_principal_point_x != parameters_.end()){
    principal_point(0) = find_principal_point_x->second;
  }
  const auto find_principal_point_y = parameters_.find(Camera::Parameters::Cy);
  if(find_principal_point_y != parameters_.end()){
    principal_point(1) = find_principal_point_y->second;
  }

  unnormalized(0, 0) = focal;
  unnormalized(1, 1) = focal*aspect_ratio;
  unnormalized.col(2) << principal_point, 1.0;
  return unnormalized;
}

Mat3d Camera::GetProjectionMatrixScaled(int width, int height) const {
  const auto unnormalizer = std::max(width, height);
  Mat3d unnormalized = Mat3d::Zero();

  const auto projection_matrix = GetProjectionMatrix();
  unnormalized.block<2, 2>(0, 0) << unnormalizer * projection_matrix.block<2, 2>(0, 0);
  unnormalized.col(2) << projection_matrix(0, 2) * unnormalizer + 0.5 * width,
      projection_matrix(1, 2)  * unnormalizer + 0.5 * height, 1.0;
  return unnormalized;
}

Vec2d Camera::Project(const Vec3d& point) const {
  Vec2d projected;
  const auto parameters = GetParametersValues();
  Dispatch<ProjectFunction>(type_, point.data(), parameters.data(),
                            projected.data());
  return projected;
}

Eigen::MatrixX2d Camera::ProjectMany(const Eigen::MatrixX3d& points) const {
  Eigen::MatrixX2d projected(points.rows(), 2);
  for (int i = 0; i < points.rows(); ++i) {
    projected.row(i) = Project(points.row(i));
  }
  return projected;
}

Vec3d Camera::Bearing(const Vec2d& point) const {
  Vec3d bearing;
  const auto parameters = GetParametersValues();
  Dispatch<BearingFunction>(type_, point.data(), parameters.data(),
                            bearing.data());
  return bearing;
}

Eigen::MatrixX3d Camera::BearingsMany(const Eigen::MatrixX2d& points) const {
  Eigen::MatrixX3d projected(points.rows(), 3);
  for (int i = 0; i < points.rows(); ++i) {
    projected.row(i) = Bearing(points.row(i));
  }
  return projected;
}

Camera::Camera() : type_(ProjectionType::PERSPECTIVE) {
}

std::pair<MatXf, MatXf> ComputeCameraMapping(const Camera& from, const Camera& to, int width, int height){
  const auto normalizer_factor = std::max(width, height);
  const auto inv_normalizer_factor = 1.0/normalizer_factor;

  MatXf u_from(height, width);
  MatXf v_from(height, width);

  const auto half_width = width*0.5;
  const auto half_height = height*0.5;

  for(int v = 0; v < height; ++v){
    for(int u = 0; u < width; ++u){
      const auto uv = Vec2d(u-half_width, v-half_height);
      const Vec2d point_uv_from = normalizer_factor*from.Project(to.Bearing(inv_normalizer_factor*uv));
      u_from(v, u) = point_uv_from(0) + half_width;
      v_from(v, u) = point_uv_from(1) + half_height;
    }
  }
  return std::make_pair(u_from, v_from);
}
<|endoftext|>