<commit_before>#include <catch.hpp>

#include <pmath/Vector.hpp>

using namespace pmath;

TEST_CASE("Vector2 tests", "[vector]")
{
	SECTION("Boolean tests")
	{
		CHECK(Vec2(1, 1) != Vec2(2, 1));
		CHECK(Vec2(2, 2) == Vec2(2, 2));
		CHECK_FALSE(Vec2(2, 2) == Vec2(1, 2));
		CHECK_FALSE(Vec2(2, 2) != Vec2(2, 2));
	}

	SECTION("Basic operators")
	{
		Vec2 vec1(5, 10);
		Vec2 vec2(2, 4);

		CHECK((vec1 - vec2) == Vec2(3, 6));
		CHECK((vec1 + vec2) == Vec2(7, 14));
		CHECK((vec1 * 2) == Vec2(10, 20));
		CHECK((vec2 / 2) == Vec2(1, 2));

		vec1 *= 2;
		CHECK(vec1 == Vec2(10, 20));
		vec2 /= 2;
		CHECK(vec2 == Vec2(1, 2));

		vec1 = Vec2(5, 10);
		vec2 = Vec2(2, 4);
		CHECK(vec1 == Vec2(5, 10));
		CHECK(vec2 == Vec2(2, 4));

		vec1 += Vec2(5, 5);
		vec2 -= Vec2(2, 4);
		CHECK(vec1 == Vec2(10, 15));
		CHECK(vec2 == Vec2());

        CHECK(Vec2(1, 2) > Vec2(1, 1));
        CHECK(Vec2(1, 2) >= Vec2(1, 2));
        CHECK(Vec2(1, 2) <= Vec2(2, 2));
        CHECK(Vec2(1, 2) < Vec2(-2, -2));

        vec1 = Vec2(1, 2);
        CHECK(vec1[0] == 1);
        CHECK(vec1[1] == 2);
	}

	SECTION("Dot, cross and length")
	{
		Vec2 vec1(2, 2);
		Vec2 vec2(5, 5);

		CHECK(vec1.dot(vec2) == 20);
		CHECK(Vec2::dot(vec1, vec2) == 20);

		CHECK(vec1.length() == sqrt(8.0));
		CHECK(vec2.lengthSquared() == 50);

        Vec2 a(1,2), b(9,8);
        CHECK(a.cross(b) == -10);
        CHECK(Vec2::cross(b, a) == 10);

		CHECK(Vec2::distance(Vec2(1, 2), Vec2(2,1)) == sqrt(2.0));
	}

    SECTION("Normals")
    {
        Vec2 vec(5, 9);
        CHECK(vec.unitVector() == Vec2(5 / sqrt(106.f), 9 / sqrt(106.f)));
        CHECK(vec.normalize() == Vec2(5 / sqrt(106.f), 9 / sqrt(106.f)));
    }
}

TEST_CASE("Vector3 tests", "[vector]")
{
	SECTION("Boolean tests")
	{
        Vec3 vec1(1, 2, 3);
        Vec3 vec2(3, 2, 1);

        CHECK(vec1 == Vec3(1, 2, 3));
        CHECK(vec1 != vec2);
        CHECK_FALSE(vec1 == vec2);
        CHECK_FALSE(vec2 != vec2);
	}

	SECTION("Basic operators")
	{
        Vec3 vec1(5, 10, 15);
        Vec3 vec2(2, 4, 8);

        CHECK(-vec1 == Vec3(-5, -10, -15));
        CHECK((vec1 - vec2) == Vec3(3, 6, 7));
        CHECK_FALSE((vec1 - vec2) == Vec3(7, 6, 3));
        CHECK((vec1 + vec2) == Vec3(7, 14, 23));
        CHECK_FALSE((vec1 + vec2) == Vec3(23, 14, 7));
        CHECK((vec1 * 2) == Vec3(10, 20, 30));
        CHECK((vec2 / 2) == Vec3(1, 2, 4));

        vec1 *= 2;
        CHECK(vec1 == Vec3(10, 20, 30));
        vec2 /= 2;
        CHECK(vec2 == Vec3(1, 2, 4));

        vec1 = Vec3(5, 10, 15);
        vec2 = Vec3(2, 4, 8);
        REQUIRE(vec1 == Vec3(5, 10, 15));
        REQUIRE(vec2 == Vec3(2, 4, 8));

        vec1 += Vec3(5, 5, 5);
        vec2 -= Vec3(2, 4, 8);
        CHECK(vec1 == Vec3(10, 15, 20));
        CHECK(vec2 == Vec3());

        CHECK(Vec3(1, 2, 3) > Vec3(1, 2, 2));
        CHECK(Vec3(1, 2, 3) >= Vec3(1, 2, 3));
        CHECK(Vec3(1, 2, 3) <= Vec3(2, 2, 3));
        CHECK(Vec3(1, 2, 3) < Vec3(-2, -2, -4));

        vec1 = Vec3(1, 2, 3);
        CHECK(vec1[1] == 2);
        CHECK(vec1[2] == 3);
	}

	SECTION("Dot, cross and length")
	{
        Vec3 vec1(1, 2, 3);
        Vec3 vec2(7, 8, 9);

        CHECK(vec1.dot(vec2) == 50);
        CHECK(Vec3::dot(vec2, vec1) == 50);

        CHECK(vec1.length() == sqrt(14.0));
        CHECK(vec2.lengthSquared() == 194);

        CHECK(vec1.cross(vec2) == Vec3(-6, 12, -6));
        CHECK(Vec3::cross(vec2, vec1) == Vec3(6, -12, 6));

		CHECK(Vec3::distance(Vec3(1, 2, 3), Vec3(3, 2, 1)) == 2*sqrt(2.0));
	}

    SECTION("Normals")
    {
        Vec3 vec(5, 9, 7);
        CHECK(vec.unitVector() == Vec3(sqrt(5.f / 31.f), 9 / sqrt(155.f), 7 / sqrt(155.f)));
        CHECK(vec.normalize() == Vec3(sqrt(5.f / 31.f), 9 / sqrt(155.f), 7 / sqrt(155.f)));
    }
}

TEST_CASE("Vector4 tests", "[vector]")
{
    SECTION("Boolean tests")
    {
        Vec4 vec1(1, 2, 3, 4);
        Vec4 vec2(4, 3, 2, 1);

        CHECK(vec1 == Vec4(1, 2, 3, 4));
        CHECK(vec1 != vec2);
        CHECK_FALSE(vec1 == vec2);
        CHECK_FALSE(vec2 != vec2);
    }

    SECTION("Basic operators")
    {
        Vec4 vec1(5, 10, 15, 20);
        Vec4 vec2(2, 4, 8, 16);

        CHECK(-vec1 == Vec4(-5, -10, -15, -20));
        CHECK((vec1 - vec2) == Vec4(3, 6, 7, 4));
        CHECK_FALSE((vec1 - vec2) == Vec4(4, 7, 6, 3));
        CHECK((vec1 + vec2) == Vec4(7, 14, 23, 36));
        CHECK_FALSE((vec1 + vec2) == Vec4(36, 23, 14, 7));
        CHECK((vec1 * 2) == Vec4(10, 20, 30, 40));
        CHECK((vec2 / 2) == Vec4(1, 2, 4, 8));

        vec1 *= 2;
        CHECK(vec1 == Vec4(10, 20, 30, 40));
        vec2 /= 2;
        CHECK(vec2 == Vec4(1, 2, 4, 8));

        vec1 = Vec4(5, 10, 15, 20);
        vec2 = Vec4(2, 4, 8, 16);
        REQUIRE(vec1 == Vec4(5, 10, 15, 20));
        REQUIRE(vec2 == Vec4(2, 4, 8, 16));

        vec1 += Vec4(5, 5, 5, 5);
        vec2 -= Vec4(2, 4, 8, 16);
        CHECK(vec1 == Vec4(10, 15, 20, 25));
        CHECK(vec2 == Vec4());

        CHECK(Vec4(1, 2, 3, 4) > Vec4(1, 2, 2, 3));
        CHECK(Vec4(1, 2, 3, 4) >= Vec4(1, 2, 3, 4));
        CHECK(Vec4(1, 2, 3, 4) <= Vec4(2, 2, 3, 4));
        CHECK(Vec4(1, 2, 3, 4) < Vec4(-2, -2, -4, -4));

        vec1 = Vec4(1, 2, 3, 4);
        CHECK(vec1[1] == 2);
        CHECK(vec1[3] == 4);
    }

    SECTION("Dot and length")
    {
        Vec4 vec1(1, 2, 3, 4);
        Vec4 vec2(7, 8, 9, 10);

        CHECK(vec1.dot(vec2) == 90);
        CHECK(Vec4::dot(vec2, vec1) == 90);

        CHECK(vec2.length() == sqrt(294.0));
        CHECK(vec1.lengthSquared() == 30);

		CHECK(Vec4::distance(Vec4(1, 2, 3, 4), Vec4(4,3,2,1)) == 2*sqrt(5.0));
    }

    SECTION("Normals")
    {
        Vec4 vec(5, 9, 3, 1);
        Vec4 result(5 / (2 * sqrt(29.f)), 9 / (2 * sqrt(29.f)),
            3 / (2 * sqrt(29.f)), 1 / (2 * sqrt(29.f)));

        CHECK(vec.unitVector() == result);
        CHECK(vec.normalize() == result);
    }
}<commit_msg>Fix tabs<commit_after>#include <catch.hpp>

#include <pmath/Vector.hpp>

using namespace pmath;

TEST_CASE("Vector2 tests", "[vector]")
{
    SECTION("Boolean tests")
    {
        CHECK(Vec2(1, 1) != Vec2(2, 1));
        CHECK(Vec2(2, 2) == Vec2(2, 2));
        CHECK_FALSE(Vec2(2, 2) == Vec2(1, 2));
        CHECK_FALSE(Vec2(2, 2) != Vec2(2, 2));
    }

    SECTION("Basic operators")
    {
        Vec2 vec1(5, 10);
        Vec2 vec2(2, 4);

        CHECK((vec1 - vec2) == Vec2(3, 6));
        CHECK((vec1 + vec2) == Vec2(7, 14));
        CHECK((vec1 * 2) == Vec2(10, 20));
        CHECK((vec2 / 2) == Vec2(1, 2));

        vec1 *= 2;
        CHECK(vec1 == Vec2(10, 20));
        vec2 /= 2;
        CHECK(vec2 == Vec2(1, 2));

        vec1 = Vec2(5, 10);
        vec2 = Vec2(2, 4);
        CHECK(vec1 == Vec2(5, 10));
        CHECK(vec2 == Vec2(2, 4));

        vec1 += Vec2(5, 5);
        vec2 -= Vec2(2, 4);
        CHECK(vec1 == Vec2(10, 15));
        CHECK(vec2 == Vec2());

        CHECK(Vec2(1, 2) > Vec2(1, 1));
        CHECK(Vec2(1, 2) >= Vec2(1, 2));
        CHECK(Vec2(1, 2) <= Vec2(2, 2));
        CHECK(Vec2(1, 2) < Vec2(-2, -2));

        vec1 = Vec2(1, 2);
        CHECK(vec1[0] == 1);
        CHECK(vec1[1] == 2);
    }

    SECTION("Dot, cross and length")
    {
        Vec2 vec1(2, 2);
        Vec2 vec2(5, 5);

        CHECK(vec1.dot(vec2) == 20);
        CHECK(Vec2::dot(vec1, vec2) == 20);

        CHECK(vec1.length() == sqrt(8.0));
        CHECK(vec2.lengthSquared() == 50);

        Vec2 a(1,2), b(9,8);
        CHECK(a.cross(b) == -10);
        CHECK(Vec2::cross(b, a) == 10);

        CHECK(Vec2::distance(Vec2(1, 2), Vec2(2,1)) == sqrt(2.0));
    }

    SECTION("Normals")
    {
        Vec2 vec(5, 9);
        CHECK(vec.unitVector() == Vec2(5 / sqrt(106.f), 9 / sqrt(106.f)));
        CHECK(vec.normalize() == Vec2(5 / sqrt(106.f), 9 / sqrt(106.f)));
    }
}

TEST_CASE("Vector3 tests", "[vector]")
{
    SECTION("Boolean tests")
    {
        Vec3 vec1(1, 2, 3);
        Vec3 vec2(3, 2, 1);

        CHECK(vec1 == Vec3(1, 2, 3));
        CHECK(vec1 != vec2);
        CHECK_FALSE(vec1 == vec2);
        CHECK_FALSE(vec2 != vec2);
    }

    SECTION("Basic operators")
    {
        Vec3 vec1(5, 10, 15);
        Vec3 vec2(2, 4, 8);

        CHECK(-vec1 == Vec3(-5, -10, -15));
        CHECK((vec1 - vec2) == Vec3(3, 6, 7));
        CHECK_FALSE((vec1 - vec2) == Vec3(7, 6, 3));
        CHECK((vec1 + vec2) == Vec3(7, 14, 23));
        CHECK_FALSE((vec1 + vec2) == Vec3(23, 14, 7));
        CHECK((vec1 * 2) == Vec3(10, 20, 30));
        CHECK((vec2 / 2) == Vec3(1, 2, 4));

        vec1 *= 2;
        CHECK(vec1 == Vec3(10, 20, 30));
        vec2 /= 2;
        CHECK(vec2 == Vec3(1, 2, 4));

        vec1 = Vec3(5, 10, 15);
        vec2 = Vec3(2, 4, 8);
        REQUIRE(vec1 == Vec3(5, 10, 15));
        REQUIRE(vec2 == Vec3(2, 4, 8));

        vec1 += Vec3(5, 5, 5);
        vec2 -= Vec3(2, 4, 8);
        CHECK(vec1 == Vec3(10, 15, 20));
        CHECK(vec2 == Vec3());

        CHECK(Vec3(1, 2, 3) > Vec3(1, 2, 2));
        CHECK(Vec3(1, 2, 3) >= Vec3(1, 2, 3));
        CHECK(Vec3(1, 2, 3) <= Vec3(2, 2, 3));
        CHECK(Vec3(1, 2, 3) < Vec3(-2, -2, -4));

        vec1 = Vec3(1, 2, 3);
        CHECK(vec1[1] == 2);
        CHECK(vec1[2] == 3);
    }

    SECTION("Dot, cross and length")
    {
        Vec3 vec1(1, 2, 3);
        Vec3 vec2(7, 8, 9);

        CHECK(vec1.dot(vec2) == 50);
        CHECK(Vec3::dot(vec2, vec1) == 50);

        CHECK(vec1.length() == sqrt(14.0));
        CHECK(vec2.lengthSquared() == 194);

        CHECK(vec1.cross(vec2) == Vec3(-6, 12, -6));
        CHECK(Vec3::cross(vec2, vec1) == Vec3(6, -12, 6));

        CHECK(Vec3::distance(Vec3(1, 2, 3), Vec3(3, 2, 1)) == 2*sqrt(2.0));
    }

    SECTION("Normals")
    {
        Vec3 vec(5, 9, 7);
        CHECK(vec.unitVector() == Vec3(sqrt(5.f / 31.f), 9 / sqrt(155.f), 7 / sqrt(155.f)));
        CHECK(vec.normalize() == Vec3(sqrt(5.f / 31.f), 9 / sqrt(155.f), 7 / sqrt(155.f)));
    }
}

TEST_CASE("Vector4 tests", "[vector]")
{
    SECTION("Boolean tests")
    {
        Vec4 vec1(1, 2, 3, 4);
        Vec4 vec2(4, 3, 2, 1);

        CHECK(vec1 == Vec4(1, 2, 3, 4));
        CHECK(vec1 != vec2);
        CHECK_FALSE(vec1 == vec2);
        CHECK_FALSE(vec2 != vec2);
    }

    SECTION("Basic operators")
    {
        Vec4 vec1(5, 10, 15, 20);
        Vec4 vec2(2, 4, 8, 16);

        CHECK(-vec1 == Vec4(-5, -10, -15, -20));
        CHECK((vec1 - vec2) == Vec4(3, 6, 7, 4));
        CHECK_FALSE((vec1 - vec2) == Vec4(4, 7, 6, 3));
        CHECK((vec1 + vec2) == Vec4(7, 14, 23, 36));
        CHECK_FALSE((vec1 + vec2) == Vec4(36, 23, 14, 7));
        CHECK((vec1 * 2) == Vec4(10, 20, 30, 40));
        CHECK((vec2 / 2) == Vec4(1, 2, 4, 8));

        vec1 *= 2;
        CHECK(vec1 == Vec4(10, 20, 30, 40));
        vec2 /= 2;
        CHECK(vec2 == Vec4(1, 2, 4, 8));

        vec1 = Vec4(5, 10, 15, 20);
        vec2 = Vec4(2, 4, 8, 16);
        REQUIRE(vec1 == Vec4(5, 10, 15, 20));
        REQUIRE(vec2 == Vec4(2, 4, 8, 16));

        vec1 += Vec4(5, 5, 5, 5);
        vec2 -= Vec4(2, 4, 8, 16);
        CHECK(vec1 == Vec4(10, 15, 20, 25));
        CHECK(vec2 == Vec4());

        CHECK(Vec4(1, 2, 3, 4) > Vec4(1, 2, 2, 3));
        CHECK(Vec4(1, 2, 3, 4) >= Vec4(1, 2, 3, 4));
        CHECK(Vec4(1, 2, 3, 4) <= Vec4(2, 2, 3, 4));
        CHECK(Vec4(1, 2, 3, 4) < Vec4(-2, -2, -4, -4));

        vec1 = Vec4(1, 2, 3, 4);
        CHECK(vec1[1] == 2);
        CHECK(vec1[3] == 4);
    }

    SECTION("Dot and length")
    {
        Vec4 vec1(1, 2, 3, 4);
        Vec4 vec2(7, 8, 9, 10);

        CHECK(vec1.dot(vec2) == 90);
        CHECK(Vec4::dot(vec2, vec1) == 90);

        CHECK(vec2.length() == sqrt(294.0));
        CHECK(vec1.lengthSquared() == 30);

        CHECK(Vec4::distance(Vec4(1, 2, 3, 4), Vec4(4,3,2,1)) == 2*sqrt(5.0));
    }

    SECTION("Normals")
    {
        Vec4 vec(5, 9, 3, 1);
        Vec4 result(5 / (2 * sqrt(29.f)), 9 / (2 * sqrt(29.f)),
            3 / (2 * sqrt(29.f)), 1 / (2 * sqrt(29.f)));

        CHECK(vec.unitVector() == result);
        CHECK(vec.normalize() == result);
    }
}<|endoftext|>


<commit_before>#pragma once

#include <csv.h>
#include <iostream>
#include <boost/lexical_cast.hpp>

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>

#include <typeinfo>

namespace csv {
namespace detail {

struct Result {
  int number{0};
  std::string message{"success"};
  operator bool() const { return number == 0; }
};
class MappedFile {
 private:
  int fd_;
  size_t size_;
  char* data_;

 public:
  MappedFile(const std::string& filename) : fd_(0), size_(0), data_(NULL) {
    fd_ = ::open(filename.c_str(), O_RDONLY);
    if (fd_ < 0) {
      set_error();
      return;
    }

    struct stat statbuf;
    if (::fstat(fd_, &statbuf) < 0) {
      set_error();
      return;
    }
    size_ = statbuf.st_size;

    data_ = (char*)::mmap(NULL, size_, PROT_READ, MAP_PRIVATE, fd_, 0);
    if (data_ == NULL) {
      set_error();
      return;
    }
  }
  ~MappedFile() {
    ::munmap(data_, size_);
    ::close(fd_);
  }

  const char* begin() const { return data_; }
  const char* end() const { return data_ + size_; }

  operator bool() { return status; }
  detail::Result status;

 private:
  void set_error() {
    status.number = errno;
    status.message = strerror(errno);
  }
};

// generates sequence numbers used in template expansion
namespace sequence {
template <int... Is>
struct index {};

template <int N, int... Is>
struct generate : generate<N - 1, N - 1, Is...> {};

template <int... Is>
struct generate<0, Is...> : index<Is...> {};
}  // namespace sequence

namespace meta {

template <class F>
class fields;
// function pointer
template <class R, class... Args>
class fields<R (*)(Args...)> : public fields<R(Args...)> {};
// member function pointer
template <class C, class R, class... Args>
class fields<R (C::*)(Args...)> : public fields<R(Args...)> {};
// const member function pointer
template <class C, class R, class... Args>
class fields<R (C::*)(Args...) const> : public fields<R(Args...)> {};
// member object pointer
template <class C, class R>
class fields<R(C::*)> : public fields<R(C&)> {};
// functor
template <class F>
class fields : public fields<decltype(&F::operator())> {};
// reference
template <class F>
class fields<F&> : public fields<F> {};
// perfect reference
template <class F>
class fields<F&&> : public fields<F> {};
// impl
template <class R, class... Args>
class fields<R(Args...)> {
  using mutator_t = std::function<void(const char* buf, size_t len)>;

 public:
  fields() {
    setupFieldHandlers(
        typename detail::sequence::generate<sizeof...(Args)>::index());
  }
  void accept_field(size_t field_pos, const char* buf, size_t len) {
    if (field_pos < mutators.size()) {
      mutators[field_pos](buf, len);
    }
  }
  template <typename F>
  void accept_row(F& sink) {
    call_func(sink,
              typename detail::sequence::generate<sizeof...(Args)>::index());
  }
  template <typename F, int... S>
  void call_func(F& sink, detail::sequence::index<S...>) {
    sink(std::get<S>(values)...);
  }

 private:
  std::tuple<typename std::decay<Args>::type...> values;
  std::vector<mutator_t> mutators;

 private:
  template <int... S>
  void setupFieldHandlers(detail::sequence::index<S...>) {
    setupFieldHandlers(std::get<S>(values)...);
  }
  template <typename F, typename... Fa>
  void setupFieldHandlers(F& arg, Fa&... args) {
    size_t field_num = mutators.size();
    mutators.push_back([field_num, &arg](const char* buf, size_t len) {
      if (len > 0) {
        arg = boost::lexical_cast<F>(buf, len);
      } else {
        arg = F();
      }
    });
    setupFieldHandlers(args...);
  }
  void setupFieldHandlers() {
    // this is the terminal function for recursive template expansion
  }
};

}  // namespace meta
}  // detail

/* A C++ wrapper around libcsv, see `make_parser` below */
struct filter_result {
  bool drop;
  constexpr filter_result(bool b) : drop(b) {}
  operator bool() const { return drop; }
};
static constexpr filter_result ROW_DROP{true};
static constexpr filter_result ROW_OK{false};

template <typename F>
class CsvParser {
  using this_type = CsvParser<F>;

 public:
  // return true if field should cause row to be ignored
  using filter_function_type = std::function<
      filter_result(size_t field_num, const char* buf, size_t len)>;
  using error_callback_type = std::function<
      filter_result(size_t line_number, size_t field_number,
                    const std::string& error_message, std::exception_ptr ex)>;
  CsvParser(const F& sink) : sink{sink} { csv_init(&parser, 0); }
  ~CsvParser() { csv_free(&parser); }

  //
  void set_delim_char(unsigned char delim) { parser.delim_char = delim; }
  void set_quote_char(unsigned char quote) { parser.quote_char = quote; }
  void set_skip_header() { skip_row = true; }
  void set_error_func(const error_callback_type func) { error_func = func; }
  void set_comment_mark(const std::string& prefix) {
    auto is_comment = [prefix](size_t field_num, const char* buf, size_t len) {
      return field_num == 0 &&          //
             len >= prefix.length() &&  //
             std::equal(prefix.begin(), prefix.end(), buf);
    };
    return add_row_filter(is_comment);
  }
  /* Limitation: Fields are coerced to their types as they are
   * encountered, so these filters can't prevent conversion by
   * looking at data later in the same row. */
  void add_row_filter(const filter_function_type filter) {
    auto orig = filter_func;
    filter_func = [orig, filter](size_t field_num, const char* buf,
                                 size_t len) {
      return orig(field_num, buf, len) || filter(field_num, buf, len);
    };
  }

  //
  bool ParseFile(const std::string& filename) {
    detail::MappedFile data(filename);
    if (!data) {
      return status = data.status;
    }
    return Parse(data.begin(), data.end()) && Finish();
  }
  template <typename T>
  bool Parse(const T& str) {
    return Parse(str.data(), str.data() + str.length());
  }
  template <typename It>
  bool Parse(const It& begin, const It& end) {
    csv_parse(&parser, begin, end - begin, on_field, on_record, this);
    return update_status();
  }
  template <typename IoStream>
  bool ParseStream(IoStream& input) {
    char buf[4096];
    do {
      input.read(buf, sizeof(buf));
      csv_parse(&parser, buf, input.gcount(), on_field, on_record, this);
    } while (input && update_status());
    return Finish();
  }
  bool Finish() {
    csv_fini(&parser, on_field, on_record, this);
    return update_status();
  }
  const std::string& ErrorString() { return status.message; }
  operator bool() { return status; }

 private:
  static void on_field(void* data, size_t len, void* this_ptr) {
    this_type* t = reinterpret_cast<this_type*>(this_ptr);
    t->accept_field((char*)data, len);
  }
  static void on_record(int, void* this_ptr) {
    this_type* t = reinterpret_cast<this_type*>(this_ptr);
    t->accept_row();
  };

 private:
  detail::meta::fields<F> fields;
  csv_parser parser;
  const F& sink;
  detail::Result status;
  filter_function_type filter_func = [](size_t, const char*,
                                        size_t) { return ROW_OK; };
  error_callback_type error_func = [](size_t row, size_t column,
                                      const std::string& err,
                                      const std::exception_ptr) {
    std::cerr << "[csv.hpp] Exception at row " << row << ", column " << column
              << ": " << err << "\n";
    return ROW_DROP;
  };
  bool skip_row{false};
  size_t current_line = 0;
  size_t current_field = 0;

 private:
  void accept_field(const char* buf, size_t len) {
    skip_row = skip_row || filter_func(current_field, buf, len);
    if (!skip_row) {
      try {
        fields.accept_field(current_field, buf, len);
      }
      catch (std::exception& e) {
        skip_row = error_func(current_line + 1, current_field + 1, e.what(),
                              std::current_exception());
      }
    }
    ++current_field;
  }
  void accept_row() {
    if (!skip_row) {
      fields.accept_row(sink);
    } else {
      skip_row = false;
    }
    current_field = 0;
    ++current_line;
  }
  const detail::Result& update_status() {
    if (status.number == 0 && parser.status != 0) {
      status.number = parser.status;
      status.message = csv_error(&parser);
    }
    return status;
  }
};

template <typename F>
CsvParser<F> make_parser(F&& f) {
  return CsvParser<F>(f);
}

// used to ignore input fields
struct ignore {};

}  // namespace csv

namespace boost {
template <>
csv::ignore lexical_cast(const char*, size_t) {
  static csv::ignore instance;
  return instance;
}
}
<commit_msg>Add missing include vector<commit_after>#pragma once

#include <csv.h>
#include <vector>
#include <iostream>
#include <boost/lexical_cast.hpp>

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>

#include <typeinfo>

namespace csv {
namespace detail {

struct Result {
  int number{0};
  std::string message{"success"};
  operator bool() const { return number == 0; }
};
class MappedFile {
 private:
  int fd_;
  size_t size_;
  char* data_;

 public:
  MappedFile(const std::string& filename) : fd_(0), size_(0), data_(NULL) {
    fd_ = ::open(filename.c_str(), O_RDONLY);
    if (fd_ < 0) {
      set_error();
      return;
    }

    struct stat statbuf;
    if (::fstat(fd_, &statbuf) < 0) {
      set_error();
      return;
    }
    size_ = statbuf.st_size;

    data_ = (char*)::mmap(NULL, size_, PROT_READ, MAP_PRIVATE, fd_, 0);
    if (data_ == NULL) {
      set_error();
      return;
    }
  }
  ~MappedFile() {
    ::munmap(data_, size_);
    ::close(fd_);
  }

  const char* begin() const { return data_; }
  const char* end() const { return data_ + size_; }

  operator bool() { return status; }
  detail::Result status;

 private:
  void set_error() {
    status.number = errno;
    status.message = strerror(errno);
  }
};

// generates sequence numbers used in template expansion
namespace sequence {
template <int... Is>
struct index {};

template <int N, int... Is>
struct generate : generate<N - 1, N - 1, Is...> {};

template <int... Is>
struct generate<0, Is...> : index<Is...> {};
}  // namespace sequence

namespace meta {

template <class F>
class fields;
// function pointer
template <class R, class... Args>
class fields<R (*)(Args...)> : public fields<R(Args...)> {};
// member function pointer
template <class C, class R, class... Args>
class fields<R (C::*)(Args...)> : public fields<R(Args...)> {};
// const member function pointer
template <class C, class R, class... Args>
class fields<R (C::*)(Args...) const> : public fields<R(Args...)> {};
// member object pointer
template <class C, class R>
class fields<R(C::*)> : public fields<R(C&)> {};
// functor
template <class F>
class fields : public fields<decltype(&F::operator())> {};
// reference
template <class F>
class fields<F&> : public fields<F> {};
// perfect reference
template <class F>
class fields<F&&> : public fields<F> {};
// impl
template <class R, class... Args>
class fields<R(Args...)> {
  using mutator_t = std::function<void(const char* buf, size_t len)>;

 public:
  fields() {
    setupFieldHandlers(
        typename detail::sequence::generate<sizeof...(Args)>::index());
  }
  void accept_field(size_t field_pos, const char* buf, size_t len) {
    if (field_pos < mutators.size()) {
      mutators[field_pos](buf, len);
    }
  }
  template <typename F>
  void accept_row(F& sink) {
    call_func(sink,
              typename detail::sequence::generate<sizeof...(Args)>::index());
  }
  template <typename F, int... S>
  void call_func(F& sink, detail::sequence::index<S...>) {
    sink(std::get<S>(values)...);
  }

 private:
  std::tuple<typename std::decay<Args>::type...> values;
  std::vector<mutator_t> mutators;

 private:
  template <int... S>
  void setupFieldHandlers(detail::sequence::index<S...>) {
    setupFieldHandlers(std::get<S>(values)...);
  }
  template <typename F, typename... Fa>
  void setupFieldHandlers(F& arg, Fa&... args) {
    size_t field_num = mutators.size();
    mutators.push_back([field_num, &arg](const char* buf, size_t len) {
      if (len > 0) {
        arg = boost::lexical_cast<F>(buf, len);
      } else {
        arg = F();
      }
    });
    setupFieldHandlers(args...);
  }
  void setupFieldHandlers() {
    // this is the terminal function for recursive template expansion
  }
};

}  // namespace meta
}  // detail

/* A C++ wrapper around libcsv, see `make_parser` below */
struct filter_result {
  bool drop;
  constexpr filter_result(bool b) : drop(b) {}
  operator bool() const { return drop; }
};
static constexpr filter_result ROW_DROP{true};
static constexpr filter_result ROW_OK{false};

template <typename F>
class CsvParser {
  using this_type = CsvParser<F>;

 public:
  // return true if field should cause row to be ignored
  using filter_function_type = std::function<
      filter_result(size_t field_num, const char* buf, size_t len)>;
  using error_callback_type = std::function<
      filter_result(size_t line_number, size_t field_number,
                    const std::string& error_message, std::exception_ptr ex)>;
  CsvParser(const F& sink) : sink{sink} { csv_init(&parser, 0); }
  ~CsvParser() { csv_free(&parser); }

  //
  void set_delim_char(unsigned char delim) { parser.delim_char = delim; }
  void set_quote_char(unsigned char quote) { parser.quote_char = quote; }
  void set_skip_header() { skip_row = true; }
  void set_error_func(const error_callback_type func) { error_func = func; }
  void set_comment_mark(const std::string& prefix) {
    auto is_comment = [prefix](size_t field_num, const char* buf, size_t len) {
      return field_num == 0 &&          //
             len >= prefix.length() &&  //
             std::equal(prefix.begin(), prefix.end(), buf);
    };
    return add_row_filter(is_comment);
  }
  /* Limitation: Fields are coerced to their types as they are
   * encountered, so these filters can't prevent conversion by
   * looking at data later in the same row. */
  void add_row_filter(const filter_function_type filter) {
    auto orig = filter_func;
    filter_func = [orig, filter](size_t field_num, const char* buf,
                                 size_t len) {
      return orig(field_num, buf, len) || filter(field_num, buf, len);
    };
  }

  //
  bool ParseFile(const std::string& filename) {
    detail::MappedFile data(filename);
    if (!data) {
      return status = data.status;
    }
    return Parse(data.begin(), data.end()) && Finish();
  }
  template <typename T>
  bool Parse(const T& str) {
    return Parse(str.data(), str.data() + str.length());
  }
  template <typename It>
  bool Parse(const It& begin, const It& end) {
    csv_parse(&parser, begin, end - begin, on_field, on_record, this);
    return update_status();
  }
  template <typename IoStream>
  bool ParseStream(IoStream& input) {
    char buf[4096];
    do {
      input.read(buf, sizeof(buf));
      csv_parse(&parser, buf, input.gcount(), on_field, on_record, this);
    } while (input && update_status());
    return Finish();
  }
  bool Finish() {
    csv_fini(&parser, on_field, on_record, this);
    return update_status();
  }
  const std::string& ErrorString() { return status.message; }
  operator bool() { return status; }

 private:
  static void on_field(void* data, size_t len, void* this_ptr) {
    this_type* t = reinterpret_cast<this_type*>(this_ptr);
    t->accept_field((char*)data, len);
  }
  static void on_record(int, void* this_ptr) {
    this_type* t = reinterpret_cast<this_type*>(this_ptr);
    t->accept_row();
  };

 private:
  detail::meta::fields<F> fields;
  csv_parser parser;
  const F& sink;
  detail::Result status;
  filter_function_type filter_func = [](size_t, const char*,
                                        size_t) { return ROW_OK; };
  error_callback_type error_func = [](size_t row, size_t column,
                                      const std::string& err,
                                      const std::exception_ptr) {
    std::cerr << "[csv.hpp] Exception at row " << row << ", column " << column
              << ": " << err << "\n";
    return ROW_DROP;
  };
  bool skip_row{false};
  size_t current_line = 0;
  size_t current_field = 0;

 private:
  void accept_field(const char* buf, size_t len) {
    skip_row = skip_row || filter_func(current_field, buf, len);
    if (!skip_row) {
      try {
        fields.accept_field(current_field, buf, len);
      }
      catch (std::exception& e) {
        skip_row = error_func(current_line + 1, current_field + 1, e.what(),
                              std::current_exception());
      }
    }
    ++current_field;
  }
  void accept_row() {
    if (!skip_row) {
      fields.accept_row(sink);
    } else {
      skip_row = false;
    }
    current_field = 0;
    ++current_line;
  }
  const detail::Result& update_status() {
    if (status.number == 0 && parser.status != 0) {
      status.number = parser.status;
      status.message = csv_error(&parser);
    }
    return status;
  }
};

template <typename F>
CsvParser<F> make_parser(F&& f) {
  return CsvParser<F>(f);
}

// used to ignore input fields
struct ignore {};

}  // namespace csv

namespace boost {
template <>
csv::ignore lexical_cast(const char*, size_t) {
  static csv::ignore instance;
  return instance;
}
}
<|endoftext|>


<commit_before>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/
#include "PackedColumn.h"

template<>
InputParameters validParams<PackedColumn>()
{
  InputParameters params = validParams<Material>();

  // Add a parameter to get the radius of the balls in the column
  // (used later to interpolate permeability).
  params.addParam<Real>("ball_radius",
                        "The radius of the steel balls that are packed in the column. "
                        "Used to interpolate _permeability.");
  return params;
}

PackedColumn::PackedColumn(const InputParameters & parameters) :
    Material(parameters),
    // Get the one parameter from the input file
    _ball_radius(getParam<Real>("ball_radius")),
    // Declare two material properties.  This returns references that
    // we hold onto as member variables.
    _permeability(declareProperty<Real>("permeability")),
    _porosity(declareProperty<Real>("porosity")),
    _viscosity(declareProperty<Real>("viscosity")),
    _thermal_conductivity(declareProperty<Real>("thermal_conductivity")),
    _heat_capacity(declareProperty<Real>("heat_capacity")),
    _density(declareProperty<Real>("density"))
{
  // The media is modeled by spheres with different radii.
  std::vector<Real> ball_sizes(2);
  ball_sizes[0] = 1;
  ball_sizes[1] = 3;

  // From the paper: Table 1
  std::vector<Real> permeability(2);
  permeability[0] = 0.8451e-9;
  permeability[1] = 8.968e-9;

  // Set the x,y data on the LinearInterpolation object.
  _permeability_interpolation.setData(ball_sizes, permeability);
}

void
PackedColumn::computeQpProperties()
{
  // Viscosity of Water in Pa*s at 30 degrees C (Wikipedia)
  _viscosity[_qp] = 7.98e-4;

  // Sample the LinearInterpolation object to get the permeability for the ball size
  _permeability[_qp] = _permeability_interpolation.sample(_ball_radius);

  // Compute the heat conduction material properties as a linear combination of
  // the material properties for water and steel.

  // We're assuming close packing, so the porosity will be
  // approximately 1 - 0.74048 = 0.25952.  See:
  // http://en.wikipedia.org/wiki/Close-packing_of_equal_spheres
  _porosity[_qp] = 0.25952;

  // We will compute "bulk" thermal conductivity, specific heat, and
  // density as linear combinations of the water and steel (all values
  // are from Wikipedia).
  Real water_k = 0.6;  // (W/m*K)
  Real water_cp = 4181.3; // (J/kg*K)
  Real water_rho = 995.6502;  // (kg/m^3 @ 303K)

  Real steel_k = 18;  // (W/m*K)
  Real steel_cp = 466;  // (J/kg*K)
  Real steel_rho = 8000;  // (kg/m^3)

  // Now actually set the value at the quadrature point
  _thermal_conductivity[_qp] = _porosity[_qp]*water_k + (1.0-_porosity[_qp])*steel_k;
  _density[_qp] = _porosity[_qp]*water_rho + (1.0-_porosity[_qp])*steel_rho;
  _heat_capacity[_qp] = _porosity[_qp]*water_cp*water_rho + (1.0-_porosity[_qp])*steel_cp*steel_rho;
}
<commit_msg>Tutorial: Use C++11 vector initialization in step06.<commit_after>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/
#include "PackedColumn.h"

template<>
InputParameters validParams<PackedColumn>()
{
  InputParameters params = validParams<Material>();

  // Add a parameter to get the radius of the balls in the column
  // (used later to interpolate permeability).
  params.addParam<Real>("ball_radius",
                        "The radius of the steel balls that are packed in the column. "
                        "Used to interpolate _permeability.");
  return params;
}

PackedColumn::PackedColumn(const InputParameters & parameters) :
    Material(parameters),
    // Get the one parameter from the input file
    _ball_radius(getParam<Real>("ball_radius")),
    // Declare two material properties.  This returns references that
    // we hold onto as member variables.
    _permeability(declareProperty<Real>("permeability")),
    _porosity(declareProperty<Real>("porosity")),
    _viscosity(declareProperty<Real>("viscosity")),
    _thermal_conductivity(declareProperty<Real>("thermal_conductivity")),
    _heat_capacity(declareProperty<Real>("heat_capacity")),
    _density(declareProperty<Real>("density"))
{
  std::vector<Real> ball_sizes = {1, 3};

  // From the paper: Table 1
  std::vector<Real> permeability = {0.8451e-9, 8.968e-9};

  // Set the x,y data on the LinearInterpolation object.
  _permeability_interpolation.setData(ball_sizes, permeability);
}

void
PackedColumn::computeQpProperties()
{
  // Viscosity of Water in Pa*s at 30 degrees C (Wikipedia)
  _viscosity[_qp] = 7.98e-4;

  // Sample the LinearInterpolation object to get the permeability for the ball size
  _permeability[_qp] = _permeability_interpolation.sample(_ball_radius);

  // Compute the heat conduction material properties as a linear combination of
  // the material properties for water and steel.

  // We're assuming close packing, so the porosity will be
  // approximately 1 - 0.74048 = 0.25952.  See:
  // http://en.wikipedia.org/wiki/Close-packing_of_equal_spheres
  _porosity[_qp] = 0.25952;

  // We will compute "bulk" thermal conductivity, specific heat, and
  // density as linear combinations of the water and steel (all values
  // are from Wikipedia).
  Real water_k = 0.6;  // (W/m*K)
  Real water_cp = 4181.3; // (J/kg*K)
  Real water_rho = 995.6502;  // (kg/m^3 @ 303K)

  Real steel_k = 18;  // (W/m*K)
  Real steel_cp = 466;  // (J/kg*K)
  Real steel_rho = 8000;  // (kg/m^3)

  // Now actually set the value at the quadrature point
  _thermal_conductivity[_qp] = _porosity[_qp]*water_k + (1.0-_porosity[_qp])*steel_k;
  _density[_qp] = _porosity[_qp]*water_rho + (1.0-_porosity[_qp])*steel_rho;
  _heat_capacity[_qp] = _porosity[_qp]*water_cp*water_rho + (1.0-_porosity[_qp])*steel_cp*steel_rho;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <sstream>
#include <map>
#include <unordered_map>
#include <vector>
#include <string>
#include "dict.h"
#include "dictglobal.h"

typedef std::unordered_map<std::string, std::string> Dict;
typedef unsigned long IdentificatorType;

// consider map<unsigned long, unordered_map>
// somehow initialize dictglobal dictionary
std::map<IdentificatorType, Dict> dictionaries;
IdentificatorType dictCounter = dict_global();

static std::string parse_char_param(std::string param) {
    if (param != "")
        return "\"" + param + "\"";
    else
        return "NULL";
}

static void function_called_msg(std::string funcName,
                                std::string params) {
    std::cerr << funcName << "(" << params << ")" << std::endl;
}

static void dict_new_msg(IdentificatorType id) {
    std::cerr << "dict_new: dict " << id
              << " has been created" << std::endl;
}

static void dict_delete_success_msg(IdentificatorType id) {
    std::cerr << "dict_delete: dict " << id
              << " has been deleted" << std::endl;
}

static void dict_delete_error_msg() {
    std::cerr << "dict_delete: an attempt to remove the Global Dictionary"
              << std::endl;
}

static void dict_description_msg(IdentificatorType id) {
    if (id == dict_global())
        std::cerr << "dict " << id;
    else
        std::cerr << "the Global Dictionary";
}

static void dict_size_msg(IdentificatorType id, size_t size) {
    std::cerr << "dict_size: ";

    dict_description_msg(id);

    std::cerr << " contains " << size << " element(s)" << std::endl;
}

static void dict_insert_success_msg(IdentificatorType id,
                                    std::string key,
                                    std::string value) {
    std::cerr << "dict_insert: ";

    dict_description_msg(id);

    std::cerr << ", the pair (" << key << ", " << value << ")"
              << "has been inserted" << std::endl;
}

static void dict_insert_error_msg(IdentificatorType id, std::string param) {
    std::cerr << "dict_insert: dict " << id
              << " an attempt to insert NULL " << param << std::endl;
}

static void dict_not_found_msg(std::string funcName, IdentificatorType id) {
    std::cerr << funcName << ": dict " << id << " does not exist" << "\n";
}

static void key_not_found_msg(std::string funcName,
                              IdentificatorType id,
                              const char* key) {
    std::cerr << funcName << ": dict " << id
              << " does not contain the key " << key << "\"\n";
}

static void key_removed_msg(std::string funcName,
                            IdentificatorType id,
                            const char* key) {
    std::cerr << funcName << ": dict " << id
              << ", the key \"" << key << "\" has been removed\n";
}

static void value_found_msg(std::string funcName,
                            IdentificatorType id,
                            const char* key,
                            std::string value) {
    std::cerr << funcName << ": dict " << id
              << ", the key \"" << key
              << "\" has the value \"" << value << "\"\n";
}

static void dict_copied_msg(std::string funcName,
                            IdentificatorType src_id,
                            IdentificatorType dst_id) {
    std::cerr << funcName << ": dict " << src_id
              << " has been copied into dict " << dst_id << "\n";
}

static void search_global_dict_msg(std::string funcName) {
    std::cerr << funcName << ": looking up the Global Dictionary\n";
}

static void dict_cleared_msg(std::string funcName, IdentificatorType id) {
    std::cerr << funcName << ": dict " << id << " has been cleared\n";
}

IdentificatorType dict_new() {
    function_called_msg("dict_new", "");
    dictionaries.insert(std::make_pair(++dictCounter, Dict()));

    dict_new_msg(dictCounter);

    return dictCounter;
}

void dict_delete(unsigned long id) {
    std::stringstream ss;
    ss << id;
    function_called_msg("dict_delete", ss.str());

    auto dictionaryIt = dictionaries.find(id);
    if (dictionaryIt != dictionaries.end()) {
        if (id == dict_global()) {
            dict_delete_error_msg();
        }
        else {
            dictionaries.erase(id);
            dict_delete_success_msg(id);
        }
    }
}

size_t dict_size(unsigned long id) {
    std::stringstream ss;
    ss << id;
    function_called_msg("dict_size", ss.str());

    auto dictionaryIt = dictionaries.find(id);
    if (dictionaryIt != dictionaries.end()) {
        size_t dictSize = dictionaryIt->second.size();

        dict_size_msg(id, dictSize);

        return dictSize;
    }
    else {
        dict_not_found_msg("dict_size", id);
        return 0;
    }
}

void dict_insert(unsigned long id, const char* key, const char* value) {
    std::stringstream ss;
    std::string keyStr, valueStr;
    keyStr = parse_char_param(key);
    valueStr = parse_char_param(value);
    ss << id << ", " << keyStr << ", " << valueStr;

    function_called_msg("dict_insert", ss.str());

    auto dictionaryIt = dictionaries.find(id);
    if (dictionaryIt != dictionaries.end()) {
        if (key == NULL) {
            dict_insert_error_msg(id, "key");
        }
        else if (value == NULL) {
            dict_insert_error_msg(id, "value");
        }
        else {
            dictionaryIt->second.insert(std::make_pair(key, value));
            dict_insert_success_msg(id, keyStr, valueStr);
        }
    }
    else
        dict_not_found_msg("dict_insert", id);
}

void dict_remove(IdentificatorType id, const char* key) {
    auto dictionaryIt = dictionaries.find(id);
    if (dictionaryIt != dictionaries.end()) {
        if (dictionaryIt->second.erase(key) > 0) {
            key_removed_msg("dict_remove", id, key);
        }
        else {
            key_not_found_msg("dict_remove", id, key);
        }
    }
    else {
        dict_not_found_msg("dict_remove", id);
    }
}

const char* dict_find(IdentificatorType id, const char* key) {
    auto dictionaryIt = dictionaries.find(id);
    if (dictionaryIt != dictionaries.end()) {
        auto stringIt = dictionaryIt->second.find(key);
        if (stringIt != dictionaryIt->second.end()) {
            value_found_msg("dict_find", id, key, stringIt->second);

            return stringIt->second.c_str();
        }
        else {
            key_not_found_msg("dict_find", id, key);
        }
    }
    else {
        dict_not_found_msg("dict_find", id);
    }

    search_global_dict_msg("dict_find");

    auto stringIt = dictionaries.at(dict_global()).find(key);
    if (stringIt != dictionaries.at(dict_global()).end()) {
        value_found_msg("dict_find", dict_global(), key, stringIt->second);

        return stringIt->second.c_str();
    }
    else {
        key_not_found_msg("dict_find", dict_global(), key);
    }

    return NULL;
}

void dict_clear(IdentificatorType id) {
    auto dictionaryIt = dictionaries.find(id);
    if (dictionaryIt != dictionaries.end()) {
        dict_cleared_msg("dict_clear", id);

        dictionaryIt->second.clear();
    }
    else {
        dict_not_found_msg("dict_clear", id);
    }
}

void dict_copy(IdentificatorType src_id, IdentificatorType dst_id) {
    auto srcDictionaryIt = dictionaries.find(src_id);
    auto dstDictionaryIt = dictionaries.find(dst_id);
    if (srcDictionaryIt != dictionaries.end() &&
        dstDictionaryIt != dictionaries.end()) {
        // do not copy if destination dictionary is dictglobal and amount of keys exceeds size

        // copy contents
    }
}<commit_msg>Fixed dict_insert<commit_after>#include <iostream>
#include <sstream>
#include <map>
#include <unordered_map>
#include <vector>
#include <string>
#include "dict.h"
#include "dictglobal.h"

typedef std::unordered_map<std::string, std::string> Dict;
typedef unsigned long IdentificatorType;

// consider map<unsigned long, unordered_map>
// somehow initialize dictglobal dictionary
std::map<IdentificatorType, Dict> dictionaries;
IdentificatorType dictCounter = dict_global();

static std::string parse_char_param(std::string param) {
    if (param != "")
        return "\"" + param + "\"";
    else
        return "NULL";
}

static void function_called_msg(std::string funcName,
                                std::string params) {
    std::cerr << funcName << "(" << params << ")" << std::endl;
}

static void dict_new_msg(IdentificatorType id) {
    std::cerr << "dict_new: dict " << id
              << " has been created" << std::endl;
}

static void dict_delete_success_msg(IdentificatorType id) {
    std::cerr << "dict_delete: dict " << id
              << " has been deleted" << std::endl;
}

static void dict_delete_error_msg() {
    std::cerr << "dict_delete: an attempt to remove the Global Dictionary"
              << std::endl;
}

static void dict_description_msg(IdentificatorType id) {
    if (id == dict_global())
        std::cerr << "dict " << id;
    else
        std::cerr << "the Global Dictionary";
}

static void dict_size_msg(IdentificatorType id, size_t size) {
    std::cerr << "dict_size: ";

    dict_description_msg(id);

    std::cerr << " contains " << size << " element(s)" << std::endl;
}

static void dict_insert_success_msg(IdentificatorType id,
                                    std::string key,
                                    std::string value) {
    std::cerr << "dict_insert: ";

    dict_description_msg(id);

    std::cerr << ", the pair (" << key << ", " << value << ")"
              << "has been inserted" << std::endl;
}

static void dict_insert_error_msg(IdentificatorType id, std::string param) {
    std::cerr << "dict_insert: dict " << id
              << " an attempt to insert NULL " << param << std::endl;
}

static void dict_not_found_msg(std::string funcName, IdentificatorType id) {
    std::cerr << funcName << ": dict " << id << " does not exist" << "\n";
}

static void key_not_found_msg(std::string funcName,
                              IdentificatorType id,
                              const char* key) {
    std::cerr << funcName << ": dict " << id
              << " does not contain the key " << key << "\"\n";
}

static void key_removed_msg(std::string funcName,
                            IdentificatorType id,
                            const char* key) {
    std::cerr << funcName << ": dict " << id
              << ", the key \"" << key << "\" has been removed\n";
}

static void value_found_msg(std::string funcName,
                            IdentificatorType id,
                            const char* key,
                            std::string value) {
    std::cerr << funcName << ": dict " << id
              << ", the key \"" << key
              << "\" has the value \"" << value << "\"\n";
}

static void dict_copied_msg(std::string funcName,
                            IdentificatorType src_id,
                            IdentificatorType dst_id) {
    std::cerr << funcName << ": dict " << src_id
              << " has been copied into dict " << dst_id << "\n";
}

static void search_global_dict_msg(std::string funcName) {
    std::cerr << funcName << ": looking up the Global Dictionary\n";
}

static void dict_cleared_msg(std::string funcName, IdentificatorType id) {
    std::cerr << funcName << ": dict " << id << " has been cleared\n";
}

IdentificatorType dict_new() {
    function_called_msg("dict_new", "");
    dictionaries.insert(std::make_pair(++dictCounter, Dict()));

    dict_new_msg(dictCounter);

    return dictCounter;
}

void dict_delete(unsigned long id) {
    std::stringstream ss;
    ss << id;
    function_called_msg("dict_delete", ss.str());

    auto dictionaryIt = dictionaries.find(id);
    if (dictionaryIt != dictionaries.end()) {
        if (id == dict_global()) {
            dict_delete_error_msg();
        }
        else {
            dictionaries.erase(id);
            dict_delete_success_msg(id);
        }
    }
}

size_t dict_size(unsigned long id) {
    std::stringstream ss;
    ss << id;
    function_called_msg("dict_size", ss.str());

    auto dictionaryIt = dictionaries.find(id);
    if (dictionaryIt != dictionaries.end()) {
        size_t dictSize = dictionaryIt->second.size();

        dict_size_msg(id, dictSize);

        return dictSize;
    }
    else {
        dict_not_found_msg("dict_size", id);
        return 0;
    }
}

void dict_insert(unsigned long id, const char* key, const char* value) {
    std::stringstream ss;
    std::string keyDescription, valueDescription;
    keyDescription = parse_char_param(key);
    valueDescription = parse_char_param(value);
    ss << id << ", " << keyDescription << ", " << valueDescription;

    function_called_msg("dict_insert", ss.str());

    auto dictionaryIt = dictionaries.find(id);
    if (dictionaryIt != dictionaries.end()) {
        if (key == NULL) {
            dict_insert_error_msg(id, "key");
        }
        else if (value == NULL) {
            dict_insert_error_msg(id, "value");
        }
        else {
            std::string keyStr(key);
            std::string valueStr(value);

            dictionaryIt->second.insert(std::make_pair(keyStr, valueStr));
            dict_insert_success_msg(id, keyDescription, valueDescription);
        }
    }
    else
        dict_not_found_msg("dict_insert", id);
}

void dict_remove(IdentificatorType id, const char* key) {
    auto dictionaryIt = dictionaries.find(id);
    if (dictionaryIt != dictionaries.end()) {
        if (dictionaryIt->second.erase(key) > 0) {
            key_removed_msg("dict_remove", id, key);
        }
        else {
            key_not_found_msg("dict_remove", id, key);
        }
    }
    else {
        dict_not_found_msg("dict_remove", id);
    }
}

const char* dict_find(IdentificatorType id, const char* key) {
    auto dictionaryIt = dictionaries.find(id);
    if (dictionaryIt != dictionaries.end()) {
        auto stringIt = dictionaryIt->second.find(key);
        if (stringIt != dictionaryIt->second.end()) {
            value_found_msg("dict_find", id, key, stringIt->second);

            return stringIt->second.c_str();
        }
        else {
            key_not_found_msg("dict_find", id, key);
        }
    }
    else {
        dict_not_found_msg("dict_find", id);
    }

    search_global_dict_msg("dict_find");

    auto stringIt = dictionaries.at(dict_global()).find(key);
    if (stringIt != dictionaries.at(dict_global()).end()) {
        value_found_msg("dict_find", dict_global(), key, stringIt->second);

        return stringIt->second.c_str();
    }
    else {
        key_not_found_msg("dict_find", dict_global(), key);
    }

    return NULL;
}

void dict_clear(IdentificatorType id) {
    auto dictionaryIt = dictionaries.find(id);
    if (dictionaryIt != dictionaries.end()) {
        dict_cleared_msg("dict_clear", id);

        dictionaryIt->second.clear();
    }
    else {
        dict_not_found_msg("dict_clear", id);
    }
}

void dict_copy(IdentificatorType src_id, IdentificatorType dst_id) {
    auto srcDictionaryIt = dictionaries.find(src_id);
    auto dstDictionaryIt = dictionaries.find(dst_id);
    if (srcDictionaryIt != dictionaries.end() &&
        dstDictionaryIt != dictionaries.end()) {
        // do not copy if destination dictionary is dictglobal and amount of keys exceeds size

        // copy contents
    }
}<|endoftext|>


<commit_before>/**
 * \file
 * \brief Reset_Handler() for ARMv6-M and ARMv7-M
 *
 * \author Copyright (C) 2014-2017 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * 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/.
 */

#include "distortos/chip/CMSIS-proxy.h"

extern "C"
{

/*---------------------------------------------------------------------------------------------------------------------+
| global functions
+---------------------------------------------------------------------------------------------------------------------*/

// weak definition of lowLevelInitialization0() called at the very beginning of Reset_Handler()
__attribute__ ((weak)) void lowLevelInitialization0()
{

}

/**
 * \brief Reset_Handler() for ARMv6-M and ARMv7-M
 */

__attribute__ ((naked)) void Reset_Handler()
{
	asm volatile
	(
			"	ldr		r0, =lowLevelInitialization0		\n"		// call lowLevelInitialization0() (PSP not set,
			"	blx		r0									\n"		// CONTROL not modified, memory not initialized)
			"												\n"
			"	ldr		r0, =__process_stack_end			\n"		// initialize PSP
			"	msr		psp, r0								\n"
			"												\n"
			"	movs	r0, %[controlSpselMsk]				\n"		// thread mode uses PSP and is privileged
			"	msr		control, r0							\n"
			"	isb											\n"
			"												\n"
			"	ldr		r4, =__data_array_start				\n"		// initialize data_array (including .data)
			"	ldr		r5, =__data_array_end				\n"
			"												\n"
#ifdef __ARM_ARCH_6M__
			"1:	cmp		r4, r5								\n"		// outer loop - addresses from data_array
			"	bhs		4f									\n"
			"	ldmia	r4!, {r1-r3}						\n"		// r1 - start of source, r2 - start of destination,
			"												\n"		// r3 - end of destination
			"	b		3f									\n"
			"2:	ldmia	r1!, {r0}							\n"		// inner loop - section initialization
			"	stmia	r2!, {r0}							\n"
			"3:	cmp		r2, r3								\n"
			"	bne		2b									\n"
			"												\n"
			"	b		1b									\n"		// go back to start
			"												\n"
			"4:												\n"
			"												\n"
#else	// !def __ARM_ARCH_6M__
			"1:	cmp		r4, r5								\n"		// outer loop - addresses from data_array
			"	ite		lo									\n"
			"	ldmialo	r4!, {r1-r3}						\n"		// r1 - start of source, r2 - start of destination,
			"	bhs		3f									\n"		// r3 - end of destination
			"												\n"
			"2:	cmp		r2, r3								\n"		// inner loop - section initialization
			"	ittt	lo									\n"
			"	ldrlo	r0, [r1], #4						\n"
			"	strlo	r0, [r2], #4						\n"
			"	blo		2b									\n"
			"												\n"
			"	b		1b									\n"		// go back to start
			"												\n"
			"3:												\n"
			"												\n"
#endif	// !def __ARM_ARCH_6M__
			"	ldr		r3, =__bss_array_start				\n"		// initialize bss_array (including .bss)
			"	ldr		r4, =__bss_array_end				\n"
			"												\n"
#ifdef __ARM_ARCH_6M__
			"1:	cmp		r3, r4								\n"		// outer loop - addresses from bss_array
			"	bhs		4f									\n"
			"	ldmia	r3!, {r0-r2}						\n"		// r0 - value, r1 - start of destination, r2 - end
			"												\n"		// of destination
			"	b		3f									\n"
			"2:	stmia	r1!, {r0}							\n"		// inner loop - section initialization
			"3:	cmp		r1, r2								\n"
			"	bne		2b									\n"
			"												\n"
			"	b		1b									\n"		// go back to start
			"												\n"
			"4:												\n"
			"												\n"
#else	// !def __ARM_ARCH_6M__
			"1:	cmp		r3, r4								\n"		// outer loop - addresses from bss_array
			"	ite		lo									\n"
			"	ldmialo	r3!, {r0-r2}						\n"		// r0 - value, r1 - start of destination, r2 - end
			"	bhs		3f									\n"		// of destination
			"												\n"
			"2:	cmp		r1, r2								\n"		// inner loop - section initialization
			"	itt		lo									\n"
			"	strlo	r0, [r1], #4						\n"
			"	blo		2b									\n"
			"												\n"
			"	b		1b									\n"		// go back to start
			"												\n"
			"3:												\n"
			"												\n"
#endif	// !def __ARM_ARCH_6M__
			"	ldr		r0, =__libc_init_array				\n"		// call constructors for global and static objects
			"	blx		r0									\n"
			"												\n"
			"	ldr		r0, =main							\n"		// call main()
			"	blx		r0									\n"
			"												\n"
			"	ldr		r0, =__libc_fini_array				\n"		// call destructors for global and static objects
			"	blx		r0									\n"
			"												\n"
			"	b		.									\n"		// on return - loop till the end of the world

			::	[controlSpselMsk] "i" (CONTROL_SPSEL_Msk)
	);

	__builtin_unreachable();
}

}	// extern "C"
<commit_msg>Force dumping of literal pool in Reset_Handler()<commit_after>/**
 * \file
 * \brief Reset_Handler() for ARMv6-M and ARMv7-M
 *
 * \author Copyright (C) 2014-2017 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * 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/.
 */

#include "distortos/chip/CMSIS-proxy.h"

extern "C"
{

/*---------------------------------------------------------------------------------------------------------------------+
| global functions
+---------------------------------------------------------------------------------------------------------------------*/

// weak definition of lowLevelInitialization0() called at the very beginning of Reset_Handler()
__attribute__ ((weak)) void lowLevelInitialization0()
{

}

/**
 * \brief Reset_Handler() for ARMv6-M and ARMv7-M
 */

__attribute__ ((naked)) void Reset_Handler()
{
	asm volatile
	(
			"	ldr		r0, =lowLevelInitialization0		\n"		// call lowLevelInitialization0() (PSP not set,
			"	blx		r0									\n"		// CONTROL not modified, memory not initialized)
			"												\n"
			"	ldr		r0, =__process_stack_end			\n"		// initialize PSP
			"	msr		psp, r0								\n"
			"												\n"
			"	movs	r0, %[controlSpselMsk]				\n"		// thread mode uses PSP and is privileged
			"	msr		control, r0							\n"
			"	isb											\n"
			"												\n"
			"	ldr		r4, =__data_array_start				\n"		// initialize data_array (including .data)
			"	ldr		r5, =__data_array_end				\n"
			"												\n"
#ifdef __ARM_ARCH_6M__
			"1:	cmp		r4, r5								\n"		// outer loop - addresses from data_array
			"	bhs		4f									\n"
			"	ldmia	r4!, {r1-r3}						\n"		// r1 - start of source, r2 - start of destination,
			"												\n"		// r3 - end of destination
			"	b		3f									\n"
			"2:	ldmia	r1!, {r0}							\n"		// inner loop - section initialization
			"	stmia	r2!, {r0}							\n"
			"3:	cmp		r2, r3								\n"
			"	bne		2b									\n"
			"												\n"
			"	b		1b									\n"		// go back to start
			"												\n"
			"4:												\n"
			"												\n"
#else	// !def __ARM_ARCH_6M__
			"1:	cmp		r4, r5								\n"		// outer loop - addresses from data_array
			"	ite		lo									\n"
			"	ldmialo	r4!, {r1-r3}						\n"		// r1 - start of source, r2 - start of destination,
			"	bhs		3f									\n"		// r3 - end of destination
			"												\n"
			"2:	cmp		r2, r3								\n"		// inner loop - section initialization
			"	ittt	lo									\n"
			"	ldrlo	r0, [r1], #4						\n"
			"	strlo	r0, [r2], #4						\n"
			"	blo		2b									\n"
			"												\n"
			"	b		1b									\n"		// go back to start
			"												\n"
			"3:												\n"
			"												\n"
#endif	// !def __ARM_ARCH_6M__
			"	ldr		r3, =__bss_array_start				\n"		// initialize bss_array (including .bss)
			"	ldr		r4, =__bss_array_end				\n"
			"												\n"
#ifdef __ARM_ARCH_6M__
			"1:	cmp		r3, r4								\n"		// outer loop - addresses from bss_array
			"	bhs		4f									\n"
			"	ldmia	r3!, {r0-r2}						\n"		// r0 - value, r1 - start of destination, r2 - end
			"												\n"		// of destination
			"	b		3f									\n"
			"2:	stmia	r1!, {r0}							\n"		// inner loop - section initialization
			"3:	cmp		r1, r2								\n"
			"	bne		2b									\n"
			"												\n"
			"	b		1b									\n"		// go back to start
			"												\n"
			"4:												\n"
			"												\n"
#else	// !def __ARM_ARCH_6M__
			"1:	cmp		r3, r4								\n"		// outer loop - addresses from bss_array
			"	ite		lo									\n"
			"	ldmialo	r3!, {r0-r2}						\n"		// r0 - value, r1 - start of destination, r2 - end
			"	bhs		3f									\n"		// of destination
			"												\n"
			"2:	cmp		r1, r2								\n"		// inner loop - section initialization
			"	itt		lo									\n"
			"	strlo	r0, [r1], #4						\n"
			"	blo		2b									\n"
			"												\n"
			"	b		1b									\n"		// go back to start
			"												\n"
			"3:												\n"
			"												\n"
#endif	// !def __ARM_ARCH_6M__
			"	ldr		r0, =__libc_init_array				\n"		// call constructors for global and static objects
			"	blx		r0									\n"
			"												\n"
			"	ldr		r0, =main							\n"		// call main()
			"	blx		r0									\n"
			"												\n"
			"	ldr		r0, =__libc_fini_array				\n"		// call destructors for global and static objects
			"	blx		r0									\n"
			"												\n"
			"	b		.									\n"		// on return - loop till the end of the world
			"												\n"
			".ltorg											\n"		// force dumping of literal pool

			::	[controlSpselMsk] "i" (CONTROL_SPSEL_Msk)
	);

	__builtin_unreachable();
}

}	// extern "C"
<|endoftext|>


<commit_before>/*
 * BBGHHibe.cpp
 *
 *  Created on: Dec 21, 2014
 *      Author: imiers
 */
#include <assert.h>
#include "BBGHibe.h"
namespace forwardsec{

using namespace std;
void Bbghibe::setup(const unsigned int & l, BbhHIBEPublicKey & pk, G2 & msk) const
{
    ZR alpha = group.randomZR();
    pk.gG1 = group.randomG1();
    pk.gG2 = group.randomG2();
    pk.hibeg1 = group.exp(pk.gG2, alpha);
    pk.l = l;
    const ZR r = group.randomZR();
    pk.g2G1 = group.exp(pk.gG1, r);
    pk.g2G2 = group.exp(pk.gG2, r);
    const ZR r1 = group.randomZR();
    pk.g3G1 = group.exp(pk.gG1, r1);
    pk.g3G2 = group.exp(pk.gG2, r1);
    for (unsigned int i = 0; i < l; i++)
    {
        ZR h = group.randomZR();
        pk.hG1.push_back(group.exp(pk.gG1, h));
        pk.hG2.push_back(group.exp(pk.gG2, h));
    }
    msk = group.exp(pk.g2G2, alpha);

    return;
}

void Bbghibe::keygen(const BbhHIBEPublicKey & pk, const G2 & msk, const std::vector<ZR> & id, BbghPrivatekey & sk) const
{
    const ZR r = group.randomZR();
    const unsigned int k = id.size();
    for (unsigned int i = 0; i < k; i++)
    {
        sk.a0 = group.mul(sk.a0, group.exp(pk.hG2[i], id[i]));
    }
    sk.a0 = group.exp(group.mul(sk.a0, pk.g3G2), r);
    sk.a0 = group.mul(msk, sk.a0);
    sk.a1 = group.exp(pk.gG2, r);

    sk.b.resize(pk.l);
    sk.bG2.resize(pk.l);
    for (unsigned int i =  k;i < pk.l; i++)
    {
        sk.b[i] = group.exp(pk.hG1[i], r);

        sk.bG2[i] = group.exp(pk.hG2[i], r);
    }
    return;
}

void Bbghibe::keygen(const BbhHIBEPublicKey & pk,const  BbghPrivatekey & sk, const std::vector<ZR> &id,BbghPrivatekey & skout) const{
    const unsigned int k = id.size();
    ZR t = group.randomZR();

    G2 hprod;
    for (unsigned int i = 0; i < k ; i++)
    {
        hprod = group.mul(hprod, group.exp(pk.hG2[i], id[i]));
    }
    hprod = group.exp(group.mul(hprod, pk.g3G2), t);
    hprod = group.mul(hprod,group.exp(sk.bG2[k-1],(id[k-1])));
    skout.a0 = group.mul(hprod,sk.a0);
    skout.a1 = group.mul(sk.a1,group.exp(pk.gG2,t));
    skout.b.resize(pk.l);
    skout.bG2.resize(pk.l);
    assert(skout.b.size() == sk.b.size());
    assert(skout.bG2.size() == sk.bG2.size());

    for (unsigned int i = k ; i < pk.l; i++)
    {
        skout.b[i] = group.mul(sk.b[i],group.exp(pk.hG1[i],t));
        skout.bG2[i] = group.mul(sk.bG2[i],group.exp(pk.hG2[i],t));

    }
    return;
}

BbghCT Bbghibe::encrypt(const BbhHIBEPublicKey & pk, const GT & M, const std::vector<ZR> & id) const{
    ZR s = group.randomZR();

     BbghCT ct =blind(pk,s,id);
     ct.A = group.mul(group.exp(group.pair(pk.g2G1, pk.hibeg1), s), M);
     return ct;
}

PartialBbghCT Bbghibe::blind(const BbhHIBEPublicKey & pk, const ZR & s,const std::vector<ZR> & id) const
{
	PartialBbghCT ct;
    const unsigned int k = id.size();
    assert(k<=pk.l);

    ct.B = group.exp(pk.gG1, s);

    G1 dotProd2;
    for (unsigned int i = 0; i < k; i++)
    {
        dotProd2 = group.mul(dotProd2,group.exp(pk.hG1[i], id[i]));
    }
    ct.C = group.exp(group.mul(dotProd2, pk.g3G1), s);
    return ct;
}

GT Bbghibe::recoverBlind(const BbghPrivatekey & sk, const PartialBbghCT & ct) const{
	// This is inverted so that decrypt is ct/result. I.e. it aligns with the ppke scheme.
    return group.div(group.pair(ct.B, sk.a0),group.pair(ct.C, sk.a1));
}

GT Bbghibe::decrypt(const BbghPrivatekey & sk, const BbghCT & ct) const
{

    return group.div(ct.A, recoverBlind(sk,ct));
}

}

<commit_msg>HIBE KEYS GET SMALLER ON FURTHER DERIVATIONS<commit_after>/*
 * BBGHHibe.cpp
 *
 *  Created on: Dec 21, 2014
 *      Author: imiers
 */
#include <assert.h>
#include "BBGHibe.h"
namespace forwardsec{

using namespace std;
void Bbghibe::setup(const unsigned int & l, BbhHIBEPublicKey & pk, G2 & msk) const
{
    ZR alpha = group.randomZR();
    pk.gG1 = group.randomG1();
    pk.gG2 = group.randomG2();
    pk.hibeg1 = group.exp(pk.gG2, alpha);
    pk.l = l;
    const ZR r = group.randomZR();
    pk.g2G1 = group.exp(pk.gG1, r);
    pk.g2G2 = group.exp(pk.gG2, r);
    const ZR r1 = group.randomZR();
    pk.g3G1 = group.exp(pk.gG1, r1);
    pk.g3G2 = group.exp(pk.gG2, r1);
    for (unsigned int i = 0; i < l; i++)
    {
        ZR h = group.randomZR();
        pk.hG1.push_back(group.exp(pk.gG1, h));
        pk.hG2.push_back(group.exp(pk.gG2, h));
    }
    msk = group.exp(pk.g2G2, alpha);

    return;
}

void Bbghibe::keygen(const BbhHIBEPublicKey & pk, const G2 & msk, const std::vector<ZR> & id, BbghPrivatekey & sk) const
{
    const ZR r = group.randomZR();
    const unsigned int k = id.size();
    for (unsigned int i = 0; i < k; i++)
    {
        sk.a0 = group.mul(sk.a0, group.exp(pk.hG2[i], id[i]));
    }
    sk.a0 = group.exp(group.mul(sk.a0, pk.g3G2), r);
    sk.a0 = group.mul(msk, sk.a0);
    sk.a1 = group.exp(pk.gG2, r);

    sk.b.resize(pk.l);
    sk.bG2.resize(pk.l);
    for (unsigned int i =  k;i < pk.l; i++)
    {
        sk.b[i-(k-1)] = group.exp(pk.hG1[i], r);

        sk.bG2[i-(k-1)] = group.exp(pk.hG2[i], r);
    }
    return;
}

void Bbghibe::keygen(const BbhHIBEPublicKey & pk,const  BbghPrivatekey & sk, const std::vector<ZR> &id,BbghPrivatekey & skout) const{
    const unsigned int k = id.size();
    ZR t = group.randomZR();

    G2 hprod;
    for (unsigned int i = 0; i < k ; i++)
    {
        hprod = group.mul(hprod, group.exp(pk.hG2[i], id[i]));
    }
    hprod = group.exp(group.mul(hprod, pk.g3G2), t);
    hprod = group.mul(hprod,group.exp(sk.bG2[k-1],(id[k-1])));
    skout.a0 = group.mul(hprod,sk.a0);
    skout.a1 = group.mul(sk.a1,group.exp(pk.gG2,t));

    const unsigned int  kk = k-2;
    skout.b.resize(pk.l-kk);
    skout.bG2.resize(pk.l-kk);
    for (unsigned int i = k ; i < pk.l; i++)
    {
        skout.b[i-kk] = group.mul(sk.b[i-kk],group.exp(pk.hG1[i],t));
        skout.bG2[i-kk] = group.mul(sk.bG2[i-kk],group.exp(pk.hG2[i],t));

    }
    return;
}

BbghCT Bbghibe::encrypt(const BbhHIBEPublicKey & pk, const GT & M, const std::vector<ZR> & id) const{
    ZR s = group.randomZR();

     BbghCT ct =blind(pk,s,id);
     ct.A = group.mul(group.exp(group.pair(pk.g2G1, pk.hibeg1), s), M);
     return ct;
}

PartialBbghCT Bbghibe::blind(const BbhHIBEPublicKey & pk, const ZR & s,const std::vector<ZR> & id) const
{
	PartialBbghCT ct;
    const unsigned int k = id.size();
    assert(k<=pk.l);

    ct.B = group.exp(pk.gG1, s);

    G1 dotProd2;
    for (unsigned int i = 0; i < k; i++)
    {
        dotProd2 = group.mul(dotProd2,group.exp(pk.hG1[i], id[i]));
    }
    ct.C = group.exp(group.mul(dotProd2, pk.g3G1), s);
    return ct;
}

GT Bbghibe::recoverBlind(const BbghPrivatekey & sk, const PartialBbghCT & ct) const{
	// This is inverted so that decrypt is ct/result. I.e. it aligns with the ppke scheme.
    return group.div(group.pair(ct.B, sk.a0),group.pair(ct.C, sk.a1));
}

GT Bbghibe::decrypt(const BbghPrivatekey & sk, const BbghCT & ct) const
{

    return group.div(ct.A, recoverBlind(sk,ct));
}

}

<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkImageToStructuredPoints.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$
  Thanks:    Thanks to C. Charles Law who developed this class.

Copyright (c) 1993-1995 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include <math.h>
#include "vtkImageToStructuredPoints.h"
#include "vtkScalars.h"
#include "vtkStructuredPoints.h"

//----------------------------------------------------------------------------
vtkImageToStructuredPoints::vtkImageToStructuredPoints()
{
  int idx;

  this->Translate[0] = this->Translate[1] = this->Translate[2] = 0;
  this->SetOutput(0,vtkStructuredPoints::New());
}

//----------------------------------------------------------------------------
vtkImageToStructuredPoints::~vtkImageToStructuredPoints()
{
}

//----------------------------------------------------------------------------
void vtkImageToStructuredPoints::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkSource::PrintSelf(os,indent);

}

//----------------------------------------------------------------------------
vtkStructuredPoints *vtkImageToStructuredPoints::GetOutput()
{
  if (this->NumberOfOutputs < 1)
    {
    return NULL;
    }

  return (vtkStructuredPoints *)(this->Outputs[0]);
}

//----------------------------------------------------------------------------
void vtkImageToStructuredPoints::SetInput(vtkImageData *input)
{
  this->vtkProcessObject::SetInput(0, input);
}

//----------------------------------------------------------------------------
vtkImageData *vtkImageToStructuredPoints::GetInput()
{
  if (this->NumberOfInputs < 1)
    {
    return NULL;
    }

  return (vtkImageData *)(this->Inputs[0]);
}

//----------------------------------------------------------------------------
void vtkImageToStructuredPoints::SetVectorInput(vtkImageData *input)
{
  this->vtkProcessObject::SetInput(1, input);
}

//----------------------------------------------------------------------------
vtkImageData *vtkImageToStructuredPoints::GetVectorInput()
{
  if (this->NumberOfInputs < 2)
    {
    return NULL;
    }

  return (vtkImageData *)(this->Inputs[1]);
}

//----------------------------------------------------------------------------
void vtkImageToStructuredPoints::Execute()
{
  int uExtent[6];
  int *wExtent;

  int idxX, idxY, idxZ, maxX, maxY, maxZ;
  int inIncX, inIncY, inIncZ, rowLength;
  unsigned char *inPtr1, *inPtr, *outPtr;

  vtkStructuredPoints *output = this->GetOutput();
  vtkImageData *data = this->GetInput();
  vtkImageData *vData = this->GetVectorInput();

  if (!data)
    {
    vtkErrorMacro("Unable to generate data!");
    return;
    }

  output->GetUpdateExtent(uExtent);
  output->SetExtent(uExtent);

  uExtent[0] += this->Translate[0];
  uExtent[1] += this->Translate[0];
  uExtent[2] += this->Translate[1];
  uExtent[3] += this->Translate[1];
  uExtent[4] += this->Translate[2];
  uExtent[5] += this->Translate[2];

  // if the data extent matches the update extent then just pass the data
  // otherwise we must reformat and copy the data
  wExtent = data->GetExtent();
  if (wExtent[0] == uExtent[0] && wExtent[1] == uExtent[1] &&
      wExtent[2] == uExtent[2] && wExtent[3] == uExtent[3] &&
      wExtent[4] == uExtent[4] && wExtent[5] == uExtent[5])
    {
    output->GetPointData()->PassData(data->GetPointData());
    }
  else
    {
    inPtr = (unsigned char *) data->GetScalarPointerForExtent(uExtent);
    outPtr = (unsigned char *) output->GetScalarPointer();

    // Get increments to march through data
    data->GetIncrements(inIncX, inIncY, inIncZ);

    // find the region to loop over
    rowLength = (uExtent[1] - uExtent[0]+1)*inIncX*data->GetScalarSize();
    maxX = uExtent[1] - uExtent[0];
    maxY = uExtent[3] - uExtent[2];
    maxZ = uExtent[5] - uExtent[4];
    inIncY *= data->GetScalarSize();
    inIncZ *= data->GetScalarSize();

    // Loop through output pixels
    for (idxZ = 0; idxZ <= maxZ; idxZ++)
      {
      inPtr1 = inPtr + idxZ*inIncZ;
      for (idxY = 0; idxY <= maxY; idxY++)
	{
	memcpy(outPtr,inPtr1,rowLength);
	inPtr1 += inIncY;
	outPtr += rowLength;
	}
      }
    }

  if (!vData)
    {
    return;
    }
  // if the data extent matches the update extent then just pass the data
  // otherwise we must reformat and copy the data
  wExtent = vData->GetExtent();
  if (wExtent[0] == uExtent[0] && wExtent[1] == uExtent[1] &&
      wExtent[2] == uExtent[2] && wExtent[3] == uExtent[3] &&
      wExtent[4] == uExtent[4] && wExtent[5] == uExtent[5])
    {
    vtkVectors *fv = vtkVectors::New(vData->GetScalarType());
    output->GetPointData()->SetVectors(fv);
    fv->SetData(vData->GetPointData()->GetScalars()->GetData());
    fv->Delete();
    }
  else
    {
    vtkVectors *fv = vtkVectors::New(vData->GetScalarType());
    output->GetPointData()->SetVectors(fv);
    float *inPtr2 = (float *)(vData->GetScalarPointerForExtent(uExtent));

    fv->SetNumberOfVectors((maxZ+1)*(maxY+1)*(maxX+1));
    vData->GetContinuousIncrements(uExtent, inIncX, inIncY, inIncZ);
    int numComp = vData->GetNumberOfScalarComponents();
    int idx = 0;

    // Loop through ouput pixels
    for (idxZ = 0; idxZ <= maxZ; idxZ++)
      {
      for (idxY = 0; idxY <= maxY; idxY++)
	{
	for (idxX = 0; idxX <= maxX; idxX++)
	  {
	  fv->SetVector(idx,inPtr2);
	  inPtr2 += numComp;
	  idx++;
	  }
	inPtr2 += inIncY;
	}
      inPtr2 += inIncZ;
      }
    fv->Delete();
    }
}

//----------------------------------------------------------------------------
// Copy WholeExtent, Spacing and Origin.
void vtkImageToStructuredPoints::ExecuteInformation()
{
  vtkImageData *input = this->GetInput();
  vtkImageData *vInput = this->GetVectorInput();
  vtkStructuredPoints *output = this->GetOutput();
  int whole[6], *tmp;
  float *spacing, origin[3];

  if (output == NULL || input == NULL)
    {
    return;
    }

  output->SetScalarType(input->GetScalarType());
  output->SetNumberOfScalarComponents(input->GetNumberOfScalarComponents());

  // intersections for whole extent
  input->GetWholeExtent(whole);
  if (vInput)
    {
    tmp = vInput->GetWholeExtent();
    if (tmp[0] > whole[0]) {whole[0] = tmp[0];}
    if (tmp[2] > whole[2]) {whole[2] = tmp[2];}
    if (tmp[4] > whole[4]) {whole[4] = tmp[4];}
    if (tmp[1] < whole[1]) {whole[1] = tmp[1];}
    if (tmp[3] < whole[1]) {whole[3] = tmp[3];}
    if (tmp[5] < whole[1]) {whole[5] = tmp[5];}
    }
  spacing = input->GetSpacing();
  input->GetOrigin(origin);

  // slide min extent to 0,0,0 (I Hate this !!!!)
  this->Translate[0] = whole[0];
  this->Translate[1] = whole[2];
  this->Translate[2] = whole[4];

  origin[0] += spacing[0] * whole[0];
  origin[1] += spacing[1] * whole[2];
  origin[2] += spacing[2] * whole[4];
  whole[1] -= whole[0];
  whole[3] -= whole[2];
  whole[5] -= whole[4];
  whole[0] = whole[2] = whole[4];

  output->SetWholeExtent(whole);
  // Now should Origin and Spacing really be part of information?
  // How about xyx arrays in RectilinearGrid of Points in StructuredGrid?
  output->SetOrigin(origin);
  output->SetSpacing(spacing);
}

//----------------------------------------------------------------------------
int vtkImageToStructuredPoints::ComputeInputUpdateExtents(vtkDataObject *data)
{
  vtkStructuredPoints *output = (vtkStructuredPoints*)data;
  int ext[6];
  vtkImageData *input;

  output->GetUpdateExtent(ext);
  ext[0] += this->Translate[0];
  ext[1] += this->Translate[0];
  ext[2] += this->Translate[1];
  ext[3] += this->Translate[1];
  ext[4] += this->Translate[2];
  ext[5] += this->Translate[2];

  input = this->GetInput();
  if (input)
    {
    input->SetUpdateExtent(ext);
    }

  input = this->GetVectorInput();
  if (input)
    {
    input->SetUpdateExtent(ext);
    }

  return 1;
}

<commit_msg>Translate extent bug<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkImageToStructuredPoints.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$
  Thanks:    Thanks to C. Charles Law who developed this class.

Copyright (c) 1993-1995 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include <math.h>
#include "vtkImageToStructuredPoints.h"
#include "vtkScalars.h"
#include "vtkStructuredPoints.h"

//----------------------------------------------------------------------------
vtkImageToStructuredPoints::vtkImageToStructuredPoints()
{
  int idx;

  this->Translate[0] = this->Translate[1] = this->Translate[2] = 0;
  this->SetOutput(0,vtkStructuredPoints::New());
}

//----------------------------------------------------------------------------
vtkImageToStructuredPoints::~vtkImageToStructuredPoints()
{
}

//----------------------------------------------------------------------------
void vtkImageToStructuredPoints::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkSource::PrintSelf(os,indent);

}

//----------------------------------------------------------------------------
vtkStructuredPoints *vtkImageToStructuredPoints::GetOutput()
{
  if (this->NumberOfOutputs < 1)
    {
    return NULL;
    }

  return (vtkStructuredPoints *)(this->Outputs[0]);
}

//----------------------------------------------------------------------------
void vtkImageToStructuredPoints::SetInput(vtkImageData *input)
{
  this->vtkProcessObject::SetInput(0, input);
}

//----------------------------------------------------------------------------
vtkImageData *vtkImageToStructuredPoints::GetInput()
{
  if (this->NumberOfInputs < 1)
    {
    return NULL;
    }

  return (vtkImageData *)(this->Inputs[0]);
}

//----------------------------------------------------------------------------
void vtkImageToStructuredPoints::SetVectorInput(vtkImageData *input)
{
  this->vtkProcessObject::SetInput(1, input);
}

//----------------------------------------------------------------------------
vtkImageData *vtkImageToStructuredPoints::GetVectorInput()
{
  if (this->NumberOfInputs < 2)
    {
    return NULL;
    }

  return (vtkImageData *)(this->Inputs[1]);
}

//----------------------------------------------------------------------------
void vtkImageToStructuredPoints::Execute()
{
  int uExtent[6];
  int *wExtent;

  int idxX, idxY, idxZ, maxX, maxY, maxZ;
  int inIncX, inIncY, inIncZ, rowLength;
  unsigned char *inPtr1, *inPtr, *outPtr;

  vtkStructuredPoints *output = this->GetOutput();
  vtkImageData *data = this->GetInput();
  vtkImageData *vData = this->GetVectorInput();

  if (!data)
    {
    vtkErrorMacro("Unable to generate data!");
    return;
    }

  output->GetUpdateExtent(uExtent);
  output->SetExtent(uExtent);

  uExtent[0] += this->Translate[0];
  uExtent[1] += this->Translate[0];
  uExtent[2] += this->Translate[1];
  uExtent[3] += this->Translate[1];
  uExtent[4] += this->Translate[2];
  uExtent[5] += this->Translate[2];

  // if the data extent matches the update extent then just pass the data
  // otherwise we must reformat and copy the data
  wExtent = data->GetExtent();
  if (wExtent[0] == uExtent[0] && wExtent[1] == uExtent[1] &&
      wExtent[2] == uExtent[2] && wExtent[3] == uExtent[3] &&
      wExtent[4] == uExtent[4] && wExtent[5] == uExtent[5])
    {
    output->GetPointData()->PassData(data->GetPointData());
    }
  else
    {
    inPtr = (unsigned char *) data->GetScalarPointerForExtent(uExtent);
    outPtr = (unsigned char *) output->GetScalarPointer();

    // Get increments to march through data
    data->GetIncrements(inIncX, inIncY, inIncZ);

    // find the region to loop over
    rowLength = (uExtent[1] - uExtent[0]+1)*inIncX*data->GetScalarSize();
    maxX = uExtent[1] - uExtent[0];
    maxY = uExtent[3] - uExtent[2];
    maxZ = uExtent[5] - uExtent[4];
    inIncY *= data->GetScalarSize();
    inIncZ *= data->GetScalarSize();

    // Loop through output pixels
    for (idxZ = 0; idxZ <= maxZ; idxZ++)
      {
      inPtr1 = inPtr + idxZ*inIncZ;
      for (idxY = 0; idxY <= maxY; idxY++)
	{
	memcpy(outPtr,inPtr1,rowLength);
	inPtr1 += inIncY;
	outPtr += rowLength;
	}
      }
    }

  if (!vData)
    {
    return;
    }
  // if the data extent matches the update extent then just pass the data
  // otherwise we must reformat and copy the data
  wExtent = vData->GetExtent();
  if (wExtent[0] == uExtent[0] && wExtent[1] == uExtent[1] &&
      wExtent[2] == uExtent[2] && wExtent[3] == uExtent[3] &&
      wExtent[4] == uExtent[4] && wExtent[5] == uExtent[5])
    {
    vtkVectors *fv = vtkVectors::New(vData->GetScalarType());
    output->GetPointData()->SetVectors(fv);
    fv->SetData(vData->GetPointData()->GetScalars()->GetData());
    fv->Delete();
    }
  else
    {
    vtkVectors *fv = vtkVectors::New(vData->GetScalarType());
    output->GetPointData()->SetVectors(fv);
    float *inPtr2 = (float *)(vData->GetScalarPointerForExtent(uExtent));

    fv->SetNumberOfVectors((maxZ+1)*(maxY+1)*(maxX+1));
    vData->GetContinuousIncrements(uExtent, inIncX, inIncY, inIncZ);
    int numComp = vData->GetNumberOfScalarComponents();
    int idx = 0;

    // Loop through ouput pixels
    for (idxZ = 0; idxZ <= maxZ; idxZ++)
      {
      for (idxY = 0; idxY <= maxY; idxY++)
	{
	for (idxX = 0; idxX <= maxX; idxX++)
	  {
	  fv->SetVector(idx,inPtr2);
	  inPtr2 += numComp;
	  idx++;
	  }
	inPtr2 += inIncY;
	}
      inPtr2 += inIncZ;
      }
    fv->Delete();
    }
}

//----------------------------------------------------------------------------
// Copy WholeExtent, Spacing and Origin.
void vtkImageToStructuredPoints::ExecuteInformation()
{
  vtkImageData *input = this->GetInput();
  vtkImageData *vInput = this->GetVectorInput();
  vtkStructuredPoints *output = this->GetOutput();
  int whole[6], *tmp;
  float *spacing, origin[3];

  if (output == NULL || input == NULL)
    {
    return;
    }

  output->SetScalarType(input->GetScalarType());
  output->SetNumberOfScalarComponents(input->GetNumberOfScalarComponents());

  // intersections for whole extent
  input->GetWholeExtent(whole);
  if (vInput)
    {
    tmp = vInput->GetWholeExtent();
    if (tmp[0] > whole[0]) {whole[0] = tmp[0];}
    if (tmp[2] > whole[2]) {whole[2] = tmp[2];}
    if (tmp[4] > whole[4]) {whole[4] = tmp[4];}
    if (tmp[1] < whole[1]) {whole[1] = tmp[1];}
    if (tmp[3] < whole[1]) {whole[3] = tmp[3];}
    if (tmp[5] < whole[1]) {whole[5] = tmp[5];}
    }
  spacing = input->GetSpacing();
  input->GetOrigin(origin);

  // slide min extent to 0,0,0 (I Hate this !!!!)
  this->Translate[0] = whole[0];
  this->Translate[1] = whole[2];
  this->Translate[2] = whole[4];

  origin[0] += spacing[0] * whole[0];
  origin[1] += spacing[1] * whole[2];
  origin[2] += spacing[2] * whole[4];
  whole[1] -= whole[0];
  whole[3] -= whole[2];
  whole[5] -= whole[4];
  whole[0] = whole[2] = whole[4] = 0;

  output->SetWholeExtent(whole);
  // Now should Origin and Spacing really be part of information?
  // How about xyx arrays in RectilinearGrid of Points in StructuredGrid?
  output->SetOrigin(origin);
  output->SetSpacing(spacing);
}

//----------------------------------------------------------------------------
int vtkImageToStructuredPoints::ComputeInputUpdateExtents(vtkDataObject *data)
{
  vtkStructuredPoints *output = (vtkStructuredPoints*)data;
  int ext[6];
  vtkImageData *input;

  output->GetUpdateExtent(ext);
  ext[0] += this->Translate[0];
  ext[1] += this->Translate[0];
  ext[2] += this->Translate[1];
  ext[3] += this->Translate[1];
  ext[4] += this->Translate[2];
  ext[5] += this->Translate[2];

  input = this->GetInput();
  if (input)
    {
    input->SetUpdateExtent(ext);
    }

  input = this->GetVectorInput();
  if (input)
    {
    input->SetUpdateExtent(ext);
    }

  return 1;
}

<|endoftext|>


<commit_before>///
/// @file  BitSieve.cpp
/// @brief Bit array for prime sieving.
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#if !defined(__STDC_CONSTANT_MACROS)
  #define __STDC_CONSTANT_MACROS
#endif

#include <stdint.h>
#include <algorithm>
#include <cassert>
#include <vector>

#include <BitSieve.hpp>
#include <popcount.hpp>
#include <pmath.hpp>

namespace primecount {

const uint64_t BitSieve::unset_bit_[64] =
{
  ~(UINT64_C(1) <<  0), ~(UINT64_C(1) <<  1), ~(UINT64_C(1) <<  2),
  ~(UINT64_C(1) <<  3), ~(UINT64_C(1) <<  4), ~(UINT64_C(1) <<  5),
  ~(UINT64_C(1) <<  6), ~(UINT64_C(1) <<  7), ~(UINT64_C(1) <<  8),
  ~(UINT64_C(1) <<  9), ~(UINT64_C(1) << 10), ~(UINT64_C(1) << 11),
  ~(UINT64_C(1) << 12), ~(UINT64_C(1) << 13), ~(UINT64_C(1) << 14),
  ~(UINT64_C(1) << 15), ~(UINT64_C(1) << 16), ~(UINT64_C(1) << 17),
  ~(UINT64_C(1) << 18), ~(UINT64_C(1) << 19), ~(UINT64_C(1) << 20),
  ~(UINT64_C(1) << 21), ~(UINT64_C(1) << 22), ~(UINT64_C(1) << 23),
  ~(UINT64_C(1) << 24), ~(UINT64_C(1) << 25), ~(UINT64_C(1) << 26),
  ~(UINT64_C(1) << 27), ~(UINT64_C(1) << 28), ~(UINT64_C(1) << 29),
  ~(UINT64_C(1) << 30), ~(UINT64_C(1) << 31), ~(UINT64_C(1) << 32),
  ~(UINT64_C(1) << 33), ~(UINT64_C(1) << 34), ~(UINT64_C(1) << 35),
  ~(UINT64_C(1) << 36), ~(UINT64_C(1) << 37), ~(UINT64_C(1) << 38),
  ~(UINT64_C(1) << 39), ~(UINT64_C(1) << 40), ~(UINT64_C(1) << 41),
  ~(UINT64_C(1) << 42), ~(UINT64_C(1) << 43), ~(UINT64_C(1) << 44),
  ~(UINT64_C(1) << 45), ~(UINT64_C(1) << 46), ~(UINT64_C(1) << 47),
  ~(UINT64_C(1) << 48), ~(UINT64_C(1) << 49), ~(UINT64_C(1) << 50),
  ~(UINT64_C(1) << 51), ~(UINT64_C(1) << 52), ~(UINT64_C(1) << 53),
  ~(UINT64_C(1) << 54), ~(UINT64_C(1) << 55), ~(UINT64_C(1) << 56),
  ~(UINT64_C(1) << 57), ~(UINT64_C(1) << 58), ~(UINT64_C(1) << 59),
  ~(UINT64_C(1) << 60), ~(UINT64_C(1) << 61), ~(UINT64_C(1) << 62),
  ~(UINT64_C(1) << 63)
};

BitSieve::BitSieve(std::size_t size) :
  bits_(ceil_div(size, 64)),
  size_(size)
{ }

/// Set all bits to 1, except bits corresponding
/// to 0, 1 and even numbers > 2.
///
void BitSieve::memset(uint64_t low)
{
  std::fill(bits_.begin(), bits_.end(), (low & 1)
      ? UINT64_C(0x5555555555555555) : UINT64_C(0xAAAAAAAAAAAAAAAA));

  // correct 0, 1 and 2
  if (low <= 2)
  {
    uint64_t bit = 1 << (2 - low);
    bits_[0] &= ~(bit - 1);
    bits_[0] |= bit;
  }
}

/// Count the number of 1 bits inside [start, stop]
uint64_t BitSieve::count(uint64_t start, uint64_t stop) const
{
  if (start > stop)
    return 0;

  assert(stop < size_);
  uint64_t bit_count = count_edges(start, stop);
  uint64_t start_idx = (start >> 6) + 1;
  uint64_t limit = stop >> 6;

  for (uint64_t i = start_idx; i < limit; i++)
    bit_count += popcount64(bits_[i]);

  return bit_count;
}

uint64_t BitSieve::count_edges(uint64_t start, uint64_t stop) const
{
  uint64_t index1 = start >> 6;
  uint64_t index2 = stop  >> 6;
  uint64_t mask1 = UINT64_C(0xffffffffffffffff) << (start & 63);
  uint64_t mask2 = UINT64_C(0xffffffffffffffff) >> (63 - (stop & 63));
  uint64_t count = 0;

  if (index1 == index2)
    count += popcount64(bits_[index1] & (mask1 & mask2));
  else
  {
    count += popcount64(bits_[index1] & mask1);
    count += popcount64(bits_[index2] & mask2);
  }

  return count;
}

} // namespace
<commit_msg>Add comment<commit_after>///
/// @file  BitSieve.cpp
/// @brief The BitSieve class is a bit array for use with
///        Eratosthenes-like prime sieving algorithms. BitSieve
///        assigns 64 numbers to the bits of an 8 byte word thus
///        reducing the memory usage by a factor of 8.
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#if !defined(__STDC_CONSTANT_MACROS)
  #define __STDC_CONSTANT_MACROS
#endif

#include <stdint.h>
#include <algorithm>
#include <cassert>
#include <vector>

#include <BitSieve.hpp>
#include <popcount.hpp>
#include <pmath.hpp>

namespace primecount {

const uint64_t BitSieve::unset_bit_[64] =
{
  ~(UINT64_C(1) <<  0), ~(UINT64_C(1) <<  1), ~(UINT64_C(1) <<  2),
  ~(UINT64_C(1) <<  3), ~(UINT64_C(1) <<  4), ~(UINT64_C(1) <<  5),
  ~(UINT64_C(1) <<  6), ~(UINT64_C(1) <<  7), ~(UINT64_C(1) <<  8),
  ~(UINT64_C(1) <<  9), ~(UINT64_C(1) << 10), ~(UINT64_C(1) << 11),
  ~(UINT64_C(1) << 12), ~(UINT64_C(1) << 13), ~(UINT64_C(1) << 14),
  ~(UINT64_C(1) << 15), ~(UINT64_C(1) << 16), ~(UINT64_C(1) << 17),
  ~(UINT64_C(1) << 18), ~(UINT64_C(1) << 19), ~(UINT64_C(1) << 20),
  ~(UINT64_C(1) << 21), ~(UINT64_C(1) << 22), ~(UINT64_C(1) << 23),
  ~(UINT64_C(1) << 24), ~(UINT64_C(1) << 25), ~(UINT64_C(1) << 26),
  ~(UINT64_C(1) << 27), ~(UINT64_C(1) << 28), ~(UINT64_C(1) << 29),
  ~(UINT64_C(1) << 30), ~(UINT64_C(1) << 31), ~(UINT64_C(1) << 32),
  ~(UINT64_C(1) << 33), ~(UINT64_C(1) << 34), ~(UINT64_C(1) << 35),
  ~(UINT64_C(1) << 36), ~(UINT64_C(1) << 37), ~(UINT64_C(1) << 38),
  ~(UINT64_C(1) << 39), ~(UINT64_C(1) << 40), ~(UINT64_C(1) << 41),
  ~(UINT64_C(1) << 42), ~(UINT64_C(1) << 43), ~(UINT64_C(1) << 44),
  ~(UINT64_C(1) << 45), ~(UINT64_C(1) << 46), ~(UINT64_C(1) << 47),
  ~(UINT64_C(1) << 48), ~(UINT64_C(1) << 49), ~(UINT64_C(1) << 50),
  ~(UINT64_C(1) << 51), ~(UINT64_C(1) << 52), ~(UINT64_C(1) << 53),
  ~(UINT64_C(1) << 54), ~(UINT64_C(1) << 55), ~(UINT64_C(1) << 56),
  ~(UINT64_C(1) << 57), ~(UINT64_C(1) << 58), ~(UINT64_C(1) << 59),
  ~(UINT64_C(1) << 60), ~(UINT64_C(1) << 61), ~(UINT64_C(1) << 62),
  ~(UINT64_C(1) << 63)
};

BitSieve::BitSieve(std::size_t size) :
  bits_(ceil_div(size, 64)),
  size_(size)
{ }

/// Set all bits to 1, except bits corresponding
/// to 0, 1 and even numbers > 2.
///
void BitSieve::memset(uint64_t low)
{
  std::fill(bits_.begin(), bits_.end(), (low & 1)
      ? UINT64_C(0x5555555555555555) : UINT64_C(0xAAAAAAAAAAAAAAAA));

  // correct 0, 1 and 2
  if (low <= 2)
  {
    uint64_t bit = 1 << (2 - low);
    bits_[0] &= ~(bit - 1);
    bits_[0] |= bit;
  }
}

/// Count the number of 1 bits inside [start, stop]
uint64_t BitSieve::count(uint64_t start, uint64_t stop) const
{
  if (start > stop)
    return 0;

  assert(stop < size_);
  uint64_t bit_count = count_edges(start, stop);
  uint64_t start_idx = (start >> 6) + 1;
  uint64_t limit = stop >> 6;

  for (uint64_t i = start_idx; i < limit; i++)
    bit_count += popcount64(bits_[i]);

  return bit_count;
}

uint64_t BitSieve::count_edges(uint64_t start, uint64_t stop) const
{
  uint64_t index1 = start >> 6;
  uint64_t index2 = stop  >> 6;
  uint64_t mask1 = UINT64_C(0xffffffffffffffff) << (start & 63);
  uint64_t mask2 = UINT64_C(0xffffffffffffffff) >> (63 - (stop & 63));
  uint64_t count = 0;

  if (index1 == index2)
    count += popcount64(bits_[index1] & (mask1 & mask2));
  else
  {
    count += popcount64(bits_[index1] & mask1);
    count += popcount64(bits_[index2] & mask2);
  }

  return count;
}

} // namespace
<|endoftext|>