<commit_before>
#include "cmath" // For isnan(), when it's defined

#include "diff_system.h"
#include "equation_systems.h"
#include "libmesh_logging.h"
#include "linear_solver.h"
#include "newton_solver.h"
#include "numeric_vector.h"
#include "sparse_matrix.h"
#include "dof_map.h"

NewtonSolver::NewtonSolver (sys_type& s)
  : Parent(s),
    require_residual_reduction(true),
    minsteplength(1e-5),
    linear_tolerance_multiplier(1e-3),
    linear_solver(LinearSolver<Number>::build())
{
}

NewtonSolver::~NewtonSolver ()
{
}

void NewtonSolver::reinit()
{
  Parent::reinit();

  linear_solver->clear();
}

void NewtonSolver::solve()
{
  START_LOG("solve()", "NewtonSolver");

  NumericVector<Number> &solution = *(_system.solution);
  NumericVector<Number> &newton_iterate =
    _system.get_vector("_nonlinear_solution");
  newton_iterate.close();
  solution.close();

  solution = newton_iterate;
  _system.get_dof_map().enforce_constraints_exactly(_system);
  newton_iterate = solution;

  NumericVector<Number> &rhs = *(_system.rhs);

  SparseMatrix<Number> &matrix = *(_system.matrix);

  // Prepare to take incomplete steps
  Real last_residual=0.;

  // Set starting linear tolerance
  Real current_linear_tolerance = initial_linear_tolerance;

  // Now we begin the nonlinear loop
  for (unsigned int l=0; l<max_nonlinear_iterations; ++l)
    {
      if (!quiet)
        std::cout << "Assembling System" << std::endl;

      PAUSE_LOG("solve()", "NewtonSolver");
      _system.assembly(true, true);
      RESTART_LOG("solve()", "NewtonSolver");
      rhs.close();
      Real current_residual = rhs.l2_norm();
      last_residual = current_residual;

// isnan() isn't standard C++ yet
#ifdef isnan
      if (isnan(current_residual))
        {
          std::cout << "  Nonlinear solver DIVERGED at step " << l
                    << " with norm Not-a-Number"
                    << std::endl;
          error();
          continue;
        }
#endif // isnan

      max_residual_norm = std::max (current_residual,
                                    max_residual_norm);

      // Compute the l2 norm of the whole solution
      Real norm_total = newton_iterate.l2_norm();

      max_solution_norm = std::max(max_solution_norm, norm_total);

      if (!quiet)
        std::cout << "Nonlinear Residual: "
                  << current_residual << std::endl;

      // Make sure our linear tolerance is low enough
      current_linear_tolerance = std::min (current_linear_tolerance,
        current_residual * linear_tolerance_multiplier);

      // But don't let it be zero
      if (current_linear_tolerance == 0.)
        {
          current_linear_tolerance = TOLERANCE * TOLERANCE;
        }

      // At this point newton_iterate is the current guess, and
      // solution is now about to become the NEGATIVE of the next
      // Newton step.

      // Our best initial guess for the solution is zero!
      solution.zero();

      if (!quiet)
        std::cout << "Linear solve starting" << std::endl;

      PAUSE_LOG("solve()", "NewtonSolver");
      // Solve the linear system.  Two cases:
      const std::pair<unsigned int, Real> rval =
        (_system.have_matrix("Preconditioner")) ?
      // 1.) User-supplied preconditioner
        linear_solver->solve (matrix, _system.get_matrix("Preconditioner"),
                              solution, rhs, current_linear_tolerance,
                              max_linear_iterations) :
      // 2.) Use system matrix for the preconditioner
        linear_solver->solve (matrix, solution, rhs,
                              current_linear_tolerance,
                              max_linear_iterations);
      // We may need to localize a parallel solution
      _system.update ();
      RESTART_LOG("solve()", "NewtonSolver");
      // The linear solver may not have fit our constraints exactly
      _system.get_dof_map().enforce_constraints_exactly(_system);

      const unsigned int linear_steps = rval.first;
      assert(linear_steps <= max_linear_iterations);
      const bool linear_solve_finished =
        !(linear_steps == max_linear_iterations);

      if (!quiet)
        std::cout << "Linear solve finished, step " << linear_steps
                  << ", residual " << rval.second
                  << ", tolerance " << current_linear_tolerance
                  << std::endl;

      // Compute the l2 norm of the nonlinear update
      Real norm_delta = solution.l2_norm();

      if (!quiet)
        std::cout << "Trying full Newton step" << std::endl;
      // Take a full Newton step
      newton_iterate.add (-1., solution);
      newton_iterate.close();

      // Check residual with full Newton step
      Real steplength = 1.;
      PAUSE_LOG("solve()", "NewtonSolver");
      _system.assembly(true, false);
      RESTART_LOG("solve()", "NewtonSolver");

      rhs.close();
      current_residual = rhs.l2_norm();

      // backtrack if necessary
      if (require_residual_reduction)
        {
          // but don't fiddle around if we've already converged
          if (test_convergence(current_residual, norm_delta,
                               linear_solve_finished))
            {
              if (!quiet)
		print_convergence(l, current_residual, norm_delta,
                                  linear_solve_finished);
              break;
            }

          while (current_residual > last_residual)
            {
              // Reduce step size to 1/2, 1/4, etc.
              steplength /= 2.;
              norm_delta /= 2.;
              if (!quiet)
                std::cout << "Shrinking Newton step to "
                          << steplength << std::endl;
              newton_iterate.add (steplength, solution);
              newton_iterate.close();

              // Check residual with fractional Newton step
              PAUSE_LOG("solve()", "NewtonSolver");
              _system.assembly (true, false);
              RESTART_LOG("solve()", "NewtonSolver");

              rhs.close();
              current_residual = rhs.l2_norm();
              if (!quiet)
                std::cout << "Current Residual: "
                          << current_residual << std::endl;

              if (steplength/2. < minsteplength &&
                  current_residual > last_residual)
                {
                  std::cout << "Inexact Newton step FAILED at step "
                            << l << std::endl;

                  error();
                }
            }
        }

      // Compute the l2 norm of the whole solution
      norm_total = newton_iterate.l2_norm();

      max_solution_norm = std::max(max_solution_norm, norm_total);

      // Print out information for the
      // nonlinear iterations.
      if (!quiet)
        std::cout << "  Nonlinear step: |du|/|u| = "
                  << norm_delta / norm_total
                  << ", |du| = " << norm_delta
                  << std::endl;

      // Terminate the solution iteration if the difference between
      // this iteration and the last is sufficiently small.
      if (!quiet)
        print_convergence(l, current_residual,
                          norm_delta / steplength,
                          linear_solve_finished);
      if (test_convergence(current_residual, norm_delta / steplength,
                           linear_solve_finished))
        {
          break;
        }
      if (l >= max_nonlinear_iterations - 1)
        {
          std::cout << "  Nonlinear solver FAILED TO CONVERGE by step " << l
                    << " with norm " << norm_total
                    << std::endl;
          error();
          continue;
        }
    } // end nonlinear loop

  // Copy the final nonlinear iterate into the current_solution,
  // for other libMesh functions that expect it

  solution = newton_iterate;
//  solution.close();

  // The linear solver may not have fit our constraints exactly
  _system.get_dof_map().enforce_constraints_exactly(_system);
  newton_iterate = solution;

  // We may need to localize a parallel solution
  _system.update ();

  STOP_LOG("solve()", "NewtonSolver");
}

bool NewtonSolver::test_convergence(Real current_residual,
                                    Real step_norm,
                                    bool linear_solve_finished)
{
  // We haven't converged unless we pass a convergence test
  bool has_converged = false;

  // Is our absolute residual low enough?
  if (current_residual < absolute_residual_tolerance)
    has_converged = true;

  // Is our relative residual low enough?
  if ((current_residual / max_residual_norm) <
      relative_residual_tolerance)
    has_converged = true;

  // For incomplete linear solves, it's not safe to test step sizes
  if (!linear_solve_finished)
    return has_converged;

  // Is our absolute Newton step size small enough?
  if (step_norm < absolute_step_tolerance)
    has_converged = true;

  // Is our relative Newton step size small enough?
  if (step_norm / max_solution_norm <
      relative_step_tolerance)
    has_converged = true;

  return has_converged;
}

void NewtonSolver::print_convergence(unsigned int step_num,
                                     Real current_residual,
                                     Real step_norm,
                                     bool linear_solve_finished)
{
  // Is our absolute residual low enough?
  if (current_residual < absolute_residual_tolerance)
    {
      std::cout << "  Nonlinear solver converged, step " << step_num
                << ", residual " << current_residual
                << std::endl;
    }
  else if (absolute_residual_tolerance)
    {
      std::cout << "  Nonlinear solver current_residual "
                << current_residual << " > "
                << (absolute_residual_tolerance) << std::endl;
    }

  // Is our relative residual low enough?
  if ((current_residual / max_residual_norm) <
      relative_residual_tolerance)
    {
      std::cout << "  Nonlinear solver converged, step " << step_num
                << ", residual reduction "
                << current_residual / max_residual_norm
                << " < " << relative_residual_tolerance
                << std::endl;
    }
  else if (relative_residual_tolerance)
    {
      if (!quiet)
        std::cout << "  Nonlinear solver relative residual "
                  << (current_residual / max_residual_norm)
                  << " > " << relative_residual_tolerance
                  << std::endl;
    }

  // For incomplete linear solves, it's not safe to test step sizes
  if (!linear_solve_finished)
    return;

  // Is our absolute Newton step size small enough?
  if (step_norm < absolute_step_tolerance)
    {
      std::cout << "  Nonlinear solver converged, step " << step_num
                << ", absolute step size "
                << step_norm
                << " < " << absolute_step_tolerance
                << std::endl;
    }
  else if (absolute_step_tolerance)
    {
      std::cout << "  Nonlinear solver absolute step size "
                << step_norm
                << " > " << absolute_step_tolerance
                << std::endl;
    }

  // Is our relative Newton step size small enough?
  if (step_norm / max_solution_norm <
      relative_step_tolerance)
    {
      std::cout << "  Nonlinear solver converged, step " << step_num
                << ", relative step size "
                << (step_norm / max_solution_norm)
                << " < " << relative_step_tolerance
                << std::endl;
    }
  else if (relative_step_tolerance)
    {
      std::cout << "  Nonlinear solver relative step size "
                << (step_norm / max_solution_norm)
                << " > " << relative_step_tolerance
                << std::endl;
    }
}
<commit_msg>More paranoia in parallel<commit_after>
#include "cmath" // For isnan(), when it's defined

#include "diff_system.h"
#include "equation_systems.h"
#include "libmesh_logging.h"
#include "linear_solver.h"
#include "newton_solver.h"
#include "numeric_vector.h"
#include "sparse_matrix.h"
#include "dof_map.h"

NewtonSolver::NewtonSolver (sys_type& s)
  : Parent(s),
    require_residual_reduction(true),
    minsteplength(1e-5),
    linear_tolerance_multiplier(1e-3),
    linear_solver(LinearSolver<Number>::build())
{
}

NewtonSolver::~NewtonSolver ()
{
}

void NewtonSolver::reinit()
{
  Parent::reinit();

  linear_solver->clear();
}

void NewtonSolver::solve()
{
  START_LOG("solve()", "NewtonSolver");

  NumericVector<Number> &solution = *(_system.solution);
  NumericVector<Number> &newton_iterate =
    _system.get_vector("_nonlinear_solution");
  newton_iterate.close();
  solution.close();

  solution = newton_iterate;
  _system.get_dof_map().enforce_constraints_exactly(_system);
  newton_iterate = solution;

  NumericVector<Number> &rhs = *(_system.rhs);

  SparseMatrix<Number> &matrix = *(_system.matrix);

  // Prepare to take incomplete steps
  Real last_residual=0.;

  // Set starting linear tolerance
  Real current_linear_tolerance = initial_linear_tolerance;

  // Now we begin the nonlinear loop
  for (unsigned int l=0; l<max_nonlinear_iterations; ++l)
    {
      if (!quiet)
        std::cout << "Assembling System" << std::endl;

      PAUSE_LOG("solve()", "NewtonSolver");
      _system.assembly(true, true);
      RESTART_LOG("solve()", "NewtonSolver");
      rhs.close();
      Real current_residual = rhs.l2_norm();
      last_residual = current_residual;

// isnan() isn't standard C++ yet
#ifdef isnan
      if (isnan(current_residual))
        {
          std::cout << "  Nonlinear solver DIVERGED at step " << l
                    << " with norm Not-a-Number"
                    << std::endl;
          error();
          continue;
        }
#endif // isnan

      max_residual_norm = std::max (current_residual,
                                    max_residual_norm);

      // Compute the l2 norm of the whole solution
      Real norm_total = newton_iterate.l2_norm();

      max_solution_norm = std::max(max_solution_norm, norm_total);

      if (!quiet)
        std::cout << "Nonlinear Residual: "
                  << current_residual << std::endl;

      // Make sure our linear tolerance is low enough
      current_linear_tolerance = std::min (current_linear_tolerance,
        current_residual * linear_tolerance_multiplier);

      // But don't let it be zero
      if (current_linear_tolerance == 0.)
        {
          current_linear_tolerance = TOLERANCE * TOLERANCE;
        }

      // At this point newton_iterate is the current guess, and
      // solution is now about to become the NEGATIVE of the next
      // Newton step.

      // Our best initial guess for the solution is zero!
      solution.zero();

      if (!quiet)
        std::cout << "Linear solve starting" << std::endl;

      PAUSE_LOG("solve()", "NewtonSolver");
      // Solve the linear system.  Two cases:
      const std::pair<unsigned int, Real> rval =
        (_system.have_matrix("Preconditioner")) ?
      // 1.) User-supplied preconditioner
        linear_solver->solve (matrix, _system.get_matrix("Preconditioner"),
                              solution, rhs, current_linear_tolerance,
                              max_linear_iterations) :
      // 2.) Use system matrix for the preconditioner
        linear_solver->solve (matrix, solution, rhs,
                              current_linear_tolerance,
                              max_linear_iterations);
      // We may need to localize a parallel solution
      _system.update ();
      RESTART_LOG("solve()", "NewtonSolver");
      // The linear solver may not have fit our constraints exactly
      _system.get_dof_map().enforce_constraints_exactly(_system);

      const unsigned int linear_steps = rval.first;
      assert(linear_steps <= max_linear_iterations);
      const bool linear_solve_finished =
        !(linear_steps == max_linear_iterations);

      if (!quiet)
        std::cout << "Linear solve finished, step " << linear_steps
                  << ", residual " << rval.second
                  << ", tolerance " << current_linear_tolerance
                  << std::endl;

      // Compute the l2 norm of the nonlinear update
      Real norm_delta = solution.l2_norm();

      if (!quiet)
        std::cout << "Trying full Newton step" << std::endl;
      // Take a full Newton step
      newton_iterate.add (-1., solution);
      newton_iterate.close();

      // Check residual with full Newton step
      Real steplength = 1.;
      PAUSE_LOG("solve()", "NewtonSolver");
      _system.assembly(true, false);
      RESTART_LOG("solve()", "NewtonSolver");

      rhs.close();
      current_residual = rhs.l2_norm();

      // backtrack if necessary
      if (require_residual_reduction)
        {
          // but don't fiddle around if we've already converged
          if (test_convergence(current_residual, norm_delta,
                               linear_solve_finished))
            {
              if (!quiet)
		print_convergence(l, current_residual, norm_delta,
                                  linear_solve_finished);
              break;
            }

          while (current_residual > last_residual)
            {
              // Reduce step size to 1/2, 1/4, etc.
              steplength /= 2.;
              norm_delta /= 2.;
              if (!quiet)
                std::cout << "Shrinking Newton step to "
                          << steplength << std::endl;
              newton_iterate.add (steplength, solution);
              newton_iterate.close();

              // Check residual with fractional Newton step
              PAUSE_LOG("solve()", "NewtonSolver");
              _system.assembly (true, false);
              RESTART_LOG("solve()", "NewtonSolver");

              rhs.close();
              current_residual = rhs.l2_norm();
              if (!quiet)
                std::cout << "Current Residual: "
                          << current_residual << std::endl;

              if (steplength/2. < minsteplength &&
                  current_residual > last_residual)
                {
                  std::cout << "Inexact Newton step FAILED at step "
                            << l << std::endl;

                  error();
                }
            }
        }

      // Compute the l2 norm of the whole solution
      norm_total = newton_iterate.l2_norm();

      max_solution_norm = std::max(max_solution_norm, norm_total);

      // Print out information for the
      // nonlinear iterations.
      if (!quiet)
        std::cout << "  Nonlinear step: |du|/|u| = "
                  << norm_delta / norm_total
                  << ", |du| = " << norm_delta
                  << std::endl;

      // Terminate the solution iteration if the difference between
      // this iteration and the last is sufficiently small.
      if (!quiet)
        print_convergence(l, current_residual,
                          norm_delta / steplength,
                          linear_solve_finished);
      if (test_convergence(current_residual, norm_delta / steplength,
                           linear_solve_finished))
        {
          break;
        }
      if (l >= max_nonlinear_iterations - 1)
        {
          std::cout << "  Nonlinear solver FAILED TO CONVERGE by step " << l
                    << " with norm " << norm_total
                    << std::endl;
          error();
          continue;
        }
    } // end nonlinear loop

  // Copy the final nonlinear iterate into the current_solution,
  // for other libMesh functions that expect it

  solution = newton_iterate;
  solution.close();

  // The linear solver may not have fit our constraints exactly
  _system.get_dof_map().enforce_constraints_exactly(_system);
  newton_iterate = solution;
  solution.close();

  // We may need to localize a parallel solution
  _system.update ();

  STOP_LOG("solve()", "NewtonSolver");
}

bool NewtonSolver::test_convergence(Real current_residual,
                                    Real step_norm,
                                    bool linear_solve_finished)
{
  // We haven't converged unless we pass a convergence test
  bool has_converged = false;

  // Is our absolute residual low enough?
  if (current_residual < absolute_residual_tolerance)
    has_converged = true;

  // Is our relative residual low enough?
  if ((current_residual / max_residual_norm) <
      relative_residual_tolerance)
    has_converged = true;

  // For incomplete linear solves, it's not safe to test step sizes
  if (!linear_solve_finished)
    return has_converged;

  // Is our absolute Newton step size small enough?
  if (step_norm < absolute_step_tolerance)
    has_converged = true;

  // Is our relative Newton step size small enough?
  if (step_norm / max_solution_norm <
      relative_step_tolerance)
    has_converged = true;

  return has_converged;
}

void NewtonSolver::print_convergence(unsigned int step_num,
                                     Real current_residual,
                                     Real step_norm,
                                     bool linear_solve_finished)
{
  // Is our absolute residual low enough?
  if (current_residual < absolute_residual_tolerance)
    {
      std::cout << "  Nonlinear solver converged, step " << step_num
                << ", residual " << current_residual
                << std::endl;
    }
  else if (absolute_residual_tolerance)
    {
      std::cout << "  Nonlinear solver current_residual "
                << current_residual << " > "
                << (absolute_residual_tolerance) << std::endl;
    }

  // Is our relative residual low enough?
  if ((current_residual / max_residual_norm) <
      relative_residual_tolerance)
    {
      std::cout << "  Nonlinear solver converged, step " << step_num
                << ", residual reduction "
                << current_residual / max_residual_norm
                << " < " << relative_residual_tolerance
                << std::endl;
    }
  else if (relative_residual_tolerance)
    {
      if (!quiet)
        std::cout << "  Nonlinear solver relative residual "
                  << (current_residual / max_residual_norm)
                  << " > " << relative_residual_tolerance
                  << std::endl;
    }

  // For incomplete linear solves, it's not safe to test step sizes
  if (!linear_solve_finished)
    return;

  // Is our absolute Newton step size small enough?
  if (step_norm < absolute_step_tolerance)
    {
      std::cout << "  Nonlinear solver converged, step " << step_num
                << ", absolute step size "
                << step_norm
                << " < " << absolute_step_tolerance
                << std::endl;
    }
  else if (absolute_step_tolerance)
    {
      std::cout << "  Nonlinear solver absolute step size "
                << step_norm
                << " > " << absolute_step_tolerance
                << std::endl;
    }

  // Is our relative Newton step size small enough?
  if (step_norm / max_solution_norm <
      relative_step_tolerance)
    {
      std::cout << "  Nonlinear solver converged, step " << step_num
                << ", relative step size "
                << (step_norm / max_solution_norm)
                << " < " << relative_step_tolerance
                << std::endl;
    }
  else if (relative_step_tolerance)
    {
      std::cout << "  Nonlinear solver relative step size "
                << (step_norm / max_solution_norm)
                << " > " << relative_step_tolerance
                << std::endl;
    }
}
<|endoftext|>


<commit_before>/*
 * test_RepresentationTransformation.cpp
 *
 *  Created on: Nov 25, 2015
 *      Author: sni
 */

#include <memory>
#include <ros/package.h>

#include "ice/representation/Representation.h"
#include "ice/representation/GContainer.h"
#include "ice/representation/GContainerFactory.h"
#include "ice/representation/Transformation.h"
#include "ice/representation/XMLTransformationReader.h"

#include "ice/ICEngine.h"

#include "gtest/gtest.h"

namespace
{

TEST(RepresentationTransformationTest, useOperation)
{
  std::shared_ptr<ice::GContainerFactory> factory = std::make_shared<ice::GContainerFactory>();

  std::unique_ptr<std::vector<std::string>> lines(new std::vector<std::string>);
  lines->push_back("testRep1;dim1;doubleRep");
  lines->push_back("testRep1;dim2;integerRep");
  lines->push_back("|");
  lines->push_back("testRep2;dim1;integerRep");
  lines->push_back("testRep2;dim2;doubleRep");

  factory->fromCSVStrings(std::move(lines));

  auto rep1 = factory->getRepresentation("testRep1");
  auto rep2 = factory->getRepresentation("testRep2");

  auto dim11 = rep1->accessPath( {"dim1"});
  auto dim12 = rep1->accessPath( {"dim2"});
  auto dim21 = rep2->accessPath( {"dim1"});
  auto dim22 = rep2->accessPath( {"dim2"});

  const double testValDouble = 4.2f;
  const int testValInt = 358735;

  auto rep1Ind = factory->makeInstance(rep1);
  rep1Ind->set(dim11, &testValDouble);
  rep1Ind->set(dim12, &testValInt);

  EXPECT_EQ(testValDouble, *((double* ) rep1Ind->get(dim11)));
  EXPECT_EQ(testValInt, *((int* ) rep1Ind->get(dim12)));

  ice::Transformation trans(factory, "TestTransformation", rep2);

  ice::TransformationOperation* o;
  o = new ice::TransformationOperation();
  o->sourceIndex = 0;
  o->sourceDimension = dim11;
//  o.valueType = ice::BasicRepresentationType::DOUBLE;
//  o.value = ;
  o->type = ice::TransformationOperationType::USE;
  o->targetDimension = dim22;
  trans.getOperations().push_back(o);

  o = new ice::TransformationOperation();
  o->sourceIndex = 0;
  o->sourceDimension = dim12;
//  o.valueType = ice::BasicRepresentationType::DOUBLE;
//  o.value = ;
  o->type = ice::TransformationOperationType::USE;
  o->targetDimension = dim21;
  trans.getOperations().push_back(o);

  auto rep2Ind = trans.transform(&rep1Ind);

  EXPECT_EQ(testValDouble, rep2Ind->getValue<double>(dim22));
  EXPECT_EQ(testValInt, rep2Ind->getValue<int>(dim21));

//  rep1Ind->print();
//  std::cout << "----------------------------------------------" << std::endl;
//  rep2Ind->print();
}

TEST(RepresentationTransformationTest, defaultOperation)
{
  std::shared_ptr<ice::GContainerFactory> factory = std::make_shared<ice::GContainerFactory>();

  std::unique_ptr<std::vector<std::string>> lines(new std::vector<std::string>);
  lines->push_back("testRep1;dim1;doubleRep");
  lines->push_back("testRep1;dim2;integerRep");
  lines->push_back("|");
  lines->push_back("testRep2;dim1;integerRep");
  lines->push_back("testRep2;dim2;doubleRep");

  factory->fromCSVStrings(std::move(lines));

  auto rep1 = factory->getRepresentation("testRep1");
  auto rep2 = factory->getRepresentation("testRep2");

  auto dim11 = rep1->accessPath( {"dim1"});
  auto dim12 = rep1->accessPath( {"dim2"});
  auto dim21 = rep2->accessPath( {"dim1"});
  auto dim22 = rep2->accessPath( {"dim2"});

  const double testValDouble = 4.2f;
  const int testValInt = 358735;

  auto rep1Ind = factory->makeInstance(rep1);
  rep1Ind->set(dim11, &testValDouble);
  rep1Ind->set(dim12, &testValInt);

  EXPECT_EQ(testValDouble, *((double* ) rep1Ind->get(dim11)));
  EXPECT_EQ(testValInt, *((int* ) rep1Ind->get(dim12)));

  ice::Transformation trans(factory, "TestTransformation", rep2);

  ice::TransformationOperation* o;
  o = new ice::TransformationOperation();
  o->sourceIndex = 0;
  o->sourceDimension = rep1->accessPath( {"dim1"});
//  o.valueType = ice::BasicRepresentationType::DOUBLE;
//  o.value = ;
  o->type = ice::TransformationOperationType::USE;
  o->targetDimension = rep2->accessPath( {"dim2"});
  trans.getOperations().push_back(o);

  o = new ice::TransformationOperation();
//  o.sourceIndex = 0;
//  o.sourceDimension = rep1->accessPath({"dim2"});
  o->valueType = ice::BasicRepresentationType::INT;
  o->value = new int(0);
  o->type = ice::TransformationOperationType::DEFAULT;
  o->targetDimension = rep2->accessPath( {"dim1"});
  trans.getOperations().push_back(o);

  auto rep2Ind = trans.transform(&rep1Ind);

  EXPECT_EQ(testValDouble, rep2Ind->getValue<double>(dim22));
  EXPECT_EQ(0, rep2Ind->getValue<int>(dim21));

//  rep1Ind->print();
//  std::cout << "----------------------------------------------" << std::endl;
//  rep2Ind->print();
}

TEST(RepresentationTransformationTest, xmlReader)
{
  std::string path = ros::package::getPath("ice");
  bool result;

  auto oi = std::make_shared<ice::OntologyInterface>(path + "/java/lib/");
  oi->addIRIMapper(path + "/ontology/");

  ASSERT_FALSE(oi->errorOccurred());

  result = oi->addOntologyIRI("http://vs.uni-kassel.de/IceTest");

  ASSERT_FALSE(oi->errorOccurred());
  ASSERT_TRUE(result);

  result = oi->loadOntologies();

  ASSERT_FALSE(oi->errorOccurred());
  ASSERT_TRUE(result);

  result = oi->isConsistent();

  ASSERT_FALSE(oi->errorOccurred());
  ASSERT_TRUE(result);

  std::shared_ptr<ice::GContainerFactory> factory = std::make_shared<ice::GContainerFactory>();
  factory->setOntologyInterface(oi);
  factory->init();

  ice::XMLTransformationReader reader;

  result = reader.readFile("data/transformation_example_1.xml");

  ASSERT_TRUE(result);

  auto p2dRep = factory->getRepresentation("o0_Pos2D");
  auto p3dRep = factory->getRepresentation("o0_Pos3D");
  auto p3dRotRep = factory->getRepresentation("o0_Pos3DRot");

  ASSERT_TRUE(p2dRep != false);
  ASSERT_TRUE(p3dRep != false);
  ASSERT_TRUE(p3dRotRep != false);

  auto p2dX = p2dRep->accessPath({"o2_XCoordinate"});
  auto p2dY = p2dRep->accessPath({"o2_YCoordinate"});

  auto p3dX = p3dRep->accessPath({"o2_XCoordinate"});
  auto p3dY = p3dRep->accessPath({"o2_YCoordinate"});
  auto p3dZ = p3dRep->accessPath({"o2_ZCoordinate"});

  auto p3dRotX = p3dRotRep->accessPath({"o2_XCoordinate"});
  auto p3dRotY = p3dRotRep->accessPath({"o2_YCoordinate"});
  auto p3dRotZ = p3dRotRep->accessPath({"o2_ZCoordinate"});
  auto p3dRotOri = p3dRotRep->accessPath({"o2_Orientation"});

  auto p3dRotOriA = p3dRotRep->accessPath({"o2_Orientation", "o2_Alpha"});
  auto p3dRotOriB = p3dRotRep->accessPath({"o2_Orientation", "o2_Beta"});
  auto p3dRotOriC = p3dRotRep->accessPath({"o2_Orientation", "o2_Gamma"});

  bool foundP2toP3 = false;
  bool foundP3toP2 = false;
  bool foundP3Rot = false;

  for (auto desc : reader.getTransformations())
  {
    auto trans = factory->fromXMLDesc(desc);

    ASSERT_TRUE(trans != false);

    if (trans->getName() == "P2Dto3D")
    {
      auto p2d = factory->makeInstance(p2dRep);

      double val1 = 3.5;
      double val2 = 35.5;

      p2d->set(p2dX, &val1);
      p2d->set(p2dY, &val2);

      auto p3d = trans->transform(&p2d);

      ASSERT_EQ(p3d->getValue<double>(p3dX), val1);
      ASSERT_EQ(p3d->getValue<double>(p3dY), val2);
      ASSERT_EQ(p3d->getValue<double>(p3dZ), 1.0);

      foundP2toP3 = true;
    }
    else if (trans->getName() == "P3Dto2D")
    {
      auto p3d = factory->makeInstance(p3dRep);

      double val1 = 3.5;
      double val2 = 35.5;
      double val3 = 315.5;

      p3d->set(p3dX, &val1);
      p3d->set(p3dY, &val2);
      p3d->set(p3dZ, &val3);

      auto p2d = trans->transform(&p3d);

      ASSERT_EQ(p2d->getValue<double>(p2dX), val1);
      ASSERT_EQ(p2d->getValue<double>(p2dY), val2);

      foundP3toP2 = true;
    }
    else if (trans->getName() == "TestComplex1")
    {
      auto p3dRo1 = factory->makeInstance(p3dRotRep);

      double val1 = 3.5;
      double val2 = 35.5;
      double val3 = 315.5;

      double vala = 13.5;
      double valb = 135.5;
      double valc = 1315.5;

      p3dRo1->set(p3dRotX, &val1);
      p3dRo1->set(p3dRotY, &val2);
      p3dRo1->set(p3dRotZ, &val3);

      p3dRo1->set(p3dRotOriA, &vala);
      p3dRo1->set(p3dRotOriB, &valb);
      p3dRo1->set(p3dRotOriC, &valc);

      auto p3dRo2 = trans->transform(&p3dRo1);

      ASSERT_EQ(p3dRo2->getValue<double>(p3dRotX), val1);
      ASSERT_EQ(p3dRo2->getValue<double>(p3dRotY), val2);
      ASSERT_EQ(p3dRo2->getValue<double>(p3dRotZ), val3);

      ASSERT_EQ(p3dRo2->getValue<double>(p3dRotOriA), vala);
      ASSERT_EQ(p3dRo2->getValue<double>(p3dRotOriB), valb);
      ASSERT_EQ(p3dRo2->getValue<double>(p3dRotOriC), valc);

      foundP3Rot = true;
    }
    else
    {
      ASSERT_FALSE(true);
    }
  }

  ASSERT_TRUE(foundP2toP3);
  ASSERT_TRUE(foundP3toP2);
  ASSERT_TRUE(foundP3Rot);
}

}

<commit_msg>Add formulaOperation test<commit_after>/*
 * test_RepresentationTransformation.cpp
 *
 *  Created on: Nov 25, 2015
 *      Author: sni
 */

#include <memory>
#include <ros/package.h>

#include "ice/representation/Representation.h"
#include "ice/representation/GContainer.h"
#include "ice/representation/GContainerFactory.h"
#include "ice/representation/Transformation.h"
#include "ice/representation/XMLTransformationReader.h"

#include "ice/ICEngine.h"

#include "gtest/gtest.h"

namespace
{

TEST(RepresentationTransformationTest, useOperation)
{
  std::shared_ptr<ice::GContainerFactory> factory = std::make_shared<ice::GContainerFactory>();

  std::unique_ptr<std::vector<std::string>> lines(new std::vector<std::string>);
  lines->push_back("testRep1;dim1;doubleRep");
  lines->push_back("testRep1;dim2;integerRep");
  lines->push_back("|");
  lines->push_back("testRep2;dim1;integerRep");
  lines->push_back("testRep2;dim2;doubleRep");

  factory->fromCSVStrings(std::move(lines));

  auto rep1 = factory->getRepresentation("testRep1");
  auto rep2 = factory->getRepresentation("testRep2");

  auto dim11 = rep1->accessPath( {"dim1"});
  auto dim12 = rep1->accessPath( {"dim2"});
  auto dim21 = rep2->accessPath( {"dim1"});
  auto dim22 = rep2->accessPath( {"dim2"});

  const double testValDouble = 4.2f;
  const int testValInt = 358735;

  auto rep1Ind = factory->makeInstance(rep1);
  rep1Ind->set(dim11, &testValDouble);
  rep1Ind->set(dim12, &testValInt);

  EXPECT_EQ(testValDouble, *((double* ) rep1Ind->get(dim11)));
  EXPECT_EQ(testValInt, *((int* ) rep1Ind->get(dim12)));

  ice::Transformation trans(factory, "TestTransformation", rep2);

  ice::TransformationOperation* o;
  o = new ice::TransformationOperation();
  o->sourceIndex = 0;
  o->sourceDimension = dim11;
//  o.valueType = ice::BasicRepresentationType::DOUBLE;
//  o.value = ;
  o->type = ice::TransformationOperationType::USE;
  o->targetDimension = dim22;
  trans.getOperations().push_back(o);

  o = new ice::TransformationOperation();
  o->sourceIndex = 0;
  o->sourceDimension = dim12;
//  o.valueType = ice::BasicRepresentationType::DOUBLE;
//  o.value = ;
  o->type = ice::TransformationOperationType::USE;
  o->targetDimension = dim21;
  trans.getOperations().push_back(o);

  auto rep2Ind = trans.transform(&rep1Ind);

  EXPECT_EQ(testValDouble, rep2Ind->getValue<double>(dim22));
  EXPECT_EQ(testValInt, rep2Ind->getValue<int>(dim21));

//  rep1Ind->print();
//  std::cout << "----------------------------------------------" << std::endl;
//  rep2Ind->print();
}

TEST(RepresentationTransformationTest, defaultOperation)
{
  std::shared_ptr<ice::GContainerFactory> factory = std::make_shared<ice::GContainerFactory>();

  std::unique_ptr<std::vector<std::string>> lines(new std::vector<std::string>);
  lines->push_back("testRep1;dim1;doubleRep");
  lines->push_back("testRep1;dim2;integerRep");
  lines->push_back("|");
  lines->push_back("testRep2;dim1;integerRep");
  lines->push_back("testRep2;dim2;doubleRep");

  factory->fromCSVStrings(std::move(lines));

  auto rep1 = factory->getRepresentation("testRep1");
  auto rep2 = factory->getRepresentation("testRep2");

  auto dim11 = rep1->accessPath( {"dim1"});
  auto dim12 = rep1->accessPath( {"dim2"});
  auto dim21 = rep2->accessPath( {"dim1"});
  auto dim22 = rep2->accessPath( {"dim2"});

  const double testValDouble = 4.2f;
  const int testValInt = 358735;

  auto rep1Ind = factory->makeInstance(rep1);
  rep1Ind->set(dim11, &testValDouble);
  rep1Ind->set(dim12, &testValInt);

  EXPECT_EQ(testValDouble, *((double* ) rep1Ind->get(dim11)));
  EXPECT_EQ(testValInt, *((int* ) rep1Ind->get(dim12)));

  ice::Transformation trans(factory, "TestTransformation", rep2);

  ice::TransformationOperation* o;
  o = new ice::TransformationOperation();
  o->sourceIndex = 0;
  o->sourceDimension = rep1->accessPath( {"dim1"});
//  o.valueType = ice::BasicRepresentationType::DOUBLE;
//  o.value = ;
  o->type = ice::TransformationOperationType::USE;
  o->targetDimension = rep2->accessPath( {"dim2"});
  trans.getOperations().push_back(o);

  o = new ice::TransformationOperation();
//  o.sourceIndex = 0;
//  o.sourceDimension = rep1->accessPath({"dim2"});
  o->valueType = ice::BasicRepresentationType::INT;
  o->value = new int(0);
  o->type = ice::TransformationOperationType::DEFAULT;
  o->targetDimension = rep2->accessPath( {"dim1"});
  trans.getOperations().push_back(o);

  auto rep2Ind = trans.transform(&rep1Ind);

  EXPECT_EQ(testValDouble, rep2Ind->getValue<double>(dim22));
  EXPECT_EQ(0, rep2Ind->getValue<int>(dim21));

//  rep1Ind->print();
//  std::cout << "----------------------------------------------" << std::endl;
//  rep2Ind->print();
}

TEST(RepresentationTransformationTest, formulaOperation)
{
  std::shared_ptr<ice::GContainerFactory> factory = std::make_shared<ice::GContainerFactory>();

  std::unique_ptr<std::vector<std::string>> lines(new std::vector<std::string>);
  lines->push_back("testRep1;dim1;doubleRep");
  lines->push_back("testRep1;dim2;integerRep");
  lines->push_back("|");
  lines->push_back("testRep2;dim1;integerRep");
  lines->push_back("testRep2;dim2;doubleRep");

  factory->fromCSVStrings(std::move(lines));

  auto rep1 = factory->getRepresentation("testRep1");
  auto rep2 = factory->getRepresentation("testRep2");

  auto dim11 = rep1->accessPath( {"dim1"});
  auto dim12 = rep1->accessPath( {"dim2"});
  auto dim21 = rep2->accessPath( {"dim1"});
  auto dim22 = rep2->accessPath( {"dim2"});

  const double testValDouble = 4.2f;
  const int testValInt = 8;

  auto rep1Ind = factory->makeInstance(rep1);

  rep1Ind->set(dim11, &testValDouble);
  rep1Ind->set(dim12, &testValInt);

  EXPECT_EQ(testValDouble, *((double* ) rep1Ind->get(dim11)));
  EXPECT_EQ(testValInt, *((int* ) rep1Ind->get(dim12)));

  ice::Transformation trans(factory, "TestSquaredTransformation", rep2);
  ice::TransformationOperation* o;

  o = new ice::TransformationOperation();
  o->sourceIndex = 0;
  o->sourceDimension = rep1->accessPath( {"dim1"});
  o->type = ice::TransformationOperationType::FORMULA;
  o->targetDimension = rep2->accessPath( {"dim1"});
  trans.getOperations().push_back(o);

  o = new ice::TransformationOperation();
  o->sourceIndex = 1;
  o->sourceDimension = rep1->accessPath( {"dim2"});
  o->type = ice::TransformationOperationType::FORMULA;
  o->targetDimension = rep2->accessPath( {"dim2"});
  trans.getOperations().push_back(o);

  auto rep2Ind = trans.transform(&rep1Ind);

  EXPECT_EQ(testValDouble*testValDouble, rep2Ind->getValue<double>(dim22));
  EXPECT_EQ(testValInt*testValInt, rep2Ind->getValue<int>(dim21));

}

TEST(RepresentationTransformationTest, xmlReader)
{
  std::string path = ros::package::getPath("ice");
  bool result;

  auto oi = std::make_shared<ice::OntologyInterface>(path + "/java/lib/");
  oi->addIRIMapper(path + "/ontology/");

  ASSERT_FALSE(oi->errorOccurred());

  result = oi->addOntologyIRI("http://vs.uni-kassel.de/IceTest");

  ASSERT_FALSE(oi->errorOccurred());
  ASSERT_TRUE(result);

  result = oi->loadOntologies();

  ASSERT_FALSE(oi->errorOccurred());
  ASSERT_TRUE(result);

  result = oi->isConsistent();

  ASSERT_FALSE(oi->errorOccurred());
  ASSERT_TRUE(result);

  std::shared_ptr<ice::GContainerFactory> factory = std::make_shared<ice::GContainerFactory>();
  factory->setOntologyInterface(oi);
  factory->init();

  ice::XMLTransformationReader reader;

  result = reader.readFile("data/transformation_example_1.xml");

  ASSERT_TRUE(result);

  auto p2dRep = factory->getRepresentation("o0_Pos2D");
  auto p3dRep = factory->getRepresentation("o0_Pos3D");
  auto p3dRotRep = factory->getRepresentation("o0_Pos3DRot");

  ASSERT_TRUE(p2dRep != false);
  ASSERT_TRUE(p3dRep != false);
  ASSERT_TRUE(p3dRotRep != false);

  auto p2dX = p2dRep->accessPath({"o2_XCoordinate"});
  auto p2dY = p2dRep->accessPath({"o2_YCoordinate"});

  auto p3dX = p3dRep->accessPath({"o2_XCoordinate"});
  auto p3dY = p3dRep->accessPath({"o2_YCoordinate"});
  auto p3dZ = p3dRep->accessPath({"o2_ZCoordinate"});

  auto p3dRotX = p3dRotRep->accessPath({"o2_XCoordinate"});
  auto p3dRotY = p3dRotRep->accessPath({"o2_YCoordinate"});
  auto p3dRotZ = p3dRotRep->accessPath({"o2_ZCoordinate"});
  auto p3dRotOri = p3dRotRep->accessPath({"o2_Orientation"});

  auto p3dRotOriA = p3dRotRep->accessPath({"o2_Orientation", "o2_Alpha"});
  auto p3dRotOriB = p3dRotRep->accessPath({"o2_Orientation", "o2_Beta"});
  auto p3dRotOriC = p3dRotRep->accessPath({"o2_Orientation", "o2_Gamma"});

  bool foundP2toP3 = false;
  bool foundP3toP2 = false;
  bool foundP3Rot = false;

  for (auto desc : reader.getTransformations())
  {
    auto trans = factory->fromXMLDesc(desc);

    ASSERT_TRUE(trans != false);

    if (trans->getName() == "P2Dto3D")
    {
      auto p2d = factory->makeInstance(p2dRep);

      double val1 = 3.5;
      double val2 = 35.5;

      p2d->set(p2dX, &val1);
      p2d->set(p2dY, &val2);

      auto p3d = trans->transform(&p2d);

      ASSERT_EQ(p3d->getValue<double>(p3dX), val1);
      ASSERT_EQ(p3d->getValue<double>(p3dY), val2);
      ASSERT_EQ(p3d->getValue<double>(p3dZ), 1.0);

      foundP2toP3 = true;
    }
    else if (trans->getName() == "P3Dto2D")
    {
      auto p3d = factory->makeInstance(p3dRep);

      double val1 = 3.5;
      double val2 = 35.5;
      double val3 = 315.5;

      p3d->set(p3dX, &val1);
      p3d->set(p3dY, &val2);
      p3d->set(p3dZ, &val3);

      auto p2d = trans->transform(&p3d);

      ASSERT_EQ(p2d->getValue<double>(p2dX), val1);
      ASSERT_EQ(p2d->getValue<double>(p2dY), val2);

      foundP3toP2 = true;
    }
    else if (trans->getName() == "TestComplex1")
    {
      auto p3dRo1 = factory->makeInstance(p3dRotRep);

      double val1 = 3.5;
      double val2 = 35.5;
      double val3 = 315.5;

      double vala = 13.5;
      double valb = 135.5;
      double valc = 1315.5;

      p3dRo1->set(p3dRotX, &val1);
      p3dRo1->set(p3dRotY, &val2);
      p3dRo1->set(p3dRotZ, &val3);

      p3dRo1->set(p3dRotOriA, &vala);
      p3dRo1->set(p3dRotOriB, &valb);
      p3dRo1->set(p3dRotOriC, &valc);

      auto p3dRo2 = trans->transform(&p3dRo1);

      ASSERT_EQ(p3dRo2->getValue<double>(p3dRotX), val1);
      ASSERT_EQ(p3dRo2->getValue<double>(p3dRotY), val2);
      ASSERT_EQ(p3dRo2->getValue<double>(p3dRotZ), val3);

      ASSERT_EQ(p3dRo2->getValue<double>(p3dRotOriA), vala);
      ASSERT_EQ(p3dRo2->getValue<double>(p3dRotOriB), valb);
      ASSERT_EQ(p3dRo2->getValue<double>(p3dRotOriC), valc);

      foundP3Rot = true;
    }
    else
    {
      ASSERT_FALSE(true);
    }
  }

  ASSERT_TRUE(foundP2toP3);
  ASSERT_TRUE(foundP3toP2);
  ASSERT_TRUE(foundP3Rot);
}

}

<|endoftext|>


<commit_before>#include "SyntaxTree.h"

#include <list>
#include <vector>
#include <sstream>
#include <iostream>
#include <stdexcept>
#include <assert.h>

#include <boost/format.hpp>

#include "parser.tab.hh"

#include "template.common.h"
#include "template.cs.h"

using namespace std;

// class Node
// {
// public:
    Node::~Node()
    {
    }

    int Node::getType() { return 0; } //TODO: remove getType() if unnecessary
    int Node::getHash(vector<Node*>* referencingStack) { return 0; }
    string* Node::getParsed(int as) { return 0; }

// };

// class NodeKst : public Node
// {
    // list<Node*>* commands;
    // string* fileName;
    // public:
    NodeKst::NodeKst(list<Node*>* _commands, string* _fileName) : Node()
    {
        commands = _commands;
        fileName = _fileName;
    }

    int NodeKst::getType()
    {
       return CsNodeType::kst;
    }

    int NodeKst::getHash(vector<Node*>* referencingStack)
    {
        return 0;
    }

    string* NodeKst::getParsed(int as)
    {
        stringstream parsed;

        parsed << boost::format(TCS_HEADER) % *fileName;
        parsed << TCS_USINGS;

        string namespaceByFileName = fileName->substr(0, fileName->find("."));

        parsed << boost::format(TCS_NAMESPACE_BEGIN) % namespaceByFileName;

        list<Node*>::iterator i = commands->begin();
        list<Node*>::iterator end = commands->end();

        string* temp;

        for (; i != end; ++i)
        {
            temp = (*i)->getParsed(CsParseAs::Default);
            temp = indent(temp);
            parsed << *temp;
            parsed << "\n";
        }

        parsed << TCS_NAMESPACE_END;

        parsed << "\n\n";

        return new string(parsed.str());
    }
// };

// class NodeInclude : public Node
// {
//     string* value;
//     public:
    NodeInclude::NodeInclude(string* _value) : Node()
    {
        value = _value;
    }

    int NodeInclude::getType()
    {
       return CsNodeType::include;
    }

    int NodeInclude::getHash(vector<Node*>* referencingStack)
    {
        return 0;
    }

    string* NodeInclude::getParsed(int as)
    {
        stringstream parsed;

        parsed << "#include \"";
        parsed << *(value);
        parsed << "\"";

        return new string(parsed.str());
    }
// };

// class NodePacket : public Node
// {
//     string* packetName;
//     list<Node*>* packetMembers;
//     public:
    NodePacket::NodePacket(string* _packetName, list<Node*>* _packetMembers) : Node()
    {
        packetName = _packetName;
        packetMembers = _packetMembers;
    }

    int NodePacket::getType()
    {
       return CsNodeType::packet;
    }

    int NodePacket::getHash(vector<Node*>* referencingStack)
    {
        if (referencingStack == NULL)
        {
            referencingStack = new vector<Node*>();
        }

        referencingStack->push_back(this);

        size_t packetHash = getHashCode(packetName);

        list<Node*>::iterator i = packetMembers->begin();
        list<Node*>::iterator end = packetMembers->end();
        for (; i != end; ++i)
        {
            combineHashCode(packetHash, (*i)->getHash(referencingStack));
        }

        return (int) packetHash;
    }

    string* NodePacket::getParsed(int as)
    {
        stringstream parsed;

        switch (as)
        {
            case CsParseAs::Default:
            {
                parsed << boost::format(TCS_PACKET_BEGIN) % *packetName;
                parsed << "\t<temp> packet hash: " << getHash(NULL) << "\n";
                list<Node*>::iterator i = packetMembers->begin();
                list<Node*>::iterator end = packetMembers->end();
                for (; i != end; ++i)
                {
                    parsed << "\t" << *((*i)->getParsed(CsParseAs::Default));
                }
                parsed << TCS_PACKET_END;
            }
            break;
        }

        return new string(parsed.str());
    }
// };

// class NodePacketMember : public Node
// {
//     Node* memberType;
//     Node* memberName;
//     public:
    NodePacketMember::NodePacketMember(Node* _memberType, Node* _memberName) : Node()
    {
        memberType = _memberType;
        memberName = _memberName;
    }

    int NodePacketMember::getType()
    {
       return CsNodeType::packetMember;
    }

    int NodePacketMember::getHash(vector<Node*>* referencingStack)
    {
        assert(referencingStack != NULL);

        size_t packetMemberHash = memberType->getHash(referencingStack);
        combineHashCode(packetMemberHash, memberName->getHash(referencingStack));

        return (int) packetMemberHash;
    }

    string* NodePacketMember::getParsed(int as)
    {
        stringstream parsed;

        switch (as)
        {
            case CsParseAs::Default:
            {
                parsed << boost::format(TCS_PACKET_MEMBER_AS_DEFAULT)
                    % *(memberType->getParsed(CsParseAs::Default))
                    % *(memberName->getParsed(CsParseAs::Default));
            }
            break;
        }

        return new string(parsed.str());
    }
// };

// class NodePacketMemberType : public Node
// {
//     int typeType; // one of PRIMITIVE_DATA_TYPE, REFERENCE_DATA_TYPE, MAP, LIST
//     string* value; // "int", "bool", ..., "MyPacket", "Skill" or NULL when type is MAP or LIST
//     Node* generic1; // LIST<generic1>
//     Node* generic2; // MAP <generic1, generic2>
//     Node* generic3; // reserved
//     public:
    NodePacketMemberType::NodePacketMemberType(int _type, string* _value) : Node()
    {
        typeType = _type;
        value = _value;
        generic1 = NULL;
        generic2 = NULL;
        generic3 = NULL;
    }

    NodePacketMemberType::NodePacketMemberType(int _type, Node* _generic1) : Node()
    {
        typeType = _type;
        value = NULL;
        generic1 = _generic1;
        generic2 = NULL;
        generic3 = NULL;
    }

    NodePacketMemberType::NodePacketMemberType(int _type, Node* _generic1, Node* _generic2) : Node()
    {
        typeType = _type;
        value = NULL;
        generic1 = _generic1;
        generic2 = _generic2;
        generic3 = NULL;
    }

    NodePacketMemberType::NodePacketMemberType(int _type, Node* _generic1, Node* _generic2, Node* _generic3) : Node()
    {
        typeType = _type;
        value = NULL;
        generic1 = _generic1;
        generic2 = _generic2;
        generic3 = _generic3;
    }

    int NodePacketMemberType::getType()
    {
       return CsNodeType::packetMemberType;
    }

    int NodePacketMemberType::getHash(vector<Node*>* referencingStack)
    {
        assert(referencingStack != NULL);

        size_t packetMemberTypeHash = 0;
        switch(typeType)
        {
            case Rakjin::Krystal::Parser::token::PRIMITIVE_DATA_TYPE:
            packetMemberTypeHash = getHashCode(value);
            break;
        }

        return (int) packetMemberTypeHash;
    }

    string* NodePacketMemberType::getParsed(int as)
    {
        stringstream parsed;

        switch (typeType) {

            case Rakjin::Krystal::Parser::token::PRIMITIVE_DATA_TYPE:
            parsed << *value;
            break;

            case Rakjin::Krystal::Parser::token::REFERENCE_DATA_TYPE:
            parsed << *value;
            break;

            case Rakjin::Krystal::Parser::token::MAP:
            parsed << "Dictionary";
            parsed << "<" << *(generic1->getParsed(CsParseAs::Default)) << ", " << *(generic2->getParsed(CsParseAs::Default)) << ">";
            break;

            case Rakjin::Krystal::Parser::token::LIST:
            parsed << "List";
            parsed << "<" << *(generic1->getParsed(CsParseAs::Default)) << ">";
            break;

            default:
            throw(runtime_error("Unknown NodePacketMemberType type."));
            break;
        }

        return new string(parsed.str());
    }
// };

// class NodePacketMemberName : public Node
// {
//     string* value;
//     public:
    NodePacketMemberName::NodePacketMemberName(string* _value) : Node()
    {
        value = _value;
    }

    int NodePacketMemberName::getType()
    {
       return CsNodeType::packetMemberName;
    }

    int NodePacketMemberName::getHash(vector<Node*>* referencingStack)
    {
        size_t packetMemberNameHash = getHashCode(value);
        return (int) packetMemberNameHash;
    }

    string* NodePacketMemberName::getParsed(int as)
    {
       return value;
    }
// };

<commit_msg>(trivial) using namespace<commit_after>#include "SyntaxTree.h"

#include <list>
#include <vector>
#include <sstream>
#include <iostream>
#include <stdexcept>
#include <assert.h>

#include <boost/format.hpp>

#include "parser.tab.hh"

#include "template.common.h"
#include "template.cs.h"

using namespace std;
using namespace Rakjin::Krystal;

// class Node
// {
// public:
    Node::~Node()
    {
    }

    int Node::getType() { return 0; } //TODO: remove getType() if unnecessary
    int Node::getHash(vector<Node*>* referencingStack) { return 0; }
    string* Node::getParsed(int as) { return 0; }

// };

// class NodeKst : public Node
// {
    // list<Node*>* commands;
    // string* fileName;
    // public:
    NodeKst::NodeKst(list<Node*>* _commands, string* _fileName) : Node()
    {
        commands = _commands;
        fileName = _fileName;
    }

    int NodeKst::getType()
    {
       return CsNodeType::kst;
    }

    int NodeKst::getHash(vector<Node*>* referencingStack)
    {
        return 0;
    }

    string* NodeKst::getParsed(int as)
    {
        stringstream parsed;

        parsed << boost::format(TCS_HEADER) % *fileName;
        parsed << TCS_USINGS;

        string namespaceByFileName = fileName->substr(0, fileName->find("."));

        parsed << boost::format(TCS_NAMESPACE_BEGIN) % namespaceByFileName;

        list<Node*>::iterator i = commands->begin();
        list<Node*>::iterator end = commands->end();

        string* temp;

        for (; i != end; ++i)
        {
            temp = (*i)->getParsed(CsParseAs::Default);
            temp = indent(temp);
            parsed << *temp;
            parsed << "\n";
        }

        parsed << TCS_NAMESPACE_END;

        parsed << "\n\n";

        return new string(parsed.str());
    }
// };

// class NodeInclude : public Node
// {
//     string* value;
//     public:
    NodeInclude::NodeInclude(string* _value) : Node()
    {
        value = _value;
    }

    int NodeInclude::getType()
    {
       return CsNodeType::include;
    }

    int NodeInclude::getHash(vector<Node*>* referencingStack)
    {
        return 0;
    }

    string* NodeInclude::getParsed(int as)
    {
        stringstream parsed;

        parsed << "#include \"";
        parsed << *(value);
        parsed << "\"";

        return new string(parsed.str());
    }
// };

// class NodePacket : public Node
// {
//     string* packetName;
//     list<Node*>* packetMembers;
//     public:
    NodePacket::NodePacket(string* _packetName, list<Node*>* _packetMembers) : Node()
    {
        packetName = _packetName;
        packetMembers = _packetMembers;
    }

    int NodePacket::getType()
    {
       return CsNodeType::packet;
    }

    int NodePacket::getHash(vector<Node*>* referencingStack)
    {
        if (referencingStack == NULL)
        {
            referencingStack = new vector<Node*>();
        }

        referencingStack->push_back(this);

        size_t packetHash = getHashCode(packetName);

        list<Node*>::iterator i = packetMembers->begin();
        list<Node*>::iterator end = packetMembers->end();
        for (; i != end; ++i)
        {
            combineHashCode(packetHash, (*i)->getHash(referencingStack));
        }

        return (int) packetHash;
    }

    string* NodePacket::getParsed(int as)
    {
        stringstream parsed;

        switch (as)
        {
            case CsParseAs::Default:
            {
                parsed << boost::format(TCS_PACKET_BEGIN) % *packetName;
                parsed << "\t<temp> packet hash: " << getHash(NULL) << "\n";
                list<Node*>::iterator i = packetMembers->begin();
                list<Node*>::iterator end = packetMembers->end();
                for (; i != end; ++i)
                {
                    parsed << "\t" << *((*i)->getParsed(CsParseAs::Default));
                }
                parsed << TCS_PACKET_END;
            }
            break;
        }

        return new string(parsed.str());
    }
// };

// class NodePacketMember : public Node
// {
//     Node* memberType;
//     Node* memberName;
//     public:
    NodePacketMember::NodePacketMember(Node* _memberType, Node* _memberName) : Node()
    {
        memberType = _memberType;
        memberName = _memberName;
    }

    int NodePacketMember::getType()
    {
       return CsNodeType::packetMember;
    }

    int NodePacketMember::getHash(vector<Node*>* referencingStack)
    {
        assert(referencingStack != NULL);

        size_t packetMemberHash = memberType->getHash(referencingStack);
        combineHashCode(packetMemberHash, memberName->getHash(referencingStack));

        return (int) packetMemberHash;
    }

    string* NodePacketMember::getParsed(int as)
    {
        stringstream parsed;

        switch (as)
        {
            case CsParseAs::Default:
            {
                parsed << boost::format(TCS_PACKET_MEMBER_AS_DEFAULT)
                    % *(memberType->getParsed(CsParseAs::Default))
                    % *(memberName->getParsed(CsParseAs::Default));
            }
            break;
        }

        return new string(parsed.str());
    }
// };

// class NodePacketMemberType : public Node
// {
//     int typeType; // one of PRIMITIVE_DATA_TYPE, REFERENCE_DATA_TYPE, MAP, LIST
//     string* value; // "int", "bool", ..., "MyPacket", "Skill" or NULL when type is MAP or LIST
//     Node* generic1; // LIST<generic1>
//     Node* generic2; // MAP <generic1, generic2>
//     Node* generic3; // reserved
//     public:
    NodePacketMemberType::NodePacketMemberType(int _type, string* _value) : Node()
    {
        typeType = _type;
        value = _value;
        generic1 = NULL;
        generic2 = NULL;
        generic3 = NULL;
    }

    NodePacketMemberType::NodePacketMemberType(int _type, Node* _generic1) : Node()
    {
        typeType = _type;
        value = NULL;
        generic1 = _generic1;
        generic2 = NULL;
        generic3 = NULL;
    }

    NodePacketMemberType::NodePacketMemberType(int _type, Node* _generic1, Node* _generic2) : Node()
    {
        typeType = _type;
        value = NULL;
        generic1 = _generic1;
        generic2 = _generic2;
        generic3 = NULL;
    }

    NodePacketMemberType::NodePacketMemberType(int _type, Node* _generic1, Node* _generic2, Node* _generic3) : Node()
    {
        typeType = _type;
        value = NULL;
        generic1 = _generic1;
        generic2 = _generic2;
        generic3 = _generic3;
    }

    int NodePacketMemberType::getType()
    {
       return CsNodeType::packetMemberType;
    }

    int NodePacketMemberType::getHash(vector<Node*>* referencingStack)
    {
        assert(referencingStack != NULL);

        size_t packetMemberTypeHash = 0;
        switch(typeType)
        {
            case Parser::token::PRIMITIVE_DATA_TYPE:
            packetMemberTypeHash = getHashCode(value);
            break;
        }

        return (int) packetMemberTypeHash;
    }

    string* NodePacketMemberType::getParsed(int as)
    {
        stringstream parsed;

        switch (typeType) {

            case Parser::token::PRIMITIVE_DATA_TYPE:
            parsed << *value;
            break;

            case Parser::token::REFERENCE_DATA_TYPE:
            parsed << *value;
            break;

            case Parser::token::MAP:
            parsed << "Dictionary";
            parsed << "<" << *(generic1->getParsed(CsParseAs::Default)) << ", " << *(generic2->getParsed(CsParseAs::Default)) << ">";
            break;

            case Parser::token::LIST:
            parsed << "List";
            parsed << "<" << *(generic1->getParsed(CsParseAs::Default)) << ">";
            break;

            default:
            throw(runtime_error("Unknown NodePacketMemberType type."));
            break;
        }

        return new string(parsed.str());
    }
// };

// class NodePacketMemberName : public Node
// {
//     string* value;
//     public:
    NodePacketMemberName::NodePacketMemberName(string* _value) : Node()
    {
        value = _value;
    }

    int NodePacketMemberName::getType()
    {
       return CsNodeType::packetMemberName;
    }

    int NodePacketMemberName::getHash(vector<Node*>* referencingStack)
    {
        size_t packetMemberNameHash = getHashCode(value);
        return (int) packetMemberNameHash;
    }

    string* NodePacketMemberName::getParsed(int as)
    {
       return value;
    }
// };

<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	I/O ユーティリティー @n
			Copyright 2013,2016 Kunihito Hiramatsu
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <cstdint>

namespace device {

	// RL78
	typedef uint32_t address_type;

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  ８ビット書き込み
		@param[in]	adr		書き込みアドレス
		@param[in]	data	書き込みデータ
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	static inline void wr8_(address_type adr, uint8_t data) {
		*reinterpret_cast<volatile uint8_t*>(adr) = data;
	}

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  ８ビット読み込み
		@param[in]	adr		読み込みアドレス
		@param[in]	data	読み込みデータ
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	static inline uint8_t rd8_(address_type adr) {
		return *reinterpret_cast<volatile uint8_t*>(adr);
	}

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  １６ビット書き込み
		@param[in]	adr		書き込みアドレス
		@param[in]	data	書き込みデータ
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	static inline void wr16_(address_type adr, uint16_t data) {
		*reinterpret_cast<volatile uint16_t*>(adr) = data;
	}

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  １６ビット読み込み
		@param[in]	adr		読み込みアドレス
		@param[in]	data	読み込みデータ
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	static inline uint16_t rd16_(address_type adr) {
		return *reinterpret_cast<volatile uint16_t*>(adr);
	}

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  ３２ビット書き込み
		@param[in]	adr		書き込みアドレス
		@param[in]	data	書き込みデータ
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	static inline void wr32_(address_type adr, uint32_t data) {
		*reinterpret_cast<volatile uint32_t*>(adr) = data;
	}

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  ３２ビット読み込み
		@param[in]	adr		読み込みアドレス
		@param[in]	data	読み込みデータ
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	static inline uint32_t rd32_(address_type adr) {
		return *reinterpret_cast<volatile uint32_t*>(adr);
	}

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  Read/Write 8 bits アクセス・テンプレート
		@param[in]	adr	アドレス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <address_type adr>
	struct rw8_t {
		typedef uint8_t value_type;

		//-----------------------------------------------------------------//
		/*!
			@brief  書き込み
			@param[in]	data	書き込み値
		*/
		//-----------------------------------------------------------------//
		static void write(value_type data) { wr8_(adr, data); }

		//-----------------------------------------------------------------//
		/*!
			@brief 読み出し
			@return 読み出し値
		*/
		//-----------------------------------------------------------------//
		static value_type read() { return rd8_(adr); }

		void operator = (value_type data) const { write(data); }
		value_type operator () () const { return read(); }
		void operator |= (value_type data) const { write(read() | data); }
		void operator &= (value_type data) const { write(read() & data); }
	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  Read Only 8 bits アクセス・テンプレート
		@param[in]	adr	アドレス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <address_type adr>
	struct ro8_t {
		typedef uint8_t value_type;

		//-----------------------------------------------------------------//
		/*!
			@brief 読み出し
			@return 読み出し値
		*/
		//-----------------------------------------------------------------//
		static value_type read() { return rd8_(adr); }

		value_type operator () () const { return read(); }
	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  Write Only 8 bits アクセス・テンプレート
		@param[in]	adr	アドレス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <address_type adr>
	struct wo8_t {
		typedef uint8_t value_type;

		//-----------------------------------------------------------------//
		/*!
			@brief  書き込み
			@param[in]	data	書き込み値
		*/
		//-----------------------------------------------------------------//
		static void write(uint8_t data) { wr8_(adr, data); }

		void operator = (value_type data) const { write(data); }
	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  Read/Write 16 bits アクセス・テンプレート
		@param[in]	adr	アドレス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <address_type adr>
	struct rw16_t {
		typedef uint16_t value_type;

		//-----------------------------------------------------------------//
		/*!
			@brief  書き込み
			@param[in]	data	書き込み値
		*/
		//-----------------------------------------------------------------//
		static void write(uint16_t data) { wr16_(adr, data); }

		//-----------------------------------------------------------------//
		/*!
			@brief 読み出し
			@return 読み出し値
		*/
		//-----------------------------------------------------------------//
		static uint16_t read() { return rd16_(adr); }

		void operator = (value_type data) const { write(data); }
		value_type operator () () const { return read(); }
		void operator |= (value_type data) const { write(read() | data); }
		void operator &= (value_type data) const { write(read() & data); }
	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  Read Only 16 bits アクセス・テンプレート
		@param[in]	adr	アドレス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <address_type adr>
	struct ro16_t {
		typedef uint16_t value_type;

		//-----------------------------------------------------------------//
		/*!
			@brief 読み出し
			@return 読み出し値
		*/
		//-----------------------------------------------------------------//
		static uint16_t read() { return rd16_(adr); }

		value_type operator () () const { return read(); }
	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  Write Only 16 bits アクセス・テンプレート
		@param[in]	adr	アドレス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <address_type adr>
	struct wo16_t {
		typedef uint16_t value_type;

		//-----------------------------------------------------------------//
		/*!
			@brief  書き込み
			@param[in]	data	書き込み値
		*/
		//-----------------------------------------------------------------//
		static void write(uint16_t data) { wr16_(adr, data); }

		void operator = (value_type data) const { write(data); }
	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  Read/Write ビット・アクセス・テンプレート
		@param[in]	T	アクセス・クラス
		@param[in]	pos	初期位置
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class T, uint8_t pos>
	struct bit_rw_t {
		static bool get() {
			return (T::read() >> pos) & 1;
		}
		static void set(bool v) {
			if(v) {
				T::write(T::read() | (static_cast<typename T::value_type>(v) << pos));
			} else {
				T::write(T::read() & ~(static_cast<typename T::value_type>(1) << pos));
			}
		}

	    typename T::value_type b(bool v) const {
			return v << pos;
		}

		void operator = (bool v) const { set(v); }
		bool operator () () const { return get(); }
	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  Read/Write ビット・アクセス・テンプレート
		@param[in]	T	アクセス・クラス
		@param[in]	pos	初期位置
		@param[in]	len	ビット幅
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class T, uint8_t pos, uint8_t len>
	struct bits_rw_t {
		static typename T::value_type get() {
			return (typename T::read() >> pos) & ((1 << len) - 1);
		}
		static void set(typename T::value_type v) {
			auto m = static_cast<typename T::value_type>(((1 << len) - 1) << pos);
			T::write((T::read() & ~m) | (static_cast<typename T::value_type>(v) << pos));
		}

	    typename T::value_type b(typename T::value_type v) const {
			return (((1 << len) - 1) & v) << pos;
		}

		void operator = (typename T::value_type v) const { set(v); }
		typename T::value_type operator () () const { return get(); }
	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  Read ビット・アクセス・テンプレート
		@param[in]	T	アクセス・クラス
		@param[in]	pos	初期位置
		@param[in]	len	ビット幅
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class T, uint8_t pos>
	struct bit_ro_t {
		static bool get() {
			return (T::read() >> pos) & 1;
		}

	    typename T::value_type b(typename T::value_type v) const {
			return 1 << pos;
		}

		bool operator () () const { return get(); }
	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  標準 Read/Write アクセス・テンプレート
		@param[in]	T	アクセステンプレート
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class T>
	struct basic_rw_t : public T {

		using T::operator =;
		using T::operator ();
		using T::operator |=;
		using T::operator &=;

		bit_rw_t<T, 7> B7;	///< B7 アクセス
		bit_rw_t<T, 6> B6;	///< B6 アクセス
		bit_rw_t<T, 5> B5;	///< B5 アクセス
		bit_rw_t<T, 4> B4;	///< B4 アクセス
		bit_rw_t<T, 3> B3;	///< B3 アクセス
		bit_rw_t<T, 2> B2;	///< B2 アクセス
		bit_rw_t<T, 1> B1;	///< B1 アクセス
		bit_rw_t<T, 0> B0;	///< B0 アクセス
	};
}
<commit_msg>fix bitpos enum class<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	I/O ユーティリティー @n
			Copyright 2013,2016 Kunihito Hiramatsu
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <cstdint>

namespace device {

	// RL78
	typedef uint32_t address_type;

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  ８ビット書き込み
		@param[in]	adr		書き込みアドレス
		@param[in]	data	書き込みデータ
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	static inline void wr8_(address_type adr, uint8_t data) {
		*reinterpret_cast<volatile uint8_t*>(adr) = data;
	}

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  ８ビット読み込み
		@param[in]	adr		読み込みアドレス
		@param[in]	data	読み込みデータ
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	static inline uint8_t rd8_(address_type adr) {
		return *reinterpret_cast<volatile uint8_t*>(adr);
	}

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  １６ビット書き込み
		@param[in]	adr		書き込みアドレス
		@param[in]	data	書き込みデータ
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	static inline void wr16_(address_type adr, uint16_t data) {
		*reinterpret_cast<volatile uint16_t*>(adr) = data;
	}

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  １６ビット読み込み
		@param[in]	adr		読み込みアドレス
		@param[in]	data	読み込みデータ
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	static inline uint16_t rd16_(address_type adr) {
		return *reinterpret_cast<volatile uint16_t*>(adr);
	}

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  ３２ビット書き込み
		@param[in]	adr		書き込みアドレス
		@param[in]	data	書き込みデータ
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	static inline void wr32_(address_type adr, uint32_t data) {
		*reinterpret_cast<volatile uint32_t*>(adr) = data;
	}

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  ３２ビット読み込み
		@param[in]	adr		読み込みアドレス
		@param[in]	data	読み込みデータ
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	static inline uint32_t rd32_(address_type adr) {
		return *reinterpret_cast<volatile uint32_t*>(adr);
	}

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  Read/Write 8 bits アクセス・テンプレート
		@param[in]	adr	アドレス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <address_type adr>
	struct rw8_t {
		typedef uint8_t value_type;

		//-----------------------------------------------------------------//
		/*!
			@brief  書き込み
			@param[in]	data	書き込み値
		*/
		//-----------------------------------------------------------------//
		static void write(value_type data) { wr8_(adr, data); }

		//-----------------------------------------------------------------//
		/*!
			@brief 読み出し
			@return 読み出し値
		*/
		//-----------------------------------------------------------------//
		static value_type read() { return rd8_(adr); }

		void operator = (value_type data) const { write(data); }
		value_type operator () () const { return read(); }
		void operator |= (value_type data) const { write(read() | data); }
		void operator &= (value_type data) const { write(read() & data); }
	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  Read Only 8 bits アクセス・テンプレート
		@param[in]	adr	アドレス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <address_type adr>
	struct ro8_t {
		typedef uint8_t value_type;

		//-----------------------------------------------------------------//
		/*!
			@brief 読み出し
			@return 読み出し値
		*/
		//-----------------------------------------------------------------//
		static value_type read() { return rd8_(adr); }

		value_type operator () () const { return read(); }
	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  Write Only 8 bits アクセス・テンプレート
		@param[in]	adr	アドレス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <address_type adr>
	struct wo8_t {
		typedef uint8_t value_type;

		//-----------------------------------------------------------------//
		/*!
			@brief  書き込み
			@param[in]	data	書き込み値
		*/
		//-----------------------------------------------------------------//
		static void write(uint8_t data) { wr8_(adr, data); }

		void operator = (value_type data) const { write(data); }
	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  Read/Write 16 bits アクセス・テンプレート
		@param[in]	adr	アドレス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <address_type adr>
	struct rw16_t {
		typedef uint16_t value_type;

		//-----------------------------------------------------------------//
		/*!
			@brief  書き込み
			@param[in]	data	書き込み値
		*/
		//-----------------------------------------------------------------//
		static void write(uint16_t data) { wr16_(adr, data); }

		//-----------------------------------------------------------------//
		/*!
			@brief 読み出し
			@return 読み出し値
		*/
		//-----------------------------------------------------------------//
		static uint16_t read() { return rd16_(adr); }

		void operator = (value_type data) const { write(data); }
		value_type operator () () const { return read(); }
		void operator |= (value_type data) const { write(read() | data); }
		void operator &= (value_type data) const { write(read() & data); }
	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  Read Only 16 bits アクセス・テンプレート
		@param[in]	adr	アドレス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <address_type adr>
	struct ro16_t {
		typedef uint16_t value_type;

		//-----------------------------------------------------------------//
		/*!
			@brief 読み出し
			@return 読み出し値
		*/
		//-----------------------------------------------------------------//
		static uint16_t read() { return rd16_(adr); }

		value_type operator () () const { return read(); }
	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  Write Only 16 bits アクセス・テンプレート
		@param[in]	adr	アドレス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <address_type adr>
	struct wo16_t {
		typedef uint16_t value_type;

		//-----------------------------------------------------------------//
		/*!
			@brief  書き込み
			@param[in]	data	書き込み値
		*/
		//-----------------------------------------------------------------//
		static void write(uint16_t data) { wr16_(adr, data); }

		void operator = (value_type data) const { write(data); }
	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  ビット位置定義
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	enum class bitpos : uint8_t {
		B0,		///< ビット０
		B1,		///< ビット１
		B2,		///< ビット２
		B3,		///< ビット３
		B4,		///< ビット４
		B5,		///< ビット５
		B6,		///< ビット６
		B7,		///< ビット７
		B8,		///< ビット８
		B9,		///< ビット９
		B10,	///< ビット１０
		B11,	///< ビット１１
		B12,	///< ビット１２
		B13,	///< ビット１３
		B14,	///< ビット１４
		B15,	///< ビット１５
	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  Read/Write ビット・アクセス・テンプレート
		@param[in]	T	アクセス・クラス
		@param[in]	pos	ビット位置
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class T, bitpos pos>
	struct bit_rw_t {
		static bool get() {
			return (T::read() >> static_cast<uint8_t>(pos)) & 1;
		}
		static void set(bool v) {
			if(v) {
				T::write(T::read() | (static_cast<typename T::value_type>(v) << static_cast<uint8_t>(pos)));
			} else {
				T::write(T::read() & ~(static_cast<typename T::value_type>(1) << static_cast<uint8_t>(pos)));
			}
		}

	    typename T::value_type b(bool v) const {
			return v << static_cast<uint8_t>(pos);
		}

		void operator = (bool v) const { set(v); }
		bool operator () () const { return get(); }
	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  Read/Write ビット・アクセス・テンプレート
		@param[in]	T	アクセス・クラス
		@param[in]	pos	初期ビット位置
		@param[in]	len	ビット幅
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class T, bitpos pos, uint8_t len>
	struct bits_rw_t {
		static typename T::value_type get() {
			return (typename T::read() >> static_cast<uint8_t>(pos)) & ((1 << len) - 1);
		}
		static void set(typename T::value_type v) {
			auto m = static_cast<typename T::value_type>(((1 << len) - 1) << static_cast<uint8_t>(pos));
			T::write((T::read() & ~m) | (static_cast<typename T::value_type>(v) << static_cast<uint8_t>(pos)));
		}

	    typename T::value_type b(typename T::value_type v) const {
			return (((1 << len) - 1) & v) << static_cast<uint8_t>(pos);
		}

		void operator = (typename T::value_type v) const { set(v); }
		typename T::value_type operator () () const { return get(); }
	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  Read ビット・アクセス・テンプレート
		@param[in]	T	アクセス・クラス
		@param[in]	pos	ビット位置
		@param[in]	len	ビット幅
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class T, bitpos pos>
	struct bit_ro_t {
		static bool get() {
			return (T::read() >> static_cast<uint8_t>(pos)) & 1;
		}

	    typename T::value_type b(typename T::value_type v) const {
			return 1 << static_cast<uint8_t>(pos);
		}

		bool operator () () const { return get(); }
	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  標準 Read/Write アクセス・テンプレート
		@param[in]	T	アクセステンプレート
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class T>
	struct basic_rw_t : public T {

		using T::operator =;
		using T::operator ();
		using T::operator |=;
		using T::operator &=;

		bit_rw_t<T, bitpos::B7> B7;	///< B7 アクセス
		bit_rw_t<T, bitpos::B6> B6;	///< B6 アクセス
		bit_rw_t<T, bitpos::B5> B5;	///< B5 アクセス
		bit_rw_t<T, bitpos::B4> B4;	///< B4 アクセス
		bit_rw_t<T, bitpos::B3> B3;	///< B3 アクセス
		bit_rw_t<T, bitpos::B2> B2;	///< B2 アクセス
		bit_rw_t<T, bitpos::B1> B1;	///< B1 アクセス
		bit_rw_t<T, bitpos::B0> B0;	///< B0 アクセス
	};
}
<|endoftext|>


<commit_before>//===- JITTest.cpp - Unit tests for the JIT -------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "gtest/gtest.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/BasicBlock.h"
#include "llvm/Constant.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/ExecutionEngine/JITMemoryManager.h"
#include "llvm/Function.h"
#include "llvm/GlobalValue.h"
#include "llvm/GlobalVariable.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/Support/IRBuilder.h"
#include "llvm/Support/TypeBuilder.h"
#include "llvm/Target/TargetSelect.h"
#include "llvm/Type.h"

using namespace llvm;

namespace {

Function *makeReturnGlobal(std::string Name, GlobalVariable *G, Module *M) {
  std::vector<const Type*> params;
  const FunctionType *FTy = FunctionType::get(G->getType()->getElementType(),
                                              params, false);
  Function *F = Function::Create(FTy, GlobalValue::ExternalLinkage, Name, M);
  BasicBlock *Entry = BasicBlock::Create(M->getContext(), "entry", F);
  IRBuilder<> builder(Entry);
  Value *Load = builder.CreateLoad(G);
  const Type *GTy = G->getType()->getElementType();
  Value *Add = builder.CreateAdd(Load, ConstantInt::get(GTy, 1LL));
  builder.CreateStore(Add, G);
  builder.CreateRet(Add);
  return F;
}

class JITTest : public testing::Test {
 protected:
  virtual void SetUp() {
    M = new Module("<main>", Context);
    std::string Error;
    TheJIT.reset(EngineBuilder(M).setEngineKind(EngineKind::JIT)
                 .setErrorStr(&Error).create());
    ASSERT_TRUE(TheJIT.get() != NULL) << Error;
  }

  LLVMContext Context;
  Module *M;  // Owned by ExecutionEngine.
  OwningPtr<ExecutionEngine> TheJIT;
};

// Regression test for a bug.  The JIT used to allocate globals inside the same
// memory block used for the function, and when the function code was freed,
// the global was left in the same place.  This test allocates a function
// that uses and global, deallocates it, and then makes sure that the global
// stays alive after that.
TEST(JIT, GlobalInFunction) {
  LLVMContext context;
  Module *M = new Module("<main>", context);
  ExistingModuleProvider *MP = new ExistingModuleProvider(M);

  JITMemoryManager *MemMgr = JITMemoryManager::CreateDefaultMemManager();
  // Tell the memory manager to poison freed memory so that accessing freed
  // memory is more easily tested.
  MemMgr->setPoisonMemory(true);
  std::string Error;
  OwningPtr<ExecutionEngine> JIT(EngineBuilder(MP)
                                 .setEngineKind(EngineKind::JIT)
                                 .setErrorStr(&Error)
                                 .setJITMemoryManager(MemMgr)
                                 // The next line enables the fix:
                                 .setAllocateGVsWithCode(false)
                                 .create());
  ASSERT_EQ(Error, "");

  // Create a global variable.
  const Type *GTy = Type::getInt32Ty(context);
  GlobalVariable *G = new GlobalVariable(
      *M,
      GTy,
      false,  // Not constant.
      GlobalValue::InternalLinkage,
      Constant::getNullValue(GTy),
      "myglobal");

  // Make a function that points to a global.
  Function *F1 = makeReturnGlobal("F1", G, M);

  // Get the pointer to the native code to force it to JIT the function and
  // allocate space for the global.
  void (*F1Ptr)();
  // Hack to avoid ISO C++ warning about casting function pointers.
  *(void**)(void*)&F1Ptr = JIT->getPointerToFunction(F1);

  // Since F1 was codegen'd, a pointer to G should be available.
  int32_t *GPtr = (int32_t*)JIT->getPointerToGlobalIfAvailable(G);
  ASSERT_NE((int32_t*)NULL, GPtr);
  EXPECT_EQ(0, *GPtr);

  // F1() should increment G.
  F1Ptr();
  EXPECT_EQ(1, *GPtr);

  // Make a second function identical to the first, referring to the same
  // global.
  Function *F2 = makeReturnGlobal("F2", G, M);
  // Hack to avoid ISO C++ warning about casting function pointers.
  void (*F2Ptr)();
  *(void**)(void*)&F2Ptr = JIT->getPointerToFunction(F2);

  // F2() should increment G.
  F2Ptr();
  EXPECT_EQ(2, *GPtr);

  // Deallocate F1.
  JIT->freeMachineCodeForFunction(F1);

  // F2() should *still* increment G.
  F2Ptr();
  EXPECT_EQ(3, *GPtr);
}

int PlusOne(int arg) {
  return arg + 1;
}

TEST_F(JITTest, FarCallToKnownFunction) {
  // x86-64 can only make direct calls to functions within 32 bits of
  // the current PC.  To call anything farther away, we have to load
  // the address into a register and call through the register.  The
  // current JIT does this by allocating a stub for any far call.
  // There was a bug in which the JIT tried to emit a direct call when
  // the target was already in the JIT's global mappings and lazy
  // compilation was disabled.

  Function *KnownFunction = Function::Create(
      TypeBuilder<int(int), false>::get(Context),
      GlobalValue::ExternalLinkage, "known", M);
  TheJIT->addGlobalMapping(KnownFunction, (void*)(intptr_t)PlusOne);

  // int test() { return known(7); }
  Function *TestFunction = Function::Create(
      TypeBuilder<int(), false>::get(Context),
      GlobalValue::ExternalLinkage, "test", M);
  BasicBlock *Entry = BasicBlock::Create(Context, "entry", TestFunction);
  IRBuilder<> Builder(Entry);
  Value *result = Builder.CreateCall(
      KnownFunction,
      ConstantInt::get(TypeBuilder<int, false>::get(Context), 7));
  Builder.CreateRet(result);

  TheJIT->EnableDlsymStubs(false);
  TheJIT->DisableLazyCompilation();
  int (*TestFunctionPtr)() = reinterpret_cast<int(*)()>(
      (intptr_t)TheJIT->getPointerToFunction(TestFunction));
  // This used to crash in trying to call PlusOne().
  EXPECT_EQ(8, TestFunctionPtr());
}

// This code is copied from JITEventListenerTest, but it only runs once for all
// the tests in this directory.  Everything seems fine, but that's strange
// behavior.
class JITEnvironment : public testing::Environment {
  virtual void SetUp() {
    // Required to create a JIT.
    InitializeNativeTarget();
  }
};
testing::Environment* const jit_env =
  testing::AddGlobalTestEnvironment(new JITEnvironment);

}
<commit_msg>Fix illegal cross-type aliasing. Found by baldrick on a newer gcc.<commit_after>//===- JITTest.cpp - Unit tests for the JIT -------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "gtest/gtest.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/BasicBlock.h"
#include "llvm/Constant.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/ExecutionEngine/JITMemoryManager.h"
#include "llvm/Function.h"
#include "llvm/GlobalValue.h"
#include "llvm/GlobalVariable.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/Support/IRBuilder.h"
#include "llvm/Support/TypeBuilder.h"
#include "llvm/Target/TargetSelect.h"
#include "llvm/Type.h"

using namespace llvm;

namespace {

Function *makeReturnGlobal(std::string Name, GlobalVariable *G, Module *M) {
  std::vector<const Type*> params;
  const FunctionType *FTy = FunctionType::get(G->getType()->getElementType(),
                                              params, false);
  Function *F = Function::Create(FTy, GlobalValue::ExternalLinkage, Name, M);
  BasicBlock *Entry = BasicBlock::Create(M->getContext(), "entry", F);
  IRBuilder<> builder(Entry);
  Value *Load = builder.CreateLoad(G);
  const Type *GTy = G->getType()->getElementType();
  Value *Add = builder.CreateAdd(Load, ConstantInt::get(GTy, 1LL));
  builder.CreateStore(Add, G);
  builder.CreateRet(Add);
  return F;
}

class JITTest : public testing::Test {
 protected:
  virtual void SetUp() {
    M = new Module("<main>", Context);
    std::string Error;
    TheJIT.reset(EngineBuilder(M).setEngineKind(EngineKind::JIT)
                 .setErrorStr(&Error).create());
    ASSERT_TRUE(TheJIT.get() != NULL) << Error;
  }

  LLVMContext Context;
  Module *M;  // Owned by ExecutionEngine.
  OwningPtr<ExecutionEngine> TheJIT;
};

// Regression test for a bug.  The JIT used to allocate globals inside the same
// memory block used for the function, and when the function code was freed,
// the global was left in the same place.  This test allocates a function
// that uses and global, deallocates it, and then makes sure that the global
// stays alive after that.
TEST(JIT, GlobalInFunction) {
  LLVMContext context;
  Module *M = new Module("<main>", context);
  ExistingModuleProvider *MP = new ExistingModuleProvider(M);

  JITMemoryManager *MemMgr = JITMemoryManager::CreateDefaultMemManager();
  // Tell the memory manager to poison freed memory so that accessing freed
  // memory is more easily tested.
  MemMgr->setPoisonMemory(true);
  std::string Error;
  OwningPtr<ExecutionEngine> JIT(EngineBuilder(MP)
                                 .setEngineKind(EngineKind::JIT)
                                 .setErrorStr(&Error)
                                 .setJITMemoryManager(MemMgr)
                                 // The next line enables the fix:
                                 .setAllocateGVsWithCode(false)
                                 .create());
  ASSERT_EQ(Error, "");

  // Create a global variable.
  const Type *GTy = Type::getInt32Ty(context);
  GlobalVariable *G = new GlobalVariable(
      *M,
      GTy,
      false,  // Not constant.
      GlobalValue::InternalLinkage,
      Constant::getNullValue(GTy),
      "myglobal");

  // Make a function that points to a global.
  Function *F1 = makeReturnGlobal("F1", G, M);

  // Get the pointer to the native code to force it to JIT the function and
  // allocate space for the global.
  void (*F1Ptr)() =
      reinterpret_cast<void(*)()>((intptr_t)JIT->getPointerToFunction(F1));

  // Since F1 was codegen'd, a pointer to G should be available.
  int32_t *GPtr = (int32_t*)JIT->getPointerToGlobalIfAvailable(G);
  ASSERT_NE((int32_t*)NULL, GPtr);
  EXPECT_EQ(0, *GPtr);

  // F1() should increment G.
  F1Ptr();
  EXPECT_EQ(1, *GPtr);

  // Make a second function identical to the first, referring to the same
  // global.
  Function *F2 = makeReturnGlobal("F2", G, M);
  void (*F2Ptr)() =
      reinterpret_cast<void(*)()>((intptr_t)JIT->getPointerToFunction(F2));

  // F2() should increment G.
  F2Ptr();
  EXPECT_EQ(2, *GPtr);

  // Deallocate F1.
  JIT->freeMachineCodeForFunction(F1);

  // F2() should *still* increment G.
  F2Ptr();
  EXPECT_EQ(3, *GPtr);
}

int PlusOne(int arg) {
  return arg + 1;
}

TEST_F(JITTest, FarCallToKnownFunction) {
  // x86-64 can only make direct calls to functions within 32 bits of
  // the current PC.  To call anything farther away, we have to load
  // the address into a register and call through the register.  The
  // current JIT does this by allocating a stub for any far call.
  // There was a bug in which the JIT tried to emit a direct call when
  // the target was already in the JIT's global mappings and lazy
  // compilation was disabled.

  Function *KnownFunction = Function::Create(
      TypeBuilder<int(int), false>::get(Context),
      GlobalValue::ExternalLinkage, "known", M);
  TheJIT->addGlobalMapping(KnownFunction, (void*)(intptr_t)PlusOne);

  // int test() { return known(7); }
  Function *TestFunction = Function::Create(
      TypeBuilder<int(), false>::get(Context),
      GlobalValue::ExternalLinkage, "test", M);
  BasicBlock *Entry = BasicBlock::Create(Context, "entry", TestFunction);
  IRBuilder<> Builder(Entry);
  Value *result = Builder.CreateCall(
      KnownFunction,
      ConstantInt::get(TypeBuilder<int, false>::get(Context), 7));
  Builder.CreateRet(result);

  TheJIT->EnableDlsymStubs(false);
  TheJIT->DisableLazyCompilation();
  int (*TestFunctionPtr)() = reinterpret_cast<int(*)()>(
      (intptr_t)TheJIT->getPointerToFunction(TestFunction));
  // This used to crash in trying to call PlusOne().
  EXPECT_EQ(8, TestFunctionPtr());
}

// This code is copied from JITEventListenerTest, but it only runs once for all
// the tests in this directory.  Everything seems fine, but that's strange
// behavior.
class JITEnvironment : public testing::Environment {
  virtual void SetUp() {
    // Required to create a JIT.
    InitializeNativeTarget();
  }
};
testing::Environment* const jit_env =
  testing::AddGlobalTestEnvironment(new JITEnvironment);

}
<|endoftext|>