<commit_before>/*=========================================================================
 *
 *  Copyright Leiden University Medical Center, Erasmus University Medical
 *  Center and contributors
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

#include "selxSuperElastixFilter.h"

#include "selxItkSmoothingRecursiveGaussianImageFilterComponent.h"
#include "selxItkImageSink.h"
#include "selxItkImageSource.h"

#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"

#include "selxDefaultComponents.h"

#include "selxDataManager.h"
#include "gtest/gtest.h"

/** this test uses the following blueprint setup

 [SourceComponent] - [itkImageFilter] - [itkImageFilter] - [SinkComponent]

 - All the nodes are identified by their Class names
 - All Connections are identified by their Interface names

 The overlord finds the Source and Sink Components and connects these to it's external pipeline (internal reader and writer filters, currently).
*/

namespace selx
{
class itkImageFilterTest : public ::testing::Test
{
public:
  using BlueprintITKType = itk::SharedPointerDataObjectDecorator< Blueprint >;
  typedef BlueprintITKType::Pointer                                 BlueprintITKPointer;

  typedef std::shared_ptr< Blueprint >        BlueprintPointer;
  typedef Blueprint::ParameterMapType         ParameterMapType;
  typedef Blueprint::ParameterValueType       ParameterValueType;
  typedef DataManager                         DataManagerType;

  typedef SuperElastixFilter< TypeList< > >   SuperElastixFilterType;

  typedef itk::Image< double, 3 >             Image3DType;
  typedef itk::ImageFileReader< Image3DType > ImageReader3DType;
  typedef itk::ImageFileWriter< Image3DType > ImageWriter3DType;

  virtual void SetUp()
  {
    /** register all components used for this test */
    // For testing the itkfilter pipeline
    ComponentFactory< ItkSmoothingRecursiveGaussianImageFilterComponent< 3, double >>::RegisterOneFactory();
    ComponentFactory< ItkImageSinkComponent< 3, double >>::RegisterOneFactory();
    ComponentFactory< ItkImageSourceComponent< 3, double >>::RegisterOneFactory();
    // For testing templated components
    ComponentFactory< ItkSmoothingRecursiveGaussianImageFilterComponent< 2, double >>::RegisterOneFactory();
    ComponentFactory< ItkSmoothingRecursiveGaussianImageFilterComponent< 3, float >>::RegisterOneFactory();
    ComponentFactory< ItkSmoothingRecursiveGaussianImageFilterComponent< 2, float >>::RegisterOneFactory();

    /** make example blueprint configuration */
    BlueprintPointer blueprint = BlueprintPointer( new Blueprint() );

    /** the 2 itkImageFilter Components are ItkSmoothingRecursiveGaussianImageFilterComponent*/
    ParameterMapType componentParameters;
    componentParameters[ "NameOfClass" ] = { "ItkSmoothingRecursiveGaussianImageFilterComponent" };
    // The parameters over which the Component is templated are criteria for the ComponentSelector too.
    componentParameters[ "Dimensionality" ] = { "3" }; // template parameters
    componentParameters[ "PixelType" ]      = { "double" };

    // Setting of the component are considered as criteria too. If the components can interpret the parameters, it's all good.
    componentParameters[ "Sigma" ] = { "2.5" };

    blueprint->SetComponent( "FistStageFilter", componentParameters );
    blueprint->SetComponent( "SecondStageFilter", componentParameters );

    // TODO: For now, the connections to make are explicitly indicated by the Interface name.
    // Design consideration: connections might be indicated by higher concepts ( MetricCostConnection: value and/or derivative? DefaultPipeline? )
    ParameterMapType connectionParameters;
    //connectionParameters["NameOfInterface"] = { "itkImageSourceInterface" };

    //TODO: check direction
    blueprint->SetConnection( "FistStageFilter", "SecondStageFilter", connectionParameters );

    /** Add a description of the SourceComponent*/
    ParameterMapType sourceComponentParameters;
    sourceComponentParameters[ "NameOfClass" ] = { "ItkImageSourceComponent" };
    blueprint->SetComponent( "Source", sourceComponentParameters );

    /** Add a description of the SinkComponent*/
    ParameterMapType sinkComponentParameters;
    sinkComponentParameters[ "NameOfClass" ] = { "ItkImageSinkComponent" };
    blueprint->SetComponent( "Sink", sinkComponentParameters );

    /** Connect Sink and Source to the itkImageFilter Components*/
    blueprint->SetConnection( "Source", "FistStageFilter", connectionParameters ); //
    blueprint->SetConnection( "SecondStageFilter", "Sink", connectionParameters );

    BlueprintITKPointer ITKBlueprint = BlueprintITKType::New();
    ITKBlueprint->Set( blueprint );
  }

  virtual void TearDown()
  {
    itk::ObjectFactoryBase::UnRegisterAllFactories();
  }

  BlueprintITKPointer ITKBlueprint;
};

TEST_F( itkImageFilterTest, Run )
{
  // Instantiate SuperElastix
  SuperElastixFilterType::Pointer superElastixFilter;
  EXPECT_NO_THROW( superElastixFilter = SuperElastixFilterType::New() );

  // Data manager provides the paths to the input and output data for unit tests
  DataManagerType::Pointer dataManager = DataManagerType::New();

  // Set up the readers and writers
  ImageReader3DType::Pointer inputImageReader = ImageReader3DType::New();
  inputImageReader->SetFileName( dataManager->GetInputFile( "sphereA3d.mhd" ) );

  ImageWriter3DType::Pointer resultImageWriter = ImageWriter3DType::New();
  resultImageWriter->SetFileName( dataManager->GetOutputFile( "itkImageFilterTest.mhd" ) );

  // Connect SuperElastix in an itk pipeline
  superElastixFilter->SetInput( "Source", inputImageReader->GetOutput() );
  resultImageWriter->SetInput( superElastixFilter->GetOutput< Image3DType >( "Sink" ) );

  EXPECT_NO_THROW( superElastixFilter->SetBlueprint( ITKBlueprint ) );

  //Optional Update call
  //superElastixFilter->Update();

  // Update call on the writers triggers SuperElastix to configure and execute
  EXPECT_NO_THROW( resultImageWriter->Update() );
}
} // namespace selx
<commit_msg>BUG: incorrect blueprint member assignment<commit_after>/*=========================================================================
 *
 *  Copyright Leiden University Medical Center, Erasmus University Medical
 *  Center and contributors
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

#include "selxSuperElastixFilter.h"

#include "selxItkSmoothingRecursiveGaussianImageFilterComponent.h"
#include "selxItkImageSink.h"
#include "selxItkImageSource.h"

#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"

#include "selxDefaultComponents.h"

#include "selxDataManager.h"
#include "gtest/gtest.h"

/** this test uses the following blueprint setup

 [SourceComponent] - [itkImageFilter] - [itkImageFilter] - [SinkComponent]

 - All the nodes are identified by their Class names
 - All Connections are identified by their Interface names

 The overlord finds the Source and Sink Components and connects these to it's external pipeline (internal reader and writer filters, currently).
*/

namespace selx
{
class itkImageFilterTest : public ::testing::Test
{
public:
  using BlueprintITKType = itk::SharedPointerDataObjectDecorator< Blueprint >;
  typedef BlueprintITKType::Pointer                                 BlueprintITKPointer;

  typedef std::shared_ptr< Blueprint >        BlueprintPointer;
  typedef Blueprint::ParameterMapType         ParameterMapType;
  typedef Blueprint::ParameterValueType       ParameterValueType;
  typedef DataManager                         DataManagerType;

  typedef SuperElastixFilter< TypeList< > >   SuperElastixFilterType;

  typedef itk::Image< double, 3 >             Image3DType;
  typedef itk::ImageFileReader< Image3DType > ImageReader3DType;
  typedef itk::ImageFileWriter< Image3DType > ImageWriter3DType;

  virtual void SetUp()
  {
    /** register all components used for this test */
    // For testing the itkfilter pipeline
    ComponentFactory< ItkSmoothingRecursiveGaussianImageFilterComponent< 3, double >>::RegisterOneFactory();
    ComponentFactory< ItkImageSinkComponent< 3, double >>::RegisterOneFactory();
    ComponentFactory< ItkImageSourceComponent< 3, double >>::RegisterOneFactory();
    // For testing templated components
    ComponentFactory< ItkSmoothingRecursiveGaussianImageFilterComponent< 2, double >>::RegisterOneFactory();
    ComponentFactory< ItkSmoothingRecursiveGaussianImageFilterComponent< 3, float >>::RegisterOneFactory();
    ComponentFactory< ItkSmoothingRecursiveGaussianImageFilterComponent< 2, float >>::RegisterOneFactory();

    /** make example blueprint configuration */
    BlueprintPointer blueprint = BlueprintPointer( new Blueprint() );

    /** the 2 itkImageFilter Components are ItkSmoothingRecursiveGaussianImageFilterComponent*/
    ParameterMapType componentParameters;
    componentParameters[ "NameOfClass" ] = { "ItkSmoothingRecursiveGaussianImageFilterComponent" };
    // The parameters over which the Component is templated are criteria for the ComponentSelector too.
    componentParameters[ "Dimensionality" ] = { "3" }; // template parameters
    componentParameters[ "PixelType" ]      = { "double" };

    // Setting of the component are considered as criteria too. If the components can interpret the parameters, it's all good.
    componentParameters[ "Sigma" ] = { "2.5" };

    blueprint->SetComponent( "FistStageFilter", componentParameters );
    blueprint->SetComponent( "SecondStageFilter", componentParameters );

    // TODO: For now, the connections to make are explicitly indicated by the Interface name.
    // Design consideration: connections might be indicated by higher concepts ( MetricCostConnection: value and/or derivative? DefaultPipeline? )
    ParameterMapType connectionParameters;
    //connectionParameters["NameOfInterface"] = { "itkImageSourceInterface" };

    //TODO: check direction
    blueprint->SetConnection( "FistStageFilter", "SecondStageFilter", connectionParameters );

    /** Add a description of the SourceComponent*/
    ParameterMapType sourceComponentParameters;
    sourceComponentParameters[ "NameOfClass" ] = { "ItkImageSourceComponent" };
    blueprint->SetComponent( "Source", sourceComponentParameters );

    /** Add a description of the SinkComponent*/
    ParameterMapType sinkComponentParameters;
    sinkComponentParameters[ "NameOfClass" ] = { "ItkImageSinkComponent" };
    blueprint->SetComponent( "Sink", sinkComponentParameters );

    /** Connect Sink and Source to the itkImageFilter Components*/
    blueprint->SetConnection( "Source", "FistStageFilter", connectionParameters ); //
    blueprint->SetConnection( "SecondStageFilter", "Sink", connectionParameters );

    ITKBlueprint = BlueprintITKType::New();
    ITKBlueprint->Set( blueprint );
  }

  virtual void TearDown()
  {
    itk::ObjectFactoryBase::UnRegisterAllFactories();
  }

  BlueprintITKPointer ITKBlueprint;
};

TEST_F( itkImageFilterTest, Run )
{
  // Instantiate SuperElastix
  SuperElastixFilterType::Pointer superElastixFilter;
  EXPECT_NO_THROW( superElastixFilter = SuperElastixFilterType::New() );

  // Data manager provides the paths to the input and output data for unit tests
  DataManagerType::Pointer dataManager = DataManagerType::New();

  // Set up the readers and writers
  ImageReader3DType::Pointer inputImageReader = ImageReader3DType::New();
  inputImageReader->SetFileName( dataManager->GetInputFile( "sphereA3d.mhd" ) );

  ImageWriter3DType::Pointer resultImageWriter = ImageWriter3DType::New();
  resultImageWriter->SetFileName( dataManager->GetOutputFile( "itkImageFilterTest.mhd" ) );

  // Connect SuperElastix in an itk pipeline
  superElastixFilter->SetInput( "Source", inputImageReader->GetOutput() );
  resultImageWriter->SetInput( superElastixFilter->GetOutput< Image3DType >( "Sink" ) );

  EXPECT_NO_THROW( superElastixFilter->SetBlueprint( ITKBlueprint ) );

  //Optional Update call
  //superElastixFilter->Update();

  // Update call on the writers triggers SuperElastix to configure and execute
  EXPECT_NO_THROW( resultImageWriter->Update() );
}
} // namespace selx
<|endoftext|>


<commit_before>// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
//
//      --------------------------------------------------------------
//      Field Interp Miniapp: Transfer a GridFunction from one mesh onto another
//      --------------------------------------------------------------
//
// This miniapp provides the capability to transfer a GridFunction
// (H1, L2, H(div), and H(curl)) from one mesh onto another using FindPointsGSLIB.
// Using FindPoints, we identify the nodal positions of the target mesh with
// respect to the source mesh and then interpolate the source GridFunction.
// The interpolated values are then projected onto the desired FiniteElementSpace
// on the target mesh. Finally, the transferred solution is visualized using GLVis.
//
// Compile with: make field-interp
//
// An H(div) function file is provided in this directory for a sample run.
// Other functions [H1, H(curl), and L2] can be generated using existing MFEM
// example codes in the "../../examples/" directory.
//
// Sample run:
//   field-interp
//   field-interp -ft 3
//   field-interp -m1 triple-pt-1.mesh -s1 triple-pt-1.gf -m2 triple-pt-2.mesh -ft 1
//   field-interp -m2 ../meshing/amr-quad-q2.mesh -ft 0 -r 1

#include "mfem.hpp"
#include <fstream>

using namespace mfem;
using namespace std;

int main (int argc, char *argv[])
{
   // Set the method's default parameters.
   const char *src_mesh_file = "../meshing/square01.mesh";
   const char *tar_mesh_file = "../../data/inline-tri.mesh";
   const char *src_sltn_file = "square01_hdiv.gf";
   int order      = 3;
   int ref_levels = 0;
   int fieldtype  = -1;
   bool visualization = true;

   // Parse command-line options.
   OptionsParser args(argc, argv);
   args.AddOption(&src_mesh_file, "-m1", "--mesh1",
                  "Mesh file for the starting solution.");
   args.AddOption(&src_sltn_file, "-s1", "--solution1",
                  "Grid function for the starting solution.");
   args.AddOption(&tar_mesh_file, "-m2", "--mesh2",
                  "Mesh file for interpolation.");
   args.AddOption(&order, "-o", "--order",
                  "Order of the interpolated solution.");
   args.AddOption(&ref_levels, "-r", "--refine",
                  "Number of refinements of the interpolation mesh.");
   args.AddOption(&fieldtype, "-ft", "--field-type",
                  "Target GridFunction type: -1 - source GridFunction type (default),"
                  "0 - H1, 1 - L2, 2 - H(div), 3 - H(curl).");
   args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
                  "--no-visualization",
                  "Enable or disable GLVis visualization.");
   args.Parse();
   if (!args.Good())
   {
      args.PrintUsage(cout);
      return 1;
   }
   args.PrintOptions(cout);

   // Input meshes.
   Mesh mesh_1(src_mesh_file, 1, 1, false);
   Mesh mesh_2(tar_mesh_file, 1, 1, false);
   const int dim = mesh_1.Dimension();
   MFEM_ASSERT(dim == mesh_2.Dimension(), "Source and target meshes "
               "must be in the same dimension.");
   MFEM_VERIFY(dim > 1, "GSLIB requires a 2D or a 3D mesh" );

   for (int lev = 0; lev < ref_levels; lev++)
   {
      mesh_2.UniformRefinement();
   }

   if (mesh_1.GetNodes() == NULL) { mesh_1.SetCurvature(1); }
   if (mesh_2.GetNodes() == NULL) { mesh_2.SetCurvature(1); }
   const int mesh_poly_deg = mesh_2.GetNodes()->FESpace()->GetOrder(0);
   cout << "Source mesh curvature: "
        << mesh_1.GetNodes()->OwnFEC()->Name() << endl
        << "Target mesh curvature: "
        << mesh_2.GetNodes()->OwnFEC()->Name() << endl;

   ifstream mat_stream_1(src_sltn_file);
   GridFunction func_source(&mesh_1, mat_stream_1);

   // Display the starting mesh and the field.
   if (visualization)
   {
      char vishost[] = "localhost";
      int  visport   = 19916;
      socketstream sout1;
      sout1.open(vishost, visport);
      if (!sout1)
      {
         cout << "Unable to connect to GLVis server at "
              << vishost << ':' << visport << endl;
      }
      else
      {
         sout1.precision(8);
         sout1 << "solution\n" << mesh_1 << func_source
               << "window_title 'Source mesh and solution'"
               << "window_geometry 0 0 600 600";
         if (dim == 2) { sout1 << "keys RmjAc"; }
         if (dim == 3) { sout1 << "keys mA\n"; }
         sout1 << flush;
      }
   }

   const Geometry::Type gt = mesh_2.GetNodalFESpace()->GetFE(0)->GetGeomType();
   MFEM_VERIFY(gt != Geometry::PRISM, "Wedge elements are not currently "
               "supported.");

   // Ensure the source GridFunction can be transferred using FindPointsGSLIB.
   const FiniteElementCollection *fec_in = func_source.FESpace()->FEColl();
   std::cout << "Source FE collection: " << fec_in->Name() << std::endl;
   const int vdim_src   = func_source.FESpace()->GetVDim();
   int fieldtype_src = -1;
   {
      const H1_FECollection *fec_h1 = dynamic_cast<const H1_FECollection *>(fec_in);
      const L2_FECollection *fec_l2 = dynamic_cast<const L2_FECollection *>(fec_in);
      const RT_FECollection *fec_rt = dynamic_cast<const RT_FECollection *>(fec_in);
      const ND_FECollection *fec_nd = dynamic_cast<const ND_FECollection *>(fec_in);
      if (fec_h1)      { fieldtype_src = 0; }
      else if (fec_l2) { fieldtype_src = 1; }
      else if (fec_rt) { fieldtype_src = 2; }
      else if (fec_nd) { fieldtype_src = 3; }
      else { MFEM_ABORT("GridFunction type not supported yet."); }

      if (fieldtype_src <= 1 &&
          fec_h1->GetBasisType() != BasisType::GaussLobatto &&
          fec_h1->GetBasisType() != BasisType::GaussLegendre)
      {
         MFEM_ABORT("Only nodal basis are currently supported in this miniapp.");
      }
   }
   if (fieldtype == -1) { fieldtype = fieldtype_src; }

   // Setup the FiniteElementSpace and GridFunction on the target mesh.
   FiniteElementCollection *fec = NULL;
   FiniteElementSpace *fes = NULL;

   int vdim_tar = vdim_src;
   if (fieldtype == 0)
   {
      fec = new H1_FECollection(order, dim);
      vdim_tar = (fieldtype_src > 1) ? dim : vdim_src;
   }
   else if (fieldtype == 1)
   {
      fec = new L2_FECollection(order, dim);
      vdim_tar = (fieldtype_src > 1) ? dim : vdim_src;
   }
   else if (fieldtype == 2)
   {
      fec = new RT_FECollection(order, dim);
      vdim_tar = 1;
      MFEM_VERIFY(fieldtype_src > 1, "Cannot interpolate a scalar "
                  "GridFunction to a vector");

   }
   else if (fieldtype == 3)
   {
      fec = new ND_FECollection(order, dim);
      vdim_tar = 1;
      MFEM_VERIFY(fieldtype_src > 1, "Cannot interpolate a scalar "
                  "GridFunction to a vector");
   }
   else
   {
      MFEM_ABORT("GridFunction type not supported.");
   }
   std::cout << "Target FE collection: " << fec->Name() << std::endl;
   fes = new FiniteElementSpace(&mesh_2, fec, vdim_tar);
   GridFunction func_target(fes);

   const int NE = mesh_2.GetNE(),
             nsp = fes->GetFE(0)->GetNodes().GetNPoints(),
             ncomp_tar = func_target.VectorDim();

   // Generate list of points where the Gridfunction will be evaluated.
   Vector vxyz;
   if (fieldtype == 0 && order == mesh_poly_deg)
   {
      vxyz = *mesh_2.GetNodes();
   }
   else
   {
      vxyz.SetSize(nsp*NE*dim);
      for (int i = 0; i < NE; i++)
      {
         const FiniteElement *fe = fes->GetFE(i);
         const IntegrationRule ir = fe->GetNodes();
         ElementTransformation *et = fes->GetElementTransformation(i);

         DenseMatrix pos;
         et->Transform(ir, pos);
         Vector rowx(vxyz.GetData() + i*nsp, nsp),
                rowy(vxyz.GetData() + i*nsp + NE*nsp, nsp),
                rowz;
         if (dim == 3)
         {
            rowz.SetDataAndSize(vxyz.GetData() + i*nsp + 2*NE*nsp, nsp);
         }
         pos.GetRow(0, rowx);
         pos.GetRow(1, rowy);
         if (dim == 3) { pos.GetRow(2, rowz); }
      }
   }
   const int nodes_cnt = vxyz.Size() / dim;

   // Evaluate source gridfunction.
   Vector interp_vals(nodes_cnt*ncomp_tar);
   FindPointsGSLIB finder;
   finder.Setup(mesh_1);
   finder.Interpolate(vxyz, func_source, interp_vals);

   // Project the interpolated values to the target FiniteElementSpace.
   if (fieldtype <= 1) // H1 or L2
   {
      if ((fieldtype == 0 && order == mesh_poly_deg) || fieldtype == 1)
      {
         func_target = interp_vals;
      }
      else // H1 - but mesh order != GridFunction order
      {
         Array<int> vdofs;
         Vector vals;
         const int nsp = func_target.FESpace()->GetFE(0)->GetNodes().GetNPoints(),
                   NE  = mesh_2.GetNE();
         Vector elem_dof_vals(nsp*dim);

         for (int i = 0; i < mesh_2.GetNE(); i++)
         {
            fes->GetElementVDofs(i, vdofs);
            vals.SetSize(vdofs.Size());
            for (int j = 0; j < nsp; j++)
            {
               for (int d = 0; d < ncomp_tar; d++)
               {
                  // Arrange values byNodes
                  elem_dof_vals(j+d*nsp) = interp_vals(d*nsp*NE + i*nsp + j);
               }
            }
            func_target.SetSubVector(vdofs, elem_dof_vals);
         }
      }
   }
   else // H(div) or H(curl)
   {
      Array<int> vdofs;
      Vector vals;
      const int nsp = func_target.FESpace()->GetFE(0)->GetNodes().GetNPoints(),
                NE  = mesh_2.GetNE();
      Vector elem_dof_vals(nsp*dim);

      for (int i = 0; i < mesh_2.GetNE(); i++)
      {
         fes->GetElementVDofs(i, vdofs);
         vals.SetSize(vdofs.Size());
         for (int j = 0; j < nsp; j++)
         {
            for (int d = 0; d < ncomp_tar; d++)
            {
               // Arrange values byVDim
               elem_dof_vals(j*ncomp_tar+d) = interp_vals(d*nsp*NE + i*nsp + j);
            }
         }
         fes->GetFE(i)->ProjectFromNodes(elem_dof_vals,
                                         *fes->GetElementTransformation(i),
                                         vals);
         func_target.SetSubVector(vdofs, vals);
      }
   }

   // Visualize the transferred solution.
   if (visualization)
   {
      char vishost[] = "localhost";
      int  visport   = 19916;
      socketstream sout1;
      sout1.open(vishost, visport);
      if (!sout1)
      {
         cout << "Unable to connect to GLVis server at "
              << vishost << ':' << visport << endl;
      }
      else
      {
         sout1.precision(8);
         sout1 << "solution\n" << mesh_2 << func_target
               << "window_title 'Target mesh and solution'"
               << "window_geometry 600 0 600 600";
         if (dim == 2) { sout1 << "keys RmjAc"; }
         if (dim == 3) { sout1 << "keys mA\n"; }
         sout1 << flush;
      }
   }

   // Output the target mesh with the interpolated solution.
   ostringstream rho_name;
   rho_name  << "interpolated.gf";
   ofstream rho_ofs(rho_name.str().c_str());
   rho_ofs.precision(8);
   func_target.Save(rho_ofs);
   rho_ofs.close();

   // Free the internal gslib data.
   finder.FreeData();

   // Delete
   delete fes;
   delete fec;

   return 0;
}
<commit_msg>Minor.<commit_after>// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
//
//      --------------------------------------------------------------
//      Field Interp Miniapp: Transfer a GridFunction from one mesh onto another
//      --------------------------------------------------------------
//
// This miniapp provides the capability to transfer a GridFunction
// (H1, L2, H(div), and H(curl)) from one mesh onto another using FindPointsGSLIB.
// Using FindPoints, we identify the nodal positions of the target mesh with
// respect to the source mesh and then interpolate the source GridFunction.
// The interpolated values are then projected onto the desired FiniteElementSpace
// on the target mesh. Finally, the transferred solution is visualized using GLVis.
//
// Compile with: make field-interp
//
// An H(div) function file is provided in this directory for a sample run.
// Other functions [H1, H(curl), and L2] can be generated using existing MFEM
// example codes in the "../../examples/" directory.
//
// Sample runs:
//   field-interp
//   field-interp -ft 3
//   field-interp -m1 triple-pt-1.mesh -s1 triple-pt-1.gf -m2 triple-pt-2.mesh -ft 1
//   field-interp -m2 ../meshing/amr-quad-q2.mesh -ft 0 -r 1

#include "mfem.hpp"
#include <fstream>

using namespace mfem;
using namespace std;

int main (int argc, char *argv[])
{
   // Set the method's default parameters.
   const char *src_mesh_file = "../meshing/square01.mesh";
   const char *tar_mesh_file = "../../data/inline-tri.mesh";
   const char *src_sltn_file = "square01_hdiv.gf";
   int order      = 3;
   int ref_levels = 0;
   int fieldtype  = -1;
   bool visualization = true;

   // Parse command-line options.
   OptionsParser args(argc, argv);
   args.AddOption(&src_mesh_file, "-m1", "--mesh1",
                  "Mesh file for the starting solution.");
   args.AddOption(&src_sltn_file, "-s1", "--solution1",
                  "Grid function for the starting solution.");
   args.AddOption(&tar_mesh_file, "-m2", "--mesh2",
                  "Mesh file for interpolation.");
   args.AddOption(&order, "-o", "--order",
                  "Order of the interpolated solution.");
   args.AddOption(&ref_levels, "-r", "--refine",
                  "Number of refinements of the interpolation mesh.");
   args.AddOption(&fieldtype, "-ft", "--field-type",
                  "Target GridFunction type: -1 - source GridFunction type (default),"
                  "0 - H1, 1 - L2, 2 - H(div), 3 - H(curl).");
   args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
                  "--no-visualization",
                  "Enable or disable GLVis visualization.");
   args.Parse();
   if (!args.Good())
   {
      args.PrintUsage(cout);
      return 1;
   }
   args.PrintOptions(cout);

   // Input meshes.
   Mesh mesh_1(src_mesh_file, 1, 1, false);
   Mesh mesh_2(tar_mesh_file, 1, 1, false);
   const int dim = mesh_1.Dimension();
   MFEM_ASSERT(dim == mesh_2.Dimension(), "Source and target meshes "
               "must be in the same dimension.");
   MFEM_VERIFY(dim > 1, "GSLIB requires a 2D or a 3D mesh" );

   for (int lev = 0; lev < ref_levels; lev++)
   {
      mesh_2.UniformRefinement();
   }

   if (mesh_1.GetNodes() == NULL) { mesh_1.SetCurvature(1); }
   if (mesh_2.GetNodes() == NULL) { mesh_2.SetCurvature(1); }
   const int mesh_poly_deg = mesh_2.GetNodes()->FESpace()->GetOrder(0);
   cout << "Source mesh curvature: "
        << mesh_1.GetNodes()->OwnFEC()->Name() << endl
        << "Target mesh curvature: "
        << mesh_2.GetNodes()->OwnFEC()->Name() << endl;

   ifstream mat_stream_1(src_sltn_file);
   GridFunction func_source(&mesh_1, mat_stream_1);

   // Display the starting mesh and the field.
   if (visualization)
   {
      char vishost[] = "localhost";
      int  visport   = 19916;
      socketstream sout1;
      sout1.open(vishost, visport);
      if (!sout1)
      {
         cout << "Unable to connect to GLVis server at "
              << vishost << ':' << visport << endl;
      }
      else
      {
         sout1.precision(8);
         sout1 << "solution\n" << mesh_1 << func_source
               << "window_title 'Source mesh and solution'"
               << "window_geometry 0 0 600 600";
         if (dim == 2) { sout1 << "keys RmjAc"; }
         if (dim == 3) { sout1 << "keys mA\n"; }
         sout1 << flush;
      }
   }

   const Geometry::Type gt = mesh_2.GetNodalFESpace()->GetFE(0)->GetGeomType();
   MFEM_VERIFY(gt != Geometry::PRISM, "Wedge elements are not currently "
               "supported.");

   // Ensure the source GridFunction can be transferred using FindPointsGSLIB.
   const FiniteElementCollection *fec_in = func_source.FESpace()->FEColl();
   std::cout << "Source FE collection: " << fec_in->Name() << std::endl;
   const int vdim_src   = func_source.FESpace()->GetVDim();
   int fieldtype_src = -1;
   {
      const H1_FECollection *fec_h1 = dynamic_cast<const H1_FECollection *>(fec_in);
      const L2_FECollection *fec_l2 = dynamic_cast<const L2_FECollection *>(fec_in);
      const RT_FECollection *fec_rt = dynamic_cast<const RT_FECollection *>(fec_in);
      const ND_FECollection *fec_nd = dynamic_cast<const ND_FECollection *>(fec_in);
      if (fec_h1)      { fieldtype_src = 0; }
      else if (fec_l2) { fieldtype_src = 1; }
      else if (fec_rt) { fieldtype_src = 2; }
      else if (fec_nd) { fieldtype_src = 3; }
      else { MFEM_ABORT("GridFunction type not supported yet."); }

      if (fieldtype_src <= 1 &&
          fec_h1->GetBasisType() != BasisType::GaussLobatto &&
          fec_h1->GetBasisType() != BasisType::GaussLegendre)
      {
         MFEM_ABORT("Only nodal basis are currently supported in this miniapp.");
      }
   }
   if (fieldtype == -1) { fieldtype = fieldtype_src; }

   // Setup the FiniteElementSpace and GridFunction on the target mesh.
   FiniteElementCollection *fec = NULL;
   FiniteElementSpace *fes = NULL;

   int vdim_tar = vdim_src;
   if (fieldtype == 0)
   {
      fec = new H1_FECollection(order, dim);
      vdim_tar = (fieldtype_src > 1) ? dim : vdim_src;
   }
   else if (fieldtype == 1)
   {
      fec = new L2_FECollection(order, dim);
      vdim_tar = (fieldtype_src > 1) ? dim : vdim_src;
   }
   else if (fieldtype == 2)
   {
      fec = new RT_FECollection(order, dim);
      vdim_tar = 1;
      MFEM_VERIFY(fieldtype_src > 1, "Cannot interpolate a scalar "
                  "GridFunction to a vector");

   }
   else if (fieldtype == 3)
   {
      fec = new ND_FECollection(order, dim);
      vdim_tar = 1;
      MFEM_VERIFY(fieldtype_src > 1, "Cannot interpolate a scalar "
                  "GridFunction to a vector");
   }
   else
   {
      MFEM_ABORT("GridFunction type not supported.");
   }
   std::cout << "Target FE collection: " << fec->Name() << std::endl;
   fes = new FiniteElementSpace(&mesh_2, fec, vdim_tar);
   GridFunction func_target(fes);

   const int NE = mesh_2.GetNE(),
             nsp = fes->GetFE(0)->GetNodes().GetNPoints(),
             ncomp_tar = func_target.VectorDim();

   // Generate list of points where the Gridfunction will be evaluated.
   Vector vxyz;
   if (fieldtype == 0 && order == mesh_poly_deg)
   {
      vxyz = *mesh_2.GetNodes();
   }
   else
   {
      vxyz.SetSize(nsp*NE*dim);
      for (int i = 0; i < NE; i++)
      {
         const FiniteElement *fe = fes->GetFE(i);
         const IntegrationRule ir = fe->GetNodes();
         ElementTransformation *et = fes->GetElementTransformation(i);

         DenseMatrix pos;
         et->Transform(ir, pos);
         Vector rowx(vxyz.GetData() + i*nsp, nsp),
                rowy(vxyz.GetData() + i*nsp + NE*nsp, nsp),
                rowz;
         if (dim == 3)
         {
            rowz.SetDataAndSize(vxyz.GetData() + i*nsp + 2*NE*nsp, nsp);
         }
         pos.GetRow(0, rowx);
         pos.GetRow(1, rowy);
         if (dim == 3) { pos.GetRow(2, rowz); }
      }
   }
   const int nodes_cnt = vxyz.Size() / dim;

   // Evaluate source gridfunction.
   Vector interp_vals(nodes_cnt*ncomp_tar);
   FindPointsGSLIB finder;
   finder.Setup(mesh_1);
   finder.Interpolate(vxyz, func_source, interp_vals);

   // Project the interpolated values to the target FiniteElementSpace.
   if (fieldtype <= 1) // H1 or L2
   {
      if ((fieldtype == 0 && order == mesh_poly_deg) || fieldtype == 1)
      {
         func_target = interp_vals;
      }
      else // H1 - but mesh order != GridFunction order
      {
         Array<int> vdofs;
         Vector vals;
         const int nsp = func_target.FESpace()->GetFE(0)->GetNodes().GetNPoints(),
                   NE  = mesh_2.GetNE();
         Vector elem_dof_vals(nsp*dim);

         for (int i = 0; i < mesh_2.GetNE(); i++)
         {
            fes->GetElementVDofs(i, vdofs);
            vals.SetSize(vdofs.Size());
            for (int j = 0; j < nsp; j++)
            {
               for (int d = 0; d < ncomp_tar; d++)
               {
                  // Arrange values byNodes
                  elem_dof_vals(j+d*nsp) = interp_vals(d*nsp*NE + i*nsp + j);
               }
            }
            func_target.SetSubVector(vdofs, elem_dof_vals);
         }
      }
   }
   else // H(div) or H(curl)
   {
      Array<int> vdofs;
      Vector vals;
      const int nsp = func_target.FESpace()->GetFE(0)->GetNodes().GetNPoints(),
                NE  = mesh_2.GetNE();
      Vector elem_dof_vals(nsp*dim);

      for (int i = 0; i < mesh_2.GetNE(); i++)
      {
         fes->GetElementVDofs(i, vdofs);
         vals.SetSize(vdofs.Size());
         for (int j = 0; j < nsp; j++)
         {
            for (int d = 0; d < ncomp_tar; d++)
            {
               // Arrange values byVDim
               elem_dof_vals(j*ncomp_tar+d) = interp_vals(d*nsp*NE + i*nsp + j);
            }
         }
         fes->GetFE(i)->ProjectFromNodes(elem_dof_vals,
                                         *fes->GetElementTransformation(i),
                                         vals);
         func_target.SetSubVector(vdofs, vals);
      }
   }

   // Visualize the transferred solution.
   if (visualization)
   {
      char vishost[] = "localhost";
      int  visport   = 19916;
      socketstream sout1;
      sout1.open(vishost, visport);
      if (!sout1)
      {
         cout << "Unable to connect to GLVis server at "
              << vishost << ':' << visport << endl;
      }
      else
      {
         sout1.precision(8);
         sout1 << "solution\n" << mesh_2 << func_target
               << "window_title 'Target mesh and solution'"
               << "window_geometry 600 0 600 600";
         if (dim == 2) { sout1 << "keys RmjAc"; }
         if (dim == 3) { sout1 << "keys mA\n"; }
         sout1 << flush;
      }
   }

   // Output the target mesh with the interpolated solution.
   ostringstream rho_name;
   rho_name  << "interpolated.gf";
   ofstream rho_ofs(rho_name.str().c_str());
   rho_ofs.precision(8);
   func_target.Save(rho_ofs);
   rho_ofs.close();

   // Free the internal gslib data.
   finder.FreeData();

   // Delete
   delete fes;
   delete fec;

   return 0;
}
<|endoftext|>


<commit_before>/* -*- mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

#include <iostream>
#include "linbox/matrix/polynomial-matrix.h"
#include "linbox/randiter/random-fftprime.h"
#include "linbox/randiter/random-prime.h"
#include "linbox/ring/modular.h"

#include "linbox/algorithms/polynomial-matrix/polynomial-matrix-domain.h"
#include "linbox/algorithms/polynomial-matrix/order-basis.h"
#include "linbox/algorithms/block-coppersmith-domain.h"

using namespace LinBox;
using namespace std;

template<typename Field, typename Mat>
string check_sigma(const Field& F, const Mat& sigma,  Mat& serie, size_t ord){
	Mat T(F,sigma.rowdim(),serie.coldim(),sigma.size()+serie.size()-1);
	PolynomialMatrixMulDomain<Field> PMD(F);
	PMD.mul(T,sigma,serie);
	MatrixDomain<Field> MD(F);
	size_t i=0;
	string msg(".....");
	bool nul_sigma=true;
	while(i<ord && MD.isZero(T[i])){
		if (!MD.isZero(sigma[i])) nul_sigma=false;
		i++;
	}
	if (i<ord){
		cout<<"error at degree="<<i<<endl;
		T[i].write(std::cout, Tag::FileFormat::Plain);
		cout<<"***"<<endl;
		cout<<serie<<endl;
		cout<<sigma<<endl;
	}

	if (i==ord && !nul_sigma)
		msg+="done";
	else
		msg+="error";
	return msg;
}

template<typename MatPol>
bool operator==(const MatPol& A, const MatPol& B){
	MatrixDomain<typename MatPol::Field> MD(A.field());
	if (A.real_degree()!=B.real_degree()|| A.rowdim()!= B.rowdim() || A.coldim()!=B.coldim()){
		cout<<A.size()<<"("<<A.rowdim()<<"x"<<A.coldim()<<") <> "
		    <<B.size()<<"("<<B.rowdim()<<"x"<<B.coldim()<<") <> "<<endl;
		return false;
	}
	size_t i=0;
	while (i<=A.real_degree() && MD.areEqual(A[i],B[i]))
		i++;

	if (i<=A.real_degree() && A.rowdim()<10 && A.coldim()<10){
		cout<<"first:"<<endl<<A<<endl;
		cout<<"second:"<<endl<<B<<endl;
	}

	return i>A.real_degree();
}

template<typename Field, typename RandIter>
void check_sigma(const Field& F, const RandIter& Gen, size_t m, size_t n, size_t d) {
	//typedef typename Field::Element Element;
	typedef PolynomialMatrix<PMType::matfirst,PMStorage::plain,Field> MatrixP;
	//typedef PolynomialMatrix<PMType::polfirst,PMStorage::plain,Field> MatrixP;
	MatrixP Serie(F, m, n,  d);
	MatrixP Sigma1(F, m, m, d+1),Sigma2(F, m, m, d+1),Sigma3(F, m, m, d+1);

	// set the Serie at random
	for (size_t k=0;k<d;++k)
		for (size_t i=0;i<m;++i)
			for (size_t j=0;j<n;++j)
				Gen.random(Serie.ref(i,j,k));

	//std::cout<<"Serie:="<<Serie<<std::endl;

	// define the shift
	vector<size_t> shift(m,0);
	vector<size_t> shift2(shift),shift3(shift);

	OrderBasis<Field> SB(F);

	SB.M_Basis(Sigma3, Serie, d, shift3);
	std::cout << "M-Basis       : " <<check_sigma(F,Sigma3,Serie,d)<<endl;
	SB.PM_Basis2(Sigma1,Serie, d, shift);
	std::cout << "PM-Basis      : " <<check_sigma(F,Sigma1,Serie,d)<<endl;
	SB.oPM_Basis(Sigma2, Serie, d, shift2);
	std::cout << "PM-Basis iter : " <<check_sigma(F,Sigma2,Serie,d)<<endl;

	// if (!(Sigma1==Sigma2)){
	// cout<<"---> different basis for PM-Basis and PM-Basis iter"<<endl;
	// cout<<Sigma1<<endl;
	// cout<<Sigma2<<endl;
	// }
	cout<<endl;
}

int main(int argc, char** argv){
	static size_t  m = 64; // matrix dimension
	static size_t  n = 32; // matrix dimension
	static size_t  b = 20; // entries bitsize
	static size_t  d = 32;  // matrix degree
	static long    seed = time(NULL);

	static Argument args[] = {
		{ 'm', "-m M", "Set row dimension of matrix series to M.", TYPE_INT,     &m },
		{ 'n', "-n N", "Set column dimension of matrix series to N.", TYPE_INT,     &n },
		{ 'd', "-d D", "Set degree of  matrix series to D.", TYPE_INT,     &d },
		{ 'b', "-b B", "Set bitsize of the matrix entries", TYPE_INT, &b },
		{ 's', "-s s", "Set the random seed to a specific value", TYPE_INT, &seed},
		END_OF_ARGUMENTS
	};

	parseArguments (argc, argv, args);

	typedef Givaro::Modular<double>              SmallField;
	typedef Givaro::Modular<Givaro::Integer>      LargeField;

	size_t logd=integer(d).bitsize();

	std::cout<<"###  matrix series is of size "<<m<<" x "<<n<<" of degree "<<d<<std::endl;
	if (b < 26){
		if (logd>b-2){
			std::cout<<"degree is to large for field bitsize: "<<b<<std::endl;
			exit(0);
		}
		RandomFFTPrime Rd(b,seed);
		integer p = Rd.randomPrime(logd+1);
		std::cout<<"# starting sigma basis computation over Fp[x] with p="<<p<<endl;;
		SmallField F(p);
		typename SmallField::RandIter G(F,0,seed);
		check_sigma(F,G,m,n,d);
	}
	else {
		RandomPrimeIterator Rd(b,seed);
		integer p = Rd.randomPrime();
		std::cout<<"# starting sigma basis computation over Fp[x] with p="<<p<<endl;;

		LargeField F(p);
		typename LargeField::RandIter G(F,0,seed);
		check_sigma(F,G,m,n,d);
	}

	return 0;
}

<commit_msg>remove bug with const qualifier<commit_after>/* -*- mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

#include <iostream>
#include "linbox/matrix/polynomial-matrix.h"
#include "linbox/randiter/random-fftprime.h"
#include "linbox/randiter/random-prime.h"
#include "linbox/ring/modular.h"

#include "linbox/algorithms/polynomial-matrix/polynomial-matrix-domain.h"
#include "linbox/algorithms/polynomial-matrix/order-basis.h"
#include "linbox/algorithms/block-coppersmith-domain.h"

using namespace LinBox;
using namespace std;

template<typename Field, typename Mat>
string check_sigma(const Field& F, const Mat& sigma,  Mat& serie, size_t ord){
	Mat T(F,sigma.rowdim(),serie.coldim(),sigma.size()+serie.size()-1);
	PolynomialMatrixMulDomain<Field> PMD(F);
	PMD.mul(T,sigma,serie);
	MatrixDomain<Field> MD(F);
	size_t i=0;
	string msg(".....");
	bool nul_sigma=true;
	while(i<ord && MD.isZero(T[i])){
		if (!MD.isZero(sigma[i])) nul_sigma=false;
		i++;
	}
	if (i<ord){
		cout<<"error at degree="<<i<<endl;
		T[i].write(std::cout, Tag::FileFormat::Plain);
		cout<<"***"<<endl;
		cout<<serie<<endl;
		cout<<sigma<<endl;
	}

	if (i==ord && !nul_sigma)
		msg+="done";
	else
		msg+="error";
	return msg;
}

template<typename MatPol>
bool operator==(const MatPol& A, const MatPol& B){
	MatrixDomain<typename MatPol::Field> MD(A.field());
	if (A.real_degree()!=B.real_degree()|| A.rowdim()!= B.rowdim() || A.coldim()!=B.coldim()){
		cout<<A.size()<<"("<<A.rowdim()<<"x"<<A.coldim()<<") <> "
		    <<B.size()<<"("<<B.rowdim()<<"x"<<B.coldim()<<") <> "<<endl;
		return false;
	}
	size_t i=0;
	while (i<=A.real_degree() && MD.areEqual(A[i],B[i]))
		i++;

	if (i<=A.real_degree() && A.rowdim()<10 && A.coldim()<10){
		cout<<"first:"<<endl<<A<<endl;
		cout<<"second:"<<endl<<B<<endl;
	}

	return i>A.real_degree();
}

template<typename Field, typename RandIter>
void check_sigma(const Field& F, RandIter& Gen, size_t m, size_t n, size_t d) {
	//typedef typename Field::Element Element;
	typedef PolynomialMatrix<PMType::matfirst,PMStorage::plain,Field> MatrixP;
	//typedef PolynomialMatrix<PMType::polfirst,PMStorage::plain,Field> MatrixP;
	MatrixP Serie(F, m, n,  d);
	MatrixP Sigma1(F, m, m, d+1),Sigma2(F, m, m, d+1),Sigma3(F, m, m, d+1);

	// set the Serie at random
	for (size_t k=0;k<d;++k)
		for (size_t i=0;i<m;++i)
			for (size_t j=0;j<n;++j)
				Gen.random(Serie.ref(i,j,k));

	//std::cout<<"Serie:="<<Serie<<std::endl;

	// define the shift
	vector<size_t> shift(m,0);
	vector<size_t> shift2(shift),shift3(shift);

	OrderBasis<Field> SB(F);

	SB.M_Basis(Sigma3, Serie, d, shift3);
	std::cout << "M-Basis       : " <<check_sigma(F,Sigma3,Serie,d)<<endl;
	SB.PM_Basis2(Sigma1,Serie, d, shift);
	std::cout << "PM-Basis      : " <<check_sigma(F,Sigma1,Serie,d)<<endl;
	SB.oPM_Basis(Sigma2, Serie, d, shift2);
	std::cout << "PM-Basis iter : " <<check_sigma(F,Sigma2,Serie,d)<<endl;

	// if (!(Sigma1==Sigma2)){
	// cout<<"---> different basis for PM-Basis and PM-Basis iter"<<endl;
	// cout<<Sigma1<<endl;
	// cout<<Sigma2<<endl;
	// }
	cout<<endl;
}

int main(int argc, char** argv){
	static size_t  m = 64; // matrix dimension
	static size_t  n = 32; // matrix dimension
	static size_t  b = 20; // entries bitsize
	static size_t  d = 32;  // matrix degree
	static long    seed = time(NULL);

	static Argument args[] = {
		{ 'm', "-m M", "Set row dimension of matrix series to M.", TYPE_INT,     &m },
		{ 'n', "-n N", "Set column dimension of matrix series to N.", TYPE_INT,     &n },
		{ 'd', "-d D", "Set degree of  matrix series to D.", TYPE_INT,     &d },
		{ 'b', "-b B", "Set bitsize of the matrix entries", TYPE_INT, &b },
		{ 's', "-s s", "Set the random seed to a specific value", TYPE_INT, &seed},
		END_OF_ARGUMENTS
	};

	parseArguments (argc, argv, args);

	typedef Givaro::Modular<double>              SmallField;
	typedef Givaro::Modular<Givaro::Integer>      LargeField;

	size_t logd=integer(d).bitsize();

	std::cout<<"###  matrix series is of size "<<m<<" x "<<n<<" of degree "<<d<<std::endl;
	if (b < 26){
		if (logd>b-2){
			std::cout<<"degree is to large for field bitsize: "<<b<<std::endl;
			exit(0);
		}
		RandomFFTPrime Rd(b,seed);
		integer p = Rd.randomPrime(logd+1);
		std::cout<<"# starting sigma basis computation over Fp[x] with p="<<p<<endl;;
		SmallField F(p);
		typename SmallField::RandIter G(F,0,seed);
		check_sigma(F,G,m,n,d);
	}
	else {
		RandomPrimeIterator Rd(b,seed);
		integer p = Rd.randomPrime();
		std::cout<<"# starting sigma basis computation over Fp[x] with p="<<p<<endl;;

		LargeField F(p);
		typename LargeField::RandIter G(F,0,seed);
		check_sigma(F,G,m,n,d);
	}

	return 0;
}

<|endoftext|>


<commit_before>#include <raindance/Core/Headers.hh>

#include <raindance/Core/OpenCL.hh>

class GPUGraph
{
public:

    struct ParticleForce
    {
        glm::vec4 Direction;
    };

	struct NodeParticle
	{
		glm::vec4 Origin;
	};

	struct NodeInstance
	{
		typedef unsigned int ID;

        glm::vec4 Position;
        glm::vec4 Color;
        cl_float Size;

        ParticleForce Force;

        glm::vec3 __Unused; // NOTE: Memory alignment with OpenCL, reserved for later.
	};

    struct EdgeParticle
    {
        glm::vec4 Origin;
    };

	struct EdgeInstance
	{
		typedef unsigned int ID;

		glm::vec4 SourcePosition;
        glm::vec4 SourceColor;

        glm::vec4 TargetPosition;
        glm::vec4 TargetColor;

		cl_float Width;

        cl_uint SourceID;
        cl_uint TargetID;

        cl_float __Unused; // NOTE : Memory alignment with OpenCL, reserved for later.
	};

	GPUGraph()
	{
		m_Icon = new Icon();
        m_Icon->load("network/shapes/disk", FS::BinaryFile("Assets/NetworkView/shape_disk.png"));

		FS::TextFile nodes_vert("Assets/NetworkView/nodes.vert");
		FS::TextFile nodes_geom("Assets/NetworkView/nodes.geom");
		FS::TextFile nodes_frag("Assets/NetworkView/nodes.frag");
        m_NodeShader = ResourceManager::getInstance().loadShader("NetworkView/nodes",
        	nodes_vert.content(),
        	nodes_frag.content(),
        	nodes_geom.content());
        // m_NodeShader->dump();

        FS::TextFile edges_vert("Assets/NetworkView/edges.vert");
		FS::TextFile edges_geom("Assets/NetworkView/edges.geom");
		FS::TextFile edges_frag("Assets/NetworkView/edges.frag");
        m_EdgeShader = ResourceManager::getInstance().loadShader("NetworkView/edges",
        	edges_vert.content(),
        	edges_frag.content(),
        	edges_geom.content());
        // m_EdgeShader->dump();

        m_NeedsUpdate = true;
	}

	virtual ~GPUGraph()
	{
		SAFE_DELETE(m_Icon);
		ResourceManager::getInstance().unload(m_NodeShader);
	}

    void initialize(Context* context)
    {
        // OpenGL
        {
            // ----- Node Particle Geometry -----
            m_NodeParticleBuffer << glm::vec4(0, 0, 0, 0);
            m_NodeParticleBuffer.describe("a_Origin", 4, GL_FLOAT, sizeof(NodeParticle), 0);
            m_NodeParticleBuffer.generate(Buffer::STATIC);

            // ----- Edge Particle Geometry -----
            m_EdgeParticleBuffer << glm::vec4(0, 0, 0, 0);
            m_EdgeParticleBuffer.describe("a_Origin", 4, GL_FLOAT, sizeof(EdgeParticle), 0);
            m_EdgeParticleBuffer.generate(Buffer::STATIC);
        }

        // OpenCL
        {
            m_OpenCL.detect();
            //m_OpenCL.dump();

            // NOTE : We are assuming the last device is the best one.
            m_CL.Device = m_OpenCL.devices().back();

            m_OpenCL.dump(*m_CL.Device);

            m_CL.Context = m_OpenCL.createContext(*m_CL.Device);
            m_CL.Queue = m_OpenCL.createCommandQueue(*m_CL.Context);

            auto source = FS::TextFile("./Assets/NetworkView/physics.cl");

            m_CL.Program = m_OpenCL.loadProgram(*m_CL.Context, "physics", source.content());

            m_CL.RepulsionK = m_OpenCL.createKernel(*m_CL.Program, "repulsion");
            m_CL.AttractionK = m_OpenCL.createKernel(*m_CL.Program, "attraction");
            m_CL.NodeAnimationK = m_OpenCL.createKernel(*m_CL.Program, "node_animation");
            m_CL.EdgeAnimationK = m_OpenCL.createKernel(*m_CL.Program, "edge_animation");

            clFinish(m_CL.Queue->Object);
        }
    }

    void updateOpenGL(Context* context)
    {
        // LOG("updateOpenGL: %u nodes, %u edges.\n", m_NodeBuffer.size() / sizeof(Node), m_EdgeBuffer.size() / sizeof(Edge));

        if (m_NodeInstanceBuffer.size() == 0) // TODO: HACK: OpenGL doesn't like VBO resizing, Find a way to handle it properly.
            return;

        // --- Define Node Instances

        static bool m_NodeInstanceBufferFirstUpdate = true;

        if (!m_NodeInstanceBufferFirstUpdate)
            m_NodeInstanceBuffer.update();

        m_NodeInstanceBuffer.describe("a_Position", 4, GL_FLOAT, sizeof(NodeInstance), 0);
        m_NodeInstanceBuffer.describe("a_Color",    4, GL_FLOAT, sizeof(NodeInstance), 1 * sizeof(glm::vec4));
        m_NodeInstanceBuffer.describe("a_Size",     1, GL_FLOAT, sizeof(NodeInstance), 2 * sizeof(glm::vec4));

        if (m_NodeInstanceBufferFirstUpdate)
            m_NodeInstanceBuffer.generate(Buffer::DYNAMIC);

        m_NodeInstanceBufferFirstUpdate = false;

        // --- Define Edge Instances

        static bool m_EdgeInstanceBufferFirstUpdate = true;

        if (!m_EdgeInstanceBufferFirstUpdate)
            m_EdgeInstanceBuffer.update();

        m_EdgeInstanceBuffer.describe("a_SourcePosition", 4, GL_FLOAT, sizeof(EdgeInstance), 0);
        m_EdgeInstanceBuffer.describe("a_SourceColor",    4, GL_FLOAT, sizeof(EdgeInstance), 1 * sizeof(glm::vec4));
        m_EdgeInstanceBuffer.describe("a_TargetPosition", 4, GL_FLOAT, sizeof(EdgeInstance), 2 * sizeof(glm::vec4));
        m_EdgeInstanceBuffer.describe("a_TargetColor",    4, GL_FLOAT, sizeof(EdgeInstance), 3 * sizeof(glm::vec4));
        m_EdgeInstanceBuffer.describe("a_Width",          1, GL_FLOAT, sizeof(EdgeInstance), 4 * sizeof(glm::vec4));

        if (m_EdgeInstanceBufferFirstUpdate)
            m_EdgeInstanceBuffer.generate(Buffer::DYNAMIC);

        m_EdgeInstanceBufferFirstUpdate = false;
    }

    void updateOpenCL(Context* context)
    {
        size_t node_count = m_NodeInstanceBuffer.size() / sizeof(NodeInstance);
        size_t edge_count = m_EdgeInstanceBuffer.size() / sizeof(EdgeInstance);

        if (node_count == 0) // TODO: HACK: OpenGL doesn't like VBO resizing, Find a way to handle it properly.
            return;

        static bool m_OCLNeedsUpdate = true;
        if (m_OCLNeedsUpdate)
        {
            m_CL.NodeInstanceBuffer = m_OpenCL.createFromGLBuffer(*m_CL.Context, CL_MEM_READ_WRITE, m_NodeInstanceBuffer.vbo());
            m_CL.EdgeInstanceBuffer = m_OpenCL.createFromGLBuffer(*m_CL.Context, CL_MEM_READ_WRITE, m_EdgeInstanceBuffer.vbo());
            clFinish(m_CL.Queue->Object);
            m_OCLNeedsUpdate = false;
        }

        // ----- Parameters -----

        static int Iterations = 0;
        if (Iterations >= 100)
            return;

        const float cube_side = 100; // NOTE : Graph should fit in this cube
        const float volume = cube_side * cube_side * cube_side;

        m_CL.K = pow(volume / node_count, 1.0 / 3.0);

        m_CL.Time = context->clock().seconds();

        m_CL.Temperature = cube_side / (Iterations + 1);

        LOG("Iteration: %i, K: %f, Time: %f, Temperature: %f\n", Iterations, m_CL.K, m_CL.Time, m_CL.Temperature);

        // ----- Node Repulsion -----

        m_OpenCL.enqueueAcquireGLObjects(*m_CL.Queue, 1, &m_CL.NodeInstanceBuffer->Object, 0, 0, NULL);
        {
            m_CL.RepulsionK->setArgument(0, *m_CL.NodeInstanceBuffer);
            m_CL.RepulsionK->setArgument(1, &m_CL.K, sizeof(float));

            m_OpenCL.enqueueNDRangeKernel(*m_CL.Queue, *m_CL.RepulsionK, 1, NULL, &node_count, NULL, 0, NULL, NULL);
        }
        m_OpenCL.enqueueReleaseGLObjects(*m_CL.Queue, 1, &m_CL.NodeInstanceBuffer->Object, 0, 0, NULL);

        // ----- Edge Attraction -----

        m_OpenCL.enqueueAcquireGLObjects(*m_CL.Queue, 1, &m_CL.NodeInstanceBuffer->Object, 0, 0, NULL);
        m_OpenCL.enqueueAcquireGLObjects(*m_CL.Queue, 1, &m_CL.EdgeInstanceBuffer->Object, 0, 0, NULL);
        {
            m_CL.AttractionK->setArgument(0, *m_CL.NodeInstanceBuffer);
            m_CL.AttractionK->setArgument(1, *m_CL.EdgeInstanceBuffer);
            m_CL.AttractionK->setArgument(2, &m_CL.K, sizeof(float));

            m_OpenCL.enqueueNDRangeKernel(*m_CL.Queue, *m_CL.AttractionK, 1, NULL, &edge_count, NULL, 0, NULL, NULL);
        }
        m_OpenCL.enqueueReleaseGLObjects(*m_CL.Queue, 1, &m_CL.EdgeInstanceBuffer->Object, 0, 0, NULL);
        m_OpenCL.enqueueReleaseGLObjects(*m_CL.Queue, 1, &m_CL.NodeInstanceBuffer->Object, 0, 0, NULL);

        // ----- Node Animation -----

        m_OpenCL.enqueueAcquireGLObjects(*m_CL.Queue, 1, &m_CL.NodeInstanceBuffer->Object, 0, 0, NULL);
        {
            m_CL.NodeAnimationK->setArgument(0, *m_CL.NodeInstanceBuffer);
            m_CL.NodeAnimationK->setArgument(1, &m_CL.Temperature, sizeof(float));

            m_OpenCL.enqueueNDRangeKernel(*m_CL.Queue, *m_CL.NodeAnimationK, 1, NULL, &node_count, NULL, 0, NULL, NULL);
        }
        m_OpenCL.enqueueReleaseGLObjects(*m_CL.Queue, 1, &m_CL.NodeInstanceBuffer->Object, 0, 0, NULL);

        // ----- Edge Animation -----

        m_OpenCL.enqueueAcquireGLObjects(*m_CL.Queue, 1, &m_CL.NodeInstanceBuffer->Object, 0, 0, NULL);
        m_OpenCL.enqueueAcquireGLObjects(*m_CL.Queue, 1, &m_CL.EdgeInstanceBuffer->Object, 0, 0, NULL);
        {
            m_CL.EdgeAnimationK->setArgument(0, *m_CL.NodeInstanceBuffer);
            m_CL.EdgeAnimationK->setArgument(1, *m_CL.EdgeInstanceBuffer);

            m_OpenCL.enqueueNDRangeKernel(*m_CL.Queue, *m_CL.EdgeAnimationK, 1, NULL, &edge_count, NULL, 0, NULL, NULL);
        }
        m_OpenCL.enqueueReleaseGLObjects(*m_CL.Queue, 1, &m_CL.EdgeInstanceBuffer->Object, 0, 0, NULL);
        m_OpenCL.enqueueReleaseGLObjects(*m_CL.Queue, 1, &m_CL.NodeInstanceBuffer->Object, 0, 0, NULL);

        clFinish(m_CL.Queue->Object);

        Iterations++;
    }

	void idle(Context* context)
	{
        if (m_NeedsUpdate)
        {
            updateOpenGL(context);
            m_NeedsUpdate = false;
        }

        updateOpenCL(context);
	}

	virtual void drawEdges(Context* context, Camera& camera, Transformation& transformation)
	{
        if (!m_EdgeInstanceBuffer.isGenerated() || m_EdgeInstanceBuffer.size() == 0)
            return;

        m_EdgeShader->use();
        //m_EdgeShader->uniform("u_Texture").set(m_Icon->getTexture(0));

        m_EdgeShader->uniform("u_ModelViewMatrix").set(camera.getViewMatrix() * transformation.state());
        m_EdgeShader->uniform("u_ProjectionMatrix").set(camera.getProjectionMatrix());

        context->geometry().bind(m_EdgeParticleBuffer, *m_EdgeShader);
        context->geometry().bind(m_EdgeInstanceBuffer, *m_EdgeShader);

        glVertexAttribDivisorARB(m_EdgeShader->attribute("a_Origin").location(), 0); // Same vertices per instance

        glVertexAttribDivisorARB(m_EdgeShader->attribute("a_SourcePosition").location(), 1);
        glVertexAttribDivisorARB(m_EdgeShader->attribute("a_SourceColor").location(), 1);

        glVertexAttribDivisorARB(m_EdgeShader->attribute("a_TargetPosition").location(), 1);
        glVertexAttribDivisorARB(m_EdgeShader->attribute("a_TargetColor").location(), 1);

        glVertexAttribDivisorARB(m_EdgeShader->attribute("a_Width").location(), 1);

        context->geometry().drawArraysInstanced(GL_POINTS, 0, m_EdgeParticleBuffer.size() / sizeof(EdgeParticle), m_EdgeInstanceBuffer.size() / sizeof(EdgeInstance));

        context->geometry().unbind(m_EdgeParticleBuffer);
        context->geometry().unbind(m_EdgeInstanceBuffer);
	}

    virtual void drawNodes(Context* context, Camera& camera, Transformation& transformation)
    {
        if (!m_NodeInstanceBuffer.isGenerated() || m_NodeInstanceBuffer.size() == 0)
            return;

        m_NodeShader->use();
        m_NodeShader->uniform("u_Texture").set(m_Icon->getTexture(0));

        m_NodeShader->uniform("u_ModelViewMatrix").set(camera.getViewMatrix() * transformation.state());
        m_NodeShader->uniform("u_ProjectionMatrix").set(camera.getProjectionMatrix());

        context->geometry().bind(m_NodeParticleBuffer, *m_NodeShader);
        context->geometry().bind(m_NodeInstanceBuffer, *m_NodeShader);

        glVertexAttribDivisorARB(m_NodeShader->attribute("a_Origin").location(), 0); // Same vertices per instance

        glVertexAttribDivisorARB(m_NodeShader->attribute("a_Position").location(), 1);
        glVertexAttribDivisorARB(m_NodeShader->attribute("a_Color").location(), 1);
        glVertexAttribDivisorARB(m_NodeShader->attribute("a_Size").location(), 1);

        context->geometry().drawArraysInstanced(GL_POINTS, 0, m_NodeParticleBuffer.size() / sizeof(NodeParticle), m_NodeInstanceBuffer.size() / sizeof(NodeInstance));

        context->geometry().unbind(m_NodeParticleBuffer);
        context->geometry().unbind(m_NodeInstanceBuffer);
    }

    virtual void draw(Context* context, Camera& camera, Transformation& transformation)
    {
        glDisable(GL_DEPTH_TEST);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);

        drawEdges(context, camera, transformation);
        drawNodes(context, camera, transformation);
    }

    // ----- Nodes Accessors -----

    inline Buffer& getNodes() { return m_NodeInstanceBuffer; }

    void addNode(const NodeInstance& node)
    {
        m_NodeInstanceBuffer.push(&node, sizeof(NodeInstance));
        m_NeedsUpdate = true;
    }

    inline NodeInstance getNode(NodeInstance::ID id)
    {
        NodeInstance node;
        m_NodeInstanceBuffer.get(id, &node, sizeof(NodeInstance));
        return node;
    }

    inline void setNode(NodeInstance::ID id, const NodeInstance& node)
    {
        m_NodeInstanceBuffer.set(id, &node, sizeof(NodeInstance));
        m_NeedsUpdate = true;
    }

    // ----- Edges Accessors -----

    inline Buffer& getEdges() { return m_EdgeInstanceBuffer; }

    void addEdge(const EdgeInstance& edge)
    {
        m_EdgeInstanceBuffer.push(&edge, sizeof(EdgeInstance));
        m_NeedsUpdate = true;
    }

    inline EdgeInstance getEdge(EdgeInstance::ID id)
    {
        EdgeInstance edge;
        m_EdgeInstanceBuffer.get(id, &edge, sizeof(EdgeInstance));
        return edge;
    }

    inline void setEdge(EdgeInstance::ID id, const EdgeInstance& edge)
    {
        m_EdgeInstanceBuffer.set(id, &edge, sizeof(EdgeInstance));
        m_NeedsUpdate = true;
    }

private:
	Icon* m_Icon;
    bool m_NeedsUpdate;

	Shader::Program* m_NodeShader;
    Buffer m_NodeParticleBuffer;
	Buffer m_NodeInstanceBuffer;

	Shader::Program* m_EdgeShader;
    Buffer m_EdgeParticleBuffer;
    Buffer m_EdgeInstanceBuffer;

    struct OCLData
    {
        OCLData() {}

        OpenCL::Device* Device;
        OpenCL::Context* Context;
        OpenCL::CommandQueue* Queue;
        OpenCL::Program* Program;

        OpenCL::Kernel* RepulsionK;
        OpenCL::Kernel* AttractionK;
        OpenCL::Kernel* NodeAnimationK;
        OpenCL::Kernel* EdgeAnimationK;

        OpenCL::Memory* NodeInstanceBuffer;
        OpenCL::Memory* EdgeInstanceBuffer;

        float Time;
        float K;
        float Temperature;
    };

    OpenCL m_OpenCL;
    OCLData m_CL;
};
<commit_msg>Remove unnecessary acquire/release<commit_after>#include <raindance/Core/Headers.hh>

#include <raindance/Core/OpenCL.hh>

class GPUGraph
{
public:

    struct ParticleForce
    {
        glm::vec4 Direction;
    };

	struct NodeParticle
	{
		glm::vec4 Origin;
	};

	struct NodeInstance
	{
		typedef unsigned int ID;

        glm::vec4 Position;
        glm::vec4 Color;
        cl_float Size;

        ParticleForce Force;

        glm::vec3 __Unused; // NOTE: Memory alignment with OpenCL, reserved for later.
	};

    struct EdgeParticle
    {
        glm::vec4 Origin;
    };

	struct EdgeInstance
	{
		typedef unsigned int ID;

		glm::vec4 SourcePosition;
        glm::vec4 SourceColor;

        glm::vec4 TargetPosition;
        glm::vec4 TargetColor;

		cl_float Width;

        cl_uint SourceID;
        cl_uint TargetID;

        cl_float __Unused; // NOTE : Memory alignment with OpenCL, reserved for later.
	};

	GPUGraph()
	{
		m_Icon = new Icon();
        m_Icon->load("network/shapes/disk", FS::BinaryFile("Assets/NetworkView/shape_disk.png"));

		FS::TextFile nodes_vert("Assets/NetworkView/nodes.vert");
		FS::TextFile nodes_geom("Assets/NetworkView/nodes.geom");
		FS::TextFile nodes_frag("Assets/NetworkView/nodes.frag");
        m_NodeShader = ResourceManager::getInstance().loadShader("NetworkView/nodes",
        	nodes_vert.content(),
        	nodes_frag.content(),
        	nodes_geom.content());
        // m_NodeShader->dump();

        FS::TextFile edges_vert("Assets/NetworkView/edges.vert");
		FS::TextFile edges_geom("Assets/NetworkView/edges.geom");
		FS::TextFile edges_frag("Assets/NetworkView/edges.frag");
        m_EdgeShader = ResourceManager::getInstance().loadShader("NetworkView/edges",
        	edges_vert.content(),
        	edges_frag.content(),
        	edges_geom.content());
        // m_EdgeShader->dump();

        m_NeedsUpdate = true;
	}

	virtual ~GPUGraph()
	{
		SAFE_DELETE(m_Icon);
		ResourceManager::getInstance().unload(m_NodeShader);
	}

    void initialize(Context* context)
    {
        // OpenGL
        {
            // ----- Node Particle Geometry -----
            m_NodeParticleBuffer << glm::vec4(0, 0, 0, 0);
            m_NodeParticleBuffer.describe("a_Origin", 4, GL_FLOAT, sizeof(NodeParticle), 0);
            m_NodeParticleBuffer.generate(Buffer::STATIC);

            // ----- Edge Particle Geometry -----
            m_EdgeParticleBuffer << glm::vec4(0, 0, 0, 0);
            m_EdgeParticleBuffer.describe("a_Origin", 4, GL_FLOAT, sizeof(EdgeParticle), 0);
            m_EdgeParticleBuffer.generate(Buffer::STATIC);
        }

        // OpenCL
        {
            m_OpenCL.detect();
            //m_OpenCL.dump();

            // NOTE : We are assuming the last device is the best one.
            m_CL.Device = m_OpenCL.devices().back();

            m_OpenCL.dump(*m_CL.Device);

            m_CL.Context = m_OpenCL.createContext(*m_CL.Device);
            m_CL.Queue = m_OpenCL.createCommandQueue(*m_CL.Context);

            auto source = FS::TextFile("./Assets/NetworkView/physics.cl");

            m_CL.Program = m_OpenCL.loadProgram(*m_CL.Context, "physics", source.content());

            m_CL.RepulsionK = m_OpenCL.createKernel(*m_CL.Program, "repulsion");
            m_CL.AttractionK = m_OpenCL.createKernel(*m_CL.Program, "attraction");
            m_CL.NodeAnimationK = m_OpenCL.createKernel(*m_CL.Program, "node_animation");
            m_CL.EdgeAnimationK = m_OpenCL.createKernel(*m_CL.Program, "edge_animation");

            clFinish(m_CL.Queue->Object);
        }
    }

    void updateOpenGL(Context* context)
    {
        // LOG("updateOpenGL: %u nodes, %u edges.\n", m_NodeBuffer.size() / sizeof(Node), m_EdgeBuffer.size() / sizeof(Edge));

        if (m_NodeInstanceBuffer.size() == 0) // TODO: HACK: OpenGL doesn't like VBO resizing, Find a way to handle it properly.
            return;

        // --- Define Node Instances

        static bool m_NodeInstanceBufferFirstUpdate = true;

        if (!m_NodeInstanceBufferFirstUpdate)
            m_NodeInstanceBuffer.update();

        m_NodeInstanceBuffer.describe("a_Position", 4, GL_FLOAT, sizeof(NodeInstance), 0);
        m_NodeInstanceBuffer.describe("a_Color",    4, GL_FLOAT, sizeof(NodeInstance), 1 * sizeof(glm::vec4));
        m_NodeInstanceBuffer.describe("a_Size",     1, GL_FLOAT, sizeof(NodeInstance), 2 * sizeof(glm::vec4));

        if (m_NodeInstanceBufferFirstUpdate)
            m_NodeInstanceBuffer.generate(Buffer::DYNAMIC);

        m_NodeInstanceBufferFirstUpdate = false;

        // --- Define Edge Instances

        static bool m_EdgeInstanceBufferFirstUpdate = true;

        if (!m_EdgeInstanceBufferFirstUpdate)
            m_EdgeInstanceBuffer.update();

        m_EdgeInstanceBuffer.describe("a_SourcePosition", 4, GL_FLOAT, sizeof(EdgeInstance), 0);
        m_EdgeInstanceBuffer.describe("a_SourceColor",    4, GL_FLOAT, sizeof(EdgeInstance), 1 * sizeof(glm::vec4));
        m_EdgeInstanceBuffer.describe("a_TargetPosition", 4, GL_FLOAT, sizeof(EdgeInstance), 2 * sizeof(glm::vec4));
        m_EdgeInstanceBuffer.describe("a_TargetColor",    4, GL_FLOAT, sizeof(EdgeInstance), 3 * sizeof(glm::vec4));
        m_EdgeInstanceBuffer.describe("a_Width",          1, GL_FLOAT, sizeof(EdgeInstance), 4 * sizeof(glm::vec4));

        if (m_EdgeInstanceBufferFirstUpdate)
            m_EdgeInstanceBuffer.generate(Buffer::DYNAMIC);

        m_EdgeInstanceBufferFirstUpdate = false;
    }

    void updateOpenCL(Context* context)
    {
        size_t node_count = m_NodeInstanceBuffer.size() / sizeof(NodeInstance);
        size_t edge_count = m_EdgeInstanceBuffer.size() / sizeof(EdgeInstance);

        if (node_count == 0) // TODO: HACK: OpenGL doesn't like VBO resizing, Find a way to handle it properly.
            return;

        static bool m_OCLNeedsUpdate = true;
        if (m_OCLNeedsUpdate)
        {
            m_CL.NodeInstanceBuffer = m_OpenCL.createFromGLBuffer(*m_CL.Context, CL_MEM_READ_WRITE, m_NodeInstanceBuffer.vbo());
            m_CL.EdgeInstanceBuffer = m_OpenCL.createFromGLBuffer(*m_CL.Context, CL_MEM_READ_WRITE, m_EdgeInstanceBuffer.vbo());
            clFinish(m_CL.Queue->Object);
            m_OCLNeedsUpdate = false;
        }

        // ----- Parameters -----

        static int Iterations = 0;
        if (Iterations >= 100)
            return;

        const float cube_side = 100; // NOTE : Graph should fit in this cube
        const float volume = cube_side * cube_side * cube_side;

        m_CL.K = pow(volume / node_count, 1.0 / 3.0);

        m_CL.Time = context->clock().seconds();

        m_CL.Temperature = cube_side / (Iterations + 1);

        LOG("Iteration: %i, K: %f, Time: %f, Temperature: %f\n", Iterations, m_CL.K, m_CL.Time, m_CL.Temperature);

        m_OpenCL.enqueueAcquireGLObjects(*m_CL.Queue, 1, &m_CL.NodeInstanceBuffer->Object, 0, 0, NULL);
        m_OpenCL.enqueueAcquireGLObjects(*m_CL.Queue, 1, &m_CL.EdgeInstanceBuffer->Object, 0, 0, NULL);
        {
            // ----- Node Repulsion -----
            m_CL.RepulsionK->setArgument(0, *m_CL.NodeInstanceBuffer);
            m_CL.RepulsionK->setArgument(1, &m_CL.K, sizeof(float));
            m_OpenCL.enqueueNDRangeKernel(*m_CL.Queue, *m_CL.RepulsionK, 1, NULL, &node_count, NULL, 0, NULL, NULL);

            // ----- Edge Attraction -----

            m_CL.AttractionK->setArgument(0, *m_CL.NodeInstanceBuffer);
            m_CL.AttractionK->setArgument(1, *m_CL.EdgeInstanceBuffer);
            m_CL.AttractionK->setArgument(2, &m_CL.K, sizeof(float));
            m_OpenCL.enqueueNDRangeKernel(*m_CL.Queue, *m_CL.AttractionK, 1, NULL, &edge_count, NULL, 0, NULL, NULL);

            // ----- Node Animation -----

            m_CL.NodeAnimationK->setArgument(0, *m_CL.NodeInstanceBuffer);
            m_CL.NodeAnimationK->setArgument(1, &m_CL.Temperature, sizeof(float));
            m_OpenCL.enqueueNDRangeKernel(*m_CL.Queue, *m_CL.NodeAnimationK, 1, NULL, &node_count, NULL, 0, NULL, NULL);

            // ----- Edge Animation -----

            m_CL.EdgeAnimationK->setArgument(0, *m_CL.NodeInstanceBuffer);
            m_CL.EdgeAnimationK->setArgument(1, *m_CL.EdgeInstanceBuffer);
            m_OpenCL.enqueueNDRangeKernel(*m_CL.Queue, *m_CL.EdgeAnimationK, 1, NULL, &edge_count, NULL, 0, NULL, NULL);
        }
        m_OpenCL.enqueueReleaseGLObjects(*m_CL.Queue, 1, &m_CL.EdgeInstanceBuffer->Object, 0, 0, NULL);
        m_OpenCL.enqueueReleaseGLObjects(*m_CL.Queue, 1, &m_CL.NodeInstanceBuffer->Object, 0, 0, NULL);

        clFinish(m_CL.Queue->Object);

        Iterations++;
    }

	void idle(Context* context)
	{
        if (m_NeedsUpdate)
        {
            updateOpenGL(context);
            m_NeedsUpdate = false;
        }

        updateOpenCL(context);
	}

	virtual void drawEdges(Context* context, Camera& camera, Transformation& transformation)
	{
        if (!m_EdgeInstanceBuffer.isGenerated() || m_EdgeInstanceBuffer.size() == 0)
            return;

        m_EdgeShader->use();
        //m_EdgeShader->uniform("u_Texture").set(m_Icon->getTexture(0));

        m_EdgeShader->uniform("u_ModelViewMatrix").set(camera.getViewMatrix() * transformation.state());
        m_EdgeShader->uniform("u_ProjectionMatrix").set(camera.getProjectionMatrix());

        context->geometry().bind(m_EdgeParticleBuffer, *m_EdgeShader);
        context->geometry().bind(m_EdgeInstanceBuffer, *m_EdgeShader);

        glVertexAttribDivisorARB(m_EdgeShader->attribute("a_Origin").location(), 0); // Same vertices per instance

        glVertexAttribDivisorARB(m_EdgeShader->attribute("a_SourcePosition").location(), 1);
        glVertexAttribDivisorARB(m_EdgeShader->attribute("a_SourceColor").location(), 1);

        glVertexAttribDivisorARB(m_EdgeShader->attribute("a_TargetPosition").location(), 1);
        glVertexAttribDivisorARB(m_EdgeShader->attribute("a_TargetColor").location(), 1);

        glVertexAttribDivisorARB(m_EdgeShader->attribute("a_Width").location(), 1);

        context->geometry().drawArraysInstanced(GL_POINTS, 0, m_EdgeParticleBuffer.size() / sizeof(EdgeParticle), m_EdgeInstanceBuffer.size() / sizeof(EdgeInstance));

        context->geometry().unbind(m_EdgeParticleBuffer);
        context->geometry().unbind(m_EdgeInstanceBuffer);
	}

    virtual void drawNodes(Context* context, Camera& camera, Transformation& transformation)
    {
        if (!m_NodeInstanceBuffer.isGenerated() || m_NodeInstanceBuffer.size() == 0)
            return;

        m_NodeShader->use();
        m_NodeShader->uniform("u_Texture").set(m_Icon->getTexture(0));

        m_NodeShader->uniform("u_ModelViewMatrix").set(camera.getViewMatrix() * transformation.state());
        m_NodeShader->uniform("u_ProjectionMatrix").set(camera.getProjectionMatrix());

        context->geometry().bind(m_NodeParticleBuffer, *m_NodeShader);
        context->geometry().bind(m_NodeInstanceBuffer, *m_NodeShader);

        glVertexAttribDivisorARB(m_NodeShader->attribute("a_Origin").location(), 0); // Same vertices per instance

        glVertexAttribDivisorARB(m_NodeShader->attribute("a_Position").location(), 1);
        glVertexAttribDivisorARB(m_NodeShader->attribute("a_Color").location(), 1);
        glVertexAttribDivisorARB(m_NodeShader->attribute("a_Size").location(), 1);

        context->geometry().drawArraysInstanced(GL_POINTS, 0, m_NodeParticleBuffer.size() / sizeof(NodeParticle), m_NodeInstanceBuffer.size() / sizeof(NodeInstance));

        context->geometry().unbind(m_NodeParticleBuffer);
        context->geometry().unbind(m_NodeInstanceBuffer);
    }

    virtual void draw(Context* context, Camera& camera, Transformation& transformation)
    {
        glDisable(GL_DEPTH_TEST);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);

        drawEdges(context, camera, transformation);
        drawNodes(context, camera, transformation);
    }

    // ----- Nodes Accessors -----

    inline Buffer& getNodes() { return m_NodeInstanceBuffer; }

    void addNode(const NodeInstance& node)
    {
        m_NodeInstanceBuffer.push(&node, sizeof(NodeInstance));
        m_NeedsUpdate = true;
    }

    inline NodeInstance getNode(NodeInstance::ID id)
    {
        NodeInstance node;
        m_NodeInstanceBuffer.get(id, &node, sizeof(NodeInstance));
        return node;
    }

    inline void setNode(NodeInstance::ID id, const NodeInstance& node)
    {
        m_NodeInstanceBuffer.set(id, &node, sizeof(NodeInstance));
        m_NeedsUpdate = true;
    }

    // ----- Edges Accessors -----

    inline Buffer& getEdges() { return m_EdgeInstanceBuffer; }

    void addEdge(const EdgeInstance& edge)
    {
        m_EdgeInstanceBuffer.push(&edge, sizeof(EdgeInstance));
        m_NeedsUpdate = true;
    }

    inline EdgeInstance getEdge(EdgeInstance::ID id)
    {
        EdgeInstance edge;
        m_EdgeInstanceBuffer.get(id, &edge, sizeof(EdgeInstance));
        return edge;
    }

    inline void setEdge(EdgeInstance::ID id, const EdgeInstance& edge)
    {
        m_EdgeInstanceBuffer.set(id, &edge, sizeof(EdgeInstance));
        m_NeedsUpdate = true;
    }

private:
	Icon* m_Icon;
    bool m_NeedsUpdate;

	Shader::Program* m_NodeShader;
    Buffer m_NodeParticleBuffer;
	Buffer m_NodeInstanceBuffer;

	Shader::Program* m_EdgeShader;
    Buffer m_EdgeParticleBuffer;
    Buffer m_EdgeInstanceBuffer;

    struct OCLData
    {
        OCLData() {}

        OpenCL::Device* Device;
        OpenCL::Context* Context;
        OpenCL::CommandQueue* Queue;
        OpenCL::Program* Program;

        OpenCL::Kernel* RepulsionK;
        OpenCL::Kernel* AttractionK;
        OpenCL::Kernel* NodeAnimationK;
        OpenCL::Kernel* EdgeAnimationK;

        OpenCL::Memory* NodeInstanceBuffer;
        OpenCL::Memory* EdgeInstanceBuffer;

        float Time;
        float K;
        float Temperature;
    };

    OpenCL m_OpenCL;
    OCLData m_CL;
};
<|endoftext|>


<commit_before>//
#include "spack.h"

#include <cstdint>
#include <algorithm>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string/replace.hpp>

#include "sections_packer.h"
#include "import_packer.h"
#include "file_utils.h"
#include "tiny_logger.h"

typedef std::shared_ptr<PeLib::PeFile> PeFilePtr;

uint32_t rebuildMZHeader(PeFilePtr& peFile, std::vector<uint8_t>& outFileBuffer, std::vector<uint8_t>& sourceFileBuff)
{
  std::vector<PeLib::byte> mzHeadBuffer;
  auto mzHead = peFile->mzHeader();
  mzHead.rebuild(mzHeadBuffer);

  std::copy(mzHeadBuffer.cbegin(), mzHeadBuffer.cend(), std::back_inserter(outFileBuffer));

  // append mzHeader with undocumented data located between MZHeader & PEHeader
  auto peOffset = mzHead.getAddressOfPeHeader();
  auto cbMZHead = mzHead.size();
  auto cbJunkData = std::max(peOffset - cbMZHead, static_cast<uint32_t>(0));
  if (cbJunkData)
  {
    std::copy(&sourceFileBuff.at(cbMZHead), &sourceFileBuff.at(cbMZHead + cbJunkData), std::back_inserter(outFileBuffer));
  }

  return cbMZHead + cbJunkData;
}

template<int bits>
void rebuildPEHeader(PeLib::PeFile& peFile, std::vector<uint8_t>& outFileBuffer, uint32_t& offset)
{
  const PeLib::PeHeaderT<bits>& peh = static_cast<PeLib::PeFileT<bits>&>(peFile).peHeader();

  std::vector<PeLib::byte> peHeaderBuff;
  peh.rebuild(peHeaderBuff);

  PeLib::PeHeaderT<bits> pehOut;
  auto cbAfterHeader = peh.size();
  std::copy(peHeaderBuff.cbegin(), peHeaderBuff.cend(), std::back_inserter(outFileBuffer));

  offset += pehOut.size();

  // append with aligned zero-bytes
  auto headersSize = peh.getSizeOfHeaders() - offset;
  if (headersSize)
  {
    //todo(azerg): strip unused data by fixing size of headers ?
    outFileBuffer.insert(outFileBuffer.end(), headersSize, 0);
  }
  offset += headersSize;
}

//------------------------------------------------------------------------

class DumpPeHeaderVisitor: public PeLib::PeFileVisitor
{
public:
  DumpPeHeaderVisitor(std::vector<uint8_t>& outFileBuffer, uint32_t& offset) :
    outFileBuffer_(outFileBuffer)
    , offset_(offset)
  {}
  virtual void callback(PeLib::PeFile32& file) { rebuildPEHeader<32>(file, outFileBuffer_, offset_); }
  virtual void callback(PeLib::PeFile64& file) { rebuildPEHeader<64>(file, outFileBuffer_, offset_); }
private:
  std::vector<uint8_t>& outFileBuffer_;
  uint32_t& offset_;
};

//------------------------------------------------------------------------

ErrorCode PackExecutable(const std::string& srcFileName, const std::string& outFileName)
{
  try
  {
    if (!boost::filesystem::exists(srcFileName))
    {
      return ErrorCode::FILE_NOT_FOUND;
    }

    auto sourceFileBuff = file_utils::readFile(srcFileName.c_str());
    decltype(sourceFileBuff) outFileBuff;

    if (boost::filesystem::exists(outFileName))
    {
      boost::filesystem::remove(outFileName);
    }

    auto pef = PeLib::openPeFile(srcFileName);
    if (!pef)
    {
      std::cout << "Invalid PE File" << std::endl;
      return ErrorCode::INVALID_PE_FILE;
    }

    std::vector<uint8_t> outFileBuffer;

    pef->readMzHeader();
    auto offset = rebuildMZHeader(pef, outFileBuffer, sourceFileBuff);

    // stores data sizes required by different packers
    std::vector<RequiredDataBlock> additionalSizeRequest;

    //-----------------------------------------------------

    pef->readPeHeader();
    DumpPeHeaderVisitor peVisitor(outFileBuffer, offset);
    pef->visit(peVisitor);

    //-----------------------------------------------------

    ImportPacker importPacker(pef);
    additionalSizeRequest.push_back({importPacker.GetRequiredSpaceSize(), PackerTypes::kImportPacker});

    //-----------------------------------------------------

    SectionsPacker sectionsPacker(pef);
    auto sectionsArr = sectionsPacker.ProcessExecutable(sourceFileBuff, additionalSizeRequest);

    //-----------------------------------------------------

    auto importsArr = importPacker.ProcessExecutable(0); // new import RVA passed here

    //-----------------------------------------------------

    return ErrorCode::ERROR_SUCC;
  }
  catch (std::runtime_error& err)
  {
    std::cout << err.what();
  }

  return ErrorCode::FATAL_ERROR;
}<commit_msg>using VA from additional block for constructing new imports<commit_after>//
#include "spack.h"

#include <cstdint>
#include <algorithm>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string/replace.hpp>

#include "sections_packer.h"
#include "import_packer.h"
#include "file_utils.h"
#include "tiny_logger.h"

typedef std::shared_ptr<PeLib::PeFile> PeFilePtr;

uint32_t rebuildMZHeader(PeFilePtr& peFile, std::vector<uint8_t>& outFileBuffer, std::vector<uint8_t>& sourceFileBuff)
{
  std::vector<PeLib::byte> mzHeadBuffer;
  auto mzHead = peFile->mzHeader();
  mzHead.rebuild(mzHeadBuffer);

  std::copy(mzHeadBuffer.cbegin(), mzHeadBuffer.cend(), std::back_inserter(outFileBuffer));

  // append mzHeader with undocumented data located between MZHeader & PEHeader
  auto peOffset = mzHead.getAddressOfPeHeader();
  auto cbMZHead = mzHead.size();
  auto cbJunkData = std::max(peOffset - cbMZHead, static_cast<uint32_t>(0));
  if (cbJunkData)
  {
    std::copy(&sourceFileBuff.at(cbMZHead), &sourceFileBuff.at(cbMZHead + cbJunkData), std::back_inserter(outFileBuffer));
  }

  return cbMZHead + cbJunkData;
}

template<int bits>
void rebuildPEHeader(PeLib::PeFile& peFile, std::vector<uint8_t>& outFileBuffer, uint32_t& offset)
{
  const PeLib::PeHeaderT<bits>& peh = static_cast<PeLib::PeFileT<bits>&>(peFile).peHeader();

  std::vector<PeLib::byte> peHeaderBuff;
  peh.rebuild(peHeaderBuff);

  PeLib::PeHeaderT<bits> pehOut;
  auto cbAfterHeader = peh.size();
  std::copy(peHeaderBuff.cbegin(), peHeaderBuff.cend(), std::back_inserter(outFileBuffer));

  offset += pehOut.size();

  // append with aligned zero-bytes
  auto headersSize = peh.getSizeOfHeaders() - offset;
  if (headersSize)
  {
    //todo(azerg): strip unused data by fixing size of headers ?
    outFileBuffer.insert(outFileBuffer.end(), headersSize, 0);
  }
  offset += headersSize;
}

//------------------------------------------------------------------------

class DumpPeHeaderVisitor: public PeLib::PeFileVisitor
{
public:
  DumpPeHeaderVisitor(std::vector<uint8_t>& outFileBuffer, uint32_t& offset) :
    outFileBuffer_(outFileBuffer)
    , offset_(offset)
  {}
  virtual void callback(PeLib::PeFile32& file) { rebuildPEHeader<32>(file, outFileBuffer_, offset_); }
  virtual void callback(PeLib::PeFile64& file) { rebuildPEHeader<64>(file, outFileBuffer_, offset_); }
private:
  std::vector<uint8_t>& outFileBuffer_;
  uint32_t& offset_;
};

//------------------------------------------------------------------------

ErrorCode PackExecutable(const std::string& srcFileName, const std::string& outFileName)
{
  try
  {
    if (!boost::filesystem::exists(srcFileName))
    {
      return ErrorCode::FILE_NOT_FOUND;
    }

    auto sourceFileBuff = file_utils::readFile(srcFileName.c_str());
    decltype(sourceFileBuff) outFileBuff;

    if (boost::filesystem::exists(outFileName))
    {
      boost::filesystem::remove(outFileName);
    }

    auto pef = PeLib::openPeFile(srcFileName);
    if (!pef)
    {
      std::cout << "Invalid PE File" << std::endl;
      return ErrorCode::INVALID_PE_FILE;
    }

    std::vector<uint8_t> outFileBuffer;

    pef->readMzHeader();
    auto offset = rebuildMZHeader(pef, outFileBuffer, sourceFileBuff);

    // stores data sizes required by different packers
    std::vector<RequiredDataBlock> additionalSizeRequest;

    //-----------------------------------------------------

    pef->readPeHeader();
    DumpPeHeaderVisitor peVisitor(outFileBuffer, offset);
    pef->visit(peVisitor);

    //-----------------------------------------------------

    ImportPacker importPacker(pef);
    additionalSizeRequest.push_back({importPacker.GetRequiredSpaceSize(), PackerTypes::kImportPacker});

    //-----------------------------------------------------

    SectionsPacker sectionsPacker(pef);
    auto sectionsArr = sectionsPacker.ProcessExecutable(sourceFileBuff, additionalSizeRequest);

    //-----------------------------------------------------

    // pick last section VA to use it as new imports VA
    auto additionalImportsBlock = std::find_if(
      sectionsArr.additionalDataBlocks.begin()
      , sectionsArr.additionalDataBlocks.end()
      ,[&](decltype(sectionsArr.additionalDataBlocks)::value_type& valIt)
    {
      return valIt.ownerType == PackerTypes::kImportPacker;
    });

    auto newImportsVA = 0;

    if (additionalImportsBlock != sectionsArr.additionalDataBlocks.end())
    {
      newImportsVA = additionalImportsBlock->virtualOffset;
    }

    auto importsArr = importPacker.ProcessExecutable(newImportsVA); // new import RVA passed here

    //-----------------------------------------------------

    return ErrorCode::ERROR_SUCC;
  }
  catch (std::runtime_error& err)
  {
    std::cout << err.what();
  }

  return ErrorCode::FATAL_ERROR;
}<|endoftext|>


<commit_before><commit_msg>cppcheck reduce scope of var in vcl/unx/...wmadaptor.cxx<commit_after><|endoftext|>


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

Program:   ORFEO Toolbox
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.txt for details.

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

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

int main(int argc, char* argv[])
{
 try
    {
  typedef double PixelType;
  typedef otb::ImageViewerManager<PixelType> ManagerType;
  ManagerType::Pointer manager = ManagerType::New();
  manager->Show();
  std::string strTest("--Test");
  bool bFlRun(true);

  for(int i = 1; i<argc;++i)
    {
      if( strTest.compare(argv[i])==0 )
      {
        std::cout << "--Test option. No FL::run() call !" << std::endl;
        bFlRun=false;
      }
      else
      {
        manager->OpenImage(argv[i]);
        Fl::check();
      }
    }
  if( bFlRun==true) return Fl::run();
    }
  catch( itk::ExceptionObject & err )
    {
    std::cout << "Following otbException catch :" << std::endl;
    std::cout << err << std::endl;
    return EXIT_FAILURE;
    }
  catch( std::bad_alloc & err )
    {
    std::cout << "Exception bad_alloc : "<<(char*)err.what()<< std::endl;
    return EXIT_FAILURE;
    }
  catch( ... )
    {
    std::cout << "Unknown Exception found !" << std::endl;
    return EXIT_FAILURE;
    }
  return EXIT_SUCCESS;
}
<commit_msg>Ajout du filtre de lecture/ecriture des shapefiles (encore en cours de développement) Ajout de tests du répertoire Projections dans OTB-Applications Ajout de fichiers en Baseline d'OTB-Applications pour les tests de non-régression du répertoire Projections Ajout d'une option --OTB-Testing par défaut dans le otb::CommandLineArgumentParser (non visible par un usage()) Suppression du troisième paramètre template "bidon" dans otb::Image et otb::VectorImage<commit_after>/*=========================================================================

Program:   ORFEO Toolbox
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.txt for details.

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

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

int main(int argc, char* argv[])
{
 try
    {
  typedef double PixelType;
  typedef otb::ImageViewerManager<PixelType> ManagerType;
  ManagerType::Pointer manager = ManagerType::New();
  manager->Show();
  std::string strTest("--OTBTesting");
  bool bFlRun(true);

  for(int i = 1; i<argc;++i)
    {
      if( strTest.compare(argv[i])==0 )
      {
        std::cout << "--OTBTesting option. No FL::run() call !" << std::endl;
        bFlRun=false;
      }
      else
      {
        manager->OpenImage(argv[i]);
        Fl::check();
      }
    }
  if( bFlRun==true) return Fl::run();
    }
  catch( itk::ExceptionObject & err )
    {
    std::cout << "Following otbException catch :" << std::endl;
    std::cout << err << std::endl;
    return EXIT_FAILURE;
    }
  catch( std::bad_alloc & err )
    {
    std::cout << "Exception bad_alloc : "<<(char*)err.what()<< std::endl;
    return EXIT_FAILURE;
    }
  catch( ... )
    {
    std::cout << "Unknown Exception found !" << std::endl;
    return EXIT_FAILURE;
    }
  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before><commit_msg>Land additional doctype piece.  toString fix of doctype.<commit_after><|endoftext|>