text:
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// test_cyclic_ptrs.cpp

// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

// should pass compilation and execution

#include <cstddef> // NULL
#include <fstream>

#include <cstdio> // remove
#include <boost/config.hpp>
#if defined(BOOST_NO_STDC_NAMESPACE)
namespace std{
    using ::remove;
}
#endif

#include <archive/archive_exception.hpp>
#include <serialization/nvp.hpp>
#include <serialization/version.hpp>
#include <serialization/base_object.hpp>

#include <I3Test.h>

#include "A.hpp"
#include "A.ipp"

///////////////////////////////////////////////////////
// class with a member which refers to itself
class J : public A
{
private:
    friend class icecube::serialization::access;
    template<class Archive>
    void serialize(Archive &ar, const unsigned int /* file_version */){
        ar & I3_SERIALIZATION_BASE_OBJECT_NVP(A);
        ar & I3_SERIALIZATION_NVP(j);
    }
public:
    bool operator==(const J &rhs) const;
    J *j;
    J(J *_j) : j(_j) {}
    J() : j(NULL){}
};

I3_CLASS_VERSION(J, 6)

bool J::operator==(const J &rhs) const
{
    return static_cast<const A &>(*this) == static_cast<const A &>(rhs);
}

///////////////////////////////////////////////////////
// class with members that refer to each other
// this is an example of a class that, as written, cannot
// be serialized with this system.  The problem is that the
// serialization of the first member - j1 , provokes serialization
// of those objects which it points to either directly or indirectly.
// When those objects are subsequently serialized, it is discovered
// that have already been serialized through pointers.  This is
// detected by the system and an exception - pointer_conflict -
// is thrown.  Permiting this to go undetected would result in the
// creation of multiple equal objects rather than the original
// structure.
class K
{
    J j1;
    J j2;
    J j3;
    friend class icecube::serialization::access;
    template<class Archive>
    void serialize(
        Archive &ar,
        const unsigned int /* file_version */
    ){
        ar & I3_SERIALIZATION_NVP(j1);
        ar & I3_SERIALIZATION_NVP(j2);
        ar & I3_SERIALIZATION_NVP(j3);
    }
public:
    bool operator==(const K &rhs) const;
    K();
};

K::K()
: j1(&j2), j2(&j3), j3(&j1)
{
}

bool K::operator==(const K &rhs) const
{
    return
        j1.j == & j2
        && j2.j == & j3
        && j3.j == & j1
        && j1 == rhs.j1
        && j2 == rhs.j2
        && j3 == rhs.j3
    ;
}

template <typename TS /*test settings*/>
void test1(){
    auto testfile = I3Test::testfile("test_cyclic_ptrs_1");

    J j1, j2;
    {
        typename TS::test_ostream os(testfile, TS::TEST_STREAM_FLAGS);
        typename TS::test_oarchive oa(os, TS::TEST_ARCHIVE_FLAGS);
        oa << I3_SERIALIZATION_NVP(j1);
    }
    {
        // try to read the archive
        typename TS::test_istream is(testfile, TS::TEST_STREAM_FLAGS);
        typename TS::test_iarchive ia(is, TS::TEST_ARCHIVE_FLAGS);
        ia >> I3_SERIALIZATION_NVP(j2);
    }
    ENSURE(j1 == j2);
    std::remove(testfile.c_str());
}

template <typename TS /*test settings*/>
void test2(){
    auto testfile = I3Test::testfile("test_cyclic_ptrs_2");

    J *j1 = new J;
    j1->j = j1;
    J *j2 = reinterpret_cast<J *>(0xBAADF00D);
    {
        typename TS::test_ostream os(testfile, TS::TEST_STREAM_FLAGS);
        typename TS::test_oarchive oa(os, TS::TEST_ARCHIVE_FLAGS);
        oa << I3_SERIALIZATION_NVP(j1);
    }
    {
        // try to read the archive
        typename TS::test_istream is(testfile, TS::TEST_STREAM_FLAGS);
        typename TS::test_iarchive ia(is, TS::TEST_ARCHIVE_FLAGS);
        ia >> I3_SERIALIZATION_NVP(j2);
    }
    ENSURE(*j1 == *j2);
    ENSURE(j2 == j2->j);
    std::remove(testfile.c_str());
}

template <typename TS /*test settings*/>
void test3(){
    auto testfile = I3Test::testfile("test_cyclic_ptrs_3");

    K k;
    icecube::archive::archive_exception exception(
        icecube::archive::archive_exception::no_exception
    );
    {
        typename TS::test_ostream os(testfile, TS::TEST_STREAM_FLAGS);
        typename TS::test_oarchive oa(os, TS::TEST_ARCHIVE_FLAGS);
        try{
            oa << I3_SERIALIZATION_NVP(k);
        }
        catch(icecube::archive::archive_exception &ae){
            exception = ae;
        }
        ENSURE(
            exception.code == icecube::archive::archive_exception::pointer_conflict
        );
    }
    // if exception wasn't invoked
    if(exception.code == icecube::archive::archive_exception::no_exception){
        // try to read the archive
        typename TS::test_istream is(testfile, TS::TEST_STREAM_FLAGS);
        typename TS::test_iarchive ia(is, TS::TEST_ARCHIVE_FLAGS);
        exception = icecube::archive::archive_exception(
            icecube::archive::archive_exception::no_exception
        );
        try{
            ia >> I3_SERIALIZATION_NVP(k);
        }
        catch(icecube::archive::archive_exception &ae){
            exception = ae;
        }
        ENSURE(
            exception.code == icecube::archive::archive_exception::pointer_conflict
        );
    }
    std::remove(testfile.c_str());
}

TEST_GROUP(cyclic_ptrs)

#define TEST_SET(name) \
TEST(name ## _test1){ \
    test1<test_settings>(); \
} \
TEST(name ## _test2){ \
    test2<test_settings>(); \
} \
TEST(name ## _test3){ \
    test3<test_settings>(); \
}

#define I3_ARCHIVE_TEST binary_archive.hpp
#include "select_archive.hpp"
TEST_SET(binary_archive)

#undef I3_ARCHIVE_TEST
#define I3_ARCHIVE_TEST text_archive.hpp
#include "select_archive.hpp"
TEST_SET(text_archive)

#undef I3_ARCHIVE_TEST
#define I3_ARCHIVE_TEST xml_archive.hpp
#include "select_archive.hpp"
TEST_SET(xml_archive)

#undef I3_ARCHIVE_TEST
#define I3_ARCHIVE_TEST portable_binary_archive.hpp
#include "select_archive.hpp"
TEST_SET(portable_binary_archive)

// EOF


text:
//#include <Eigen/Core>
#include <Eigen/LU>
#include <stdint.h>
#include "tilebase.h"
#include "nd.h"
#include "xform.h"

#define LOG(...)          fprintf(stderr,__VA_ARGS__)
#define REPORT(msg1,msg2) LOG("%s(%d) - %s()\n\t%s\n\t%s\n",__FILE__,__LINE__,__FUNCTION__,msg1,msg2)
#define TRY(e)            do{ if(!(e)) {REPORT(#e,"Expression evaluated as false"); goto Error;}}while(0)

using namespace Eigen;

typedef  Map<Matrix<float,Dynamic,Dynamic,RowMajor> > xform_t;
typedef  Matrix<int64_t,Dynamic,1>     vi64_t;
typedef  vi64_t                        vori_t;
typedef  vi64_t                        vshape_t;

/** returned value is reference to static variable.
    Past references may change value when this function is called again!
 */
static const vori_t vori(aabb_t box_nm)
{ int64_t *v=0;
  size_t ndim=0;
  AABBGet(box_nm,&ndim,&v,0);
  vi64_t r(ndim+2,1); // bbox omits color and affine-lifting dimensions
  r.tail<2>()<<0,1;
  r.segment(0,ndim)=Map<vi64_t>(v,ndim);
  return r;
}

/** returned value is reference to static variable.
    Past references may change value when this function is called again!
 */
static const vshape_t vshape(aabb_t box_nm)
{ int64_t *v=0;
  size_t ndim=0;
  AABBGet(box_nm,&ndim,0,&v);
  vi64_t r(ndim+2,1); // bbox omits color and affine-lifting dimensions
  r.tail<2>()<<0,1;
  r.segment(0,ndim)=Map<vi64_t>(v,ndim);
  return r;
}

static const xform_t xform(tile_t self)
{ xform_t xform(TileTransform(self),5,5);
  return xform;
}

/** makes a bounding box from two opposed corners */
static aabb_t fromCorners(const MatrixXf& r1, const MatrixXf& r2)
{ vi64_t tl,br,s;
  tl=r1.cwiseMin(r2).cast<int64_t>();
  br=r1.cwiseMax(r2).cast<int64_t>();
  s=br-tl;
  aabb_t out=AABBMake(tl.rows()-2); // remove affine and color dims
  AABBSet(out,tl.rows()-2,tl.data(),s.data());
  return out;
}

/** makes a bounding box from an array's shape. */
static aabb_t fromShape(nd_t shape)
{ aabb_t out=AABBMake(3); // hardcoded number of dimensions
  size_t *s=ndshape(shape);
  int64_t o[3]={0,0,0},
         is[3]={s[0],s[1],s[2]};
  return AABBSet(out,3,o,is);
}

/** caller must free returned result with AABBFree */
aabb_t AABBToPx(tile_t self, aabb_t box_nm)
{ MatrixXf T,r1,r2;
  r1=vori(box_nm).cast<float>();
  T=xform(self).inverse();
  r2=(vori(box_nm)+vshape(box_nm)).cast<float>();
  r2.bottomRightCorner<1,1>()<<1;
  aabb_t pbox=fromShape(TileShape(self)),
          out=AABBIntersectIP(fromCorners(T*r1,T*r2),pbox);
  AABBFree(pbox);
  return out;
Error:
  return 0;
}

static size_t* int64_to_static_sizet(int64_t* v,size_t n)
{ size_t i;
  static size_t *out=0,sz=0;
  if(n>sz)
  { sz=1.2*n+50;
    TRY(out=(size_t*)malloc(sizeof(size_t)*sz));
  }
  for(i=0;i<n;++i) out[i]=(size_t)v[i];
Error:
  return out;
}

static size_t* int64_to_new_sizet(int64_t* v,size_t n)
{ size_t i,*out=0;
  TRY(out=(size_t*)malloc(sizeof(size_t)*n));
  for(i=0;i<n;++i) out[i]=(size_t)v[i];
Error:
  return out;
}

//caller must use ndfree to release shape field in returned struct.
struct nd_subarray_t AABBToSubarray(tile_t self, aabb_t box_nm)
{ aabb_t box_px=0;
  struct nd_subarray_t out={0};
  TRY(box_px=AABBToPx(self,box_nm)); // should already be cropped to tile
  { size_t ndim,i;
    int64_t *ori,*shape;
    nd_t s=TileShape(self);
    AABBGet(box_px,&ndim,&ori,&shape);
    ndPushShape(s);
    for(i=0;i<ndim;++i)
      ndShapeSet(s,(unsigned)i,(size_t)shape[i]); // leave the non spatial dimensions the same.  This will get all color channels, for example.
    out.shape=ndheap(s);
    ndPopShape(s);

    TRY(out.ori=(size_t*)malloc(sizeof(size_t)*ndndim(s)));
    for(i=0;i<ndim;++i)
      out.ori[i]=(size_t)ori[i];
    for(;i<ndndim(s);++i)
      out.ori[i]=0;
  }
Finalize:
  AABBFree(box_px);
  return out;
Error:
  out.ori=0;
  ndfree(out.shape);
  out.shape=0;
  goto Finalize;
}

ext: cc

max_stars_repo_name: TeravoxelTwoPhotonTomography/tilebase

max_issues_repo_name: TeravoxelTwoPhotonTomography/tilebase

max_forks_repo_name: TeravoxelTwoPhotonTomography/tilebase


text:
#include "framework/builder/cfem_framework_builder.h"

#include <fstream>
#include <streambuf>
#include <deal.II/base/mpi.h>
#include <formulation/angular/self_adjoint_angular_flux.h>

#include "calculator/cell/integrated_fission_source.h"
#include "calculator/cell/total_aggregated_fission_source.h"
#include "convergence/moments/convergence_checker_l1_norm.hpp"
#include "convergence/reporter/mpi_noisy.h"
#include "domain/domain.hpp"
#include "domain/finite_element/finite_element_gaussian.h"
#include "domain/mesh/mesh_cartesian.hpp"
#include "eigenvalue/k_effective/updater_via_fission_source.h"
#include "formulation/cfem_diffusion_stamper.h"
#include "formulation/scalar/diffusion.hpp"
#include "formulation/cfem_saaf_stamper.h"
#include "framework/framework.h"
#include "iteration/updater/source_updater_gauss_seidel.h"
#include "iteration/updater/angular_source_updater_gauss_seidel.h"
#include "iteration/updater/fixed_updater.h"
#include "iteration/updater/angular_fixed_updater.h"
#include "iteration/initializer/initialize_fixed_terms_once.h"
#include "iteration/initializer/set_fixed_terms_once.h" // to be removed
#include "iteration/group/group_source_iteration.hpp"
#include "iteration/outer/outer_power_iteration.h"
#include "material/material_protobuf.h"
#include "problem/parameter_types.h"
#include "convergence/parameters/single_parameter_checker.h"
#include "convergence/final_checker_or_n.h"
#include "quadrature/utility/quadrature_utilities.h"
#include "quadrature/factory/quadrature_factories.h"
#include "results/output_dealii_vtu.h"
#include "solver/group/single_group_solver.h"
#include "solver/gmres.h"
#include "system/system.h"
#include "system/solution/mpi_group_angular_solution.h"
#include "system/terms/term.h"
#include "system/terms/term_types.h"
#include "system/moments/spherical_harmonic.h"
#include "system/system_functions.h"

namespace bart {

namespace framework {

namespace builder {

template <int dim>
std::unique_ptr<FrameworkI> CFEM_FrameworkBuilder<dim>::BuildFramework(
    problem::ParametersI &prm,
    dealii::ParameterHandler &d2_prm) {

  std::cout << "Setting up materials" << std::endl;

  std::ifstream mapping_file(prm.MaterialMapFilename());
  std::string material_mapping(
      (std::istreambuf_iterator<char>(mapping_file)),
      std::istreambuf_iterator<char>());

  const int n_groups = prm.NEnergyGroups();
  int n_angles;

  MaterialProtobuf materials(d2_prm);
  auto cross_sections_ptr = std::make_shared<bart::data::CrossSections>(materials);

  std::cout << "Building Finite Element"<< std::endl;
  std::shared_ptr<FiniteElement>finite_element_ptr(std::move(BuildFiniteElement(
      &prm)));

  std::cout << "Building Domain" << std::endl;
  std::shared_ptr<Domain> domain_ptr(std::move(BuildDomain(
      &prm,finite_element_ptr, material_mapping)));

  std::cout << "Setting up domain" << std::endl;
  domain_ptr->SetUpMesh().SetUpDOF();

  std::shared_ptr<SourceUpdater> source_updater_ptr;
  std::unique_ptr<Initializer> initializer_ptr;

  std::shared_ptr<AngularQuadratureSet> quadrature_ptr = nullptr;

  if (prm.TransportModel() == problem::EquationType::kSelfAdjointAngularFlux) {
    printf("Building Quadrature Set\n");
    quadrature_ptr = BuildAngularQuadratureSet(&prm);
    n_angles = quadrature_ptr->size();
  } else {
    printf("Scalar solve\n");
    n_angles = 1;
  }

  if (prm.TransportModel() == problem::EquationType::kSelfAdjointAngularFlux) {
    printf("Building Stamper\n");
    std::shared_ptr<CFEMAngularStamper> stamper_ptr(std::move(BuildAngularStamper(
        &prm, domain_ptr, finite_element_ptr, cross_sections_ptr, quadrature_ptr)));
    printf("Building Source Updater\n");
    source_updater_ptr = std::move(BuildSourceUpdater(&prm, stamper_ptr, quadrature_ptr));
    printf("Building Initializer\n");
    initializer_ptr = BuildInitializer(&prm, stamper_ptr, quadrature_ptr);
  } else {
    printf("Building Scalar Stamper\n");
    std::shared_ptr<CFEMStamper> stamper_ptr(std::move(BuildStamper(
        &prm, domain_ptr, finite_element_ptr, cross_sections_ptr)));
    printf("Building Source Updater\n");
    source_updater_ptr = std::move(BuildSourceUpdater(&prm, stamper_ptr));
    printf("Building Initializer\n");
    initializer_ptr = BuildInitializer(&prm, stamper_ptr);
  }

  std::cout << "Building single group solver" << std::endl;
  auto single_group_solver_ptr = BuildSingleGroupSolver();

  std::cout << "Building inner iteration objects" << std::endl;

  auto in_group_final_checker = BuildMomentConvergenceChecker(1e-10, 100);

  // Build reporter
  std::shared_ptr<ConvergenceReporter> reporter(std::move(BuildConvergenceReporter()));

  auto moment_calculator_type = quadrature::MomentCalculatorImpl::kScalarMoment;

  // Moment calculator
  if (prm.TransportModel() == problem::EquationType::kSelfAdjointAngularFlux) {
    moment_calculator_type = quadrature::MomentCalculatorImpl::kZerothMomentOnly;
  }

  auto moment_calculator_ptr = quadrature::factory::MakeMomentCalculator<dim>(
      moment_calculator_type,
      quadrature_ptr);

  std::cout << "Building and initializing system object" << std::endl;

  // Solution group
  auto solution_ptr =
      std::make_shared<system::solution::MPIGroupAngularSolution>(n_angles);

  system::SetUpMPIAngularSolution(*solution_ptr, *domain_ptr);

  std::cout << "Building in-group iteration" << std::endl;

  auto in_group_iteration =
      std::make_unique<iteration::group::GroupSourceIteration<dim>>(
          std::move(single_group_solver_ptr),
          std::move(in_group_final_checker),
          std::move(moment_calculator_ptr),
          solution_ptr,
          source_updater_ptr,
          reporter);

  std::cout << "Building K_Effective updater" << std::endl;

  // KEffectiveUpdater
  using FissionSourceCalulator = calculator::cell::TotalAggregatedFissionSource<dim>;
  using IntegratedFissionSourceCalc = calculator::cell::IntegratedFissionSource<dim>;
  auto int_fission_ptr = std::make_unique<IntegratedFissionSourceCalc>(
      finite_element_ptr, cross_sections_ptr);
  auto fission_source_calc_ptr = std::make_unique<FissionSourceCalulator>(
      std::move(int_fission_ptr), domain_ptr);
  using KEffectiveUpdater = eigenvalue::k_effective::UpdaterViaFissionSource;

  // KEffective convergence checker
  using KEffConvChecker = bart::convergence::parameters::SingleParameterChecker;
  auto k_eff_conv_checker = std::make_unique<KEffConvChecker>();
  using KEffectiveFinalCovergence = bart::convergence::FinalCheckerOrN<double,
      bart::convergence::parameters::SingleParameterChecker>;
  auto k_eff_final_checker = std::make_unique<KEffectiveFinalCovergence>(
      std::move(k_eff_conv_checker)
      );

  // KEffective updater
  auto k_effective_updater = std::make_unique<KEffectiveUpdater>(
      std::move(fission_source_calc_ptr), 2.0, 10);

  std::cout << "Building outer-iteration" << std::endl;

  using PowerIteration = iteration::outer::OuterPowerIteration;
  auto power_iteration_ptr = std::make_unique<PowerIteration>(
      std::move(in_group_iteration),
      std::move(k_eff_final_checker),
      std::move(k_effective_updater),
      source_updater_ptr,
      reporter
  );

  std::cout << "Building System" << std::endl;

  auto system = std::make_unique<system::System>();

  system->total_groups = n_groups;
  std::unordered_set<bart::system::terms::VariableLinearTerms>
      source_terms{bart::system::terms::VariableLinearTerms::kScatteringSource,
                   bart::system::terms::VariableLinearTerms::kFissionSource};
  system->right_hand_side_ptr_ =
      std::make_unique<system::terms::MPILinearTerm>(source_terms);
  system->left_hand_side_ptr_ =
      std::make_unique<system::terms::MPIBilinearTerm>();

  std::cout << "Filling system" << std::endl;

  // Fill system with objects
  for (int group = 0; group < n_groups; ++group) {
    for (int angle = 0; angle < n_angles; ++angle) {
      system::Index index{group, angle};
      // LHS
      auto fixed_matrix_ptr = domain_ptr->MakeSystemMatrix();
      system->left_hand_side_ptr_->SetFixedTermPtr(index, fixed_matrix_ptr);

      // RHS
      auto fixed_vector_ptr =
          std::make_shared<bart::system::MPIVector>(domain_ptr->locally_owned_dofs(),
                                                    MPI_COMM_WORLD);
      system->right_hand_side_ptr_->SetFixedTermPtr(index, fixed_vector_ptr);

      for (auto term : source_terms) {
        auto variable_vector_ptr =
            std::make_shared<bart::system::MPIVector>(domain_ptr->locally_owned_dofs(),
                                                      MPI_COMM_WORLD);
        system->right_hand_side_ptr_->SetVariableTermPtr(
            index, term, variable_vector_ptr);
      }
    }
  }

  std::cout << "Fill system moments" << std::endl;

  // Moments
  system->current_moments =
      std::make_unique<system::moments::SphericalHarmonic>(n_groups, 0);
  system->previous_moments =
      std::make_unique<system::moments::SphericalHarmonic>(n_groups, 0);

  for (auto& moment_pair : system->current_moments->moments()) {
    auto index = moment_pair.first;
    auto& current_moment = system->current_moments->operator[](index);
    current_moment.reinit(solution_ptr->operator[](0).size());
    auto& previous_moment = system->previous_moments->operator[](index);
    previous_moment.reinit(solution_ptr->operator[](0).size());
    current_moment = 1;
    previous_moment = 1;
  }

  // Initialize System
  system->k_effective = 1.0;
  system->total_groups = n_groups;
  system->total_angles = n_angles;

  std::cout << "Build Results Output" << std::endl;
  auto results_output_ptr =
      std::make_unique<results::OutputDealiiVtu<dim>>(domain_ptr);

  return std::make_unique<framework::Framework>(
      std::move(system),
      std::move(initializer_ptr),
      std::move(power_iteration_ptr),
      std::move(results_output_ptr));
}

template <int dim>
auto CFEM_FrameworkBuilder<dim>::BuildAngularQuadratureSet(
        problem::ParametersI* problem_parameters)
-> std::shared_ptr<AngularQuadratureSet> {

  std::shared_ptr<AngularQuadratureSet> return_ptr = nullptr;

  std::shared_ptr<quadrature::QuadratureGeneratorI<dim>>
      quadrature_generator_ptr = nullptr;

  const int order_value = problem_parameters->AngularQuadOrder();
  switch (problem_parameters->AngularQuad()) {
    default: {
      if (dim == 3) {
        quadrature_generator_ptr =
            quadrature::factory::MakeAngularQuadratureGeneratorPtr<dim>(
                quadrature::Order(order_value),
                quadrature::AngularQuadratureSetType::kLevelSymmetricGaussian);
      } else {
        AssertThrow(false,
            dealii::ExcMessage("No supported quadratures for this dimension "
                               "and transport model"))
      }
    }
  }

  return_ptr = quadrature::factory::MakeQuadratureSetPtr<dim>();

  auto quadrature_points = quadrature::utility::GenerateAllPositiveX<dim>(
      quadrature_generator_ptr->GenerateSet());

  quadrature::factory::FillQuadratureSet<dim>(return_ptr.get(),
                                              quadrature_points);

  return std::move(return_ptr);
}

template <int dim>
auto CFEM_FrameworkBuilder<dim>::BuildConvergenceReporter()
-> std::unique_ptr<ConvergenceReporter> {
  std::unique_ptr<ConvergenceReporter> return_ptr = nullptr;

  using Reporter = bart::convergence::reporter::MpiNoisy;
  int this_process = dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD);
  auto pout_ptr = std::make_unique<dealii::ConditionalOStream>(std::cout, this_process == 0);
  return_ptr = std::make_unique<Reporter>(std::move(pout_ptr));

  return std::move(return_ptr);
}

template<int dim>
auto CFEM_FrameworkBuilder<dim>::BuildDomain(
    problem::ParametersI *problem_parameters,
    const std::shared_ptr<FiniteElement> &finite_element_ptr,
    std::string material_mapping)-> std::unique_ptr<Domain> {

  // Build mesh
  auto mesh_ptr = std::make_unique<domain::mesh::MeshCartesian<dim>>(
      problem_parameters->SpatialMax(),
      problem_parameters->NCells(),
      material_mapping);

  return std::make_unique<domain::Definition<dim>>(
      std::move(mesh_ptr), finite_element_ptr);
}

template<int dim>
auto CFEM_FrameworkBuilder<dim>::BuildFiniteElement(
    problem::ParametersI *problem_parameters)-> std::unique_ptr<FiniteElement> {
  return std::make_unique<domain::finite_element::FiniteElementGaussian<dim>>(
      problem::DiscretizationType::kContinuousFEM,
      problem_parameters->FEPolynomialDegree());
}

template <int dim>
auto CFEM_FrameworkBuilder<dim>::BuildInitializer(
    const problem::ParametersI *problem_parameters,
    const std::shared_ptr<CFEMStamper> &stamper_ptr)
-> std::unique_ptr<Initializer> {

  std::unique_ptr<Initializer> return_ptr = nullptr;

  using FixedUpdaterType = iteration::updater::FixedUpdater<CFEMStamper>;
  auto fixed_updater_ptr = std::make_unique<FixedUpdaterType>(stamper_ptr);

  if (problem_parameters->TransportModel() == problem::EquationType::kDiffusion) {
    return_ptr = std::make_unique<iteration::initializer::SetFixedTermsOnce>(
        std::move(fixed_updater_ptr), problem_parameters->NEnergyGroups(), 1);
  }

  return std::move(return_ptr);
}

template <int dim>
auto CFEM_FrameworkBuilder<dim>::BuildInitializer(
    const problem::ParametersI *problem_parameters,
    const std::shared_ptr<CFEMAngularStamper> &stamper_ptr,
    const std::shared_ptr<AngularQuadratureSet>& quadrature_set_ptr)
-> std::unique_ptr<Initializer> {

  std::unique_ptr<Initializer> return_ptr = nullptr;

  using FixedUpdaterType = iteration::updater::AngularFixedUpdater<CFEMAngularStamper>;
  auto fixed_updater_ptr = std::make_unique<FixedUpdaterType>(
      stamper_ptr, quadrature_set_ptr);

  if (problem_parameters->TransportModel() == problem::EquationType::kSelfAdjointAngularFlux) {
    return_ptr = std::make_unique<iteration::initializer::SetFixedTermsOnce>(
        std::move(fixed_updater_ptr),
        problem_parameters->NEnergyGroups(),
        quadrature_set_ptr->size());
  }

  return std::move(return_ptr);
}

template<int dim>
auto CFEM_FrameworkBuilder<dim>::BuildMomentConvergenceChecker(
    double max_delta, int max_iterations)
-> std::unique_ptr<MomentConvergenceChecker>{
  //TODO(Josh): Add option for using other than L1Norm

  using CheckerType = convergence::moments::SingleMomentCheckerL1Norm;
  using FinalCheckerType = convergence::FinalCheckerOrN<
      system::moments::MomentVector,
      convergence::moments::SingleMomentCheckerI>;

  auto single_checker_ptr = std::make_unique<CheckerType>(max_delta);
  auto return_ptr = std::make_unique<FinalCheckerType>(
      std::move(single_checker_ptr));

  return_ptr->SetMaxIterations(max_iterations);

  return std::move(return_ptr);
}

template<int dim>
auto CFEM_FrameworkBuilder<dim>::BuildParameterConvergenceChecker(
    double max_delta, int max_iterations)
-> std::unique_ptr<ParameterConvergenceChecker>{

  using CheckerType = convergence::parameters::SingleParameterChecker;
  using FinalCheckerType = convergence::FinalCheckerOrN<double, CheckerType>;

  auto single_checker_ptr = std::make_unique<CheckerType>(max_delta);
  auto return_ptr = std::make_unique<FinalCheckerType>(
      std::move(single_checker_ptr));

  return_ptr->SetMaxIterations(max_iterations);

  return std::move(return_ptr);
}

template<int dim>
auto CFEM_FrameworkBuilder<dim>::BuildSingleGroupSolver(
    const int max_iterations,
    const double convergence_tolerance) -> std::unique_ptr<SingleGroupSolver> {
  std::unique_ptr<SingleGroupSolver> return_ptr = nullptr;

  auto linear_solver_ptr = std::make_unique<solver::GMRES>(max_iterations,
                                                           convergence_tolerance);

  return_ptr = std::move(
      std::make_unique<solver::group::SingleGroupSolver>(
          std::move(linear_solver_ptr)));

  return return_ptr;
}

template<int dim>
auto CFEM_FrameworkBuilder<dim>::BuildSourceUpdater(
    problem::ParametersI *,
    const std::shared_ptr<CFEMStamper> stamper_ptr)
    -> std::unique_ptr<SourceUpdater> {
  // TODO(Josh): Add option for non-gauss-seidel updating
  using SourceUpdater = iteration::updater::SourceUpdaterGaussSeidel<CFEMStamper>;
  return std::make_unique<SourceUpdater>(stamper_ptr);
}

template<int dim>
auto CFEM_FrameworkBuilder<dim>::BuildSourceUpdater(
    problem::ParametersI *,
    const std::shared_ptr<CFEMAngularStamper> stamper_ptr,
    const std::shared_ptr<AngularQuadratureSet>& quadrature_set_ptr)
-> std::unique_ptr<SourceUpdater> {
  // TODO(Josh): Add option for non-gauss-seidel updating
  using SourceUpdater = iteration::updater::AngularSourceUpdaterGaussSeidel<CFEMAngularStamper>;
  return std::make_unique<SourceUpdater>(stamper_ptr, quadrature_set_ptr);
}

template<int dim>
auto CFEM_FrameworkBuilder<dim>::BuildStamper(
    problem::ParametersI *problem_parameters,
    const std::shared_ptr<Domain> &domain_ptr,
    const std::shared_ptr<FiniteElement> &finite_element_ptr,
    const std::shared_ptr<CrossSections> &cross_sections_ptr)
-> std::unique_ptr<CFEMStamper> {

  std::unique_ptr<CFEMStamper> return_ptr = nullptr;

  // Diffusion Stamper
  if (problem_parameters->TransportModel() == problem::EquationType::kDiffusion) {

    auto diffusion_ptr = std::make_unique<formulation::scalar::Diffusion<dim>>(
        finite_element_ptr, cross_sections_ptr);

    return_ptr = std::move(
        std::make_unique<formulation::CFEM_DiffusionStamper<dim>>(
            std::move(diffusion_ptr),
            domain_ptr,
            problem_parameters->ReflectiveBoundary()));

  } else {
    AssertThrow(false, dealii::ExcMessage("Unsuppored equation type passed"
                                          " to BuildScalarFormulation"));
  }

  return return_ptr;
}

template<int dim>
auto CFEM_FrameworkBuilder<dim>::BuildAngularStamper(
    problem::ParametersI *problem_parameters,
    const std::shared_ptr<Domain> &domain_ptr,
    const std::shared_ptr<FiniteElement> &finite_element_ptr,
    const std::shared_ptr<CrossSections> &cross_sections_ptr,
    const std::shared_ptr<AngularQuadratureSet>& quadrature_set_ptr)
-> std::unique_ptr<CFEMAngularStamper> {

  std::unique_ptr<CFEMAngularStamper> return_ptr = nullptr;

  if (problem_parameters->TransportModel() == problem::EquationType::kSelfAdjointAngularFlux) {

    auto saaf_formulation_ptr =
        std::make_unique<formulation::angular::SelfAdjointAngularFlux<dim>>(
        finite_element_ptr, cross_sections_ptr, quadrature_set_ptr);

    return_ptr = std::move(
        std::make_unique<formulation::CFEM_SAAF_Stamper<dim>>(
            std::move(saaf_formulation_ptr),
            domain_ptr));
  } else {
    AssertThrow(false, dealii::ExcMessage("Unsuppored equation type passed"
                                          "to BuildScalarFormulation"));
  }

  return return_ptr;
}

template class CFEM_FrameworkBuilder<1>;
template class CFEM_FrameworkBuilder<2>;
template class CFEM_FrameworkBuilder<3>;

} // namespace builder

} // namespace framework

} // namespace bart

max_stars_repo_name: SlaybaughLab/Transport

max_issues_repo_name: SlaybaughLab/Transport

max_forks_repo_name: SlaybaughLab/Transport


text:
/* Copyright 2006-2008 Joaquin M Lopez Munoz.
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or copy at
 * http://www.boost.org/LICENSE_1_0.txt)
 *
 * See http://www.boost.org/libs/flyweight for library home page.
 */

#ifndef BOOST_FLYWEIGHT_NO_LOCKING_HPP
#define BOOST_FLYWEIGHT_NO_LOCKING_HPP

#if defined(_MSC_VER)
#pragma once
#endif

#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/flyweight/no_locking_fwd.hpp>
#include <boost/flyweight/locking_tag.hpp>

/* null locking policy */

namespace boost{

namespace flyweights{

struct no_locking:locking_marker
{
  struct             mutex_type{};
  typedef mutex_type lock_type;
};

} /* namespace flyweights */

} /* namespace boost */

#endif

ext: hpp

max_stars_repo_name: rudylee/expo

max_issues_repo_name: rudylee/expo

max_forks_repo_name: rudylee/expo


text:
// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef VSOMEIP_ROUTING_MANAGER_STUB
#define VSOMEIP_ROUTING_MANAGER_STUB

#include <condition_variable>
#include <list>
#include <map>
#include <memory>
#include <mutex>
#include <set>
#include <thread>
#include <atomic>

#include <boost/asio/io_service.hpp>
#include <boost/asio/steady_timer.hpp>

#include "../../endpoints/include/endpoint_host.hpp"
#include "../../configuration/include/internal.hpp"
#include "types.hpp"

namespace vsomeip {

class configuration;
class routing_manager_stub_host;

class routing_manager_stub: public endpoint_host,
        public std::enable_shared_from_this<routing_manager_stub> {
public:
    routing_manager_stub(
            routing_manager_stub_host *_host,
            std::shared_ptr<configuration> _configuration);
    virtual ~routing_manager_stub();

    void init();
    void start();
    void stop();

    const std::shared_ptr<configuration> get_configuration() const;

    void on_connect(std::shared_ptr<endpoint> _endpoint);
    void on_disconnect(std::shared_ptr<endpoint> _endpoint);
    void on_message(const byte_t *_data, length_t _length, endpoint *_receiver,
            const boost::asio::ip::address &_destination,
            client_t _bound_client,
            const boost::asio::ip::address &_remote_address,
            std::uint16_t _remote_port);
    void on_error(const byte_t *_data, length_t _length, endpoint *_receiver,
                  const boost::asio::ip::address &_remote_address,
                  std::uint16_t _remote_port);
    void release_port(uint16_t _port, bool _reliable);

    void on_offer_service(client_t _client, service_t _service,
            instance_t _instance, major_version_t _major, minor_version_t _minor);
    void on_stop_offer_service(client_t _client, service_t _service,
            instance_t _instance,  major_version_t _major, minor_version_t _minor);

    bool send_subscribe(std::shared_ptr<vsomeip::endpoint> _target,
            client_t _client, service_t _service, instance_t _instance,
            eventgroup_t _eventgroup, major_version_t _major,
            event_t _event, pending_subscription_id_t _subscription_id);

    bool send_unsubscribe(std::shared_ptr<vsomeip::endpoint> _target,
            client_t _client, service_t _service,
            instance_t _instance, eventgroup_t _eventgroup,
            event_t _event, pending_subscription_id_t _unsubscription_id);

    void send_subscribe_nack(client_t _client, service_t _service,
            instance_t _instance, eventgroup_t _eventgroup, event_t _event);

    void send_subscribe_ack(client_t _client, service_t _service,
            instance_t _instance, eventgroup_t _eventgroup, event_t _event);

    bool contained_in_routing_info(client_t _client, service_t _service,
                                   instance_t _instance, major_version_t _major,
                                   minor_version_t _minor) const;

    void create_local_receiver();
    bool send_ping(client_t _client);
    bool is_registered(client_t _client) const;
    client_t get_client() const;
    void handle_requests(const client_t _client, std::set<service_data_t>& _requests);

    void send_identify_request_command(std::shared_ptr<vsomeip::endpoint> _target,
            service_t _service, instance_t _instance, major_version_t _major,
            bool _reliable);

#ifndef _WIN32
    virtual bool check_credentials(client_t _client, uid_t _uid, gid_t _gid);
#endif

    void update_registration(client_t _client, registration_type_e _type);

    void print_endpoint_status() const;
private:
    void broadcast(const std::vector<byte_t> &_command) const;

    void on_register_application(client_t _client);
    void on_deregister_application(client_t _client);

    void inform_requesters(client_t _hoster, service_t _service,
            instance_t _instance, major_version_t _major,
            minor_version_t _minor, routing_info_entry_e _entry,
            bool _inform_service);

    void broadcast_ping() const;
    void on_pong(client_t _client);
    void start_watchdog();
    void check_watchdog();
    void send_application_lost(std::list<client_t> &_lost);

    void client_registration_func(void);
    void init_routing_endpoint();
    void on_ping_timer_expired(boost::system::error_code const &_error);
    void remove_from_pinged_clients(client_t _client);
    void set_routing_state(routing_state_e _routing_state) {
        (void)_routing_state;
    };

    bool is_already_connected(client_t _source, client_t _sink);
    void create_client_routing_info(const client_t _target);
    void insert_client_routing_info(client_t _target, routing_info_entry_e _entry,
            client_t _client, service_t _service = ANY_SERVICE,
            instance_t _instance = ANY_INSTANCE,
            major_version_t _major = ANY_MAJOR,
            minor_version_t _minor = ANY_MINOR);
    void send_client_routing_info(const client_t _target);

    void create_offered_services_info(const client_t _target);
    void insert_offered_services_info(client_t _target,
            routing_info_entry_e _entry,
            service_t _service,
            instance_t _instance,
            major_version_t _major,
            minor_version_t _minor);
    void send_offered_services_info(const client_t _target);

    void on_client_id_timer_expired(boost::system::error_code const &_error);

private:
    routing_manager_stub_host *host_;
    boost::asio::io_service &io_;
    std::mutex watchdog_timer_mutex_;
    boost::asio::steady_timer watchdog_timer_;

    boost::asio::steady_timer client_id_timer_;
    std::set<client_t> used_client_ids_;
    std::mutex used_client_ids_mutex_;

    std::string endpoint_path_;
    std::string local_receiver_path_;
    std::shared_ptr<endpoint> endpoint_;
    std::shared_ptr<endpoint> local_receiver_;
    std::mutex local_receiver_mutex_;

    std::map<client_t,
            std::pair<uint8_t, std::map<service_t, std::map<instance_t, std::pair<major_version_t, minor_version_t>> > > > routing_info_;
    mutable std::mutex routing_info_mutex_;
    std::shared_ptr<configuration> configuration_;

    size_t routingCommandSize_;

    bool is_socket_activated_;
    std::atomic<bool> client_registration_running_;
    std::shared_ptr<std::thread> client_registration_thread_;
    std::mutex client_registration_mutex_;
    std::condition_variable client_registration_condition_;

    std::map<client_t, std::vector<registration_type_e>> pending_client_registrations_;
    const std::uint32_t max_local_message_size_;
    static const std::vector<byte_t> its_ping_;
    const std::chrono::milliseconds configured_watchdog_timeout_;
    boost::asio::steady_timer pinged_clients_timer_;
    std::mutex pinged_clients_mutex_;
    std::map<client_t, boost::asio::steady_timer::time_point> pinged_clients_;

    std::map<client_t, std::map<service_t, std::map<instance_t, std::pair<major_version_t, minor_version_t> > > > service_requests_;
    std::map<client_t, std::set<client_t>> connection_matrix_;

    std::map<client_t, std::vector<byte_t>> client_routing_info_;
    std::map<client_t, std::vector<byte_t>> offered_services_info_;
};

} // namespace vsomeip

#endif // VSOMEIP_ROUTING_MANAGER_STUB

max_stars_repo_name: MicrochipTech/some-ip

max_issues_repo_name: MicrochipTech/some-ip

max_forks_repo_name: MicrochipTech/some-ip


text:
#include <random>
#include <functional>
#include <vector>
#include <chrono>
#include <boost/format.hpp>
#include <algorithm>
#include "mpi.h"
#include "array3d.h"

using namespace std;

uniform_real_distribution<double> generator { -10, 10 };
default_random_engine re;

int mpi_rank;
int mpi_size;

const double GB = 1024 * 1024 * 1024;

const double kappa = 1.25 * (sqrt(3) - 1) * 0.5 / sqrt(3);
const double bx = (1 - kappa);
const double ax = 0.5 * (1 - bx);

double dt;
double dtdx;
double dtdy;
double dtdz;
double ay, az;
double by, bz;

double gen() {
    return generator(re);
}

struct vector3d {
    double x = 0, y = 0, z = 0;

    vector3d operator-(const vector3d & other) {
        vector3d res;
        res.x = x - other.x;
        res.y = y - other.y;
        res.z = z - other.z;
        return res;
    }
};

template <typename T>
void randomize(T & a) {
    int n = a.get_n();
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            for (int k = 0; k < n; k++){
                a(i, j, k).x = gen();
                a(i, j, k).y = gen();
                a(i, j, k).z = gen();
            }
        }
    }
}

template <typename T>
void advance_b(const T & e, T & b) {
    const int n = e.get_n();

    for(int i=2;i<n-1;i++) {
        for(int j=2;j<n-1;j++) {
            for(int k=2;k<n-1;k++) {
                b(i,j,k).x += 0.5*(   -dtdy*( bz*(e(i,j+1,k).z-e(i,j,k).z) + az*(e(i,j+1,k+1).z-e(i,j,k+1).z+e(i,j+1,k-1).z-e(i,j,k-1).z) )    +   dtdz*( by*(e(i,j,k+1).y-e(i,j,k).y) + ay*(e(i,j+1,k+1).y-e(i,j+1,k).y+e(i,j-1,k+1).y-e(i,j-1,k).y) )  );
                b(i,j,k).y += 0.5*(   dtdx*( bz*(e(i+1,j,k).z-e(i,j,k).z) + az*(e(i+1,j,k+1).z-e(i,j,k+1).z+e(i+1,j,k-1).z-e(i,j,k-1).z) )    -   dtdz*( bx*(e(i,j,k+1).x-e(i,j,k).x) + ax*(e(i+1,j,k+1).x-e(i+1,j,k).x+e(i-1,j,k+1).x-e(i-1,j,k).x) )  );
                b(i,j,k).z += 0.5*(   dtdy*( bx*(e(i,j+1,k).x-e(i,j,k).x) + ax*(e(i+1,j+1,k).x-e(i+1,j,k).x+e(i-1,j+1,k).x-e(i-1,j,k).x) )    -   dtdx*( by*(e(i+1,j,k).y-e(i,j,k).y) + ay*(e(i+1,j+1,k).y-e(i,j+1,k).y+e(i+1,j-1,k).y-e(i,j-1,k).y) )  );
            }
        }
    }
    {int i=1;
        for(int j=2;j<n-1;j++) {
            for(int k=2;k<n-1;k++) {
                b(i,j,k).y += 0.5*(   dtdx*( bz*(e(i+1,j,k).z-e(i,j,k).z) + az*(e(i+1,j,k+1).z-e(i,j,k+1).z+e(i+1,j,k-1).z-e(i,j,k-1).z) )    -   dtdz*( bx*(e(i,j,k+1).x-e(i,j,k).x) + ax*(e(i+1,j,k+1).x-e(i+1,j,k).x+e(i-1,j,k+1).x-e(i-1,j,k).x) )  );
                b(i,j,k).z += 0.5*(   dtdy*( bx*(e(i,j+1,k).x-e(i,j,k).x) + ax*(e(i+1,j+1,k).x-e(i+1,j,k).x+e(i-1,j+1,k).x-e(i-1,j,k).x) )    -   dtdx*( by*(e(i+1,j,k).y-e(i,j,k).y) + ay*(e(i+1,j+1,k).y-e(i,j+1,k).y+e(i+1,j-1,k).y-e(i,j-1,k).y) )  );
            }
        }
    }
    for(int i=2;i<n-1;i++) {
        {int j=1;
            for(int k=2;k<n-1;k++) {
                b(i,j,k).x += 0.5*(   -dtdy*( bz*(e(i,j+1,k).z-e(i,j,k).z) + az*(e(i,j+1,k+1).z-e(i,j,k+1).z+e(i,j+1,k-1).z-e(i,j,k-1).z) )    +   dtdz*( by*(e(i,j,k+1).y-e(i,j,k).y) + ay*(e(i,j+1,k+1).y-e(i,j+1,k).y+e(i,j-1,k+1).y-e(i,j-1,k).y) )  );
                b(i,j,k).z += 0.5*(   dtdy*( bx*(e(i,j+1,k).x-e(i,j,k).x) + ax*(e(i+1,j+1,k).x-e(i+1,j,k).x+e(i-1,j+1,k).x-e(i-1,j,k).x) )    -   dtdx*( by*(e(i+1,j,k).y-e(i,j,k).y) + ay*(e(i+1,j+1,k).y-e(i,j+1,k).y+e(i+1,j-1,k).y-e(i,j-1,k).y) )  );
            }
        }
    }
    for(int i=2;i<n-1;i++) {
        for(int j=2;j<n-1;j++) {
            {int k=1;
                b(i,j,k).x += 0.5*(   -dtdy*( bz*(e(i,j+1,k).z-e(i,j,k).z) + az*(e(i,j+1,k+1).z-e(i,j,k+1).z+e(i,j+1,k-1).z-e(i,j,k-1).z) )    +   dtdz*( by*(e(i,j,k+1).y-e(i,j,k).y) + ay*(e(i,j+1,k+1).y-e(i,j+1,k).y+e(i,j-1,k+1).y-e(i,j-1,k).y) )  );
                b(i,j,k).y += 0.5*(   dtdx*( bz*(e(i+1,j,k).z-e(i,j,k).z) + az*(e(i+1,j,k+1).z-e(i,j,k+1).z+e(i+1,j,k-1).z-e(i,j,k-1).z) )    -   dtdz*( bx*(e(i,j,k+1).x-e(i,j,k).x) + ax*(e(i+1,j,k+1).x-e(i+1,j,k).x+e(i-1,j,k+1).x-e(i-1,j,k).x) )  );
            }
        }
    }
}

void advance_b_z(const morton_array<vector3d> & e, morton_array<vector3d> & b) {
    const unsigned int n = e.get_size();

    for (unsigned int curr = 0; curr < n; curr++) {
        if (e.is_xmax(curr) || e.is_ymax(curr) || e.is_zmax(curr)) {
            continue;
        }

        if (e.is_xmin(curr) || e.is_ymin(curr) || e.is_zmin(curr)) {
            continue;
        }

        auto x_m = e.get_x_prev(curr);
        auto y_m = e.get_y_prev(curr);
        auto z_m = e.get_z_prev(curr);

        auto x_p = e.get_x_next(curr);
        auto y_p = e.get_y_next(curr);
        auto z_p = e.get_z_next(curr);

        auto xy_pp = e.get_y_next(x_p);
        auto xy_pm = e.get_y_prev(x_p);
        auto xy_mp = e.get_y_next(x_m);

        auto xz_pp = e.get_z_next(x_p);
        auto xz_pm = e.get_z_prev(x_p);
        auto xz_mp = e.get_z_next(x_m);

        auto yz_pp = e.get_z_next(y_p);
        auto yz_pm = e.get_z_prev(y_p);
        auto yz_mp = e.get_z_next(y_m);

        if (e.is_xmin(x_m)) {
            if (!e.is_ymin(y_m) && !e.is_zmin(z_m)) {
                b[curr].y += 0.5*(    dtdx*( bz*(e[x_p].z-e[curr].z) + az*(e[xz_pp].z-e[z_p].z+e[xz_pm].z-e[z_m].z) )    -   dtdz*( bx*(e[z_p].x-e[curr].x) + ax*(e[xz_pp].x-e[x_p].x+e[xz_mp].x-e[x_m].x) )  );
                b[curr].z += 0.5*(    dtdy*( bx*(e[y_p].x-e[curr].x) + ax*(e[xy_pp].x-e[x_p].x+e[xy_mp].x-e[x_m].x) )    -   dtdx*( by*(e[x_p].y-e[curr].y) + ay*(e[xy_pp].y-e[y_p].y+e[xy_pm].y-e[y_m].y) )  );
            }
        } else if (e.is_ymin(y_m)) {
            if (!e.is_xmin(x_m) && !e.is_zmin(z_m)) {
                b[curr].x += 0.5*(   -dtdy*( bz*(e[y_p].z-e[curr].z) + az*(e[yz_pp].z-e[z_p].z+e[yz_pm].z-e[z_m].z) )    +   dtdz*( by*(e[z_p].y-e[curr].y) + ay*(e[yz_pp].y-e[y_p].y+e[yz_mp].y-e[y_m].y) )  );
                b[curr].z += 0.5*(    dtdy*( bx*(e[y_p].x-e[curr].x) + ax*(e[xy_pp].x-e[x_p].x+e[xy_mp].x-e[x_m].x) )    -   dtdx*( by*(e[x_p].y-e[curr].y) + ay*(e[xy_pp].y-e[y_p].y+e[xy_pm].y-e[y_m].y) )  );
            }
        } else if (e.is_zmin(z_m)) {
            if (!e.is_xmin(x_m) && !e.is_ymin(y_m)) {
                b[curr].x += 0.5*(   -dtdy*( bz*(e[y_p].z-e[curr].z) + az*(e[yz_pp].z-e[z_p].z+e[yz_pm].z-e[z_m].z) )    +   dtdz*( by*(e[z_p].y-e[curr].y) + ay*(e[yz_pp].y-e[y_p].y+e[yz_mp].y-e[y_m].y) )  );
                b[curr].y += 0.5*(    dtdx*( bz*(e[x_p].z-e[curr].z) + az*(e[xz_pp].z-e[z_p].z+e[xz_pm].z-e[z_m].z) )    -   dtdz*( bx*(e[z_p].x-e[curr].x) + ax*(e[xz_pp].x-e[x_p].x+e[xz_mp].x-e[x_m].x) )  );
            }
        } else {
            b[curr].x += 0.5*(   -dtdy*( bz*(e[y_p].z-e[curr].z) + az*(e[yz_pp].z-e[z_p].z+e[yz_pm].z-e[z_m].z) )    +   dtdz*( by*(e[z_p].y-e[curr].y) + ay*(e[yz_pp].y-e[y_p].y+e[yz_mp].y-e[y_m].y) )  );
            b[curr].y += 0.5*(    dtdx*( bz*(e[x_p].z-e[curr].z) + az*(e[xz_pp].z-e[z_p].z+e[xz_pm].z-e[z_m].z) )    -   dtdz*( bx*(e[z_p].x-e[curr].x) + ax*(e[xz_pp].x-e[x_p].x+e[xz_mp].x-e[x_m].x) )  );
            b[curr].z += 0.5*(    dtdy*( bx*(e[y_p].x-e[curr].x) + ax*(e[xy_pp].x-e[x_p].x+e[xy_mp].x-e[x_m].x) )    -   dtdx*( by*(e[x_p].y-e[curr].y) + ay*(e[xy_pp].y-e[y_p].y+e[xy_pm].y-e[y_m].y) )  );
        }
    }
}

template <typename T>
inline void advance_b_point(const T & e, T & b, int i, int j, int k, int i_prev, int j_prev, int k_prev, int i_next, int j_next, int k_next) {
    b(i,j,k).x += 0.5*(   -dtdy*( bz*(e(i,j_next,k).z-e(i,j,k).z) + az*(e(i,j_next,k_next).z-e(i,j,k_next).z+e(i,j_next,k_prev).z-e(i,j,k_prev).z) )    +   dtdz*( by*(e(i,j,k_next).y-e(i,j,k).y) + ay*(e(i,j_next,k_next).y-e(i,j_next,k).y+e(i,j_prev,k_next).y-e(i,j_prev,k).y) )  );
    b(i,j,k).y += 0.5*(   dtdx*( bz*(e(i_next,j,k).z-e(i,j,k).z) + az*(e(i_next,j,k_next).z-e(i,j,k_next).z+e(i_next,j,k_prev).z-e(i,j,k_prev).z) )    -   dtdz*( bx*(e(i,j,k_next).x-e(i,j,k).x) + ax*(e(i_next,j,k_next).x-e(i_next,j,k).x+e(i_prev,j,k_next).x-e(i_prev,j,k).x) )  );
    b(i,j,k).z += 0.5*(   dtdy*( bx*(e(i,j_next,k).x-e(i,j,k).x) + ax*(e(i_next,j_next,k).x-e(i_next,j,k).x+e(i_prev,j_next,k).x-e(i_prev,j,k).x) )    -   dtdx*( by*(e(i_next,j,k).y-e(i,j,k).y) + ay*(e(i_next,j_next,k).y-e(i,j_next,k).y+e(i_next,j_prev,k).y-e(i,j_prev,k).y) )  );
}

template <typename T>
void advance_b_periodic(const T & e, T & b) {
    const int n = e.get_n();

    for(int i=0;i<n;i++) {
        for(int j=0;j<n;j++) {
            for(int k=0;k<n;k++) {
                int i_prev = (i != 0 ? i-1 : n-1);
                int j_prev = (j != 0 ? j-1 : n-1);
                int k_prev = (k != 0 ? k-1 : n-1);
                int i_next = (i != n-1 ? i+1 : 0);
                int j_next = (j != n-1 ? j+1 : 0);
                int k_next = (k != n-1 ? k+1 : 0);
                advance_b_point(e, b, i, j, k, i_prev, j_prev, k_prev, i_next, j_next, k_next);
            }
        }
    }
}

template <typename T>
void advance_b_periodic2(const T & e, T & b) {
    const int n = e.get_n();

    int i = 0;
    int j = 0;
    advance_b_point(e, b, i, j, 0, n-1, n-1, n-1, i+1, j+1, 1);

    for(int k=1;k<n-1;k++) {
        advance_b_point(e, b, i, j, k, n-1, n-1, k-1, i+1, j+1, k+1);
    }

    advance_b_point(e, b, i, j, n-1, n-1, n-1, n-2, i+1, j+1, 0);

    for(int j=1;j<n-1;j++) {
        advance_b_point(e, b, i, j, 0, n-1, j-1, n-1, i+1, j+1, 1);

        for(int k=1;k<n-1;k++) {
            advance_b_point(e, b, i, j, k, n-1, j-1, k-1, i+1, j+1, k+1);
        }

        advance_b_point(e, b, i, j, n-1, n-1, j-1, n-2, i+1, j+1, 0);
    }

    j = n-1;
    advance_b_point(e, b, i, j, 0, n-1, j-1, n-1, i+1, 0, 1);

    for(int k=1;k<n-1;k++) {
        advance_b_point(e, b, i, j, k, n-1, j-1, k-1, i+1, 0, k+1);
    }

    advance_b_point(e, b, i, j, n-1, n-1, j-1, n-2, i+1, 0, 0);

    for(int i=1;i<n-1;i++) {
        int j = 0;
        advance_b_point(e, b, i, j, 0, i-1, n-1, n-1, i+1, j+1, 1);

        for(int k=1;k<n-1;k++) {
            advance_b_point(e, b, i, j, k, i-1, n-1, k-1, i+1, j+1, k+1);
        }

        advance_b_point(e, b, i, j, n-1, i-1, n-1, n-2, i+1, j+1, 0);

        for(int j=1;j<n-1;j++) {
            advance_b_point(e, b, i, j, 0, i-1, j-1, n-1, i+1, j+1, 1);

            for(int k=1;k<n-1;k++) {
                advance_b_point(e, b, i, j, k, i-1, j-1, k-1, i+1, j+1, k+1);
            }

            advance_b_point(e, b, i, j, n-1, i-1, j-1, n-2, i+1, j+1, 0);
        }

        j = n-1;
        advance_b_point(e, b, i, j, 0, i-1, j-1, n-1, i+1, 0, 1);

        for(int k=1;k<n-1;k++) {
            advance_b_point(e, b, i, j, k, i-1, j-1, k-1, i+1, 0, k+1);
        }

        advance_b_point(e, b, i, j, n-1, i-1, j-1, n-2, i+1, 0, 0);
    }

    i = n-1;
    j = 0;
    advance_b_point(e, b, i, j, 0, i-1, n-1, n-1, 0, j+1, 1);

    for(int k=1;k<n-1;k++) {
        advance_b_point(e, b, i, j, k, i-1, n-1, k-1, 0, j+1, k+1);
    }

    advance_b_point(e, b, i, j, n-1, i-1, n-1, n-2, 0, j+1, 0);

    for(int j=1;j<n-1;j++) {
        advance_b_point(e, b, i, j, 0, i-1, j-1, n-1, 0, j+1, 1);

        for(int k=1;k<n-1;k++) {
            advance_b_point(e, b, i, j, k, i-1, j-1, k-1, 0, j+1, k+1);
        }

        advance_b_point(e, b, i, j, n-1, i-1, j-1, n-2, 0, j+1, 0);
    }

    j = n-1;
    advance_b_point(e, b, i, j, 0, i-1, j-1, n-1, 0, 0, 1);

    for(int k=1;k<n-1;k++) {
        advance_b_point(e, b, i, j, k, i-1, j-1, k-1, 0, 0, k+1);
    }

    advance_b_point(e, b, i, j, n-1, i-1, j-1, n-2, 0, 0, 0);
}

void advance_b_z_periodic(const morton_array<vector3d> & e, morton_array<vector3d> & b) {
    const unsigned int n = e.get_size();

    for (unsigned int curr = 0; curr < n; curr++) {
        auto x_p = e.get_x_next(curr);
        auto y_p = e.get_y_next(curr);
        auto z_p = e.get_z_next(curr);

        auto x_m = e.get_x_prev(curr);
        auto y_m = e.get_y_prev(curr);
        auto z_m = e.get_z_prev(curr);

        auto xy_pp = e.get_y_next(x_p);
        auto xy_pm = e.get_y_prev(x_p);
        auto xy_mp = e.get_y_next(x_m);

        auto xz_pp = e.get_z_next(x_p);
        auto xz_pm = e.get_z_prev(x_p);
        auto xz_mp = e.get_z_next(x_m);

        auto yz_pp = e.get_z_next(y_p);
        auto yz_pm = e.get_z_prev(y_p);
        auto yz_mp = e.get_z_next(y_m);

        b[curr].x += 0.5*(   -dtdy*( bz*(e[y_p].z-e[curr].z) + az*(e[yz_pp].z-e[z_p].z+e[yz_pm].z-e[z_m].z) )    +   dtdz*( by*(e[z_p].y-e[curr].y) + ay*(e[yz_pp].y-e[y_p].y+e[yz_mp].y-e[y_m].y) )  );
        b[curr].y += 0.5*(    dtdx*( bz*(e[x_p].z-e[curr].z) + az*(e[xz_pp].z-e[z_p].z+e[xz_pm].z-e[z_m].z) )    -   dtdz*( bx*(e[z_p].x-e[curr].x) + ax*(e[xz_pp].x-e[x_p].x+e[xz_mp].x-e[x_m].x) )  );
        b[curr].z += 0.5*(    dtdy*( bx*(e[y_p].x-e[curr].x) + ax*(e[xy_pp].x-e[x_p].x+e[xy_mp].x-e[x_m].x) )    -   dtdx*( by*(e[x_p].y-e[curr].y) + ay*(e[xy_pp].y-e[y_p].y+e[xy_pm].y-e[y_m].y) )  );

    }
}

template <typename T>
void advance_e(T & e, const T & b) {
    const int n = e.get_n();

    for(int i=2;i<n-1;i++) {
        for(int j=2;j<n-1;j++) {
            for(int k=2;k<n-1;k++) {
                e(i,j,k).x = e(i,j,k).x   +   dtdy*( bz*(b(i,j,k).z-b(i,j-1,k).z) + az*(b(i,j,k+1).z-b(i,j-1,k+1).z+b(i,j,k-1).z-b(i,j-1,k-1).z) )  -   dtdz*( by*(b(i,j,k).y-b(i,j,k-1).y) + ay*(b(i,j+1,k).y-b(i,j+1,k-1).y+b(i,j-1,k).y-b(i,j-1,k-1).y) );
                e(i,j,k).y = e(i,j,k).y   -   dtdx*( bz*(b(i,j,k).z-b(i-1,j,k).z) + az*(b(i,j,k+1).z-b(i-1,j,k+1).z+b(i,j,k-1).z-b(i-1,j,k-1).z) )  +   dtdz*( bx*(b(i,j,k).x-b(i,j,k-1).x) + ax*(b(i+1,j,k).x-b(i+1,j,k-1).x+b(i-1,j,k).x-b(i-1,j,k-1).x) );
                e(i,j,k).z = e(i,j,k).z   +   dtdx*( by*(b(i,j,k).y-b(i-1,j,k).y) + ay*(b(i,j+1,k).y-b(i-1,j+1,k).y+b(i,j-1,k).y-b(i-1,j-1,k).y) )  -   dtdy*( bx*(b(i,j,k).x-b(i,j-1,k).x) + ax*(b(i+1,j,k).x-b(i+1,j-1,k).x+b(i-1,j,k).x-b(i-1,j-1,k).x) );
            }
        }
    }
    {int i=1;
        for(int j=2;j<n-1;j++) {
            for(int k=2;k<n-1;k++) {
                e(i,j,k).x = e(i,j,k).x   +   dtdy*( bz*(b(i,j,k).z-b(i,j-1,k).z) + az*(b(i,j,k+1).z-b(i,j-1,k+1).z+b(i,j,k-1).z-b(i,j-1,k-1).z) )  -   dtdz*( by*(b(i,j,k).y-b(i,j,k-1).y) + ay*(b(i,j+1,k).y-b(i,j+1,k-1).y+b(i,j-1,k).y-b(i,j-1,k-1).y) );
            }
        }
    }
    for(int i=2;i<n-1;i++) {
        {int j=1;
            for(int k=2;k<n-1;k++) {
                e(i,j,k).y = e(i,j,k).y   -   dtdx*( bz*(b(i,j,k).z-b(i-1,j,k).z) + az*(b(i,j,k+1).z-b(i-1,j,k+1).z+b(i,j,k-1).z-b(i-1,j,k-1).z) )  +   dtdz*( bx*(b(i,j,k).x-b(i,j,k-1).x) + ax*(b(i+1,j,k).x-b(i+1,j,k-1).x+b(i-1,j,k).x-b(i-1,j,k-1).x) );
            }
        }
    }
    for(int i=2;i<n-1;i++) {
        for(int j=2;j<n-1;j++) {
            {int k=1;
                e(i,j,k).z = e(i,j,k).z   +   dtdx*( by*(b(i,j,k).y-b(i-1,j,k).y) + ay*(b(i,j+1,k).y-b(i-1,j+1,k).y+b(i,j-1,k).y-b(i-1,j-1,k).y) )  -   dtdy*( bx*(b(i,j,k).x-b(i,j-1,k).x) + ax*(b(i+1,j,k).x-b(i+1,j-1,k).x+b(i-1,j,k).x-b(i-1,j-1,k).x) );
            }
        }
    }
}

void advance_e_z(morton_array<vector3d> & e, const morton_array<vector3d> & b) {
    const unsigned int n = e.get_size();

    for (unsigned int curr = 0; curr < n; curr++) {
        if (b.is_xmax(curr) || b.is_ymax(curr) || b.is_zmax(curr)) {
            continue;
        }

        if (b.is_xmin(curr) || b.is_ymin(curr) || b.is_zmin(curr)) {
            continue;
        }

        auto x_p = b.get_x_next(curr);
        auto y_p = b.get_y_next(curr);
        auto z_p = b.get_z_next(curr);

        auto x_m = b.get_x_prev(curr);
        auto y_m = b.get_y_prev(curr);
        auto z_m = b.get_z_prev(curr);

        auto xy_mm = b.get_y_prev(x_m);
        auto xy_pm = b.get_y_prev(x_p);
        auto xy_mp = b.get_y_next(x_m);

        auto xz_mm = b.get_z_prev(x_m);
        auto xz_pm = b.get_z_prev(x_p);
        auto xz_mp = b.get_z_next(x_m);

        auto yz_mm = b.get_z_prev(y_m);
        auto yz_pm = b.get_z_prev(y_p);
        auto yz_mp = b.get_z_next(y_m);

        if (b.is_xmin(x_m)) {
            if (!b.is_ymin(y_m) && !b.is_zmin(z_m)) {
                e[curr].x = e[curr].x   +   dtdy*( bz*(b[curr].z-b[y_m].z) + az*(b[z_p].z-b[yz_mp].z+b[z_m].z-b[yz_mm].z) )  -   dtdz*( by*(b[curr].y-b[z_m].y) + ay*(b[y_p].y-b[yz_pm].y+b[y_m].y-b[yz_mm].y) );
            }
        } else if (b.is_ymin(y_m)) {
            if (!b.is_xmin(x_m) && !b.is_zmin(z_m)) {
                e[curr].y = e[curr].y   -   dtdx*( bz*(b[curr].z-b[x_m].z) + az*(b[z_p].z-b[xz_mp].z+b[z_m].z-b[xz_mm].z) )  +   dtdz*( bx*(b[curr].x-b[z_m].x) + ax*(b[x_p].x-b[xz_pm].x+b[x_m].x-b[xz_mm].x) );            }
        } else if (b.is_zmin(z_m)) {
            if (!b.is_xmin(x_m) && !b.is_ymin(y_m)) {
                e[curr].z = e[curr].z   +   dtdx*( by*(b[curr].y-b[x_m].y) + ay*(b[y_p].y-b[xy_mp].y+b[y_m].y-b[xy_mm].y) )  -   dtdy*( bx*(b[curr].x-b[y_m].x) + ax*(b[x_p].x-b[xy_pm].x+b[x_m].x-b[xy_mm].x) );
            }
        } else {
            e[curr].x = e[curr].x   +   dtdy*( bz*(b[curr].z-b[y_m].z) + az*(b[z_p].z-b[yz_mp].z+b[z_m].z-b[yz_mm].z) )  -   dtdz*( by*(b[curr].y-b[z_m].y) + ay*(b[y_p].y-b[yz_pm].y+b[y_m].y-b[yz_mm].y) );
            e[curr].y = e[curr].y   -   dtdx*( bz*(b[curr].z-b[x_m].z) + az*(b[z_p].z-b[xz_mp].z+b[z_m].z-b[xz_mm].z) )  +   dtdz*( bx*(b[curr].x-b[z_m].x) + ax*(b[x_p].x-b[xz_pm].x+b[x_m].x-b[xz_mm].x) );
            e[curr].z = e[curr].z   +   dtdx*( by*(b[curr].y-b[x_m].y) + ay*(b[y_p].y-b[xy_mp].y+b[y_m].y-b[xy_mm].y) )  -   dtdy*( bx*(b[curr].x-b[y_m].x) + ax*(b[x_p].x-b[xy_pm].x+b[x_m].x-b[xy_mm].x) );
        }

    }
}

template <typename T>
inline void advance_e_point(T & e, const T & b, int i, int j, int k, int i_prev, int j_prev, int k_prev, int i_next, int j_next, int k_next) {
    e(i,j,k).x = e(i,j,k).x   +   dtdy*( bz*(b(i,j,k).z-b(i,j_prev,k).z) + az*(b(i,j,k_next).z-b(i,j_prev,k_next).z+b(i,j,k_prev).z-b(i,j_prev,k_prev).z) )  -   dtdz*( by*(b(i,j,k).y-b(i,j,k_prev).y) + ay*(b(i,j_next,k).y-b(i,j_next,k_prev).y+b(i,j_prev,k).y-b(i,j_prev,k_prev).y) );
    e(i,j,k).y = e(i,j,k).y   -   dtdx*( bz*(b(i,j,k).z-b(i_prev,j,k).z) + az*(b(i,j,k_next).z-b(i_prev,j,k_next).z+b(i,j,k_prev).z-b(i_prev,j,k_prev).z) )  +   dtdz*( bx*(b(i,j,k).x-b(i,j,k_prev).x) + ax*(b(i_next,j,k).x-b(i_next,j,k_prev).x+b(i_prev,j,k).x-b(i_prev,j,k_prev).x) );
    e(i,j,k).z = e(i,j,k).z   +   dtdx*( by*(b(i,j,k).y-b(i_prev,j,k).y) + ay*(b(i,j_next,k).y-b(i_prev,j_next,k).y+b(i,j_prev,k).y-b(i_prev,j_prev,k).y) )  -   dtdy*( bx*(b(i,j,k).x-b(i,j_prev,k).x) + ax*(b(i_next,j,k).x-b(i_next,j_prev,k).x+b(i_prev,j,k).x-b(i_prev,j_prev,k).x) );
}

template <typename T>
void advance_e_periodic(T & e, const T & b) {
    const int n = e.get_n();

    for(int i=0;i<n;i++) {
        for(int j=0;j<n;j++) {
            for(int k=0;k<n;k++) {
                int i_prev = (i != 0 ? i-1 : n-1);
                int j_prev = (j != 0 ? j-1 : n-1);
                int k_prev = (k != 0 ? k-1 : n-1);
                int i_next = (i != n-1 ? i+1 : 0);
                int j_next = (j != n-1 ? j+1 : 0);
                int k_next = (k != n-1 ? k+1 : 0);
                advance_e_point(e, b, i, j, k, i_prev, j_prev, k_prev, i_next, j_next, k_next);
            }
        }
    }
}

void advance_e_z_periodic(morton_array<vector3d> & e, const morton_array<vector3d> & b) {
    const unsigned int n = e.get_size();

    for (unsigned int curr = 0; curr < n; curr++) {
        auto x_p = b.get_x_next(curr);
        auto y_p = b.get_y_next(curr);
        auto z_p = b.get_z_next(curr);

        auto x_m = b.get_x_prev(curr);
        auto y_m = b.get_y_prev(curr);
        auto z_m = b.get_z_prev(curr);

        auto xy_mm = b.get_y_prev(x_m);
        auto xy_pm = b.get_y_prev(x_p);
        auto xy_mp = b.get_y_next(x_m);

        auto xz_mm = b.get_z_prev(x_m);
        auto xz_pm = b.get_z_prev(x_p);
        auto xz_mp = b.get_z_next(x_m);

        auto yz_mm = b.get_z_prev(y_m);
        auto yz_pm = b.get_z_prev(y_p);
        auto yz_mp = b.get_z_next(y_m);

        e[curr].x = e[curr].x   +   dtdy*( bz*(b[curr].z-b[y_m].z) + az*(b[z_p].z-b[yz_mp].z+b[z_m].z-b[yz_mm].z) )  -   dtdz*( by*(b[curr].y-b[z_m].y) + ay*(b[y_p].y-b[yz_pm].y+b[y_m].y-b[yz_mm].y) );
        e[curr].y = e[curr].y   -   dtdx*( bz*(b[curr].z-b[x_m].z) + az*(b[z_p].z-b[xz_mp].z+b[z_m].z-b[xz_mm].z) )  +   dtdz*( bx*(b[curr].x-b[z_m].x) + ax*(b[x_p].x-b[xz_pm].x+b[x_m].x-b[xz_mm].x) );
        e[curr].z = e[curr].z   +   dtdx*( by*(b[curr].y-b[x_m].y) + ay*(b[y_p].y-b[xy_mp].y+b[y_m].y-b[xy_mm].y) )  -   dtdy*( bx*(b[curr].x-b[y_m].x) + ax*(b[x_p].x-b[xy_pm].x+b[x_m].x-b[xy_mm].x) );
    }
}

template <typename T>
void advance(T & e, T & b) {
    advance_b(e, b);
    advance_e(e, b);
    advance_b(e, b);
}

void advance_z(morton_array<vector3d> & e, morton_array<vector3d> & b) {
    advance_b_z(e, b);
    advance_e_z(e, b);
    advance_b_z(e, b);
}

template <typename T>
void advance_periodic(T & e, T & b) {
    advance_b_periodic(e, b);
    advance_e_periodic(e, b);
    advance_b_periodic(e, b);
}

void advance_z_periodic(morton_array<vector3d> & e, morton_array<vector3d> & b) {
    advance_b_z_periodic(e, b);
    advance_e_z_periodic(e, b);
    advance_b_z_periodic(e, b);
}

template <typename T>
void run_test(std::function<void(T&, T&)> func, const std::string & testname, int size, int iterations=10) {
    T a(size);
    T b(size);
    vector<double> times(iterations);
    for (int i = 0; i < iterations; i++) {
        randomize(a);
        randomize(b);
        MPI_Barrier(MPI_COMM_WORLD);
        chrono::steady_clock::time_point begin = chrono::steady_clock::now();
        func(a, b);
        MPI_Barrier(MPI_COMM_WORLD);
        chrono::steady_clock::time_point end = chrono::steady_clock::now();
        times[i] = chrono::duration_cast<chrono::nanoseconds>(end - begin).count() / 1e6;
    }
    if (mpi_rank == 0) {
        sort(times.begin(), times.end());
        times.pop_back();
        double avg = accumulate(times.begin(), times.end(), 0.0) / times.size();
        double avg_sq = inner_product(times.begin(), times.end(), times.begin(), 0.0) / times.size();
        double standard_deviation = sqrt(avg_sq - avg * avg);
        double throughput = (2 * static_cast<double>(mpi_size) * size * size * size * sizeof(vector3d)) / GB * 1e3 / avg; // Gb / s
        cout << boost::format("%15s ") % testname << boost::format("%9.3f ms") % avg
                << boost::format(" (+-%7.3f ms)") % standard_deviation << boost::format(" %5.2f Gb/s") % throughput
                << endl;
    }
}

template <typename T, typename V>
bool is_equal(T & a, V & b) {
    int n = a.get_n();
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            for (int k = 0; k < n; k++) {
                if (std::fabs(b(i, j, k).x - a(i, j, k).x) > 1e-6) return false;
                if (std::fabs(b(i, j, k).y - a(i, j, k).y) > 1e-6) return false;
                if (std::fabs(b(i, j, k).z - a(i, j, k).z) > 1e-6) return false;
            }
        }
    }
    return true;
}

template <typename T>
void print_array(const T& a) {
    int n = a.get_n();
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            for (int k = 0; k < n; k++) {
                cout << boost::format("[%6.2f,%6.2f,%6.2f]") % a(i, j, k).x % a(i, j, k).y % a(i, j, k).z;
            }
            cout << endl;
        }
        cout << endl;
    }
}

void run_checks(int size) {
    cout << "Checking size " << size << "..." << endl;

    // vector3d checks

    morton_array<vector3d> e1(size);
    morton_array<vector3d> e2(size);
    morton_array<vector3d> b1(size);
    morton_array<vector3d> b2(size);

    randomize(e1);
    e2 = e1;
    randomize(b1);
    b2 = b1;

    advance_b(e1, b1);
    advance_b_z(e2, b2);

    if (!is_equal(b1, b2)) cout << "advance_b_z is different" << endl;

    randomize(e1);
    e2 = e1;
    randomize(b1);
    b2 = b1;

    advance_e(e1, b1);
    advance_e_z(e2, b2);

    if (!is_equal(e1, e2)) cout << "advance_e_z is different" << endl;

    randomize(e1);
    e2 = e1;
    randomize(b1);
    b2 = b1;

    advance(e1, b1);
    advance_z(e2, b2);

    if (!is_equal(e1, e2) || !is_equal(b1, b2)) cout << "advance_z is different" << endl;

    randomize(e1);
    e2 = e1;
    randomize(b1);
    b2 = b1;

    advance_b_periodic(e1, b1);
    advance_b_z_periodic(e2, b2);

    if (!is_equal(b1, b2)) cout << "advance_b_z_periodic is different" << endl;

    randomize(e1);
    e2 = e1;
    randomize(b1);
    b2 = b1;

    advance_e_periodic(e1, b1);
    advance_e_z_periodic(e2, b2);

    if (!is_equal(e1, e2)) cout << "advance_e_z_periodic is different" << endl;

    randomize(e1);
    e2 = e1;
    randomize(b1);
    b2 = b1;

    advance_periodic(e1, b1);
    advance_z_periodic(e2, b2);

    if (!is_equal(e1, e2) || !is_equal(b1, b2)) cout << "advance_z_periodic is different" << endl;
}

int main(int argc, char **argv) {
    dt = 0.01;
    double dx = 0.05;
    double dy = 0.05;
    double dz = 0.05;

    dtdx = dt / dx;
    dtdy = dt / dy;
    dtdz = dt / dz;

    by = 1 - kappa * dx * dx / (dy * dy);
    bz = 1 - kappa * dx * dx / (dz * dz);
    ay = 0.5 * (1 - by);
    az = 0.5 * (1 - bz);

    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
    MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);

    re.seed(chrono::system_clock::now().time_since_epoch().count());

    const int iterations = 6;

    vector<int> sizes = {32, 64, 128, 256, 512};

    if (argc > 1) {
        sizes.erase(sizes.begin(), sizes.end());
        for (int i = 1; i < argc; i++) {
            sizes.push_back(atoi(argv[i]));
        }
    }

    if (mpi_rank == 0) {
        cout << "Sizes:";
        for (auto size : sizes) {
            cout << " " << size;
        }
        cout << endl;
    }

    if (mpi_rank == 0) {
        for (auto size : sizes) {
            run_checks(size);
        }
    }

    for (auto size : sizes) {
        if (mpi_rank == 0) {
            cout << "Size " << size << endl;
            cout << endl;
        }

        run_test<simple_array<vector3d>>(advance_b<simple_array<vector3d>>, "simple(b)", size, iterations);
        run_test<cached_array<vector3d>>(advance_b<cached_array<vector3d>>, "cached(b)", size, iterations);
        run_test<morton_array<vector3d>>(advance_b<morton_array<vector3d>>, "morton_bad(b)", size, iterations);
        run_test<morton_array<vector3d>>(advance_b_z, "morton(b)", size, iterations);

        run_test<simple_array<vector3d>>(advance_e<simple_array<vector3d>>, "simple(e)", size, iterations);
        run_test<cached_array<vector3d>>(advance_e<cached_array<vector3d>>, "cached(e)", size, iterations);
        run_test<morton_array<vector3d>>(advance_e<morton_array<vector3d>>, "morton_bad(e)", size, iterations);
        run_test<morton_array<vector3d>>(advance_e_z, "morton(e)", size, iterations);

        run_test<simple_array<vector3d>>(advance<simple_array<vector3d>>, "simple", size, iterations);
        run_test<cached_array<vector3d>>(advance<cached_array<vector3d>>, "cached", size, iterations);
        run_test<morton_array<vector3d>>(advance<morton_array<vector3d>>, "morton_bad", size, iterations);
        run_test<morton_array<vector3d>>(advance_z, "morton", size, iterations);

        run_test<simple_array<vector3d>>(advance_periodic<simple_array<vector3d>>, "simple_p", size, iterations);
        run_test<cached_array<vector3d>>(advance_periodic<cached_array<vector3d>>, "cached_p", size, iterations);
        run_test<morton_array<vector3d>>(advance_periodic<morton_array<vector3d>>, "morton_bad_p", size, iterations);
        run_test<morton_array<vector3d>>(advance_z_periodic, "morton_p", size, iterations);

    }

    MPI_Finalize();
    return 0;
}

ext: cpp


text:
/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
#include <iostream>
#include <json/json.h>

#include "DexClass.h"
#include "DexLoader.h"
#include "PassRegistry.h"
#include "RedexContext.h"
#include "Timer.h"
#include "ToolsCommon.h"

namespace {

struct Arguments {
  std::string input_ir_dir;
  std::string output_ir_dir;
  std::vector<std::string> pass_names;
  RedexOptions redex_options;
  std::string config_file;
  std::vector<std::string> s_args;
  std::vector<std::string> j_args;
};

Arguments parse_args(int argc, char* argv[]) {
  namespace po = boost::program_options;
  po::options_description desc(
      "Run one pass with dex and IR meta as input and output");
  desc.add_options()("help,h", "produce help message");
  desc.add_options()("input-ir,i", po::value<std::string>(),
                     "input dex and IR meta directory");
  desc.add_options()("output-ir,o",
                     po::value<std::string>(),
                     "output dex and IR meta directory");
  desc.add_options()("pass-name,p", po::value<std::vector<std::string>>(),
                     "pass name");
  desc.add_options()("config,c",
                     po::value<std::string>(),
                     "A JSON-formatted config file to replace the one from "
                     "{input-ir}/entry.json");
  desc.add_options()(",S",
                     po::value<std::vector<std::string>>(), // Accumulation
                     "-Skey=string\n"
                     "  \tAdd a string value to the global config, overwriting "
                     "the existing value if any\n"
                     "    \te.g. -Smy_param_name=foo\n"
                     "-Spass_name.key=string\n"
                     "  \tAdd a string value to a pass"
                     "config, overwriting the existing value if any\n"
                     "    \te.g. -SMyPass.config=\"foo bar\"");
  desc.add_options()(
      ",J",
      po::value<std::vector<std::string>>(), // Accumulation
      "-Jkey=<json value>\n"
      "  \tAdd a json value to the global config, overwriting the existing "
      "value if any\n"
      "    \te.g. -Jmy_param_name={\"foo\": true}\n"
      "-JSomePassName.key=<json value>\n"
      "  \tAdd a json value to a pass config, overwriting the existing value "
      "if any\n"
      "    \te.g. -JMyPass.config=[1, 2, 3]\n"
      "Note: Be careful to properly escape JSON parameters, e.g., strings must "
      "be quoted.");

  po::variables_map vm;
  po::store(po::parse_command_line(argc, argv, desc), vm);
  po::notify(vm);

  if (vm.count("help")) {
    desc.print(std::cout);
    exit(EXIT_SUCCESS);
  }

  Arguments args;

  if (vm.count("input-ir")) {
    args.input_ir_dir = vm["input-ir"].as<std::string>();
  }

  if (vm.count("output-ir")) {
    args.output_ir_dir = vm["output-ir"].as<std::string>();
  }
  if (args.output_ir_dir.empty()) {
    std::cerr << "output-dir is empty\n";
    exit(EXIT_FAILURE);
  }
  std::string meta_dir = args.output_ir_dir + "/meta";
  boost::filesystem::create_directories(meta_dir);
  if (!boost::filesystem::is_directory(meta_dir)) {
    std::cerr << "Could not create " << meta_dir << std::endl;
    exit(EXIT_FAILURE);
  }

  if (vm.count("pass-name")) {
    args.pass_names = vm["pass-name"].as<std::vector<std::string>>();
  }

  if (vm.count("config")) {
    args.config_file = vm["config"].as<std::string>();
  }

  if (vm.count("-S")) {
    args.s_args = vm["-S"].as<std::vector<std::string>>();
  }
  if (vm.count("-J")) {
    args.j_args = vm["-J"].as<std::vector<std::string>>();
  }

  return args;
}

Json::Value parse_json_value(const std::string& value_string) {
  std::istringstream temp_stream(value_string);
  Json::Value temp_json;
  temp_stream >> temp_json;
  return temp_json;
}

bool add_value_to_config(Json::Value& config,
                         const std::string& key_value,
                         bool is_json) {
  const size_t equals_idx = key_value.find('=');
  if (equals_idx == std::string::npos) {
    return false;
  }

  const size_t dot_idx = key_value.find('.');
  if (dot_idx != std::string::npos && dot_idx < equals_idx) {
    // Pass-specific config value specified with -Dpassname.key=value
    std::string pass = key_value.substr(0, dot_idx);
    std::string key = key_value.substr(dot_idx + 1, equals_idx - dot_idx - 1);
    std::string value_string = key_value.substr(equals_idx + 1);
    if (is_json) {
      config[pass][key] = parse_json_value(value_string);
    } else {
      config[pass][key] = value_string;
    }
  } else {
    // Global config value specified with -Dkey=value
    std::string key = key_value.substr(0, equals_idx);
    std::string value_string = key_value.substr(equals_idx + 1);
    if (is_json) {
      config[key] = parse_json_value(value_string);
    } else {
      config[key] = value_string;
    }
  }
  return true;
}

/**
 * Load config file and change the passes list.
 * entry_data.json is a json file in the following format:
 * - apk_dir
 * - dex_list
 * - redex_options
 * - config
 * - jars
 */
Json::Value process_entry_data(const Json::Value& entry_data,
                               const Arguments& args) {
  Json::Value config_data =
      redex::parse_config(entry_data["config"].asString());
  // Change passes list in config data.
  config_data["redex"]["passes"] = Json::arrayValue;
  Json::Value& passes_list = config_data["redex"]["passes"];
  for (const std::string& pass_name : args.pass_names) {
    passes_list.append(pass_name);
  }
  int len = config_data["redex"]["passes"].size();
  if (len == 0 || passes_list[len - 1].asString() != "RegAllocPass") {
    passes_list.append("RegAllocPass");
  }

  // apk_dir
  if (entry_data.isMember("apk_dir")) {
    config_data["apk_dir"] = entry_data["apk_dir"].asString();
  }

  // Include -S and -J params.
  for (auto& key_value : args.s_args) {
    if (!add_value_to_config(config_data, key_value, false)) {
      std::cerr << "warning: cannot parse -S" << key_value << std::endl;
    }
  }
  for (auto& key_value : args.j_args) {
    if (!add_value_to_config(config_data, key_value, true)) {
      std::cerr << "warning: cannot parse -S" << key_value << std::endl;
    }
  }

  return config_data;
}
} // namespace

int main(int argc, char* argv[]) {
  Timer opt_timer("Redex-opt");
  Arguments args = parse_args(argc, argv);

  g_redex = new RedexContext();

  Json::Value entry_data;

  DexStoresVector stores;

  redex::load_all_intermediate(args.input_ir_dir, stores, &entry_data);

  // Set input dex magic to the first DexStore from the first dex file
  if (!stores.empty()) {
    auto first_dex_path = boost::filesystem::path(args.input_ir_dir) /
                          entry_data["dex_list"][0]["list"][0].asString();
    stores[0].set_dex_magic(load_dex_magic_from_dex(first_dex_path.c_str()));
  }

  if (!args.config_file.empty()) {
    entry_data["config"] = args.config_file;
  }

  args.redex_options.deserialize(entry_data);

  Json::Value config_data = process_entry_data(entry_data, args);
  ConfigFiles conf(config_data, args.output_ir_dir);

  const auto& passes = PassRegistry::get().get_passes();
  PassManager manager(passes, config_data, args.redex_options);
  manager.set_testing_mode();
  manager.run_passes(stores, conf);

  redex::write_all_intermediate(conf, args.output_ir_dir, args.redex_options,
                                stores, entry_data);

  delete g_redex;
  return 0;
}

max_stars_repo_name: NTillmann/redex

max_issues_repo_name: NTillmann/redex

max_forks_repo_name: NTillmann/redex


text:
/*#include "Generic/common/leak_detection.h"
#include "Temporal/features/RelationSourceFeature.h"

#include <sstream>
#include <boost/foreach.hpp>
#include <boost/functional/hash.hpp>
#include <boost/make_shared.hpp>
#include "Generic/common/SessionLogger.h"
#include "Generic/theories/SentenceTheory.h"
#include "Generic/theories/DocTheory.h"
#include "PredFinder/elf/ElfRelation.h"
#include "Temporal/TemporalInstance.h"
#include "Temporal/TemporalAttribute.h"

// Studio is over-paranoid about bounds checking for the boost string
// classification module, so we wrap its import statement with pragmas
// that tell studio to not display warnings about it.  For more info:
// <http://msdn.microsoft.com/en-us/library/ttcz0bys.aspx>
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable:4996)
# include "boost/algorithm/string/classification.hpp"
# pragma warning(pop)
#else
# include "boost/algorithm/string/classification.hpp"
#endif

using std::wstring;
using std::wstringstream;
using std::vector;
using boost::dynamic_pointer_cast;
using boost::make_shared;
using boost::algorithm::split;
using boost::is_any_of;

RelationSourceFeature::RelationSourceFeature(const std::wstring& sourceComponent,
		const Symbol& relation)
	: TemporalFeature(L"Source", relation), _sourceComponent(sourceComponent)
{ }

RelationSourceFeature_ptr RelationSourceFeature::create(
		const std::vector<std::wstring>& parts, const Symbol& relation)
{
	if (parts.empty()) {
		throw UnexpectedInputException("RelationSourceFeature::create",
				"No metadata provided.");
	}

	if (parts.size() != 1) {
		throw UnexpectedInputException("RelationSourceFeature::create",
				"Expected exactly one field of metadata");
	}

	return make_shared<RelationSourceFeature>(parts[0], relation);
}

std::wstring RelationSourceFeature::pretty() const {
	wstringstream str;
	str << L"Source(" << relation().to_string() << L", " << _sourceComponent << L")";

	return str.str();
}

std::wstring RelationSourceFeature::dump() const {
	return pretty();
}

std::wstring RelationSourceFeature::metadata() const {
	wstringstream str;

	TemporalFeature::metadata(str);
	str << L"\t" << _sourceComponent;
	return str.str();
}

bool RelationSourceFeature::equals(const TemporalFeature_ptr& other) const {
	if (!topEquals(other)) {
		return false;
	}

	if (RelationSourceFeature_ptr rsf =
			dynamic_pointer_cast<RelationSourceFeature>(other)) {
		return _sourceComponent == rsf->_sourceComponent;
	}
	return false;
}

size_t RelationSourceFeature::calcHash() const {
	size_t ret = topHash();
	boost::hash_combine(ret, _sourceComponent);
	return ret;
}

bool RelationSourceFeature::matches(TemporalInstance_ptr inst,
		const DocTheory* dt, unsigned int sn) const
{
	if (!relationNameMatches(inst)) {
		return false;
	}

	if (inst->provenance) {
		BOOST_FOREACH(const wstring& provComp, *inst->provenance) {
			if (provComp == _sourceComponent) {
				return true;
			}
		}
	}

	return false;
}

void RelationSourceFeature::addFeaturesToInstance(const TemporalInstance& inst,
		std::vector<TemporalFeature_ptr>& fv)
{
	if (inst.provenance) {
		BOOST_FOREACH(std::wstring& part, *inst.provenance) {
			fv.push_back(make_shared<RelationSourceFeature>(
							part, inst.relation()->get_name()));
		}
	}
}
*/

max_stars_repo_name: BBN-E/serif

max_issues_repo_name: BBN-E/serif

max_forks_repo_name: BBN-E/serif


text:
/*
  Copyright 2018 Tenable, Inc.                                                                                *

  Redistribution and use in source and binary forms, with or without modification,
  are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this
     list of conditions and the following disclaimer.

  2. Redistributions in binary form must reproduce the above copyright notice,
     this list of conditions and the following disclaimer in the documentation
     and/or other materials provided with the distribution.

  3. Neither the name of the copyright holder nor the names of its contributors
     may be used to endorse or promote products derived from this software
     without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef WINBOX_MESSAGE_HPP
#define WINBOX_MESSAGE_HPP

#include <map>
#include <vector>
#include <string>
#include <boost/array.hpp>
#include <boost/cstdint.hpp>

/*!
 * \brief An implementation of the RouterOS nv::Message.
 *
 * This object represents the RouterOS nv::Message. It can parse in a message in
 * JSON format (webfig) or in the binary format (webfig and winbox). It can
 * also serialize the message into the binary format as well as the JSON format
 * (although the JSON version is not perfect).
 */
class WinboxMessage
{
public:

    /*!
     * Default constructor
     */
    WinboxMessage();

    /*!
     * Default deconstructor
     */
    ~WinboxMessage();

    /*!
     * Clears all the member variables.
     * Effecitvely returns the object to the default constructor state.
     */
    void reset();

    /*!
     * Converts the object into a binary format for network communication.
     *
     * \return the binary representation of the data
     */
    std::string serialize_to_binary() const;

    /*!
     * Converts the object into a JSON format for network communication.
     *
     * \return the binary representation of the data
     */
    std::string serialize_to_json() const;

    /*!
     * Parses a binary WinboxMessage
     * Parses the provided data and stores the results in member variables.
     *
     * \note This is vulnerable to a stack overflow due to recusion within
     *       message variables. The irony is that I reported that exact bug
     *       to Mikrotik. However, I currently have no plans to alter the
     *       implementation.
     *
     * \param[in] p_input the data to convert into a WinboxMessage
     * \return true if successful and false otherwise
     */
    bool parse_binary(const std::string& p_input);

    /*!
     * Parses a JSON WinboxMessage
     * Parses the provided data and stores the results in member variables.
     *
     * \note This JSON parser has some serious shortcomings due to its
     *       complete reliance on regular expressions to parse data.
     *       I've justified this by first accepting that the JSON format of the
     *       nv::Message seems little used by modern RouterOS. Also the JSON
     *       isn't even well formed. So please excuse that this isn't a fool
     *       proof implementation
     *
     * \param[in] p_input the data to convert into a WinboxMessage
     * \return true if successful and false otherwise
     */
    bool parse_json(const std::string& p_input);

    /*!
     * Returns true if an error parameter is present
     *
     * \return true if an error is present. false otherwise.
     */
    bool has_error() const;

    /*!
     * Returns the provided error message or builtin error message corresponding
     * to the error number.
     *
     * \return a string indicating the error
     */
    std::string get_error_string() const;

    /*!
     * Returns the session ID.
     *
     * \return the session ID
     */
    boost::uint32_t get_session_id() const;

    /*!
     * Returns the value of a boolean variable.
     *
     * \param[in] p_name the name of the variable (ie. 0xff0007)
     * \return the stored value for the provided variable
     */
    bool get_boolean(boost::uint32_t p_name) const;

    /*!
     * Returns the value of a 32 bit variable.
     *
     * \param[in] p_name the name of the variable (ie. 0xff0007)
     * \return the stored value for the provided variable
     */
    boost::uint32_t get_u32(boost::uint32_t p_name) const;

    /*!
     * Returns the value of a 64 bit variable.
     *
     * \param[in] p_name the name of the variable (ie. 0xff0007)
     * \return the stored value for the provided variable
     */
    boost::uint64_t get_u64(boost::uint32_t p_name) const;

    /*!
     * Returns the value of an IPv6 variable.
     *
     * \param[in] p_name the name of the variable (ie. 0xff0007)
     * \return the stored value for the provided variable
     */
    boost::array<unsigned char, 16> get_ip6(boost::uint32_t p_name) const;

    /*!
     * Returns the value of a string variable.
     *
     * \param[in] p_name the name of the variable (ie. 0xff0007)
     * \return the stored value for the provided variable
     */
    std::string get_string(boost::uint32_t p_name) const;

    /*!
     * Returns the value of a message variable.
     *
     * \param[in] p_name the name of the variable (ie. 0xff0007)
     * \return the stored value for the provided variable
     */
    WinboxMessage get_msg(boost::uint32_t p_name) const;

    /*!
     * Returns the value of a raw variable.
     *
     * \param[in] p_name the name of the variable (ie. 0xff0007)
     * \return the stored value for the provided variable
     */
    std::string get_raw(boost::uint32_t p_name) const;

    /*!
     * Returns the value of a boolean array variable.
     *
     * \param[in] p_name the name of the variable (ie. 0xff0007)
     * \return the stored value for the provided variable
     */
    std::vector<bool> get_boolean_array(boost::uint32_t p_name) const;

    /*!
     * Returns the value of a 32 bit array variable.
     *
     * \param[in] p_name the name of the variable (ie. 0xff0007)
     * \return the stored value for the provided variable
     */
    std::vector<boost::uint32_t> get_u32_array(boost::uint32_t p_name) const;

    /*!
     * Returns the value of a 64 bit array variable.
     *
     * \param[in] p_name the name of the variable (ie. 0xff0007)
     * \return the stored value for the provided variable
     */
    std::vector<boost::uint64_t> get_u64_array(boost::uint32_t p_name) const;

    /*!
     * Returns the value of an IPv6 array variable.
     *
     * \param[in] p_name the name of the variable (ie. 0xff0007)
     * \return the stored value for the provided variable
     */
    std::vector<boost::array<unsigned char, 16> > get_ip6_array(boost::uint32_t p_name) const;

    /*!
     * Returns the value of a string array variable.
     *
     * \param[in] p_name the name of the variable (ie. 0xff0007)
     * \return the stored value for the provided variable
     */
    std::vector<std::string> get_string_array(boost::uint32_t p_name) const;

    /*!
     * Returns the value of a message array variable.
     *
     * \param[in] p_name the name of the variable (ie. 0xff0007)
     * \return the stored value for the provided variable
     */
    std::vector<WinboxMessage> get_msg_array(boost::uint32_t p_name) const;

    /*!
     * Returns the value of a raw array variable.
     *
     * \param[in] p_name the name of the variable (ie. 0xff0007)
     * \return the stored value for the provided variable
     */
    std::vector<std::string> get_raw_array(boost::uint32_t p_name) const;

    /*!
     * Sets the messages "to" variable.
     * This controls where the message will be routed to in RouterOS
     *
     * \param[in] p_to The integer representing the binary to send to
     */
    void set_to(boost::uint32_t p_to);

    /*!
     * Sets the messages "to" variable.
     * This controls where the message will be routed to in RouterOS
     *
     * \param[in] p_to The integer representing the binary to send to
     * \param[in] p_handler The registered handler that should handle this message
     */
    void set_to(boost::uint32_t p_to, boost::uint32_t p_handler);

    /*!
     * Sets the command variable to the provided value.
     *
     * \param[in] p_command the command to execute
     */
    void set_command(boost::uint32_t p_command);

    /*!
     * Sets the reply expected variable to the provided value.
     *
     * \param[in] p_reply_expected true if we expect a reply and false otherwise
     */
    void set_reply_expected(bool p_reply_expected);

    /*!
     * Sets the request ID for the message.
     * The server will include this ID in the response.
     *
     * \param[in] p_id the ID for the request.
     */
    void set_request_id(boost::uint32_t p_id);

    /*!
     * Sets the messages session ID variable.
     * The first message won't need a message ID, but every subsequent message
     * does need one. The server will respond with it in the first reply
     *
     * \param[in] p_to The integer representing the session ID
     */
    void set_session_id(boost::uint32_t p_session_id);

    /*!
     * Adds a new boolean value to the message
     *
     * \param[in] p_name the variables name (ie. 0xff0007)
     * \param[in] p_value the variable's value
     */
    void add_boolean(boost::uint32_t p_name, bool p_value);

    /*!
     * Adds a new 32 bit value to the message
     *
     * \param[in] p_name the variables name (ie. 0xff0007)
     * \param[in] p_value the variable's value
     */
    void add_u32(boost::uint32_t p_name, boost::uint32_t p_value);

    /*!
     * Adds a new 64 bit value to the message
     *
     * \param[in] p_name the variables name (ie. 0xff0007)
     * \param[in] p_value the variable's value
     */
    void add_u64(boost::uint32_t p_name, boost::uint64_t p_value);

    /*!
     * Adds a new IPv6 value to the message
     *
     * \param[in] p_name the variables name (ie. 0xff0007)
     * \param[in] p_value the variable's value
     */
    void add_ip6(boost::uint32_t p_name, boost::array<unsigned char, 16> p_value);

    /*!
     * Adds a new string value to the message
     *
     * \param[in] p_name the variables name (ie. 0xff0007)
     * \param[in] p_value the variable's value
     */
    void add_string(boost::uint32_t p_name, const std::string& p_string);

    /*!
     * Adds a new message value to the message
     *
     * \param[in] p_name the variables name (ie. 0xff0007)
     * \param[in] p_value the variable's value
     */
    void add_msg(boost::uint32_t p_name, const WinboxMessage& p_msg);

    /*!
     * Adds a new raw value to the message
     *
     * \param[in] p_name the variables name (ie. 0xff0007)
     * \param[in] p_value the variable's value
     */
    void add_raw(boost::uint32_t p_name, const std::string& p_raw);

    /*!
     * Adds a new boolean array to the message
     *
     * \param[in] p_name the variables name (ie. 0xff0007)
     * \param[in] p_value the variable's value
     */
    void add_boolean_array(boost::uint32_t p_name, const std::vector<bool>& p_value);

    /*!
     * Adds a new 32 bit array to the message
     *
     * \param[in] p_name the variables name (ie. 0xff0007)
     * \param[in] p_value the variable's value
     */
    void add_u32_array(boost::uint32_t p_name, const std::vector<boost::uint32_t>& p_value);

    /*!
     * Adds a new 64 bit array to the message
     *
     * \param[in] p_name the variables name (ie. 0xff0007)
     * \param[in] p_value the variable's value
     */
    void add_u64_array(boost::uint32_t p_name, const std::vector<boost::uint64_t>& p_value);

    /*!
     * Adds a new IPv6 array to the message
     *
     * \param[in] p_name the variables name (ie. 0xff0007)
     * \param[in] p_value the variable's value
     */
    void add_ip6_array(boost::uint32_t p_name, const std::vector<boost::array<unsigned char, 16> >& p_value);

    /*!
     * Adds a new string array to the message
     *
     * \param[in] p_name the variables name (ie. 0xff0007)
     * \param[in] p_value the variable's value
     */
    void add_string_array(boost::uint32_t p_name, const std::vector<std::string>& p_value);

    /*!
     * Adds a new message array to the message
     *
     * \param[in] p_name the variables name (ie. 0xff0007)
     * \param[in] p_value the variable's value
     */
    void add_msg_array(boost::uint32_t p_name, const std::vector<WinboxMessage>& p_value);

    /*!
     * Adds a new raw array to the message
     *
     * \param[in] p_name the variables name (ie. 0xff0007)
     * \param[in] p_value the variable's value
     */
    void add_raw_array(boost::uint32_t p_name, const std::vector<std::string>& p_value);

    void erase_u32(boost::uint32_t p_name);

private:

    //! The boolean variable mapping
    std::map<boost::uint32_t, bool> m_bools;

    //! The 32 bit integer variable mapping
    std::map<boost::uint32_t, boost::uint32_t> m_u32s;

    //! The 64 bit integer variable mapping
    std::map<boost::uint32_t, boost::uint64_t> m_u64s;

    //! The IPv6 variable mapping
    std::map<boost::uint32_t, boost::array<unsigned char, 16> > m_ip6s;

    //! The strings variable mapping
    std::map<boost::uint32_t, std::string> m_strings;

    //! The message variable mapping
    std::map<boost::uint32_t, WinboxMessage> m_msgs;

    //! The raw variable mapping
    std::map<boost::uint32_t, std::string> m_raw;

    //! The bool array variable mapping
    std::map<boost::uint32_t, std::vector<bool> > m_bool_array;

    //! The 32 bit integer array variable mapping
    std::map<boost::uint32_t, std::vector<boost::uint32_t> > m_u32_array;

    //! The 64 bit integer array variable mapping
    std::map<boost::uint32_t, std::vector<boost::uint64_t> > m_u64_array;

    //! The IPv6 array variable mapping
    std::map<boost::uint32_t, std::vector<boost::array<unsigned char, 16> > > m_ip6_array;

    //! The string array variable mapping
    std::map<boost::uint32_t, std::vector<std::string> > m_string_array;

    //! The message array variable mapping
    std::map<boost::uint32_t, std::vector<WinboxMessage> > m_msg_array;

    //! The raw array variable mapping
    std::map<boost::uint32_t, std::vector<std::string> > m_raw_array;
};

#endif

max_stars_repo_name: Bram-Wel/routeros

max_issues_repo_name: Bram-Wel/routeros

max_forks_repo_name: Bram-Wel/routeros