<commit_before>//===-- LLVMContext.cpp - Implement LLVMContext ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements LLVMContext, as a wrapper around the opaque
//  class LLVMContextImpl.
//
//===----------------------------------------------------------------------===//

#include "llvm/IR/LLVMContext.h"
#include "LLVMContextImpl.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Metadata.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/SourceMgr.h"
#include <cctype>
using namespace llvm;

static ManagedStatic<LLVMContext> GlobalContext;

LLVMContext& llvm::getGlobalContext() {
  return *GlobalContext;
}

LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) {
  // Create the fixed metadata kinds. This is done in the same order as the
  // MD_* enum values so that they correspond.

  // Create the 'dbg' metadata kind.
  unsigned DbgID = getMDKindID("dbg");
  assert(DbgID == MD_dbg && "dbg kind id drifted"); (void)DbgID;

  // Create the 'tbaa' metadata kind.
  unsigned TBAAID = getMDKindID("tbaa");
  assert(TBAAID == MD_tbaa && "tbaa kind id drifted"); (void)TBAAID;

  // Create the 'prof' metadata kind.
  unsigned ProfID = getMDKindID("prof");
  assert(ProfID == MD_prof && "prof kind id drifted"); (void)ProfID;

  // Create the 'fpmath' metadata kind.
  unsigned FPAccuracyID = getMDKindID("fpmath");
  assert(FPAccuracyID == MD_fpmath && "fpmath kind id drifted");
  (void)FPAccuracyID;

  // Create the 'range' metadata kind.
  unsigned RangeID = getMDKindID("range");
  assert(RangeID == MD_range && "range kind id drifted");
  (void)RangeID;

  // Create the 'tbaa.struct' metadata kind.
  unsigned TBAAStructID = getMDKindID("tbaa.struct");
  assert(TBAAStructID == MD_tbaa_struct && "tbaa.struct kind id drifted");
  (void)TBAAStructID;

  // Create the 'invariant.load' metadata kind.
  unsigned InvariantLdId = getMDKindID("invariant.load");
  assert(InvariantLdId == MD_invariant_load && "invariant.load kind id drifted");
  (void)InvariantLdId;

  // Create the 'alias.scope' metadata kind.
  unsigned AliasScopeID = getMDKindID("alias.scope");
  assert(AliasScopeID == MD_alias_scope && "alias.scope kind id drifted");
  (void)AliasScopeID;

  // Create the 'noalias' metadata kind.
  unsigned NoAliasID = getMDKindID("noalias");
  assert(NoAliasID == MD_noalias && "noalias kind id drifted");
  (void)NoAliasID;

  // Create the 'nontemporal' metadata kind.
  unsigned NonTemporalID = getMDKindID("nontemporal");
  assert(NonTemporalID == MD_nontemporal && "nontemporal kind id drifted");
  (void)NonTemporalID;

  // Create the 'llvm.mem.parallel_loop_access' metadata kind.
  unsigned MemParallelLoopAccessID = getMDKindID("llvm.mem.parallel_loop_access");
  assert(MemParallelLoopAccessID == MD_mem_parallel_loop_access &&
         "mem_parallel_loop_access kind id drifted");
  (void)MemParallelLoopAccessID;

  // Create the 'nonnull' metadata kind.
  unsigned NonNullID = getMDKindID("nonnull");
  assert(NonNullID == MD_nonnull && "nonnull kind id drifted");
  (void)NonNullID;

  // Create the 'dereferenceable' metadata kind.
  unsigned DereferenceableID = getMDKindID("dereferenceable");
  assert(DereferenceableID == MD_dereferenceable &&
         "dereferenceable kind id drifted");
  (void)DereferenceableID;

  // Create the 'dereferenceable_or_null' metadata kind.
  unsigned DereferenceableOrNullID = getMDKindID("dereferenceable_or_null");
  assert(DereferenceableOrNullID == MD_dereferenceable_or_null &&
         "dereferenceable_or_null kind id drifted");
  (void)DereferenceableOrNullID;

  // Create the 'make.implicit' metadata kind.
  unsigned MakeImplicitID = getMDKindID("make.implicit");
  assert(MakeImplicitID == MD_make_implicit &&
         "make.implicit kind id drifted");
  (void)MakeImplicitID;

  // Create the 'unpredictable' metadata kind.
  unsigned UnpredictableID = getMDKindID("unpredictable");
  assert(UnpredictableID == MD_unpredictable &&
         "unpredictable kind id drifted");
  (void)UnpredictableID;

  // Create the 'invariant.group' metadata kind.
  unsigned InvariantGroupId = getMDKindID("invariant.group");
  assert(InvariantGroupId == MD_invariant_group &&
         "invariant.group kind id drifted");
  (void)InvariantGroupId;

  // Create the 'align' metadata kind.
  unsigned AlignID = getMDKindID("align");
  assert(AlignID == MD_align && "align kind id drifted");
  (void)AlignID;

  // Create the 'llvm.loop' metadata kind.
  unsigned LoopID = getMDKindID("llvm.loop");
  assert(LoopID == MD_loop && "llvm.loop kind id drifted");
  (void)LoopID;

  auto *DeoptEntry = pImpl->getOrInsertBundleTag("deopt");
  assert(DeoptEntry->second == LLVMContext::OB_deopt &&
         "deopt operand bundle id drifted!");
  (void)DeoptEntry;

  auto *FuncletEntry = pImpl->getOrInsertBundleTag("funclet");
  assert(FuncletEntry->second == LLVMContext::OB_funclet &&
         "funclet operand bundle id drifted!");
  (void)FuncletEntry;

  auto *GCTransitionEntry = pImpl->getOrInsertBundleTag("gc-transition");
  assert(GCTransitionEntry->second == LLVMContext::OB_gc_transition &&
         "gc-transition operand bundle id drifted!");
  (void)GCTransitionEntry;
}
LLVMContext::~LLVMContext() { delete pImpl; }

void LLVMContext::addModule(Module *M) {
  pImpl->OwnedModules.insert(M);
}

void LLVMContext::removeModule(Module *M) {
  pImpl->OwnedModules.erase(M);
}

//===----------------------------------------------------------------------===//
// Recoverable Backend Errors
//===----------------------------------------------------------------------===//

void LLVMContext::
setInlineAsmDiagnosticHandler(InlineAsmDiagHandlerTy DiagHandler,
                              void *DiagContext) {
  pImpl->InlineAsmDiagHandler = DiagHandler;
  pImpl->InlineAsmDiagContext = DiagContext;
}

/// getInlineAsmDiagnosticHandler - Return the diagnostic handler set by
/// setInlineAsmDiagnosticHandler.
LLVMContext::InlineAsmDiagHandlerTy
LLVMContext::getInlineAsmDiagnosticHandler() const {
  return pImpl->InlineAsmDiagHandler;
}

/// getInlineAsmDiagnosticContext - Return the diagnostic context set by
/// setInlineAsmDiagnosticHandler.
void *LLVMContext::getInlineAsmDiagnosticContext() const {
  return pImpl->InlineAsmDiagContext;
}

void LLVMContext::setDiagnosticHandler(DiagnosticHandlerTy DiagnosticHandler,
                                       void *DiagnosticContext,
                                       bool RespectFilters) {
  pImpl->DiagnosticHandler = DiagnosticHandler;
  pImpl->DiagnosticContext = DiagnosticContext;
  pImpl->RespectDiagnosticFilters = RespectFilters;
}

LLVMContext::DiagnosticHandlerTy LLVMContext::getDiagnosticHandler() const {
  return pImpl->DiagnosticHandler;
}

void *LLVMContext::getDiagnosticContext() const {
  return pImpl->DiagnosticContext;
}

void LLVMContext::setYieldCallback(YieldCallbackTy Callback, void *OpaqueHandle)
{
  pImpl->YieldCallback = Callback;
  pImpl->YieldOpaqueHandle = OpaqueHandle;
}

void LLVMContext::yield() {
  if (pImpl->YieldCallback)
    pImpl->YieldCallback(this, pImpl->YieldOpaqueHandle);
}

void LLVMContext::emitError(const Twine &ErrorStr) {
  diagnose(DiagnosticInfoInlineAsm(ErrorStr));
}

void LLVMContext::emitError(const Instruction *I, const Twine &ErrorStr) {
  assert (I && "Invalid instruction");
  diagnose(DiagnosticInfoInlineAsm(*I, ErrorStr));
}

static bool isDiagnosticEnabled(const DiagnosticInfo &DI) {
  // Optimization remarks are selective. They need to check whether the regexp
  // pattern, passed via one of the -pass-remarks* flags, matches the name of
  // the pass that is emitting the diagnostic. If there is no match, ignore the
  // diagnostic and return.
  if (auto *Remark = dyn_cast<DiagnosticInfoOptimizationBase>(&DI))
    return Remark->isEnabled();

  return true;
}

static const char *getDiagnosticMessagePrefix(DiagnosticSeverity Severity) {
  switch (Severity) {
  case DS_Error:
    return "error";
  case DS_Warning:
    return "warning";
  case DS_Remark:
    return "remark";
  case DS_Note:
    return "note";
  }
  llvm_unreachable("Unknown DiagnosticSeverity");
}

void LLVMContext::diagnose(const DiagnosticInfo &DI) {
  // If there is a report handler, use it.
  if (pImpl->DiagnosticHandler) {
    if (!pImpl->RespectDiagnosticFilters || isDiagnosticEnabled(DI))
      pImpl->DiagnosticHandler(DI, pImpl->DiagnosticContext);
    return;
  }

  if (!isDiagnosticEnabled(DI))
    return;

  // Otherwise, print the message with a prefix based on the severity.
  DiagnosticPrinterRawOStream DP(errs());
  errs() << getDiagnosticMessagePrefix(DI.getSeverity()) << ": ";
  DI.print(DP);
  errs() << "\n";
  if (DI.getSeverity() == DS_Error)
    exit(1);
}

void LLVMContext::emitError(unsigned LocCookie, const Twine &ErrorStr) {
  diagnose(DiagnosticInfoInlineAsm(LocCookie, ErrorStr));
}

//===----------------------------------------------------------------------===//
// Metadata Kind Uniquing
//===----------------------------------------------------------------------===//

/// Return a unique non-zero ID for the specified metadata kind.
unsigned LLVMContext::getMDKindID(StringRef Name) const {
  // If this is new, assign it its ID.
  return pImpl->CustomMDKindNames.insert(
                                     std::make_pair(
                                         Name, pImpl->CustomMDKindNames.size()))
      .first->second;
}

/// getHandlerNames - Populate client-supplied smallvector using custom
/// metadata name and ID.
void LLVMContext::getMDKindNames(SmallVectorImpl<StringRef> &Names) const {
  Names.resize(pImpl->CustomMDKindNames.size());
  for (StringMap<unsigned>::const_iterator I = pImpl->CustomMDKindNames.begin(),
       E = pImpl->CustomMDKindNames.end(); I != E; ++I)
    Names[I->second] = I->first();
}

void LLVMContext::getOperandBundleTags(SmallVectorImpl<StringRef> &Tags) const {
  pImpl->getOperandBundleTags(Tags);
}

uint32_t LLVMContext::getOperandBundleTagID(StringRef Tag) const {
  return pImpl->getOperandBundleTagID(Tag);
}

void LLVMContext::setGC(const Function &Fn, std::string GCName) {
  auto It = pImpl->GCNames.find(&Fn);

  if (It == pImpl->GCNames.end()) {
    pImpl->GCNames.insert(std::make_pair(&Fn, std::move(GCName)));
    return;
  }
  It->second = std::move(GCName);
}
const std::string &LLVMContext::getGC(const Function &Fn) {
  return pImpl->GCNames[&Fn];
}
void LLVMContext::deleteGC(const Function &Fn) {
  pImpl->GCNames.erase(&Fn);
}

bool LLVMContext::shouldDiscardValueNames() const { return pImpl->DiscardValueNames; }

void LLVMContext::setDiscardValueNames(bool Discard) {
  pImpl->DiscardValueNames = Discard;
}
<commit_msg>80 lines column after renaming "shouldDiscardValueNames" (NFC)<commit_after>//===-- LLVMContext.cpp - Implement LLVMContext ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements LLVMContext, as a wrapper around the opaque
//  class LLVMContextImpl.
//
//===----------------------------------------------------------------------===//

#include "llvm/IR/LLVMContext.h"
#include "LLVMContextImpl.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Metadata.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/SourceMgr.h"
#include <cctype>
using namespace llvm;

static ManagedStatic<LLVMContext> GlobalContext;

LLVMContext& llvm::getGlobalContext() {
  return *GlobalContext;
}

LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) {
  // Create the fixed metadata kinds. This is done in the same order as the
  // MD_* enum values so that they correspond.

  // Create the 'dbg' metadata kind.
  unsigned DbgID = getMDKindID("dbg");
  assert(DbgID == MD_dbg && "dbg kind id drifted"); (void)DbgID;

  // Create the 'tbaa' metadata kind.
  unsigned TBAAID = getMDKindID("tbaa");
  assert(TBAAID == MD_tbaa && "tbaa kind id drifted"); (void)TBAAID;

  // Create the 'prof' metadata kind.
  unsigned ProfID = getMDKindID("prof");
  assert(ProfID == MD_prof && "prof kind id drifted"); (void)ProfID;

  // Create the 'fpmath' metadata kind.
  unsigned FPAccuracyID = getMDKindID("fpmath");
  assert(FPAccuracyID == MD_fpmath && "fpmath kind id drifted");
  (void)FPAccuracyID;

  // Create the 'range' metadata kind.
  unsigned RangeID = getMDKindID("range");
  assert(RangeID == MD_range && "range kind id drifted");
  (void)RangeID;

  // Create the 'tbaa.struct' metadata kind.
  unsigned TBAAStructID = getMDKindID("tbaa.struct");
  assert(TBAAStructID == MD_tbaa_struct && "tbaa.struct kind id drifted");
  (void)TBAAStructID;

  // Create the 'invariant.load' metadata kind.
  unsigned InvariantLdId = getMDKindID("invariant.load");
  assert(InvariantLdId == MD_invariant_load && "invariant.load kind id drifted");
  (void)InvariantLdId;

  // Create the 'alias.scope' metadata kind.
  unsigned AliasScopeID = getMDKindID("alias.scope");
  assert(AliasScopeID == MD_alias_scope && "alias.scope kind id drifted");
  (void)AliasScopeID;

  // Create the 'noalias' metadata kind.
  unsigned NoAliasID = getMDKindID("noalias");
  assert(NoAliasID == MD_noalias && "noalias kind id drifted");
  (void)NoAliasID;

  // Create the 'nontemporal' metadata kind.
  unsigned NonTemporalID = getMDKindID("nontemporal");
  assert(NonTemporalID == MD_nontemporal && "nontemporal kind id drifted");
  (void)NonTemporalID;

  // Create the 'llvm.mem.parallel_loop_access' metadata kind.
  unsigned MemParallelLoopAccessID = getMDKindID("llvm.mem.parallel_loop_access");
  assert(MemParallelLoopAccessID == MD_mem_parallel_loop_access &&
         "mem_parallel_loop_access kind id drifted");
  (void)MemParallelLoopAccessID;

  // Create the 'nonnull' metadata kind.
  unsigned NonNullID = getMDKindID("nonnull");
  assert(NonNullID == MD_nonnull && "nonnull kind id drifted");
  (void)NonNullID;

  // Create the 'dereferenceable' metadata kind.
  unsigned DereferenceableID = getMDKindID("dereferenceable");
  assert(DereferenceableID == MD_dereferenceable &&
         "dereferenceable kind id drifted");
  (void)DereferenceableID;

  // Create the 'dereferenceable_or_null' metadata kind.
  unsigned DereferenceableOrNullID = getMDKindID("dereferenceable_or_null");
  assert(DereferenceableOrNullID == MD_dereferenceable_or_null &&
         "dereferenceable_or_null kind id drifted");
  (void)DereferenceableOrNullID;

  // Create the 'make.implicit' metadata kind.
  unsigned MakeImplicitID = getMDKindID("make.implicit");
  assert(MakeImplicitID == MD_make_implicit &&
         "make.implicit kind id drifted");
  (void)MakeImplicitID;

  // Create the 'unpredictable' metadata kind.
  unsigned UnpredictableID = getMDKindID("unpredictable");
  assert(UnpredictableID == MD_unpredictable &&
         "unpredictable kind id drifted");
  (void)UnpredictableID;

  // Create the 'invariant.group' metadata kind.
  unsigned InvariantGroupId = getMDKindID("invariant.group");
  assert(InvariantGroupId == MD_invariant_group &&
         "invariant.group kind id drifted");
  (void)InvariantGroupId;

  // Create the 'align' metadata kind.
  unsigned AlignID = getMDKindID("align");
  assert(AlignID == MD_align && "align kind id drifted");
  (void)AlignID;

  // Create the 'llvm.loop' metadata kind.
  unsigned LoopID = getMDKindID("llvm.loop");
  assert(LoopID == MD_loop && "llvm.loop kind id drifted");
  (void)LoopID;

  auto *DeoptEntry = pImpl->getOrInsertBundleTag("deopt");
  assert(DeoptEntry->second == LLVMContext::OB_deopt &&
         "deopt operand bundle id drifted!");
  (void)DeoptEntry;

  auto *FuncletEntry = pImpl->getOrInsertBundleTag("funclet");
  assert(FuncletEntry->second == LLVMContext::OB_funclet &&
         "funclet operand bundle id drifted!");
  (void)FuncletEntry;

  auto *GCTransitionEntry = pImpl->getOrInsertBundleTag("gc-transition");
  assert(GCTransitionEntry->second == LLVMContext::OB_gc_transition &&
         "gc-transition operand bundle id drifted!");
  (void)GCTransitionEntry;
}
LLVMContext::~LLVMContext() { delete pImpl; }

void LLVMContext::addModule(Module *M) {
  pImpl->OwnedModules.insert(M);
}

void LLVMContext::removeModule(Module *M) {
  pImpl->OwnedModules.erase(M);
}

//===----------------------------------------------------------------------===//
// Recoverable Backend Errors
//===----------------------------------------------------------------------===//

void LLVMContext::
setInlineAsmDiagnosticHandler(InlineAsmDiagHandlerTy DiagHandler,
                              void *DiagContext) {
  pImpl->InlineAsmDiagHandler = DiagHandler;
  pImpl->InlineAsmDiagContext = DiagContext;
}

/// getInlineAsmDiagnosticHandler - Return the diagnostic handler set by
/// setInlineAsmDiagnosticHandler.
LLVMContext::InlineAsmDiagHandlerTy
LLVMContext::getInlineAsmDiagnosticHandler() const {
  return pImpl->InlineAsmDiagHandler;
}

/// getInlineAsmDiagnosticContext - Return the diagnostic context set by
/// setInlineAsmDiagnosticHandler.
void *LLVMContext::getInlineAsmDiagnosticContext() const {
  return pImpl->InlineAsmDiagContext;
}

void LLVMContext::setDiagnosticHandler(DiagnosticHandlerTy DiagnosticHandler,
                                       void *DiagnosticContext,
                                       bool RespectFilters) {
  pImpl->DiagnosticHandler = DiagnosticHandler;
  pImpl->DiagnosticContext = DiagnosticContext;
  pImpl->RespectDiagnosticFilters = RespectFilters;
}

LLVMContext::DiagnosticHandlerTy LLVMContext::getDiagnosticHandler() const {
  return pImpl->DiagnosticHandler;
}

void *LLVMContext::getDiagnosticContext() const {
  return pImpl->DiagnosticContext;
}

void LLVMContext::setYieldCallback(YieldCallbackTy Callback, void *OpaqueHandle)
{
  pImpl->YieldCallback = Callback;
  pImpl->YieldOpaqueHandle = OpaqueHandle;
}

void LLVMContext::yield() {
  if (pImpl->YieldCallback)
    pImpl->YieldCallback(this, pImpl->YieldOpaqueHandle);
}

void LLVMContext::emitError(const Twine &ErrorStr) {
  diagnose(DiagnosticInfoInlineAsm(ErrorStr));
}

void LLVMContext::emitError(const Instruction *I, const Twine &ErrorStr) {
  assert (I && "Invalid instruction");
  diagnose(DiagnosticInfoInlineAsm(*I, ErrorStr));
}

static bool isDiagnosticEnabled(const DiagnosticInfo &DI) {
  // Optimization remarks are selective. They need to check whether the regexp
  // pattern, passed via one of the -pass-remarks* flags, matches the name of
  // the pass that is emitting the diagnostic. If there is no match, ignore the
  // diagnostic and return.
  if (auto *Remark = dyn_cast<DiagnosticInfoOptimizationBase>(&DI))
    return Remark->isEnabled();

  return true;
}

static const char *getDiagnosticMessagePrefix(DiagnosticSeverity Severity) {
  switch (Severity) {
  case DS_Error:
    return "error";
  case DS_Warning:
    return "warning";
  case DS_Remark:
    return "remark";
  case DS_Note:
    return "note";
  }
  llvm_unreachable("Unknown DiagnosticSeverity");
}

void LLVMContext::diagnose(const DiagnosticInfo &DI) {
  // If there is a report handler, use it.
  if (pImpl->DiagnosticHandler) {
    if (!pImpl->RespectDiagnosticFilters || isDiagnosticEnabled(DI))
      pImpl->DiagnosticHandler(DI, pImpl->DiagnosticContext);
    return;
  }

  if (!isDiagnosticEnabled(DI))
    return;

  // Otherwise, print the message with a prefix based on the severity.
  DiagnosticPrinterRawOStream DP(errs());
  errs() << getDiagnosticMessagePrefix(DI.getSeverity()) << ": ";
  DI.print(DP);
  errs() << "\n";
  if (DI.getSeverity() == DS_Error)
    exit(1);
}

void LLVMContext::emitError(unsigned LocCookie, const Twine &ErrorStr) {
  diagnose(DiagnosticInfoInlineAsm(LocCookie, ErrorStr));
}

//===----------------------------------------------------------------------===//
// Metadata Kind Uniquing
//===----------------------------------------------------------------------===//

/// Return a unique non-zero ID for the specified metadata kind.
unsigned LLVMContext::getMDKindID(StringRef Name) const {
  // If this is new, assign it its ID.
  return pImpl->CustomMDKindNames.insert(
                                     std::make_pair(
                                         Name, pImpl->CustomMDKindNames.size()))
      .first->second;
}

/// getHandlerNames - Populate client-supplied smallvector using custom
/// metadata name and ID.
void LLVMContext::getMDKindNames(SmallVectorImpl<StringRef> &Names) const {
  Names.resize(pImpl->CustomMDKindNames.size());
  for (StringMap<unsigned>::const_iterator I = pImpl->CustomMDKindNames.begin(),
       E = pImpl->CustomMDKindNames.end(); I != E; ++I)
    Names[I->second] = I->first();
}

void LLVMContext::getOperandBundleTags(SmallVectorImpl<StringRef> &Tags) const {
  pImpl->getOperandBundleTags(Tags);
}

uint32_t LLVMContext::getOperandBundleTagID(StringRef Tag) const {
  return pImpl->getOperandBundleTagID(Tag);
}

void LLVMContext::setGC(const Function &Fn, std::string GCName) {
  auto It = pImpl->GCNames.find(&Fn);

  if (It == pImpl->GCNames.end()) {
    pImpl->GCNames.insert(std::make_pair(&Fn, std::move(GCName)));
    return;
  }
  It->second = std::move(GCName);
}
const std::string &LLVMContext::getGC(const Function &Fn) {
  return pImpl->GCNames[&Fn];
}
void LLVMContext::deleteGC(const Function &Fn) {
  pImpl->GCNames.erase(&Fn);
}

bool LLVMContext::shouldDiscardValueNames() const {
  return pImpl->DiscardValueNames;
}

void LLVMContext::setDiscardValueNames(bool Discard) {
  pImpl->DiscardValueNames = Discard;
}
<|endoftext|>


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2012 Chen-Pang He <jdh8@ms63.hinet.net>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "matrix_functions.h"

template<typename T>
void test2dRotation(double tol)
{
  Matrix<T,2,2> A, B, C;
  T angle, c, s;

  A << 0, 1, -1, 0;
  MatrixPower<Matrix<T,2,2> > Apow(A);

  for (int i=0; i<=20; ++i) {
    angle = pow(10, (i-10) / 5.);
    c = std::cos(angle);
    s = std::sin(angle);
    B << c, s, -s, c;

    C = Apow(std::ldexp(angle,1) / M_PI);
    std::cout << "test2dRotation: i = " << i << "   error powerm = " << relerr(C,B) << '\n';
    VERIFY(C.isApprox(B, tol));
  }
}

template<typename T>
void test2dHyperbolicRotation(double tol)
{
  Matrix<std::complex<T>,2,2> A, B, C;
  T angle, ch = std::cosh((T)1);
  std::complex<T> ish(0, std::sinh((T)1));

  A << ch, ish, -ish, ch;
  MatrixPower<Matrix<std::complex<T>,2,2> > Apow(A);

  for (int i=0; i<=20; ++i) {
    angle = std::ldexp(static_cast<T>(i-10), -1);
    ch = std::cosh(angle);
    ish = std::complex<T>(0, std::sinh(angle));
    B << ch, ish, -ish, ch;

    C = Apow(angle);
    std::cout << "test2dHyperbolicRotation: i = " << i << "   error powerm = " << relerr(C,B) << '\n';
    VERIFY(C.isApprox(B, tol));
  }
}

template<typename MatrixType>
void testExponentLaws(const MatrixType& m, double tol)
{
  typedef typename MatrixType::RealScalar RealScalar;
  MatrixType m1, m2, m3, m4, m5;
  RealScalar x, y;

  for (int i=0; i < g_repeat; ++i) {
    generateTestMatrix<MatrixType>::run(m1, m.rows());
    MatrixPower<MatrixType> mpow(m1);

    x = internal::random<RealScalar>();
    y = internal::random<RealScalar>();
    m2 = mpow(x);
    m3 = mpow(y);

    m4 = mpow(x+y);
    m5.noalias() = m2 * m3;
    VERIFY(m4.isApprox(m5, tol));

    m4 = mpow(x*y);
    m5 = m2.pow(y);
    VERIFY(m4.isApprox(m5, tol));

    m4 = (std::abs(x) * m1).pow(y);
    m5 = std::pow(std::abs(x), y) * m3;
    VERIFY(m4.isApprox(m5, tol));
  }
}

typedef Matrix<double,3,3,RowMajor>         Matrix3dRowMajor;
typedef Matrix<long double,Dynamic,Dynamic> MatrixXe;

void test_matrix_power()
{
  CALL_SUBTEST_2(test2dRotation<double>(1e-13));
  CALL_SUBTEST_1(test2dRotation<float>(2e-5));  // was 1e-5, relaxed for clang 2.8 / linux / x86-64
  CALL_SUBTEST_9(test2dRotation<long double>(1e-13));
  CALL_SUBTEST_2(test2dHyperbolicRotation<double>(1e-14));
  CALL_SUBTEST_1(test2dHyperbolicRotation<float>(1e-5));
  CALL_SUBTEST_9(test2dHyperbolicRotation<long double>(1e-14));

  CALL_SUBTEST_2(testExponentLaws(Matrix2d(),         1e-13));
  CALL_SUBTEST_7(testExponentLaws(Matrix3dRowMajor(), 1e-13));
  CALL_SUBTEST_3(testExponentLaws(Matrix4cd(),        1e-13));
  CALL_SUBTEST_4(testExponentLaws(MatrixXd(8,8),      2e-12));
  CALL_SUBTEST_1(testExponentLaws(Matrix2f(),         1e-4));
  CALL_SUBTEST_5(testExponentLaws(Matrix3cf(),        1e-4));
  CALL_SUBTEST_8(testExponentLaws(Matrix4f(),         1e-4));
  CALL_SUBTEST_6(testExponentLaws(MatrixXf(2,2),      1e-3)); // see bug 614
  CALL_SUBTEST_9(testExponentLaws(MatrixXe(7,7),      1e-13));
}
<commit_msg>Test power of singular matrices.<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2012 Chen-Pang He <jdh8@ms63.hinet.net>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "matrix_functions.h"

// for complex matrices, any matrix is fine
template<typename MatrixType, int IsComplex = NumTraits<typename internal::traits<MatrixType>::Scalar>::IsComplex>
struct generateSingularMatrix
{
  static void run(MatrixType& result, typename MatrixType::Index size)
  {
    result = MatrixType::Random(size, size);
    result.col(0).fill(0);
  }
};

// for real matrices, make sure none of the eigenvalues are negative
template<typename MatrixType>
struct generateSingularMatrix<MatrixType,0>
{
  static void run(MatrixType& result, typename MatrixType::Index size)
  {
    MatrixType mat = MatrixType::Random(size, size);
    mat.col(0).fill(0);
    ComplexSchur<MatrixType> schur(mat);
    typename ComplexSchur<MatrixType>::ComplexMatrixType T = schur.matrixT();

    for (typename MatrixType::Index i = 0; i < size; ++i) {
      if (T.coeff(i,i).imag() == 0 && T.coeff(i,i).real() < 0)
	T.coeffRef(i,i) = -T.coeff(i,i);
    }
    result = (schur.matrixU() * (T.template triangularView<Upper>() * schur.matrixU().adjoint())).real();
  }
};

template<typename T>
void test2dRotation(double tol)
{
  Matrix<T,2,2> A, B, C;
  T angle, c, s;

  A << 0, 1, -1, 0;
  MatrixPower<Matrix<T,2,2> > Apow(A);

  for (int i=0; i<=20; ++i) {
    angle = pow(10, (i-10) / 5.);
    c = std::cos(angle);
    s = std::sin(angle);
    B << c, s, -s, c;

    C = Apow(std::ldexp(angle,1) / M_PI);
    std::cout << "test2dRotation: i = " << i << "   error powerm = " << relerr(C,B) << '\n';
    VERIFY(C.isApprox(B, tol));
  }
}

template<typename T>
void test2dHyperbolicRotation(double tol)
{
  Matrix<std::complex<T>,2,2> A, B, C;
  T angle, ch = std::cosh((T)1);
  std::complex<T> ish(0, std::sinh((T)1));

  A << ch, ish, -ish, ch;
  MatrixPower<Matrix<std::complex<T>,2,2> > Apow(A);

  for (int i=0; i<=20; ++i) {
    angle = std::ldexp(static_cast<T>(i-10), -1);
    ch = std::cosh(angle);
    ish = std::complex<T>(0, std::sinh(angle));
    B << ch, ish, -ish, ch;

    C = Apow(angle);
    std::cout << "test2dHyperbolicRotation: i = " << i << "   error powerm = " << relerr(C,B) << '\n';
    VERIFY(C.isApprox(B, tol));
  }
}

template<typename MatrixType>
void testGeneral(const MatrixType& m, double tol)
{
  typedef typename MatrixType::RealScalar RealScalar;
  MatrixType m1, m2, m3, m4, m5;
  RealScalar x, y;

  for (int i=0; i < g_repeat; ++i) {
    generateTestMatrix<MatrixType>::run(m1, m.rows());
    MatrixPower<MatrixType> mpow(m1);

    x = internal::random<RealScalar>();
    y = internal::random<RealScalar>();
    m2 = mpow(x);
    m3 = mpow(y);

    m4 = mpow(x+y);
    m5.noalias() = m2 * m3;
    VERIFY(m4.isApprox(m5, tol));

    m4 = mpow(x*y);
    m5 = m2.pow(y);
    VERIFY(m4.isApprox(m5, tol));

    m4 = (std::abs(x) * m1).pow(y);
    m5 = std::pow(std::abs(x), y) * m3;
    VERIFY(m4.isApprox(m5, tol));
  }
}

template<typename MatrixType>
void testSingular(MatrixType m, double tol)
{
  typedef typename MatrixType::RealScalar RealScalar;
  MatrixType m1, m2, m3, m4, m5;
  RealScalar x, y;

  for (int i=0; i < g_repeat; ++i) {
    generateTestMatrix<MatrixType>::run(m1, m.rows());
    MatrixPower<MatrixType> mpow(m1);

    x = internal::random<RealScalar>(0, 1);
    y = internal::random<RealScalar>(0, 1);
    m2 = mpow(x);
    m3 = mpow(y);

    m4 = mpow(x+y);
    m5.noalias() = m2 * m3;
    VERIFY(m4.isApprox(m5, tol));

    m4 = mpow(x*y);
    m5 = m2.pow(y);
    VERIFY(m4.isApprox(m5, tol));

    m4 = (x * m1).pow(y);
    m5 = std::pow(x, y) * m3;
    VERIFY(m4.isApprox(m5, tol));
  }
}

typedef Matrix<double,3,3,RowMajor>         Matrix3dRowMajor;
typedef Matrix<long double,Dynamic,Dynamic> MatrixXe;

void test_matrix_power()
{
  CALL_SUBTEST_2(test2dRotation<double>(1e-13));
  CALL_SUBTEST_1(test2dRotation<float>(2e-5));  // was 1e-5, relaxed for clang 2.8 / linux / x86-64
  CALL_SUBTEST_9(test2dRotation<long double>(1e-13));
  CALL_SUBTEST_2(test2dHyperbolicRotation<double>(1e-14));
  CALL_SUBTEST_1(test2dHyperbolicRotation<float>(1e-5));
  CALL_SUBTEST_9(test2dHyperbolicRotation<long double>(1e-14));

  CALL_SUBTEST_2(testGeneral(Matrix2d(),         1e-13));
  CALL_SUBTEST_7(testGeneral(Matrix3dRowMajor(), 1e-13));
  CALL_SUBTEST_3(testGeneral(Matrix4cd(),        1e-13));
  CALL_SUBTEST_4(testGeneral(MatrixXd(8,8),      2e-12));
  CALL_SUBTEST_1(testGeneral(Matrix2f(),         1e-4));
  CALL_SUBTEST_5(testGeneral(Matrix3cf(),        1e-4));
  CALL_SUBTEST_8(testGeneral(Matrix4f(),         1e-4));
  CALL_SUBTEST_6(testGeneral(MatrixXf(2,2),      1e-3)); // see bug 614
  CALL_SUBTEST_9(testGeneral(MatrixXe(7,7),      1e-13));

  CALL_SUBTEST_2(testSingular(Matrix2d(),         1e-13));
  CALL_SUBTEST_7(testSingular(Matrix3dRowMajor(), 1e-13));
  CALL_SUBTEST_3(testSingular(Matrix4cd(),        1e-13));
  CALL_SUBTEST_4(testSingular(MatrixXd(8,8),      2e-12));
  CALL_SUBTEST_1(testSingular(Matrix2f(),         1e-4));
  CALL_SUBTEST_5(testSingular(Matrix3cf(),        1e-4));
  CALL_SUBTEST_8(testSingular(Matrix4f(),         1e-4));
  CALL_SUBTEST_6(testSingular(MatrixXf(2,2),      1e-3));
  CALL_SUBTEST_9(testSingular(MatrixXe(7,7),      1e-13));
}
<|endoftext|>


<commit_before>/*
Copyright (C) 2016-2018 Draios Inc dba Sysdig.

This file is part of falco.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/

#include "falco_outputs.h"

#include "config_falco.h"

#include "formats.h"
#include "logger.h"
#include "falco_output_queue.h"

using namespace std;
using namespace falco::output;

const static struct luaL_reg ll_falco_outputs [] =
{
	{"handle_http", &falco_outputs::handle_http},
	{"handle_grpc", &falco_outputs::handle_grpc},
	{NULL,NULL}
};

falco_outputs::falco_outputs(falco_engine *engine)
	: m_falco_engine(engine),
	  m_initialized(false),
	  m_buffered(true),
	  m_json_output(false),
	  m_time_format_iso_8601(false)
{

}

falco_outputs::~falco_outputs()
{
	// Note: The assert()s in this destructor were previously places where
	//       exceptions were thrown.  C++11 doesn't allow destructors to
	//       emit exceptions; if they're thrown, they'll trigger a call
	//       to 'terminate()'.  To maintain similar behavior, the exceptions
	//       were replace with calls to 'assert()'
	if(m_initialized)
	{
		lua_getglobal(m_ls, m_lua_output_cleanup.c_str());

		if(!lua_isfunction(m_ls, -1))
		{
			falco_logger::log(LOG_ERR, std::string("No function ") + m_lua_output_cleanup + " found. ");
			assert(nullptr == "Missing lua cleanup function in ~falco_outputs");
		}

		if(lua_pcall(m_ls, 0, 0, 0) != 0)
		{
			const char* lerr = lua_tostring(m_ls, -1);
			falco_logger::log(LOG_ERR, std::string("lua_pcall failed, err: ") + lerr);
			assert(nullptr == "lua_pcall failed in ~falco_outputs");
		}
	}
}

void falco_outputs::init(bool json_output,
			 bool json_include_output_property,
			 uint32_t rate, uint32_t max_burst, bool buffered,
			 bool time_format_iso_8601)
{
	// The engine must have been given an inspector by now.
	if(! m_inspector)
	{
		throw falco_exception("No inspector provided");
	}

	m_json_output = json_output;

	falco_common::init(m_lua_main_filename.c_str(), FALCO_SOURCE_LUA_DIR);

	// Note that falco_formats is added to both the lua state used
	// by the falco engine as well as the separate lua state used
	// by falco outputs.
	falco_formats::init(m_inspector, m_falco_engine, m_ls, json_output, json_include_output_property);

	falco_logger::init(m_ls);

	luaL_openlib(m_ls, "c_outputs", ll_falco_outputs, 0);

	m_notifications_tb.init(rate, max_burst);

	m_buffered = buffered;
	m_time_format_iso_8601 = time_format_iso_8601;

	m_initialized = true;
}

void falco_outputs::add_output(output_config oc)
{
	uint8_t nargs = 3;
	lua_getglobal(m_ls, m_lua_add_output.c_str());

	if(!lua_isfunction(m_ls, -1))
	{
		throw falco_exception("No function " + m_lua_add_output + " found. ");
	}
	lua_pushstring(m_ls, oc.name.c_str());
	lua_pushnumber(m_ls, (m_buffered ? 1 : 0));
	lua_pushnumber(m_ls, (m_time_format_iso_8601 ? 1 : 0));

	// If we have options, build up a lua table containing them
	if (oc.options.size())
	{
		nargs = 4;
		lua_createtable(m_ls, 0, oc.options.size());

		for (auto it = oc.options.cbegin(); it != oc.options.cend(); ++it)
		{
			lua_pushstring(m_ls, (*it).second.c_str());
			lua_setfield(m_ls, -2, (*it).first.c_str());
		}
	}

	if(lua_pcall(m_ls, nargs, 0, 0) != 0)
	{
		const char* lerr = lua_tostring(m_ls, -1);
		throw falco_exception(string(lerr));
	}

}

void falco_outputs::handle_event(gen_event *ev, string &rule, string &source,
				 falco_common::priority_type priority, string &format)
{
	if(!m_notifications_tb.claim())
	{
		falco_logger::log(LOG_DEBUG, "Skipping rate-limited notification for rule " + rule + "\n");
		return;
	}

	lua_getglobal(m_ls, m_lua_output_event.c_str());

	if(lua_isfunction(m_ls, -1))
	{
		lua_pushlightuserdata(m_ls, ev);
		lua_pushstring(m_ls, rule.c_str());
		lua_pushstring(m_ls, source.c_str());
		lua_pushstring(m_ls, falco_common::priority_names[priority].c_str());
		lua_pushnumber(m_ls, priority);
		lua_pushstring(m_ls, format.c_str());

		if(lua_pcall(m_ls, 6, 0, 0) != 0)
		{
			const char* lerr = lua_tostring(m_ls, -1);
			string err = "Error invoking function output: " + string(lerr);
			throw falco_exception(err);
		}
	}
	else
	{
		throw falco_exception("No function " + m_lua_output_event + " found in lua compiler module");
	}

}

void falco_outputs::handle_msg(uint64_t now,
			       falco_common::priority_type priority,
			       std::string &msg,
			       std::string &rule,
			       std::map<std::string,std::string> &output_fields)
{
	std::string full_msg;

	if(m_json_output)
	{
		nlohmann::json jmsg;

		// Convert the time-as-nanoseconds to a more json-friendly ISO8601.
		time_t evttime = now/1000000000;
		char time_sec[20]; // sizeof "YYYY-MM-DDTHH:MM:SS"
		char time_ns[12]; // sizeof ".sssssssssZ"
		string iso8601evttime;

		strftime(time_sec, sizeof(time_sec), "%FT%T", gmtime(&evttime));
		snprintf(time_ns, sizeof(time_ns), ".%09luZ", now % 1000000000);
		iso8601evttime = time_sec;
		iso8601evttime += time_ns;

		jmsg["output"] = msg;
		jmsg["priority"] = "Critical";
		jmsg["rule"] = rule;
		jmsg["time"] = iso8601evttime;
		jmsg["output_fields"] = output_fields;

		full_msg = jmsg.dump();
	}
	else
	{
		std::string timestr;
		bool first = true;

		sinsp_utils::ts_to_string(now, &timestr, false, true);
		full_msg = timestr + ": " + falco_common::priority_names[LOG_CRIT] + " " + msg + " (";
		for(auto &pair : output_fields)
		{
			if(first)
			{
				first = false;
			}
			else
			{
				full_msg += " ";
			}
			full_msg += pair.first + "=" + pair.second;
		}
		full_msg += ")";
	}

	lua_getglobal(m_ls, m_lua_output_msg.c_str());

	if(lua_isfunction(m_ls, -1))
	{
		lua_pushstring(m_ls, full_msg.c_str());
		lua_pushstring(m_ls, falco_common::priority_names[priority].c_str());
		lua_pushnumber(m_ls, priority);

		if(lua_pcall(m_ls, 3, 0, 0) != 0)
		{
			const char* lerr = lua_tostring(m_ls, -1);
			string err = "Error invoking function output: " + string(lerr);
			throw falco_exception(err);
		}
	}
	else
	{
		throw falco_exception("No function " + m_lua_output_msg + " found in lua compiler module");
	}

}

void falco_outputs::reopen_outputs()
{
	lua_getglobal(m_ls, m_lua_output_reopen.c_str());

	if(!lua_isfunction(m_ls, -1))
	{
		throw falco_exception("No function " + m_lua_output_reopen + " found. ");
	}

	if(lua_pcall(m_ls, 0, 0, 0) != 0)
	{
		const char* lerr = lua_tostring(m_ls, -1);
		throw falco_exception(string(lerr));
	}
}

int falco_outputs::handle_http(lua_State *ls)
{
	CURL *curl = NULL;
	CURLcode res = CURLE_FAILED_INIT;
	struct curl_slist *slist1;
	slist1 = NULL;

	if (!lua_isstring(ls, -1) ||
	    !lua_isstring(ls, -2))
	{
		lua_pushstring(ls, "Invalid arguments passed to handle_http()");
		lua_error(ls);
	}

	string url = (char *) lua_tostring(ls, 1);
	string msg = (char *) lua_tostring(ls, 2);

	curl = curl_easy_init();
	if(curl)
	{
		slist1 = curl_slist_append(slist1, "Content-Type: application/json");
		curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist1);
		curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
		curl_easy_setopt(curl, CURLOPT_POSTFIELDS, msg.c_str());
		curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, -1L);

		res = curl_easy_perform(curl);

		if(res != CURLE_OK) {
			falco_logger::log(LOG_ERR,"libcurl error: " + string(curl_easy_strerror(res)));
		}
		curl_easy_cleanup(curl);
		curl = NULL;
		curl_slist_free_all(slist1);
  		slist1 = NULL;
	}
	return 1;
}

// TODO(fntlnz, leodido): verify if this works with k8s_audit as source
int falco_outputs::handle_grpc(lua_State *ls)
{
	response grpc_res = response();
	// TODO(fntlnz, leodido): do the checks and make sure all the fields are sent
	// fixme > check parameters later
	// if(!lua_isstring(ls, -1) ||
	//    !lua_isstring(ls, -2))
	// {
	// 	lua_pushstring(ls, "Invalid arguments passed to handle_grpc()");
	// 	lua_error(ls);
	// }

	// todo(leodido, fntlnz) > pass the ID (?)
	// grpc_res.set_id("...");

	// rule
	grpc_res.set_rule((char *)lua_tostring(ls, 2));

	// priority
	priority p = priority::EMERGENCY;
	string pstr = (char *)lua_tostring(ls, 4);
	if(!priority_Parse(pstr, &p))
	{
		lua_pushstring(ls, "Unknown priority passed to to handle_grpc()");
		lua_error(ls);
	}
	grpc_res.set_priority(p);

	// output
	grpc_res.set_output((char *)lua_tostring(ls, 5));

	// output fields
	auto& fields = *grpc_res.mutable_output_fields();

	lua_pushnil(ls);
	while (lua_next(ls, 6) != 0) {
		fields[lua_tostring(ls, -2)] = lua_tostring(ls, -1);
		lua_pop(ls, 1);
	}

	falco_output_queue::get().push(grpc_res);

	return 1;
}<commit_msg>new(usespace/falco): transmit output sources<commit_after>/*
Copyright (C) 2016-2018 Draios Inc dba Sysdig.

This file is part of falco.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/

#include "falco_outputs.h"

#include "config_falco.h"

#include "formats.h"
#include "logger.h"
#include "falco_output_queue.h"

using namespace std;
using namespace falco::output;

const static struct luaL_reg ll_falco_outputs [] =
{
	{"handle_http", &falco_outputs::handle_http},
	{"handle_grpc", &falco_outputs::handle_grpc},
	{NULL,NULL}
};

falco_outputs::falco_outputs(falco_engine *engine)
	: m_falco_engine(engine),
	  m_initialized(false),
	  m_buffered(true),
	  m_json_output(false),
	  m_time_format_iso_8601(false)
{

}

falco_outputs::~falco_outputs()
{
	// Note: The assert()s in this destructor were previously places where
	//       exceptions were thrown.  C++11 doesn't allow destructors to
	//       emit exceptions; if they're thrown, they'll trigger a call
	//       to 'terminate()'.  To maintain similar behavior, the exceptions
	//       were replace with calls to 'assert()'
	if(m_initialized)
	{
		lua_getglobal(m_ls, m_lua_output_cleanup.c_str());

		if(!lua_isfunction(m_ls, -1))
		{
			falco_logger::log(LOG_ERR, std::string("No function ") + m_lua_output_cleanup + " found. ");
			assert(nullptr == "Missing lua cleanup function in ~falco_outputs");
		}

		if(lua_pcall(m_ls, 0, 0, 0) != 0)
		{
			const char* lerr = lua_tostring(m_ls, -1);
			falco_logger::log(LOG_ERR, std::string("lua_pcall failed, err: ") + lerr);
			assert(nullptr == "lua_pcall failed in ~falco_outputs");
		}
	}
}

void falco_outputs::init(bool json_output,
			 bool json_include_output_property,
			 uint32_t rate, uint32_t max_burst, bool buffered,
			 bool time_format_iso_8601)
{
	// The engine must have been given an inspector by now.
	if(! m_inspector)
	{
		throw falco_exception("No inspector provided");
	}

	m_json_output = json_output;

	falco_common::init(m_lua_main_filename.c_str(), FALCO_SOURCE_LUA_DIR);

	// Note that falco_formats is added to both the lua state used
	// by the falco engine as well as the separate lua state used
	// by falco outputs.
	falco_formats::init(m_inspector, m_falco_engine, m_ls, json_output, json_include_output_property);

	falco_logger::init(m_ls);

	luaL_openlib(m_ls, "c_outputs", ll_falco_outputs, 0);

	m_notifications_tb.init(rate, max_burst);

	m_buffered = buffered;
	m_time_format_iso_8601 = time_format_iso_8601;

	m_initialized = true;
}

void falco_outputs::add_output(output_config oc)
{
	uint8_t nargs = 3;
	lua_getglobal(m_ls, m_lua_add_output.c_str());

	if(!lua_isfunction(m_ls, -1))
	{
		throw falco_exception("No function " + m_lua_add_output + " found. ");
	}
	lua_pushstring(m_ls, oc.name.c_str());
	lua_pushnumber(m_ls, (m_buffered ? 1 : 0));
	lua_pushnumber(m_ls, (m_time_format_iso_8601 ? 1 : 0));

	// If we have options, build up a lua table containing them
	if (oc.options.size())
	{
		nargs = 4;
		lua_createtable(m_ls, 0, oc.options.size());

		for (auto it = oc.options.cbegin(); it != oc.options.cend(); ++it)
		{
			lua_pushstring(m_ls, (*it).second.c_str());
			lua_setfield(m_ls, -2, (*it).first.c_str());
		}
	}

	if(lua_pcall(m_ls, nargs, 0, 0) != 0)
	{
		const char* lerr = lua_tostring(m_ls, -1);
		throw falco_exception(string(lerr));
	}

}

void falco_outputs::handle_event(gen_event *ev, string &rule, string &source,
				 falco_common::priority_type priority, string &format)
{
	if(!m_notifications_tb.claim())
	{
		falco_logger::log(LOG_DEBUG, "Skipping rate-limited notification for rule " + rule + "\n");
		return;
	}

	lua_getglobal(m_ls, m_lua_output_event.c_str());

	if(lua_isfunction(m_ls, -1))
	{
		lua_pushlightuserdata(m_ls, ev);
		lua_pushstring(m_ls, rule.c_str());
		lua_pushstring(m_ls, source.c_str());
		lua_pushstring(m_ls, falco_common::priority_names[priority].c_str());
		lua_pushnumber(m_ls, priority);
		lua_pushstring(m_ls, format.c_str());

		if(lua_pcall(m_ls, 6, 0, 0) != 0)
		{
			const char* lerr = lua_tostring(m_ls, -1);
			string err = "Error invoking function output: " + string(lerr);
			throw falco_exception(err);
		}
	}
	else
	{
		throw falco_exception("No function " + m_lua_output_event + " found in lua compiler module");
	}

}

void falco_outputs::handle_msg(uint64_t now,
			       falco_common::priority_type priority,
			       std::string &msg,
			       std::string &rule,
			       std::map<std::string,std::string> &output_fields)
{
	std::string full_msg;

	if(m_json_output)
	{
		nlohmann::json jmsg;

		// Convert the time-as-nanoseconds to a more json-friendly ISO8601.
		time_t evttime = now/1000000000;
		char time_sec[20]; // sizeof "YYYY-MM-DDTHH:MM:SS"
		char time_ns[12]; // sizeof ".sssssssssZ"
		string iso8601evttime;

		strftime(time_sec, sizeof(time_sec), "%FT%T", gmtime(&evttime));
		snprintf(time_ns, sizeof(time_ns), ".%09luZ", now % 1000000000);
		iso8601evttime = time_sec;
		iso8601evttime += time_ns;

		jmsg["output"] = msg;
		jmsg["priority"] = "Critical";
		jmsg["rule"] = rule;
		jmsg["time"] = iso8601evttime;
		jmsg["output_fields"] = output_fields;

		full_msg = jmsg.dump();
	}
	else
	{
		std::string timestr;
		bool first = true;

		sinsp_utils::ts_to_string(now, &timestr, false, true);
		full_msg = timestr + ": " + falco_common::priority_names[LOG_CRIT] + " " + msg + " (";
		for(auto &pair : output_fields)
		{
			if(first)
			{
				first = false;
			}
			else
			{
				full_msg += " ";
			}
			full_msg += pair.first + "=" + pair.second;
		}
		full_msg += ")";
	}

	lua_getglobal(m_ls, m_lua_output_msg.c_str());

	if(lua_isfunction(m_ls, -1))
	{
		lua_pushstring(m_ls, full_msg.c_str());
		lua_pushstring(m_ls, falco_common::priority_names[priority].c_str());
		lua_pushnumber(m_ls, priority);

		if(lua_pcall(m_ls, 3, 0, 0) != 0)
		{
			const char* lerr = lua_tostring(m_ls, -1);
			string err = "Error invoking function output: " + string(lerr);
			throw falco_exception(err);
		}
	}
	else
	{
		throw falco_exception("No function " + m_lua_output_msg + " found in lua compiler module");
	}

}

void falco_outputs::reopen_outputs()
{
	lua_getglobal(m_ls, m_lua_output_reopen.c_str());

	if(!lua_isfunction(m_ls, -1))
	{
		throw falco_exception("No function " + m_lua_output_reopen + " found. ");
	}

	if(lua_pcall(m_ls, 0, 0, 0) != 0)
	{
		const char* lerr = lua_tostring(m_ls, -1);
		throw falco_exception(string(lerr));
	}
}

int falco_outputs::handle_http(lua_State *ls)
{
	CURL *curl = NULL;
	CURLcode res = CURLE_FAILED_INIT;
	struct curl_slist *slist1;
	slist1 = NULL;

	if (!lua_isstring(ls, -1) ||
	    !lua_isstring(ls, -2))
	{
		lua_pushstring(ls, "Invalid arguments passed to handle_http()");
		lua_error(ls);
	}

	string url = (char *) lua_tostring(ls, 1);
	string msg = (char *) lua_tostring(ls, 2);

	curl = curl_easy_init();
	if(curl)
	{
		slist1 = curl_slist_append(slist1, "Content-Type: application/json");
		curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist1);
		curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
		curl_easy_setopt(curl, CURLOPT_POSTFIELDS, msg.c_str());
		curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, -1L);

		res = curl_easy_perform(curl);

		if(res != CURLE_OK) {
			falco_logger::log(LOG_ERR,"libcurl error: " + string(curl_easy_strerror(res)));
		}
		curl_easy_cleanup(curl);
		curl = NULL;
		curl_slist_free_all(slist1);
  		slist1 = NULL;
	}
	return 1;
}

// TODO(fntlnz, leodido): verify if this works with k8s_audit as source
int falco_outputs::handle_grpc(lua_State *ls)
{
	response grpc_res = response();
	// TODO(fntlnz, leodido): do the checks and make sure all the fields are sent
	// fixme > check parameters later
	// if(!lua_isstring(ls, -1) ||
	//    !lua_isstring(ls, -2))
	// {
	// 	lua_pushstring(ls, "Invalid arguments passed to handle_grpc()");
	// 	lua_error(ls);
	// }

	// todo(leodido, fntlnz) > pass the ID (?)
	// grpc_res.set_id("...");

	// rule
	grpc_res.set_rule((char *)lua_tostring(ls, 2));

	// source
	source s = source::SYSCALL;
	string sstr = (char *)lua_tostring(ls, 3);
	if(!source_Parse(sstr, &s))
	{
		lua_pushstring(ls, "Unknown source passed to to handle_grpc()");
		lua_error(ls);
	}
	grpc_res.set_source(s);

	// priority
	priority p = priority::EMERGENCY;
	string pstr = (char *)lua_tostring(ls, 4);
	if(!priority_Parse(pstr, &p))
	{
		lua_pushstring(ls, "Unknown priority passed to to handle_grpc()");
		lua_error(ls);
	}
	grpc_res.set_priority(p);

	// output
	grpc_res.set_output((char *)lua_tostring(ls, 5));

	// output fields
	auto& fields = *grpc_res.mutable_output_fields();

	lua_pushnil(ls);
	while (lua_next(ls, 6) != 0) {
		fields[lua_tostring(ls, -2)] = lua_tostring(ls, -1);
		lua_pop(ls, 1);
	}

	falco_output_queue::get().push(grpc_res);

	return 1;
}<|endoftext|>


<commit_before>//
// Copyright (c) .NET Foundation and Contributors
// See LICENSE file in the project root for full license information.
//

#include "nf_hardware_stm32_native.h"

HRESULT Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_BackupMemory::
    ReadBytes___STATIC__VOID__U4__SZARRAY_U1(CLR_RT_StackFrame &stack)
{
    NANOCLR_HEADER();

    uint32_t position = stack.Arg0().NumericByRef().u4;

    // dereference the data buffer from the argument
    CLR_RT_HeapBlock_Array *buffer = stack.Arg1().DereferenceArray();
    // get a the pointer to the byffer by using the first element of the array
    uint8_t *data = buffer->GetFirstElement();
    // get the length of the data buffer
    uint32_t dataLength = buffer->m_numOfElements;

    // address of bkp register 0
    __IO uint32_t *baseAddress = &(RTC->BKP0R);
    uint8_t *storeAddress = ((uint8_t *)baseAddress + position);
    uint32_t *registerAddress = NULL;
    uint32_t tempRegisterValue;
    uint32_t counter = 0;
    uint32_t remainder;
    int32_t index = 3;

    // sanity check for out of range position
    if (position > (BACKUP_SIZE - 1))
        NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);

    // sanity check for over sized data buffer
    if ((position + dataLength) > BACKUP_SIZE)
        NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);

    // check if the store address is starting at a register address boundary
    remainder = (uint32_t)((uint32_t *)storeAddress) % sizeof(RTC_BKP0R_Msk);

    if (remainder > 0)
    {
        // read register
        registerAddress = (uint32_t *)(storeAddress - remainder);
        tempRegisterValue = *registerAddress;

        // adjust remainder to the amount of bytes to move
        remainder = 4 - remainder;

        do
        {
            *data = (uint8_t)(tempRegisterValue >> ((remainder - 1) * 8));
            data++;
            remainder--;
            counter++;
        } while (remainder && (counter < dataLength));
        registerAddress++;
    }

    // keep reading into the buffer if there enough bytes
    if ((dataLength - counter) >= 4)
    {
        // load register
        tempRegisterValue = *registerAddress;

        do
        {
            *data = (uint8_t)(tempRegisterValue >> (index-- * 8));
            data++;
            counter++;

            if (index < 0)
            {
                index = 3;
                registerAddress++;

                // is there enough data in buffer for another round
                if ((dataLength - counter) < 4)
                {
                    // no, exit loop
                    break;
                }

                // load register
                tempRegisterValue = *registerAddress;
            }
        } while (1);
    }

    // now read the remaining bytes, if any
    if ((dataLength - counter) > 0)
    {
        remainder = dataLength - counter;

        // read register
        tempRegisterValue = *registerAddress;

        // adjust remainder to the amount of bytes to move
        remainder = 4 - remainder;

        do
        {
            *data = (uint8_t)(tempRegisterValue >> (remainder * 8));
            remainder--;
            data++;
            counter++;
        } while (remainder);
    }

    NANOCLR_NOCLEANUP();
}

HRESULT Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_BackupMemory::
    WriteBytes___STATIC__VOID__U4__SZARRAY_U1(CLR_RT_StackFrame &stack)
{
    NANOCLR_HEADER();

    // get position to write to
    uint32_t position = stack.Arg0().NumericByRef().u4;

    // dereference the data buffer from the argument
    CLR_RT_HeapBlock_Array *buffer = stack.Arg1().DereferenceArray();
    // get a the pointer to the byffer by using the first element of the array
    uint8_t *data = buffer->GetFirstElement();
    // get the length of the data buffer
    uint32_t dataLength = buffer->m_numOfElements;

    // address of bkp register 0
    __IO uint32_t *baseAddress = &(RTC->BKP0R);
    uint8_t *storeAddress = ((uint8_t *)baseAddress + position);
    uint32_t *registerAddress = NULL;
    uint32_t tempRegisterValue;
    uint32_t counter = 0;
    uint32_t remainder;
    int32_t index = 3;

    // sanity check for out of range position
    if (position > (BACKUP_SIZE - 1))
        NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);

    // sanity check for over sized data buffer
    if ((position + dataLength) > BACKUP_SIZE)
        NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);

    // write has to be done register wide, so if a write address is "in the middle" of a register, need to read it first
    // and overwrite as required this can happen at the begining and/or at the end of the buffer

    // check if the store address is starting at a register address boundary
    remainder = (uint32_t)((uint32_t *)storeAddress) % sizeof(RTC_BKP0R_Msk);

    if (remainder > 0)
    {
        // read register
        registerAddress = (uint32_t *)(storeAddress - remainder);
        tempRegisterValue = *registerAddress;

        // adjust remainder to the amount of bytes to move
        remainder = 4 - remainder;

        // clear the bytes we'll be filling
        tempRegisterValue &= (uint32_t)(0xFFFFFF00 << ((remainder - 1) * 8));

        do
        {
            tempRegisterValue |= (uint32_t)((uint32_t)*data << ((remainder - 1) * 8));
            remainder--;
            data++;
            counter++;
        } while (remainder && (counter < dataLength));

        // write back register
        *registerAddress = tempRegisterValue;
        registerAddress++;
    }

    // keep processing the buffer if there enough bytes
    if ((dataLength - counter) >= 4)
    {
        // clear register
        *registerAddress = 0;

        do
        {
            *registerAddress |= (uint32_t)((uint32_t)*data << (index-- * 8));
            data++;
            counter++;

            if (index < 0)
            {
                index = 3;
                registerAddress++;

                // is there enough data in buffer for another round
                if ((dataLength - counter) < 4)
                {
                    // no, exit loop
                    break;
                }

                // clear register
                *registerAddress = 0;
            }
        } while (1);
    }

    // take care of the remaining bytes, if any
    if ((dataLength - counter) > 0)
    {
        remainder = dataLength - counter;

        // read register
        tempRegisterValue = *registerAddress;

        // clear the bytes we'll be filling
        tempRegisterValue &= (uint32_t)(0x00FFFFFF >> ((remainder - 1) * 8));

        // adjust remainder to the amount of bytes to move
        remainder = 4 - remainder;

        do
        {
            tempRegisterValue |= (uint32_t)((uint32_t)*data << (remainder * 8));
            remainder--;
            data++;
            counter++;
        } while (remainder);

        // write back register
        *registerAddress = tempRegisterValue;
    }

    NANOCLR_NOCLEANUP();
}

HRESULT Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_BackupMemory::GetSize___STATIC__I4(
    CLR_RT_StackFrame &stack)
{
    NANOCLR_HEADER();

    stack.SetResult_I4(BACKUP_SIZE);

    NANOCLR_NOCLEANUP_NOLABEL();
}
<commit_msg>Corrected some position combinations when R/W to backup memory (#1978)<commit_after>//
// Copyright (c) .NET Foundation and Contributors
// See LICENSE file in the project root for full license information.
//

#include "nf_hardware_stm32_native.h"

HRESULT Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_BackupMemory::
    ReadBytes___STATIC__VOID__U4__SZARRAY_U1(CLR_RT_StackFrame &stack)
{
    NANOCLR_HEADER();

    uint32_t position = stack.Arg0().NumericByRef().u4;

    // dereference the data buffer from the argument
    CLR_RT_HeapBlock_Array *buffer = stack.Arg1().DereferenceArray();
    // get a the pointer to the byffer by using the first element of the array
    uint8_t *data = buffer->GetFirstElement();
    // get the length of the data buffer
    uint32_t dataLength = buffer->m_numOfElements;

    // address of bkp register 0
    __IO uint32_t *baseAddress = &(RTC->BKP0R);
    uint8_t *storeAddress = ((uint8_t *)baseAddress + position);
    uint32_t *registerAddress = NULL;
    uint32_t tempRegisterValue;
    uint32_t counter = 0;
    uint32_t remainder;
    int32_t index = 3;

    // sanity check for out of range position
    if (position > (BACKUP_SIZE - 1))
        NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);

    // sanity check for over sized data buffer
    if ((position + dataLength) > BACKUP_SIZE)
        NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);

    // check if the store address is starting at a register address boundary
    remainder = (uint32_t)((uint32_t *)storeAddress) % sizeof(RTC_BKP0R_Msk);
    registerAddress = (uint32_t *)(storeAddress - remainder);

    if (remainder > 0)
    {
        // read register
        tempRegisterValue = *registerAddress;

        // adjust remainder to the amount of bytes to move
        remainder = 4 - remainder;

        do
        {
            *data = (uint8_t)(tempRegisterValue >> ((remainder - 1) * 8));
            data++;
            remainder--;
            counter++;
        } while (remainder && (counter < dataLength));
        registerAddress++;
    }

    // keep reading into the buffer if there enough bytes
    if ((dataLength - counter) >= 4)
    {
        // load register
        tempRegisterValue = *registerAddress;

        do
        {
            *data = (uint8_t)(tempRegisterValue >> (index-- * 8));
            data++;
            counter++;

            if (index < 0)
            {
                index = 3;
                registerAddress++;

                // is there enough data in buffer for another round
                if ((dataLength - counter) < 4)
                {
                    // no, exit loop
                    break;
                }

                // load register
                tempRegisterValue = *registerAddress;
            }
        } while (1);
    }

    // now read the remaining bytes, if any
    if ((dataLength - counter) > 0)
    {
        remainder = dataLength - counter;

        // read register
        tempRegisterValue = *registerAddress;

        int offset = 3;
        do
        {
            *data = (uint8_t)(tempRegisterValue >> (offset * 8));
            remainder--;
            data++;
            counter++;
            offset--;
        } while (remainder);
    }

    NANOCLR_NOCLEANUP();
}

HRESULT Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_BackupMemory::
    WriteBytes___STATIC__VOID__U4__SZARRAY_U1(CLR_RT_StackFrame &stack)
{
    NANOCLR_HEADER();

    // get position to write to
    uint32_t position = stack.Arg0().NumericByRef().u4;

    // dereference the data buffer from the argument
    CLR_RT_HeapBlock_Array *buffer = stack.Arg1().DereferenceArray();
    // get a the pointer to the byffer by using the first element of the array
    uint8_t *data = buffer->GetFirstElement();
    // get the length of the data buffer
    uint32_t dataLength = buffer->m_numOfElements;

    // address of bkp register 0
    __IO uint32_t *baseAddress = &(RTC->BKP0R);
    uint8_t *storeAddress = ((uint8_t *)baseAddress + position);
    uint32_t *registerAddress = NULL;
    uint32_t tempRegisterValue;
    uint32_t counter = 0;
    uint32_t remainder;
    int32_t index = 3;
    uint32_t tempMask, tempLen;

    // sanity check for out of range position
    if (position > (BACKUP_SIZE - 1))
        NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);

    // sanity check for over sized data buffer
    if ((position + dataLength) > BACKUP_SIZE)
        NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);

    // write has to be done register wide, so if a write address is "in the middle" of a register, need to read it first
    // and overwrite as required this can happen at the begining and/or at the end of the buffer

    // check if the store address is starting at a register address boundary
    remainder = (uint32_t)((uint32_t *)storeAddress) % sizeof(RTC_BKP0R_Msk);
    registerAddress = (uint32_t *)(storeAddress - remainder);

    if (remainder > 0)
    {
        // read register
        tempRegisterValue = *registerAddress;

        // adjust remainder to the amount of bytes to move
        remainder = 4 - remainder;

        // clear the bytes we'll be filling
        tempMask = 0x00000000;
        tempLen = (dataLength > 2) ? 3 : (dataLength > 1) ? 2 : 1;
        for (int i = remainder - 1; i >= 0 && tempLen > 0; i--, tempLen--)
        {
            tempMask |= (uint32_t)(0x000000FF << (i * 8));
        }

        tempRegisterValue &= ~tempMask;

        do
        {
            tempRegisterValue |= (uint32_t)((uint32_t)*data << ((remainder - 1) * 8));
            remainder--;
            data++;
            counter++;
        } while (remainder && (counter < dataLength));

        // write back register
        *registerAddress = tempRegisterValue;
        registerAddress++;
    }

    // keep processing the buffer if there enough bytes
    if ((dataLength - counter) >= 4)
    {
        // clear register
        *registerAddress = 0;

        do
        {
            *registerAddress |= (uint32_t)((uint32_t)*data << (index-- * 8));
            data++;
            counter++;

            if (index < 0)
            {
                index = 3;
                registerAddress++;

                // is there enough data in buffer for another round
                if ((dataLength - counter) < 4)
                {
                    // no, exit loop
                    break;
                }

                // clear register
                *registerAddress = 0;
            }
        } while (1);
    }

    // take care of the remaining bytes, if any
    if ((dataLength - counter) > 0)
    {
        remainder = dataLength - counter;

        // read register
        tempRegisterValue = *registerAddress;

        // clear the bytes we'll be filling
        tempRegisterValue &= (uint32_t)(0x00FFFFFF >> ((remainder - 1) * 8));

        // adjust remainder to the amount of bytes to move
        remainder = 4 - remainder;

        int offset = 3;
        do
        {
            tempRegisterValue |= (uint32_t)((uint32_t)*data << (offset * 8));
            remainder--;
            data++;
            counter++;
            offset--;
        } while (remainder);

        // write back register
        *registerAddress = tempRegisterValue;
    }

    NANOCLR_NOCLEANUP();
}

HRESULT Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_BackupMemory::GetSize___STATIC__I4(
    CLR_RT_StackFrame &stack)
{
    NANOCLR_HEADER();

    stack.SetResult_I4(BACKUP_SIZE);

    NANOCLR_NOCLEANUP_NOLABEL();
}
<|endoftext|>


<commit_before>// Copyright 2013 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <vector>
#include <algorithm>

#include <Observation.hpp>
#include <utils.hpp>

#ifndef BINS_HPP
#define BINS_HPP

namespace PulsarSearch {

template< typename T > std::vector< unsigned int > * getNrSamplesPerBin(const AstroData::Observation< T > & obs);

// Implementation
template< typename T > std::vector< unsigned int > * getNrSamplesPerBin(const AstroData::Observation< T > & obs) {
  std::vector< unsigned int > * samplesPerBin = new std::vector< unsigned int >(obs.getNrPeriods() * obs.getNrBins() * isa::utils::pad(2, obs.getPadding()));

	for ( unsigned int period = 0; period < obs.getNrPeriods(); period++ ) {
		unsigned int offset = 0;
    std::vector< unsigned int > itemsPerBin;
    std::vector< unsigned int > offsetPerBin;

    std::fill(itemsPerBin.begin(), itemsPerBin.end(), 0);
    std::fill(offsetPerBin.begin(), offsetPerBin.end(), 0);
    for ( unsigned int i = 0; i < period; i++ ) {
      float samplePhase = (i / period);

      for ( unsigned int bin = 0; bin < obs.getNrBins(); bin++ ) {
        if ( samplePhase - ((bin + 0.5) / obs.getNrBins()) < 1.0f / obs.getNrBins() ) {
          itemsPerBin[bin] += 1;
          break;
        }
      }
    }

		for ( unsigned int bin = 0; bin < obs.getNrBins(); bin++ ) {
      samplesPerBin->at((period * obs.getNrBins() * pad(2, obs.getPadding())) + (bin * pad(2, obs.getPadding()))) = itemsPerBin[bin];
      samplesPerBin->at((period * obs.getNrBins() * pad(2, obs.getPadding())) + (bin * pad(2, obs.getPadding())) + 1) = offset;
      offset += itemsPerBin[bin];
    }
	}

	return samplesPerBin;
}

} // PulsarSearch

#endif // BINS_HPP
<commit_msg>Forgot that vectors do not allocate memory if you add elements using [].<commit_after>// Copyright 2013 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <vector>
#include <algorithm>

#include <Observation.hpp>
#include <utils.hpp>

#ifndef BINS_HPP
#define BINS_HPP

namespace PulsarSearch {

template< typename T > std::vector< unsigned int > * getNrSamplesPerBin(const AstroData::Observation< T > & obs);

// Implementation
template< typename T > std::vector< unsigned int > * getNrSamplesPerBin(const AstroData::Observation< T > & obs) {
  std::vector< unsigned int > * samplesPerBin = new std::vector< unsigned int >(obs.getNrPeriods() * obs.getNrBins() * isa::utils::pad(2, obs.getPadding()));

	for ( unsigned int period = 0; period < obs.getNrPeriods(); period++ ) {
		unsigned int offset = 0;
    std::vector< unsigned int > itemsPerBin(obs.getNrBins());
    std::vector< unsigned int > offsetPerBin(obs.getNrBins());

    std::fill(itemsPerBin.begin(), itemsPerBin.end(), 0);
    std::fill(offsetPerBin.begin(), offsetPerBin.end(), 0);
    for ( unsigned int i = 0; i < period; i++ ) {
      float samplePhase = (i / period);

      for ( unsigned int bin = 0; bin < obs.getNrBins(); bin++ ) {
        if ( samplePhase - ((bin + 0.5) / obs.getNrBins()) < 1.0f / obs.getNrBins() ) {
          itemsPerBin[bin] += 1;
          break;
        }
      }
    }

		for ( unsigned int bin = 0; bin < obs.getNrBins(); bin++ ) {
      samplesPerBin->at((period * obs.getNrBins() * isa::utils::pad(2, obs.getPadding())) + (bin * isa::utils::pad(2, obs.getPadding()))) = itemsPerBin[bin];
      samplesPerBin->at((period * obs.getNrBins() * isa::utils::pad(2, obs.getPadding())) + (bin * isa::utils::pad(2, obs.getPadding())) + 1) = offset;
      offset += itemsPerBin[bin];
    }
	}

	return samplesPerBin;
}

} // PulsarSearch

#endif // BINS_HPP
<|endoftext|>


<commit_before><commit_msg>reword, rename .. not much left to do after dtr cept this entire check probably would do well in a SpamFilter object that tracks better.<commit_after><|endoftext|>


<commit_before>/**
 *	\file
 */

#include <rleahylib/rleahylib.hpp>
#include <functional>
#include <type_traits>

/**
 *	\cond
 */

namespace std {

	template <>
	struct hash<String> {

		public:

			size_t operator () (String str) const {

				//	Normalize string
				str.Normalize(NormalizationForm::NFC);

				//	djb2
				size_t retr=5381;

				for (auto cp : str.CodePoints()) {

					retr*=33;
					retr^=cp;

				}

				return retr;

			}

	};

	template <>
	struct hash<IPAddress> {

		public:

			size_t operator () (IPAddress ip) const noexcept {

				//	Is this an IPv4 or IPv6
				//	address?
				if (ip.IsV6()) {

					//	This static assert ensures the operation
					//	planned will work
					static_assert(
						(sizeof(UInt128)%sizeof(size_t))==0,
						"Hash for IP addresses not compatible with integer sizes on this platform"
					);

					union {
						UInt128 raw_ip;
						size_t split [sizeof(UInt128)/sizeof(size_t)];
					};

					raw_ip=static_cast<UInt128>(ip);

					size_t retr=23;

					for (auto m : split) {

						retr*=31;
						retr+=m;

					}

					return retr;

				}

				//	Just return the IPv4 address
				//	to use as the hash
				return static_cast<size_t>(
					static_cast<UInt32>(ip)
				);

			}

	};

	template <typename... Args>
	struct hash<Tuple<Args...>> {

		private:

			template <Word i>
			typename std::enable_if<
				i<sizeof...(Args),
				size_t
			>::type compute_hash (size_t curr, const Tuple<Args...> & t) const {

				curr*=31;

				curr+=std::hash<
					typename std::decay<
						decltype(t.template Item<i>())
					>::type
				>()(t.template Item<i>());

				return compute_hash<i+1>(curr,t);

			}

			template <Word i>
			typename std::enable_if<
				i>=sizeof...(Args),
				size_t
			>::type compute_hash (size_t curr, const Tuple<Args...> &) const noexcept {

				return curr;

			}

		public:

			size_t operator () (const Tuple<Args...> & t) const {

				return compute_hash<0>(23,t);

			}

	};

	template <typename T>
	struct hash<SmartPointer<T>> {

		public:

			size_t operator () (const SmartPointer<T> & sp) const noexcept {

				return hash<const T *>()(static_cast<const T *>(sp));

			}

	};

}

/**
 *	\endcond
 */
<commit_msg>Hash Header Fix<commit_after>/**
 *	\file
 */

#pragma once

#include <rleahylib/rleahylib.hpp>
#include <functional>
#include <type_traits>

/**
 *	\cond
 */

namespace std {

	template <>
	struct hash<String> {

		public:

			size_t operator () (String str) const {

				//	Normalize string
				str.Normalize(NormalizationForm::NFC);

				//	djb2
				size_t retr=5381;

				for (auto cp : str.CodePoints()) {

					retr*=33;
					retr^=cp;

				}

				return retr;

			}

	};

	template <>
	struct hash<IPAddress> {

		public:

			size_t operator () (IPAddress ip) const noexcept {

				//	Is this an IPv4 or IPv6
				//	address?
				if (ip.IsV6()) {

					//	This static assert ensures the operation
					//	planned will work
					static_assert(
						(sizeof(UInt128)%sizeof(size_t))==0,
						"Hash for IP addresses not compatible with integer sizes on this platform"
					);

					union {
						UInt128 raw_ip;
						size_t split [sizeof(UInt128)/sizeof(size_t)];
					};

					raw_ip=static_cast<UInt128>(ip);

					size_t retr=23;

					for (auto m : split) {

						retr*=31;
						retr+=m;

					}

					return retr;

				}

				//	Just return the IPv4 address
				//	to use as the hash
				return static_cast<size_t>(
					static_cast<UInt32>(ip)
				);

			}

	};

	template <typename... Args>
	struct hash<Tuple<Args...>> {

		private:

			template <Word i>
			typename std::enable_if<
				i<sizeof...(Args),
				size_t
			>::type compute_hash (size_t curr, const Tuple<Args...> & t) const {

				curr*=31;

				curr+=std::hash<
					typename std::decay<
						decltype(t.template Item<i>())
					>::type
				>()(t.template Item<i>());

				return compute_hash<i+1>(curr,t);

			}

			template <Word i>
			typename std::enable_if<
				i>=sizeof...(Args),
				size_t
			>::type compute_hash (size_t curr, const Tuple<Args...> &) const noexcept {

				return curr;

			}

		public:

			size_t operator () (const Tuple<Args...> & t) const {

				return compute_hash<0>(23,t);

			}

	};

	template <typename T>
	struct hash<SmartPointer<T>> {

		public:

			size_t operator () (const SmartPointer<T> & sp) const noexcept {

				return hash<const T *>()(static_cast<const T *>(sp));

			}

	};

}

/**
 *	\endcond
 */
<|endoftext|>


<commit_before>#include "read.h"
#include <boost/dynamic_bitset.hpp>
#include <numeric>
#include <iostream>

std::string ReadBase::bit_to_str(const BitSet &bits) {
    size_t str_len = bits.size()/2;
    std::string out;
    out.resize(str_len);
    size_t i = bits.size() -1;
    for(size_t stridx = 0; stridx < str_len; ++stridx) {
        if (bits[i] == 0 && bits[i-1] == 0) {
            out[stridx] = 'A';
        } else if (bits[i] == 0 && bits[i-1] == 1) {
            out[stridx] = 'C';
        } else if (bits[i] == 1 && bits[i-1] == 0) {
            out[stridx] = 'G';
        } else {
            out[stridx] = 'T';
        }
        i -= 2;
    }
    return out;
}

// Read
Read Read::subread(size_t start, size_t length){
    return Read(seq.substr(start, length), qual.substr(start,length), id);
}

std::string Read::subseq(size_t start, size_t length){
    return seq.substr(start, length);
}

//PairedEndRead
boost::optional<BitSet> PairedEndRead::get_key(size_t start, size_t length){
    return std::max(str_to_bit(one.subseq(start, length) + two.subseq(start, length)),
                    str_to_bit(two.subseq(start, length) + one.subseq(start, length)));
}

boost::optional<BitSet> ReadBase::reverse_complement(const std::string& str, int start, int length) {
    auto rstart = str.rbegin() + start;
    auto rend = str.rbegin() + start + length;
    auto rv = str_to_bit(std::string(rstart, rend));
    if (rv) {
        return ~(*rv);
    } else {
        return rv;
    }
}

//SingleEndRead
boost::optional<BitSet> SingleEndRead::get_key(size_t start, size_t length){
    //The C ensures no PE and SE are mapped to the same locaitn
    return str_to_bit("C" + one.subseq(start, length*2));
}

inline size_t qual_sum(size_t s, const char c) {
    return size_t(c) + s;
}

double SingleEndRead::avg_q_score()
{
    size_t sum = std::accumulate(one.get_qual().begin(), one.get_qual().end(), size_t(0), qual_sum);
    return sum/double(one.get_qual().length());

}

double PairedEndRead::avg_q_score()
{
    size_t sum = std::accumulate(one.get_qual().begin(), one.get_qual().end(), size_t(0), qual_sum);
    sum += std::accumulate(two.get_qual().begin(), two.get_qual().end(), size_t(0), qual_sum);
    return sum/double(one.get_qual().length() + two.get_qual().length());
}

<commit_msg>Removed unused header files<commit_after>#include "read.h"
#include <boost/dynamic_bitset.hpp>
#include <numeric>

std::string ReadBase::bit_to_str(const BitSet &bits) {
    size_t str_len = bits.size()/2;
    std::string out;
    out.resize(str_len);
    size_t i = bits.size() -1;
    for(size_t stridx = 0; stridx < str_len; ++stridx) {
        if (bits[i] == 0 && bits[i-1] == 0) {
            out[stridx] = 'A';
        } else if (bits[i] == 0 && bits[i-1] == 1) {
            out[stridx] = 'C';
        } else if (bits[i] == 1 && bits[i-1] == 0) {
            out[stridx] = 'G';
        } else {
            out[stridx] = 'T';
        }
        i -= 2;
    }
    return out;
}

// Read
Read Read::subread(size_t start, size_t length){
    return Read(seq.substr(start, length), qual.substr(start,length), id);
}

std::string Read::subseq(size_t start, size_t length){
    return seq.substr(start, length);
}

//PairedEndRead
boost::optional<BitSet> PairedEndRead::get_key(size_t start, size_t length){
    return std::max(str_to_bit(one.subseq(start, length) + two.subseq(start, length)),
                    str_to_bit(two.subseq(start, length) + one.subseq(start, length)));
}

boost::optional<BitSet> ReadBase::reverse_complement(const std::string& str, int start, int length) {
    auto rstart = str.rbegin() + start;
    auto rend = str.rbegin() + start + length;
    auto rv = str_to_bit(std::string(rstart, rend));
    if (rv) {
        return ~(*rv);
    } else {
        return rv;
    }
}

//SingleEndRead
boost::optional<BitSet> SingleEndRead::get_key(size_t start, size_t length){
    //The C ensures no PE and SE are mapped to the same locaitn
    return str_to_bit("C" + one.subseq(start, length*2));
}

inline size_t qual_sum(size_t s, const char c) {
    return size_t(c) + s;
}

double SingleEndRead::avg_q_score()
{
    size_t sum = std::accumulate(one.get_qual().begin(), one.get_qual().end(), size_t(0), qual_sum);
    return sum/double(one.get_qual().length());

}

double PairedEndRead::avg_q_score()
{
    size_t sum = std::accumulate(one.get_qual().begin(), one.get_qual().end(), size_t(0), qual_sum);
    sum += std::accumulate(two.get_qual().begin(), two.get_qual().end(), size_t(0), qual_sum);
    return sum/double(one.get_qual().length() + two.get_qual().length());
}

<|endoftext|>


<commit_before>#include "mitkAffineInteractor.h"
#include "mitkInteractionConst.h"
#include <mitkDataTreeNode.h>
#include "mitkGeometry3D.h"
#include "mitkAffineTransformationOperation.h"
#include "mitkPositionEvent.h"
#include "vtkTransform.h"
#include <mitkRenderWindow.h>

#include <math.h>

mitk::AffineInteractor::AffineInteractor(std::string type, DataTreeNode* dataTreeNode)
	 : Interactor(type, dataTreeNode)
{
  //m_ScaleFactor = 1.0;
}

bool mitk::AffineInteractor::ExecuteSideEffect(int sideEffectId, mitk::StateEvent const* stateEvent, int objectEventId, int groupEventId)
{
	bool ok = false;//for return type bool

  mitk::Geometry3D* geometry = m_DataTreeNode->GetData()->GetGeometry();
	if (geometry == NULL)
		return false;

  /* Each case must watch the type of the event! */
  switch (sideEffectId)
	{
   case SeNEWPOINT:
  {
    break;
  }
  case SeTRANSLATE:
  {
    mitk::PositionEvent const  *posEvent = dynamic_cast <const mitk::PositionEvent *> (stateEvent->GetEvent());
		if (posEvent == NULL) return false;

    //converting from Point3D to itk::Point
		mitk::ITKPoint3D newPosition;
		mitk::vm2itk(posEvent->GetWorldPosition(), newPosition);

    // create operation with new position
    AffineTransformationOperation* doOp = new mitk::AffineTransformationOperation(OpMOVE, newPosition, 0.0, 0); // Index is not used here
		if (m_UndoEnabled)	//write to UndoMechanism
		{
      mitk::ScalarType pos[3];
      geometry->GetTransform()->GetPosition(pos);
      mitk::ITKPoint3D oldPosition;
      oldPosition[0] = pos[0];
      oldPosition[1] = pos[1];
      oldPosition[2] = pos[2];

      AffineTransformationOperation* undoOp = new mitk::AffineTransformationOperation(OpMOVE, oldPosition, 0.0, 0);
			OperationEvent *operationEvent = new OperationEvent(geometry,
																	doOp, undoOp,
																	objectEventId, groupEventId);
			m_UndoController->SetOperationEvent(operationEvent);
		}
		//execute the Operation
		geometry->ExecuteOperation(doOp);

    ok = true;
	  break;
  }
  case SeROTATESTART:
  {
    mitk::PositionEvent const  *posEvent = dynamic_cast <const mitk::PositionEvent *> (stateEvent->GetEvent());
		if (posEvent == NULL) return false;
    //converting from Point3D to itk::Point
		mitk::ITKPoint3D newPosition;
		mitk::vm2itk(posEvent->GetWorldPosition(), newPosition);
    // save mouse down position
    m_lastRotatePosition = newPosition.GetVectorFromOrigin();
    ok = true;
    break;
  }
  case SeROTATE:
  {
    mitk::PositionEvent const  *posEvent = dynamic_cast <const mitk::PositionEvent *> (stateEvent->GetEvent());
		if (posEvent == NULL) return false;
    //converting from Point3D to itk::Point
		mitk::ITKPoint3D dummy;
    mitk::vm2itk(posEvent->GetWorldPosition(), dummy);

    mitk::ITKVector3D newPosition = dummy.GetVectorFromOrigin();

    mitk::ScalarType position[3];
    geometry->GetTransform()->GetPosition(position);
    mitk::ITKVector3D dataPosition = position;

    newPosition -= dataPosition;  // calculate vector from center of the data object to the mouse position

    mitk::ITKVector3D startPosition = m_lastRotatePosition - dataPosition;  // calculate vector from center of the data object to the last mouse position

    mitk::ITKVector3D rotationaxis;   // calculate rotation axis (by calculating the cross produkt of the vectors)
    rotationaxis[0] =  startPosition[1] * newPosition[2] - startPosition[2] * newPosition[1];
    rotationaxis[1] =  startPosition[2] * newPosition[0] - startPosition[0] * newPosition[2];
    rotationaxis[2] =  startPosition[0] * newPosition[1] - startPosition[1] * newPosition[0];

    mitk::ScalarType angle = atan2(rotationaxis.GetNorm(), newPosition * startPosition) * (180/(4 * atan(1)));

    m_lastRotatePosition = dummy.GetVectorFromOrigin(); // save actual mouse position as last mouse position

    dummy[0] = rotationaxis[0];  // encapsulate rotation vector into a ITKPoint3D for the Operation
    dummy[1] = rotationaxis[1];
    dummy[2] = rotationaxis[2];

    // create operation with angle and axis
    AffineTransformationOperation* doOp = new mitk::AffineTransformationOperation(OpROTATE, dummy, angle, 0); // Index is not used here

    if (m_UndoEnabled)	//write to UndoMechanism
		{
      AffineTransformationOperation* undoOp = new mitk::AffineTransformationOperation(OpROTATE, dummy, -angle, 0); // Index is not used here
			OperationEvent *operationEvent = new OperationEvent(geometry,
																	doOp, undoOp,
																	objectEventId, groupEventId);
			m_UndoController->SetOperationEvent(operationEvent);
		}
		//execute the Operation
		geometry->ExecuteOperation(doOp);

    ok = true;
	  break;
  }
  case SeSCALESTART:
  {
    mitk::PositionEvent const  *posEvent = dynamic_cast <const mitk::PositionEvent *> (stateEvent->GetEvent());
		if (posEvent == NULL) return false;
    //converting from Point3D to itk::Point
		mitk::ITKPoint3D newPosition;
		mitk::vm2itk(posEvent->GetWorldPosition(), newPosition);
    m_lastScalePosition = newPosition;
    mitk::ScalarType lastScale[3];
    // Save initial scale
    geometry->GetTransform()->GetScale(lastScale);
    m_lastScaleData = lastScale;

    ok = true;
    break;
  }
  case SeSCALE:
  {
    mitk::PositionEvent const  *posEvent = dynamic_cast <const mitk::PositionEvent *> (stateEvent->GetEvent());
		if (posEvent == NULL) return false;
    //converting from Point3D to itk::Point
		mitk::ITKPoint3D newPosition;
		mitk::vm2itk(posEvent->GetWorldPosition(), newPosition);

    mitk::ITKPoint3D newScale;
    newScale[0] = m_lastScaleData[0] + (newPosition[0] - m_lastScalePosition[0]);// * m_ScaleFactor;
    newScale[1] = m_lastScaleData[1] + (newPosition[1] - m_lastScalePosition[1]);// * m_ScaleFactor;
    newScale[2] = m_lastScaleData[2] + (newPosition[2] - m_lastScalePosition[2]);// * m_ScaleFactor;

    newScale[0] = (newScale[0] < 1) ? 1 : newScale[0]; // cap at a minimum scale factor of 1
    newScale[1] = (newScale[1] < 1) ? 1 : newScale[1];
    newScale[2] = (newScale[2] < 1) ? 1 : newScale[2];

    AffineTransformationOperation* doOp = new mitk::AffineTransformationOperation(OpSCALE, newScale, 0.0, 0); // Index is not used here

		if (m_UndoEnabled)	//write to UndoMechanism
		{
      mitk::ScalarType oldScale[3];
      geometry->GetTransform()->GetScale(oldScale);
      mitk::ITKPoint3D oldScaleData = oldScale;

      AffineTransformationOperation* undoOp = new mitk::AffineTransformationOperation(OpSCALE, oldScaleData, 0.0, 0);
			OperationEvent *operationEvent = new OperationEvent(geometry,
																	doOp, undoOp,
																	objectEventId, groupEventId);
			m_UndoController->SetOperationEvent(operationEvent);
		}
		//execute the Operation
		geometry->ExecuteOperation(doOp);

    ok = true;
	  break;
  }
  default:
    ok = true;
  }
  mitk::RenderWindow::UpdateAllInstances();
  return ok;
}
<commit_msg>changed computation of the angle for the rotation event<commit_after>#include "mitkAffineInteractor.h"
#include "mitkInteractionConst.h"
#include <mitkDataTreeNode.h>
#include "mitkGeometry3D.h"
#include "mitkAffineTransformationOperation.h"
#include "mitkPositionEvent.h"
#include "vtkTransform.h"
#include <mitkRenderWindow.h>

#include <math.h>

mitk::AffineInteractor::AffineInteractor(std::string type, DataTreeNode* dataTreeNode)
	 : Interactor(type, dataTreeNode)
{
  //m_ScaleFactor = 1.0;
}

bool mitk::AffineInteractor::ExecuteSideEffect(int sideEffectId, mitk::StateEvent const* stateEvent, int objectEventId, int groupEventId)
{
	bool ok = false;//for return type bool

  mitk::Geometry3D* geometry = m_DataTreeNode->GetData()->GetGeometry();
	if (geometry == NULL)
		return false;

  /* Each case must watch the type of the event! */
  switch (sideEffectId)
	{
   case SeNEWPOINT:
  {
    break;
  }
  case SeTRANSLATE:
  {
    mitk::PositionEvent const  *posEvent = dynamic_cast <const mitk::PositionEvent *> (stateEvent->GetEvent());
		if (posEvent == NULL) return false;

    //converting from Point3D to itk::Point
		mitk::ITKPoint3D newPosition;
		mitk::vm2itk(posEvent->GetWorldPosition(), newPosition);

    // create operation with new position
    AffineTransformationOperation* doOp = new mitk::AffineTransformationOperation(OpMOVE, newPosition, 0.0, 0); // Index is not used here
		if (m_UndoEnabled)	//write to UndoMechanism
		{
      mitk::ScalarType pos[3];
      geometry->GetTransform()->GetPosition(pos);
      mitk::ITKPoint3D oldPosition;
      oldPosition[0] = pos[0];
      oldPosition[1] = pos[1];
      oldPosition[2] = pos[2];

      AffineTransformationOperation* undoOp = new mitk::AffineTransformationOperation(OpMOVE, oldPosition, 0.0, 0);
			OperationEvent *operationEvent = new OperationEvent(geometry,
																	doOp, undoOp,
																	objectEventId, groupEventId);
			m_UndoController->SetOperationEvent(operationEvent);
		}
		//execute the Operation
		geometry->ExecuteOperation(doOp);

    ok = true;
	  break;
  }
  case SeROTATESTART:
  {
    mitk::PositionEvent const  *posEvent = dynamic_cast <const mitk::PositionEvent *> (stateEvent->GetEvent());
		if (posEvent == NULL) return false;
    //converting from Point3D to itk::Point
		mitk::ITKPoint3D newPosition;
		mitk::vm2itk(posEvent->GetWorldPosition(), newPosition);
    // save mouse down position
    m_lastRotatePosition = newPosition.GetVectorFromOrigin();
    ok = true;
    break;
  }
  case SeROTATE:
  {
    mitk::PositionEvent const  *posEvent = dynamic_cast <const mitk::PositionEvent *> (stateEvent->GetEvent());
		if (posEvent == NULL) return false;
    //converting from Point3D to itk::Point
		mitk::ITKPoint3D dummy;
    mitk::vm2itk(posEvent->GetWorldPosition(), dummy);

    mitk::ITKVector3D newPosition = dummy.GetVectorFromOrigin();

    mitk::ScalarType position[3];
    geometry->GetTransform()->GetPosition(position);
    mitk::ITKVector3D dataPosition = position;

    newPosition -= dataPosition;  // calculate vector from center of the data object to the mouse position

    mitk::ITKVector3D startPosition = m_lastRotatePosition - dataPosition;  // calculate vector from center of the data object to the last mouse position

    mitk::ITKVector3D rotationaxis;   // calculate rotation axis (by calculating the cross produkt of the vectors)
    rotationaxis[0] =  startPosition[1] * newPosition[2] - startPosition[2] * newPosition[1];
    rotationaxis[1] =  startPosition[2] * newPosition[0] - startPosition[0] * newPosition[2];
    rotationaxis[2] =  startPosition[0] * newPosition[1] - startPosition[1] * newPosition[0];

    mitk::ScalarType angle = atan2(rotationaxis.GetNorm(), newPosition * startPosition) * (180/vnl_math::pi);

    m_lastRotatePosition = dummy.GetVectorFromOrigin(); // save actual mouse position as last mouse position

    dummy[0] = rotationaxis[0];  // encapsulate rotation vector into a ITKPoint3D for the Operation
    dummy[1] = rotationaxis[1];
    dummy[2] = rotationaxis[2];

    // create operation with angle and axis
    AffineTransformationOperation* doOp = new mitk::AffineTransformationOperation(OpROTATE, dummy, angle, 0); // Index is not used here

    if (m_UndoEnabled)	//write to UndoMechanism
		{
      AffineTransformationOperation* undoOp = new mitk::AffineTransformationOperation(OpROTATE, dummy, -angle, 0); // Index is not used here
			OperationEvent *operationEvent = new OperationEvent(geometry,
																	doOp, undoOp,
																	objectEventId, groupEventId);
			m_UndoController->SetOperationEvent(operationEvent);
		}
		//execute the Operation
		geometry->ExecuteOperation(doOp);

    ok = true;
	  break;
  }
  case SeSCALESTART:
  {
    mitk::PositionEvent const  *posEvent = dynamic_cast <const mitk::PositionEvent *> (stateEvent->GetEvent());
		if (posEvent == NULL) return false;
    //converting from Point3D to itk::Point
		mitk::ITKPoint3D newPosition;
		mitk::vm2itk(posEvent->GetWorldPosition(), newPosition);
    m_lastScalePosition = newPosition;
    mitk::ScalarType lastScale[3];
    // Save initial scale
    geometry->GetTransform()->GetScale(lastScale);
    m_lastScaleData = lastScale;

    ok = true;
    break;
  }
  case SeSCALE:
  {
    mitk::PositionEvent const  *posEvent = dynamic_cast <const mitk::PositionEvent *> (stateEvent->GetEvent());
		if (posEvent == NULL) return false;
    //converting from Point3D to itk::Point
		mitk::ITKPoint3D newPosition;
		mitk::vm2itk(posEvent->GetWorldPosition(), newPosition);

    mitk::ITKPoint3D newScale;
    newScale[0] = m_lastScaleData[0] + (newPosition[0] - m_lastScalePosition[0]);// * m_ScaleFactor;
    newScale[1] = m_lastScaleData[1] + (newPosition[1] - m_lastScalePosition[1]);// * m_ScaleFactor;
    newScale[2] = m_lastScaleData[2] + (newPosition[2] - m_lastScalePosition[2]);// * m_ScaleFactor;

    newScale[0] = (newScale[0] < 1) ? 1 : newScale[0]; // cap at a minimum scale factor of 1
    newScale[1] = (newScale[1] < 1) ? 1 : newScale[1];
    newScale[2] = (newScale[2] < 1) ? 1 : newScale[2];

    AffineTransformationOperation* doOp = new mitk::AffineTransformationOperation(OpSCALE, newScale, 0.0, 0); // Index is not used here

		if (m_UndoEnabled)	//write to UndoMechanism
		{
      mitk::ScalarType oldScale[3];
      geometry->GetTransform()->GetScale(oldScale);
      mitk::ITKPoint3D oldScaleData = oldScale;

      AffineTransformationOperation* undoOp = new mitk::AffineTransformationOperation(OpSCALE, oldScaleData, 0.0, 0);
			OperationEvent *operationEvent = new OperationEvent(geometry,
																	doOp, undoOp,
																	objectEventId, groupEventId);
			m_UndoController->SetOperationEvent(operationEvent);
		}
		//execute the Operation
		geometry->ExecuteOperation(doOp);

    ok = true;
	  break;
  }
  default:
    ok = true;
  }
  mitk::RenderWindow::UpdateAllInstances();
  return ok;
}
<|endoftext|>