<commit_before>#include "Tiny_Tree.hpp"

#include <vector>
#include <algorithm>

#include "tiny_util.hpp"
#include "pll_util.hpp"
#include "optimize.hpp"
#include "Tree_Numbers.hpp"
#include "Range.hpp"
#include "set_manipulators.hpp"

using namespace std;

static constexpr size_t NT_A = 0;
static constexpr size_t NT_C = 1;
static constexpr size_t NT_G = 2;
static constexpr size_t NT_T = 3;
static constexpr size_t NT_GAP = 4;
static constexpr char NT_MAP[5] = {'A', 'C', 'G', 'T', '-'};

static void precompute_sites_static(char nt, vector<double>& result,
  pll_partition_t* partition, pll_utree_t* tree, Model& model)
{
  const size_t sites = partition->sites;
  result.clear();
  result.resize(sites);
  string seq(sites, nt);

  vector<unsigned int> param_indices(model.rate_cats(), 0);

  auto err_check = pll_set_tip_states(partition, tree->back->clv_index, model.char_map(),
                     seq.c_str());

  if (err_check == PLL_FAILURE)
    throw runtime_error{"Set tip states during sites precompution failed!"};

  pll_compute_edge_loglikelihood(partition,
                                  tree->back->clv_index,
                                  PLL_SCALE_BUFFER_NONE,
                                  tree->clv_index,
                                  tree->scaler_index,
                                  tree->pmatrix_index,
                                  &param_indices[0], &result[0]);
}

static double sum_precomputed_sitelk(vector<vector<double>>& lookup, const Sequence& s)
{
  string seq = s.sequence();
  assert(seq.length() == lookup[NT_A].size());
  assert(lookup[NT_G].size() == lookup[NT_A].size());
  assert(lookup[NT_C].size() == lookup[NT_A].size());
  assert(lookup[NT_T].size() == lookup[NT_A].size());
  assert(lookup[NT_GAP].size() == lookup[NT_A].size());

  transform(seq.begin(), seq.end(), seq.begin(), ::toupper);
  double sum = 0;
  for (size_t i = 0; i < seq.length(); ++i)
  {
    size_t c;
    switch (seq[i])
    {
      case 'A':
        c = NT_A;
        break;
      case 'C':
        c = NT_C;
        break;
      case 'G':
        c = NT_G;
        break;
      case 'T':
        c = NT_T;
        break;
      case '-':
        c = NT_GAP;
        break;
      default:
        throw runtime_error{"derp"};
    }
    sum += lookup[c][i];
  }
  return sum;
}

Tiny_Tree::Tiny_Tree(pll_utree_t *edge_node, unsigned int branch_id, Tree& reference_tree,
                     bool opt_branches, Range reference_tip_range, bool ranged)
    : partition_(nullptr, tiny_partition_destroy), tree_(nullptr, utree_destroy), opt_branches_(opt_branches)
    , model_(reference_tree.model())
    , reference_tip_range_(reference_tip_range), ranged_computation_(ranged), branch_id_(branch_id)
{
  original_branch_length_ = (edge_node->length < 2*PLLMOD_OPT_MIN_BRANCH_LEN) ?
    2*PLLMOD_OPT_MIN_BRANCH_LEN : edge_node->length;
  assert(edge_node);

  const pll_utree_t *old_proximal = edge_node->back;
  const pll_utree_t *old_distal = edge_node;

  // detect the tip-tip case. In the tip-tip case, the reference tip should
  // always be the DISTAL
  if (!old_distal->next) {
    tip_tip_case_ = true;
  } else if (!old_proximal->next) {
    tip_tip_case_ = true;
    // do the switcheroo
    old_distal = old_proximal;
    old_proximal = old_distal->back;
  }

  tree_ = unique_ptr<pll_utree_t, utree_deleter>(
      	                    make_tiny_tree_structure(old_proximal, old_distal, tip_tip_case_),
                            utree_destroy);

  partition_ = unique_ptr<pll_partition_t, partition_deleter>(
                                make_tiny_partition(reference_tree, tree_.get(), old_proximal, old_distal, tip_tip_case_),
                                tiny_partition_destroy);

  // operation for computing the clv toward the new tip (for initialization and logl in non-blo case)
  auto distal = tree_->next->back;
  auto proximal = tree_->next->next->back;

  pll_operation_t op;
  op.parent_clv_index = tree_->clv_index;
  op.child1_clv_index = distal->clv_index;
  op.child1_scaler_index = distal->scaler_index;
  op.child2_clv_index = proximal->clv_index;
  op.child2_scaler_index = proximal->scaler_index;
  op.parent_scaler_index = tree_->scaler_index;
  op.child1_matrix_index = distal->pmatrix_index;
  op.child2_matrix_index = proximal->pmatrix_index;

  // wether heuristic is used or not, this is the initial branch length configuration
  double branch_lengths[3] = {proximal->length, distal->length, tree_->length};
  unsigned int matrix_indices[3] = {proximal->pmatrix_index, distal->pmatrix_index, tree_->pmatrix_index};

  // use branch lengths to compute the probability matrices
  vector<unsigned int> param_indices(model_.rate_cats(), 0);
  pll_update_prob_matrices(partition_.get(), &param_indices[0], matrix_indices, branch_lengths, 3);

  // use update_partials to compute the clv pointing toward the new tip
  pll_update_partials(partition_.get(), &op, 1);

  lookup_.clear();
  lookup_.resize(5);

  // precompute all possible site likelihoods
  size_t i = 0;
  for (char nt : NT_MAP)
    precompute_sites_static(nt, lookup_[i++], partition_.get(), tree_.get(), model_);
}

Placement Tiny_Tree::place(const Sequence &s)
{
  assert(partition_);
  assert(tree_);

  auto distal_length = tree_->next->length;
  auto pendant_length = tree_->length;
  double logl = 0.0;
  vector<unsigned int> param_indices(model_.rate_cats(), 0);

  Range range(0, partition_->sites);
  // if (ranged_computation_)
  //   range = get_valid_range(s.sequence());
    // range = superset(get_valid_range(s.sequence()), reference_tip_range_);

  if (opt_branches_)
  {

    /* differentiate between the normal case and the tip tip case:
      in the normal case we want to compute the partial toward the newly placed sequence.
      In other words, we set the virtual root as the node whose back-neighbour is the new
      sequence, which is tree_. (*)
      */
    auto virtual_root = tree_.get();

    if (tip_tip_case_)
    {
      /* (cont. from (*))... however in the tip-tip case we want that virtual root to be toward the non-tip
        node of the reference tree. Thus virtual_root needs to reflect that.
        optimize_branch_triplet then takes care of the single computation operation for us
        using that node.*/
      virtual_root = tree_->next->next;
    }

    // init the new tip with s.sequence(), branch length
    auto err_check = pll_set_tip_states(partition_.get(), tree_->back->clv_index, model_.char_map(),
                       s.sequence().c_str());

    if (err_check == PLL_FAILURE)
      throw runtime_error{"Set tip states during placement failed!"};

    // optimize the branches using pnly the portion of the sites specified by range
    logl = call_focused(partition_.get(), range, optimize_branch_triplet, virtual_root);
    // logl = optimize_branch_triplet(partition_.get(), virtual_root);

    assert(tree_->length >= 0);
    assert(tree_->next->length >= 0);
    assert(tree_->next->next->length >= 0);

    // rescale the distal length, as it has likely changed during optimization
    // done as in raxml
    double proximal_length = tree_->next->next->length;
    double new_total_branch_length = distal_length + proximal_length;
    distal_length = (original_branch_length_ / new_total_branch_length) * distal_length;
    pendant_length = tree_->length;

    reset_triplet_lengths(tree_.get(), partition_.get(), original_branch_length_);
  }
  else
  {
    logl = sum_precomputed_sitelk(lookup_, s);
  }
  // logl = call_focused(partition_.get(), range, pll_compute_edge_loglikelihood,
  //                                       tree_->back->clv_index,
  //                                       PLL_SCALE_BUFFER_NONE, // scaler_index
  //                                       tree_->clv_index,
  //                                       tree_->scaler_index, // scaler_index
  //                                       tree_->pmatrix_index,
  //                                       &param_indices[0], nullptr); // freq index

  assert(distal_length <= original_branch_length_);
  assert(distal_length >= 0.0);

  return Placement(branch_id_, logl, pendant_length, distal_length);
}
<commit_msg>removed unneeded precomp for thorough insertion, removed toupper conversion<commit_after>#include "Tiny_Tree.hpp"

#include <vector>
#include <algorithm>

#include "tiny_util.hpp"
#include "pll_util.hpp"
#include "optimize.hpp"
#include "Tree_Numbers.hpp"
#include "Range.hpp"
#include "set_manipulators.hpp"

using namespace std;

static constexpr size_t NT_A = 0;
static constexpr size_t NT_C = 1;
static constexpr size_t NT_G = 2;
static constexpr size_t NT_T = 3;
static constexpr size_t NT_GAP = 4;
static constexpr char NT_MAP[5] = {'A', 'C', 'G', 'T', '-'};

static void precompute_sites_static(char nt, vector<double>& result,
  pll_partition_t* partition, pll_utree_t* tree, Model& model)
{
  const size_t sites = partition->sites;
  result.clear();
  result.resize(sites);
  string seq(sites, nt);

  vector<unsigned int> param_indices(model.rate_cats(), 0);

  auto err_check = pll_set_tip_states(partition, tree->back->clv_index, model.char_map(),
                     seq.c_str());

  if (err_check == PLL_FAILURE)
    throw runtime_error{"Set tip states during sites precompution failed!"};

  pll_compute_edge_loglikelihood(partition,
                                  tree->back->clv_index,
                                  PLL_SCALE_BUFFER_NONE,
                                  tree->clv_index,
                                  tree->scaler_index,
                                  tree->pmatrix_index,
                                  &param_indices[0], &result[0]);
}

static double sum_precomputed_sitelk(vector<vector<double>>& lookup, const Sequence& s)
{
  string seq = s.sequence();
  assert(seq.length() == lookup[NT_A].size());
  assert(lookup[NT_G].size() == lookup[NT_A].size());
  assert(lookup[NT_C].size() == lookup[NT_A].size());
  assert(lookup[NT_T].size() == lookup[NT_A].size());
  assert(lookup[NT_GAP].size() == lookup[NT_A].size());

  // transform(seq.begin(), seq.end(), seq.begin(), ::toupper);
  double sum = 0;
  for (size_t i = 0; i < seq.length(); ++i)
  {
    size_t c;
    switch (seq[i])
    {
      case 'A':
      case 'a':
        c = NT_A;
        break;
      case 'C':
      case 'c':
        c = NT_C;
        break;
      case 'G':
      case 'g':
        c = NT_G;
        break;
      case 'T':
      case 't':
        c = NT_T;
        break;
      case '-':
        c = NT_GAP;
        break;
      default:
        throw runtime_error{"derp"};
    }
    sum += lookup[c][i];
  }
  return sum;
}

Tiny_Tree::Tiny_Tree(pll_utree_t *edge_node, unsigned int branch_id, Tree& reference_tree,
                     bool opt_branches, Range reference_tip_range, bool ranged)
    : partition_(nullptr, tiny_partition_destroy), tree_(nullptr, utree_destroy), opt_branches_(opt_branches)
    , model_(reference_tree.model())
    , reference_tip_range_(reference_tip_range), ranged_computation_(ranged), branch_id_(branch_id)
{
  original_branch_length_ = (edge_node->length < 2*PLLMOD_OPT_MIN_BRANCH_LEN) ?
    2*PLLMOD_OPT_MIN_BRANCH_LEN : edge_node->length;
  assert(edge_node);

  const pll_utree_t *old_proximal = edge_node->back;
  const pll_utree_t *old_distal = edge_node;

  // detect the tip-tip case. In the tip-tip case, the reference tip should
  // always be the DISTAL
  if (!old_distal->next) {
    tip_tip_case_ = true;
  } else if (!old_proximal->next) {
    tip_tip_case_ = true;
    // do the switcheroo
    old_distal = old_proximal;
    old_proximal = old_distal->back;
  }

  tree_ = unique_ptr<pll_utree_t, utree_deleter>(
      	                    make_tiny_tree_structure(old_proximal, old_distal, tip_tip_case_),
                            utree_destroy);

  partition_ = unique_ptr<pll_partition_t, partition_deleter>(
                                make_tiny_partition(reference_tree, tree_.get(), old_proximal, old_distal, tip_tip_case_),
                                tiny_partition_destroy);

  // operation for computing the clv toward the new tip (for initialization and logl in non-blo case)
  auto distal = tree_->next->back;
  auto proximal = tree_->next->next->back;

  pll_operation_t op;
  op.parent_clv_index = tree_->clv_index;
  op.child1_clv_index = distal->clv_index;
  op.child1_scaler_index = distal->scaler_index;
  op.child2_clv_index = proximal->clv_index;
  op.child2_scaler_index = proximal->scaler_index;
  op.parent_scaler_index = tree_->scaler_index;
  op.child1_matrix_index = distal->pmatrix_index;
  op.child2_matrix_index = proximal->pmatrix_index;

  // wether heuristic is used or not, this is the initial branch length configuration
  double branch_lengths[3] = {proximal->length, distal->length, tree_->length};
  unsigned int matrix_indices[3] = {proximal->pmatrix_index, distal->pmatrix_index, tree_->pmatrix_index};

  // use branch lengths to compute the probability matrices
  vector<unsigned int> param_indices(model_.rate_cats(), 0);
  pll_update_prob_matrices(partition_.get(), &param_indices[0], matrix_indices, branch_lengths, 3);

  if (!opt_branches)
  {
    // use update_partials to compute the clv pointing toward the new tip
    pll_update_partials(partition_.get(), &op, 1);

    lookup_.clear();
    lookup_.resize(5);

    // precompute all possible site likelihoods
    size_t i = 0;
    for (char nt : NT_MAP)
      precompute_sites_static(nt, lookup_[i++], partition_.get(), tree_.get(), model_);
  }

}

Placement Tiny_Tree::place(const Sequence &s)
{
  assert(partition_);
  assert(tree_);

  auto distal_length = tree_->next->length;
  auto pendant_length = tree_->length;
  double logl = 0.0;
  vector<unsigned int> param_indices(model_.rate_cats(), 0);

  Range range(0, partition_->sites);
  // if (ranged_computation_)
  //   range = get_valid_range(s.sequence());
    // range = superset(get_valid_range(s.sequence()), reference_tip_range_);

  if (opt_branches_)
  {

    /* differentiate between the normal case and the tip tip case:
      in the normal case we want to compute the partial toward the newly placed sequence.
      In other words, we set the virtual root as the node whose back-neighbour is the new
      sequence, which is tree_. (*)
      */
    auto virtual_root = tree_.get();

    if (tip_tip_case_)
    {
      /* (cont. from (*))... however in the tip-tip case we want that virtual root to be toward the non-tip
        node of the reference tree. Thus virtual_root needs to reflect that.
        optimize_branch_triplet then takes care of the single computation operation for us
        using that node.*/
      virtual_root = tree_->next->next;
    }

    // init the new tip with s.sequence(), branch length
    auto err_check = pll_set_tip_states(partition_.get(), tree_->back->clv_index, model_.char_map(),
                       s.sequence().c_str());

    if (err_check == PLL_FAILURE)
      throw runtime_error{"Set tip states during placement failed!"};

    // optimize the branches using pnly the portion of the sites specified by range
    logl = call_focused(partition_.get(), range, optimize_branch_triplet, virtual_root);
    // logl = optimize_branch_triplet(partition_.get(), virtual_root);

    assert(tree_->length >= 0);
    assert(tree_->next->length >= 0);
    assert(tree_->next->next->length >= 0);

    // rescale the distal length, as it has likely changed during optimization
    // done as in raxml
    double proximal_length = tree_->next->next->length;
    double new_total_branch_length = distal_length + proximal_length;
    distal_length = (original_branch_length_ / new_total_branch_length) * distal_length;
    pendant_length = tree_->length;

    reset_triplet_lengths(tree_.get(), partition_.get(), original_branch_length_);
  }
  else
  {
    logl = sum_precomputed_sitelk(lookup_, s);
  }
  // logl = call_focused(partition_.get(), range, pll_compute_edge_loglikelihood,
  //                                       tree_->back->clv_index,
  //                                       PLL_SCALE_BUFFER_NONE, // scaler_index
  //                                       tree_->clv_index,
  //                                       tree_->scaler_index, // scaler_index
  //                                       tree_->pmatrix_index,
  //                                       &param_indices[0], nullptr); // freq index

  assert(distal_length <= original_branch_length_);
  assert(distal_length >= 0.0);

  return Placement(branch_id_, logl, pendant_length, distal_length);
}
<|endoftext|>


<commit_before>#include "algo.h"
#include "cube.h"
#include <tuple>
#include <queue>
#include <fstream>
#include <cstdint>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <set>

namespace rubik_cube
{

namespace __krof_algo_impl
{

class krof_t : public algo_t
{
public:
	krof_t();
	~krof_t();
public:
	void init(const char*);
	void save(const char*) const;
	move_seq_t solve(cube_t) const;
private:
	int estimate(const cube_t&) const;

	typedef std::pair<int64_t, int32_t> cube_encode_t;
	template<int, int>
	static int encode_perm(const int *perm, const int *k);
	static int encode_corners(const cube_t&);
	static int encode_edges1(const cube_t&);
	static int encode_edges2(const cube_t&);
	static cube_encode_t encode_cube(const cube_t&);

	void init0(int8_t *buf, int(*encoder)(const cube_t&));
private:
	static const int disallow_faces[6];
	static const int corners_size = 88179840; // 3^7 * 8!
	static const int edges_size = 42577920;   // 2^6 * 12! / 6!
	int8_t corners[corners_size];
	int8_t edges1[edges_size];
	int8_t edges2[edges_size];

}; // class krof_t

const int krof_t::disallow_faces[6] = { -1, -1, -1, 1, 2, 0 };

krof_t::krof_t()
{
}

krof_t::~krof_t()
{
}

move_seq_t krof_t::solve(cube_t cb) const
{
	struct krof_search_data_t
	{
		cube_t c;
		int g, h;

		int64_t prev;
	};

	cube_encode_t final_state = encode_cube({});

	for(int depth = 0; ; ++depth)
	{
//		printf("Solving %d...\n", depth);
		std::queue<krof_search_data_t> H;
		std::vector<std::pair<int64_t, move_step_t>> P;
		std::set<cube_encode_t> M;
		H.push( { cb, 0, estimate(cb), -1 } );
		P.push_back( { -1, { face_t::face_type::top, 0 } } );

		for(int64_t id = 0; !H.empty(); ++id)
		{
			krof_search_data_t s = H.front();
			int face = id ? (int)P[id].first : 6;

			for(int i = 0; i != 6; ++i)
			{
				if(i == face || disallow_faces[i] == face)
					continue;

				cube_t cube = s.c;
				for(int j = 1; j <= 3; ++j)
				{
					cube.rotate(face_t::face_type(i), 1);
					int h = estimate(cube);
					if(h + s.g + 1 <= depth)
					{
						cube_encode_t state = encode_cube(cube);
						if(state == final_state)
						{
							move_seq_t seq;
							seq.push_back( { face_t::face_type(i), j } );

							for(auto p = P[id]; p.first != -1; p = P[p.first])
								seq.push_back(p.second);

							for(auto& r : seq)
								if(r.second == 3)
									r.second = -1;

							std::reverse(seq.begin(), seq.end());

							return seq;
						}

						if(M.count(state) == 0)
						{
							M.insert(state);
							H.push( { cube, s.g + 1, h, id } );
							P.push_back( { id, move_step_t{ face_t::face_type(i), j } } );
						}
					}
				}
			}

			H.pop();
		}
	}

	return {};
}

int krof_t::estimate(const cube_t& c) const
{
	return std::max(
		corners[encode_corners(c)],
		std::max(
			edges1[encode_edges1(c)],
			edges2[encode_edges2(c)]
		)
	);
}

void krof_t::init(const char* filename)
{
	if(!filename)
	{
		std::memset(edges1, 0xff, sizeof(edges1));
		init0(edges1, &krof_t::encode_edges1);

		std::memset(edges2, 0xff, sizeof(edges2));
		init0(edges2, &krof_t::encode_edges2);

		std::memset(corners, 0xff, sizeof(corners));
		init0(corners, &krof_t::encode_corners);
	} else {
		std::ifstream ifs(filename, std::ios::binary);
		ifs.read(reinterpret_cast<char*>(edges1), edges_size);
		ifs.read(reinterpret_cast<char*>(edges2), edges_size);
		ifs.read(reinterpret_cast<char*>(corners), corners_size);
	}
}

void krof_t::save(const char* filename) const
{
	std::ofstream ofs(filename, std::ios::binary);
	ofs.write(reinterpret_cast<const char*>(edges1), edges_size);
	ofs.write(reinterpret_cast<const char*>(edges2), edges_size);
	ofs.write(reinterpret_cast<const char*>(corners), corners_size);
}

void krof_t::init0(int8_t *buf, int(*encoder)(const cube_t&))
{
	std::queue<std::pair<cube_t, uint8_t>> que;
	buf[(*encoder)(cube_t())] = 0;
	que.push( { cube_t(), 0 | (6 << 4) } );

	while(!que.empty())
	{
		auto u = que.front();
		int face = u.second >> 4;
		int step = u.second & 0xf;

		for(int i = 0; i != 6; ++i)
		{
			if(i == face || disallow_faces[i] == face)
				continue;

			cube_t c = u.first;
			for(int j = 0; j != 3; ++j)
			{
				c.rotate(face_t::face_type(i), 1);
				int code = (*encoder)(c);
				if(buf[code] == -1)
				{
					buf[code] = step + 1;
					que.push( { c, (step + 1) | (i << 4) } );
				}
			}
		}

		que.pop();
	}
}

template<int N, int S>
int krof_t::encode_perm(const int *p, const int *k)
{
	int pos[N], elem[N];

	for(int i = 0; i != N; ++i)
		pos[i] = elem[i] = i;

	int v = 0, t;
	for(int i = 0; i != S; ++i)
	{
		t = pos[p[i]];
		v += k[i] * t;
		pos[elem[N - i - 1]] = t;
		elem[t] = elem[N - i - 1];
	}

	return v;
}

int krof_t::encode_edges1(const cube_t& c)
{
	static const int k[6] = { 1, 12, 132, 1320, 11880, 95040 };
	static const int color_map[][6] =
	{
		{ 0, 1, 1, 1, 1, 0 },
		{ 0, 1, 0, 1, 0, 0 }
	};

	edge_block_t eb = c.getEdgeBlock();

	int t, v = 0, perm[6];
	for(int i = 0; i != 12; ++i)
	{
		if(eb.permutation[i] < 14)
		{
			t = eb.permutation[i] - 8;
			perm[t] = i;
			v |= color_map[t >= 4][eb.color[i]] << t;
		}
	}

	return v + (encode_perm<12, 6>(perm, k) << 6);
}

int krof_t::encode_edges2(const cube_t& c)
{
	static const int k[6] = { 1, 12, 132, 1320, 11880, 95040 };
	static const int color_map[][6] =
	{
		{ 0, 1, 1, 1, 1, 0 },
		{ 0, 1, 0, 1, 0, 0 }
	};

	edge_block_t eb = c.getEdgeBlock();

	int t, v = 0, perm[6];
	for(int i = 0; i != 12; ++i)
	{
		if(eb.permutation[i] >= 14)
		{
			t = eb.permutation[i] - 14;
			perm[t] = i;
			v |= color_map[t <= 7][eb.color[i]] << t;
		}
	}

	return v + (encode_perm<12, 6>(perm, k) << 6);
}

int krof_t::encode_corners(const cube_t& c)
{
	static const int base0 = 2187; // 3^7
	static const int color_map[6] = { 0, 1, 2, 1, 2, 0 };
	static const int k[7] = { 1, 8, 56, 336, 1680, 6720, 20160 };

	corner_block_t cb = c.getCornerBlock();
	int v = 0;
	for(int i = 0; i != 7; ++i)
		v = v * 3 + color_map[cb.top_bottom_color[i]];

	return v + encode_perm<8, 7>(cb.permutation, k) * base0;
}

krof_t::cube_encode_t krof_t::encode_cube(const cube_t& c)
{
	static const int k[12] =
	{
		1, 12, 132, 1320, 11880,
		95040, 665280, 3991680,
		19958400, 79833600,
		239500800, 479001600
	};

	static const int color_map[][6] =
	{
		{ 0, 1, 1, 1, 1, 0 },
		{ 0, 1, 0, 1, 0, 0 }
	};

	edge_block_t eb = c.getEdgeBlock();

	int v = 0;
	for(int i = 0; i != 12; ++i)
	{
		int t = (eb.permutation[i] -= 8);
		v |= color_map[7 >= t && t >= 4][eb.color[i]] << t;
	}

	return {
		v + ((long long)encode_perm<12, 11>(eb.permutation, k) << 12),
		encode_corners(c)
	};

}

} // namespace __krof_algo_impl

std::shared_ptr<algo_t> create_krof_algo()
{
	return std::make_shared<__krof_algo_impl::krof_t>();
}

} // namespace rubik_cube
<commit_msg>Fix bug in IDA* algorithm.<commit_after>#include "algo.h"
#include "cube.h"
#include <tuple>
#include <queue>
#include <fstream>
#include <cstdint>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <set>

namespace rubik_cube
{

namespace __krof_algo_impl
{

class krof_t : public algo_t
{
public:
	krof_t();
	~krof_t();
public:
	void init(const char*);
	void save(const char*) const;
	move_seq_t solve(cube_t) const;
private:
	int estimate(const cube_t&) const;

	typedef std::pair<int64_t, int32_t> cube_encode_t;
	template<int, int>
	static int encode_perm(const int *perm, const int *k);
	static int encode_corners(const cube_t&);
	static int encode_edges1(const cube_t&);
	static int encode_edges2(const cube_t&);
	static cube_encode_t encode_cube(const cube_t&);

	void init0(int8_t *buf, int(*encoder)(const cube_t&));
private:
	static const int disallow_faces[6];
	static const int edges_color_map[2][6];
	static const int corners_size = 88179840; // 3^7 * 8!
	static const int edges_size = 42577920;   // 2^6 * 12! / 6!
	int8_t corners[corners_size];
	int8_t edges1[edges_size];
	int8_t edges2[edges_size];

}; // class krof_t

const int krof_t::disallow_faces[6] = { -1, -1, -1, 1, 2, 0 };
const int krof_t::edges_color_map[][6] = { { 0, 1, 1, 1, 1, 0 }, { 0, 1, 0, 1, 0, 0 } };

krof_t::krof_t()
{
}

krof_t::~krof_t()
{
}

move_seq_t krof_t::solve(cube_t cb) const
{
	struct krof_search_data_t
	{
		cube_t c;
		int g, h;

		int64_t prev;
	};

	cube_encode_t final_state = encode_cube({});

	for(int depth = 0; ; ++depth)
	{
//		printf("Solving %d...\n", depth);
		std::queue<krof_search_data_t> H;
		std::vector<std::tuple<int64_t, int, int>> P;
		std::set<cube_encode_t> M;
		H.push( { cb, 0, estimate(cb), -1 } );
		P.push_back( { -1, 6, 0 } );

		for(int64_t id = 0; !H.empty(); ++id)
		{
			krof_search_data_t s = H.front();
			int face = std::get<1>(P[id]);

			for(int i = 0; i != 6; ++i)
			{
				if(i == face || disallow_faces[i] == face)
					continue;

				cube_t cube = s.c;
				for(int j = 1; j <= 3; ++j)
				{
					cube.rotate(face_t::face_type(i), 1);
					int h = estimate(cube);
					if(h + s.g + 1 <= depth)
					{
						cube_encode_t state = encode_cube(cube);
						if(state == final_state)
						{
							move_seq_t seq;
							seq.push_back( { face_t::face_type(i), j } );

							for(auto p = P[id]; std::get<0>(p) != -1; p = P[std::get<0>(p)])
								seq.push_back( { face_t::face_type(std::get<1>(p)), std::get<2>(p) } );

							for(auto& r : seq)
								if(r.second == 3)
									r.second = -1;

							std::reverse(seq.begin(), seq.end());

							return seq;
						}

						if(M.count(state) == 0)
						{
							M.insert(state);
							H.push( { cube, s.g + 1, h, id } );
							P.push_back( { id, i, j } );
						}
					}
				}
			}

			H.pop();
		}
	}

	return {};
}

int krof_t::estimate(const cube_t& c) const
{
	return std::max(
		corners[encode_corners(c)],
		std::max(
			edges1[encode_edges1(c)],
			edges2[encode_edges2(c)]
		)
	);
}

void krof_t::init(const char* filename)
{
	if(!filename)
	{
		std::memset(edges1, 0xff, sizeof(edges1));
		init0(edges1, &krof_t::encode_edges1);

		std::memset(edges2, 0xff, sizeof(edges2));
		init0(edges2, &krof_t::encode_edges2);

		std::memset(corners, 0xff, sizeof(corners));
		init0(corners, &krof_t::encode_corners);
	} else {
		std::ifstream ifs(filename, std::ios::binary);
		ifs.read(reinterpret_cast<char*>(edges1), edges_size);
		ifs.read(reinterpret_cast<char*>(edges2), edges_size);
		ifs.read(reinterpret_cast<char*>(corners), corners_size);
	}
}

void krof_t::save(const char* filename) const
{
	std::ofstream ofs(filename, std::ios::binary);
	ofs.write(reinterpret_cast<const char*>(edges1), edges_size);
	ofs.write(reinterpret_cast<const char*>(edges2), edges_size);
	ofs.write(reinterpret_cast<const char*>(corners), corners_size);
}

void krof_t::init0(int8_t *buf, int(*encoder)(const cube_t&))
{
	std::queue<std::pair<cube_t, uint8_t>> que;
	buf[(*encoder)(cube_t())] = 0;
	que.push( { cube_t(), 0 | (6 << 4) } );

	while(!que.empty())
	{
		auto u = que.front();
		int face = u.second >> 4;
		int step = u.second & 0xf;

		for(int i = 0; i != 6; ++i)
		{
			if(i == face || disallow_faces[i] == face)
				continue;

			cube_t c = u.first;
			for(int j = 0; j != 3; ++j)
			{
				c.rotate(face_t::face_type(i), 1);
				int code = (*encoder)(c);
				if(buf[code] == -1)
				{
					buf[code] = step + 1;
					que.push( { c, (step + 1) | (i << 4) } );
				}
			}
		}

		que.pop();
	}
}

template<int N, int S>
int krof_t::encode_perm(const int *p, const int *k)
{
	int pos[N], elem[N];

	for(int i = 0; i != N; ++i)
		pos[i] = elem[i] = i;

	int v = 0, t;
	for(int i = 0; i != S; ++i)
	{
		t = pos[p[i]];
		v += k[i] * t;
		pos[elem[N - i - 1]] = t;
		elem[t] = elem[N - i - 1];
	}

	return v;
}

int krof_t::encode_edges1(const cube_t& c)
{
	static const int k[6] = { 1, 12, 132, 1320, 11880, 95040 };

	edge_block_t eb = c.getEdgeBlock();

	int t, v = 0, perm[6];
	for(int i = 0; i != 12; ++i)
	{
		if(eb.permutation[i] < 14)
		{
			t = eb.permutation[i] - 8;
			perm[t] = i;
			v |= edges_color_map[t >= 4][eb.color[i]] << t;
		}
	}

	return v + (encode_perm<12, 6>(perm, k) << 6);
}

int krof_t::encode_edges2(const cube_t& c)
{
	static const int k[6] = { 1, 12, 132, 1320, 11880, 95040 };

	edge_block_t eb = c.getEdgeBlock();

	int t, v = 0, perm[6];
	for(int i = 0; i != 12; ++i)
	{
		if(eb.permutation[i] >= 14)
		{
			t = eb.permutation[i] - 14;
			perm[t] = i;
			v |= edges_color_map[t < 2][eb.color[i]] << t;
		}
	}

	return v + (encode_perm<12, 6>(perm, k) << 6);
}

int krof_t::encode_corners(const cube_t& c)
{
	static const int base0 = 2187; // 3^7
	static const int color_map[6] = { 0, 1, 2, 1, 2, 0 };
	static const int k[7] = { 1, 8, 56, 336, 1680, 6720, 20160 };

	corner_block_t cb = c.getCornerBlock();
	int v = 0;
	for(int i = 0; i != 7; ++i)
		v = v * 3 + color_map[cb.top_bottom_color[i]];

	return v + encode_perm<8, 7>(cb.permutation, k) * base0;
}

krof_t::cube_encode_t krof_t::encode_cube(const cube_t& c)
{
	static const int k[12] =
	{
		1, 12, 132, 1320, 11880,
		95040, 665280, 3991680,
		19958400, 79833600,
		239500800, 479001600
	};

	edge_block_t eb = c.getEdgeBlock();

	int v = 0;
	for(int i = 0; i != 12; ++i)
	{
		int t = (eb.permutation[i] -= 8);
		v |= edges_color_map[7 >= t && t >= 4][eb.color[i]] << t;
	}

	return {
		v + ((long long)encode_perm<12, 11>(eb.permutation, k) << 12),
		encode_corners(c)
	};

}

} // namespace __krof_algo_impl

std::shared_ptr<algo_t> create_krof_algo()
{
	return std::make_shared<__krof_algo_impl::krof_t>();
}

} // namespace rubik_cube
<|endoftext|>


<commit_before>#include "../include/graph.h"
#include "../include/tournament.h"
#include <cmath>

bool check_if_fixable(TournamentGraph& graph, int node)
{
    int wins = 0;
    for (int i=0; i<graph.get_size(); ++i)
    {
        if(i != node && graph.wins(node, i))
            wins++;
    }
    return wins >= log2(graph.get_size());
}

void fix_tournament(TournamentGraph& graph, int node)
{
    if(check_if_fixable(graph, node))
        printf("Solvable\n");
}
<commit_msg>Tournament fix case A.<commit_after>#include "../include/graph.h"
#include "../include/tournament.h"
#include <vector>
#include <cmath>
#include <set>
#include <cassert>

bool check_if_fixable(TournamentGraph& graph, int node)
{
    int wins = 0;
    for (int i=0; i<graph.get_size(); ++i)
    {
        if(i != node && graph.wins(node, i))
            wins++;
    }
    return wins >= log2(graph.get_size());
}

bool check_case_A(TournamentGraph& graph, int node)
{
    int wins = 0;
    int max_wins_from_losses = 0;
    int wins_from_losses;

    for (int i=0; i<graph.get_size(); ++i)
    {
        if(i != node && graph.wins(node, i))
            wins++;
        else
        {
            wins_from_losses = 0;
            for (int j=0; j<graph.get_size(); ++j)
            {
                if(i == j)
                    break;
                if(graph.wins(i,j))
                    wins_from_losses++;
            }
            if(wins_from_losses > max_wins_from_losses)
            {
                max_wins_from_losses = wins_from_losses;
            }
        }
    }
    return wins > max_wins_from_losses;
}

void fix_tournament_A(TournamentGraph& graph, int node)
{
    std::set<int> won_with, lost_with;
    std::vector<std::shared_ptr<Tournament>> tournaments;
    for (int i=0; i<graph.get_size(); ++i)
    {
        if(node == i)
            continue;
        if(graph.wins(node, i))
            won_with.insert(i);
        else
            lost_with.insert(i);
    }
    std::set<int> won_copy(won_with), lost_copy(lost_with);
    for(auto lose: lost_copy)
    {
        for(auto win: won_copy)
        {
            if(won_with.count(win) && graph.wins(win, lose))
            {
                won_with.erase(win);
                lost_with.erase(lose);
                tournaments.push_back(
                    std::shared_ptr<Tournament>(
                        new Tournament(&graph, win, lose)));
                break;
            }
        }
    }
    assert(lost_with.size() == 0);

    for (auto i = won_with.begin(); i!=won_with.end(); ++i)
    {
        auto compatitor1 = *i;
        if (++i==won_with.end())
            break;
        auto compatitor2 = *i;
        tournaments.push_back(
            std::shared_ptr<Tournament>(
                new Tournament(&graph, compatitor1, compatitor2)));
    }
    auto last_element = *won_with.begin();
    tournaments.push_back(
        std::shared_ptr<Tournament>(
            new Tournament(&graph, node, last_element)));

    std::vector<std::shared_ptr<Tournament>> tournaments_temp;
    while(tournaments.size() > 1)
    {
        for (auto i = tournaments.begin(); i!=tournaments.end(); ++i)
        {
            auto tournament1 = *i;
            i++;
            auto tournament2 = *i;
            tournaments_temp.push_back(std::unique_ptr<Tournament>(
                new Tournament(*tournament1 + *tournament2)));
        }
        tournaments = tournaments_temp;
    }
    printf("%d\n",tournaments[0]->get_winner());
 }

void fix_tournament(TournamentGraph& graph, int node)
{
    if(check_if_fixable(graph, node))
        printf("Solvable\n");
    if (check_case_A(graph, node))
    {
        printf("Case A\n");
        fix_tournament_A(graph, node);
    }
}
<|endoftext|>


<commit_before>/////////////////////////////////////////////////////////////////////////
// $Id: syntax.cc,v 1.13 2008/02/05 22:33:33 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include "disasm.h"

//////////////////
// Intel STYLE
//////////////////

#define BX_DISASM_SUPPORT_X86_64

#ifdef BX_DISASM_SUPPORT_X86_64

static const char *intel_general_16bit_regname[16] = {
    "ax",  "cx",  "dx",   "bx",   "sp",   "bp",   "si",   "di",
    "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"
};

static const char *intel_general_32bit_regname[16] = {
    "eax", "ecx", "edx",  "ebx",  "esp",  "ebp",  "esi",  "edi",
    "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"
};

static const char *intel_general_64bit_regname[16] = {
    "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
    "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15"
};

static const char *intel_general_8bit_regname_rex[16] = {
    "al",  "cl",  "dl",   "bl",   "spl",  "bpl",  "sil",  "dil",
    "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b"
};

#else

static const char *intel_general_16bit_regname[8] = {
    "ax",  "cx",  "dx",  "bx",  "sp",  "bp",  "si",  "di"
};

static const char *intel_general_32bit_regname[8] = {
    "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
};

#endif

static const char *intel_general_8bit_regname[8] = {
    "al",  "cl",  "dl",  "bl",  "ah",  "ch",  "dh",  "bh"
};

static const char *intel_segment_name[8] = {
    "es",  "cs",  "ss",  "ds",  "fs",  "gs",  "??",  "??"
};

static const char *intel_index16[8] = {
    "bx+si",
    "bx+di",
    "bp+si",
    "bp+di",
    "si",
    "di",
    "bp",
    "bx"
};

//////////////////
// AT&T STYLE
//////////////////

#ifdef BX_DISASM_SUPPORT_X86_64

static const char *att_general_16bit_regname[16] = {
    "%ax",  "%cx",  "%dx",   "%bx",   "%sp",   "%bp",   "%si",   "%di",
    "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w"
};

static const char *att_general_32bit_regname[16] = {
    "%eax", "%ecx", "%edx",  "%ebx",  "%esp",  "%ebp",  "%esi",  "%edi",
    "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d"
};

static const char *att_general_64bit_regname[16] = {
    "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
    "%r8",  "%r9",  "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
};

static const char *att_general_8bit_regname_rex[16] = {
    "%al",  "%cl",  "%dl",   "%bl",   "%spl",  "%bpl",  "%sil",  "%dil",
    "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"
};

#else

static const char *att_general_16bit_regname[8] = {
    "%ax",  "%cx",  "%dx",  "%bx",  "%sp",  "%bp",  "%si",  "%di"
};

static const char *att_general_32bit_regname[8] = {
    "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi"
};

#endif

static const char *att_general_8bit_regname[8] = {
    "%al",  "%cl",  "%dl",  "%bl",  "%ah",  "%ch",  "%dh",  "%bh"
};

static const char *att_segment_name[8] = {
    "%es",  "%cs",  "%ss",  "%ds",  "%fs",  "%gs",  "%??",  "%??"
};

static const char *att_index16[8] = {
    "%bx, %si",
    "%bx, %di",
    "%bp, %si",
    "%bp, %di",
    "%si",
    "%di",
    "%bp",
    "%bx"
};

#define NULL_SEGMENT_REGISTER 7

void disassembler::initialize_modrm_segregs()
{
  sreg_mod00_rm16[0] = segment_name[DS_REG];
  sreg_mod00_rm16[1] = segment_name[DS_REG];
  sreg_mod00_rm16[2] = segment_name[SS_REG];
  sreg_mod00_rm16[3] = segment_name[SS_REG];
  sreg_mod00_rm16[4] = segment_name[DS_REG];
  sreg_mod00_rm16[5] = segment_name[DS_REG];
  sreg_mod00_rm16[6] = segment_name[DS_REG];
  sreg_mod00_rm16[7] = segment_name[DS_REG];

  sreg_mod01or10_rm16[0] = segment_name[DS_REG];
  sreg_mod01or10_rm16[1] = segment_name[DS_REG];
  sreg_mod01or10_rm16[2] = segment_name[SS_REG];
  sreg_mod01or10_rm16[3] = segment_name[SS_REG];
  sreg_mod01or10_rm16[4] = segment_name[DS_REG];
  sreg_mod01or10_rm16[5] = segment_name[DS_REG];
  sreg_mod01or10_rm16[6] = segment_name[SS_REG];
  sreg_mod01or10_rm16[7] = segment_name[DS_REG];

  sreg_mod01or10_rm32[0]  = segment_name[DS_REG];
  sreg_mod01or10_rm32[1]  = segment_name[DS_REG];
  sreg_mod01or10_rm32[2]  = segment_name[DS_REG];
  sreg_mod01or10_rm32[3]  = segment_name[DS_REG];
  sreg_mod01or10_rm32[4]  = segment_name[NULL_SEGMENT_REGISTER];
  sreg_mod01or10_rm32[5]  = segment_name[SS_REG];
  sreg_mod01or10_rm32[6]  = segment_name[DS_REG];
  sreg_mod01or10_rm32[7]  = segment_name[DS_REG];
  sreg_mod01or10_rm32[8]  = segment_name[DS_REG];
  sreg_mod01or10_rm32[9]  = segment_name[DS_REG];
  sreg_mod01or10_rm32[10] = segment_name[DS_REG];
  sreg_mod01or10_rm32[11] = segment_name[DS_REG];
  sreg_mod01or10_rm32[12] = segment_name[NULL_SEGMENT_REGISTER];
  sreg_mod01or10_rm32[13] = segment_name[DS_REG];
  sreg_mod01or10_rm32[14] = segment_name[DS_REG];
  sreg_mod01or10_rm32[15] = segment_name[DS_REG];

  sreg_mod00_base32[0]  = segment_name[DS_REG];
  sreg_mod00_base32[1]  = segment_name[DS_REG];
  sreg_mod00_base32[2]  = segment_name[DS_REG];
  sreg_mod00_base32[3]  = segment_name[DS_REG];
  sreg_mod00_base32[4]  = segment_name[SS_REG];
  sreg_mod00_base32[5]  = segment_name[DS_REG];
  sreg_mod00_base32[6]  = segment_name[DS_REG];
  sreg_mod00_base32[7]  = segment_name[DS_REG];
  sreg_mod00_base32[8]  = segment_name[DS_REG];
  sreg_mod00_base32[9]  = segment_name[DS_REG];
  sreg_mod00_base32[10] = segment_name[DS_REG];
  sreg_mod00_base32[11] = segment_name[DS_REG];
  sreg_mod00_base32[12] = segment_name[DS_REG];
  sreg_mod00_base32[13] = segment_name[DS_REG];
  sreg_mod00_base32[14] = segment_name[DS_REG];
  sreg_mod00_base32[15] = segment_name[DS_REG];

  sreg_mod01or10_base32[0]  = segment_name[DS_REG];
  sreg_mod01or10_base32[1]  = segment_name[DS_REG];
  sreg_mod01or10_base32[2]  = segment_name[DS_REG];
  sreg_mod01or10_base32[3]  = segment_name[DS_REG];
  sreg_mod01or10_base32[4]  = segment_name[SS_REG];
  sreg_mod01or10_base32[5]  = segment_name[SS_REG];
  sreg_mod01or10_base32[6]  = segment_name[DS_REG];
  sreg_mod01or10_base32[7]  = segment_name[DS_REG];
  sreg_mod01or10_base32[8]  = segment_name[DS_REG];
  sreg_mod01or10_base32[9]  = segment_name[DS_REG];
  sreg_mod01or10_base32[10] = segment_name[DS_REG];
  sreg_mod01or10_base32[11] = segment_name[DS_REG];
  sreg_mod01or10_base32[12] = segment_name[DS_REG];
  sreg_mod01or10_base32[13] = segment_name[DS_REG];
  sreg_mod01or10_base32[14] = segment_name[DS_REG];
  sreg_mod01or10_base32[15] = segment_name[DS_REG];
}

//////////////////
// Intel STYLE
//////////////////

void disassembler::set_syntax_intel()
{
  intel_mode = 1;

  general_16bit_regname = intel_general_16bit_regname;
  general_8bit_regname = intel_general_8bit_regname;
  general_32bit_regname = intel_general_32bit_regname;
  general_8bit_regname_rex = intel_general_8bit_regname_rex;
  general_64bit_regname = intel_general_64bit_regname;

  segment_name = intel_segment_name;
  index16 = intel_index16;

  initialize_modrm_segregs();
}

void disassembler::print_disassembly_intel(const x86_insn *insn, const BxDisasmOpcodeInfo_t *entry)
{
  // print opcode
  dis_sprintf("%s ", entry->IntelOpcode);

  if (entry->Operand1) {
    (this->*entry->Operand1)(insn);
  }
  if (entry->Operand2) {
    dis_sprintf(", ");
    (this->*entry->Operand2)(insn);
  }
  if (entry->Operand3) {
    dis_sprintf(", ");
    (this->*entry->Operand3)(insn);
  }
  if (entry->Operand4) {
    dis_sprintf(", ");
    (this->*entry->Operand4)(insn);
  }
}

//////////////////
// AT&T STYLE
//////////////////

void disassembler::set_syntax_att()
{
  intel_mode = 0;

  general_16bit_regname = att_general_16bit_regname;
  general_8bit_regname = att_general_8bit_regname;
  general_32bit_regname = att_general_32bit_regname;
  general_8bit_regname_rex = att_general_8bit_regname_rex;
  general_64bit_regname = att_general_64bit_regname;

  segment_name = att_segment_name;
  index16 = att_index16;

  initialize_modrm_segregs();
}

void disassembler::toggle_syntax_mode()
{
  if (intel_mode) set_syntax_att();
  else set_syntax_intel();
}

void disassembler::print_disassembly_att(const x86_insn *insn, const BxDisasmOpcodeInfo_t *entry)
{
  // print opcode
  dis_sprintf("%s ", entry->AttOpcode);

  if (entry->Operand4) {
    (this->*entry->Operand4)(insn);
    dis_sprintf(", ");
  }
  if (entry->Operand3) {
    (this->*entry->Operand3)(insn);
    dis_sprintf(", ");
  }
  if (entry->Operand2) {
    (this->*entry->Operand2)(insn);
    dis_sprintf(", ");
  }
  if (entry->Operand1) {
    (this->*entry->Operand1)(insn);
  }
}
<commit_msg>Disasm print fixed for AT&T style<commit_after>/////////////////////////////////////////////////////////////////////////
// $Id: syntax.cc,v 1.14 2008/03/20 18:11:57 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include "disasm.h"

//////////////////
// Intel STYLE
//////////////////

#define BX_DISASM_SUPPORT_X86_64

#ifdef BX_DISASM_SUPPORT_X86_64

static const char *intel_general_16bit_regname[16] = {
    "ax",  "cx",  "dx",   "bx",   "sp",   "bp",   "si",   "di",
    "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"
};

static const char *intel_general_32bit_regname[16] = {
    "eax", "ecx", "edx",  "ebx",  "esp",  "ebp",  "esi",  "edi",
    "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"
};

static const char *intel_general_64bit_regname[16] = {
    "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
    "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15"
};

static const char *intel_general_8bit_regname_rex[16] = {
    "al",  "cl",  "dl",   "bl",   "spl",  "bpl",  "sil",  "dil",
    "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b"
};

#else

static const char *intel_general_16bit_regname[8] = {
    "ax",  "cx",  "dx",  "bx",  "sp",  "bp",  "si",  "di"
};

static const char *intel_general_32bit_regname[8] = {
    "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
};

#endif

static const char *intel_general_8bit_regname[8] = {
    "al",  "cl",  "dl",  "bl",  "ah",  "ch",  "dh",  "bh"
};

static const char *intel_segment_name[8] = {
    "es",  "cs",  "ss",  "ds",  "fs",  "gs",  "??",  "??"
};

static const char *intel_index16[8] = {
    "bx+si",
    "bx+di",
    "bp+si",
    "bp+di",
    "si",
    "di",
    "bp",
    "bx"
};

//////////////////
// AT&T STYLE
//////////////////

#ifdef BX_DISASM_SUPPORT_X86_64

static const char *att_general_16bit_regname[16] = {
    "%ax",  "%cx",  "%dx",   "%bx",   "%sp",   "%bp",   "%si",   "%di",
    "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w"
};

static const char *att_general_32bit_regname[16] = {
    "%eax", "%ecx", "%edx",  "%ebx",  "%esp",  "%ebp",  "%esi",  "%edi",
    "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d"
};

static const char *att_general_64bit_regname[16] = {
    "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
    "%r8",  "%r9",  "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
};

static const char *att_general_8bit_regname_rex[16] = {
    "%al",  "%cl",  "%dl",   "%bl",   "%spl",  "%bpl",  "%sil",  "%dil",
    "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"
};

#else

static const char *att_general_16bit_regname[8] = {
    "%ax",  "%cx",  "%dx",  "%bx",  "%sp",  "%bp",  "%si",  "%di"
};

static const char *att_general_32bit_regname[8] = {
    "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi"
};

#endif

static const char *att_general_8bit_regname[8] = {
    "%al",  "%cl",  "%dl",  "%bl",  "%ah",  "%ch",  "%dh",  "%bh"
};

static const char *att_segment_name[8] = {
    "%es",  "%cs",  "%ss",  "%ds",  "%fs",  "%gs",  "%??",  "%??"
};

static const char *att_index16[8] = {
    "%bx,%si",
    "%bx,%di",
    "%bp,%si",
    "%bp,%di",
    "%si",
    "%di",
    "%bp",
    "%bx"
};

#define NULL_SEGMENT_REGISTER 7

void disassembler::initialize_modrm_segregs()
{
  sreg_mod00_rm16[0] = segment_name[DS_REG];
  sreg_mod00_rm16[1] = segment_name[DS_REG];
  sreg_mod00_rm16[2] = segment_name[SS_REG];
  sreg_mod00_rm16[3] = segment_name[SS_REG];
  sreg_mod00_rm16[4] = segment_name[DS_REG];
  sreg_mod00_rm16[5] = segment_name[DS_REG];
  sreg_mod00_rm16[6] = segment_name[DS_REG];
  sreg_mod00_rm16[7] = segment_name[DS_REG];

  sreg_mod01or10_rm16[0] = segment_name[DS_REG];
  sreg_mod01or10_rm16[1] = segment_name[DS_REG];
  sreg_mod01or10_rm16[2] = segment_name[SS_REG];
  sreg_mod01or10_rm16[3] = segment_name[SS_REG];
  sreg_mod01or10_rm16[4] = segment_name[DS_REG];
  sreg_mod01or10_rm16[5] = segment_name[DS_REG];
  sreg_mod01or10_rm16[6] = segment_name[SS_REG];
  sreg_mod01or10_rm16[7] = segment_name[DS_REG];

  sreg_mod01or10_rm32[0]  = segment_name[DS_REG];
  sreg_mod01or10_rm32[1]  = segment_name[DS_REG];
  sreg_mod01or10_rm32[2]  = segment_name[DS_REG];
  sreg_mod01or10_rm32[3]  = segment_name[DS_REG];
  sreg_mod01or10_rm32[4]  = segment_name[NULL_SEGMENT_REGISTER];
  sreg_mod01or10_rm32[5]  = segment_name[SS_REG];
  sreg_mod01or10_rm32[6]  = segment_name[DS_REG];
  sreg_mod01or10_rm32[7]  = segment_name[DS_REG];
  sreg_mod01or10_rm32[8]  = segment_name[DS_REG];
  sreg_mod01or10_rm32[9]  = segment_name[DS_REG];
  sreg_mod01or10_rm32[10] = segment_name[DS_REG];
  sreg_mod01or10_rm32[11] = segment_name[DS_REG];
  sreg_mod01or10_rm32[12] = segment_name[NULL_SEGMENT_REGISTER];
  sreg_mod01or10_rm32[13] = segment_name[DS_REG];
  sreg_mod01or10_rm32[14] = segment_name[DS_REG];
  sreg_mod01or10_rm32[15] = segment_name[DS_REG];

  sreg_mod00_base32[0]  = segment_name[DS_REG];
  sreg_mod00_base32[1]  = segment_name[DS_REG];
  sreg_mod00_base32[2]  = segment_name[DS_REG];
  sreg_mod00_base32[3]  = segment_name[DS_REG];
  sreg_mod00_base32[4]  = segment_name[SS_REG];
  sreg_mod00_base32[5]  = segment_name[DS_REG];
  sreg_mod00_base32[6]  = segment_name[DS_REG];
  sreg_mod00_base32[7]  = segment_name[DS_REG];
  sreg_mod00_base32[8]  = segment_name[DS_REG];
  sreg_mod00_base32[9]  = segment_name[DS_REG];
  sreg_mod00_base32[10] = segment_name[DS_REG];
  sreg_mod00_base32[11] = segment_name[DS_REG];
  sreg_mod00_base32[12] = segment_name[DS_REG];
  sreg_mod00_base32[13] = segment_name[DS_REG];
  sreg_mod00_base32[14] = segment_name[DS_REG];
  sreg_mod00_base32[15] = segment_name[DS_REG];

  sreg_mod01or10_base32[0]  = segment_name[DS_REG];
  sreg_mod01or10_base32[1]  = segment_name[DS_REG];
  sreg_mod01or10_base32[2]  = segment_name[DS_REG];
  sreg_mod01or10_base32[3]  = segment_name[DS_REG];
  sreg_mod01or10_base32[4]  = segment_name[SS_REG];
  sreg_mod01or10_base32[5]  = segment_name[SS_REG];
  sreg_mod01or10_base32[6]  = segment_name[DS_REG];
  sreg_mod01or10_base32[7]  = segment_name[DS_REG];
  sreg_mod01or10_base32[8]  = segment_name[DS_REG];
  sreg_mod01or10_base32[9]  = segment_name[DS_REG];
  sreg_mod01or10_base32[10] = segment_name[DS_REG];
  sreg_mod01or10_base32[11] = segment_name[DS_REG];
  sreg_mod01or10_base32[12] = segment_name[DS_REG];
  sreg_mod01or10_base32[13] = segment_name[DS_REG];
  sreg_mod01or10_base32[14] = segment_name[DS_REG];
  sreg_mod01or10_base32[15] = segment_name[DS_REG];
}

//////////////////
// Intel STYLE
//////////////////

void disassembler::set_syntax_intel()
{
  intel_mode = 1;

  general_16bit_regname = intel_general_16bit_regname;
  general_8bit_regname = intel_general_8bit_regname;
  general_32bit_regname = intel_general_32bit_regname;
  general_8bit_regname_rex = intel_general_8bit_regname_rex;
  general_64bit_regname = intel_general_64bit_regname;

  segment_name = intel_segment_name;
  index16 = intel_index16;

  initialize_modrm_segregs();
}

void disassembler::print_disassembly_intel(const x86_insn *insn, const BxDisasmOpcodeInfo_t *entry)
{
  // print opcode
  dis_sprintf("%s ", entry->IntelOpcode);

  if (entry->Operand1) {
    (this->*entry->Operand1)(insn);
  }
  if (entry->Operand2) {
    dis_sprintf(", ");
    (this->*entry->Operand2)(insn);
  }
  if (entry->Operand3) {
    dis_sprintf(", ");
    (this->*entry->Operand3)(insn);
  }
  if (entry->Operand4) {
    dis_sprintf(", ");
    (this->*entry->Operand4)(insn);
  }
}

//////////////////
// AT&T STYLE
//////////////////

void disassembler::set_syntax_att()
{
  intel_mode = 0;

  general_16bit_regname = att_general_16bit_regname;
  general_8bit_regname = att_general_8bit_regname;
  general_32bit_regname = att_general_32bit_regname;
  general_8bit_regname_rex = att_general_8bit_regname_rex;
  general_64bit_regname = att_general_64bit_regname;

  segment_name = att_segment_name;
  index16 = att_index16;

  initialize_modrm_segregs();
}

void disassembler::toggle_syntax_mode()
{
  if (intel_mode) set_syntax_att();
  else set_syntax_intel();
}

void disassembler::print_disassembly_att(const x86_insn *insn, const BxDisasmOpcodeInfo_t *entry)
{
  // print opcode
  dis_sprintf("%s ", entry->AttOpcode);

  if (entry->Operand4) {
    (this->*entry->Operand4)(insn);
    dis_sprintf(", ");
  }
  if (entry->Operand3) {
    (this->*entry->Operand3)(insn);
    dis_sprintf(", ");
  }
  if (entry->Operand2) {
    (this->*entry->Operand2)(insn);
    dis_sprintf(", ");
  }
  if (entry->Operand1) {
    (this->*entry->Operand1)(insn);
  }
}
<|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (C) 2008 by Jason Ansel                                     *
 *   jansel@csail.mit.edu                                                  *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 3 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "autotuner.h"
#include "hecuraruntime.h"

#include <limits>
#include <algorithm>

JTUNABLE(autotune_alg_slots,                5, 1, 32);
JTUNABLE(autotune_branch_attempts,          3, 1, 32);
JTUNABLE(autotune_improvement_threshold,    90, 10, 100);

#define MAX_ALGS autotune_alg_slots
#define BIRTH_ATTEMPTS autotune_branch_attempts
#define BIRTH_THRESH  (autotune_improvement_threshold.value()/100.0)
#define FIXED_CUTOFF

#ifdef FIXED_CUTOFF
static const int DUP_CUTOFF_THRESH = 1; // how different cutoffs must be to be duplicates
#else
static const int DUP_CUTOFF_THRESH = 1024; // how different cutoffs must be to be duplicates
#endif

namespace{ //file local
  struct CmpLastPerformance {
    bool operator() (const hecura::CandidateAlgorithmPtr& a, const hecura::CandidateAlgorithmPtr& b){
      return a->lastResult() < b->lastResult();
    }
  };

  struct CmpLastLastPerformance {
    bool operator() (const hecura::CandidateAlgorithmPtr& a, const hecura::CandidateAlgorithmPtr& b){
      return a->lastlastResult() < b->lastlastResult();
    }
  };

  struct CmpAlgType {
    bool operator() (const hecura::CandidateAlgorithmPtr& a, const hecura::CandidateAlgorithmPtr& b){
      if(a->lvl() != b->lvl()) return a->lvl() < b->lvl();
      hecura::CandidateAlgorithmPtr ta=a, tb=b;
      while(ta && tb){
        if(ta->alg() != tb->alg()) return ta->alg() < tb->alg();
        ta=ta->next();
        tb=tb->next();
      }
      return a->cutoff() < b->cutoff();
    }
  };

  std::string _mktname(int lvl, const std::string& prefix, const std::string& type){
    return prefix + "_lvl" + jalib::XToString(lvl) + "_" + type;
  }
}

jalib::JTunable* hecura::Autotuner::algTunable(int lvl){
  return _tunableMap[_mktname(lvl, _prefix, "rule")];
}
jalib::JTunable* hecura::Autotuner::cutoffTunable(int lvl){
  return _tunableMap[_mktname(lvl, _prefix, "cutoff")];
}

hecura::Autotuner::Autotuner(HecuraRuntime& rt, std::string& prefix)
  : _runtime(rt)
  , _tunableMap(jalib::JTunableManager::instance().getReverseMap())
  , _prefix(prefix)
{
  using jalib::JTunable;
  //find numlevels
  for(int lvl=2; true; ++lvl){
    JTunable* rule   = algTunable(lvl);
    JTunable* cutoff = cutoffTunable(lvl);
    if(rule==0 && cutoff==0){
      _maxLevels = lvl-1;
      break;
    }
  }
  JASSERT(_maxLevels>1)(prefix).Text("invalid prefix to autotune");

  //make initialconfig (all level disabled)
  for(int lvl=1; lvl<=_maxLevels; ++lvl){
    JTunable* at   = algTunable(lvl);
    JTunable* ct = cutoffTunable(lvl);
    int a=0, c=std::numeric_limits<int>::max();
    if(ct!=0) c=ct->max();
    _initialConfig = new CandidateAlgorithm(lvl, a, at, c, ct, _initialConfig);
  }

  //add 1 level candidates
  CandidateAlgorithmList lvl1Candidates;
  {
    JTunable* at = algTunable(1);
    JTunable* ct = cutoffTunable(1);
    int a=0, c=1;
    if(at==0){
      lvl1Candidates.push_back(new CandidateAlgorithm(1, a, at, c, ct, NULL));
    }else{
      for(a=at->min(); a<=at->max(); ++a){
        lvl1Candidates.push_back(new CandidateAlgorithm(1, a, at, c, ct, NULL));
      }
    }
  }

  //add 2 level candidates
  CandidateAlgorithmList lvl2Candidates;
  {
    JTunable* at = algTunable(2);
    JTunable* ct = cutoffTunable(2);
    int a=0, c=1;
    if(at==0){
      for(CandidateAlgorithmList::const_iterator i=lvl1Candidates.begin(); i!=lvl1Candidates.end(); ++i)
        lvl2Candidates.push_back(new CandidateAlgorithm(2, a, at, c, ct, *i));
    }else{
      for(a=at->min(); a<=at->max(); ++a){
        for(CandidateAlgorithmList::const_iterator i=lvl1Candidates.begin(); i!=lvl1Candidates.end(); ++i)
          lvl2Candidates.push_back(new CandidateAlgorithm(2, a, at, c, ct, *i));
      }
    }
  }

  JTRACE("Autotuner constructed")(lvl1Candidates.size())(lvl2Candidates.size());
  _candidates.swap(lvl1Candidates);
  _candidates.insert(_candidates.end(), lvl2Candidates.begin(), lvl2Candidates.end());
}

void hecura::Autotuner::runAll(){
  for(CandidateAlgorithmList::iterator i=_candidates.begin(); i!=_candidates.end(); ++i){
    _initialConfig->activate();
    (*i)->activate();
    double d = _runtime.runTrial();
    (*i)->addResult(d);
    fflush(stdout);
  }
}

void hecura::Autotuner::train(int min, int max){
  for(int n=min; n<=max; n*=2){
    _runtime.setSize(n);
    trainOnce();
  }
}

void hecura::Autotuner::trainOnce(){
  std::cout << "BEGIN ITERATION " << _prefix << " / " << _runtime.curSize() << std::endl;
  runAll();

  std::sort(_candidates.begin(), _candidates.end(), CmpLastPerformance());
  double bestPerf = _candidates[0]->lastResult();

  // add new algorithms -- by last rounds performance
  std::sort(_candidates.begin(), _candidates.end(), CmpLastLastPerformance());
  for(int i=0; i<BIRTH_ATTEMPTS && i<_candidates.size(); ++i){
    _initialConfig->activate();
    CandidateAlgorithmPtr b=_candidates[i]->attemptBirth(_runtime, *this, bestPerf*BIRTH_THRESH);
    if(b){
      _candidates.push_back(b);
      std::cout << "  ADDED " << b << std::endl;
    }
  }

  removeDuplicates();

  std::sort(_candidates.begin(), _candidates.end(), CmpLastPerformance());
  //kill slowest algorithms
  for(int i=_candidates.size()-1; i>0; --i){
      if(_candidates[i]->lastResult() > std::numeric_limits<double>::max()/2
        || i>=MAX_ALGS){
        std::cout << "  REMOVED " << _candidates[i] << std::endl;
        _candidates.pop_back();
      }else break;
  }

  printCanidates();

  //reset config
  _initialConfig->activate();
  _candidates[0]->activate();
}

void hecura::Autotuner::printCanidates(){
  for(CandidateAlgorithmList::iterator i=_candidates.begin(); i!=_candidates.end(); ++i){
    std::cout << "  * " << jalib::StringPad((*i)->toString(),20) << " = " << (*i)->lastResult() << std::endl;
  }
}

void hecura::Autotuner::removeDuplicates(){
  std::sort(_candidates.begin(), _candidates.end(), CmpAlgType());
  //kill duplicates
  for(int i=0; i<_candidates.size()-1; ++i){
    if(_candidates[i]->isDuplicate(_candidates[i+1])){
      if(_candidates[i]->lastResult() > _candidates[i+1]->lastResult()){
        std::cout << "  DUPLICATE " << _candidates[i] << std::endl;
        _candidates.erase(_candidates.begin()+i);
      }else{
        std::cout << "  DUPLICATE " << _candidates[i+1] << std::endl;
        _candidates.erase(_candidates.begin()+i+1);
      }
      --i; //redo this iteration
    }
  }
}

hecura::CandidateAlgorithmPtr hecura::CandidateAlgorithm::attemptBirth(HecuraRuntime& rt, Autotuner& autotuner, double thresh) {
  CandidateAlgorithmList possible;
  activate();

#ifndef FIXED_CUTOFF
  if(_cutoffTunable!=0){
    int min = _cutoffTunable->min();
    if(_nextLevel) min=_nextLevel->cutoff();
    int max = std::min(rt.curSize(), _cutoffTunable->max());
    if(max>500) max = std::min(max, _cutoff*4);
    double p = rt.optimizeParameter(*_cutoffTunable, min, max);
    if(p<thresh && p>=0){
      CandidateAlgorithmPtr c = new CandidateAlgorithm(_lvl, _alg, _algTunable, _cutoffTunable->value() , _cutoffTunable, _nextLevel);
      c->addResult(p);
      if(c->isDuplicate(this)){
        _cutoff=_cutoffTunable->value();
        addResult(p);
      }else
        return c;
    }
    activate();
  }
#endif

  jalib::JTunable* at = autotuner.algTunable(_lvl+1);
  jalib::JTunable* ct = autotuner.cutoffTunable(_lvl+1);
  if(ct!=0){
    int min = _cutoff;
    int max = std::min(rt.curSize(), ct->max());
    int amin=0,amax=0;
    if(at!=0){
      amin=at->min();
      amax=at->max();
    }
    for(int a=amin; a<=amax; ++a){
      if(_lvl>1 && a==_alg) continue;
      if(at!=0) at->setValue(a);
#ifndef FIXED_CUTOFF
      double p = rt.optimizeParameter(*ct, min, max);
#else
      ct->setValue(rt.curSize() * 3 / 4);
      if (ct->value() <= 1) {
        continue;
      }
      double p = rt.runTrial();
#endif
      CandidateAlgorithmPtr c = new CandidateAlgorithm(_lvl+1, a, at, ct->value(), ct, this);
      c->addResult(p);
      if(p<thresh && p>=0){
        possible.push_back(c);
        std::cout << "  SPAWN " << c << ' ' << p << std::endl;
      }
      else
        std::cout << "  FAILED SPAWN " << c << ' ' << p << std::endl;
    }
  }

  if(possible.empty())
    return 0;

  std::sort(possible.begin(), possible.end(), CmpLastPerformance());
  return possible[0];
}

bool hecura::CandidateAlgorithm::isDuplicate(const CandidateAlgorithmPtr& that){
  if(!that) return false;
  if(_lvl != that->lvl()) return false;
  if(_alg != that->alg()) return false;
  if(std::abs(_cutoff - that->cutoff()) > DUP_CUTOFF_THRESH) return false;
  if(_nextLevel) return _nextLevel->isDuplicate(that->next());
  return true;
}

<commit_msg>- report times for removed algorithms<commit_after>/***************************************************************************
 *   Copyright (C) 2008 by Jason Ansel                                     *
 *   jansel@csail.mit.edu                                                  *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 3 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "autotuner.h"
#include "hecuraruntime.h"

#include <limits>
#include <algorithm>

JTUNABLE(autotune_alg_slots,                5, 1, 32);
JTUNABLE(autotune_branch_attempts,          3, 1, 32);
JTUNABLE(autotune_improvement_threshold,    90, 10, 100);

#define MAX_ALGS autotune_alg_slots
#define BIRTH_ATTEMPTS autotune_branch_attempts
#define BIRTH_THRESH  (autotune_improvement_threshold.value()/100.0)
#define FIXED_CUTOFF

#ifdef FIXED_CUTOFF
static const int DUP_CUTOFF_THRESH = 1; // how different cutoffs must be to be duplicates
#else
static const int DUP_CUTOFF_THRESH = 1024; // how different cutoffs must be to be duplicates
#endif

namespace{ //file local
  struct CmpLastPerformance {
    bool operator() (const hecura::CandidateAlgorithmPtr& a, const hecura::CandidateAlgorithmPtr& b){
      return a->lastResult() < b->lastResult();
    }
  };

  struct CmpLastLastPerformance {
    bool operator() (const hecura::CandidateAlgorithmPtr& a, const hecura::CandidateAlgorithmPtr& b){
      return a->lastlastResult() < b->lastlastResult();
    }
  };

  struct CmpAlgType {
    bool operator() (const hecura::CandidateAlgorithmPtr& a, const hecura::CandidateAlgorithmPtr& b){
      if(a->lvl() != b->lvl()) return a->lvl() < b->lvl();
      hecura::CandidateAlgorithmPtr ta=a, tb=b;
      while(ta && tb){
        if(ta->alg() != tb->alg()) return ta->alg() < tb->alg();
        ta=ta->next();
        tb=tb->next();
      }
      return a->cutoff() < b->cutoff();
    }
  };

  std::string _mktname(int lvl, const std::string& prefix, const std::string& type){
    return prefix + "_lvl" + jalib::XToString(lvl) + "_" + type;
  }
}

jalib::JTunable* hecura::Autotuner::algTunable(int lvl){
  return _tunableMap[_mktname(lvl, _prefix, "rule")];
}
jalib::JTunable* hecura::Autotuner::cutoffTunable(int lvl){
  return _tunableMap[_mktname(lvl, _prefix, "cutoff")];
}

hecura::Autotuner::Autotuner(HecuraRuntime& rt, std::string& prefix)
  : _runtime(rt)
  , _tunableMap(jalib::JTunableManager::instance().getReverseMap())
  , _prefix(prefix)
{
  using jalib::JTunable;
  //find numlevels
  for(int lvl=2; true; ++lvl){
    JTunable* rule   = algTunable(lvl);
    JTunable* cutoff = cutoffTunable(lvl);
    if(rule==0 && cutoff==0){
      _maxLevels = lvl-1;
      break;
    }
  }
  JASSERT(_maxLevels>1)(prefix).Text("invalid prefix to autotune");

  //make initialconfig (all level disabled)
  for(int lvl=1; lvl<=_maxLevels; ++lvl){
    JTunable* at   = algTunable(lvl);
    JTunable* ct = cutoffTunable(lvl);
    int a=0, c=std::numeric_limits<int>::max();
    if(ct!=0) c=ct->max();
    _initialConfig = new CandidateAlgorithm(lvl, a, at, c, ct, _initialConfig);
  }

  //add 1 level candidates
  CandidateAlgorithmList lvl1Candidates;
  {
    JTunable* at = algTunable(1);
    JTunable* ct = cutoffTunable(1);
    int a=0, c=1;
    if(at==0){
      lvl1Candidates.push_back(new CandidateAlgorithm(1, a, at, c, ct, NULL));
    }else{
      for(a=at->min(); a<=at->max(); ++a){
        lvl1Candidates.push_back(new CandidateAlgorithm(1, a, at, c, ct, NULL));
      }
    }
  }

  //add 2 level candidates
  CandidateAlgorithmList lvl2Candidates;
  {
    JTunable* at = algTunable(2);
    JTunable* ct = cutoffTunable(2);
    int a=0, c=1;
    if(at==0){
      for(CandidateAlgorithmList::const_iterator i=lvl1Candidates.begin(); i!=lvl1Candidates.end(); ++i)
        lvl2Candidates.push_back(new CandidateAlgorithm(2, a, at, c, ct, *i));
    }else{
      for(a=at->min(); a<=at->max(); ++a){
        for(CandidateAlgorithmList::const_iterator i=lvl1Candidates.begin(); i!=lvl1Candidates.end(); ++i)
          lvl2Candidates.push_back(new CandidateAlgorithm(2, a, at, c, ct, *i));
      }
    }
  }

  JTRACE("Autotuner constructed")(lvl1Candidates.size())(lvl2Candidates.size());
  _candidates.swap(lvl1Candidates);
  _candidates.insert(_candidates.end(), lvl2Candidates.begin(), lvl2Candidates.end());
}

void hecura::Autotuner::runAll(){
  for(CandidateAlgorithmList::iterator i=_candidates.begin(); i!=_candidates.end(); ++i){
    _initialConfig->activate();
    (*i)->activate();
    double d = _runtime.runTrial();
    (*i)->addResult(d);
    fflush(stdout);
  }
}

void hecura::Autotuner::train(int min, int max){
  for(int n=min; n<=max; n*=2){
    _runtime.setSize(n);
    trainOnce();
  }
}

void hecura::Autotuner::trainOnce(){
  std::cout << "BEGIN ITERATION " << _prefix << " / " << _runtime.curSize() << std::endl;
  runAll();

  std::sort(_candidates.begin(), _candidates.end(), CmpLastPerformance());
  double bestPerf = _candidates[0]->lastResult();

  // add new algorithms -- by last rounds performance
  std::sort(_candidates.begin(), _candidates.end(), CmpLastLastPerformance());
  for(int i=0; i<BIRTH_ATTEMPTS && i<_candidates.size(); ++i){
    _initialConfig->activate();
    CandidateAlgorithmPtr b=_candidates[i]->attemptBirth(_runtime, *this, bestPerf*BIRTH_THRESH);
    if(b){
      _candidates.push_back(b);
      std::cout << "  ADDED " << b << std::endl;
    }
  }

  removeDuplicates();

  std::sort(_candidates.begin(), _candidates.end(), CmpLastPerformance());
  //kill slowest algorithms
  for(int i=_candidates.size()-1; i>0; --i){
      if(_candidates[i]->lastResult() > std::numeric_limits<double>::max()/2
        || i>=MAX_ALGS){
        std::cout << "  REMOVED " << _candidates[i] << ' ' << _candidates[i]->lastResult() << std::endl;
        _candidates.pop_back();
      }else break;
  }

  printCanidates();

  //reset config
  _initialConfig->activate();
  _candidates[0]->activate();
}

void hecura::Autotuner::printCanidates(){
  for(CandidateAlgorithmList::iterator i=_candidates.begin(); i!=_candidates.end(); ++i){
    std::cout << "  * " << jalib::StringPad((*i)->toString(),20) << " = " << (*i)->lastResult() << std::endl;
  }
}

void hecura::Autotuner::removeDuplicates(){
  std::sort(_candidates.begin(), _candidates.end(), CmpAlgType());
  //kill duplicates
  for(int i=0; i<_candidates.size()-1; ++i){
    if(_candidates[i]->isDuplicate(_candidates[i+1])){
      if(_candidates[i]->lastResult() > _candidates[i+1]->lastResult()){
        std::cout << "  DUPLICATE " << _candidates[i] << std::endl;
        _candidates.erase(_candidates.begin()+i);
      }else{
        std::cout << "  DUPLICATE " << _candidates[i+1] << std::endl;
        _candidates.erase(_candidates.begin()+i+1);
      }
      --i; //redo this iteration
    }
  }
}

hecura::CandidateAlgorithmPtr hecura::CandidateAlgorithm::attemptBirth(HecuraRuntime& rt, Autotuner& autotuner, double thresh) {
  CandidateAlgorithmList possible;
  activate();

#ifndef FIXED_CUTOFF
  if(_cutoffTunable!=0){
    int min = _cutoffTunable->min();
    if(_nextLevel) min=_nextLevel->cutoff();
    int max = std::min(rt.curSize(), _cutoffTunable->max());
    if(max>500) max = std::min(max, _cutoff*4);
    double p = rt.optimizeParameter(*_cutoffTunable, min, max);
    if(p<thresh && p>=0){
      CandidateAlgorithmPtr c = new CandidateAlgorithm(_lvl, _alg, _algTunable, _cutoffTunable->value() , _cutoffTunable, _nextLevel);
      c->addResult(p);
      if(c->isDuplicate(this)){
        _cutoff=_cutoffTunable->value();
        addResult(p);
      }else
        return c;
    }
    activate();
  }
#endif

  jalib::JTunable* at = autotuner.algTunable(_lvl+1);
  jalib::JTunable* ct = autotuner.cutoffTunable(_lvl+1);
  if(ct!=0){
    int min = _cutoff;
    int max = std::min(rt.curSize(), ct->max());
    int amin=0,amax=0;
    if(at!=0){
      amin=at->min();
      amax=at->max();
    }
    for(int a=amin; a<=amax; ++a){
      if(_lvl>1 && a==_alg) continue;
      if(at!=0) at->setValue(a);
#ifndef FIXED_CUTOFF
      double p = rt.optimizeParameter(*ct, min, max);
#else
      ct->setValue(rt.curSize() * 3 / 4);
      if (ct->value() <= 1) {
        continue;
      }
      double p = rt.runTrial();
#endif
      CandidateAlgorithmPtr c = new CandidateAlgorithm(_lvl+1, a, at, ct->value(), ct, this);
      c->addResult(p);
      if(p<thresh && p>=0){
        possible.push_back(c);
        std::cout << "  SPAWN " << c << ' ' << p << std::endl;
      }
      else
        std::cout << "  FAILED SPAWN " << c << ' ' << p << std::endl;
    }
  }

  if(possible.empty())
    return 0;

  std::sort(possible.begin(), possible.end(), CmpLastPerformance());
  return possible[0];
}

bool hecura::CandidateAlgorithm::isDuplicate(const CandidateAlgorithmPtr& that){
  if(!that) return false;
  if(_lvl != that->lvl()) return false;
  if(_alg != that->alg()) return false;
  if(std::abs(_cutoff - that->cutoff()) > DUP_CUTOFF_THRESH) return false;
  if(_nextLevel) return _nextLevel->isDuplicate(that->next());
  return true;
}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2012
 * Alessio Sclocco <a.sclocco@vu.nl>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <iostream>
#include <string>
#include <vector>
#include <exception>
#include <fstream>
#include <iomanip>
#include <limits>
using std::cout;
using std::cerr;
using std::endl;
using std::string;
using std::vector;
using std::exception;
using std::ofstream;
using std::fixed;
using std::setprecision;
using std::numeric_limits;

#include <ArgumentList.hpp>
#include <Observation.hpp>
#include <ReadData.hpp>
#include <InitializeOpenCL.hpp>
#include <CLData.hpp>
#include <utils.hpp>
#include <Shifts.hpp>
#include <ShiftsCPU.hpp>
#include <Dedispersion.hpp>
#include <DedispersionCPU.hpp>
using isa::utils::ArgumentList;
using AstroData::Observation;
using AstroData::readLOFAR;
using isa::OpenCL::initializeOpenCL;
using isa::OpenCL::CLData;
using isa::utils::same;
using TDM::getShifts;
using TDM::getShiftsCPU;
using TDM::Dedispersion;
using TDM::dedispersion;

typedef float dataType;
const string typeName("float");

// Common parameters
const unsigned int nrBeams = 1;
const unsigned int nrStations = 64;
const unsigned int paddingCL = 32;
const unsigned int paddingCPU = 8;
// LOFAR
/*const float minFreq = 138.965f;
const float channelBandwidth = 0.195f;
const unsigned int nrSamplesPerSecond = 200000;
const unsigned int nrChannels = 32;*/
// Apertif
const float minFreq = 1425.0f;
const float channelBandwidth = 0.2929f;
const unsigned int nrSamplesPerSecond = 20000;
const unsigned int nrChannels = 1024;
// DMs
const unsigned int nrDMs = 256;
const float firstDM = 0.0f;
const float DMStep = 0.25f;

int main(int argc, char *argv[]) {
	unsigned int clPlatformID = 0;
	unsigned int clDeviceID = 0;
	unsigned int nrSamplesPerBlock = 0;
	unsigned int nrDMsPerBlock = 0;
	unsigned int nrSamplesPerThread = 0;
	unsigned int nrDMsPerThread = 0;
	unsigned int nrSamplesPerChannel = 0;
	unsigned int secondsToBuffer = 0;
	long long unsigned int wrongOnes = 0;
	Observation< dataType > observation("DedispersionTest", typeName);
	Observation< dataType > observationCPU("DedispersionTest", typeName);
	CLData< unsigned int > * clShifts = 0;
	unsigned int * shifts = 0;
	CLData< dataType > * dispersedData = new CLData< dataType >("DispersedData", true);
	dataType * dedispersedData = 0;
	CLData< dataType > * clDedispersedData = new CLData< dataType >("clDedispersedData", true);

	try {
		ArgumentList args(argc, argv);

		clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
		clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");

		nrSamplesPerBlock = args.getSwitchArgument< unsigned int >("-sb");
		nrDMsPerBlock = args.getSwitchArgument< unsigned int >("-db");
		nrSamplesPerThread = args.getSwitchArgument< unsigned int >("-st");
		nrDMsPerThread = args.getSwitchArgument< unsigned int >("-dt");
	} catch ( exception &err ) {
		cerr << err.what() << endl;
		return 1;
	}

	// Setup of the observation
	observation.setPadding(paddingCL);
	observation.setNrBeams(nrStations);
	observation.setNrStations(nrBeams);
	observation.setMinFreq(minFreq);
	observation.setMaxFreq(minFreq + (channelBandwidth * (nrChannels - 1)));
	observation.setChannelBandwidth(channelBandwidth);
	observation.setNrSamplesPerSecond(nrSamplesPerSecond);
	observation.setNrChannels(nrChannels);
	observation.setNrDMs(nrDMs);
	observation.setFirstDM(firstDM);
	observation.setDMStep(DMStep);
	observationCPU = observation;
	observationCPU.setPadding(paddingCPU);

	// Test
	cl::Context *clContext = new cl::Context();
	vector< cl::Platform > *clPlatforms = new vector< cl::Platform >();
	vector< cl::Device > *clDevices = new vector< cl::Device >();
	vector< vector< cl::CommandQueue > > *clQueues = new vector< vector < cl::CommandQueue > >();

	initializeOpenCL(clPlatformID, 1, clPlatforms, clContext, clDevices, clQueues);
	shiftsCL = getShifts(observation);
	shifts = getShiftsCPU(observationCPU);

	if ( ((observation.getNrSamplesPerSecond() + (*shiftsCL)[((observation.getNrDMs() - 1) * observation.getNrPaddedChannels())]) % paddingCL) != 0 ) {
		nrSamplesPerChannel = (observation.getNrSamplesPerSecond() + (*shiftsCL)[((observation.getNrDMs() - 1) * observation.getNrPaddedChannels())]) + (paddingCL - ((observation.getNrSamplesPerSecond() + (*shiftsCL)[((observation.getNrDMs() - 1) * observation.getNrPaddedChannels())]) % paddingCL));
	} else {
		nrSamplesPerChannel = (observation.getNrSamplesPerSecond() + (*shiftsCL)[((observation.getNrDMs() - 1) * observation.getNrPaddedChannels())]);
	}
	secondsToBuffer = static_cast< unsigned int >(ceil(static_cast< float >(nrSamplesPerChannel) / observation.getNrSamplesPerPaddedSecond()));

	// Allocate memory
	dispersedData->allocateHostData(secondsToBuffer * observation.getNrChannels() * observation.getNrSamplesPerPaddedSecond());
	dedispersedData = new dataType [observationCPU.getNrDMs() * observationCPU.getNrSamplesPerPaddedSecond()];
	clDedispersedData->allocateHostData(observation.getNrDMs() * observation.getNrSamplesPerPaddedSecond());

	srand(time(NULL));
	for ( unsigned int channel = 0; channel < observation.getNrChannels(); channel++ ) {
		for ( unsigned int sample = 0; sample < (secondsToBuffer * observation.getNrSamplesPerSecond()); sample++ ) {
			dispersedData->setHostDataItem((channel * (secondsToBuffer * observation.getNrSamplesPerPaddedSecond())) + sample, static_cast< dataType >(rand() % 10));
		}
	}

	try {
		shiftsCL->setCLContext(clContext);
		shiftsCL->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
		shiftsCL->allocateDeviceData();
		shiftsCL->copyHostToDevice();

		dispersedData->setCLContext(clContext);
		dispersedData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
		dispersedData->setDeviceReadOnly();
		dispersedData->allocateDeviceData();
		dispersedData->copyHostToDevice();

		clDedispersedData->setCLContext(clContext);
		clDedispersedData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
		clDedispersedData->allocateDeviceData();
	} catch ( OpenCLError err ) {
		cerr << err.what() << endl;
		return 1;
	}

	// Generate kernel
	try {
		Dedispersion< dataType > clDedisperse("Dedisperse", typeName);
		clDedisperse.bindOpenCL(clContext, &(clDevices->at(clDeviceID)), &((clQueues->at(clDeviceID)).at(0)));
		clDedisperse.setNrSamplesPerBlock(nrSamplesPerBlock);
		clDedisperse.setNrDMsPerBlock(nrDMsPerBlock);
		clDedisperse.setNrSamplesPerThread(nrSamplesPerThread);
		clDedisperse.setNrDMsPerThread(nrDMsPerThread);
		clDedisperse.setNrSamplesPerDispersedChannel(secondsToBuffer * observation.getNrSamplesPerPaddedSecond());
		clDedisperse.setObservation(&observation);
		clDedisperse.setShifts(shiftsCL);
		clDedisperse.generateCode();

		cout << clDedisperse.getCode() << endl;
		cout << endl;

		clDedisperse(dispersedData, clDedispersedData);
		clDedispersedData->copyDeviceToHost();
	} catch ( OpenCLError err ) {
		cerr << err.what() << endl;
		return 1;
	}

	dedispersion(secondsToBuffer * observationCPU.getNrSamplesPerPaddedSecond(), observationCPU, dispersedData->getHostData(), dedispersedData, shifts);

	for ( unsigned int dm = 0; dm < observation.getNrDMs(); dm++ ) {
		for ( unsigned int sample = 0; sample < observation.getNrSamplesPerSecond(); sample++ ) {
			if ( !same((*dedispersedData)[(dm * observationCPU.getNrSamplesPerPaddedSecond()) + sample], (*clDedispersedData)[(dm * observation.getNrSamplesPerPaddedSecond()) + sample]) ) {
				wrongOnes++;

				cout << dm << " " << sample << " " << (*dedispersedData)[(dm * observationCPU.getNrSamplesPerPaddedSecond()) + sample] << " " << (*clDedispersedData)[(dm * observation.getNrSamplesPerPaddedSecond()) + sample] << " " << (*dedispersedData)[(dm * observation.getNrSamplesPerPaddedSecond()) + sample] - (*clDedispersedData)[(dm * observation.getNrSamplesPerPaddedSecond()) + sample] << endl;
			}
		}
	}

	cout << endl;

	cout << "Wrong samples: " << wrongOnes << " (" << (wrongOnes * 100) / (static_cast< long long unsigned int >(observation.getNrSeconds()) * observation.getNrDMs() * observation.getNrSamplesPerSecond()) << "%)." << endl;
	cout << endl;

	return 0;
}

<commit_msg>Silly typo. Yes, it's Monday.<commit_after>/*
 * Copyright (C) 2012
 * Alessio Sclocco <a.sclocco@vu.nl>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <iostream>
#include <string>
#include <vector>
#include <exception>
#include <fstream>
#include <iomanip>
#include <limits>
using std::cout;
using std::cerr;
using std::endl;
using std::string;
using std::vector;
using std::exception;
using std::ofstream;
using std::fixed;
using std::setprecision;
using std::numeric_limits;

#include <ArgumentList.hpp>
#include <Observation.hpp>
#include <ReadData.hpp>
#include <InitializeOpenCL.hpp>
#include <CLData.hpp>
#include <utils.hpp>
#include <Shifts.hpp>
#include <ShiftsCPU.hpp>
#include <Dedispersion.hpp>
#include <DedispersionCPU.hpp>
using isa::utils::ArgumentList;
using AstroData::Observation;
using AstroData::readLOFAR;
using isa::OpenCL::initializeOpenCL;
using isa::OpenCL::CLData;
using isa::utils::same;
using TDM::getShifts;
using TDM::getShiftsCPU;
using TDM::Dedispersion;
using TDM::dedispersion;

typedef float dataType;
const string typeName("float");

// Common parameters
const unsigned int nrBeams = 1;
const unsigned int nrStations = 64;
const unsigned int paddingCL = 32;
const unsigned int paddingCPU = 8;
// LOFAR
/*const float minFreq = 138.965f;
const float channelBandwidth = 0.195f;
const unsigned int nrSamplesPerSecond = 200000;
const unsigned int nrChannels = 32;*/
// Apertif
const float minFreq = 1425.0f;
const float channelBandwidth = 0.2929f;
const unsigned int nrSamplesPerSecond = 20000;
const unsigned int nrChannels = 1024;
// DMs
const unsigned int nrDMs = 256;
const float firstDM = 0.0f;
const float DMStep = 0.25f;

int main(int argc, char *argv[]) {
	unsigned int clPlatformID = 0;
	unsigned int clDeviceID = 0;
	unsigned int nrSamplesPerBlock = 0;
	unsigned int nrDMsPerBlock = 0;
	unsigned int nrSamplesPerThread = 0;
	unsigned int nrDMsPerThread = 0;
	unsigned int nrSamplesPerChannel = 0;
	unsigned int secondsToBuffer = 0;
	long long unsigned int wrongOnes = 0;
	Observation< dataType > observation("DedispersionTest", typeName);
	Observation< dataType > observationCPU("DedispersionTest", typeName);
	CLData< unsigned int > * clShifts = 0;
	unsigned int * shifts = 0;
	CLData< dataType > * dispersedData = new CLData< dataType >("DispersedData", true);
	dataType * dedispersedData = 0;
	CLData< dataType > * clDedispersedData = new CLData< dataType >("clDedispersedData", true);

	try {
		ArgumentList args(argc, argv);

		clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
		clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");

		nrSamplesPerBlock = args.getSwitchArgument< unsigned int >("-sb");
		nrDMsPerBlock = args.getSwitchArgument< unsigned int >("-db");
		nrSamplesPerThread = args.getSwitchArgument< unsigned int >("-st");
		nrDMsPerThread = args.getSwitchArgument< unsigned int >("-dt");
	} catch ( exception &err ) {
		cerr << err.what() << endl;
		return 1;
	}

	// Setup of the observation
	observation.setPadding(paddingCL);
	observation.setNrBeams(nrStations);
	observation.setNrStations(nrBeams);
	observation.setMinFreq(minFreq);
	observation.setMaxFreq(minFreq + (channelBandwidth * (nrChannels - 1)));
	observation.setChannelBandwidth(channelBandwidth);
	observation.setNrSamplesPerSecond(nrSamplesPerSecond);
	observation.setNrChannels(nrChannels);
	observation.setNrDMs(nrDMs);
	observation.setFirstDM(firstDM);
	observation.setDMStep(DMStep);
	observationCPU = observation;
	observationCPU.setPadding(paddingCPU);

	// Test
	cl::Context *clContext = new cl::Context();
	vector< cl::Platform > *clPlatforms = new vector< cl::Platform >();
	vector< cl::Device > *clDevices = new vector< cl::Device >();
	vector< vector< cl::CommandQueue > > *clQueues = new vector< vector < cl::CommandQueue > >();

	initializeOpenCL(clPlatformID, 1, clPlatforms, clContext, clDevices, clQueues);
	clShifts = getShifts(observation);
	shifts = getShiftsCPU(observationCPU);

	if ( ((observation.getNrSamplesPerSecond() + (*clShifts)[((observation.getNrDMs() - 1) * observation.getNrPaddedChannels())]) % paddingCL) != 0 ) {
		nrSamplesPerChannel = (observation.getNrSamplesPerSecond() + (*clShifts)[((observation.getNrDMs() - 1) * observation.getNrPaddedChannels())]) + (paddingCL - ((observation.getNrSamplesPerSecond() + (*clShifts)[((observation.getNrDMs() - 1) * observation.getNrPaddedChannels())]) % paddingCL));
	} else {
		nrSamplesPerChannel = (observation.getNrSamplesPerSecond() + (*clShifts)[((observation.getNrDMs() - 1) * observation.getNrPaddedChannels())]);
	}
	secondsToBuffer = static_cast< unsigned int >(ceil(static_cast< float >(nrSamplesPerChannel) / observation.getNrSamplesPerPaddedSecond()));

	// Allocate memory
	dispersedData->allocateHostData(secondsToBuffer * observation.getNrChannels() * observation.getNrSamplesPerPaddedSecond());
	dedispersedData = new dataType [observationCPU.getNrDMs() * observationCPU.getNrSamplesPerPaddedSecond()];
	clDedispersedData->allocateHostData(observation.getNrDMs() * observation.getNrSamplesPerPaddedSecond());

	srand(time(NULL));
	for ( unsigned int channel = 0; channel < observation.getNrChannels(); channel++ ) {
		for ( unsigned int sample = 0; sample < (secondsToBuffer * observation.getNrSamplesPerSecond()); sample++ ) {
			dispersedData->setHostDataItem((channel * (secondsToBuffer * observation.getNrSamplesPerPaddedSecond())) + sample, static_cast< dataType >(rand() % 10));
		}
	}

	try {
		clShifts->setCLContext(clContext);
		clShifts->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
		clShifts->allocateDeviceData();
		clShifts->copyHostToDevice();

		dispersedData->setCLContext(clContext);
		dispersedData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
		dispersedData->setDeviceReadOnly();
		dispersedData->allocateDeviceData();
		dispersedData->copyHostToDevice();

		clDedispersedData->setCLContext(clContext);
		clDedispersedData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
		clDedispersedData->allocateDeviceData();
	} catch ( OpenCLError err ) {
		cerr << err.what() << endl;
		return 1;
	}

	// Generate kernel
	try {
		Dedispersion< dataType > clDedisperse("Dedisperse", typeName);
		clDedisperse.bindOpenCL(clContext, &(clDevices->at(clDeviceID)), &((clQueues->at(clDeviceID)).at(0)));
		clDedisperse.setNrSamplesPerBlock(nrSamplesPerBlock);
		clDedisperse.setNrDMsPerBlock(nrDMsPerBlock);
		clDedisperse.setNrSamplesPerThread(nrSamplesPerThread);
		clDedisperse.setNrDMsPerThread(nrDMsPerThread);
		clDedisperse.setNrSamplesPerDispersedChannel(secondsToBuffer * observation.getNrSamplesPerPaddedSecond());
		clDedisperse.setObservation(&observation);
		clDedisperse.setShifts(clShifts);
		clDedisperse.generateCode();

		cout << clDedisperse.getCode() << endl;
		cout << endl;

		clDedisperse(dispersedData, clDedispersedData);
		clDedispersedData->copyDeviceToHost();
	} catch ( OpenCLError err ) {
		cerr << err.what() << endl;
		return 1;
	}

	dedispersion(secondsToBuffer * observationCPU.getNrSamplesPerPaddedSecond(), observationCPU, dispersedData->getHostData(), dedispersedData, shifts);

	for ( unsigned int dm = 0; dm < observation.getNrDMs(); dm++ ) {
		for ( unsigned int sample = 0; sample < observation.getNrSamplesPerSecond(); sample++ ) {
			if ( !same((*dedispersedData)[(dm * observationCPU.getNrSamplesPerPaddedSecond()) + sample], (*clDedispersedData)[(dm * observation.getNrSamplesPerPaddedSecond()) + sample]) ) {
				wrongOnes++;

				cout << dm << " " << sample << " " << (*dedispersedData)[(dm * observationCPU.getNrSamplesPerPaddedSecond()) + sample] << " " << (*clDedispersedData)[(dm * observation.getNrSamplesPerPaddedSecond()) + sample] << " " << (*dedispersedData)[(dm * observation.getNrSamplesPerPaddedSecond()) + sample] - (*clDedispersedData)[(dm * observation.getNrSamplesPerPaddedSecond()) + sample] << endl;
			}
		}
	}

	cout << endl;

	cout << "Wrong samples: " << wrongOnes << " (" << (wrongOnes * 100) / (static_cast< long long unsigned int >(observation.getNrSeconds()) * observation.getNrDMs() * observation.getNrSamplesPerSecond()) << "%)." << endl;
	cout << endl;

	return 0;
}

<|endoftext|>


<commit_before>/*
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
#include "cxxtools/xml/xmlwriter.h"
#include "cxxtools/xml/startelement.h"
#include "cxxtools/utf8codec.h"
#include <iostream>

namespace cxxtools {

namespace xml {

XmlWriter::XmlWriter()
: _tos(new Utf8Codec)
, _flags(UseIndent | UseEndl)
{
}

XmlWriter::XmlWriter(std::ostream& os)
: _tos(os, new Utf8Codec)
, _flags(UseIndent | UseEndl)
{
    _tos << cxxtools::String(L"<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
    if (_flags & UseEndl)
        this->endl();
}

XmlWriter::~XmlWriter()
{
}

void XmlWriter::begin(std::ostream& os)
{
    _tos.attach(os);
    _tos << cxxtools::String(L"<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
    if (_flags & UseEndl)
        this->endl();
}

void XmlWriter::writeStartElement(const cxxtools::String& prefix, const cxxtools::String& localName, const cxxtools::String& ns)
{
}

void XmlWriter::writeStartElement(const cxxtools::String& localName)
{
    this->writeStartElement(localName, 0, 0);
}

void XmlWriter::writeStartElement(const cxxtools::String& localName, const Attribute* attr, size_t attrCount)
{
    if (_flags & UseIndent)
    {
        for(size_t n = 0; n < _elements.size(); ++n)
        {
            _tos << cxxtools::String(L"  ");
        }
    }

    _tos << cxxtools::Char(L'<') << localName;

    for(size_t n = 0; n < attrCount; ++n)
    {
        _tos << cxxtools::Char(' ') << attr[n].name() << cxxtools::String(L"=\"") << attr[n].value() << cxxtools::Char('"');
    }

    _tos << cxxtools::Char(L'>');

    if (_flags & UseEndl)
        this->endl();

    _elements.push(localName);
}

void XmlWriter::writeEndElement()
{
    if( _elements.empty() )
        return;

    if (_flags & UseIndent)
    {
        for(size_t n = 0; n < _elements.size(); ++n)
        {
            _tos << cxxtools::String(L"  ");
        }
    }

    _tos << cxxtools::Char(L'<') << cxxtools::Char(L'/') << _elements.top() << cxxtools::Char(L'>');

    if (_flags & UseEndl)
        this->endl();

    _elements.pop();
}

void XmlWriter::writeElement(const cxxtools::String& localName, const cxxtools::String& content)
{
    this->writeElement(localName, 0, 0, content);
}

void XmlWriter::writeElement(const cxxtools::String& localName, const Attribute* attr, size_t attrCount, const cxxtools::String& content)
{
    if (_flags & UseIndent)
    {
        for(size_t n = 0; n < _elements.size(); ++n)
        {
            _tos << cxxtools::String(L"  ");
        }
    }

    _tos << cxxtools::Char(L'<') << localName;

    for(size_t n = 0; n < attrCount; ++n)
    {
        _tos << cxxtools::Char(' ') << attr[n].name() << cxxtools::String(L"=\"") << attr[n].value() << cxxtools::Char('"');
    }

    _tos << cxxtools::Char(L'>');

    this->writeCharacters(content);
    _tos << cxxtools::Char(L'<') << cxxtools::Char(L'/') << localName << cxxtools::Char(L'>');

    if (_flags & UseEndl)
        this->endl();
}

void XmlWriter::writeCharacters(const cxxtools::String& text)
{
    static const cxxtools::Char lt[] = { '&', 'l', 't', ';', 0 };
    static const cxxtools::Char gt[] = { '&', 'g', 't', ';', 0 };
    static const cxxtools::Char amp[] = { '&', 'a', 'm', 'p', ';', 0 };

    cxxtools::String::const_iterator it;
    for(it = text.begin(); it != text.end(); ++it)
    {
        switch( it->value() )
        {
            case '<':
                _tos << lt;
                break;

            case '>':
                _tos << gt;
                break;

            case '&':
                _tos << amp;
                break;

            default:
                _tos << *it;
        }
    }
}

void XmlWriter::flush()
{
    _tos.flush();
}

void XmlWriter::endl()
{
    _tos << cxxtools::Char('\n');
}

} // namespace xml

} // namespace cxxtools
<commit_msg>fix formatting of xml documents<commit_after>/*
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
#include "cxxtools/xml/xmlwriter.h"
#include "cxxtools/xml/startelement.h"
#include "cxxtools/utf8codec.h"
#include <iostream>

namespace cxxtools {

namespace xml {

XmlWriter::XmlWriter()
: _tos(new Utf8Codec)
, _flags(UseIndent | UseEndl)
{
}

XmlWriter::XmlWriter(std::ostream& os)
: _tos(os, new Utf8Codec)
, _flags(UseIndent | UseEndl)
{
    _tos << cxxtools::String(L"<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
    if (_flags & UseEndl)
        this->endl();
}

XmlWriter::~XmlWriter()
{
}

void XmlWriter::begin(std::ostream& os)
{
    _tos.attach(os);
    _tos << cxxtools::String(L"<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
    if (_flags & UseEndl)
        this->endl();
}

void XmlWriter::writeStartElement(const cxxtools::String& prefix, const cxxtools::String& localName, const cxxtools::String& ns)
{
}

void XmlWriter::writeStartElement(const cxxtools::String& localName)
{
    this->writeStartElement(localName, 0, 0);
}

void XmlWriter::writeStartElement(const cxxtools::String& localName, const Attribute* attr, size_t attrCount)
{
    if (_flags & UseIndent)
    {
        for(size_t n = 0; n < _elements.size(); ++n)
        {
            _tos << cxxtools::String(L"  ");
        }
    }

    _tos << cxxtools::Char(L'<') << localName;

    for(size_t n = 0; n < attrCount; ++n)
    {
        _tos << cxxtools::Char(' ') << attr[n].name() << cxxtools::String(L"=\"") << attr[n].value() << cxxtools::Char('"');
    }

    _tos << cxxtools::Char(L'>');

    if (_flags & UseEndl)
        this->endl();

    _elements.push(localName);
}

void XmlWriter::writeEndElement()
{
    if( _elements.empty() )
        return;

    if (_flags & UseIndent)
    {
        for(size_t n = 1; n < _elements.size(); ++n)
        {
            _tos << cxxtools::String(L"  ");
        }
    }

    _tos << cxxtools::Char(L'<') << cxxtools::Char(L'/') << _elements.top() << cxxtools::Char(L'>');

    if (_flags & UseEndl)
        this->endl();

    _elements.pop();
}

void XmlWriter::writeElement(const cxxtools::String& localName, const cxxtools::String& content)
{
    this->writeElement(localName, 0, 0, content);
}

void XmlWriter::writeElement(const cxxtools::String& localName, const Attribute* attr, size_t attrCount, const cxxtools::String& content)
{
    if (_flags & UseIndent)
    {
        for(size_t n = 0; n < _elements.size(); ++n)
        {
            _tos << cxxtools::String(L"  ");
        }
    }

    _tos << cxxtools::Char(L'<') << localName;

    for(size_t n = 0; n < attrCount; ++n)
    {
        _tos << cxxtools::Char(' ') << attr[n].name() << cxxtools::String(L"=\"") << attr[n].value() << cxxtools::Char('"');
    }

    _tos << cxxtools::Char(L'>');

    this->writeCharacters(content);
    _tos << cxxtools::Char(L'<') << cxxtools::Char(L'/') << localName << cxxtools::Char(L'>');

    if (_flags & UseEndl)
        this->endl();
}

void XmlWriter::writeCharacters(const cxxtools::String& text)
{
    static const cxxtools::Char lt[] = { '&', 'l', 't', ';', 0 };
    static const cxxtools::Char gt[] = { '&', 'g', 't', ';', 0 };
    static const cxxtools::Char amp[] = { '&', 'a', 'm', 'p', ';', 0 };

    cxxtools::String::const_iterator it;
    for(it = text.begin(); it != text.end(); ++it)
    {
        switch( it->value() )
        {
            case '<':
                _tos << lt;
                break;

            case '>':
                _tos << gt;
                break;

            case '&':
                _tos << amp;
                break;

            default:
                _tos << *it;
        }
    }
}

void XmlWriter::flush()
{
    _tos.flush();
}

void XmlWriter::endl()
{
    _tos << cxxtools::Char('\n');
}

} // namespace xml

} // namespace cxxtools
<|endoftext|>