<commit_before>/*
For more information, please see: http://software.sci.utah.edu

The MIT License

Copyright (c) 2012 Scientific Computing and Imaging Institute,
University of Utah.

License for the specific language governing rights and limitations under
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

Author            : Moritz Dannhauer
Last modification : March 16 2014
ToDo: Padding is always enabled because of exit() in cleaver lib
*/

///TODO: fix include path to remove Externals/ part

#include <Externals/cleaver/lib/FloatField.h>
#include <Externals/cleaver/lib/vec3.h>
#include <Externals/cleaver/lib/BoundingBox.h>
#include <Externals/cleaver/lib/Cleaver.h>
#include <Externals/cleaver/lib/InverseField.h>
#include <Externals/cleaver/lib/PaddedVolume.h>
#include <Externals/cleaver/lib/Volume.h>
#include <Core/Algorithms/Base/AlgorithmPreconditions.h>
#include <Core/Algorithms/Field/InterfaceWithCleaverAlgorithm.h>
#include <Core/Algorithms/Base/AlgorithmVariableNames.h>
#include <Core/GeometryPrimitives/Vector.h>
#include <Core/Datatypes/Legacy/Field/Field.h>
#include <Core/Datatypes/Legacy/Field/VField.h>
#include <Core/Datatypes/Legacy/Field/VMesh.h>
#include <Core/Datatypes/Legacy/Field/FieldInformation.h>
#include <iostream>
#include <Core/GeometryPrimitives/Point.h>
#include <Core/Utils/StringUtil.h>
#include <boost/scoped_ptr.hpp>
#include <Core/Logging/Log.h>
#include <Core/Math/MiscMath.h>

using namespace SCIRun::Core::Algorithms;
using namespace SCIRun::Core::Algorithms::Fields;
using namespace SCIRun::Core::Geometry;
using namespace SCIRun;
using namespace SCIRun::Core;
using namespace SCIRun::Core::Logging;

AlgorithmParameterName InterfaceWithCleaverAlgorithm::Verbose("VerboseCheckBox");
AlgorithmParameterName InterfaceWithCleaverAlgorithm::Padding("PaddingCheckBox");
AlgorithmParameterName InterfaceWithCleaverAlgorithm::VolumeScalingOption("VolumeScalingOption");
AlgorithmParameterName InterfaceWithCleaverAlgorithm::VolumeScalingX("VolumeScalingSpinBox_X");
AlgorithmParameterName InterfaceWithCleaverAlgorithm::VolumeScalingY("VolumeScalingSpinBox_Y");
AlgorithmParameterName InterfaceWithCleaverAlgorithm::VolumeScalingZ("VolumeScalingSpinBox_Z");

InterfaceWithCleaverAlgorithm::InterfaceWithCleaverAlgorithm()
{
  addParameter(Verbose,true);
  addParameter(Padding,true);
  add_option(VolumeScalingOption, "Relative size", "Absolute size|Relative size|None");
  addParameter(VolumeScalingX,1.0);
  addParameter(VolumeScalingY,1.0);
  addParameter(VolumeScalingZ,1.0);
}

boost::shared_ptr<Cleaver::ScalarField> InterfaceWithCleaverAlgorithm::makeCleaverFieldFromLatVol(FieldHandle field )
{
  VMesh*  vmesh   = field->vmesh();
  VField* vfield = field->vfield();
  VMesh::dimension_type dims;
  vmesh->get_dimensions( dims );

  float* ptr = static_cast<float*>(vfield->fdata_pointer());

  auto cleaverField = boost::make_shared<Cleaver::FloatField>(dims[0], dims[1], dims[2], ptr);

  BBox bbox=vmesh->get_bounding_box();
  Point bmin, bmax;
  if (bbox.valid())
  {
   bmin = bbox.min();
   bmax = bbox.max();
  }
  Cleaver::BoundingBox  bb = Cleaver::BoundingBox(Cleaver::vec3::zero, Cleaver::vec3(dims[0],dims[1],dims[2]));
  cleaverField->setBounds(bb);
  const Transform &transform = vmesh->get_transform();

  int x_spacing=fabs(transform.get_mat_val(0,0)), y_spacing=fabs(transform.get_mat_val(1,1)), z_spacing=fabs(transform.get_mat_val(2,2));
  if (IsNan(x_spacing)) x_spacing=1;
  if (IsNan(y_spacing)) y_spacing=1;
  if (IsNan(z_spacing)) z_spacing=1;

  cleaverField->setScale(Cleaver::vec3(x_spacing,y_spacing,z_spacing));

  return cleaverField;
}

FieldHandle InterfaceWithCleaverAlgorithm::run(const std::vector<FieldHandle>& input) const
{
  FieldHandle output;
  std::vector<FieldHandle> inputs;
  std::copy_if(input.begin(), input.end(), std::back_inserter(inputs), [](FieldHandle f) { return f; });

  if (inputs.empty())
  {
    THROW_ALGORITHM_INPUT_ERROR(" No input fields given ");
    return FieldHandle();
  }
  if (inputs.size()<2)
  {
    THROW_ALGORITHM_INPUT_ERROR(" At least 2 indicator functions stored as float values are needed to run cleaver! " );
    return FieldHandle();
  }

  std::vector<boost::shared_ptr<Cleaver::ScalarField>> fields;

  VMesh::dimension_type dims; int x=0,y=0,z=0;
  for (size_t p=0; p<inputs.size(); p++)
  {
    FieldHandle input = inputs[p];
    VMesh*  imesh1   = input->vmesh();

    if( !imesh1->is_structuredmesh() )
    {
      THROW_ALGORITHM_INPUT_ERROR("needs to be structured mesh!");
    }
    else
    {
      VField* vfield1 = input->vfield();
      if (!vfield1->is_scalar())
      {
        THROW_ALGORITHM_INPUT_ERROR("values at the node needs to be scalar!");
        return FieldHandle();
      }

      imesh1->get_dimensions( dims );
      if (p==0)
      {
        x=dims[0]; y=dims[1]; z=dims[2];
        if (x<1 || y<1 || z<1)
        {
          THROW_ALGORITHM_INPUT_ERROR(" Size of input fields should be non-zero !");
        }
      }
      else
      {
        if ( dims[0]!=x || dims[1]!=y || dims[2]!=z)
        {
          THROW_ALGORITHM_INPUT_ERROR(" Size of input fields is inconsistent !");
        }
      }

      if (dims.size()!=3)
      {
        THROW_ALGORITHM_INPUT_ERROR("need a three dimensional indicator function");
        return FieldHandle();
      }

      //0 = constant, 1 = linear
       if (1 != vfield1->basis_order())
       {
        THROW_ALGORITHM_INPUT_ERROR("Input data need to be defined on input mesh nodes.");
       }

      if (vfield1->is_float())
      {
        float* ptr = static_cast<float*>(vfield1->fdata_pointer());
	if (ptr)
        {
          fields.push_back(makeCleaverFieldFromLatVol(input));
        }
        else
        {
          THROW_ALGORITHM_INPUT_ERROR(" float field is NULL pointer");
          return FieldHandle();
        }
      } else
      {
       THROW_ALGORITHM_INPUT_ERROR(" Input field needs to be a structured mesh (best would be a LatVol) with float values defnied on mesh nodes. ");
      }

    }

  }

  boost::shared_ptr<Cleaver::Volume> volume(new Cleaver::Volume(toVectorOfRawPointers(fields)));

  const double xScale = get(VolumeScalingX).toDouble();
  const double yScale = get(VolumeScalingY).toDouble();
  const double zScale = get(VolumeScalingZ).toDouble();

  if (xScale > 0 && yScale > 0 && zScale > 0)
  {
    const std::string scaling = get_option(VolumeScalingOption);
    if ("Absolute size" == scaling)
    {
      volume->setSize(xScale, yScale,zScale);
    }
    else if ("Relative size" == scaling)
    {
      double newX = xScale*volume->size().x;
      double newY = yScale*volume->size().y;
      double newZ = zScale*volume->size().z;
      volume->setSize(newX, newY, newZ);
    }
    else // None
    {
      volume->setSize(dims[0],dims[1],dims[2]);
    }
  }
  else
  {
    THROW_ALGORITHM_INPUT_ERROR(" Invalid Scaling. Use Input sizes.");
  }

  /// Padding is now optional!
  boost::shared_ptr<Cleaver::AbstractVolume> paddedVolume(volume);
  const bool verbose = get(Verbose).toBool();
  const bool pad = get(Padding).toBool();
  if (pad)
    paddedVolume.reset(new Cleaver::PaddedVolume(volume.get()));

  std::cout << "Creating Mesh with Volume Size " << paddedVolume->size().toString() << std::endl;

  boost::scoped_ptr<Cleaver::TetMesh> mesh(Cleaver::createMeshFromVolume(paddedVolume.get(), verbose));

  auto nr_of_tets  = mesh->tets.size();
  auto nr_of_verts = mesh->verts.size();

  if (nr_of_tets==0 || nr_of_verts==0)
  {
    THROW_ALGORITHM_INPUT_ERROR(" Number of resulting tetrahedral nodes or elements is 0. If you disabled padding enable it and execute again. ");
  }

  FieldInformation fi("TetVolMesh",0,"double");   ///create output field

  output = CreateField(fi);
  auto omesh = output->vmesh();
  auto ofield = output->vfield();

  omesh->node_reserve(nr_of_verts);
  omesh->elem_reserve(nr_of_tets);

  for (auto i=0; i<nr_of_verts; i++)
  {
    omesh->add_point(Point(mesh->verts[i]->pos().x,mesh->verts[i]->pos().y,mesh->verts[i]->pos().z));
  }

  VMesh::Node::array_type vdata;
  vdata.resize(4);
  std::vector<double> values(nr_of_tets);

  for (auto i=0; i<nr_of_tets; i++)
  {
    vdata[0]=mesh->tets[i]->verts[0]->tm_v_index;
    vdata[1]=mesh->tets[i]->verts[1]->tm_v_index;
    vdata[2]=mesh->tets[i]->verts[2]->tm_v_index;
    vdata[3]=mesh->tets[i]->verts[3]->tm_v_index;
    omesh->add_elem(vdata);
    auto mat_label = mesh->tets[i]->mat_label;
    values[i]=mat_label;
  }
  ofield->resize_values();
  ofield->set_values(values);
  mesh->computeAngles();
  std::ostringstream ostr1;
  ostr1 << "Number of tetrahedral elements:" << nr_of_tets <<  std::endl;
  ostr1 << "Number of tetrahedral nodes:" << nr_of_verts << std::endl;
  ostr1 << "Worst Angle (min):" <<  mesh->min_angle << std::endl;
  ostr1 << "Worst Angle (max):" <<  mesh->max_angle << std::endl;
  ostr1 << "Volume:" << volume->size().toString() << std::endl;

  remark(ostr1.str());

  return output;
}

AlgorithmOutput InterfaceWithCleaverAlgorithm::run_generic(const AlgorithmInput& input) const
{
  auto inputfields = input.getList<Field>(Variables::InputFields);

  FieldHandle output_fld = run(inputfields);
  if ( !output_fld )
    THROW_ALGORITHM_PROCESSING_ERROR("Null returned on legacy run call.");

  AlgorithmOutput output;
  output[Variables::OutputField] = output_fld;
  return output;
}
<commit_msg>Delete unused code<commit_after>/*
For more information, please see: http://software.sci.utah.edu

The MIT License

Copyright (c) 2012 Scientific Computing and Imaging Institute,
University of Utah.

License for the specific language governing rights and limitations under
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

Author            : Moritz Dannhauer
Last modification : March 16 2014
ToDo: Padding is always enabled because of exit() in cleaver lib
*/

///TODO: fix include path to remove Externals/ part

#include <Externals/cleaver/lib/FloatField.h>
#include <Externals/cleaver/lib/vec3.h>
#include <Externals/cleaver/lib/BoundingBox.h>
#include <Externals/cleaver/lib/Cleaver.h>
#include <Externals/cleaver/lib/InverseField.h>
#include <Externals/cleaver/lib/PaddedVolume.h>
#include <Externals/cleaver/lib/Volume.h>
#include <Core/Algorithms/Base/AlgorithmPreconditions.h>
#include <Core/Algorithms/Field/InterfaceWithCleaverAlgorithm.h>
#include <Core/Algorithms/Base/AlgorithmVariableNames.h>
#include <Core/GeometryPrimitives/Vector.h>
#include <Core/Datatypes/Legacy/Field/Field.h>
#include <Core/Datatypes/Legacy/Field/VField.h>
#include <Core/Datatypes/Legacy/Field/VMesh.h>
#include <Core/Datatypes/Legacy/Field/FieldInformation.h>
#include <iostream>
#include <Core/GeometryPrimitives/Point.h>
#include <Core/Utils/StringUtil.h>
#include <boost/scoped_ptr.hpp>
#include <Core/Logging/Log.h>
#include <Core/Math/MiscMath.h>

using namespace SCIRun::Core::Algorithms;
using namespace SCIRun::Core::Algorithms::Fields;
using namespace SCIRun::Core::Geometry;
using namespace SCIRun;
using namespace SCIRun::Core;
using namespace SCIRun::Core::Logging;

AlgorithmParameterName InterfaceWithCleaverAlgorithm::Verbose("VerboseCheckBox");
AlgorithmParameterName InterfaceWithCleaverAlgorithm::Padding("PaddingCheckBox");
AlgorithmParameterName InterfaceWithCleaverAlgorithm::VolumeScalingOption("VolumeScalingOption");
AlgorithmParameterName InterfaceWithCleaverAlgorithm::VolumeScalingX("VolumeScalingSpinBox_X");
AlgorithmParameterName InterfaceWithCleaverAlgorithm::VolumeScalingY("VolumeScalingSpinBox_Y");
AlgorithmParameterName InterfaceWithCleaverAlgorithm::VolumeScalingZ("VolumeScalingSpinBox_Z");

InterfaceWithCleaverAlgorithm::InterfaceWithCleaverAlgorithm()
{
  addParameter(Verbose,true);
  addParameter(Padding,true);
  add_option(VolumeScalingOption, "Relative size", "Absolute size|Relative size|None");
  addParameter(VolumeScalingX,1.0);
  addParameter(VolumeScalingY,1.0);
  addParameter(VolumeScalingZ,1.0);
}

boost::shared_ptr<Cleaver::ScalarField> InterfaceWithCleaverAlgorithm::makeCleaverFieldFromLatVol(FieldHandle field )
{
  VMesh*  vmesh   = field->vmesh();
  VField* vfield = field->vfield();
  VMesh::dimension_type dims;
  vmesh->get_dimensions( dims );

  float* ptr = static_cast<float*>(vfield->fdata_pointer());

  auto cleaverField = boost::make_shared<Cleaver::FloatField>(dims[0], dims[1], dims[2], ptr);
  Cleaver::BoundingBox bb(Cleaver::vec3::zero, Cleaver::vec3(dims[0],dims[1],dims[2]));
  cleaverField->setBounds(bb);
  const Transform &transform = vmesh->get_transform();

  int x_spacing=fabs(transform.get_mat_val(0,0)), y_spacing=fabs(transform.get_mat_val(1,1)), z_spacing=fabs(transform.get_mat_val(2,2));
  if (IsNan(x_spacing)) x_spacing=1;
  if (IsNan(y_spacing)) y_spacing=1;
  if (IsNan(z_spacing)) z_spacing=1;

  cleaverField->setScale(Cleaver::vec3(x_spacing,y_spacing,z_spacing));

  return cleaverField;
}

FieldHandle InterfaceWithCleaverAlgorithm::run(const std::vector<FieldHandle>& input) const
{
  FieldHandle output;
  std::vector<FieldHandle> inputs;
  std::copy_if(input.begin(), input.end(), std::back_inserter(inputs), [](FieldHandle f) { return f; });

  if (inputs.empty())
  {
    THROW_ALGORITHM_INPUT_ERROR(" No input fields given ");
    return FieldHandle();
  }
  if (inputs.size()<2)
  {
    THROW_ALGORITHM_INPUT_ERROR(" At least 2 indicator functions stored as float values are needed to run cleaver! " );
    return FieldHandle();
  }

  std::vector<boost::shared_ptr<Cleaver::ScalarField>> fields;

  VMesh::dimension_type dims; int x=0,y=0,z=0;
  for (size_t p=0; p<inputs.size(); p++)
  {
    FieldHandle input = inputs[p];
    VMesh*  imesh1   = input->vmesh();

    if( !imesh1->is_structuredmesh() )
    {
      THROW_ALGORITHM_INPUT_ERROR("needs to be structured mesh!");
    }
    else
    {
      VField* vfield1 = input->vfield();
      if (!vfield1->is_scalar())
      {
        THROW_ALGORITHM_INPUT_ERROR("values at the node needs to be scalar!");
        return FieldHandle();
      }

      imesh1->get_dimensions( dims );
      if (p==0)
      {
        x=dims[0]; y=dims[1]; z=dims[2];
        if (x<1 || y<1 || z<1)
        {
          THROW_ALGORITHM_INPUT_ERROR(" Size of input fields should be non-zero !");
        }
      }
      else
      {
        if ( dims[0]!=x || dims[1]!=y || dims[2]!=z)
        {
          THROW_ALGORITHM_INPUT_ERROR(" Size of input fields is inconsistent !");
        }
      }

      if (dims.size()!=3)
      {
        THROW_ALGORITHM_INPUT_ERROR("need a three dimensional indicator function");
        return FieldHandle();
      }

      //0 = constant, 1 = linear
       if (1 != vfield1->basis_order())
       {
        THROW_ALGORITHM_INPUT_ERROR("Input data need to be defined on input mesh nodes.");
       }

      if (vfield1->is_float())
      {
        float* ptr = static_cast<float*>(vfield1->fdata_pointer());
	if (ptr)
        {
          fields.push_back(makeCleaverFieldFromLatVol(input));
        }
        else
        {
          THROW_ALGORITHM_INPUT_ERROR(" float field is NULL pointer");
          return FieldHandle();
        }
      } else
      {
       THROW_ALGORITHM_INPUT_ERROR(" Input field needs to be a structured mesh (best would be a LatVol) with float values defnied on mesh nodes. ");
      }

    }

  }

  boost::shared_ptr<Cleaver::Volume> volume(new Cleaver::Volume(toVectorOfRawPointers(fields)));

  const double xScale = get(VolumeScalingX).toDouble();
  const double yScale = get(VolumeScalingY).toDouble();
  const double zScale = get(VolumeScalingZ).toDouble();

  if (xScale > 0 && yScale > 0 && zScale > 0)
  {
    const std::string scaling = get_option(VolumeScalingOption);
    if ("Absolute size" == scaling)
    {
      volume->setSize(xScale, yScale,zScale);
    }
    else if ("Relative size" == scaling)
    {
      double newX = xScale*volume->size().x;
      double newY = yScale*volume->size().y;
      double newZ = zScale*volume->size().z;
      volume->setSize(newX, newY, newZ);
    }
    else // None
    {
      volume->setSize(dims[0],dims[1],dims[2]);
    }
  }
  else
  {
    THROW_ALGORITHM_INPUT_ERROR(" Invalid Scaling. Use Input sizes.");
  }

  /// Padding is now optional!
  boost::shared_ptr<Cleaver::AbstractVolume> paddedVolume(volume);
  const bool verbose = get(Verbose).toBool();
  const bool pad = get(Padding).toBool();
  if (pad)
    paddedVolume.reset(new Cleaver::PaddedVolume(volume.get()));

  std::cout << "Creating Mesh with Volume Size " << paddedVolume->size().toString() << std::endl;

  boost::scoped_ptr<Cleaver::TetMesh> mesh(Cleaver::createMeshFromVolume(paddedVolume.get(), verbose));

  auto nr_of_tets  = mesh->tets.size();
  auto nr_of_verts = mesh->verts.size();

  if (nr_of_tets==0 || nr_of_verts==0)
  {
    THROW_ALGORITHM_INPUT_ERROR(" Number of resulting tetrahedral nodes or elements is 0. If you disabled padding enable it and execute again. ");
  }

  FieldInformation fi("TetVolMesh",0,"double");   ///create output field

  output = CreateField(fi);
  auto omesh = output->vmesh();
  auto ofield = output->vfield();

  omesh->node_reserve(nr_of_verts);
  omesh->elem_reserve(nr_of_tets);

  for (auto i=0; i<nr_of_verts; i++)
  {
    omesh->add_point(Point(mesh->verts[i]->pos().x,mesh->verts[i]->pos().y,mesh->verts[i]->pos().z));
  }

  VMesh::Node::array_type vdata;
  vdata.resize(4);
  std::vector<double> values(nr_of_tets);

  for (auto i=0; i<nr_of_tets; i++)
  {
    vdata[0]=mesh->tets[i]->verts[0]->tm_v_index;
    vdata[1]=mesh->tets[i]->verts[1]->tm_v_index;
    vdata[2]=mesh->tets[i]->verts[2]->tm_v_index;
    vdata[3]=mesh->tets[i]->verts[3]->tm_v_index;
    omesh->add_elem(vdata);
    auto mat_label = mesh->tets[i]->mat_label;
    values[i]=mat_label;
  }
  ofield->resize_values();
  ofield->set_values(values);
  mesh->computeAngles();
  std::ostringstream ostr1;
  ostr1 << "Number of tetrahedral elements:" << nr_of_tets <<  std::endl;
  ostr1 << "Number of tetrahedral nodes:" << nr_of_verts << std::endl;
  ostr1 << "Worst Angle (min):" <<  mesh->min_angle << std::endl;
  ostr1 << "Worst Angle (max):" <<  mesh->max_angle << std::endl;
  ostr1 << "Volume:" << volume->size().toString() << std::endl;

  remark(ostr1.str());

  return output;
}

AlgorithmOutput InterfaceWithCleaverAlgorithm::run_generic(const AlgorithmInput& input) const
{
  auto inputfields = input.getList<Field>(Variables::InputFields);

  FieldHandle output_fld = run(inputfields);
  if ( !output_fld )
    THROW_ALGORITHM_PROCESSING_ERROR("Null returned on legacy run call.");

  AlgorithmOutput output;
  output[Variables::OutputField] = output_fld;
  return output;
}
<|endoftext|>


<commit_before>/** @file mixed_logit.test.cc
 *
 *  A "stress" test driver for mixed logit.
 *
 *  @author Dongryeol Lee (dongryel@cc.gatech.edu)
 */

// for BOOST testing
#define BOOST_TEST_MAIN

#include <boost/test/unit_test.hpp>
#include <numeric>
#include <time.h>
#include "core/table/table.h"
#include "core/tree/gen_metric_tree.h"
#include "mlpack/mixed_logit_dcm/mixed_logit_dcm_argument_parser.h"
#include "mlpack/mixed_logit_dcm/mixed_logit_dcm_dev.h"

namespace mlpack {
namespace mixed_logit_dcm {

int num_attributes_;
int num_people_;
std::vector<int> num_discrete_choices_;

class TestMixedLogitDCM {

  private:

    template<typename TableType>
    void GenerateRandomDataset_(
      TableType *random_attribute_dataset,
      TableType *random_discrete_choice_set_info_dataset) {

      // Find the total number of discrete choices.
      int total_num_attributes =
        std::accumulate(
          mlpack::mixed_logit_dcm::num_discrete_choices_.begin(),
          mlpack::mixed_logit_dcm::num_discrete_choices_.end(), 0);

      random_attribute_dataset->Init(
        mlpack::mixed_logit_dcm::num_attributes_, total_num_attributes);

      for(int j = 0; j < total_num_attributes; j++) {
        core::table::DensePoint point;
        random_attribute_dataset->get(j, &point);
        for(int i = 0; i < mlpack::mixed_logit_dcm::num_attributes_; i++) {
          point[i] = core::math::Random(0.1, 1.0);
        }
      }

      random_discrete_choice_set_info_dataset->Init(
        2, mlpack::mixed_logit_dcm::num_people_);
      for(int j = 0; j < mlpack::mixed_logit_dcm::num_people_; j++) {
        core::table::DensePoint point;
        random_discrete_choice_set_info_dataset->get(j, &point);

        // This is the discrete choice index of the given person.
        point[0] = core::math::RandInt(
                     mlpack::mixed_logit_dcm::num_discrete_choices_[j]);

        // This is the number of discrete choices for the given
        // person.
        point[1] = mlpack::mixed_logit_dcm::num_discrete_choices_[j];
      }
    }

  public:

    int StressTestMain() {
      for(int i = 0; i < 20; i++) {
        for(int k = 0; k < 2; k++) {

          // Randomly choose the number of attributes and the number
          // of people and the number of discrete choices per each
          // person.
          mlpack::mixed_logit_dcm::num_attributes_ = core::math::RandInt(5, 20);
          mlpack::mixed_logit_dcm::num_people_ = core::math::RandInt(50, 101);
          mlpack::mixed_logit_dcm::num_discrete_choices_.resize(
            mlpack::mixed_logit_dcm::num_people_);

          switch(k) {
            case 0:

              // Test the constant distribution.
              StressTest();
              break;
            case 1:

              // Test the Gaussian distribution.
              StressTest();
              break;
          }
        }
      }
      return 0;
    }

    int StressTest() {

      typedef core::table::Table <
      core::tree::GenMetricTree <
      core::tree::AbstractStatistic > > TableType;

      // The list of arguments.
      std::vector< std::string > args;

      // Push in the reference dataset name.
      std::string attributes_in("random_attributes.csv");
      args.push_back(std::string("--attributes_in=") + attributes_in);

      // Push in the discrete choice set info name.
      std::string discrete_choice_set_info_in(
        "random_discrete_choice_set_info.csv");
      args.push_back(
        std::string("--discrete_choice_set_info_in=") +
        discrete_choice_set_info_in);

      // Print out the header of the trial.
      std::cout << "\n==================\n";
      std::cout << "Test trial begin\n";
      std::cout << "Number of attributes: " <<
                mlpack::mixed_logit_dcm::num_attributes_ << "\n";
      std::cout << "Number of people: " <<
                mlpack::mixed_logit_dcm::num_people_ << "\n";

      // Generate the random dataset and save it.
      TableType random_attribute_table;
      TableType random_discrete_choice_set_info_table;
      GenerateRandomDataset_(
        &random_attribute_table, &random_discrete_choice_set_info_table);
      random_attribute_table.Save(attributes_in);
      random_discrete_choice_set_info_table.Save(discrete_choice_set_info_in);

      // Parse the mixed logit DCM arguments.
      mlpack::mixed_logit_dcm::MixedLogitDCMArguments<TableType> arguments;
      boost::program_options::variables_map vm;
      mlpack::mixed_logit_dcm::MixedLogitDCMArgumentParser::
      ConstructBoostVariableMap(args, &vm);
      mlpack::mixed_logit_dcm::MixedLogitDCMArgumentParser::ParseArguments(
        vm, &arguments);

      // Call the mixed logit driver.
      mlpack::mixed_logit_dcm::MixedLogitDCM<TableType> instance;
      instance.Init(arguments);

      // Compute the result.
      mlpack::mixed_logit_dcm::MixedLogitDCMResult result;
      instance.Compute(arguments, &result);

      return 0;
    };
};
}
}

BOOST_AUTO_TEST_SUITE(TestSuiteMixedLogitDCM)
BOOST_AUTO_TEST_CASE(TestCaseMixedLogitDCM) {

  // Call the tests.
  mlpack::mixed_logit_dcm::TestMixedLogitDCM dcm_test;
  dcm_test.StressTestMain();

  std::cout << "All tests passed!\n";
}
BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Almost there.<commit_after>/** @file mixed_logit.test.cc
 *
 *  A "stress" test driver for mixed logit.
 *
 *  @author Dongryeol Lee (dongryel@cc.gatech.edu)
 */

// for BOOST testing
#define BOOST_TEST_MAIN

#include <boost/test/unit_test.hpp>
#include <numeric>
#include <time.h>
#include "core/table/table.h"
#include "core/tree/gen_metric_tree.h"
#include "mlpack/mixed_logit_dcm/mixed_logit_dcm_argument_parser.h"
#include "mlpack/mixed_logit_dcm/mixed_logit_dcm_dev.h"

namespace mlpack {
namespace mixed_logit_dcm {

int num_attributes_;
int num_people_;
std::vector<int> num_discrete_choices_;

class TestMixedLogitDCM {

  private:

    template<typename TableType>
    void GenerateRandomDataset_(
      TableType *random_attribute_dataset,
      TableType *random_discrete_choice_set_info_dataset) {

      // Find the total number of discrete choices.
      int total_num_attributes =
        std::accumulate(
          mlpack::mixed_logit_dcm::num_discrete_choices_.begin(),
          mlpack::mixed_logit_dcm::num_discrete_choices_.end(), 0);

      random_attribute_dataset->Init(
        mlpack::mixed_logit_dcm::num_attributes_, total_num_attributes);

      for(int j = 0; j < total_num_attributes; j++) {
        core::table::DensePoint point;
        random_attribute_dataset->get(j, &point);
        for(int i = 0; i < mlpack::mixed_logit_dcm::num_attributes_; i++) {
          point[i] = core::math::Random(0.1, 1.0);
        }
      }

      random_discrete_choice_set_info_dataset->Init(
        2, mlpack::mixed_logit_dcm::num_people_);
      for(int j = 0; j < mlpack::mixed_logit_dcm::num_people_; j++) {
        core::table::DensePoint point;
        random_discrete_choice_set_info_dataset->get(j, &point);

        // This is the discrete choice index of the given person.
        point[0] = core::math::RandInt(
                     mlpack::mixed_logit_dcm::num_discrete_choices_[j]);

        // This is the number of discrete choices for the given
        // person.
        point[1] = mlpack::mixed_logit_dcm::num_discrete_choices_[j];
      }
    }

  public:

    int StressTestMain() {
      for(int i = 0; i < 20; i++) {
        for(int k = 0; k < 2; k++) {

          // Randomly choose the number of attributes and the number
          // of people and the number of discrete choices per each
          // person.
          mlpack::mixed_logit_dcm::num_attributes_ = core::math::RandInt(5, 20);
          mlpack::mixed_logit_dcm::num_people_ = core::math::RandInt(50, 101);
          mlpack::mixed_logit_dcm::num_discrete_choices_.resize(
            mlpack::mixed_logit_dcm::num_people_);
          for(int j = 0; j < mlpack::mixed_logit_dcm::num_people_; j++) {
            mlpack::mixed_logit_dcm::num_discrete_choices_[j] =
              core::math::RandInt(3, 7);
          }

          switch(k) {
            case 0:

              // Test the constant distribution.
              StressTest();
              break;
            case 1:

              // Test the Gaussian distribution.
              StressTest();
              break;
          }
        }
      }
      return 0;
    }

    int StressTest() {

      typedef core::table::Table <
      core::tree::GenMetricTree <
      core::tree::AbstractStatistic > > TableType;

      // The list of arguments.
      std::vector< std::string > args;

      // Push in the reference dataset name.
      std::string attributes_in("random_attributes.csv");
      args.push_back(std::string("--attributes_in=") + attributes_in);

      // Push in the discrete choice set info name.
      std::string discrete_choice_set_info_in(
        "random_discrete_choice_set_info.csv");
      args.push_back(
        std::string("--discrete_choice_set_info_in=") +
        discrete_choice_set_info_in);

      // Print out the header of the trial.
      std::cout << "\n==================\n";
      std::cout << "Test trial begin\n";
      std::cout << "Number of attributes: " <<
                mlpack::mixed_logit_dcm::num_attributes_ << "\n";
      std::cout << "Number of people: " <<
                mlpack::mixed_logit_dcm::num_people_ << "\n";

      // Generate the random dataset and save it.
      TableType random_attribute_table;
      TableType random_discrete_choice_set_info_table;
      GenerateRandomDataset_(
        &random_attribute_table, &random_discrete_choice_set_info_table);
      random_attribute_table.Save(attributes_in);
      random_discrete_choice_set_info_table.Save(discrete_choice_set_info_in);

      // Parse the mixed logit DCM arguments.
      mlpack::mixed_logit_dcm::MixedLogitDCMArguments<TableType> arguments;
      boost::program_options::variables_map vm;
      mlpack::mixed_logit_dcm::MixedLogitDCMArgumentParser::
      ConstructBoostVariableMap(args, &vm);
      mlpack::mixed_logit_dcm::MixedLogitDCMArgumentParser::ParseArguments(
        vm, &arguments);

      // Call the mixed logit driver.
      mlpack::mixed_logit_dcm::MixedLogitDCM<TableType> instance;
      instance.Init(arguments);

      // Compute the result.
      mlpack::mixed_logit_dcm::MixedLogitDCMResult result;
      instance.Compute(arguments, &result);

      return 0;
    };
};
}
}

BOOST_AUTO_TEST_SUITE(TestSuiteMixedLogitDCM)
BOOST_AUTO_TEST_CASE(TestCaseMixedLogitDCM) {

  // Call the tests.
  mlpack::mixed_logit_dcm::TestMixedLogitDCM dcm_test;
  dcm_test.StressTestMain();

  std::cout << "All tests passed!\n";
}
BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/latch_wr_vref.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file latch_wr_vref.C
/// @brief Latches WR VREF according to JEDEC spec
///
// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com>
// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB Memory

#include <vector>
#include <fapi2.H>
#include <c_str.H>
#include <lib/dimm/ddr4/mrs_load_ddr4.H>
#include <lib/dimm/ddr4/latch_wr_vref.H>
#include <lib/dimm/rank.H>

using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_DIMM;

namespace mss
{

namespace ddr4
{

///
/// @brief Add latching commands for WR VREF to the instruction array - allows for custom MR06 data
/// @param[in] i_target, a fapi2::Target<TARGET_TYPE_DIMM>
/// @param[in] i_mrs06, base MRS 06 allows the user to setup custom values and pass it in
/// @param[in] i_rank, rank on which to latch MRS 06
/// @param[in,out] a vector of CCS instructions we should add to
/// @return FAPI2_RC_SUCCESS if and only if ok
///
fapi2::ReturnCode add_latch_wr_vref_commands( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
        const mrs06_data& i_mrs06,
        const uint64_t& i_rank,
        std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst)
{
    // JEDEC has a 3 step latching process for WR VREF
    // 1) enter into VREFDQ training mode, with the desired range value is XXXXXX
    // 2) set the VREFDQ value while in training mode - this actually latches the value
    // 3) exit VREFDQ training mode and go into normal operation mode

    // Adds both VREFDQ train enables
    // Note: this isn't general - assumes Nimbus via MCBIST instruction here BRS
    auto l_mr_override = i_mrs06;

    // Add both to the CCS program - JEDEC step 1
    enable_vref_train_enable(l_mr_override);
    FAPI_TRY( mrs_engine(i_target, l_mr_override, i_rank, mss::tvrefdqe(i_target), io_inst) );

    // Add both to the CCS program - JEDEC step 2
    FAPI_TRY( mrs_engine(i_target, l_mr_override, i_rank, mss::tvrefdqe(i_target), io_inst) );

    // Hits VREFDQ train disable - putting the DRAM's back in mainline mode
    // Add both to the CCS program - JEDEC step 3
    disable_vref_train_enable(l_mr_override);
    FAPI_TRY( mrs_engine(i_target, l_mr_override, i_rank, mss::tvrefdqe(i_target), io_inst) );

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Add latching commands for WR VREF to the instruction array
/// @param[in] i_target, a fapi2::Target<TARGET_TYPE_MCA>
/// @param[in] i_rank_pair, rank pair on which to latch MRS 06 - hits all ranks in the rank pair
/// @param[in] i_train_range, VREF range to setup
/// @param[in] i_train_value, VREF value to setup
/// @param[in,out] a vector of CCS instructions we should add to
/// @return FAPI2_RC_SUCCESS if and only if ok
///
fapi2::ReturnCode latch_wr_vref_commands_by_rank_pair( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
        const uint64_t& i_rank_pair,
        const uint8_t& i_train_range,
        const uint8_t& i_train_value)
{
    // Declares variables
    const auto l_mcbist = find_target<fapi2::TARGET_TYPE_MCBIST>(i_target);
    const auto l_dimms = mss::find_targets<fapi2::TARGET_TYPE_DIMM>(i_target);
    mss::ccs::program<fapi2::TARGET_TYPE_MCBIST, fapi2::TARGET_TYPE_MCA> l_program;
    std::vector<uint64_t> l_ranks;

    // Gets the ranks on which to latch the VREF's
    FAPI_TRY(mss::rank::get_ranks_in_pair( i_target, i_rank_pair, l_ranks));

    // Adds in latching commands for all ranks
    for( const auto& l_rank : l_ranks)
    {
        // Skips this rank if no rank is configured
        if( l_rank == NO_RANK)
        {
            continue;
        }

        // Sets up the DIMM target
        const auto l_dimm = (l_rank < MAX_RANK_PER_DIMM) ? l_dimms[0] : l_dimms[1];

        // Adds the latching commands to the CCS program for this current rank
        FAPI_TRY(setup_latch_wr_vref_commands_by_rank(l_dimm,
                 l_rank,
                 i_train_range,
                 i_train_value,
                 l_program.iv_instructions));
    }

    // Executes the CCS commands
    FAPI_TRY( mss::ccs::execute(l_mcbist, l_program, i_target) );

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Add latching commands for WR VREF to the instruction array by a given rank
/// @param[in] i_target, a fapi2::Target<TARGET_TYPE_MCA>
/// @param[in] i_rank, rank on which to latch MRS 06 - hits all ranks in the rank pair
/// @param[in] i_train_range, VREF range to setup
/// @param[in] i_train_value, VREF value to setup
/// @param[in,out] a vector of CCS instructions we should add to
/// @return FAPI2_RC_SUCCESS if and only if ok
///
fapi2::ReturnCode setup_latch_wr_vref_commands_by_rank( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
        const uint64_t& i_rank,
        const uint8_t& i_train_range,
        const uint8_t& i_train_value,
        std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst)
{
    // Check to make sure our ctor worked ok
    mrs06_data l_mrs06( i_target, fapi2::current_err );
    FAPI_TRY( fapi2::current_err, "Unable to construct MRS06 data from attributes");

    // Setup training range if the value is not the default
    if(i_train_range != wr_vref_override::USE_DEFAULT_WR_VREF_SETTINGS)
    {
        FAPI_INF("%s Overriding vrefdq train %s data to be 0x%02x for rank %lu", mss::c_str(i_target), "range", i_train_value,
                 i_rank);

        // Sets up the MR information
        for(uint64_t i = 0; i < MAX_RANK_PER_DIMM; ++i)
        {
            l_mrs06.iv_vrefdq_train_range[i] = i_train_range;
        }
    }

    // Setup training value if the value is not the default
    if(i_train_value != wr_vref_override::USE_DEFAULT_WR_VREF_SETTINGS)
    {
        FAPI_INF("%s Overriding vrefdq train %s data to be 0x%02x for rank %lu", mss::c_str(i_target), "value", i_train_value,
                 i_rank);

        // Sets up the MR information
        for(uint64_t i = 0; i < MAX_RANK_PER_DIMM; ++i)
        {
            l_mrs06.iv_vrefdq_train_value[i] = i_train_value;
        }
    }

    // Adds the latching commands
    FAPI_TRY(add_latch_wr_vref_commands(i_target,
                                        l_mrs06,
                                        i_rank,
                                        io_inst));

fapi_try_exit:
    return fapi2::current_err;
}

} // close namespace DDR4
} // close namespace mss
<commit_msg>Fix 1R dual-drop bugs<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/latch_wr_vref.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file latch_wr_vref.C
/// @brief Latches WR VREF according to JEDEC spec
///
// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com>
// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB Memory

#include <vector>
#include <fapi2.H>
#include <c_str.H>
#include <lib/dimm/ddr4/mrs_load_ddr4.H>
#include <lib/dimm/ddr4/latch_wr_vref.H>
#include <lib/dimm/rank.H>

using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_DIMM;

namespace mss
{

namespace ddr4
{

///
/// @brief Add latching commands for WR VREF to the instruction array - allows for custom MR06 data
/// @param[in] i_target, a fapi2::Target<TARGET_TYPE_DIMM>
/// @param[in] i_mrs06, base MRS 06 allows the user to setup custom values and pass it in
/// @param[in] i_rank, rank on which to latch MRS 06
/// @param[in,out] a vector of CCS instructions we should add to
/// @return FAPI2_RC_SUCCESS if and only if ok
///
fapi2::ReturnCode add_latch_wr_vref_commands( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
        const mrs06_data& i_mrs06,
        const uint64_t& i_rank,
        std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst)
{
    // JEDEC has a 3 step latching process for WR VREF
    // 1) enter into VREFDQ training mode, with the desired range value is XXXXXX
    // 2) set the VREFDQ value while in training mode - this actually latches the value
    // 3) exit VREFDQ training mode and go into normal operation mode

    // Adds both VREFDQ train enables
    // Note: this isn't general - assumes Nimbus via MCBIST instruction here BRS
    auto l_mr_override = i_mrs06;

    // Add both to the CCS program - JEDEC step 1
    enable_vref_train_enable(l_mr_override);
    FAPI_TRY( mrs_engine(i_target, l_mr_override, i_rank, mss::tvrefdqe(i_target), io_inst) );

    // Add both to the CCS program - JEDEC step 2
    FAPI_TRY( mrs_engine(i_target, l_mr_override, i_rank, mss::tvrefdqe(i_target), io_inst) );

    // Hits VREFDQ train disable - putting the DRAM's back in mainline mode
    // Add both to the CCS program - JEDEC step 3
    disable_vref_train_enable(l_mr_override);
    FAPI_TRY( mrs_engine(i_target, l_mr_override, i_rank, mss::tvrefdqe(i_target), io_inst) );

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Add latching commands for WR VREF to the instruction array
/// @param[in] i_target, a fapi2::Target<TARGET_TYPE_MCA>
/// @param[in] i_rank_pair, rank pair on which to latch MRS 06 - hits all ranks in the rank pair
/// @param[in] i_train_range, VREF range to setup
/// @param[in] i_train_value, VREF value to setup
/// @param[in,out] a vector of CCS instructions we should add to
/// @return FAPI2_RC_SUCCESS if and only if ok
///
fapi2::ReturnCode latch_wr_vref_commands_by_rank_pair( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
        const uint64_t& i_rank_pair,
        const uint8_t& i_train_range,
        const uint8_t& i_train_value)
{
    // Declares variables
    const auto l_mcbist = find_target<fapi2::TARGET_TYPE_MCBIST>(i_target);
    // Warning: l_dimm is not a valid Target and will crash Cronus if used before it gets filled in by mss::rank::get_dimm_target_from_rank
    fapi2::Target<fapi2::TARGET_TYPE_DIMM> l_dimm;
    mss::ccs::program<fapi2::TARGET_TYPE_MCBIST, fapi2::TARGET_TYPE_MCA> l_program;
    std::vector<uint64_t> l_ranks;

    // Gets the ranks on which to latch the VREF's
    FAPI_TRY(mss::rank::get_ranks_in_pair( i_target, i_rank_pair, l_ranks));

    // Adds in latching commands for all ranks
    for (const auto& l_rank : l_ranks)
    {
        // Skips this rank if no rank is configured
        if (l_rank == NO_RANK)
        {
            continue;
        }

        // Ensures we get a valid DIMM target / rank combo
        FAPI_TRY( mss::rank::get_dimm_target_from_rank(i_target, l_rank, l_dimm) );

        // Adds the latching commands to the CCS program for this current rank
        FAPI_TRY(setup_latch_wr_vref_commands_by_rank(l_dimm,
                 l_rank,
                 i_train_range,
                 i_train_value,
                 l_program.iv_instructions));
    }

    // Executes the CCS commands
    FAPI_TRY( mss::ccs::execute(l_mcbist, l_program, i_target) );

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Add latching commands for WR VREF to the instruction array by a given rank
/// @param[in] i_target, a fapi2::Target<TARGET_TYPE_MCA>
/// @param[in] i_rank, rank on which to latch MRS 06 - hits all ranks in the rank pair
/// @param[in] i_train_range, VREF range to setup
/// @param[in] i_train_value, VREF value to setup
/// @param[in,out] a vector of CCS instructions we should add to
/// @return FAPI2_RC_SUCCESS if and only if ok
///
fapi2::ReturnCode setup_latch_wr_vref_commands_by_rank( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
        const uint64_t& i_rank,
        const uint8_t& i_train_range,
        const uint8_t& i_train_value,
        std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst)
{
    // Check to make sure our ctor worked ok
    mrs06_data l_mrs06( i_target, fapi2::current_err );
    FAPI_TRY( fapi2::current_err, "Unable to construct MRS06 data from attributes");

    // Setup training range if the value is not the default
    if(i_train_range != wr_vref_override::USE_DEFAULT_WR_VREF_SETTINGS)
    {
        FAPI_INF("%s Overriding vrefdq train %s data to be 0x%02x for rank %lu", mss::c_str(i_target), "range", i_train_value,
                 i_rank);

        // Sets up the MR information
        for(uint64_t i = 0; i < MAX_RANK_PER_DIMM; ++i)
        {
            l_mrs06.iv_vrefdq_train_range[i] = i_train_range;
        }
    }

    // Setup training value if the value is not the default
    if(i_train_value != wr_vref_override::USE_DEFAULT_WR_VREF_SETTINGS)
    {
        FAPI_INF("%s Overriding vrefdq train %s data to be 0x%02x for rank %lu", mss::c_str(i_target), "value", i_train_value,
                 i_rank);

        // Sets up the MR information
        for(uint64_t i = 0; i < MAX_RANK_PER_DIMM; ++i)
        {
            l_mrs06.iv_vrefdq_train_value[i] = i_train_value;
        }
    }

    // Adds the latching commands
    FAPI_TRY(add_latch_wr_vref_commands(i_target,
                                        l_mrs06,
                                        i_rank,
                                        io_inst));

fapi_try_exit:
    return fapi2::current_err;
}

} // close namespace DDR4
} // close namespace mss
<|endoftext|>


<commit_before>#include "Wren++.h"
#include <cstdlib>  // for malloc
#include <cstring>  // for strcmp, memcpy
#include <cassert>
#include <iostream>

namespace
{

struct BoundState
{
    std::unordered_map< std::size_t, WrenForeignMethodFn > methods{};
    std::unordered_map< std::size_t, WrenForeignClassMethods > classes{};
};

WrenForeignMethodFn foreignMethodProvider(WrenVM* vm,
    const char* module,
    const char* className,
    bool isStatic,
    const char* signature)
{
    auto* boundState = (BoundState*)wrenGetUserData(vm);
    auto it = boundState->methods.find(wrenpp::detail::hashMethodSignature(module, className, isStatic, signature));
    if (it == boundState->methods.end())
    {
        return NULL;
    }

    return it->second;
}

WrenForeignClassMethods foreignClassProvider(WrenVM* vm, const char* m, const char* c)
{
    auto* boundState = (BoundState*)wrenGetUserData(vm);
    auto it = boundState->classes.find(wrenpp::detail::hashClassSignature(m, c));
    if (it == boundState->classes.end())
    {
        return WrenForeignClassMethods{ nullptr, nullptr };
    }

    return it->second;
}

inline const char* errorTypeToString(WrenErrorType type)
{
    switch (type)
    {
        case WREN_ERROR_COMPILE: return "WREN_ERROR_COMPILE";
        case WREN_ERROR_RUNTIME: return "WREN_ERROR_RUNTIME";
        case WREN_ERROR_STACK_TRACE: return "WREN_ERROR_STACK_TRACE";
        default: assert(false); return "";
    }
}

char* loadModuleFnWrapper(WrenVM* vm, const char* mod)
{
    return wrenpp::VM::loadModuleFn(mod);
}

void writeFnWrapper(WrenVM* vm, const char* text)
{
    wrenpp::VM::writeFn(text);
}

void errorFnWrapper(WrenVM*, WrenErrorType type, const char* module, int line, const char* message)
{
    wrenpp::VM::errorFn(type, module, line, message);
}

void* reallocateFnWrapper(void* memory, std::size_t newSize)
{
    return wrenpp::VM::reallocateFn(memory, newSize);
}

}

namespace wrenpp
{

namespace detail
{
void registerFunction(WrenVM* vm, const std::string& mod, const std::string& cName, bool isStatic, std::string sig, WrenForeignMethodFn function)
{
    BoundState* boundState = (BoundState*)wrenGetUserData(vm);
    std::size_t hash = detail::hashMethodSignature(mod.c_str(), cName.c_str(), isStatic, sig.c_str());
    boundState->methods.insert(std::make_pair(hash, function));
}

void registerClass(WrenVM* vm, const std::string& mod, std::string cName, WrenForeignClassMethods methods)
{
    BoundState* boundState = (BoundState*)wrenGetUserData(vm);
    std::size_t hash = detail::hashClassSignature(mod.c_str(), cName.c_str());
    boundState->classes.insert(std::make_pair(hash, methods));
}

}

Value::Value(bool val)
    : valueType_{ WREN_TYPE_BOOL }, string_{ nullptr }
{
    set_(val);
}

Value::Value(float val)
    : valueType_{ WREN_TYPE_NUM }, string_{ nullptr }
{
    set_(val);
}

Value::Value(double val)
    : valueType_{ WREN_TYPE_NUM }, string_{ nullptr }
{
    set_(val);
}

Value::Value(int val)
    : valueType_{ WREN_TYPE_NUM }, string_{ nullptr }
{
    set_(val);
}

Value::Value(unsigned int val)
    : valueType_{ WREN_TYPE_NUM }, string_{ nullptr }
{
    set_(val);
}

Value::Value(const char* str)
    : valueType_{ WREN_TYPE_STRING }, string_{ nullptr }
{
    string_ = (char*)VM::reallocateFn(nullptr, std::strlen(str) + 1);
    std::strcpy(string_, str);
}

Value::~Value()
{
    if (string_)
    {
        VM::reallocateFn(string_, 0u);
    }
}

Method::Method(VM* vm, WrenHandle* variable, WrenHandle* method)
    : vm_(vm),
    method_(method),
    variable_(variable)
{}

Method::Method(Method&& other)
    : vm_(other.vm_),
    method_(other.method_),
    variable_(other.variable_)
{
    other.vm_ = nullptr;
    other.method_ = nullptr;
    other.variable_ = nullptr;
}

Method::~Method()
{
    if (vm_)
    {
        assert(method_ && variable_);
        wrenReleaseHandle(vm_->vm(), method_);
        wrenReleaseHandle(vm_->vm(), variable_);
    }
}

Method& Method::operator=(Method&& rhs)
{
    vm_ = rhs.vm_;
    method_ = rhs.method_;
    variable_ = rhs.variable_;
    rhs.vm_ = nullptr;
    rhs.method_ = nullptr;
    rhs.variable_ = nullptr;

    return *this;
}

ClassContext ModuleContext::beginClass(std::string c)
{
    return ClassContext(c, *this);
}

void ModuleContext::endModule() {}

ModuleContext& ClassContext::endClass()
{
    return module_;
}

ClassContext::ClassContext(std::string c, ModuleContext& mod)
    : module_(mod),
    class_(c)
{}

ClassContext& ClassContext::bindCFunction(bool isStatic, std::string signature, WrenForeignMethodFn function)
{
    detail::registerFunction(module_.vm_, module_.name_, class_, isStatic, signature, function);
    return *this;
}

/*
 * Returns the source as a heap-allocated string.
 * Uses malloc, because our reallocateFn is set to default:
 * it uses malloc, realloc and free.
 * */
LoadModuleFn VM::loadModuleFn = [](const char* mod) -> char*
{
    std::string path(mod);
    path += ".wren";
    std::string source;
    try
    {
        source = wrenpp::detail::fileToString(path);
    }
    catch (const std::exception&)
    {
        return NULL;
    }
    char* buffer = (char*)malloc(source.size());
    assert(buffer != nullptr);
    memcpy(buffer, source.c_str(), source.size());
    return buffer;
};

WriteFn VM::writeFn = [](const char* text) -> void
{
    std::cout << text;
};

ErrorFn VM::errorFn = [](WrenErrorType type, const char* module, int line, const char* message) -> void
{
    const char* typeStr = errorTypeToString(type);
    std::cout << typeStr << " in " << module << ":" << line << " > " << message << std::endl;
};

ReallocateFn VM::reallocateFn = std::realloc;

std::size_t VM::initialHeapSize = 0xA00000u;

std::size_t VM::minHeapSize = 0x100000u;

int VM::heapGrowthPercent = 50;

std::size_t VM::chunkSize = 0x500000u;

VM::VM()
    : vm_{ nullptr }
{
    WrenConfiguration configuration{};
    wrenInitConfiguration(&configuration);
    configuration.reallocateFn = reallocateFnWrapper;
    configuration.initialHeapSize = initialHeapSize;
    configuration.minHeapSize = minHeapSize;
    configuration.heapGrowthPercent = heapGrowthPercent;
    configuration.bindForeignMethodFn = foreignMethodProvider;
    configuration.loadModuleFn = loadModuleFnWrapper;
    configuration.bindForeignClassFn = foreignClassProvider;
    configuration.writeFn = writeFnWrapper;
    configuration.errorFn = errorFnWrapper;
    configuration.userData = new BoundState();

    vm_ = wrenNewVM(&configuration);
}

VM::VM(VM&& other)
    : vm_{ other.vm_ }
{
    other.vm_ = nullptr;
}

VM& VM::operator=(VM&& rhs)
{
    vm_ = rhs.vm_;
    rhs.vm_ = nullptr;
    return *this;
}

VM::~VM()
{
    if (vm_ != nullptr)
    {
        delete (BoundState*)wrenGetUserData(vm_);
        wrenFreeVM(vm_);
    }
}

WrenVM* VM::vm()
{
    return vm_;
}

Result VM::executeModule(const std::string& mod)
{
    const std::string source(loadModuleFn(mod.c_str()));
    auto res = wrenInterpret(vm_, source.c_str());

    if (res == WrenInterpretResult::WREN_RESULT_COMPILE_ERROR)
    {
        return Result::CompileError;
    }

    if (res == WrenInterpretResult::WREN_RESULT_RUNTIME_ERROR)
    {
        return Result::RuntimeError;
    }

    return Result::Success;
}

Result VM::executeString(const std::string& code)
{
    auto res = wrenInterpret(vm_, code.c_str());

    if (res == WrenInterpretResult::WREN_RESULT_COMPILE_ERROR)
    {
        return Result::CompileError;
    }

    if (res == WrenInterpretResult::WREN_RESULT_RUNTIME_ERROR)
    {
        return Result::RuntimeError;
    }

    return Result::Success;
}

void VM::collectGarbage()
{
    wrenCollectGarbage(vm_);
}

Method VM::method(
    const std::string& mod,
    const std::string& var,
    const std::string& sig
)
{
    wrenEnsureSlots(vm_, 1);
    wrenGetVariable(vm_, mod.c_str(), var.c_str(), 0);
    WrenHandle* variable = wrenGetSlotHandle(vm_, 0);
    WrenHandle* handle = wrenMakeCallHandle(vm_, sig.c_str());
    return Method(this, variable, handle);
}

ModuleContext VM::beginModule(std::string name)
{
    return ModuleContext(vm_, name);
}

}
<commit_msg>Default error print must allow null module name<commit_after>#include "Wren++.h"
#include <cstdlib>  // for malloc
#include <cstring>  // for strcmp, memcpy
#include <cassert>
#include <iostream>

namespace
{

struct BoundState
{
    std::unordered_map< std::size_t, WrenForeignMethodFn > methods{};
    std::unordered_map< std::size_t, WrenForeignClassMethods > classes{};
};

WrenForeignMethodFn foreignMethodProvider(WrenVM* vm,
    const char* module,
    const char* className,
    bool isStatic,
    const char* signature)
{
    auto* boundState = (BoundState*)wrenGetUserData(vm);
    auto it = boundState->methods.find(wrenpp::detail::hashMethodSignature(module, className, isStatic, signature));
    if (it == boundState->methods.end())
    {
        return NULL;
    }

    return it->second;
}

WrenForeignClassMethods foreignClassProvider(WrenVM* vm, const char* m, const char* c)
{
    auto* boundState = (BoundState*)wrenGetUserData(vm);
    auto it = boundState->classes.find(wrenpp::detail::hashClassSignature(m, c));
    if (it == boundState->classes.end())
    {
        return WrenForeignClassMethods{ nullptr, nullptr };
    }

    return it->second;
}

inline const char* errorTypeToString(WrenErrorType type)
{
    switch (type)
    {
        case WREN_ERROR_COMPILE: return "WREN_ERROR_COMPILE";
        case WREN_ERROR_RUNTIME: return "WREN_ERROR_RUNTIME";
        case WREN_ERROR_STACK_TRACE: return "WREN_ERROR_STACK_TRACE";
        default: assert(false); return "";
    }
}

char* loadModuleFnWrapper(WrenVM* vm, const char* mod)
{
    return wrenpp::VM::loadModuleFn(mod);
}

void writeFnWrapper(WrenVM* vm, const char* text)
{
    wrenpp::VM::writeFn(text);
}

void errorFnWrapper(WrenVM*, WrenErrorType type, const char* module, int line, const char* message)
{
    wrenpp::VM::errorFn(type, module, line, message);
}

void* reallocateFnWrapper(void* memory, std::size_t newSize)
{
    return wrenpp::VM::reallocateFn(memory, newSize);
}

}

namespace wrenpp
{

namespace detail
{
void registerFunction(WrenVM* vm, const std::string& mod, const std::string& cName, bool isStatic, std::string sig, WrenForeignMethodFn function)
{
    BoundState* boundState = (BoundState*)wrenGetUserData(vm);
    std::size_t hash = detail::hashMethodSignature(mod.c_str(), cName.c_str(), isStatic, sig.c_str());
    boundState->methods.insert(std::make_pair(hash, function));
}

void registerClass(WrenVM* vm, const std::string& mod, std::string cName, WrenForeignClassMethods methods)
{
    BoundState* boundState = (BoundState*)wrenGetUserData(vm);
    std::size_t hash = detail::hashClassSignature(mod.c_str(), cName.c_str());
    boundState->classes.insert(std::make_pair(hash, methods));
}

}

Value::Value(bool val)
    : valueType_{ WREN_TYPE_BOOL }, string_{ nullptr }
{
    set_(val);
}

Value::Value(float val)
    : valueType_{ WREN_TYPE_NUM }, string_{ nullptr }
{
    set_(val);
}

Value::Value(double val)
    : valueType_{ WREN_TYPE_NUM }, string_{ nullptr }
{
    set_(val);
}

Value::Value(int val)
    : valueType_{ WREN_TYPE_NUM }, string_{ nullptr }
{
    set_(val);
}

Value::Value(unsigned int val)
    : valueType_{ WREN_TYPE_NUM }, string_{ nullptr }
{
    set_(val);
}

Value::Value(const char* str)
    : valueType_{ WREN_TYPE_STRING }, string_{ nullptr }
{
    string_ = (char*)VM::reallocateFn(nullptr, std::strlen(str) + 1);
    std::strcpy(string_, str);
}

Value::~Value()
{
    if (string_)
    {
        VM::reallocateFn(string_, 0u);
    }
}

Method::Method(VM* vm, WrenHandle* variable, WrenHandle* method)
    : vm_(vm),
    method_(method),
    variable_(variable)
{}

Method::Method(Method&& other)
    : vm_(other.vm_),
    method_(other.method_),
    variable_(other.variable_)
{
    other.vm_ = nullptr;
    other.method_ = nullptr;
    other.variable_ = nullptr;
}

Method::~Method()
{
    if (vm_)
    {
        assert(method_ && variable_);
        wrenReleaseHandle(vm_->vm(), method_);
        wrenReleaseHandle(vm_->vm(), variable_);
    }
}

Method& Method::operator=(Method&& rhs)
{
    vm_ = rhs.vm_;
    method_ = rhs.method_;
    variable_ = rhs.variable_;
    rhs.vm_ = nullptr;
    rhs.method_ = nullptr;
    rhs.variable_ = nullptr;

    return *this;
}

ClassContext ModuleContext::beginClass(std::string c)
{
    return ClassContext(c, *this);
}

void ModuleContext::endModule() {}

ModuleContext& ClassContext::endClass()
{
    return module_;
}

ClassContext::ClassContext(std::string c, ModuleContext& mod)
    : module_(mod),
    class_(c)
{}

ClassContext& ClassContext::bindCFunction(bool isStatic, std::string signature, WrenForeignMethodFn function)
{
    detail::registerFunction(module_.vm_, module_.name_, class_, isStatic, signature, function);
    return *this;
}

/*
 * Returns the source as a heap-allocated string.
 * Uses malloc, because our reallocateFn is set to default:
 * it uses malloc, realloc and free.
 * */
LoadModuleFn VM::loadModuleFn = [](const char* mod) -> char*
{
    std::string path(mod);
    path += ".wren";
    std::string source;
    try
    {
        source = wrenpp::detail::fileToString(path);
    }
    catch (const std::exception&)
    {
        return NULL;
    }
    char* buffer = (char*)malloc(source.size());
    assert(buffer != nullptr);
    memcpy(buffer, source.c_str(), source.size());
    return buffer;
};

WriteFn VM::writeFn = [](const char* text) -> void
{
    std::cout << text;
};

ErrorFn VM::errorFn = [](WrenErrorType type, const char* module_name, int line, const char* message) -> void
{
    const char* typeStr = errorTypeToString(type);
    if (module_name)
    {
        std::cout << typeStr << " in " << module_name << ":" << line << "> " << message << std::endl;
    }
    else
    {
        std::cout << typeStr << "> " << message << std::endl;
    }
};

ReallocateFn VM::reallocateFn = std::realloc;

std::size_t VM::initialHeapSize = 0xA00000u;

std::size_t VM::minHeapSize = 0x100000u;

int VM::heapGrowthPercent = 50;

std::size_t VM::chunkSize = 0x500000u;

VM::VM()
    : vm_{ nullptr }
{
    WrenConfiguration configuration{};
    wrenInitConfiguration(&configuration);
    configuration.reallocateFn = reallocateFnWrapper;
    configuration.initialHeapSize = initialHeapSize;
    configuration.minHeapSize = minHeapSize;
    configuration.heapGrowthPercent = heapGrowthPercent;
    configuration.bindForeignMethodFn = foreignMethodProvider;
    configuration.loadModuleFn = loadModuleFnWrapper;
    configuration.bindForeignClassFn = foreignClassProvider;
    configuration.writeFn = writeFnWrapper;
    configuration.errorFn = errorFnWrapper;
    configuration.userData = new BoundState();

    vm_ = wrenNewVM(&configuration);
}

VM::VM(VM&& other)
    : vm_{ other.vm_ }
{
    other.vm_ = nullptr;
}

VM& VM::operator=(VM&& rhs)
{
    vm_ = rhs.vm_;
    rhs.vm_ = nullptr;
    return *this;
}

VM::~VM()
{
    if (vm_ != nullptr)
    {
        delete (BoundState*)wrenGetUserData(vm_);
        wrenFreeVM(vm_);
    }
}

WrenVM* VM::vm()
{
    return vm_;
}

Result VM::executeModule(const std::string& mod)
{
    const std::string source(loadModuleFn(mod.c_str()));
    auto res = wrenInterpret(vm_, source.c_str());

    if (res == WrenInterpretResult::WREN_RESULT_COMPILE_ERROR)
    {
        return Result::CompileError;
    }

    if (res == WrenInterpretResult::WREN_RESULT_RUNTIME_ERROR)
    {
        return Result::RuntimeError;
    }

    return Result::Success;
}

Result VM::executeString(const std::string& code)
{
    auto res = wrenInterpret(vm_, code.c_str());

    if (res == WrenInterpretResult::WREN_RESULT_COMPILE_ERROR)
    {
        return Result::CompileError;
    }

    if (res == WrenInterpretResult::WREN_RESULT_RUNTIME_ERROR)
    {
        return Result::RuntimeError;
    }

    return Result::Success;
}

void VM::collectGarbage()
{
    wrenCollectGarbage(vm_);
}

Method VM::method(
    const std::string& mod,
    const std::string& var,
    const std::string& sig
)
{
    wrenEnsureSlots(vm_, 1);
    wrenGetVariable(vm_, mod.c_str(), var.c_str(), 0);
    WrenHandle* variable = wrenGetSlotHandle(vm_, 0);
    WrenHandle* handle = wrenMakeCallHandle(vm_, sig.c_str());
    return Method(this, variable, handle);
}

ModuleContext VM::beginModule(std::string name)
{
    return ModuleContext(vm_, name);
}

}
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkPointSet.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

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

=========================================================================*/
#include "vtkPointSet.h"

#include "vtkCell.h"
#include "vtkGarbageCollector.h"
#include "vtkGenericCell.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkPointLocator.h"
#include "vtkPointSetCellIterator.h"

#include "vtkSmartPointer.h"
#define VTK_CREATE(type, name) \
  vtkSmartPointer<type> name = vtkSmartPointer<type>::New()

#include <set>

vtkCxxSetObjectMacro(vtkPointSet,Points,vtkPoints);

vtkPointSet::vtkPointSet ()
{
  this->Points = NULL;
  this->Locator = NULL;
}

//----------------------------------------------------------------------------
vtkPointSet::~vtkPointSet ()
{
  this->Cleanup();

  if ( this->Locator )
    {
    this->Locator->UnRegister(this);
    this->Locator = NULL;
    }
}

//----------------------------------------------------------------------------
// Copy the geometric structure of an input point set object.
void vtkPointSet::CopyStructure(vtkDataSet *ds)
{
  vtkPointSet *ps=static_cast<vtkPointSet *>(ds);

  if ( this->Points != ps->Points )
    {
    if ( this->Locator )
      {
      this->Locator->Initialize();
      }
    this->SetPoints(ps->Points);
    }
}

//----------------------------------------------------------------------------
void vtkPointSet::Cleanup()
{
  if ( this->Points )
    {
    this->Points->UnRegister(this);
    this->Points = NULL;
    }
}

//----------------------------------------------------------------------------
void vtkPointSet::Initialize()
{
  vtkDataSet::Initialize();

  this->Cleanup();

  if ( this->Locator )
    {
    this->Locator->Initialize();
    }
}
//----------------------------------------------------------------------------
void vtkPointSet::ComputeBounds()
{
  double *bounds;

  if ( this->Points )
    {
    if ( this->GetMTime() >= this->ComputeTime )
      {
      bounds = this->Points->GetBounds();
      for (int i=0; i<6; i++)
        {
        this->Bounds[i] = bounds[i];
        }
      this->ComputeTime.Modified();
      }
    }
}

//----------------------------------------------------------------------------
unsigned long int vtkPointSet::GetMTime()
{
  unsigned long int dsTime = vtkDataSet::GetMTime();

  if ( this->Points )
    {
    if ( this->Points->GetMTime() > dsTime )
      {
      dsTime = this->Points->GetMTime();
      }
    }

  // don't get locator's mtime because its an internal object that cannot be
  // modified directly from outside. Causes problems due to FindCell()
  // SetPoints() method.

  return dsTime;
}

//----------------------------------------------------------------------------
vtkIdType vtkPointSet::FindPoint(double x[3])
{
  if ( !this->Points )
    {
    return -1;
    }

  if ( !this->Locator )
    {
    this->Locator = vtkPointLocator::New();
    this->Locator->Register(this);
    this->Locator->Delete();
    this->Locator->SetDataSet(this);
    }

  if ( this->Points->GetMTime() > this->Locator->GetMTime() )
    {
    this->Locator->SetDataSet(this);
    }

  return this->Locator->FindClosestPoint(x);
}

//the furthest the walk can be - prevents aimless wandering
#define VTK_MAX_WALK 12

//-----------------------------------------------------------------------------
// Used internally by FindCell to walk through neighbors from a starting cell.
// The arguments are the same as those for FindCell.  In addition, visitedCells
// keeps a list of cells already traversed.  If we run into such already
// visited, the walk terminates since we assume we already walked from that cell
// and found nothing.  The ptIds and neighbors lists are buffers used
// internally.  They are passed in so that they do not have to be continuously
// reallocated.
static vtkIdType FindCellWalk(vtkPointSet *self, double x[3], vtkCell *cell,
                              vtkGenericCell *gencell, vtkIdType cellId,
                              double tol2, int &subId, double pcoords[3],
                              double *weights,
                              std::set<vtkIdType> &visitedCells,
                              vtkIdList *ptIds, vtkIdList *neighbors)
{
  for (int walk = 0; walk < VTK_MAX_WALK; walk++)
    {
    // Check to see if we already visited this cell.
    if (visitedCells.find(cellId) != visitedCells.end()) break;
    visitedCells.insert(cellId);

    // Get information for the cell.
    if (!cell)
      {
      if (gencell)
        {
        self->GetCell(cellId, gencell);
        cell = gencell;
        }
      else
        {
        cell = self->GetCell(cellId);
        }
      }

    // Check to see if the cell contains the point.
    double closestPoint[3];
    double dist2;
    if (   (cell->EvaluatePosition(x, closestPoint, subId,
                                   pcoords, dist2, weights) == 1)
        && (dist2 <= tol2) )
      {
      return cellId;
      }

    // This is not the right cell.  Find the next one.
    cell->CellBoundary(subId, pcoords, ptIds);
    self->GetCellNeighbors(cellId, ptIds, neighbors);
    // If there is no next one, exit.
    if (neighbors->GetNumberOfIds() < 1) break;
    // Set the next cell as the current one and iterate.
    cellId = neighbors->GetId(0);
    cell = NULL;
    }

  // Could not find a cell.
  return -1;
}

//-----------------------------------------------------------------------------
static vtkIdType FindCellWalk(vtkPointSet *self, double x[3],
                              vtkGenericCell *gencell, vtkIdList *cellIds,
                              double tol2, int &subId, double pcoords[3],
                              double *weights,
                              std::set<vtkIdType> &visitedCells,
                              vtkIdList *ptIds, vtkIdList *neighbors)
{
  for (vtkIdType i = 0; i < cellIds->GetNumberOfIds(); i++)
    {
    vtkIdType cellId = cellIds->GetId(i);
    vtkIdType foundCell = FindCellWalk(self, x, NULL, gencell, cellId,
                                       tol2, subId, pcoords, weights,
                                       visitedCells, ptIds, neighbors);
    if (foundCell >= 0) return foundCell;
    }
  return -1;
}

//----------------------------------------------------------------------------
vtkIdType vtkPointSet::FindCell(double x[3], vtkCell *cell,
                                vtkGenericCell *gencell, vtkIdType cellId,
                                double tol2, int& subId, double pcoords[3],
                                double *weights)
{
  vtkIdType foundCell;

  // make sure everything is up to snuff
  if ( !this->Points || this->Points->GetNumberOfPoints() < 1)
    {
    return -1;
    }

  // Check to see if the point is within the bounds of the data.  This is not
  // a strict check, but it is fast.
  double bounds[6];
  this->GetBounds(bounds);
  double tol = sqrt(tol2);
  if (   (x[0] < bounds[0] - tol) || (x[0] > bounds[1] + tol)
      || (x[1] < bounds[2] - tol) || (x[1] > bounds[3] + tol)
      || (x[2] < bounds[4] - tol) || (x[2] > bounds[5] + tol) )
    {
    return -1;
    }

  if ( !this->Locator )
    {
    this->Locator = vtkPointLocator::New();
    this->Locator->Register(this);
    this->Locator->Delete();
    this->Locator->SetDataSet(this);
    this->Locator->BuildLocator();
    }

  if ( this->Points->GetMTime() > this->Locator->GetMTime() )
    {
    this->Locator->SetDataSet(this);
    this->Locator->BuildLocator();
    }

  std::set<vtkIdType> visitedCells;
  VTK_CREATE(vtkIdList, ptIds);
  ptIds->Allocate(8, 100);
  VTK_CREATE(vtkIdList, neighbors);
  neighbors->Allocate(8, 100);

  // If we are given a starting cell, try that.
  if (cell && (cellId >= 0))
    {
    foundCell = FindCellWalk(this, x, cell, gencell, cellId,
                             tol2, subId, pcoords, weights,
                             visitedCells, ptIds, neighbors);
    if (foundCell >= 0) return foundCell;
    }

  VTK_CREATE(vtkIdList, cellIds);
  cellIds->Allocate(8,100);

  // Now find the point closest to the coordinates given and search from the
  // adjacent cells.
  vtkIdType ptId = this->Locator->FindClosestPoint(x);
  if (ptId < 0) return -1;
  this->GetPointCells(ptId, cellIds);
  foundCell = FindCellWalk(this, x, gencell, cellIds,
                           tol2, subId, pcoords, weights,
                           visitedCells, ptIds, neighbors);
  if (foundCell >= 0) return foundCell;

  // It is possible that the toplogy is not fully connected.  That is, two
  // points in the point list could be coincident.  Handle that by looking
  // at every point within the tolerance and consider all cells connected.
  // It has been suggested that we should really do this coincident point
  // check at every point as we walk through neighbors, which would happen
  // in FindCellWalk.  If that were ever implemented, this step might become
  // unnecessary.
  double ptCoord[3];
  this->GetPoint(ptId, ptCoord);
  VTK_CREATE(vtkIdList, coincidentPtIds);
  coincidentPtIds->Allocate(8, 100);
  this->Locator->FindPointsWithinRadius(tol2, ptCoord, coincidentPtIds);
  coincidentPtIds->DeleteId(ptId);      // Already searched this one.
  for (vtkIdType i = 0; i < coincidentPtIds->GetNumberOfIds(); i++)
    {
    this->GetPointCells(coincidentPtIds->GetId(i), cellIds);
    foundCell = FindCellWalk(this, x, gencell, cellIds,
                             tol2, subId, pcoords, weights,
                             visitedCells, ptIds, neighbors);
    if (foundCell >= 0) return foundCell;
    }

  // Could not find the cell.
  return -1;
}

//----------------------------------------------------------------------------
vtkCellIterator *vtkPointSet::NewCellIterator()
{
  vtkPointSetCellIterator *iter = vtkPointSetCellIterator::New();
  iter->SetPointSet(this);
  return iter;
}

//----------------------------------------------------------------------------
vtkIdType vtkPointSet::FindCell(double x[3], vtkCell *cell, vtkIdType cellId,
                                double tol2, int& subId,double pcoords[3],
                                double *weights)
{
  return
    this->FindCell( x, cell, NULL, cellId, tol2, subId, pcoords, weights );
}

#undef VTK_MAX_WALK

//----------------------------------------------------------------------------
void vtkPointSet::Squeeze()
{
  if ( this->Points )
    {
    this->Points->Squeeze();
    }
  vtkDataSet::Squeeze();
}

//----------------------------------------------------------------------------
void vtkPointSet::ReportReferences(vtkGarbageCollector* collector)
{
  this->Superclass::ReportReferences(collector);
  vtkGarbageCollectorReport(collector, this->Locator, "Locator");
}

//----------------------------------------------------------------------------
unsigned long vtkPointSet::GetActualMemorySize()
{
  unsigned long size=this->vtkDataSet::GetActualMemorySize();
  if ( this->Points )
    {
    size += this->Points->GetActualMemorySize();
    }
  return size;
}

//----------------------------------------------------------------------------
void vtkPointSet::ShallowCopy(vtkDataObject *dataObject)
{
  vtkPointSet *pointSet = vtkPointSet::SafeDownCast(dataObject);

  if ( pointSet != NULL )
    {
    this->SetPoints(pointSet->GetPoints());
    }

  // Do superclass
  this->vtkDataSet::ShallowCopy(dataObject);
}

//----------------------------------------------------------------------------
void vtkPointSet::DeepCopy(vtkDataObject *dataObject)
{
  vtkPointSet *pointSet = vtkPointSet::SafeDownCast(dataObject);

  if ( pointSet != NULL )
    {
    vtkPoints* newPoints;
    vtkPoints* pointsToCopy = pointSet->GetPoints();
    if (pointsToCopy)
      {
      newPoints = pointsToCopy->NewInstance();
      newPoints->SetDataType(pointsToCopy->GetDataType());
      newPoints->DeepCopy(pointsToCopy);
      }
    else
      {
      newPoints = vtkPoints::New();
      }
    this->SetPoints(newPoints);
    newPoints->Delete();
    }

  // Do superclass
  this->vtkDataSet::DeepCopy(dataObject);
}

//----------------------------------------------------------------------------
vtkPointSet* vtkPointSet::GetData(vtkInformation* info)
{
  return info? vtkPointSet::SafeDownCast(info->Get(DATA_OBJECT())) : 0;
}

//----------------------------------------------------------------------------
vtkPointSet* vtkPointSet::GetData(vtkInformationVector* v, int i)
{
  return vtkPointSet::GetData(v->GetInformationObject(i));
}

//----------------------------------------------------------------------------
void vtkPointSet::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "Number Of Points: " << this->GetNumberOfPoints() << "\n";
  os << indent << "Point Coordinates: " << this->Points << "\n";
  os << indent << "Locator: " << this->Locator << "\n";
}

//----------------------------------------------------------------------------
void vtkPointSet::Register(vtkObjectBase* o)
{
  this->RegisterInternal(o, 1);
}

//----------------------------------------------------------------------------
void vtkPointSet::UnRegister(vtkObjectBase* o)
{
  this->UnRegisterInternal(o, 1);
}
<commit_msg>The wrong MTime was being checked in vtkPointSet::FindCell. Fixed.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkPointSet.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

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

=========================================================================*/
#include "vtkPointSet.h"

#include "vtkCell.h"
#include "vtkGarbageCollector.h"
#include "vtkGenericCell.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkPointLocator.h"
#include "vtkPointSetCellIterator.h"

#include "vtkSmartPointer.h"
#define VTK_CREATE(type, name) \
  vtkSmartPointer<type> name = vtkSmartPointer<type>::New()

#include <set>

vtkCxxSetObjectMacro(vtkPointSet,Points,vtkPoints);

vtkPointSet::vtkPointSet ()
{
  this->Points = NULL;
  this->Locator = NULL;
}

//----------------------------------------------------------------------------
vtkPointSet::~vtkPointSet ()
{
  this->Cleanup();

  if ( this->Locator )
    {
    this->Locator->UnRegister(this);
    this->Locator = NULL;
    }
}

//----------------------------------------------------------------------------
// Copy the geometric structure of an input point set object.
void vtkPointSet::CopyStructure(vtkDataSet *ds)
{
  vtkPointSet *ps=static_cast<vtkPointSet *>(ds);

  if ( this->Points != ps->Points )
    {
    if ( this->Locator )
      {
      this->Locator->Initialize();
      }
    this->SetPoints(ps->Points);
    }
}

//----------------------------------------------------------------------------
void vtkPointSet::Cleanup()
{
  if ( this->Points )
    {
    this->Points->UnRegister(this);
    this->Points = NULL;
    }
}

//----------------------------------------------------------------------------
void vtkPointSet::Initialize()
{
  vtkDataSet::Initialize();

  this->Cleanup();

  if ( this->Locator )
    {
    this->Locator->Initialize();
    }
}
//----------------------------------------------------------------------------
void vtkPointSet::ComputeBounds()
{
  double *bounds;

  if ( this->Points )
    {
    if ( this->GetMTime() >= this->ComputeTime )
      {
      bounds = this->Points->GetBounds();
      for (int i=0; i<6; i++)
        {
        this->Bounds[i] = bounds[i];
        }
      this->ComputeTime.Modified();
      }
    }
}

//----------------------------------------------------------------------------
unsigned long int vtkPointSet::GetMTime()
{
  unsigned long int dsTime = vtkDataSet::GetMTime();

  if ( this->Points )
    {
    if ( this->Points->GetMTime() > dsTime )
      {
      dsTime = this->Points->GetMTime();
      }
    }

  // don't get locator's mtime because its an internal object that cannot be
  // modified directly from outside. Causes problems due to FindCell()
  // SetPoints() method.

  return dsTime;
}

//----------------------------------------------------------------------------
vtkIdType vtkPointSet::FindPoint(double x[3])
{
  if ( !this->Points )
    {
    return -1;
    }

  if ( !this->Locator )
    {
    this->Locator = vtkPointLocator::New();
    this->Locator->Register(this);
    this->Locator->Delete();
    this->Locator->SetDataSet(this);
    }

  if ( this->Points->GetMTime() > this->Locator->GetMTime() )
    {
    this->Locator->SetDataSet(this);
    }

  return this->Locator->FindClosestPoint(x);
}

//the furthest the walk can be - prevents aimless wandering
#define VTK_MAX_WALK 12

//-----------------------------------------------------------------------------
// Used internally by FindCell to walk through neighbors from a starting cell.
// The arguments are the same as those for FindCell.  In addition, visitedCells
// keeps a list of cells already traversed.  If we run into such already
// visited, the walk terminates since we assume we already walked from that cell
// and found nothing.  The ptIds and neighbors lists are buffers used
// internally.  They are passed in so that they do not have to be continuously
// reallocated.
static vtkIdType FindCellWalk(vtkPointSet *self, double x[3], vtkCell *cell,
                              vtkGenericCell *gencell, vtkIdType cellId,
                              double tol2, int &subId, double pcoords[3],
                              double *weights,
                              std::set<vtkIdType> &visitedCells,
                              vtkIdList *ptIds, vtkIdList *neighbors)
{
  for (int walk = 0; walk < VTK_MAX_WALK; walk++)
    {
    // Check to see if we already visited this cell.
    if (visitedCells.find(cellId) != visitedCells.end()) break;
    visitedCells.insert(cellId);

    // Get information for the cell.
    if (!cell)
      {
      if (gencell)
        {
        self->GetCell(cellId, gencell);
        cell = gencell;
        }
      else
        {
        cell = self->GetCell(cellId);
        }
      }

    // Check to see if the cell contains the point.
    double closestPoint[3];
    double dist2;
    if (   (cell->EvaluatePosition(x, closestPoint, subId,
                                   pcoords, dist2, weights) == 1)
        && (dist2 <= tol2) )
      {
      return cellId;
      }

    // This is not the right cell.  Find the next one.
    cell->CellBoundary(subId, pcoords, ptIds);
    self->GetCellNeighbors(cellId, ptIds, neighbors);
    // If there is no next one, exit.
    if (neighbors->GetNumberOfIds() < 1) break;
    // Set the next cell as the current one and iterate.
    cellId = neighbors->GetId(0);
    cell = NULL;
    }

  // Could not find a cell.
  return -1;
}

//-----------------------------------------------------------------------------
static vtkIdType FindCellWalk(vtkPointSet *self, double x[3],
                              vtkGenericCell *gencell, vtkIdList *cellIds,
                              double tol2, int &subId, double pcoords[3],
                              double *weights,
                              std::set<vtkIdType> &visitedCells,
                              vtkIdList *ptIds, vtkIdList *neighbors)
{
  for (vtkIdType i = 0; i < cellIds->GetNumberOfIds(); i++)
    {
    vtkIdType cellId = cellIds->GetId(i);
    vtkIdType foundCell = FindCellWalk(self, x, NULL, gencell, cellId,
                                       tol2, subId, pcoords, weights,
                                       visitedCells, ptIds, neighbors);
    if (foundCell >= 0) return foundCell;
    }
  return -1;
}

//----------------------------------------------------------------------------
vtkIdType vtkPointSet::FindCell(double x[3], vtkCell *cell,
                                vtkGenericCell *gencell, vtkIdType cellId,
                                double tol2, int& subId, double pcoords[3],
                                double *weights)
{
  vtkIdType foundCell;

  // make sure everything is up to snuff
  if ( !this->Points || this->Points->GetNumberOfPoints() < 1)
    {
    return -1;
    }

  // Check to see if the point is within the bounds of the data.  This is not
  // a strict check, but it is fast.
  double bounds[6];
  this->GetBounds(bounds);
  double tol = sqrt(tol2);
  if (   (x[0] < bounds[0] - tol) || (x[0] > bounds[1] + tol)
      || (x[1] < bounds[2] - tol) || (x[1] > bounds[3] + tol)
      || (x[2] < bounds[4] - tol) || (x[2] > bounds[5] + tol) )
    {
    return -1;
    }

  if ( !this->Locator )
    {
    this->Locator = vtkPointLocator::New();
    this->Locator->Register(this);
    this->Locator->Delete();
    this->Locator->SetDataSet(this);
    this->Locator->BuildLocator();
    }

  if ( this->Points->GetMTime() > this->Locator->GetBuildTime() )
    {
    this->Locator->SetDataSet(this);
    this->Locator->BuildLocator();
    }

  std::set<vtkIdType> visitedCells;
  VTK_CREATE(vtkIdList, ptIds);
  ptIds->Allocate(8, 100);
  VTK_CREATE(vtkIdList, neighbors);
  neighbors->Allocate(8, 100);

  // If we are given a starting cell, try that.
  if (cell && (cellId >= 0))
    {
    foundCell = FindCellWalk(this, x, cell, gencell, cellId,
                             tol2, subId, pcoords, weights,
                             visitedCells, ptIds, neighbors);
    if (foundCell >= 0) return foundCell;
    }

  VTK_CREATE(vtkIdList, cellIds);
  cellIds->Allocate(8,100);

  // Now find the point closest to the coordinates given and search from the
  // adjacent cells.
  vtkIdType ptId = this->Locator->FindClosestPoint(x);
  if (ptId < 0) return -1;
  this->GetPointCells(ptId, cellIds);
  foundCell = FindCellWalk(this, x, gencell, cellIds,
                           tol2, subId, pcoords, weights,
                           visitedCells, ptIds, neighbors);
  if (foundCell >= 0) return foundCell;

  // It is possible that the toplogy is not fully connected.  That is, two
  // points in the point list could be coincident.  Handle that by looking
  // at every point within the tolerance and consider all cells connected.
  // It has been suggested that we should really do this coincident point
  // check at every point as we walk through neighbors, which would happen
  // in FindCellWalk.  If that were ever implemented, this step might become
  // unnecessary.
  double ptCoord[3];
  this->GetPoint(ptId, ptCoord);
  VTK_CREATE(vtkIdList, coincidentPtIds);
  coincidentPtIds->Allocate(8, 100);
  this->Locator->FindPointsWithinRadius(tol2, ptCoord, coincidentPtIds);
  coincidentPtIds->DeleteId(ptId);      // Already searched this one.
  for (vtkIdType i = 0; i < coincidentPtIds->GetNumberOfIds(); i++)
    {
    this->GetPointCells(coincidentPtIds->GetId(i), cellIds);
    foundCell = FindCellWalk(this, x, gencell, cellIds,
                             tol2, subId, pcoords, weights,
                             visitedCells, ptIds, neighbors);
    if (foundCell >= 0) return foundCell;
    }

  // Could not find the cell.
  return -1;
}

//----------------------------------------------------------------------------
vtkCellIterator *vtkPointSet::NewCellIterator()
{
  vtkPointSetCellIterator *iter = vtkPointSetCellIterator::New();
  iter->SetPointSet(this);
  return iter;
}

//----------------------------------------------------------------------------
vtkIdType vtkPointSet::FindCell(double x[3], vtkCell *cell, vtkIdType cellId,
                                double tol2, int& subId,double pcoords[3],
                                double *weights)
{
  return
    this->FindCell( x, cell, NULL, cellId, tol2, subId, pcoords, weights );
}

#undef VTK_MAX_WALK

//----------------------------------------------------------------------------
void vtkPointSet::Squeeze()
{
  if ( this->Points )
    {
    this->Points->Squeeze();
    }
  vtkDataSet::Squeeze();
}

//----------------------------------------------------------------------------
void vtkPointSet::ReportReferences(vtkGarbageCollector* collector)
{
  this->Superclass::ReportReferences(collector);
  vtkGarbageCollectorReport(collector, this->Locator, "Locator");
}

//----------------------------------------------------------------------------
unsigned long vtkPointSet::GetActualMemorySize()
{
  unsigned long size=this->vtkDataSet::GetActualMemorySize();
  if ( this->Points )
    {
    size += this->Points->GetActualMemorySize();
    }
  return size;
}

//----------------------------------------------------------------------------
void vtkPointSet::ShallowCopy(vtkDataObject *dataObject)
{
  vtkPointSet *pointSet = vtkPointSet::SafeDownCast(dataObject);

  if ( pointSet != NULL )
    {
    this->SetPoints(pointSet->GetPoints());
    }

  // Do superclass
  this->vtkDataSet::ShallowCopy(dataObject);
}

//----------------------------------------------------------------------------
void vtkPointSet::DeepCopy(vtkDataObject *dataObject)
{
  vtkPointSet *pointSet = vtkPointSet::SafeDownCast(dataObject);

  if ( pointSet != NULL )
    {
    vtkPoints* newPoints;
    vtkPoints* pointsToCopy = pointSet->GetPoints();
    if (pointsToCopy)
      {
      newPoints = pointsToCopy->NewInstance();
      newPoints->SetDataType(pointsToCopy->GetDataType());
      newPoints->DeepCopy(pointsToCopy);
      }
    else
      {
      newPoints = vtkPoints::New();
      }
    this->SetPoints(newPoints);
    newPoints->Delete();
    }

  // Do superclass
  this->vtkDataSet::DeepCopy(dataObject);
}

//----------------------------------------------------------------------------
vtkPointSet* vtkPointSet::GetData(vtkInformation* info)
{
  return info? vtkPointSet::SafeDownCast(info->Get(DATA_OBJECT())) : 0;
}

//----------------------------------------------------------------------------
vtkPointSet* vtkPointSet::GetData(vtkInformationVector* v, int i)
{
  return vtkPointSet::GetData(v->GetInformationObject(i));
}

//----------------------------------------------------------------------------
void vtkPointSet::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "Number Of Points: " << this->GetNumberOfPoints() << "\n";
  os << indent << "Point Coordinates: " << this->Points << "\n";
  os << indent << "Locator: " << this->Locator << "\n";
}

//----------------------------------------------------------------------------
void vtkPointSet::Register(vtkObjectBase* o)
{
  this->RegisterInternal(o, 1);
}

//----------------------------------------------------------------------------
void vtkPointSet::UnRegister(vtkObjectBase* o)
{
  this->UnRegisterInternal(o, 1);
}
<|endoftext|>