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

  Library:   CTK

  Copyright (c) German Cancer Research Center,
    Division of Medical and Biological Informatics

  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.txt

  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.

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

//
// Code taken from http://thread.gmane.org/gmane.comp.lib.boost.devel/209982
// and modified for CTK.
//
// Original Copyright (c) 2010 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0.
// (See http://www.boost.org/LICENSE_1_0.txt)
//

#include "ctkBackTrace.h"

#include <QList>

#include <vector>

#if defined(__linux) || defined(__APPLE__) || defined(__sun)
#define CTK_HAVE_EXECINFO
#define CTK_HAVE_DLADDR
#endif

#if defined(__GNUC__)
#define CTK_HAVE_ABI_CXA_DEMANGLE
#endif

#ifdef CTK_HAVE_EXECINFO
#include <execinfo.h>
#endif

#ifdef CTK_HAVE_ABI_CXA_DEMANGLE
#include <cxxabi.h>
#endif

#ifdef CTK_HAVE_DLADDR
#include <dlfcn.h>
#endif

#include <stdlib.h>
#include <sstream>

#if defined(Q_CC_MSVC)
#include <windows.h>
#include <stdlib.h>
#include <dbghelp.h>
#endif

// --------------------------------------------------------------------------
size_t const ctkBackTrace::DefaultStackSize = 32;

// --------------------------------------------------------------------------
struct ctkBackTracePrivate
{
  std::vector<void *> Frames;

  int trace(void** addresses, size_t size) const;
  std::string getSymbol(void* address) const;
};

// --------------------------------------------------------------------------
ctkBackTrace::ctkBackTrace(const ctkBackTrace& other)
  : d(new ctkBackTracePrivate(*other.d.data()))
{
}

ctkBackTrace::ctkBackTrace(size_t framesNumber)
  : d(new ctkBackTracePrivate)
{
  if(framesNumber == 0)
    return;
  d->Frames.resize(framesNumber, 0);
  size_t size = d->trace(&d->Frames.front(), framesNumber);
  d->Frames.resize(size);
}

// --------------------------------------------------------------------------
ctkBackTrace::~ctkBackTrace() throw()
{
}

// --------------------------------------------------------------------------
size_t ctkBackTrace::stackSize() const
{
  return d->Frames.size();
}

// --------------------------------------------------------------------------
void* ctkBackTrace::returnAddress(unsigned frameNumber) const
{
  if(frameNumber < stackSize())
    return d->Frames[frameNumber];
  return 0;
}

// --------------------------------------------------------------------------
QString ctkBackTrace::stackFrame(unsigned frameNumber) const
{
  if(frameNumber < d->Frames.size())
    return QString::fromStdString(d->getSymbol(d->Frames[frameNumber]));
  return QString();
}

// --------------------------------------------------------------------------
QList<QString> ctkBackTrace::stackTrace() const
{
  QList<QString> trace;

  if(d->Frames.empty())
    return trace;

  for (std::size_t i = 0; i < d->Frames.size(); ++i)
  {
    std::string s = d->getSymbol(d->Frames[i]);
    if (!s.empty())
    {
      trace.push_back(QString::fromStdString(s));
    }
  }

  return trace;

  //std::ostringstream res;
  //d->writeSymbols(&d->Frames.front(), d->Frames.size(), res, framePrefix.toStdString());
  //return QString::fromStdString(res.str());
}

#if defined(CTK_HAVE_EXECINFO)

// --------------------------------------------------------------------------
int ctkBackTracePrivate::trace(void** array, int n) const
{
  return :: backtrace(array,n);
}

#elif defined(Q_CC_MSVC)

// --------------------------------------------------------------------------
int ctkBackTracePrivate::trace(void** array, size_t n) const
{
  if(n>=63)
    n=62;
  return RtlCaptureStackBackTrace(0, n, array, 0);
}

#else

// --------------------------------------------------------------------------
int ctkBackTracePrivate::trace(void** /*array*/, int /*n*/) const
{
  return 0;
}

#endif

#if defined(CTK_HAVE_DLADDR) && defined(CTK_HAVE_ABI_CXA_DEMANGLE)

// --------------------------------------------------------------------------
std::string ctkBackTracePrivate::getSymbol(void* ptr) const
{
  if(!ptr)
    return std::string();

  std::ostringstream res;
  res.imbue(std::locale::classic());
  res << ptr << ": ";
  Dl_info info = {0,0,0,0};
  if(dladdr(ptr,&info) == 0)
  {
    res << "???";
  }
  else
  {
    if(info.dli_sname)
    {
      int status = 0;
      char *demangled = abi::__cxa_demangle(info.dli_sname, 0, 0, &status);
      if(demangled)
      {
        res << demangled;
        free(demangled);
      }
      else
      {
        res << info.dli_sname;
      }
    }
    else
    {
      res << "???";
    }

    unsigned offset = reinterpret_cast<char*>(ptr) - reinterpret_cast<char*>(info.dli_saddr);
    res << std::hex <<" + 0x" << offset ;

    if(info.dli_fname)
      res << " in " << info.dli_fname;
  }
  return res.str();
}

#elif defined(CTK_HAVE_EXECINFO)
// --------------------------------------------------------------------------
std::string ctkBackTracePrivate::getSymbol(void *address) const
{
  char ** ptr = backtrace_symbols(&address, 1);
  try
  {
    if(ptr == 0)
      return std::string();
    std::string res = ptr[0];
    free(ptr);
    ptr = 0;
    return res;
  }
  catch(...)
  {
    free(ptr);
    throw;
  }
}

#elif defined(Q_CC_MSVC)

// --------------------------------------------------------------------------
namespace {
HANDLE hProcess = 0;
bool syms_ready = false;
}

// --------------------------------------------------------------------------
namespace ctk {
bool DebugSymInitialize()
{
  if(hProcess == 0)
  {
    hProcess = GetCurrentProcess();
    SymSetOptions(SYMOPT_DEFERRED_LOADS);

    if (SymInitialize(hProcess, NULL, TRUE))
    {
      syms_ready = true;
    }
  }
  return syms_ready;
}
}

// --------------------------------------------------------------------------
std::string ctkBackTracePrivate::getSymbol(void* ptr) const
{
  if(ptr==0)
    return std::string();

  ctk::DebugSymInitialize();
  std::ostringstream ss;
  ss.imbue(std::locale::classic());
  ss << ptr;
  if(syms_ready)
  {
    DWORD64  dwDisplacement = 0;
    DWORD64  dwAddress = (DWORD64)ptr;

    std::vector<char> buffer(sizeof(SYMBOL_INFO) + MAX_SYM_NAME);
    PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)&buffer.front();

    pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
    pSymbol->MaxNameLen = MAX_SYM_NAME;

    if (SymFromAddr(hProcess, dwAddress, &dwDisplacement, pSymbol))
    {
      ss <<": " << pSymbol->Name << std::hex << " + 0x" << dwDisplacement;
    }
    else
    {
      ss << ": ???";
    }

    std::vector<char> moduleBuffer(sizeof(IMAGEHLP_MODULE64));
    PIMAGEHLP_MODULE64 pModuleInfo = (PIMAGEHLP_MODULE64)&moduleBuffer.front();
    pModuleInfo->SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
    if (SymGetModuleInfo64(hProcess, pSymbol->ModBase, pModuleInfo))
    {
      ss << " in " << pModuleInfo->LoadedImageName;
    }
  }
  return ss.str();
}

#else

// --------------------------------------------------------------------------
std::string ctkBackTracePrivate::getSymbol(void* ptr) const
{
  if(!ptr)
    return std::string();

  std::ostringstream res;
  res.imbue(std::locale::classic());
  res << ptr;
  return res.str();
}

#endif
<commit_msg>Propagate new ctkBackTracePrivate::trace signature<commit_after>/*=========================================================================

  Library:   CTK

  Copyright (c) German Cancer Research Center,
    Division of Medical and Biological Informatics

  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.txt

  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.

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

//
// Code taken from http://thread.gmane.org/gmane.comp.lib.boost.devel/209982
// and modified for CTK.
//
// Original Copyright (c) 2010 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0.
// (See http://www.boost.org/LICENSE_1_0.txt)
//

#include "ctkBackTrace.h"

#include <QList>

#include <vector>

#if defined(__linux) || defined(__APPLE__) || defined(__sun)
#define CTK_HAVE_EXECINFO
#define CTK_HAVE_DLADDR
#endif

#if defined(__GNUC__)
#define CTK_HAVE_ABI_CXA_DEMANGLE
#endif

#ifdef CTK_HAVE_EXECINFO
#include <execinfo.h>
#endif

#ifdef CTK_HAVE_ABI_CXA_DEMANGLE
#include <cxxabi.h>
#endif

#ifdef CTK_HAVE_DLADDR
#include <dlfcn.h>
#endif

#include <stdlib.h>
#include <sstream>

#if defined(Q_CC_MSVC)
#include <windows.h>
#include <stdlib.h>
#include <dbghelp.h>
#endif

// --------------------------------------------------------------------------
size_t const ctkBackTrace::DefaultStackSize = 32;

// --------------------------------------------------------------------------
struct ctkBackTracePrivate
{
  std::vector<void *> Frames;

  int trace(void** addresses, size_t size) const;
  std::string getSymbol(void* address) const;
};

// --------------------------------------------------------------------------
ctkBackTrace::ctkBackTrace(const ctkBackTrace& other)
  : d(new ctkBackTracePrivate(*other.d.data()))
{
}

ctkBackTrace::ctkBackTrace(size_t framesNumber)
  : d(new ctkBackTracePrivate)
{
  if(framesNumber == 0)
    return;
  d->Frames.resize(framesNumber, 0);
  size_t size = d->trace(&d->Frames.front(), framesNumber);
  d->Frames.resize(size);
}

// --------------------------------------------------------------------------
ctkBackTrace::~ctkBackTrace() throw()
{
}

// --------------------------------------------------------------------------
size_t ctkBackTrace::stackSize() const
{
  return d->Frames.size();
}

// --------------------------------------------------------------------------
void* ctkBackTrace::returnAddress(unsigned frameNumber) const
{
  if(frameNumber < stackSize())
    return d->Frames[frameNumber];
  return 0;
}

// --------------------------------------------------------------------------
QString ctkBackTrace::stackFrame(unsigned frameNumber) const
{
  if(frameNumber < d->Frames.size())
    return QString::fromStdString(d->getSymbol(d->Frames[frameNumber]));
  return QString();
}

// --------------------------------------------------------------------------
QList<QString> ctkBackTrace::stackTrace() const
{
  QList<QString> trace;

  if(d->Frames.empty())
    return trace;

  for (std::size_t i = 0; i < d->Frames.size(); ++i)
  {
    std::string s = d->getSymbol(d->Frames[i]);
    if (!s.empty())
    {
      trace.push_back(QString::fromStdString(s));
    }
  }

  return trace;

  //std::ostringstream res;
  //d->writeSymbols(&d->Frames.front(), d->Frames.size(), res, framePrefix.toStdString());
  //return QString::fromStdString(res.str());
}

#if defined(CTK_HAVE_EXECINFO)

// --------------------------------------------------------------------------
int ctkBackTracePrivate::trace(void** array, size_t n) const
{
  return :: backtrace(array,n);
}

#elif defined(Q_CC_MSVC)

// --------------------------------------------------------------------------
int ctkBackTracePrivate::trace(void** array, size_t n) const
{
  if(n>=63)
    n=62;
  return RtlCaptureStackBackTrace(0, n, array, 0);
}

#else

// --------------------------------------------------------------------------
int ctkBackTracePrivate::trace(void** /*array*/, size_t /*n*/) const
{
  return 0;
}

#endif

#if defined(CTK_HAVE_DLADDR) && defined(CTK_HAVE_ABI_CXA_DEMANGLE)

// --------------------------------------------------------------------------
std::string ctkBackTracePrivate::getSymbol(void* ptr) const
{
  if(!ptr)
    return std::string();

  std::ostringstream res;
  res.imbue(std::locale::classic());
  res << ptr << ": ";
  Dl_info info = {0,0,0,0};
  if(dladdr(ptr,&info) == 0)
  {
    res << "???";
  }
  else
  {
    if(info.dli_sname)
    {
      int status = 0;
      char *demangled = abi::__cxa_demangle(info.dli_sname, 0, 0, &status);
      if(demangled)
      {
        res << demangled;
        free(demangled);
      }
      else
      {
        res << info.dli_sname;
      }
    }
    else
    {
      res << "???";
    }

    unsigned offset = reinterpret_cast<char*>(ptr) - reinterpret_cast<char*>(info.dli_saddr);
    res << std::hex <<" + 0x" << offset ;

    if(info.dli_fname)
      res << " in " << info.dli_fname;
  }
  return res.str();
}

#elif defined(CTK_HAVE_EXECINFO)
// --------------------------------------------------------------------------
std::string ctkBackTracePrivate::getSymbol(void *address) const
{
  char ** ptr = backtrace_symbols(&address, 1);
  try
  {
    if(ptr == 0)
      return std::string();
    std::string res = ptr[0];
    free(ptr);
    ptr = 0;
    return res;
  }
  catch(...)
  {
    free(ptr);
    throw;
  }
}

#elif defined(Q_CC_MSVC)

// --------------------------------------------------------------------------
namespace {
HANDLE hProcess = 0;
bool syms_ready = false;
}

// --------------------------------------------------------------------------
namespace ctk {
bool DebugSymInitialize()
{
  if(hProcess == 0)
  {
    hProcess = GetCurrentProcess();
    SymSetOptions(SYMOPT_DEFERRED_LOADS);

    if (SymInitialize(hProcess, NULL, TRUE))
    {
      syms_ready = true;
    }
  }
  return syms_ready;
}
}

// --------------------------------------------------------------------------
std::string ctkBackTracePrivate::getSymbol(void* ptr) const
{
  if(ptr==0)
    return std::string();

  ctk::DebugSymInitialize();
  std::ostringstream ss;
  ss.imbue(std::locale::classic());
  ss << ptr;
  if(syms_ready)
  {
    DWORD64  dwDisplacement = 0;
    DWORD64  dwAddress = (DWORD64)ptr;

    std::vector<char> buffer(sizeof(SYMBOL_INFO) + MAX_SYM_NAME);
    PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)&buffer.front();

    pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
    pSymbol->MaxNameLen = MAX_SYM_NAME;

    if (SymFromAddr(hProcess, dwAddress, &dwDisplacement, pSymbol))
    {
      ss <<": " << pSymbol->Name << std::hex << " + 0x" << dwDisplacement;
    }
    else
    {
      ss << ": ???";
    }

    std::vector<char> moduleBuffer(sizeof(IMAGEHLP_MODULE64));
    PIMAGEHLP_MODULE64 pModuleInfo = (PIMAGEHLP_MODULE64)&moduleBuffer.front();
    pModuleInfo->SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
    if (SymGetModuleInfo64(hProcess, pSymbol->ModBase, pModuleInfo))
    {
      ss << " in " << pModuleInfo->LoadedImageName;
    }
  }
  return ss.str();
}

#else

// --------------------------------------------------------------------------
std::string ctkBackTracePrivate::getSymbol(void* ptr) const
{
  if(!ptr)
    return std::string();

  std::ostringstream res;
  res.imbue(std::locale::classic());
  res << ptr;
  return res.str();
}

#endif
<|endoftext|>


<commit_before>#include <fstream>
#include <iostream>
#include <string>

#include <boost/archive/binary_oarchive.hpp>
#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
#include <boost/program_options/variables_map.hpp>

#include "alignment.h"
#include "data_array.h"
#include "precomputation.h"
#include "suffix_array.h"
#include "time_util.h"
#include "translation_table.h"
#include "vocabulary.h"

namespace ar = boost::archive;
namespace fs = boost::filesystem;
namespace po = boost::program_options;
using namespace std;
using namespace extractor;

int main(int argc, char** argv) {
  po::options_description desc("Command line options");
  desc.add_options()
    ("help,h", "Show available options")
    ("source,f", po::value<string>(), "Source language corpus")
    ("target,e", po::value<string>(), "Target language corpus")
    ("bitext,b", po::value<string>(), "Parallel text (source ||| target)")
    ("alignment,a", po::value<string>()->required(), "Bitext word alignment")
    ("output,o", po::value<string>()->required(), "Output path")
    ("config,c", po::value<string>()->required(),
        "Path where the config file will be generated")
    ("frequent", po::value<int>()->default_value(100),
        "Number of precomputed frequent patterns")
    ("super_frequent", po::value<int>()->default_value(10),
        "Number of precomputed super frequent patterns")
    ("max_rule_span,s", po::value<int>()->default_value(15),
        "Maximum rule span")
    ("max_rule_symbols,l", po::value<int>()->default_value(5),
        "Maximum number of symbols (terminals + nontermals) in a rule")
    ("min_gap_size,g", po::value<int>()->default_value(1), "Minimum gap size")
    ("max_phrase_len,p", po::value<int>()->default_value(4),
        "Maximum frequent phrase length")
    ("min_frequency", po::value<int>()->default_value(1000),
        "Minimum number of occurrences for a pharse to be considered frequent");

  po::variables_map vm;
  po::store(po::parse_command_line(argc, argv, desc), vm);

  // Check for help argument before notify, so we don't need to pass in the
  // required parameters.
  if (vm.count("help")) {
    cout << desc << endl;
    return 0;
  }

  po::notify(vm);

  if (!((vm.count("source") && vm.count("target")) || vm.count("bitext"))) {
    cerr << "A paralel corpus is required. "
         << "Use -f (source) with -e (target) or -b (bitext)."
         << endl;
    return 1;
  }

  fs::path output_dir(vm["output"].as<string>());
  if (!fs::exists(output_dir)) {
    fs::create_directory(output_dir);
  }

  // Reading source and target data.
  Clock::time_point start_time = Clock::now();
  cerr << "Reading source and target data..." << endl;
  shared_ptr<DataArray> source_data_array, target_data_array;
  if (vm.count("bitext")) {
    source_data_array = make_shared<DataArray>(
        vm["bitext"].as<string>(), SOURCE);
    target_data_array = make_shared<DataArray>(
        vm["bitext"].as<string>(), TARGET);
  } else {
    source_data_array = make_shared<DataArray>(vm["source"].as<string>());
    target_data_array = make_shared<DataArray>(vm["target"].as<string>());
  }

  ofstream config_stream(vm["config"].as<string>());

  Clock::time_point start_write = Clock::now();
  string target_path = (output_dir / fs::path("target.bin")).string();
  config_stream << "target = " << target_path << endl;
  ofstream target_fstream(target_path);
  ar::binary_oarchive target_stream(target_fstream);
  target_stream << *target_data_array;
  Clock::time_point stop_write = Clock::now();
  double write_duration = GetDuration(start_write, stop_write);

  Clock::time_point stop_time = Clock::now();
  cerr << "Reading data took " << GetDuration(start_time, stop_time)
       << " seconds" << endl;

  // Constructing and compiling the suffix array.
  start_time = Clock::now();
  cerr << "Constructing source suffix array..." << endl;
  shared_ptr<SuffixArray> source_suffix_array =
      make_shared<SuffixArray>(source_data_array);

  start_write = Clock::now();
  string source_path = (output_dir / fs::path("source.bin")).string();
  config_stream << "source = " << source_path << endl;
  ofstream source_fstream(source_path);
  ar::binary_oarchive output_stream(source_fstream);
  output_stream << *source_suffix_array;
  stop_write = Clock::now();
  write_duration += GetDuration(start_write, stop_write);

  cerr << "Constructing suffix array took "
       << GetDuration(start_time, stop_time) << " seconds" << endl;

  // Reading alignment.
  start_time = Clock::now();
  cerr << "Reading alignment..." << endl;
  shared_ptr<Alignment> alignment =
      make_shared<Alignment>(vm["alignment"].as<string>());

  start_write = Clock::now();
  string alignment_path = (output_dir / fs::path("alignment.bin")).string();
  config_stream << "alignment = " << alignment_path << endl;
  ofstream alignment_fstream(alignment_path);
  ar::binary_oarchive alignment_stream(alignment_fstream);
  alignment_stream << *alignment;
  stop_write = Clock::now();
  write_duration += GetDuration(start_write, stop_write);

  stop_time = Clock::now();
  cerr << "Reading alignment took "
       << GetDuration(start_time, stop_time) << " seconds" << endl;

  shared_ptr<Vocabulary> vocabulary = make_shared<Vocabulary>();

  start_time = Clock::now();
  cerr << "Precomputing collocations..." << endl;
  Precomputation precomputation(
      vocabulary,
      source_suffix_array,
      vm["frequent"].as<int>(),
      vm["super_frequent"].as<int>(),
      vm["max_rule_span"].as<int>(),
      vm["max_rule_symbols"].as<int>(),
      vm["min_gap_size"].as<int>(),
      vm["max_phrase_len"].as<int>(),
      vm["min_frequency"].as<int>());

  start_write = Clock::now();
  string precomputation_path = (output_dir / fs::path("precomp.bin")).string();
  config_stream << "precomputation = " << precomputation_path << endl;
  ofstream precomp_fstream(precomputation_path);
  ar::binary_oarchive precomp_stream(precomp_fstream);
  precomp_stream << precomputation;

  string vocabulary_path = (output_dir / fs::path("vocab.bin")).string();
  config_stream << "vocabulary = " << vocabulary_path << endl;
  ofstream vocab_fstream(vocabulary_path);
  ar::binary_oarchive vocab_stream(vocab_fstream);
  vocab_stream << *vocabulary;
  stop_write = Clock::now();
  write_duration += GetDuration(start_write, stop_write);

  stop_time = Clock::now();
  cerr << "Precomputing collocations took "
       << GetDuration(start_time, stop_time) << " seconds" << endl;

  start_time = Clock::now();
  cerr << "Precomputing conditional probabilities..." << endl;
  TranslationTable table(source_data_array, target_data_array, alignment);

  start_write = Clock::now();
  string table_path = (output_dir / fs::path("bilex.bin")).string();
  config_stream << "ttable = " << table_path << endl;
  ofstream table_fstream(table_path);
  ar::binary_oarchive table_stream(table_fstream);
  table_stream << table;
  stop_write = Clock::now();
  write_duration += GetDuration(start_write, stop_write);

  stop_time = Clock::now();
  cerr << "Precomputing conditional probabilities took "
       << GetDuration(start_time, stop_time) << " seconds" << endl;

  cerr << "Total time spent writing: " << write_duration
       << " seconds" << endl;

  return 0;
}
<commit_msg>Fix time tracking for suffix array construction.<commit_after>#include <fstream>
#include <iostream>
#include <string>

#include <boost/archive/binary_oarchive.hpp>
#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
#include <boost/program_options/variables_map.hpp>

#include "alignment.h"
#include "data_array.h"
#include "precomputation.h"
#include "suffix_array.h"
#include "time_util.h"
#include "translation_table.h"
#include "vocabulary.h"

namespace ar = boost::archive;
namespace fs = boost::filesystem;
namespace po = boost::program_options;
using namespace std;
using namespace extractor;

int main(int argc, char** argv) {
  po::options_description desc("Command line options");
  desc.add_options()
    ("help,h", "Show available options")
    ("source,f", po::value<string>(), "Source language corpus")
    ("target,e", po::value<string>(), "Target language corpus")
    ("bitext,b", po::value<string>(), "Parallel text (source ||| target)")
    ("alignment,a", po::value<string>()->required(), "Bitext word alignment")
    ("output,o", po::value<string>()->required(), "Output path")
    ("config,c", po::value<string>()->required(),
        "Path where the config file will be generated")
    ("frequent", po::value<int>()->default_value(100),
        "Number of precomputed frequent patterns")
    ("super_frequent", po::value<int>()->default_value(10),
        "Number of precomputed super frequent patterns")
    ("max_rule_span,s", po::value<int>()->default_value(15),
        "Maximum rule span")
    ("max_rule_symbols,l", po::value<int>()->default_value(5),
        "Maximum number of symbols (terminals + nontermals) in a rule")
    ("min_gap_size,g", po::value<int>()->default_value(1), "Minimum gap size")
    ("max_phrase_len,p", po::value<int>()->default_value(4),
        "Maximum frequent phrase length")
    ("min_frequency", po::value<int>()->default_value(1000),
        "Minimum number of occurrences for a pharse to be considered frequent");

  po::variables_map vm;
  po::store(po::parse_command_line(argc, argv, desc), vm);

  // Check for help argument before notify, so we don't need to pass in the
  // required parameters.
  if (vm.count("help")) {
    cout << desc << endl;
    return 0;
  }

  po::notify(vm);

  if (!((vm.count("source") && vm.count("target")) || vm.count("bitext"))) {
    cerr << "A paralel corpus is required. "
         << "Use -f (source) with -e (target) or -b (bitext)."
         << endl;
    return 1;
  }

  fs::path output_dir(vm["output"].as<string>());
  if (!fs::exists(output_dir)) {
    fs::create_directory(output_dir);
  }

  // Reading source and target data.
  Clock::time_point start_time = Clock::now();
  cerr << "Reading source and target data..." << endl;
  shared_ptr<DataArray> source_data_array, target_data_array;
  if (vm.count("bitext")) {
    source_data_array = make_shared<DataArray>(
        vm["bitext"].as<string>(), SOURCE);
    target_data_array = make_shared<DataArray>(
        vm["bitext"].as<string>(), TARGET);
  } else {
    source_data_array = make_shared<DataArray>(vm["source"].as<string>());
    target_data_array = make_shared<DataArray>(vm["target"].as<string>());
  }

  ofstream config_stream(vm["config"].as<string>());

  Clock::time_point start_write = Clock::now();
  string target_path = (output_dir / fs::path("target.bin")).string();
  config_stream << "target = " << target_path << endl;
  ofstream target_fstream(target_path);
  ar::binary_oarchive target_stream(target_fstream);
  target_stream << *target_data_array;
  Clock::time_point stop_write = Clock::now();
  double write_duration = GetDuration(start_write, stop_write);

  Clock::time_point stop_time = Clock::now();
  cerr << "Reading data took " << GetDuration(start_time, stop_time)
       << " seconds" << endl;

  // Constructing and compiling the suffix array.
  start_time = Clock::now();
  cerr << "Constructing source suffix array..." << endl;
  shared_ptr<SuffixArray> source_suffix_array =
      make_shared<SuffixArray>(source_data_array);

  start_write = Clock::now();
  string source_path = (output_dir / fs::path("source.bin")).string();
  config_stream << "source = " << source_path << endl;
  ofstream source_fstream(source_path);
  ar::binary_oarchive output_stream(source_fstream);
  output_stream << *source_suffix_array;
  stop_write = Clock::now();
  write_duration += GetDuration(start_write, stop_write);

  stop_time = Clock::now();
  cerr << "Constructing suffix array took "
       << GetDuration(start_time, stop_time) << " seconds" << endl;

  // Reading alignment.
  start_time = Clock::now();
  cerr << "Reading alignment..." << endl;
  shared_ptr<Alignment> alignment =
      make_shared<Alignment>(vm["alignment"].as<string>());

  start_write = Clock::now();
  string alignment_path = (output_dir / fs::path("alignment.bin")).string();
  config_stream << "alignment = " << alignment_path << endl;
  ofstream alignment_fstream(alignment_path);
  ar::binary_oarchive alignment_stream(alignment_fstream);
  alignment_stream << *alignment;
  stop_write = Clock::now();
  write_duration += GetDuration(start_write, stop_write);

  stop_time = Clock::now();
  cerr << "Reading alignment took "
       << GetDuration(start_time, stop_time) << " seconds" << endl;

  shared_ptr<Vocabulary> vocabulary = make_shared<Vocabulary>();

  start_time = Clock::now();
  cerr << "Precomputing collocations..." << endl;
  Precomputation precomputation(
      vocabulary,
      source_suffix_array,
      vm["frequent"].as<int>(),
      vm["super_frequent"].as<int>(),
      vm["max_rule_span"].as<int>(),
      vm["max_rule_symbols"].as<int>(),
      vm["min_gap_size"].as<int>(),
      vm["max_phrase_len"].as<int>(),
      vm["min_frequency"].as<int>());

  start_write = Clock::now();
  string precomputation_path = (output_dir / fs::path("precomp.bin")).string();
  config_stream << "precomputation = " << precomputation_path << endl;
  ofstream precomp_fstream(precomputation_path);
  ar::binary_oarchive precomp_stream(precomp_fstream);
  precomp_stream << precomputation;

  string vocabulary_path = (output_dir / fs::path("vocab.bin")).string();
  config_stream << "vocabulary = " << vocabulary_path << endl;
  ofstream vocab_fstream(vocabulary_path);
  ar::binary_oarchive vocab_stream(vocab_fstream);
  vocab_stream << *vocabulary;
  stop_write = Clock::now();
  write_duration += GetDuration(start_write, stop_write);

  stop_time = Clock::now();
  cerr << "Precomputing collocations took "
       << GetDuration(start_time, stop_time) << " seconds" << endl;

  start_time = Clock::now();
  cerr << "Precomputing conditional probabilities..." << endl;
  TranslationTable table(source_data_array, target_data_array, alignment);

  start_write = Clock::now();
  string table_path = (output_dir / fs::path("bilex.bin")).string();
  config_stream << "ttable = " << table_path << endl;
  ofstream table_fstream(table_path);
  ar::binary_oarchive table_stream(table_fstream);
  table_stream << table;
  stop_write = Clock::now();
  write_duration += GetDuration(start_write, stop_write);

  stop_time = Clock::now();
  cerr << "Precomputing conditional probabilities took "
       << GetDuration(start_time, stop_time) << " seconds" << endl;

  cerr << "Total time spent writing: " << write_duration
       << " seconds" << endl;

  return 0;
}
<|endoftext|>


<commit_before>template <typename Type>
class Queue
{
	Data <Type> *first;
	Data <Type> *last;
	unsigned long int count;
public:
	Queue();
	~Queue();

	const unsigned int length();
	void push(Type data);
	void remove();
	void show();
	void remove_all();
};

template <typename Type>
Queue<Type>::Queue()
{
	first = nullptr;
	last = nullptr;
	count = 0;
}

template <typename Type>
Queue<Type>::~Queue()
{
	first = nullptr;
	last = nullptr;
}

template <typename Type>
const unsigned int Queue<Type>::length()
{
	return count;
}

template <typename Type>
void Queue<Type>::push(Type data)
{
	Data <Type> *new_data = new Data <Type>;

	if (first==nullptr){
		new_data->new_data(data);
		first=new_data;
		last=new_data;
	} else {
		new_data->new_data(data);
		last->change_p_next_data(new_data); // current last has nullptr, so change to new adress
		last=new_data;	// change last
	}

	count++;
	new_data=nullptr;
}

template <typename Type>
void Queue<Type>::show()
{
	Data <Type> *pointer = first;
	unsigned int counter = 0;

	while(pointer!=nullptr)
	{
		cout << "Nr " << ++counter << " : " << pointer->return_data() << endl;
		pointer = pointer->return_p_next_data();
	}
	pointer = nullptr;
}

template <typename Type>
void Queue<Type>::remove_all()
{
	Data <Type> *pointer = first;
	Data <Type> *temp = nullptr;

	while(pointer!=nullptr)
	{
		temp = pointer->return_p_next_data();
		delete pointer;
		pointer = temp;
	}

	pointer = nullptr;
	temp = nullptr;
	count = 0;
}

template <typename Type>
void Queue<Type>::remove()
{
	Data <Type> *pointer = first;
	Data <Type> *temp = nullptr;

	if (count==1) {
		delete pointer;
		first = nullptr;
	} else {
		for(unsigned int i = 1; i < count-1; i++){
			pointer = pointer->return_p_next_data();
		}

		temp = pointer;
		pointer = pointer->return_p_next_data();
		delete pointer;

		temp->change_p_next_data(nullptr);
		last = temp;
	}

	count --;
	temp = nullptr;
	pointer = nullptr;

}
<commit_msg>Final version, changed push function<commit_after>#include "Data.hpp"

template <typename Type>
class Queue
{
	Data <Type> *first;
	Data <Type> *last;
	unsigned long int count;
public:
	Queue();
	~Queue();

	const unsigned int length();
	void push(Type data);
	void pop();
	void show();
	void remove_all();
};

template <typename Type>
Queue<Type>::Queue()
{
	first = nullptr;
	last = nullptr;
	count = 0;
}

template <typename Type>
Queue<Type>::~Queue()
{
	first = nullptr;
	last = nullptr;
}

template <typename Type>
const unsigned int Queue<Type>::length()
{
	return count;
}

template <typename Type>
void Queue<Type>::push(Type data)
{
	Data <Type> *new_data = new Data <Type>;

	if (first==nullptr){
		new_data->new_data(data);
		first=new_data;
		last=new_data;
	} else {
		new_data->new_data(data);
		last->change_p_next_data(new_data); // current last has nullptr, so change to new adress
		last=new_data;	// change last
	}

	count++;
	new_data=nullptr;
}

template <typename Type>
void Queue<Type>::show()
{
	Data <Type> *pointer = first;
	unsigned int counter = 0;

	while(pointer!=nullptr)
	{
		cout << "Nr " << ++counter << " : " << pointer->return_data() << endl;
		pointer = pointer->return_p_next_data();
	}
	pointer = nullptr;
}

template <typename Type>
void Queue<Type>::remove_all()
{
	Data <Type> *pointer = first;
	Data <Type> *temp = nullptr;

	while(pointer!=nullptr)
	{
		temp = pointer->return_p_next_data();
		delete pointer;
		pointer = temp;
	}

	pointer = nullptr;
	temp = nullptr;
	count = 0;
}

template <typename Type>
void Queue<Type>::pop()
{
	Data <Type> *pointer = first;
	Data <Type> *temp = nullptr;

	if (count==1) {
		delete pointer;
		first = nullptr;
	} else {
		temp=pointer->return_p_next_data();
		delete pointer;
		first = temp;
	}

	count --;
	temp = nullptr;
	pointer = nullptr;

}
<|endoftext|>


<commit_before>//
//  ZX8081.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 04/06/2017.
//  Copyright © 2017 Thomas Harte. All rights reserved.
//

#include "ZX8081.hpp"

#include "../MemoryFuzzer.hpp"

using namespace ZX8081;

Machine::Machine() :
	vsync_(false),
	hsync_(false),
	ram_(1024),
	line_data_(nullptr) {
	// run at 3.25 Mhz
	set_clock_rate(3250000);
	Memory::Fuzz(ram_);
}

int Machine::perform_machine_cycle(const CPU::Z80::MachineCycle &cycle) {
	cycles_since_display_update_ += cycle.length;

	uint8_t r;
	uint16_t address = cycle.address ? *cycle.address : 0;
	switch(cycle.operation) {
		case CPU::Z80::BusOperation::Output:
			if((address&7) == 7) {
				set_vsync(false);
			}
		break;

		case CPU::Z80::BusOperation::Input:
			if((address&7) == 6) {
				set_vsync(true);
			}
			*cycle.value = 0xff;
		break;

		case CPU::Z80::BusOperation::Interrupt:
			set_hsync(true);
			*cycle.value = 0xff;
		break;

		case CPU::Z80::BusOperation::ReadOpcode:
			set_hsync(false);
			r = (uint8_t)get_value_of_register(CPU::Z80::Register::R);
			set_interrupt_line(!(r & 0x40));
		case CPU::Z80::BusOperation::Read:
			if((address & 0xc000) == 0x0000) *cycle.value = rom_[address & (rom_.size() - 1)];
			else if((address & 0x4000) == 0x4000) {
				uint8_t value = ram_[address & 1023];
				if(address&0x8000 && !(value & 0x40) && cycle.operation == CPU::Z80::BusOperation::ReadOpcode && !get_halt_line()) {
					// TODO: character lookup.
					output_byte(value);
					*cycle.value = 0;
				} else *cycle.value = value;
			}
		break;

		case CPU::Z80::BusOperation::Write:
			if((address & 0x4000) == 0x4000) ram_[address & 1023] = *cycle.value;
		break;

		default: break;
	}

	return 0;
}

void Machine::setup_output(float aspect_ratio) {
	crt_.reset(new Outputs::CRT::CRT(210, 1, Outputs::CRT::DisplayType::PAL50, 1));
	crt_->set_rgb_sampling_function(
		"vec3 rgb_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate)"
		"{"
			"return vec3(float(texture(texID, coordinate).r) / 255.0);"
		"}");
}

void Machine::flush() {
	update_display();
}

void Machine::close_output() {
}

std::shared_ptr<Outputs::CRT::CRT> Machine::get_crt() {
	return crt_;
}

std::shared_ptr<Outputs::Speaker> Machine::get_speaker() {
	return nullptr;
}

void Machine::run_for_cycles(int number_of_cycles) {
	CPU::Z80::Processor<Machine>::run_for_cycles(number_of_cycles);
}

void Machine::configure_as_target(const StaticAnalyser::Target &target) {
	// TODO: pay attention to the target
	rom_ = zx80_rom_;
}

void Machine::set_rom(ROMType type, std::vector<uint8_t> data) {
	switch(type) {
		case ZX80: zx80_rom_ = data; break;
		case ZX81: zx81_rom_ = data; break;
	}
}

#pragma mark - Video

void Machine::update_display() {
//	cycles_since_display_update_ = 0;
}

void Machine::set_vsync(bool sync) {
	if(sync == vsync_) return;
	vsync_ = sync;
	update_sync();
}

void Machine::set_hsync(bool sync) {
	if(sync == hsync_) return;
	hsync_ = sync;
	update_sync();
}

void Machine::update_sync() {
	bool is_sync = hsync_ || vsync_;
	if(is_sync == is_sync_) return;

	if(line_data_) {
		output_data();
	}

	if(is_sync_) {
		crt_->output_sync(cycles_since_display_update_);
	} else {
		output_level(cycles_since_display_update_);
	}
	cycles_since_display_update_ = 0;
	is_sync_ = is_sync;
}

void Machine::output_level(unsigned int number_of_cycles) {
	uint8_t *colour_pointer = (uint8_t *)crt_->allocate_write_area(1);
	if(colour_pointer) *colour_pointer = 0xff;
	crt_->output_level(number_of_cycles);
}

void Machine::output_data() {
	unsigned int data_length = (unsigned int)(line_data_pointer_ - line_data_);
	crt_->output_data(data_length, 1);
	line_data_pointer_ = line_data_ = nullptr;
	cycles_since_display_update_ -= data_length;
}

void Machine::output_byte(uint8_t byte) {
	if(line_data_) {
		if(cycles_since_display_update_ > 4) {
			output_data();
		}
	} else {
		output_level(cycles_since_display_update_);
	}

	if(!line_data_) {
		line_data_pointer_ = line_data_ = crt_->allocate_write_area(320);
	}

	if(line_data_) {
		line_data_pointer_[0] = byte;
		line_data_pointer_[1] = byte;
		line_data_pointer_[2] = byte;
		line_data_pointer_[3] = byte;
		line_data_pointer_ += 4;
	}
}
<commit_msg>Probably more-or-less corrected. But this is all a bit too interdependent.<commit_after>//
//  ZX8081.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 04/06/2017.
//  Copyright © 2017 Thomas Harte. All rights reserved.
//

#include "ZX8081.hpp"

#include "../MemoryFuzzer.hpp"

using namespace ZX8081;

Machine::Machine() :
	vsync_(false),
	hsync_(false),
	ram_(1024),
	line_data_(nullptr) {
	// run at 3.25 Mhz
	set_clock_rate(3250000);
	Memory::Fuzz(ram_);
}

int Machine::perform_machine_cycle(const CPU::Z80::MachineCycle &cycle) {
	cycles_since_display_update_ += cycle.length;

	uint8_t r;
	uint16_t address = cycle.address ? *cycle.address : 0;
	switch(cycle.operation) {
		case CPU::Z80::BusOperation::Output:
			if((address&7) == 7) {
				set_vsync(false);
			}
		break;

		case CPU::Z80::BusOperation::Input:
			if((address&7) == 6) {
				set_vsync(true);
			}
			*cycle.value = 0xff;
		break;

		case CPU::Z80::BusOperation::Interrupt:
			set_hsync(true);
			*cycle.value = 0xff;
		break;

		case CPU::Z80::BusOperation::ReadOpcode:
			set_hsync(false);
			r = (uint8_t)get_value_of_register(CPU::Z80::Register::R);
			set_interrupt_line(!(r & 0x40));
		case CPU::Z80::BusOperation::Read:
			if((address & 0xc000) == 0x0000) *cycle.value = rom_[address & (rom_.size() - 1)];
			else if((address & 0x4000) == 0x4000) {
				uint8_t value = ram_[address & 1023];
				if(address&0x8000 && !(value & 0x40) && cycle.operation == CPU::Z80::BusOperation::ReadOpcode && !get_halt_line()) {
					// TODO: character lookup.
					output_byte(value);
					*cycle.value = 0;
				} else *cycle.value = value;
			}
		break;

		case CPU::Z80::BusOperation::Write:
			if((address & 0x4000) == 0x4000) ram_[address & 1023] = *cycle.value;
		break;

		default: break;
	}

	return 0;
}

void Machine::setup_output(float aspect_ratio) {
	crt_.reset(new Outputs::CRT::CRT(210, 1, Outputs::CRT::DisplayType::PAL50, 1));
	crt_->set_rgb_sampling_function(
		"vec3 rgb_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate)"
		"{"
			"return vec3(float(texture(texID, coordinate).r) / 255.0);"
		"}");
}

void Machine::flush() {
	update_display();
}

void Machine::close_output() {
}

std::shared_ptr<Outputs::CRT::CRT> Machine::get_crt() {
	return crt_;
}

std::shared_ptr<Outputs::Speaker> Machine::get_speaker() {
	return nullptr;
}

void Machine::run_for_cycles(int number_of_cycles) {
	CPU::Z80::Processor<Machine>::run_for_cycles(number_of_cycles);
}

void Machine::configure_as_target(const StaticAnalyser::Target &target) {
	// TODO: pay attention to the target
	rom_ = zx80_rom_;
}

void Machine::set_rom(ROMType type, std::vector<uint8_t> data) {
	switch(type) {
		case ZX80: zx80_rom_ = data; break;
		case ZX81: zx81_rom_ = data; break;
	}
}

#pragma mark - Video

void Machine::update_display() {
//	cycles_since_display_update_ = 0;
}

void Machine::set_vsync(bool sync) {
	if(sync == vsync_) return;
	vsync_ = sync;
	update_sync();
}

void Machine::set_hsync(bool sync) {
	if(sync == hsync_) return;
	hsync_ = sync;
	update_sync();
}

void Machine::update_sync() {
	bool is_sync = hsync_ || vsync_;
	if(is_sync == is_sync_) return;

	if(line_data_) {
		output_data();
	}

	if(is_sync_) {
		crt_->output_sync(cycles_since_display_update_);
	} else {
		output_level(cycles_since_display_update_);
	}
	cycles_since_display_update_ = 0;
	is_sync_ = is_sync;
}

void Machine::output_level(unsigned int number_of_cycles) {
	uint8_t *colour_pointer = (uint8_t *)crt_->allocate_write_area(1);
	if(colour_pointer) *colour_pointer = 0xff;
	crt_->output_level(number_of_cycles);
}

void Machine::output_data() {
	unsigned int data_length = (unsigned int)(line_data_pointer_ - line_data_);
	crt_->output_data(data_length, 1);
	line_data_pointer_ = line_data_ = nullptr;
	cycles_since_display_update_ -= data_length;
}

void Machine::output_byte(uint8_t byte) {
	if(line_data_) {
		if(cycles_since_display_update_ > 4) {
			output_data();
		}
	} else {
		output_level(cycles_since_display_update_);
		cycles_since_display_update_ = 0;
	}

	if(!line_data_) {
		line_data_pointer_ = line_data_ = crt_->allocate_write_area(320);
	}

	if(line_data_) {
		line_data_pointer_[0] = byte;
		line_data_pointer_[1] = byte;
		line_data_pointer_[2] = byte;
		line_data_pointer_[3] = byte;
		line_data_pointer_ += 4;
	}
}
<|endoftext|>


<commit_before>#include "rcc.h"
#include "flash.h"

void rcc_init() {
	// Initialize flash.
	flash_init();

	#if defined(STM32F1) || defined(STM32F3)

	// Enable HSE.
	RCC.CR |= 0x10000;
	while(RCC.CR & 0x20000);

	// Configure and enable PLL.
	RCC.CFGR = 0x1d0000;
	RCC.CR |= 0x1000000;
	while(!(RCC.CR & 0x2000000));

	// Switch to PLL.
	RCC.CFGR |= 0x2;
	while(!(RCC.CFGR & 0x8));

	// Set APB1 prescaler to /2.
	RCC.CFGR |= 0x400;

	// Set ADCCLK prescaler to /6.
	RCC.CFGR |= 0x8000;

	#elif defined(STM32F4)

	// Enable HSE.
	RCC.CR |= 0x10000;
	while(!(RCC.CR & 0x20000));

	// Configure and enable PLL.
	RCC.PLLCFGR = 0x20400000 | (7 << 24) | (2 * 168 << 6) | 8;
	RCC.CR |= 0x1000000;
	while(!(RCC.CR & 0x2000000));

	// Switch to PLL.
	RCC.CFGR |= 0x2;
	while(!(RCC.CFGR & 0x8));

	// Set APB1 prescaler to /4.
	RCC.CFGR |= 5 << 10;

	// Set APB2 prescaler to /2.
	RCC.CFGR |= 4 << 13;

	#endif
}
<commit_msg>Fixed F1 RCC bug.<commit_after>#include "rcc.h"
#include "flash.h"

void rcc_init() {
	// Initialize flash.
	flash_init();

	#if defined(STM32F1) || defined(STM32F3)

	// Enable HSE.
	RCC.CR |= 0x10000;
	while(!(RCC.CR & 0x20000));

	// Configure and enable PLL.
	RCC.CFGR = 0x1d0000;
	RCC.CR |= 0x1000000;
	while(!(RCC.CR & 0x2000000));

	// Switch to PLL.
	RCC.CFGR |= 0x2;
	while(!(RCC.CFGR & 0x8));

	// Set APB1 prescaler to /2.
	RCC.CFGR |= 0x400;

	// Set ADCCLK prescaler to /6.
	RCC.CFGR |= 0x8000;

	#elif defined(STM32F4)

	// Enable HSE.
	RCC.CR |= 0x10000;
	while(!(RCC.CR & 0x20000));

	// Configure and enable PLL.
	RCC.PLLCFGR = 0x20400000 | (7 << 24) | (2 * 168 << 6) | 8;
	RCC.CR |= 0x1000000;
	while(!(RCC.CR & 0x2000000));

	// Switch to PLL.
	RCC.CFGR |= 0x2;
	while(!(RCC.CFGR & 0x8));

	// Set APB1 prescaler to /4.
	RCC.CFGR |= 5 << 10;

	// Set APB2 prescaler to /2.
	RCC.CFGR |= 4 << 13;

	#endif
}
<|endoftext|>


<commit_before>// This file is a part of the OpenSurgSim project.
// Copyright 2013, SimQuest Solutions Inc.
//
// 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 "SurgSim/Framework/Log.h"
#include "SurgSim/Graphics/TangentSpaceGenerator.h"

#include <osg/TriangleIndexFunctor>
#include <osg/Vec3>
#include <osg/Array>

namespace
{

void orthogonalize(const osg::Vec3& normal, osg::Vec4* tangent, osg::Vec4* bitangent,
				   bool createOrthonormalBasis = false)
{
	SURGSIM_ASSERT(tangent != nullptr) << "Tanget parameter can't be nullptr.";
	SURGSIM_ASSERT(bitangent != nullptr) << "BiTangent parameter can't be nullptr.";

	osg::Vec4 normal4(normal, 0.0);
	// Gram-Schmidt orthogonalize the tangent
	(*tangent) = (*tangent) - normal4 * (normal4 * (*tangent));
	tangent->normalize();

	if (createOrthonormalBasis)
	{
		osg::Vec3 tangent3 = osg::Vec3(tangent->x(), tangent->y(), tangent->z());
		osg::Vec3 bitangent3 = osg::Vec3(bitangent->x(), bitangent->y(), bitangent->z());
		osg::Vec3 cross = normal ^ tangent3;

		// Calculate handedness
		float handedness = 1.0f;
		if ((cross * bitangent3) < 0.0f)
		{
			handedness = -1.0f;
		}

		(*bitangent) = osg::Vec4(cross * handedness, 0.0f);
	}
	else
	{
		// Gram-Schmidt orthogonalize the bitangent
		(*bitangent) = (*bitangent) - normal4 * (normal4 * (*bitangent));
		bitangent->normalize();
	}
}

}

namespace SurgSim
{
namespace Graphics
{

GenerateTangentSpaceTriangleIndexFunctor::GenerateTangentSpaceTriangleIndexFunctor() :
	m_vertexArray(nullptr),
	m_normalArray(nullptr),
	m_textureCoordArray(nullptr),
	m_tangentArray(nullptr),
	m_bitangentArray(nullptr),
	m_createOrthonormalBasis(false)
{
}

void GenerateTangentSpaceTriangleIndexFunctor::setBasisOrthonormality(bool orthonormal)
{
	m_createOrthonormalBasis = orthonormal;
}
bool GenerateTangentSpaceTriangleIndexFunctor::getBasisOrthonormality()
{
	return m_createOrthonormalBasis;
}

void GenerateTangentSpaceTriangleIndexFunctor::set(
	const osg::Vec3Array* vertexArray,
	const osg::Vec3Array* normalArray,
	const osg::Vec2Array* textureCoordArray,
	osg::Vec4Array* tangentArray,
	osg::Vec4Array* bitangentArray)
{

	SURGSIM_ASSERT(vertexArray != nullptr) << "Need vertex array to generate normals!";
	size_t numVertices = vertexArray->size();

	SURGSIM_ASSERT(normalArray != nullptr) << "Need normal array to store normals!";
	SURGSIM_ASSERT(normalArray->size() == numVertices)
			<< "Size of normal array must match the number of vertices to generate tangent space!";

	SURGSIM_ASSERT(tangentArray != nullptr) << "Need tangent array to store tangent space!";
	SURGSIM_ASSERT(tangentArray->size() == numVertices)
			<< "Size of tangent array must match the number of vertices to generate tangent space!";

	SURGSIM_ASSERT(bitangentArray != nullptr) <<  "Need bitangent array to store tangent space!";
	SURGSIM_ASSERT(bitangentArray->size() == numVertices)
			<< "Size of bitangent array must match the number of vertices to generate tangent space!";

	m_vertexArray = vertexArray;
	m_normalArray = normalArray;
	m_textureCoordArray = textureCoordArray;
	m_tangentArray = tangentArray;
	m_bitangentArray = bitangentArray;
}

void GenerateTangentSpaceTriangleIndexFunctor::orthogonalize()
{
	size_t numVertices = m_vertexArray->size();

	for (size_t vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex)
	{
		::orthogonalize((*m_normalArray)[vertexIndex],
						 &(*m_tangentArray)[vertexIndex],
						 &(*m_bitangentArray)[vertexIndex],
						 m_createOrthonormalBasis);
	}
}

void GenerateTangentSpaceTriangleIndexFunctor::reset()
{
	size_t numVertices = m_vertexArray->size();

	for (size_t vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex)
	{
		(*m_tangentArray)[vertexIndex].set(0.0f, 0.0f, 0.0f, 0.0f);
		(*m_bitangentArray)[vertexIndex].set(0.0f, 0.0f, 0.0f, 0.0f);
	}
}

void GenerateTangentSpaceTriangleIndexFunctor::operator()(unsigned int vertexIndex1, unsigned int vertexIndex2,
		unsigned int vertexIndex3)
{
	if (vertexIndex1 == vertexIndex2 || vertexIndex2 == vertexIndex3 || vertexIndex1 == vertexIndex3)
	{
		return;
	}

	const osg::Vec3& v1 = (*m_vertexArray)[vertexIndex1];
	const osg::Vec3& v2 = (*m_vertexArray)[vertexIndex2];
	const osg::Vec3& v3 = (*m_vertexArray)[vertexIndex3];

	const osg::Vec2& w1 = (*m_textureCoordArray)[vertexIndex1];
	const osg::Vec2& w2 = (*m_textureCoordArray)[vertexIndex2];
	const osg::Vec2& w3 = (*m_textureCoordArray)[vertexIndex3];

	float x1 = v2.x() - v1.x();
	float x2 = v3.x() - v1.x();
	float y1 = v2.y() - v1.y();
	float y2 = v3.y() - v1.y();
	float z1 = v2.z() - v1.z();
	float z2 = v3.z() - v1.z();

	float s1 = w2.x() - w1.x();
	float s2 = w3.x() - w1.x();
	float t1 = w2.y() - w1.y();
	float t2 = w3.y() - w1.y();

	float r = 1.0f / (s1 * t2 - s2 * t1);
	osg::Vec4 tangent((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r, 0.0f);
	osg::Vec4 bitangent((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r, 0.0f);

	(*m_tangentArray)[vertexIndex1] += tangent;
	(*m_bitangentArray)[vertexIndex1] += bitangent;

	(*m_tangentArray)[vertexIndex2] += tangent;
	(*m_bitangentArray)[vertexIndex2] += bitangent;

	(*m_tangentArray)[vertexIndex3] += tangent;
	(*m_bitangentArray)[vertexIndex3] += bitangent;
}

TangentSpaceGenerator::TangentSpaceGenerator(int textureCoordUnit, int tangentAttribIndex, int bitangentAttribIndex) :
	osg::NodeVisitor(),
	m_textureCoordUnit(textureCoordUnit),
	m_tangentAttribIndex(tangentAttribIndex),
	m_bitangentAttribIndex(bitangentAttribIndex)
{
	setTraversalMode(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN);
}

TangentSpaceGenerator::~TangentSpaceGenerator()
{
}

void TangentSpaceGenerator::setBasisOrthonormality(bool orthonormal)
{
	m_createOrthonormalBasis = orthonormal;
}
bool TangentSpaceGenerator::getBasisOrthonormality()
{
	return m_createOrthonormalBasis;
}

void TangentSpaceGenerator::apply(osg::Geode& geode)
{
	for (unsigned int i = 0; i < geode.getNumDrawables(); i++)
	{
		osg::Geometry* geometry = geode.getDrawable(i)->asGeometry();
		if (geometry)
		{
			generateTangentSpace(geometry, m_textureCoordUnit, m_tangentAttribIndex, m_bitangentAttribIndex,
								 m_createOrthonormalBasis);
		}
	}
}

void TangentSpaceGenerator::generateTangentSpace(osg::Geometry* geometry, int textureCoordUnit, int tangentAttribIndex,
		int bitangentAttribIndex,
		bool orthonormal)
{

	auto logger = SurgSim::Framework::Logger::getLogger("Graphics/TangetSpaceGenerator");

	osg::Vec3Array* vertexArray = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());
	if (vertexArray == nullptr)
	{
		SURGSIM_LOG_WARNING(logger) << "No Vertices found, could not produce tangents.";
		return;
	}

	osg::Vec3Array* normalArray = dynamic_cast<osg::Vec3Array*>(geometry->getNormalArray());
	if (normalArray == nullptr || normalArray->size() != vertexArray->size())
	{
		SURGSIM_LOG_WARNING(logger) << "No Normals found, or mismatch in array sizes, could not produce tangents.";
		return;
	}

	osg::Vec2Array* textureCoordArray =
		dynamic_cast<osg::Vec2Array*>(geometry->getTexCoordArray(textureCoordUnit));
	if (textureCoordArray == nullptr || textureCoordArray->size() != vertexArray->size())
	{
		SURGSIM_LOG_WARNING(logger)
				<< "No Texture Coordinates found, or mismatch in array sizes could not produce tangents.";
		return;
	}

	bool didUpdateGeom = false;

	osg::Vec4Array* tangentArray =
		dynamic_cast<osg::Vec4Array*>(geometry->getVertexAttribArray(tangentAttribIndex));
	if (tangentArray == nullptr || tangentArray->size() != vertexArray->size())
	{
		tangentArray = new osg::Vec4Array(vertexArray->size());
		geometry->setVertexAttribArray(tangentAttribIndex, tangentArray);
		geometry->setVertexAttribBinding(tangentAttribIndex, osg::Geometry::BIND_PER_VERTEX);
		didUpdateGeom = true;
	}

	osg::Vec4Array* bitangentArray =
		dynamic_cast<osg::Vec4Array*>(geometry->getVertexAttribArray(bitangentAttribIndex));
	if (bitangentArray == nullptr || bitangentArray->size() != vertexArray->size())
	{
		bitangentArray = new osg::Vec4Array(vertexArray->size());
		geometry->setVertexAttribArray(bitangentAttribIndex, bitangentArray);
		geometry->setVertexAttribBinding(bitangentAttribIndex, osg::Geometry::BIND_PER_VERTEX);
		didUpdateGeom = true;
	}

	osg::TriangleIndexFunctor<GenerateTangentSpaceTriangleIndexFunctor> tangentSpaceGenerator;
	tangentSpaceGenerator.setBasisOrthonormality(orthonormal);
	tangentSpaceGenerator.set(vertexArray, normalArray, textureCoordArray, tangentArray, bitangentArray);
	tangentSpaceGenerator.reset();
	geometry->accept(tangentSpaceGenerator);
	tangentSpaceGenerator.orthogonalize();

	if (didUpdateGeom)
	{
		// geometry->dirtyDisplayList();
		geometry->setUseDisplayList(false);
		geometry->dirtyBound();
		geometry->setDataVariance(osg::Object::DYNAMIC);
	}
}

}
}
<commit_msg>Fix tangent generator to accommodate for cases when the denominator for the r scaling variable is 0 or smaller than epsilon<commit_after>// This file is a part of the OpenSurgSim project.
// Copyright 2013, SimQuest Solutions Inc.
//
// 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 "SurgSim/Framework/Log.h"
#include "SurgSim/Graphics/TangentSpaceGenerator.h"
#include "SurgSim/Math/Geometry.h"

#include <osg/TriangleIndexFunctor>
#include <osg/Vec3>
#include <osg/Array>

namespace
{

void orthogonalize(const osg::Vec3& normal, osg::Vec4* tangent, osg::Vec4* bitangent,
				   bool createOrthonormalBasis = false)
{
	SURGSIM_ASSERT(tangent != nullptr) << "Tanget parameter can't be nullptr.";
	SURGSIM_ASSERT(bitangent != nullptr) << "BiTangent parameter can't be nullptr.";

	osg::Vec4 normal4(normal, 0.0);
	// Gram-Schmidt orthogonalize the tangent
	(*tangent) = (*tangent) - normal4 * (normal4 * (*tangent));
	tangent->normalize();

	if (createOrthonormalBasis)
	{
		osg::Vec3 tangent3 = osg::Vec3(tangent->x(), tangent->y(), tangent->z());
		osg::Vec3 bitangent3 = osg::Vec3(bitangent->x(), bitangent->y(), bitangent->z());
		osg::Vec3 cross = normal ^ tangent3;

		// Calculate handedness
		float handedness = 1.0f;
		if ((cross * bitangent3) < 0.0f)
		{
			handedness = -1.0f;
		}

		(*bitangent) = osg::Vec4(cross * handedness, 0.0f);
	}
	else
	{
		// Gram-Schmidt orthogonalize the bitangent
		(*bitangent) = (*bitangent) - normal4 * (normal4 * (*bitangent));
		bitangent->normalize();
	}
}

}

namespace SurgSim
{
namespace Graphics
{

GenerateTangentSpaceTriangleIndexFunctor::GenerateTangentSpaceTriangleIndexFunctor() :
	m_vertexArray(nullptr),
	m_normalArray(nullptr),
	m_textureCoordArray(nullptr),
	m_tangentArray(nullptr),
	m_bitangentArray(nullptr),
	m_createOrthonormalBasis(false)
{
}

void GenerateTangentSpaceTriangleIndexFunctor::setBasisOrthonormality(bool orthonormal)
{
	m_createOrthonormalBasis = orthonormal;
}
bool GenerateTangentSpaceTriangleIndexFunctor::getBasisOrthonormality()
{
	return m_createOrthonormalBasis;
}

void GenerateTangentSpaceTriangleIndexFunctor::set(
	const osg::Vec3Array* vertexArray,
	const osg::Vec3Array* normalArray,
	const osg::Vec2Array* textureCoordArray,
	osg::Vec4Array* tangentArray,
	osg::Vec4Array* bitangentArray)
{

	SURGSIM_ASSERT(vertexArray != nullptr) << "Need vertex array to generate normals!";
	size_t numVertices = vertexArray->size();

	SURGSIM_ASSERT(normalArray != nullptr) << "Need normal array to store normals!";
	SURGSIM_ASSERT(normalArray->size() == numVertices)
			<< "Size of normal array must match the number of vertices to generate tangent space!";

	SURGSIM_ASSERT(tangentArray != nullptr) << "Need tangent array to store tangent space!";
	SURGSIM_ASSERT(tangentArray->size() == numVertices)
			<< "Size of tangent array must match the number of vertices to generate tangent space!";

	SURGSIM_ASSERT(bitangentArray != nullptr) <<  "Need bitangent array to store tangent space!";
	SURGSIM_ASSERT(bitangentArray->size() == numVertices)
			<< "Size of bitangent array must match the number of vertices to generate tangent space!";

	m_vertexArray = vertexArray;
	m_normalArray = normalArray;
	m_textureCoordArray = textureCoordArray;
	m_tangentArray = tangentArray;
	m_bitangentArray = bitangentArray;
}

void GenerateTangentSpaceTriangleIndexFunctor::orthogonalize()
{
	size_t numVertices = m_vertexArray->size();

	for (size_t vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex)
	{
		::orthogonalize((*m_normalArray)[vertexIndex],
						 &(*m_tangentArray)[vertexIndex],
						 &(*m_bitangentArray)[vertexIndex],
						 m_createOrthonormalBasis);
	}
}

void GenerateTangentSpaceTriangleIndexFunctor::reset()
{
	size_t numVertices = m_vertexArray->size();

	for (size_t vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex)
	{
		(*m_tangentArray)[vertexIndex].set(0.0f, 0.0f, 0.0f, 0.0f);
		(*m_bitangentArray)[vertexIndex].set(0.0f, 0.0f, 0.0f, 0.0f);
	}
}

void GenerateTangentSpaceTriangleIndexFunctor::operator()(unsigned int vertexIndex1, unsigned int vertexIndex2,
		unsigned int vertexIndex3)
{
	if (vertexIndex1 == vertexIndex2 || vertexIndex2 == vertexIndex3 || vertexIndex1 == vertexIndex3)
	{
		return;
	}

	const osg::Vec3& v1 = (*m_vertexArray)[vertexIndex1];
	const osg::Vec3& v2 = (*m_vertexArray)[vertexIndex2];
	const osg::Vec3& v3 = (*m_vertexArray)[vertexIndex3];

	const osg::Vec2& w1 = (*m_textureCoordArray)[vertexIndex1];
	const osg::Vec2& w2 = (*m_textureCoordArray)[vertexIndex2];
	const osg::Vec2& w3 = (*m_textureCoordArray)[vertexIndex3];

	float x1 = v2.x() - v1.x();
	float x2 = v3.x() - v1.x();
	float y1 = v2.y() - v1.y();
	float y2 = v3.y() - v1.y();
	float z1 = v2.z() - v1.z();
	float z2 = v3.z() - v1.z();

	float s1 = w2.x() - w1.x();
	float s2 = w3.x() - w1.x();
	float t1 = w2.y() - w1.y();
	float t2 = w3.y() - w1.y();

	float denominator = (s1 * t2 - s2 * t1);
	if (denominator == 0)
	{
		denominator = 1.0f;
	}
	else if (abs(denominator) < Math::Geometry::ScalarEpsilon)
	{
		denominator = Math::Geometry::ScalarEpsilon * ((denominator < 0) ? -1 : 1);
	}

	float r = 1.0f / denominator;
	osg::Vec4 tangent((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r, 0.0f);
	osg::Vec4 bitangent((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r, 0.0f);

	(*m_tangentArray)[vertexIndex1] += tangent;
	(*m_bitangentArray)[vertexIndex1] += bitangent;

	(*m_tangentArray)[vertexIndex2] += tangent;
	(*m_bitangentArray)[vertexIndex2] += bitangent;

	(*m_tangentArray)[vertexIndex3] += tangent;
	(*m_bitangentArray)[vertexIndex3] += bitangent;
}

TangentSpaceGenerator::TangentSpaceGenerator(int textureCoordUnit, int tangentAttribIndex, int bitangentAttribIndex) :
	osg::NodeVisitor(),
	m_textureCoordUnit(textureCoordUnit),
	m_tangentAttribIndex(tangentAttribIndex),
	m_bitangentAttribIndex(bitangentAttribIndex)
{
	setTraversalMode(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN);
}

TangentSpaceGenerator::~TangentSpaceGenerator()
{
}

void TangentSpaceGenerator::setBasisOrthonormality(bool orthonormal)
{
	m_createOrthonormalBasis = orthonormal;
}
bool TangentSpaceGenerator::getBasisOrthonormality()
{
	return m_createOrthonormalBasis;
}

void TangentSpaceGenerator::apply(osg::Geode& geode)
{
	for (unsigned int i = 0; i < geode.getNumDrawables(); i++)
	{
		osg::Geometry* geometry = geode.getDrawable(i)->asGeometry();
		if (geometry)
		{
			generateTangentSpace(geometry, m_textureCoordUnit, m_tangentAttribIndex, m_bitangentAttribIndex,
								 m_createOrthonormalBasis);
		}
	}
}

void TangentSpaceGenerator::generateTangentSpace(osg::Geometry* geometry, int textureCoordUnit, int tangentAttribIndex,
		int bitangentAttribIndex,
		bool orthonormal)
{

	auto logger = SurgSim::Framework::Logger::getLogger("Graphics/TangetSpaceGenerator");

	osg::Vec3Array* vertexArray = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());
	if (vertexArray == nullptr)
	{
		SURGSIM_LOG_WARNING(logger) << "No Vertices found, could not produce tangents.";
		return;
	}

	osg::Vec3Array* normalArray = dynamic_cast<osg::Vec3Array*>(geometry->getNormalArray());
	if (normalArray == nullptr || normalArray->size() != vertexArray->size())
	{
		SURGSIM_LOG_WARNING(logger) << "No Normals found, or mismatch in array sizes, could not produce tangents.";
		return;
	}

	osg::Vec2Array* textureCoordArray =
		dynamic_cast<osg::Vec2Array*>(geometry->getTexCoordArray(textureCoordUnit));
	if (textureCoordArray == nullptr || textureCoordArray->size() != vertexArray->size())
	{
		SURGSIM_LOG_WARNING(logger)
				<< "No Texture Coordinates found, or mismatch in array sizes could not produce tangents.";
		return;
	}

	bool didUpdateGeom = false;

	osg::Vec4Array* tangentArray =
		dynamic_cast<osg::Vec4Array*>(geometry->getVertexAttribArray(tangentAttribIndex));
	if (tangentArray == nullptr || tangentArray->size() != vertexArray->size())
	{
		tangentArray = new osg::Vec4Array(vertexArray->size());
		geometry->setVertexAttribArray(tangentAttribIndex, tangentArray);
		geometry->setVertexAttribBinding(tangentAttribIndex, osg::Geometry::BIND_PER_VERTEX);
		didUpdateGeom = true;
	}

	osg::Vec4Array* bitangentArray =
		dynamic_cast<osg::Vec4Array*>(geometry->getVertexAttribArray(bitangentAttribIndex));
	if (bitangentArray == nullptr || bitangentArray->size() != vertexArray->size())
	{
		bitangentArray = new osg::Vec4Array(vertexArray->size());
		geometry->setVertexAttribArray(bitangentAttribIndex, bitangentArray);
		geometry->setVertexAttribBinding(bitangentAttribIndex, osg::Geometry::BIND_PER_VERTEX);
		didUpdateGeom = true;
	}

	osg::TriangleIndexFunctor<GenerateTangentSpaceTriangleIndexFunctor> tangentSpaceGenerator;
	tangentSpaceGenerator.setBasisOrthonormality(orthonormal);
	tangentSpaceGenerator.set(vertexArray, normalArray, textureCoordArray, tangentArray, bitangentArray);
	tangentSpaceGenerator.reset();
	geometry->accept(tangentSpaceGenerator);
	tangentSpaceGenerator.orthogonalize();

	if (didUpdateGeom)
	{
		// geometry->dirtyDisplayList();
		geometry->setUseDisplayList(false);
		geometry->dirtyBound();
		geometry->setDataVariance(osg::Object::DYNAMIC);
	}
}

}
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>

#include <gtest/gtest.h>

#include "env.h"
#include "logger.h"

int main(int argc, char* argv[]) {
  // tell ENV the path between the cwd and the cyclus executable
  using cyclus::Env;
  using cyclus::Logger;
  std::string path = Env::PathBase(argv[0]);
  Env::SetCyclusRelPath(path);
  Logger::ReportLevel() = cyclus::LEV_ERROR;

  for ( int i = 0; i < argc; i++ ) {
    std::string arg = argv[i];
    if ( arg == "--help" ) {
      std::cout << "GTest flags" << std::endl;
      std::cout << "\t--gtest_list_tests List the tests" << std::endl;
      std::cout << "\t--gtest_repeat Number of times to repeat each test" << std::endl;
      std::cout << "\t--gtest_filter Glob filter of test name" << std::endl;
      std::cout << "\t--gtest_print_time Time required to run" << std::endl;
      std::cout << "\nBy default, a Google Test program runs all tests the user has defined. Sometimes, you want to run only a subset of the tests (e.g. for debugging or quickly verifying a change). If you set the GTEST_FILTER environment variable or the --gtest_filter flag to a filter string, Google Test will only run the tests whose full names (in the form of TestCaseName.TestName) match the filter.\n"
        "The format of a filter is a ':'-separated list of wildcard patterns (called the positive patterns) optionally followed by a '-' and another ':'-separated pattern list (called the negative patterns). A test matches the filter if and only if it matches any of the positive patterns but does not match any of the negative patterns.\n"
        "A pattern may contain '*' (matches any string) or '?' (matches any single character). For convenience, the filter '*-NegativePatterns' can be also written as '-NegativePatterns'.\n"
        "For example:\n\n"
        " * ./foo_test Has no flag, and thus runs all its tests.\n"
        " * ./foo_test --gtest_filter=* Also runs everything, due to the single match-everything * value.\n"
        " * ./foo_test --gtest_filter=FooTest.* Runs everything in test case FooTest.\n"
        " * ./foo_test --gtest_filter=*Null*:*Constructor* Runs any test whose full name contains either \"Null\" or \"Constructor\".\n"
        " * ./foo_test --gtest_filter=-*DeathTest.* Runs all non-death tests.\n"
        " * ./foo_test --gtest_filter=FooTest.*-FooTest.Bar Runs everything in test case FooTest except FooTest.Bar. " << std::endl;
      return 0;
    }
  }
  testing::InitGoogleTest ( &argc, argv );
  return RUN_ALL_TESTS();
}
<commit_msg>test driver now adds the build directory to the cyclus module path. fixes #592. note that this overwrites the global module variable only for the test driver's environment.<commit_after>#include <iostream>
#include <string>
#include <stdio.h>

#include <gtest/gtest.h>

#include "env.h"
#include "logger.h"

int main(int argc, char* argv[]) {
  // tell ENV the path between the cwd and the cyclus executable
  using cyclus::Env;
  using cyclus::Logger;
  std::string path = Env::PathBase(argv[0]);
  Env::SetCyclusRelPath(path);
  Logger::ReportLevel() = cyclus::LEV_ERROR;

  std::string module_path = Env::ModuleEnvVarName() + "=" +
                            Env::GetBuildPath();
  putenv(const_cast<char *>(module_path.c_str()));

  for ( int i = 0; i < argc; i++ ) {
    std::string arg = argv[i];
    if ( arg == "--help" ) {
      std::cout << "GTest flags" << std::endl;
      std::cout << "\t--gtest_list_tests List the tests" << std::endl;
      std::cout << "\t--gtest_repeat Number of times to repeat each test" << std::endl;
      std::cout << "\t--gtest_filter Glob filter of test name" << std::endl;
      std::cout << "\t--gtest_print_time Time required to run" << std::endl;
      std::cout << "\nBy default, a Google Test program runs all tests the user has defined. Sometimes, you want to run only a subset of the tests (e.g. for debugging or quickly verifying a change). If you set the GTEST_FILTER environment variable or the --gtest_filter flag to a filter string, Google Test will only run the tests whose full names (in the form of TestCaseName.TestName) match the filter.\n"
        "The format of a filter is a ':'-separated list of wildcard patterns (called the positive patterns) optionally followed by a '-' and another ':'-separated pattern list (called the negative patterns). A test matches the filter if and only if it matches any of the positive patterns but does not match any of the negative patterns.\n"
        "A pattern may contain '*' (matches any string) or '?' (matches any single character). For convenience, the filter '*-NegativePatterns' can be also written as '-NegativePatterns'.\n"
        "For example:\n\n"
        " * ./foo_test Has no flag, and thus runs all its tests.\n"
        " * ./foo_test --gtest_filter=* Also runs everything, due to the single match-everything * value.\n"
        " * ./foo_test --gtest_filter=FooTest.* Runs everything in test case FooTest.\n"
        " * ./foo_test --gtest_filter=*Null*:*Constructor* Runs any test whose full name contains either \"Null\" or \"Constructor\".\n"
        " * ./foo_test --gtest_filter=-*DeathTest.* Runs all non-death tests.\n"
        " * ./foo_test --gtest_filter=FooTest.*-FooTest.Bar Runs everything in test case FooTest except FooTest.Bar. " << std::endl;
      return 0;
    }
  }
  testing::InitGoogleTest ( &argc, argv );
  return RUN_ALL_TESTS();
}
<|endoftext|>


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

Program:   Insight Segmentation & Registration Toolkit
Module:    itkSimplexMeshTest.cxx
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) Insight Software Consortium. All rights reserved.
See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

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

#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <math.h>
#include <iostream>
#include <time.h>

#include "itkMesh.h"
#include "itkSimplexMesh.h"
#include "itkSimplexMeshGeometry.h"
#include "itkDefaultDynamicMeshTraits.h"
#include "itkTimeProbe.h"

int itkSimplexMeshTest(int argc, char *argv[] )
{

  // Declare the type of the input and output mesh
  typedef itk::DefaultDynamicMeshTraits<double, 3, 3, double, double, double> MeshTraits;

  typedef itk::Mesh<double,3,MeshTraits> TriangleMeshType;
  typedef itk::SimplexMesh<double,3,MeshTraits> SimplexMeshType;

  SimplexMeshType::Pointer simplexMesh = SimplexMeshType::New();

  typedef  SimplexMeshType::NeighborListType              NeighborsListType;
  NeighborsListType* neighbors;
  NeighborsListType::iterator nIt, nEnd;

  for (int i=0; i < 9; i++)
    {
    itk::TimeProbe * timeProbe = new itk::TimeProbe();

    timeProbe->Start();
    for (int pointIndex = 0; pointIndex < simplexMesh->GetPoints()->Size(); pointIndex++)
    {
      neighbors = simplexMesh->GetNeighbors( pointIndex, i );
    }
    timeProbe->Stop();
    std::cout << "Rigidity: " << i << ", neighbor list size: " << neighbors->size() << std::endl;

    std::cout << ", Elapsed time (for getting neighbors): " << timeProbe->GetMeanTime() << std::endl;
    }

  std::cout << "[TEST DONE]" << std::endl;
  return EXIT_SUCCESS;

}

<commit_msg>ERR: warnings.<commit_after>/*=========================================================================

Program:   Insight Segmentation & Registration Toolkit
Module:    itkSimplexMeshTest.cxx
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) Insight Software Consortium. All rights reserved.
See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

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

#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <math.h>
#include <iostream>
#include <time.h>

#include "itkMesh.h"
#include "itkSimplexMesh.h"
#include "itkSimplexMeshGeometry.h"
#include "itkDefaultDynamicMeshTraits.h"
#include "itkTimeProbe.h"

int itkSimplexMeshTest(int , char *[] )
{

  // Declare the type of the input and output mesh
  typedef itk::DefaultDynamicMeshTraits<double, 3, 3, double, double, double> MeshTraits;

  typedef itk::Mesh<double,3,MeshTraits> TriangleMeshType;
  typedef itk::SimplexMesh<double,3,MeshTraits> SimplexMeshType;

  SimplexMeshType::Pointer simplexMesh = SimplexMeshType::New();

  typedef  SimplexMeshType::NeighborListType              NeighborsListType;
  NeighborsListType* neighbors;
  NeighborsListType::iterator nIt, nEnd;

  for (int i=0; i < 9; i++)
    {
    itk::TimeProbe * timeProbe = new itk::TimeProbe();

    timeProbe->Start();
    for (int pointIndex = 0; pointIndex < simplexMesh->GetPoints()->Size(); pointIndex++)
    {
      neighbors = simplexMesh->GetNeighbors( pointIndex, i );
    }
    timeProbe->Stop();
    std::cout << "Rigidity: " << i << ", neighbor list size: " << neighbors->size() << std::endl;

    std::cout << ", Elapsed time (for getting neighbors): " << timeProbe->GetMeanTime() << std::endl;
    }

  std::cout << "[TEST DONE]" << std::endl;
  return EXIT_SUCCESS;

}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2006-2013  Music Technology Group - Universitat Pompeu Fabra
 *
 * This file is part of Essentia
 *
 * Essentia is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation (FSF), either version 3 of the License, or (at your
 * option) any later version.
 *
 * This program 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 General Public License for more
 * details.
 *
 * You should have received a copy of the Affero GNU General Public License
 * version 3 along with this program.  If not, see http://www.gnu.org/licenses/
 */

#include "harmonicpeaks.h"
#include "essentiamath.h"

using namespace std;
using namespace essentia;
using namespace standard;

const char* HarmonicPeaks::name = "HarmonicPeaks";
const char* HarmonicPeaks::description = DOC("This algorithm finds the harmonic peaks of a signal given its spectral peaks and its fundamental frequency.\n"
"Note:\n"
"  - \"tolerance\" parameter defines the allowed fixed deviation from ideal harmonics, being a percentage over the F0. For example: if the F0 is 100Hz you may decide to allow a deviation of 20%, that is a fixed deviation of 20Hz; for the harmonic series it is: [180-220], [280-320], [380-420], etc.\n"
"  - If \"pitch\" is zero, it means its value is unknown, or the sound is unpitched, and in that case the HarmonicPeaks algorithm returns an empty vector.\n"
"  - The output frequency and magnitude vectors are of size \"maxHarmonics\". If a particular harmonic was not found among spectral peaks, its ideal frequency value is output together with 0 magnitude.\n"
"This algorithm is intended to receive its \"frequencies\" and \"magnitudes\" inputs from the SpectralPeaks algorithm.\n"
"  - When input vectors differ in size or are empty, an exception is thrown. Input vectors must be ordered by ascending frequency excluding DC components and not contain duplicates, otherwise an exception is thrown.\n"
"\n"
"References:\n"
"  [1] Harmonic Spectrum - Wikipedia, the free encyclopedia,\n"
"  http://en.wikipedia.org/wiki/Harmonic_spectrum");

bool sortCandidates(const std::pair<Real, std::pair<int, int> >& x, const std::pair<Real, std::pair<int, int> >& y) {
  return x.first < y.first;
}

void HarmonicPeaks::configure() {
  _maxHarmonics = parameter("maxHarmonics").toInt();
  _ratioTolerance = parameter("tolerance").toReal();
  _ratioMax = (Real) _maxHarmonics + _ratioTolerance;
}

void HarmonicPeaks::compute() {

  const vector<Real>& frequencies = _frequencies.get();
  const vector<Real>& magnitudes = _magnitudes.get();
  const Real& f0 = _pitch.get();
  vector<Real>& harmonicFrequencies = _harmonicFrequencies.get();
  vector<Real>& harmonicMagnitudes = _harmonicMagnitudes.get();

  if (magnitudes.size() != frequencies.size()) {
    throw EssentiaException("HarmonicPeaks: frequency and magnitude input vectors must have the same size");
  }

  if (f0 < 0) {
    throw EssentiaException("HarmonicPeaks: input pitch must be greater than zero");
  }

  harmonicFrequencies.resize(0);
  harmonicMagnitudes.resize(0);

  if (f0 == 0) {
    // pitch is unknown -> no harmonic peaks found
    return;
  }

  if (frequencies.empty()) {
    // no peaks -> no harmonic peaks either
    return;
  }

  if (frequencies[0] <= 0) {
    throw EssentiaException("HarmonicPeaks: spectral peak frequencies must be greater than 0Hz");
  }
  for (int i=1; i<int(frequencies.size()); ++i) {
    if (frequencies[i] < frequencies[i-1]) {
      throw EssentiaException("HarmonicPeaks: spectral peaks input must be ordered by frequency");
    }
    if (frequencies[i] == frequencies[i-1]) {
      throw EssentiaException("HarmonicPeaks: duplicate spectral peak found, peaks cannot be duplicated");
    }
    if (frequencies[i] <= 0) {
      throw EssentiaException("HarmonicPeaks: spectral peak frequencies must be greater than 0Hz");
    }
  }

  // Maximum allowed tolerance is less than 0.5 therefore, each peak can
  // correspond only to one ideal harmonic

  // Init candidates with <-1, 0> -- ideal harmonics
  vector<pair<int, Real> > candidates (_maxHarmonics, make_pair(-1, 0));

  for (int i=0; i<int(frequencies.size()); ++i) {
    Real ratio = frequencies[i] / f0;
    int harmonicNumber = round(ratio);

    Real distance = abs(ratio - harmonicNumber);
    if (distance <= _ratioTolerance && ratio <= _ratioMax) {
      if (candidates[harmonicNumber-1].first == -1 ||
            distance < candidates[harmonicNumber-1].second) {
        // first occured candidate or a better candidate for harmonic
        candidates[harmonicNumber-1].first = i;
        candidates[harmonicNumber-1].second = distance;
      }
      else if (distance == candidates[harmonicNumber-1].second) {
        // select the one with max amplitude
        if (magnitudes[i] > magnitudes[candidates[harmonicNumber-1].first]) {
          candidates[harmonicNumber-1].first = i;
          candidates[harmonicNumber-1].second = distance;
        }
      }
    }
  }

  for (int h=0; h < _maxHarmonics; ++h) {
    int i = candidates[h].first;
    if (i < 0) {
      // harmonic not found, output ideal harmonic with 0 magnitude
      harmonicFrequencies.push_back((h+1) * f0);
      harmonicMagnitudes.push_back(0.);
    }
    else {
      harmonicFrequencies.push_back(frequencies[i]);
      harmonicMagnitudes.push_back(magnitudes[i]);
    }
  }
}
<commit_msg>fix wrong behaviour of harmonicpeaks and so HPCP/and keydetection algorithms: was accessing to negative array index when if spectralpeaks had frequencies < f0/2<commit_after>/*
 * Copyright (C) 2006-2013  Music Technology Group - Universitat Pompeu Fabra
 *
 * This file is part of Essentia
 *
 * Essentia is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation (FSF), either version 3 of the License, or (at your
 * option) any later version.
 *
 * This program 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 General Public License for more
 * details.
 *
 * You should have received a copy of the Affero GNU General Public License
 * version 3 along with this program.  If not, see http://www.gnu.org/licenses/
 */

#include "harmonicpeaks.h"
#include "essentiamath.h"

using namespace std;
using namespace essentia;
using namespace standard;

const char* HarmonicPeaks::name = "HarmonicPeaks";
const char* HarmonicPeaks::description = DOC("This algorithm finds the harmonic peaks of a signal given its spectral peaks and its fundamental frequency.\n"
"Note:\n"
"  - \"tolerance\" parameter defines the allowed fixed deviation from ideal harmonics, being a percentage over the F0. For example: if the F0 is 100Hz you may decide to allow a deviation of 20%, that is a fixed deviation of 20Hz; for the harmonic series it is: [180-220], [280-320], [380-420], etc.\n"
"  - If \"pitch\" is zero, it means its value is unknown, or the sound is unpitched, and in that case the HarmonicPeaks algorithm returns an empty vector.\n"
"  - The output frequency and magnitude vectors are of size \"maxHarmonics\". If a particular harmonic was not found among spectral peaks, its ideal frequency value is output together with 0 magnitude.\n"
"This algorithm is intended to receive its \"frequencies\" and \"magnitudes\" inputs from the SpectralPeaks algorithm.\n"
"  - When input vectors differ in size or are empty, an exception is thrown. Input vectors must be ordered by ascending frequency excluding DC components and not contain duplicates, otherwise an exception is thrown.\n"
"\n"
"References:\n"
"  [1] Harmonic Spectrum - Wikipedia, the free encyclopedia,\n"
"  http://en.wikipedia.org/wiki/Harmonic_spectrum");

bool sortCandidates(const std::pair<Real, std::pair<int, int> >& x, const std::pair<Real, std::pair<int, int> >& y) {
  return x.first < y.first;
}

void HarmonicPeaks::configure() {
  _maxHarmonics = parameter("maxHarmonics").toInt();
  _ratioTolerance = parameter("tolerance").toReal();
  _ratioMax = (Real) _maxHarmonics + _ratioTolerance;
}

void HarmonicPeaks::compute() {

  const vector<Real>& frequencies = _frequencies.get();
  const vector<Real>& magnitudes = _magnitudes.get();
  const Real& f0 = _pitch.get();
  vector<Real>& harmonicFrequencies = _harmonicFrequencies.get();
  vector<Real>& harmonicMagnitudes = _harmonicMagnitudes.get();

  if (magnitudes.size() != frequencies.size()) {
    throw EssentiaException("HarmonicPeaks: frequency and magnitude input vectors must have the same size");
  }

  if (f0 < 0) {
    throw EssentiaException("HarmonicPeaks: input pitch must be greater than zero");
  }

  harmonicFrequencies.resize(0);
  harmonicMagnitudes.resize(0);

  if (f0 == 0) {
    // pitch is unknown -> no harmonic peaks found
    return;
  }

  if (frequencies.empty()) {
    // no peaks -> no harmonic peaks either
    return;
  }

  if (frequencies[0] <= 0) {
    throw EssentiaException("HarmonicPeaks: spectral peak frequencies must be greater than 0Hz");
  }
  for (int i=1; i<int(frequencies.size()); ++i) {
    if (frequencies[i] < frequencies[i-1]) {
      throw EssentiaException("HarmonicPeaks: spectral peaks input must be ordered by frequency");
    }
    if (frequencies[i] == frequencies[i-1]) {
      throw EssentiaException("HarmonicPeaks: duplicate spectral peak found, peaks cannot be duplicated");
    }
    if (frequencies[i] <= 0) {
      throw EssentiaException("HarmonicPeaks: spectral peak frequencies must be greater than 0Hz");
    }
  }

  // Maximum allowed tolerance is less than 0.5 therefore, each peak can
  // correspond only to one ideal harmonic

  // Init candidates with <-1, 0> -- ideal harmonics
  vector<pair<int, Real> > candidates (_maxHarmonics, make_pair(-1, 0));

  for (int i=0; i<int(frequencies.size()); ++i) {
    Real ratio = frequencies[i] / f0;
    int harmonicNumber = round(ratio);

    Real distance = abs(ratio - harmonicNumber);
    if (distance <= _ratioTolerance && ratio <= _ratioMax && harmonicNumber>0) {
      if (candidates[harmonicNumber-1].first == -1 ||
            distance < candidates[harmonicNumber-1].second) {
        // first occured candidate or a better candidate for harmonic
        candidates[harmonicNumber-1].first = i;
        candidates[harmonicNumber-1].second = distance;
      }
      else if (distance == candidates[harmonicNumber-1].second) {
        // select the one with max amplitude
        if (magnitudes[i] > magnitudes[candidates[harmonicNumber-1].first]) {
          candidates[harmonicNumber-1].first = i;
          candidates[harmonicNumber-1].second = distance;
        }
      }
    }
  }

  for (int h=0; h < _maxHarmonics; ++h) {
    int i = candidates[h].first;
    if (i < 0) {
      // harmonic not found, output ideal harmonic with 0 magnitude
      harmonicFrequencies.push_back((h+1) * f0);
      harmonicMagnitudes.push_back(0.);
    }
    else {
      harmonicFrequencies.push_back(frequencies[i]);
      harmonicMagnitudes.push_back(magnitudes[i]);
    }
  }
}
<|endoftext|>