<commit_before>#include "mfem.hpp"
#include <memory>
#include <iostream>
#include <fstream>

using namespace std;
using namespace mfem;

/** After spatial discretization, the rubber model can be written as:
 *     0=H(x)
 *  where x is the block vector representing the deformation and pressure
 *  and H(x) is the nonlinear incompressible neo-Hookean operator. */
class RubberOperator : public Operator
{
protected:
   Array<ParFiniteElementSpace *> spaces;

   ParBlockNonlinearForm *Hform;
   mutable Operator *Jacobian;
   const BlockVector *x;

   /// Newton solver for the hyperelastic operator
   NewtonSolver newton_solver;
   /// Solver for the Jacobian solve in the Newton method
   mutable Solver *J_solver;
   /// Preconditioner for the Jacobian
   mutable Solver *J_prec;

   Coefficient μ

public:
   RubberOperator(Array<ParFiniteElementSpace *> &fes, Array<Array<int> *>&ess_bdr,
                  Array<int> &block_trueOffsets, double rel_tol, double abs_tol, int iter,
                  Coefficient &mu);

   /// Required to use the native newton solver
   virtual Operator &GetGradientSolver(const Vector &xp) const;
   virtual void Mult(const Vector &k, Vector &y) const;

   /// Driver for the newton solver
   void Solve(Vector &xp) const;

   virtual ~RubberOperator();
};

void visualize(ostream &out, ParMesh *mesh, ParGridFunction *deformed_nodes,
               ParGridFunction *field, const char *field_name = NULL,
               bool init_vis = false);

void ReferenceConfiguration(const Vector &x, Vector &y);
void InitialDeformation(const Vector &x, Vector &y);

int main(int argc, char *argv[])
{
   // Initialize MPI.
   int num_procs, myid;
   MPI_Init(&argc, &argv);
   MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
   MPI_Comm_rank(MPI_COMM_WORLD, &myid);

   // Parse command-line options.
   const char *mesh_file = "../data/beam-hex.mesh";
   int ser_ref_levels = 0;
   int par_ref_levels = 0;
   int order = 2;
   bool visualization = true;
   double newton_rel_tol = 1.0e-6;
   double newton_abs_tol = 1.0e-8;
   int newton_iter = 500;
   double mu = 1.0;

   OptionsParser args(argc, argv);
   args.AddOption(&mesh_file, "-m", "--mesh",
                  "Mesh file to use.");
   args.AddOption(&ser_ref_levels, "-rs", "--refine-serial",
                  "Number of times to refine the mesh uniformly in serial.");
   args.AddOption(&par_ref_levels, "-rp", "--refine-parallel",
                  "Number of times to refine the mesh uniformly in parallel.");
   args.AddOption(&order, "-o", "--order",
                  "Order (degree) of the finite elements.");
   args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
                  "--no-visualization",
                  "Enable or disable GLVis visualization.");
   args.AddOption(&newton_rel_tol, "-rel", "--relative-tolerance",
                  "Relative tolerance for the Newton solve.");
   args.AddOption(&newton_abs_tol, "-abs", "--absolute-tolerance",
                  "Absolute tolerance for the Newton solve.");
   args.AddOption(&newton_iter, "-it", "--newton-iterations",
                  "Maximum iterations for the Newton solve.");
   args.AddOption(&mu, "-mu", "--shear-modulus",
                  "Shear modulus for the neo-Hookean material.");

   args.Parse();
   if (!args.Good())
   {
      if (myid == 0)
      {
         args.PrintUsage(cout);
      }
      MPI_Finalize();
      return 1;
   }
   if (myid == 0)
   {
      args.PrintOptions(cout);
   }

   // Open the mesh
   Mesh *mesh;
   ifstream imesh(mesh_file);
   if (!imesh)
   {
      if (myid == 0)
      {
         cerr << "\nCan not open mesh file: " << mesh_file << '\n' << endl;
      }
      MPI_Finalize();
      return 2;
   }
   mesh = new Mesh(imesh, 1, 1);
   imesh.close();
   ParMesh *pmesh = NULL;

   for (int lev = 0; lev < ser_ref_levels; lev++)
   {
      mesh->UniformRefinement();
   }
   pmesh = new ParMesh(MPI_COMM_WORLD, *mesh);
   for (int lev = 0; lev < par_ref_levels; lev++)
   {
      pmesh->UniformRefinement();
   }

   delete mesh;
   int dim = pmesh->Dimension();

   ConstantCoefficient c_mu(mu);

   // Definie the finite element spaces for displacement and pressure (Stokes elements)
   H1_FECollection quad_coll(order, dim);
   H1_FECollection lin_coll(order-1, dim);

   ParFiniteElementSpace R_space(pmesh, &quad_coll, dim);
   ParFiniteElementSpace W_space(pmesh, &lin_coll);

   Array<ParFiniteElementSpace *> spaces(2);
   spaces[0] = &R_space;
   spaces[1] = &W_space;

   HYPRE_Int glob_R_size = R_space.GlobalTrueVSize();
   HYPRE_Int glob_W_size = W_space.GlobalTrueVSize();

   // Define the Dirichlet conditions (set to boundary attribute 1)
   Array<Array<int> *> ess_bdr(2);

   Array<int> ess_bdr_u(R_space.GetMesh()->bdr_attributes.Max());
   Array<int> ess_bdr_p(W_space.GetMesh()->bdr_attributes.Max());

   ess_bdr_p = 0;
   ess_bdr_u = 0;
   ess_bdr_u[0] = 1;
   ess_bdr_u[1] = 1;

   ess_bdr[0] = &ess_bdr_u;
   ess_bdr[1] = &ess_bdr_p;

   // Print the mesh statistics
   if (myid == 0)
   {
      std::cout << "***********************************************************\n";
      std::cout << "dim(u) = " << glob_R_size << "\n";
      std::cout << "dim(p) = " << glob_W_size << "\n";
      std::cout << "dim(u+p) = " << glob_R_size + glob_W_size << "\n";
      std::cout << "***********************************************************\n";
   }

   // Define the block structure of the solution vector (u then p)
   Array<int> block_offsets(3);
   block_offsets[0] = 0;
   block_offsets[1] = R_space.GetVSize();
   block_offsets[2] = W_space.GetVSize();
   block_offsets.PartialSum();

   Array<int> block_trueOffsets(3);
   block_trueOffsets[0] = 0;
   block_trueOffsets[1] = R_space.TrueVSize();
   block_trueOffsets[2] = W_space.TrueVSize();
   block_trueOffsets.PartialSum();

   BlockVector xp(block_trueOffsets);

   // Define grid functions for the current configuration, reference configuration,
   // final deformation, and pressure
   ParGridFunction x_gf(&R_space);
   ParGridFunction x_ref(&R_space);
   ParGridFunction x_def(&R_space);
   ParGridFunction p_gf(&W_space);

   // Project the initial and reference configuration functions onto the appropriate grid functions
   VectorFunctionCoefficient deform(dim, InitialDeformation);
   VectorFunctionCoefficient refconfig(dim, ReferenceConfiguration);

   x_gf.ProjectCoefficient(deform);
   x_ref.ProjectCoefficient(refconfig);

   // Set up the block solution vectors
   x_gf.GetTrueDofs(xp.GetBlock(0));
   p_gf.GetTrueDofs(xp.GetBlock(1));

   // Initialize the incompressible neo-Hookean operator
   RubberOperator oper(spaces, ess_bdr, block_trueOffsets,
                       newton_rel_tol, newton_abs_tol, newton_iter, c_mu);

   // Solve the Newton system
   oper.Solve(xp);

   // Distribute the ghost dofs
   x_gf.Distribute(xp.GetBlock(0));
   p_gf.Distribute(xp.GetBlock(1));

   // Set the final deformation
   subtract(x_gf, x_ref, x_def);

   // Visualize the results if requested
   socketstream vis_u, vis_p;
   if (visualization)
   {
      char vishost[] = "localhost";
      int  visport   = 19916;
      vis_u.open(vishost, visport);
      vis_u.precision(8);
      visualize(vis_u, pmesh, &x_gf, &x_def, "Deformation", true);
      // Make sure all ranks have sent their 'u' solution before initiating
      // another set of GLVis connections (one from each rank):
      MPI_Barrier(pmesh->GetComm());
      vis_p.open(vishost, visport);
      vis_p.precision(8);
      visualize(vis_p, pmesh, &x_gf, &p_gf, "Pressure", true);
   }

   // Save the displaced mesh, the final deformation, and the pressure
   {
      GridFunction *nodes = &x_gf;
      int owns_nodes = 0;
      pmesh->SwapNodes(nodes, owns_nodes);

      ostringstream mesh_name, pressure_name, deformation_name;
      mesh_name << "mesh." << setfill('0') << setw(6) << myid;
      pressure_name << "pressure." << setfill('0') << setw(6) << myid;
      deformation_name << "deformation." << setfill('0') << setw(6) << myid;

      ofstream mesh_ofs(mesh_name.str().c_str());
      mesh_ofs.precision(8);
      pmesh->Print(mesh_ofs);

      ofstream pressure_ofs(pressure_name.str().c_str());
      pressure_ofs.precision(8);
      p_gf.Save(pressure_ofs);

      ofstream deformation_ofs(deformation_name.str().c_str());
      deformation_ofs.precision(8);
      x_def.Save(deformation_ofs);
   }

   // Free the used memory.
   delete pmesh;

   MPI_Finalize();

   return 0;
}

RubberOperator::RubberOperator(Array<ParFiniteElementSpace *> &fes,
                               Array<Array<int> *> &ess_bdr,
                               Array<int> &block_trueOffsets,
                               double rel_tol,
                               double abs_tol,
                               int iter,
                               Coefficient &c_mu)
   : Operator(fes[0]->TrueVSize() + fes[1]->TrueVSize()),
     newton_solver(fes[0]->GetComm(), true), mu(c_mu)
{
   Array<Vector *> rhs(2);

   rhs[0] = NULL;
   rhs[1] = NULL;

   fes.Copy(spaces);

   // Define the mixed nonlinear form
   Hform = new ParBlockNonlinearForm(spaces);

   // Add the passive stress integrator
   Hform->AddDomainIntegrator(new IncompressibleNeoHookeanIntegrator(mu));

   // Set the essential boundary conditions
   Hform->SetEssentialBC(ess_bdr, rhs);
   // Set the newton solve parameters
   newton_solver.iterative_mode = true;

   newton_solver.SetOperator(*this);
   newton_solver.SetPrintLevel(1);
   newton_solver.SetRelTol(rel_tol);
   newton_solver.SetAbsTol(abs_tol);
   newton_solver.SetMaxIter(iter);
}

// Solve the Newton system
void RubberOperator::Solve(Vector &xp) const
{
   Vector zero;
   newton_solver.Mult(zero, xp);
   MFEM_VERIFY(newton_solver.GetConverged(), "Newton Solver did not converge.");
}

// compute: y = H(x,p)
void RubberOperator::Mult(const Vector &k, Vector &y) const
{
   Hform->Mult(k, y);

}

// Compute the Jacobian from the nonlinear form
Operator &RubberOperator::GetGradientSolver(const Vector &xp) const
{
   Jacobian = &Hform->GetGradient(xp);

   SuperLUSolver *superlu = NULL;
   superlu = new SuperLUSolver(MPI_COMM_WORLD);
   superlu->SetPrintStatistics(false);
   superlu->SetSymmetricPattern(false);
   superlu->SetColumnPermutation(superlu::PARMETIS);

   J_solver = superlu;
   J_prec = NULL;

   J_solver->SetOperator(*Jacobian);

   return *J_solver;
}

RubberOperator::~RubberOperator()
{
   delete J_solver;
   if (J_prec != NULL)
   {
      delete J_prec;
   }
}

// In line visualization
void visualize(ostream &out, ParMesh *mesh, ParGridFunction *deformed_nodes,
               ParGridFunction *field, const char *field_name, bool init_vis)
{
   if (!out)
   {
      return;
   }

   GridFunction *nodes = deformed_nodes;
   int owns_nodes = 0;

   mesh->SwapNodes(nodes, owns_nodes);

   out << "parallel " << mesh->GetNRanks() << " " << mesh->GetMyRank() << "\n";
   out << "solution\n" << *mesh << *field;

   mesh->SwapNodes(nodes, owns_nodes);

   if (init_vis)
   {
      out << "window_size 800 800\n";
      out << "window_title '" << field_name << "'\n";
      if (mesh->SpaceDimension() == 2)
      {
         out << "view 0 0\n"; // view from top
         out << "keys jl\n";  // turn off perspective and light
      }
      out << "keys cm\n";         // show colorbar and mesh
      out << "autoscale value\n"; // update value-range; keep mesh-extents fixed
      out << "pause\n";
   }
   out << flush;
}

void ReferenceConfiguration(const Vector &x, Vector &y)
{
   // set the reference, stress
   // free, configuration
   y = x;
}

void InitialDeformation(const Vector &x, Vector &y)
{
   // set the initial configuration. Having this different from the
   // reference configuration can help convergence
   y = x;
   y[1] = x[1] + 0.25*x[0];
}
<commit_msg>Fixed memory leak<commit_after>#include "mfem.hpp"
#include <memory>
#include <iostream>
#include <fstream>

using namespace std;
using namespace mfem;

/** After spatial discretization, the rubber model can be written as:
 *     0=H(x)
 *  where x is the block vector representing the deformation and pressure
 *  and H(x) is the nonlinear incompressible neo-Hookean operator. */
class RubberOperator : public Operator
{
protected:
   Array<ParFiniteElementSpace *> spaces;

   ParBlockNonlinearForm *Hform;
   mutable Operator *Jacobian;
   const BlockVector *x;

   /// Newton solver for the hyperelastic operator
   NewtonSolver newton_solver;
   /// Solver for the Jacobian solve in the Newton method
   mutable Solver *J_solver;
   /// Preconditioner for the Jacobian
   mutable Solver *J_prec;

   Coefficient μ

public:
   RubberOperator(Array<ParFiniteElementSpace *> &fes, Array<Array<int> *>&ess_bdr,
                  Array<int> &block_trueOffsets, double rel_tol, double abs_tol, int iter,
                  Coefficient &mu);

   /// Required to use the native newton solver
   virtual Operator &GetGradientSolver(const Vector &xp) const;
   virtual void Mult(const Vector &k, Vector &y) const;

   /// Driver for the newton solver
   void Solve(Vector &xp) const;

   virtual ~RubberOperator();
};

void visualize(ostream &out, ParMesh *mesh, ParGridFunction *deformed_nodes,
               ParGridFunction *field, const char *field_name = NULL,
               bool init_vis = false);

void ReferenceConfiguration(const Vector &x, Vector &y);
void InitialDeformation(const Vector &x, Vector &y);

int main(int argc, char *argv[])
{
   // Initialize MPI.
   int num_procs, myid;
   MPI_Init(&argc, &argv);
   MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
   MPI_Comm_rank(MPI_COMM_WORLD, &myid);

   // Parse command-line options.
   const char *mesh_file = "../data/beam-hex.mesh";
   int ser_ref_levels = 0;
   int par_ref_levels = 0;
   int order = 2;
   bool visualization = true;
   double newton_rel_tol = 1.0e-6;
   double newton_abs_tol = 1.0e-8;
   int newton_iter = 500;
   double mu = 1.0;

   OptionsParser args(argc, argv);
   args.AddOption(&mesh_file, "-m", "--mesh",
                  "Mesh file to use.");
   args.AddOption(&ser_ref_levels, "-rs", "--refine-serial",
                  "Number of times to refine the mesh uniformly in serial.");
   args.AddOption(&par_ref_levels, "-rp", "--refine-parallel",
                  "Number of times to refine the mesh uniformly in parallel.");
   args.AddOption(&order, "-o", "--order",
                  "Order (degree) of the finite elements.");
   args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
                  "--no-visualization",
                  "Enable or disable GLVis visualization.");
   args.AddOption(&newton_rel_tol, "-rel", "--relative-tolerance",
                  "Relative tolerance for the Newton solve.");
   args.AddOption(&newton_abs_tol, "-abs", "--absolute-tolerance",
                  "Absolute tolerance for the Newton solve.");
   args.AddOption(&newton_iter, "-it", "--newton-iterations",
                  "Maximum iterations for the Newton solve.");
   args.AddOption(&mu, "-mu", "--shear-modulus",
                  "Shear modulus for the neo-Hookean material.");

   args.Parse();
   if (!args.Good())
   {
      if (myid == 0)
      {
         args.PrintUsage(cout);
      }
      MPI_Finalize();
      return 1;
   }
   if (myid == 0)
   {
      args.PrintOptions(cout);
   }

   // Open the mesh
   Mesh *mesh;
   ifstream imesh(mesh_file);
   if (!imesh)
   {
      if (myid == 0)
      {
         cerr << "\nCan not open mesh file: " << mesh_file << '\n' << endl;
      }
      MPI_Finalize();
      return 2;
   }
   mesh = new Mesh(imesh, 1, 1);
   imesh.close();
   ParMesh *pmesh = NULL;

   for (int lev = 0; lev < ser_ref_levels; lev++)
   {
      mesh->UniformRefinement();
   }
   pmesh = new ParMesh(MPI_COMM_WORLD, *mesh);
   for (int lev = 0; lev < par_ref_levels; lev++)
   {
      pmesh->UniformRefinement();
   }

   delete mesh;
   int dim = pmesh->Dimension();

   ConstantCoefficient c_mu(mu);

   // Definie the finite element spaces for displacement and pressure (Stokes elements)
   H1_FECollection quad_coll(order, dim);
   H1_FECollection lin_coll(order-1, dim);

   ParFiniteElementSpace R_space(pmesh, &quad_coll, dim);
   ParFiniteElementSpace W_space(pmesh, &lin_coll);

   Array<ParFiniteElementSpace *> spaces(2);
   spaces[0] = &R_space;
   spaces[1] = &W_space;

   HYPRE_Int glob_R_size = R_space.GlobalTrueVSize();
   HYPRE_Int glob_W_size = W_space.GlobalTrueVSize();

   // Define the Dirichlet conditions (set to boundary attribute 1)
   Array<Array<int> *> ess_bdr(2);

   Array<int> ess_bdr_u(R_space.GetMesh()->bdr_attributes.Max());
   Array<int> ess_bdr_p(W_space.GetMesh()->bdr_attributes.Max());

   ess_bdr_p = 0;
   ess_bdr_u = 0;
   ess_bdr_u[0] = 1;
   ess_bdr_u[1] = 1;

   ess_bdr[0] = &ess_bdr_u;
   ess_bdr[1] = &ess_bdr_p;

   // Print the mesh statistics
   if (myid == 0)
   {
      std::cout << "***********************************************************\n";
      std::cout << "dim(u) = " << glob_R_size << "\n";
      std::cout << "dim(p) = " << glob_W_size << "\n";
      std::cout << "dim(u+p) = " << glob_R_size + glob_W_size << "\n";
      std::cout << "***********************************************************\n";
   }

   // Define the block structure of the solution vector (u then p)
   Array<int> block_offsets(3);
   block_offsets[0] = 0;
   block_offsets[1] = R_space.GetVSize();
   block_offsets[2] = W_space.GetVSize();
   block_offsets.PartialSum();

   Array<int> block_trueOffsets(3);
   block_trueOffsets[0] = 0;
   block_trueOffsets[1] = R_space.TrueVSize();
   block_trueOffsets[2] = W_space.TrueVSize();
   block_trueOffsets.PartialSum();

   BlockVector xp(block_trueOffsets);

   // Define grid functions for the current configuration, reference configuration,
   // final deformation, and pressure
   ParGridFunction x_gf(&R_space);
   ParGridFunction x_ref(&R_space);
   ParGridFunction x_def(&R_space);
   ParGridFunction p_gf(&W_space);

   // Project the initial and reference configuration functions onto the appropriate grid functions
   VectorFunctionCoefficient deform(dim, InitialDeformation);
   VectorFunctionCoefficient refconfig(dim, ReferenceConfiguration);

   x_gf.ProjectCoefficient(deform);
   x_ref.ProjectCoefficient(refconfig);

   // Set up the block solution vectors
   x_gf.GetTrueDofs(xp.GetBlock(0));
   p_gf.GetTrueDofs(xp.GetBlock(1));

   // Initialize the incompressible neo-Hookean operator
   RubberOperator oper(spaces, ess_bdr, block_trueOffsets,
                       newton_rel_tol, newton_abs_tol, newton_iter, c_mu);

   // Solve the Newton system
   oper.Solve(xp);

   // Distribute the ghost dofs
   x_gf.Distribute(xp.GetBlock(0));
   p_gf.Distribute(xp.GetBlock(1));

   // Set the final deformation
   subtract(x_gf, x_ref, x_def);

   // Visualize the results if requested
   socketstream vis_u, vis_p;
   if (visualization)
   {
      char vishost[] = "localhost";
      int  visport   = 19916;
      vis_u.open(vishost, visport);
      vis_u.precision(8);
      visualize(vis_u, pmesh, &x_gf, &x_def, "Deformation", true);
      // Make sure all ranks have sent their 'u' solution before initiating
      // another set of GLVis connections (one from each rank):
      MPI_Barrier(pmesh->GetComm());
      vis_p.open(vishost, visport);
      vis_p.precision(8);
      visualize(vis_p, pmesh, &x_gf, &p_gf, "Pressure", true);
   }

   // Save the displaced mesh, the final deformation, and the pressure
   {
      GridFunction *nodes = &x_gf;
      int owns_nodes = 0;
      pmesh->SwapNodes(nodes, owns_nodes);

      ostringstream mesh_name, pressure_name, deformation_name;
      mesh_name << "mesh." << setfill('0') << setw(6) << myid;
      pressure_name << "pressure." << setfill('0') << setw(6) << myid;
      deformation_name << "deformation." << setfill('0') << setw(6) << myid;

      ofstream mesh_ofs(mesh_name.str().c_str());
      mesh_ofs.precision(8);
      pmesh->Print(mesh_ofs);

      ofstream pressure_ofs(pressure_name.str().c_str());
      pressure_ofs.precision(8);
      p_gf.Save(pressure_ofs);

      ofstream deformation_ofs(deformation_name.str().c_str());
      deformation_ofs.precision(8);
      x_def.Save(deformation_ofs);
   }

   // Free the used memory.
   delete pmesh;

   MPI_Finalize();

   return 0;
}

RubberOperator::RubberOperator(Array<ParFiniteElementSpace *> &fes,
                               Array<Array<int> *> &ess_bdr,
                               Array<int> &block_trueOffsets,
                               double rel_tol,
                               double abs_tol,
                               int iter,
                               Coefficient &c_mu)
   : Operator(fes[0]->TrueVSize() + fes[1]->TrueVSize()),
     newton_solver(fes[0]->GetComm(), true), mu(c_mu)
{
   Array<Vector *> rhs(2);

   rhs[0] = NULL;
   rhs[1] = NULL;

   fes.Copy(spaces);

   // Define the mixed nonlinear form
   Hform = new ParBlockNonlinearForm(spaces);

   // Add the passive stress integrator
   Hform->AddDomainIntegrator(new IncompressibleNeoHookeanIntegrator(mu));

   // Set the essential boundary conditions
   Hform->SetEssentialBC(ess_bdr, rhs);
   // Set the newton solve parameters
   newton_solver.iterative_mode = true;

   newton_solver.SetOperator(*this);
   newton_solver.SetPrintLevel(1);
   newton_solver.SetRelTol(rel_tol);
   newton_solver.SetAbsTol(abs_tol);
   newton_solver.SetMaxIter(iter);

   J_solver = NULL;
   J_prec = NULL;

}

// Solve the Newton system
void RubberOperator::Solve(Vector &xp) const
{
   Vector zero;
   newton_solver.Mult(zero, xp);
   MFEM_VERIFY(newton_solver.GetConverged(), "Newton Solver did not converge.");
}

// compute: y = H(x,p)
void RubberOperator::Mult(const Vector &k, Vector &y) const
{
   Hform->Mult(k, y);

}

// Compute the Jacobian from the nonlinear form
Operator &RubberOperator::GetGradientSolver(const Vector &xp) const
{
   Jacobian = &Hform->GetGradient(xp);

   if (J_solver != NULL) {
      delete J_solver;
   }

   SuperLUSolver *superlu = NULL;
   superlu = new SuperLUSolver(MPI_COMM_WORLD);
   superlu->SetPrintStatistics(false);
   superlu->SetSymmetricPattern(false);
   superlu->SetColumnPermutation(superlu::PARMETIS);

   J_solver = superlu;
   J_prec = NULL;

   J_solver->SetOperator(*Jacobian);

   return *J_solver;
}

RubberOperator::~RubberOperator()
{
   delete J_solver;
   if (J_prec != NULL)
   {
      delete J_prec;
   }
}

// In line visualization
void visualize(ostream &out, ParMesh *mesh, ParGridFunction *deformed_nodes,
               ParGridFunction *field, const char *field_name, bool init_vis)
{
   if (!out)
   {
      return;
   }

   GridFunction *nodes = deformed_nodes;
   int owns_nodes = 0;

   mesh->SwapNodes(nodes, owns_nodes);

   out << "parallel " << mesh->GetNRanks() << " " << mesh->GetMyRank() << "\n";
   out << "solution\n" << *mesh << *field;

   mesh->SwapNodes(nodes, owns_nodes);

   if (init_vis)
   {
      out << "window_size 800 800\n";
      out << "window_title '" << field_name << "'\n";
      if (mesh->SpaceDimension() == 2)
      {
         out << "view 0 0\n"; // view from top
         out << "keys jl\n";  // turn off perspective and light
      }
      out << "keys cm\n";         // show colorbar and mesh
      out << "autoscale value\n"; // update value-range; keep mesh-extents fixed
      out << "pause\n";
   }
   out << flush;
}

void ReferenceConfiguration(const Vector &x, Vector &y)
{
   // set the reference, stress
   // free, configuration
   y = x;
}

void InitialDeformation(const Vector &x, Vector &y)
{
   // set the initial configuration. Having this different from the
   // reference configuration can help convergence
   y = x;
   y[1] = x[1] + 0.25*x[0];
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "scheduler.h"

#include <assert.h>
#include <boost/bind.hpp>
#include <utility>

CScheduler::CScheduler() : nThreadsServicingQueue(0), stopRequested(false), stopWhenEmpty(false)
{
}

CScheduler::~CScheduler()
{
    assert(nThreadsServicingQueue == 0);
}

#if BOOST_VERSION < 105000
static boost::system_time toPosixTime(const boost::chrono::system_clock::time_point& t)
{
    return boost::posix_time::from_time_t(boost::chrono::system_clock::to_time_t(t));
}
#endif

void CScheduler::serviceQueue()
{
    boost::unique_lock<boost::mutex> lock(newTaskMutex);
    ++nThreadsServicingQueue;

    // newTaskMutex is locked throughout this loop EXCEPT
    // when the thread is waiting or when the user's function
    // is called.
    while (!shouldStop()) {
        try {
            while (!shouldStop() && taskQueue.empty()) {
                // Wait until there is something to do.
                newTaskScheduled.wait(lock);
            }

            // Wait until either there is a new task, or until
            // the time of the first item on the queue:

// wait_until needs boost 1.50 or later; older versions have timed_wait:
#if BOOST_VERSION < 105000
            while (!shouldStop() && !taskQueue.empty() &&
                   newTaskScheduled.timed_wait(lock, toPosixTime(taskQueue.begin()->first))) {
                // Keep waiting until timeout
            }
#else
            while (!shouldStop() && !taskQueue.empty() &&
                   newTaskScheduled.wait_until(lock, taskQueue.begin()->first) != boost::cv_status::timeout) {
                // Keep waiting until timeout
            }
#endif
            // If there are multiple threads, the queue can empty while we're waiting (another
            // thread may service the task we were waiting on).
            if (shouldStop() || taskQueue.empty())
                continue;

            Function f = taskQueue.begin()->second;
            taskQueue.erase(taskQueue.begin());

            // Unlock before calling f, so it can reschedule itself or another task
            // without deadlocking:
            lock.unlock();
            f();
            lock.lock();
        } catch (...) {
            --nThreadsServicingQueue;
            throw;
        }
    }
    --nThreadsServicingQueue;
}

void CScheduler::stop(bool drain)
{
    {
        boost::unique_lock<boost::mutex> lock(newTaskMutex);
        if (drain)
            stopWhenEmpty = true;
        else
            stopRequested = true;
    }
    newTaskScheduled.notify_all();
}

void CScheduler::schedule(CScheduler::Function f, boost::chrono::system_clock::time_point t)
{
    {
        boost::unique_lock<boost::mutex> lock(newTaskMutex);
        taskQueue.insert(std::make_pair(t, f));
    }
    newTaskScheduled.notify_one();
}

void CScheduler::scheduleFromNow(CScheduler::Function f, int64_t deltaSeconds)
{
    schedule(f, boost::chrono::system_clock::now() + boost::chrono::seconds(deltaSeconds));
}

static void Repeat(CScheduler* s, CScheduler::Function f, int64_t deltaSeconds)
{
    f();
    s->scheduleFromNow(boost::bind(&Repeat, s, f, deltaSeconds), deltaSeconds);
}

void CScheduler::scheduleEvery(CScheduler::Function f, int64_t deltaSeconds)
{
    scheduleFromNow(boost::bind(&Repeat, this, f, deltaSeconds), deltaSeconds);
}

size_t CScheduler::getQueueInfo(boost::chrono::system_clock::time_point &first,
                             boost::chrono::system_clock::time_point &last) const
{
    boost::unique_lock<boost::mutex> lock(newTaskMutex);
    size_t result = taskQueue.size();
    if (!taskQueue.empty()) {
        first = taskQueue.begin()->first;
        last = taskQueue.rbegin()->first;
    }
    return result;
}
<commit_msg>Fix scheduler build with some boost versions.<commit_after>// Copyright (c) 2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "scheduler.h"

#include <assert.h>
#include <boost/bind.hpp>
#include <utility>

CScheduler::CScheduler() : nThreadsServicingQueue(0), stopRequested(false), stopWhenEmpty(false)
{
}

CScheduler::~CScheduler()
{
    assert(nThreadsServicingQueue == 0);
}

#if BOOST_VERSION < 105000
static boost::system_time toPosixTime(const boost::chrono::system_clock::time_point& t)
{
    return boost::posix_time::from_time_t(boost::chrono::system_clock::to_time_t(t));
}
#endif

void CScheduler::serviceQueue()
{
    boost::unique_lock<boost::mutex> lock(newTaskMutex);
    ++nThreadsServicingQueue;

    // newTaskMutex is locked throughout this loop EXCEPT
    // when the thread is waiting or when the user's function
    // is called.
    while (!shouldStop()) {
        try {
            while (!shouldStop() && taskQueue.empty()) {
                // Wait until there is something to do.
                newTaskScheduled.wait(lock);
            }

            // Wait until either there is a new task, or until
            // the time of the first item on the queue:

// wait_until needs boost 1.50 or later; older versions have timed_wait:
#if BOOST_VERSION < 105000
            while (!shouldStop() && !taskQueue.empty() &&
                   newTaskScheduled.timed_wait(lock, toPosixTime(taskQueue.begin()->first))) {
                // Keep waiting until timeout
            }
#else
            // Some boost versions have a conflicting overload of wait_until that returns void.
            // Explicitly use a template here to avoid hitting that overload.
            while (!shouldStop() && !taskQueue.empty() &&
                   newTaskScheduled.wait_until<>(lock, taskQueue.begin()->first) != boost::cv_status::timeout) {
                // Keep waiting until timeout
            }
#endif
            // If there are multiple threads, the queue can empty while we're waiting (another
            // thread may service the task we were waiting on).
            if (shouldStop() || taskQueue.empty())
                continue;

            Function f = taskQueue.begin()->second;
            taskQueue.erase(taskQueue.begin());

            // Unlock before calling f, so it can reschedule itself or another task
            // without deadlocking:
            lock.unlock();
            f();
            lock.lock();
        } catch (...) {
            --nThreadsServicingQueue;
            throw;
        }
    }
    --nThreadsServicingQueue;
}

void CScheduler::stop(bool drain)
{
    {
        boost::unique_lock<boost::mutex> lock(newTaskMutex);
        if (drain)
            stopWhenEmpty = true;
        else
            stopRequested = true;
    }
    newTaskScheduled.notify_all();
}

void CScheduler::schedule(CScheduler::Function f, boost::chrono::system_clock::time_point t)
{
    {
        boost::unique_lock<boost::mutex> lock(newTaskMutex);
        taskQueue.insert(std::make_pair(t, f));
    }
    newTaskScheduled.notify_one();
}

void CScheduler::scheduleFromNow(CScheduler::Function f, int64_t deltaSeconds)
{
    schedule(f, boost::chrono::system_clock::now() + boost::chrono::seconds(deltaSeconds));
}

static void Repeat(CScheduler* s, CScheduler::Function f, int64_t deltaSeconds)
{
    f();
    s->scheduleFromNow(boost::bind(&Repeat, s, f, deltaSeconds), deltaSeconds);
}

void CScheduler::scheduleEvery(CScheduler::Function f, int64_t deltaSeconds)
{
    scheduleFromNow(boost::bind(&Repeat, this, f, deltaSeconds), deltaSeconds);
}

size_t CScheduler::getQueueInfo(boost::chrono::system_clock::time_point &first,
                             boost::chrono::system_clock::time_point &last) const
{
    boost::unique_lock<boost::mutex> lock(newTaskMutex);
    size_t result = taskQueue.size();
    if (!taskQueue.empty()) {
        first = taskQueue.begin()->first;
        last = taskQueue.rbegin()->first;
    }
    return result;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <iomanip>
#include <array>
#include <bitset>

struct sudoku_cell{
    using numset = std::bitset<9>;
    sudoku_cell():cells{}{}
    std::array<unsigned,81> cells;
    std::array<numset,81> cands;
    std::array<numset,9> reduced_row;
    std::array<numset,9> reduced_col;

    inline unsigned rc_to_idx(const unsigned row, const unsigned col){
        return 9*row+col;
    }

    inline unsigned idx_to_row(const unsigned idx){
        return idx/9;
    }

    inline unsigned idx_to_col(const unsigned idx){
        return idx%9;
    }

    numset cand_in_row(const unsigned idx){
        numset ret;
        ret.set();
        const unsigned row = idx_to_row(idx);
        for(unsigned i=0;i<9;++i) if(cells[rc_to_idx(row,i)] != 0) ret.reset(cells[rc_to_idx(row,i)]-1);
        return ret;
    }

    numset cand_in_col(const unsigned idx){
        numset ret;
        ret.set();
        const unsigned col = idx_to_col(idx);
        for(unsigned i=0;i<9;++i) if(cells[rc_to_idx(i,col)] != 0) ret.reset(cells[rc_to_idx(i,col)]-1);
        return ret;
    }

    numset cand_in_3x3(const unsigned idx){
        numset ret;
        ret.set();
        const unsigned row_begin = idx_to_row(idx)/3*3;
        const unsigned col_begin = idx_to_col(idx)/3*3;
        for(unsigned i=row_begin;i<row_begin+3;++i){
            for(unsigned j=col_begin;j<col_begin+3;++j){
                if(cells[rc_to_idx(i,j)] != 0) ret.reset(cells[rc_to_idx(i,j)]-1);
            }
        }

        return ret;
    }

    inline unsigned num_of_onbit(const numset& e){ // return least canding number indicated in e
        for(unsigned i=0;i<9;++i) if(e[i]) return i+1;
        return 0; // unreachable
    }

    void solve(){
        gen_cands();
        BEGIN:
            if(reduce_nearby_pair())    goto BEGIN;
            if(solve_3x3())             goto BEGIN;
            if(solve_one_cand())        goto BEGIN;
    }

    bool solve_one_cand(){
    	// solve cells which have only one candidate
        bool changed = false;
        for(unsigned i=0;i<81;++i){
            if(cells[i] == 0){
                if(cands[i].count() == 1){
                    cells[i] = num_of_onbit(cands[i]);
                    rebuild_cand(i);
                    changed = true;
                }
            }
        }
        return changed;
    }

    bool solve_3x3(){
    	// solve cells in 3x3 block
        bool changed = false;
        for(unsigned i=0;i<3;++i){
            for(unsigned j=0;j<3;++j){
                if(solve_each_3x3(i,j)) changed = true;
            }
        }
        return changed;
    }

    bool solve_each_3x3(const unsigned row_3x3, const unsigned col_3x3){
        bool changed = false;
        for(unsigned i=0;i<9;++i){
            bool found = false;
            unsigned idx = 0;
            for(unsigned j=3*row_3x3;j<3*row_3x3+3;++j){
                for(unsigned k=3*col_3x3;k<3*col_3x3+3;++k){
                    auto idx_ = rc_to_idx(j,k);
                    if(cands[idx_][i]){
                        if(found) goto LEND;
                        found = true;
                        idx = idx_;
                    }
                }
            }
            if(cells[idx] == 0 && found){
                cells[idx] = i+1;
                rebuild_cand(idx);
                changed = true;
            }
            LEND: ;
        }
        return changed;
    }

    bool reduce_nearby_pair(){
        bool changed = false;
        for(unsigned i=0;i<3;++i){
            for(unsigned j=0;j<3;++j){
                if(reduce_nearby_pair_3x3(i,j)) changed = true;
            }
        }
        return changed;
    }

    bool reduce_nearby_pair_3x3(const unsigned row_3x3, const unsigned col_3x3){
        bool changed = false;
        for(unsigned i=0;i<9;++i){
            for(unsigned j=3*row_3x3;j<3*row_3x3+3;++j){
                if(
                    !reduced_row[j][i] &&
                    (
                        (cands[rc_to_idx(j,3*col_3x3)][i] && (cands[rc_to_idx(j,3*col_3x3+1)][i] || cands[rc_to_idx(j,3*col_3x3+2)][i]))
                        ||
                        (cands[rc_to_idx(j,3*col_3x3+1)][i] && cands[rc_to_idx(j,3*col_3x3+2)][i])
                    )
                ){
                    for(unsigned k=3*row_3x3;k<3*row_3x3+3;++k){
                        if(j != k){
                            for(unsigned l=3*col_3x3;l<3*col_3x3+3;++l){
                                if(cands[rc_to_idx(k,l)][i]) goto LEND;
                            }
                        }
                    }
                    for(unsigned k=0;k<9;++k){
                        if(k/3*3 != 3*col_3x3) cands[rc_to_idx(j,k)].reset(i);
                    }
                    reduced_row[j].set(i);
                    changed = true;
                    goto LEND;
                }
            }

            for(unsigned j=3*col_3x3;j<3*col_3x3+3;++j){
                if(
                    !reduced_col[j][i] &&
                    (
                        (cands[rc_to_idx(3*row_3x3,j)][i] && (cands[rc_to_idx(3*row_3x3+1,j)][i] || cands[rc_to_idx(3*row_3x3+2,j)][i]))
                        ||
                        (cands[rc_to_idx(3*row_3x3+1,j)][i] && cands[rc_to_idx(3*row_3x3+2,j)][i])                    )
                ){
                    for(unsigned k=3*row_3x3;k<3*row_3x3+3;++k){
                        for(unsigned l=col_3x3*3;l<col_3x3*3+3;++l){
                            if(j == l) continue;
                            if(cands[rc_to_idx(k,l)][i]) goto LEND;
                        }
                    }
                    for(unsigned k=0;k<9;++k){
                        if(k/3*3 != 3*row_3x3) cands[rc_to_idx(k,j)].reset(i);
                    }
                    reduced_col[j].set(i);
                    changed = true;
                    goto LEND;
                }
            }

            LEND: ;
        }
        return changed;
    }

    void gen_cands(){
    	// generate candidates for each cells
        for(unsigned i=0; i<81;++i) if(cells[i] == 0) cands[i] = (cand_in_row(i) & cand_in_col(i) & cand_in_3x3(i));
    }

    void rebuild_cand(unsigned idx){
    	// modify candidates when value of any cells has changed
        const unsigned val = cells[idx];
        const unsigned row = idx_to_row(idx);
        const unsigned col = idx_to_col(idx);
        const unsigned row_begin = row/3*3;
        const unsigned col_begin = col/3*3;
        cands[idx].reset();
        for(unsigned i=0;i<9;++i){
            cands[rc_to_idx(row,i)].reset(val-1);
            cands[rc_to_idx(i,col)].reset(val-1);
        }
        for(unsigned i=row_begin;i<row_begin+3;++i){
            for(unsigned j=col_begin;j<col_begin+3;++j){
                cands[rc_to_idx(i,j)].reset(val-1);
            }
        }
    }

    friend std::ostream& operator<<(std::ostream& os, sudoku_cell& s){
        for (unsigned i=0;i<9;++i){
            os << ' ';
            for(unsigned j=0;j<9;++j){
                os << s.cells[9*i+j] << ((j+1)%3 == 0 && j != 8 ? " | " : " ");
            }
            std::cout << (((i+1)%3 == 0 && i != 8) ? "\n-------+-------+-------\n" : "\n");
        }
        return os;
    }
};

int main(){
    sudoku_cell s;
    s.cells = {{
            #include "problem.txt"
    }};

    std::cout << s << std::endl;
    s.solve();
    std::cout << s << std::endl;
}
<commit_msg>Added new algorithms<commit_after>#include <iostream>
#include <iomanip>
#include <array>
#include <bitset>

struct sudoku_cell{
    using numset = std::bitset<9>;
    sudoku_cell():cells{}{}
    std::array<unsigned,81> cells;
    std::array<numset,81> cands;
    std::array<numset,9> reduced_row;
    std::array<numset,9> reduced_col;

    inline unsigned rc_to_idx(const unsigned row, const unsigned col){
        return 9*row+col;
    }

    inline unsigned idx_to_row(const unsigned idx){
        return idx/9;
    }

    inline unsigned idx_to_col(const unsigned idx){
        return idx%9;
    }

    numset cand_in_row(const unsigned idx){
        numset ret;
        ret.set();
        const unsigned row = idx_to_row(idx);
        for(unsigned i=0;i<9;++i) if(cells[rc_to_idx(row,i)] != 0) ret.reset(cells[rc_to_idx(row,i)]-1);
        return ret;
    }

    numset cand_in_col(const unsigned idx){
        numset ret;
        ret.set();
        const unsigned col = idx_to_col(idx);
        for(unsigned i=0;i<9;++i) if(cells[rc_to_idx(i,col)] != 0) ret.reset(cells[rc_to_idx(i,col)]-1);
        return ret;
    }

    numset cand_in_3x3(const unsigned idx){
        numset ret;
        ret.set();
        const unsigned row_begin = idx_to_row(idx)/3*3;
        const unsigned col_begin = idx_to_col(idx)/3*3;
        for(unsigned i=row_begin;i<row_begin+3;++i){
            for(unsigned j=col_begin;j<col_begin+3;++j){
                if(cells[rc_to_idx(i,j)] != 0) ret.reset(cells[rc_to_idx(i,j)]-1);
            }
        }

        return ret;
    }

    inline unsigned num_of_onbit(const numset& e){ // return least canding number indicated in e
        for(unsigned i=0;i<9;++i) if(e[i]) return i+1;
        return 0; // unreachable
    }

    void solve(){
        gen_cands();
        BEGIN:
            if(reduce_nearby_pair())    goto BEGIN;
            if(solve_3x3())             goto BEGIN;
	    if(solve_row())		goto BEGIN;
	    if(solve_col())		goto BEGIN;
            if(solve_one_cand())        goto BEGIN;
    }

    bool solve_one_cand(){
    	// solve cells which have only one candidate
        bool changed = false;
        for(unsigned i=0;i<81;++i){
            if(cells[i] == 0){
                if(cands[i].count() == 1){
                    cells[i] = num_of_onbit(cands[i]);
                    rebuild_cand(i);
                    changed = true;
                }
            }
        }
        return changed;
    }

    bool solve_3x3(){
    	// solve cells in 3x3 block
        bool changed = false;
        for(unsigned i=0;i<3;++i){
            for(unsigned j=0;j<3;++j){
                if(solve_each_3x3(i,j)) changed = true;
            }
        }
        return changed;
    }

    bool solve_each_3x3(const unsigned row_3x3, const unsigned col_3x3){
        bool changed = false;
        for(unsigned i=0;i<9;++i){
            bool found = false;
            unsigned idx = 0;
            for(unsigned j=3*row_3x3;j<3*row_3x3+3;++j){
                for(unsigned k=3*col_3x3;k<3*col_3x3+3;++k){
                    auto idx_ = rc_to_idx(j,k);
                    if(cands[idx_][i]){
                        if(found) goto LEND;
                        found = true;
                        idx = idx_;
                    }
                }
            }
            if(cells[idx] == 0 && found){
                cells[idx] = i+1;
		rebuild_cand(idx);
                changed = true;
            }
            LEND: ;
        }
        return changed;
    }

    bool solve_row(){
	//solve cells in 3x3 block
	bool changed = false;
	for(unsigned i=0;i<9;++i){
	    if(solve_each_row(i)) changed = true;
	}
	return changed;
    }

    bool solve_each_row(const unsigned row){
        bool changed = false;
        for(unsigned i=0;i<9;++i){
            bool found = false;
            unsigned idx = 0;
            for(unsigned j=0;j<27;++j){
		if(cands[rc_to_idx(row,j)][i]){
		    if(found){
			found = false;
			break;
		    }
		    else{
			found = true;
			idx = rc_to_idx(row,j);
		    }
		}
            }
            if(cells[idx] == 0 && found){
                cells[idx] = i+1;
                rebuild_cand(idx);
                changed = true;
            }
        }
        return changed;
    }

    bool reduce_nearby_pair(){
        bool changed = false;
        for(unsigned i=0;i<3;++i){
            for(unsigned j=0;j<3;++j){
                if(reduce_nearby_pair_3x3(i,j)) changed = true;
            }
        }
        return changed;
    }

    bool solve_col(){
	//solve cells in 3x3 block
	bool changed = false;
	for(unsigned i=0;i<9;++i){
	    if(solve_each_col(i)) changed = true;
	}
	return changed;
    }

    bool solve_each_col(const unsigned col){
        bool changed = false;
        for(unsigned i=0;i<9;++i){
            bool found = false;
            unsigned idx = 0;
            for(unsigned j=0;j<27;++j){
		if(cands[rc_to_idx(j,col)][i]){
		    if(found){
			found = false;
			break;
		    }
		    else{
			found = true;
			idx = rc_to_idx(j,col);
		    }
		}
            }
            if(cells[idx] == 0 && found){
                cells[idx] = i+1;
                rebuild_cand(idx);
                changed = true;
            }
        }
        return changed;
    }

    bool reduce_nearby_pair_3x3(const unsigned row_3x3, const unsigned col_3x3){
        bool changed = false;
        for(unsigned i=0;i<9;++i){
            for(unsigned j=3*row_3x3;j<3*row_3x3+3;++j){
                if(
                    !reduced_row[j][i] &&
                    (
                        (cands[rc_to_idx(j,3*col_3x3)][i] && (cands[rc_to_idx(j,3*col_3x3+1)][i] || cands[rc_to_idx(j,3*col_3x3+2)][i]))
                        ||
                        (cands[rc_to_idx(j,3*col_3x3+1)][i] && cands[rc_to_idx(j,3*col_3x3+2)][i])
                    )
                ){
                    for(unsigned k=3*row_3x3;k<3*row_3x3+3;++k){
                        if(j != k){
                            for(unsigned l=3*col_3x3;l<3*col_3x3+3;++l){
                                if(cands[rc_to_idx(k,l)][i]) goto LEND;
                            }
                        }
                    }
                    for(unsigned k=0;k<9;++k){
                        if(k/3*3 != 3*col_3x3) cands[rc_to_idx(j,k)].reset(i);
                    }
                    reduced_row[j].set(i);
                    changed = true;
                    goto LEND;
                }
            }

            for(unsigned j=3*col_3x3;j<3*col_3x3+3;++j){
                if(
                    !reduced_col[j][i] &&
                    (
                        (cands[rc_to_idx(3*row_3x3,j)][i] && (cands[rc_to_idx(3*row_3x3+1,j)][i] || cands[rc_to_idx(3*row_3x3+2,j)][i]))
                        ||
                        (cands[rc_to_idx(3*row_3x3+1,j)][i] && cands[rc_to_idx(3*row_3x3+2,j)][i])                    )
                ){
                    for(unsigned k=3*row_3x3;k<3*row_3x3+3;++k){
                        for(unsigned l=col_3x3*3;l<col_3x3*3+3;++l){
                            if(j == l) continue;
                            if(cands[rc_to_idx(k,l)][i]) goto LEND;
                        }
                    }
                    for(unsigned k=0;k<9;++k){
                        if(k/3*3 != 3*row_3x3) cands[rc_to_idx(k,j)].reset(i);
                    }
                    reduced_col[j].set(i);
                    changed = true;
                    goto LEND;
                }
            }

            LEND: ;
        }
        return changed;
    }

    void gen_cands(){
    	// generate candidates for each cells
        for(unsigned i=0; i<81;++i) if(cells[i] == 0) cands[i] = (cand_in_row(i) & cand_in_col(i) & cand_in_3x3(i));
    }

    void rebuild_cand(unsigned idx){
    	// modify candidates when value of any cells has changed
        const unsigned val = cells[idx];
        const unsigned row = idx_to_row(idx);
        const unsigned col = idx_to_col(idx);
        const unsigned row_begin = row/3*3;
        const unsigned col_begin = col/3*3;
        cands[idx].reset();
        for(unsigned i=0;i<9;++i){
            cands[rc_to_idx(row,i)].reset(val-1);
            cands[rc_to_idx(i,col)].reset(val-1);
        }
        for(unsigned i=row_begin;i<row_begin+3;++i){
            for(unsigned j=col_begin;j<col_begin+3;++j){
                cands[rc_to_idx(i,j)].reset(val-1);
            }
        }
    }

    friend std::ostream& operator<<(std::ostream& os, sudoku_cell& s){
        for (unsigned i=0;i<9;++i){
            os << ' ';
            for(unsigned j=0;j<9;++j){
                os << s.cells[9*i+j] << ((j+1)%3 == 0 && j != 8 ? " | " : " ");
            }
            std::cout << (((i+1)%3 == 0 && i != 8) ? "\n-------+-------+-------\n" : "\n");
        }
        return os;
    }
};

int main(){
    sudoku_cell s;
    s.cells = {{
            #include "problem.txt"
    }};

    std::cout << s << std::endl;
    s.solve();
    std::cout << s << std::endl;
}
<|endoftext|>


<commit_before>/* $Id$ */

/*
 * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*****************************************************************************
 UserTests.cpp

 Contains test cases to C_InitPIN, C_SetPIN, C_Login, and C_Logout
 *****************************************************************************/

#include <stdlib.h>
#include <string.h>
#include <cppunit/extensions/HelperMacros.h>
#include "UserTests.h"
#include "testconfig.h"

CPPUNIT_TEST_SUITE_REGISTRATION(UserTests);

void UserTests::setUp()
{
	setenv("SOFTHSM2_CONF", "./softhsm2.conf", 1);

	CK_UTF8CHAR pin[] = SLOT_0_SO1_PIN;
	CK_ULONG pinLength = sizeof(pin) - 1;
	CK_UTF8CHAR label[32];
	memset(label, ' ', 32);
	memcpy(label, "token1", strlen("token1"));

	// (Re)initialize the token
	CK_RV rv = C_Initialize(NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_OK);
	rv = C_InitToken(SLOT_INIT_TOKEN, pin, pinLength, label);
	CPPUNIT_ASSERT(rv == CKR_OK);
	C_Finalize(NULL_PTR);
}

void UserTests::tearDown()
{
	// Just make sure that we finalize any previous tests
	C_Finalize(NULL_PTR);
}

void UserTests::testInitPIN()
{
	CK_RV rv;
	CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
	CK_ULONG pinLength = sizeof(pin) - 1;
	CK_UTF8CHAR sopin[] = SLOT_0_SO1_PIN;
	CK_ULONG sopinLength = sizeof(sopin) - 1;
	CK_SESSION_HANDLE hSession;

	// Just make sure that we finalize any previous tests
	C_Finalize(NULL_PTR);

	rv = C_InitPIN(hSession, pin, pinLength);
	CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);

	rv = C_Initialize(NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_InitPIN(hSession, pin, pinLength);
	CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);

	rv = C_Login(hSession, CKU_SO, sopin, sopinLength);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_InitPIN(CK_INVALID_HANDLE, pin, pinLength);
	CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);

	rv = C_InitPIN(hSession, pin, 0);
	CPPUNIT_ASSERT(rv == CKR_PIN_LEN_RANGE);

	rv = C_InitPIN(hSession, pin, pinLength);
	CPPUNIT_ASSERT(rv == CKR_OK);
}

void UserTests::testLogin()
{
	CK_RV rv;
	CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
	CK_ULONG pinLength = sizeof(pin) - 1;
	CK_UTF8CHAR sopin[] = SLOT_0_SO1_PIN;
	CK_ULONG sopinLength = sizeof(sopin) - 1;
	CK_SESSION_HANDLE hSession[2];

	// Just make sure that we finalize any previous tests
	C_Finalize(NULL_PTR);

	// Set up user PIN
	rv = C_Initialize(NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_OK);
	rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession[0]);
	CPPUNIT_ASSERT(rv == CKR_OK);
	rv = C_Login(hSession[0], CKU_SO, sopin, sopinLength);
	CPPUNIT_ASSERT(rv == CKR_OK);
	rv = C_InitPIN(hSession[0], pin, pinLength);
	CPPUNIT_ASSERT(rv == CKR_OK);
	C_Finalize(NULL_PTR);

	rv = C_Login(hSession[0], CKU_SO, sopin, sopinLength);
	CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);

	rv = C_Initialize(NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession[0]);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Login(CK_INVALID_HANDLE, CKU_SO, sopin, sopinLength);
	CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);

	rv = C_Login(hSession[0], CKU_SO, NULL_PTR, sopinLength);
	CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);

	rv = C_Login(hSession[0], CKU_SO, sopin, 0);
	CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);

	rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession[1]);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Login(hSession[0], CKU_SO, sopin, sopinLength);
	CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY_EXISTS);

	rv = C_CloseSession(hSession[1]);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Login(hSession[0], CKU_USER, pin, pinLength);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Login(hSession[0], CKU_SO, sopin, sopinLength);
	CPPUNIT_ASSERT(rv == CKR_USER_ANOTHER_ALREADY_LOGGED_IN);

	rv = C_Logout(hSession[0]);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Login(hSession[0], CKU_SO, sopin, sopinLength);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Login(hSession[0], CKU_SO, sopin, sopinLength);
	CPPUNIT_ASSERT(rv == CKR_USER_ALREADY_LOGGED_IN);

	rv = C_Login(hSession[0], CKU_USER, pin, pinLength);
	CPPUNIT_ASSERT(rv == CKR_USER_ANOTHER_ALREADY_LOGGED_IN);

	rv = C_Logout(hSession[0]);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Login(hSession[0], CKU_USER, pin, pinLength - 1);
	CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);

	rv = C_Login(hSession[0], CKU_USER, pin, pinLength);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Login(hSession[0], CKU_USER, pin, pinLength);
	CPPUNIT_ASSERT(rv == CKR_USER_ALREADY_LOGGED_IN);
}

void UserTests::testLogout()
{
	CK_RV rv;
	CK_UTF8CHAR pin[] = SLOT_0_SO1_PIN;
	CK_ULONG pinLength = sizeof(pin) - 1;
	CK_SESSION_HANDLE hSession;

	// Just make sure that we finalize any previous tests
	C_Finalize(NULL_PTR);

	rv = C_Logout(hSession);
	CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);

	rv = C_Initialize(NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Login(hSession, CKU_SO, pin, pinLength);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Logout(CK_INVALID_HANDLE);
	CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);

	rv = C_Logout(hSession);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Logout(hSession);
	CPPUNIT_ASSERT(rv == CKR_OK);
}

void UserTests::testSetPIN()
{
	CK_RV rv;
	CK_UTF8CHAR pin1[] = SLOT_0_USER1_PIN;
	CK_ULONG pin1Length = sizeof(pin1) - 1;
	CK_UTF8CHAR pin2[] = SLOT_0_USER2_PIN;
	CK_ULONG pin2Length = sizeof(pin2) - 1;
	CK_UTF8CHAR so1pin[] = SLOT_0_SO1_PIN;
	CK_ULONG so1pinLength = sizeof(so1pin) - 1;
	CK_UTF8CHAR so2pin[] = SLOT_0_SO2_PIN;
	CK_ULONG so2pinLength = sizeof(so2pin) - 1;
	CK_SESSION_HANDLE hSession;

	// Just make sure that we finalize any previous tests
	C_Finalize(NULL_PTR);

	// Set up user PIN
	rv = C_Initialize(NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_OK);
	rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
	CPPUNIT_ASSERT(rv == CKR_OK);
	rv = C_Login(hSession, CKU_SO, so1pin, so1pinLength);
	CPPUNIT_ASSERT(rv == CKR_OK);
	rv = C_InitPIN(hSession, pin1, pin1Length);
	CPPUNIT_ASSERT(rv == CKR_OK);
	C_Finalize(NULL_PTR);

	rv = C_SetPIN(hSession, pin1, pin1Length, pin2, pin2Length);
	CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);

	rv = C_Initialize(NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_SetPIN(CK_INVALID_HANDLE, pin1, pin1Length, pin2, pin2Length);
	CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);

	rv = C_SetPIN(hSession, pin1, pin1Length, pin2, pin2Length);
	CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);

	rv = C_CloseSession(hSession);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_SetPIN(hSession, NULL_PTR, pin1Length, pin2, pin2Length);
	CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);

	rv = C_SetPIN(hSession, pin1, pin1Length, NULL_PTR, pin2Length);
	CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);

	rv = C_SetPIN(hSession, pin1, pin1Length, pin2, 0);
	CPPUNIT_ASSERT(rv == CKR_PIN_LEN_RANGE);

	rv = C_SetPIN(hSession, pin2, pin2Length, pin2, pin2Length);
	CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);

	rv = C_SetPIN(hSession, pin1, pin1Length, pin2, pin2Length);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Login(hSession, CKU_USER, pin2, pin2Length);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_SetPIN(hSession, pin1, pin1Length, pin2, pin2Length);
	CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);

	rv = C_SetPIN(hSession, pin2, pin2Length, pin1, pin1Length);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Login(hSession, CKU_SO, so1pin, so1pinLength);
	CPPUNIT_ASSERT(rv == CKR_USER_ANOTHER_ALREADY_LOGGED_IN);

	rv = C_Logout(hSession);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Login(hSession, CKU_SO, so1pin, so1pinLength);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_SetPIN(hSession, so2pin, so2pinLength, so2pin, so2pinLength);
	CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);

	rv = C_SetPIN(hSession, so1pin, so1pinLength, so2pin, so2pinLength);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_SetPIN(hSession, so1pin, so1pinLength, so1pin, so1pinLength);
	CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);

	rv = C_SetPIN(hSession, so2pin, so2pinLength, so1pin, so1pinLength);
	CPPUNIT_ASSERT(rv == CKR_OK);
}
<commit_msg>Also check for CKR_USER_PIN_NOT_INITIALIZED<commit_after>/* $Id$ */

/*
 * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*****************************************************************************
 UserTests.cpp

 Contains test cases to C_InitPIN, C_SetPIN, C_Login, and C_Logout
 *****************************************************************************/

#include <stdlib.h>
#include <string.h>
#include <cppunit/extensions/HelperMacros.h>
#include "UserTests.h"
#include "testconfig.h"

CPPUNIT_TEST_SUITE_REGISTRATION(UserTests);

void UserTests::setUp()
{
	setenv("SOFTHSM2_CONF", "./softhsm2.conf", 1);

	CK_UTF8CHAR pin[] = SLOT_0_SO1_PIN;
	CK_ULONG pinLength = sizeof(pin) - 1;
	CK_UTF8CHAR label[32];
	memset(label, ' ', 32);
	memcpy(label, "token1", strlen("token1"));

	// (Re)initialize the token
	CK_RV rv = C_Initialize(NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_OK);
	rv = C_InitToken(SLOT_INIT_TOKEN, pin, pinLength, label);
	CPPUNIT_ASSERT(rv == CKR_OK);
	C_Finalize(NULL_PTR);
}

void UserTests::tearDown()
{
	// Just make sure that we finalize any previous tests
	C_Finalize(NULL_PTR);
}

void UserTests::testInitPIN()
{
	CK_RV rv;
	CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
	CK_ULONG pinLength = sizeof(pin) - 1;
	CK_UTF8CHAR sopin[] = SLOT_0_SO1_PIN;
	CK_ULONG sopinLength = sizeof(sopin) - 1;
	CK_SESSION_HANDLE hSession;

	// Just make sure that we finalize any previous tests
	C_Finalize(NULL_PTR);

	rv = C_InitPIN(hSession, pin, pinLength);
	CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);

	rv = C_Initialize(NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_InitPIN(hSession, pin, pinLength);
	CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);

	rv = C_Login(hSession, CKU_SO, sopin, sopinLength);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_InitPIN(CK_INVALID_HANDLE, pin, pinLength);
	CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);

	rv = C_InitPIN(hSession, pin, 0);
	CPPUNIT_ASSERT(rv == CKR_PIN_LEN_RANGE);

	rv = C_InitPIN(hSession, pin, pinLength);
	CPPUNIT_ASSERT(rv == CKR_OK);
}

void UserTests::testLogin()
{
	CK_RV rv;
	CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
	CK_ULONG pinLength = sizeof(pin) - 1;
	CK_UTF8CHAR sopin[] = SLOT_0_SO1_PIN;
	CK_ULONG sopinLength = sizeof(sopin) - 1;
	CK_SESSION_HANDLE hSession[2];

	// Just make sure that we finalize any previous tests
	C_Finalize(NULL_PTR);

	// Set up user PIN
	rv = C_Initialize(NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_OK);
	rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession[0]);
	CPPUNIT_ASSERT(rv == CKR_OK);
	rv = C_Login(hSession[0], CKU_USER, pin, pinLength);
	CPPUNIT_ASSERT(rv == CKR_USER_PIN_NOT_INITIALIZED);
	rv = C_Login(hSession[0], CKU_SO, sopin, sopinLength);
	CPPUNIT_ASSERT(rv == CKR_OK);
	rv = C_InitPIN(hSession[0], pin, pinLength);
	CPPUNIT_ASSERT(rv == CKR_OK);
	C_Finalize(NULL_PTR);

	rv = C_Login(hSession[0], CKU_SO, sopin, sopinLength);
	CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);

	rv = C_Initialize(NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession[0]);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Login(CK_INVALID_HANDLE, CKU_SO, sopin, sopinLength);
	CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);

	rv = C_Login(hSession[0], CKU_SO, NULL_PTR, sopinLength);
	CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);

	rv = C_Login(hSession[0], CKU_SO, sopin, 0);
	CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);

	rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession[1]);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Login(hSession[0], CKU_SO, sopin, sopinLength);
	CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY_EXISTS);

	rv = C_CloseSession(hSession[1]);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Login(hSession[0], CKU_USER, pin, pinLength);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Login(hSession[0], CKU_SO, sopin, sopinLength);
	CPPUNIT_ASSERT(rv == CKR_USER_ANOTHER_ALREADY_LOGGED_IN);

	rv = C_Logout(hSession[0]);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Login(hSession[0], CKU_SO, sopin, sopinLength);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Login(hSession[0], CKU_SO, sopin, sopinLength);
	CPPUNIT_ASSERT(rv == CKR_USER_ALREADY_LOGGED_IN);

	rv = C_Login(hSession[0], CKU_USER, pin, pinLength);
	CPPUNIT_ASSERT(rv == CKR_USER_ANOTHER_ALREADY_LOGGED_IN);

	rv = C_Logout(hSession[0]);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Login(hSession[0], CKU_USER, pin, pinLength - 1);
	CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);

	rv = C_Login(hSession[0], CKU_USER, pin, pinLength);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Login(hSession[0], CKU_USER, pin, pinLength);
	CPPUNIT_ASSERT(rv == CKR_USER_ALREADY_LOGGED_IN);
}

void UserTests::testLogout()
{
	CK_RV rv;
	CK_UTF8CHAR pin[] = SLOT_0_SO1_PIN;
	CK_ULONG pinLength = sizeof(pin) - 1;
	CK_SESSION_HANDLE hSession;

	// Just make sure that we finalize any previous tests
	C_Finalize(NULL_PTR);

	rv = C_Logout(hSession);
	CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);

	rv = C_Initialize(NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Login(hSession, CKU_SO, pin, pinLength);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Logout(CK_INVALID_HANDLE);
	CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);

	rv = C_Logout(hSession);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Logout(hSession);
	CPPUNIT_ASSERT(rv == CKR_OK);
}

void UserTests::testSetPIN()
{
	CK_RV rv;
	CK_UTF8CHAR pin1[] = SLOT_0_USER1_PIN;
	CK_ULONG pin1Length = sizeof(pin1) - 1;
	CK_UTF8CHAR pin2[] = SLOT_0_USER2_PIN;
	CK_ULONG pin2Length = sizeof(pin2) - 1;
	CK_UTF8CHAR so1pin[] = SLOT_0_SO1_PIN;
	CK_ULONG so1pinLength = sizeof(so1pin) - 1;
	CK_UTF8CHAR so2pin[] = SLOT_0_SO2_PIN;
	CK_ULONG so2pinLength = sizeof(so2pin) - 1;
	CK_SESSION_HANDLE hSession;

	// Just make sure that we finalize any previous tests
	C_Finalize(NULL_PTR);

	// Set up user PIN
	rv = C_Initialize(NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_OK);
	rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
	CPPUNIT_ASSERT(rv == CKR_OK);
	rv = C_Login(hSession, CKU_SO, so1pin, so1pinLength);
	CPPUNIT_ASSERT(rv == CKR_OK);
	rv = C_InitPIN(hSession, pin1, pin1Length);
	CPPUNIT_ASSERT(rv == CKR_OK);
	C_Finalize(NULL_PTR);

	rv = C_SetPIN(hSession, pin1, pin1Length, pin2, pin2Length);
	CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);

	rv = C_Initialize(NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_SetPIN(CK_INVALID_HANDLE, pin1, pin1Length, pin2, pin2Length);
	CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);

	rv = C_SetPIN(hSession, pin1, pin1Length, pin2, pin2Length);
	CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);

	rv = C_CloseSession(hSession);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_SetPIN(hSession, NULL_PTR, pin1Length, pin2, pin2Length);
	CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);

	rv = C_SetPIN(hSession, pin1, pin1Length, NULL_PTR, pin2Length);
	CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);

	rv = C_SetPIN(hSession, pin1, pin1Length, pin2, 0);
	CPPUNIT_ASSERT(rv == CKR_PIN_LEN_RANGE);

	rv = C_SetPIN(hSession, pin2, pin2Length, pin2, pin2Length);
	CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);

	rv = C_SetPIN(hSession, pin1, pin1Length, pin2, pin2Length);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Login(hSession, CKU_USER, pin2, pin2Length);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_SetPIN(hSession, pin1, pin1Length, pin2, pin2Length);
	CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);

	rv = C_SetPIN(hSession, pin2, pin2Length, pin1, pin1Length);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Login(hSession, CKU_SO, so1pin, so1pinLength);
	CPPUNIT_ASSERT(rv == CKR_USER_ANOTHER_ALREADY_LOGGED_IN);

	rv = C_Logout(hSession);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Login(hSession, CKU_SO, so1pin, so1pinLength);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_SetPIN(hSession, so2pin, so2pinLength, so2pin, so2pinLength);
	CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);

	rv = C_SetPIN(hSession, so1pin, so1pinLength, so2pin, so2pinLength);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_SetPIN(hSession, so1pin, so1pinLength, so1pin, so1pinLength);
	CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);

	rv = C_SetPIN(hSession, so2pin, so2pinLength, so1pin, so1pinLength);
	CPPUNIT_ASSERT(rv == CKR_OK);
}
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2007-2009, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
//     * Neither the name of Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#ifndef IE_CORE_TYPEDPARAMETER_INL
#define IE_CORE_TYPEDPARAMETER_INL

#include "boost/static_assert.hpp"

#include "IECore/TypedParameter.h"
#include "IECore/CompoundObject.h"

namespace IECore
{

/////////////////////////////////////////////////////////////////////////////////////
// constructor stuff
/////////////////////////////////////////////////////////////////////////////////////

template<typename T>
static Parameter::PresetsContainer convertPresets( const typename TypedParameter<T>::PresetsContainer &p )
{
	Parameter::PresetsContainer result;
	for( typename TypedParameter<T>::PresetsContainer::const_iterator it=p.begin(); it!=p.end(); it++ )
	{
		result.push_back( typename Parameter::PresetsContainer::value_type( it->first, new ObjectType( it->second ) ) );
	}
	return result;
}

template<typename T>
static Parameter::PresetsContainer convertPresets( const typename TypedParameter<T>::ObjectPresetsContainer &p )
{
	Parameter::PresetsContainer result;
	for( typename TypedParameter<T>::ObjectPresetsContainer::const_iterator it=p.begin(); it!=p.end(); it++ )
	{
		result.push_back( typename Parameter::PresetsContainer::value_type( it->first, it->second ) );
	}
	return result;
}

template<typename T>
TypedParameter<T>::TypedParameter( const std::string &name, const std::string &description, const T &defaultValue,
	const PresetsContainer &presets, bool presetsOnly, ConstCompoundObjectPtr userData )
	:	Parameter( name, description, new ObjectType( defaultValue ), convertPresets<T>( presets ), presetsOnly, userData )
{
}

template<typename T>
TypedParameter<T>::TypedParameter( const std::string &name, const std::string &description, ObjectTypePtr defaultValue,
	const ObjectPresetsContainer &presets, bool presetsOnly, ConstCompoundObjectPtr userData )
	:	Parameter( name, description, defaultValue, convertPresets<T>( presets ), presetsOnly, userData )
{
}

/////////////////////////////////////////////////////////////////////////////////////
// runtimetyped stuff
/////////////////////////////////////////////////////////////////////////////////////

template <class T>
TypeId TypedParameter<T>::typeId() const
{
	return staticTypeId();
}

template <class T>
TypeId TypedParameter<T>::staticTypeId()
{
	BOOST_STATIC_ASSERT( sizeof(T) == 0 ); // this function must be specialised for each type!
	return InvalidTypeId;
}

template <class T>
std::string TypedParameter<T>::typeName() const
{
	return staticTypeName();
}

template <class T>
std::string TypedParameter<T>::staticTypeName()
{
	BOOST_STATIC_ASSERT( sizeof(T) == 0 ); // this function must be specialised for each type!
	return "";
}

template<class T>
bool TypedParameter<T>::isInstanceOf( TypeId typeId ) const
{
	if( typeId==staticTypeId() )
	{
		return true;
	}
	return Parameter::isInstanceOf( typeId );
}

template<class T>
bool TypedParameter<T>::isInstanceOf( const std::string &typeName ) const
{
	if( typeName==staticTypeName() )
	{
		return true;
	}
	return Parameter::isInstanceOf( typeName );
}

template<class T>
bool TypedParameter<T>::inheritsFrom( TypeId typeId )
{
	return Parameter::staticTypeId()==typeId ? true : Parameter::inheritsFrom( typeId );
}

template<class T>
bool TypedParameter<T>::inheritsFrom( const std::string &typeName )
{
	return Parameter::staticTypeName()==typeName ? true : Parameter::inheritsFrom( typeName );
}

/////////////////////////////////////////////////////////////////////////////////////
// other stuff
/////////////////////////////////////////////////////////////////////////////////////

template<typename T>
bool TypedParameter<T>::valueValid( ConstObjectPtr value, std::string *reason ) const
{
	if( !Parameter::valueValid( value, reason ) )
	{
		return false;
	}
	ConstObjectTypePtr tValue = runTimeCast<const ObjectType>( value );
	if( !tValue )
	{
		if( reason )
		{
			*reason = std::string( "Value is not an instance of \"" ) + ObjectType::staticTypeName() + "\"";
		}
		return false;
	}
	return true;
}

template<typename T>
const typename TypedParameter<T>::ValueType &TypedParameter<T>::typedDefaultValue() const
{
	return boost::static_pointer_cast<const ObjectType>( defaultValue() )->readable();
}

template<typename T>
typename TypedParameter<T>::ValueType &TypedParameter<T>::getTypedValue()
{
	ConstObjectTypePtr tValue = runTimeCast<const ObjectType>( getValue() );
	if( !tValue )
	{
		throw Exception( std::string( "Value is not an instance of \"" ) + ObjectType::staticTypeName() + "\"");
	}
	return boost::static_pointer_cast<ObjectType>( getValue() )->writable();
}

template<typename T>
const typename TypedParameter<T>::ValueType &TypedParameter<T>::getTypedValue() const
{
	ConstObjectTypePtr tValue = runTimeCast<const ObjectType>( getValue() );
	if( !tValue )
	{
		throw Exception( std::string( "Value is not an instance of \"" ) + ObjectType::staticTypeName() + "\"");
	}
	return boost::static_pointer_cast<const ObjectType>( getValue() )->readable();
}

template<typename T>
void TypedParameter<T>::setTypedValue( const T &value )
{
	setValue( new ObjectType( value ) );
}

/////////////////////////////////////////////////////////////////////////////////////
// specialisation and template instantiation
/////////////////////////////////////////////////////////////////////////////////////

#define IE_CORE_DEFINETYPEDPARAMETERSPECIALISATION( T, TNAME )						\
																					\
	template<>																		\
	TypeId TypedParameter<T>::staticTypeId()										\
	{																				\
		return TNAME ## TypeId;														\
	}																				\
																					\
	template<>																		\
	std::string TypedParameter<T>::staticTypeName()									\
	{																				\
		return # TNAME;																\
	}																				\
																					\
	template class TypedParameter<T>;

}

#endif // IE_CORE_TYPEDPARAMETER_INL
<commit_msg>gcc 4.1.2 fix<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2007-2009, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
//     * Neither the name of Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#ifndef IE_CORE_TYPEDPARAMETER_INL
#define IE_CORE_TYPEDPARAMETER_INL

#include "boost/static_assert.hpp"

#include "IECore/TypedParameter.h"
#include "IECore/CompoundObject.h"

namespace IECore
{

/////////////////////////////////////////////////////////////////////////////////////
// constructor stuff
/////////////////////////////////////////////////////////////////////////////////////

template<typename T>
static Parameter::PresetsContainer convertPresets( const typename TypedParameter<T>::PresetsContainer &p )
{
	Parameter::PresetsContainer result;
	for( typename TypedParameter<T>::PresetsContainer::const_iterator it=p.begin(); it!=p.end(); it++ )
	{
		result.push_back( typename Parameter::PresetsContainer::value_type( it->first, new (typename TypedParameter<T>::ObjectType)( it->second ) ) );
	}
	return result;
}

template<typename T>
static Parameter::PresetsContainer convertPresets( const typename TypedParameter<T>::ObjectPresetsContainer &p )
{
	Parameter::PresetsContainer result;
	for( typename TypedParameter<T>::ObjectPresetsContainer::const_iterator it=p.begin(); it!=p.end(); it++ )
	{
		result.push_back( typename Parameter::PresetsContainer::value_type( it->first, it->second ) );
	}
	return result;
}

template<typename T>
TypedParameter<T>::TypedParameter( const std::string &name, const std::string &description, const T &defaultValue,
	const PresetsContainer &presets, bool presetsOnly, ConstCompoundObjectPtr userData )
	:	Parameter( name, description, new ObjectType( defaultValue ), convertPresets<T>( presets ), presetsOnly, userData )
{
}

template<typename T>
TypedParameter<T>::TypedParameter( const std::string &name, const std::string &description, ObjectTypePtr defaultValue,
	const ObjectPresetsContainer &presets, bool presetsOnly, ConstCompoundObjectPtr userData )
	:	Parameter( name, description, defaultValue, convertPresets<T>( presets ), presetsOnly, userData )
{
}

/////////////////////////////////////////////////////////////////////////////////////
// runtimetyped stuff
/////////////////////////////////////////////////////////////////////////////////////

template <class T>
TypeId TypedParameter<T>::typeId() const
{
	return staticTypeId();
}

template <class T>
TypeId TypedParameter<T>::staticTypeId()
{
	BOOST_STATIC_ASSERT( sizeof(T) == 0 ); // this function must be specialised for each type!
	return InvalidTypeId;
}

template <class T>
std::string TypedParameter<T>::typeName() const
{
	return staticTypeName();
}

template <class T>
std::string TypedParameter<T>::staticTypeName()
{
	BOOST_STATIC_ASSERT( sizeof(T) == 0 ); // this function must be specialised for each type!
	return "";
}

template<class T>
bool TypedParameter<T>::isInstanceOf( TypeId typeId ) const
{
	if( typeId==staticTypeId() )
	{
		return true;
	}
	return Parameter::isInstanceOf( typeId );
}

template<class T>
bool TypedParameter<T>::isInstanceOf( const std::string &typeName ) const
{
	if( typeName==staticTypeName() )
	{
		return true;
	}
	return Parameter::isInstanceOf( typeName );
}

template<class T>
bool TypedParameter<T>::inheritsFrom( TypeId typeId )
{
	return Parameter::staticTypeId()==typeId ? true : Parameter::inheritsFrom( typeId );
}

template<class T>
bool TypedParameter<T>::inheritsFrom( const std::string &typeName )
{
	return Parameter::staticTypeName()==typeName ? true : Parameter::inheritsFrom( typeName );
}

/////////////////////////////////////////////////////////////////////////////////////
// other stuff
/////////////////////////////////////////////////////////////////////////////////////

template<typename T>
bool TypedParameter<T>::valueValid( ConstObjectPtr value, std::string *reason ) const
{
	if( !Parameter::valueValid( value, reason ) )
	{
		return false;
	}
	ConstObjectTypePtr tValue = runTimeCast<const ObjectType>( value );
	if( !tValue )
	{
		if( reason )
		{
			*reason = std::string( "Value is not an instance of \"" ) + ObjectType::staticTypeName() + "\"";
		}
		return false;
	}
	return true;
}

template<typename T>
const typename TypedParameter<T>::ValueType &TypedParameter<T>::typedDefaultValue() const
{
	return boost::static_pointer_cast<const ObjectType>( defaultValue() )->readable();
}

template<typename T>
typename TypedParameter<T>::ValueType &TypedParameter<T>::getTypedValue()
{
	ConstObjectTypePtr tValue = runTimeCast<const ObjectType>( getValue() );
	if( !tValue )
	{
		throw Exception( std::string( "Value is not an instance of \"" ) + ObjectType::staticTypeName() + "\"");
	}
	return boost::static_pointer_cast<ObjectType>( getValue() )->writable();
}

template<typename T>
const typename TypedParameter<T>::ValueType &TypedParameter<T>::getTypedValue() const
{
	ConstObjectTypePtr tValue = runTimeCast<const ObjectType>( getValue() );
	if( !tValue )
	{
		throw Exception( std::string( "Value is not an instance of \"" ) + ObjectType::staticTypeName() + "\"");
	}
	return boost::static_pointer_cast<const ObjectType>( getValue() )->readable();
}

template<typename T>
void TypedParameter<T>::setTypedValue( const T &value )
{
	setValue( new ObjectType( value ) );
}

/////////////////////////////////////////////////////////////////////////////////////
// specialisation and template instantiation
/////////////////////////////////////////////////////////////////////////////////////

#define IE_CORE_DEFINETYPEDPARAMETERSPECIALISATION( T, TNAME )						\
																					\
	template<>																		\
	TypeId TypedParameter<T>::staticTypeId()										\
	{																				\
		return TNAME ## TypeId;														\
	}																				\
																					\
	template<>																		\
	std::string TypedParameter<T>::staticTypeName()									\
	{																				\
		return # TNAME;																\
	}																				\
																					\
	template class TypedParameter<T>;

}

#endif // IE_CORE_TYPEDPARAMETER_INL
<|endoftext|>


<commit_before>#include "EventSystem.hpp"

#include <algorithm>
#include <type_traits>

namespace Kunlaboro
{

	namespace detail
	{

		template<typename Event>
		struct EventType
		{
			std::function<void(const Event&)> Func;
		};

		struct BaseComponentEvent : public EventSystem::BaseEvent
		{
			ComponentId Component;
		};
		template<typename Event>
		struct ComponentEvent : public BaseComponentEvent, public EventType<Event>
		{ };

		struct BaseLooseEvent : public EventSystem::BaseEvent
		{
			std::size_t ID;
		};
		template<typename Event>
		struct LooseEvent : public BaseLooseEvent, public EventType<Event>
		{ };

	}

	template<typename Event, typename Functor>
	void EventSystem::eventRegister(ComponentId cId, Functor&& func)
	{
		auto& list = mEvents[typeid(Event)];

		auto* ev = new detail::ComponentEvent<Event>();
		ev->Component = cId;
		ev->Func = std::move(func);
		ev->Type = sComponentEvent;

		list.push_back(ev);
	}
	template<typename Event, typename Functor>
	std::size_t EventSystem::eventRegister(Functor&& func)
	{
		auto& list = mEvents[typeid(Event)];

		auto* ev = new detail::LooseEvent<Event>();
		ev->Func = std::move(func);
		ev->ID = list.size();
		ev->Type = sLooseEvent;

		list.push_back(ev);
		return ev->ID;
	}
	template<typename Event>
	void EventSystem::eventUnregister(ComponentId cId)
	{
		auto& list = mEvents[typeid(Event)];

		auto it = std::find_if(list.cbegin(), list.cend(), [cId](const BaseEvent* ev) {
			return ev->Type == sComponentEvent && static_cast<const detail::BaseComponentEvent*>(ev)->Component == cId;
		});

		if (it != list.cend())
			list.erase(it);
	}
	template<typename Event>
	void EventSystem::eventUnregister(std::size_t id)
	{
		auto& list = mEvents[typeid(Event)];

		auto it = std::find_if(list.cbegin(), list.cend(), [cId](const BaseEvent* ev) {
			return ev->Type == sLooseEvent && static_cast<const detail::BaseLooseEvent*>(ev)->Component == cId;
		});

		if (it != list.cend())
			list.erase(it);
	}
	template<typename Event>
	void EventSystem::eventEmit(const Event& toSend) const
	{
		if (mEvents.count(typeid(Event)) == 0)
			return;

		const auto& list = mEvents.at(typeid(Event));

		for (auto& ev : list)
		{
			if (ev->Type == sLooseEvent)
				static_cast<const detail::LooseEvent<Event>*>(ev)->Func(toSend);
			else
				static_cast<const detail::ComponentEvent<Event>*>(ev)->Func(toSend);
		}
	}
	template<typename Event, typename... Args>
	void EventSystem::eventEmit(Args... args) const
	{
		// static_assert(std::is_trivial<Event>::value, "Must be a POD type.");

		Event toSend{ std::forward<Args>(args)... };
		eventEmit(toSend);
	}

}<commit_msg>Pass along the correct ID to the lambda<commit_after>#include "EventSystem.hpp"

#include <algorithm>
#include <type_traits>

namespace Kunlaboro
{

	namespace detail
	{

		template<typename Event>
		struct EventType
		{
			std::function<void(const Event&)> Func;
		};

		struct BaseComponentEvent : public EventSystem::BaseEvent
		{
			ComponentId Component;
		};
		template<typename Event>
		struct ComponentEvent : public BaseComponentEvent, public EventType<Event>
		{ };

		struct BaseLooseEvent : public EventSystem::BaseEvent
		{
			std::size_t ID;
		};
		template<typename Event>
		struct LooseEvent : public BaseLooseEvent, public EventType<Event>
		{ };

	}

	template<typename Event, typename Functor>
	void EventSystem::eventRegister(ComponentId cId, Functor&& func)
	{
		auto& list = mEvents[typeid(Event)];

		auto* ev = new detail::ComponentEvent<Event>();
		ev->Component = cId;
		ev->Func = std::move(func);
		ev->Type = sComponentEvent;

		list.push_back(ev);
	}
	template<typename Event, typename Functor>
	std::size_t EventSystem::eventRegister(Functor&& func)
	{
		auto& list = mEvents[typeid(Event)];

		auto* ev = new detail::LooseEvent<Event>();
		ev->Func = std::move(func);
		ev->ID = list.size();
		ev->Type = sLooseEvent;

		list.push_back(ev);
		return ev->ID;
	}
	template<typename Event>
	void EventSystem::eventUnregister(ComponentId cId)
	{
		auto& list = mEvents[typeid(Event)];

		auto it = std::find_if(list.cbegin(), list.cend(), [cId](const BaseEvent* ev) {
			return ev->Type == sComponentEvent && static_cast<const detail::BaseComponentEvent*>(ev)->Component == cId;
		});

		if (it != list.cend())
			list.erase(it);
	}
	template<typename Event>
	void EventSystem::eventUnregister(std::size_t id)
	{
		auto& list = mEvents[typeid(Event)];

		auto it = std::find_if(list.cbegin(), list.cend(), [id](const BaseEvent* ev) {
			return ev->Type == sLooseEvent && static_cast<const detail::BaseLooseEvent*>(ev)->ID == id;
		});

		if (it != list.cend())
			list.erase(it);
	}
	template<typename Event>
	void EventSystem::eventEmit(const Event& toSend) const
	{
		if (mEvents.count(typeid(Event)) == 0)
			return;

		const auto& list = mEvents.at(typeid(Event));

		for (auto& ev : list)
		{
			if (ev->Type == sLooseEvent)
				static_cast<const detail::LooseEvent<Event>*>(ev)->Func(toSend);
			else
				static_cast<const detail::ComponentEvent<Event>*>(ev)->Func(toSend);
		}
	}
	template<typename Event, typename... Args>
	void EventSystem::eventEmit(Args... args) const
	{
		// static_assert(std::is_trivial<Event>::value, "Must be a POD type.");

		Event toSend{ std::forward<Args>(args)... };
		eventEmit(toSend);
	}

}<|endoftext|>


<commit_before>// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#include <memory>
#include <Nazara/Renderer/Debug.hpp>

template<typename... Args>
NzModelRef NzModel::New(Args&&... args)
{
	std::unique_ptr<NzModel> object(new NzModel(std::forward<Args>(args)...));
	object->SetPersistent(false);

	return object.release();
}

#include <Nazara/Renderer/DebugOff.hpp>
<commit_msg>Graphics/Model: Fix includes<commit_after>// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#include <memory>
#include <Nazara/Graphics/Debug.hpp>

template<typename... Args>
NzModelRef NzModel::New(Args&&... args)
{
	std::unique_ptr<NzModel> object(new NzModel(std::forward<Args>(args)...));
	object->SetPersistent(false);

	return object.release();
}

#include <Nazara/Graphics/DebugOff.hpp>
<|endoftext|>


<commit_before>#ifndef ALEPH_UTILITIES_STRING_HH__
#define ALEPH_UTILITIES_STRING_HH__

#include <algorithm>
#include <limits>
#include <regex>
#include <sstream>
#include <string>
#include <vector>

#include <cctype>

namespace aleph
{

namespace utilities
{

template <class T> T ltrim( T sequence )
{
  sequence.erase( sequence.begin(),
                  std::find_if_not( sequence.begin(), sequence.end(),
                                    [] ( const typename T::value_type& c )
                                    {
                                      return std::isspace( c );
                                    } ) );

  return sequence;
}

template <class T> T rtrim( T sequence )
{
  sequence.erase( std::find_if_not( sequence.rbegin(), sequence.rend(),
                                    [] ( const typename T::value_type& c )
                                    {
                                      return std::isspace( c );
                                    } ).base(),
                  sequence.end() );

  return sequence;
}

template <class T> T trim( T sequence )
{
  return ltrim( rtrim( sequence ) );
}

template <class T> std::vector<T> split( const T& sequence,
                                         const T& regex = "[[:space:]]+" )
{
  std::regex re( regex );
  std::sregex_token_iterator begin( sequence.begin(), sequence.end(), re, -1 );
  std::sregex_token_iterator end;

  return { begin, end };
}

/**
  Attempts to convert a sequence type `S` to a non-sequence type `T` by
  using `std::stringstream`. This makes converting strings to different
  types such as numbers easier.

  @tparam S Sequence type (e.g. `std::string`)
  @tparam T Non-sequence type (e.g. `ìnt`)

  @param sequence Sequence to convert
  @param success  Flag indicating the success of the conversion

  @returns Result of the conversion. Errors do *not* result in an error
  being thrown. Use the \p success parameter to check for errors.
*/

template <class T, class S> T convert( const S& sequence, bool& success )
{
  T result = T();
  success  = false;

  std::istringstream converter( sequence );
  converter >> result;

  // Try some special handling for some special tokens. Other errors are
  // silently ignored. I am not sure whether this is the right behaviour
  // but I see no pressing reason to change it now.
  if( converter.fail() )
  {
    std::string string = sequence;

    std::transform( string.begin(), string.end(),
                    string.begin(), ::tolower );

    if( string == "+inf" || string == "inf" || string == "+infinity" || string == "infinity" )
      result = std::numeric_limits<T>::infinity();
    else if ( string == "-inf" || string == "-infinity" )
      result = -std::numeric_limits<T>::infinity();
    else if( string == "nan" )
      result = std::numeric_limits<T>::quiet_NaN();

    success = result != T();
  }
  else
    success = true;

  return result;

}

/** @overload convert() */
template <class T, class S> T convert( const S& sequence )
{
  bool success = false;
  return convert<T>( sequence, success );
}

} // namespace utilities

} // namespace aleph

#endif
<commit_msg>Improved function for tokenizing a string<commit_after>#ifndef ALEPH_UTILITIES_STRING_HH__
#define ALEPH_UTILITIES_STRING_HH__

#include <algorithm>
#include <limits>
#include <regex>
#include <sstream>
#include <string>
#include <vector>

#include <cctype>

namespace aleph
{

namespace utilities
{

template <class T> T ltrim( T sequence )
{
  sequence.erase( sequence.begin(),
                  std::find_if_not( sequence.begin(), sequence.end(),
                                    [] ( const typename T::value_type& c )
                                    {
                                      return std::isspace( c );
                                    } ) );

  return sequence;
}

template <class T> T rtrim( T sequence )
{
  sequence.erase( std::find_if_not( sequence.rbegin(), sequence.rend(),
                                    [] ( const typename T::value_type& c )
                                    {
                                      return std::isspace( c );
                                    } ).base(),
                  sequence.end() );

  return sequence;
}

template <class T> T trim( T sequence )
{
  return ltrim( rtrim( sequence ) );
}

template <class T> std::vector<T> split( const T& sequence,
                                         const T& regex = "[[:space:]]+" )
{
  std::regex re( regex );
  std::sregex_token_iterator begin( sequence.begin(), sequence.end(), re, -1 );
  std::sregex_token_iterator end;

  return { begin, end };
}

/**
  This is a variant for tokenizing a string according to whitespace
  characters. It is more efficient but less generic than `split()`,
  which permits the use of arbitrary regular expressions.
*/

template <class T> std::vector<T> splitByWhitespace( const T& sequence )
{
  std::vector<T> tokens;

  std::istringstream iss( sequence );

  std::copy( std::istream_iterator<T>( iss ),
             std::istream_iterator<T>(),
             std::back_inserter( tokens ) );

  return tokens;
}

/**
  Attempts to convert a sequence type `S` to a non-sequence type `T` by
  using `std::stringstream`. This makes converting strings to different
  types such as numbers easier.

  @tparam S Sequence type (e.g. `std::string`)
  @tparam T Non-sequence type (e.g. `ìnt`)

  @param sequence Sequence to convert
  @param success  Flag indicating the success of the conversion

  @returns Result of the conversion. Errors do *not* result in an error
  being thrown. Use the \p success parameter to check for errors.
*/

template <class T, class S> T convert( const S& sequence, bool& success )
{
  T result = T();
  success  = false;

  std::istringstream converter( sequence );
  converter >> result;

  // Try some special handling for some special tokens. Other errors are
  // silently ignored. I am not sure whether this is the right behaviour
  // but I see no pressing reason to change it now.
  if( converter.fail() )
  {
    std::string string = sequence;

    std::transform( string.begin(), string.end(),
                    string.begin(), ::tolower );

    if( string == "+inf" || string == "inf" || string == "+infinity" || string == "infinity" )
      result = std::numeric_limits<T>::infinity();
    else if ( string == "-inf" || string == "-infinity" )
      result = -std::numeric_limits<T>::infinity();
    else if( string == "nan" )
      result = std::numeric_limits<T>::quiet_NaN();

    success = result != T();
  }
  else
    success = true;

  return result;

}

/** @overload convert() */
template <class T, class S> T convert( const S& sequence )
{
  bool success = false;
  return convert<T>( sequence, success );
}

} // namespace utilities

} // namespace aleph

#endif
<|endoftext|>


<commit_before>#ifndef _IZENELIB_AM_SUCCINCT_CONSTANTS_HPP
#define _IZENELIB_AM_SUCCINCT_CONSTANTS_HPP

#include <types.h>

NS_IZENELIB_AM_BEGIN

namespace succinct
{

#ifndef UINT8_MAX
#define UINT8_MAX (255U)
#endif

/* Defined by BSIZE */
typedef uint64_t block_t;

/* Block size (64-bit environment) */
static const size_t BSIZE = 64;
static const size_t PRESUM_SZ = 128;
static const size_t CACHELINE_SZ = 256;
static const size_t LEVEL1_NUM = 256;
static const size_t LEVEL2_NUM = BSIZE;

static const size_t kLargeBlockSize = 1024;
static const size_t kSuperBlockSize = 256;
static const size_t kBlockSize = 64;
static const size_t kSelectBlockSize = 2048;
static const size_t kBlockPerLargeBlock = kLargeBlockSize / kBlockSize;
static const size_t kBlockPerSuperBlock = kSuperBlockSize / kBlockSize;

}

NS_IZENELIB_AM_END

#endif
<commit_msg>decrease rank/select sample rate of RSDic<commit_after>#ifndef _IZENELIB_AM_SUCCINCT_CONSTANTS_HPP
#define _IZENELIB_AM_SUCCINCT_CONSTANTS_HPP

#include <types.h>

NS_IZENELIB_AM_BEGIN

namespace succinct
{

#ifndef UINT8_MAX
#define UINT8_MAX (255U)
#endif

/* Defined by BSIZE */
typedef uint64_t block_t;

/* Block size (64-bit environment) */
static const size_t BSIZE = 64;
static const size_t PRESUM_SZ = 128;
static const size_t CACHELINE_SZ = 256;
static const size_t LEVEL1_NUM = 256;
static const size_t LEVEL2_NUM = BSIZE;

static const size_t kLargeBlockSize = 2048;
static const size_t kSuperBlockSize = 256;
static const size_t kBlockSize = 64;
static const size_t kSelectBlockSize = 4096;
static const size_t kBlockPerLargeBlock = kLargeBlockSize / kBlockSize;
static const size_t kBlockPerSuperBlock = kSuperBlockSize / kBlockSize;

}

NS_IZENELIB_AM_END

#endif
<|endoftext|>