<commit_before>//------------------------------------------------------------------------------
// 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 "cling/MetaProcessor/MetaProcessor.h"

#include "Display.h"
#include "InputValidator.h"
#include "MetaParser.h"
#include "MetaSema.h"
#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/Value.h"

#include "clang/Basic/FileManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/Preprocessor.h"

#include "llvm/Support/Path.h"

#include <fstream>
#include <cstdlib>
#include <cctype>
#include <stdio.h>
#ifndef WIN32
#include <unistd.h>
#else
#include <io.h>
#define STDIN_FILENO  0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
#endif

using namespace clang;

namespace cling {

  MetaProcessor::MaybeRedirectOutputRAII::MaybeRedirectOutputRAII(
                                          MetaProcessor* p)
  :m_MetaProcessor(p), m_isCurrentlyRedirecting(0) {
    StringRef redirectionFile;
    m_MetaProcessor->increaseRedirectionRAIILevel();
    if (!m_MetaProcessor->m_PrevStdoutFileName.empty()) {
      redirectionFile = m_MetaProcessor->m_PrevStdoutFileName.back();
      redirect(stdout, redirectionFile.str(), kSTDOUT);
    }
    if (!m_MetaProcessor->m_PrevStderrFileName.empty()) {
      redirectionFile = m_MetaProcessor->m_PrevStderrFileName.back();
      // Deal with the case 2>&1 and 2&>1
      if (strcmp(redirectionFile.data(), "_IO_2_1_stdout_") == 0) {
        // If out is redirected to a file.
        if (!m_MetaProcessor->m_PrevStdoutFileName.empty()) {
          redirectionFile = m_MetaProcessor->m_PrevStdoutFileName.back();
        } else {
          unredirect(m_MetaProcessor->m_backupFDStderr, STDERR_FILENO, stderr);
        }
      }
      redirect(stderr, redirectionFile.str(), kSTDERR);
    }
  }

  MetaProcessor::MaybeRedirectOutputRAII::~MaybeRedirectOutputRAII() {
    pop();
    m_MetaProcessor->decreaseRedirectionRAIILevel();
  }

  void MetaProcessor::MaybeRedirectOutputRAII::redirect(FILE* file,
                                        const std::string& fileName,
                                        MetaProcessor::RedirectionScope scope) {
    if (!fileName.empty()) {
      FILE* redirectionFile = freopen(fileName.c_str(), "a", file);
      if (!redirectionFile) {
        llvm::errs()<<"cling::MetaProcessor::MaybeRedirectOutputRAII::redirect:"
                    " Not succefully reopened the redirection file "
                    << fileName.c_str() << "\n.";
      } else {
        m_isCurrentlyRedirecting |= scope;
      }
    }
  }

  void MetaProcessor::MaybeRedirectOutputRAII::pop() {
    //If we have only one redirection RAII
    //only then do the unredirection.
    if (m_MetaProcessor->getRedirectionRAIILevel() != 1)
      return;

    if (m_isCurrentlyRedirecting & kSTDOUT) {
      unredirect(m_MetaProcessor->m_backupFDStdout, STDOUT_FILENO, stdout);
    }
    if (m_isCurrentlyRedirecting & kSTDERR) {
      unredirect(m_MetaProcessor->m_backupFDStderr, STDERR_FILENO, stderr);
    }
  }

  void MetaProcessor::MaybeRedirectOutputRAII::unredirect(int backupFD,
                                                          int expectedFD,
                                                          FILE* file) {
    // Switch back to previous file after line is processed.

    // Flush the current content if there is any.
    if (!feof(file)) {
      fflush(file);
    }
    // Copy the original fd for the std.
    if (dup2(backupFD, expectedFD) != expectedFD) {
        llvm::errs() << "cling::MetaProcessor::unredirect "
                     << "The unredirection file descriptor not valid "
                     << backupFD << ".\n";
    }
  }

  MetaProcessor::MetaProcessor(Interpreter& interp, raw_ostream& outs)
    : m_Interp(interp), m_Outs(&outs) {
    m_InputValidator.reset(new InputValidator());
    m_MetaParser.reset(new MetaParser(new MetaSema(interp, *this)));
    m_backupFDStdout = copyFileDescriptor(STDOUT_FILENO);
    m_backupFDStderr = copyFileDescriptor(STDERR_FILENO);
  }

  MetaProcessor::~MetaProcessor() {
    close(m_backupFDStdout);
    close(m_backupFDStderr);
  }

  int MetaProcessor::process(const char* input_text,
                             Interpreter::CompilationResult& compRes,
                             Value* result) {
    if (result)
      *result = Value();
    compRes = Interpreter::kSuccess;
    int expectedIndent = m_InputValidator->getExpectedIndent();

    if (expectedIndent)
      compRes = Interpreter::kMoreInputExpected;
    if (!input_text || !input_text[0]) {
      // nullptr / empty string, nothing to do.
      return expectedIndent;
    }
    std::string input_line(input_text);
    if (input_line == "\n") { // just a blank line, nothing to do.
      return expectedIndent;
    }
    //  Check for and handle meta commands.
    m_MetaParser->enterNewInputLine(input_line);
    MetaSema::ActionResult actionResult = MetaSema::AR_Success;
    if (m_MetaParser->isMetaCommand(actionResult, result)) {

      if (m_MetaParser->isQuitRequested())
        return -1;

      if (actionResult != MetaSema::AR_Success)
        compRes = Interpreter::kFailure;
       // ExpectedIndent might have changed after meta command.
       return m_InputValidator->getExpectedIndent();
    }

    // Check if the current statement is now complete. If not, return to
    // prompt for more.
    if (m_InputValidator->validate(input_line) == InputValidator::kIncomplete) {
      compRes = Interpreter::kMoreInputExpected;
      return m_InputValidator->getExpectedIndent();
    }

    //  We have a complete statement, compile and execute it.
    std::string input = m_InputValidator->getInput();
    m_InputValidator->reset();
    // if (m_Options.RawInput)
    //   compResLocal = m_Interp.declare(input);
    // else
    compRes = m_Interp.process(input, result);

    return 0;
  }

  void MetaProcessor::cancelContinuation() const {
    m_InputValidator->reset();
  }

  int MetaProcessor::getExpectedIndent() const {
    return m_InputValidator->getExpectedIndent();
  }

  Interpreter::CompilationResult
  MetaProcessor::readInputFromFile(llvm::StringRef filename,
                                   Value* result,
                                   size_t posOpenCurly) {

    {
      // check that it's not binary:
      std::ifstream in(filename.str().c_str(), std::ios::in | std::ios::binary);
      char magic[1024] = {0};
      in.read(magic, sizeof(magic));
      size_t readMagic = in.gcount();
      // Binary files < 300 bytes are rare, and below newlines etc make the
      // heuristic unreliable.
      if (readMagic >= 300) {
        llvm::StringRef magicStr(magic,in.gcount());
        llvm::sys::fs::file_magic fileType
          = llvm::sys::fs::identify_magic(magicStr);
        if (fileType != llvm::sys::fs::file_magic::unknown) {
          llvm::errs() << "Error in cling::MetaProcessor: "
            "cannot read input from a binary file!\n";
          return Interpreter::kFailure;
        }
        unsigned printable = 0;
        for (size_t i = 0; i < readMagic; ++i)
          if (isprint(magic[i]))
            ++printable;
        if (10 * printable <  5 * readMagic) {
          // 50% printable for ASCII files should be a safe guess.
          llvm::errs() << "Error in cling::MetaProcessor: "
            "cannot read input from a (likely) binary file!\n" << printable;
          return Interpreter::kFailure;
        }
      }
    }

    std::ifstream in(filename.str().c_str());
    in.seekg(0, std::ios::end);
    size_t size = in.tellg();
    std::string content(size, ' ');
    in.seekg(0);
    in.read(&content[0], size);

    if (posOpenCurly != (size_t)-1 && !content.empty()) {
      assert(content[posOpenCurly] == '{'
             && "No curly at claimed position of opening curly!");
      // hide the curly brace:
      content[posOpenCurly] = ' ';
      // and the matching closing '}'
      static const char whitespace[] = " \t\r\n";
      size_t posCloseCurly = content.find_last_not_of(whitespace);
      if (posCloseCurly != std::string::npos) {
        if (content[posCloseCurly] == ';' && content[posCloseCurly-1] == '}') {
          content[posCloseCurly--] = ' '; // replace ';' and enter next if
        }
        if (content[posCloseCurly] == '}') {
          content[posCloseCurly] = ' '; // replace '}'
        } else {
          std::string::size_type posBlockClose = content.find_last_of('}');
          if (posBlockClose != std::string::npos) {
            content[posBlockClose] = ' '; // replace '}'
          }
          std::string::size_type posComment
            = content.find_first_not_of(whitespace, posBlockClose);
          if (posComment != std::string::npos
              && content[posComment] == '/' && content[posComment+1] == '/') {
            // More text (comments) are okay after the last '}', but
            // we can not easily find it to remove it (so we need to upgrade
            // this code to better handle the case with comments or
            // preprocessor code before and after the leading { and
            // trailing })
            while (posComment <= posCloseCurly) {
              content[posComment++] = ' '; // replace '}' and comment
            }
          } else {
            content[posCloseCurly] = '{';
            // By putting the '{' back, we keep the code as consistent as
            // the user wrote it ... but we should still warn that we not
            // goint to treat this file an unamed macro.
            llvm::errs()
              << "Warning in cling::MetaProcessor: can not find the closing '}', "
              << llvm::sys::path::filename(filename)
              << " is not handled as an unamed script!\n";
          } // did not find "//"
        } // remove comments after the trailing '}'
      } // find '}'
    } // ignore outermost block

    std::string strFilename(filename.str());
    m_CurrentlyExecutingFile = strFilename;
    bool topmost = !m_TopExecutingFile.data();
    if (topmost)
      m_TopExecutingFile = m_CurrentlyExecutingFile;
    Interpreter::CompilationResult ret;
    // We don't want to value print the results of a unnamed macro.
    content = "#line 2 \"" + filename.str() + "\" \n" + content;
    if (process((content + ";").c_str(), ret, result)) {
      // Input file has to be complete.
       llvm::errs()
          << "Error in cling::MetaProcessor: file "
          << llvm::sys::path::filename(filename)
          << " is incomplete (missing parenthesis or similar)!\n";
      ret = Interpreter::kFailure;
    }
    m_CurrentlyExecutingFile = llvm::StringRef();
    if (topmost)
      m_TopExecutingFile = llvm::StringRef();
    return ret;
  }

  void MetaProcessor::setFileStream(llvm::StringRef file, bool append, int fd,
              llvm::SmallVector<llvm::SmallString<128>, 2>& prevFileStack) {
    // If we have a fileName to redirect to store it.
    if (!file.empty()) {
      prevFileStack.push_back(file);
      // pop and push a null terminating 0.
      // SmallVectorImpl<T> does not have a c_str(), thus instead of casting to
      // a SmallString<T> we null terminate the data that we have and pop the
      // 0 char back.
      prevFileStack.back().push_back(0);
      prevFileStack.back().pop_back();
      if (!append) {
        FILE * f;
        if (!(f = fopen(file.data(), "w"))) {
          llvm::errs() << "cling::MetaProcessor::setFileStream:"
                       " The file path " << file.data() << "is not valid.";
        } else {
          fclose(f);
        }
      }
    // Else unredirection, so switch to the previous file.
    } else {
      // If there is no previous file on the stack we pop the file
      if (!prevFileStack.empty()) {
        prevFileStack.pop_back();
      }
    }
  }

  void MetaProcessor::setStdStream(llvm::StringRef file,
                                   RedirectionScope stream, bool append) {

    if (stream & kSTDOUT) {
      setFileStream(file, append, STDOUT_FILENO, m_PrevStdoutFileName);
    }
    if (stream & kSTDERR) {
      setFileStream(file, append, STDERR_FILENO, m_PrevStderrFileName);
    }
  }

  int MetaProcessor::copyFileDescriptor(int fd) {
    int backupFD = dup(fd);
    if (backupFD < 0) {
      llvm::errs() << "MetaProcessor::copyFileDescriptor: Duplicating the file"
                   " descriptor " << fd << "resulted in an error."
                   " Will not be able to unredirect.";
    }
    return backupFD;
  }

  void MetaProcessor::registerUnloadPoint(const Transaction* T,
                                          llvm::StringRef filename) {
    m_MetaParser->getActions().registerUnloadPoint(T, filename);
  }

} // end namespace cling
<commit_msg>Add missing newline.<commit_after>//------------------------------------------------------------------------------
// 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 "cling/MetaProcessor/MetaProcessor.h"

#include "Display.h"
#include "InputValidator.h"
#include "MetaParser.h"
#include "MetaSema.h"
#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/Value.h"

#include "clang/Basic/FileManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/Preprocessor.h"

#include "llvm/Support/Path.h"

#include <fstream>
#include <cstdlib>
#include <cctype>
#include <stdio.h>
#ifndef WIN32
#include <unistd.h>
#else
#include <io.h>
#define STDIN_FILENO  0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
#endif

using namespace clang;

namespace cling {

  MetaProcessor::MaybeRedirectOutputRAII::MaybeRedirectOutputRAII(
                                          MetaProcessor* p)
  :m_MetaProcessor(p), m_isCurrentlyRedirecting(0) {
    StringRef redirectionFile;
    m_MetaProcessor->increaseRedirectionRAIILevel();
    if (!m_MetaProcessor->m_PrevStdoutFileName.empty()) {
      redirectionFile = m_MetaProcessor->m_PrevStdoutFileName.back();
      redirect(stdout, redirectionFile.str(), kSTDOUT);
    }
    if (!m_MetaProcessor->m_PrevStderrFileName.empty()) {
      redirectionFile = m_MetaProcessor->m_PrevStderrFileName.back();
      // Deal with the case 2>&1 and 2&>1
      if (strcmp(redirectionFile.data(), "_IO_2_1_stdout_") == 0) {
        // If out is redirected to a file.
        if (!m_MetaProcessor->m_PrevStdoutFileName.empty()) {
          redirectionFile = m_MetaProcessor->m_PrevStdoutFileName.back();
        } else {
          unredirect(m_MetaProcessor->m_backupFDStderr, STDERR_FILENO, stderr);
        }
      }
      redirect(stderr, redirectionFile.str(), kSTDERR);
    }
  }

  MetaProcessor::MaybeRedirectOutputRAII::~MaybeRedirectOutputRAII() {
    pop();
    m_MetaProcessor->decreaseRedirectionRAIILevel();
  }

  void MetaProcessor::MaybeRedirectOutputRAII::redirect(FILE* file,
                                        const std::string& fileName,
                                        MetaProcessor::RedirectionScope scope) {
    if (!fileName.empty()) {
      FILE* redirectionFile = freopen(fileName.c_str(), "a", file);
      if (!redirectionFile) {
        llvm::errs()<<"cling::MetaProcessor::MaybeRedirectOutputRAII::redirect:"
                    " Not succefully reopened the redirection file "
                    << fileName.c_str() << "\n.";
      } else {
        m_isCurrentlyRedirecting |= scope;
      }
    }
  }

  void MetaProcessor::MaybeRedirectOutputRAII::pop() {
    //If we have only one redirection RAII
    //only then do the unredirection.
    if (m_MetaProcessor->getRedirectionRAIILevel() != 1)
      return;

    if (m_isCurrentlyRedirecting & kSTDOUT) {
      unredirect(m_MetaProcessor->m_backupFDStdout, STDOUT_FILENO, stdout);
    }
    if (m_isCurrentlyRedirecting & kSTDERR) {
      unredirect(m_MetaProcessor->m_backupFDStderr, STDERR_FILENO, stderr);
    }
  }

  void MetaProcessor::MaybeRedirectOutputRAII::unredirect(int backupFD,
                                                          int expectedFD,
                                                          FILE* file) {
    // Switch back to previous file after line is processed.

    // Flush the current content if there is any.
    if (!feof(file)) {
      fflush(file);
    }
    // Copy the original fd for the std.
    if (dup2(backupFD, expectedFD) != expectedFD) {
        llvm::errs() << "cling::MetaProcessor::unredirect "
                     << "The unredirection file descriptor not valid "
                     << backupFD << ".\n";
    }
  }

  MetaProcessor::MetaProcessor(Interpreter& interp, raw_ostream& outs)
    : m_Interp(interp), m_Outs(&outs) {
    m_InputValidator.reset(new InputValidator());
    m_MetaParser.reset(new MetaParser(new MetaSema(interp, *this)));
    m_backupFDStdout = copyFileDescriptor(STDOUT_FILENO);
    m_backupFDStderr = copyFileDescriptor(STDERR_FILENO);
  }

  MetaProcessor::~MetaProcessor() {
    close(m_backupFDStdout);
    close(m_backupFDStderr);
  }

  int MetaProcessor::process(const char* input_text,
                             Interpreter::CompilationResult& compRes,
                             Value* result) {
    if (result)
      *result = Value();
    compRes = Interpreter::kSuccess;
    int expectedIndent = m_InputValidator->getExpectedIndent();

    if (expectedIndent)
      compRes = Interpreter::kMoreInputExpected;
    if (!input_text || !input_text[0]) {
      // nullptr / empty string, nothing to do.
      return expectedIndent;
    }
    std::string input_line(input_text);
    if (input_line == "\n") { // just a blank line, nothing to do.
      return expectedIndent;
    }
    //  Check for and handle meta commands.
    m_MetaParser->enterNewInputLine(input_line);
    MetaSema::ActionResult actionResult = MetaSema::AR_Success;
    if (m_MetaParser->isMetaCommand(actionResult, result)) {

      if (m_MetaParser->isQuitRequested())
        return -1;

      if (actionResult != MetaSema::AR_Success)
        compRes = Interpreter::kFailure;
       // ExpectedIndent might have changed after meta command.
       return m_InputValidator->getExpectedIndent();
    }

    // Check if the current statement is now complete. If not, return to
    // prompt for more.
    if (m_InputValidator->validate(input_line) == InputValidator::kIncomplete) {
      compRes = Interpreter::kMoreInputExpected;
      return m_InputValidator->getExpectedIndent();
    }

    //  We have a complete statement, compile and execute it.
    std::string input = m_InputValidator->getInput();
    m_InputValidator->reset();
    // if (m_Options.RawInput)
    //   compResLocal = m_Interp.declare(input);
    // else
    compRes = m_Interp.process(input, result);

    return 0;
  }

  void MetaProcessor::cancelContinuation() const {
    m_InputValidator->reset();
  }

  int MetaProcessor::getExpectedIndent() const {
    return m_InputValidator->getExpectedIndent();
  }

  Interpreter::CompilationResult
  MetaProcessor::readInputFromFile(llvm::StringRef filename,
                                   Value* result,
                                   size_t posOpenCurly) {

    {
      // check that it's not binary:
      std::ifstream in(filename.str().c_str(), std::ios::in | std::ios::binary);
      char magic[1024] = {0};
      in.read(magic, sizeof(magic));
      size_t readMagic = in.gcount();
      // Binary files < 300 bytes are rare, and below newlines etc make the
      // heuristic unreliable.
      if (readMagic >= 300) {
        llvm::StringRef magicStr(magic,in.gcount());
        llvm::sys::fs::file_magic fileType
          = llvm::sys::fs::identify_magic(magicStr);
        if (fileType != llvm::sys::fs::file_magic::unknown) {
          llvm::errs() << "Error in cling::MetaProcessor: "
            "cannot read input from a binary file!\n";
          return Interpreter::kFailure;
        }
        unsigned printable = 0;
        for (size_t i = 0; i < readMagic; ++i)
          if (isprint(magic[i]))
            ++printable;
        if (10 * printable <  5 * readMagic) {
          // 50% printable for ASCII files should be a safe guess.
          llvm::errs() << "Error in cling::MetaProcessor: "
            "cannot read input from a (likely) binary file!\n" << printable;
          return Interpreter::kFailure;
        }
      }
    }

    std::ifstream in(filename.str().c_str());
    in.seekg(0, std::ios::end);
    size_t size = in.tellg();
    std::string content(size, ' ');
    in.seekg(0);
    in.read(&content[0], size);

    if (posOpenCurly != (size_t)-1 && !content.empty()) {
      assert(content[posOpenCurly] == '{'
             && "No curly at claimed position of opening curly!");
      // hide the curly brace:
      content[posOpenCurly] = ' ';
      // and the matching closing '}'
      static const char whitespace[] = " \t\r\n";
      size_t posCloseCurly = content.find_last_not_of(whitespace);
      if (posCloseCurly != std::string::npos) {
        if (content[posCloseCurly] == ';' && content[posCloseCurly-1] == '}') {
          content[posCloseCurly--] = ' '; // replace ';' and enter next if
        }
        if (content[posCloseCurly] == '}') {
          content[posCloseCurly] = ' '; // replace '}'
        } else {
          std::string::size_type posBlockClose = content.find_last_of('}');
          if (posBlockClose != std::string::npos) {
            content[posBlockClose] = ' '; // replace '}'
          }
          std::string::size_type posComment
            = content.find_first_not_of(whitespace, posBlockClose);
          if (posComment != std::string::npos
              && content[posComment] == '/' && content[posComment+1] == '/') {
            // More text (comments) are okay after the last '}', but
            // we can not easily find it to remove it (so we need to upgrade
            // this code to better handle the case with comments or
            // preprocessor code before and after the leading { and
            // trailing })
            while (posComment <= posCloseCurly) {
              content[posComment++] = ' '; // replace '}' and comment
            }
          } else {
            content[posCloseCurly] = '{';
            // By putting the '{' back, we keep the code as consistent as
            // the user wrote it ... but we should still warn that we not
            // goint to treat this file an unamed macro.
            llvm::errs()
              << "Warning in cling::MetaProcessor: can not find the closing '}', "
              << llvm::sys::path::filename(filename)
              << " is not handled as an unamed script!\n";
          } // did not find "//"
        } // remove comments after the trailing '}'
      } // find '}'
    } // ignore outermost block

    std::string strFilename(filename.str());
    m_CurrentlyExecutingFile = strFilename;
    bool topmost = !m_TopExecutingFile.data();
    if (topmost)
      m_TopExecutingFile = m_CurrentlyExecutingFile;
    Interpreter::CompilationResult ret;
    // We don't want to value print the results of a unnamed macro.
    content = "#line 2 \"" + filename.str() + "\" \n" + content;
    if (process((content + ";").c_str(), ret, result)) {
      // Input file has to be complete.
       llvm::errs()
          << "Error in cling::MetaProcessor: file "
          << llvm::sys::path::filename(filename)
          << " is incomplete (missing parenthesis or similar)!\n";
      ret = Interpreter::kFailure;
    }
    m_CurrentlyExecutingFile = llvm::StringRef();
    if (topmost)
      m_TopExecutingFile = llvm::StringRef();
    return ret;
  }

  void MetaProcessor::setFileStream(llvm::StringRef file, bool append, int fd,
              llvm::SmallVector<llvm::SmallString<128>, 2>& prevFileStack) {
    // If we have a fileName to redirect to store it.
    if (!file.empty()) {
      prevFileStack.push_back(file);
      // pop and push a null terminating 0.
      // SmallVectorImpl<T> does not have a c_str(), thus instead of casting to
      // a SmallString<T> we null terminate the data that we have and pop the
      // 0 char back.
      prevFileStack.back().push_back(0);
      prevFileStack.back().pop_back();
      if (!append) {
        FILE * f;
        if (!(f = fopen(file.data(), "w"))) {
          llvm::errs() << "cling::MetaProcessor::setFileStream:"
                       " The file path " << file.data() << "is not valid.\n";
        } else {
          fclose(f);
        }
      }
    // Else unredirection, so switch to the previous file.
    } else {
      // If there is no previous file on the stack we pop the file
      if (!prevFileStack.empty()) {
        prevFileStack.pop_back();
      }
    }
  }

  void MetaProcessor::setStdStream(llvm::StringRef file,
                                   RedirectionScope stream, bool append) {

    if (stream & kSTDOUT) {
      setFileStream(file, append, STDOUT_FILENO, m_PrevStdoutFileName);
    }
    if (stream & kSTDERR) {
      setFileStream(file, append, STDERR_FILENO, m_PrevStderrFileName);
    }
  }

  int MetaProcessor::copyFileDescriptor(int fd) {
    int backupFD = dup(fd);
    if (backupFD < 0) {
      llvm::errs() << "MetaProcessor::copyFileDescriptor: Duplicating the file"
                   " descriptor " << fd << "resulted in an error."
                   " Will not be able to unredirect.\n";
    }
    return backupFD;
  }

  void MetaProcessor::registerUnloadPoint(const Transaction* T,
                                          llvm::StringRef filename) {
    m_MetaParser->getActions().registerUnloadPoint(T, filename);
  }

} // end namespace cling
<|endoftext|>


<commit_before>#include <carl_safety/nav_safety.h>

NavSafety::NavSafety() :
    acMoveBase("/move_base", true),
    acHome("jaco_arm/home_arm", true),
    asSafeMove(node, "/move_base_safe", boost::bind(&NavSafety::safeMoveCallback, this, _1), false)
{
  // a private handle for this ROS node (allows retrieval of relative parameters)
  ros::NodeHandle private_nh("~");
  private_nh.param<bool>("use_teleop_safety", use_teleop_safety, false);

  // read in parameters
  std::string str;
  private_nh.param<std::string>("controller_type", str, "digital");
  if (str.compare("digital") == 0)
    controllerType = DIGITAL;
  else
    controllerType = ANALOG;

  // ROS topics
  if(use_teleop_safety)
    baseCommandPublisher = node.advertise<geometry_msgs::Twist>("cmd_vel_safety_check", 1);
  else
    baseCommandPublisher = node.advertise<geometry_msgs::Twist>("cmd_vel", 1);

  safeBaseCommandSubscriber = node.subscribe("cmd_vel_safe", 1, &NavSafety::safeBaseCommandCallback, this);
  joySubscriber = node.subscribe("joy", 1, &NavSafety::joyCallback, this);
  robotPoseSubscriber = node.subscribe("robot_pose", 1, &NavSafety::poseCallback, this);

  // ROS services
  jacoPosClient = node.serviceClient<wpi_jaco_msgs::GetAngularPosition>("jaco_arm/get_angular_position");

  //initialization
  stopped = false;
  x = 0.0;
  y = 0.0;
  theta = 0.0;
  retractPos.resize(6);
  retractPos[0] = -2.57;
  retractPos[1] = 1.39;
  retractPos[2] = .527;
  retractPos[3] = -.084;
  retractPos[4] = .515;
  retractPos[5] = -1.745;

  asSafeMove.start();
}

void NavSafety::joyCallback(const sensor_msgs::Joy::ConstPtr& joy)
{
  if (controllerType == DIGITAL)
  {
    if (joy->buttons.at(8) == 1)
    {
      stopped = true;
      cancelNavGoals();
    }
    else if (joy->buttons.at(9) == 1)
      stopped = false;
  }
  else
  {
    if (joy->buttons.at(6) == 1)
    {
      stopped = true;
      cancelNavGoals();
    }
    else if (joy->buttons.at(7) == 1)
      stopped = false;
  }
}

void NavSafety::safeBaseCommandCallback(const geometry_msgs::Twist::ConstPtr& msg)
{
  if (!stopped)
  {
    if (!isArmRetracted())
    {
      ROS_INFO("Overriding manual navigation because arm is not retracted.");
      return;
    }
    if (x < BOUNDARY_X && y > BOUNDARY_Y)
    {
      //pass command through
      baseCommandPublisher.publish(*msg);
    }
    else
    {
      if (x >= BOUNDARY_X)
      {
        if (theta > -PI / 2.0 && theta < PI / 2.0)
        {
          //only publish if going backwards (left on map)
          if (msg->linear.x <= 0.0)
            baseCommandPublisher.publish(*msg);
        }
        else
        {
          //only publish if going forwards (left on map)
          if (msg->linear.x >= 0.0)
            baseCommandPublisher.publish(*msg);
        }
      }

      if (y <= BOUNDARY_Y)
      {
        if (theta > 0.0)
        {
          //only publish if going forwards (up on map)
          if (msg->linear.x <= 0.0)
            baseCommandPublisher.publish(*msg);
        }
        else
        {
          //only publish if going backwards (up on map)
          if (msg->linear.x >= 0.0)
            baseCommandPublisher.publish(*msg);
        }
      }
    }
  }
}

void NavSafety::cancelNavGoals()
{
  acMoveBase.cancelAllGoals();
  move_base_msgs::MoveBaseResult moveResult;
  asSafeMove.setAborted(moveResult, "Navigation aborted for safety reasons.");
}

void NavSafety::poseCallback(const geometry_msgs::Pose::ConstPtr& msg)
{
  x = msg->position.x;
  y = msg->position.y;

  //convert quaternion to yaw
  float q0 = msg->orientation.w;
  float q1 = msg->orientation.x;
  float q2 = msg->orientation.y;
  float q3 = msg->orientation.z;
  theta = -atan2(2 * (q0 * q3 + q1 * q2), 1 - 2 * (q2 * q2 + q3 * q3));
}

void NavSafety::safeMoveCallback(const move_base_msgs::MoveBaseGoalConstPtr &goal)
{
  if (!stopped)
  {
    if (!isArmRetracted())
    {
      ROS_INFO("Retracting arm for safe navigation...");
      wpi_jaco_msgs::HomeArmGoal retractGoal;
      retractGoal.retract = true;
      retractGoal.retractPosition.position = true;
      retractGoal.retractPosition.armCommand = true;
      retractGoal.retractPosition.fingerCommand = false;
      retractGoal.retractPosition.repeat = false;
      retractGoal.retractPosition.joints.resize(6);
      retractGoal.retractPosition.joints = retractPos;
      acHome.sendGoal(retractGoal);
      acHome.waitForResult(ros::Duration(15.0));
      ros::Duration(3.0).sleep();
    }
    ROS_INFO("Sending nav goal to move_base action server.");
    acMoveBase.sendGoal(*goal);
    acMoveBase.waitForResult();
    asSafeMove.setSucceeded(*acMoveBase.getResult());
    ROS_INFO("Finished");
  }
  else
  {
    move_base_msgs::MoveBaseResult moveResult;
    asSafeMove.setAborted(moveResult, "Navigation aborted for safety reasons.");
  }
}

bool NavSafety::isArmRetracted()
{
  float dstFromRetract = 0;

  //get joint positions
  wpi_jaco_msgs::GetAngularPosition::Request req;
  wpi_jaco_msgs::GetAngularPosition::Response res;
  if(!jacoPosClient.call(req, res))
  {
    ROS_INFO("Could not call Jaco joint position service.");
    move_base_msgs::MoveBaseResult moveResult;
    asSafeMove.setAborted(moveResult, "Navigation aborted for safety reasons.");
    return false;
  }

  for (unsigned int i = 0; i < 6; i ++)
  {
    dstFromRetract += fabs(retractPos[i] - res.pos[i]);
  }

  if (dstFromRetract > 0.175)
    return false;
  return true;
}

int main(int argc, char **argv)
{
  // initialize ROS and the node
  ros::init(argc, argv, "nav_safety");

  NavSafety n;

  ros::spin();

  return EXIT_SUCCESS;
}
<commit_msg>Removed some debugging statements<commit_after>#include <carl_safety/nav_safety.h>

NavSafety::NavSafety() :
    acMoveBase("/move_base", true),
    acHome("jaco_arm/home_arm", true),
    asSafeMove(node, "/move_base_safe", boost::bind(&NavSafety::safeMoveCallback, this, _1), false)
{
  // a private handle for this ROS node (allows retrieval of relative parameters)
  ros::NodeHandle private_nh("~");
  private_nh.param<bool>("use_teleop_safety", use_teleop_safety, false);

  // read in parameters
  std::string str;
  private_nh.param<std::string>("controller_type", str, "digital");
  if (str.compare("digital") == 0)
    controllerType = DIGITAL;
  else
    controllerType = ANALOG;

  // ROS topics
  if(use_teleop_safety)
    baseCommandPublisher = node.advertise<geometry_msgs::Twist>("cmd_vel_safety_check", 1);
  else
    baseCommandPublisher = node.advertise<geometry_msgs::Twist>("cmd_vel", 1);

  safeBaseCommandSubscriber = node.subscribe("cmd_vel_safe", 1, &NavSafety::safeBaseCommandCallback, this);
  joySubscriber = node.subscribe("joy", 1, &NavSafety::joyCallback, this);
  robotPoseSubscriber = node.subscribe("robot_pose", 1, &NavSafety::poseCallback, this);

  // ROS services
  jacoPosClient = node.serviceClient<wpi_jaco_msgs::GetAngularPosition>("jaco_arm/get_angular_position");

  //initialization
  stopped = false;
  x = 0.0;
  y = 0.0;
  theta = 0.0;
  retractPos.resize(6);
  retractPos[0] = -2.57;
  retractPos[1] = 1.39;
  retractPos[2] = .527;
  retractPos[3] = -.084;
  retractPos[4] = .515;
  retractPos[5] = -1.745;

  asSafeMove.start();
}

void NavSafety::joyCallback(const sensor_msgs::Joy::ConstPtr& joy)
{
  if (controllerType == DIGITAL)
  {
    if (joy->buttons.at(8) == 1)
    {
      stopped = true;
      cancelNavGoals();
    }
    else if (joy->buttons.at(9) == 1)
      stopped = false;
  }
  else
  {
    if (joy->buttons.at(6) == 1)
    {
      stopped = true;
      cancelNavGoals();
    }
    else if (joy->buttons.at(7) == 1)
      stopped = false;
  }
}

void NavSafety::safeBaseCommandCallback(const geometry_msgs::Twist::ConstPtr& msg)
{
  if (!stopped)
  {
    if (!isArmRetracted())
    {
      //ignore movement command if arm is in a dangerous position
      return;
    }
    if (x < BOUNDARY_X && y > BOUNDARY_Y)
    {
      //pass command through
      baseCommandPublisher.publish(*msg);
    }
    else
    {
      if (x >= BOUNDARY_X)
      {
        if (theta > -PI / 2.0 && theta < PI / 2.0)
        {
          //only publish if going backwards (left on map)
          if (msg->linear.x <= 0.0)
            baseCommandPublisher.publish(*msg);
        }
        else
        {
          //only publish if going forwards (left on map)
          if (msg->linear.x >= 0.0)
            baseCommandPublisher.publish(*msg);
        }
      }

      if (y <= BOUNDARY_Y)
      {
        if (theta > 0.0)
        {
          //only publish if going forwards (up on map)
          if (msg->linear.x <= 0.0)
            baseCommandPublisher.publish(*msg);
        }
        else
        {
          //only publish if going backwards (up on map)
          if (msg->linear.x >= 0.0)
            baseCommandPublisher.publish(*msg);
        }
      }
    }
  }
}

void NavSafety::cancelNavGoals()
{
  acMoveBase.cancelAllGoals();
  move_base_msgs::MoveBaseResult moveResult;
  asSafeMove.setAborted(moveResult, "Navigation aborted for safety reasons.");
}

void NavSafety::poseCallback(const geometry_msgs::Pose::ConstPtr& msg)
{
  x = msg->position.x;
  y = msg->position.y;

  //convert quaternion to yaw
  float q0 = msg->orientation.w;
  float q1 = msg->orientation.x;
  float q2 = msg->orientation.y;
  float q3 = msg->orientation.z;
  theta = -atan2(2 * (q0 * q3 + q1 * q2), 1 - 2 * (q2 * q2 + q3 * q3));
}

void NavSafety::safeMoveCallback(const move_base_msgs::MoveBaseGoalConstPtr &goal)
{
  if (!stopped)
  {
    if (!isArmRetracted())
    {
      ROS_INFO("Retracting arm for safe navigation...");
      wpi_jaco_msgs::HomeArmGoal retractGoal;
      retractGoal.retract = true;
      retractGoal.retractPosition.position = true;
      retractGoal.retractPosition.armCommand = true;
      retractGoal.retractPosition.fingerCommand = false;
      retractGoal.retractPosition.repeat = false;
      retractGoal.retractPosition.joints.resize(6);
      retractGoal.retractPosition.joints = retractPos;
      acHome.sendGoal(retractGoal);
      acHome.waitForResult(ros::Duration(15.0));
      ros::Duration(3.0).sleep();
    }
    ROS_INFO("Sending nav goal to move_base action server.");
    acMoveBase.sendGoal(*goal);
    acMoveBase.waitForResult();
    asSafeMove.setSucceeded(*acMoveBase.getResult());
    ROS_INFO("Navigation finished");
  }
  else
  {
    move_base_msgs::MoveBaseResult moveResult;
    asSafeMove.setAborted(moveResult, "Navigation aborted for safety reasons.");
  }
}

bool NavSafety::isArmRetracted()
{
  float dstFromRetract = 0;

  //get joint positions
  wpi_jaco_msgs::GetAngularPosition::Request req;
  wpi_jaco_msgs::GetAngularPosition::Response res;
  if(!jacoPosClient.call(req, res))
  {
    ROS_INFO("Could not call Jaco joint position service.");
    move_base_msgs::MoveBaseResult moveResult;
    asSafeMove.setAborted(moveResult, "Navigation aborted for safety reasons.");
    return false;
  }

  for (unsigned int i = 0; i < 6; i ++)
  {
    dstFromRetract += fabs(retractPos[i] - res.pos[i]);
  }

  if (dstFromRetract > 0.175)
    return false;
  return true;
}

int main(int argc, char **argv)
{
  // initialize ROS and the node
  ros::init(argc, argv, "nav_safety");

  NavSafety n;

  ros::spin();

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>//*****************************************************************************
// Copyright 2017-2018 Intel Corporation
//
// 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 <chrono>
#include <condition_variable>
#include <ctime>
#include <functional>
#include <iomanip>
#include <iostream>
#include <mutex>
#include <thread>

#include "ngraph/log.hpp"

using namespace std;
using namespace ngraph;

ostream& ngraph::get_nil_stream()
{
    static stringstream nil;
    return nil;
}

void ngraph::default_logger_handler_func(const string& s)
{
    cout << s << endl;
}

LogHelper::LogHelper(LOG_TYPE type,
                     const char* file,
                     int line,
                     function<void(const string&)> handler_func)
    : m_handler_func(handler_func)
{
    switch (type)
    {
    case LOG_TYPE::_LOG_TYPE_ERROR: m_stream << "[ERR] "; break;
    case LOG_TYPE::_LOG_TYPE_WARNING: m_stream << "[WARN] "; break;
    case LOG_TYPE::_LOG_TYPE_INFO: m_stream << "[INFO] "; break;
    case LOG_TYPE::_LOG_TYPE_DEBUG: m_stream << "[DEBUG] "; break;
    }

    time_t tt = chrono::system_clock::to_time_t(chrono::system_clock::now());
    auto tm = gmtime(&tt);
    char buffer[256];
    strftime(buffer, sizeof(buffer), "%Y-%m-%dT%H:%M:%Sz", tm);
    m_stream << buffer << " ";

    m_stream << file;
    m_stream << " " << line;
    m_stream << "\t";
}

LogHelper::~LogHelper()
{
    if (m_handler_func)
    {
        m_handler_func(m_stream.str());
    }
    // Logger::log_item(m_stream.str());
}
<commit_msg>Make debug logging threadsafe (#1977)<commit_after>//*****************************************************************************
// Copyright 2017-2018 Intel Corporation
//
// 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 <chrono>
#include <condition_variable>
#include <ctime>
#include <functional>
#include <iomanip>
#include <iostream>
#include <mutex>
#include <thread>

#include "ngraph/log.hpp"

using namespace std;
using namespace ngraph;

namespace
{
    class NilStreamBuf final : public streambuf
    {
        // N.B. We derive from the base streambuf implementation, in
        //      which underflow() and overflow() both return
        //      Traits::eof() -- any access returns a failure.
    };
}

ostream& ngraph::get_nil_stream()
{
    // N.B. When debug logging is disabled, multiple threads may
    //      access the nil stream simultaneously, so it's important to
    //      return a threadsafe nil stream implementation.
    static NilStreamBuf nil_buf;
    static ostream nil{&nil_buf};
    return nil;
}

void ngraph::default_logger_handler_func(const string& s)
{
    cout << s << endl;
}

LogHelper::LogHelper(LOG_TYPE type,
                     const char* file,
                     int line,
                     function<void(const string&)> handler_func)
    : m_handler_func(handler_func)
{
    switch (type)
    {
    case LOG_TYPE::_LOG_TYPE_ERROR: m_stream << "[ERR] "; break;
    case LOG_TYPE::_LOG_TYPE_WARNING: m_stream << "[WARN] "; break;
    case LOG_TYPE::_LOG_TYPE_INFO: m_stream << "[INFO] "; break;
    case LOG_TYPE::_LOG_TYPE_DEBUG: m_stream << "[DEBUG] "; break;
    }

    time_t tt = chrono::system_clock::to_time_t(chrono::system_clock::now());
    auto tm = gmtime(&tt);
    char buffer[256];
    strftime(buffer, sizeof(buffer), "%Y-%m-%dT%H:%M:%Sz", tm);
    m_stream << buffer << " ";

    m_stream << file;
    m_stream << " " << line;
    m_stream << "\t";
}

LogHelper::~LogHelper()
{
    if (m_handler_func)
    {
        m_handler_func(m_stream.str());
    }
    // Logger::log_item(m_stream.str());
}
<|endoftext|>


<commit_before>/* $Id: math.C,v 1.17 2007-03-01 15:53:22 phruksar Exp $ */
#include "alara.h"
#include "Matrix.h"

/* this is used to determine how many terms are needed in the expansion */
#define MAXEXPTOL 1e-15

/* This is the maximum number of terms allowed for the expansion method
 * If more are needed, the inversion method is used */
#define MAXNUMEXPTERMS 15

/* This is used to determine if poles are degenerate.  Loops should
 * generate poles which are exactly the same, but poles with small
 * relative differences may act as degeneracies anyway */
#define SMALL_REL_DIFF 1e-8

/* routine for to calculate factorial */
double fact(int i)
{
  int idx,idx2;
  /* create a look-up table for factorials */
  const int maxFactorial = 50;
  static double *factorials = NULL;

  if (factorials == NULL)
    {
      factorials = new double[maxFactorial];
      for (idx=0;idx<maxFactorial;idx++)
	{
	  idx2 = idx;
	  factorials[idx] = 1;
	  while (idx2>1) factorials[idx] *= idx2--;
	}
    }

  if (i < maxFactorial)
    return factorials[i];
  else
    {
      double result=1;

      while (i>1) result *= i--;

      return result;
    }
}

double bateman(int row, int col, double* d, double t, int& finitePositive)
{
  //A short-term solution to a loop problem is to bypass a Bateman method.
  ////////
//   double sum_la = laplaceExpansion(row, col, d, t, finitePositive);
//   if (finitePositive)
//     return sum_la;
//   else
    return laplaceInverse(row, col, d, t, finitePositive);
  ////////

  double sum, sumInc, den;
  int term, denTerm;

  finitePositive = TRUE;

  sum = 0;
  sumInc = 0;

  for (term=col;term<row;term++)
    {
      /* set denominator element based on Laplace root: d[term]
       * (traditional analytic inverse Laplace transform) */
      den = 1;

      for (denTerm=col;denTerm<term;denTerm++)
	den *= (d[denTerm]-d[term]);

      for (denTerm++;denTerm<=row;denTerm++)
	den *= (d[denTerm]-d[term]);

      /* set numerator element based on Laplace root: d[term] */
      sumInc = expm1(-d[term]*t)-expm1(-d[row]*t);

      /* add element based on Laplace root: d[term] */
      sum += sumInc/den;
    }

  /* negative results are due to round-off error and
   * imply very small results */
  if (sum < 0 || isnan(sum))
    {
      finitePositive = FALSE;
      return 0;
    }
  else
   return sum;

};

double dGn(int idx, double *pole, int *mult, int numPoles, int termNum)
{
  int pNum, pwr;
  double invPwrSum,result = 0;

  if (termNum==0)   /* End Condition - 0th derivative */
    /* return inverse product of pole-otherPoles */
    {
      result = 1;

      /* all poles before the current pole */
      for (pNum=0; pNum<idx; pNum++)
	result /= pow( pole[pNum] - pole[idx] , mult[pNum] );

      /* all poles after the current pole */
      for (pNum++; pNum<numPoles; pNum++)
	result /= pow( pole[pNum] - pole[idx] , mult[pNum] );
    }
  else
    for (pwr=termNum;pwr>0;pwr--)
      {
	invPwrSum = 0;

	/* all poles before the current pole */
	for (pNum=0; pNum<idx; pNum++)
	  invPwrSum += mult[pNum] * pow( pole[pNum]-pole[idx] , -pwr );

	/* all poles after the current pole */
	for (pNum++; pNum<numPoles; pNum++)
	  invPwrSum += mult[pNum] * pow( pole[pNum]-pole[idx] , -pwr );

	/* recursively add terms */
	result += -2*(pwr%2 -.5) * (fact(termNum-1)/fact(termNum-pwr))
	  * invPwrSum * dGn(idx,pole,mult,numPoles,termNum-pwr);
      }

  return result;

}

double laplaceInverse(int row, int col, double *d, double t,
		      int& finitePositive)
{
  int idx, checkIdx, multCnt;
  int numPoles = 0;
  int *mult = new int[row-col+1];
  double *pole = new double[row-col+1];
  double poleResult, result  = 0;

  finitePositive = TRUE;

  /* index all the poles with the multiplicities */
  for (idx = col;idx<=row;idx++)
    {
      for (checkIdx=0;checkIdx<numPoles;checkIdx++)
	if ( fabs((d[idx]-pole[checkIdx]))<SMALL_REL_DIFF*d[idx] )
	  {
	    mult[checkIdx]++;
	    break;
	  }
      if (checkIdx == numPoles)
	{
	  pole[checkIdx] = d[idx];
	  mult[checkIdx] = 1;
	  numPoles++;
	}
    }

  /* perform recursive analytic Laplace inversion */
  for (idx=0;idx<numPoles;idx++)
    {
      poleResult = 0;

      for (multCnt=mult[idx];multCnt>0;multCnt--)
	poleResult += dGn(idx, pole, mult, numPoles, mult[idx] - multCnt)
	  * pow(t,multCnt-1)
	  / fact(multCnt-1)
	  / fact(mult[idx]-multCnt) ;

      result += poleResult * exp(-pole[idx]*t);
    }

  delete mult;
  delete pole;

  if (result < 0 || isnan(result))
    {
      finitePositive = FALSE;
      return 0;
    }
  else
    return result;

}

/* function to return a rough estimate of whether or not the expansion technique
   will converge quickly enough */
int smallExpansion(int row, int col, double *d, double t)
{
  int poleNum, n=MAXNUMEXPTERMS;
  int rank=row-col+1;
  double max=0;

  /* for each pole in the problem */
  for (poleNum=col;poleNum<=row;poleNum++)
    /* determine the largest pole */
    max = d[poleNum]>max?d[poleNum]:max;

  /* using a defined maximum number of terms, if the last term results
   * in a correction which is too large */
  if (rank*pow(max*t,n)*fact(rank-1)/(n*fact(n+rank-1)) > MAXEXPTOL)
    /* if too large, return false */
    return FALSE;

  return TRUE;
}

double laplaceExpansion(int row, int col, double *d, double t, int &converged)
{

  int idx, termNum;
  int sz = row-col;
  double result, correction;

  /* initialize matrix with destruction rates */
  Matrix poleMat(d,sz+1,col);
  Matrix powPoleMat(sz+1);

  /* innocent until proven guilty */
  converged = TRUE;

  /* zeroth term is simply the correct power of t/n!  */
  result = pow(t,sz)/fact(sz);

  /* for each successive term */
  for (termNum=1;termNum<MAXNUMEXPTERMS;termNum++)
    {
      /* multiply the power matrix by the non-power matrix */
      powPoleMat *= poleMat;

      /* power of t/n! times coefficient, with alternating sign!! */
      correction = powPoleMat.rowSum(sz) * ( 1-2*(termNum%2) )
	* pow(t,termNum+sz)/fact(termNum+sz);

      if (fabs(correction/result) > MAXEXPTOL)
	/* use this term if significant */
	result += correction;
      else
	/* otherwise break */
	break;
    }

  /* for monstrous decay rates (e.g. Be-8) the correction or
   * result may become infinite */
  if (termNum == MAXNUMEXPTERMS || isnan(result))
    converged = FALSE;

  return result;
}

double fillTElement(int row, int col, double *P, double *d, double t,
		    int* loopRank, int rank)
{

  int idx,loopIdx,parLoopIdx;
  int defSuccess, altSuccess;
  double result;

  /* process loop information in reverse problem */
  if (rank != row)
    {
      loopIdx = loopRank[rank];
      parLoopIdx = loopRank[rank+1];
    }
  else
    {
      loopIdx = loopRank[row];
      parLoopIdx = loopRank[row-1];
    }

  /* if there is no loop, at this level, row - loopIdx = -1 */
  if (loopIdx == -1)
    loopIdx = row+1;

  /* do this product up front to eliminate costly
   * computation which may end in 0 anyway */
  double productionProduct = 1;
  for (idx=col;idx<row;idx++)
    productionProduct *= P[idx+1];

  if (productionProduct == 0)
    return productionProduct;

  /* implement default method */

  /* This seemingly complicated condition saves using the loop
   * solution during a reference calculation when only the last
   * isotope introduces the loop.  In this case, there is no real
   * degeneracy, since the destruction rate of the last isotope is
   * zero'ed for a reference calculation.  The condition can be
   * understood as follows:
   *  - when checking for loop solution, if we are calculating the
   *    production from an isotope inside the loop, generally use
   *    the loop sol'n, but only iff
   *  - only the last isotope can ever have a destruction rate of
   *    zero
   *      - if d[row] > 0, use loop sol'n
   *  - even if last isotope does have a 0 destruction rate, if
   *    the previous isotope was already in a loop, we need to use
   *    the loop sol'n
   *      - if loopRank[row-1] > -1, check for loop sol'n \
   *        (This check must be done after the first one because
   *        it ensures that we are not checking loopRank[-1])*/
  if (col<=row-loopIdx && (d[row] > 0 || parLoopIdx >-1))
    {
      /* get rough estimate of success of expansion method */
      defSuccess = smallExpansion(row,col,d,t);

      /* if we think the expansion method is good, use it */
      if (defSuccess)
	result = laplaceExpansion(row,col,d,t,defSuccess);

      /* if either we think the expansion method is bad,
         or we prove that it is bad, use the inversion method */
      if (!defSuccess)
	result = laplaceInverse(row,col,d,t,altSuccess);
    }
  else
    result = bateman(row,col,d,t,altSuccess);

  /* used during debugging
  if (isinf(result) || isnan(result) )
    error(2001,"No mathematical method was successful!");  */

  return result*productionProduct;
}

<commit_msg>Get rid of Bateman bypassing<commit_after>/* $Id: math.C,v 1.18 2007-03-09 16:45:09 phruksar Exp $ */
#include "alara.h"
#include "Matrix.h"

/* this is used to determine how many terms are needed in the expansion */
#define MAXEXPTOL 1e-15

/* This is the maximum number of terms allowed for the expansion method
 * If more are needed, the inversion method is used */
#define MAXNUMEXPTERMS 15

/* This is used to determine if poles are degenerate.  Loops should
 * generate poles which are exactly the same, but poles with small
 * relative differences may act as degeneracies anyway */
#define SMALL_REL_DIFF 1e-8

/* routine for to calculate factorial */
double fact(int i)
{
  int idx,idx2;
  /* create a look-up table for factorials */
  const int maxFactorial = 50;
  static double *factorials = NULL;

  if (factorials == NULL)
    {
      factorials = new double[maxFactorial];
      for (idx=0;idx<maxFactorial;idx++)
	{
	  idx2 = idx;
	  factorials[idx] = 1;
	  while (idx2>1) factorials[idx] *= idx2--;
	}
    }

  if (i < maxFactorial)
    return factorials[i];
  else
    {
      double result=1;

      while (i>1) result *= i--;

      return result;
    }
}

double bateman(int row, int col, double* d, double t, int& finitePositive)
{
  double sum, sumInc, den;
  int term, denTerm;

  finitePositive = TRUE;

  sum = 0;
  sumInc = 0;

  for (term=col;term<row;term++)
    {
      /* set denominator element based on Laplace root: d[term]
       * (traditional analytic inverse Laplace transform) */
      den = 1;

      for (denTerm=col;denTerm<term;denTerm++)
	den *= (d[denTerm]-d[term]);

      for (denTerm++;denTerm<=row;denTerm++)
	den *= (d[denTerm]-d[term]);

      /* set numerator element based on Laplace root: d[term] */
      sumInc = expm1(-d[term]*t)-expm1(-d[row]*t);

      /* add element based on Laplace root: d[term] */
      sum += sumInc/den;
    }

  /* negative results are due to round-off error and
   * imply very small results */
  if (sum < 0 || isnan(sum))
    {
      finitePositive = FALSE;
      return 0;
    }
  else
   return sum;

};

double dGn(int idx, double *pole, int *mult, int numPoles, int termNum)
{
  int pNum, pwr;
  double invPwrSum,result = 0;

  if (termNum==0)   /* End Condition - 0th derivative */
    /* return inverse product of pole-otherPoles */
    {
      result = 1;

      /* all poles before the current pole */
      for (pNum=0; pNum<idx; pNum++)
	result /= pow( pole[pNum] - pole[idx] , mult[pNum] );

      /* all poles after the current pole */
      for (pNum++; pNum<numPoles; pNum++)
	result /= pow( pole[pNum] - pole[idx] , mult[pNum] );
    }
  else
    for (pwr=termNum;pwr>0;pwr--)
      {
	invPwrSum = 0;

	/* all poles before the current pole */
	for (pNum=0; pNum<idx; pNum++)
	  invPwrSum += mult[pNum] * pow( pole[pNum]-pole[idx] , -pwr );

	/* all poles after the current pole */
	for (pNum++; pNum<numPoles; pNum++)
	  invPwrSum += mult[pNum] * pow( pole[pNum]-pole[idx] , -pwr );

	/* recursively add terms */
	result += -2*(pwr%2 -.5) * (fact(termNum-1)/fact(termNum-pwr))
	  * invPwrSum * dGn(idx,pole,mult,numPoles,termNum-pwr);
      }

  return result;

}

double laplaceInverse(int row, int col, double *d, double t,
		      int& finitePositive)
{
  int idx, checkIdx, multCnt;
  int numPoles = 0;
  int *mult = new int[row-col+1];
  double *pole = new double[row-col+1];
  double poleResult, result  = 0;

  finitePositive = TRUE;

  /* index all the poles with the multiplicities */
  for (idx = col;idx<=row;idx++)
    {
      for (checkIdx=0;checkIdx<numPoles;checkIdx++)
	if ( fabs((d[idx]-pole[checkIdx]))<SMALL_REL_DIFF*d[idx] )
	  {
	    mult[checkIdx]++;
	    break;
	  }
      if (checkIdx == numPoles)
	{
	  pole[checkIdx] = d[idx];
	  mult[checkIdx] = 1;
	  numPoles++;
	}
    }

  /* perform recursive analytic Laplace inversion */
  for (idx=0;idx<numPoles;idx++)
    {
      poleResult = 0;

      for (multCnt=mult[idx];multCnt>0;multCnt--)
	poleResult += dGn(idx, pole, mult, numPoles, mult[idx] - multCnt)
	  * pow(t,multCnt-1)
	  / fact(multCnt-1)
	  / fact(mult[idx]-multCnt) ;

      result += poleResult * exp(-pole[idx]*t);
    }

  delete mult;
  delete pole;

  if (result < 0 || isnan(result))
    {
      finitePositive = FALSE;
      return 0;
    }
  else
    return result;

}

/* function to return a rough estimate of whether or not the expansion technique
   will converge quickly enough */
int smallExpansion(int row, int col, double *d, double t)
{
  int poleNum, n=MAXNUMEXPTERMS;
  int rank=row-col+1;
  double max=0;

  /* for each pole in the problem */
  for (poleNum=col;poleNum<=row;poleNum++)
    /* determine the largest pole */
    max = d[poleNum]>max?d[poleNum]:max;

  /* using a defined maximum number of terms, if the last term results
   * in a correction which is too large */
  if (rank*pow(max*t,n)*fact(rank-1)/(n*fact(n+rank-1)) > MAXEXPTOL)
    /* if too large, return false */
    return FALSE;

  return TRUE;
}

double laplaceExpansion(int row, int col, double *d, double t, int &converged)
{

  int idx, termNum;
  int sz = row-col;
  double result, correction;

  /* initialize matrix with destruction rates */
  Matrix poleMat(d,sz+1,col);
  Matrix powPoleMat(sz+1);

  /* innocent until proven guilty */
  converged = TRUE;

  /* zeroth term is simply the correct power of t/n!  */
  result = pow(t,sz)/fact(sz);

  /* for each successive term */
  for (termNum=1;termNum<MAXNUMEXPTERMS;termNum++)
    {
      /* multiply the power matrix by the non-power matrix */
      powPoleMat *= poleMat;

      /* power of t/n! times coefficient, with alternating sign!! */
      correction = powPoleMat.rowSum(sz) * ( 1-2*(termNum%2) )
	* pow(t,termNum+sz)/fact(termNum+sz);

      if (fabs(correction/result) > MAXEXPTOL)
	/* use this term if significant */
	result += correction;
      else
	/* otherwise break */
	break;
    }

  /* for monstrous decay rates (e.g. Be-8) the correction or
   * result may become infinite */
  if (termNum == MAXNUMEXPTERMS || isnan(result))
    converged = FALSE;

  return result;
}

double fillTElement(int row, int col, double *P, double *d, double t,
		    int* loopRank, int rank)
{

  int idx,loopIdx,parLoopIdx;
  int defSuccess, altSuccess;
  double result;

  /* process loop information in reverse problem */
  if (rank != row)
    {
      loopIdx = loopRank[rank];
      parLoopIdx = loopRank[rank+1];
    }
  else
    {
      loopIdx = loopRank[row];
      parLoopIdx = loopRank[row-1];
    }

  /* if there is no loop, at this level, row - loopIdx = -1 */
  if (loopIdx == -1)
    loopIdx = row+1;

  /* do this product up front to eliminate costly
   * computation which may end in 0 anyway */
  double productionProduct = 1;
  for (idx=col;idx<row;idx++)
    productionProduct *= P[idx+1];

  if (productionProduct == 0)
    return productionProduct;

  /* implement default method */

  /* This seemingly complicated condition saves using the loop
   * solution during a reference calculation when only the last
   * isotope introduces the loop.  In this case, there is no real
   * degeneracy, since the destruction rate of the last isotope is
   * zero'ed for a reference calculation.  The condition can be
   * understood as follows:
   *  - when checking for loop solution, if we are calculating the
   *    production from an isotope inside the loop, generally use
   *    the loop sol'n, but only iff
   *  - only the last isotope can ever have a destruction rate of
   *    zero
   *      - if d[row] > 0, use loop sol'n
   *  - even if last isotope does have a 0 destruction rate, if
   *    the previous isotope was already in a loop, we need to use
   *    the loop sol'n
   *      - if loopRank[row-1] > -1, check for loop sol'n \
   *        (This check must be done after the first one because
   *        it ensures that we are not checking loopRank[-1])*/
  if (col<=row-loopIdx && (d[row] > 0 || parLoopIdx >-1))
    {
      /* get rough estimate of success of expansion method */
      defSuccess = smallExpansion(row,col,d,t);

      /* if we think the expansion method is good, use it */
      if (defSuccess)
	result = laplaceExpansion(row,col,d,t,defSuccess);

      /* if either we think the expansion method is bad,
         or we prove that it is bad, use the inversion method */
      if (!defSuccess)
	result = laplaceInverse(row,col,d,t,altSuccess);
    }
  else
    result = bateman(row,col,d,t,altSuccess);

  /* used during debugging
  if (isinf(result) || isnan(result) )
    error(2001,"No mathematical method was successful!");  */

  return result*productionProduct;
}

<|endoftext|>


<commit_before>//===-- AMDGPUSubtarget.cpp - AMDGPU Subtarget Information ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
/// \file
/// \brief Implements the AMDGPU specific subclass of TargetSubtarget.
//
//===----------------------------------------------------------------------===//

#include "AMDGPUSubtarget.h"

using namespace llvm;

#define GET_SUBTARGETINFO_ENUM
#define GET_SUBTARGETINFO_TARGET_DESC
#define GET_SUBTARGETINFO_CTOR
#include "AMDGPUGenSubtargetInfo.inc"

AMDGPUSubtarget::AMDGPUSubtarget(StringRef TT, StringRef CPU, StringRef FS) :
  AMDGPUGenSubtargetInfo(TT, CPU, FS), DumpCode(false) {
    InstrItins = getInstrItineraryForCPU(CPU);

  // Default card
  StringRef GPU = CPU;
  Is64bit = false;
  DefaultSize[0] = 64;
  DefaultSize[1] = 1;
  DefaultSize[2] = 1;
  HasVertexCache = false;
  TexVTXClauseSize = 0;
  Gen = AMDGPUSubtarget::R600;
  FP64 = false;
  CaymanISA = false;
  EnableIRStructurizer = true;
  EnableIfCvt = true;
  ParseSubtargetFeatures(GPU, FS);
  DevName = GPU;
}

bool
AMDGPUSubtarget::is64bit() const  {
  return Is64bit;
}
bool
AMDGPUSubtarget::hasVertexCache() const {
  return HasVertexCache;
}
short
AMDGPUSubtarget::getTexVTXClauseSize() const {
  return TexVTXClauseSize;
}
enum AMDGPUSubtarget::Generation
AMDGPUSubtarget::getGeneration() const {
  return Gen;
}
bool
AMDGPUSubtarget::hasHWFP64() const {
  return FP64;
}
bool
AMDGPUSubtarget::hasCaymanISA() const {
  return CaymanISA;
}
bool
AMDGPUSubtarget::IsIRStructurizerEnabled() const {
  return EnableIRStructurizer;
}
bool
AMDGPUSubtarget::isIfCvtEnabled() const {
  return EnableIfCvt;
}
bool
AMDGPUSubtarget::isTargetELF() const {
  return false;
}
size_t
AMDGPUSubtarget::getDefaultSize(uint32_t dim) const {
  if (dim > 3) {
    return 1;
  } else {
    return DefaultSize[dim];
  }
}

std::string
AMDGPUSubtarget::getDataLayout() const {
  std::string DataLayout = std::string(
   "e"
   "-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32"
   "-v16:16:16-v24:32:32-v32:32:32-v48:64:64-v64:64:64-v96:128:128-v128:128:128"
   "-v192:256:256-v256:256:256-v512:512:512-v1024:1024:1024-v2048:2048:2048"
   "-n32:64"
  );

  if (hasHWFP64()) {
    DataLayout.append("-f64:64:64");
  }

  if (is64bit()) {
    DataLayout.append("-p:64:64:64");
  } else {
    DataLayout.append("-p:32:32:32");
  }

  if (Gen >= AMDGPUSubtarget::SOUTHERN_ISLANDS) {
    DataLayout.append("-p3:32:32:32");
  }

  return DataLayout;
}

std::string
AMDGPUSubtarget::getDeviceName() const {
  return DevName;
}
<commit_msg>Fix an index array check.<commit_after>//===-- AMDGPUSubtarget.cpp - AMDGPU Subtarget Information ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
/// \file
/// \brief Implements the AMDGPU specific subclass of TargetSubtarget.
//
//===----------------------------------------------------------------------===//

#include "AMDGPUSubtarget.h"

using namespace llvm;

#define GET_SUBTARGETINFO_ENUM
#define GET_SUBTARGETINFO_TARGET_DESC
#define GET_SUBTARGETINFO_CTOR
#include "AMDGPUGenSubtargetInfo.inc"

AMDGPUSubtarget::AMDGPUSubtarget(StringRef TT, StringRef CPU, StringRef FS) :
  AMDGPUGenSubtargetInfo(TT, CPU, FS), DumpCode(false) {
    InstrItins = getInstrItineraryForCPU(CPU);

  // Default card
  StringRef GPU = CPU;
  Is64bit = false;
  DefaultSize[0] = 64;
  DefaultSize[1] = 1;
  DefaultSize[2] = 1;
  HasVertexCache = false;
  TexVTXClauseSize = 0;
  Gen = AMDGPUSubtarget::R600;
  FP64 = false;
  CaymanISA = false;
  EnableIRStructurizer = true;
  EnableIfCvt = true;
  ParseSubtargetFeatures(GPU, FS);
  DevName = GPU;
}

bool
AMDGPUSubtarget::is64bit() const  {
  return Is64bit;
}
bool
AMDGPUSubtarget::hasVertexCache() const {
  return HasVertexCache;
}
short
AMDGPUSubtarget::getTexVTXClauseSize() const {
  return TexVTXClauseSize;
}
enum AMDGPUSubtarget::Generation
AMDGPUSubtarget::getGeneration() const {
  return Gen;
}
bool
AMDGPUSubtarget::hasHWFP64() const {
  return FP64;
}
bool
AMDGPUSubtarget::hasCaymanISA() const {
  return CaymanISA;
}
bool
AMDGPUSubtarget::IsIRStructurizerEnabled() const {
  return EnableIRStructurizer;
}
bool
AMDGPUSubtarget::isIfCvtEnabled() const {
  return EnableIfCvt;
}
bool
AMDGPUSubtarget::isTargetELF() const {
  return false;
}
size_t
AMDGPUSubtarget::getDefaultSize(uint32_t dim) const {
  if (dim > 2) {
    return 1;
  } else {
    return DefaultSize[dim];
  }
}

std::string
AMDGPUSubtarget::getDataLayout() const {
  std::string DataLayout = std::string(
   "e"
   "-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32"
   "-v16:16:16-v24:32:32-v32:32:32-v48:64:64-v64:64:64-v96:128:128-v128:128:128"
   "-v192:256:256-v256:256:256-v512:512:512-v1024:1024:1024-v2048:2048:2048"
   "-n32:64"
  );

  if (hasHWFP64()) {
    DataLayout.append("-f64:64:64");
  }

  if (is64bit()) {
    DataLayout.append("-p:64:64:64");
  } else {
    DataLayout.append("-p:32:32:32");
  }

  if (Gen >= AMDGPUSubtarget::SOUTHERN_ISLANDS) {
    DataLayout.append("-p3:32:32:32");
  }

  return DataLayout;
}

std::string
AMDGPUSubtarget::getDeviceName() const {
  return DevName;
}
<|endoftext|>


<commit_before>//----------------------------------------------------------------------------
// electron-vibrancy
// Copyright 2016 arkenthera
//
// MIT License
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice
// shall be included in all copies or substantial
// portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//----------------------------------------------------------------------------
#include "./Vibrancy.h"
#include <dwmapi.h>
//----------------------------------------------------------------------------
namespace Vibrancy {
    static VibrancyHelper vibHelper_;

    Vibrancy::Vibrancy() {
    }

    Vibrancy::~Vibrancy() {
    }
    void Vibrancy::Init(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) {
        v8::Local<v8::FunctionTemplate> tpl =
            Nan::New<v8::FunctionTemplate>(SetVibrancy);

        tpl->InstanceTemplate()->SetInternalFieldCount(1);

        v8::Local<v8::FunctionTemplate> tpl1 =
            Nan::New<v8::FunctionTemplate>(AddView);
        tpl1->InstanceTemplate()->SetInternalFieldCount(1);

        v8::Local<v8::FunctionTemplate> tpl2 =
            Nan::New<v8::FunctionTemplate>(UpdateView);
        tpl2->InstanceTemplate()->SetInternalFieldCount(1);

        v8::Local<v8::FunctionTemplate> tpl3 =
            Nan::New<v8::FunctionTemplate>(RemoveView);
        tpl3->InstanceTemplate()->SetInternalFieldCount(1);

        Nan::Set(target,
            Nan::New("SetVibrancy").ToLocalChecked(),
            Nan::GetFunction(tpl).ToLocalChecked());

        Nan::Set(target,
            Nan::New("AddView").ToLocalChecked(),
            Nan::GetFunction(tpl1).ToLocalChecked());

        Nan::Set(target,
            Nan::New("UpdateView").ToLocalChecked(),
            Nan::GetFunction(tpl2).ToLocalChecked());

        Nan::Set(target,
            Nan::New("RemoveView").ToLocalChecked(),
            Nan::GetFunction(tpl3).ToLocalChecked());
    }

    NAN_METHOD(Vibrancy::SetVibrancy) {
        v8::Local<v8::Object> toggleStateObj =
            info[0].As<v8::Object>();
        v8::Local<v8::Object> handleBuffer =
            info[1].As<v8::Object>();

        v8::Isolate* isolate = info.GetIsolate();
        v8::HandleScope scope(isolate);

        if (toggleStateObj->IsNull())
            return;

        if (handleBuffer->IsNull())
            return;

        bool toggleState = toggleStateObj->BooleanValue();

        char* bufferData = node::Buffer::Data(handleBuffer);

        bool result = false;

        if (!toggleState)
            result = vibHelper_.DisableVibrancy((unsigned char*)bufferData);

        info.GetReturnValue().Set(result);
    }

    NAN_METHOD(Vibrancy::AddView) {
        v8::Local<v8::Object> handleBuffer = info[0].As<v8::Object>();
        v8::Local<v8::Array> options = info[1].As<v8::Array>();

        v8::Isolate* isolate = info.GetIsolate();
        v8::HandleScope scope(isolate);

        char* bufferData = node::Buffer::Data(handleBuffer);

        int32_t result = -1;

        result = vibHelper_.AddView((unsigned char*)bufferData, options);

        info.GetReturnValue().Set(result);
    }

    NAN_METHOD(Vibrancy::UpdateView) {
        v8::Local<v8::Object> handleBuffer =
            info[0].As<v8::Object>();
        v8::Local<v8::Array> options =
            info[1].As<v8::Array>();

        v8::Isolate* isolate = info.GetIsolate();
        v8::HandleScope scope(isolate);

        char* bufferData = node::Buffer::Data(handleBuffer);

        bool result = false;

        result = vibHelper_.UpdateView((unsigned char*)bufferData, options);

        info.GetReturnValue().Set(result);
    }

    NAN_METHOD(Vibrancy::RemoveView) {
        v8::Local<v8::Object> handleBuffer =
            info[0].As<v8::Object>();
        v8::Local<v8::Array> options =
            info[1].As<v8::Array>();

        v8::Isolate* isolate = info.GetIsolate();
        v8::HandleScope scope(isolate);

        char* bufferData = node::Buffer::Data(handleBuffer);

        bool result = false;

        result = vibHelper_.RemoveView((unsigned char*)bufferData, options);

        info.GetReturnValue().Set(result);
    }
}   //  namespace Vibrancy
<commit_msg>Ah I can't believe I forgot this<commit_after>//----------------------------------------------------------------------------
// electron-vibrancy
// Copyright 2016 arkenthera
//
// MIT License
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice
// shall be included in all copies or substantial
// portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//----------------------------------------------------------------------------
#include "./Vibrancy.h"

//----------------------------------------------------------------------------
namespace Vibrancy {
    static VibrancyHelper vibHelper_;

    Vibrancy::Vibrancy() {
    }

    Vibrancy::~Vibrancy() {
    }
    void Vibrancy::Init(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) {
        v8::Local<v8::FunctionTemplate> tpl =
            Nan::New<v8::FunctionTemplate>(SetVibrancy);

        tpl->InstanceTemplate()->SetInternalFieldCount(1);

        v8::Local<v8::FunctionTemplate> tpl1 =
            Nan::New<v8::FunctionTemplate>(AddView);
        tpl1->InstanceTemplate()->SetInternalFieldCount(1);

        v8::Local<v8::FunctionTemplate> tpl2 =
            Nan::New<v8::FunctionTemplate>(UpdateView);
        tpl2->InstanceTemplate()->SetInternalFieldCount(1);

        v8::Local<v8::FunctionTemplate> tpl3 =
            Nan::New<v8::FunctionTemplate>(RemoveView);
        tpl3->InstanceTemplate()->SetInternalFieldCount(1);

        Nan::Set(target,
            Nan::New("SetVibrancy").ToLocalChecked(),
            Nan::GetFunction(tpl).ToLocalChecked());

        Nan::Set(target,
            Nan::New("AddView").ToLocalChecked(),
            Nan::GetFunction(tpl1).ToLocalChecked());

        Nan::Set(target,
            Nan::New("UpdateView").ToLocalChecked(),
            Nan::GetFunction(tpl2).ToLocalChecked());

        Nan::Set(target,
            Nan::New("RemoveView").ToLocalChecked(),
            Nan::GetFunction(tpl3).ToLocalChecked());
    }

    NAN_METHOD(Vibrancy::SetVibrancy) {
        v8::Local<v8::Object> toggleStateObj =
            info[0].As<v8::Object>();
        v8::Local<v8::Object> handleBuffer =
            info[1].As<v8::Object>();

        v8::Isolate* isolate = info.GetIsolate();
        v8::HandleScope scope(isolate);

        if (toggleStateObj->IsNull())
            return;

        if (handleBuffer->IsNull())
            return;

        bool toggleState = toggleStateObj->BooleanValue();

        char* bufferData = node::Buffer::Data(handleBuffer);

        bool result = false;

        if (!toggleState)
            result = vibHelper_.DisableVibrancy((unsigned char*)bufferData);

        info.GetReturnValue().Set(result);
    }

    NAN_METHOD(Vibrancy::AddView) {
        v8::Local<v8::Object> handleBuffer = info[0].As<v8::Object>();
        v8::Local<v8::Array> options = info[1].As<v8::Array>();

        v8::Isolate* isolate = info.GetIsolate();
        v8::HandleScope scope(isolate);

        char* bufferData = node::Buffer::Data(handleBuffer);

        int32_t result = -1;

        result = vibHelper_.AddView((unsigned char*)bufferData, options);

        info.GetReturnValue().Set(result);
    }

    NAN_METHOD(Vibrancy::UpdateView) {
        v8::Local<v8::Object> handleBuffer =
            info[0].As<v8::Object>();
        v8::Local<v8::Array> options =
            info[1].As<v8::Array>();

        v8::Isolate* isolate = info.GetIsolate();
        v8::HandleScope scope(isolate);

        char* bufferData = node::Buffer::Data(handleBuffer);

        bool result = false;

        result = vibHelper_.UpdateView((unsigned char*)bufferData, options);

        info.GetReturnValue().Set(result);
    }

    NAN_METHOD(Vibrancy::RemoveView) {
        v8::Local<v8::Object> handleBuffer =
            info[0].As<v8::Object>();
        v8::Local<v8::Array> options =
            info[1].As<v8::Array>();

        v8::Isolate* isolate = info.GetIsolate();
        v8::HandleScope scope(isolate);

        char* bufferData = node::Buffer::Data(handleBuffer);

        bool result = false;

        result = vibHelper_.RemoveView((unsigned char*)bufferData, options);

        info.GetReturnValue().Set(result);
    }
}   //  namespace Vibrancy
<|endoftext|>


<commit_before>/* Rapicorn
 * Copyright (C) 2008 Tim Janik
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * A copy of the GNU Lesser General Public License should ship along
 * with this library; if not, see http://www.gnu.org/copyleft/.
 */
#ifndef __RAPICORN_TESTUTILS_HH__
#define __RAPICORN_TESTUTILS_HH__

#include <rcore/rcore.hh>

// Test Macros
#define TTITLE(...)             Rapicorn::Test::test_output (3, __VA_ARGS__)
#define TSTART(...)             Rapicorn::Test::test_output (4, __VA_ARGS__)
#define TDONE()                 Rapicorn::Test::test_output (5, "%s", "")
#define TOUT(...)               Rapicorn::Test::test_output (0, __VA_ARGS__)
#define TMSG(...)               Rapicorn::Test::test_output (1, __VA_ARGS__)
#define TINFO(...)              Rapicorn::Test::test_output (2, __VA_ARGS__)
#define TWARN(...)              Rapicorn::Test::test_output (6, __VA_ARGS__)
#define TRUN(name, func)        ({ TSTART (name); func(); TDONE(); })
#define TCMP(a,cmp,b)           TCMP_op (a,cmp,b,#a,#b)
#define TASSERT(code)           TASSERT_impl (code)
#define TOK()                   do {} while (0) // printerr (".")
#define TASSERT_impl(code)      do { if (code) TOK(); else      \
      Rapicorn::Logging::message ("ABORT", RAPICORN__FILE__, __LINE__, RAPICORN__FUNC__.c_str(), \
                                  "assertion failed: %s", #code);       \
  } while (0)
#define TCMP_op(a,cmp,b,sa,sb)  do { if (a cmp b) TOK(); else {     \
  String __tassert_va = Rapicorn::Test::stringify_arg (a, #a);  \
  String __tassert_vb = Rapicorn::Test::stringify_arg (b, #b);  \
  Rapicorn::Logging::message ("ABORT", RAPICORN__FILE__, __LINE__, RAPICORN__FUNC__.c_str(), \
                              "assertion failed: %s %s %s: %s %s %s", \
                              sa, #cmp, sb, __tassert_va.c_str(), #cmp, __tassert_vb.c_str()); \
    } } while (0)

namespace Rapicorn {

void init_core_test (const String &app_ident, int *argcp, char **argv, const StringVector &args = StringVector());

namespace Test {

/**
 * Class for profiling benchmark tests.
 * UseCase: Benchmarking function implementations, e.g. to compare sorting implementations.
 */
class Timer {
  const double   m_deadline;
  vector<double> m_samples;
  double         m_test_duration;
  int64          m_n_runs;
  int64          loops_needed () const;
  void           reset        ();
  void           submit       (double elapsed, int64 repetitions);
  static double  bench_time   ();
public:
  /// Create a Timer() instance, specifying an optional upper bound for test durations.
  explicit       Timer        (double deadline_in_secs = 0);
  virtual       ~Timer        ();
  int64          n_runs       () const { return m_n_runs; }             ///< Number of benchmark runs executed
  double         test_elapsed () const { return m_test_duration; }      ///< Seconds spent in benchmark()
  double         min_elapsed  () const;         ///< Minimum time benchmarked for a @a callee() call.
  double         max_elapsed  () const;         ///< Maximum time benchmarked for a @a callee() call.
  template<typename Callee>
  double         benchmark    (Callee callee);
};

/**
 * @param callee        A callable function or object.
 * Method to benchmark the execution time of @a callee.
 * @returns Minimum runtime in seconds,
 */
template<typename Callee> double
Timer::benchmark (Callee callee)
{
  reset();
  for (int64 runs = loops_needed(); runs; runs = loops_needed())
    {
      int64 n = runs;
      const double start = bench_time();
      while (RAPICORN_LIKELY (n--))
        callee();
      const double stop = bench_time();
      submit (stop - start, runs);
    }
  return min_elapsed();
}

// === test maintenance ===
int     run             (void);         ///< Run all registered tests.
bool    verbose         (void);         ///< Indicates whether tests should run verbosely.
bool    logging         (void);         ///< Indicates whether only logging tests should be run.
bool    slow            (void);         ///< Indicates whether only slow tests should be run.
bool    ui_test         (void);         ///< Indicates execution of ui-thread tests.

void    test_output     (int kind, const char *format, ...) RAPICORN_PRINTF (2, 3);

void    add_internal    (const String &testname,
                         void        (*test_func) (void*),
                         void         *data);
void    add             (const String &funcname,
                         void (*test_func) (void));
template<typename D>
void    add             (const String &testname,
                         void        (*test_func) (D*),
                         D            *data)
{
  add_internal (testname, (void(*)(void*)) test_func, (void*) data);
}

/// == Stringify Args ==
inline String                   stringify_arg  (const char   *a, const char *str_a) { return string_to_cquote (a); }
template<class V> inline String stringify_arg  (V            *a, const char *str_a) { return string_printf ("%p", a); }
template<class A> inline String stringify_arg  (const A      &a, const char *str_a) { return str_a; }
template<> inline String stringify_arg<float>  (const float  &a, const char *str_a) { return string_printf ("%.8g", a); }
template<> inline String stringify_arg<double> (const double &a, const char *str_a) { return string_printf ("%.17g", a); }
template<> inline String stringify_arg<bool>   (const bool   &a, const char *str_a) { return string_printf ("%u", a); }
template<> inline String stringify_arg<int8>   (const int8   &a, const char *str_a) { return string_printf ("%d", a); }
template<> inline String stringify_arg<int16>  (const int16  &a, const char *str_a) { return string_printf ("%d", a); }
template<> inline String stringify_arg<int32>  (const int32  &a, const char *str_a) { return string_printf ("%d", a); }
template<> inline String stringify_arg<int64>  (const int64  &a, const char *str_a) { return string_printf ("%lld", a); }
template<> inline String stringify_arg<uint8>  (const uint8  &a, const char *str_a) { return string_printf ("0x%02x", a); }
template<> inline String stringify_arg<uint16> (const uint16 &a, const char *str_a) { return string_printf ("0x%04x", a); }
template<> inline String stringify_arg<uint32> (const uint32 &a, const char *str_a) { return string_printf ("0x%08x", a); }
template<> inline String stringify_arg<uint64> (const uint64 &a, const char *str_a) { return string_printf ("0x%08Lx", a); }
template<> inline String stringify_arg<String> (const String &a, const char *str_a) { return string_to_cquote (a); }

class RegisterTest {
  static void add_test (char kind, const String &testname, void (*test_func) (void*), void *data);
public:
  RegisterTest (const char k, const String &testname, void (*test_func) (void))
  { add_test (k, testname, (void(*)(void*)) test_func, NULL); }
  RegisterTest (const char k, const String &testname, void (*test_func) (ptrdiff_t), ptrdiff_t data)
  { add_test (k, testname, (void(*)(void*)) test_func, (void*) data); }
  template<typename D>
  RegisterTest (const char k, const String &testname, void (*test_func) (D*), D *data)
  { add_test (k, testname, (void(*)(void*)) test_func, (void*) data); }
  typedef void (*TestTrigger)  (void (*runner) (void));
  static void test_set_trigger (TestTrigger func);
};

/// Register a standard test function for execution as unit test.
#define REGISTER_TEST(name, ...)     static const Rapicorn::Test::RegisterTest \
  RAPICORN_CPP_PASTE2 (__Rapicorn_RegisterTest__line, __LINE__) ('t', name, __VA_ARGS__)

/// Register a slow test function for execution as during slow unit testing.
#define REGISTER_SLOWTEST(name, ...) static const Rapicorn::Test::RegisterTest \
  RAPICORN_CPP_PASTE2 (__Rapicorn_RegisterTest__line, __LINE__) ('s', name, __VA_ARGS__)

/// Register a logging test function for output recording and verification.
#define REGISTER_LOGTEST(name, ...) static const Rapicorn::Test::RegisterTest \
  RAPICORN_CPP_PASTE2 (__Rapicorn_RegisterTest__line, __LINE__) ('l', name, __VA_ARGS__)

// == Deterministic random numbers for tests ===
char    rand_bit                (void);                                 ///< Return a random bit.
int32   rand_int                (void);                                 ///< Return random int.
int32   rand_int_range          (int32 begin, int32 end);               ///< Return random int within range.
double  test_rand_double        (void);                                 ///< Return random double.
double  test_rand_double_range  (double range_start, double range_end); ///< Return random double within range.

} // Test
} // Rapicorn

#endif /* __RAPICORN_TESTUTILS_HH__ */
<commit_msg>RCORE: reduced TASSERT to a simple alias<commit_after>/* Rapicorn
 * Copyright (C) 2008 Tim Janik
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * A copy of the GNU Lesser General Public License should ship along
 * with this library; if not, see http://www.gnu.org/copyleft/.
 */
#ifndef __RAPICORN_TESTUTILS_HH__
#define __RAPICORN_TESTUTILS_HH__

#include <rcore/rcore.hh>

// Test Macros
#define TTITLE(...)             Rapicorn::Test::test_output (3, __VA_ARGS__)
#define TSTART(...)             Rapicorn::Test::test_output (4, __VA_ARGS__)
#define TDONE()                 Rapicorn::Test::test_output (5, "%s", "")
#define TOUT(...)               Rapicorn::Test::test_output (0, __VA_ARGS__)
#define TMSG(...)               Rapicorn::Test::test_output (1, __VA_ARGS__)
#define TINFO(...)              Rapicorn::Test::test_output (2, __VA_ARGS__)
#define TWARN(...)              Rapicorn::Test::test_output (6, __VA_ARGS__)
#define TRUN(name, func)        ({ TSTART (name); func(); TDONE(); })
#define TCMP(a,cmp,b)           TCMP_op (a,cmp,b,#a,#b)
#define TASSERT                 RAPICORN_ASSERT // TASSERT (condition)
#define TOK()                   do {} while (0) // printerr (".")
#define TCMP_op(a,cmp,b,sa,sb)  do { if (a cmp b) TOK(); else {     \
  String __tassert_va = Rapicorn::Test::stringify_arg (a, #a);  \
  String __tassert_vb = Rapicorn::Test::stringify_arg (b, #b);  \
  Rapicorn::Logging::message ("ABORT", RAPICORN__FILE__, __LINE__, RAPICORN__FUNC__.c_str(), \
                              "assertion failed: %s %s %s: %s %s %s", \
                              sa, #cmp, sb, __tassert_va.c_str(), #cmp, __tassert_vb.c_str()); \
    } } while (0)

namespace Rapicorn {

void init_core_test (const String &app_ident, int *argcp, char **argv, const StringVector &args = StringVector());

namespace Test {

/**
 * Class for profiling benchmark tests.
 * UseCase: Benchmarking function implementations, e.g. to compare sorting implementations.
 */
class Timer {
  const double   m_deadline;
  vector<double> m_samples;
  double         m_test_duration;
  int64          m_n_runs;
  int64          loops_needed () const;
  void           reset        ();
  void           submit       (double elapsed, int64 repetitions);
  static double  bench_time   ();
public:
  /// Create a Timer() instance, specifying an optional upper bound for test durations.
  explicit       Timer        (double deadline_in_secs = 0);
  virtual       ~Timer        ();
  int64          n_runs       () const { return m_n_runs; }             ///< Number of benchmark runs executed
  double         test_elapsed () const { return m_test_duration; }      ///< Seconds spent in benchmark()
  double         min_elapsed  () const;         ///< Minimum time benchmarked for a @a callee() call.
  double         max_elapsed  () const;         ///< Maximum time benchmarked for a @a callee() call.
  template<typename Callee>
  double         benchmark    (Callee callee);
};

/**
 * @param callee        A callable function or object.
 * Method to benchmark the execution time of @a callee.
 * @returns Minimum runtime in seconds,
 */
template<typename Callee> double
Timer::benchmark (Callee callee)
{
  reset();
  for (int64 runs = loops_needed(); runs; runs = loops_needed())
    {
      int64 n = runs;
      const double start = bench_time();
      while (RAPICORN_LIKELY (n--))
        callee();
      const double stop = bench_time();
      submit (stop - start, runs);
    }
  return min_elapsed();
}

// === test maintenance ===
int     run             (void);         ///< Run all registered tests.
bool    verbose         (void);         ///< Indicates whether tests should run verbosely.
bool    logging         (void);         ///< Indicates whether only logging tests should be run.
bool    slow            (void);         ///< Indicates whether only slow tests should be run.
bool    ui_test         (void);         ///< Indicates execution of ui-thread tests.

void    test_output     (int kind, const char *format, ...) RAPICORN_PRINTF (2, 3);

void    add_internal    (const String &testname,
                         void        (*test_func) (void*),
                         void         *data);
void    add             (const String &funcname,
                         void (*test_func) (void));
template<typename D>
void    add             (const String &testname,
                         void        (*test_func) (D*),
                         D            *data)
{
  add_internal (testname, (void(*)(void*)) test_func, (void*) data);
}

/// == Stringify Args ==
inline String                   stringify_arg  (const char   *a, const char *str_a) { return string_to_cquote (a); }
template<class V> inline String stringify_arg  (V            *a, const char *str_a) { return string_printf ("%p", a); }
template<class A> inline String stringify_arg  (const A      &a, const char *str_a) { return str_a; }
template<> inline String stringify_arg<float>  (const float  &a, const char *str_a) { return string_printf ("%.8g", a); }
template<> inline String stringify_arg<double> (const double &a, const char *str_a) { return string_printf ("%.17g", a); }
template<> inline String stringify_arg<bool>   (const bool   &a, const char *str_a) { return string_printf ("%u", a); }
template<> inline String stringify_arg<int8>   (const int8   &a, const char *str_a) { return string_printf ("%d", a); }
template<> inline String stringify_arg<int16>  (const int16  &a, const char *str_a) { return string_printf ("%d", a); }
template<> inline String stringify_arg<int32>  (const int32  &a, const char *str_a) { return string_printf ("%d", a); }
template<> inline String stringify_arg<int64>  (const int64  &a, const char *str_a) { return string_printf ("%lld", a); }
template<> inline String stringify_arg<uint8>  (const uint8  &a, const char *str_a) { return string_printf ("0x%02x", a); }
template<> inline String stringify_arg<uint16> (const uint16 &a, const char *str_a) { return string_printf ("0x%04x", a); }
template<> inline String stringify_arg<uint32> (const uint32 &a, const char *str_a) { return string_printf ("0x%08x", a); }
template<> inline String stringify_arg<uint64> (const uint64 &a, const char *str_a) { return string_printf ("0x%08Lx", a); }
template<> inline String stringify_arg<String> (const String &a, const char *str_a) { return string_to_cquote (a); }

class RegisterTest {
  static void add_test (char kind, const String &testname, void (*test_func) (void*), void *data);
public:
  RegisterTest (const char k, const String &testname, void (*test_func) (void))
  { add_test (k, testname, (void(*)(void*)) test_func, NULL); }
  RegisterTest (const char k, const String &testname, void (*test_func) (ptrdiff_t), ptrdiff_t data)
  { add_test (k, testname, (void(*)(void*)) test_func, (void*) data); }
  template<typename D>
  RegisterTest (const char k, const String &testname, void (*test_func) (D*), D *data)
  { add_test (k, testname, (void(*)(void*)) test_func, (void*) data); }
  typedef void (*TestTrigger)  (void (*runner) (void));
  static void test_set_trigger (TestTrigger func);
};

/// Register a standard test function for execution as unit test.
#define REGISTER_TEST(name, ...)     static const Rapicorn::Test::RegisterTest \
  RAPICORN_CPP_PASTE2 (__Rapicorn_RegisterTest__line, __LINE__) ('t', name, __VA_ARGS__)

/// Register a slow test function for execution as during slow unit testing.
#define REGISTER_SLOWTEST(name, ...) static const Rapicorn::Test::RegisterTest \
  RAPICORN_CPP_PASTE2 (__Rapicorn_RegisterTest__line, __LINE__) ('s', name, __VA_ARGS__)

/// Register a logging test function for output recording and verification.
#define REGISTER_LOGTEST(name, ...) static const Rapicorn::Test::RegisterTest \
  RAPICORN_CPP_PASTE2 (__Rapicorn_RegisterTest__line, __LINE__) ('l', name, __VA_ARGS__)

// == Deterministic random numbers for tests ===
char    rand_bit                (void);                                 ///< Return a random bit.
int32   rand_int                (void);                                 ///< Return random int.
int32   rand_int_range          (int32 begin, int32 end);               ///< Return random int within range.
double  test_rand_double        (void);                                 ///< Return random double.
double  test_rand_double_range  (double range_start, double range_end); ///< Return random double within range.

} // Test
} // Rapicorn

#endif /* __RAPICORN_TESTUTILS_HH__ */
<|endoftext|>