<commit_before>#include <sys/time.h>

#include <sstream>
#include <algorithm>

#include <benchmark.h>

extern "C" {
#include "MerkleTree.h"
}

static const size_t hash_size = 32;

class MerkleInsert : public Benchmark
{
  protected:
    size_t num_nodes = 0;
    merkle_tree *tree;
    std::vector<uint8_t*> hashes;

  public:
    static std::string column_headers() { return "\"Nodes\"" + Benchmark::column_headers(); }

    MerkleInsert(size_t num_nodes) : Benchmark(), num_nodes(num_nodes) { }

    virtual ~MerkleInsert() {}

    virtual void bench_setup(const BenchmarkSettings & s)
    {
      Benchmark::bench_setup(s);
      uint8_t *ih = init_hash(hash_size);
      tree = mt_create(ih);
      free_hash(hash_size, ih);

      hashes.resize(num_nodes, NULL);
      for (uint64_t i = 0; i < num_nodes; i++)
      {
        hashes[i] = init_hash(hash_size);
        for (size_t j = 0; j < 8; j++)
           *(hashes[i] + j) = rand() % 8;
      }
    }

    virtual void bench_func()
    {
      for (uint64_t i = 0; i < num_nodes; i++)
      {
        #ifdef _DEBUG
        if (!mt_insert_pre(hash_size, tree, hashes[i]))
          throw std::logic_error("precondition violation");
        #endif
        mt_insert(hash_size, tree, hashes[i]);
      }

    }

    virtual void bench_cleanup(const BenchmarkSettings & s)
    {
      for (uint64_t i = 0; i < num_nodes; i++)
        free_hash(hash_size, hashes[i]);
      mt_free(tree);
      Benchmark::bench_cleanup(s);
    }

    virtual void report(std::ostream & rs, const BenchmarkSettings & s) const
    {
      rs << num_nodes;
      Benchmark::report(rs, s);
      rs << "\n";
    }
};

class MerklePathExtraction : public Benchmark
{
  protected:
    size_t num_nodes = 0;
    merkle_tree *tree;
    std::vector<uint8_t*> hashes;
    std::vector<LowStar_Vector_vector_str___uint8_t_*> paths;
    std::vector<uint8_t*> roots;

  public:
    static std::string column_headers() { return "\"Nodes\"" + Benchmark::column_headers(); }

    MerklePathExtraction(size_t num_nodes) : Benchmark(), num_nodes(num_nodes) { }

    virtual ~MerklePathExtraction() {}

    virtual void bench_setup(const BenchmarkSettings & s)
    {
      Benchmark::bench_setup(s);
      uint8_t *ih = init_hash(hash_size);
      tree = mt_create(ih);
      free_hash(hash_size, ih);

      hashes.resize(num_nodes, NULL);
      for (uint64_t i = 0; i < num_nodes; i++)
      {
        uint8_t *hash = init_hash(hash_size);
        hashes[i] = init_hash(hash_size);
        for (size_t j = 0; j < 8; j++)
           *(hashes[i] + j) = rand() % 8;
        #ifdef _DEBUG
        if (!mt_insert_pre(hash_size, tree, hashes[i]))
          throw std::logic_error("precondition violation");
        #endif
        mt_insert(hash_size, tree, hash);
      }

      paths.resize(num_nodes);
      roots.resize(num_nodes);
      for (uint64_t i = 0; i < num_nodes; i++)
      {
        roots[i] = init_hash(hash_size);
        paths[i] = init_path(hash_size);
      }
    }

    virtual void bench_func()
    {
      for (uint64_t i = 0; i < num_nodes; i++)
      {
        #ifdef _DEBUG
        if (!mt_get_path_pre(tree, i, paths[i], roots[i]))
          throw std::logic_error("precondition violation");
        #endif
        mt_get_path(tree, i, paths[i], roots[i]);
      }
    }

    virtual void bench_cleanup(const BenchmarkSettings & s)
    {
      for (uint64_t i = 0; i < num_nodes; i++)
      {
        clear_path(hash_size, paths[i]);
        free_path(hash_size, paths[i]);
        free_hash(hash_size, roots[i]);
        free_hash(hash_size, hashes[i]);
      }
      mt_free(tree);
      Benchmark::bench_cleanup(s);
    }

    virtual void report(std::ostream & rs, const BenchmarkSettings & s) const
    {
      rs << num_nodes;
      Benchmark::report(rs, s);
      rs << "\n";
    }
};

class MerklePathVerification : public Benchmark
{
  protected:
    size_t num_nodes = 0;
    merkle_tree *tree;
    std::vector<uint8_t*> hashes;
    std::vector<LowStar_Vector_vector_str___uint8_t_*> paths;
    std::vector<uint8_t*> roots;
    std::vector<uint32_t> js;

  public:
    static std::string column_headers() { return "\"Nodes\"" + Benchmark::column_headers(); }

    MerklePathVerification(size_t num_nodes) : Benchmark(), num_nodes(num_nodes) { }

    virtual ~MerklePathVerification() {}

    virtual void bench_setup(const BenchmarkSettings & s)
    {
      Benchmark::bench_setup(s);
      uint8_t *ih = init_hash(hash_size);
      tree = mt_create(ih);
      free_hash(hash_size, ih);

      hashes.resize(num_nodes, NULL);
      for (uint64_t i = 0; i < num_nodes; i++)
      {
        uint8_t *hash = init_hash(hash_size);
        hashes[i] = init_hash(hash_size);
        for (size_t j = 0; j < 8; j++)
           *(hashes[i] + j) = rand() % 8;
        #ifdef _DEBUG
        if (!mt_insert_pre(hash_size, tree, hashes[i]))
          throw std::logic_error("precondition violation");
        #endif
        mt_insert(hash_size, tree, hash);
      }

      paths.resize(num_nodes);
      roots.resize(num_nodes);
      js.resize(num_nodes);
      for (uint64_t i = 0; i < num_nodes; i++)
      {
        roots[i] = init_hash(hash_size);
        paths[i] = init_path(hash_size);

        #ifdef _DEBUG
        if (!mt_get_path_pre(tree, i, paths[i], roots[i]))
          throw std::logic_error("precondition violation");
        #endif
        js[i] = mt_get_path(tree, i, paths[i], roots[i]);
      }
    }

    virtual void bench_func()
    {
      for (uint64_t i = 0; i < num_nodes; i++)
      {
        #ifdef _DEBUG
        if (!mt_verify(tree, i, js[i], paths[i], roots[i]))
          throw std::logic_error("precondition violation");
        bool ok =
        #endif
          mt_verify(tree, i, js[i], paths[i], roots[i]);
        #ifdef _DEBUG
        if (!ok)
          throw std::logic_error("postcondition violation");
        #endif
      }
    }

    virtual void bench_cleanup(const BenchmarkSettings & s)
    {
      for (uint64_t i = 0; i < num_nodes; i++)
      {
        clear_path(hash_size, paths[i]);
        free_path(hash_size, paths[i]);
        free_hash(hash_size, roots[i]);
        free_hash(hash_size, hashes[i]);
      }
      mt_free(tree);
      Benchmark::bench_cleanup(s);
    }

    virtual void report(std::ostream & rs, const BenchmarkSettings & s) const
    {
      rs << num_nodes;
      Benchmark::report(rs, s);
      rs << "\n";
    }
};

void bench_merkle_insert(const BenchmarkSettings & s)
{
  size_t data_sizes[] = { 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576 };
  std::string data_filename = "bench_merkle_insert.csv";

  std::list<Benchmark*> todo;
  for (size_t ds: data_sizes)
    todo.push_back(new MerkleInsert(ds));

  Benchmark::run_batch(s, MerkleInsert::column_headers(), data_filename, todo);

  std::stringstream extras;
  extras << "set boxwidth 0.8\n";
  extras << "set key off\n";
  extras << "set style histogram clustered gap 3 title\n";
  extras << "set style data histograms\n";
  extras << "set bmargin 5\n";

  Benchmark::make_plot(s,
                  "svg",
                  "Merkle tree insertion performance",
                  "# tree nodes",
                  "Avg. performance [CPU cycles/insertion]",
                  Benchmark::histogram_line(data_filename, "", "Avg", "strcol('Nodes')", 0),
                  "bench_merkle_insert_cycles.svg",
                  extras.str());

  std::string X = "((" + std::to_string(s.samples) + " * column('Nodes'))/(column('CPUexcl')/1000000000))";
  std::string lbls = "sprintf(\"%dk\", column('Nodes')/1024)";
  Benchmark::PlotSpec plot_specs_timed = {
    std::make_pair(data_filename, "using " + X + ":xticlabels(" + lbls + ") with boxes"),
    std::make_pair("", "using 0:" + X + ":xticlabels(" + lbls + "):(sprintf(\"%0.0f\", " + X + ")) with labels font \"Courier,8\" offset char 0,.5 center notitle"),
  };

  Benchmark::make_plot(s,
                  "svg",
                  "Merkle tree insertion performance",
                  "# tree nodes",
                  "Avg. performance [insertion/sec]",
                  plot_specs_timed,
                  "bench_merkle_insert_timed.svg",
                  extras.str());
}

void bench_merkle_get_path(const BenchmarkSettings & s)
{
  size_t data_sizes[] = { 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576 };
  std::string data_filename = "bench_merkle_get_path.csv";

  std::list<Benchmark*> todo;
  for (size_t ds: data_sizes)
    todo.push_back(new MerklePathExtraction(ds));

  Benchmark::run_batch(s, MerklePathExtraction::column_headers(), data_filename, todo);

  std::stringstream extras;
  extras << "set boxwidth 0.8\n";
  extras << "set key off\n";
  extras << "set style histogram clustered gap 3 title\n";
  extras << "set style data histograms\n";
  extras << "set bmargin 5\n";

  Benchmark::make_plot(s,
                  "svg",
                  "Merkle tree path extraction performance",
                  "# tree nodes",
                  "Avg. performance [CPU cycles/path]",
                  Benchmark::histogram_line(data_filename, "", "Avg", "strcol('Nodes')", 0),
                  "bench_merkle_get_path_cycles.svg",
                  extras.str());

  std::string X = "((" + std::to_string(s.samples) + " * column('Nodes'))/(column('CPUexcl')/1000000000))";
  std::string lbls = "sprintf(\"%dk\", column('Nodes')/1024)";
  Benchmark::PlotSpec plot_specs_timed = {
    std::make_pair(data_filename, "using " + X + ":xticlabels(" + lbls + ") with boxes"),
    std::make_pair("", "using 0:" + X + ":xticlabels(" + lbls + "):(sprintf(\"%0.0f\", " + X + ")) with labels font \"Courier,8\" offset char 0,.5 center notitle"),
  };

  Benchmark::make_plot(s,
                  "svg",
                  "Merkle tree path extraction performance",
                  "# tree nodes",
                  "Avg. performance [paths/sec]",
                  plot_specs_timed,
                  "bench_merkle_get_path_timed.svg",
                  extras.str());
}

void bench_merkle_verify(const BenchmarkSettings & s)
{
  size_t data_sizes[] = { 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576 };
  std::string data_filename = "bench_merkle_verify.csv";

  std::list<Benchmark*> todo;
  for (size_t ds: data_sizes)
    todo.push_back(new MerklePathVerification(ds));

  Benchmark::run_batch(s, MerklePathVerification::column_headers(), data_filename, todo);

  std::stringstream extras;
  extras << "set boxwidth 0.8\n";
  extras << "set key off\n";
  extras << "set style histogram clustered gap 3 title\n";
  extras << "set style data histograms\n";
  extras << "set bmargin 5\n";

  Benchmark::make_plot(s,
                  "svg",
                  "Merkle tree path verification performance",
                  "# tree nodes",
                  "Avg. performance [CPU cycles/verification]",
                  Benchmark::histogram_line(data_filename, "", "Avg", "strcol('Nodes')", 0),
                  "bench_merkle_verify_cycles.svg",
                  extras.str());

  std::string X = "((" + std::to_string(s.samples) + " * column('Nodes'))/(column('CPUexcl')/1000000000))";
  std::string lbls = "sprintf(\"%dk\", column('Nodes')/1024)";
  Benchmark::PlotSpec plot_specs_timed = {
    std::make_pair(data_filename, "using " + X + ":xticlabels(" + lbls + ") with boxes"),
    std::make_pair("", "using 0:" + X + ":xticlabels(" + lbls + "):(sprintf(\"%0.0f\", " + X + ")) with labels font \"Courier,8\" offset char 0,.5 center notitle"),
  };

  Benchmark::make_plot(s,
                  "svg",
                  "Merkle tree path verification performance",
                  "# tree nodes",
                  "Avg. performance [paths/sec]",
                  plot_specs_timed,
                  "bench_merkle_verify_timed.svg",
                  extras.str());
}

void bench_merkle(const BenchmarkSettings & s)
{
  // These amortize over a number of tree nodes, so shouldn't need many samples.
  BenchmarkSettings s_local = s;
  s_local.samples = std::max<size_t>(s.samples / 1000, 1ul);
  s_local.warmup_samples = 0;

  bench_merkle_insert(s_local);
  bench_merkle_get_path(s_local);
  bench_merkle_verify(s_local);
}<commit_msg>Fix Merkle tree benchmark<commit_after>#include <sys/time.h>

#include <sstream>
#include <algorithm>

#include <benchmark.h>

extern "C" {
#include "MerkleTree.h"
}

static const size_t hash_size = 32;

class MerkleInsert : public Benchmark
{
  protected:
    size_t num_nodes = 0;
    merkle_tree *tree;
    std::vector<uint8_t*> hashes;

  public:
    static std::string column_headers() { return "\"Nodes\"" + Benchmark::column_headers(); }

    MerkleInsert(size_t num_nodes) : Benchmark(), num_nodes(num_nodes) { }

    virtual ~MerkleInsert() {}

    virtual void bench_setup(const BenchmarkSettings & s)
    {
      Benchmark::bench_setup(s);
      uint8_t *ih = init_hash(hash_size);
      tree = mt_create(ih);
      free_hash(hash_size, ih);

      hashes.resize(num_nodes, NULL);
      for (uint64_t i = 0; i < num_nodes; i++)
      {
        hashes[i] = init_hash(hash_size);
        for (size_t j = 0; j < 8; j++)
           *(hashes[i] + j) = rand() % 8;
      }
    }

    virtual void bench_func()
    {
      for (uint64_t i = 0; i < num_nodes; i++)
      {
        #ifdef _DEBUG
        if (!mt_insert_pre(tree, hashes[i]))
          throw std::logic_error("precondition violation");
        #endif
        mt_insert(tree, hashes[i]);
      }

    }

    virtual void bench_cleanup(const BenchmarkSettings & s)
    {
      for (uint64_t i = 0; i < num_nodes; i++)
        free_hash(hash_size, hashes[i]);
      mt_free(tree);
      Benchmark::bench_cleanup(s);
    }

    virtual void report(std::ostream & rs, const BenchmarkSettings & s) const
    {
      rs << num_nodes;
      Benchmark::report(rs, s);
      rs << "\n";
    }
};

class MerklePathExtraction : public Benchmark
{
  protected:
    size_t num_nodes = 0;
    merkle_tree *tree;
    std::vector<uint8_t*> hashes;
    std::vector<LowStar_Vector_vector_str___uint8_t_*> paths;
    std::vector<uint8_t*> roots;

  public:
    static std::string column_headers() { return "\"Nodes\"" + Benchmark::column_headers(); }

    MerklePathExtraction(size_t num_nodes) : Benchmark(), num_nodes(num_nodes) { }

    virtual ~MerklePathExtraction() {}

    virtual void bench_setup(const BenchmarkSettings & s)
    {
      Benchmark::bench_setup(s);
      uint8_t *ih = init_hash(hash_size);
      tree = mt_create(ih);
      free_hash(hash_size, ih);

      hashes.resize(num_nodes, NULL);
      for (uint64_t i = 0; i < num_nodes; i++)
      {
        uint8_t *hash = init_hash(hash_size);
        hashes[i] = init_hash(hash_size);
        for (size_t j = 0; j < 8; j++)
           *(hashes[i] + j) = rand() % 8;
        #ifdef _DEBUG
        if (!mt_insert_pre(tree, hashes[i]))
          throw std::logic_error("precondition violation");
        #endif
        mt_insert(tree, hash);
      }

      paths.resize(num_nodes);
      roots.resize(num_nodes);
      for (uint64_t i = 0; i < num_nodes; i++)
      {
        roots[i] = init_hash(hash_size);
        paths[i] = init_path(hash_size);
      }
    }

    virtual void bench_func()
    {
      for (uint64_t i = 0; i < num_nodes; i++)
      {
        #ifdef _DEBUG
        if (!mt_get_path_pre(tree, i, paths[i], roots[i]))
          throw std::logic_error("precondition violation");
        #endif
        mt_get_path(tree, i, paths[i], roots[i]);
      }
    }

    virtual void bench_cleanup(const BenchmarkSettings & s)
    {
      for (uint64_t i = 0; i < num_nodes; i++)
      {
        clear_path(hash_size, paths[i]);
        free_path(hash_size, paths[i]);
        free_hash(hash_size, roots[i]);
        free_hash(hash_size, hashes[i]);
      }
      mt_free(tree);
      Benchmark::bench_cleanup(s);
    }

    virtual void report(std::ostream & rs, const BenchmarkSettings & s) const
    {
      rs << num_nodes;
      Benchmark::report(rs, s);
      rs << "\n";
    }
};

class MerklePathVerification : public Benchmark
{
  protected:
    size_t num_nodes = 0;
    merkle_tree *tree;
    std::vector<uint8_t*> hashes;
    std::vector<LowStar_Vector_vector_str___uint8_t_*> paths;
    std::vector<uint8_t*> roots;
    std::vector<uint32_t> js;

  public:
    static std::string column_headers() { return "\"Nodes\"" + Benchmark::column_headers(); }

    MerklePathVerification(size_t num_nodes) : Benchmark(), num_nodes(num_nodes) { }

    virtual ~MerklePathVerification() {}

    virtual void bench_setup(const BenchmarkSettings & s)
    {
      Benchmark::bench_setup(s);
      uint8_t *ih = init_hash(hash_size);
      tree = mt_create(ih);
      free_hash(hash_size, ih);

      hashes.resize(num_nodes, NULL);
      for (uint64_t i = 0; i < num_nodes; i++)
      {
        uint8_t *hash = init_hash(hash_size);
        hashes[i] = init_hash(hash_size);
        for (size_t j = 0; j < 8; j++)
           *(hashes[i] + j) = rand() % 8;
        #ifdef _DEBUG
        if (!mt_insert_pre(tree, hashes[i]))
          throw std::logic_error("precondition violation");
        #endif
        mt_insert(tree, hash);
      }

      paths.resize(num_nodes);
      roots.resize(num_nodes);
      js.resize(num_nodes);
      for (uint64_t i = 0; i < num_nodes; i++)
      {
        roots[i] = init_hash(hash_size);
        paths[i] = init_path(hash_size);

        #ifdef _DEBUG
        if (!mt_get_path_pre(tree, i, paths[i], roots[i]))
          throw std::logic_error("precondition violation");
        #endif
        js[i] = mt_get_path(tree, i, paths[i], roots[i]);
      }
    }

    virtual void bench_func()
    {
      for (uint64_t i = 0; i < num_nodes; i++)
      {
        #ifdef _DEBUG
        if (!mt_verify(tree, i, js[i], paths[i], roots[i]))
          throw std::logic_error("precondition violation");
        bool ok =
        #endif
          mt_verify(tree, i, js[i], paths[i], roots[i]);
        #ifdef _DEBUG
        if (!ok)
          throw std::logic_error("postcondition violation");
        #endif
      }
    }

    virtual void bench_cleanup(const BenchmarkSettings & s)
    {
      for (uint64_t i = 0; i < num_nodes; i++)
      {
        clear_path(hash_size, paths[i]);
        free_path(hash_size, paths[i]);
        free_hash(hash_size, roots[i]);
        free_hash(hash_size, hashes[i]);
      }
      mt_free(tree);
      Benchmark::bench_cleanup(s);
    }

    virtual void report(std::ostream & rs, const BenchmarkSettings & s) const
    {
      rs << num_nodes;
      Benchmark::report(rs, s);
      rs << "\n";
    }
};

void bench_merkle_insert(const BenchmarkSettings & s)
{
  size_t data_sizes[] = { 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576 };
  std::string data_filename = "bench_merkle_insert.csv";

  std::list<Benchmark*> todo;
  for (size_t ds: data_sizes)
    todo.push_back(new MerkleInsert(ds));

  Benchmark::run_batch(s, MerkleInsert::column_headers(), data_filename, todo);

  std::stringstream extras;
  extras << "set boxwidth 0.8\n";
  extras << "set key off\n";
  extras << "set style histogram clustered gap 3 title\n";
  extras << "set style data histograms\n";
  extras << "set bmargin 5\n";

  Benchmark::make_plot(s,
                  "svg",
                  "Merkle tree insertion performance",
                  "# tree nodes",
                  "Avg. performance [CPU cycles/insertion]",
                  Benchmark::histogram_line(data_filename, "", "Avg", "strcol('Nodes')", 0),
                  "bench_merkle_insert_cycles.svg",
                  extras.str());

  std::string X = "((" + std::to_string(s.samples) + " * column('Nodes'))/(column('CPUexcl')/1000000000))";
  std::string lbls = "sprintf(\"%dk\", column('Nodes')/1024)";
  Benchmark::PlotSpec plot_specs_timed = {
    std::make_pair(data_filename, "using " + X + ":xticlabels(" + lbls + ") with boxes"),
    std::make_pair("", "using 0:" + X + ":xticlabels(" + lbls + "):(sprintf(\"%0.0f\", " + X + ")) with labels font \"Courier,8\" offset char 0,.5 center notitle"),
  };

  Benchmark::make_plot(s,
                  "svg",
                  "Merkle tree insertion performance",
                  "# tree nodes",
                  "Avg. performance [insertion/sec]",
                  plot_specs_timed,
                  "bench_merkle_insert_timed.svg",
                  extras.str());
}

void bench_merkle_get_path(const BenchmarkSettings & s)
{
  size_t data_sizes[] = { 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576 };
  std::string data_filename = "bench_merkle_get_path.csv";

  std::list<Benchmark*> todo;
  for (size_t ds: data_sizes)
    todo.push_back(new MerklePathExtraction(ds));

  Benchmark::run_batch(s, MerklePathExtraction::column_headers(), data_filename, todo);

  std::stringstream extras;
  extras << "set boxwidth 0.8\n";
  extras << "set key off\n";
  extras << "set style histogram clustered gap 3 title\n";
  extras << "set style data histograms\n";
  extras << "set bmargin 5\n";

  Benchmark::make_plot(s,
                  "svg",
                  "Merkle tree path extraction performance",
                  "# tree nodes",
                  "Avg. performance [CPU cycles/path]",
                  Benchmark::histogram_line(data_filename, "", "Avg", "strcol('Nodes')", 0),
                  "bench_merkle_get_path_cycles.svg",
                  extras.str());

  std::string X = "((" + std::to_string(s.samples) + " * column('Nodes'))/(column('CPUexcl')/1000000000))";
  std::string lbls = "sprintf(\"%dk\", column('Nodes')/1024)";
  Benchmark::PlotSpec plot_specs_timed = {
    std::make_pair(data_filename, "using " + X + ":xticlabels(" + lbls + ") with boxes"),
    std::make_pair("", "using 0:" + X + ":xticlabels(" + lbls + "):(sprintf(\"%0.0f\", " + X + ")) with labels font \"Courier,8\" offset char 0,.5 center notitle"),
  };

  Benchmark::make_plot(s,
                  "svg",
                  "Merkle tree path extraction performance",
                  "# tree nodes",
                  "Avg. performance [paths/sec]",
                  plot_specs_timed,
                  "bench_merkle_get_path_timed.svg",
                  extras.str());
}

void bench_merkle_verify(const BenchmarkSettings & s)
{
  size_t data_sizes[] = { 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576 };
  std::string data_filename = "bench_merkle_verify.csv";

  std::list<Benchmark*> todo;
  for (size_t ds: data_sizes)
    todo.push_back(new MerklePathVerification(ds));

  Benchmark::run_batch(s, MerklePathVerification::column_headers(), data_filename, todo);

  std::stringstream extras;
  extras << "set boxwidth 0.8\n";
  extras << "set key off\n";
  extras << "set style histogram clustered gap 3 title\n";
  extras << "set style data histograms\n";
  extras << "set bmargin 5\n";

  Benchmark::make_plot(s,
                  "svg",
                  "Merkle tree path verification performance",
                  "# tree nodes",
                  "Avg. performance [CPU cycles/verification]",
                  Benchmark::histogram_line(data_filename, "", "Avg", "strcol('Nodes')", 0),
                  "bench_merkle_verify_cycles.svg",
                  extras.str());

  std::string X = "((" + std::to_string(s.samples) + " * column('Nodes'))/(column('CPUexcl')/1000000000))";
  std::string lbls = "sprintf(\"%dk\", column('Nodes')/1024)";
  Benchmark::PlotSpec plot_specs_timed = {
    std::make_pair(data_filename, "using " + X + ":xticlabels(" + lbls + ") with boxes"),
    std::make_pair("", "using 0:" + X + ":xticlabels(" + lbls + "):(sprintf(\"%0.0f\", " + X + ")) with labels font \"Courier,8\" offset char 0,.5 center notitle"),
  };

  Benchmark::make_plot(s,
                  "svg",
                  "Merkle tree path verification performance",
                  "# tree nodes",
                  "Avg. performance [paths/sec]",
                  plot_specs_timed,
                  "bench_merkle_verify_timed.svg",
                  extras.str());
}

void bench_merkle(const BenchmarkSettings & s)
{
  // These amortize over a number of tree nodes, so shouldn't need many samples.
  BenchmarkSettings s_local = s;
  s_local.samples = std::max<size_t>(s.samples / 1000, 1ul);
  s_local.warmup_samples = 0;

  bench_merkle_insert(s_local);
  bench_merkle_get_path(s_local);
  bench_merkle_verify(s_local);
}<|endoftext|>


<commit_before>//----------------------------  get_dof_indices_01.cc  ---------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 2006 by the deal.II authors and Anna Schneebeli
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//----------------------------  get_dof_indices_01.cc  ---------------------------

// make sure we can call DoFCellAccessor::get_dof_indices also for
// inactive cells

#include "../tests.h"
#include <base/function.h>
#include <base/logstream.h>
#include <lac/vector.h>

#include <grid/tria.h>
#include <dofs/dof_handler.h>
#include <grid/grid_generator.h>
#include <grid/grid_refinement.h>
#include <grid/tria_accessor.h>
#include <grid/tria_iterator.h>
#include <grid/tria_boundary_lib.h>
#include <dofs/dof_accessor.h>
#include <dofs/dof_tools.h>
#include <fe/fe_q.h>

#include <fstream>
#include <iostream>
#include <vector>

template <int dim>
void test ()
{
  Triangulation<dim> triangulation;
  DoFHandler<dim> dof_handler(triangulation);

  GridGenerator::hyper_cube (triangulation);
  triangulation.refine_global (1);

  FE_Q<dim> fe(1);
  dof_handler.distribute_dofs (fe);

				   // loop over all cells, active or
				   // not
  std::vector<unsigned int> local_dof_indices (fe.dofs_per_cell);
  for (typename DoFHandler<dim>::cell_iterator cell=dof_handler.begin();
       cell != dof_handler.end(); ++cell)
    {
      cell->get_dof_indices (local_dof_indices);

      deallog << "Cell = " << cell
	      << ", DoFs=";
      for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
	{
	  Assert (local_dof_indices[i] != DoFHandler<dim>::invalid_dof_index,
		  ExcInternalError());
	  deallog << local_dof_indices[i] << ' ';
	}

      deallog << std::endl;
    }
}

int main ()
{
  std::ofstream logfile("get_dof_indices_01/output");
  deallog.attach(logfile);
  deallog.depth_console(0);
  deallog.threshold_double(1.e-10);

  test<1>();
  test<2>();
  test<3>();

  return 0;
}

<commit_msg>Avoid exception with Subscriptor.<commit_after>//----------------------------  get_dof_indices_01.cc  ---------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 2006 by the deal.II authors and Anna Schneebeli
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//----------------------------  get_dof_indices_01.cc  ---------------------------

// make sure we can call DoFCellAccessor::get_dof_indices also for
// inactive cells

#include "../tests.h"
#include <base/function.h>
#include <base/logstream.h>
#include <lac/vector.h>

#include <grid/tria.h>
#include <dofs/dof_handler.h>
#include <grid/grid_generator.h>
#include <grid/grid_refinement.h>
#include <grid/tria_accessor.h>
#include <grid/tria_iterator.h>
#include <grid/tria_boundary_lib.h>
#include <dofs/dof_accessor.h>
#include <dofs/dof_tools.h>
#include <fe/fe_q.h>

#include <fstream>
#include <iostream>
#include <vector>

template <int dim>
void test ()
{
  Triangulation<dim> triangulation;
  FE_Q<dim> fe(1);
  DoFHandler<dim> dof_handler(triangulation);

  GridGenerator::hyper_cube (triangulation);
  triangulation.refine_global (1);

  dof_handler.distribute_dofs (fe);

				   // loop over all cells, active or
				   // not
  std::vector<unsigned int> local_dof_indices (fe.dofs_per_cell);
  for (typename DoFHandler<dim>::cell_iterator cell=dof_handler.begin();
       cell != dof_handler.end(); ++cell)
    {
      cell->get_dof_indices (local_dof_indices);

      deallog << "Cell = " << cell
	      << ", DoFs=";
      for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
	{
	  Assert (local_dof_indices[i] != DoFHandler<dim>::invalid_dof_index,
		  ExcInternalError());
	  deallog << local_dof_indices[i] << ' ';
	}

      deallog << std::endl;
    }
}

int main ()
{
  std::ofstream logfile("get_dof_indices_01/output");
  deallog.attach(logfile);
  deallog.depth_console(0);
  deallog.threshold_double(1.e-10);

  test<1>();
  test<2>();
  test<3>();

  return 0;
}

<|endoftext|>


<commit_before>#include <sparsehash/dense_hash_map>
#include <unordered_map>

#include "hashtable_test_interface.h"
#include "gtest/gtest.h"
#include <unordered_map>
#include <unordered_set>
#include <chrono>

using google::dense_hash_map;
using google::dense_hash_set;

namespace sparsehash_internal = google::sparsehash_internal;

TEST(HashtableMoveTest, Insert_RValue)
{
    dense_hash_map<int, std::unique_ptr<int>> h;
    h.set_empty_key(0);

    auto p1 = std::make_pair(5, std::unique_ptr<int>(new int(1234)));
    auto p = h.insert(std::move(p1));
    ASSERT_EQ(true, p.second);
    ASSERT_EQ(5, p.first->first);
    ASSERT_EQ(1234, *p.first->second);

    p = h.insert(std::make_pair(10, std::unique_ptr<int>(new int(5678))));
    ASSERT_EQ(true, p.second);
    ASSERT_EQ(10, p.first->first);
    ASSERT_EQ(5678, *p.first->second);

    ASSERT_EQ(2, (int)h.size());
}

TEST(HashtableMoveTest, Emplace)
{
    dense_hash_map<int, std::unique_ptr<int>> h;
    h.set_empty_key(0);

    auto p = h.emplace(5, new int(1234));
    ASSERT_EQ(true, p.second);
    ASSERT_EQ(5, p.first->first);
    ASSERT_EQ(1234, *p.first->second);

    p = h.emplace(10, new int(5678));
    ASSERT_EQ(true, p.second);
    ASSERT_EQ(10, p.first->first);
    ASSERT_EQ(5678, *p.first->second);

    ASSERT_EQ(2, (int)h.size());

    ASSERT_TRUE(h.emplace(11, new int(1)).second);
    ASSERT_FALSE(h.emplace(11, new int(1)).second);
    ASSERT_TRUE(h.emplace(12, new int(1)).second);
    ASSERT_FALSE(h.emplace(12, new int(1)).second);
}

TEST(HashtableMoveTest, EmplaceHint)
{
    dense_hash_map<int, int> h;
    h.set_empty_key(0);

    h[1] = 1;
    h[3] = 3;
    h[5] = 5;

    ASSERT_FALSE(h.emplace_hint(h.find(1), 1, 0).second);
    ASSERT_FALSE(h.emplace_hint(h.find(3), 1, 0).second);
    ASSERT_FALSE(h.emplace_hint(h.end(), 1, 0).second);
    ASSERT_EQ(3, (int)h.size());

    ASSERT_TRUE(h.emplace_hint(h.find(1), 2, 0).second);
    ASSERT_TRUE(h.emplace_hint(h.find(3), 4, 0).second);
    ASSERT_TRUE(h.emplace_hint(h.end(), 6, 0).second);
    ASSERT_EQ(6, (int)h.size());
}

TEST(HashtableMoveTest, EmplaceHint_SpeedComparison)
{
    static const int Elements = 1e6;
    static const int Duplicates = 5;

    std::vector<int> v(Elements * Duplicates);

    for (int i = 0; i < Elements * Duplicates; i += Duplicates)
    {
        auto r = std::rand();

        for (int j = 0; j < Duplicates; ++j)
            v[i + j] = r;
    }

    std::sort(std::begin(v), std::end(v));

    auto start = std::chrono::system_clock::now();

    {
        dense_hash_map<int, int> h;
        h.set_empty_key(-1);

        for (int i = 0; i < Elements; ++i)
            h.emplace(v[i], 0);
    }

    auto end = std::chrono::system_clock::now();
    auto emplace_time = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();

    start = std::chrono::system_clock::now();

    {
        dense_hash_map<int, int> h;
        h.set_empty_key(-1);

        auto hint = h.begin();
        for (int i = 0; i < Elements; ++i)
            hint = h.emplace_hint(hint, v[i], 0).first;
    }

    end = std::chrono::system_clock::now();
    auto emplace_hint_time = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();

    ASSERT_LE(emplace_hint_time, emplace_time);
}

struct A
{
    A() =default;
    A(int i) noexcept : _i(i) {}

    A(const A&) =delete;
    A& operator=(const A&) =delete;

    A(A&& a) { _i = a._i; move_ctor = a.move_ctor + 1; }
    A& operator=(A&& a) { _i = a._i; move_assign = a.move_assign + 1; return *this; }

    int _i = 0;
    int move_ctor = 0;
    int move_assign = 0;
};

bool operator==(const A& a1, const A& a2) { return a1._i == a2._i; }

struct HashA
{
    std::size_t operator()(const A& a) const { return std::hash<int>()(a._i); }
};

TEST(HashtableMoveTest, MoveCount)
{
    dense_hash_map<int, A> h(10);
    h.set_empty_key(0);

    h.insert(std::make_pair(5, A()));
    ASSERT_EQ(0, h[5].move_assign);
    ASSERT_EQ(3, h[5].move_ctor);
}

TEST(HashtableMoveTest, EmplaceMoveCount)
{
    dense_hash_map<int, A> h;
    h.set_empty_key(0);

    h.emplace(1, 2);
    ASSERT_EQ(0, h[1].move_assign);
    ASSERT_EQ(0, h[1].move_ctor);
}

struct B
{
    B() =default;
    B(int i) noexcept : _i(i) {}

    B(const B& b) { _i = b._i; ++copy_ctor;; }
    B& operator=(const B& b) { _i = b._i; ++copy_assign; return *this; }

    B(B&& b) { _i = b._i; ++move_ctor; }
    B& operator=(B&& b) { _i = b._i; ++move_assign; return *this; }

    static void reset()
    {
        copy_ctor = 0;
        copy_assign = 0;
        move_ctor = 0;
        move_assign = 0;
    }

    int _i = 0;

    static int copy_ctor;
    static int copy_assign;
    static int move_ctor;
    static int move_assign;
};

int B::copy_ctor = 0;
int B::copy_assign = 0;
int B::move_ctor = 0;
int B::move_assign = 0;

std::ostream& operator<<(std::ostream& os, const B& b)
{
    return os << b._i << " copy_ctor=" << b.copy_ctor << " copy_assign=" << b.copy_assign <<
                         " move_ctor=" << b.move_ctor << " move_assign=" << b.move_assign;
}

bool operator==(const B& b1, const B& b2) { return b1._i == b2._i; }

struct HashB
{
    std::size_t operator()(const B& b) const { return std::hash<int>()(b._i); }
};

TEST(HashtableMoveTest, EmplaceKeyMoveCount)
{
    dense_hash_map<B, int, HashB> h;
    h.set_empty_key(B(0));

    B::reset();
    auto p = h.emplace(1, 2);
    ASSERT_EQ(0, p.first->first.copy_ctor);
    ASSERT_EQ(0, p.first->first.copy_assign);
    ASSERT_EQ(0, p.first->first.move_ctor);
    ASSERT_EQ(0, p.first->first.move_assign);
}

TEST(HashtableMoveTest, InsertKeyRValueCount)
{
    dense_hash_map<B, int, HashB> h;
    h.set_empty_key(B(0));

    B::reset();
    auto p = h.insert(std::make_pair(B(2), 2));
    std::cout << p.first->first << std::endl;
    ASSERT_EQ(0, p.first->first.copy_ctor);
    ASSERT_EQ(0, p.first->first.copy_assign);
}

TEST(HashtableMoveTest, InsertKeyMovedCount)
{
    dense_hash_map<B, int, HashB> h;
    h.set_empty_key(B(0));

    B::reset();
    auto m = std::make_pair(B(2), 2);
    auto p = h.insert(std::move(m));

    std::cout << p.first->first << std::endl;
    ASSERT_EQ(0, p.first->first.copy_ctor);
    ASSERT_EQ(0, p.first->first.copy_assign);
}

TEST(HashtableMoveTest, InsertValueRValueCount)
{
    dense_hash_map<int, B> h;
    h.set_empty_key(0);

    B::reset();
    auto p = h.insert(std::make_pair(2, B(2)));

    std::cout << p.first->second << std::endl;
    ASSERT_EQ(0, p.first->second.copy_ctor);
    ASSERT_EQ(0, p.first->second.copy_assign);
}
TEST(HashtableMoveTest, InsertValueMovedCount)
{
    dense_hash_map<int, B> h;
    h.set_empty_key(0);

    B::reset();
    auto m = std::make_pair(2, B(2));
    auto p = h.insert(std::move(m));

    std::cout << p.first->second << std::endl;
    ASSERT_EQ(0, p.first->second.copy_ctor);
    ASSERT_EQ(0, p.first->second.copy_assign);
}

TEST(HashtableMoveTest, OperatorInsertRValueCount)
{
    dense_hash_map<B, int, HashB> h;
    h.set_empty_key(B(0));

    B::reset();
    h[B(1)] = 1;

    std::cout << B() << std::endl;
    // without operator[](const K&): copy_ctor=2 copy_assign=0 move_ctor=1 move_assign=0
    // now:    copy_ctor=0 copy_assign=0 move_ctor=1 move_assign=0
    ASSERT_EQ(0, B::copy_ctor);
    ASSERT_EQ(0, B::copy_assign);
    ASSERT_EQ(1, B::move_ctor);
    ASSERT_EQ(0, B::move_assign);
}

TEST(HashtableMoveTest, EraseConstIterator)
{
    dense_hash_map<int, int> h;
    h.set_empty_key(0);
    h.set_deleted_key(-1);

    h[1] = 1;
    const auto it = h.begin();
    ASSERT_TRUE(h.end() == h.erase(it));
    ASSERT_EQ(0, (int)h.size());
}

TEST(HashtableMoveTest, EraseRange)
{
    dense_hash_map<int, int> h;
    h.set_empty_key(0);
    h.set_deleted_key(-1);

    for (int i = 0; i < 10; ++i)
        h[i + 1] = i;

    auto it = h.begin();
    std::advance(it, 2);

    auto it2 = h.begin();
    std::advance(it2, 8);

    auto nextit = h.erase(it, it2);
    ASSERT_FALSE(h.end() == nextit);
    nextit = h.erase(nextit);
    ASSERT_FALSE(h.end() == nextit);
    ASSERT_TRUE(h.end() == h.erase(nextit));

    ASSERT_FALSE(h.end() == h.erase(h.begin()));
    ASSERT_TRUE(h.end() == h.erase(h.begin()));

    ASSERT_TRUE(h.empty());
}

TEST(HashtableMoveTest, EraseRangeEntireMap)
{
    dense_hash_map<int, int> h;
    h.set_empty_key(0);
    h.set_deleted_key(-1);

    for (int i = 0; i < 10; ++i)
        h[i + 1] = i;

    ASSERT_TRUE(h.end() == h.erase(h.begin(), h.end()));
    ASSERT_TRUE(h.empty());
}

TEST(HashtableMoveTest, EraseNextElementReturned)
{
    dense_hash_map<int, int> h;
    h.set_empty_key(0);
    h.set_deleted_key(-1);

    h[1] = 1;
    h[2] = 2;

    int first = h.begin()->first;
    int second = first == 1 ? 2 : 1;

    ASSERT_EQ(second, h.erase(h.begin())->first); // second element is returned when erasing the first one
    ASSERT_TRUE(h.end() == h.erase(h.begin())); // end() is returned when erasing the second and last element
}

TEST(HashtableMoveTest, EraseNumberOfElementsDeleted)
{
    dense_hash_map<int, int> h;
    h.set_empty_key(0);
    h.set_deleted_key(-1);

    h[1] = 1;
    h[2] = 2;

    ASSERT_EQ(0, (int)h.erase(3));
    ASSERT_EQ(1, (int)h.erase(1));
    ASSERT_EQ(1, (int)h.erase(2));
    ASSERT_EQ(0, (int)h.erase(4));
    ASSERT_TRUE(h.empty());
}

TEST(HashtableMoveTest, CBeginCEnd)
{
    dense_hash_map<int, int> h;
    h.set_empty_key(0);
    h.set_deleted_key(-1);

    h[1] = 1;

    auto it = h.cbegin();
    ASSERT_EQ(1, it->first);

    std::advance(it, 1);
    ASSERT_TRUE(it == h.cend());

    using cit = dense_hash_map<int, int>::const_iterator;
    cit begin = h.begin();
    cit end = h.end();
    ASSERT_TRUE(begin == h.cbegin());
    ASSERT_TRUE(end == h.cend());
}
<commit_msg>Clean up in unit tests<commit_after>#include <sparsehash/dense_hash_map>
#include <unordered_map>

#include "hashtable_test_interface.h"
#include "gtest/gtest.h"
#include <unordered_map>
#include <unordered_set>
#include <chrono>

using google::dense_hash_map;
using google::dense_hash_set;

namespace sparsehash_internal = google::sparsehash_internal;

TEST(HashtableMoveTest, Insert_RValue)
{
    dense_hash_map<int, std::unique_ptr<int>> h;
    h.set_empty_key(0);

    auto p1 = std::make_pair(5, std::unique_ptr<int>(new int(1234)));
    auto p = h.insert(std::move(p1));
    ASSERT_EQ(true, p.second);
    ASSERT_EQ(5, p.first->first);
    ASSERT_EQ(1234, *p.first->second);

    p = h.insert(std::make_pair(10, std::unique_ptr<int>(new int(5678))));
    ASSERT_EQ(true, p.second);
    ASSERT_EQ(10, p.first->first);
    ASSERT_EQ(5678, *p.first->second);

    ASSERT_EQ(2, (int)h.size());
}

TEST(HashtableMoveTest, Emplace)
{
    dense_hash_map<int, std::unique_ptr<int>> h;
    h.set_empty_key(0);

    auto p = h.emplace(5, new int(1234));
    ASSERT_EQ(true, p.second);
    ASSERT_EQ(5, p.first->first);
    ASSERT_EQ(1234, *p.first->second);

    p = h.emplace(10, new int(5678));
    ASSERT_EQ(true, p.second);
    ASSERT_EQ(10, p.first->first);
    ASSERT_EQ(5678, *p.first->second);

    ASSERT_EQ(2, (int)h.size());

    ASSERT_TRUE(h.emplace(11, new int(1)).second);
    ASSERT_FALSE(h.emplace(11, new int(1)).second);
    ASSERT_TRUE(h.emplace(12, new int(1)).second);
    ASSERT_FALSE(h.emplace(12, new int(1)).second);
}

TEST(HashtableMoveTest, EmplaceHint)
{
    dense_hash_map<int, int> h;
    h.set_empty_key(0);

    h[1] = 1;
    h[3] = 3;
    h[5] = 5;

    ASSERT_FALSE(h.emplace_hint(h.find(1), 1, 0).second);
    ASSERT_FALSE(h.emplace_hint(h.find(3), 1, 0).second);
    ASSERT_FALSE(h.emplace_hint(h.end(), 1, 0).second);
    ASSERT_EQ(3, (int)h.size());

    ASSERT_TRUE(h.emplace_hint(h.find(1), 2, 0).second);
    ASSERT_TRUE(h.emplace_hint(h.find(3), 4, 0).second);
    ASSERT_TRUE(h.emplace_hint(h.end(), 6, 0).second);
    ASSERT_EQ(6, (int)h.size());
}

TEST(HashtableMoveTest, EmplaceHint_SpeedComparison)
{
    static const int Elements = 1e6;
    static const int Duplicates = 5;

    std::vector<int> v(Elements * Duplicates);

    for (int i = 0; i < Elements * Duplicates; i += Duplicates)
    {
        auto r = std::rand();

        for (int j = 0; j < Duplicates; ++j)
            v[i + j] = r;
    }

    std::sort(std::begin(v), std::end(v));

    auto start = std::chrono::system_clock::now();

    {
        dense_hash_map<int, int> h;
        h.set_empty_key(-1);

        for (int i = 0; i < Elements; ++i)
            h.emplace(v[i], 0);
    }

    auto end = std::chrono::system_clock::now();
    auto emplace_time = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();

    start = std::chrono::system_clock::now();

    {
        dense_hash_map<int, int> h;
        h.set_empty_key(-1);

        auto hint = h.begin();
        for (int i = 0; i < Elements; ++i)
            hint = h.emplace_hint(hint, v[i], 0).first;
    }

    end = std::chrono::system_clock::now();
    auto emplace_hint_time = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();

    ASSERT_LE(emplace_hint_time, emplace_time);
}

struct A
{
    A() =default;
    A(int i) noexcept : _i(i) {}

    A(const A&) =delete;
    A& operator=(const A&) =delete;

    A(A&& a) { _i = a._i; move_ctor = a.move_ctor + 1; }
    A& operator=(A&& a) { _i = a._i; move_assign = a.move_assign + 1; return *this; }

    int _i = 0;
    int move_ctor = 0;
    int move_assign = 0;
};

bool operator==(const A& a1, const A& a2) { return a1._i == a2._i; }

struct HashA
{
    std::size_t operator()(const A& a) const { return std::hash<int>()(a._i); }
};

TEST(HashtableMoveTest, MoveCount)
{
    dense_hash_map<int, A> h(10);
    h.set_empty_key(0);

    h.insert(std::make_pair(5, A()));
    ASSERT_EQ(0, h[5].move_assign);
    ASSERT_EQ(3, h[5].move_ctor);
}

TEST(HashtableMoveTest, EmplaceMoveCount)
{
    dense_hash_map<int, A> h;
    h.set_empty_key(0);

    h.emplace(1, 2);
    ASSERT_EQ(0, h[1].move_assign);
    ASSERT_EQ(0, h[1].move_ctor);
}

struct B
{
    B() =default;
    B(int i) noexcept : _i(i) {}

    B(const B& b) { _i = b._i; ++copy_ctor;; }
    B& operator=(const B& b) { _i = b._i; ++copy_assign; return *this; }

    B(B&& b) { _i = b._i; ++move_ctor; }
    B& operator=(B&& b) { _i = b._i; ++move_assign; return *this; }

    static void reset()
    {
        copy_ctor = 0;
        copy_assign = 0;
        move_ctor = 0;
        move_assign = 0;
    }

    int _i = 0;

    static int copy_ctor;
    static int copy_assign;
    static int move_ctor;
    static int move_assign;
};

int B::copy_ctor = 0;
int B::copy_assign = 0;
int B::move_ctor = 0;
int B::move_assign = 0;

std::ostream& operator<<(std::ostream& os, const B& b)
{
    return os << b._i << " copy_ctor=" << b.copy_ctor << " copy_assign=" << b.copy_assign <<
                         " move_ctor=" << b.move_ctor << " move_assign=" << b.move_assign;
}

bool operator==(const B& b1, const B& b2) { return b1._i == b2._i; }

struct HashB
{
    std::size_t operator()(const B& b) const { return std::hash<int>()(b._i); }
};

TEST(HashtableMoveTest, EmplaceKeyMoveCount)
{
    dense_hash_map<B, int, HashB> h;
    h.set_empty_key(B(0));

    B::reset();
    auto p = h.emplace(1, 2);
    ASSERT_EQ(0, p.first->first.copy_ctor);
    ASSERT_EQ(0, p.first->first.copy_assign);
    ASSERT_EQ(0, p.first->first.move_ctor);
    ASSERT_EQ(0, p.first->first.move_assign);
}

TEST(HashtableMoveTest, InsertKeyRValueCount)
{
    dense_hash_map<B, int, HashB> h;
    h.set_empty_key(B(0));

    B::reset();
    h.insert(std::make_pair(B(2), 2));

    std::cout << B() << std::endl;
    ASSERT_EQ(0, B::copy_ctor);
    ASSERT_EQ(0, B::copy_assign);
}

TEST(HashtableMoveTest, InsertKeyMovedCount)
{
    dense_hash_map<B, int, HashB> h;
    h.set_empty_key(B(0));

    B::reset();
    auto m = std::make_pair(B(2), 2);
    h.insert(std::move(m));

    std::cout << B() << std::endl;
    ASSERT_EQ(0, B::copy_ctor);
    ASSERT_EQ(0, B::copy_assign);
}

TEST(HashtableMoveTest, InsertValueRValueCount)
{
    dense_hash_map<int, B> h;
    h.set_empty_key(0);

    B::reset();
    auto p = h.insert(std::make_pair(2, B(2)));

    std::cout << p.first->second << std::endl;
    ASSERT_EQ(0, p.first->second.copy_ctor);
    ASSERT_EQ(0, p.first->second.copy_assign);
}
TEST(HashtableMoveTest, InsertValueMovedCount)
{
    dense_hash_map<int, B> h;
    h.set_empty_key(0);

    B::reset();
    auto m = std::make_pair(2, B(2));
    auto p = h.insert(std::move(m));

    std::cout << p.first->second << std::endl;
    ASSERT_EQ(0, p.first->second.copy_ctor);
    ASSERT_EQ(0, p.first->second.copy_assign);
}

TEST(HashtableMoveTest, OperatorInsertRValueCount)
{
    dense_hash_map<B, int, HashB> h;
    h.set_empty_key(B(0));

    B::reset();
    h[B(1)] = 1;

    std::cout << B() << std::endl;
    // without operator[](const K&): copy_ctor=2 copy_assign=0 move_ctor=1 move_assign=0
    // now:    copy_ctor=0 copy_assign=0 move_ctor=1 move_assign=0
    ASSERT_EQ(0, B::copy_ctor);
    ASSERT_EQ(0, B::copy_assign);
    ASSERT_EQ(1, B::move_ctor);
    ASSERT_EQ(0, B::move_assign);
}

TEST(HashtableMoveTest, EraseConstIterator)
{
    dense_hash_map<int, int> h;
    h.set_empty_key(0);
    h.set_deleted_key(-1);

    h[1] = 1;
    const auto it = h.begin();
    ASSERT_TRUE(h.end() == h.erase(it));
    ASSERT_EQ(0, (int)h.size());
}

TEST(HashtableMoveTest, EraseRange)
{
    dense_hash_map<int, int> h;
    h.set_empty_key(0);
    h.set_deleted_key(-1);

    for (int i = 0; i < 10; ++i)
        h[i + 1] = i;

    auto it = h.begin();
    std::advance(it, 2);

    auto it2 = h.begin();
    std::advance(it2, 8);

    auto nextit = h.erase(it, it2);
    ASSERT_FALSE(h.end() == nextit);
    nextit = h.erase(nextit);
    ASSERT_FALSE(h.end() == nextit);
    ASSERT_TRUE(h.end() == h.erase(nextit));

    ASSERT_FALSE(h.end() == h.erase(h.begin()));
    ASSERT_TRUE(h.end() == h.erase(h.begin()));

    ASSERT_TRUE(h.empty());
}

TEST(HashtableMoveTest, EraseRangeEntireMap)
{
    dense_hash_map<int, int> h;
    h.set_empty_key(0);
    h.set_deleted_key(-1);

    for (int i = 0; i < 10; ++i)
        h[i + 1] = i;

    ASSERT_TRUE(h.end() == h.erase(h.begin(), h.end()));
    ASSERT_TRUE(h.empty());
}

TEST(HashtableMoveTest, EraseNextElementReturned)
{
    dense_hash_map<int, int> h;
    h.set_empty_key(0);
    h.set_deleted_key(-1);

    h[1] = 1;
    h[2] = 2;

    int first = h.begin()->first;
    int second = first == 1 ? 2 : 1;

    ASSERT_EQ(second, h.erase(h.begin())->first); // second element is returned when erasing the first one
    ASSERT_TRUE(h.end() == h.erase(h.begin())); // end() is returned when erasing the second and last element
}

TEST(HashtableMoveTest, EraseNumberOfElementsDeleted)
{
    dense_hash_map<int, int> h;
    h.set_empty_key(0);
    h.set_deleted_key(-1);

    h[1] = 1;
    h[2] = 2;

    ASSERT_EQ(0, (int)h.erase(3));
    ASSERT_EQ(1, (int)h.erase(1));
    ASSERT_EQ(1, (int)h.erase(2));
    ASSERT_EQ(0, (int)h.erase(4));
    ASSERT_TRUE(h.empty());
}

TEST(HashtableMoveTest, CBeginCEnd)
{
    dense_hash_map<int, int> h;
    h.set_empty_key(0);
    h.set_deleted_key(-1);

    h[1] = 1;

    auto it = h.cbegin();
    ASSERT_EQ(1, it->first);

    std::advance(it, 1);
    ASSERT_TRUE(it == h.cend());

    using cit = dense_hash_map<int, int>::const_iterator;
    cit begin = h.begin();
    cit end = h.end();
    ASSERT_TRUE(begin == h.cbegin());
    ASSERT_TRUE(end == h.cend());
}

<|endoftext|>


<commit_before>/*********************************************************************
 *
 * Copyright (C) 2008,  Simon Kagstrom
 *
 * Filename:      registerallocator.cc
 * Author:        Simon Kagstrom <simon.kagstrom@gmail.com>
 * Description:   The register allocator class
 *
 * $Id:$
 *
 ********************************************************************/
#include <string.h>
#include <registerallocator.hh>

RegisterAllocator::RegisterAllocator()
{
  memset(this->mips_to_local, 0, sizeof(this->mips_to_local));
  memset(this->mips_to_static, 0, sizeof(this->mips_to_static));

  this->n_locals = 0;
}

static int allocateRegister(int n, MIPS_register_t reg, MIPS_register_t *sorted, int *usage)
{
  sorted[n++] = reg;
  usage[reg] = 0;
  return n;
}

void RegisterAllocator::setAllocation(int *registerUsage)
{
  MIPS_register_t sorted[N_REGS];
  int usage[N_REGS];
  int n = 0;

  memset(this->mips_to_local, -1, sizeof(this->mips_to_local));
  memset(sorted, 0, sizeof(sorted));
  memcpy(usage, registerUsage, sizeof(usage));

  /* Allocate initial registers */
  if (registerUsage[R_SP] > 0)
    n = allocateRegister(n, R_SP, sorted, usage);
  if (registerUsage[R_A0] > 0)
    n = allocateRegister(n, R_A0, sorted, usage);
  if (registerUsage[R_A1] > 0)
    n = allocateRegister(n, R_A1, sorted, usage);
  if (registerUsage[R_A2] > 0)
    n = allocateRegister(n, R_A2, sorted, usage);
  if (registerUsage[R_A3] > 0)
    n = allocateRegister(n, R_A3, sorted, usage);

  /* Allocate the rest of the registers */
  int largest;
  do
    {
      largest = 0;
      MIPS_register_t largestIndex = R_ZERO;
      for (int i = 0; i < N_REGS; i++)
	{
	  if (usage[i] > 0 && usage[i] > largest)
	    {
	      largest = usage[i];
	      largestIndex = (MIPS_register_t)i;
	    }
	}
      if (largest != 0)
	n = allocateRegister(n, largestIndex, sorted, usage);
    } while (largest != 0);

  /* Setup the register to local mapping */
  for (int i = 0; i < n; i++)
    this->mips_to_local[sorted[i]] = i;

  this->n_locals = n;
}

bool RegisterAllocator::regIsStatic(MIPS_register_t reg)
{
  return this->regToStatic(reg) != NULL;
}

const char *RegisterAllocator::regToStatic(MIPS_register_t reg)
{
  return this->mips_to_static[reg];
}

int RegisterAllocator::regToLocal(MIPS_register_t reg)
{
  return this->mips_to_local[reg];
}

RegisterAllocator *regalloc;
<commit_msg>Always pass R_FNA as the last arg if it's used<commit_after>/*********************************************************************
 *
 * Copyright (C) 2008,  Simon Kagstrom
 *
 * Filename:      registerallocator.cc
 * Author:        Simon Kagstrom <simon.kagstrom@gmail.com>
 * Description:   The register allocator class
 *
 * $Id:$
 *
 ********************************************************************/
#include <string.h>
#include <registerallocator.hh>

RegisterAllocator::RegisterAllocator()
{
  memset(this->mips_to_local, 0, sizeof(this->mips_to_local));
  memset(this->mips_to_static, 0, sizeof(this->mips_to_static));

  this->n_locals = 0;
}

static int allocateRegister(int n, MIPS_register_t reg, MIPS_register_t *sorted, int *usage)
{
  sorted[n++] = reg;
  usage[reg] = 0;
  return n;
}

void RegisterAllocator::setAllocation(int *registerUsage)
{
  MIPS_register_t sorted[N_REGS];
  int usage[N_REGS];
  int n = 0;

  memset(this->mips_to_local, -1, sizeof(this->mips_to_local));
  memset(sorted, 0, sizeof(sorted));
  memcpy(usage, registerUsage, sizeof(usage));

  /* Allocate initial registers */
  if (registerUsage[R_SP] > 0)
    n = allocateRegister(n, R_SP, sorted, usage);
  if (registerUsage[R_A0] > 0)
    n = allocateRegister(n, R_A0, sorted, usage);
  if (registerUsage[R_A1] > 0)
    n = allocateRegister(n, R_A1, sorted, usage);
  if (registerUsage[R_A2] > 0)
    n = allocateRegister(n, R_A2, sorted, usage);
  if (registerUsage[R_A3] > 0)
    n = allocateRegister(n, R_A3, sorted, usage);
  if (registerUsage[R_FNA] > 0)
    n = allocateRegister(n, R_FNA, sorted, usage);

  /* Allocate the rest of the registers */
  int largest;
  do
    {
      largest = 0;
      MIPS_register_t largestIndex = R_ZERO;
      for (int i = 0; i < N_REGS; i++)
	{
	  if (usage[i] > 0 && usage[i] > largest)
	    {
	      largest = usage[i];
	      largestIndex = (MIPS_register_t)i;
	    }
	}
      if (largest != 0)
	n = allocateRegister(n, largestIndex, sorted, usage);
    } while (largest != 0);

  /* Setup the register to local mapping */
  for (int i = 0; i < n; i++)
    this->mips_to_local[sorted[i]] = i;

  this->n_locals = n;
}

bool RegisterAllocator::regIsStatic(MIPS_register_t reg)
{
  return this->regToStatic(reg) != NULL;
}

const char *RegisterAllocator::regToStatic(MIPS_register_t reg)
{
  return this->mips_to_static[reg];
}

int RegisterAllocator::regToLocal(MIPS_register_t reg)
{
  return this->mips_to_local[reg];
}

RegisterAllocator *regalloc;
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <sstream>

std::string GetHelloString(std::string in)
{
	std::stringstream ss;
	ss << "Hello, " << in << "!";
	return ss.str();
}

int main (int argc, char * argv[])
{
	std::string name = "Bob";

	if(argc > 1)
		name = argv[1];

	std::cout << GetHelloString(name) << std::endl;
}<commit_msg>Changing default name to Larry.<commit_after>#include <iostream>
#include <string>
#include <sstream>

std::string GetHelloString(std::string in)
{
	std::stringstream ss;
	ss << "Hello, " << in << "!";
	return ss.str();
}

int main (int argc, char * argv[])
{
	std::string name = "Larry";

	if(argc > 1)
		name = argv[1];

	std::cout << GetHelloString(name) << std::endl;
}<|endoftext|>


<commit_before>
/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkBBoxRecord.h"

void SkBBoxRecord::drawOval(const SkRect& rect, const SkPaint& paint) {
    if (this->transformBounds(rect, &paint)) {
        INHERITED::drawOval(rect, paint);
    }
}

void SkBBoxRecord::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
    if (this->transformBounds(rrect.rect(), &paint)) {
        INHERITED::drawRRect(rrect, paint);
    }
}

void SkBBoxRecord::drawRect(const SkRect& rect, const SkPaint& paint) {
    if (this->transformBounds(rect, &paint)) {
        INHERITED::drawRect(rect, paint);
    }
}

void SkBBoxRecord::drawPath(const SkPath& path, const SkPaint& paint) {
    if (this->transformBounds(path.getBounds(), &paint)) {
        INHERITED::drawPath(path, paint);
    }
}

void SkBBoxRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
                              const SkPaint& paint) {
    SkRect bbox;
    bbox.set(pts, count);
    // Small min width value, just to ensure hairline point bounding boxes aren't empty.
    // Even though we know hairline primitives are drawn one pixel wide, we do not use a
    // minimum of 1 because the playback scale factor is unknown at record time. Later
    // outsets will take care of adding additional padding for antialiasing and rounding out
    // to integer device coordinates, guaranteeing that the rasterized pixels will be included
    // in the computed bounds.
    // Note: The device coordinate outset in SkBBoxHierarchyRecord::handleBBox is currently
    // done in the recording coordinate space, which is wrong.
    // http://code.google.com/p/skia/issues/detail?id=1021
    static const SkScalar kMinWidth = SkFloatToScalar(0.01f);
    SkScalar halfStrokeWidth = SkMaxScalar(paint.getStrokeWidth(), kMinWidth) / 2;
    bbox.outset(halfStrokeWidth, halfStrokeWidth);
    if (this->transformBounds(bbox, &paint)) {
        INHERITED::drawPoints(mode, count, pts, paint);
    }
}

void SkBBoxRecord::drawPaint(const SkPaint& paint) {
    SkRect bbox;
    if (this->getClipBounds(&bbox)) {
        if (this->transformBounds(bbox, &paint)) {
            INHERITED::drawPaint(paint);
        }
    }
}

void SkBBoxRecord::clear(SkColor color) {
    SkISize size = this->getDeviceSize();
    SkRect bbox = {0, 0, SkIntToScalar(size.width()), SkIntToScalar(size.height())};
    this->handleBBox(bbox);
    INHERITED::clear(color);
}

void SkBBoxRecord::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
                            const SkPaint& paint) {
    SkRect bbox;
    paint.measureText(text, byteLength, &bbox);
    SkPaint::FontMetrics metrics;
    paint.getFontMetrics(&metrics);

    // Vertical and aligned text need to be offset
    if (paint.isVerticalText()) {
        SkScalar h = bbox.fBottom - bbox.fTop;
        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
            bbox.fTop    -= h / 2;
            bbox.fBottom -= h / 2;
        }
        // Pad top and bottom with max extents from FontMetrics
        bbox.fBottom += metrics.fBottom;
        bbox.fTop += metrics.fTop;
    } else {
        SkScalar w = bbox.fRight - bbox.fLeft;
        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
            bbox.fLeft  -= w / 2;
            bbox.fRight -= w / 2;
        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
            bbox.fLeft  -= w;
            bbox.fRight -= w;
        }
        // Set vertical bounds to max extents from font metrics
        bbox.fTop = metrics.fTop;
        bbox.fBottom = metrics.fBottom;
    }

    // Pad horizontal bounds on each side by half of max vertical extents (this is sort of
    // arbitrary, but seems to produce reasonable results, if there were a way of getting max
    // glyph X-extents to pad by, that may be better here, but FontMetrics fXMin and fXMax seem
    // incorrect on most platforms (too small in Linux, never even set in Windows).
    SkScalar pad = (metrics.fBottom - metrics.fTop) / 2;
    bbox.fLeft  -= pad;
    bbox.fRight += pad;

    bbox.fLeft += x;
    bbox.fRight += x;
    bbox.fTop += y;
    bbox.fBottom += y;
    if (this->transformBounds(bbox, &paint)) {
        INHERITED::drawText(text, byteLength, x, y, paint);
    }
}

void SkBBoxRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
                              const SkPaint* paint) {
    SkRect bbox = {left, top, left + bitmap.width(), top + bitmap.height()};
    if (this->transformBounds(bbox, paint)) {
        INHERITED::drawBitmap(bitmap, left, top, paint);
    }
}

void SkBBoxRecord::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
                                  const SkRect& dst, const SkPaint* paint) {
    if (this->transformBounds(dst, paint)) {
        INHERITED::drawBitmapRectToRect(bitmap, src, dst, paint);
    }
}

void SkBBoxRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& mat,
                                    const SkPaint* paint) {
    SkMatrix m = mat;
    SkRect bbox = {0, 0, SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())};
    m.mapRect(&bbox);
    if (this->transformBounds(bbox, paint)) {
        INHERITED::drawBitmapMatrix(bitmap, mat, paint);
    }
}

void SkBBoxRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
                                  const SkRect& dst, const SkPaint* paint) {
    if (this->transformBounds(dst, paint)) {
        INHERITED::drawBitmapNine(bitmap, center, dst, paint);
    }
}

void SkBBoxRecord::drawPosText(const void* text, size_t byteLength,
                               const SkPoint pos[], const SkPaint& paint) {
    SkRect bbox;
    bbox.set(pos, paint.countText(text, byteLength));
    SkPaint::FontMetrics metrics;
    paint.getFontMetrics(&metrics);
    bbox.fTop += metrics.fTop;
    bbox.fBottom += metrics.fBottom;

    // pad on left and right by half of max vertical glyph extents
    SkScalar pad = (metrics.fTop - metrics.fBottom) / 2;
    bbox.fLeft += pad;
    bbox.fRight -= pad;

    if (this->transformBounds(bbox, &paint)) {
        INHERITED::drawPosText(text, byteLength, pos, paint);
    }
}

void SkBBoxRecord::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
                                SkScalar constY, const SkPaint& paint) {
    SkRect bbox;
    size_t numChars = paint.countText(text, byteLength);
    if (numChars > 0) {
        bbox.fLeft  = xpos[0];
        bbox.fRight = xpos[numChars - 1];
        // if we had a guarantee that these will be monotonically increasing, this could be sped up
        for (size_t i = 1; i < numChars; ++i) {
            if (xpos[i] < bbox.fLeft) {
                bbox.fLeft = xpos[i];
            }
            if (xpos[i] > bbox.fRight) {
                bbox.fRight = xpos[i];
            }
        }
        SkPaint::FontMetrics metrics;
        paint.getFontMetrics(&metrics);

        // pad horizontally by max glyph height
        SkScalar pad = (metrics.fTop - metrics.fBottom);
        bbox.fLeft  += pad;
        bbox.fRight -= pad;

        bbox.fTop    = metrics.fTop + constY;
        bbox.fBottom = metrics.fBottom + constY;
        if (!this->transformBounds(bbox, &paint)) {
            return;
        }
    }
    INHERITED::drawPosTextH(text, byteLength, xpos, constY, paint);
}

void SkBBoxRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
                              const SkPaint* paint) {
    SkRect bbox = {SkIntToScalar(left), SkIntToScalar(top), SkIntToScalar(left + bitmap.width()), SkIntToScalar(top + bitmap.height())};
    this->handleBBox(bbox); // directly call handleBBox, matrix is ignored
    INHERITED::drawBitmap(bitmap, left, top, paint);
}

void SkBBoxRecord::drawTextOnPath(const void* text, size_t byteLength,
                                  const SkPath& path, const SkMatrix* matrix,
                                  const SkPaint& paint) {
    SkRect bbox = path.getBounds();
    SkPaint::FontMetrics metrics;
    paint.getFontMetrics(&metrics);

    // pad out all sides by the max glyph height above baseline
    SkScalar pad = metrics.fTop;
    bbox.fLeft += pad;
    bbox.fRight -= pad;
    bbox.fTop += pad;
    bbox.fBottom -= pad;

    if (this->transformBounds(bbox, &paint)) {
        INHERITED::drawTextOnPath(text, byteLength, path, matrix, paint);
    }
}

void SkBBoxRecord::drawVertices(VertexMode mode, int vertexCount,
                                const SkPoint vertices[], const SkPoint texs[],
                                const SkColor colors[], SkXfermode* xfer,
                                const uint16_t indices[], int indexCount,
                                const SkPaint& paint) {
    SkRect bbox;
    bbox.set(vertices, vertexCount);
    if (this->transformBounds(bbox, &paint)) {
        INHERITED::drawVertices(mode, vertexCount, vertices, texs,
                                colors, xfer, indices, indexCount, paint);
    }
}

void SkBBoxRecord::drawPicture(SkPicture& picture) {
    if (picture.width() > 0 && picture.height() > 0 &&
        this->transformBounds(SkRect::MakeWH(picture.width(), picture.height()), NULL)) {
        INHERITED::drawPicture(picture);
    }
}

bool SkBBoxRecord::transformBounds(const SkRect& bounds, const SkPaint* paint) {
    SkRect outBounds = bounds;

    if (paint) {
        // account for stroking, path effects, shadows, etc
        if (paint->canComputeFastBounds()) {
            SkRect temp;
            outBounds = paint->computeFastBounds(bounds, &temp);
        } else {
            // set bounds to current clip
            if (!this->getClipBounds(&outBounds)) {
                // current clip is empty
                return false;
            }
        }
    }

    SkRect clip;

    if (this->getClipBounds(&clip) && outBounds.intersect(clip)) {
        this->getTotalMatrix().mapRect(&outBounds);
        this->handleBBox(outBounds);
        return true;
    }

    return false;
}

<commit_msg>Fixing bounding box computation for inverse filled paths in SkBBoxRecord<commit_after>
/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkBBoxRecord.h"

void SkBBoxRecord::drawOval(const SkRect& rect, const SkPaint& paint) {
    if (this->transformBounds(rect, &paint)) {
        INHERITED::drawOval(rect, paint);
    }
}

void SkBBoxRecord::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
    if (this->transformBounds(rrect.rect(), &paint)) {
        INHERITED::drawRRect(rrect, paint);
    }
}

void SkBBoxRecord::drawRect(const SkRect& rect, const SkPaint& paint) {
    if (this->transformBounds(rect, &paint)) {
        INHERITED::drawRect(rect, paint);
    }
}

void SkBBoxRecord::drawPath(const SkPath& path, const SkPaint& paint) {
    if (path.isInverseFillType()) {
        // If path is inverse filled, use the current clip bounds as the
        // path's device-space bounding box.
        SkIRect clipBounds;
        if (this->getClipDeviceBounds(&clipBounds)) {
            this->handleBBox(SkRect::MakeFromIRect(clipBounds));
            INHERITED::drawPath(path, paint);
        }
    } else if (this->transformBounds(path.getBounds(), &paint)) {
        INHERITED::drawPath(path, paint);
    }
}

void SkBBoxRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
                              const SkPaint& paint) {
    SkRect bbox;
    bbox.set(pts, count);
    // Small min width value, just to ensure hairline point bounding boxes aren't empty.
    // Even though we know hairline primitives are drawn one pixel wide, we do not use a
    // minimum of 1 because the playback scale factor is unknown at record time. Later
    // outsets will take care of adding additional padding for antialiasing and rounding out
    // to integer device coordinates, guaranteeing that the rasterized pixels will be included
    // in the computed bounds.
    // Note: The device coordinate outset in SkBBoxHierarchyRecord::handleBBox is currently
    // done in the recording coordinate space, which is wrong.
    // http://code.google.com/p/skia/issues/detail?id=1021
    static const SkScalar kMinWidth = SkFloatToScalar(0.01f);
    SkScalar halfStrokeWidth = SkMaxScalar(paint.getStrokeWidth(), kMinWidth) / 2;
    bbox.outset(halfStrokeWidth, halfStrokeWidth);
    if (this->transformBounds(bbox, &paint)) {
        INHERITED::drawPoints(mode, count, pts, paint);
    }
}

void SkBBoxRecord::drawPaint(const SkPaint& paint) {
    SkRect bbox;
    if (this->getClipBounds(&bbox)) {
        if (this->transformBounds(bbox, &paint)) {
            INHERITED::drawPaint(paint);
        }
    }
}

void SkBBoxRecord::clear(SkColor color) {
    SkISize size = this->getDeviceSize();
    SkRect bbox = {0, 0, SkIntToScalar(size.width()), SkIntToScalar(size.height())};
    this->handleBBox(bbox);
    INHERITED::clear(color);
}

void SkBBoxRecord::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
                            const SkPaint& paint) {
    SkRect bbox;
    paint.measureText(text, byteLength, &bbox);
    SkPaint::FontMetrics metrics;
    paint.getFontMetrics(&metrics);

    // Vertical and aligned text need to be offset
    if (paint.isVerticalText()) {
        SkScalar h = bbox.fBottom - bbox.fTop;
        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
            bbox.fTop    -= h / 2;
            bbox.fBottom -= h / 2;
        }
        // Pad top and bottom with max extents from FontMetrics
        bbox.fBottom += metrics.fBottom;
        bbox.fTop += metrics.fTop;
    } else {
        SkScalar w = bbox.fRight - bbox.fLeft;
        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
            bbox.fLeft  -= w / 2;
            bbox.fRight -= w / 2;
        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
            bbox.fLeft  -= w;
            bbox.fRight -= w;
        }
        // Set vertical bounds to max extents from font metrics
        bbox.fTop = metrics.fTop;
        bbox.fBottom = metrics.fBottom;
    }

    // Pad horizontal bounds on each side by half of max vertical extents (this is sort of
    // arbitrary, but seems to produce reasonable results, if there were a way of getting max
    // glyph X-extents to pad by, that may be better here, but FontMetrics fXMin and fXMax seem
    // incorrect on most platforms (too small in Linux, never even set in Windows).
    SkScalar pad = (metrics.fBottom - metrics.fTop) / 2;
    bbox.fLeft  -= pad;
    bbox.fRight += pad;

    bbox.fLeft += x;
    bbox.fRight += x;
    bbox.fTop += y;
    bbox.fBottom += y;
    if (this->transformBounds(bbox, &paint)) {
        INHERITED::drawText(text, byteLength, x, y, paint);
    }
}

void SkBBoxRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
                              const SkPaint* paint) {
    SkRect bbox = {left, top, left + bitmap.width(), top + bitmap.height()};
    if (this->transformBounds(bbox, paint)) {
        INHERITED::drawBitmap(bitmap, left, top, paint);
    }
}

void SkBBoxRecord::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
                                  const SkRect& dst, const SkPaint* paint) {
    if (this->transformBounds(dst, paint)) {
        INHERITED::drawBitmapRectToRect(bitmap, src, dst, paint);
    }
}

void SkBBoxRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& mat,
                                    const SkPaint* paint) {
    SkMatrix m = mat;
    SkRect bbox = {0, 0, SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())};
    m.mapRect(&bbox);
    if (this->transformBounds(bbox, paint)) {
        INHERITED::drawBitmapMatrix(bitmap, mat, paint);
    }
}

void SkBBoxRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
                                  const SkRect& dst, const SkPaint* paint) {
    if (this->transformBounds(dst, paint)) {
        INHERITED::drawBitmapNine(bitmap, center, dst, paint);
    }
}

void SkBBoxRecord::drawPosText(const void* text, size_t byteLength,
                               const SkPoint pos[], const SkPaint& paint) {
    SkRect bbox;
    bbox.set(pos, paint.countText(text, byteLength));
    SkPaint::FontMetrics metrics;
    paint.getFontMetrics(&metrics);
    bbox.fTop += metrics.fTop;
    bbox.fBottom += metrics.fBottom;

    // pad on left and right by half of max vertical glyph extents
    SkScalar pad = (metrics.fTop - metrics.fBottom) / 2;
    bbox.fLeft += pad;
    bbox.fRight -= pad;

    if (this->transformBounds(bbox, &paint)) {
        INHERITED::drawPosText(text, byteLength, pos, paint);
    }
}

void SkBBoxRecord::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
                                SkScalar constY, const SkPaint& paint) {
    SkRect bbox;
    size_t numChars = paint.countText(text, byteLength);
    if (numChars > 0) {
        bbox.fLeft  = xpos[0];
        bbox.fRight = xpos[numChars - 1];
        // if we had a guarantee that these will be monotonically increasing, this could be sped up
        for (size_t i = 1; i < numChars; ++i) {
            if (xpos[i] < bbox.fLeft) {
                bbox.fLeft = xpos[i];
            }
            if (xpos[i] > bbox.fRight) {
                bbox.fRight = xpos[i];
            }
        }
        SkPaint::FontMetrics metrics;
        paint.getFontMetrics(&metrics);

        // pad horizontally by max glyph height
        SkScalar pad = (metrics.fTop - metrics.fBottom);
        bbox.fLeft  += pad;
        bbox.fRight -= pad;

        bbox.fTop    = metrics.fTop + constY;
        bbox.fBottom = metrics.fBottom + constY;
        if (!this->transformBounds(bbox, &paint)) {
            return;
        }
    }
    INHERITED::drawPosTextH(text, byteLength, xpos, constY, paint);
}

void SkBBoxRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
                              const SkPaint* paint) {
    SkRect bbox = {SkIntToScalar(left), SkIntToScalar(top), SkIntToScalar(left + bitmap.width()), SkIntToScalar(top + bitmap.height())};
    this->handleBBox(bbox); // directly call handleBBox, matrix is ignored
    INHERITED::drawBitmap(bitmap, left, top, paint);
}

void SkBBoxRecord::drawTextOnPath(const void* text, size_t byteLength,
                                  const SkPath& path, const SkMatrix* matrix,
                                  const SkPaint& paint) {
    SkRect bbox = path.getBounds();
    SkPaint::FontMetrics metrics;
    paint.getFontMetrics(&metrics);

    // pad out all sides by the max glyph height above baseline
    SkScalar pad = metrics.fTop;
    bbox.fLeft += pad;
    bbox.fRight -= pad;
    bbox.fTop += pad;
    bbox.fBottom -= pad;

    if (this->transformBounds(bbox, &paint)) {
        INHERITED::drawTextOnPath(text, byteLength, path, matrix, paint);
    }
}

void SkBBoxRecord::drawVertices(VertexMode mode, int vertexCount,
                                const SkPoint vertices[], const SkPoint texs[],
                                const SkColor colors[], SkXfermode* xfer,
                                const uint16_t indices[], int indexCount,
                                const SkPaint& paint) {
    SkRect bbox;
    bbox.set(vertices, vertexCount);
    if (this->transformBounds(bbox, &paint)) {
        INHERITED::drawVertices(mode, vertexCount, vertices, texs,
                                colors, xfer, indices, indexCount, paint);
    }
}

void SkBBoxRecord::drawPicture(SkPicture& picture) {
    if (picture.width() > 0 && picture.height() > 0 &&
        this->transformBounds(SkRect::MakeWH(picture.width(), picture.height()), NULL)) {
        INHERITED::drawPicture(picture);
    }
}

bool SkBBoxRecord::transformBounds(const SkRect& bounds, const SkPaint* paint) {
    SkRect outBounds = bounds;

    if (paint) {
        // account for stroking, path effects, shadows, etc
        if (paint->canComputeFastBounds()) {
            SkRect temp;
            outBounds = paint->computeFastBounds(bounds, &temp);
        } else {
            // set bounds to current clip
            if (!this->getClipBounds(&outBounds)) {
                // current clip is empty
                return false;
            }
        }
    }

    SkRect clip;

    if (this->getClipBounds(&clip) && outBounds.intersect(clip)) {
        this->getTotalMatrix().mapRect(&outBounds);
        this->handleBBox(outBounds);
        return true;
    }

    return false;
}

<|endoftext|>


<commit_before>#ifndef ENTITY_MANAGER_HPP
#define ENTITY_MANAGER_HPP

#include <string>
#include <map>

#include "item.hpp"
#include "weapon.hpp"
#include "armor.hpp"
#include "creature.hpp"
#include "area.hpp"
#include "door.hpp"

class EntityManager
{
	private:

	std::map<std::string, Item> dataItem;
	std::map<std::string, Weapon> dataWeapon;
	std::map<std::string, Armor> dataArmor;
	std::map<std::string, Creature> dataCreature;
	std::map<std::string, Area> dataArea;
	std::map<std::string, Door> dataDoor;

	template<typename T>
	void loadJson(std::string filename, std::map<std::string, T>& data);

	public:

	template<typename T>
	void loadJson(std::string filename);

	template<typename T>
	T* getEntity(std::string id);

	EntityManager();

};
#endif /* ENTITY_MANAGER_HPP */<commit_msg>Commented EntityManager<commit_after>#ifndef ENTITY_MANAGER_HPP
#define ENTITY_MANAGER_HPP

#include <string>
#include <map>

#include "item.hpp"
#include "weapon.hpp"
#include "armor.hpp"
#include "creature.hpp"
#include "area.hpp"
#include "door.hpp"

class EntityManager
{
	private:

	std::map<std::string, Item> dataItem;
	std::map<std::string, Weapon> dataWeapon;
	std::map<std::string, Armor> dataArmor;
	std::map<std::string, Creature> dataCreature;
	std::map<std::string, Area> dataArea;
	std::map<std::string, Door> dataDoor;

	// Read the JSON file given by filename and interpret it according
	// to the type T, before storing all entities read in the data map
	template<typename T>
	void loadJson(std::string filename, std::map<std::string, T>& data);

	public:

	// Load the JSON file and determine which map to save the data to
	// according to the type T
	template<typename T>
	void loadJson(std::string filename);

	// Return the entity given by id
	template<typename T>
	T* getEntity(std::string id);

	// Constructor
	EntityManager();

};
#endif /* ENTITY_MANAGER_HPP */<|endoftext|>