<commit_before>#include <cmath>
#include <cstdio>
#include <omp.h>

// Structure of individual particle
struct ParticleType {
  float x, y, z;
  float vx, vy, vz;
};

// define a function that moves each particle due to interaction with other particles
void MoveParticles(const int nParticles, ParticleType *const particle, const float dt) {

#pragma omp parallel for
  // Loop over particles that experience force
  for (int i = 0; i < nParticles; i++) {

    // Components of the gravity force on particle i
    float Fx = 0, Fy = 0, Fz = 0;

    // Loop over particles that exert force: vectorization expected here
    for (int j = 0; j < nParticles; j++) {

      // Avoid singularity and interaction with self
      const float softening = 1e-20;

      // Newton's law of universal gravity
      const float dx = particle[j].x - particle[i].x;
      const float dy = particle[j].y - particle[i].y;
      const float dz = particle[j].z - particle[i].z;
      const float drSquared  = dx*dx + dy*dy + dz*dz + softening;

      const float oodr = 1.0f/sqrtf(drSquared);
      const float drPowerN3 = oodr*oodr*oodr;

      // Calculate the net force
      // Assume mass is 1 (for ease of computation)
      // F = ma = 1*a = a
      Fx += dx * oodr;  // scalar tuning
      Fy += dy * oodr;  // scalar tuning
      Fz += dz * oodr;  // scalar tuning
    }

    // Accelerate particles in response to the gravitational force
    // Note: 1st order Euler Approximation.
    // http://spiff.rit.edu/classes/phys317/lectures/euler.html
    particle[i].vx += dt*Fx;
    particle[i].vy += dt*Fy;
    particle[i].vz += dt*Fz;
  }

#pragma omp parallel for
  // Move particles according to their velocities
  for (int i = 0 ; i < nParticles; i++) {
    particle[i].x  += particle[i].vx*dt;
    particle[i].y  += particle[i].vy*dt;
    particle[i].z  += particle[i].vz*dt;
  }
}

// Do it!
int main(const int argc, const char *argv[]) {

  // Problem size and other parameters
  const int nParticles = (argc > 1 ? atoi(argv[1]) : 16384);
  const int nSteps = 10;  // Duration of test
  const float dt = 0.01f; // Particle propagation time step

  // Particle data stored as an Array of Structures (AoS)
  // this is good object-oriented programming style,
  // but inefficient for the purposes of vectorization
  ParticleType *particle = new ParticleType[nParticles];

  // Initialize random number generator and particles
  srand(0);
  for(int i = 0; i < nParticles; i++) {
    particle[i].x = rand()/RAND_MAX;
    particle[i].y = rand()/RAND_MAX;
    particle[i].z = rand()/RAND_MAX;
    particle[i].vx = rand()/RAND_MAX;
    particle[i].vy = rand()/RAND_MAX;
    particle[i].vz = rand()/RAND_MAX;
  }

  // Perform benchmark
  const int version = 6; // implementation version - update as needed
  printf("\n\033[1mNBODY Version %d\033[0m\n", version);
  const int num_threads = omp_get_max_threads();
  printf("\nPropagating %d particles using %d threads on %s...\n\n",
	 nParticles, num_threads,

#ifndef __MIC__
	 "CPU"
#else
	 "MIC"
#endif
	 );
  double rate = 0, dRate = 0; // Benchmarking data

  // Skip first few steps in the computation of average performance. Likely warm-up on Xeon Phi processor
  const int skipSteps = 3;
  printf("\033[1m%5s %10s %10s %8s\033[0m\n", "Step", "Time, s", "Interact/s", "GFLOP/s");
  fflush(stdout);
  for (int step = 1; step <= nSteps; step++) {

    const double tStart = omp_get_wtime(); // Start timing
    MoveParticles(nParticles, particle, dt);
    const double tEnd = omp_get_wtime(); // End timing

    // Estimate total interactions and GFLOPS consumed
    const float HztoInts   = float(nParticles)*float(nParticles-1) ;
    const float HztoGFLOPs = 20.0*1e-9*float(nParticles)*float(nParticles-1);

    // For average performance and short-cut method standard deviation computation
    if (step > skipSteps) { // Collect statistics

      // our sum of assumed mean D (for short-cut method standard deviation)
      rate  += HztoGFLOPs/(tEnd - tStart);

      // sum of D^2 (for short-cut method standard deviation)
      dRate += HztoGFLOPs*HztoGFLOPs/((tEnd - tStart)*(tEnd-tStart));
    }

    printf("%5d %10.3e %10.3e %8.1f %s\n",
	   step, (tEnd-tStart), HztoInts/(tEnd-tStart), HztoGFLOPs/(tEnd-tStart), (step<=skipSteps?"*":""));
    fflush(stdout);
  }

  // Compute the short-cut method standard deviaion.
  rate/=(double)(nSteps-skipSteps);
  dRate=sqrt(dRate/(double)(nSteps-skipSteps)-rate*rate);

  printf("-----------------------------------------------------\n");
  printf("\033[1m%s %4s \033[42m%10.1f +- %.1f GFLOP/s\033[0m\n",
	 "Average performance:", "", rate, dRate);
  printf("-----------------------------------------------------\n");
  printf("* - warm-up, not included in average\n\n");
  delete particle;
}

<commit_msg>Update nbody.cc<commit_after>#include <cmath>
#include <cstdio>
#include <omp.h>

// Structure of individual particle
struct ParticleType {
  float x, y, z;
  float vx, vy, vz;
};

// define a function that moves each particle due to interaction with other particles
void MoveParticles(const int nParticles, ParticleType *const particle, const float dt) {

#pragma omp parallel for
  // Loop over particles that experience force
  for (int i = 0; i < nParticles; i++) {

    // Components of the gravity force on particle i
    float Fx = 0, Fy = 0, Fz = 0;

    // Loop over particles that exert force: vectorization expected here
    for (int j = 0; j < nParticles; j++) {

      // Avoid singularity and interaction with self
      const float softening = 1e-20;

      // Newton's law of universal gravity
      const float dx = particle[j].x - particle[i].x;
      const float dy = particle[j].y - particle[i].y;
      const float dz = particle[j].z - particle[i].z;
      const float drSquared  = dx*dx + dy*dy + dz*dz + softening;

      const float oodr = 1.0f/sqrtf(drSquared);
      const float drPowerN3 = oodr*oodr*oodr;

      // Calculate the net force
      // Assume mass is 1 (for ease of computation)
      // F = ma = 1*a = a
      Fx += dx * drPowerN3;  // scalar tuning
      Fy += dy * drPowerN3;  // scalar tuning
      Fz += dz * drPowerN3;  // scalar tuning
    }

    // Accelerate particles in response to the gravitational force
    // Note: 1st order Euler Approximation.
    // http://spiff.rit.edu/classes/phys317/lectures/euler.html
    particle[i].vx += dt*Fx;
    particle[i].vy += dt*Fy;
    particle[i].vz += dt*Fz;
  }

#pragma omp parallel for
  // Move particles according to their velocities
  for (int i = 0 ; i < nParticles; i++) {
    particle[i].x  += particle[i].vx*dt;
    particle[i].y  += particle[i].vy*dt;
    particle[i].z  += particle[i].vz*dt;
  }
}

// Do it!
int main(const int argc, const char *argv[]) {

  // Problem size and other parameters
  const int nParticles = (argc > 1 ? atoi(argv[1]) : 16384);
  const int nSteps = 10;  // Duration of test
  const float dt = 0.01f; // Particle propagation time step

  // Particle data stored as an Array of Structures (AoS)
  // this is good object-oriented programming style,
  // but inefficient for the purposes of vectorization
  ParticleType *particle = new ParticleType[nParticles];

  // Initialize random number generator and particles
  srand(0);
  for(int i = 0; i < nParticles; i++) {
    particle[i].x = rand()/RAND_MAX;
    particle[i].y = rand()/RAND_MAX;
    particle[i].z = rand()/RAND_MAX;
    particle[i].vx = rand()/RAND_MAX;
    particle[i].vy = rand()/RAND_MAX;
    particle[i].vz = rand()/RAND_MAX;
  }

  // Perform benchmark
  const int version = 6; // implementation version - update as needed
  printf("\n\033[1mNBODY Version %d\033[0m\n", version);
  const int num_threads = omp_get_max_threads();
  printf("\nPropagating %d particles using %d threads on %s...\n\n",
	 nParticles, num_threads,

#ifndef __MIC__
	 "CPU"
#else
	 "MIC"
#endif
	 );
  double rate = 0, dRate = 0; // Benchmarking data

  // Skip first few steps in the computation of average performance. Likely warm-up on Xeon Phi processor
  const int skipSteps = 3;
  printf("\033[1m%5s %10s %10s %8s\033[0m\n", "Step", "Time, s", "Interact/s", "GFLOP/s");
  fflush(stdout);
  for (int step = 1; step <= nSteps; step++) {

    const double tStart = omp_get_wtime(); // Start timing
    MoveParticles(nParticles, particle, dt);
    const double tEnd = omp_get_wtime(); // End timing

    // Estimate total interactions and GFLOPS consumed
    const float HztoInts   = float(nParticles)*float(nParticles-1) ;
    const float HztoGFLOPs = 20.0*1e-9*float(nParticles)*float(nParticles-1);

    // For average performance and short-cut method standard deviation computation
    if (step > skipSteps) { // Collect statistics

      // our sum of assumed mean D (for short-cut method standard deviation)
      rate  += HztoGFLOPs/(tEnd - tStart);

      // sum of D^2 (for short-cut method standard deviation)
      dRate += HztoGFLOPs*HztoGFLOPs/((tEnd - tStart)*(tEnd-tStart));
    }

    printf("%5d %10.3e %10.3e %8.1f %s\n",
	   step, (tEnd-tStart), HztoInts/(tEnd-tStart), HztoGFLOPs/(tEnd-tStart), (step<=skipSteps?"*":""));
    fflush(stdout);
  }

  // Compute the short-cut method standard deviaion.
  rate/=(double)(nSteps-skipSteps);
  dRate=sqrt(dRate/(double)(nSteps-skipSteps)-rate*rate);

  printf("-----------------------------------------------------\n");
  printf("\033[1m%s %4s \033[42m%10.1f +- %.1f GFLOP/s\033[0m\n",
	 "Average performance:", "", rate, dRate);
  printf("-----------------------------------------------------\n");
  printf("* - warm-up, not included in average\n\n");
  delete particle;
}

<|endoftext|>


<commit_before>#include "ncurses_ui_impl.hpp"
#include "exception.hpp"

namespace Quoridor {
namespace UI {

NcursesUIImpl::NcursesUIImpl() : win_(), menu_()
{
    initscr();
    raw();
    keypad(stdscr, TRUE);
    noecho();
}

NcursesUIImpl::~NcursesUIImpl()
{
    endwin();
}

void NcursesUIImpl::draw_window()
{
    int height = 21;
    int width = 21;

    win_ = newwin(height, width, 0, 0);
    box(win_, 0, 0);
    wrefresh(win_);
}

void NcursesUIImpl::update(const std::vector<std::vector<char>> &repr)
{
    int i = 1;
    wmove(win_, i, 1);
    for (auto cols : repr) {
        for (auto col : cols) {
            waddch(win_, col);
        }
        ++i;
        wmove(win_, i, 1);
    }
    wrefresh(win_);
}

void NcursesUIImpl::add_menu(const std::vector<std::string> &items)
{
    menu_ = std::shared_ptr<NcursesMenu>(new NcursesMenu(win_, items));
}

void NcursesUIImpl::up_menu()
{
    if (menu_) {
        menu_->up();
    }
    throw Exception("menu is not initialized");
}

void NcursesUIImpl::down_menu()
{
    if (menu_) {
        menu_->down();
    }
    throw Exception("menu is not initialized");
}

std::string NcursesUIImpl::menu_item()
{
    if (menu_) {
        return menu_->item();
    }
    throw Exception("menu is not initialized");
}

}  /* namespace UI */
}  /* namespace Quoridor */
<commit_msg>bugfix: remove exception on initialized menu actions.<commit_after>#include "ncurses_ui_impl.hpp"
#include "exception.hpp"

namespace Quoridor {
namespace UI {

NcursesUIImpl::NcursesUIImpl() : win_(), menu_()
{
    initscr();
    raw();
    keypad(stdscr, TRUE);
    noecho();
}

NcursesUIImpl::~NcursesUIImpl()
{
    endwin();
}

void NcursesUIImpl::draw_window()
{
    int height = 21;
    int width = 21;

    win_ = newwin(height, width, 0, 0);
    box(win_, 0, 0);
    wrefresh(win_);
}

void NcursesUIImpl::update(const std::vector<std::vector<char>> &repr)
{
    int i = 1;
    wmove(win_, i, 1);
    for (auto cols : repr) {
        for (auto col : cols) {
            waddch(win_, col);
        }
        ++i;
        wmove(win_, i, 1);
    }
    wrefresh(win_);
}

void NcursesUIImpl::add_menu(const std::vector<std::string> &items)
{
    menu_ = std::shared_ptr<NcursesMenu>(new NcursesMenu(win_, items));
}

void NcursesUIImpl::up_menu()
{
    if (menu_) {
        menu_->up();
    }
    else {
        throw Exception("menu is not initialized");
    }
}

void NcursesUIImpl::down_menu()
{
    if (menu_) {
        menu_->down();
    }
    else {
        throw Exception("menu is not initialized");
    }
}

std::string NcursesUIImpl::menu_item()
{
    if (menu_) {
        return menu_->item();
    }
    else {
        throw Exception("menu is not initialized");
    }
}

}  /* namespace UI */
}  /* namespace Quoridor */
<|endoftext|>


<commit_before>#ifndef ALEPH_TOPOLOGY_IO_LEXICOGRAPHIC_TRIANGULATION_HH__
#define ALEPH_TOPOLOGY_IO_LEXICOGRAPHIC_TRIANGULATION_HH__

#include <aleph/utilities/String.hh>

#include <algorithm>
#include <fstream>
#include <istream>
#include <iterator>
#include <regex>
#include <string>
#include <stdexcept>
#include <vector>

#include <cctype>

namespace aleph
{

namespace topology
{

namespace io
{

/**
  @class LexicographicTriangulationReader
  @brief Class for reading a list of lexicographic triangulations

  This class supports loading triangulations in the lexicographic format
  developed by Frank H. Lutz. The format contains an identifier for each
  manifold, followed by a list of simplices. Start and end of every item
  is denoted by "[" and "]", respectively.

  An example of a valid triangulation:

  \code
  manifold_2_4_1=[[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
  \endcode

  This parser supports whitespace characters at any point of the list or
  the simplex. Moreover, comments indicated by '#' at the beginning of a
  line are supported as well.

  @see http://page.math.tu-berlin.de/~lutz/stellar/mixed.html
*/

class LexicographicTriangulationReader
{
public:

  template <class SimplicialComplex, class OutputIterator> void operator()( const std::string& filename, OutputIterator result )
  {
    std::ifstream in( filename );
    if( !in )
      throw std::runtime_error( "Unable to read input file" );

    this->operator()( in, result );
  }

  template <class SimplicialComplex, class OutputIterator> void operator()( std::istream& in, OutputIterator result )
  {
    using namespace aleph::utilities;

    std::string line;
    std::string block; // contains _all_ data belonging to the current block

    Mode mode = Mode::ParsingBlocks;

    while( std::getline( in, line ) )
    {
      line     = trim( line );
      auto pos = line.find( '=' );

      // Skip empty lines and comment lines
      if( line.empty() || line.front() == '#' )
        continue;

      if( pos != std::string::npos )
      {
        block.clear();

        if( mode != Mode::ParsingBlocks )
          throw std::runtime_error( "Format error; unexpected open block detected" );

        mode  = Mode::ParsingList;
        block = block + line.substr(pos+1);
        block = trim( block );
      }
      else if( mode == Mode::ParsingList )
      {
        block = block + line;
        block = trim( block );
      }

      if( isBlockFinished( block ) )
      {
        *result++ = parseBlock<SimplicialComplex>( block );
        mode      = Mode::ParsingBlocks;

        block.clear();
      }
    }
  }

private:

  enum class Mode
  {
    ParsingBlocks,  // Parsing blocks of triangulations
    ParsingList     // Parsing lists of simplices
  };

  static bool isBlockFinished( const std::string& block ) noexcept
  {
    auto numOpeningBrackets = std::count( block.begin(), block.end(), '[' );
    auto numClosingBrackets = std::count( block.begin(), block.end(), ']' );

    return numOpeningBrackets == numClosingBrackets;
  }

  /**
    Parses a block consisting of a list of simplices. Since the block
    cannot be easily tokenized at the beginning, this function merely
    uses a simple lookahead method.

    Upon success, a non-empty simplicial complex is returned.
  */

  template <class SimplicialComplex> static SimplicialComplex parseBlock( const std::string& block ) noexcept
  {
    // Sanity check
    if( !isBlockFinished( block ) )
      return {};

    using Simplex    = typename SimplicialComplex::ValueType;
    using VertexType = typename Simplex::VertexType;

    SimplicialComplex K;

    std::vector<VertexType> vertices; // list of vertices belonging to the current simplex
    bool parsingSimplex = false;      // flag indicating whether the parser is between two
                                      // simplices or parsing an individual simplex

    // Remove the opening bracket from the block. It makes the number of
    // brackets unbalanced but it also simplifies parsing because we may
    // rely on the fact that every opening bracket starts a new simplex.
    for( auto it = block.begin() + block.find_first_of( '[' ) + 1; it != block.end(); )
    {
      // Either the beginning of a list of simplices, or the very
      // beginning of the whole block
      if( *it == '[' )
      {
        // Format error: the parser is already parsing a simplex
        if( parsingSimplex )
          return {};

        // The parser is now in simplex parsing mode
        else
          parsingSimplex = true;
      }

      // Either the end of a list of simplices, or the very end of the
      // whole block
      else if( *it == ']' )
      {
        // Add parsed simplex to the simplicial complex and clear the
        // set of vertices afterwards. Reset the parse mode as well.
        if( parsingSimplex )
        {
          K.push_back( Simplex( vertices.begin(), vertices.end() ) );
          vertices.clear();

          ++it;
          parsingSimplex = false;
        }
        // Finished parsing the simplicial complex
        else
          break;
      }

      // Just skip all valid characters and try to directly proceed with
      // the parsing process.
      if( *it == ',' || std::isspace( *it ) )
        ++it;

      // Look ahead until the next "]" appears. Tokenize the list of
      // vertices in between.
      if( parsingSimplex )
      {
        auto offset        = std::distance( block.begin(), it );
        auto positionBegin = block.find_first_of( '[', offset );
        auto positionEnd   = block.find_first_of( ']', offset );

        // Format error: the list of simplices requires an opening and
        // a closing bracket
        if( positionBegin == std::string::npos || positionEnd == std::string::npos  )
          return {};

        using namespace aleph::utilities;

        auto list   = trim( block.substr( positionBegin + 1, positionEnd - positionBegin - 1 ) );
        auto tokens = split( list, std::string(",") );

        for( auto&& token : tokens )
          vertices.emplace_back( convert<VertexType>( token ) );

        std::advance( it, positionEnd - offset );
      }
    }

    return K;
  }
};

} // namespace io

} // namespace topology

} // namespace aleph

#endif
<commit_msg>Fixed implicit conversion issues<commit_after>#ifndef ALEPH_TOPOLOGY_IO_LEXICOGRAPHIC_TRIANGULATION_HH__
#define ALEPH_TOPOLOGY_IO_LEXICOGRAPHIC_TRIANGULATION_HH__

#include <aleph/utilities/String.hh>

#include <algorithm>
#include <fstream>
#include <istream>
#include <iterator>
#include <regex>
#include <string>
#include <stdexcept>
#include <vector>

#include <cctype>

namespace aleph
{

namespace topology
{

namespace io
{

/**
  @class LexicographicTriangulationReader
  @brief Class for reading a list of lexicographic triangulations

  This class supports loading triangulations in the lexicographic format
  developed by Frank H. Lutz. The format contains an identifier for each
  manifold, followed by a list of simplices. Start and end of every item
  is denoted by "[" and "]", respectively.

  An example of a valid triangulation:

  \code
  manifold_2_4_1=[[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
  \endcode

  This parser supports whitespace characters at any point of the list or
  the simplex. Moreover, comments indicated by '#' at the beginning of a
  line are supported as well.

  @see http://page.math.tu-berlin.de/~lutz/stellar/mixed.html
*/

class LexicographicTriangulationReader
{
public:

  template <class SimplicialComplex, class OutputIterator> void operator()( const std::string& filename, OutputIterator result )
  {
    std::ifstream in( filename );
    if( !in )
      throw std::runtime_error( "Unable to read input file" );

    this->operator()( in, result );
  }

  template <class SimplicialComplex, class OutputIterator> void operator()( std::istream& in, OutputIterator result )
  {
    using namespace aleph::utilities;

    std::string line;
    std::string block; // contains _all_ data belonging to the current block

    Mode mode = Mode::ParsingBlocks;

    while( std::getline( in, line ) )
    {
      line     = trim( line );
      auto pos = line.find( '=' );

      // Skip empty lines and comment lines
      if( line.empty() || line.front() == '#' )
        continue;

      if( pos != std::string::npos )
      {
        block.clear();

        if( mode != Mode::ParsingBlocks )
          throw std::runtime_error( "Format error; unexpected open block detected" );

        mode  = Mode::ParsingList;
        block = block + line.substr(pos+1);
        block = trim( block );
      }
      else if( mode == Mode::ParsingList )
      {
        block = block + line;
        block = trim( block );
      }

      if( isBlockFinished( block ) )
      {
        *result++ = parseBlock<SimplicialComplex>( block );
        mode      = Mode::ParsingBlocks;

        block.clear();
      }
    }
  }

private:

  enum class Mode
  {
    ParsingBlocks,  // Parsing blocks of triangulations
    ParsingList     // Parsing lists of simplices
  };

  static bool isBlockFinished( const std::string& block ) noexcept
  {
    auto numOpeningBrackets = std::count( block.begin(), block.end(), '[' );
    auto numClosingBrackets = std::count( block.begin(), block.end(), ']' );

    return numOpeningBrackets == numClosingBrackets;
  }

  /**
    Parses a block consisting of a list of simplices. Since the block
    cannot be easily tokenized at the beginning, this function merely
    uses a simple lookahead method.

    Upon success, a non-empty simplicial complex is returned.
  */

  template <class SimplicialComplex> static SimplicialComplex parseBlock( const std::string& block ) noexcept
  {
    // Sanity check
    if( !isBlockFinished( block ) )
      return {};

    using Simplex    = typename SimplicialComplex::ValueType;
    using VertexType = typename Simplex::VertexType;

    SimplicialComplex K;

    std::vector<VertexType> vertices; // list of vertices belonging to the current simplex
    bool parsingSimplex = false;      // flag indicating whether the parser is between two
                                      // simplices or parsing an individual simplex

    using DifferenceType = std::string::difference_type;
    using SizeType       = std::string::size_type;

    // Remove the opening bracket from the block. It makes the number of
    // brackets unbalanced but it also simplifies parsing because we may
    // rely on the fact that every opening bracket starts a new simplex.
    for( auto it = block.begin() + DifferenceType( block.find_first_of( '[' ) + 1 ); it != block.end(); )
    {
      // Either the beginning of a list of simplices, or the very
      // beginning of the whole block
      if( *it == '[' )
      {
        // Format error: the parser is already parsing a simplex
        if( parsingSimplex )
          return {};

        // The parser is now in simplex parsing mode
        else
          parsingSimplex = true;
      }

      // Either the end of a list of simplices, or the very end of the
      // whole block
      else if( *it == ']' )
      {
        // Add parsed simplex to the simplicial complex and clear the
        // set of vertices afterwards. Reset the parse mode as well.
        if( parsingSimplex )
        {
          K.push_back( Simplex( vertices.begin(), vertices.end() ) );
          vertices.clear();

          ++it;
          parsingSimplex = false;
        }
        // Finished parsing the simplicial complex
        else
          break;
      }

      // Just skip all valid characters and try to directly proceed with
      // the parsing process.
      if( *it == ',' || std::isspace( *it ) )
        ++it;

      // Look ahead until the next "]" appears. Tokenize the list of
      // vertices in between.
      if( parsingSimplex )
      {
        auto offset        = static_cast<SizeType>( std::distance( block.begin(), it ) );
        auto positionBegin = block.find_first_of( '[', offset );
        auto positionEnd   = block.find_first_of( ']', offset );

        // Format error: the list of simplices requires an opening and
        // a closing bracket
        if( positionBegin == std::string::npos || positionEnd == std::string::npos  )
          return {};

        using namespace aleph::utilities;

        auto list   = trim( block.substr( positionBegin + 1, positionEnd - positionBegin - 1 ) );
        auto tokens = split( list, std::string(",") );

        for( auto&& token : tokens )
          vertices.emplace_back( convert<VertexType>( token ) );

        std::advance( it, positionEnd - offset );
      }
    }

    return K;
  }
};

} // namespace io

} // namespace topology

} // namespace aleph

#endif
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2014, Oculus VR, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */

#include "NativeFeatureIncludes.h"
#if _RAKNET_SUPPORT_PacketizedTCP==1 && _RAKNET_SUPPORT_TCPInterface==1

#include "PacketizedTCP.h"
#include "NativeTypes.h"
#include "BitStream.h"
#include "MessageIdentifiers.h"
#include "RakAlloca.h"

using namespace RakNet;

typedef uint32_t PTCPHeader;

STATIC_FACTORY_DEFINITIONS(PacketizedTCP,PacketizedTCP);

PacketizedTCP::PacketizedTCP()
{

}
PacketizedTCP::~PacketizedTCP()
{
	ClearAllConnections();
}

void PacketizedTCP::Stop(void)
{
	unsigned int i;
	TCPInterface::Stop();
	for (i=0; i < waitingPackets.Size(); i++)
		DeallocatePacket(waitingPackets[i]);
	ClearAllConnections();
}

void PacketizedTCP::Send( const char *data, unsigned length, const SystemAddress &systemAddress, bool broadcast )
{
	PTCPHeader dataLength;
	dataLength=length;
#ifndef __BITSTREAM_NATIVE_END
	if (RakNet::BitStream::DoEndianSwap())
		RakNet::BitStream::ReverseBytes((unsigned char*) &length,(unsigned char*) &dataLength,sizeof(dataLength));
#else
		dataLength=length;
#endif

	unsigned int lengthsArray[2];
	const char *dataArray[2];
	dataArray[0]=(char*) &dataLength;
	dataArray[1]=data;
	lengthsArray[0]=sizeof(dataLength);
	lengthsArray[1]=length;
	TCPInterface::SendList(dataArray,lengthsArray,2,systemAddress,broadcast);
}
bool PacketizedTCP::SendList( const char **data, const unsigned int *lengths, const int numParameters, const SystemAddress &systemAddress, bool broadcast )
{
	if (isStarted.GetValue()==0)
		return false;
	if (data==0)
		return false;
	if (systemAddress==UNASSIGNED_SYSTEM_ADDRESS && broadcast==false)
		return false;
	PTCPHeader totalLengthOfUserData=0;
	int i;
	for (i=0; i < numParameters; i++)
	{
		if (lengths[i]>0)
			totalLengthOfUserData+=lengths[i];
	}
	if (totalLengthOfUserData==0)
		return false;

	PTCPHeader dataLength;
#ifndef __BITSTREAM_NATIVE_END
	if (RakNet::BitStream::DoEndianSwap())
		RakNet::BitStream::ReverseBytes((unsigned char*) &totalLengthOfUserData,(unsigned char*) &dataLength,sizeof(dataLength));
#else
	dataLength=totalLengthOfUserData;
#endif

	unsigned int lengthsArray[512];
	const char *dataArray[512];
	dataArray[0]=(char*) &dataLength;
	lengthsArray[0]=sizeof(dataLength);
	for (int i=0; i < 512 && i < numParameters; i++)
	{
		dataArray[i+1]=data[i];
		lengthsArray[i+1]=lengths[i];
	}
	return TCPInterface::SendList(dataArray,lengthsArray,numParameters+1,systemAddress,broadcast);
}
void PacketizedTCP::PushNotificationsToQueues(void)
{
	SystemAddress sa;
	sa = TCPInterface::HasNewIncomingConnection();
	if (sa!=UNASSIGNED_SYSTEM_ADDRESS)
	{
		_newIncomingConnections.Push(sa, _FILE_AND_LINE_ );
		AddToConnectionList(sa);
	}

	sa = TCPInterface::HasFailedConnectionAttempt();
	if (sa!=UNASSIGNED_SYSTEM_ADDRESS)
	{
		_failedConnectionAttempts.Push(sa, _FILE_AND_LINE_ );
	}

	sa = TCPInterface::HasLostConnection();
	if (sa!=UNASSIGNED_SYSTEM_ADDRESS)
	{
		_lostConnections.Push(sa, _FILE_AND_LINE_ );
		RemoveFromConnectionList(sa);
	}

	sa = TCPInterface::HasCompletedConnectionAttempt();
	if (sa!=UNASSIGNED_SYSTEM_ADDRESS)
	{
		_completedConnectionAttempts.Push(sa, _FILE_AND_LINE_ );
		AddToConnectionList(sa);
	}
}
Packet* PacketizedTCP::Receive( void )
{
	PushNotificationsToQueues();

	unsigned int i;
	for (i=0; i < messageHandlerList.Size(); i++)
		messageHandlerList[i]->Update();

	Packet *outgoingPacket=ReturnOutgoingPacket();
	if (outgoingPacket)
		return outgoingPacket;

	Packet *incomingPacket;
	incomingPacket = TCPInterface::ReceiveInt();
	unsigned int index;

	while (incomingPacket)
	{
		if (connections.Has(incomingPacket->systemAddress))
			index = connections.GetIndexAtKey(incomingPacket->systemAddress);
		else
			index=(unsigned int) -1;
		if ((unsigned int)index==(unsigned int)-1)
		{
			DeallocatePacket(incomingPacket);
			incomingPacket = TCPInterface::ReceiveInt();
			continue;
		}

		if (incomingPacket->deleteData==true)
		{
			// Came from network
			SystemAddress systemAddressFromPacket;
			if (index < connections.Size())
			{
				DataStructures::ByteQueue *bq = connections[index];
				// Buffer data
				bq->WriteBytes((const char*) incomingPacket->data,incomingPacket->length, _FILE_AND_LINE_);
				systemAddressFromPacket=incomingPacket->systemAddress;
				PTCPHeader dataLength;

				// Peek the header to see if a full message is waiting
				bq->ReadBytes((char*) &dataLength,sizeof(PTCPHeader),true);
				if (RakNet::BitStream::DoEndianSwap())
					RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &dataLength,sizeof(dataLength));
				// Header indicates packet length. If enough data is available, read out and return one packet
				if (bq->GetBytesWritten()>=dataLength+sizeof(PTCPHeader))
				{
					do
					{
						bq->IncrementReadOffset(sizeof(PTCPHeader));
						outgoingPacket = RakNet::OP_NEW<Packet>(_FILE_AND_LINE_);
						outgoingPacket->length=dataLength;
						outgoingPacket->bitSize=BYTES_TO_BITS(dataLength);
						outgoingPacket->guid=UNASSIGNED_RAKNET_GUID;
						outgoingPacket->systemAddress=systemAddressFromPacket;
						outgoingPacket->deleteData=false; // Did not come from the network
						outgoingPacket->data=(unsigned char*) rakMalloc_Ex(dataLength, _FILE_AND_LINE_);
						if (outgoingPacket->data==0)
						{
							notifyOutOfMemory(_FILE_AND_LINE_);
							RakNet::OP_DELETE(outgoingPacket,_FILE_AND_LINE_);
							return 0;
						}
						bq->ReadBytes((char*) outgoingPacket->data,dataLength,false);

						waitingPackets.Push(outgoingPacket, _FILE_AND_LINE_ );

						// Peek the header to see if a full message is waiting
						if (bq->ReadBytes((char*) &dataLength,sizeof(PTCPHeader),true))
						{
							if (RakNet::BitStream::DoEndianSwap())
								RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &dataLength,sizeof(dataLength));
						}
						else
							break;
					} while (bq->GetBytesWritten()>=dataLength+sizeof(PTCPHeader));
				}
				else
				{

					unsigned int oldWritten = bq->GetBytesWritten()-incomingPacket->length;
					unsigned int newWritten = bq->GetBytesWritten();

					// Return ID_DOWNLOAD_PROGRESS
					if (newWritten/65536!=oldWritten/65536)
					{
						outgoingPacket = RakNet::OP_NEW<Packet>(_FILE_AND_LINE_);
						outgoingPacket->length=sizeof(MessageID) +
							sizeof(unsigned int)*2 +
							sizeof(unsigned int) +
							65536;
						outgoingPacket->bitSize=BYTES_TO_BITS(incomingPacket->length);
						outgoingPacket->guid=UNASSIGNED_RAKNET_GUID;
						outgoingPacket->systemAddress=incomingPacket->systemAddress;
						outgoingPacket->deleteData=false;
						outgoingPacket->data=(unsigned char*) rakMalloc_Ex(outgoingPacket->length, _FILE_AND_LINE_);
						if (outgoingPacket->data==0)
						{
							notifyOutOfMemory(_FILE_AND_LINE_);
							RakNet::OP_DELETE(outgoingPacket,_FILE_AND_LINE_);
							return 0;
						}

						outgoingPacket->data[0]=(MessageID)ID_DOWNLOAD_PROGRESS;
						unsigned int totalParts=dataLength/65536;
						unsigned int partIndex=newWritten/65536;
						unsigned int oneChunkSize=65536;
						memcpy(outgoingPacket->data+sizeof(MessageID), &partIndex, sizeof(unsigned int));
						memcpy(outgoingPacket->data+sizeof(MessageID)+sizeof(unsigned int)*1, &totalParts, sizeof(unsigned int));
						memcpy(outgoingPacket->data+sizeof(MessageID)+sizeof(unsigned int)*2, &oneChunkSize, sizeof(unsigned int));
						bq->IncrementReadOffset(sizeof(PTCPHeader));
						bq->ReadBytes((char*) outgoingPacket->data+sizeof(MessageID)+sizeof(unsigned int)*3,oneChunkSize,true);
						bq->DecrementReadOffset(sizeof(PTCPHeader));

						waitingPackets.Push(outgoingPacket, _FILE_AND_LINE_ );
					}
				}

			}

			DeallocatePacket(incomingPacket);
			incomingPacket=0;
		}
		else
			waitingPackets.Push(incomingPacket, _FILE_AND_LINE_ );

		incomingPacket = TCPInterface::ReceiveInt();
	}

	return ReturnOutgoingPacket();
}
Packet *PacketizedTCP::ReturnOutgoingPacket(void)
{
	Packet *outgoingPacket=0;
	unsigned int i;
	while (outgoingPacket==0 && waitingPackets.IsEmpty()==false)
	{
		outgoingPacket=waitingPackets.Pop();
		PluginReceiveResult pluginResult;
		for (i=0; i < messageHandlerList.Size(); i++)
		{
			pluginResult=messageHandlerList[i]->OnReceive(outgoingPacket);
			if (pluginResult==RR_STOP_PROCESSING_AND_DEALLOCATE)
			{
				DeallocatePacket( outgoingPacket );
				outgoingPacket=0; // Will do the loop again and get another packet
				break; // break out of the enclosing for
			}
			else if (pluginResult==RR_STOP_PROCESSING)
			{
				outgoingPacket=0;
				break;
			}
		}
	}

	return outgoingPacket;
}
void PacketizedTCP::CloseConnection( SystemAddress systemAddress )
{
	RemoveFromConnectionList(systemAddress);
	TCPInterface::CloseConnection(systemAddress);
}
void PacketizedTCP::RemoveFromConnectionList(const SystemAddress &sa)
{
	if (sa==UNASSIGNED_SYSTEM_ADDRESS)
		return;
	if (connections.Has(sa))
	{
		unsigned int index = connections.GetIndexAtKey(sa);
		if (index!=(unsigned int)-1)
		{
			RakNet::OP_DELETE(connections[index],_FILE_AND_LINE_);
			connections.RemoveAtIndex(index);
		}
	}
}
void PacketizedTCP::AddToConnectionList(const SystemAddress &sa)
{
	if (sa==UNASSIGNED_SYSTEM_ADDRESS)
		return;
	connections.SetNew(sa, RakNet::OP_NEW<DataStructures::ByteQueue>(_FILE_AND_LINE_));
}
void PacketizedTCP::ClearAllConnections(void)
{
	unsigned int i;
	for (i=0; i < connections.Size(); i++)
		RakNet::OP_DELETE(connections[i],_FILE_AND_LINE_);
	connections.Clear();
}
SystemAddress PacketizedTCP::HasCompletedConnectionAttempt(void)
{
	PushNotificationsToQueues();

	if (_completedConnectionAttempts.IsEmpty()==false)
		return _completedConnectionAttempts.Pop();
	return UNASSIGNED_SYSTEM_ADDRESS;
}
SystemAddress PacketizedTCP::HasFailedConnectionAttempt(void)
{
	PushNotificationsToQueues();

	if (_failedConnectionAttempts.IsEmpty()==false)
		return _failedConnectionAttempts.Pop();
	return UNASSIGNED_SYSTEM_ADDRESS;
}
SystemAddress PacketizedTCP::HasNewIncomingConnection(void)
{
	PushNotificationsToQueues();

	if (_newIncomingConnections.IsEmpty()==false)
		return _newIncomingConnections.Pop();
	return UNASSIGNED_SYSTEM_ADDRESS;
}
SystemAddress PacketizedTCP::HasLostConnection(void)
{
	PushNotificationsToQueues();

	if (_lostConnections.IsEmpty()==false)
		return _lostConnections.Pop();
	return UNASSIGNED_SYSTEM_ADDRESS;
}

#endif // _RAKNET_SUPPORT_*
<commit_msg>Fix possible buffer overrun (these arrays may be accessed at (1..512) below)<commit_after>/*
 *  Copyright (c) 2014, Oculus VR, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */

#include "NativeFeatureIncludes.h"
#if _RAKNET_SUPPORT_PacketizedTCP==1 && _RAKNET_SUPPORT_TCPInterface==1

#include "PacketizedTCP.h"
#include "NativeTypes.h"
#include "BitStream.h"
#include "MessageIdentifiers.h"
#include "RakAlloca.h"

using namespace RakNet;

typedef uint32_t PTCPHeader;

STATIC_FACTORY_DEFINITIONS(PacketizedTCP,PacketizedTCP);

PacketizedTCP::PacketizedTCP()
{

}
PacketizedTCP::~PacketizedTCP()
{
	ClearAllConnections();
}

void PacketizedTCP::Stop(void)
{
	unsigned int i;
	TCPInterface::Stop();
	for (i=0; i < waitingPackets.Size(); i++)
		DeallocatePacket(waitingPackets[i]);
	ClearAllConnections();
}

void PacketizedTCP::Send( const char *data, unsigned length, const SystemAddress &systemAddress, bool broadcast )
{
	PTCPHeader dataLength;
	dataLength=length;
#ifndef __BITSTREAM_NATIVE_END
	if (RakNet::BitStream::DoEndianSwap())
		RakNet::BitStream::ReverseBytes((unsigned char*) &length,(unsigned char*) &dataLength,sizeof(dataLength));
#else
		dataLength=length;
#endif

	unsigned int lengthsArray[2];
	const char *dataArray[2];
	dataArray[0]=(char*) &dataLength;
	dataArray[1]=data;
	lengthsArray[0]=sizeof(dataLength);
	lengthsArray[1]=length;
	TCPInterface::SendList(dataArray,lengthsArray,2,systemAddress,broadcast);
}
bool PacketizedTCP::SendList( const char **data, const unsigned int *lengths, const int numParameters, const SystemAddress &systemAddress, bool broadcast )
{
	if (isStarted.GetValue()==0)
		return false;
	if (data==0)
		return false;
	if (systemAddress==UNASSIGNED_SYSTEM_ADDRESS && broadcast==false)
		return false;
	PTCPHeader totalLengthOfUserData=0;
	int i;
	for (i=0; i < numParameters; i++)
	{
		if (lengths[i]>0)
			totalLengthOfUserData+=lengths[i];
	}
	if (totalLengthOfUserData==0)
		return false;

	PTCPHeader dataLength;
#ifndef __BITSTREAM_NATIVE_END
	if (RakNet::BitStream::DoEndianSwap())
		RakNet::BitStream::ReverseBytes((unsigned char*) &totalLengthOfUserData,(unsigned char*) &dataLength,sizeof(dataLength));
#else
	dataLength=totalLengthOfUserData;
#endif

	unsigned int lengthsArray[513];
	const char *dataArray[513];
	dataArray[0]=(char*) &dataLength;
	lengthsArray[0]=sizeof(dataLength);
	for (int i=0; i < 512 && i < numParameters; i++)
	{
		dataArray[i+1]=data[i];
		lengthsArray[i+1]=lengths[i];
	}
	return TCPInterface::SendList(dataArray,lengthsArray,numParameters+1,systemAddress,broadcast);
}
void PacketizedTCP::PushNotificationsToQueues(void)
{
	SystemAddress sa;
	sa = TCPInterface::HasNewIncomingConnection();
	if (sa!=UNASSIGNED_SYSTEM_ADDRESS)
	{
		_newIncomingConnections.Push(sa, _FILE_AND_LINE_ );
		AddToConnectionList(sa);
	}

	sa = TCPInterface::HasFailedConnectionAttempt();
	if (sa!=UNASSIGNED_SYSTEM_ADDRESS)
	{
		_failedConnectionAttempts.Push(sa, _FILE_AND_LINE_ );
	}

	sa = TCPInterface::HasLostConnection();
	if (sa!=UNASSIGNED_SYSTEM_ADDRESS)
	{
		_lostConnections.Push(sa, _FILE_AND_LINE_ );
		RemoveFromConnectionList(sa);
	}

	sa = TCPInterface::HasCompletedConnectionAttempt();
	if (sa!=UNASSIGNED_SYSTEM_ADDRESS)
	{
		_completedConnectionAttempts.Push(sa, _FILE_AND_LINE_ );
		AddToConnectionList(sa);
	}
}
Packet* PacketizedTCP::Receive( void )
{
	PushNotificationsToQueues();

	unsigned int i;
	for (i=0; i < messageHandlerList.Size(); i++)
		messageHandlerList[i]->Update();

	Packet *outgoingPacket=ReturnOutgoingPacket();
	if (outgoingPacket)
		return outgoingPacket;

	Packet *incomingPacket;
	incomingPacket = TCPInterface::ReceiveInt();
	unsigned int index;

	while (incomingPacket)
	{
		if (connections.Has(incomingPacket->systemAddress))
			index = connections.GetIndexAtKey(incomingPacket->systemAddress);
		else
			index=(unsigned int) -1;
		if ((unsigned int)index==(unsigned int)-1)
		{
			DeallocatePacket(incomingPacket);
			incomingPacket = TCPInterface::ReceiveInt();
			continue;
		}

		if (incomingPacket->deleteData==true)
		{
			// Came from network
			SystemAddress systemAddressFromPacket;
			if (index < connections.Size())
			{
				DataStructures::ByteQueue *bq = connections[index];
				// Buffer data
				bq->WriteBytes((const char*) incomingPacket->data,incomingPacket->length, _FILE_AND_LINE_);
				systemAddressFromPacket=incomingPacket->systemAddress;
				PTCPHeader dataLength;

				// Peek the header to see if a full message is waiting
				bq->ReadBytes((char*) &dataLength,sizeof(PTCPHeader),true);
				if (RakNet::BitStream::DoEndianSwap())
					RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &dataLength,sizeof(dataLength));
				// Header indicates packet length. If enough data is available, read out and return one packet
				if (bq->GetBytesWritten()>=dataLength+sizeof(PTCPHeader))
				{
					do
					{
						bq->IncrementReadOffset(sizeof(PTCPHeader));
						outgoingPacket = RakNet::OP_NEW<Packet>(_FILE_AND_LINE_);
						outgoingPacket->length=dataLength;
						outgoingPacket->bitSize=BYTES_TO_BITS(dataLength);
						outgoingPacket->guid=UNASSIGNED_RAKNET_GUID;
						outgoingPacket->systemAddress=systemAddressFromPacket;
						outgoingPacket->deleteData=false; // Did not come from the network
						outgoingPacket->data=(unsigned char*) rakMalloc_Ex(dataLength, _FILE_AND_LINE_);
						if (outgoingPacket->data==0)
						{
							notifyOutOfMemory(_FILE_AND_LINE_);
							RakNet::OP_DELETE(outgoingPacket,_FILE_AND_LINE_);
							return 0;
						}
						bq->ReadBytes((char*) outgoingPacket->data,dataLength,false);

						waitingPackets.Push(outgoingPacket, _FILE_AND_LINE_ );

						// Peek the header to see if a full message is waiting
						if (bq->ReadBytes((char*) &dataLength,sizeof(PTCPHeader),true))
						{
							if (RakNet::BitStream::DoEndianSwap())
								RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &dataLength,sizeof(dataLength));
						}
						else
							break;
					} while (bq->GetBytesWritten()>=dataLength+sizeof(PTCPHeader));
				}
				else
				{

					unsigned int oldWritten = bq->GetBytesWritten()-incomingPacket->length;
					unsigned int newWritten = bq->GetBytesWritten();

					// Return ID_DOWNLOAD_PROGRESS
					if (newWritten/65536!=oldWritten/65536)
					{
						outgoingPacket = RakNet::OP_NEW<Packet>(_FILE_AND_LINE_);
						outgoingPacket->length=sizeof(MessageID) +
							sizeof(unsigned int)*2 +
							sizeof(unsigned int) +
							65536;
						outgoingPacket->bitSize=BYTES_TO_BITS(incomingPacket->length);
						outgoingPacket->guid=UNASSIGNED_RAKNET_GUID;
						outgoingPacket->systemAddress=incomingPacket->systemAddress;
						outgoingPacket->deleteData=false;
						outgoingPacket->data=(unsigned char*) rakMalloc_Ex(outgoingPacket->length, _FILE_AND_LINE_);
						if (outgoingPacket->data==0)
						{
							notifyOutOfMemory(_FILE_AND_LINE_);
							RakNet::OP_DELETE(outgoingPacket,_FILE_AND_LINE_);
							return 0;
						}

						outgoingPacket->data[0]=(MessageID)ID_DOWNLOAD_PROGRESS;
						unsigned int totalParts=dataLength/65536;
						unsigned int partIndex=newWritten/65536;
						unsigned int oneChunkSize=65536;
						memcpy(outgoingPacket->data+sizeof(MessageID), &partIndex, sizeof(unsigned int));
						memcpy(outgoingPacket->data+sizeof(MessageID)+sizeof(unsigned int)*1, &totalParts, sizeof(unsigned int));
						memcpy(outgoingPacket->data+sizeof(MessageID)+sizeof(unsigned int)*2, &oneChunkSize, sizeof(unsigned int));
						bq->IncrementReadOffset(sizeof(PTCPHeader));
						bq->ReadBytes((char*) outgoingPacket->data+sizeof(MessageID)+sizeof(unsigned int)*3,oneChunkSize,true);
						bq->DecrementReadOffset(sizeof(PTCPHeader));

						waitingPackets.Push(outgoingPacket, _FILE_AND_LINE_ );
					}
				}

			}

			DeallocatePacket(incomingPacket);
			incomingPacket=0;
		}
		else
			waitingPackets.Push(incomingPacket, _FILE_AND_LINE_ );

		incomingPacket = TCPInterface::ReceiveInt();
	}

	return ReturnOutgoingPacket();
}
Packet *PacketizedTCP::ReturnOutgoingPacket(void)
{
	Packet *outgoingPacket=0;
	unsigned int i;
	while (outgoingPacket==0 && waitingPackets.IsEmpty()==false)
	{
		outgoingPacket=waitingPackets.Pop();
		PluginReceiveResult pluginResult;
		for (i=0; i < messageHandlerList.Size(); i++)
		{
			pluginResult=messageHandlerList[i]->OnReceive(outgoingPacket);
			if (pluginResult==RR_STOP_PROCESSING_AND_DEALLOCATE)
			{
				DeallocatePacket( outgoingPacket );
				outgoingPacket=0; // Will do the loop again and get another packet
				break; // break out of the enclosing for
			}
			else if (pluginResult==RR_STOP_PROCESSING)
			{
				outgoingPacket=0;
				break;
			}
		}
	}

	return outgoingPacket;
}
void PacketizedTCP::CloseConnection( SystemAddress systemAddress )
{
	RemoveFromConnectionList(systemAddress);
	TCPInterface::CloseConnection(systemAddress);
}
void PacketizedTCP::RemoveFromConnectionList(const SystemAddress &sa)
{
	if (sa==UNASSIGNED_SYSTEM_ADDRESS)
		return;
	if (connections.Has(sa))
	{
		unsigned int index = connections.GetIndexAtKey(sa);
		if (index!=(unsigned int)-1)
		{
			RakNet::OP_DELETE(connections[index],_FILE_AND_LINE_);
			connections.RemoveAtIndex(index);
		}
	}
}
void PacketizedTCP::AddToConnectionList(const SystemAddress &sa)
{
	if (sa==UNASSIGNED_SYSTEM_ADDRESS)
		return;
	connections.SetNew(sa, RakNet::OP_NEW<DataStructures::ByteQueue>(_FILE_AND_LINE_));
}
void PacketizedTCP::ClearAllConnections(void)
{
	unsigned int i;
	for (i=0; i < connections.Size(); i++)
		RakNet::OP_DELETE(connections[i],_FILE_AND_LINE_);
	connections.Clear();
}
SystemAddress PacketizedTCP::HasCompletedConnectionAttempt(void)
{
	PushNotificationsToQueues();

	if (_completedConnectionAttempts.IsEmpty()==false)
		return _completedConnectionAttempts.Pop();
	return UNASSIGNED_SYSTEM_ADDRESS;
}
SystemAddress PacketizedTCP::HasFailedConnectionAttempt(void)
{
	PushNotificationsToQueues();

	if (_failedConnectionAttempts.IsEmpty()==false)
		return _failedConnectionAttempts.Pop();
	return UNASSIGNED_SYSTEM_ADDRESS;
}
SystemAddress PacketizedTCP::HasNewIncomingConnection(void)
{
	PushNotificationsToQueues();

	if (_newIncomingConnections.IsEmpty()==false)
		return _newIncomingConnections.Pop();
	return UNASSIGNED_SYSTEM_ADDRESS;
}
SystemAddress PacketizedTCP::HasLostConnection(void)
{
	PushNotificationsToQueues();

	if (_lostConnections.IsEmpty()==false)
		return _lostConnections.Pop();
	return UNASSIGNED_SYSTEM_ADDRESS;
}

#endif // _RAKNET_SUPPORT_*
<|endoftext|>


<commit_before>/**
 * @doc Vector NIF module - provides a C++ implementation of the `vector` Erlang module
 *
 * @copyright 2012-2013 David H. Bronke and Christopher S. Case
 * Licensed under the MIT license; see the LICENSE file for details.
 */

#include <string>

#include "nif_helpers.h"
#include "vector_nif_utils.h"

#include "vector_nif.h"

static ERL_NIF_TERM true_atom;
static ERL_NIF_TERM false_atom;

// --------------------------------------------------------------------------------------------------------------------
// NIF Inititialization

static int nif_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
{
	true_atom = enif_make_atom_len(env, "true", 4);
	false_atom = enif_make_atom_len(env, "false", 5);

	return 0;
} // end nif_load

static int nif_upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info)
{
	true_atom = enif_make_atom_len(env, "true", 4);
	false_atom = enif_make_atom_len(env, "false", 5);

	return 0;
} // end nif_upgrade

// --------------------------------------------------------------------------------------------------------------------
// NIFs

// vec_to_list/1
static ERL_NIF_TERM vec_to_list(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
	CHECK_ARGC(1);
	int arity;
	const ERL_NIF_TERM* array;

	if(enif_get_tuple(env, argv[0], &arity, &array) && arity == 3)
	{
		return enif_make_list_from_array(env, array, 3);
	}
	else
	{
		FAIL;
	} // end if
} // end vec_to_list

// list_to_vec/1
static ERL_NIF_TERM list_to_vec(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
	CHECK_ARGC(1);
	ERL_NIF_TERM vecTuple[3];
	ERL_NIF_TERM current = argv[0], tail;

	for(size_t idx = 0; idx < 3; idx++)
	{
		if(!enif_get_list_cell(env, current, &vecTuple[idx], &tail))
		{
			FAIL;
		} // end if

		current = tail;
	} // end for

	if(enif_is_empty_list(env, tail))
	{
		return enif_make_tuple_from_array(env, vecTuple, 3);
	}
	else
	{
		FAIL;
	} // end if
} // end list_to_vec

// dot/2
static ERL_NIF_TERM dot(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
	CHECK_ARGC(2);
	Vec vec0, vec1;

	if(termToVec(env, argv[0], vec0) && termToVec(env, argv[1], vec1))
	{
		return enif_make_double(env, vec0.dot(vec1));
	}
	else
	{
		FAIL;
	} // end if
} // end dot

// cross/2
static ERL_NIF_TERM cross(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
	CHECK_ARGC(2);
	Vec vec0, vec1;

	if(termToVec(env, argv[0], vec0) && termToVec(env, argv[1], vec1))
	{
		return vecToTerm(env, vec0.cross(vec1));
	}
	else
	{
		FAIL;
	} // end if
} // end cross

// multiply/2
static ERL_NIF_TERM multiply(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
	CHECK_ARGC(2);
	Vec vec;
	double factor;

	if(termToVec(env, argv[0], vec) && getNIFDouble(env, argv[1], &factor))
	{
		return vecToTerm(env, vec *= factor);
	}
	else if(getNIFDouble(env, argv[0], &factor) && termToVec(env, argv[1], vec))
	{
		return vecToTerm(env, vec *= factor);
	}
	else
	{
		FAIL;
	} // end if
} // end multiply

// divide/2
static ERL_NIF_TERM divide(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
	CHECK_ARGC(2);
	Vec vec;
	double divisor;

	if(termToVec(env, argv[0], vec) && getNIFDouble(env, argv[1], &divisor))
	{
		return vecToTerm(env, vec /= divisor);
	}
	else
	{
		FAIL;
	} // end if
} // end divide

// squared_norm/1
static ERL_NIF_TERM squared_norm(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
	CHECK_ARGC(1);
	Vec vec;

	if(termToVec(env, argv[0], vec))
	{
		return enif_make_double(env, vec.squaredNorm());
	}
	else
	{
		FAIL;
	} // end if
} // end squared_norm

// norm/1
static ERL_NIF_TERM norm(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
	CHECK_ARGC(1);
	Vec vec;

	if(termToVec(env, argv[0], vec))
	{
		return enif_make_double(env, vec.norm());
	}
	else
	{
		FAIL;
	} // end if
} // end norm

// length/1
static ERL_NIF_TERM length(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
	CHECK_ARGC(1);
	Vec vec;

	if(termToVec(env, argv[0], vec))
	{
		return enif_make_double(env, vec.norm()); // length just forwards to norm, so we'll use norm.
	}
	else
	{
		FAIL;
	} // end if
} // end length

// unit/1
static ERL_NIF_TERM unit(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
	CHECK_ARGC(1);
	Vec vec;

	if(termToVec(env, argv[0], vec))
	{
		return vecToTerm(env, vec.normalize()); // using normalize instead of unit avoids constructing another Vec
	}
	else
	{
		FAIL;
	} // end if
} // end unit

// hpr_to/1
static ERL_NIF_TERM hpr_to(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
	CHECK_ARGC(1);
	Vec vec;

	if(termToVec(env, argv[0], vec))
	{
		return vecToTerm(env, vec.hprAlong());
	}
	else
	{
		FAIL;
	} // end if
} // end hpr_to

// add/2, add/3
static ERL_NIF_TERM add(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
	CHECK_ARGC_RANGE(2, 3)
	Vec vec0, vec1;

	if(termToVec(env, argv[0], vec0) && termToVec(env, argv[1], vec1))
	{
		if(argc == 2)
		{
			return vecToTerm(env, vec0 += vec1);
		}
		else
		{
			Vec vec2;
			if(argc == 3 && termToVec(env, argv[2], vec2))
			{
				return vecToTerm(env, vec0 += vec1 += vec2);
			} // end if
		} // end if
	} // end if

	FAIL;
} // end add

// subtract/2
static ERL_NIF_TERM subtract(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
	CHECK_ARGC(2);
	Vec vec0, vec1;

	if(termToVec(env, argv[0], vec0) && termToVec(env, argv[1], vec1))
	{
		return vecToTerm(env, vec0 -= vec1);
	}
	else
	{
		FAIL;
	} // end if
} // end subtract

// is_zero/1
static ERL_NIF_TERM is_zero(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
	CHECK_ARGC(1);
	Vec vec;

	if(termToVec(env, argv[0], vec))
	{
		return vec.isZero() ?  true_atom : false_atom;
	}
	else
	{
		FAIL;
	} // end if
} // end is_zero
<commit_msg>Minor comment clarification.<commit_after>/**
 * @doc Vector NIF module - provides a C++ implementation of the `vector` Erlang module
 *
 * @copyright 2012-2013 David H. Bronke and Christopher S. Case
 * Licensed under the MIT license; see the LICENSE file for details.
 */

#include <string>

#include "nif_helpers.h"
#include "vector_nif_utils.h"

#include "vector_nif.h"

static ERL_NIF_TERM true_atom;
static ERL_NIF_TERM false_atom;

// --------------------------------------------------------------------------------------------------------------------
// NIF Inititialization

static int nif_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
{
	true_atom = enif_make_atom_len(env, "true", 4);
	false_atom = enif_make_atom_len(env, "false", 5);

	return 0;
} // end nif_load

static int nif_upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info)
{
	true_atom = enif_make_atom_len(env, "true", 4);
	false_atom = enif_make_atom_len(env, "false", 5);

	return 0;
} // end nif_upgrade

// --------------------------------------------------------------------------------------------------------------------
// NIFs

// vec_to_list/1
static ERL_NIF_TERM vec_to_list(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
	CHECK_ARGC(1);
	int arity;
	const ERL_NIF_TERM* array;

	if(enif_get_tuple(env, argv[0], &arity, &array) && arity == 3)
	{
		return enif_make_list_from_array(env, array, 3);
	}
	else
	{
		FAIL;
	} // end if
} // end vec_to_list

// list_to_vec/1
static ERL_NIF_TERM list_to_vec(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
	CHECK_ARGC(1);
	ERL_NIF_TERM vecTuple[3];
	ERL_NIF_TERM current = argv[0], tail;

	for(size_t idx = 0; idx < 3; idx++)
	{
		if(!enif_get_list_cell(env, current, &vecTuple[idx], &tail))
		{
			FAIL;
		} // end if

		current = tail;
	} // end for

	if(enif_is_empty_list(env, tail))
	{
		return enif_make_tuple_from_array(env, vecTuple, 3);
	}
	else
	{
		FAIL;
	} // end if
} // end list_to_vec

// dot/2
static ERL_NIF_TERM dot(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
	CHECK_ARGC(2);
	Vec vec0, vec1;

	if(termToVec(env, argv[0], vec0) && termToVec(env, argv[1], vec1))
	{
		return enif_make_double(env, vec0.dot(vec1));
	}
	else
	{
		FAIL;
	} // end if
} // end dot

// cross/2
static ERL_NIF_TERM cross(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
	CHECK_ARGC(2);
	Vec vec0, vec1;

	if(termToVec(env, argv[0], vec0) && termToVec(env, argv[1], vec1))
	{
		return vecToTerm(env, vec0.cross(vec1));
	}
	else
	{
		FAIL;
	} // end if
} // end cross

// multiply/2
static ERL_NIF_TERM multiply(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
	CHECK_ARGC(2);
	Vec vec;
	double factor;

	if(termToVec(env, argv[0], vec) && getNIFDouble(env, argv[1], &factor))
	{
		return vecToTerm(env, vec *= factor);
	}
	else if(getNIFDouble(env, argv[0], &factor) && termToVec(env, argv[1], vec))
	{
		return vecToTerm(env, vec *= factor);
	}
	else
	{
		FAIL;
	} // end if
} // end multiply

// divide/2
static ERL_NIF_TERM divide(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
	CHECK_ARGC(2);
	Vec vec;
	double divisor;

	if(termToVec(env, argv[0], vec) && getNIFDouble(env, argv[1], &divisor))
	{
		return vecToTerm(env, vec /= divisor);
	}
	else
	{
		FAIL;
	} // end if
} // end divide

// squared_norm/1
static ERL_NIF_TERM squared_norm(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
	CHECK_ARGC(1);
	Vec vec;

	if(termToVec(env, argv[0], vec))
	{
		return enif_make_double(env, vec.squaredNorm());
	}
	else
	{
		FAIL;
	} // end if
} // end squared_norm

// norm/1
static ERL_NIF_TERM norm(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
	CHECK_ARGC(1);
	Vec vec;

	if(termToVec(env, argv[0], vec))
	{
		return enif_make_double(env, vec.norm());
	}
	else
	{
		FAIL;
	} // end if
} // end norm

// length/1
static ERL_NIF_TERM length(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
	CHECK_ARGC(1);
	Vec vec;

	if(termToVec(env, argv[0], vec))
	{
		return enif_make_double(env, vec.norm()); // length just forwards to norm, so we'll use norm directly.
	}
	else
	{
		FAIL;
	} // end if
} // end length

// unit/1
static ERL_NIF_TERM unit(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
	CHECK_ARGC(1);
	Vec vec;

	if(termToVec(env, argv[0], vec))
	{
		return vecToTerm(env, vec.normalize()); // using normalize instead of unit avoids constructing another Vec
	}
	else
	{
		FAIL;
	} // end if
} // end unit

// hpr_to/1
static ERL_NIF_TERM hpr_to(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
	CHECK_ARGC(1);
	Vec vec;

	if(termToVec(env, argv[0], vec))
	{
		return vecToTerm(env, vec.hprAlong());
	}
	else
	{
		FAIL;
	} // end if
} // end hpr_to

// add/2, add/3
static ERL_NIF_TERM add(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
	CHECK_ARGC_RANGE(2, 3)
	Vec vec0, vec1;

	if(termToVec(env, argv[0], vec0) && termToVec(env, argv[1], vec1))
	{
		if(argc == 2)
		{
			return vecToTerm(env, vec0 += vec1);
		}
		else
		{
			Vec vec2;
			if(argc == 3 && termToVec(env, argv[2], vec2))
			{
				return vecToTerm(env, vec0 += vec1 += vec2);
			} // end if
		} // end if
	} // end if

	FAIL;
} // end add

// subtract/2
static ERL_NIF_TERM subtract(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
	CHECK_ARGC(2);
	Vec vec0, vec1;

	if(termToVec(env, argv[0], vec0) && termToVec(env, argv[1], vec1))
	{
		return vecToTerm(env, vec0 -= vec1);
	}
	else
	{
		FAIL;
	} // end if
} // end subtract

// is_zero/1
static ERL_NIF_TERM is_zero(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
	CHECK_ARGC(1);
	Vec vec;

	if(termToVec(env, argv[0], vec))
	{
		return vec.isZero() ?  true_atom : false_atom;
	}
	else
	{
		FAIL;
	} // end if
} // end is_zero
<|endoftext|>


<commit_before>#include "AllNeurons.h"
// Default constructor
AllNeurons::AllNeurons() :
        size(0)
{
    C1 = NULL;
    C2 = NULL;
    Cm = NULL;
    I0 = NULL;
    Iinject = NULL;
    Inoise = NULL;
    Isyn = NULL;
    Rm = NULL;
    Tau = NULL;
    Trefract = NULL;
    Vinit = NULL;
    Vm = NULL;
    Vreset = NULL;
    Vrest = NULL;
    Vthresh = NULL;
    deltaT = NULL;
    hasFired = NULL;
    nStepsInRefr = NULL;
    neuron_type_map = NULL;
    spikeCount = NULL;
    totalSpikeCount = NULL;
    spike_history = NULL;
    starter_map = NULL;
    summation_map = NULL;
}

AllNeurons::AllNeurons(const int size) :
        size(size)
{
    // TODO: Rename variables for easier identification
    C1 = new BGFLOAT[size];
    C2 = new BGFLOAT[size];
    Cm = new BGFLOAT[size];
    I0 = new BGFLOAT[size];
    Iinject = new BGFLOAT[size];
    Inoise = new BGFLOAT[size];
    Isyn = new BGFLOAT[size];
    Rm = new BGFLOAT[size];
    Tau = new BGFLOAT[size];
    Trefract = new BGFLOAT[size];
    Vinit = new BGFLOAT[size];
    Vm = new BGFLOAT[size];
    Vreset = new BGFLOAT[size];
    Vrest = new BGFLOAT[size];
    Vthresh = new BGFLOAT[size];
    deltaT = new BGFLOAT[size];
    hasFired = new bool[size];
    nStepsInRefr = new int[size];
    neuron_type_map = new neuronType[size];
    spikeCount = new int[size];
    totalSpikeCount = new int[size];
    starter_map = new bool[size];
    summation_map = new BGFLOAT[size];
    spike_history = new uint64_t*[size];

    for (int i = 0; i < size; ++i) {
        summation_map[i] = 0;
        nStepsInRefr[i] = 0;
        spike_history[i] = NULL;
        hasFired[i] = false;
        spikeCount[i] = 0;
        totalSpikeCount[i] = 0;
    }
}

AllNeurons::~AllNeurons()
{
    delete[] C1;
    delete[] C2;
    delete[] Cm;
    delete[] I0;
    delete[] Iinject;
    delete[] Inoise;
    delete[] Isyn;
    delete[] Rm;
    delete[] Tau;
    delete[] Trefract;
    delete[] Vinit;
    delete[] Vm;
    delete[] Vreset;
    delete[] Vrest;
    delete[] Vthresh;
    delete[] deltaT;
    delete[] hasFired;
    delete[] nStepsInRefr;
    delete[] neuron_type_map;
    delete[] spikeCount;
    delete[] totalSpikeCount;
    delete[] starter_map;
    delete[] summation_map;
    delete[] spike_history;

    for(int i = 0; i < size; i++) {
    	delete[] spike_history[i];

    }

    C1 = NULL;
    C2 = NULL;
    Cm = NULL;
    I0 = NULL;
    Iinject = NULL;
    Inoise = NULL;
    Isyn = NULL;
    Rm = NULL;
    Tau = NULL;
    Trefract = NULL;
    Vinit = NULL;
    Vm = NULL;
    Vreset = NULL;
    Vrest = NULL;
    Vthresh = NULL;
    deltaT = NULL;
    hasFired = NULL;
    nStepsInRefr = NULL;
    neuron_type_map = NULL;
    spikeCount = NULL;
    totalSpikeCount = NULL;
    starter_map = NULL;
    summation_map = NULL;
}
<commit_msg>Fixed spike history deletion in destructor.<commit_after>#include "AllNeurons.h"
// Default constructor
AllNeurons::AllNeurons() :
        size(0)
{
    C1 = NULL;
    C2 = NULL;
    Cm = NULL;
    I0 = NULL;
    Iinject = NULL;
    Inoise = NULL;
    Isyn = NULL;
    Rm = NULL;
    Tau = NULL;
    Trefract = NULL;
    Vinit = NULL;
    Vm = NULL;
    Vreset = NULL;
    Vrest = NULL;
    Vthresh = NULL;
    deltaT = NULL;
    hasFired = NULL;
    nStepsInRefr = NULL;
    neuron_type_map = NULL;
    spikeCount = NULL;
    totalSpikeCount = NULL;
    spike_history = NULL;
    starter_map = NULL;
    summation_map = NULL;
}

AllNeurons::AllNeurons(const int size) :
        size(size)
{
    // TODO: Rename variables for easier identification
    C1 = new BGFLOAT[size];
    C2 = new BGFLOAT[size];
    Cm = new BGFLOAT[size];
    I0 = new BGFLOAT[size];
    Iinject = new BGFLOAT[size];
    Inoise = new BGFLOAT[size];
    Isyn = new BGFLOAT[size];
    Rm = new BGFLOAT[size];
    Tau = new BGFLOAT[size];
    Trefract = new BGFLOAT[size];
    Vinit = new BGFLOAT[size];
    Vm = new BGFLOAT[size];
    Vreset = new BGFLOAT[size];
    Vrest = new BGFLOAT[size];
    Vthresh = new BGFLOAT[size];
    deltaT = new BGFLOAT[size];
    hasFired = new bool[size];
    nStepsInRefr = new int[size];
    neuron_type_map = new neuronType[size];
    spikeCount = new int[size];
    totalSpikeCount = new int[size];
    starter_map = new bool[size];
    summation_map = new BGFLOAT[size];
    spike_history = new uint64_t*[size];

    for (int i = 0; i < size; ++i) {
        summation_map[i] = 0;
        nStepsInRefr[i] = 0;
        spike_history[i] = NULL;
        hasFired[i] = false;
        spikeCount[i] = 0;
        totalSpikeCount[i] = 0;
    }
}

AllNeurons::~AllNeurons()
{
    for(int i = 0; i < size; i++) {
    	delete[] spike_history[i];
    }

    delete[] C1;
    delete[] C2;
    delete[] Cm;
    delete[] I0;
    delete[] Iinject;
    delete[] Inoise;
    delete[] Isyn;
    delete[] Rm;
    delete[] Tau;
    delete[] Trefract;
    delete[] Vinit;
    delete[] Vm;
    delete[] Vreset;
    delete[] Vrest;
    delete[] Vthresh;
    delete[] deltaT;
    delete[] hasFired;
    delete[] nStepsInRefr;
    delete[] neuron_type_map;
    delete[] spikeCount;
    delete[] totalSpikeCount;
    delete[] starter_map;
    delete[] summation_map;
    delete[] spike_history;

    C1 = NULL;
    C2 = NULL;
    Cm = NULL;
    I0 = NULL;
    Iinject = NULL;
    Inoise = NULL;
    Isyn = NULL;
    Rm = NULL;
    Tau = NULL;
    Trefract = NULL;
    Vinit = NULL;
    Vm = NULL;
    Vreset = NULL;
    Vrest = NULL;
    Vthresh = NULL;
    deltaT = NULL;
    hasFired = NULL;
    nStepsInRefr = NULL;
    neuron_type_map = NULL;
    spikeCount = NULL;
    totalSpikeCount = NULL;
    starter_map = NULL;
    summation_map = NULL;
    spike_history = NULL;
}
<|endoftext|>


<commit_before>//
//  test2D.cpp
//
//  Created by Barrett Davis on 5/31/16.
//  Copyright © 2016 Tree Frog Software. All rights reserved.
//
#include <cmath>
#include "DnnBuilder.h"
#include "DnnTrainerSGD.h"
#include "Error.h"
#include "test2D.hpp"
#include "Utility.h"

namespace tfs {

    static void
    setData( std::vector< DNN_NUMERIC > &data, std::vector< DNN_INTEGER > &label, DNN_NUMERIC xx, DNN_NUMERIC yy, DNN_INTEGER value ) {
        data.push_back( xx );       // x,y pair
        data.push_back( yy );
        label.push_back( value );   // label
        return;
    }

    static void
    setUpDataSimple( std::vector< DNN_NUMERIC > &data, std::vector< DNN_INTEGER > &label ) {
        setData( data, label, -0.4326, 1.1909,   1 );
        setData( data, label,  3.0,      4.0,    1 );
        setData( data, label,  0.1253 , -0.0376, 1 );
        setData( data, label,  0.2877 ,  0.3273, 1 );
        setData( data, label, -1.1465 ,  0.1746, 1 );
        setData( data, label,  1.8133 ,  1.0139, 0 );
        setData( data, label,  2.7258 ,  1.0668, 0 );
        setData( data, label,  1.4117 ,  0.5593, 0 );
        setData( data, label,  4.1832 ,  0.3044, 0 );
        setData( data, label,  1.8636 ,  0.1677, 0 );
        setData( data, label,  0.5 ,     3.2,    1 );
        setData( data, label,  0.8 ,     3.2,    1 );
        setData( data, label,  1.0 ,    -2.2,    1 );
        return;
    }

    static void
    setUpDataRandom( std::vector< DNN_NUMERIC > &data, std::vector< DNN_INTEGER > &label, const int count ) {
        for( int ii = 0; ii < count; ii++ ) {
            const DNN_NUMERIC xx = random( -3.0, 3.0 );
            const DNN_NUMERIC yy = random( -3.0, 3.0 );
            DNN_INTEGER value = 0;
            if( random( 0.0, 1.0 ) > 0.5 ) {
                value = 1;
            }
            setData( data, label, xx, yy, value );
        }
        return;
    }

    static void
    setUpDataCircle( std::vector< DNN_NUMERIC > &data, std::vector< DNN_INTEGER > &label, const int count ) {
        for( int ii = 0; ii < count; ii++ ) {
            const DNN_NUMERIC rr = random( 0.0, 2.0 );
            const DNN_NUMERIC tt = random( 0.0, 2.0 * M_PI );
            const DNN_NUMERIC xx = rr * sin( tt );
            const DNN_NUMERIC yy = rr * cos( tt );
            setData( data, label, xx, yy, 0 );
        }
        for( int ii = 0; ii < count; ii++ ) {
            const DNN_NUMERIC rr = random( 3.0, 5.0 );
            const DNN_NUMERIC tt = 2.0 * M_PI * ii / count;
            const DNN_NUMERIC xx = rr * sin( tt );
            const DNN_NUMERIC yy = rr * cos( tt );
            setData( data, label, xx, yy, 1 );
        }
        return;
    }

    static void
    setUpDataSpiral( std::vector< DNN_NUMERIC > &data, std::vector< DNN_INTEGER > &label, const DNN_NUMERIC count ) {
        for( DNN_NUMERIC ii = 0; ii < count; ii += 1.0 ) {
            const DNN_NUMERIC rr = ii / count * 5.0 + random( -0.1, 0.1 );
            const DNN_NUMERIC tt = 1.25 * ii / count * 2.0 * M_PI + random( -0.1, 0.1 );
            const DNN_NUMERIC xx = rr * sin( tt );
            const DNN_NUMERIC yy = rr * cos( tt );
            setData( data, label, xx, yy, 0 );
        }
        for( int ii = 0; ii < count; ii += 1.0 ) {
            const DNN_NUMERIC rr = ii / count * 5.0 + random( -0.1, 0.1 );
            const DNN_NUMERIC tt = 1.25 * ii / count * 2.0 * M_PI + random( -0.1, 0.1 ) + M_PI;
            const DNN_NUMERIC xx = rr * sin( tt );
            const DNN_NUMERIC yy = rr * cos( tt );
            setData( data, label, xx, yy, 1 );
        }
        return;
    }

    static bool
    setupDnn( Dnn &dnn ) {                                      // Same DNN for all 2d tests.
        DnnBuilder builder( dnn, ACTIVATION_TANH );
        if( !builder.addLayerInput( 1, 1, 2 )) {                // Input layer a single x, y data point.
            return log_error( "Cannot add Input layer" );
        }
        if( !builder.addLayerFullyConnected( 6 )) {             // 6 Neurons
            return log_error( "Cannot add Fully Connected layer" );
        }
        if( !builder.addLayerFullyConnected( 2 )) {             // 2 Neurons
            return log_error( "Cannot add Fully Connected layer" );
        }
        if( !builder.addLayerSoftmax( 2 )) {                    // Output classifier, 2 classes.
            return log_error( "Cannot add Softmax layer" );
        }
        dnn.initialize();                                       // Randomize the weights.
        const unsigned long count = dnn.count();
        log_info( "We have set up %lu layers", count );
        return true;
    }

    static bool
    localTest2d( Dnn &dnn, std::vector< DNN_NUMERIC > &data, std::vector< DNN_INTEGER > &label ) {
        DnnTrainerSGD trainer( &dnn );
        trainer.learningRate( 0.01  );
        trainer.momentum(     0.1   );
        trainer.batchSize(   10     );
        trainer.l2Decay(      0.001 );

        Matrix *input = trainer.getMatrixInput();       // get the input matrix: x,y pair Matrix( 1, 1, 2 )
        if( input == 0 ) {
            return log_error( "Unable to obtain input matrix." );
        }
        const DNN_NUMERIC *dPtr = data.data();
        if( dPtr == 0 ) {
            return log_error( "Unable to obtain input data." );
        }
        const DNN_INTEGER *lPtr = label.data();
        if( lPtr == 0 ) {
            return log_error( "Unable to obtain input labels." );
        }
        const unsigned long DATA_COUNT = label.size();
        if( DATA_COUNT < 1 ) {
            return log_error( "Label data size < 1" );
        }
        const DNN_INTEGER *ePtr = lPtr + DATA_COUNT;

        const unsigned long MAX_ITERATION = 200;
        const DNN_NUMERIC   TARGET_LOSS   = 0.05;
        unsigned long count = 0;
        DNN_NUMERIC average_loss = 0.0;
        do {
            count++;
            average_loss = 0.0;
            for( unsigned long ii = 0; ii < MAX_ITERATION; ii++ ) {
                dPtr = data.data();
                lPtr = label.data();

                while( lPtr < ePtr ) {
                    DNN_NUMERIC *inPtr = input->data();
                    *inPtr++ = *dPtr++;     // x
                    *inPtr   = *dPtr++;     // y
                    average_loss += trainer.train( *lPtr++ );
                }
            }
            average_loss /= DATA_COUNT * MAX_ITERATION;
        } while( average_loss > TARGET_LOSS );
        log_info( "%lu: Average loss = %f", count, average_loss );

        return true;
    }

    static bool
    localTestSimple( void ) {
        log_info( "Test Simple - Start" );
        Dnn dnn;
        if( !setupDnn( dnn )) {
            return false;
        }
        std::vector< DNN_NUMERIC > data;    // x,y pairs
        std::vector< DNN_INTEGER > label;   // binary labels.

        setUpDataSimple( data, label );

        localTest2d( dnn, data, label );

        log_info( "Test Simple - End" );
        return true;
    }

    static bool
    localTestRandom( void ) {
        log_info( "Test Random - Start" );
        Dnn dnn;
        if( !setupDnn( dnn )) {
            return false;
        }
        std::vector< DNN_NUMERIC > data;    // x,y pairs
        std::vector< DNN_INTEGER > label;   // binary labels.

        setUpDataRandom( data, label, 40 );

        localTest2d( dnn, data, label );

        log_info( "Test Random - End" );
        return true;
    }

    static bool
    localTestCircle( void ) {
        log_info( "Test Circle - Start" );
        Dnn dnn;
        if( !setupDnn( dnn )) {
            return false;
        }
        std::vector< DNN_NUMERIC > data;    // x,y pairs
        std::vector< DNN_INTEGER > label;   // binary labels.

        setUpDataCircle( data, label, 50 );

        localTest2d( dnn, data, label );

        log_info( "Test Circle - End" );
        return true;
    }

    static bool
    localTestSpiral( void ) {
        log_info( "Test Spiral - Start" );
        Dnn dnn;
        if( !setupDnn( dnn )) {
            return false;
        }
        std::vector< DNN_NUMERIC > data;    // x,y pairs
        std::vector< DNN_INTEGER > label;   // binary labels.

//        setUpDataSimple( data, label );
//
//        localTest2d( dnn, data, label );
//
//        data.clear();
//        label.clear();

        setUpDataSpiral( data, label, 100.0 );

        localTest2d( dnn, data, label );

        log_info( "Test Spiral - End" );
        return true;
    }

}  // tfs namespace

bool
testSimple( void ) {
    return tfs::localTestSimple();
}

bool
testRandom( void ) {
    return tfs::localTestRandom();
}

bool
testCircle( void ) {
    return tfs::localTestCircle();
}

bool
testSpiral( void ) {
    return tfs::localTestSpiral();
}
<commit_msg>cleaning up the 2d unit test<commit_after>//
//  test2D.cpp
//
//  Created by Barrett Davis on 5/31/16.
//  Copyright © 2016 Tree Frog Software. All rights reserved.
//
#include <cmath>
#include "DnnBuilder.h"
#include "DnnTrainerSGD.h"
#include "Error.h"
#include "test2D.hpp"
#include "Utility.h"

namespace tfs {

    static void
    setData( std::vector< DNN_NUMERIC > &data, std::vector< DNN_INTEGER > &label, DNN_NUMERIC xx, DNN_NUMERIC yy, DNN_INTEGER value ) {
        data.push_back( xx );       // x,y pair
        data.push_back( yy );
        label.push_back( value );   // label
        return;
    }

    static void
    setUpDataSimple( std::vector< DNN_NUMERIC > &data, std::vector< DNN_INTEGER > &label ) {
        setData( data, label, -0.4326, 1.1909,   1 );
        setData( data, label,  3.0,      4.0,    1 );
        setData( data, label,  0.1253 , -0.0376, 1 );
        setData( data, label,  0.2877 ,  0.3273, 1 );
        setData( data, label, -1.1465 ,  0.1746, 1 );
        setData( data, label,  1.8133 ,  1.0139, 0 );
        setData( data, label,  2.7258 ,  1.0668, 0 );
        setData( data, label,  1.4117 ,  0.5593, 0 );
        setData( data, label,  4.1832 ,  0.3044, 0 );
        setData( data, label,  1.8636 ,  0.1677, 0 );
        setData( data, label,  0.5 ,     3.2,    1 );
        setData( data, label,  0.8 ,     3.2,    1 );
        setData( data, label,  1.0 ,    -2.2,    1 );
        return;
    }

    static void
    setUpDataRandom( std::vector< DNN_NUMERIC > &data, std::vector< DNN_INTEGER > &label, const int count ) {
        for( int ii = 0; ii < count; ii++ ) {
            const DNN_NUMERIC xx = random( -3.0, 3.0 );
            const DNN_NUMERIC yy = random( -3.0, 3.0 );
            DNN_INTEGER value = 0;
            if( random( 0.0, 1.0 ) > 0.5 ) {
                value = 1;
            }
            setData( data, label, xx, yy, value );
        }
        return;
    }

    static void
    setUpDataCircle( std::vector< DNN_NUMERIC > &data, std::vector< DNN_INTEGER > &label, const int count ) {
        for( int ii = 0; ii < count; ii++ ) {
            const DNN_NUMERIC rr = random( 0.0, 2.0 );
            const DNN_NUMERIC tt = random( 0.0, 2.0 * M_PI );
            const DNN_NUMERIC xx = rr * sin( tt );
            const DNN_NUMERIC yy = rr * cos( tt );
            setData( data, label, xx, yy, 0 );
        }
        for( DNN_NUMERIC ii = 0.0; ii < count; ii += 1.0 ) {
            const DNN_NUMERIC rr = random( 3.0, 5.0 );
            const DNN_NUMERIC tt = 2.0 * M_PI * ii / count;
            const DNN_NUMERIC xx = rr * sin( tt );
            const DNN_NUMERIC yy = rr * cos( tt );
            setData( data, label, xx, yy, 1 );
        }
        return;
    }

    static void
    setUpDataSpiral( std::vector< DNN_NUMERIC > &data, std::vector< DNN_INTEGER > &label, const DNN_NUMERIC count ) {
        for( DNN_NUMERIC ii = 0.0; ii < count; ii += 1.0 ) {
            const DNN_NUMERIC rr = ii / count * 5.0 + random( -0.1, 0.1 );
            const DNN_NUMERIC tt = 1.25 * ii / count * 2.0 * M_PI + random( -0.1, 0.1 );
            const DNN_NUMERIC xx = rr * sin( tt );
            const DNN_NUMERIC yy = rr * cos( tt );
            setData( data, label, xx, yy, 0 );
        }
        for( DNN_NUMERIC ii = 0.0; ii < count; ii += 1.0 ) {
            const DNN_NUMERIC rr = ii / count * 5.0 + random( -0.1, 0.1 );
            const DNN_NUMERIC tt = 1.25 * ii / count * 2.0 * M_PI + random( -0.1, 0.1 ) + M_PI;
            const DNN_NUMERIC xx = rr * sin( tt );
            const DNN_NUMERIC yy = rr * cos( tt );
            setData( data, label, xx, yy, 1 );
        }
        return;
    }

    static bool
    setupDnn( Dnn &dnn ) {                                      // Same DNN for all 2d tests.
        DnnBuilder builder( dnn, ACTIVATION_TANH );
        if( !builder.addLayerInput( 1, 1, 2 )) {                // Input layer a single x, y data point.
            return log_error( "Cannot add Input layer" );
        }
        if( !builder.addLayerFullyConnected( 6 )) {             // 6 Neurons
            return log_error( "Cannot add Fully Connected layer" );
        }
        if( !builder.addLayerFullyConnected( 2 )) {             // 2 Neurons
            return log_error( "Cannot add Fully Connected layer" );
        }
        if( !builder.addLayerSoftmax( 2 )) {                    // Output classifier, 2 classes.
            return log_error( "Cannot add Softmax layer" );
        }
        dnn.initialize();                                       // Randomize the weights.
        const unsigned long count = dnn.count();
        log_info( "We have set up %lu layers", count );
        return true;
    }

    static bool
    localTest2d( Dnn &dnn, std::vector< DNN_NUMERIC > &data, std::vector< DNN_INTEGER > &label ) {
        DnnTrainerSGD trainer( &dnn );
        trainer.learningRate( 0.01  );
        trainer.momentum(     0.1   );
        trainer.batchSize(   10     );
        trainer.l2Decay(      0.001 );

        Matrix *input = trainer.getMatrixInput();       // get the input matrix: x,y pair Matrix( 1, 1, 2 )
        if( input == 0 ) {
            return log_error( "Unable to obtain input matrix." );
        }
        const DNN_NUMERIC *dPtr = data.data();
        if( dPtr == 0 ) {
            return log_error( "Unable to obtain input data." );
        }
        const DNN_INTEGER *lPtr = label.data();
        if( lPtr == 0 ) {
            return log_error( "Unable to obtain input labels." );
        }
        const unsigned long DATA_COUNT = label.size();
        if( DATA_COUNT < 1 ) {
            return log_error( "Label data size < 1" );
        }
        const DNN_INTEGER *ePtr = lPtr + DATA_COUNT;

        const unsigned long MAX_ITERATION = 200;
        const DNN_NUMERIC   TARGET_LOSS   = 0.05;
        unsigned long count = 0;
        DNN_NUMERIC average_loss = 0.0;
        do {
            count++;
            average_loss = 0.0;
            for( unsigned long ii = 0; ii < MAX_ITERATION; ii++ ) {
                dPtr = data.data();
                lPtr = label.data();

                while( lPtr < ePtr ) {
                    DNN_NUMERIC *inPtr = input->data();
                    *inPtr++ = *dPtr++;     // x
                    *inPtr   = *dPtr++;     // y
                    average_loss += trainer.train( *lPtr++ );
                }
            }
            average_loss /= DATA_COUNT * MAX_ITERATION;
        } while( average_loss > TARGET_LOSS );
        log_info( "%lu: Average loss = %f", count, average_loss );

        return true;
    }

    static bool
    localTestSimple( void ) {
        log_info( "Test Simple - Start" );
        Dnn dnn;
        if( !setupDnn( dnn )) {
            return false;
        }
        std::vector< DNN_NUMERIC > data;    // x,y pairs
        std::vector< DNN_INTEGER > label;   // binary labels.

        setUpDataSimple( data, label );

        localTest2d( dnn, data, label );

        log_info( "Test Simple - End" );
        return true;
    }

    static bool
    localTestRandom( void ) {
        log_info( "Test Random - Start" );
        Dnn dnn;
        if( !setupDnn( dnn )) {
            return false;
        }
        std::vector< DNN_NUMERIC > data;    // x,y pairs
        std::vector< DNN_INTEGER > label;   // binary labels.

        setUpDataRandom( data, label, 40 );

        localTest2d( dnn, data, label );

        log_info( "Test Random - End" );
        return true;
    }

    static bool
    localTestCircle( void ) {
        log_info( "Test Circle - Start" );
        Dnn dnn;
        if( !setupDnn( dnn )) {
            return false;
        }
        std::vector< DNN_NUMERIC > data;    // x,y pairs
        std::vector< DNN_INTEGER > label;   // binary labels.

        setUpDataCircle( data, label, 50 );

        localTest2d( dnn, data, label );

        log_info( "Test Circle - End" );
        return true;
    }

    static bool
    localTestSpiral( void ) {
        log_info( "Test Spiral - Start" );
        Dnn dnn;
        if( !setupDnn( dnn )) {
            return false;
        }
        std::vector< DNN_NUMERIC > data;    // x,y pairs
        std::vector< DNN_INTEGER > label;   // binary labels.

//        setUpDataSimple( data, label );
//
//        localTest2d( dnn, data, label );
//
//        data.clear();
//        label.clear();

        setUpDataSpiral( data, label, 100.0 );

        localTest2d( dnn, data, label );

        log_info( "Test Spiral - End" );
        return true;
    }

}  // tfs namespace

bool
testSimple( void ) {
    return tfs::localTestSimple();
}

bool
testRandom( void ) {
    return tfs::localTestRandom();
}

bool
testCircle( void ) {
    return tfs::localTestCircle();
}

bool
testSpiral( void ) {
    return tfs::localTestSpiral();
}
<|endoftext|>


<commit_before>/*
 *
 * Copyright (c) 1998-2002
 * John Maddock
 *
 * Use, modification and distribution are subject to the
 * Boost Software License, Version 1.0. (See accompanying file
 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 *
 */

 /*
  *   LOCATION:    see http://www.boost.org for most recent version.
  *   FILE         instances.cpp
  *   VERSION      see <boost/version.hpp>
  *   DESCRIPTION: Defines those template instances that are placed in the
  *                library rather than in the users object files.
  */

//
// note no include guard, we may include this multiple times:
//
#ifndef BOOST_REGEX_NO_EXTERNAL_TEMPLATES

namespace boost{

//
// this header can be included multiple times, each time with
// a different character type, BOOST_REGEX_CHAR_T must be defined
// first:
//
#ifndef BOOST_REGEX_CHAR_T
#  error "BOOST_REGEX_CHAR_T not defined"
#endif

#ifndef BOOST_REGEX_TRAITS_T
#  define BOOST_REGEX_TRAITS_T , boost::regex_traits<BOOST_REGEX_CHAR_T >
#endif

//
// what follows is compiler specific:
//

#if  defined(__BORLANDC__) && (__BORLANDC__ < 0x600)

#ifdef BOOST_HAS_ABI_HEADERS
#  include BOOST_ABI_PREFIX
#endif

#  ifndef BOOST_REGEX_INSTANTIATE
#     pragma option push -Jgx
#  endif

template class BOOST_REGEX_DECL basic_regex< BOOST_REGEX_CHAR_T BOOST_REGEX_TRAITS_T >;
template class BOOST_REGEX_DECL match_results< const BOOST_REGEX_CHAR_T* >;
#ifndef BOOST_NO_STD_ALLOCATOR
template class BOOST_REGEX_DECL ::boost::BOOST_REGEX_DETAIL_NS::perl_matcher<BOOST_REGEX_CHAR_T const *, match_results< const BOOST_REGEX_CHAR_T* >::allocator_type BOOST_REGEX_TRAITS_T >;
#endif

#  ifndef BOOST_REGEX_INSTANTIATE
#     pragma option pop
#  endif

#ifdef BOOST_HAS_ABI_HEADERS
#  include BOOST_ABI_SUFFIX
#endif

#elif defined(BOOST_MSVC) || defined(__ICL)

#  ifndef BOOST_REGEX_INSTANTIATE
#     ifdef __GNUC__
#        define template __extension__ extern template
#     else
#        if BOOST_MSVC > 1310
#           define BOOST_REGEX_TEMPLATE_DECL
#        endif
#        define template extern template
#     endif
#  endif

#ifndef BOOST_REGEX_TEMPLATE_DECL
#  define BOOST_REGEX_TEMPLATE_DECL BOOST_REGEX_DECL
#endif

#  ifdef BOOST_MSVC
#     pragma warning(push)
#     pragma warning(disable : 4251 4231)
#     if BOOST_MSVC < 1600
#     pragma warning(disable : 4660)
#     endif
#  endif

template class BOOST_REGEX_TEMPLATE_DECL basic_regex< BOOST_REGEX_CHAR_T BOOST_REGEX_TRAITS_T >;

template class BOOST_REGEX_TEMPLATE_DECL match_results< const BOOST_REGEX_CHAR_T* >;
#ifndef BOOST_NO_STD_ALLOCATOR
template class BOOST_REGEX_TEMPLATE_DECL ::boost::BOOST_REGEX_DETAIL_NS::perl_matcher<BOOST_REGEX_CHAR_T const *, match_results< const BOOST_REGEX_CHAR_T* >::allocator_type BOOST_REGEX_TRAITS_T >;
#endif
#if !(defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB <= 1))\
   && !(defined(BOOST_INTEL_CXX_VERSION) && (BOOST_INTEL_CXX_VERSION <= 800))\
   && !(defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION))\
   && !defined(BOOST_REGEX_ICU_INSTANCES)
template class BOOST_REGEX_TEMPLATE_DECL match_results< std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator >;
#ifndef BOOST_NO_STD_ALLOCATOR
template class BOOST_REGEX_TEMPLATE_DECL ::boost::BOOST_REGEX_DETAIL_NS::perl_matcher< std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator, match_results< std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator >::allocator_type, boost::regex_traits<BOOST_REGEX_CHAR_T > >;
#endif
#endif

#  ifdef BOOST_MSVC
#     pragma warning(pop)
#  endif

#  ifdef template
#     undef template
#  endif

#undef BOOST_REGEX_TEMPLATE_DECL

#elif (defined(__GNUC__) && (__GNUC__ >= 3)) || !defined(BOOST_NO_CXX11_EXTERN_TEMPLATE)

#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wkeyword-macro"
#endif

#  ifndef BOOST_REGEX_INSTANTIATE
#     ifdef __GNUC__
#        define template __extension__ extern template
#     else
#        define template extern template
#     endif
#  endif

#if !defined(BOOST_NO_STD_LOCALE) && !defined(BOOST_REGEX_ICU_INSTANCES)
namespace BOOST_REGEX_DETAIL_NS{
template BOOST_REGEX_DECL
std::locale cpp_regex_traits_base<BOOST_REGEX_CHAR_T>::imbue(const std::locale& l);

template BOOST_REGEX_DECL
cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::string_type
   cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::transform_primary(const BOOST_REGEX_CHAR_T* p1, const BOOST_REGEX_CHAR_T* p2) const;
template BOOST_REGEX_DECL
cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::string_type
   cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::transform(const BOOST_REGEX_CHAR_T* p1, const BOOST_REGEX_CHAR_T* p2) const;
template BOOST_REGEX_DECL
cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::string_type
   cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::lookup_collatename(const BOOST_REGEX_CHAR_T* p1, const BOOST_REGEX_CHAR_T* p2) const;
template BOOST_REGEX_DECL
void cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::init();
template BOOST_REGEX_DECL
cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::char_class_type
   cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::lookup_classname_imp(const BOOST_REGEX_CHAR_T* p1, const BOOST_REGEX_CHAR_T* p2) const;
#ifdef BOOST_REGEX_BUGGY_CTYPE_FACET
template BOOST_REGEX_DECL
bool cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::isctype(const BOOST_REGEX_CHAR_T c, char_class_type mask) const;
#endif
} // namespace
template BOOST_REGEX_DECL
int cpp_regex_traits<BOOST_REGEX_CHAR_T>::toi(const BOOST_REGEX_CHAR_T*& first, const BOOST_REGEX_CHAR_T* last, int radix)const;
template BOOST_REGEX_DECL
std::string cpp_regex_traits<BOOST_REGEX_CHAR_T>::catalog_name(const std::string& name);
template BOOST_REGEX_DECL
std::string& cpp_regex_traits<BOOST_REGEX_CHAR_T>::get_catalog_name_inst();
template BOOST_REGEX_DECL
std::string cpp_regex_traits<BOOST_REGEX_CHAR_T>::get_catalog_name();
#ifdef BOOST_HAS_THREADS
template BOOST_REGEX_DECL
static_mutex& cpp_regex_traits<BOOST_REGEX_CHAR_T>::get_mutex_inst();
#endif
#endif

template BOOST_REGEX_DECL basic_regex<BOOST_REGEX_CHAR_T BOOST_REGEX_TRAITS_T >&
   basic_regex<BOOST_REGEX_CHAR_T BOOST_REGEX_TRAITS_T >::do_assign(
      const BOOST_REGEX_CHAR_T* p1,
      const BOOST_REGEX_CHAR_T* p2,
      flag_type f);
template BOOST_REGEX_DECL basic_regex<BOOST_REGEX_CHAR_T BOOST_REGEX_TRAITS_T >::locale_type BOOST_REGEX_CALL
   basic_regex<BOOST_REGEX_CHAR_T BOOST_REGEX_TRAITS_T >::imbue(locale_type l);

template BOOST_REGEX_DECL void BOOST_REGEX_CALL
   match_results<const BOOST_REGEX_CHAR_T*>::maybe_assign(
      const match_results<const BOOST_REGEX_CHAR_T*>& m);

namespace BOOST_REGEX_DETAIL_NS{
template BOOST_REGEX_DECL void perl_matcher<BOOST_REGEX_CHAR_T const *, match_results< const BOOST_REGEX_CHAR_T* >::allocator_type BOOST_REGEX_TRAITS_T >::construct_init(
      const basic_regex<BOOST_REGEX_CHAR_T BOOST_REGEX_TRAITS_T >& e, match_flag_type f);
template BOOST_REGEX_DECL bool perl_matcher<BOOST_REGEX_CHAR_T const *, match_results< const BOOST_REGEX_CHAR_T* >::allocator_type BOOST_REGEX_TRAITS_T >::match();
template BOOST_REGEX_DECL bool perl_matcher<BOOST_REGEX_CHAR_T const *, match_results< const BOOST_REGEX_CHAR_T* >::allocator_type BOOST_REGEX_TRAITS_T >::find();
} // namespace

#if (defined(__GLIBCPP__) || defined(__GLIBCXX__)) \
   && !defined(BOOST_REGEX_ICU_INSTANCES)\
   && !defined(__SGI_STL_PORT)\
   && !defined(_STLPORT_VERSION)
// std:basic_string<>::const_iterator instances as well:
template BOOST_REGEX_DECL void BOOST_REGEX_CALL
   match_results<std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator>::maybe_assign(
      const match_results<std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator>& m);

namespace BOOST_REGEX_DETAIL_NS{
template BOOST_REGEX_DECL void perl_matcher<std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator, match_results< std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator >::allocator_type, boost::regex_traits<BOOST_REGEX_CHAR_T > >::construct_init(
      const basic_regex<BOOST_REGEX_CHAR_T>& e, match_flag_type f);
template BOOST_REGEX_DECL bool perl_matcher<std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator, match_results< std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator >::allocator_type, boost::regex_traits<BOOST_REGEX_CHAR_T > >::match();
template BOOST_REGEX_DECL bool perl_matcher<std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator, match_results< std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator >::allocator_type, boost::regex_traits<BOOST_REGEX_CHAR_T > >::find();
} // namespace
#endif

#  ifdef template
#     undef template
#  endif

#ifdef __clang__
#pragma clang diagnostic pop
#endif
#endif

} // namespace boost

#endif // BOOST_REGEX_NO_EXTERNAL_TEMPLATES

<commit_msg>Disable a Clang pragma to prevent warnings on OS X<commit_after>/*
 *
 * Copyright (c) 1998-2002
 * John Maddock
 *
 * Use, modification and distribution are subject to the
 * Boost Software License, Version 1.0. (See accompanying file
 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 *
 */

 /*
  *   LOCATION:    see http://www.boost.org for most recent version.
  *   FILE         instances.cpp
  *   VERSION      see <boost/version.hpp>
  *   DESCRIPTION: Defines those template instances that are placed in the
  *                library rather than in the users object files.
  */

//
// note no include guard, we may include this multiple times:
//
#ifndef BOOST_REGEX_NO_EXTERNAL_TEMPLATES

namespace boost{

//
// this header can be included multiple times, each time with
// a different character type, BOOST_REGEX_CHAR_T must be defined
// first:
//
#ifndef BOOST_REGEX_CHAR_T
#  error "BOOST_REGEX_CHAR_T not defined"
#endif

#ifndef BOOST_REGEX_TRAITS_T
#  define BOOST_REGEX_TRAITS_T , boost::regex_traits<BOOST_REGEX_CHAR_T >
#endif

//
// what follows is compiler specific:
//

#if  defined(__BORLANDC__) && (__BORLANDC__ < 0x600)

#ifdef BOOST_HAS_ABI_HEADERS
#  include BOOST_ABI_PREFIX
#endif

#  ifndef BOOST_REGEX_INSTANTIATE
#     pragma option push -Jgx
#  endif

template class BOOST_REGEX_DECL basic_regex< BOOST_REGEX_CHAR_T BOOST_REGEX_TRAITS_T >;
template class BOOST_REGEX_DECL match_results< const BOOST_REGEX_CHAR_T* >;
#ifndef BOOST_NO_STD_ALLOCATOR
template class BOOST_REGEX_DECL ::boost::BOOST_REGEX_DETAIL_NS::perl_matcher<BOOST_REGEX_CHAR_T const *, match_results< const BOOST_REGEX_CHAR_T* >::allocator_type BOOST_REGEX_TRAITS_T >;
#endif

#  ifndef BOOST_REGEX_INSTANTIATE
#     pragma option pop
#  endif

#ifdef BOOST_HAS_ABI_HEADERS
#  include BOOST_ABI_SUFFIX
#endif

#elif defined(BOOST_MSVC) || defined(__ICL)

#  ifndef BOOST_REGEX_INSTANTIATE
#     ifdef __GNUC__
#        define template __extension__ extern template
#     else
#        if BOOST_MSVC > 1310
#           define BOOST_REGEX_TEMPLATE_DECL
#        endif
#        define template extern template
#     endif
#  endif

#ifndef BOOST_REGEX_TEMPLATE_DECL
#  define BOOST_REGEX_TEMPLATE_DECL BOOST_REGEX_DECL
#endif

#  ifdef BOOST_MSVC
#     pragma warning(push)
#     pragma warning(disable : 4251 4231)
#     if BOOST_MSVC < 1600
#     pragma warning(disable : 4660)
#     endif
#  endif

template class BOOST_REGEX_TEMPLATE_DECL basic_regex< BOOST_REGEX_CHAR_T BOOST_REGEX_TRAITS_T >;

template class BOOST_REGEX_TEMPLATE_DECL match_results< const BOOST_REGEX_CHAR_T* >;
#ifndef BOOST_NO_STD_ALLOCATOR
template class BOOST_REGEX_TEMPLATE_DECL ::boost::BOOST_REGEX_DETAIL_NS::perl_matcher<BOOST_REGEX_CHAR_T const *, match_results< const BOOST_REGEX_CHAR_T* >::allocator_type BOOST_REGEX_TRAITS_T >;
#endif
#if !(defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB <= 1))\
   && !(defined(BOOST_INTEL_CXX_VERSION) && (BOOST_INTEL_CXX_VERSION <= 800))\
   && !(defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION))\
   && !defined(BOOST_REGEX_ICU_INSTANCES)
template class BOOST_REGEX_TEMPLATE_DECL match_results< std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator >;
#ifndef BOOST_NO_STD_ALLOCATOR
template class BOOST_REGEX_TEMPLATE_DECL ::boost::BOOST_REGEX_DETAIL_NS::perl_matcher< std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator, match_results< std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator >::allocator_type, boost::regex_traits<BOOST_REGEX_CHAR_T > >;
#endif
#endif

#  ifdef BOOST_MSVC
#     pragma warning(pop)
#  endif

#  ifdef template
#     undef template
#  endif

#undef BOOST_REGEX_TEMPLATE_DECL

#elif (defined(__GNUC__) && (__GNUC__ >= 3)) || !defined(BOOST_NO_CXX11_EXTERN_TEMPLATE)

#ifdef __clang__
#pragma clang diagnostic push
//#pragma clang diagnostic ignored "-Wkeyword-macro"
#endif

#  ifndef BOOST_REGEX_INSTANTIATE
#     ifdef __GNUC__
#        define template __extension__ extern template
#     else
#        define template extern template
#     endif
#  endif

#if !defined(BOOST_NO_STD_LOCALE) && !defined(BOOST_REGEX_ICU_INSTANCES)
namespace BOOST_REGEX_DETAIL_NS{
template BOOST_REGEX_DECL
std::locale cpp_regex_traits_base<BOOST_REGEX_CHAR_T>::imbue(const std::locale& l);

template BOOST_REGEX_DECL
cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::string_type
   cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::transform_primary(const BOOST_REGEX_CHAR_T* p1, const BOOST_REGEX_CHAR_T* p2) const;
template BOOST_REGEX_DECL
cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::string_type
   cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::transform(const BOOST_REGEX_CHAR_T* p1, const BOOST_REGEX_CHAR_T* p2) const;
template BOOST_REGEX_DECL
cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::string_type
   cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::lookup_collatename(const BOOST_REGEX_CHAR_T* p1, const BOOST_REGEX_CHAR_T* p2) const;
template BOOST_REGEX_DECL
void cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::init();
template BOOST_REGEX_DECL
cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::char_class_type
   cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::lookup_classname_imp(const BOOST_REGEX_CHAR_T* p1, const BOOST_REGEX_CHAR_T* p2) const;
#ifdef BOOST_REGEX_BUGGY_CTYPE_FACET
template BOOST_REGEX_DECL
bool cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::isctype(const BOOST_REGEX_CHAR_T c, char_class_type mask) const;
#endif
} // namespace
template BOOST_REGEX_DECL
int cpp_regex_traits<BOOST_REGEX_CHAR_T>::toi(const BOOST_REGEX_CHAR_T*& first, const BOOST_REGEX_CHAR_T* last, int radix)const;
template BOOST_REGEX_DECL
std::string cpp_regex_traits<BOOST_REGEX_CHAR_T>::catalog_name(const std::string& name);
template BOOST_REGEX_DECL
std::string& cpp_regex_traits<BOOST_REGEX_CHAR_T>::get_catalog_name_inst();
template BOOST_REGEX_DECL
std::string cpp_regex_traits<BOOST_REGEX_CHAR_T>::get_catalog_name();
#ifdef BOOST_HAS_THREADS
template BOOST_REGEX_DECL
static_mutex& cpp_regex_traits<BOOST_REGEX_CHAR_T>::get_mutex_inst();
#endif
#endif

template BOOST_REGEX_DECL basic_regex<BOOST_REGEX_CHAR_T BOOST_REGEX_TRAITS_T >&
   basic_regex<BOOST_REGEX_CHAR_T BOOST_REGEX_TRAITS_T >::do_assign(
      const BOOST_REGEX_CHAR_T* p1,
      const BOOST_REGEX_CHAR_T* p2,
      flag_type f);
template BOOST_REGEX_DECL basic_regex<BOOST_REGEX_CHAR_T BOOST_REGEX_TRAITS_T >::locale_type BOOST_REGEX_CALL
   basic_regex<BOOST_REGEX_CHAR_T BOOST_REGEX_TRAITS_T >::imbue(locale_type l);

template BOOST_REGEX_DECL void BOOST_REGEX_CALL
   match_results<const BOOST_REGEX_CHAR_T*>::maybe_assign(
      const match_results<const BOOST_REGEX_CHAR_T*>& m);

namespace BOOST_REGEX_DETAIL_NS{
template BOOST_REGEX_DECL void perl_matcher<BOOST_REGEX_CHAR_T const *, match_results< const BOOST_REGEX_CHAR_T* >::allocator_type BOOST_REGEX_TRAITS_T >::construct_init(
      const basic_regex<BOOST_REGEX_CHAR_T BOOST_REGEX_TRAITS_T >& e, match_flag_type f);
template BOOST_REGEX_DECL bool perl_matcher<BOOST_REGEX_CHAR_T const *, match_results< const BOOST_REGEX_CHAR_T* >::allocator_type BOOST_REGEX_TRAITS_T >::match();
template BOOST_REGEX_DECL bool perl_matcher<BOOST_REGEX_CHAR_T const *, match_results< const BOOST_REGEX_CHAR_T* >::allocator_type BOOST_REGEX_TRAITS_T >::find();
} // namespace

#if (defined(__GLIBCPP__) || defined(__GLIBCXX__)) \
   && !defined(BOOST_REGEX_ICU_INSTANCES)\
   && !defined(__SGI_STL_PORT)\
   && !defined(_STLPORT_VERSION)
// std:basic_string<>::const_iterator instances as well:
template BOOST_REGEX_DECL void BOOST_REGEX_CALL
   match_results<std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator>::maybe_assign(
      const match_results<std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator>& m);

namespace BOOST_REGEX_DETAIL_NS{
template BOOST_REGEX_DECL void perl_matcher<std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator, match_results< std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator >::allocator_type, boost::regex_traits<BOOST_REGEX_CHAR_T > >::construct_init(
      const basic_regex<BOOST_REGEX_CHAR_T>& e, match_flag_type f);
template BOOST_REGEX_DECL bool perl_matcher<std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator, match_results< std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator >::allocator_type, boost::regex_traits<BOOST_REGEX_CHAR_T > >::match();
template BOOST_REGEX_DECL bool perl_matcher<std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator, match_results< std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator >::allocator_type, boost::regex_traits<BOOST_REGEX_CHAR_T > >::find();
} // namespace
#endif

#  ifdef template
#     undef template
#  endif

#ifdef __clang__
#pragma clang diagnostic pop
#endif
#endif

} // namespace boost

#endif // BOOST_REGEX_NO_EXTERNAL_TEMPLATES

<|endoftext|>