<commit_before>/* StartingGateMission.cpp -- Implementation of StartingGateMission class

   Copyright (C) 2014 Tushar Pankaj

   This file is part of San Diego Robotics 101 Robosub.

   San Diego Robotics 101 Robosub is free software: you can redistribute it
   and/or modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation, either version 3 of the License,
   or (at your option) any later version.

   San Diego Robotics 101 Robosub is distributed in the hope that it will be
   useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
   Public License for more details.

   You should have received a copy of the GNU General Public License
   along with San Diego Robotics 101 Robosub.  If not, see
   <http://www.gnu.org/licenses/>. */

#include <iostream>
#include <string>
#include <vector>
#include <opencv2/opencv.hpp>
#include "Robot.hpp"
#include "Logger.hpp"
#include "Contour.hpp"
#include "Circle.hpp"
#include "Rectangle.hpp"
#include "ContourDetector.hpp"
#include "Mission.hpp"
#include "StartingGateMission.hpp"

 StartingGateMission::StartingGateMission(Robot * robot_ptr):Mission(robot_ptr)
{
	mission_name = "Starting Gate Mission";
}

void StartingGateMission::run()
{
	robot->get_logger()->write("Running mission " + mission_name,
				   Logger::MESSAGE);
	//cv::Mat image = cv::imread("/tmp/starting_gate.png");
	cv::Mat image;
	while (true) {
		image = robot->get_forward_camera()->get_image();
		ContourDetector::Params detector_params;
		detector_params.filter_by_hue = true;
		detector_params.min_hue = 100;
		detector_params.max_hue = 150;
		detector_params.max_canny = 50;
		detector_params.filter_with_blur = false;
		ContourDetector detector(detector_params);
		std::vector < Contour > contours = detector.detect(image);
		if (contours.empty()) {
			robot->get_logger()->write("No contours found",
						   Logger::WARNING);
			continue;
		}
		std::vector < Rectangle > filtered_rectangles =
		    filter_rectangles(contours);
		if (filtered_rectangles.empty()) {
			robot->get_logger()->
			    write("No filtered rectangles found",
				  Logger::WARNING);
			continue;
		}
		std::vector < cv::Point2f > centroids =
		    find_centroids(filtered_rectangles);
		/*for (uint i = 0; i < centroids.size(); i++)
		   cv::circle(image, centroids.at(i), 5,
		   cv::Scalar(0, 0, 0)); */
		double angular_displacement = find_angular_displacement(centroids, cv::Point2f((float)image.rows / 2.0, (float)image.cols / 2.0));
		robot->get_serial()->get_tx_packet()->set_rot_z(angular_displacement);
		robot->get_logger()->write("StartingGateMission angular displacement is " + std::to_string(angular_displacement) + " degrees", Logger::VERBOSE);
	}
}

std::vector < Circle > StartingGateMission::contours_to_circles(std::vector <
								Contour >
								contours)
{
	std::vector < Circle > circles;
	for (uint i = 0; i < contours.size(); i++)
		circles.push_back(Circle(contours.at(i).get_points()));
	return circles;
}

std::vector < Rectangle >
    StartingGateMission::contours_to_rectangles(std::vector < Contour >
						contours)
{
	std::vector < Rectangle > rectangles;
	for (uint i = 0; i < contours.size(); i++)
		rectangles.push_back(Rectangle(contours.at(i).get_points()));
	return rectangles;
}

std::vector < Rectangle > StartingGateMission::filter_rectangles(std::vector <
								 Contour >
								 detected_contours)
{
	std::vector < Circle > detected_enclosing_circles =
	    contours_to_circles(detected_contours);
	std::vector < Rectangle > detected_bounding_rectangles =
	    contours_to_rectangles(detected_contours);
	std::vector < Rectangle > filtered_rectangles;
	for (uint i = 0; i < detected_contours.size(); i++)	// Filter out circular contours and filter on aspect ratio
	{
		if (detected_bounding_rectangles.at(i).get_area_ratio() <
		    detected_enclosing_circles.at(i).get_area_ratio()
		    && detected_bounding_rectangles.at(i).get_aspect_ratio() <
		    0.2)
			filtered_rectangles.push_back
			    (detected_bounding_rectangles.at(i));
	}
	return filtered_rectangles;
}

std::vector < cv::Point2f > StartingGateMission::find_centroids(std::vector <
								Rectangle >
								rectangles)
{
	cv::Mat data = cv::Mat::zeros(rectangles.size(), 2, CV_32F);
	for (uint i = 0; i < rectangles.size(); i++) {
		data.at < float >(i, 0) = rectangles.at(i).get_center().x;
		data.at < float >(i, 1) = rectangles.at(i).get_center().y;
	}
	int K = 2;
	cv::Mat best_labels;
	cv::TermCriteria criteria =
	    cv::TermCriteria(cv::TermCriteria::COUNT, 10, 1.0);
	int attempts = 3;
	int flags = cv::KMEANS_PP_CENTERS;
	cv::Mat centroids;
	cv::kmeans(data, K, best_labels, criteria, attempts, flags, centroids);
	std::vector < cv::Point2f > centroids_vector;
	for (int i = 0; i < centroids.rows; i++)
		centroids_vector.push_back(cv::Point2f
					   (centroids.at < float >(i, 0),
					    centroids.at < float >(i, 1)));
	return centroids_vector;
}

double StartingGateMission::find_angular_displacement(std::vector <
						      cv::Point2f > centroids, cv::Point2f image_center)
{
	cv::Point2f centroids_average = cv::Point2f(0.0, 0.0);
	for (uint i = 0; i < centroids.size(); i++)
		centroids_average += centroids.at(i);
	centroids_average.x /= centroids.size();
	centroids_average.y /= centroids.size();
	return robot->get_forward_camera()->pixels_to_angle((image_center - centroids_average).x);
}
<commit_msg>Fixed incorrect rotation direction convention<commit_after>/* StartingGateMission.cpp -- Implementation of StartingGateMission class

   Copyright (C) 2014 Tushar Pankaj

   This file is part of San Diego Robotics 101 Robosub.

   San Diego Robotics 101 Robosub is free software: you can redistribute it
   and/or modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation, either version 3 of the License,
   or (at your option) any later version.

   San Diego Robotics 101 Robosub is distributed in the hope that it will be
   useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
   Public License for more details.

   You should have received a copy of the GNU General Public License
   along with San Diego Robotics 101 Robosub.  If not, see
   <http://www.gnu.org/licenses/>. */

#include <iostream>
#include <string>
#include <vector>
#include <opencv2/opencv.hpp>
#include "Robot.hpp"
#include "Logger.hpp"
#include "Contour.hpp"
#include "Circle.hpp"
#include "Rectangle.hpp"
#include "ContourDetector.hpp"
#include "Mission.hpp"
#include "StartingGateMission.hpp"

 StartingGateMission::StartingGateMission(Robot * robot_ptr):Mission(robot_ptr)
{
	mission_name = "Starting Gate Mission";
}

void StartingGateMission::run()
{
	robot->get_logger()->write("Running mission " + mission_name,
				   Logger::MESSAGE);
	//cv::Mat image = cv::imread("/tmp/starting_gate.png");
	cv::Mat image;
	while (true) {
		image = robot->get_forward_camera()->get_image();
		ContourDetector::Params detector_params;
		detector_params.filter_by_hue = true;
		detector_params.min_hue = 100;
		detector_params.max_hue = 150;
		detector_params.max_canny = 50;
		detector_params.filter_with_blur = false;
		ContourDetector detector(detector_params);
		std::vector < Contour > contours = detector.detect(image);
		if (contours.empty()) {
			robot->get_logger()->write("No contours found",
						   Logger::WARNING);
			continue;
		}
		std::vector < Rectangle > filtered_rectangles =
		    filter_rectangles(contours);
		if (filtered_rectangles.empty()) {
			robot->get_logger()->
			    write("No filtered rectangles found",
				  Logger::WARNING);
			continue;
		}
		std::vector < cv::Point2f > centroids =
		    find_centroids(filtered_rectangles);
		/*for (uint i = 0; i < centroids.size(); i++)
		   cv::circle(image, centroids.at(i), 5,
		   cv::Scalar(0, 0, 0)); */
		double angular_displacement = find_angular_displacement(centroids, cv::Point2f((float)image.rows / 2.0, (float)image.cols / 2.0));
		robot->get_serial()->get_tx_packet()->set_rot_z(angular_displacement);
		robot->get_logger()->write("StartingGateMission angular displacement is " + std::to_string(angular_displacement) + " degrees", Logger::VERBOSE);
	}
}

std::vector < Circle > StartingGateMission::contours_to_circles(std::vector <
								Contour >
								contours)
{
	std::vector < Circle > circles;
	for (uint i = 0; i < contours.size(); i++)
		circles.push_back(Circle(contours.at(i).get_points()));
	return circles;
}

std::vector < Rectangle >
    StartingGateMission::contours_to_rectangles(std::vector < Contour >
						contours)
{
	std::vector < Rectangle > rectangles;
	for (uint i = 0; i < contours.size(); i++)
		rectangles.push_back(Rectangle(contours.at(i).get_points()));
	return rectangles;
}

std::vector < Rectangle > StartingGateMission::filter_rectangles(std::vector <
								 Contour >
								 detected_contours)
{
	std::vector < Circle > detected_enclosing_circles =
	    contours_to_circles(detected_contours);
	std::vector < Rectangle > detected_bounding_rectangles =
	    contours_to_rectangles(detected_contours);
	std::vector < Rectangle > filtered_rectangles;
	for (uint i = 0; i < detected_contours.size(); i++)	// Filter out circular contours and filter on aspect ratio
	{
		if (detected_bounding_rectangles.at(i).get_area_ratio() <
		    detected_enclosing_circles.at(i).get_area_ratio()
		    && detected_bounding_rectangles.at(i).get_aspect_ratio() <
		    0.2)
			filtered_rectangles.push_back
			    (detected_bounding_rectangles.at(i));
	}
	return filtered_rectangles;
}

std::vector < cv::Point2f > StartingGateMission::find_centroids(std::vector <
								Rectangle >
								rectangles)
{
	cv::Mat data = cv::Mat::zeros(rectangles.size(), 2, CV_32F);
	for (uint i = 0; i < rectangles.size(); i++) {
		data.at < float >(i, 0) = rectangles.at(i).get_center().x;
		data.at < float >(i, 1) = rectangles.at(i).get_center().y;
	}
	int K = 2;
	cv::Mat best_labels;
	cv::TermCriteria criteria =
	    cv::TermCriteria(cv::TermCriteria::COUNT, 10, 1.0);
	int attempts = 3;
	int flags = cv::KMEANS_PP_CENTERS;
	cv::Mat centroids;
	cv::kmeans(data, K, best_labels, criteria, attempts, flags, centroids);
	std::vector < cv::Point2f > centroids_vector;
	for (int i = 0; i < centroids.rows; i++)
		centroids_vector.push_back(cv::Point2f
					   (centroids.at < float >(i, 0),
					    centroids.at < float >(i, 1)));
	return centroids_vector;
}

double StartingGateMission::find_angular_displacement(std::vector <
						      cv::Point2f > centroids, cv::Point2f image_center)
{
	cv::Point2f centroids_average = cv::Point2f(0.0, 0.0);
	for (uint i = 0; i < centroids.size(); i++)
		centroids_average += centroids.at(i);
	centroids_average.x /= centroids.size();
	centroids_average.y /= centroids.size();
	return robot->get_forward_camera()->pixels_to_angle((centroids_average = image_center).x);
}
<|endoftext|>


<commit_before>#ifndef LIBPORT_UNIT_TEST_HH
# define LIBPORT_UNIT_TEST_HH

// See documentation on:
// https://core.gostai.com/projects/common/wiki/BoostUnit

# define BOOST_TEST_DYN_LINK
# include <boost/test/unit_test.hpp>

namespace libport
{
  using boost::unit_test::test_suite;
}

// Fwd for the entry point function the user must implement
libport::test_suite*
init_test_suite();

namespace libport
{
  bool _init_test_suite()
  {
    boost::unit_test::framework::master_test_suite().add(init_test_suite());
    return true;
  }
}

int
main(int argc, char** argv)
{
  return ::boost::unit_test::unit_test_main(
    libport::_init_test_suite, argc, argv);
}

#endif
<commit_msg>Do not assume boost is dynamic.<commit_after>#ifndef LIBPORT_UNIT_TEST_HH
# define LIBPORT_UNIT_TEST_HH

// See documentation on:
// https://core.gostai.com/projects/common/wiki/BoostUnit

# ifndef BOOST_STATIC
#  define BOOST_TEST_DYN_LINK
# endif

# include <boost/config.hpp>
# include <boost/test/detail/config.hpp>
# include <boost/test/unit_test.hpp>

namespace libport
{
  using boost::unit_test::test_suite;
}

// Fwd for the entry point function the user must implement
libport::test_suite*
init_test_suite();

// FIXME: Boost unit-test has a different API depending on whether
// it's static or dynamic (the first defines main, the later doesn't).
// Boost defines BOOST_TEST_DYN_LINK to use the dynamic API, but
// unfortunately it seems it's not available for us to test and switch
// our own API accordingly. For now, we manually define BOOST_STATIC
// on architectures where boost is static. Our m4 macro should define
// it automagically.

# ifndef BOOST_STATIC

namespace libport
{
  bool _init_test_suite()
  {
    boost::unit_test::framework::master_test_suite().add(init_test_suite());
    return true;
  }
}

int
main(int argc, char** argv)
{
  return ::boost::unit_test::unit_test_main(
    libport::_init_test_suite, argc, argv);
}

# else

libport::test_suite* init_unit_test_suite(int, char**)
{
  return init_test_suite();
}

# endif

#endif
<|endoftext|>


<commit_before>#include "iteration/group/group_source_iteration.h"

#include <memory>

#include "iteration/updater/tests/source_updater_mock.h"
#include "quadrature/calculators/tests/spherical_harmonic_moments_mock.h"
#include "convergence/tests/final_checker_mock.h"
#include "solver/group/tests/single_group_solver_mock.h"
#include "system/moments/tests/spherical_harmonic_mock.h"
#include "system/solution/tests/mpi_group_angular_solution_mock.h"
#include "system/system.h"
#include "test_helpers/gmock_wrapper.h"

namespace  {

using namespace bart;

using ::testing::Return, ::testing::Pointee, ::testing::Ref;
using ::testing::Sequence, ::testing::_;

template <typename DimensionWrapper>
class IterationGroupSourceIterationTest : public ::testing::Test {
 public:
  static constexpr int dim = DimensionWrapper::value;

  using TestGroupIterator = iteration::group::GroupSourceIteration<dim>;
  using GroupSolver = solver::group::SingleGroupSolverMock;
  using ConvergenceChecker = convergence::FinalCheckerMock<system::moments::MomentVector>;
  using MomentCalculator = quadrature::calculators::SphericalHarmonicMomentsMock<dim>;
  using GroupSolution = system::solution::MPIGroupAngularSolutionMock;
  using SourceUpdater = iteration::updater::SourceUpdaterMock;
  using Moments = system::moments::SphericalHarmonicMock;

  // Test object
  std::unique_ptr<TestGroupIterator> test_iterator_ptr_;

  // Mock dependency objects
  std::unique_ptr<GroupSolver> single_group_solver_ptr_;
  std::unique_ptr<ConvergenceChecker> convergence_checker_ptr_;
  std::unique_ptr<MomentCalculator> moment_calculator_ptr_;
  std::shared_ptr<GroupSolution> group_solution_ptr_;
  std::unique_ptr<SourceUpdater> source_updater_ptr_;

  // Supporting objects
  system::System test_system;

  // Observing pointers
  GroupSolver* single_group_obs_ptr_ = nullptr;
  ConvergenceChecker* convergence_checker_obs_ptr_ = nullptr;
  MomentCalculator* moment_calculator_obs_ptr_ = nullptr;
  SourceUpdater* source_updater_obs_ptr_ = nullptr;
  Moments* moments_obs_ptr_ = nullptr;

  // Test parameters
  const int total_groups = 2;
  const std::array<int, 2> iterations_by_group{2,3};

  void SetUp() override;
};

TYPED_TEST_CASE(IterationGroupSourceIterationTest, bart::testing::AllDimensions);

template <typename DimensionWrapper>
void IterationGroupSourceIterationTest<DimensionWrapper>::SetUp() {
  single_group_solver_ptr_ = std::make_unique<GroupSolver>();
  single_group_obs_ptr_ = single_group_solver_ptr_.get();
  convergence_checker_ptr_ = std::make_unique<ConvergenceChecker>();
  convergence_checker_obs_ptr_ = convergence_checker_ptr_.get();
  moment_calculator_ptr_ = std::make_unique<MomentCalculator>();
  moment_calculator_obs_ptr_ = moment_calculator_ptr_.get();
  group_solution_ptr_ = std::make_shared<GroupSolution>();
  source_updater_ptr_ = std::make_unique<SourceUpdater>();
  source_updater_obs_ptr_ = source_updater_ptr_.get();

  test_system.current_moments = std::make_unique<Moments>();
  moments_obs_ptr_ = dynamic_cast<Moments*>(test_system.current_moments.get());

  test_iterator_ptr_ = std::make_unique<TestGroupIterator>(
      std::move(single_group_solver_ptr_),
      std::move(convergence_checker_ptr_),
      std::move(moment_calculator_ptr_),
      group_solution_ptr_,
      std::move(source_updater_ptr_)
      );
}

TYPED_TEST(IterationGroupSourceIterationTest, Constructor) {
  using GroupSolver = solver::group::SingleGroupSolverMock;
  using ConvergenceChecker = convergence::FinalCheckerMock<system::moments::MomentVector>;
  using MomentCalculator = quadrature::calculators::SphericalHarmonicMomentsMock<this->dim>;
  using SourceUpdater = iteration::updater::SourceUpdaterMock;

  auto single_group_test_ptr = dynamic_cast<GroupSolver*>(
      this->test_iterator_ptr_->group_solver_ptr());
  auto convergence_checker_test_ptr = dynamic_cast<ConvergenceChecker*>(
      this->test_iterator_ptr_->convergence_checker_ptr());
  auto moment_calculator_test_ptr = dynamic_cast<MomentCalculator*>(
      this->test_iterator_ptr_->moment_calculator_ptr());
  auto source_updater_test_ptr = dynamic_cast<SourceUpdater*>(
      this->test_iterator_ptr_->source_updater_ptr());

  EXPECT_NE(nullptr, single_group_test_ptr);
  EXPECT_NE(nullptr, convergence_checker_test_ptr);
  EXPECT_NE(nullptr, moment_calculator_test_ptr);
  EXPECT_EQ(2, this->group_solution_ptr_.use_count());
  EXPECT_EQ(this->group_solution_ptr_.get(),
            this->test_iterator_ptr_->group_solution_ptr().get());
  EXPECT_NE(nullptr, source_updater_test_ptr);
}

TYPED_TEST(IterationGroupSourceIterationTest, Iterate) {

  // Objects to support testing
  /* Moment Vectors. These will be returned by the MomentCalculator, based on
   * group and iteration. It is important to ensure that the correct values
   * are being checked for convergence. All entries in each vector will be set
   * to a unique value, 10*group + iteration. */
  std::map<int, std::vector<system::moments::MomentVector>> calculated_moments;
  system::moments::MomentVector zero_moment(5);

  for (int group = 0; group < this->total_groups; ++group) {
    calculated_moments[group] = {};
    for (int it = 0; it < this->iterations_by_group[group]; ++it) {
      system::moments::MomentVector new_moment(5);
      new_moment = (group * 10 + it);
      calculated_moments.at(group).push_back(new_moment);
    }
  }

  EXPECT_CALL(*this->moments_obs_ptr_, total_groups())
      .WillOnce(Return(this->total_groups));

  Sequence s;

  for (int group = 0; group < this->total_groups; ++group) {
    EXPECT_CALL(*this->single_group_obs_ptr_, SolveGroup(
        group,
        Ref(this->test_system),
        Ref(*this->group_solution_ptr_)))
        .Times(this->iterations_by_group[group]);

    for (int it = 0; it < this->iterations_by_group[group]; ++it) {

      EXPECT_CALL(*this->moment_calculator_obs_ptr_, CalculateMoment(
          this->group_solution_ptr_.get(), group, 0, 0))
          //_, group, 0, 0))
          .InSequence(s)
          .WillOnce(Return(calculated_moments.at(group).at(it)));

      convergence::Status status;

      if ((it + 1) == this->iterations_by_group[group])
        status.is_complete = true;

      status.iteration_number = it + 1;

      if (it == 0) {
        EXPECT_CALL(*this->convergence_checker_obs_ptr_, CheckFinalConvergence(
            calculated_moments.at(group).at(it),
            zero_moment))
            .InSequence(s)
            .WillOnce(Return(status));
      } else {
        EXPECT_CALL(*this->convergence_checker_obs_ptr_, CheckFinalConvergence(
            calculated_moments.at(group).at(it),
            calculated_moments.at(group).at(it - 1)))
            .InSequence(s)
            .WillOnce(Return(status));
      }

    }
  }

  this->test_iterator_ptr_->Iterate(this->test_system);
}

} // namespace<commit_msg>added expectations for UpdateScatteringSource calls<commit_after>#include "iteration/group/group_source_iteration.h"

#include <memory>

#include "iteration/updater/tests/source_updater_mock.h"
#include "quadrature/calculators/tests/spherical_harmonic_moments_mock.h"
#include "convergence/tests/final_checker_mock.h"
#include "solver/group/tests/single_group_solver_mock.h"
#include "system/moments/tests/spherical_harmonic_mock.h"
#include "system/solution/tests/mpi_group_angular_solution_mock.h"
#include "system/system.h"
#include "test_helpers/gmock_wrapper.h"

namespace  {

using namespace bart;

using ::testing::Return, ::testing::Pointee, ::testing::Ref;
using ::testing::Sequence, ::testing::_;

template <typename DimensionWrapper>
class IterationGroupSourceIterationTest : public ::testing::Test {
 public:
  static constexpr int dim = DimensionWrapper::value;

  using TestGroupIterator = iteration::group::GroupSourceIteration<dim>;
  using GroupSolver = solver::group::SingleGroupSolverMock;
  using ConvergenceChecker = convergence::FinalCheckerMock<system::moments::MomentVector>;
  using MomentCalculator = quadrature::calculators::SphericalHarmonicMomentsMock<dim>;
  using GroupSolution = system::solution::MPIGroupAngularSolutionMock;
  using SourceUpdater = iteration::updater::SourceUpdaterMock;
  using Moments = system::moments::SphericalHarmonicMock;

  // Test object
  std::unique_ptr<TestGroupIterator> test_iterator_ptr_;

  // Mock dependency objects
  std::unique_ptr<GroupSolver> single_group_solver_ptr_;
  std::unique_ptr<ConvergenceChecker> convergence_checker_ptr_;
  std::unique_ptr<MomentCalculator> moment_calculator_ptr_;
  std::shared_ptr<GroupSolution> group_solution_ptr_;
  std::unique_ptr<SourceUpdater> source_updater_ptr_;

  // Supporting objects
  system::System test_system;

  // Observing pointers
  GroupSolver* single_group_obs_ptr_ = nullptr;
  ConvergenceChecker* convergence_checker_obs_ptr_ = nullptr;
  MomentCalculator* moment_calculator_obs_ptr_ = nullptr;
  SourceUpdater* source_updater_obs_ptr_ = nullptr;
  Moments* moments_obs_ptr_ = nullptr;

  // Test parameters
  const int total_groups = 2;
  const int total_angles = 3;
  const std::array<int, 2> iterations_by_group{2,3};

  void SetUp() override;
};

TYPED_TEST_CASE(IterationGroupSourceIterationTest, bart::testing::AllDimensions);

template <typename DimensionWrapper>
void IterationGroupSourceIterationTest<DimensionWrapper>::SetUp() {
  single_group_solver_ptr_ = std::make_unique<GroupSolver>();
  single_group_obs_ptr_ = single_group_solver_ptr_.get();
  convergence_checker_ptr_ = std::make_unique<ConvergenceChecker>();
  convergence_checker_obs_ptr_ = convergence_checker_ptr_.get();
  moment_calculator_ptr_ = std::make_unique<MomentCalculator>();
  moment_calculator_obs_ptr_ = moment_calculator_ptr_.get();
  group_solution_ptr_ = std::make_shared<GroupSolution>();
  source_updater_ptr_ = std::make_unique<SourceUpdater>();
  source_updater_obs_ptr_ = source_updater_ptr_.get();

  test_system.current_moments = std::make_unique<Moments>();
  moments_obs_ptr_ = dynamic_cast<Moments*>(test_system.current_moments.get());

  test_iterator_ptr_ = std::make_unique<TestGroupIterator>(
      std::move(single_group_solver_ptr_),
      std::move(convergence_checker_ptr_),
      std::move(moment_calculator_ptr_),
      group_solution_ptr_,
      std::move(source_updater_ptr_)
      );
}

TYPED_TEST(IterationGroupSourceIterationTest, Constructor) {
  using GroupSolver = solver::group::SingleGroupSolverMock;
  using ConvergenceChecker = convergence::FinalCheckerMock<system::moments::MomentVector>;
  using MomentCalculator = quadrature::calculators::SphericalHarmonicMomentsMock<this->dim>;
  using SourceUpdater = iteration::updater::SourceUpdaterMock;

  auto single_group_test_ptr = dynamic_cast<GroupSolver*>(
      this->test_iterator_ptr_->group_solver_ptr());
  auto convergence_checker_test_ptr = dynamic_cast<ConvergenceChecker*>(
      this->test_iterator_ptr_->convergence_checker_ptr());
  auto moment_calculator_test_ptr = dynamic_cast<MomentCalculator*>(
      this->test_iterator_ptr_->moment_calculator_ptr());
  auto source_updater_test_ptr = dynamic_cast<SourceUpdater*>(
      this->test_iterator_ptr_->source_updater_ptr());

  EXPECT_NE(nullptr, single_group_test_ptr);
  EXPECT_NE(nullptr, convergence_checker_test_ptr);
  EXPECT_NE(nullptr, moment_calculator_test_ptr);
  EXPECT_EQ(2, this->group_solution_ptr_.use_count());
  EXPECT_EQ(this->group_solution_ptr_.get(),
            this->test_iterator_ptr_->group_solution_ptr().get());
  EXPECT_NE(nullptr, source_updater_test_ptr);
}

TYPED_TEST(IterationGroupSourceIterationTest, Iterate) {

  // Objects to support testing
  /* Moment Vectors. These will be returned by the MomentCalculator, based on
   * group and iteration. It is important to ensure that the correct values
   * are being checked for convergence. All entries in each vector will be set
   * to a unique value, 10*group + iteration. */
  std::map<int, std::vector<system::moments::MomentVector>> calculated_moments;
  system::moments::MomentVector zero_moment(5);

  for (int group = 0; group < this->total_groups; ++group) {
    calculated_moments[group] = {};
    for (int it = 0; it < this->iterations_by_group[group]; ++it) {
      system::moments::MomentVector new_moment(5);
      new_moment = (group * 10 + it);
      calculated_moments.at(group).push_back(new_moment);
    }
  }

  EXPECT_CALL(*this->moments_obs_ptr_, total_groups())
      .WillOnce(Return(this->total_groups));
  EXPECT_CALL(*this->group_solution_ptr_, total_angles())
      .WillOnce(Return(this->total_angles));

  Sequence s;

  for (int group = 0; group < this->total_groups; ++group) {
    EXPECT_CALL(*this->single_group_obs_ptr_, SolveGroup(
        group,
        Ref(this->test_system),
        Ref(*this->group_solution_ptr_)))
        .Times(this->iterations_by_group[group]);

    for (int it = 0; it < this->iterations_by_group[group]; ++it) {

      EXPECT_CALL(*this->moment_calculator_obs_ptr_, CalculateMoment(
          this->group_solution_ptr_.get(), group, 0, 0))
          //_, group, 0, 0))
          .InSequence(s)
          .WillOnce(Return(calculated_moments.at(group).at(it)));

      convergence::Status status;

      if ((it + 1) == this->iterations_by_group[group])
        status.is_complete = true;

      status.iteration_number = it + 1;

      if (it == 0) {
        EXPECT_CALL(*this->convergence_checker_obs_ptr_, CheckFinalConvergence(
            calculated_moments.at(group).at(it),
            zero_moment))
            .InSequence(s)
            .WillOnce(Return(status));
      } else {
        EXPECT_CALL(*this->convergence_checker_obs_ptr_, CheckFinalConvergence(
            calculated_moments.at(group).at(it),
            calculated_moments.at(group).at(it - 1)))
            .InSequence(s)
            .WillOnce(Return(status));
      }

      for (int angle = 0; angle < this->total_angles; ++angle) {
        EXPECT_CALL(*this->source_updater_obs_ptr_, UpdateScatteringSource(
            Ref(this->test_system), group, angle));
      }
    }
  }

  this->test_iterator_ptr_->Iterate(this->test_system);
}

} // namespace<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <fstream>

#include "lib/store.hpp"
#include "lib/graph.hpp"

void store::save(const Graph& g, const std::string filename) {
  std::ofstream fs(filename);

  for (auto& v : g.list) {
    fs << *v.get() << std::endl;
  }
}

Graph store::load(const std::string filename) {
  Graph g;

  std::ifstream fs(filename);
  // fs >>

  return std::move(g);
}
<commit_msg>Add some TODOs<commit_after>#include <iostream>
#include <string>
#include <fstream>

#include "lib/store.hpp"
#include "lib/graph.hpp"

void store::save(const Graph& g, const std::string filename) {
  std::ofstream fs(filename);

  for (auto& v : g.list) {
    fs << *v.get() << std::endl;
  }
}

Graph store::load(const std::string filename) {
  Graph g;

  std::ifstream fs(filename);
  // fs >>
  // TODO - figure out what to do with this

  return std::move(g);
}
<|endoftext|>


<commit_before>// Steer TRD QA train for Reconstruction (Clusterizer, Tracking and PID).
//
// Usage:
//   run.C(optList, files, nev, first, runNo, ocdb_uri, grp_uri)
//
//   optList : "ALL" [default] or one/more of the following:
//     "EFF"  : TRD Tracking Efficiency
//     "EFFC" : TRD Tracking Efficiency Combined (barrel + stand alone) - only in case of simulations
//     "MULT"  : TRD single track selection
//     "RES"  : TRD tracking Resolution
//     "CLRES": clusters Resolution
//     "CAL"  : TRD calibration
//     "ALGN" : TRD alignment
//     "PID"  : TRD PID - pion efficiency
//     "PIDR" : TRD PID - reference data
//     "V0"   : monitor V0 performance for use in TRD PID calibration
//     "DET"  : Basic TRD Detector checks
//      ****** SPECIAL OPTIONS **********
//     "NOFR" : Data set does not have AliESDfriends.root
//     "NOMC" : Data set does not have Monte Carlo Informations (default have MC),
//
//     files : the list of ESD files to be processed [default AliESds.root from cwd]
//     nev   : number of events to be processed [default all]
//     first : first event to process [default 0]
//     runNo : run number [default 0]
//     ocdb_uri : OCDB location [default local, $ALICE_ROOT]. In case of AliEn the syntax should be of the form
//                 alien://folder=/alice/data/2010/OCDB?user=username?cacheF=yourDirectory?cacheS=yourSize
//     grp_uri  : GRP/GRP/Data location [default cwd]. In case of AliEn the syntax should be of the form
//                 alien://folder=/alice/data/2010/OCDB?user=username?cacheF=yourDirectory?cacheS=yourSize
// In compiled mode :
// Don't forget to load first the libraries
// gSystem->Load("libMemStat.so")
// gSystem->Load("libMemStatGui.so")
// gSystem->Load("libANALYSIS.so")
// gSystem->Load("libANALYSISalice.so")
// gSystem->Load("libTENDER.so");
// gSystem->Load("libPWG1.so");
// gSystem->Load("libNetx.so") ;
// gSystem->Load("libRAliEn.so");
//
// Authors:
//   Alex Bercuci (A.Bercuci@gsi.de)
//   Markus Fasel (m.Fasel@gsi.de)

#if ! defined (__CINT__) || defined (__MAKECINT__)
//#ifndef __CINT__
#include <Riostream.h>

#include "TStopwatch.h"
#include "TMemStat.h"
#include "TMemStatViewerGUI.h"

#include "TROOT.h"
#include "TClass.h"
#include "TSystem.h"
#include "TError.h"
#include "TChain.h"
#include "TGrid.h"
#include "TAlienCollection.h"
#include "TGridCollection.h"
#include "TGridResult.h"
#include "TGeoGlobalMagField.h"

#include "AliMagF.h"
#include "AliTracker.h"
#include "AliLog.h"
#include "AliCDBManager.h"
#include "AliGRPManager.h"
#include "AliGeomManager.h"
#include "AliAnalysisManager.h"
#include "AliAnalysisDataContainer.h"
#include "AliMCEventHandler.h"
#include "AliESDInputHandler.h"

#include "TRD/AliTRDtrackerV1.h"
#include "TRD/AliTRDcalibDB.h"

#include "PWG1/TRD/macros/AliTRDperformanceTrain.h"
#include "PWG1/TRD/macros/AddTRDcheckESD.C"
#include "PWG1/TRD/macros/AddTRDinfoGen.C"
#include "PWG1/TRD/macros/AddTRDcheckDET.C"
#include "PWG1/TRD/macros/AddTRDefficiency.C"
#include "PWG1/TRD/macros/AddTRDresolution.C"
#include "PWG1/TRD/macros/AddTRDcheckPID.C"

#endif

#include "macros/AliTRDperformanceTrain.h"

Bool_t MEM = kFALSE;

TChain* MakeChainLST(const char* filename = 0x0);
TChain* MakeChainXML(const char* filename = 0x0);
void run(Char_t *optList="ALL", const Char_t *files=0x0, Long64_t nev=1234567890, Long64_t first = 0, Int_t runNo=0, const Char_t *ocdb_uri="local://$ALICE_ROOT/OCDB", const Char_t *grp_uri=Form("local://%s", gSystem->pwd()))
{
  TMemStat *mem = 0x0;
  if(MEM){
    if(gSystem->Load("libMemStat.so")<0) return;
    if(gSystem->Load("libMemStatGui.so")<0) return;
    mem = new TMemStat("new, gnubuildin");
    mem->AddStamp("Start");
  }
  TStopwatch timer;
  timer.Start();

  // VERY GENERAL SETTINGS
  //AliLog::SetGlobalLogLevel(AliLog::kError);
  gStyle->SetOptStat(0);
  if(gSystem->Load("libANALYSIS.so")<0) return;
  if(gSystem->Load("libANALYSISalice.so")<0) return;
  if(gSystem->Load("libTENDER.so")<0) return;
  if(gSystem->Load("libPWG1.so")<0) return;

  Bool_t fHasMCdata =  HasReadMCData(optList);
  Bool_t fHasFriends = HasReadFriendData(optList);

  // INITIALIZATION OF RUNNING ENVIRONMENT
  // initialize OCDB manager
//   AliCDBManager *cdbManager = AliCDBManager::Instance();
//   cdbManager->SetDefaultStorage(ocdb_uri);
//   if(!cdbManager->IsDefaultStorageSet()){
//     Error("run.C", "Error setting OCDB.");
//     return;
//   }
//   cdbManager->SetRun(runNo);
//   cdbManager->SetSpecificStorage("GRP/GRP/Data", grp_uri);
//   cdbManager->SetCacheFlag(kFALSE);
//   cdbManager->Print();
//   // initialize magnetic field from the GRP manager.
//   AliGRPManager grpMan;
//   if(!grpMan.ReadGRPEntry()) return;
//   if(!grpMan.SetMagField()) return;
//   //AliRunInfo *runInfo = grpMan.GetRunInfo();
//   AliGeomManager::LoadGeometry();

  // DEFINE DATA CHAIN
  TChain *chain = 0x0;
  if(!files) chain = MakeChainLST();
  else{
    TString fn(files);
    if(fn.EndsWith("xml")) chain = MakeChainXML(files);
    else chain = MakeChainLST(files);
  }
  if(!chain) return;
  chain->Lookup();
  chain->GetListOfFiles()->Print();
  Int_t nfound=(Int_t)chain->GetEntries();
  printf("\tENTRIES FOUND [%d] REQUESTED [%d]\n", nfound, nev>nfound?nfound:nev);

  // BUILD ANALYSIS MANAGER
  AliAnalysisManager *mgr = new AliAnalysisManager("TRD Reconstruction Performance & Calibration");
  AliESDInputHandlerRP *esdH(NULL);
  mgr->SetInputEventHandler(esdH = new AliESDInputHandlerRP);
  esdH->SetReadFriends(kTRUE);
  esdH->SetActiveBranches("ESDfriend");
  AliMCEventHandler *mcH(NULL);
  if(fHasMCdata) mgr->SetMCtruthEventHandler(mcH = new AliMCEventHandler());
  //mgr->SetDebugLevel(10);
  mgr->SetSkipTerminate(kTRUE);

  gROOT->LoadMacro("$ALICE_ROOT/PWG1/macros/AddTrainPerformanceTRD.C");
  if(!AddTrainPerformanceTRD(optList)) {
    Error("run.C", "Error loading TRD train.");
    return;
  }

  if (!mgr->InitAnalysis()) return;
  // verbosity
  printf("\tRUNNING TRAIN FOR TASKS:\n");
  TObjArray *taskList=mgr->GetTasks();
  for(Int_t itask=0; itask<taskList->GetEntries(); itask++){
    AliAnalysisTask *task=(AliAnalysisTask*)taskList->At(itask);
    printf(" %s [%s]\n", task->GetName(), task->GetTitle());
  }
  //mgr->PrintStatus();
  mgr->StartAnalysis("local", chain, nev, first);
  timer.Stop();
  timer.Print();

  // verbosity
  printf("\tCLEANING TASK LIST:\n");
  mgr->GetTasks()->Delete();

  if(mcH) delete mcH;
  delete esdH;
  delete chain;
  if(MEM) delete mem;
  if(MEM) TMemStatViewerGUI::ShowGUI();
}

//____________________________________________
TChain* MakeChainLST(const char* filename)
{
  // Create the chain
  TChain* chain = new TChain("esdTree");

  if(!filename){
    chain->Add(Form("%s/AliESDs.root", gSystem->pwd()));
    return chain;
  }

  // read ESD files from the input list.
  ifstream in;
  in.open(filename);
  TString esdfile;
  while(in.good()) {
    in >> esdfile;
    if (!esdfile.Contains("root")) continue; // protection
    chain->Add(esdfile.Data());
  }

  in.close();

  return chain;
}

//____________________________________________
TChain* MakeChainXML(const char* xmlfile)
{
  if (!TFile::Open(xmlfile)) {
    Error("MakeChainXML", Form("No file %s was found", xmlfile));
    return 0x0;
  }

  if(gSystem->Load("libNetx.so")<0) return 0x0;
  if(gSystem->Load("libRAliEn.so")<0) return 0x0;
  TGrid::Connect("alien://") ;

  TGridCollection *collection = (TGridCollection*) TAlienCollection::Open(xmlfile);
  if (!collection) {
    Error("MakeChainXML", Form("No collection found in %s", xmlfile)) ;
    return 0x0;
  }
  //collection->CheckIfOnline();

  TGridResult* result = collection->GetGridResult("",0 ,0);
  if(!result->GetEntries()){
    Error("MakeChainXML", Form("No entries found in %s", xmlfile)) ;
    return 0x0;
  }
  // Makes the ESD chain
  TChain* chain = new TChain("esdTree");
  for (Int_t idx = 0; idx < result->GetEntries(); idx++) {
    chain->Add(result->GetKey(idx, "turl"));
  }
  return chain;
}
<commit_msg>simplified parameter list<commit_after>// Steer TRD QA train for Reconstruction (Clusterizer, Tracking and PID).
//
// Usage:
//   run.C(optList, files, nev, first, runNo, ocdb_uri, grp_uri)
//
//   optList : "ALL" [default] or one/more of the following:
//     "EFF"  : TRD Tracking Efficiency
//     "EFFC" : TRD Tracking Efficiency Combined (barrel + stand alone) - only in case of simulations
//     "MULT"  : TRD single track selection
//     "RES"  : TRD tracking Resolution
//     "CLRES": clusters Resolution
//     "CAL"  : TRD calibration
//     "ALGN" : TRD alignment
//     "PID"  : TRD PID - pion efficiency
//     "PIDR" : TRD PID - reference data
//     "V0"   : monitor V0 performance for use in TRD PID calibration
//     "DET"  : Basic TRD Detector checks
//      ****** SPECIAL OPTIONS **********
//     "NOFR" : Data set does not have AliESDfriends.root
//     "NOMC" : Data set does not have Monte Carlo Informations (default have MC),
//
//     files : the list of ESD files to be processed [default AliESds.root from cwd]
//     nev   : number of events to be processed [default all]
//     first : first event to process [default 0]
//     runNo : run number [default 0]
//     ocdb_uri : OCDB location [default local, $ALICE_ROOT]. In case of AliEn the syntax should be of the form
//                 alien://folder=/alice/data/2010/OCDB?user=username?cacheF=yourDirectory?cacheS=yourSize
//     grp_uri  : GRP/GRP/Data location [default cwd]. In case of AliEn the syntax should be of the form
//                 alien://folder=/alice/data/2010/OCDB?user=username?cacheF=yourDirectory?cacheS=yourSize
// In compiled mode :
// Don't forget to load first the libraries
// gSystem->Load("libMemStat.so")
// gSystem->Load("libMemStatGui.so")
// gSystem->Load("libANALYSIS.so")
// gSystem->Load("libANALYSISalice.so")
// gSystem->Load("libTENDER.so");
// gSystem->Load("libPWG1.so");
// gSystem->Load("libNetx.so") ;
// gSystem->Load("libRAliEn.so");
//
// Authors:
//   Alex Bercuci (A.Bercuci@gsi.de)
//   Markus Fasel (m.Fasel@gsi.de)

#if ! defined (__CINT__) || defined (__MAKECINT__)
//#ifndef __CINT__
#include <Riostream.h>

#include "TStopwatch.h"
#include "TMemStat.h"
#include "TMemStatViewerGUI.h"

#include "TROOT.h"
#include "TClass.h"
#include "TSystem.h"
#include "TError.h"
#include "TChain.h"
#include "TGrid.h"
#include "TAlienCollection.h"
#include "TGridCollection.h"
#include "TGridResult.h"
#include "TGeoGlobalMagField.h"

#include "AliMagF.h"
#include "AliTracker.h"
#include "AliLog.h"
#include "AliCDBManager.h"
#include "AliGRPManager.h"
#include "AliGeomManager.h"
#include "AliAnalysisManager.h"
#include "AliAnalysisDataContainer.h"
#include "AliMCEventHandler.h"
#include "AliESDInputHandler.h"

#include "TRD/AliTRDtrackerV1.h"
#include "TRD/AliTRDcalibDB.h"

#include "PWG1/TRD/macros/AliTRDperformanceTrain.h"
#include "PWG1/TRD/macros/AddTRDcheckESD.C"
#include "PWG1/TRD/macros/AddTRDinfoGen.C"
#include "PWG1/TRD/macros/AddTRDcheckDET.C"
#include "PWG1/TRD/macros/AddTRDefficiency.C"
#include "PWG1/TRD/macros/AddTRDresolution.C"
#include "PWG1/TRD/macros/AddTRDcheckPID.C"

#endif

#include "macros/AliTRDperformanceTrain.h"

Bool_t MEM = kFALSE;

TChain* MakeChainLST(const char* filename = 0x0);
TChain* MakeChainXML(const char* filename = 0x0);
void run(Char_t *optList="ALL", const Char_t *files=0x0, Long64_t nev=1234567890, Long64_t first = 0)
{
  TMemStat *mem = 0x0;
  if(MEM){
    if(gSystem->Load("libMemStat.so")<0) return;
    if(gSystem->Load("libMemStatGui.so")<0) return;
    mem = new TMemStat("new, gnubuildin");
    mem->AddStamp("Start");
  }
  TStopwatch timer;
  timer.Start();

  // VERY GENERAL SETTINGS
  //AliLog::SetGlobalLogLevel(AliLog::kError);
  gStyle->SetOptStat(0);
  if(gSystem->Load("libANALYSIS.so")<0) return;
  if(gSystem->Load("libANALYSISalice.so")<0) return;
  if(gSystem->Load("libTENDER.so")<0) return;
  if(gSystem->Load("libPWG1.so")<0) return;

  Bool_t fHasMCdata =  HasReadMCData(optList);
  Bool_t fHasFriends = HasReadFriendData(optList);

  // DEFINE DATA CHAIN
  TChain *chain = 0x0;
  if(!files) chain = MakeChainLST();
  else{
    TString fn(files);
    if(fn.EndsWith("xml")) chain = MakeChainXML(files);
    else chain = MakeChainLST(files);
  }
  if(!chain) return;
  chain->Lookup();
  chain->GetListOfFiles()->Print();
  Int_t nfound=(Int_t)chain->GetEntries();
  printf("\tENTRIES FOUND [%d] REQUESTED [%d]\n", nfound, nev>nfound?nfound:nev);

  // BUILD ANALYSIS MANAGER
  AliAnalysisManager *mgr = new AliAnalysisManager("TRD Reconstruction Performance & Calibration");
  AliESDInputHandlerRP *esdH(NULL);
  mgr->SetInputEventHandler(esdH = new AliESDInputHandlerRP);
  esdH->SetReadFriends(kTRUE);
  esdH->SetActiveBranches("ESDfriend");
  AliMCEventHandler *mcH(NULL);
  if(fHasMCdata) mgr->SetMCtruthEventHandler(mcH = new AliMCEventHandler());
  //mgr->SetDebugLevel(10);
  mgr->SetSkipTerminate(kTRUE);

  gROOT->LoadMacro("$ALICE_ROOT/PWG1/macros/AddTrainPerformanceTRD.C");
  if(!AddTrainPerformanceTRD(optList)) {
    Error("run.C", "Error loading TRD train.");
    return;
  }

  if (!mgr->InitAnalysis()) return;
  // verbosity
  printf("\tRUNNING TRAIN FOR TASKS:\n");
  TObjArray *taskList=mgr->GetTasks();
  for(Int_t itask=0; itask<taskList->GetEntries(); itask++){
    AliAnalysisTask *task=(AliAnalysisTask*)taskList->At(itask);
    printf(" %s [%s]\n", task->GetName(), task->GetTitle());
  }
  //mgr->PrintStatus();
  mgr->StartAnalysis("local", chain, nev, first);
  timer.Stop();
  timer.Print();

  // verbosity
  printf("\tCLEANING TASK LIST:\n");
  mgr->GetTasks()->Delete();

  if(mcH) delete mcH;
  delete esdH;
  delete chain;
  if(MEM) delete mem;
  if(MEM) TMemStatViewerGUI::ShowGUI();
}

//____________________________________________
TChain* MakeChainLST(const char* filename)
{
  // Create the chain
  TChain* chain = new TChain("esdTree");

  if(!filename){
    chain->Add(Form("%s/AliESDs.root", gSystem->pwd()));
    return chain;
  }

  // read ESD files from the input list.
  ifstream in;
  in.open(filename);
  TString esdfile;
  while(in.good()) {
    in >> esdfile;
    if (!esdfile.Contains("root")) continue; // protection
    chain->Add(esdfile.Data());
  }

  in.close();

  return chain;
}

//____________________________________________
TChain* MakeChainXML(const char* xmlfile)
{
  if (!TFile::Open(xmlfile)) {
    Error("MakeChainXML", Form("No file %s was found", xmlfile));
    return 0x0;
  }

  if(gSystem->Load("libNetx.so")<0) return 0x0;
  if(gSystem->Load("libRAliEn.so")<0) return 0x0;
  TGrid::Connect("alien://") ;

  TGridCollection *collection = (TGridCollection*) TAlienCollection::Open(xmlfile);
  if (!collection) {
    Error("MakeChainXML", Form("No collection found in %s", xmlfile)) ;
    return 0x0;
  }
  //collection->CheckIfOnline();

  TGridResult* result = collection->GetGridResult("",0 ,0);
  if(!result->GetEntries()){
    Error("MakeChainXML", Form("No entries found in %s", xmlfile)) ;
    return 0x0;
  }
  // Makes the ESD chain
  TChain* chain = new TChain("esdTree");
  for (Int_t idx = 0; idx < result->GetEntries(); idx++) {
    chain->Add(result->GetKey(idx, "turl"));
  }
  return chain;
}
<|endoftext|>


<commit_before>#ifndef LIB_MART_COMMON_GUARD_NW_UNIX_H
#define LIB_MART_COMMON_GUARD_NW_UNIX_H

/**
 * unix.h (mart-netlib)
 *
 * Copyright (C) 2019: Michael Balszun <michael.balszun@mytum.de>
 *
 * This software may be modified and distributed under the terms
 * of the MIT license. See either the LICENSE file in the library's root
 * directory or http://opensource.org/licenses/MIT for details.
 *
 * @author: Michael Balszun <michael.balszun@mytum.de>
 * @brief:	This file provides a simple unix doamin socket implementation
 *
 */

#include "port_layer.hpp"

#include <im_str/im_str.hpp>

#include <mart-common/utils.h>

#include <filesystem>
#include <string_view>

#include "detail/dgram_socket_base.hpp"

namespace mart::nw {
// classes related to the unix sockets protocol in general
namespace un {

class endpoint {
public:
	using abi_endpoint_type = mart::nw::socks::port_layer::SockaddrUn;

	constexpr endpoint() noexcept = default;
	endpoint( mba::im_zstr path ) noexcept
		: _addr( std::move( path ) )
	{
	}
	explicit endpoint( std::string_view path ) noexcept
		: _addr( path )
	{
	}
	explicit endpoint( const std::filesystem::path& path ) noexcept
		// TODO use "native()" on platforms that use u8 encoding natively
		: _addr( std::string_view( path.u8string() ) )
	{
	}

	explicit endpoint( const abi_endpoint_type& path ) noexcept
		: endpoint( std::string_view( path.path() ) )
	{
	}

	mba::im_zstr asString() const noexcept { return _addr; }
	mba::im_zstr toStringEx() const noexcept { return _addr; }

	abi_endpoint_type toSockAddrUn() const noexcept { return abi_endpoint_type( _addr.data(), _addr.size() ); }

	// for use in generic contexts
	abi_endpoint_type toSockAddr() const noexcept { return toSockAddrUn(); }

	friend bool operator==( const endpoint& l, const endpoint& r ) noexcept { return l._addr == r._addr; }
	friend bool operator!=( const endpoint& l, const endpoint& r ) noexcept { return l._addr != r._addr; }
	friend bool operator<( const endpoint& l, const endpoint& r ) noexcept { return l._addr < r._addr; }

private:
	mba::im_zstr _addr{};
};
} // namespace un
} // namespace mart::nw

namespace mart::nw::socks::detail {
extern template class DgramSocket<mart::nw::un::endpoint>;
}

namespace mart::nw {
// classes related to the unix sockets protocol in general
namespace un {
using Socket = mart::nw::socks::detail::DgramSocket<endpoint>;
}
} // namespace mart::nw

#endif<commit_msg>[netlib] Fix c++20 compatibility issue with paths<commit_after>#ifndef LIB_MART_COMMON_GUARD_NW_UNIX_H
#define LIB_MART_COMMON_GUARD_NW_UNIX_H

/**
 * unix.h (mart-netlib)
 *
 * Copyright (C) 2019: Michael Balszun <michael.balszun@mytum.de>
 *
 * This software may be modified and distributed under the terms
 * of the MIT license. See either the LICENSE file in the library's root
 * directory or http://opensource.org/licenses/MIT for details.
 *
 * @author: Michael Balszun <michael.balszun@mytum.de>
 * @brief:	This file provides a simple unix doamin socket implementation
 *
 */

#include "port_layer.hpp"

#include <im_str/im_str.hpp>

#include <mart-common/utils.h>

#include <filesystem>
#include <string_view>

#include "detail/dgram_socket_base.hpp"

namespace mart::nw {
// classes related to the unix sockets protocol in general
namespace un {

class endpoint {
public:
	using abi_endpoint_type = mart::nw::socks::port_layer::SockaddrUn;

	constexpr endpoint() noexcept = default;
	endpoint( mba::im_zstr path ) noexcept
		: _addr( std::move( path ) )
	{
	}
	explicit endpoint( std::string_view path ) noexcept
		: _addr( path )
	{
	}
	explicit endpoint( const std::filesystem::path& path ) noexcept
		// TODO use "native()" on platforms that use u8 encoding natively
		: _addr( std::string_view( path.string() ) )
	{
	}

	explicit endpoint( const abi_endpoint_type& path ) noexcept
		: endpoint( std::string_view( path.path() ) )
	{
	}

	mba::im_zstr asString() const noexcept { return _addr; }
	mba::im_zstr toStringEx() const noexcept { return _addr; }

	abi_endpoint_type toSockAddrUn() const noexcept { return abi_endpoint_type( _addr.data(), _addr.size() ); }

	// for use in generic contexts
	abi_endpoint_type toSockAddr() const noexcept { return toSockAddrUn(); }

	friend bool operator==( const endpoint& l, const endpoint& r ) noexcept { return l._addr == r._addr; }
	friend bool operator!=( const endpoint& l, const endpoint& r ) noexcept { return l._addr != r._addr; }
	friend bool operator<( const endpoint& l, const endpoint& r ) noexcept { return l._addr < r._addr; }

private:
	mba::im_zstr _addr{};
};
} // namespace un
} // namespace mart::nw

namespace mart::nw::socks::detail {
extern template class DgramSocket<mart::nw::un::endpoint>;
}

namespace mart::nw {
// classes related to the unix sockets protocol in general
namespace un {
using Socket = mart::nw::socks::detail::DgramSocket<endpoint>;
}
} // namespace mart::nw

#endif<|endoftext|>


<commit_before>/*
 * This file is part of otf2xx (https://github.com/tud-zih-energy/otf2xx)
 * otf2xx - A wrapper for the Open Trace Format 2 library
 *
 * Copyright (c) 2013-2016, Technische Universität Dresden, Germany
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * * Neither the name of 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 INCLUDE_OTF2XX_EXCEPTION_HPP
#define INCLUDE_OTF2XX_EXCEPTION_HPP

#include <otf2/OTF2_ErrorCodes.h>

#include <sstream>
#include <stdexcept>
#include <string>

namespace otf2
{

struct exception : std::runtime_error
{
    explicit exception(const std::string& arg) : std::runtime_error(arg)
    {
    }
};

namespace detail
{

    template <typename Arg, typename... Args>
    class make_exception
    {
    public:
        void operator()(std::stringstream& msg, Arg arg, Args... args)
        {
            msg << arg;
            make_exception<Args...>()(msg, args...);
        }
    };

    template <typename Arg>
    class make_exception<Arg>
    {
    public:
        void operator()(std::stringstream& msg, Arg arg)
        {
            msg << arg;
        }
    };
}

template <typename... Args>
inline void make_exception(Args... args)
{
    std::stringstream msg;

    detail::make_exception<Args...>()(msg, args...);

    throw exception(msg.str());
}

template <typename... Args>
void inline check(OTF2_ErrorCode code, Args... args)
{
    if (code != OTF2_SUCCESS)
    {
        make_exception(args...);
    }
}

} // namespace otf2

#endif // INCLUDE_OTF2XX_EXCEPTION_HPP
<commit_msg>manually cherry-picking from @flamefire 's PR<commit_after>/*
 * This file is part of otf2xx (https://github.com/tud-zih-energy/otf2xx)
 * otf2xx - A wrapper for the Open Trace Format 2 library
 *
 * Copyright (c) 2013-2016, Technische Universität Dresden, Germany
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * * Neither the name of 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 INCLUDE_OTF2XX_EXCEPTION_HPP
#define INCLUDE_OTF2XX_EXCEPTION_HPP

#include <otf2/OTF2_ErrorCodes.h>

#include <sstream>
#include <stdexcept>
#include <string>

namespace otf2
{

struct exception : std::runtime_error
{
    explicit exception(const std::string& arg) : std::runtime_error(arg)
    {
    }
};

namespace detail
{

    template <typename Arg, typename... Args>
    class make_exception
    {
    public:
        void operator()(std::stringstream& msg, Arg&& arg, Args&&... args)
        {
            msg << std::forward<Arg>(arg);
            make_exception<Args...>()(msg, std::forward<Args>(args)...);
        }
    };

    template <typename Arg>
    class make_exception<Arg>
    {
    public:
        void operator()(std::stringstream& msg, Arg&& arg)
        {
            msg << std::forward<Arg>(arg);
        }
    };
} // namespace detail

template <typename... Args>
[[noreturn]] inline void make_exception(Args&&... args)
{
    std::stringstream msg;

    detail::make_exception<Args...>()(msg, std::forward<Args>(args)...);

    throw exception(msg.str());
}

template <typename... Args>
inline void make_otf2_exception(OTF2_ErrorCode code, Args&&... args)
{
    make_exception(OTF2_Error_GetName(code), ": ", OTF2_Error_GetDescription(code), "\n",
                   std::forward<Args>(args)...);
}

template <typename... Args>
void inline check(OTF2_ErrorCode code, Args&&... args)
{
    if (code != OTF2_SUCCESS)
    {
        make_otf2_exception(code, std::forward<Args>(args)...);
    }
}

} // namespace otf2

#endif // INCLUDE_OTF2XX_EXCEPTION_HPP
<|endoftext|>


<commit_before>///
/// @file   Wheel.hpp
/// @brief  Classes and structs related to wheel factorization.
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef WHEEL_HPP
#define WHEEL_HPP

#include "config.hpp"
#include "pmath.hpp"
#include "primesieve_error.hpp"

#include <stdint.h>
#include <cassert>
#include <string>

namespace primesieve {

/// The WheelInit data structure is used to calculate the
/// first multiple >= start of each sieving prime
///
struct WheelInit
{
  uint8_t nextMultipleFactor;
  uint8_t wheelIndex;
};

extern const WheelInit wheel30Init[30];
extern const WheelInit wheel210Init[210];

/// The WheelElement data structure is used to skip multiples
/// of small primes using wheel factorization
///
struct WheelElement
{
  /// Bitmask used to unset the bit corresponding to the current
  /// multiple of a SievingPrime object
  uint8_t unsetBit;
  /// Factor used to calculate the next multiple of a sieving prime
  /// that is not divisible by any of the wheel factors
  uint8_t nextMultipleFactor;
  /// Overflow needed to correct the next multiple index
  /// (due to sievingPrime = prime / 30)
  uint8_t correct;
  /// Used to calculate the next wheel index:
  /// wheelIndex += next;
  int8_t next;
};

extern const WheelElement wheel30[8*8];
extern const WheelElement wheel210[48*8];

/// Sieving primes are used to cross-off multiples (of itself).
/// Each SievingPrime object contains a sieving prime and the
/// position of its next multiple within the SieveOfEratosthenes
/// array (i.e. multipleIndex) and a wheelIndex.
///
class SievingPrime
{
public:
  enum
  {
    MAX_MULTIPLEINDEX = (1 << 23) - 1,
    MAX_WHEELINDEX    = (1 << (32 - 23)) - 1
  };

  SievingPrime() { }

  SievingPrime(uint_t sievingPrime,
               uint_t multipleIndex,
               uint_t wheelIndex)
  {
    set(multipleIndex, wheelIndex);
    sievingPrime_ = (uint32_t) sievingPrime;
  }

  uint_t getSievingPrime() const
  {
    return sievingPrime_;
  }

  uint_t getMultipleIndex() const
  {
    return indexes_ & MAX_MULTIPLEINDEX;
  }

  uint_t getWheelIndex() const
  {
    return indexes_ >> 23;
  }

  void setMultipleIndex(uint_t multipleIndex)
  {
    assert(multipleIndex <= MAX_MULTIPLEINDEX);
    indexes_ = (uint32_t)(indexes_ | multipleIndex);
  }

  void setWheelIndex(uint_t wheelIndex)
  {
    assert(wheelIndex <= MAX_WHEELINDEX);
    indexes_ = (uint32_t)(wheelIndex << 23);
  }

  void set(uint_t multipleIndex,
           uint_t wheelIndex)
  {
    assert(multipleIndex <= MAX_MULTIPLEINDEX);
    assert(wheelIndex <= MAX_WHEELINDEX);
    indexes_ = (uint32_t)(multipleIndex | (wheelIndex << 23));
  }

  void set(uint_t sievingPrime,
           uint_t multipleIndex,
           uint_t wheelIndex)
  {
    set(multipleIndex, wheelIndex);
    sievingPrime_ = (uint32_t) sievingPrime;
  }
private:
  /// multipleIndex = 23 least significant bits of indexes_
  /// wheelIndex = 9 most significant bits of indexes_
  uint32_t indexes_;
  uint32_t sievingPrime_;
};

/// The Bucket data structure is used to store sieving primes.
/// @see http://www.ieeta.pt/~tos/software/prime_sieve.html
/// The Bucket class is designed as a singly linked list, once there
/// is no more space in the current Bucket a new Bucket node is
/// allocated.
///
class Bucket
{
public:
  Bucket()              { reset(); }
  SievingPrime* begin() { return &sievingPrimes_[0]; }
  SievingPrime* last()  { return &sievingPrimes_[config::BUCKETSIZE - 1]; }
  SievingPrime* end()   { return prime_; }
  Bucket* next()        { return next_; }
  bool hasNext() const  { return next_ != nullptr; }
  bool empty()          { return begin() == end(); }
  void reset()          { prime_ = begin(); }
  void setNext(Bucket* next)
  {
    next_ = next;
  }
  /// Store a sieving prime in the bucket
  /// @return false if the bucket is full else true
  ///
  bool store(uint_t sievingPrime,
             uint_t multipleIndex,
             uint_t wheelIndex)
  {
    prime_->set(sievingPrime, multipleIndex, wheelIndex);
    return prime_++ != last();
  }
private:
  SievingPrime* prime_;
  Bucket* next_;
  SievingPrime sievingPrimes_[config::BUCKETSIZE];
};

/// The abstract WheelFactorization class is used skip multiples
/// of small primes in the sieve of Eratosthenes. The EratSmall,
/// EratMedium and EratBig classes are derived from
/// WheelFactorization.
///
template <uint_t MODULO, uint_t SIZE, const WheelInit* INIT, const WheelElement* WHEEL>
class WheelFactorization
{
public:
  /// Add a new sieving prime to the sieving algorithm.
  /// Calculate the first multiple > segmentLow of prime and the
  /// position within the SieveOfEratosthenes array of that multiple
  /// and its wheel index. When done store the sieving prime.
  ///
  void addSievingPrime(uint_t prime, uint64_t segmentLow)
  {
    segmentLow += 6;
    // calculate the first multiple (of prime) > segmentLow
    uint64_t quotient = segmentLow / prime + 1;
    uint64_t multiple = prime * quotient;
    // prime not needed for sieving
    if (multiple > stop_ ||
        multiple < segmentLow)
      return;
    // ensure multiple >= prime * prime
    if (quotient < prime)
    {
      multiple = isquare<uint64_t>(prime);
      quotient = prime;
    }
    // calculate the next multiple of prime that is not
    // divisible by any of the wheel's factors
    uint64_t nextMultipleFactor = INIT[quotient % MODULO].nextMultipleFactor;
    uint64_t nextMultiple = prime * nextMultipleFactor;
    if (nextMultiple > stop_ - multiple)
      return;
    nextMultiple += multiple - segmentLow;
    uint_t multipleIndex = (uint_t)(nextMultiple / NUMBERS_PER_BYTE);
    uint_t wheelIndex = wheelOffsets_[prime % NUMBERS_PER_BYTE] + INIT[quotient % MODULO].wheelIndex;
    storeSievingPrime(prime, multipleIndex, wheelIndex);
  }

protected:
  WheelFactorization(uint64_t stop, uint_t sieveSize) :
    stop_(stop)
  {
    uint_t maxSieveSize = SievingPrime::MAX_MULTIPLEINDEX + 1;

    if (sieveSize > maxSieveSize)
      throw primesieve_error("WheelFactorization: sieveSize must be <= " + std::to_string(maxSieveSize));
  }

  virtual ~WheelFactorization()
  { }

  virtual void storeSievingPrime(uint_t, uint_t, uint_t) = 0;

  static uint_t getMaxFactor()
  {
    return WHEEL[0].nextMultipleFactor;
  }

  /// Cross-off the current multiple of sievingPrime
  /// and calculate its next multiple
  ///
  static void unsetBit(byte_t* sieve, uint_t sievingPrime, uint_t* multipleIndex, uint_t* wheelIndex)
  {
    sieve[*multipleIndex] &= WHEEL[*wheelIndex].unsetBit;
    *multipleIndex        += WHEEL[*wheelIndex].nextMultipleFactor * sievingPrime;
    *multipleIndex        += WHEEL[*wheelIndex].correct;
    *wheelIndex           += WHEEL[*wheelIndex].next;
  }
private:
  static const uint_t wheelOffsets_[30];
  uint64_t stop_;
};

template <uint_t MODULO, uint_t SIZE, const WheelInit* INIT, const WheelElement* WHEEL>
const uint_t
WheelFactorization<MODULO, SIZE, INIT, WHEEL>::wheelOffsets_[30] =
{
  0, SIZE * 7, 0, 0, 0, 0,
  0, SIZE * 0, 0, 0, 0, SIZE * 1,
  0, SIZE * 2, 0, 0, 0, SIZE * 3,
  0, SIZE * 4, 0, 0, 0, SIZE * 5,
  0, 0,        0, 0, 0, SIZE * 6
};

/// 3rd wheel, skips multiples of 2, 3 and 5
typedef WheelFactorization<30, 8, wheel30Init, wheel30> Modulo30Wheel_t;

/// 4th wheel, skips multiples of 2, 3, 5 and 7
typedef WheelFactorization<210, 48, wheel210Init, wheel210> Modulo210Wheel_t;

} // namespace

#endif
<commit_msg>Refactor<commit_after>///
/// @file   Wheel.hpp
/// @brief  Classes and structs related to wheel factorization.
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef WHEEL_HPP
#define WHEEL_HPP

#include "config.hpp"
#include "pmath.hpp"
#include "primesieve_error.hpp"

#include <stdint.h>
#include <cassert>
#include <string>

namespace primesieve {

/// The WheelInit data structure is used to calculate the
/// first multiple >= start of each sieving prime
///
struct WheelInit
{
  uint8_t nextMultipleFactor;
  uint8_t wheelIndex;
};

extern const WheelInit wheel30Init[30];
extern const WheelInit wheel210Init[210];

/// The WheelElement data structure is used to skip multiples
/// of small primes using wheel factorization
///
struct WheelElement
{
  /// Bitmask used to unset the bit corresponding to the current
  /// multiple of a SievingPrime object
  uint8_t unsetBit;
  /// Factor used to calculate the next multiple of a sieving prime
  /// that is not divisible by any of the wheel factors
  uint8_t nextMultipleFactor;
  /// Overflow needed to correct the next multiple index
  /// (due to sievingPrime = prime / 30)
  uint8_t correct;
  /// Used to calculate the next wheel index:
  /// wheelIndex += next;
  int8_t next;
};

extern const WheelElement wheel30[8*8];
extern const WheelElement wheel210[48*8];

/// Sieving primes are used to cross-off multiples.
/// Each SievingPrime object contains a sieving prime and the
/// position of its next multiple within the SieveOfEratosthenes
/// array (i.e. multipleIndex) and a wheelIndex.
///
class SievingPrime
{
public:
  enum
  {
    MAX_MULTIPLEINDEX = (1 << 23) - 1,
    MAX_WHEELINDEX    = (1 << (32 - 23)) - 1
  };

  SievingPrime() { }

  SievingPrime(uint_t sievingPrime,
               uint_t multipleIndex,
               uint_t wheelIndex)
  {
    set(multipleIndex, wheelIndex);
    sievingPrime_ = (uint32_t) sievingPrime;
  }

  void set(uint_t multipleIndex,
           uint_t wheelIndex)
  {
    assert(multipleIndex <= MAX_MULTIPLEINDEX);
    assert(wheelIndex <= MAX_WHEELINDEX);
    indexes_ = (uint32_t) (multipleIndex | (wheelIndex << 23));
  }

  void set(uint_t sievingPrime,
           uint_t multipleIndex,
           uint_t wheelIndex)
  {
    set(multipleIndex, wheelIndex);
    sievingPrime_ = (uint32_t) sievingPrime;
  }

  uint_t getSievingPrime() const
  {
    return sievingPrime_;
  }

  uint_t getMultipleIndex() const
  {
    return indexes_ & MAX_MULTIPLEINDEX;
  }

  uint_t getWheelIndex() const
  {
    return indexes_ >> 23;
  }

  void setMultipleIndex(uint_t multipleIndex)
  {
    assert(multipleIndex <= MAX_MULTIPLEINDEX);
    indexes_ = (uint32_t) (indexes_ | multipleIndex);
  }

  void setWheelIndex(uint_t wheelIndex)
  {
    assert(wheelIndex <= MAX_WHEELINDEX);
    indexes_ = (uint32_t) (wheelIndex << 23);
  }
private:
  /// multipleIndex = 23 least significant bits of indexes_
  /// wheelIndex = 9 most significant bits of indexes_
  uint32_t indexes_;
  uint32_t sievingPrime_;
};

/// The Bucket data structure is used to store sieving primes.
/// @see http://www.ieeta.pt/~tos/software/prime_sieve.html
/// The Bucket class is designed as a singly linked list, once there
/// is no more space in the current Bucket a new Bucket node is
/// allocated.
///
class Bucket
{
public:
  Bucket()              { reset(); }
  SievingPrime* begin() { return &sievingPrimes_[0]; }
  SievingPrime* last()  { return &sievingPrimes_[config::BUCKETSIZE - 1]; }
  SievingPrime* end()   { return prime_; }
  Bucket* next()        { return next_; }
  bool hasNext() const  { return next_ != nullptr; }
  bool empty()          { return begin() == end(); }
  void reset()          { prime_ = begin(); }
  void setNext(Bucket* next)
  {
    next_ = next;
  }
  /// Store a sieving prime in the bucket
  /// @return false if the bucket is full else true
  ///
  bool store(uint_t sievingPrime,
             uint_t multipleIndex,
             uint_t wheelIndex)
  {
    prime_->set(sievingPrime, multipleIndex, wheelIndex);
    return prime_++ != last();
  }
private:
  SievingPrime* prime_;
  Bucket* next_;
  SievingPrime sievingPrimes_[config::BUCKETSIZE];
};

/// The abstract WheelFactorization class is used skip multiples
/// of small primes in the sieve of Eratosthenes. The EratSmall,
/// EratMedium and EratBig classes are derived from
/// WheelFactorization.
///
template <uint_t MODULO, uint_t SIZE, const WheelInit* INIT, const WheelElement* WHEEL>
class WheelFactorization
{
public:
  /// Add a new sieving prime to the sieving algorithm.
  /// Calculate the first multiple > segmentLow of prime and the
  /// position within the SieveOfEratosthenes array of that multiple
  /// and its wheel index. When done store the sieving prime.
  ///
  void addSievingPrime(uint_t prime, uint64_t segmentLow)
  {
    segmentLow += 6;
    // calculate the first multiple (of prime) > segmentLow
    uint64_t quotient = segmentLow / prime + 1;
    uint64_t multiple = prime * quotient;
    // prime not needed for sieving
    if (multiple > stop_ ||
        multiple < segmentLow)
      return;
    // ensure multiple >= prime * prime
    if (quotient < prime)
    {
      multiple = isquare<uint64_t>(prime);
      quotient = prime;
    }
    // calculate the next multiple of prime that is not
    // divisible by any of the wheel's factors
    uint64_t nextMultipleFactor = INIT[quotient % MODULO].nextMultipleFactor;
    uint64_t nextMultiple = prime * nextMultipleFactor;
    if (nextMultiple > stop_ - multiple)
      return;
    nextMultiple += multiple - segmentLow;
    uint_t multipleIndex = (uint_t)(nextMultiple / NUMBERS_PER_BYTE);
    uint_t wheelIndex = wheelOffsets_[prime % NUMBERS_PER_BYTE] + INIT[quotient % MODULO].wheelIndex;
    storeSievingPrime(prime, multipleIndex, wheelIndex);
  }

protected:
  WheelFactorization(uint64_t stop, uint_t sieveSize) :
    stop_(stop)
  {
    uint_t maxSieveSize = SievingPrime::MAX_MULTIPLEINDEX + 1;

    if (sieveSize > maxSieveSize)
      throw primesieve_error("WheelFactorization: sieveSize must be <= " + std::to_string(maxSieveSize));
  }

  virtual ~WheelFactorization()
  { }

  virtual void storeSievingPrime(uint_t, uint_t, uint_t) = 0;

  static uint_t getMaxFactor()
  {
    return WHEEL[0].nextMultipleFactor;
  }

  /// Cross-off the current multiple of sievingPrime
  /// and calculate its next multiple
  ///
  static void unsetBit(byte_t* sieve, uint_t sievingPrime, uint_t* multipleIndex, uint_t* wheelIndex)
  {
    sieve[*multipleIndex] &= WHEEL[*wheelIndex].unsetBit;
    *multipleIndex        += WHEEL[*wheelIndex].nextMultipleFactor * sievingPrime;
    *multipleIndex        += WHEEL[*wheelIndex].correct;
    *wheelIndex           += WHEEL[*wheelIndex].next;
  }
private:
  static const uint_t wheelOffsets_[30];
  uint64_t stop_;
};

template <uint_t MODULO, uint_t SIZE, const WheelInit* INIT, const WheelElement* WHEEL>
const uint_t
WheelFactorization<MODULO, SIZE, INIT, WHEEL>::wheelOffsets_[30] =
{
  0, SIZE * 7, 0, 0, 0, 0,
  0, SIZE * 0, 0, 0, 0, SIZE * 1,
  0, SIZE * 2, 0, 0, 0, SIZE * 3,
  0, SIZE * 4, 0, 0, 0, SIZE * 5,
  0, 0,        0, 0, 0, SIZE * 6
};

/// 3rd wheel, skips multiples of 2, 3 and 5
typedef WheelFactorization<30, 8, wheel30Init, wheel30> Modulo30Wheel_t;

/// 4th wheel, skips multiples of 2, 3, 5 and 7
typedef WheelFactorization<210, 48, wheel210Init, wheel210> Modulo210Wheel_t;

} // namespace

#endif
<|endoftext|>


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

#include "KinectFaceMat.h"

cv::Rect* getHDfaceRect()
{
	/********    To be implemented later   *********/

	return nullptr;
}

cv::Rect* getSDFaceRect(IBodyFrameReader* _body_reader, IFaceFrameReader* _face_reader[],
	IFaceFrameSource* _face_source[], int& trackedFaces, HRESULT faceReaderinit, HRESULT bodyReaderInit)
{
	cv::Rect faceRect[BODY_COUNT];
	HRESULT hr;
	if (SUCCEEDED(faceReaderinit) && SUCCEEDED(bodyReaderInit)) {
		IBody* Bodies[BODY_COUNT] = { 0 };
		if (_body_reader != nullptr)
		{
			IBodyFrame* BodyFrame = nullptr;
			hr = _body_reader->AcquireLatestFrame(&BodyFrame);
			if (SUCCEEDED(hr))
			{
				hr = BodyFrame->GetAndRefreshBodyData(BODY_COUNT, Bodies);
			}
			SafeRelease(BodyFrame);
		}
		bool gotBodyData = SUCCEEDED(hr);

		// iterate through each face reader
		for (int iFace = 0; iFace < BODY_COUNT; ++iFace)
		{
			// fetch the latest face frame from current reader
			IFaceFrame* frame = nullptr;
			hr = _face_reader[iFace]->AcquireLatestFrame(&frame);

			BOOLEAN isFaceTracked = false;
			if (SUCCEEDED(hr) && nullptr != frame)
			{
				// check if a valid face is tracked in this face frame
				hr = frame->get_IsTrackingIdValid(&isFaceTracked);
			}

			if (SUCCEEDED(hr))
			{
				if (isFaceTracked)
				{
					IFaceFrameResult* FaceFrameResult = nullptr;
					RectI faceBox = { 0 };
					PointF facePoints[FacePointType::FacePointType_Count];

					hr = frame->get_FaceFrameResult(&FaceFrameResult);

					// ensure FaceFrameResult contains data before trying to access it
					if (SUCCEEDED(hr) && FaceFrameResult != nullptr)
					{
						hr = FaceFrameResult->get_FaceBoundingBoxInColorSpace(&faceBox);

						if (SUCCEEDED(hr))
						{
							hr = FaceFrameResult->GetFacePointsInColorSpace(FacePointType::FacePointType_Count, facePoints);
						}

						if (SUCCEEDED(hr)) {
							//gives the number of faces tracked
							trackedFaces++;
						}

						//Set the values of corresponding cv::Rect
						faceRect[iFace].x = faceBox.Left;
						faceRect[iFace].y = faceBox.Top;
						faceRect[iFace].width = faceBox.Right - faceBox.Left;
						faceRect[iFace].height = faceBox.Bottom - faceBox.Top;

					}

					SafeRelease(FaceFrameResult);
				}
				else
				{
					// face tracking is not valid - attempt to fix the issue
					// a valid body is required to perform this step
					if (gotBodyData)
					{
						// check if the corresponding body is tracked
						// if this is true then update the face frame source to track this body
						IBody* Body = Bodies[iFace];
						if (Body != nullptr)
						{
							BOOLEAN isTracked = false;
							hr = Body->get_IsTracked(&isTracked);

							UINT64 bodyTId;
							if (SUCCEEDED(hr) && isTracked)
							{
								// get the tracking ID of this body
								hr = Body->get_TrackingId(&bodyTId);
								if (SUCCEEDED(hr))
								{
									// update the face frame source with the tracking ID
									_face_source[iFace]->put_TrackingId(bodyTId);
								}
							}
						}
					}
				}
			}

			SafeRelease(frame);
		}

		if (gotBodyData)
		{
			for (int i = 0; i < _countof(Bodies); ++i)
			{
				SafeRelease(Bodies[i]);
			}
		}
	}
	return faceRect;
}
<commit_msg>Fixed KinectFaceMat (now tracks multiple faces)<commit_after>/*
* Copyright (C) 2016, Shubham Batra (https://www.github.com/batrashubham)
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/

#include "KinectFaceMat.h"

cv::Rect faceRects[BODY_COUNT];

cv::Rect* getHDfaceRect()
{
	/********    To be implemented later   *********/

	return nullptr;
}

cv::Rect* getSDFaceRect(IBodyFrameReader* _body_reader, IFaceFrameReader* _face_reader[],
	IFaceFrameSource* _face_source[], int& trackedFaces, HRESULT faceReaderinit, HRESULT bodyReaderInit)
{
	HRESULT hResult;
	if (SUCCEEDED(faceReaderinit) && SUCCEEDED(bodyReaderInit)) {
		IBodyFrame* pBodyFrame = nullptr;
		hResult = _body_reader->AcquireLatestFrame(&pBodyFrame);
		if (SUCCEEDED(hResult)) {
			IBody* pBody[BODY_COUNT] = { 0 };
			hResult = pBodyFrame->GetAndRefreshBodyData(BODY_COUNT, pBody);
			if (SUCCEEDED(hResult)) {
				for (int count = 0; count < BODY_COUNT; count++) {
					BOOLEAN bTracked = false;
					hResult = pBody[count]->get_IsTracked(&bTracked);
					if (SUCCEEDED(hResult) && bTracked) {
						/*// Joint
						Joint joint[JointType::JointType_Count];
						hResult = pBody[count]->GetJoints( JointType::JointType_Count, joint );
						if( SUCCEEDED( hResult ) ){
						for( int type = 0; type < JointType::JointType_Count; type++ ){
						ColorSpacePoint colorSpacePoint = { 0 };
						pCoordinateMapper->MapCameraPointToColorSpace( joint[type].Position, &colorSpacePoint );
						int x = static_cast<int>( colorSpacePoint.X );
						int y = static_cast<int>( colorSpacePoint.Y );
						if( ( x >= 0 ) && ( x < width ) && ( y >= 0 ) && ( y < height ) ){
						cv::circle( bufferMat, cv::Point( x, y ), 5, static_cast<cv::Scalar>( color[count] ), -1, CV_AA );
						}
						}
						}*/

						// Set TrackingID to Detect Face
						UINT64 trackingId = _UI64_MAX;
						hResult = pBody[count]->get_TrackingId(&trackingId);
						if (SUCCEEDED(hResult)) {
							_face_source[count]->put_TrackingId(trackingId);
						}
					}
				}
			}
			for (int count = 0; count < BODY_COUNT; count++) {
				SafeRelease(pBody[count]);
			}
		}
		SafeRelease(pBodyFrame);

		for (int iFace = 0; iFace < BODY_COUNT; iFace++) {
			IFaceFrame* pFaceFrame = nullptr;
			hResult = _face_reader[iFace]->AcquireLatestFrame(&pFaceFrame);
			if (SUCCEEDED(hResult) && pFaceFrame != nullptr) {
				BOOLEAN bFaceTracked = false;
				hResult = pFaceFrame->get_IsTrackingIdValid(&bFaceTracked);
				if (SUCCEEDED(hResult) && bFaceTracked) {
					IFaceFrameResult* pFaceResult = nullptr;
					hResult = pFaceFrame->get_FaceFrameResult(&pFaceResult);
					if (SUCCEEDED(hResult) && pFaceResult != nullptr) {
						RectI faceBox;
						hResult = pFaceResult->get_FaceBoundingBoxInColorSpace(&faceBox);
						if (SUCCEEDED(hResult)) {
							trackedFaces++;
							faceRects[iFace].x = faceBox.Left;
							faceRects[iFace].y = faceBox.Top;
							faceRects[iFace].width = faceBox.Right - faceBox.Left;
							faceRects[iFace].height = faceBox.Bottom - faceBox.Top;
						}
					}
					SafeRelease(pFaceResult);
				}
			}
			SafeRelease(pFaceFrame);
		}
	}
	return faceRects;
}<|endoftext|>